capistrano-edge 2.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. data/CHANGELOG.rdoc +770 -0
  2. data/Manifest +104 -0
  3. data/README.rdoc +66 -0
  4. data/Rakefile +35 -0
  5. data/bin/cap +4 -0
  6. data/bin/capify +95 -0
  7. data/capistrano.gemspec +51 -0
  8. data/examples/sample.rb +14 -0
  9. data/lib/capistrano.rb +2 -0
  10. data/lib/capistrano/callback.rb +45 -0
  11. data/lib/capistrano/cli.rb +47 -0
  12. data/lib/capistrano/cli/execute.rb +84 -0
  13. data/lib/capistrano/cli/help.rb +125 -0
  14. data/lib/capistrano/cli/help.txt +75 -0
  15. data/lib/capistrano/cli/options.rb +224 -0
  16. data/lib/capistrano/cli/ui.rb +40 -0
  17. data/lib/capistrano/command.rb +283 -0
  18. data/lib/capistrano/configuration.rb +43 -0
  19. data/lib/capistrano/configuration/actions/file_transfer.rb +47 -0
  20. data/lib/capistrano/configuration/actions/inspect.rb +46 -0
  21. data/lib/capistrano/configuration/actions/invocation.rb +293 -0
  22. data/lib/capistrano/configuration/callbacks.rb +148 -0
  23. data/lib/capistrano/configuration/connections.rb +204 -0
  24. data/lib/capistrano/configuration/execution.rb +143 -0
  25. data/lib/capistrano/configuration/loading.rb +197 -0
  26. data/lib/capistrano/configuration/namespaces.rb +197 -0
  27. data/lib/capistrano/configuration/roles.rb +73 -0
  28. data/lib/capistrano/configuration/servers.rb +85 -0
  29. data/lib/capistrano/configuration/variables.rb +127 -0
  30. data/lib/capistrano/errors.rb +15 -0
  31. data/lib/capistrano/extensions.rb +57 -0
  32. data/lib/capistrano/logger.rb +59 -0
  33. data/lib/capistrano/processable.rb +53 -0
  34. data/lib/capistrano/recipes/compat.rb +32 -0
  35. data/lib/capistrano/recipes/deploy.rb +438 -0
  36. data/lib/capistrano/recipes/deploy/dependencies.rb +44 -0
  37. data/lib/capistrano/recipes/deploy/local_dependency.rb +54 -0
  38. data/lib/capistrano/recipes/deploy/remote_dependency.rb +105 -0
  39. data/lib/capistrano/recipes/deploy/scm.rb +19 -0
  40. data/lib/capistrano/recipes/deploy/scm/accurev.rb +169 -0
  41. data/lib/capistrano/recipes/deploy/scm/base.rb +196 -0
  42. data/lib/capistrano/recipes/deploy/scm/bzr.rb +83 -0
  43. data/lib/capistrano/recipes/deploy/scm/cvs.rb +152 -0
  44. data/lib/capistrano/recipes/deploy/scm/darcs.rb +85 -0
  45. data/lib/capistrano/recipes/deploy/scm/git.rb +274 -0
  46. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +137 -0
  47. data/lib/capistrano/recipes/deploy/scm/none.rb +44 -0
  48. data/lib/capistrano/recipes/deploy/scm/perforce.rb +138 -0
  49. data/lib/capistrano/recipes/deploy/scm/subversion.rb +121 -0
  50. data/lib/capistrano/recipes/deploy/strategy.rb +19 -0
  51. data/lib/capistrano/recipes/deploy/strategy/base.rb +79 -0
  52. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +20 -0
  53. data/lib/capistrano/recipes/deploy/strategy/copy.rb +210 -0
  54. data/lib/capistrano/recipes/deploy/strategy/export.rb +20 -0
  55. data/lib/capistrano/recipes/deploy/strategy/remote.rb +52 -0
  56. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +56 -0
  57. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +53 -0
  58. data/lib/capistrano/recipes/ext/rails-database-migrations.rb +50 -0
  59. data/lib/capistrano/recipes/ext/web-disable-enable.rb +40 -0
  60. data/lib/capistrano/recipes/standard.rb +37 -0
  61. data/lib/capistrano/recipes/templates/maintenance.rhtml +53 -0
  62. data/lib/capistrano/recipes/upgrade.rb +33 -0
  63. data/lib/capistrano/role.rb +102 -0
  64. data/lib/capistrano/server_definition.rb +56 -0
  65. data/lib/capistrano/shell.rb +260 -0
  66. data/lib/capistrano/ssh.rb +99 -0
  67. data/lib/capistrano/task_definition.rb +70 -0
  68. data/lib/capistrano/transfer.rb +216 -0
  69. data/lib/capistrano/version.rb +18 -0
  70. data/setup.rb +1346 -0
  71. data/test/cli/execute_test.rb +132 -0
  72. data/test/cli/help_test.rb +165 -0
  73. data/test/cli/options_test.rb +317 -0
  74. data/test/cli/ui_test.rb +28 -0
  75. data/test/cli_test.rb +17 -0
  76. data/test/command_test.rb +286 -0
  77. data/test/configuration/actions/file_transfer_test.rb +61 -0
  78. data/test/configuration/actions/inspect_test.rb +65 -0
  79. data/test/configuration/actions/invocation_test.rb +224 -0
  80. data/test/configuration/callbacks_test.rb +220 -0
  81. data/test/configuration/connections_test.rb +349 -0
  82. data/test/configuration/execution_test.rb +175 -0
  83. data/test/configuration/loading_test.rb +132 -0
  84. data/test/configuration/namespace_dsl_test.rb +311 -0
  85. data/test/configuration/roles_test.rb +144 -0
  86. data/test/configuration/servers_test.rb +121 -0
  87. data/test/configuration/variables_test.rb +184 -0
  88. data/test/configuration_test.rb +88 -0
  89. data/test/deploy/local_dependency_test.rb +76 -0
  90. data/test/deploy/remote_dependency_test.rb +114 -0
  91. data/test/deploy/scm/accurev_test.rb +23 -0
  92. data/test/deploy/scm/base_test.rb +55 -0
  93. data/test/deploy/scm/git_test.rb +184 -0
  94. data/test/deploy/scm/mercurial_test.rb +129 -0
  95. data/test/deploy/scm/none_test.rb +35 -0
  96. data/test/deploy/strategy/copy_test.rb +258 -0
  97. data/test/extensions_test.rb +69 -0
  98. data/test/fixtures/cli_integration.rb +5 -0
  99. data/test/fixtures/config.rb +5 -0
  100. data/test/fixtures/custom.rb +3 -0
  101. data/test/logger_test.rb +123 -0
  102. data/test/role_test.rb +11 -0
  103. data/test/server_definition_test.rb +121 -0
  104. data/test/shell_test.rb +90 -0
  105. data/test/ssh_test.rb +104 -0
  106. data/test/task_definition_test.rb +101 -0
  107. data/test/transfer_test.rb +160 -0
  108. data/test/utils.rb +38 -0
  109. metadata +321 -0
@@ -0,0 +1,137 @@
1
+ # Copyright 2007 Matthew Elder <sseses@gmail.com>
2
+ # based on work by Tobias Luetke
3
+
4
+ require 'capistrano/recipes/deploy/scm/base'
5
+
6
+ module Capistrano
7
+ module Deploy
8
+ module SCM
9
+
10
+ # Implements the Capistrano SCM interface for the Mercurial revision
11
+ # control system (http://www.selenic.com/mercurial/).
12
+ # Latest updates at http://tackletechnology.org/oss/cap2-mercurial
13
+ class Mercurial < Base
14
+ # Sets the default command name for this SCM. Users may override this
15
+ # by setting the :scm_command variable.
16
+ default_command "hg"
17
+
18
+ # For mercurial HEAD == tip except that it bases this assumption on what
19
+ # tip is in the current repository (so push before you deploy)
20
+ def head
21
+ "tip"
22
+ end
23
+
24
+ # Clone the repository and update to the specified changeset.
25
+ def checkout(changeset, destination)
26
+ clone(destination) + " && " + update(changeset, destination)
27
+ end
28
+
29
+ # Pull from the repository and update to the specified changeset.
30
+ def sync(changeset, destination)
31
+ pull(destination) + " && " + update(changeset, destination)
32
+ end
33
+
34
+ # One day we will have hg archive, although i think its not needed
35
+ def export(revision, destination)
36
+ raise NotImplementedError, "`diff' is not implemented by #{self.class.name}" +
37
+ "use checkout strategy"
38
+ end
39
+
40
+ # Compute the difference between the two changesets +from+ and +to+
41
+ # as a unified diff.
42
+ def diff(from, to=nil)
43
+ scm :diff,
44
+ "--rev #{from}",
45
+ (to ? "--rev #{to}" : nil)
46
+ end
47
+
48
+ # Return a log of all changes between the two specified changesets,
49
+ # +from+ and +to+, inclusive or the log for +from+ if +to+ is omitted.
50
+ def log(from, to=nil)
51
+ scm :log,
52
+ verbose,
53
+ "--rev #{from}" +
54
+ (to ? ":#{to}" : "")
55
+ end
56
+
57
+ # Translates a tag to a changeset if needed or just returns changeset.
58
+ def query_revision(changeset)
59
+ cmd = scm :log,
60
+ verbose,
61
+ "-r #{changeset}",
62
+ "--template '{node|short}'"
63
+ yield cmd
64
+ end
65
+
66
+ # Determine response for SCM prompts
67
+ # user/pass can come from ssh and http distribution methods
68
+ # yes/no is for when ssh asks you about fingerprints
69
+ def handle_data(state, stream, text)
70
+ host = state[:channel][:host]
71
+ logger.info "[#{host} :: #{stream}] #{text}"
72
+ case text
73
+ when /^user:/mi
74
+ # support :scm_user for backwards compatibility of this module
75
+ if user = variable(:scm_username) || variable(:scm_user)
76
+ "#{user}\n"
77
+ else
78
+ raise "No variable :scm_username specified and Mercurial asked!\n" +
79
+ "Prompt was: #{text}"
80
+ end
81
+ when /\bpassword:/mi
82
+ unless pass = scm_password_or_prompt
83
+ # fall back on old behavior of erroring out with msg
84
+ raise "No variable :scm_password specified and Mercurial asked!\n" +
85
+ "Prompt was: #{text}"
86
+ end
87
+ "#{pass}\n"
88
+ when /yes\/no/i
89
+ "yes\n"
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ # Fine grained mercurial commands
96
+ def clone(destination)
97
+ scm :clone,
98
+ verbose,
99
+ "--noupdate", # do not update to tip when cloning is done
100
+ repository, # clone which repository?
101
+ destination # and put the clone where?
102
+ end
103
+
104
+ def pull(destination)
105
+ scm :pull,
106
+ verbose,
107
+ "--repository #{destination}", # pull changes into what?
108
+ repository # and pull the changes from?
109
+ end
110
+
111
+ def update(changeset, destination)
112
+ scm :update,
113
+ verbose,
114
+ "--repository #{destination}", # update what?
115
+ "--clean", # ignore untracked changes
116
+ changeset # update to this changeset
117
+ end
118
+
119
+ # verbosity configuration grokking :)
120
+ def verbose
121
+ case variable(:scm_verbose)
122
+ when nil then nil
123
+ when false then "--quiet"
124
+ else "--verbose"
125
+ end
126
+ end
127
+
128
+ # honor Cap 2.1+'s :scm_prefer_prompt if present
129
+ def scm_password_or_prompt
130
+ @scm_password_or_prompt ||= variable(:scm_password) ||
131
+ (Capistrano::CLI.password_prompt("hg password: ") if variable(:scm_prefer_prompt))
132
+ end
133
+
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,44 @@
1
+ require 'capistrano/recipes/deploy/scm/base'
2
+
3
+ module Capistrano
4
+ module Deploy
5
+ module SCM
6
+
7
+ # A trivial SCM wrapper for representing the current working directory
8
+ # as a repository. Obviously, not all operations are available for this
9
+ # SCM, but it works sufficiently for use with the "copy" deployment
10
+ # strategy.
11
+ #
12
+ # Use of this module is _not_ recommended; in general, it is good
13
+ # practice to use some kind of source code management even for anything
14
+ # you are wanting to deploy. However, this module is provided in
15
+ # acknowledgement of the cases where trivial deployment of your current
16
+ # working directory is desired.
17
+ #
18
+ # set :repository, "."
19
+ # set :scm, :none
20
+ # set :deploy_via, :copy
21
+ class None < Base
22
+ # No versioning, thus, no head. Returns the empty string.
23
+ def head
24
+ ""
25
+ end
26
+
27
+ # Simply does a copy from the :repository directory to the
28
+ # :destination directory.
29
+ def checkout(revision, destination)
30
+ !Capistrano::Deploy::LocalDependency.on_windows? ? "cp -R #{repository} #{destination}" : "xcopy #{repository} \"#{destination}\" /S/I/Y/Q/E"
31
+ end
32
+
33
+ alias_method :export, :checkout
34
+
35
+ # No versioning, so this just returns the argument, with no
36
+ # modification.
37
+ def query_revision(revision)
38
+ revision
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,138 @@
1
+ require 'capistrano/recipes/deploy/scm/base'
2
+
3
+ # Notes:
4
+ # no global verbose flag for scm_verbose
5
+ # sync, checkout and export are just sync in p4
6
+ #
7
+ module Capistrano
8
+ module Deploy
9
+ module SCM
10
+
11
+ # Implements the Capistrano SCM interface for the Perforce revision
12
+ # control system (http://www.perforce.com).
13
+ class Perforce < Base
14
+ # Sets the default command name for this SCM. Users may override this
15
+ # by setting the :scm_command variable.
16
+ default_command "p4"
17
+
18
+ # Perforce understands '#head' to refer to the latest revision in the
19
+ # depot.
20
+ def head
21
+ 'head'
22
+ end
23
+
24
+ # Returns the command that will sync the given revision to the given
25
+ # destination directory. The perforce client has a fixed destination so
26
+ # the files must be copied from there to their intended resting place.
27
+ def checkout(revision, destination)
28
+ p4_sync(revision, destination, p4sync_flags)
29
+ end
30
+
31
+ # Returns the command that will sync the given revision to the given
32
+ # destination directory. The perforce client has a fixed destination so
33
+ # the files must be copied from there to their intended resting place.
34
+ def sync(revision, destination)
35
+ p4_sync(revision, destination, p4sync_flags)
36
+ end
37
+
38
+ # Returns the command that will sync the given revision to the given
39
+ # destination directory. The perforce client has a fixed destination so
40
+ # the files must be copied from there to their intended resting place.
41
+ def export(revision, destination)
42
+ p4_sync(revision, destination, p4sync_flags)
43
+ end
44
+
45
+ # Returns the command that will do an "p4 diff2" for the two revisions.
46
+ def diff(from, to=head)
47
+ scm authentication, :diff2, "-u -db", "//#{p4client}/...#{rev_no(from)}", "//#{p4client}/...#{rev_no(to)}"
48
+ end
49
+
50
+ # Returns a "p4 changes" command for the two revisions.
51
+ def log(from=1, to=head)
52
+ scm authentication, :changes, "-s submitted", "//#{p4client}/...#{rev_no(from)},#{rev_no(to)}"
53
+ end
54
+
55
+ def query_revision(revision)
56
+ return revision if revision.to_s =~ /^\d+$/
57
+ command = scm(authentication, :changes, "-s submitted", "-m 1", "//#{p4client}/...#{rev_no(revision)}")
58
+ yield(command)[/Change (\d+) on/, 1]
59
+ end
60
+
61
+ # Increments the given revision number and returns it.
62
+ def next_revision(revision)
63
+ revision.to_i + 1
64
+ end
65
+
66
+ # Determines what the response should be for a particular bit of text
67
+ # from the SCM. Password prompts, connection requests, passphrases,
68
+ # etc. are handled here.
69
+ def handle_data(state, stream, text)
70
+ case text
71
+ when /\(P4PASSWD\) invalid or unset\./i
72
+ raise Capistrano::Error, "scm_password (or p4passwd) is incorrect or unset"
73
+ when /Can.t create a new user.*/i
74
+ raise Capistrano::Error, "scm_username (or p4user) is incorrect or unset"
75
+ when /Perforce client error\:/i
76
+ raise Capistrano::Error, "p4port is incorrect or unset"
77
+ when /Client \'[\w\-\_\.]+\' unknown.*/i
78
+ raise Capistrano::Error, "p4client is incorrect or unset"
79
+ end
80
+ end
81
+
82
+ private
83
+
84
+ # Builds the set of authentication switches that perforce understands.
85
+ def authentication
86
+ [ p4port && "-p #{p4port}",
87
+ p4user && "-u #{p4user}",
88
+ p4passwd && "-P #{p4passwd}",
89
+ p4client && "-c #{p4client}" ].compact.join(" ")
90
+ end
91
+
92
+ # Returns the command that will sync the given revision to the given
93
+ # destination directory with specific options. The perforce client has
94
+ # a fixed destination so the files must be copied from there to their
95
+ # intended resting place.
96
+ def p4_sync(revision, destination, options="")
97
+ scm authentication, :sync, options, "#{rev_no(revision)}", "&& cp -rf #{p4client_root} #{destination}"
98
+ end
99
+
100
+ def p4client
101
+ variable(:p4client)
102
+ end
103
+
104
+ def p4port
105
+ variable(:p4port)
106
+ end
107
+
108
+ def p4user
109
+ variable(:p4user) || variable(:scm_username)
110
+ end
111
+
112
+ def p4passwd
113
+ variable(:p4passwd) || variable(:scm_password)
114
+ end
115
+
116
+ def p4sync_flags
117
+ variable(:p4sync_flags) || "-f"
118
+ end
119
+
120
+ def p4client_root
121
+ variable(:p4client_root) || "`#{command} #{authentication} client -o | grep ^Root | cut -f2`"
122
+ end
123
+
124
+ def rev_no(revision)
125
+ case revision.to_s
126
+ when "head"
127
+ "#head"
128
+ when /^\d+/
129
+ "@#{revision}"
130
+ else
131
+ revision
132
+ end
133
+ end
134
+ end
135
+
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,121 @@
1
+ require 'capistrano/recipes/deploy/scm/base'
2
+ require 'yaml'
3
+
4
+ module Capistrano
5
+ module Deploy
6
+ module SCM
7
+
8
+ # Implements the Capistrano SCM interface for the Subversion revision
9
+ # control system (http://subversion.tigris.org).
10
+ class Subversion < Base
11
+ # Sets the default command name for this SCM. Users may override this
12
+ # by setting the :scm_command variable.
13
+ default_command "svn"
14
+
15
+ # Subversion understands 'HEAD' to refer to the latest revision in the
16
+ # repository.
17
+ def head
18
+ "HEAD"
19
+ end
20
+
21
+ # Returns the command that will check out the given revision to the
22
+ # given destination.
23
+ def checkout(revision, destination)
24
+ scm :checkout, arguments, verbose, authentication, "-r#{revision}", repository, destination
25
+ end
26
+
27
+ # Returns the command that will do an "svn update" to the given
28
+ # revision, for the working copy at the given destination.
29
+ def sync(revision, destination)
30
+ scm :update, arguments, verbose, authentication, "-r#{revision}", destination
31
+ end
32
+
33
+ # Returns the command that will do an "svn export" of the given revision
34
+ # to the given destination.
35
+ def export(revision, destination)
36
+ scm :export, arguments, verbose, authentication, "-r#{revision}", repository, destination
37
+ end
38
+
39
+ # Returns the command that will do an "svn diff" for the two revisions.
40
+ def diff(from, to=nil)
41
+ scm :diff, repository, authentication, "-r#{from}:#{to || head}"
42
+ end
43
+
44
+ # Returns an "svn log" command for the two revisions.
45
+ def log(from, to=nil)
46
+ scm :log, repository, authentication, "-r#{from}:#{to || head}"
47
+ end
48
+
49
+ # Attempts to translate the given revision identifier to a "real"
50
+ # revision. If the identifier is an integer, it will simply be returned.
51
+ # Otherwise, this will yield a string of the commands it needs to be
52
+ # executed (svn info), and will extract the revision from the response.
53
+ def query_revision(revision)
54
+ return revision if revision =~ /^\d+$/
55
+ command = scm(:info, repository, authentication, "-r#{revision}")
56
+ result = yield(command)
57
+ yaml = YAML.load(result)
58
+ raise "tried to run `#{command}' and got unexpected result #{result.inspect}" unless Hash === yaml
59
+ yaml['Last Changed Rev'] || yaml['Revision']
60
+ end
61
+
62
+ # Increments the given revision number and returns it.
63
+ def next_revision(revision)
64
+ revision.to_i + 1
65
+ end
66
+
67
+ # Determines what the response should be for a particular bit of text
68
+ # from the SCM. Password prompts, connection requests, passphrases,
69
+ # etc. are handled here.
70
+ def handle_data(state, stream, text)
71
+ host = state[:channel][:host]
72
+ logger.info "[#{host} :: #{stream}] #{text}"
73
+ case text
74
+ when /\bpassword.*:/i
75
+ # subversion is prompting for a password
76
+ "#{scm_password_prompt}\n"
77
+ when %r{\(yes/no\)}
78
+ # subversion is asking whether or not to connect
79
+ "yes\n"
80
+ when /passphrase/i
81
+ # subversion is asking for the passphrase for the user's key
82
+ "#{variable(:scm_passphrase)}\n"
83
+ when /The entry \'(.+?)\' is no longer a directory/
84
+ raise Capistrano::Error, "subversion can't update because directory '#{$1}' was replaced. Please add it to svn:ignore."
85
+ when /accept \(t\)emporarily/
86
+ # subversion is asking whether to accept the certificate
87
+ "t\n"
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ # If a username is configured for the SCM, return the command-line
94
+ # switches for that. Note that we don't need to return the password
95
+ # switch, since Capistrano will check for that prompt in the output
96
+ # and will respond appropriately.
97
+ def authentication
98
+ username = variable(:scm_username)
99
+ return "" unless username
100
+ result = "--username #{variable(:scm_username)} "
101
+ result << "--password #{variable(:scm_password)} " unless variable(:scm_auth_cache) || variable(:scm_prefer_prompt)
102
+ result << "--no-auth-cache " unless variable(:scm_auth_cache)
103
+ result
104
+ end
105
+
106
+ # If verbose output is requested, return nil, otherwise return the
107
+ # command-line switch for "quiet" ("-q").
108
+ def verbose
109
+ variable(:scm_verbose) ? nil : "-q"
110
+ end
111
+
112
+ def scm_password_prompt
113
+ @scm_password_prompt ||= variable(:scm_password) ||
114
+ variable(:password) ||
115
+ Capistrano::CLI.password_prompt("Subversion password: ")
116
+ end
117
+ end
118
+
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,19 @@
1
+ module Capistrano
2
+ module Deploy
3
+ module Strategy
4
+ def self.new(strategy, config={})
5
+ strategy_file = "capistrano/recipes/deploy/strategy/#{strategy}"
6
+ require(strategy_file)
7
+
8
+ strategy_const = strategy.to_s.capitalize.gsub(/_(.)/) { $1.upcase }
9
+ if const_defined?(strategy_const)
10
+ const_get(strategy_const).new(config)
11
+ else
12
+ raise Capistrano::Error, "could not find `#{name}::#{strategy_const}' in `#{strategy_file}'"
13
+ end
14
+ rescue LoadError
15
+ raise Capistrano::Error, "could not find any strategy named `#{strategy}'"
16
+ end
17
+ end
18
+ end
19
+ end