From 241ebb08e1577c99ce5f176aab9edbcbd9daff04 Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Wed, 9 May 2007 03:36:26 +0000 Subject: [PATCH] Allow (e.g.) scm_command and local_scm_command to be set in the event of different paths to the scm command on local vs. remote hosts git-svn-id: http://svn.rubyonrails.org/rails/tools/capistrano@6702 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- CHANGELOG | 2 + lib/capistrano/recipes/deploy.rb | 6 +- lib/capistrano/recipes/deploy/scm/base.rb | 63 ++++++++++++++++++- lib/capistrano/recipes/deploy/scm/darcs.rb | 2 +- lib/capistrano/recipes/deploy/scm/perforce.rb | 8 +-- .../recipes/deploy/scm/subversion.rb | 10 +-- .../recipes/deploy/strategy/copy.rb | 2 +- test/deploy/scm/base_test.rb | 55 ++++++++++++++++ 8 files changed, 131 insertions(+), 17 deletions(-) create mode 100644 test/deploy/scm/base_test.rb diff --git a/CHANGELOG b/CHANGELOG index 2b6a26db..4d4f5e12 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Allow (e.g.) scm_command and local_scm_command to be set in the event of different paths to the scm command on local vs. remote hosts. [Jamis Buck] + * Kill the "deploy:app" namespace and move those tasks into deploy, directly. [Jamis Buck] * Make sure 'desc' applies to the next defined task, in any namespace. [Jamis Buck] diff --git a/lib/capistrano/recipes/deploy.rb b/lib/capistrano/recipes/deploy.rb index 6e9a390e..fc94f6e0 100644 --- a/lib/capistrano/recipes/deploy.rb +++ b/lib/capistrano/recipes/deploy.rb @@ -28,7 +28,7 @@ set(:revision) { source.head } unless exists?(:revision) # ========================================================================= set(:source) { Capistrano::Deploy::SCM.new(scm, self) } -set(:real_revision) { source.query_revision(revision) { |cmd| `#{cmd}` } } +set(:real_revision) { source.local.query_revision(revision) { |cmd| `#{cmd}` } } set(:strategy) { Capistrano::Deploy::Strategy.new(deploy_via, self) } @@ -400,7 +400,7 @@ namespace :deploy do not be supported on all SCM's. DESC task :diff, :except => { :no_release => true } do - system(source.diff(current_revision)) + system(source.local.diff(current_revision)) end desc <<-DESC @@ -409,7 +409,7 @@ namespace :deploy do might not be supported on all SCM's. DESC task :default, :except => { :no_release => true } do - system(source.log(current_revision)) + system(source.local.log(current_revision)) end end diff --git a/lib/capistrano/recipes/deploy/scm/base.rb b/lib/capistrano/recipes/deploy/scm/base.rb index ca6c1c9b..7192b605 100644 --- a/lib/capistrano/recipes/deploy/scm/base.rb +++ b/lib/capistrano/recipes/deploy/scm/base.rb @@ -23,6 +23,19 @@ module Capistrano end end + # Wraps an SCM instance and forces all messages sent to it to be + # relayed to the underlying SCM instance, in "local" mode. See + # Base#local. + class LocalProxy + def initialize(scm) + @scm = scm + end + + def method_missing(sym, *args, &block) + @scm.local { return @scm.send(sym, *args, &block) } + end + end + # The options available for this SCM instance to reference. Should be # treated like a hash. attr_reader :configuration @@ -32,6 +45,35 @@ module Capistrano @configuration = configuration end + # Returns a proxy that wraps the SCM instance and forces it to operate + # in "local" mode, which changes how variables are looked up in the + # configuration. Normally, if the value of a variable "foo" is needed, + # it is queried for in the configuration as "foo". However, in "local" + # mode, first "local_foo" would be looked for, and only if it is not + # found would "foo" be used. This allows for both (e.g.) "scm_command" + # and "local_scm_command" to be set, if the two differ. + # + # Alternatively, it may be called with a block, and for the duration of + # the block, all requests on this configuration object will be + # considered local. + def local + if block_given? + begin + saved, @local_mode = @local_mode, true + yield + ensure + @local_mode = saved + end + else + LocalProxy.new(self) + end + end + + # Returns true if running in "local" mode. See #local. + def local? + @local_mode + end + # Returns the string used to identify the latest revision in the # repository. This will be passed as the "revision" parameter of # the methods below. @@ -87,16 +129,31 @@ module Capistrano # Returns the name of the command-line utility for this SCM. It first # looks at the :scm_command variable, and if it does not exist, it # then falls back to whatever was defined by +default_command+. + # + # If scm_command is set to :default, the default_command will be + # returned. def command - configuration[:scm_command] || default_command + command = variable(:scm_command) + command = nil if command == :default + command || default_command end private + # A helper for accessing variable values, which takes into + # consideration the current mode ("normal" vs. "local"). + def variable(name) + if local? && configuration.exists?("local_#{name}".to_sym) + return configuration["local_#{name}".to_sym] + else + configuration[name] + end + end + # A reference to a Logger instance that the SCM can use to log # activity. def logger - @logger ||= configuration[:logger] || Capistrano::Logger.new(STDOUT) + @logger ||= variable(:logger) || Capistrano::Logger.new(STDOUT) end # A helper for accessing the default command name for this SCM. It @@ -114,7 +171,7 @@ module Capistrano # A convenience method for accessing the declared repository value. def repository - configuration[:repository] + variable(:repository) end end diff --git a/lib/capistrano/recipes/deploy/scm/darcs.rb b/lib/capistrano/recipes/deploy/scm/darcs.rb index b5228268..de194a36 100644 --- a/lib/capistrano/recipes/deploy/scm/darcs.rb +++ b/lib/capistrano/recipes/deploy/scm/darcs.rb @@ -72,7 +72,7 @@ module Capistrano private def verbose - case configuration[:scm_verbose] + case variable(:scm_verbose) when nil then "-q" when false then nil else "-v" diff --git a/lib/capistrano/recipes/deploy/scm/perforce.rb b/lib/capistrano/recipes/deploy/scm/perforce.rb index 5a6ea9c1..ee4969fd 100644 --- a/lib/capistrano/recipes/deploy/scm/perforce.rb +++ b/lib/capistrano/recipes/deploy/scm/perforce.rb @@ -94,19 +94,19 @@ module Capistrano end def p4client - configuration[:p4client] + variable(:p4client) end def p4port - configuration[:p4port] + variable(:p4port) end def p4user - configuration[:p4user] || configuration[:scm_username] + variable(:p4user) || variable(:scm_username) end def p4passwd - configuration[:p4passwd] || configuration[:scm_password] + variable(:p4passwd) || variable(:scm_password) end def rev_no(revision) diff --git a/lib/capistrano/recipes/deploy/scm/subversion.rb b/lib/capistrano/recipes/deploy/scm/subversion.rb index 990f9baf..d1cd28a0 100644 --- a/lib/capistrano/recipes/deploy/scm/subversion.rb +++ b/lib/capistrano/recipes/deploy/scm/subversion.rb @@ -64,13 +64,13 @@ module Capistrano case text when /\bpassword.*:/i # subversion is prompting for a password - "#{configuration[:scm_password] || configuration[:password]}\n" + "#{variable(:scm_password) || variable(:password)}\n" when %r{\(yes/no\)} # subversion is asking whether or not to connect "yes\n" when /passphrase/i # subversion is asking for the passphrase for the user's key - "#{configuration[:scm_passphrase]}\n" + "#{variable(:scm_passphrase)}\n" when /The entry \'(.+?)\' is no longer a directory/ raise Capisrano::Error, "subversion can't update because directory '#{$1}' was replaced. Please add it to svn:ignore." when /accept \(t\)emporarily/ @@ -85,8 +85,8 @@ module Capistrano # command-line switches for those values. def authentication auth = "" - auth << "--username #{configuration[:scm_username]} " if configuration[:scm_username] - auth << "--password #{configuration[:scm_password]} " if configuration[:scm_password] + auth << "--username #{variable(:scm_username)} " if variable(:scm_username) + auth << "--password #{variable(:scm_password)} " if variable(:scm_password) auth << "--no-auth-cache" if !auth.empty? auth end @@ -94,7 +94,7 @@ module Capistrano # If verbose output is requested, return nil, otherwise return the # command-line switch for "quiet" ("-q"). def verbose - configuration[:scm_verbose] ? nil : "-q" + variable(:scm_verbose) ? nil : "-q" end end diff --git a/lib/capistrano/recipes/deploy/strategy/copy.rb b/lib/capistrano/recipes/deploy/strategy/copy.rb index 026256ab..c1a4abc8 100644 --- a/lib/capistrano/recipes/deploy/strategy/copy.rb +++ b/lib/capistrano/recipes/deploy/strategy/copy.rb @@ -41,7 +41,7 @@ module Capistrano def check! super.check do |d| - d.local.command(source.command) + d.local.command(source.local.command) d.local.command(compress(nil, nil).first) d.remote.command(decompress(nil).first) end diff --git a/test/deploy/scm/base_test.rb b/test/deploy/scm/base_test.rb new file mode 100644 index 00000000..ac272e2c --- /dev/null +++ b/test/deploy/scm/base_test.rb @@ -0,0 +1,55 @@ +require "#{File.dirname(__FILE__)}/../../utils" +require 'capistrano/recipes/deploy/scm/base' + +class DeploySCMBaseTest < Test::Unit::TestCase + class TestSCM < Capistrano::Deploy::SCM::Base + default_command "floopy" + end + + def setup + @config = { } + def @config.exists?(name); key?(name); end + + @source = TestSCM.new(@config) + end + + def test_command_should_default_to_default_command + assert_equal "floopy", @source.command + @source.local { assert_equal "floopy", @source.command } + end + + def test_command_should_use_scm_command_if_available + @config[:scm_command] = "/opt/local/bin/floopy" + assert_equal "/opt/local/bin/floopy", @source.command + end + + def test_command_should_use_scm_command_in_local_mode_if_local_scm_command_not_set + @config[:scm_command] = "/opt/local/bin/floopy" + @source.local { assert_equal "/opt/local/bin/floopy", @source.command } + end + + def test_command_should_use_local_scm_command_in_local_mode_if_local_scm_command_is_set + @config[:scm_command] = "/opt/local/bin/floopy" + @config[:local_scm_command] = "/usr/local/bin/floopy" + assert_equal "/opt/local/bin/floopy", @source.command + @source.local { assert_equal "/usr/local/bin/floopy", @source.command } + end + + def test_command_should_use_default_if_scm_command_is_default + @config[:scm_command] = :default + assert_equal "floopy", @source.command + end + + def test_command_should_use_default_in_local_mode_if_local_scm_command_is_default + @config[:scm_command] = "/foo/bar/floopy" + @config[:local_scm_command] = :default + @source.local { assert_equal "floopy", @source.command } + end + + def test_local_mode_proxy_should_treat_messages_as_being_in_local_mode + @config[:scm_command] = "/foo/bar/floopy" + @config[:local_scm_command] = :default + assert_equal "floopy", @source.local.command + assert_equal "/foo/bar/floopy", @source.command + end +end