2017-08-14 13:08:09 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-05-28 16:04:13 -04:00
|
|
|
require "active_support"
|
|
|
|
require "active_support/core_ext/enumerable"
|
|
|
|
require "active_support/core_ext/object/blank"
|
|
|
|
|
|
|
|
require "thor"
|
|
|
|
|
|
|
|
module Rails
|
|
|
|
module Command
|
2016-09-07 16:45:41 -04:00
|
|
|
extend ActiveSupport::Autoload
|
|
|
|
|
|
|
|
autoload :Behavior
|
|
|
|
autoload :Base
|
2016-05-28 16:04:13 -04:00
|
|
|
|
|
|
|
include Behavior
|
|
|
|
|
2017-01-17 00:09:00 -05:00
|
|
|
HELP_MAPPINGS = %w(-h -? --help)
|
|
|
|
|
2016-05-28 16:04:13 -04:00
|
|
|
class << self
|
|
|
|
def hidden_commands # :nodoc:
|
|
|
|
@hidden_commands ||= []
|
|
|
|
end
|
|
|
|
|
2016-09-07 16:45:41 -04:00
|
|
|
def environment # :nodoc:
|
2017-05-24 11:00:08 -04:00
|
|
|
ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || "development"
|
2016-05-28 16:04:13 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
# Receives a namespace, arguments and the behavior to invoke the command.
|
2017-02-23 12:15:28 -05:00
|
|
|
def invoke(full_namespace, args = [], **config)
|
|
|
|
namespace = full_namespace = full_namespace.to_s
|
2016-05-28 16:04:13 -04:00
|
|
|
|
2017-02-23 12:15:28 -05:00
|
|
|
if char = namespace =~ /:(\w+)$/
|
|
|
|
command_name, namespace = $1, namespace.slice(0, char)
|
2016-05-28 16:04:13 -04:00
|
|
|
else
|
2017-02-23 12:15:28 -05:00
|
|
|
command_name = namespace
|
|
|
|
end
|
|
|
|
|
2017-02-23 19:17:13 -05:00
|
|
|
command_name, namespace = "help", "help" if command_name.blank? || HELP_MAPPINGS.include?(command_name)
|
2021-05-13 13:26:41 -04:00
|
|
|
command_name, namespace, args = "application", "application", ["--help"] if rails_new_with_no_path?(args)
|
2017-02-23 19:13:44 -05:00
|
|
|
command_name, namespace = "version", "version" if %w( -v --version ).include?(command_name)
|
2017-02-23 12:15:28 -05:00
|
|
|
|
2021-03-03 17:13:36 -05:00
|
|
|
original_argv = ARGV.dup
|
|
|
|
ARGV.replace(args)
|
2020-02-18 00:59:06 -05:00
|
|
|
|
2017-02-23 12:30:49 -05:00
|
|
|
command = find_by_namespace(namespace, command_name)
|
|
|
|
if command && command.all_commands[command_name]
|
2017-02-23 12:15:28 -05:00
|
|
|
command.perform(command_name, args, config)
|
|
|
|
else
|
2021-02-14 13:30:05 -05:00
|
|
|
args = ["--describe", full_namespace] if HELP_MAPPINGS.include?(args[0])
|
2017-02-23 12:15:28 -05:00
|
|
|
find_by_namespace("rake").perform(full_namespace, args, config)
|
2016-05-28 16:04:13 -04:00
|
|
|
end
|
2020-02-18 00:59:06 -05:00
|
|
|
ensure
|
2021-03-03 17:13:36 -05:00
|
|
|
ARGV.replace(original_argv)
|
2016-05-28 16:04:13 -04:00
|
|
|
end
|
|
|
|
|
2016-12-19 20:20:10 -05:00
|
|
|
# Rails finds namespaces similar to Thor, it only adds one rule:
|
2016-05-28 16:04:13 -04:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
2021-02-13 05:32:56 -05:00
|
|
|
# find_by_namespace :webrat, :integration
|
2016-05-28 16:04:13 -04:00
|
|
|
#
|
|
|
|
# Will search for the following commands:
|
|
|
|
#
|
2021-02-13 05:32:56 -05:00
|
|
|
# "webrat", "webrat:integration", "rails:webrat", "rails:webrat:integration"
|
2016-05-28 16:04:13 -04:00
|
|
|
#
|
2017-02-23 12:15:28 -05:00
|
|
|
def find_by_namespace(namespace, command_name = nil) # :nodoc:
|
|
|
|
lookups = [ namespace ]
|
|
|
|
lookups << "#{namespace}:#{command_name}" if command_name
|
|
|
|
lookups.concat lookups.map { |lookup| "rails:#{lookup}" }
|
2016-05-28 16:04:13 -04:00
|
|
|
|
|
|
|
lookup(lookups)
|
|
|
|
|
|
|
|
namespaces = subclasses.index_by(&:namespace)
|
|
|
|
namespaces[(lookups & namespaces.keys).first]
|
|
|
|
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 print_commands # :nodoc:
|
2018-10-04 18:55:57 -04:00
|
|
|
commands.each { |command| puts(" #{command}") }
|
2016-05-28 16:04:13 -04:00
|
|
|
end
|
|
|
|
|
2018-10-04 18:55:57 -04:00
|
|
|
private
|
|
|
|
COMMANDS_IN_USAGE = %w(generate console server test test:system dbconsole new)
|
|
|
|
private_constant :COMMANDS_IN_USAGE
|
2016-05-28 16:04:13 -04:00
|
|
|
|
2021-05-13 13:26:41 -04:00
|
|
|
def rails_new_with_no_path?(args)
|
|
|
|
args == ["new"]
|
|
|
|
end
|
|
|
|
|
2018-10-04 18:55:57 -04:00
|
|
|
def commands
|
|
|
|
lookup!
|
2016-05-28 16:04:13 -04:00
|
|
|
|
2018-10-04 18:55:57 -04:00
|
|
|
visible_commands = (subclasses - hidden_commands).flat_map(&:printing_commands)
|
|
|
|
|
|
|
|
(visible_commands - COMMANDS_IN_USAGE).sort
|
|
|
|
end
|
2016-05-28 16:04:13 -04:00
|
|
|
|
2016-12-23 05:20:01 -05:00
|
|
|
def command_type # :doc:
|
2016-05-28 16:04:13 -04:00
|
|
|
@command_type ||= "command"
|
|
|
|
end
|
|
|
|
|
2016-12-23 05:20:01 -05:00
|
|
|
def lookup_paths # :doc:
|
2016-05-28 16:04:13 -04:00
|
|
|
@lookup_paths ||= %w( rails/commands commands )
|
|
|
|
end
|
|
|
|
|
2016-12-23 05:20:01 -05:00
|
|
|
def file_lookup_paths # :doc:
|
2016-05-28 16:04:13 -04:00
|
|
|
@file_lookup_paths ||= [ "{#{lookup_paths.join(',')}}", "**", "*_command.rb" ]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|