aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails/command.rb
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib/rails/command.rb')
-rw-r--r--railties/lib/rails/command.rb121
1 files changed, 75 insertions, 46 deletions
diff --git a/railties/lib/rails/command.rb b/railties/lib/rails/command.rb
index f7753cbb83..6065e78fd1 100644
--- a/railties/lib/rails/command.rb
+++ b/railties/lib/rails/command.rb
@@ -1,70 +1,99 @@
-require 'rails/commands/commands_tasks'
+require "active_support"
+require "active_support/dependencies/autoload"
+require "active_support/core_ext/enumerable"
+require "active_support/core_ext/object/blank"
+require "active_support/core_ext/hash/transform_values"
+
+require "thor"
module Rails
- class Command #:nodoc:
- attr_reader :argv
+ module Command
+ extend ActiveSupport::Autoload
- def initialize(argv = [])
- @argv = argv
+ autoload :Behavior
+ autoload :Base
- @option_parser = build_option_parser
- @options = {}
- end
+ include Behavior
- def self.run(task_name, argv)
- command_name = command_name_for(task_name)
+ class << self
+ def hidden_commands # :nodoc:
+ @hidden_commands ||= []
+ end
- if command = command_for(command_name)
- command.new(argv).run(command_name)
- else
- Rails::CommandsTasks.new(argv).run_command!(task_name)
+ def environment # :nodoc:
+ ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
end
- end
- def run(command_name)
- parse_options_for(command_name)
- @option_parser.parse! @argv
+ # Receives a namespace, arguments and the behavior to invoke the command.
+ def invoke(namespace, args = [], **config)
+ namespace = namespace.to_s
+ namespace = "help" if namespace.blank? || Thor::HELP_MAPPINGS.include?(namespace)
+ namespace = "version" if %w( -v --version ).include? namespace
- public_send(command_name)
- end
-
- def self.options_for(command_name, &options_to_parse)
- @@command_options[command_name] = options_to_parse
- end
+ if command = find_by_namespace(namespace)
+ command.perform(namespace, args, config)
+ else
+ find_by_namespace("rake").perform(namespace, args, config)
+ end
+ end
- def self.set_banner(command_name, banner)
- options_for(command_name) { |opts, _| opts.banner = banner }
- end
+ # Rails finds namespaces similar to thor, it only adds one rule:
+ #
+ # Command names must end with "_command.rb". This is required because Rails
+ # looks in load paths and loads the command just before it's going to be used.
+ #
+ # find_by_namespace :webrat, :rails, :integration
+ #
+ # Will search for the following commands:
+ #
+ # "rails:webrat", "webrat:integration", "webrat"
+ #
+ # Notice that "rails:commands:webrat" could be loaded as well, what
+ # Rails looks for is the first and last parts of the namespace.
+ def find_by_namespace(name) # :nodoc:
+ lookups = [ name, "rails:#{name}" ]
- private
- @@commands = []
- @@command_options = {}
+ lookup(lookups)
- def parse_options_for(command_name)
- @@command_options.fetch(command_name, proc {}).call(@option_parser, @options)
+ namespaces = subclasses.index_by(&:namespace)
+ namespaces[(lookups & namespaces.keys).first]
end
- def build_option_parser
- OptionParser.new do |opts|
- opts.on('-h', '--help', 'Show this help.') do
- puts opts
- exit
- end
+ # Returns the root of the Rails engine or app running the command.
+ def root
+ if defined?(ENGINE_ROOT)
+ Pathname.new(ENGINE_ROOT)
+ elsif defined?(APP_PATH)
+ Pathname.new(File.expand_path("../..", APP_PATH))
end
end
- def self.inherited(command)
- @@commands << command
+ def print_commands # :nodoc:
+ sorted_groups.each { |b, n| print_list(b, n) }
end
- def self.command_name_for(task_name)
- task_name.gsub(':', '_').to_sym
+ def sorted_groups # :nodoc:
+ lookup!
+
+ groups = (subclasses - hidden_commands).group_by { |c| c.namespace.split(":").first }
+ groups.transform_values! { |commands| commands.flat_map(&:printing_commands).sort }
+
+ rails = groups.delete("rails")
+ [[ "rails", rails ]] + groups.sort.to_a
end
- def self.command_for(command_name)
- @@commands.find do |command|
- command.public_instance_methods.include?(command_name)
+ protected
+ def command_type
+ @command_type ||= "command"
end
- end
+
+ def lookup_paths
+ @lookup_paths ||= %w( rails/commands commands )
+ end
+
+ def file_lookup_paths
+ @file_lookup_paths ||= [ "{#{lookup_paths.join(',')}}", "**", "*_command.rb" ]
+ end
+ end
end
end