Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
244 lines (201 sloc) 7.28 KB
require 'optparse'
module Capistrano
class CLI
module Options
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
# Return a new CLI instance with the given arguments pre-parsed and
# ready for execution.
def parse(args)
cli = new(args)
cli.parse_options!
cli
end
end
# The hash of (parsed) command-line options
attr_reader :options
# Return an OptionParser instance that defines the acceptable command
# line switches for Capistrano, and what their corresponding behaviors
# are.
def option_parser #:nodoc:
@logger = Logger.new
@option_parser ||= OptionParser.new do |opts|
opts.banner = "Usage: #{File.basename($0)} [options] action ..."
opts.on("-d", "--debug",
"Prompts before each remote command execution."
) { |value| options[:debug] = true }
opts.on("-e", "--explain TASK",
"Displays help (if available) for the task."
) { |value| options[:explain] = value }
opts.on("-F", "--default-config",
"Always use default config, even with -f."
) { options[:default_config] = true }
opts.on("-f", "--file FILE",
"A recipe file to load. May be given more than once."
) { |value| options[:recipes] << value }
opts.on("-H", "--long-help", "Explain these options and environment variables.") do
long_help
exit
end
opts.on("-h", "--help", "Display this help message.") do
puts opts
exit
end
opts.on("-l", "--logger [STDERR|STDOUT|file]",
"Choose logger method. STDERR used by default."
) do |value|
options[:output] = if value.nil? || value.upcase == 'STDERR'
# Using default logger.
nil
elsif value.upcase == 'STDOUT'
$stdout
else
value
end
end
opts.on("-n", "--dry-run",
"Prints out commands without running them."
) { |value| options[:dry_run] = true }
opts.on("-p", "--password",
"Immediately prompt for the password."
) { options[:password] = nil }
opts.on("-q", "--quiet",
"Make the output as quiet as possible."
) { options[:verbose] = 0 }
opts.on("-r", "--preserve-roles",
"Preserve task roles"
) { options[:preserve_roles] = true }
opts.on("-S", "--set-before NAME=VALUE",
"Set a variable before the recipes are loaded."
) do |pair|
name, value = pair.split(/=/, 2)
options[:pre_vars][name.to_sym] = value
end
opts.on("-s", "--set NAME=VALUE",
"Set a variable after the recipes are loaded."
) do |pair|
name, value = pair.split(/=/, 2)
options[:vars][name.to_sym] = value
end
opts.on("-T", "--tasks [PATTERN]",
"List all tasks (matching optional PATTERN) in the loaded recipe files."
) do |value|
options[:tasks] = if value
value
else
true
end
options[:verbose] ||= 0
end
opts.on("-t", "--tool",
"Abbreviates the output of -T for tool integration."
) { options[:tool] = true }
opts.on("-V", "--version",
"Display the Capistrano version, and exit."
) do
require 'capistrano/version'
puts "Capistrano v#{Capistrano::Version}"
exit
end
opts.on("-v", "--verbose",
"Be more verbose. May be given more than once."
) do
options[:verbose] ||= 0
options[:verbose] += 1
end
opts.on("-X", "--skip-system-config",
"Don't load the system config file (capistrano.conf)"
) { options.delete(:sysconf) }
opts.on("-x", "--skip-user-config",
"Don't load the user config file (.caprc)"
) { options.delete(:dotfile) }
end
end
# If the arguments to the command are empty, this will print the
# allowed options and exit. Otherwise, it will parse the command
# line and set up any default options.
def parse_options! #:nodoc:
@options = { :recipes => [], :actions => [],
:vars => {}, :pre_vars => {},
:sysconf => default_sysconf, :dotfile => default_dotfile }
if args.empty?
warn "Please specify at least one action to execute."
warn option_parser
exit
end
option_parser.parse!(args)
coerce_variable_types!
# if no verbosity has been specified, be verbose
options[:verbose] = 3 if !options.has_key?(:verbose)
look_for_default_recipe_file! if options[:default_config] || options[:recipes].empty?
extract_environment_variables!
options[:actions].concat(args)
password = options.has_key?(:password)
options[:password] = Proc.new { self.class.password_prompt }
options[:password] = options[:password].call if password
end
# Extracts name=value pairs from the remaining command-line arguments
# and assigns them as environment variables.
def extract_environment_variables! #:nodoc:
args.delete_if do |arg|
next unless arg.match(/^(\w+)=(.*)$/)
ENV[$1] = $2
end
end
# Looks for a default recipe file in the current directory.
def look_for_default_recipe_file! #:nodoc:
current = Dir.pwd
loop do
%w(Capfile capfile).each do |file|
if File.file?(file)
options[:recipes] << file
@logger.info "Using recipes from #{File.join(current,file)}"
return
end
end
pwd = Dir.pwd
Dir.chdir("..")
break if pwd == Dir.pwd # if changing the directory made no difference, then we're at the top
end
Dir.chdir(current)
end
def default_sysconf #:nodoc:
File.join(sysconf_directory, "capistrano.conf")
end
def default_dotfile #:nodoc:
File.join(home_directory, ".caprc")
end
def sysconf_directory #:nodoc:
# TODO if anyone cares, feel free to submit a patch that uses a more
# appropriate location for this file in Windows.
ENV["SystemRoot"] || '/etc'
end
def home_directory #:nodoc:
ENV["HOME"] ||
(ENV["HOMEPATH"] && "#{ENV["HOMEDRIVE"]}#{ENV["HOMEPATH"]}") ||
"/"
end
def coerce_variable_types!
[:pre_vars, :vars].each do |collection|
options[collection].keys.each do |key|
options[collection][key] = coerce_variable(options[collection][key])
end
end
end
def coerce_variable(value)
case value
when /^"(.*)"$/ then $1
when /^'(.*)'$/ then $1
when /^\d+$/ then value.to_i
when /^\d+\.\d*$/ then value.to_f
when "true" then true
when "false" then false
when "nil" then nil
else value
end
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.