require 'capistrano/cli' require 'progressbar' module Flucti module CLI extend self def start adjust_environment reinterpret_help_option Flucti.boot cli = Capistrano::CLI.new(ARGV) cli.parse_options! cli.options[:verbose] = Capistrano::Logger::INFO cli.execute! end def tasks adjust_environment config = Capistrano::Configuration.new config.load File.dirname(__FILE__) + '/tasks.rb' return config end private def adjust_environment expose_constants fix_cap_recipe_loading fix_cap_tasks_brief_descriptions fix_cap_help_messages allow_for_lazy_env_var_naming end def expose_constants Object.class_eval do include Flucti include Flucti::Resources include Flucti::Utilities end end # Force Capistrano::CLI to load the needed recipe files, and only them. def fix_cap_recipe_loading override 'Capistrano::CLI::Execute#load_recipes' do def load_recipes(config) config.load(File.dirname(__FILE__) + '/tasks.rb') end end end # Fix brief description of tasks to allow the first sentence to be spanned # over multiple lines. def fix_cap_tasks_brief_descriptions override 'Capistrano::CLI::Help#output_columns' do def output_columns Flucti::Utilities::UserInterface.terminal_width - 3 end end override 'Capistrano::TaskDefinition#brief_description' do def brief_description(max_length=nil) brief = (description[/\A.*?\.(?=\s|$)/m] || description).gsub(/\n+/, ' ') if max_length && brief.length > max_length brief = brief[0,max_length-3] + "..." end brief end end end # Make help messages refer to the current command instead of the hard-coded # `cap' one. def fix_cap_help_messages override 'Capistrano::CLI::Help#puts' do def puts(*lines) super(*lines.map { |line| line.to_s.gsub(/\bcap\b/, Flucti::Utilities::Miscellaneous.command) }) end end end # Fix letter-casing for environment variable assignments. def allow_for_lazy_env_var_naming ARGV.each_with_index { |arg, pos| ARGV[pos] = arg.sub(/^(\w+)(=)/) { $1.upcase + $2 } } ENV.each { |key, value| ENV[key.upcase] ||= value } end # Replace the default help message with a list of tasks. def reinterpret_help_option if ARGV.empty? || %w(-h --help).map { |opt| ARGV.delete(opt) }.any? ARGV.unshift '-vT' end end private def override(fqn, &block) name, method = fqn.to_s.split('#', 2) if mod = Object.class_eval("#{name} if defined? #{name}") and (Kernel.respond_to?(method) || [:public, :protected, :private].any? { |v| mod.send("#{v}_method_defined?", method) }) mod.module_eval(&block) else require 'capistrano/version' raise "This library is incompatible with the current version of Capistrano (#{Capistrano::Version::STRING}). Failed to override `#{fqn}'." end end end end