capistrano 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +89 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +674 -0
  7. data/README.md +226 -0
  8. data/Rakefile +5 -0
  9. data/bin/cap +2 -3
  10. data/bin/capify +7 -77
  11. data/capistrano-public_cert.pem +22 -0
  12. data/capistrano.gemspec +35 -0
  13. data/features/deploy.feature +52 -0
  14. data/features/installation.feature +16 -0
  15. data/features/remote_file_task.feature +14 -0
  16. data/features/step_definitions/assertions.rb +90 -0
  17. data/features/step_definitions/cap_commands.rb +8 -0
  18. data/features/step_definitions/setup.rb +25 -0
  19. data/features/support/env.rb +12 -0
  20. data/features/support/remote_command_helpers.rb +20 -0
  21. data/lib/Capfile +3 -0
  22. data/lib/capistrano/all.rb +16 -0
  23. data/lib/capistrano/application.rb +60 -0
  24. data/lib/capistrano/configuration/question.rb +42 -0
  25. data/lib/capistrano/configuration/server.rb +133 -0
  26. data/lib/capistrano/configuration/servers/role_filter.rb +86 -0
  27. data/lib/capistrano/configuration/servers.rb +53 -58
  28. data/lib/capistrano/configuration.rb +84 -30
  29. data/lib/capistrano/console.rb +1 -0
  30. data/lib/capistrano/defaults.rb +13 -0
  31. data/lib/capistrano/deploy.rb +3 -0
  32. data/lib/capistrano/dotfile.rb +3 -0
  33. data/lib/capistrano/dsl/env.rb +64 -0
  34. data/lib/capistrano/dsl/paths.rb +94 -0
  35. data/lib/capistrano/dsl/stages.rb +15 -0
  36. data/lib/capistrano/dsl/task_enhancements.rb +53 -0
  37. data/lib/capistrano/dsl.rb +48 -0
  38. data/lib/capistrano/git.rb +1 -0
  39. data/lib/capistrano/hg.rb +1 -0
  40. data/lib/capistrano/i18n.rb +34 -0
  41. data/lib/capistrano/install.rb +1 -0
  42. data/lib/capistrano/setup.rb +21 -0
  43. data/lib/capistrano/tasks/console.rake +21 -0
  44. data/lib/capistrano/tasks/deploy.rake +204 -0
  45. data/lib/capistrano/tasks/framework.rake +67 -0
  46. data/lib/capistrano/tasks/git.rake +62 -0
  47. data/lib/capistrano/tasks/hg.rake +39 -0
  48. data/lib/capistrano/tasks/install.rake +39 -0
  49. data/lib/capistrano/templates/Capfile +26 -0
  50. data/lib/capistrano/templates/deploy.rb.erb +40 -0
  51. data/lib/capistrano/templates/stage.rb.erb +42 -0
  52. data/lib/capistrano/version.rb +1 -20
  53. data/lib/capistrano/version_validator.rb +37 -0
  54. data/lib/capistrano.rb +0 -2
  55. data/spec/integration/dsl_spec.rb +344 -0
  56. data/spec/integration_spec_helper.rb +7 -0
  57. data/spec/lib/capistrano/application_spec.rb +61 -0
  58. data/spec/lib/capistrano/configuration/question_spec.rb +54 -0
  59. data/spec/lib/capistrano/configuration/server_spec.rb +249 -0
  60. data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +140 -0
  61. data/spec/lib/capistrano/configuration/servers_spec.rb +184 -0
  62. data/spec/lib/capistrano/configuration_spec.rb +101 -0
  63. data/spec/lib/capistrano/dsl/env_spec.rb +10 -0
  64. data/spec/lib/capistrano/dsl/paths_spec.rb +69 -0
  65. data/spec/lib/capistrano/dsl_spec.rb +63 -0
  66. data/spec/lib/capistrano/version_validator_spec.rb +103 -0
  67. data/spec/lib/capistrano_spec.rb +8 -0
  68. data/spec/spec_helper.rb +15 -0
  69. data/spec/support/.gitignore +1 -0
  70. data/spec/support/Vagrantfile +13 -0
  71. data/spec/support/matchers.rb +5 -0
  72. data/spec/support/tasks/database.cap +11 -0
  73. data/spec/support/test_app.rb +138 -0
  74. metadata +251 -179
  75. data/CHANGELOG +0 -512
  76. data/MIT-LICENSE +0 -20
  77. data/README +0 -43
  78. data/examples/sample.rb +0 -14
  79. data/lib/capistrano/callback.rb +0 -45
  80. data/lib/capistrano/cli/execute.rb +0 -82
  81. data/lib/capistrano/cli/help.rb +0 -102
  82. data/lib/capistrano/cli/help.txt +0 -53
  83. data/lib/capistrano/cli/options.rb +0 -183
  84. data/lib/capistrano/cli/ui.rb +0 -28
  85. data/lib/capistrano/cli.rb +0 -47
  86. data/lib/capistrano/command.rb +0 -161
  87. data/lib/capistrano/configuration/actions/file_transfer.rb +0 -35
  88. data/lib/capistrano/configuration/actions/inspect.rb +0 -46
  89. data/lib/capistrano/configuration/actions/invocation.rb +0 -134
  90. data/lib/capistrano/configuration/callbacks.rb +0 -148
  91. data/lib/capistrano/configuration/connections.rb +0 -159
  92. data/lib/capistrano/configuration/execution.rb +0 -126
  93. data/lib/capistrano/configuration/loading.rb +0 -198
  94. data/lib/capistrano/configuration/namespaces.rb +0 -196
  95. data/lib/capistrano/configuration/roles.rb +0 -51
  96. data/lib/capistrano/configuration/variables.rb +0 -127
  97. data/lib/capistrano/errors.rb +0 -15
  98. data/lib/capistrano/extensions.rb +0 -57
  99. data/lib/capistrano/gateway.rb +0 -131
  100. data/lib/capistrano/logger.rb +0 -59
  101. data/lib/capistrano/recipes/compat.rb +0 -32
  102. data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
  103. data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -46
  104. data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -96
  105. data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
  106. data/lib/capistrano/recipes/deploy/scm/base.rb +0 -192
  107. data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
  108. data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -151
  109. data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -85
  110. data/lib/capistrano/recipes/deploy/scm/git.rb +0 -191
  111. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -129
  112. data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -126
  113. data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -114
  114. data/lib/capistrano/recipes/deploy/scm.rb +0 -19
  115. data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -64
  116. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
  117. data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -144
  118. data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
  119. data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
  120. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -47
  121. data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
  122. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
  123. data/lib/capistrano/recipes/deploy.rb +0 -494
  124. data/lib/capistrano/recipes/standard.rb +0 -37
  125. data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
  126. data/lib/capistrano/recipes/upgrade.rb +0 -33
  127. data/lib/capistrano/server_definition.rb +0 -51
  128. data/lib/capistrano/shell.rb +0 -256
  129. data/lib/capistrano/ssh.rb +0 -109
  130. data/lib/capistrano/task_definition.rb +0 -69
  131. data/lib/capistrano/upload.rb +0 -146
  132. data/test/cli/execute_test.rb +0 -132
  133. data/test/cli/help_test.rb +0 -139
  134. data/test/cli/options_test.rb +0 -226
  135. data/test/cli/ui_test.rb +0 -28
  136. data/test/cli_test.rb +0 -17
  137. data/test/command_test.rb +0 -309
  138. data/test/configuration/actions/file_transfer_test.rb +0 -40
  139. data/test/configuration/actions/inspect_test.rb +0 -62
  140. data/test/configuration/actions/invocation_test.rb +0 -202
  141. data/test/configuration/callbacks_test.rb +0 -206
  142. data/test/configuration/connections_test.rb +0 -288
  143. data/test/configuration/execution_test.rb +0 -159
  144. data/test/configuration/loading_test.rb +0 -127
  145. data/test/configuration/namespace_dsl_test.rb +0 -297
  146. data/test/configuration/roles_test.rb +0 -47
  147. data/test/configuration/servers_test.rb +0 -90
  148. data/test/configuration/variables_test.rb +0 -180
  149. data/test/configuration_test.rb +0 -81
  150. data/test/deploy/scm/accurev_test.rb +0 -23
  151. data/test/deploy/scm/base_test.rb +0 -55
  152. data/test/deploy/scm/git_test.rb +0 -112
  153. data/test/deploy/strategy/copy_test.rb +0 -147
  154. data/test/extensions_test.rb +0 -69
  155. data/test/fixtures/cli_integration.rb +0 -5
  156. data/test/fixtures/config.rb +0 -5
  157. data/test/fixtures/custom.rb +0 -3
  158. data/test/gateway_test.rb +0 -167
  159. data/test/logger_test.rb +0 -123
  160. data/test/server_definition_test.rb +0 -108
  161. data/test/shell_test.rb +0 -64
  162. data/test/ssh_test.rb +0 -97
  163. data/test/task_definition_test.rb +0 -101
  164. data/test/upload_test.rb +0 -131
  165. data/test/utils.rb +0 -42
  166. data/test/version_test.rb +0 -24
@@ -1,82 +0,0 @@
1
- require 'capistrano/configuration'
2
-
3
- module Capistrano
4
- class CLI
5
- module Execute
6
- def self.included(base) #:nodoc:
7
- base.extend(ClassMethods)
8
- end
9
-
10
- module ClassMethods
11
- # Invoke capistrano using the ARGV array as the option parameters. This
12
- # is what the command-line capistrano utility does.
13
- def execute
14
- parse(ARGV).execute!
15
- end
16
- end
17
-
18
- # Using the options build when the command-line was parsed, instantiate
19
- # a new Capistrano configuration, initialize it, and execute the
20
- # requested actions.
21
- #
22
- # Returns the Configuration instance used, if successful.
23
- def execute!
24
- config = instantiate_configuration
25
- config.logger.level = options[:verbose]
26
-
27
- set_pre_vars(config)
28
- load_recipes(config)
29
-
30
- config.trigger(:load)
31
- execute_requested_actions(config)
32
- config.trigger(:exit)
33
-
34
- config
35
- rescue Exception => error
36
- handle_error(error)
37
- end
38
-
39
- def execute_requested_actions(config)
40
- Array(options[:vars]).each { |name, value| config.set(name, value) }
41
-
42
- Array(options[:actions]).each do |action|
43
- config.find_and_execute_task(action, :before => :start, :after => :finish)
44
- end
45
- end
46
-
47
- def set_pre_vars(config) #:nodoc:
48
- config.set :password, options[:password]
49
- Array(options[:pre_vars]).each { |name, value| config.set(name, value) }
50
- end
51
-
52
- def load_recipes(config) #:nodoc:
53
- # load the standard recipe definition
54
- config.load "standard"
55
-
56
- # load systemwide config/recipe definition
57
- config.load(options[:sysconf]) if options[:sysconf] && File.file?(options[:sysconf])
58
-
59
- # load user config/recipe definition
60
- config.load(options[:dotfile]) if options[:dotfile] && File.file?(options[:dotfile])
61
-
62
- Array(options[:recipes]).each { |recipe| config.load(recipe) }
63
- end
64
-
65
- # Primarily useful for testing, but subclasses of CLI could conceivably
66
- # override this method to return a Configuration subclass or replacement.
67
- def instantiate_configuration #:nodoc:
68
- Capistrano::Configuration.new
69
- end
70
-
71
- def handle_error(error) #:nodoc:
72
- case error
73
- when Net::SSH::AuthenticationFailed
74
- abort "authentication failed for `#{error.message}'"
75
- when Capistrano::Error
76
- abort(error.message)
77
- else raise error
78
- end
79
- end
80
- end
81
- end
82
- end
@@ -1,102 +0,0 @@
1
- module Capistrano
2
- class CLI
3
- module Help
4
- LINE_PADDING = 7
5
- MIN_MAX_LEN = 30
6
- HEADER_LEN = 60
7
-
8
- def self.included(base) #:nodoc:
9
- base.send :alias_method, :execute_requested_actions_without_help, :execute_requested_actions
10
- base.send :alias_method, :execute_requested_actions, :execute_requested_actions_with_help
11
- end
12
-
13
- def execute_requested_actions_with_help(config)
14
- if options[:tasks]
15
- task_list(config)
16
- elsif options[:explain]
17
- explain_task(config, options[:explain])
18
- else
19
- execute_requested_actions_without_help(config)
20
- end
21
- end
22
-
23
- def task_list(config) #:nodoc:
24
- tasks = config.task_list(:all)
25
-
26
- if tasks.empty?
27
- warn "There are no tasks available. Please specify a recipe file to load."
28
- else
29
- all_tasks_length = tasks.length
30
- if options[:verbose].to_i < 1
31
- tasks = tasks.reject { |t| t.description.empty? || t.description =~ /^\[internal\]/ }
32
- end
33
-
34
- tasks = tasks.sort_by { |task| task.fully_qualified_name }
35
-
36
- longest = tasks.map { |task| task.fully_qualified_name.length }.max
37
- max_length = output_columns - longest - LINE_PADDING
38
- max_length = MIN_MAX_LEN if max_length < MIN_MAX_LEN
39
-
40
- tasks.each do |task|
41
- puts "cap %-#{longest}s # %s" % [task.fully_qualified_name, task.brief_description(max_length)]
42
- end
43
-
44
- if all_tasks_length > tasks.length
45
- puts
46
- puts "Some tasks were not listed, either because they have no description,"
47
- puts "or because they are only used internally by other tasks. To see all"
48
- puts "tasks, type `#{File.basename($0)} -Tv'."
49
- end
50
-
51
- puts
52
- puts "Extended help may be available for these tasks."
53
- puts "Type `#{File.basename($0)} -e taskname' to view it."
54
- end
55
- end
56
-
57
- def explain_task(config, name) #:nodoc:
58
- task = config.find_task(name)
59
- if task.nil?
60
- warn "The task `#{name}' does not exist."
61
- else
62
- puts "-" * HEADER_LEN
63
- puts "cap #{name}"
64
- puts "-" * HEADER_LEN
65
-
66
- if task.description.empty?
67
- puts "There is no description for this task."
68
- else
69
- puts format_text(task.description)
70
- end
71
-
72
- puts
73
- end
74
- end
75
-
76
- def long_help #:nodoc:
77
- help_text = File.read(File.join(File.dirname(__FILE__), "help.txt"))
78
- self.class.ui.page_at = self.class.ui.output_rows - 2
79
- self.class.ui.say format_text(help_text)
80
- end
81
-
82
- def format_text(text) #:nodoc:
83
- formatted = ""
84
- text.each_line do |line|
85
- indentation = line[/^\s+/] || ""
86
- indentation_size = indentation.split(//).inject(0) { |c,s| c + (s[0] == ?\t ? 8 : 1) }
87
- lines = line.strip.gsub(/(.{1,#{output_columns - indentation_size}})(?:\s+|\Z)/, "\\1\n").split(/\n/)
88
- if lines.empty?
89
- formatted << "\n"
90
- else
91
- formatted << lines.map { |l| "#{indentation}#{l}\n" }.join
92
- end
93
- end
94
- formatted
95
- end
96
-
97
- def output_columns #:nodoc:
98
- @output_columns ||= self.class.ui.output_cols > 80 ? 80 : self.class.ui.output_cols
99
- end
100
- end
101
- end
102
- end
@@ -1,53 +0,0 @@
1
- -----------------------------
2
- <%= color('Capistrano', :bold) %>
3
- -----------------------------
4
-
5
- Capistrano is a utility for automating the execution of commands across multiple remote machines. It was originally conceived as an aid to deploy Ruby on Rails web applications, but has since evolved to become a much more general-purpose tool.
6
-
7
- The command-line interface to Capistrano is via the `cap' command.
8
-
9
- cap [ option ] ... action ...
10
-
11
- The following options are understood:
12
-
13
- <%= color '-e, --explain TASK', :bold %>
14
- Displays the extended description of the given task. Not all tasks will have an extended description, but for those that do, this can provide a wealth of additional usage information, such as describing environment variables or settings that can affect the execution of the task.
15
-
16
- <%= color '-F, --default-config', :bold %>
17
- By default, cap will search for a config file named `Capfile' or `capfile' in the current directory, or in any parent directory, and will automatically load it. However, if you specify the -f flag (see below), cap will use that file instead of the default config. If you want to use both the default config, and files loaded via -f, you can specify -F to force cap to search for and load the default config, even if additional files were specified via -f.
18
-
19
- <%= color '-f, --file FILE', :bold %>
20
- Causes the named file to be loaded. Capistrano will search both its own recipe directory, as well as the current directory, looking for the named file. An ".rb" extension is optional. The -f option may be given any number of times, but if it is given, it will take the place of the normal `Capfile' or `capfile' detection. Use -F if you want the default capfile to be loaded when you use -f.
21
-
22
- <%= color '-H, --long-help', :bold %>
23
- Displays this document and exits.
24
-
25
- <%= color '-h, --help', :bold %>
26
- Shows a brief summary of these options and exits.
27
-
28
- <%= color '-p, --password', :bold %>
29
- Normally, cap will prompt for the password on-demand, the first time it is needed. This can make it hard to walk away from Capistrano, since you might not know if it will prompt for a password down the road. In such cases, you can use the -p option to force cap to prompt for the password immediately.
30
-
31
- <%= color '-q, --quiet', :bold %>
32
- Display only critical error messages. All other output is suppressed.
33
-
34
- <%= color '-S, --set-before NAME=VALUE', :bold %>
35
- Sets the given variable to the given value, before loading any recipe files. This is useful if you have a recipe file that depends on a certain variable being set, at the time it is loaded.
36
-
37
- <%= color '-s, --set NAME=VALUE', :bold %>
38
- Sets the given variable to the given value, after loading all recipe files. This is useful when you want to override the value of a variable which is used in a task. Note that this will set the variables too late for them to affect conditions that are executed as the recipes are loaded.
39
-
40
- <%= color '-T, --tasks', :bold %>
41
- Displays the list of all tasks in all loaded recipe files. If a task has no description, or if the description starts with the [internal] tag, the task will not be listed unless you also specify -v.
42
-
43
- <%= color '-V, --version', :bold %>
44
- Shows the current Capistrano version number and exits.
45
-
46
- <%= color '-v, --verbose', :bold %>
47
- Increase the verbosity. You can specify this option up to three times to further increase verbosity. By default, cap will use maximum verbosity, but if you specify an explicit verbosity, that will be used instead. See also -q.
48
-
49
- <%= color '-X, --skip-system-config', :bold %>
50
- By default, cap will look for and (if it exists) load the global system configuration file located in /etc/capistrano.conf. If you don't want cap to load that file, give this option.
51
-
52
- <%= color '-x, --skip-user-config', :bold %>
53
- By default, cap will look for and (if it exists) load the user-specific configuration file located in $HOME/.caprc. If you don't want cap to load that file, give this option.
@@ -1,183 +0,0 @@
1
- require 'optparse'
2
-
3
- module Capistrano
4
- class CLI
5
- module Options
6
- def self.included(base)
7
- base.extend(ClassMethods)
8
- end
9
-
10
- module ClassMethods
11
- # Return a new CLI instance with the given arguments pre-parsed and
12
- # ready for execution.
13
- def parse(args)
14
- cli = new(args)
15
- cli.parse_options!
16
- cli
17
- end
18
- end
19
-
20
- # The hash of (parsed) command-line options
21
- attr_reader :options
22
-
23
- # Return an OptionParser instance that defines the acceptable command
24
- # line switches for Capistrano, and what their corresponding behaviors
25
- # are.
26
- def option_parser #:nodoc:
27
- @option_parser ||= OptionParser.new do |opts|
28
- opts.banner = "Usage: #{File.basename($0)} [options] action ..."
29
-
30
- opts.on("-e", "--explain TASK",
31
- "Displays help (if available) for the task."
32
- ) { |value| options[:explain] = value }
33
-
34
- opts.on("-F", "--default-config",
35
- "Always use default config, even with -f."
36
- ) { options[:default_config] = true }
37
-
38
- opts.on("-f", "--file FILE",
39
- "A recipe file to load. May be given more than once."
40
- ) { |value| options[:recipes] << value }
41
-
42
- opts.on("-H", "--long-help", "Explain these options.") do
43
- long_help
44
- exit
45
- end
46
-
47
- opts.on("-h", "--help", "Display this help message.") do
48
- puts opts
49
- exit
50
- end
51
-
52
- opts.on("-p", "--password",
53
- "Immediately prompt for the password."
54
- ) { options[:password] = nil }
55
-
56
- opts.on("-q", "--quiet",
57
- "Make the output as quiet as possible."
58
- ) { options[:verbose] = 0 }
59
-
60
- opts.on("-S", "--set-before NAME=VALUE",
61
- "Set a variable before the recipes are loaded."
62
- ) do |pair|
63
- name, value = pair.split(/=/, 2)
64
- options[:pre_vars][name.to_sym] = value
65
- end
66
-
67
- opts.on("-s", "--set NAME=VALUE",
68
- "Set a variable after the recipes are loaded."
69
- ) do |pair|
70
- name, value = pair.split(/=/, 2)
71
- options[:vars][name.to_sym] = value
72
- end
73
-
74
- opts.on("-T", "--tasks",
75
- "List all tasks in the loaded recipe files."
76
- ) do
77
- options[:tasks] = true
78
- options[:verbose] ||= 0
79
- end
80
-
81
- opts.on("-V", "--version",
82
- "Display the Capistrano version, and exit."
83
- ) do
84
- require 'capistrano/version'
85
- puts "Capistrano v#{Capistrano::Version::STRING}"
86
- exit
87
- end
88
-
89
- opts.on("-v", "--verbose",
90
- "Be more verbose. May be given more than once."
91
- ) { options[:verbose] ||= 0; options[:verbose] += 1 }
92
-
93
- opts.on("-X", "--skip-system-config",
94
- "Don't load the system config file (capistrano.conf)"
95
- ) { options.delete(:sysconf) }
96
-
97
- opts.on("-x", "--skip-user-config",
98
- "Don't load the user config file (.caprc)"
99
- ) { options.delete(:dotfile) }
100
- end
101
- end
102
-
103
- # If the arguments to the command are empty, this will print the
104
- # allowed options and exit. Otherwise, it will parse the command
105
- # line and set up any default options.
106
- def parse_options! #:nodoc:
107
- @options = { :recipes => [], :actions => [],
108
- :vars => {}, :pre_vars => {},
109
- :sysconf => default_sysconf, :dotfile => default_dotfile }
110
-
111
- if args.empty?
112
- warn "Please specify at least one action to execute."
113
- warn option_parser
114
- exit
115
- end
116
-
117
- option_parser.parse!(args)
118
-
119
- # if no verbosity has been specified, be verbose
120
- options[:verbose] = 3 if !options.has_key?(:verbose)
121
-
122
- look_for_default_recipe_file! if options[:default_config] || options[:recipes].empty?
123
- extract_environment_variables!
124
-
125
- options[:actions].concat(args)
126
-
127
- password = options.has_key?(:password)
128
- options[:password] = Proc.new { self.class.password_prompt }
129
- options[:password] = options[:password].call if password
130
- end
131
-
132
- # Extracts name=value pairs from the remaining command-line arguments
133
- # and assigns them as environment variables.
134
- def extract_environment_variables! #:nodoc:
135
- args.delete_if do |arg|
136
- next unless arg.match(/^(\w+)=(.*)$/)
137
- ENV[$1] = $2
138
- end
139
- end
140
-
141
- # Looks for a default recipe file in the current directory.
142
- def look_for_default_recipe_file! #:nodoc:
143
- current = Dir.pwd
144
-
145
- loop do
146
- %w(Capfile capfile).each do |file|
147
- if File.file?(file)
148
- options[:recipes] << file
149
- return
150
- end
151
- end
152
-
153
- pwd = Dir.pwd
154
- Dir.chdir("..")
155
- break if pwd == Dir.pwd # if changing the directory made no difference, then we're at the top
156
- end
157
-
158
- Dir.chdir(current)
159
- end
160
-
161
- def default_sysconf #:nodoc:
162
- File.join(sysconf_directory, "capistrano.conf")
163
- end
164
-
165
- def default_dotfile #:nodoc:
166
- File.join(home_directory, ".caprc")
167
- end
168
-
169
- def sysconf_directory #:nodoc:
170
- # TODO if anyone cares, feel free to submit a patch that uses a more
171
- # appropriate location for this file in Windows.
172
- ENV["SystemRoot"] || '/etc'
173
- end
174
-
175
- def home_directory #:nodoc:
176
- ENV["HOME"] ||
177
- (ENV["HOMEPATH"] && "#{ENV["HOMEDRIVE"]}#{ENV["HOMEPATH"]}") ||
178
- "/"
179
- end
180
-
181
- end
182
- end
183
- end
@@ -1,28 +0,0 @@
1
- require 'highline'
2
-
3
- # work around problem where HighLine detects an eof on $stdin and raises an
4
- # error.
5
- HighLine.track_eof = false
6
-
7
- module Capistrano
8
- class CLI
9
- module UI
10
- def self.included(base) #:nodoc:
11
- base.extend(ClassMethods)
12
- end
13
-
14
- module ClassMethods
15
- # Return the object that provides UI-specific methods, such as prompts
16
- # and more.
17
- def ui
18
- @ui ||= HighLine.new
19
- end
20
-
21
- # Prompt for a password using echo suppression.
22
- def password_prompt(prompt="Password: ")
23
- ui.ask(prompt) { |q| q.echo = false }
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,47 +0,0 @@
1
- require 'capistrano'
2
- require 'capistrano/cli/execute'
3
- require 'capistrano/cli/help'
4
- require 'capistrano/cli/options'
5
- require 'capistrano/cli/ui'
6
-
7
- module Capistrano
8
- # The CLI class encapsulates the behavior of capistrano when it is invoked
9
- # as a command-line utility. This allows other programs to embed Capistrano
10
- # and preserve its command-line semantics.
11
- class CLI
12
- # The array of (unparsed) command-line options
13
- attr_reader :args
14
-
15
- # Create a new CLI instance using the given array of command-line parameters
16
- # to initialize it. By default, +ARGV+ is used, but you can specify a
17
- # different set of parameters (such as when embedded cap in a program):
18
- #
19
- # require 'capistrano/cli'
20
- # Capistrano::CLI.parse(%w(-vvvv -r config/deploy update_code)).execute!
21
- #
22
- # Note that you can also embed cap directly by creating a new Configuration
23
- # instance and setting it up, but you'll often wind up duplicating logic
24
- # defined in the CLI class. The above snippet, redone using the Configuration
25
- # class directly, would look like:
26
- #
27
- # require 'capistrano'
28
- # require 'capistrano/cli'
29
- # config = Capistrano::Configuration.new
30
- # config.logger_level = Capistrano::Logger::TRACE
31
- # config.set(:password) { Capistrano::CLI.password_prompt }
32
- # config.load "config/deploy"
33
- # config.update_code
34
- #
35
- # There may be times that you want/need the additional control offered by
36
- # manipulating the Configuration directly, but generally interfacing with
37
- # the CLI class is recommended.
38
- def initialize(args)
39
- @args = args.dup
40
- $stdout.sync = true # so that Net::SSH prompts show up
41
- end
42
-
43
- # Mix-in the actual behavior
44
- include Execute, Options, UI
45
- include Help # needs to be included last, because it overrides some methods
46
- end
47
- end
@@ -1,161 +0,0 @@
1
- require 'capistrano/errors'
2
-
3
- module Capistrano
4
-
5
- # This class encapsulates a single command to be executed on a set of remote
6
- # machines, in parallel.
7
- class Command
8
- attr_reader :command, :sessions, :options
9
-
10
- def self.process(command, sessions, options={}, &block)
11
- new(command, sessions, options, &block).process!
12
- end
13
-
14
- # Instantiates a new command object. The +command+ must be a string
15
- # containing the command to execute. +sessions+ is an array of Net::SSH
16
- # session instances, and +options+ must be a hash containing any of the
17
- # following keys:
18
- #
19
- # * +logger+: (optional), a Capistrano::Logger instance
20
- # * +data+: (optional), a string to be sent to the command via it's stdin
21
- # * +env+: (optional), a string or hash to be interpreted as environment
22
- # variables that should be defined for this command invocation.
23
- def initialize(command, sessions, options={}, &block)
24
- @command = command.strip.gsub(/\r?\n/, "\\\n")
25
- @sessions = sessions
26
- @options = options
27
- @callback = block
28
- @channels = open_channels
29
- end
30
-
31
- # Processes the command in parallel on all specified hosts. If the command
32
- # fails (non-zero return code) on any of the hosts, this will raise a
33
- # Capistrano::CommandError.
34
- def process!
35
- since = Time.now
36
- loop do
37
- active = 0
38
- @channels.each do |ch|
39
- next if ch[:closed]
40
- active += 1
41
- ch.connection.process(true)
42
- end
43
-
44
- break if active == 0
45
- if Time.now - since >= 1
46
- since = Time.now
47
- @channels.each { |ch| ch.connection.ping! }
48
- end
49
- sleep 0.01 # a brief respite, to keep the CPU from going crazy
50
- end
51
-
52
- logger.trace "command finished" if logger
53
-
54
- if (failed = @channels.select { |ch| ch[:status] != 0 }).any?
55
- hosts = failed.map { |ch| ch[:server] }
56
- error = CommandError.new("command #{command.inspect} failed on #{hosts.join(',')}")
57
- error.hosts = hosts
58
- raise error
59
- end
60
-
61
- self
62
- end
63
-
64
- # Force the command to stop processing, by closing all open channels
65
- # associated with this command.
66
- def stop!
67
- @channels.each do |ch|
68
- ch.close unless ch[:closed]
69
- end
70
- end
71
-
72
- private
73
-
74
- def logger
75
- options[:logger]
76
- end
77
-
78
- def open_channels
79
- sessions.map do |session|
80
- session.open_channel do |channel|
81
- server = session.xserver
82
-
83
- channel[:server] = server
84
- channel[:host] = server.host
85
- channel[:options] = options
86
-
87
- execute_command = Proc.new do |ch|
88
- logger.trace "executing command", ch[:server] if logger
89
- cmd = replace_placeholders(command, ch)
90
-
91
- if options[:shell] == false
92
- shell = nil
93
- else
94
- shell = "#{options[:shell] || "sh"} -c"
95
- cmd = cmd.gsub(/[$\\`"]/) { |m| "\\#{m}" }
96
- cmd = "\"#{cmd}\""
97
- end
98
-
99
- command_line = [environment, shell, cmd].compact.join(" ")
100
-
101
- ch.exec(command_line)
102
- ch.send_data(options[:data]) if options[:data]
103
- end
104
-
105
- if options[:pty]
106
- channel.request_pty(:want_reply => true)
107
- channel.on_success(&execute_command)
108
- channel.on_failure do |ch|
109
- # just log it, don't actually raise an exception, since the
110
- # process method will see that the status is not zero and will
111
- # raise an exception then.
112
- logger.important "could not open channel", ch[:server] if logger
113
- ch.close
114
- end
115
- else
116
- execute_command.call(channel)
117
- end
118
-
119
- channel.on_data do |ch, data|
120
- @callback[ch, :out, data] if @callback
121
- end
122
-
123
- channel.on_extended_data do |ch, type, data|
124
- @callback[ch, :err, data] if @callback
125
- end
126
-
127
- channel.on_request do |ch, request, reply, data|
128
- ch[:status] = data.read_long if request == "exit-status"
129
- end
130
-
131
- channel.on_close do |ch|
132
- ch[:closed] = true
133
- end
134
- end
135
- end
136
- end
137
-
138
- def replace_placeholders(command, channel)
139
- command.gsub(/\$CAPISTRANO:HOST\$/, channel[:host])
140
- end
141
-
142
- # prepare a space-separated sequence of variables assignments
143
- # intended to be prepended to a command, so the shell sets
144
- # the environment before running the command.
145
- # i.e.: options[:env] = {'PATH' => '/opt/ruby/bin:$PATH',
146
- # 'TEST' => '( "quoted" )'}
147
- # environment returns:
148
- # "env TEST=(\ \"quoted\"\ ) PATH=/opt/ruby/bin:$PATH"
149
- def environment
150
- return if options[:env].nil? || options[:env].empty?
151
- @environment ||= if String === options[:env]
152
- "env #{options[:env]}"
153
- else
154
- options[:env].inject("env") do |string, (name, value)|
155
- value = value.to_s.gsub(/[ "]/) { |m| "\\#{m}" }
156
- string << " #{name}=#{value}"
157
- end
158
- end
159
- end
160
- end
161
- end
@@ -1,35 +0,0 @@
1
- require 'capistrano/upload'
2
-
3
- module Capistrano
4
- class Configuration
5
- module Actions
6
- module FileTransfer
7
-
8
- # Store the given data at the given location on all servers targetted
9
- # by the current task. If <tt>:mode</tt> is specified it is used to
10
- # set the mode on the file.
11
- def put(data, path, options={})
12
- execute_on_servers(options) do |servers|
13
- targets = servers.map { |s| sessions[s] }
14
- Upload.process(targets, path, :data => data, :mode => options[:mode], :logger => logger)
15
- end
16
- end
17
-
18
- # Get file remote_path from FIRST server targetted by
19
- # the current task and transfer it to local machine as path.
20
- #
21
- # get "#{deploy_to}/current/log/production.log", "log/production.log.web"
22
- def get(remote_path, path, options = {})
23
- execute_on_servers(options.merge(:once => true)) do |servers|
24
- logger.info "downloading `#{servers.first.host}:#{remote_path}' to `#{path}'"
25
- sftp = sessions[servers.first].sftp
26
- sftp.connect unless sftp.state == :open
27
- sftp.get_file remote_path, path
28
- logger.debug "download finished"
29
- end
30
- end
31
-
32
- end
33
- end
34
- end
35
- end