From 3d98ce91e3fa6380d772a39eebc0d069f85fd7ce Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Sat, 28 Jan 2006 15:58:04 +0000 Subject: [PATCH] Add branch support to CVS (closes #3596) git-svn-id: http://svn.rubyonrails.org/rails/tools/switchtower@3490 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- CHANGELOG | 2 ++ Rakefile | 3 +- lib/switchtower/scm/cvs.rb | 57 ++++++++++++++++++++++++++++++++++---- test/scm/cvs_test.rb | 17 +++++++++++- test/utils.rb | 8 ++++++ 5 files changed, 80 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 988ebb4f..f9c613d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *0.11.0* *SVN* +* Add branch support to CVS [jeremy@hinegardner.org] (#3596) + * Add bazaar-ng SCM module [Damien Merenne] * Add optional :svn_username and :svn_password variables diff --git a/Rakefile b/Rakefile index 9128c4f3..e21aceba 100644 --- a/Rakefile +++ b/Rakefile @@ -19,6 +19,7 @@ desc "Build documentation" task :doc => [ :rdoc ] Rake::TestTask.new do |t| + t.ruby_opts << "-rubygems" t.test_files = Dir["test/**/*_test.rb"] t.verbose = true end @@ -45,4 +46,4 @@ desc "Publish the beta gem" task :pgem => [:package] do Rake::SshFilePublisher.new("davidhh@wrath.rubyonrails.org", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload `ssh davidhh@wrath.rubyonrails.org './gemupdate.sh'` -end \ No newline at end of file +end diff --git a/lib/switchtower/scm/cvs.rb b/lib/switchtower/scm/cvs.rb index fa97acb6..3a8ea97c 100644 --- a/lib/switchtower/scm/cvs.rb +++ b/lib/switchtower/scm/cvs.rb @@ -19,10 +19,27 @@ module SwitchTower # the revisions, etc.) via the :local variable, which defaults to # ".". # + # You may also specify a :branch configuration variable, + # which (if specified) will be used in the '-r' option to the cvs + # check out command. If it is not set, the module will determine if a + # branch is being used in the CVS sandbox relative to + # :local and act accordingly. + # + # set :branch, "prod-20060124" + # # Also, you can specify the CVS_RSH variable to use on the remote machine(s) # via the :cvs_rsh variable. This defaults to the value of the # CVS_RSH environment variable locally, or if it is not set, to "ssh". class Cvs < Base + def initialize(configuration) + super(configuration) + if not @configuration.respond_to?(:branch) then + @configuration.set(:branch) { self.current_branch } + else + @current_branch = @configuration[:branch] + end + end + # Return a string representing the date of the last revision (CVS is # seriously retarded, in that it does not give you a way to query when # the last revision was made to the repository, so this is a fairly @@ -30,22 +47,37 @@ module SwitchTower def latest_revision return @latest_revision if @latest_revision configuration.logger.debug "querying latest revision..." - @latest_revision = cvs_log(configuration.local). + @latest_revision = cvs_log(configuration.local,configuration.branch). split(/\r?\n/). grep(/^date: (.*?);/) { Time.parse($1).strftime("%Y-%m-%d %H:%M:%S") }. sort. last end + # Return a string representing the branch that the sandbox + # relative to :local contains. + def current_branch + return @current_branch if @current_branch + configuration.logger.debug "determining current_branch..." + @current_branch = cvs_branch(configuration.local) + end + # Check out (on all servers associated with the current task) the latest - # revision. Uses the given actor instance to execute the command. + # revision, using a branch if necessary. Uses the given actor instance + # to execute the command. def checkout(actor) cvs = configuration[:cvs] || "cvs" cvs_rsh = configuration[:cvs_rsh] || ENV['CVS_RSH'] || "ssh" + if "HEAD" == configuration.branch then + branch_option = "" + else + branch_option = "-r #{configuration.branch}" + end + command = <<-CMD cd #{configuration.releases_path}; - CVS_RSH="#{cvs_rsh}" #{cvs} -d #{configuration.repository} -Q co -D "#{configuration.revision}" -d #{File.basename(actor.release_path)} #{actor.application}; + CVS_RSH="#{cvs_rsh}" #{cvs} -d #{configuration.repository} -Q co -D "#{configuration.revision}" #{branch_option} -d #{File.basename(actor.release_path)} #{actor.application}; CMD run_checkout(actor, command) do |ch, stream, out| @@ -64,8 +96,23 @@ module SwitchTower private - def cvs_log(path) - `cd #{path || "."} && cvs -q log -N -rHEAD` + # Look for a 'CVS/Tag' file in the path. If this file exists + # and contains a Line starting with 'T' then this CVS sandbox is + # 'tagged' with a branch. In the default case return 'HEAD' + def cvs_branch(path) + branch = "HEAD" + branch_file = File.join(path || ".", "CVS", "Tag") + if File.exists?(branch_file) then + File.open(branch_file) do |f| + possible_branch = f.find { |l| l =~ %r{^T} } + branch = possible_branch.strip[1..-1] if possible_branch + end + end + branch + end + + def cvs_log(path,branch) + `cd #{path || "."} && cvs -q log -N -r#{branch}` end end diff --git a/test/scm/cvs_test.rb b/test/scm/cvs_test.rb index 45328708..209ec5e1 100644 --- a/test/scm/cvs_test.rb +++ b/test/scm/cvs_test.rb @@ -9,10 +9,15 @@ class ScmCvsTest < Test::Unit::TestCase attr_accessor :story attr_reader :last_path - def cvs_log(path) + def cvs_log(path,branch) @last_path = path story.shift end + + def cvs_branch(path) + "deploy-me" + end + end class MockChannel @@ -161,4 +166,14 @@ MSG assert_nothing_raised { @scm.checkout(@actor) } assert_equal ["chocolatebrownies\n"], @actor.channels.last.sent_data end + + def test_current_branch + assert_equal "deploy-me", @scm.current_branch + end + + def test_default_current_branch + @config[:branch] = "default-branch" + @scm = CvsTest.new(@config) + assert_equal "default-branch", @scm.current_branch + end end diff --git a/test/utils.rb b/test/utils.rb index 54066ac0..36af162a 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -32,6 +32,14 @@ class MockConfiguration < Hash @logger ||= MockLogger.new end + def set(variable, value=nil, &block) + self[variable] = value + end + + def respond_to?(sym) + self.has_key?(sym) + end + def method_missing(sym, *args) if args.length == 0 self[sym]