From 520b8b59110dd130c89b317b6bd65d8644c7836f Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Wed, 18 Nov 2009 16:28:12 -0800 Subject: Final steps toward clean rails "foo"; cd foo; gem bundle; script/server working --- railties/lib/rails/application.rb | 6 +----- railties/lib/rails/commands/server.rb | 4 +++- railties/lib/rails/generators/rails/app/app_generator.rb | 2 +- railties/lib/rails/generators/rails/app/templates/config.ru | 2 +- .../lib/rails/generators/rails/app/templates/config/application.rb | 2 +- .../lib/rails/generators/rails/app/templates/config/environment.rb | 2 +- railties/lib/rails/generators/rails/app/templates/script/server | 3 +++ railties/lib/rails/rack/log_tailer.rb | 5 ++--- 8 files changed, 13 insertions(+), 13 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 7c2d8eab67..c8e4d8943b 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -3,11 +3,6 @@ module Rails include Initializable class << self - def inherited(klass) - Rails.application ||= klass unless klass.name =~ /Rails/ - super - end - # Stub out App initialize def initialize! new @@ -38,6 +33,7 @@ module Rails end def initialize + Rails.application ||= self run_initializers(self) end diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 2c90851fb2..450970e4f5 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -3,11 +3,13 @@ require 'action_dispatch' require 'fileutils' require 'optparse' +# Waiting for Rack::Server patch + options = { :Port => 3000, :Host => "0.0.0.0", :environment => (ENV['RAILS_ENV'] || "development").dup, - :config => "#{Rails.root}/config.ru", + :config => $config_ru, :detach => false, :debugger => false } diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 2bcea4bc8f..d970bd8db8 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -50,7 +50,7 @@ module Rails::Generators def create_root_files copy_file "Rakefile" copy_file "README" - copy_file "config.ru" + template "config.ru" template "Gemfile" end diff --git a/railties/lib/rails/generators/rails/app/templates/config.ru b/railties/lib/rails/generators/rails/app/templates/config.ru index 509a0da5b7..fea9ba7fe5 100644 --- a/railties/lib/rails/generators/rails/app/templates/config.ru +++ b/railties/lib/rails/generators/rails/app/templates/config.ru @@ -2,4 +2,4 @@ require ::File.expand_path('../config/environment', __FILE__) # Dispatch the request -run Rails.application +run <%= app_name.classify %> diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 8008c6ba07..43067b2530 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -1,6 +1,6 @@ require File.expand_path('../boot', __FILE__) -Rails::Initializer.run do |config| +class <%= app_name.classify %> < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environment.rb b/railties/lib/rails/generators/rails/app/templates/config/environment.rb index 0bb191f205..1c35ae44d2 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environment.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/environment.rb @@ -2,4 +2,4 @@ require File.expand_path('../application', __FILE__) # Initialize the rails application -Rails.initialize! +<%= app_name.classify %>.initialize! diff --git a/railties/lib/rails/generators/rails/app/templates/script/server b/railties/lib/rails/generators/rails/app/templates/script/server index a7aaee2953..b4864eb745 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/server +++ b/railties/lib/rails/generators/rails/app/templates/script/server @@ -1,2 +1,5 @@ require File.expand_path('../../config/application', __FILE__) +# Temporary patch until Rack::Server +# Will be Rails::Server.start(File.expand_path("../../config.ru", __FILE__)) +$config_ru = File.expand_path("../../config.ru", __FILE__) require 'rails/commands/server' diff --git a/railties/lib/rails/rack/log_tailer.rb b/railties/lib/rails/rack/log_tailer.rb index a237cee6bc..f3ebebf67d 100644 --- a/railties/lib/rails/rack/log_tailer.rb +++ b/railties/lib/rails/rack/log_tailer.rb @@ -1,12 +1,11 @@ module Rails module Rack class LogTailer - EnvironmentLog = "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log" - def initialize(app, log = nil) + @default_log = "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log" @app = app - path = Pathname.new(log || EnvironmentLog).cleanpath + path = Pathname.new(log || @default_log).cleanpath @cursor = ::File.size(path) @last_checked = Time.now.to_f -- cgit v1.2.3 From c7c39f52dcce4ea6de2051ee7816c0cb9d583f8f Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 19 Nov 2009 15:24:00 -0800 Subject: Revert "Final steps toward clean rails "foo"; cd foo; gem bundle; script/server working" Broke stuff. This reverts commit 520b8b59110dd130c89b317b6bd65d8644c7836f. --- railties/lib/rails/application.rb | 6 +++++- railties/lib/rails/commands/server.rb | 4 +--- railties/lib/rails/generators/rails/app/app_generator.rb | 2 +- railties/lib/rails/generators/rails/app/templates/config.ru | 2 +- .../lib/rails/generators/rails/app/templates/config/application.rb | 2 +- .../lib/rails/generators/rails/app/templates/config/environment.rb | 2 +- railties/lib/rails/generators/rails/app/templates/script/server | 3 --- railties/lib/rails/rack/log_tailer.rb | 5 +++-- 8 files changed, 13 insertions(+), 13 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index c8e4d8943b..7c2d8eab67 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -3,6 +3,11 @@ module Rails include Initializable class << self + def inherited(klass) + Rails.application ||= klass unless klass.name =~ /Rails/ + super + end + # Stub out App initialize def initialize! new @@ -33,7 +38,6 @@ module Rails end def initialize - Rails.application ||= self run_initializers(self) end diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 450970e4f5..2c90851fb2 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -3,13 +3,11 @@ require 'action_dispatch' require 'fileutils' require 'optparse' -# Waiting for Rack::Server patch - options = { :Port => 3000, :Host => "0.0.0.0", :environment => (ENV['RAILS_ENV'] || "development").dup, - :config => $config_ru, + :config => "#{Rails.root}/config.ru", :detach => false, :debugger => false } diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index d970bd8db8..2bcea4bc8f 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -50,7 +50,7 @@ module Rails::Generators def create_root_files copy_file "Rakefile" copy_file "README" - template "config.ru" + copy_file "config.ru" template "Gemfile" end diff --git a/railties/lib/rails/generators/rails/app/templates/config.ru b/railties/lib/rails/generators/rails/app/templates/config.ru index fea9ba7fe5..509a0da5b7 100644 --- a/railties/lib/rails/generators/rails/app/templates/config.ru +++ b/railties/lib/rails/generators/rails/app/templates/config.ru @@ -2,4 +2,4 @@ require ::File.expand_path('../config/environment', __FILE__) # Dispatch the request -run <%= app_name.classify %> +run Rails.application diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 43067b2530..8008c6ba07 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -1,6 +1,6 @@ require File.expand_path('../boot', __FILE__) -class <%= app_name.classify %> < Rails::Application +Rails::Initializer.run do |config| # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environment.rb b/railties/lib/rails/generators/rails/app/templates/config/environment.rb index 1c35ae44d2..0bb191f205 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environment.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/environment.rb @@ -2,4 +2,4 @@ require File.expand_path('../application', __FILE__) # Initialize the rails application -<%= app_name.classify %>.initialize! +Rails.initialize! diff --git a/railties/lib/rails/generators/rails/app/templates/script/server b/railties/lib/rails/generators/rails/app/templates/script/server index b4864eb745..a7aaee2953 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/server +++ b/railties/lib/rails/generators/rails/app/templates/script/server @@ -1,5 +1,2 @@ require File.expand_path('../../config/application', __FILE__) -# Temporary patch until Rack::Server -# Will be Rails::Server.start(File.expand_path("../../config.ru", __FILE__)) -$config_ru = File.expand_path("../../config.ru", __FILE__) require 'rails/commands/server' diff --git a/railties/lib/rails/rack/log_tailer.rb b/railties/lib/rails/rack/log_tailer.rb index f3ebebf67d..a237cee6bc 100644 --- a/railties/lib/rails/rack/log_tailer.rb +++ b/railties/lib/rails/rack/log_tailer.rb @@ -1,11 +1,12 @@ module Rails module Rack class LogTailer + EnvironmentLog = "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log" + def initialize(app, log = nil) - @default_log = "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log" @app = app - path = Pathname.new(log || @default_log).cleanpath + path = Pathname.new(log || EnvironmentLog).cleanpath @cursor = ::File.size(path) @last_checked = Time.now.to_f -- cgit v1.2.3 From e1935e3c0c35f8f1196239e2b1213c4436049fa5 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sat, 21 Nov 2009 10:45:42 -0800 Subject: Fix Rails::Rack::Static deprecated constant proxy --- railties/lib/rails/rack/static.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/rack/static.rb b/railties/lib/rails/rack/static.rb index d6b8face27..ebe8b9e103 100644 --- a/railties/lib/rails/rack/static.rb +++ b/railties/lib/rails/rack/static.rb @@ -1,5 +1,5 @@ require 'action_dispatch' module Rails::Rack - Static = Deprecation::DeprecatedConstantProxy.new('Rails::Rack::Static', ActionDispatch::Static) + Static = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Rails::Rack::Static', ActionDispatch::Static) end -- cgit v1.2.3 From d6f10126eb12e08ad670f803d237b942ebae5018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 20 Nov 2009 09:29:35 -0200 Subject: Also load generators at lib/rails_generators. Signed-off-by: Yehuda Katz --- railties/lib/rails/generators.rb | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 19412c259e..9f274b9edc 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -86,28 +86,16 @@ module Rails @options ||= DEFAULT_OPTIONS.dup end - # We have two scenarios here: when rubygems is loaded and when bundler is - # being used. If rubygems is loaded, we get all generators paths from loaded - # specs. Otherwise we just have to look into vendor/gems/gems. - # - def self.gems_generators_paths - paths = [] - - if defined?(Gem) && Gem.respond_to?(:loaded_specs) - Gem.loaded_specs.each do |name, spec| - generator_path = File.join(spec.full_gem_path, "lib/generators") - paths << generator_path if File.exist?(generator_path) - end + def self.gems_generators_paths #:nodoc: + return [] unless defined?(Gem) && Gem.respond_to?(:loaded_specs) + Gem.loaded_specs.inject([]) do |paths, (name, spec)| + paths += Dir[File.join(spec.full_gem_path, "lib/{generators,rails_generators}")] end - - paths end - # Load paths from plugin. - # - def self.plugins_generators_paths + def self.plugins_generators_paths #:nodoc: return [] unless Rails.root - Dir[File.join(Rails.root, "vendor", "plugins", "*", "lib", "generators")] + Dir[File.join(Rails.root, "vendor", "plugins", "*", "lib", "{generators,rails_generators}")] end # Hold configured generators fallbacks. If a plugin developer wants a @@ -147,8 +135,8 @@ module Rails def self.load_paths @load_paths ||= begin paths = [] - paths << File.join(Rails.root, "lib", "generators") if Rails.root - paths << File.join(Thor::Util.user_home, ".rails", "generators") + paths += Dir[File.join(Rails.root, "lib", "{generators,rails_generators}")] if Rails.root + paths += Dir[File.join(Thor::Util.user_home, ".rails", "{generators,rails_generators}")] paths += self.plugins_generators_paths paths += self.gems_generators_paths paths << File.expand_path(File.join(File.dirname(__FILE__), "generators")) @@ -278,13 +266,13 @@ module Rails # By default, Rails strips the generator namespace to make invocations # easier. This method generaters the both possibilities names. - def self.generator_names(first, second) + def self.generator_names(first, second) #:nodoc: [ "#{first}:generators:#{second}", "#{first}:#{second}" ] end # Try callbacks for the given base. # - def self.invoke_fallbacks_for(name, base) + def self.invoke_fallbacks_for(name, base) #:nodoc: return nil unless base && fallbacks[base.to_sym] invoked_fallbacks = [] -- cgit v1.2.3 From d0aa0cfbd76a919e536e76d65419930fb7fe31da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 20 Nov 2009 12:16:01 -0200 Subject: Ensure generator fallbacks work even when a context is given. Signed-off-by: Yehuda Katz --- railties/lib/rails/generators.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 9f274b9edc..85c2fd52a4 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -198,7 +198,7 @@ module Rails return klass if klass end - invoke_fallbacks_for(name, base) + invoke_fallbacks_for(name, base) || invoke_fallbacks_for(context, name) end # Receives a namespace, arguments and the behavior to invoke the generator. -- cgit v1.2.3 From 35eda7d6d2ea13b4e42eeea9f11245e22c245fc2 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 23 Nov 2009 15:36:48 -0600 Subject: Fixed that the debugger wouldn't go into IRB mode because of left-over ARGVs [DHH] --- railties/lib/rails/rack/debugger.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/rack/debugger.rb b/railties/lib/rails/rack/debugger.rb index aa2711c616..0a7b405553 100644 --- a/railties/lib/rails/rack/debugger.rb +++ b/railties/lib/rails/rack/debugger.rb @@ -4,6 +4,8 @@ module Rails def initialize(app) @app = app + ARGV.clear # clear ARGV so that script/server options aren't passed to IRB + require_library_or_gem 'ruby-debug' ::Debugger.start ::Debugger.settings[:autoeval] = true if ::Debugger.respond_to?(:settings) -- cgit v1.2.3 From eeb1f472a5561e769b7e6df923f4c91a7d72379d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 23 Nov 2009 16:10:43 -0800 Subject: RAILS_ENV falls back to RACK_ENV --- railties/lib/rails/initializer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/initializer.rb b/railties/lib/rails/initializer.rb index 44d04688c8..44101dcc94 100644 --- a/railties/lib/rails/initializer.rb +++ b/railties/lib/rails/initializer.rb @@ -1,6 +1,6 @@ require "rails" # In case people require this file directly -RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) +RAILS_ENV = (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development').dup unless defined?(RAILS_ENV) module Rails class Initializer @@ -14,4 +14,4 @@ module Rails end end end -end \ No newline at end of file +end -- cgit v1.2.3 From 58dec093536e63e61a9d69341da539048367f5e1 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Mon, 23 Nov 2009 17:05:13 -0800 Subject: Update rails application root detection to take into consideration a callstack that includes the rack library --- railties/lib/rails/configuration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 102a0836dc..3f43a48e2e 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -31,7 +31,7 @@ module Rails def root @root ||= begin call_stack = caller.map { |p| p.split(':').first } - root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails] } + root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] } root_path = File.dirname(root_path) while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/config.ru") -- cgit v1.2.3 From a080323cb040da5f0a63846260147b7ee730d6a1 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Mon, 23 Nov 2009 17:06:10 -0800 Subject: Refactor script/server into an object that inherits from Rack::Server --- railties/lib/rails/commands/server.rb | 120 +++++++++++---------- .../generators/rails/app/templates/script/server | 1 + 2 files changed, 62 insertions(+), 59 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 2c90851fb2..ff2282a534 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -1,73 +1,75 @@ -require 'action_dispatch' - require 'fileutils' require 'optparse' +require 'action_dispatch' -options = { - :Port => 3000, - :Host => "0.0.0.0", - :environment => (ENV['RAILS_ENV'] || "development").dup, - :config => "#{Rails.root}/config.ru", - :detach => false, - :debugger => false -} +module Rails + class Server < ::Rack::Server + class Options + def parse!(args) + options = {} + args = args.dup + opt_parser = OptionParser.new do |opts| + opts.on("-p", "--port=port", Integer, + "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v } + opts.on("-b", "--binding=ip", String, + "Binds Rails to the specified ip.", "Default: #{options[:Host]}") { |v| options[:Host] = v } + opts.on("-c", "--config=file", String, + "Use custom rackup configuration file") { |v| options[:config] = v } + opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:daemonize] = true } + opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { options[:debugger] = true } + opts.on("-e", "--environment=name", String, + "Specifies the environment to run this server under (test/development/production).", + "Default: #{options[:environment]}") { |v| options[:environment] = v } -ARGV.clone.options do |opts| - opts.on("-p", "--port=port", Integer, - "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v } - opts.on("-b", "--binding=ip", String, - "Binds Rails to the specified ip.", "Default: #{options[:Host]}") { |v| options[:Host] = v } - opts.on("-c", "--config=file", String, - "Use custom rackup configuration file") { |v| options[:config] = v } - opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:detach] = true } - opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { options[:debugger] = true } - opts.on("-e", "--environment=name", String, - "Specifies the environment to run this server under (test/development/production).", - "Default: #{options[:environment]}") { |v| options[:environment] = v } + opts.separator "" - opts.separator "" + opts.on("-h", "--help", "Show this help message.") { puts opts; exit } + end - opts.on("-h", "--help", "Show this help message.") { puts opts; exit } + opt_parser.parse! args - opts.parse! -end + options[:server] = args.shift + options + end + end -server = Rack::Handler.get(ARGV.first) rescue nil -unless server - begin - server = Rack::Handler::Mongrel - rescue LoadError => e - server = Rack::Handler::WEBrick - end -end + def opt_parser + Options.new + end -puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" -puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}" + def start + puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" + puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}" + puts "=> Call with -d to detach" unless options[:daemonize] + trap(:INT) { exit } + puts "=> Ctrl-C to shutdown server" unless options[:daemonize] -if options[:detach] - Process.daemon - pid = "#{Rails.root}/tmp/pids/server.pid" - File.open(pid, 'w'){ |f| f.write(Process.pid) } - at_exit { File.delete(pid) if File.exist?(pid) } -end - -ENV["RAILS_ENV"] = options[:environment] -RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV) - -app = Rack::Builder.new { - use Rails::Rack::LogTailer unless options[:detach] - use Rails::Rack::Debugger if options[:debugger] - run ActionDispatch::Utils.parse_config(options[:config]) -}.to_app + ENV["RAILS_ENV"] = options[:environment] + RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV) -puts "=> Call with -d to detach" + super + ensure + puts 'Exiting' unless options[:daemonize] + end -trap(:INT) { exit } + def middleware + middlewares = [] + middlewares << [Rails::Rack::LogTailer] unless options[:daemonize] + middlewares << [Rails::Rack::Debugger] if options[:debugger] + Hash.new(middlewares) + end -puts "=> Ctrl-C to shutdown server" - -begin - server.run(app, options.merge(:AccessLog => [])) -ensure - puts 'Exiting' + def default_options + { + :Port => 3000, + :Host => "0.0.0.0", + :environment => (ENV['RAILS_ENV'] || "development").dup, + :rack_file => "#{Rails.root}/config.ru", + :daemonize => false, + :debugger => false, + :pid => "#{Rails.root}/tmp/pids/server.pid", + :AccessLog => [] + } + end + end end diff --git a/railties/lib/rails/generators/rails/app/templates/script/server b/railties/lib/rails/generators/rails/app/templates/script/server index a7aaee2953..709ca002df 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/server +++ b/railties/lib/rails/generators/rails/app/templates/script/server @@ -1,2 +1,3 @@ require File.expand_path('../../config/application', __FILE__) require 'rails/commands/server' +Rails::Server.start -- cgit v1.2.3 From 53d7acdf4f3d61865fb4c4baa6f23601a93e3630 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Mon, 23 Nov 2009 16:57:34 -0800 Subject: Refactor script/console into an object and use IRB.start instead of calling exec. --- railties/lib/rails/commands/console.rb | 87 ++++++++++++---------- .../generators/rails/app/templates/script/console | 1 + 2 files changed, 49 insertions(+), 39 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index b977b7162f..1ed2db8dc9 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -1,45 +1,54 @@ -irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb' - require 'optparse' +require 'irb' +require "irb/completion" -options = { :sandbox => false, :irb => irb } -OptionParser.new do |opt| - opt.banner = "Usage: console [environment] [options]" - opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v } - opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v } - opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v } - opt.parse!(ARGV) -end +module Rails + class Console + def self.start + new.start + end -libs = " -r irb/completion" -libs << %( -r "#{Rails.root}/config/environment") -libs << " -r rails/console_app" -libs << " -r rails/console_sandbox" if options[:sandbox] -libs << " -r rails/console_with_helpers" + def start + options = {} -if options[:debugger] - begin - require 'ruby-debug' - libs << " -r ruby-debug" - puts "=> Debugger enabled" - rescue Exception - puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'" - exit - end -end + OptionParser.new do |opt| + opt.banner = "Usage: console [environment] [options]" + opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v } + opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v } + opt.parse!(ARGV) + end + + require "#{Rails.root}/config/environment" + require "rails/console_app" + require "rails/console_sandbox" if options[:sandbox] + require "rails/console_with_helpers" -ENV['RAILS_ENV'] = case ARGV.first - when "p"; "production" - when "d"; "development" - when "t"; "test" - else - ARGV.first || ENV['RAILS_ENV'] || 'development' -end + if options[:debugger] + begin + require 'ruby-debug' + puts "=> Debugger enabled" + rescue Exception + puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'" + exit + end + end -if options[:sandbox] - puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails.version})" - puts "Any modifications you make will be rolled back on exit" -else - puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails.version})" -end -exec "#{options[:irb]} #{libs} --simple-prompt" + ENV['RAILS_ENV'] = + case ARGV.first + when "p" then "production" + when "d" then "development" + when "t" then "test" + else + ARGV.first || ENV['RAILS_ENV'] || 'development' + end + + if options[:sandbox] + puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails.version})" + puts "Any modifications you make will be rolled back on exit" + else + puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails.version})" + end + IRB.start + end + end +end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/script/console b/railties/lib/rails/generators/rails/app/templates/script/console index 20aa799d2f..6043f3792b 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/console +++ b/railties/lib/rails/generators/rails/app/templates/script/console @@ -1,2 +1,3 @@ require File.expand_path('../../config/application', __FILE__) require 'rails/commands/console' +Rails::Console.start -- cgit v1.2.3 From 0088ceb6fac35cd0b0480f153a7c6e8772313037 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 23 Nov 2009 22:07:37 -0800 Subject: Set RAILS_ENV before loading config/environment --- railties/lib/rails/commands/console.rb | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index 1ed2db8dc9..1a40ed92cf 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -4,6 +4,8 @@ require "irb/completion" module Rails class Console + ENVIRONMENTS = %w(production development test) + def self.start new.start end @@ -18,6 +20,10 @@ module Rails opt.parse!(ARGV) end + if env = ARGV.first + ENV['RAILS_ENV'] = ENVIRONMENTS.find { |e| e.index(env) } || env + end + require "#{Rails.root}/config/environment" require "rails/console_app" require "rails/console_sandbox" if options[:sandbox] @@ -33,15 +39,6 @@ module Rails end end - ENV['RAILS_ENV'] = - case ARGV.first - when "p" then "production" - when "d" then "development" - when "t" then "test" - else - ARGV.first || ENV['RAILS_ENV'] || 'development' - end - if options[:sandbox] puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails.version})" puts "Any modifications you make will be rolled back on exit" @@ -51,4 +48,4 @@ module Rails IRB.start end end -end \ No newline at end of file +end -- cgit v1.2.3 From e62e6d409986cd5c99234689aa49e3162d7b3a59 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 23 Nov 2009 22:09:36 -0800 Subject: Add a dead --irb option mentioning upgrade path --- railties/lib/rails/commands/console.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index 1a40ed92cf..fc22ad64a9 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -17,6 +17,7 @@ module Rails opt.banner = "Usage: console [environment] [options]" opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v } opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v } + opt.on('--irb') { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/console` instead' } opt.parse!(ARGV) end -- cgit v1.2.3 From fa007e591d1ebf6df3fc8af4777c06e8a3d84eb3 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 24 Nov 2009 12:04:36 -0600 Subject: Quieter rake test runner --- railties/lib/rails/generators/rails/plugin/templates/Rakefile | 1 - railties/lib/rails/tasks/testing.rake | 9 --------- 2 files changed, 10 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/plugin/templates/Rakefile b/railties/lib/rails/generators/rails/plugin/templates/Rakefile index 85e8ff1834..23c2245a41 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin/templates/Rakefile @@ -10,7 +10,6 @@ Rake::TestTask.new(:test) do |t| t.libs << 'lib' t.libs << 'test' t.pattern = 'test/**/*_test.rb' - t.verbose = true end desc 'Generate documentation for the <%= file_name %> plugin.' diff --git a/railties/lib/rails/tasks/testing.rake b/railties/lib/rails/tasks/testing.rake index fd5e52a05b..5bd4aa1596 100644 --- a/railties/lib/rails/tasks/testing.rake +++ b/railties/lib/rails/tasks/testing.rake @@ -59,7 +59,6 @@ namespace :test do recent_tests('app/controllers/**/*.rb', 'test/functional', since) t.libs << 'test' - t.verbose = true t.test_files = touched.uniq end Rake::Task['test:recent'].comment = "Test recent changes" @@ -84,35 +83,30 @@ namespace :test do end t.libs << 'test' - t.verbose = true end Rake::Task['test:uncommitted'].comment = "Test changes since last checkin (only Subversion and Git)" Rake::TestTask.new(:units => "db:test:prepare") do |t| t.libs << "test" t.pattern = 'test/unit/**/*_test.rb' - t.verbose = true end Rake::Task['test:units'].comment = "Run the unit tests in test/unit" Rake::TestTask.new(:functionals => "db:test:prepare") do |t| t.libs << "test" t.pattern = 'test/functional/**/*_test.rb' - t.verbose = true end Rake::Task['test:functionals'].comment = "Run the functional tests in test/functional" Rake::TestTask.new(:integration => "db:test:prepare") do |t| t.libs << "test" t.pattern = 'test/integration/**/*_test.rb' - t.verbose = true end Rake::Task['test:integration'].comment = "Run the integration tests in test/integration" Rake::TestTask.new(:benchmark => 'db:test:prepare') do |t| t.libs << 'test' t.pattern = 'test/performance/**/*_test.rb' - t.verbose = true t.options = '-- --benchmark' end Rake::Task['test:benchmark'].comment = 'Benchmark the performance tests' @@ -120,7 +114,6 @@ namespace :test do Rake::TestTask.new(:profile => 'db:test:prepare') do |t| t.libs << 'test' t.pattern = 'test/performance/**/*_test.rb' - t.verbose = true end Rake::Task['test:profile'].comment = 'Profile the performance tests' @@ -132,8 +125,6 @@ namespace :test do else t.pattern = 'vendor/plugins/*/**/test/**/*_test.rb' end - - t.verbose = true end Rake::Task['test:plugins'].comment = "Run the plugin tests in vendor/plugins/*/**/test (or specify with PLUGIN=name)" end -- cgit v1.2.3 From d8c5ea76bce3bdc810f3d06af7908c6e474b154c Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 24 Nov 2009 10:46:16 -0800 Subject: Use Rails.env after loading environment --- railties/lib/rails/commands/console.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index fc22ad64a9..8807307271 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -41,10 +41,10 @@ module Rails end if options[:sandbox] - puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails.version})" + puts "Loading #{Rails.env} environment in sandbox (Rails #{Rails.version})" puts "Any modifications you make will be rolled back on exit" else - puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails.version})" + puts "Loading #{Rails.env} environment (Rails #{Rails.version})" end IRB.start end -- cgit v1.2.3 From a2cb90c0c246e772e9735ff59f5517e3dee313ff Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Tue, 24 Nov 2009 11:53:14 -0800 Subject: Refactor script/dbconsole into an object --- railties/lib/rails/commands/dbconsole.rb | 169 +++++++++++---------- .../rails/app/templates/script/dbconsole | 1 + 2 files changed, 90 insertions(+), 80 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index 4e699acf6b..064373f8f9 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -2,86 +2,95 @@ require 'erb' require 'yaml' require 'optparse' -include_password = false -options = {} - -OptionParser.new do |opt| - opt.banner = "Usage: dbconsole [options] [environment]" - opt.on("-p", "--include-password", "Automatically provide the password from database.yml") do |v| - include_password = true - end - - opt.on("--mode [MODE]", ['html', 'list', 'line', 'column'], - "Automatically put the sqlite3 database in the specified mode (html, list, line, column).") do |mode| - options['mode'] = mode - end - - opt.on("-h", "--header") do |h| - options['header'] = h - end - - opt.parse!(ARGV) - abort opt.to_s unless (0..1).include?(ARGV.size) -end - -env = ARGV.first || ENV['RAILS_ENV'] || 'development' -unless config = YAML::load(ERB.new(IO.read(Rails.root + "/config/database.yml")).result)[env] - abort "No database is configured for the environment '#{env}'" -end - - -def find_cmd(*commands) - dirs_on_path = ENV['PATH'].to_s.split(File::PATH_SEPARATOR) - commands += commands.map{|cmd| "#{cmd}.exe"} if RUBY_PLATFORM =~ /win32/ +module Rails + class DBConsole + def self.start + new.start + end - full_path_command = nil - found = commands.detect do |cmd| - dir = dirs_on_path.detect do |path| - full_path_command = File.join(path, cmd) - File.executable? full_path_command + def start + include_password = false + options = {} + OptionParser.new do |opt| + opt.banner = "Usage: dbconsole [options] [environment]" + opt.on("-p", "--include-password", "Automatically provide the password from database.yml") do |v| + include_password = true + end + + opt.on("--mode [MODE]", ['html', 'list', 'line', 'column'], + "Automatically put the sqlite3 database in the specified mode (html, list, line, column).") do |mode| + options['mode'] = mode + end + + opt.on("-h", "--header") do |h| + options['header'] = h + end + + opt.parse!(ARGV) + abort opt.to_s unless (0..1).include?(ARGV.size) + end + + env = ARGV.first || ENV['RAILS_ENV'] || 'development' + unless config = YAML::load(ERB.new(IO.read("#{Rails.root}/config/database.yml")).result)[env] + abort "No database is configured for the environment '#{env}'" + end + + + def find_cmd(*commands) + dirs_on_path = ENV['PATH'].to_s.split(File::PATH_SEPARATOR) + commands += commands.map{|cmd| "#{cmd}.exe"} if RUBY_PLATFORM =~ /win32/ + + full_path_command = nil + found = commands.detect do |cmd| + dir = dirs_on_path.detect do |path| + full_path_command = File.join(path, cmd) + File.executable? full_path_command + end + end + found ? full_path_command : abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.") + end + + case config["adapter"] + when "mysql" + args = { + 'host' => '--host', + 'port' => '--port', + 'socket' => '--socket', + 'username' => '--user', + 'encoding' => '--default-character-set' + }.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact + + if config['password'] && include_password + args << "--password=#{config['password']}" + elsif config['password'] && !config['password'].to_s.empty? + args << "-p" + end + + args << config['database'] + + exec(find_cmd('mysql', 'mysql5'), *args) + + when "postgresql" + ENV['PGUSER'] = config["username"] if config["username"] + ENV['PGHOST'] = config["host"] if config["host"] + ENV['PGPORT'] = config["port"].to_s if config["port"] + ENV['PGPASSWORD'] = config["password"].to_s if config["password"] && include_password + exec(find_cmd('psql'), config["database"]) + + when "sqlite" + exec(find_cmd('sqlite'), config["database"]) + + when "sqlite3" + args = [] + + args << "-#{options['mode']}" if options['mode'] + args << "-header" if options['header'] + args << config['database'] + + exec(find_cmd('sqlite3'), *args) + else + abort "Unknown command-line client for #{config['database']}. Submit a Rails patch to add support!" + end end end - found ? full_path_command : abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.") -end - -case config["adapter"] -when "mysql" - args = { - 'host' => '--host', - 'port' => '--port', - 'socket' => '--socket', - 'username' => '--user', - 'encoding' => '--default-character-set' - }.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact - - if config['password'] && include_password - args << "--password=#{config['password']}" - elsif config['password'] && !config['password'].to_s.empty? - args << "-p" - end - - args << config['database'] - - exec(find_cmd('mysql', 'mysql5'), *args) - -when "postgresql" - ENV['PGUSER'] = config["username"] if config["username"] - ENV['PGHOST'] = config["host"] if config["host"] - ENV['PGPORT'] = config["port"].to_s if config["port"] - ENV['PGPASSWORD'] = config["password"].to_s if config["password"] && include_password - exec(find_cmd('psql'), config["database"]) - -when "sqlite" - exec(find_cmd('sqlite'), config["database"]) - -when "sqlite3" - args = [] - - args << "-#{options['mode']}" if options['mode'] - args << "-header" if options['header'] - args << config['database'] - - exec(find_cmd('sqlite3'), *args) -else - abort "Unknown command-line client for #{config['database']}. Submit a Rails patch to add support!" -end +end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/script/dbconsole b/railties/lib/rails/generators/rails/app/templates/script/dbconsole index e6a1c59394..904df54ff2 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/dbconsole +++ b/railties/lib/rails/generators/rails/app/templates/script/dbconsole @@ -1,2 +1,3 @@ require File.expand_path('../../config/application', __FILE__) require 'rails/commands/dbconsole' +Rails::DBConsole.start \ No newline at end of file -- cgit v1.2.3 From 530b8ff5ae811e0dd5e1343b478f42eed6fffdbd Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Tue, 24 Nov 2009 13:03:24 -0800 Subject: Have script/* and Rakefile use the application object --- railties/lib/rails/application.rb | 18 +++++++++++++----- railties/lib/rails/commands/console.rb | 10 +++++++--- railties/lib/rails/commands/dbconsole.rb | 10 +++++++--- railties/lib/rails/commands/server.rb | 19 ++++++++++++++++--- .../lib/rails/generators/rails/app/app_generator.rb | 8 ++++++-- .../lib/rails/generators/rails/app/templates/Rakefile | 2 +- .../rails/generators/rails/app/templates/config.ru | 2 +- .../rails/app/templates/config/application.rb | 2 +- .../rails/app/templates/config/environment.rb | 2 +- .../generators/rails/app/templates/script/console | 3 --- .../generators/rails/app/templates/script/console.tt | 3 +++ .../generators/rails/app/templates/script/dbconsole | 3 --- .../rails/app/templates/script/dbconsole.tt | 3 +++ .../generators/rails/app/templates/script/server | 3 --- .../generators/rails/app/templates/script/server.tt | 3 +++ railties/lib/rails/rack/log_tailer.rb | 4 +--- railties/lib/rails/tasks/misc.rake | 4 ---- 17 files changed, 63 insertions(+), 36 deletions(-) delete mode 100755 railties/lib/rails/generators/rails/app/templates/script/console create mode 100755 railties/lib/rails/generators/rails/app/templates/script/console.tt delete mode 100755 railties/lib/rails/generators/rails/app/templates/script/dbconsole create mode 100755 railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt delete mode 100755 railties/lib/rails/generators/rails/app/templates/script/server create mode 100755 railties/lib/rails/generators/rails/app/templates/script/server.tt (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 7c2d8eab67..e49ea8973b 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -3,11 +3,6 @@ module Rails include Initializable class << self - def inherited(klass) - Rails.application ||= klass unless klass.name =~ /Rails/ - super - end - # Stub out App initialize def initialize! new @@ -32,12 +27,21 @@ module Rails config.root end + def load_tasks + require "rails/tasks" + task :environment do + $rails_rake_task = true + initialize! + end + end + def call(env) new.call(env) end end def initialize + Rails.application ||= self run_initializers(self) end @@ -45,6 +49,10 @@ module Rails self.class.config end + def root + config.root + end + alias configuration config def middleware diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index 8807307271..37eb6d40ea 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -6,8 +6,12 @@ module Rails class Console ENVIRONMENTS = %w(production development test) - def self.start - new.start + def self.start(app) + new(app).start + end + + def initialize(app) + @app = app end def start @@ -25,7 +29,7 @@ module Rails ENV['RAILS_ENV'] = ENVIRONMENTS.find { |e| e.index(env) } || env end - require "#{Rails.root}/config/environment" + @app.initialize! require "rails/console_app" require "rails/console_sandbox" if options[:sandbox] require "rails/console_with_helpers" diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index 064373f8f9..77c3404343 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -4,8 +4,12 @@ require 'optparse' module Rails class DBConsole - def self.start - new.start + def self.start(app) + new(app).start + end + + def initialize(app) + @app = app end def start @@ -31,7 +35,7 @@ module Rails end env = ARGV.first || ENV['RAILS_ENV'] || 'development' - unless config = YAML::load(ERB.new(IO.read("#{Rails.root}/config/database.yml")).result)[env] + unless config = YAML::load(ERB.new(IO.read("#{@app.root}/config/database.yml")).result)[env] abort "No database is configured for the environment '#{env}'" end diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index ff2282a534..57b7c6a49c 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -37,6 +37,15 @@ module Rails Options.new end + def self.start(app) + new(app).start + end + + def initialize(app) + super() # Call Rack::Server#initialize without passing any options to use. + @app = app + end + def start puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}" @@ -54,20 +63,24 @@ module Rails def middleware middlewares = [] - middlewares << [Rails::Rack::LogTailer] unless options[:daemonize] + middlewares << [Rails::Rack::LogTailer, log_path] unless options[:daemonize] middlewares << [Rails::Rack::Debugger] if options[:debugger] Hash.new(middlewares) end + def log_path + "#{File.expand_path(@app.root)}/log/#{options[:environment]}.log" + end + def default_options { :Port => 3000, :Host => "0.0.0.0", :environment => (ENV['RAILS_ENV'] || "development").dup, - :rack_file => "#{Rails.root}/config.ru", + :rack_file => "#{@app.root}/config.ru", :daemonize => false, :debugger => false, - :pid => "#{Rails.root}/tmp/pids/server.pid", + :pid => "#{@app.root}/tmp/pids/server.pid", :AccessLog => [] } end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 2bcea4bc8f..7e21a6d1d9 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -48,9 +48,9 @@ module Rails::Generators end def create_root_files - copy_file "Rakefile" copy_file "README" - copy_file "config.ru" + template "Rakefile" + template "config.ru" template "Gemfile" end @@ -181,6 +181,10 @@ module Rails::Generators @app_name ||= File.basename(destination_root) end + def app_const + @app_const ||= app_name.classify + end + def app_secret ActiveSupport::SecureRandom.hex(64) end diff --git a/railties/lib/rails/generators/rails/app/templates/Rakefile b/railties/lib/rails/generators/rails/app/templates/Rakefile index 6b6d07e8cc..c19ad0e945 100755 --- a/railties/lib/rails/generators/rails/app/templates/Rakefile +++ b/railties/lib/rails/generators/rails/app/templates/Rakefile @@ -7,4 +7,4 @@ require 'rake' require 'rake/testtask' require 'rake/rdoctask' -require 'rails/tasks' +<%= app_const %>.load_tasks diff --git a/railties/lib/rails/generators/rails/app/templates/config.ru b/railties/lib/rails/generators/rails/app/templates/config.ru index 509a0da5b7..f3bf3d6117 100644 --- a/railties/lib/rails/generators/rails/app/templates/config.ru +++ b/railties/lib/rails/generators/rails/app/templates/config.ru @@ -2,4 +2,4 @@ require ::File.expand_path('../config/environment', __FILE__) # Dispatch the request -run Rails.application +run <%= app_const%> diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 8008c6ba07..2c17de2a23 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -1,6 +1,6 @@ require File.expand_path('../boot', __FILE__) -Rails::Initializer.run do |config| +class <%= app_const %> < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environment.rb b/railties/lib/rails/generators/rails/app/templates/config/environment.rb index 0bb191f205..1684986a59 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environment.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/environment.rb @@ -2,4 +2,4 @@ require File.expand_path('../application', __FILE__) # Initialize the rails application -Rails.initialize! +<%= app_const %>.initialize! diff --git a/railties/lib/rails/generators/rails/app/templates/script/console b/railties/lib/rails/generators/rails/app/templates/script/console deleted file mode 100755 index 6043f3792b..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/script/console +++ /dev/null @@ -1,3 +0,0 @@ -require File.expand_path('../../config/application', __FILE__) -require 'rails/commands/console' -Rails::Console.start diff --git a/railties/lib/rails/generators/rails/app/templates/script/console.tt b/railties/lib/rails/generators/rails/app/templates/script/console.tt new file mode 100755 index 0000000000..4262439e52 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/script/console.tt @@ -0,0 +1,3 @@ +require File.expand_path('../../config/application', __FILE__) +require 'rails/commands/console' +Rails::Console.start(<%= app_const %>) diff --git a/railties/lib/rails/generators/rails/app/templates/script/dbconsole b/railties/lib/rails/generators/rails/app/templates/script/dbconsole deleted file mode 100755 index 904df54ff2..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/script/dbconsole +++ /dev/null @@ -1,3 +0,0 @@ -require File.expand_path('../../config/application', __FILE__) -require 'rails/commands/dbconsole' -Rails::DBConsole.start \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt b/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt new file mode 100755 index 0000000000..9dfa24c378 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt @@ -0,0 +1,3 @@ +require File.expand_path('../../config/application', __FILE__) +require 'rails/commands/dbconsole' +Rails::DBConsole.start(<%= app_const %>) \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/script/server b/railties/lib/rails/generators/rails/app/templates/script/server deleted file mode 100755 index 709ca002df..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/script/server +++ /dev/null @@ -1,3 +0,0 @@ -require File.expand_path('../../config/application', __FILE__) -require 'rails/commands/server' -Rails::Server.start diff --git a/railties/lib/rails/generators/rails/app/templates/script/server.tt b/railties/lib/rails/generators/rails/app/templates/script/server.tt new file mode 100755 index 0000000000..d98f677475 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/script/server.tt @@ -0,0 +1,3 @@ +require File.expand_path('../../config/application', __FILE__) +require 'rails/commands/server' +Rails::Server.start(<%= app_const %>) diff --git a/railties/lib/rails/rack/log_tailer.rb b/railties/lib/rails/rack/log_tailer.rb index a237cee6bc..077311be3c 100644 --- a/railties/lib/rails/rack/log_tailer.rb +++ b/railties/lib/rails/rack/log_tailer.rb @@ -1,12 +1,10 @@ module Rails module Rack class LogTailer - EnvironmentLog = "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log" - def initialize(app, log = nil) @app = app - path = Pathname.new(log || EnvironmentLog).cleanpath + path = Pathname.new(log || "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log").cleanpath @cursor = ::File.size(path) @last_checked = Time.now.to_f diff --git a/railties/lib/rails/tasks/misc.rake b/railties/lib/rails/tasks/misc.rake index 7f244ebaed..9433b3556a 100644 --- a/railties/lib/rails/tasks/misc.rake +++ b/railties/lib/rails/tasks/misc.rake @@ -1,8 +1,4 @@ task :default => :test -task :environment do - $rails_rake_task = true - require(File.join(Rails.root, 'config', 'environment')) -end task :rails_env do unless defined? RAILS_ENV -- cgit v1.2.3 From 34eac1cf1cf52784b4c344b44034d98adebdcc28 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Wed, 25 Nov 2009 14:29:28 -0800 Subject: Load application specific rake tasks in the application object --- railties/lib/rails/application.rb | 2 ++ railties/lib/rails/tasks.rb | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index e49ea8973b..7ea79aa9c9 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -29,6 +29,8 @@ module Rails def load_tasks require "rails/tasks" + Dir["#{root}/vendor/plugins/*/**/tasks/**/*.rake"].sort.each { |ext| load ext } + Dir["#{root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } task :environment do $rails_rake_task = true initialize! diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index 82113a297c..dc886f4a4d 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -16,8 +16,3 @@ $VERBOSE = nil ).each do |task| load "rails/tasks/#{task}.rake" end - -# Load any custom rakefile extensions -# TODO: Don't hardcode these paths. -Dir["#{Rails.root}/vendor/plugins/*/**/tasks/**/*.rake"].sort.each { |ext| load ext } -Dir["#{Rails.root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } -- cgit v1.2.3 From 02c3c9dfbcec05e3b0cecc062da8acd0cf7c53e0 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Wed, 25 Nov 2009 14:52:56 -0800 Subject: Fix the application.rb generator --- railties/lib/rails/generators/actions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 8677bf283b..57abc151d2 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -104,7 +104,7 @@ module Rails # file in config/environments. # def environment(data=nil, options={}, &block) - sentinel = "Rails::Initializer.run do |config|" + sentinel = /class [a-z_:]+ < Rails::Application/i data = block.call if !data && block_given? in_root do -- cgit v1.2.3 From eeb1afa20003050039eab7420003a775343754c1 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 24 Nov 2009 18:41:30 -0800 Subject: Expand path relative to __FILE__ --- .../generators/rails/generator/templates/%file_name%_generator.rb.tt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt b/railties/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt index 675f00043f..d8757460e4 100644 --- a/railties/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt +++ b/railties/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt @@ -1,5 +1,5 @@ class <%= class_name %>Generator < Rails::Generators::NamedBase def self.source_root - @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates')) + @source_root ||= File.expand_path('../templates', __FILE__) end end -- cgit v1.2.3 From fe319103dbb5f883b4320410a8b8e5bb64bfaebc Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 1 Dec 2009 13:18:14 -0800 Subject: Fix rails:update:scripts --- railties/lib/rails/tasks/framework.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake index 1611d1d94d..2b8f3378fc 100644 --- a/railties/lib/rails/tasks/framework.rake +++ b/railties/lib/rails/tasks/framework.rake @@ -92,7 +92,7 @@ namespace :rails do namespace :update do def invoke_from_app_generator(method) - require 'generators' + require 'rails/generators' require 'rails/generators/rails/app/app_generator' generator = Rails::Generators::AppGenerator.new ["rails"], { :with_dispatchers => true }, -- cgit v1.2.3 From df9f5e771b0b3d5f2b95d3124514a1fd7db572ab Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 1 Dec 2009 13:27:59 -0800 Subject: Reinstate rails:update:configs task removed in e1fdc8b --- railties/lib/rails/tasks/framework.rake | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake index 2b8f3378fc..975c180f86 100644 --- a/railties/lib/rails/tasks/framework.rake +++ b/railties/lib/rails/tasks/framework.rake @@ -100,6 +100,11 @@ namespace :rails do generator.invoke(method) end + desc "Update config/boot.rb from your current rails install" + task :configs do + invoke_from_app_generator :create_boot_file + end + desc "Update Prototype javascripts from your current rails install" task :javascripts do invoke_from_app_generator :create_prototype_files -- cgit v1.2.3 From 544de096316b81c7cd890884537a513f2d22f6ba Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 1 Dec 2009 13:37:12 -0800 Subject: rails:update:configs updates boot.rb and the rest of config/* --- railties/lib/rails/tasks/framework.rake | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake index 975c180f86..f7b53885c8 100644 --- a/railties/lib/rails/tasks/framework.rake +++ b/railties/lib/rails/tasks/framework.rake @@ -103,6 +103,7 @@ namespace :rails do desc "Update config/boot.rb from your current rails install" task :configs do invoke_from_app_generator :create_boot_file + invoke_from_app_generator :create_config_files end desc "Update Prototype javascripts from your current rails install" -- cgit v1.2.3 From 74be70039f0718a2f8102302c9ea1ea5b2db681a Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 1 Dec 2009 15:07:41 -0800 Subject: Avoid using unrequired core extensions --- railties/lib/rails/tasks/testing.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/tasks/testing.rake b/railties/lib/rails/tasks/testing.rake index 5bd4aa1596..57857fb911 100644 --- a/railties/lib/rails/tasks/testing.rake +++ b/railties/lib/rails/tasks/testing.rake @@ -48,7 +48,7 @@ task :test do task end end.compact - abort "Errors running #{errors.to_sentence(:locale => :en)}!" if errors.any? + abort "Errors running #{errors * ', '}!" if errors.any? end namespace :test do -- cgit v1.2.3 From 28657e4f418c84dad08ae1f541d24df2d91d93aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 1 Dec 2009 23:42:07 -0200 Subject: Update vendored thor and ensure that content is completely modified before checking file collisions. Signed-off-by: Jeremy Kemper --- railties/lib/rails/generators.rb | 2 +- .../rails/generators/rails/app/app_generator.rb | 6 +- .../lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc | 82 ---- railties/lib/rails/vendor/thor-0.12.0/LICENSE | 20 - railties/lib/rails/vendor/thor-0.12.0/README.rdoc | 234 ---------- railties/lib/rails/vendor/thor-0.12.0/Thorfile | 63 --- railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb | 242 ---------- .../rails/vendor/thor-0.12.0/lib/thor/actions.rb | 273 ----------- .../thor-0.12.0/lib/thor/actions/create_file.rb | 103 ---- .../thor-0.12.0/lib/thor/actions/directory.rb | 93 ---- .../lib/thor/actions/empty_directory.rb | 134 ------ .../lib/thor/actions/file_manipulation.rb | 219 --------- .../lib/thor/actions/inject_into_file.rb | 101 ---- .../lib/rails/vendor/thor-0.12.0/lib/thor/base.rb | 517 --------------------- .../thor/core_ext/hash_with_indifferent_access.rb | 75 --- .../thor-0.12.0/lib/thor/core_ext/ordered_hash.rb | 100 ---- .../lib/rails/vendor/thor-0.12.0/lib/thor/error.rb | 27 -- .../lib/rails/vendor/thor-0.12.0/lib/thor/group.rb | 263 ----------- .../vendor/thor-0.12.0/lib/thor/invocation.rb | 178 ------- .../rails/vendor/thor-0.12.0/lib/thor/parser.rb | 4 - .../vendor/thor-0.12.0/lib/thor/parser/argument.rb | 67 --- .../thor-0.12.0/lib/thor/parser/arguments.rb | 145 ------ .../vendor/thor-0.12.0/lib/thor/parser/option.rb | 132 ------ .../vendor/thor-0.12.0/lib/thor/parser/options.rb | 142 ------ .../vendor/thor-0.12.0/lib/thor/rake_compat.rb | 66 --- .../rails/vendor/thor-0.12.0/lib/thor/runner.rb | 299 ------------ .../lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb | 78 ---- .../vendor/thor-0.12.0/lib/thor/shell/basic.rb | 219 --------- .../vendor/thor-0.12.0/lib/thor/shell/color.rb | 108 ----- .../lib/rails/vendor/thor-0.12.0/lib/thor/task.rb | 122 ----- .../lib/rails/vendor/thor-0.12.0/lib/thor/util.rb | 251 ---------- .../rails/vendor/thor-0.12.0/lib/thor/version.rb | 3 - .../lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc | 82 ++++ railties/lib/rails/vendor/thor-0.12.1/LICENSE | 20 + railties/lib/rails/vendor/thor-0.12.1/README.rdoc | 234 ++++++++++ railties/lib/rails/vendor/thor-0.12.1/Thorfile | 63 +++ railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb | 242 ++++++++++ .../rails/vendor/thor-0.12.1/lib/thor/actions.rb | 273 +++++++++++ .../thor-0.12.1/lib/thor/actions/create_file.rb | 103 ++++ .../thor-0.12.1/lib/thor/actions/directory.rb | 91 ++++ .../lib/thor/actions/empty_directory.rb | 134 ++++++ .../lib/thor/actions/file_manipulation.rb | 223 +++++++++ .../lib/thor/actions/inject_into_file.rb | 101 ++++ .../lib/rails/vendor/thor-0.12.1/lib/thor/base.rb | 517 +++++++++++++++++++++ .../thor/core_ext/hash_with_indifferent_access.rb | 75 +++ .../thor-0.12.1/lib/thor/core_ext/ordered_hash.rb | 100 ++++ .../lib/rails/vendor/thor-0.12.1/lib/thor/error.rb | 27 ++ .../lib/rails/vendor/thor-0.12.1/lib/thor/group.rb | 263 +++++++++++ .../vendor/thor-0.12.1/lib/thor/invocation.rb | 178 +++++++ .../rails/vendor/thor-0.12.1/lib/thor/parser.rb | 4 + .../vendor/thor-0.12.1/lib/thor/parser/argument.rb | 67 +++ .../thor-0.12.1/lib/thor/parser/arguments.rb | 145 ++++++ .../vendor/thor-0.12.1/lib/thor/parser/option.rb | 132 ++++++ .../vendor/thor-0.12.1/lib/thor/parser/options.rb | 142 ++++++ .../vendor/thor-0.12.1/lib/thor/rake_compat.rb | 66 +++ .../rails/vendor/thor-0.12.1/lib/thor/runner.rb | 299 ++++++++++++ .../lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb | 78 ++++ .../vendor/thor-0.12.1/lib/thor/shell/basic.rb | 219 +++++++++ .../vendor/thor-0.12.1/lib/thor/shell/color.rb | 108 +++++ .../lib/rails/vendor/thor-0.12.1/lib/thor/task.rb | 122 +++++ .../lib/rails/vendor/thor-0.12.1/lib/thor/util.rb | 251 ++++++++++ .../rails/vendor/thor-0.12.1/lib/thor/version.rb | 3 + 62 files changed, 4366 insertions(+), 4364 deletions(-) delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/LICENSE delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/README.rdoc delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/Thorfile delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/color.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/task.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc create mode 100644 railties/lib/rails/vendor/thor-0.12.1/LICENSE create mode 100644 railties/lib/rails/vendor/thor-0.12.1/README.rdoc create mode 100644 railties/lib/rails/vendor/thor-0.12.1/Thorfile create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/create_file.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/directory.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/empty_directory.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/file_manipulation.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/inject_into_file.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/base.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/hash_with_indifferent_access.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/ordered_hash.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/error.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/group.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/invocation.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/argument.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/arguments.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/option.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/options.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/rake_compat.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/runner.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/basic.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/color.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/task.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/util.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/version.rb (limited to 'railties/lib') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 85c2fd52a4..ffb9cfe1cd 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -9,7 +9,7 @@ require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/string/inflections' # TODO: Do not always push on vendored thor -$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.12.0/lib") +$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.12.1/lib") require 'rails/generators/base' require 'rails/generators/named_base' diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 7e21a6d1d9..ae18fa843b 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -123,10 +123,10 @@ module Rails::Generators end def create_script_files - directory "script" do |file| - prepend_file file, "#{shebang}\n", :verbose => false - chmod file, 0755, :verbose => false + directory "script" do |content| + "#{shebang}\n" + content end + chmod "script", 0755, :verbose => false end def create_test_files diff --git a/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc b/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc deleted file mode 100644 index adedfeca9d..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc +++ /dev/null @@ -1,82 +0,0 @@ -== TODO - -* Improve spec coverage for Thor::Runner - -== 0.12, released 2009-11-06 - -* [#7] Do not force white color on status -* [#8] Yield a block with the filename on directory - -== 0.11, released 2009-07-01 - -* Added a rake compatibility layer. It allows you to use spec and rdoc tasks on - Thor classes. - -* BACKWARDS INCOMPATIBLE: aliases are not generated automatically anymore - since it wrong behavior to the invocation system. - -* thor help now show information about any class/task. All those calls are - possible: - - thor help describe - thor help describe:amazing - - Or even with default namespaces: - - thor help :spec - -* Thor::Runner now invokes the default task if none is supplied: - - thor describe # invokes the default task, usually help - -* Thor::Runner now works with mappings: - - thor describe -h - -* Added some documentation and code refactoring. - -== 0.9.8, released 2008-10-20 - -* Fixed some tiny issues that were introduced lately. - -== 0.9.7, released 2008-10-13 - -* Setting global method options on the initialize method works as expected: - All other tasks will accept these global options in addition to their own. -* Added 'group' notion to Thor task sets (class Thor); by default all tasks - are in the 'standard' group. Running 'thor -T' will only show the standard - tasks - adding --all will show all tasks. You can also filter on a specific - group using the --group option: thor -T --group advanced - -== 0.9.6, released 2008-09-13 - -* Generic improvements - -== 0.9.5, released 2008-08-27 - -* Improve Windows compatibility -* Update (incorrect) README and task.thor sample file -* Options hash is now frozen (once returned) -* Allow magic predicates on options object. For instance: `options.force?` -* Add support for :numeric type -* BACKWARDS INCOMPATIBLE: Refactor Thor::Options. You cannot access shorthand forms in options hash anymore (for instance, options[:f]) -* Allow specifying optional args with default values: method_options(:user => "mislav") -* Don't write options for nil or false values. This allows, for example, turning color off when running specs. -* Exit with the status of the spec command to help CI stuff out some. - -== 0.9.4, released 2008-08-13 - -* Try to add Windows compatibility. -* BACKWARDS INCOMPATIBLE: options hash is now accessed as a property in your class and is not passed as last argument anymore -* Allow options at the beginning of the argument list as well as the end. -* Make options available with symbol keys in addition to string keys. -* Allow true to be passed to Thor#method_options to denote a boolean option. -* If loading a thor file fails, don't give up, just print a warning and keep going. -* Make sure that we re-raise errors if they happened further down the pipe than we care about. -* Only delete the old file on updating when the installation of the new one is a success -* Make it Ruby 1.8.5 compatible. -* Don't raise an error if a boolean switch is defined multiple times. -* Thor::Options now doesn't parse through things that look like options but aren't. -* Add URI detection to install task, and make sure we don't append ".thor" to URIs -* Add rake2thor to the gem binfiles. -* Make sure local Thorfiles override system-wide ones. diff --git a/railties/lib/rails/vendor/thor-0.12.0/LICENSE b/railties/lib/rails/vendor/thor-0.12.0/LICENSE deleted file mode 100644 index 98722da459..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008 Yehuda Katz - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/railties/lib/rails/vendor/thor-0.12.0/README.rdoc b/railties/lib/rails/vendor/thor-0.12.0/README.rdoc deleted file mode 100644 index f1106f02b6..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/README.rdoc +++ /dev/null @@ -1,234 +0,0 @@ -= thor - -Map options to a class. Simply create a class with the appropriate annotations -and have options automatically map to functions and parameters. - -Example: - - class App < Thor # [1] - map "-L" => :list # [2] - - desc "install APP_NAME", "install one of the available apps" # [3] - method_options :force => :boolean, :alias => :string # [4] - def install(name) - user_alias = options[:alias] - if options.force? - # do something - end - # other code - end - - desc "list [SEARCH]", "list all of the available apps, limited by SEARCH" - def list(search="") - # list everything - end - end - -Thor automatically maps commands as such: - - thor app:install myname --force - -That gets converted to: - - App.new.install("myname") - # with {'force' => true} as options hash - -1. Inherit from Thor to turn a class into an option mapper -2. Map additional non-valid identifiers to specific methods. In this case, convert -L to :list -3. Describe the method immediately below. The first parameter is the usage information, and the second parameter is the description -4. Provide any additional options that will be available the instance method options. - -== Types for method_options - -* :boolean - is parsed as --option or --option=true -* :string - is parsed as --option=VALUE -* :numeric - is parsed as --option=N -* :array - is parsed as --option=one two three -* :hash - is parsed as --option=name:string age:integer - -Besides, method_option allows a default value to be given, examples: - - method_options :force => false - #=> Creates a boolean option with default value false - - method_options :alias => "bar" - #=> Creates a string option with default value "bar" - - method_options :threshold => 3.0 - #=> Creates a numeric option with default value 3.0 - -You can also supply :option => :required to mark an option as required. The -type is assumed to be string. If you want a required hash with default values -as option, you can use method_option which uses a more declarative style: - - method_option :attributes, :type => :hash, :default => {}, :required => true - -All arguments can be set to nil (except required arguments), by suppling a no or -skip variant. For example: - - thor app name --no-attributes - -In previous versions, aliases for options were created automatically, but now -they should be explicit. You can supply aliases in both short and declarative -styles: - - method_options %w( force -f ) => :boolean - -Or: - - method_option :force, :type => :boolean, :aliases => "-f" - -You can supply as many aliases as you want. - -NOTE: Type :optional available in Thor 0.9.0 was deprecated. Use :string or :boolean instead. - -== Namespaces - -By default, your Thor tasks are invoked using Ruby namespace. In the example -above, tasks are invoked as: - - thor app:install name --force - -However, you could namespace your class as: - - module Sinatra - class App < Thor - # tasks - end - end - -And then you should invoke your tasks as: - - thor sinatra:app:install name --force - -If desired, you can change the namespace: - - module Sinatra - class App < Thor - namespace :myapp - # tasks - end - end - -And then your tasks hould be invoked as: - - thor myapp:install name --force - -== Invocations - -Thor comes with a invocation-dependency system as well which allows a task to be -invoked only once. For example: - - class Counter < Thor - desc "one", "Prints 1, 2, 3" - def one - puts 1 - invoke :two - invoke :three - end - - desc "two", "Prints 2, 3" - def two - puts 2 - invoke :three - end - - desc "three", "Prints 3" - def three - puts 3 - end - end - -When invoking the task one: - - thor counter:one - -The output is "1 2 3", which means that the three task was invoked only once. -You can even invoke tasks from another class, so be sure to check the -documentation. - -== Thor::Group - -Thor has a special class called Thor::Group. The main difference to Thor class -is that it invokes all tasks at once. The example above could be rewritten in -Thor::Group as this: - - class Counter < Thor::Group - desc "Prints 1, 2, 3" - - def one - puts 1 - end - - def two - puts 2 - end - - def three - puts 3 - end - end - -When invoked: - - thor counter - -It prints "1 2 3" as well. Notice you should describe (using the method desc) -only the class and not each task anymore. Thor::Group is a great tool to create -generators, since you can define several steps which are invoked in the order they -are defined (Thor::Group is the tool use in generators in Rails 3.0). - -Besides, Thor::Group can parse arguments and options as Thor tasks: - - class Counter < Thor::Group - # number will be available as attr_accessor - argument :number, :type => :numeric, :desc => "The number to start counting" - desc "Prints the 'number' given upto 'number+2'" - - def one - puts number + 0 - end - - def two - puts number + 1 - end - - def three - puts number + 2 - end - end - -The counter above expects one parameter and has the folling outputs: - - thor counter 5 - # Prints "5 6 7" - - thor counter 11 - # Prints "11 12 13" - -You can also give options to Thor::Group, but instead of using method_option -and method_options, you should use class_option and class_options. -Both argument and class_options methods are available to Thor class as well. - -== Actions - -Thor comes with several actions which helps with script and generator tasks. You -might be familiar with them since some came from Rails Templates. They are: -say, ask, yes?, no?, add_file, -remove_file, copy_file, template, directory, -inside, run, inject_into_file and a couple more. - -To use them, you just need to include Thor::Actions in your Thor classes: - - class App < Thor - include Thor::Actions - # tasks - end - -Some actions like copy file requires that a class method called source_root is -defined in your class. This is the directory where your templates should be -placed. Be sure to check the documentation. - -== License - -See MIT LICENSE. diff --git a/railties/lib/rails/vendor/thor-0.12.0/Thorfile b/railties/lib/rails/vendor/thor-0.12.0/Thorfile deleted file mode 100644 index f71a1e57e2..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/Thorfile +++ /dev/null @@ -1,63 +0,0 @@ -# enconding: utf-8 - -require File.join(File.dirname(__FILE__), "lib", "thor", "version") -require 'thor/rake_compat' -require 'spec/rake/spectask' -require 'rdoc/task' - -GEM_NAME = 'thor' -EXTRA_RDOC_FILES = ["README.rdoc", "LICENSE", "CHANGELOG.rdoc", "VERSION", "Thorfile"] - -class Default < Thor - include Thor::RakeCompat - - Spec::Rake::SpecTask.new(:spec) do |t| - t.libs << 'lib' - t.spec_opts = ['--options', "spec/spec.opts"] - t.spec_files = FileList['spec/**/*_spec.rb'] - end - - Spec::Rake::SpecTask.new(:rcov) do |t| - t.libs << 'lib' - t.spec_opts = ['--options', "spec/spec.opts"] - t.spec_files = FileList['spec/**/*_spec.rb'] - t.rcov = true - t.rcov_dir = "rcov" - end - - RDoc::Task.new do |rdoc| - rdoc.main = "README.rdoc" - rdoc.rdoc_dir = "rdoc" - rdoc.title = GEM_NAME - rdoc.rdoc_files.include(*EXTRA_RDOC_FILES) - rdoc.rdoc_files.include('lib/**/*.rb') - rdoc.options << '--line-numbers' << '--inline-source' - end - - begin - require 'jeweler' - Jeweler::Tasks.new do |s| - s.name = GEM_NAME - s.version = Thor::VERSION - s.rubyforge_project = "textmate" - s.platform = Gem::Platform::RUBY - s.summary = "A scripting framework that replaces rake, sake and rubigen" - s.email = "ruby-thor@googlegroups.com" - s.homepage = "http://yehudakatz.com" - s.description = "A scripting framework that replaces rake, sake and rubigen" - s.authors = ['Yehuda Katz', 'José Valim'] - s.has_rdoc = true - s.extra_rdoc_files = EXTRA_RDOC_FILES - s.require_path = 'lib' - s.bindir = "bin" - s.executables = %w( thor rake2thor ) - s.files = s.extra_rdoc_files + Dir.glob("{bin,lib}/**/*") - s.files.exclude 'spec/sandbox/**/*' - s.test_files.exclude 'spec/sandbox/**/*' - end - - Jeweler::RubyforgeTasks.new - rescue LoadError - puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb deleted file mode 100644 index 68944f140d..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb +++ /dev/null @@ -1,242 +0,0 @@ -require 'thor/base' -require 'thor/group' -require 'thor/actions' - -class Thor - class << self - # Sets the default task when thor is executed without an explicit task to be called. - # - # ==== Parameters - # meth:: name of the defaut task - # - def default_task(meth=nil) - case meth - when :none - @default_task = 'help' - when nil - @default_task ||= from_superclass(:default_task, 'help') - else - @default_task = meth.to_s - end - end - - # Defines the usage and the description of the next task. - # - # ==== Parameters - # usage - # description - # - def desc(usage, description, options={}) - if options[:for] - task = find_and_refresh_task(options[:for]) - task.usage = usage if usage - task.description = description if description - else - @usage, @desc = usage, description - end - end - - # Maps an input to a task. If you define: - # - # map "-T" => "list" - # - # Running: - # - # thor -T - # - # Will invoke the list task. - # - # ==== Parameters - # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task. - # - def map(mappings=nil) - @map ||= from_superclass(:map, {}) - - if mappings - mappings.each do |key, value| - if key.respond_to?(:each) - key.each {|subkey| @map[subkey] = value} - else - @map[key] = value - end - end - end - - @map - end - - # Declares the options for the next task to be declared. - # - # ==== Parameters - # Hash[Symbol => Object]:: The hash key is the name of the option and the value - # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric - # or :required (string). If you give a value, the type of the value is used. - # - def method_options(options=nil) - @method_options ||= {} - build_options(options, @method_options) if options - @method_options - end - - # Adds an option to the set of class options. If :for is given as option, - # it allows you to change the options from a previous defined task. - # - # def previous_task - # # magic - # end - # - # method_options :foo => :bar, :for => :previous_task - # - # def next_task - # # magic - # end - # - # ==== Parameters - # name:: The name of the argument. - # options:: Described below. - # - # ==== Options - # :desc - Description for the argument. - # :required - If the argument is required or not. - # :default - Default value for this argument. It cannot be required and have default values. - # :aliases - Aliases for this option. - # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. - # :group - The group for this options. Use by class options to output options in different levels. - # :banner - String to show on usage notes. - # - def method_option(name, options={}) - scope = if options[:for] - find_and_refresh_task(options[:for]).options - else - method_options - end - - build_option(name, options, scope) - end - - # Parses the task and options from the given args, instantiate the class - # and invoke the task. This method is used when the arguments must be parsed - # from an array. If you are inside Ruby and want to use a Thor class, you - # can simply initialize it: - # - # script = MyScript.new(args, options, config) - # script.invoke(:task, first_arg, second_arg, third_arg) - # - def start(given_args=ARGV, config={}) - super do - meth = normalize_task_name(given_args.shift) - task = all_tasks[meth] - - if task - args, opts = Thor::Options.split(given_args) - config.merge!(:task_options => task.options) - else - args, opts = given_args, {} - end - - task ||= Thor::Task::Dynamic.new(meth) - trailing = args[Range.new(arguments.size, -1)] - new(args, opts, config).invoke(task, trailing || []) - end - end - - # Prints help information. If a task name is given, it shows information - # only about the specific task. - # - # ==== Parameters - # meth:: An optional task name to print usage information about. - # - # ==== Options - # namespace:: When true, shows the namespace in the output before the usage. - # skip_inherited:: When true, does not show tasks from superclass. - # - def help(shell, meth=nil, options={}) - meth, options = nil, meth if meth.is_a?(Hash) - - if meth - task = all_tasks[meth] - raise UndefinedTaskError, "task '#{meth}' could not be found in namespace '#{self.namespace}'" unless task - - shell.say "Usage:" - shell.say " #{banner(task, options[:namespace], false)}" - shell.say - class_options_help(shell, "Class", :Method => task.options.map { |_, o| o }) - shell.say task.description - else - list = (options[:short] ? tasks : all_tasks).map do |_, task| - item = [ banner(task, options[:namespace]) ] - item << "# #{task.short_description}" if task.short_description - item << " " - end - - options[:ident] ||= 2 - if options[:short] - shell.print_list(list, :ident => options[:ident]) - else - shell.say "Tasks:" - shell.print_list(list, :ident => options[:ident]) - end - - Thor::Util.thor_classes_in(self).each do |subclass| - namespace = options[:namespace] == true || subclass.namespace.gsub(/^#{self.namespace}:/, '') - subclass.help(shell, options.merge(:short => true, :namespace => namespace)) - end - - class_options_help(shell, "Class") unless options[:short] - end - end - - protected - - # The banner for this class. You can customize it if you are invoking the - # thor class by another ways which is not the Thor::Runner. It receives - # the task that is going to be invoked and a boolean which indicates if - # the namespace should be displayed as arguments. - # - def banner(task, namespace=true, show_options=true) - task.formatted_usage(self, namespace, show_options) - end - - def baseclass #:nodoc: - Thor - end - - def create_task(meth) #:nodoc: - if @usage && @desc - tasks[meth.to_s] = Thor::Task.new(meth, @desc, @usage, method_options) - @usage, @desc, @method_options = nil - true - elsif self.all_tasks[meth.to_s] || meth.to_sym == :method_missing - true - else - puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " << - "Call desc if you want this method to be available as task or declare it inside a " << - "no_tasks{} block. Invoked from #{caller[1].inspect}." - false - end - end - - def initialize_added #:nodoc: - class_options.merge!(method_options) - @method_options = nil - end - - # Receives a task name (can be nil), and try to get a map from it. - # If a map can't be found use the sent name or the default task. - # - def normalize_task_name(meth) #:nodoc: - mapping = map[meth.to_s] - meth = mapping || meth || default_task - meth.to_s.gsub('-','_') # treat foo-bar > foo_bar - end - end - - include Thor::Base - - map HELP_MAPPINGS => :help - - desc "help [TASK]", "Describe available tasks or one specific task" - def help(task=nil) - self.class.help(shell, task, :namespace => task && task.include?(?:)) - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb deleted file mode 100644 index d561ccb2aa..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb +++ /dev/null @@ -1,273 +0,0 @@ -require 'fileutils' - -Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action| - require action -end - -class Thor - module Actions - attr_accessor :behavior - - def self.included(base) #:nodoc: - base.extend ClassMethods - end - - module ClassMethods - # Hold source paths for one Thor instance. source_paths_for_search is the - # method responsible to gather source_paths from this current class, - # inherited paths and the source root. - # - def source_paths - @source_paths ||= [] - end - - # Returns the source paths in the following order: - # - # 1) This class source paths - # 2) Source root - # 3) Parents source paths - # - def source_paths_for_search - paths = [] - paths += self.source_paths - paths << self.source_root if self.respond_to?(:source_root) - paths += from_superclass(:source_paths, []) - paths - end - - # Add runtime options that help actions execution. - # - def add_runtime_options! - class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime, - :desc => "Run but do not make any changes" - - class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime, - :desc => "Overwrite files that already exist" - - class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime, - :desc => "Skip files that already exist" - - class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime, - :desc => "Supress status output" - end - end - - # Extends initializer to add more configuration options. - # - # ==== Configuration - # behavior:: The actions default behavior. Can be :invoke or :revoke. - # It also accepts :force, :skip and :pretend to set the behavior - # and the respective option. - # - # destination_root:: The root directory needed for some actions. - # - def initialize(args=[], options={}, config={}) - self.behavior = case config[:behavior].to_s - when "force", "skip" - _cleanup_options_and_set(options, config[:behavior]) - :invoke - when "revoke" - :revoke - else - :invoke - end - - super - self.destination_root = config[:destination_root] - end - - # Wraps an action object and call it accordingly to the thor class behavior. - # - def action(instance) #:nodoc: - if behavior == :revoke - instance.revoke! - else - instance.invoke! - end - end - - # Returns the root for this thor class (also aliased as destination root). - # - def destination_root - @destination_stack.last - end - - # Sets the root for this thor class. Relatives path are added to the - # directory where the script was invoked and expanded. - # - def destination_root=(root) - @destination_stack ||= [] - @destination_stack[0] = File.expand_path(root || '') - end - - # Returns the given path relative to the absolute root (ie, root where - # the script started). - # - def relative_to_original_destination_root(path, remove_dot=true) - path = path.gsub(@destination_stack[0], '.') - remove_dot ? (path[2..-1] || '') : path - end - - # Holds source paths in instance so they can be manipulated. - # - def source_paths - @source_paths ||= self.class.source_paths_for_search - end - - # Receives a file or directory and search for it in the source paths. - # - def find_in_source_paths(file) - relative_root = relative_to_original_destination_root(destination_root, false) - - source_paths.each do |source| - source_file = File.expand_path(file, File.join(source, relative_root)) - return source_file if File.exists?(source_file) - end - - if source_paths.empty? - raise Error, "You don't have any source path defined for class #{self.class.name}. To fix this, " << - "you can define a source_root in your class." - else - raise Error, "Could not find #{file.inspect} in source paths." - end - end - - # Do something in the root or on a provided subfolder. If a relative path - # is given it's referenced from the current root. The full path is yielded - # to the block you provide. The path is set back to the previous path when - # the method exits. - # - # ==== Parameters - # dir:: the directory to move to. - # config:: give :verbose => true to log and use padding. - # - def inside(dir='', config={}, &block) - verbose = config.fetch(:verbose, false) - - say_status :inside, dir, verbose - shell.padding += 1 if verbose - @destination_stack.push File.expand_path(dir, destination_root) - - FileUtils.mkdir_p(destination_root) unless File.exist?(destination_root) - FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield } - - @destination_stack.pop - shell.padding -= 1 if verbose - end - - # Goes to the root and execute the given block. - # - def in_root - inside(@destination_stack.first) { yield } - end - - # Loads an external file and execute it in the instance binding. - # - # ==== Parameters - # path:: The path to the file to execute. Can be a web address or - # a relative path from the source root. - # - # ==== Examples - # - # apply "http://gist.github.com/103208" - # - # apply "recipes/jquery.rb" - # - def apply(path, config={}) - verbose = config.fetch(:verbose, true) - path = find_in_source_paths(path) unless path =~ /^http\:\/\// - - say_status :apply, path, verbose - shell.padding += 1 if verbose - instance_eval(open(path).read) - shell.padding -= 1 if verbose - end - - # Executes a command. - # - # ==== Parameters - # command:: the command to be executed. - # config:: give :verbose => false to not log the status. Specify :with - # to append an executable to command executation. - # - # ==== Example - # - # inside('vendor') do - # run('ln -s ~/edge rails') - # end - # - def run(command, config={}) - return unless behavior == :invoke - - destination = relative_to_original_destination_root(destination_root, false) - desc = "#{command} from #{destination.inspect}" - - if config[:with] - desc = "#{File.basename(config[:with].to_s)} #{desc}" - command = "#{config[:with]} #{command}" - end - - say_status :run, desc, config.fetch(:verbose, true) - system(command) unless options[:pretend] - end - - # Executes a ruby script (taking into account WIN32 platform quirks). - # - # ==== Parameters - # command:: the command to be executed. - # config:: give :verbose => false to not log the status. - # - def run_ruby_script(command, config={}) - return unless behavior == :invoke - run "#{command}", config.merge(:with => Thor::Util.ruby_command) - end - - # Run a thor command. A hash of options can be given and it's converted to - # switches. - # - # ==== Parameters - # task:: the task to be invoked - # args:: arguments to the task - # config:: give :verbose => false to not log the status. Other options - # are given as parameter to Thor. - # - # ==== Examples - # - # thor :install, "http://gist.github.com/103208" - # #=> thor install http://gist.github.com/103208 - # - # thor :list, :all => true, :substring => 'rails' - # #=> thor list --all --substring=rails - # - def thor(task, *args) - config = args.last.is_a?(Hash) ? args.pop : {} - verbose = config.key?(:verbose) ? config.delete(:verbose) : true - - args.unshift task - args.push Thor::Options.to_switches(config) - command = args.join(' ').strip - - run command, :with => :thor, :verbose => verbose - end - - protected - - # Allow current root to be shared between invocations. - # - def _shared_configuration #:nodoc: - super.merge!(:destination_root => self.destination_root) - end - - def _cleanup_options_and_set(options, key) #:nodoc: - case options - when Array - %w(--force -f --skip -s).each { |i| options.delete(i) } - options << "--#{key}" - when Hash - [:force, :skip, "force", "skip"].each { |i| options.delete(i) } - options.merge!(key => true) - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb deleted file mode 100644 index a3d9296823..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb +++ /dev/null @@ -1,103 +0,0 @@ -require 'thor/actions/empty_directory' - -class Thor - module Actions - - # Create a new file relative to the destination root with the given data, - # which is the return value of a block or a data string. - # - # ==== Parameters - # destination:: the relative path to the destination root. - # data:: the data to append to the file. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # create_file "lib/fun_party.rb" do - # hostname = ask("What is the virtual hostname I should use?") - # "vhost.name = #{hostname}" - # end - # - # create_file "config/apach.conf", "your apache config" - # - def create_file(destination, data=nil, config={}, &block) - action CreateFile.new(self, destination, block || data.to_s, config) - end - alias :add_file :create_file - - # AddFile is a subset of Template, which instead of rendering a file with - # ERB, it gets the content from the user. - # - class CreateFile < EmptyDirectory #:nodoc: - attr_reader :data - - def initialize(base, destination, data, config={}) - @data = data - super(base, destination, config) - end - - # Checks if the content of the file at the destination is identical to the rendered result. - # - # ==== Returns - # Boolean:: true if it is identical, false otherwise. - # - def identical? - exists? && File.read(destination) == render - end - - # Holds the content to be added to the file. - # - def render - @render ||= if data.is_a?(Proc) - data.call - else - data - end - end - - def invoke! - invoke_with_conflict_check do - FileUtils.mkdir_p(File.dirname(destination)) - File.open(destination, 'w'){ |f| f.write render } - end - given_destination - end - - protected - - # Now on conflict we check if the file is identical or not. - # - def on_conflict_behavior(&block) - if identical? - say_status :identical, :blue - else - options = base.options.merge(config) - force_or_skip_or_conflict(options[:force], options[:skip], &block) - end - end - - # If force is true, run the action, otherwise check if it's not being - # skipped. If both are false, show the file_collision menu, if the menu - # returns true, force it, otherwise skip. - # - def force_or_skip_or_conflict(force, skip, &block) - if force - say_status :force, :yellow - block.call unless pretend? - elsif skip - say_status :skip, :yellow - else - say_status :conflict, :red - force_or_skip_or_conflict(force_on_collision?, true, &block) - end - end - - # Shows the file collision menu to the user and gets the result. - # - def force_on_collision? - base.shell.file_collision(destination){ render } - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb deleted file mode 100644 index 467e63732a..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb +++ /dev/null @@ -1,93 +0,0 @@ -require 'thor/actions/empty_directory' - -class Thor - module Actions - - # Copies recursively the files from source directory to root directory. - # If any of the files finishes with .tt, it's considered to be a template - # and is placed in the destination without the extension .tt. If any - # empty directory is found, it's copied and all .empty_directory files are - # ignored. Remember that file paths can also be encoded, let's suppose a doc - # directory with the following files: - # - # doc/ - # components/.empty_directory - # README - # rdoc.rb.tt - # %app_name%.rb - # - # When invoked as: - # - # directory "doc" - # - # It will create a doc directory in the destination with the following - # files (assuming that the app_name is "blog"): - # - # doc/ - # components/ - # README - # rdoc.rb - # blog.rb - # - # ==== Parameters - # source:: the relative path to the source root. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # If :recursive => false, does not look for paths recursively. - # - # ==== Examples - # - # directory "doc" - # directory "doc", "docs", :recursive => false - # - def directory(source, destination=nil, config={}, &block) - action Directory.new(self, source, destination || source, config, &block) - end - - class Directory < EmptyDirectory #:nodoc: - attr_reader :source - - def initialize(base, source, destination=nil, config={}, &block) - @source = File.expand_path(base.find_in_source_paths(source.to_s)) - @block = block - super(base, destination, { :recursive => true }.merge(config)) - end - - def invoke! - base.empty_directory given_destination, config - execute! - end - - def revoke! - execute! - end - - protected - - def execute! - lookup = config[:recursive] ? File.join(source, '**') : source - lookup = File.join(lookup, '{*,.[a-z]*}') - - Dir[lookup].each do |file_source| - next if File.directory?(file_source) - file_destination = File.join(given_destination, file_source.gsub(source, '.')) - file_destination.gsub!('/./', '/') - - case file_source - when /\.empty_directory$/ - dirname = File.dirname(file_destination).gsub(/\/\.$/, '') - next if dirname == given_destination - base.empty_directory(dirname, config) - when /\.tt$/ - destination = base.template(file_source, file_destination[0..-4], config) - @block.call(destination) if @block - else - destination = base.copy_file(file_source, file_destination, config) - @block.call(destination) if @block - end - end - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb deleted file mode 100644 index 484cb820f8..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb +++ /dev/null @@ -1,134 +0,0 @@ -class Thor - module Actions - - # Creates an empty directory. - # - # ==== Parameters - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # empty_directory "doc" - # - def empty_directory(destination, config={}) - action EmptyDirectory.new(self, destination, config) - end - - # Class which holds create directory logic. This is the base class for - # other actions like create_file and directory. - # - # This implementation is based in Templater actions, created by Jonas Nicklas - # and Michael S. Klishin under MIT LICENSE. - # - class EmptyDirectory #:nodoc: - attr_reader :base, :destination, :given_destination, :relative_destination, :config - - # Initializes given the source and destination. - # - # ==== Parameters - # base:: A Thor::Base instance - # source:: Relative path to the source of this file - # destination:: Relative path to the destination of this file - # config:: give :verbose => false to not log the status. - # - def initialize(base, destination, config={}) - @base, @config = base, { :verbose => true }.merge(config) - self.destination = destination - end - - # Checks if the destination file already exists. - # - # ==== Returns - # Boolean:: true if the file exists, false otherwise. - # - def exists? - ::File.exists?(destination) - end - - def invoke! - invoke_with_conflict_check do - ::FileUtils.mkdir_p(destination) - end - end - - def revoke! - say_status :remove, :red - ::FileUtils.rm_rf(destination) if !pretend? && exists? - given_destination - end - - protected - - # Shortcut for pretend. - # - def pretend? - base.options[:pretend] - end - - # Sets the absolute destination value from a relative destination value. - # It also stores the given and relative destination. Let's suppose our - # script is being executed on "dest", it sets the destination root to - # "dest". The destination, given_destination and relative_destination - # are related in the following way: - # - # inside "bar" do - # empty_directory "baz" - # end - # - # destination #=> dest/bar/baz - # relative_destination #=> bar/baz - # given_destination #=> baz - # - def destination=(destination) - if destination - @given_destination = convert_encoded_instructions(destination.to_s) - @destination = ::File.expand_path(@given_destination, base.destination_root) - @relative_destination = base.relative_to_original_destination_root(@destination) - end - end - - # Filenames in the encoded form are converted. If you have a file: - # - # %class_name%.rb - # - # It gets the class name from the base and replace it: - # - # user.rb - # - def convert_encoded_instructions(filename) - filename.gsub(/%(.*?)%/) do |string| - instruction = $1.strip - base.respond_to?(instruction) ? base.send(instruction) : string - end - end - - # Receives a hash of options and just execute the block if some - # conditions are met. - # - def invoke_with_conflict_check(&block) - if exists? - on_conflict_behavior(&block) - else - say_status :create, :green - block.call unless pretend? - end - - destination - end - - # What to do when the destination file already exists. - # - def on_conflict_behavior(&block) - say_status :exist, :blue - end - - # Shortcut to say_status shell method. - # - def say_status(status, color) - base.shell.say_status status, relative_destination, color if config[:verbose] - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb deleted file mode 100644 index d77d90d448..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb +++ /dev/null @@ -1,219 +0,0 @@ -require 'erb' -require 'open-uri' - -class Thor - module Actions - - # Copies the file from the relative source to the relative destination. If - # the destination is not given it's assumed to be equal to the source. - # - # ==== Parameters - # source:: the relative path to the source root. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # copy_file "README", "doc/README" - # - # copy_file "doc/README" - # - def copy_file(source, destination=nil, config={}) - destination ||= source - source = File.expand_path(find_in_source_paths(source.to_s)) - - create_file destination, nil, config do - File.read(source) - end - end - - # Gets the content at the given address and places it at the given relative - # destination. If a block is given instead of destination, the content of - # the url is yielded and used as location. - # - # ==== Parameters - # source:: the address of the given content. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # get "http://gist.github.com/103208", "doc/README" - # - # get "http://gist.github.com/103208" do |content| - # content.split("\n").first - # end - # - def get(source, destination=nil, config={}, &block) - source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^http\:\/\// - render = open(source).read - - destination ||= if block_given? - block.arity == 1 ? block.call(render) : block.call - else - File.basename(source) - end - - create_file destination, render, config - end - - # Gets an ERB template at the relative source, executes it and makes a copy - # at the relative destination. If the destination is not given it's assumed - # to be equal to the source removing .tt from the filename. - # - # ==== Parameters - # source:: the relative path to the source root. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # template "README", "doc/README" - # - # template "doc/README" - # - def template(source, destination=nil, config={}) - destination ||= source - source = File.expand_path(find_in_source_paths(source.to_s)) - context = instance_eval('binding') - - create_file destination, nil, config do - ERB.new(::File.read(source), nil, '-').result(context) - end - end - - # Changes the mode of the given file or directory. - # - # ==== Parameters - # mode:: the file mode - # path:: the name of the file to change mode - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # chmod "script/*", 0755 - # - def chmod(path, mode, config={}) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) - FileUtils.chmod_R(mode, path) unless options[:pretend] - end - - # Prepend text to a file. Since it depends on inject_into_file, it's reversible. - # - # ==== Parameters - # path:: path of the file to be changed - # data:: the data to prepend to the file, can be also given as a block. - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # prepend_file 'config/environments/test.rb', 'config.gem "rspec"' - # - # prepend_file 'config/environments/test.rb' do - # 'config.gem "rspec"' - # end - # - def prepend_file(path, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config.merge!(:after => /\A/) - inject_into_file(path, *(args << config), &block) - end - - # Append text to a file. Since it depends on inject_into_file, it's reversible. - # - # ==== Parameters - # path:: path of the file to be changed - # data:: the data to append to the file, can be also given as a block. - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # append_file 'config/environments/test.rb', 'config.gem "rspec"' - # - # append_file 'config/environments/test.rb' do - # 'config.gem "rspec"' - # end - # - def append_file(path, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config.merge!(:before => /\z/) - inject_into_file(path, *(args << config), &block) - end - - # Injects text right after the class definition. Since it depends on - # inject_into_file, it's reversible. - # - # ==== Parameters - # path:: path of the file to be changed - # klass:: the class to be manipulated - # data:: the data to append to the class, can be also given as a block. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # inject_into_class "app/controllers/application_controller.rb", " filter_parameter :password\n" - # - # inject_into_class "app/controllers/application_controller.rb", ApplicationController do - # " filter_parameter :password\n" - # end - # - def inject_into_class(path, klass, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/) - inject_into_file(path, *(args << config), &block) - end - - # Run a regular expression replacement on a file. - # - # ==== Parameters - # path:: path of the file to be changed - # flag:: the regexp or string to be replaced - # replacement:: the replacement, can be also given as a block - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' - # - # gsub_file 'README', /rake/, :green do |match| - # match << " no more. Use thor!" - # end - # - def gsub_file(path, flag, *args, &block) - return unless behavior == :invoke - config = args.last.is_a?(Hash) ? args.pop : {} - - path = File.expand_path(path, destination_root) - say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) - - unless options[:pretend] - content = File.read(path) - content.gsub!(flag, *args, &block) - File.open(path, 'wb') { |file| file.write(content) } - end - end - - # Removes a file at the given location. - # - # ==== Parameters - # path:: path of the file to be changed - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # remove_file 'README' - # remove_file 'app/controllers/application_controller.rb' - # - def remove_file(path, config={}) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - - say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) - ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path) - end - alias :remove_dir :remove_file - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb deleted file mode 100644 index 0636ec6591..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb +++ /dev/null @@ -1,101 +0,0 @@ -require 'thor/actions/empty_directory' - -class Thor - module Actions - - # Injects the given content into a file. Different from gsub_file, this - # method is reversible. - # - # ==== Parameters - # destination:: Relative path to the destination root - # data:: Data to add to the file. Can be given as a block. - # config:: give :verbose => false to not log the status and the flag - # for injection (:after or :before). - # - # ==== Examples - # - # inject_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n" - # - # inject_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do - # gems = ask "Which gems would you like to add?" - # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n") - # end - # - def inject_into_file(destination, *args, &block) - if block_given? - data, config = block, args.shift - else - data, config = args.shift, args.shift - end - action InjectIntoFile.new(self, destination, data, config) - end - - class InjectIntoFile < EmptyDirectory #:nodoc: - attr_reader :replacement, :flag, :behavior - - def initialize(base, destination, data, config) - super(base, destination, { :verbose => true }.merge(config)) - - @behavior, @flag = if @config.key?(:after) - [:after, @config.delete(:after)] - else - [:before, @config.delete(:before)] - end - - @replacement = data.is_a?(Proc) ? data.call : data - @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp) - end - - def invoke! - say_status :invoke - - content = if @behavior == :after - '\0' + replacement - else - replacement + '\0' - end - - replace!(/#{flag}/, content) - end - - def revoke! - say_status :revoke - - regexp = if @behavior == :after - content = '\1\2' - /(#{flag})(.*)(#{Regexp.escape(replacement)})/m - else - content = '\2\3' - /(#{Regexp.escape(replacement)})(.*)(#{flag})/m - end - - replace!(regexp, content) - end - - protected - - def say_status(behavior) - status = if flag == /\A/ - behavior == :invoke ? :prepend : :unprepend - elsif flag == /\z/ - behavior == :invoke ? :append : :unappend - else - behavior == :invoke ? :inject : :deinject - end - - super(status, config[:verbose]) - end - - # Adds the content to the file. - # - def replace!(regexp, string) - unless base.options[:pretend] - content = File.read(destination) - content.gsub!(regexp, string) - File.open(destination, 'wb') { |file| file.write(content) } - end - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb deleted file mode 100644 index 700d794123..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb +++ /dev/null @@ -1,517 +0,0 @@ -require 'thor/core_ext/hash_with_indifferent_access' -require 'thor/core_ext/ordered_hash' -require 'thor/error' -require 'thor/shell' -require 'thor/invocation' -require 'thor/parser' -require 'thor/task' -require 'thor/util' - -class Thor - # Shortcuts for help. - HELP_MAPPINGS = %w(-h -? --help -D) - - # Thor methods that should not be overwritten by the user. - THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root - action add_file create_file in_root inside run run_ruby_script) - - module Base - attr_accessor :options - - # It receives arguments in an Array and two hashes, one for options and - # other for configuration. - # - # Notice that it does not check if all required arguments were supplied. - # It should be done by the parser. - # - # ==== Parameters - # args:: An array of objects. The objects are applied to their - # respective accessors declared with argument. - # - # options:: An options hash that will be available as self.options. - # The hash given is converted to a hash with indifferent - # access, magic predicates (options.skip?) and then frozen. - # - # config:: Configuration for this Thor class. - # - def initialize(args=[], options={}, config={}) - Thor::Arguments.parse(self.class.arguments, args).each do |key, value| - send("#{key}=", value) - end - - parse_options = self.class.class_options - - if options.is_a?(Array) - task_options = config.delete(:task_options) # hook for start - parse_options = parse_options.merge(task_options) if task_options - array_options, hash_options = options, {} - else - array_options, hash_options = [], options - end - - options = Thor::Options.parse(parse_options, array_options) - self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).merge!(hash_options) - self.options.freeze - end - - class << self - def included(base) #:nodoc: - base.send :extend, ClassMethods - base.send :include, Invocation - base.send :include, Shell - end - - # Returns the classes that inherits from Thor or Thor::Group. - # - # ==== Returns - # Array[Class] - # - def subclasses - @subclasses ||= [] - end - - # Returns the files where the subclasses are kept. - # - # ==== Returns - # Hash[path => Class] - # - def subclass_files - @subclass_files ||= Hash.new{ |h,k| h[k] = [] } - end - - # Whenever a class inherits from Thor or Thor::Group, we should track the - # class and the file on Thor::Base. This is the method responsable for it. - # - def register_klass_file(klass) #:nodoc: - file = caller[1].match(/(.*):\d+/)[1] - Thor::Base.subclasses << klass unless Thor::Base.subclasses.include?(klass) - - file_subclasses = Thor::Base.subclass_files[File.expand_path(file)] - file_subclasses << klass unless file_subclasses.include?(klass) - end - end - - module ClassMethods - # Adds an argument to the class and creates an attr_accessor for it. - # - # Arguments are different from options in several aspects. The first one - # is how they are parsed from the command line, arguments are retrieved - # from position: - # - # thor task NAME - # - # Instead of: - # - # thor task --name=NAME - # - # Besides, arguments are used inside your code as an accessor (self.argument), - # while options are all kept in a hash (self.options). - # - # Finally, arguments cannot have type :default or :boolean but can be - # optional (supplying :optional => :true or :required => false), although - # you cannot have a required argument after a non-required argument. If you - # try it, an error is raised. - # - # ==== Parameters - # name:: The name of the argument. - # options:: Described below. - # - # ==== Options - # :desc - Description for the argument. - # :required - If the argument is required or not. - # :optional - If the argument is optional or not. - # :type - The type of the argument, can be :string, :hash, :array, :numeric. - # :default - Default value for this argument. It cannot be required and have default values. - # :banner - String to show on usage notes. - # - # ==== Errors - # ArgumentError:: Raised if you supply a required argument after a non required one. - # - def argument(name, options={}) - is_thor_reserved_word?(name, :argument) - no_tasks { attr_accessor name } - - required = if options.key?(:optional) - !options[:optional] - elsif options.key?(:required) - options[:required] - else - options[:default].nil? - end - - remove_argument name - - arguments.each do |argument| - next if argument.required? - raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " << - "the non-required argument #{argument.human_name.inspect}." - end if required - - arguments << Thor::Argument.new(name, options[:desc], required, options[:type], - options[:default], options[:banner]) - end - - # Returns this class arguments, looking up in the ancestors chain. - # - # ==== Returns - # Array[Thor::Argument] - # - def arguments - @arguments ||= from_superclass(:arguments, []) - end - - # Adds a bunch of options to the set of class options. - # - # class_options :foo => false, :bar => :required, :baz => :string - # - # If you prefer more detailed declaration, check class_option. - # - # ==== Parameters - # Hash[Symbol => Object] - # - def class_options(options=nil) - @class_options ||= from_superclass(:class_options, {}) - build_options(options, @class_options) if options - @class_options - end - - # Adds an option to the set of class options - # - # ==== Parameters - # name:: The name of the argument. - # options:: Described below. - # - # ==== Options - # :desc - Description for the argument. - # :required - If the argument is required or not. - # :default - Default value for this argument. - # :group - The group for this options. Use by class options to output options in different levels. - # :aliases - Aliases for this option. - # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. - # :banner - String to show on usage notes. - # - def class_option(name, options={}) - build_option(name, options, class_options) - end - - # Removes a previous defined argument. If :undefine is given, undefine - # accessors as well. - # - # ==== Paremeters - # names:: Arguments to be removed - # - # ==== Examples - # - # remove_argument :foo - # remove_argument :foo, :bar, :baz, :undefine => true - # - def remove_argument(*names) - options = names.last.is_a?(Hash) ? names.pop : {} - - names.each do |name| - arguments.delete_if { |a| a.name == name.to_s } - undef_method name, "#{name}=" if options[:undefine] - end - end - - # Removes a previous defined class option. - # - # ==== Paremeters - # names:: Class options to be removed - # - # ==== Examples - # - # remove_class_option :foo - # remove_class_option :foo, :bar, :baz - # - def remove_class_option(*names) - names.each do |name| - class_options.delete(name) - end - end - - # Defines the group. This is used when thor list is invoked so you can specify - # that only tasks from a pre-defined group will be shown. Defaults to standard. - # - # ==== Parameters - # name - # - def group(name=nil) - case name - when nil - @group ||= from_superclass(:group, 'standard') - else - @group = name.to_s - end - end - - # Returns the tasks for this Thor class. - # - # ==== Returns - # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task - # objects as values. - # - def tasks - @tasks ||= Thor::CoreExt::OrderedHash.new - end - - # Returns the tasks for this Thor class and all subclasses. - # - # ==== Returns - # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task - # objects as values. - # - def all_tasks - @all_tasks ||= from_superclass(:all_tasks, Thor::CoreExt::OrderedHash.new) - @all_tasks.merge(tasks) - end - - # Removes a given task from this Thor class. This is usually done if you - # are inheriting from another class and don't want it to be available - # anymore. - # - # By default it only remove the mapping to the task. But you can supply - # :undefine => true to undefine the method from the class as well. - # - # ==== Parameters - # name:: The name of the task to be removed - # options:: You can give :undefine => true if you want tasks the method - # to be undefined from the class as well. - # - def remove_task(*names) - options = names.last.is_a?(Hash) ? names.pop : {} - - names.each do |name| - tasks.delete(name.to_s) - all_tasks.delete(name.to_s) - undef_method name if options[:undefine] - end - end - - # All methods defined inside the given block are not added as tasks. - # - # So you can do: - # - # class MyScript < Thor - # no_tasks do - # def this_is_not_a_task - # end - # end - # end - # - # You can also add the method and remove it from the task list: - # - # class MyScript < Thor - # def this_is_not_a_task - # end - # remove_task :this_is_not_a_task - # end - # - def no_tasks - @no_tasks = true - yield - @no_tasks = false - end - - # Sets the namespace for the Thor or Thor::Group class. By default the - # namespace is retrieved from the class name. If your Thor class is named - # Scripts::MyScript, the help method, for example, will be called as: - # - # thor scripts:my_script -h - # - # If you change the namespace: - # - # namespace :my_scripts - # - # You change how your tasks are invoked: - # - # thor my_scripts -h - # - # Finally, if you change your namespace to default: - # - # namespace :default - # - # Your tasks can be invoked with a shortcut. Instead of: - # - # thor :my_task - # - def namespace(name=nil) - case name - when nil - @namespace ||= Thor::Util.namespace_from_thor_class(self, false) - else - @namespace = name.to_s - end - end - - # Default way to start generators from the command line. - # - def start(given_args=ARGV, config={}) - config[:shell] ||= Thor::Base.shell.new - yield - rescue Thor::Error => e - if given_args.include?("--debug") - raise e - else - config[:shell].error e.message - end - exit(1) if exit_on_failure? - end - - protected - - # Prints the class options per group. If an option does not belong to - # any group, it uses the ungrouped name value. This method provide to - # hooks to add extra options, one of them if the third argument called - # extra_group that should be a hash in the format :group => Array[Options]. - # - # The second is by returning a lambda used to print values. The lambda - # requires two options: the group name and the array of options. - # - def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc: - groups = {} - - class_options.each do |_, value| - groups[value.group] ||= [] - groups[value.group] << value - end - - printer = proc do |group_name, options| - list = [] - padding = options.collect{ |o| o.aliases.size }.max.to_i * 4 - - options.each do |option| - item = [ option.usage(padding) ] - item.push(option.description ? "# #{option.description}" : "") - - list << item - list << [ "", "# Default: #{option.default}" ] if option.show_default? - end - - unless list.empty? - shell.say(group_name ? "#{group_name} options:" : "Options:") - shell.print_table(list, :ident => 2) - shell.say "" - end - end - - # Deal with default group - global_options = groups.delete(nil) || [] - printer.call(ungrouped_name, global_options) if global_options - - # Print all others - groups = extra_group.merge(groups) if extra_group - groups.each(&printer) - printer - end - - # Raises an error if the word given is a Thor reserved word. - # - def is_thor_reserved_word?(word, type) #:nodoc: - return false unless THOR_RESERVED_WORDS.include?(word.to_s) - raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}" - end - - # Build an option and adds it to the given scope. - # - # ==== Parameters - # name:: The name of the argument. - # options:: Described in both class_option and method_option. - # - def build_option(name, options, scope) #:nodoc: - scope[name] = Thor::Option.new(name, options[:desc], options[:required], - options[:type], options[:default], options[:banner], - options[:group], options[:aliases]) - end - - # Receives a hash of options, parse them and add to the scope. This is a - # fast way to set a bunch of options: - # - # build_options :foo => true, :bar => :required, :baz => :string - # - # ==== Parameters - # Hash[Symbol => Object] - # - def build_options(options, scope) #:nodoc: - options.each do |key, value| - scope[key] = Thor::Option.parse(key, value) - end - end - - # Finds a task with the given name. If the task belongs to the current - # class, just return it, otherwise dup it and add the fresh copy to the - # current task hash. - # - def find_and_refresh_task(name) #:nodoc: - task = if task = tasks[name.to_s] - task - elsif task = all_tasks[name.to_s] - tasks[name.to_s] = task.clone - else - raise ArgumentError, "You supplied :for => #{name.inspect}, but the task #{name.inspect} could not be found." - end - end - - # Everytime someone inherits from a Thor class, register the klass - # and file into baseclass. - # - def inherited(klass) - Thor::Base.register_klass_file(klass) - end - - # Fire this callback whenever a method is added. Added methods are - # tracked as tasks by invoking the create_task method. - # - def method_added(meth) - meth = meth.to_s - - if meth == "initialize" - initialize_added - return - end - - # Return if it's not a public instance method - return unless public_instance_methods.include?(meth) || - public_instance_methods.include?(meth.to_sym) - - return if @no_tasks || !create_task(meth) - - is_thor_reserved_word?(meth, :task) - Thor::Base.register_klass_file(self) - end - - # Retrieves a value from superclass. If it reaches the baseclass, - # returns default. - # - def from_superclass(method, default=nil) - if self == baseclass || !superclass.respond_to?(method, true) - default - else - value = superclass.send(method) - value.dup if value - end - end - - # A flag that makes the process exit with status 1 if any error happens. - # - def exit_on_failure? - false - end - - # SIGNATURE: Sets the baseclass. This is where the superclass lookup - # finishes. - def baseclass #:nodoc: - end - - # SIGNATURE: Creates a new task if valid_task? is true. This method is - # called when a new method is added to the class. - def create_task(meth) #:nodoc: - end - - # SIGNATURE: Defines behavior when the initialize method is added to the - # class. - def initialize_added #:nodoc: - end - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb deleted file mode 100644 index 78bc5cf4bf..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb +++ /dev/null @@ -1,75 +0,0 @@ -class Thor - module CoreExt #:nodoc: - - # A hash with indifferent access and magic predicates. - # - # hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true - # - # hash[:foo] #=> 'bar' - # hash['foo'] #=> 'bar' - # hash.foo? #=> true - # - class HashWithIndifferentAccess < ::Hash #:nodoc: - - def initialize(hash={}) - super() - hash.each do |key, value| - self[convert_key(key)] = value - end - end - - def [](key) - super(convert_key(key)) - end - - def []=(key, value) - super(convert_key(key), value) - end - - def delete(key) - super(convert_key(key)) - end - - def values_at(*indices) - indices.collect { |key| self[convert_key(key)] } - end - - def merge(other) - dup.merge!(other) - end - - def merge!(other) - other.each do |key, value| - self[convert_key(key)] = value - end - self - end - - protected - - def convert_key(key) - key.is_a?(Symbol) ? key.to_s : key - end - - # Magic predicates. For instance: - # - # options.force? # => !!options['force'] - # options.shebang # => "/usr/lib/local/ruby" - # options.test_framework?(:rspec) # => options[:test_framework] == :rspec - # - def method_missing(method, *args, &block) - method = method.to_s - if method =~ /^(\w+)\?$/ - if args.empty? - !!self[$1] - else - self[$1] == args.first - end - else - self[method] - end - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb deleted file mode 100644 index 27fea5bb35..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb +++ /dev/null @@ -1,100 +0,0 @@ -class Thor - module CoreExt #:nodoc: - - if RUBY_VERSION >= '1.9' - class OrderedHash < ::Hash - end - else - # This class is based on the Ruby 1.9 ordered hashes. - # - # It keeps the semantics and most of the efficiency of normal hashes - # while also keeping track of the order in which elements were set. - # - class OrderedHash #:nodoc: - include Enumerable - - Node = Struct.new(:key, :value, :next, :prev) - - def initialize - @hash = {} - end - - def [](key) - @hash[key] && @hash[key].value - end - - def []=(key, value) - if node = @hash[key] - node.value = value - else - node = Node.new(key, value) - - if @first.nil? - @first = @last = node - else - node.prev = @last - @last.next = node - @last = node - end - end - - @hash[key] = node - value - end - - def delete(key) - if node = @hash[key] - prev_node = node.prev - next_node = node.next - - next_node.prev = prev_node if next_node - prev_node.next = next_node if prev_node - - @first = next_node if @first == node - @last = prev_node if @last == node - - value = node.value - end - - @hash.delete(key) - value - end - - def keys - self.map { |k, v| k } - end - - def values - self.map { |k, v| v } - end - - def each - return unless @first - yield [@first.key, @first.value] - node = @first - yield [node.key, node.value] while node = node.next - self - end - - def merge(other) - hash = self.class.new - - self.each do |key, value| - hash[key] = value - end - - other.each do |key, value| - hash[key] = value - end - - hash - end - - def empty? - @hash.empty? - end - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb deleted file mode 100644 index f9b31a35d1..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb +++ /dev/null @@ -1,27 +0,0 @@ -class Thor - # Thor::Error is raised when it's caused by wrong usage of thor classes. Those - # errors have their backtrace supressed and are nicely shown to the user. - # - # Errors that are caused by the developer, like declaring a method which - # overwrites a thor keyword, it SHOULD NOT raise a Thor::Error. This way, we - # ensure that developer errors are shown with full backtrace. - # - class Error < StandardError - end - - # Raised when a task was not found. - # - class UndefinedTaskError < Error - end - - # Raised when a task was found, but not invoked properly. - # - class InvocationError < Error - end - - class RequiredArgumentMissingError < InvocationError - end - - class MalformattedArgumentError < InvocationError - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb deleted file mode 100644 index 0964a9667a..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb +++ /dev/null @@ -1,263 +0,0 @@ -# Thor has a special class called Thor::Group. The main difference to Thor class -# is that it invokes all tasks at once. It also include some methods that allows -# invocations to be done at the class method, which are not available to Thor -# tasks. -# -class Thor::Group - class << self - # The descrition for this Thor::Group. If none is provided, but a source root - # exists, tries to find the USAGE one folder above it, otherwise searches - # in the superclass. - # - # ==== Parameters - # description:: The description for this Thor::Group. - # - def desc(description=nil) - case description - when nil - @desc ||= from_superclass(:desc, nil) - else - @desc = description - end - end - - # Start works differently in Thor::Group, it simply invokes all tasks - # inside the class. - # - def start(given_args=ARGV, config={}) - super do - if Thor::HELP_MAPPINGS.include?(given_args.first) - help(config[:shell]) - return - end - - args, opts = Thor::Options.split(given_args) - new(args, opts, config).invoke - end - end - - # Prints help information. - # - # ==== Options - # short:: When true, shows only usage. - # - def help(shell, options={}) - if options[:short] - shell.say banner - else - shell.say "Usage:" - shell.say " #{banner}" - shell.say - class_options_help(shell) - shell.say self.desc if self.desc - end - end - - # Stores invocations for this class merging with superclass values. - # - def invocations #:nodoc: - @invocations ||= from_superclass(:invocations, {}) - end - - # Stores invocation blocks used on invoke_from_option. - # - def invocation_blocks #:nodoc: - @invocation_blocks ||= from_superclass(:invocation_blocks, {}) - end - - # Invoke the given namespace or class given. It adds an instance - # method that will invoke the klass and task. You can give a block to - # configure how it will be invoked. - # - # The namespace/class given will have its options showed on the help - # usage. Check invoke_from_option for more information. - # - def invoke(*names, &block) - options = names.last.is_a?(Hash) ? names.pop : {} - verbose = options.fetch(:verbose, true) - - names.each do |name| - invocations[name] = false - invocation_blocks[name] = block if block_given? - - class_eval <<-METHOD, __FILE__, __LINE__ - def _invoke_#{name.to_s.gsub(/\W/, '_')} - klass, task = self.class.prepare_for_invocation(nil, #{name.inspect}) - - if klass - say_status :invoke, #{name.inspect}, #{verbose.inspect} - block = self.class.invocation_blocks[#{name.inspect}] - _invoke_for_class_method klass, task, &block - else - say_status :error, %(#{name.inspect} [not found]), :red - end - end - METHOD - end - end - - # Invoke a thor class based on the value supplied by the user to the - # given option named "name". A class option must be created before this - # method is invoked for each name given. - # - # ==== Examples - # - # class GemGenerator < Thor::Group - # class_option :test_framework, :type => :string - # invoke_from_option :test_framework - # end - # - # ==== Boolean options - # - # In some cases, you want to invoke a thor class if some option is true or - # false. This is automatically handled by invoke_from_option. Then the - # option name is used to invoke the generator. - # - # ==== Preparing for invocation - # - # In some cases you want to customize how a specified hook is going to be - # invoked. You can do that by overwriting the class method - # prepare_for_invocation. The class method must necessarily return a klass - # and an optional task. - # - # ==== Custom invocations - # - # You can also supply a block to customize how the option is giong to be - # invoked. The block receives two parameters, an instance of the current - # class and the klass to be invoked. - # - def invoke_from_option(*names, &block) - options = names.last.is_a?(Hash) ? names.pop : {} - verbose = options.fetch(:verbose, :white) - - names.each do |name| - unless class_options.key?(name) - raise ArgumentError, "You have to define the option #{name.inspect} " << - "before setting invoke_from_option." - end - - invocations[name] = true - invocation_blocks[name] = block if block_given? - - class_eval <<-METHOD, __FILE__, __LINE__ - def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')} - return unless options[#{name.inspect}] - - value = options[#{name.inspect}] - value = #{name.inspect} if TrueClass === value - klass, task = self.class.prepare_for_invocation(#{name.inspect}, value) - - if klass - say_status :invoke, value, #{verbose.inspect} - block = self.class.invocation_blocks[#{name.inspect}] - _invoke_for_class_method klass, task, &block - else - say_status :error, %(\#{value} [not found]), :red - end - end - METHOD - end - end - - # Remove a previously added invocation. - # - # ==== Examples - # - # remove_invocation :test_framework - # - def remove_invocation(*names) - names.each do |name| - remove_task(name) - remove_class_option(name) - invocations.delete(name) - invocation_blocks.delete(name) - end - end - - # Overwrite class options help to allow invoked generators options to be - # shown recursively when invoking a generator. - # - def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc: - group_options = {} - - get_options_from_invocations(group_options, class_options) do |klass| - klass.send(:get_options_from_invocations, group_options, class_options) - end - - group_options.merge!(extra_group) if extra_group - super(shell, ungrouped_name, group_options) - end - - # Get invocations array and merge options from invocations. Those - # options are added to group_options hash. Options that already exists - # in base_options are not added twice. - # - def get_options_from_invocations(group_options, base_options) #:nodoc: - invocations.each do |name, from_option| - value = if from_option - option = class_options[name] - option.type == :boolean ? name : option.default - else - name - end - next unless value - - klass, task = prepare_for_invocation(name, value) - next unless klass && klass.respond_to?(:class_options) - - value = value.to_s - human_name = value.respond_to?(:classify) ? value.classify : value - - group_options[human_name] ||= [] - group_options[human_name] += klass.class_options.values.select do |option| - base_options[option.name.to_sym].nil? && option.group.nil? && - !group_options.values.flatten.any? { |i| i.name == option.name } - end - - yield klass if block_given? - end - end - - protected - - # The banner for this class. You can customize it if you are invoking the - # thor class by another ways which is not the Thor::Runner. - # - def banner - "#{self.namespace} #{self.arguments.map {|a| a.usage }.join(' ')}" - end - - def baseclass #:nodoc: - Thor::Group - end - - def create_task(meth) #:nodoc: - tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil) - true - end - end - - include Thor::Base - - protected - - # Shortcut to invoke with padding and block handling. Use internally by - # invoke and invoke_from_option class methods. - # - def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc: - shell.padding += 1 - - result = if block_given? - if block.arity == 2 - block.call(self, klass) - else - block.call(self, klass, task) - end - else - invoke klass, task, *args - end - - shell.padding -= 1 - result - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb deleted file mode 100644 index 32e6a72454..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb +++ /dev/null @@ -1,178 +0,0 @@ -class Thor - module Invocation - def self.included(base) #:nodoc: - base.extend ClassMethods - end - - module ClassMethods - # Prepare for class methods invocations. This method must return a klass to - # have the invoked class options showed in help messages in generators. - # - def prepare_for_invocation(key, name) #:nodoc: - case name - when Symbol, String - Thor::Util.namespace_to_thor_class_and_task(name.to_s, false) - else - name - end - end - end - - # Make initializer aware of invocations and the initializer proc. - # - def initialize(args=[], options={}, config={}, &block) #:nodoc: - @_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] } - @_initializer = [ args, options, config ] - super - end - - # Receives a name and invokes it. The name can be a string (either "task" or - # "namespace:task"), a Thor::Task, a Class or a Thor instance. If the task - # cannot be guessed by name, it can also be supplied as second argument. - # - # You can also supply the arguments, options and configuration values for - # the task to be invoked, if none is given, the same values used to - # initialize the invoker are used to initialize the invoked. - # - # ==== Examples - # - # class A < Thor - # def foo - # invoke :bar - # invoke "b:hello", ["José"] - # end - # - # def bar - # invoke "b:hello", ["José"] - # end - # end - # - # class B < Thor - # def hello(name) - # puts "hello #{name}" - # end - # end - # - # You can notice that the method "foo" above invokes two tasks: "bar", - # which belongs to the same class and "hello" which belongs to the class B. - # - # By using an invocation system you ensure that a task is invoked only once. - # In the example above, invoking "foo" will invoke "b:hello" just once, even - # if it's invoked later by "bar" method. - # - # When class A invokes class B, all arguments used on A initialization are - # supplied to B. This allows lazy parse of options. Let's suppose you have - # some rspec tasks: - # - # class Rspec < Thor::Group - # class_option :mock_framework, :type => :string, :default => :rr - # - # def invoke_mock_framework - # invoke "rspec:#{options[:mock_framework]}" - # end - # end - # - # As you noticed, it invokes the given mock framework, which might have its - # own options: - # - # class Rspec::RR < Thor::Group - # class_option :style, :type => :string, :default => :mock - # end - # - # Since it's not rspec concern to parse mock framework options, when RR - # is invoked all options are parsed again, so RR can extract only the options - # that it's going to use. - # - # If you want Rspec::RR to be initialized with its own set of options, you - # have to do that explicitely: - # - # invoke "rspec:rr", [], :style => :foo - # - # Besides giving an instance, you can also give a class to invoke: - # - # invoke Rspec::RR, [], :style => :foo - # - def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil) - task, args, opts, config = nil, task, args, opts if task.nil? || task.is_a?(Array) - args, opts, config = nil, args, opts if args.is_a?(Hash) - - object, task = _prepare_for_invocation(name, task) - klass, instance = _initialize_klass_with_initializer(object, args, opts, config) - - method_args = [] - current = @_invocations[klass] - - iterator = proc do |_, task| - unless current.include?(task.name) - current << task.name - task.run(instance, method_args) - end - end - - if task - args ||= [] - method_args = args[Range.new(klass.arguments.size, -1)] || [] - iterator.call(nil, task) - else - klass.all_tasks.map(&iterator) - end - end - - protected - - # Configuration values that are shared between invocations. - # - def _shared_configuration #:nodoc: - { :invocations => @_invocations } - end - - # Prepare for invocation in the instance level. In this case, we have to - # take into account that a just a task name from the current class was - # given or even a Thor::Task object. - # - def _prepare_for_invocation(name, sent_task=nil) #:nodoc: - if name.is_a?(Thor::Task) - task = name - elsif task = self.class.all_tasks[name.to_s] - object = self - else - object, task = self.class.prepare_for_invocation(nil, name) - task ||= sent_task - end - - # If the object was not set, use self and use the name as task. - object, task = self, name unless object - return object, _validate_task(object, task) - end - - # Check if the object given is a Thor class object and get a task object - # for it. - # - def _validate_task(object, task) #:nodoc: - klass = object.is_a?(Class) ? object : object.class - raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base - - task ||= klass.default_task if klass <= Thor - task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task) - task - end - - # Initialize klass using values stored in the @_initializer. - # - def _initialize_klass_with_initializer(object, args, opts, config) #:nodoc: - if object.is_a?(Class) - klass = object - - stored_args, stored_opts, stored_config = @_initializer - args ||= stored_args.dup - opts ||= stored_opts.dup - - config ||= {} - config = stored_config.merge(_shared_configuration).merge!(config) - [ klass, klass.new(args, opts, config) ] - else - [ object.class, object ] - end - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb deleted file mode 100644 index 57a3f6e1a5..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'thor/parser/argument' -require 'thor/parser/arguments' -require 'thor/parser/option' -require 'thor/parser/options' diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb deleted file mode 100644 index aa8ace4719..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb +++ /dev/null @@ -1,67 +0,0 @@ -class Thor - class Argument #:nodoc: - VALID_TYPES = [ :numeric, :hash, :array, :string ] - - attr_reader :name, :description, :required, :type, :default, :banner - alias :human_name :name - - def initialize(name, description=nil, required=true, type=:string, default=nil, banner=nil) - class_name = self.class.name.split("::").last - - raise ArgumentError, "#{class_name} name can't be nil." if name.nil? - raise ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type) - - @name = name.to_s - @description = description - @required = required || false - @type = (type || :string).to_sym - @default = default - @banner = banner || default_banner - - validate! # Trigger specific validations - end - - def usage - required? ? banner : "[#{banner}]" - end - - def required? - required - end - - def show_default? - case default - when Array, String, Hash - !default.empty? - else - default - end - end - - protected - - def validate! - raise ArgumentError, "An argument cannot be required and have default value." if required? && !default.nil? - end - - def valid_type?(type) - VALID_TYPES.include?(type.to_sym) - end - - def default_banner - case type - when :boolean - nil - when :string, :default - human_name.upcase - when :numeric - "N" - when :hash - "key:value" - when :array - "one two three" - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb deleted file mode 100644 index fb5d965e06..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb +++ /dev/null @@ -1,145 +0,0 @@ -class Thor - class Arguments #:nodoc: - NUMERIC = /(\d*\.\d+|\d+)/ - - # Receives an array of args and returns two arrays, one with arguments - # and one with switches. - # - def self.split(args) - arguments = [] - - args.each do |item| - break if item =~ /^-/ - arguments << item - end - - return arguments, args[Range.new(arguments.size, -1)] - end - - def self.parse(base, args) - new(base).parse(args) - end - - # Takes an array of Thor::Argument objects. - # - def initialize(arguments=[]) - @assigns, @non_assigned_required = {}, [] - @switches = arguments - - arguments.each do |argument| - if argument.default - @assigns[argument.human_name] = argument.default - elsif argument.required? - @non_assigned_required << argument - end - end - end - - def parse(args) - @pile = args.dup - - @switches.each do |argument| - break unless peek - @non_assigned_required.delete(argument) - @assigns[argument.human_name] = send(:"parse_#{argument.type}", argument.human_name) - end - - check_requirement! - @assigns - end - - private - - def peek - @pile.first - end - - def shift - @pile.shift - end - - def unshift(arg) - unless arg.kind_of?(Array) - @pile.unshift(arg) - else - @pile = arg + @pile - end - end - - def current_is_value? - peek && peek.to_s !~ /^-/ - end - - # Runs through the argument array getting strings that contains ":" and - # mark it as a hash: - # - # [ "name:string", "age:integer" ] - # - # Becomes: - # - # { "name" => "string", "age" => "integer" } - # - def parse_hash(name) - return shift if peek.is_a?(Hash) - hash = {} - - while current_is_value? && peek.include?(?:) - key, value = shift.split(':') - hash[key] = value - end - hash - end - - # Runs through the argument array getting all strings until no string is - # found or a switch is found. - # - # ["a", "b", "c"] - # - # And returns it as an array: - # - # ["a", "b", "c"] - # - def parse_array(name) - return shift if peek.is_a?(Array) - array = [] - - while current_is_value? - array << shift - end - array - end - - # Check if the peel is numeric ofrmat and return a Float or Integer. - # Otherwise raises an error. - # - def parse_numeric(name) - return shift if peek.is_a?(Numeric) - - unless peek =~ NUMERIC && $& == peek - raise MalformattedArgumentError, "expected numeric value for '#{name}'; got #{peek.inspect}" - end - - $&.index('.') ? shift.to_f : shift.to_i - end - - # Parse string, i.e., just return the current value in the pile. - # - def parse_string(name) - shift - end - - # Raises an error if @non_assigned_required array is not empty. - # - def check_requirement! - unless @non_assigned_required.empty? - names = @non_assigned_required.map do |o| - o.respond_to?(:switch_name) ? o.switch_name : o.human_name - end.join("', '") - - class_name = self.class.name.split('::').last.downcase - raise RequiredArgumentMissingError, "no value provided for required #{class_name} '#{names}'" - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb deleted file mode 100644 index 9e40ec73fa..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb +++ /dev/null @@ -1,132 +0,0 @@ -class Thor - class Option < Argument #:nodoc: - attr_reader :aliases, :group - - VALID_TYPES = [:boolean, :numeric, :hash, :array, :string] - - def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, group=nil, aliases=nil) - super(name, description, required, type, default, banner) - @aliases = [*aliases].compact - @group = group.to_s.capitalize if group - end - - # This parse quick options given as method_options. It makes several - # assumptions, but you can be more specific using the option method. - # - # parse :foo => "bar" - # #=> Option foo with default value bar - # - # parse [:foo, :baz] => "bar" - # #=> Option foo with default value bar and alias :baz - # - # parse :foo => :required - # #=> Required option foo without default value - # - # parse :foo => 2 - # #=> Option foo with default value 2 and type numeric - # - # parse :foo => :numeric - # #=> Option foo without default value and type numeric - # - # parse :foo => true - # #=> Option foo with default value true and type boolean - # - # The valid types are :boolean, :numeric, :hash, :array and :string. If none - # is given a default type is assumed. This default type accepts arguments as - # string (--foo=value) or booleans (just --foo). - # - # By default all options are optional, unless :required is given. - # - def self.parse(key, value) - if key.is_a?(Array) - name, *aliases = key - else - name, aliases = key, [] - end - - name = name.to_s - default = value - - type = case value - when Symbol - default = nil - - if VALID_TYPES.include?(value) - value - elsif required = (value == :required) - :string - elsif value == :optional - # TODO Remove this warning in the future. - warn "Optional type is deprecated. Choose :boolean or :string instead. Assumed to be :boolean." - :boolean - end - when TrueClass, FalseClass - :boolean - when Numeric - :numeric - when Hash, Array, String - value.class.name.downcase.to_sym - end - - self.new(name.to_s, nil, required, type, default, nil, nil, aliases) - end - - def switch_name - @switch_name ||= dasherized? ? name : dasherize(name) - end - - def human_name - @human_name ||= dasherized? ? undasherize(name) : name - end - - def usage(padding=0) - sample = if banner && !banner.to_s.empty? - "#{switch_name}=#{banner}" - else - switch_name - end - - sample = "[#{sample}]" unless required? - - if aliases.empty? - (" " * padding) << sample - else - "#{aliases.join(', ')}, #{sample}" - end - end - - # Allow some type predicates as: boolean?, string? and etc. - # - def method_missing(method, *args, &block) - given = method.to_s.sub(/\?$/, '').to_sym - if valid_type?(given) - self.type == given - else - super - end - end - - protected - - def validate! - raise ArgumentError, "An option cannot be boolean and required." if boolean? && required? - end - - def valid_type?(type) - VALID_TYPES.include?(type.to_sym) - end - - def dasherized? - name.index('-') == 0 - end - - def undasherize(str) - str.sub(/^-{1,2}/, '') - end - - def dasherize(str) - (str.length > 1 ? "--" : "-") + str.gsub('_', '-') - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb deleted file mode 100644 index 75092308b5..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb +++ /dev/null @@ -1,142 +0,0 @@ -class Thor - # This is a modified version of Daniel Berger's Getopt::Long class, licensed - # under Ruby's license. - # - class Options < Arguments #:nodoc: - LONG_RE = /^(--\w+[-\w+]*)$/ - SHORT_RE = /^(-[a-z])$/i - EQ_RE = /^(--\w+[-\w+]*|-[a-z])=(.*)$/i - SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args - SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i - - # Receives a hash and makes it switches. - # - def self.to_switches(options) - options.map do |key, value| - case value - when true - "--#{key}" - when Array - "--#{key} #{value.map{ |v| v.inspect }.join(' ')}" - when Hash - "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}" - when nil, false - "" - else - "--#{key} #{value.inspect}" - end - end.join(" ") - end - - # Takes a hash of Thor::Option objects. - # - def initialize(options={}) - options = options.values - super(options) - @shorts, @switches = {}, {} - - options.each do |option| - @switches[option.switch_name] = option - - option.aliases.each do |short| - @shorts[short.to_s] ||= option.switch_name - end - end - end - - def parse(args) - @pile = args.dup - - while peek - if current_is_switch? - case shift - when SHORT_SQ_RE - unshift($1.split('').map { |f| "-#{f}" }) - next - when EQ_RE, SHORT_NUM - unshift($2) - switch = $1 - when LONG_RE, SHORT_RE - switch = $1 - end - - switch = normalize_switch(switch) - next unless option = switch_option(switch) - - @assigns[option.human_name] = parse_peek(switch, option) - else - shift - end - end - - check_requirement! - @assigns - end - - protected - - # Returns true if the current value in peek is a registered switch. - # - def current_is_switch? - case peek - when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM - switch?($1) - when SHORT_SQ_RE - $1.split('').any? { |f| switch?("-#{f}") } - end - end - - def switch?(arg) - switch_option(arg) || @shorts.key?(arg) - end - - def switch_option(arg) - if match = no_or_skip?(arg) - @switches[arg] || @switches["--#{match}"] - else - @switches[arg] - end - end - - def no_or_skip?(arg) - arg =~ /^--(no|skip)-([-\w]+)$/ - $2 - end - - # Check if the given argument is actually a shortcut. - # - def normalize_switch(arg) - @shorts.key?(arg) ? @shorts[arg] : arg - end - - # Parse boolean values which can be given as --foo=true, --foo or --no-foo. - # - def parse_boolean(switch) - if current_is_value? - ["true", "TRUE", "t", "T", true].include?(shift) - else - @switches.key?(switch) || !no_or_skip?(switch) - end - end - - # Parse the value at the peek analyzing if it requires an input or not. - # - def parse_peek(switch, option) - unless current_is_value? - if option.boolean? - # No problem for boolean types - elsif no_or_skip?(switch) - return nil # User set value to nil - elsif option.string? && !option.required? - return option.human_name # Return the option name - else - raise MalformattedArgumentError, "no value provided for option '#{switch}'" - end - end - - @non_assigned_required.delete(option) - send(:"parse_#{option.type}", switch) - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb deleted file mode 100644 index 0d0757fdda..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'rake' - -class Thor - # Adds a compatibility layer to your Thor classes which allows you to use - # rake package tasks. For example, to use rspec rake tasks, one can do: - # - # require 'thor/rake_compat' - # - # class Default < Thor - # include Thor::RakeCompat - # - # Spec::Rake::SpecTask.new(:spec) do |t| - # t.spec_opts = ['--options', "spec/spec.opts"] - # t.spec_files = FileList['spec/**/*_spec.rb'] - # end - # end - # - module RakeCompat - def self.rake_classes - @rake_classes ||= [] - end - - def self.included(base) - # Hack. Make rakefile point to invoker, so rdoc task is generated properly. - rakefile = File.basename(caller[0].match(/(.*):\d+/)[1]) - Rake.application.instance_variable_set(:@rakefile, rakefile) - self.rake_classes << base - end - end -end - -class Object #:nodoc: - alias :rake_task :task - alias :rake_namespace :namespace - - def task(*args, &block) - task = rake_task(*args, &block) - - if klass = Thor::RakeCompat.rake_classes.last - non_namespaced_name = task.name.split(':').last - - description = non_namespaced_name - description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ') - description.strip! - - klass.desc description, task.comment || non_namespaced_name - klass.send :define_method, non_namespaced_name do |*args| - Rake::Task[task.name.to_sym].invoke(*args) - end - end - - task - end - - def namespace(name, &block) - if klass = Thor::RakeCompat.rake_classes.last - const_name = Thor::Util.camel_case(name.to_s).to_sym - klass.const_set(const_name, Class.new(Thor)) - new_klass = klass.const_get(const_name) - Thor::RakeCompat.rake_classes << new_klass - end - - rake_namespace(name, &block) - Thor::RakeCompat.rake_classes.pop - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb deleted file mode 100644 index 9dc70ea069..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb +++ /dev/null @@ -1,299 +0,0 @@ -require 'fileutils' -require 'open-uri' -require 'yaml' -require 'digest/md5' -require 'pathname' - -class Thor::Runner < Thor #:nodoc: - map "-T" => :list, "-i" => :install, "-u" => :update - - # Override Thor#help so it can give information about any class and any method. - # - def help(meth=nil) - if meth && !self.respond_to?(meth) - initialize_thorfiles(meth) - klass, task = Thor::Util.namespace_to_thor_class_and_task(meth) - # Send mapping -h because it works with Thor::Group too - klass.start(["-h", task].compact, :shell => self.shell) - else - super - end - end - - # If a task is not found on Thor::Runner, method missing is invoked and - # Thor::Runner is then responsable for finding the task in all classes. - # - def method_missing(meth, *args) - meth = meth.to_s - initialize_thorfiles(meth) - klass, task = Thor::Util.namespace_to_thor_class_and_task(meth) - args.unshift(task) if task - klass.start(args, :shell => shell) - end - - desc "install NAME", "Install an optionally named Thor file into your system tasks" - method_options :as => :string, :relative => :boolean - def install(name) - initialize_thorfiles - - # If a directory name is provided as the argument, look for a 'main.thor' - # task in said directory. - begin - if File.directory?(File.expand_path(name)) - base, package = File.join(name, "main.thor"), :directory - contents = open(base).read - else - base, package = name, :file - contents = open(name).read - end - rescue OpenURI::HTTPError - raise Error, "Error opening URI '#{name}'" - rescue Errno::ENOENT - raise Error, "Error opening file '#{name}'" - end - - say "Your Thorfile contains:" - say contents - - return false if no?("Do you wish to continue [y/N]?") - - as = options["as"] || begin - first_line = contents.split("\n")[0] - (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil - end - - unless as - basename = File.basename(name) - as = ask("Please specify a name for #{name} in the system repository [#{basename}]:") - as = basename if as.empty? - end - - location = if options[:relative] || name =~ /^http:\/\// - name - else - File.expand_path(name) - end - - thor_yaml[as] = { - :filename => Digest::MD5.hexdigest(name + as), - :location => location, - :namespaces => Thor::Util.namespaces_in_content(contents, base) - } - - save_yaml(thor_yaml) - say "Storing thor file in your system repository" - destination = File.join(thor_root, thor_yaml[as][:filename]) - - if package == :file - File.open(destination, "w") { |f| f.puts contents } - else - FileUtils.cp_r(name, destination) - end - - thor_yaml[as][:filename] # Indicate success - end - - desc "uninstall NAME", "Uninstall a named Thor module" - def uninstall(name) - raise Error, "Can't find module '#{name}'" unless thor_yaml[name] - say "Uninstalling #{name}." - FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}")) - - thor_yaml.delete(name) - save_yaml(thor_yaml) - - puts "Done." - end - - desc "update NAME", "Update a Thor file from its original location" - def update(name) - raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location] - - say "Updating '#{name}' from #{thor_yaml[name][:location]}" - - old_filename = thor_yaml[name][:filename] - self.options = self.options.merge("as" => name) - filename = install(thor_yaml[name][:location]) - - unless filename == old_filename - File.delete(File.join(thor_root, old_filename)) - end - end - - desc "installed", "List the installed Thor modules and tasks" - method_options :internal => :boolean - def installed - initialize_thorfiles(nil, true) - - klasses = Thor::Base.subclasses - klasses -= [Thor, Thor::Runner] unless options["internal"] - - display_klasses(true, klasses) - end - - desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)" - method_options :substring => :boolean, :group => :string, :all => :boolean - def list(search="") - initialize_thorfiles - - search = ".*#{search}" if options["substring"] - search = /^#{search}.*/i - group = options[:group] || "standard" - - klasses = Thor::Base.subclasses.select do |k| - (options[:all] || k.group == group) && k.namespace =~ search - end - - display_klasses(false, klasses) - end - - private - - def thor_root - Thor::Util.thor_root - end - - def thor_yaml - @thor_yaml ||= begin - yaml_file = File.join(thor_root, "thor.yml") - yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file) - yaml || {} - end - end - - # Save the yaml file. If none exists in thor root, creates one. - # - def save_yaml(yaml) - yaml_file = File.join(thor_root, "thor.yml") - - unless File.exists?(yaml_file) - FileUtils.mkdir_p(thor_root) - yaml_file = File.join(thor_root, "thor.yml") - FileUtils.touch(yaml_file) - end - - File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml } - end - - def self.exit_on_failure? - true - end - - # Load the thorfiles. If relevant_to is supplied, looks for specific files - # in the thor_root instead of loading them all. - # - # By default, it also traverses the current path until find Thor files, as - # described in thorfiles. This look up can be skipped by suppliying - # skip_lookup true. - # - def initialize_thorfiles(relevant_to=nil, skip_lookup=false) - thorfiles(relevant_to, skip_lookup).each do |f| - Thor::Util.load_thorfile(f) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f)) - end - end - - # Finds Thorfiles by traversing from your current directory down to the root - # directory of your system. If at any time we find a Thor file, we stop. - # - # We also ensure that system-wide Thorfiles are loaded first, so local - # Thorfiles can override them. - # - # ==== Example - # - # If we start at /Users/wycats/dev/thor ... - # - # 1. /Users/wycats/dev/thor - # 2. /Users/wycats/dev - # 3. /Users/wycats <-- we find a Thorfile here, so we stop - # - # Suppose we start at c:\Documents and Settings\james\dev\thor ... - # - # 1. c:\Documents and Settings\james\dev\thor - # 2. c:\Documents and Settings\james\dev - # 3. c:\Documents and Settings\james - # 4. c:\Documents and Settings - # 5. c:\ <-- no Thorfiles found! - # - def thorfiles(relevant_to=nil, skip_lookup=false) - # TODO Remove this dealing with deprecated thor when :namespaces: is available as constants - save_yaml(thor_yaml) if Thor::Util.convert_constants_to_namespaces(thor_yaml) - - thorfiles = [] - - unless skip_lookup - Pathname.pwd.ascend do |path| - thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten - break unless thorfiles.empty? - end - end - - files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob) - files += thorfiles - files -= ["#{thor_root}/thor.yml"] - - files.map! do |file| - File.directory?(file) ? File.join(file, "main.thor") : file - end - end - - # Load thorfiles relevant to the given method. If you provide "foo:bar" it - # will load all thor files in the thor.yaml that has "foo" e "foo:bar" - # namespaces registered. - # - def thorfiles_relevant_to(meth) - lookup = [ meth, meth.split(":")[0...-1].join(":") ] - - files = thor_yaml.select do |k, v| - v[:namespaces] && !(v[:namespaces] & lookup).empty? - end - - files.map { |k, v| File.join(thor_root, "#{v[:filename]}") } - end - - # Display information about the given klasses. If with_module is given, - # it shows a table with information extracted from the yaml file. - # - def display_klasses(with_modules=false, klasses=Thor.subclasses) - klasses -= [Thor, Thor::Runner] unless with_modules - raise Error, "No Thor tasks available" if klasses.empty? - - if with_modules && !thor_yaml.empty? - info = [] - labels = ["Modules", "Namespaces"] - - info << labels - info << [ "-" * labels[0].size, "-" * labels[1].size ] - - thor_yaml.each do |name, hash| - info << [ name, hash[:namespaces].join(", ") ] - end - - print_table info - say "" - end - - unless klasses.empty? - klasses.dup.each do |klass| - klasses -= Thor::Util.thor_classes_in(klass) - end - - klasses.each { |k| display_tasks(k) } - else - say "\033[1;34mNo Thor tasks available\033[0m" - end - end - - # Display tasks from the given Thor class. - # - def display_tasks(klass) - unless klass.tasks.empty? - base = klass.namespace - - color = base == "default" ? :magenta : :blue - say shell.set_color(base, color, true) - say "-" * base.length - - klass.help(shell, :short => true, :ident => 0, :namespace => true) - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb deleted file mode 100644 index 1dc8f0e5b4..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb +++ /dev/null @@ -1,78 +0,0 @@ -require 'rbconfig' -require 'thor/shell/color' - -class Thor - module Base - # Returns the shell used in all Thor classes. If you are in a Unix platform - # it will use a colored log, otherwise it will use a basic one without color. - # - def self.shell - @shell ||= if Config::CONFIG['host_os'] =~ /mswin|mingw/ - Thor::Shell::Basic - else - Thor::Shell::Color - end - end - - # Sets the shell used in all Thor classes. - # - def self.shell=(klass) - @shell = klass - end - end - - module Shell - SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_list, :print_table] - - # Add shell to initialize config values. - # - # ==== Configuration - # shell:: An instance of the shell to be used. - # - # ==== Examples - # - # class MyScript < Thor - # argument :first, :type => :numeric - # end - # - # MyScript.new [1.0], { :foo => :bar }, :shell => Thor::Shell::Basic.new - # - def initialize(args=[], options={}, config={}) - super - self.shell = config[:shell] - self.shell.base ||= self if self.shell.respond_to?(:base) - end - - # Holds the shell for the given Thor instance. If no shell is given, - # it gets a default shell from Thor::Base.shell. - # - def shell - @shell ||= Thor::Base.shell.new - end - - # Sets the shell for this thor class. - # - def shell=(shell) - @shell = shell - end - - # Common methods that are delegated to the shell. - # - SHELL_DELEGATED_METHODS.each do |method| - module_eval <<-METHOD, __FILE__, __LINE__ - def #{method}(*args) - shell.#{method}(*args) - end - METHOD - end - - protected - - # Allow shell to be shared between invocations. - # - def _shared_configuration #:nodoc: - super.merge!(:shell => self.shell) - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb deleted file mode 100644 index ea9665380b..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb +++ /dev/null @@ -1,219 +0,0 @@ -require 'tempfile' - -class Thor - module Shell - class Basic - attr_accessor :base, :padding - - # Initialize base and padding to nil. - # - def initialize #:nodoc: - @base, @padding = nil, 0 - end - - # Sets the output padding, not allowing less than zero values. - # - def padding=(value) - @padding = [0, value].max - end - - # Ask something to the user and receives a response. - # - # ==== Example - # ask("What is your name?") - # - def ask(statement, color=nil) - say("#{statement} ", color) - $stdin.gets.strip - end - - # Say (print) something to the user. If the sentence ends with a whitespace - # or tab character, a new line is not appended (print + flush). Otherwise - # are passed straight to puts (behavior got from Highline). - # - # ==== Example - # say("I know you knew that.") - # - def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/)) - message = message.to_s - message = set_color(message, color) if color - - if force_new_line - $stdout.puts(message) - else - $stdout.print(message) - $stdout.flush - end - end - - # Say a status with the given color and appends the message. Since this - # method is used frequently by actions, it allows nil or false to be given - # in log_status, avoiding the message from being shown. If a Symbol is - # given in log_status, it's used as the color. - # - def say_status(status, message, log_status=true) - return if quiet? || log_status == false - spaces = " " * (padding + 1) - color = log_status.is_a?(Symbol) ? log_status : :green - - status = status.to_s.rjust(12) - status = set_color status, color, true if color - say "#{status}#{spaces}#{message}", nil, true - end - - # Make a question the to user and returns true if the user replies "y" or - # "yes". - # - def yes?(statement, color=nil) - ask(statement, color) =~ is?(:yes) - end - - # Make a question the to user and returns true if the user replies "n" or - # "no". - # - def no?(statement, color=nil) - !yes?(statement, color) - end - - # Prints a list of items. - # - # ==== Parameters - # list - # - # ==== Options - # mode:: Can be :rows or :inline. Defaults to :rows. - # ident:: Ident each item with the value given. - # - def print_list(list, options={}) - return if list.empty? - - ident = " " * (options[:ident] || 0) - content = case options[:mode] - when :inline - last = list.pop - "#{list.join(", ")}, and #{last}" - else # rows - ident + list.join("\n#{ident}") - end - - $stdout.puts content - end - - # Prints a table. - # - # ==== Parameters - # Array[Array[String, String, ...]] - # - # ==== Options - # ident:: Ident the first column by ident value. - # - def print_table(table, options={}) - return if table.empty? - - formats = [] - 0.upto(table.first.length - 2) do |i| - maxima = table.max{ |a,b| a[i].size <=> b[i].size }[i].size - formats << "%-#{maxima + 2}s" - end - - formats[0] = formats[0].insert(0, " " * options[:ident]) if options[:ident] - formats << "%s" - - table.each do |row| - row.each_with_index do |column, i| - $stdout.print formats[i] % column.to_s - end - $stdout.puts - end - end - - # Deals with file collision and returns true if the file should be - # overwriten and false otherwise. If a block is given, it uses the block - # response as the content for the diff. - # - # ==== Parameters - # destination:: the destination file to solve conflicts - # block:: an optional block that returns the value to be used in diff - # - def file_collision(destination) - return true if @always_force - options = block_given? ? "[Ynaqdh]" : "[Ynaqh]" - - while true - answer = ask %[Overwrite #{destination}? (enter "h" for help) #{options}] - - case answer - when is?(:yes), is?(:force) - return true - when is?(:no), is?(:skip) - return false - when is?(:always) - return @always_force = true - when is?(:quit) - say 'Aborting...' - raise SystemExit - when is?(:diff) - show_diff(destination, yield) if block_given? - say 'Retrying...' - else - say file_collision_help - end - end - end - - # Called if something goes wrong during the execution. This is used by Thor - # internally and should not be used inside your scripts. If someone went - # wrong, you can always raise an exception. If you raise a Thor::Error, it - # will be rescued and wrapped in the method below. - # - def error(statement) - $stderr.puts statement - end - - # Apply color to the given string with optional bold. Disabled in the - # Thor::Shell::Basic class. - # - def set_color(string, color, bold=false) #:nodoc: - string - end - - protected - - def is?(value) #:nodoc: - value = value.to_s - - if value.size == 1 - /\A#{value}\z/i - else - /\A(#{value}|#{value[0,1]})\z/i - end - end - - def file_collision_help #:nodoc: -< e - parse_argument_error(instance, e, caller) - rescue NoMethodError => e - parse_no_method_error(instance, e) - end - - # Returns the formatted usage. If a class is given, the class arguments are - # injected in the usage. - # - def formatted_usage(klass=nil, namespace=false, show_options=true) - formatted = if namespace.is_a?(String) - "#{namespace}:" - elsif klass && namespace - "#{klass.namespace.gsub(/^default/,'')}:" - else - "" - end - - formatted << formatted_arguments(klass) - formatted << " #{formatted_options}" if show_options - formatted.strip! - formatted - end - - # Injects the class arguments into the task usage. - # - def formatted_arguments(klass) - if klass && !klass.arguments.empty? - usage.to_s.gsub(/^#{name}/) do |match| - match << " " << klass.arguments.map{ |a| a.usage }.join(' ') - end - else - usage.to_s - end - end - - # Returns the options usage for this task. - # - def formatted_options - @formatted_options ||= options.map{ |_, o| o.usage }.sort.join(" ") - end - - protected - - # Given a target, checks if this class name is not a private/protected method. - # - def public_method?(instance) #:nodoc: - collection = instance.private_methods + instance.protected_methods - (collection & [name.to_s, name.to_sym]).empty? - end - - # Clean everything that comes from the Thor gempath and remove the caller. - # - def sans_backtrace(backtrace, caller) #:nodoc: - dirname = /^#{Regexp.escape(File.dirname(__FILE__))}/ - saned = backtrace.reject { |frame| frame =~ dirname } - saned -= caller - end - - def parse_argument_error(instance, e, caller) #:nodoc: - backtrace = sans_backtrace(e.backtrace, caller) - - if backtrace.empty? && e.message =~ /wrong number of arguments/ - if instance.is_a?(Thor::Group) - raise e, "'#{name}' was called incorrectly. Are you sure it has arity equals to 0?" - else - raise InvocationError, "'#{name}' was called incorrectly. Call as " << - "'#{formatted_usage(instance.class, true)}'" - end - else - raise e - end - end - - def parse_no_method_error(instance, e) #:nodoc: - if e.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/ - raise UndefinedTaskError, "The #{instance.class.namespace} namespace " << - "doesn't have a '#{name}' task" - else - raise e - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb deleted file mode 100644 index ebae0a3193..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb +++ /dev/null @@ -1,251 +0,0 @@ -require 'rbconfig' - -class Thor - module Sandbox #:nodoc: - end - - # This module holds several utilities: - # - # 1) Methods to convert thor namespaces to constants and vice-versa. - # - # Thor::Utils.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz" - # - # 2) Loading thor files and sandboxing: - # - # Thor::Utils.load_thorfile("~/.thor/foo") - # - module Util - - # Receives a namespace and search for it in the Thor::Base subclasses. - # - # ==== Parameters - # namespace:: The namespace to search for. - # - def self.find_by_namespace(namespace) - namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/ - - Thor::Base.subclasses.find do |klass| - klass.namespace == namespace - end - end - - # Receives a constant and converts it to a Thor namespace. Since Thor tasks - # can be added to a sandbox, this method is also responsable for removing - # the sandbox namespace. - # - # This method should not be used in general because it's used to deal with - # older versions of Thor. On current versions, if you need to get the - # namespace from a class, just call namespace on it. - # - # ==== Parameters - # constant:: The constant to be converted to the thor path. - # - # ==== Returns - # String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz" - # - def self.namespace_from_thor_class(constant, remove_default=true) - constant = constant.to_s.gsub(/^Thor::Sandbox::/, "") - constant = snake_case(constant).squeeze(":") - constant.gsub!(/^default/, '') if remove_default - constant - end - - # Given the contents, evaluate it inside the sandbox and returns the - # namespaces defined in the sandbox. - # - # ==== Parameters - # contents - # - # ==== Returns - # Array[Object] - # - def self.namespaces_in_content(contents, file=__FILE__) - old_constants = Thor::Base.subclasses.dup - Thor::Base.subclasses.clear - - load_thorfile(file, contents) - - new_constants = Thor::Base.subclasses.dup - Thor::Base.subclasses.replace(old_constants) - - new_constants.map!{ |c| c.namespace } - new_constants.compact! - new_constants - end - - # Returns the thor classes declared inside the given class. - # - def self.thor_classes_in(klass) - Thor::Base.subclasses.select do |subclass| - klass.constants.include?(subclass.name.gsub("#{klass.name}::", '')) - end - end - - # Receives a string and convert it to snake case. SnakeCase returns snake_case. - # - # ==== Parameters - # String - # - # ==== Returns - # String - # - def self.snake_case(str) - return str.downcase if str =~ /^[A-Z_]+$/ - str.gsub(/\B[A-Z]/, '_\&').squeeze('_') =~ /_*(.*)/ - return $+.downcase - end - - # Receives a string and convert it to camel case. camel_case returns CamelCase. - # - # ==== Parameters - # String - # - # ==== Returns - # String - # - def self.camel_case(str) - return str if str !~ /_/ && str =~ /[A-Z]+.*/ - str.split('_').map { |i| i.capitalize }.join - end - - # Receives a namespace and tries to retrieve a Thor or Thor::Group class - # from it. It first searches for a class using the all the given namespace, - # if it's not found, removes the highest entry and searches for the class - # again. If found, returns the highest entry as the class name. - # - # ==== Examples - # - # class Foo::Bar < Thor - # def baz - # end - # end - # - # class Baz::Foo < Thor::Group - # end - # - # Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default task - # Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil - # Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz" - # - # ==== Parameters - # namespace - # - # ==== Errors - # Thor::Error:: raised if the namespace cannot be found. - # - # Thor::Error:: raised if the namespace evals to a class which does not - # inherit from Thor or Thor::Group. - # - def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true) - if namespace.include?(?:) - pieces = namespace.split(":") - task = pieces.pop - klass = Thor::Util.find_by_namespace(pieces.join(":")) - end - - unless klass - klass, task = Thor::Util.find_by_namespace(namespace), nil - end - - raise Error, "could not find Thor class or task '#{namespace}'" if raise_if_nil && klass.nil? - return klass, task - end - - # Receives a path and load the thor file in the path. The file is evaluated - # inside the sandbox to avoid namespacing conflicts. - # - def self.load_thorfile(path, content=nil) - content ||= File.read(path) - - begin - Thor::Sandbox.class_eval(content, path) - rescue Exception => e - $stderr.puts "WARNING: unable to load thorfile #{path.inspect}: #{e.message}" - end - end - - # Receives a yaml (hash) and updates all constants entries to namespace. - # This was added to deal with deprecated versions of Thor. - # - # TODO Deprecate this method in the future. - # - # ==== Returns - # TrueClass|FalseClass:: Returns true if any change to the yaml file was made. - # - def self.convert_constants_to_namespaces(yaml) - yaml_changed = false - - yaml.each do |k, v| - next unless v[:constants] && v[:namespaces].nil? - yaml_changed = true - yaml[k][:namespaces] = v[:constants].map{|c| Thor::Util.namespace_from_thor_class(c)} - end - - yaml_changed - end - - def self.user_home - @@user_home ||= if ENV["HOME"] - ENV["HOME"] - elsif ENV["USERPROFILE"] - ENV["USERPROFILE"] - elsif ENV["HOMEDRIVE"] && ENV["HOMEPATH"] - File.join(ENV["HOMEDRIVE"], ENV["HOMEPATH"]) - elsif ENV["APPDATA"] - ENV["APPDATA"] - else - begin - File.expand_path("~") - rescue - if File::ALT_SEPARATOR - "C:/" - else - "/" - end - end - end - end - - # Returns the root where thor files are located, dependending on the OS. - # - def self.thor_root - File.join(user_home, ".thor").gsub(/\\/, '/') - end - - # Returns the files in the thor root. On Windows thor_root will be something - # like this: - # - # C:\Documents and Settings\james\.thor - # - # If we don't #gsub the \ character, Dir.glob will fail. - # - def self.thor_root_glob - files = Dir["#{thor_root}/*"] - - files.map! do |file| - File.directory?(file) ? File.join(file, "main.thor") : file - end - end - - # Where to look for Thor files. - # - def self.globs_for(path) - ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] - end - - # Return the path to the ruby interpreter taking into account multiple - # installations and windows extensions. - # - def self.ruby_command - @ruby_command ||= begin - ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) - ruby << Config::CONFIG['EXEEXT'] - - # escape string in case path to ruby executable contain spaces. - ruby.sub!(/.*\s.*/m, '"\&"') - ruby - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb deleted file mode 100644 index 885230fac4..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Thor - VERSION = "0.11.8".freeze -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc b/railties/lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc new file mode 100644 index 0000000000..606a0cdb52 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc @@ -0,0 +1,82 @@ +== TODO + +* Improve spec coverage for Thor::Runner + +== 0.12, released 2009-11-06 + +* [#7] Do not force white color on status +* [#8] Yield a block with the filename on directory + +== 0.11, released 2009-07-01 + +* Added a rake compatibility layer. It allows you to use spec and rdoc tasks on + Thor classes. + +* BACKWARDS INCOMPATIBLE: aliases are not generated automatically anymore + since it wrong behavior to the invocation system. + +* thor help now show information about any class/task. All those calls are + possible: + + thor help describe + thor help describe:amazing + + Or even with default namespaces: + + thor help :spec + +* Thor::Runner now invokes the default task if none is supplied: + + thor describe # invokes the default task, usually help + +* Thor::Runner now works with mappings: + + thor describe -h + +* Added some documentation and code refactoring. + +== 0.9.8, released 2008-10-20 + +* Fixed some tiny issues that were introduced lately. + +== 0.9.7, released 2008-10-13 + +* Setting global method options on the initialize method works as expected: + All other tasks will accept these global options in addition to their own. +* Added 'group' notion to Thor task sets (class Thor); by default all tasks + are in the 'standard' group. Running 'thor -T' will only show the standard + tasks - adding --all will show all tasks. You can also filter on a specific + group using the --group option: thor -T --group advanced + +== 0.9.6, released 2008-09-13 + +* Generic improvements + +== 0.9.5, released 2008-08-27 + +* Improve Windows compatibility +* Update (incorrect) README and task.thor sample file +* Options hash is now frozen (once returned) +* Allow magic predicates on options object. For instance: `options.force?` +* Add support for :numeric type +* BACKWARDS INCOMPATIBLE: Refactor Thor::Options. You cannot access shorthand forms in options hash anymore (for instance, options[:f]) +* Allow specifying optional args with default values: method_options(:user => "mislav") +* Don't write options for nil or false values. This allows, for example, turning color off when running specs. +* Exit with the status of the spec command to help CI stuff out some. + +== 0.9.4, released 2008-08-13 + +* Try to add Windows compatibility. +* BACKWARDS INCOMPATIBLE: options hash is now accessed as a property in your class and is not passed as last argument anymore +* Allow options at the beginning of the argument list as well as the end. +* Make options available with symbol keys in addition to string keys. +* Allow true to be passed to Thor#method_options to denote a boolean option. +* If loading a thor file fails, don't give up, just print a warning and keep going. +* Make sure that we re-raise errors if they happened further down the pipe than we care about. +* Only delete the old file on updating when the installation of the new one is a success +* Make it Ruby 1.8.5 compatible. +* Don't raise an error if a boolean switch is defined multiple times. +* Thor::Options now doesn't parse through things that look like options but aren't. +* Add URI detection to install task, and make sure we don't append ".thor" to URIs +* Add rake2thor to the gem binfiles. +* Make sure local Thorfiles override system-wide ones. diff --git a/railties/lib/rails/vendor/thor-0.12.1/LICENSE b/railties/lib/rails/vendor/thor-0.12.1/LICENSE new file mode 100644 index 0000000000..98722da459 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008 Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/railties/lib/rails/vendor/thor-0.12.1/README.rdoc b/railties/lib/rails/vendor/thor-0.12.1/README.rdoc new file mode 100644 index 0000000000..ee545f3d97 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/README.rdoc @@ -0,0 +1,234 @@ += thor + +Map options to a class. Simply create a class with the appropriate annotations +and have options automatically map to functions and parameters. + +Example: + + class App < Thor # [1] + map "-L" => :list # [2] + + desc "install APP_NAME", "install one of the available apps" # [3] + method_options :force => :boolean, :alias => :string # [4] + def install(name) + user_alias = options[:alias] + if options.force? + # do something + end + # other code + end + + desc "list [SEARCH]", "list all of the available apps, limited by SEARCH" + def list(search="") + # list everything + end + end + +Thor automatically maps commands as such: + + thor app:install myname --force + +That gets converted to: + + App.new.install("myname") + # with {'force' => true} as options hash + +1. Inherit from Thor to turn a class into an option mapper +2. Map additional non-valid identifiers to specific methods. In this case, convert -L to :list +3. Describe the method immediately below. The first parameter is the usage information, and the second parameter is the description +4. Provide any additional options that will be available the instance method options. + +== Types for method_options + +* :boolean - is parsed as --option or --option=true +* :string - is parsed as --option=VALUE +* :numeric - is parsed as --option=N +* :array - is parsed as --option=one two three +* :hash - is parsed as --option=name:string age:integer + +Besides, method_option allows a default value to be given, examples: + + method_options :force => false + #=> Creates a boolean option with default value false + + method_options :alias => "bar" + #=> Creates a string option with default value "bar" + + method_options :threshold => 3.0 + #=> Creates a numeric option with default value 3.0 + +You can also supply :option => :required to mark an option as required. The +type is assumed to be string. If you want a required hash with default values +as option, you can use method_option which uses a more declarative style: + + method_option :attributes, :type => :hash, :default => {}, :required => true + +All arguments can be set to nil (except required arguments), by suppling a no or +skip variant. For example: + + thor app name --no-attributes + +In previous versions, aliases for options were created automatically, but now +they should be explicit. You can supply aliases in both short and declarative +styles: + + method_options %w( force -f ) => :boolean + +Or: + + method_option :force, :type => :boolean, :aliases => "-f" + +You can supply as many aliases as you want. + +NOTE: Type :optional available in Thor 0.9.0 was deprecated. Use :string or :boolean instead. + +== Namespaces + +By default, your Thor tasks are invoked using Ruby namespace. In the example +above, tasks are invoked as: + + thor app:install name --force + +However, you could namespace your class as: + + module Sinatra + class App < Thor + # tasks + end + end + +And then you should invoke your tasks as: + + thor sinatra:app:install name --force + +If desired, you can change the namespace: + + module Sinatra + class App < Thor + namespace :myapp + # tasks + end + end + +And then your tasks hould be invoked as: + + thor myapp:install name --force + +== Invocations + +Thor comes with a invocation-dependency system as well which allows a task to be +invoked only once. For example: + + class Counter < Thor + desc "one", "Prints 1, 2, 3" + def one + puts 1 + invoke :two + invoke :three + end + + desc "two", "Prints 2, 3" + def two + puts 2 + invoke :three + end + + desc "three", "Prints 3" + def three + puts 3 + end + end + +When invoking the task one: + + thor counter:one + +The output is "1 2 3", which means that the three task was invoked only once. +You can even invoke tasks from another class, so be sure to check the +documentation. + +== Thor::Group + +Thor has a special class called Thor::Group. The main difference to Thor class +is that it invokes all tasks at once. The example above could be rewritten in +Thor::Group as this: + + class Counter < Thor::Group + desc "Prints 1, 2, 3" + + def one + puts 1 + end + + def two + puts 2 + end + + def three + puts 3 + end + end + +When invoked: + + thor counter + +It prints "1 2 3" as well. Notice you should describe (using the method desc) +only the class and not each task anymore. Thor::Group is a great tool to create +generators, since you can define several steps which are invoked in the order they +are defined (Thor::Group is the tool use in generators in Rails 3.0). + +Besides, Thor::Group can parse arguments and options as Thor tasks: + + class Counter < Thor::Group + # number will be available as attr_accessor + argument :number, :type => :numeric, :desc => "The number to start counting" + desc "Prints the 'number' given upto 'number+2'" + + def one + puts number + 0 + end + + def two + puts number + 1 + end + + def three + puts number + 2 + end + end + +The counter above expects one parameter and has the folling outputs: + + thor counter 5 + # Prints "5 6 7" + + thor counter 11 + # Prints "11 12 13" + +You can also give options to Thor::Group, but instead of using method_option +and method_options, you should use class_option and class_options. +Both argument and class_options methods are available to Thor class as well. + +== Actions + +Thor comes with several actions which helps with script and generator tasks. You +might be familiar with them since some came from Rails Templates. They are: +say, ask, yes?, no?, add_file, +remove_file, copy_file, template, directory, +inside, run, inject_into_file and a couple more. + +To use them, you just need to include Thor::Actions in your Thor classes: + + class App < Thor + include Thor::Actions + # tasks + end + +Some actions like copy file requires that a class method called source_root is +defined in your class. This is the directory where your templates should be +placed. Be sure to check the documentation. + +== License + +See MIT LICENSE. diff --git a/railties/lib/rails/vendor/thor-0.12.1/Thorfile b/railties/lib/rails/vendor/thor-0.12.1/Thorfile new file mode 100644 index 0000000000..ff1cb4498a --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/Thorfile @@ -0,0 +1,63 @@ +# enconding: utf-8 + +require File.join(File.dirname(__FILE__), "lib", "thor", "version") +require 'thor/rake_compat' +require 'spec/rake/spectask' +require 'rdoc/task' + +GEM_NAME = 'thor' +EXTRA_RDOC_FILES = ["README.rdoc", "LICENSE", "CHANGELOG.rdoc", "VERSION", "Thorfile"] + +class Default < Thor + include Thor::RakeCompat + + Spec::Rake::SpecTask.new(:spec) do |t| + t.libs << 'lib' + t.spec_opts = ['--options', "spec/spec.opts"] + t.spec_files = FileList['spec/**/*_spec.rb'] + end + + Spec::Rake::SpecTask.new(:rcov) do |t| + t.libs << 'lib' + t.spec_opts = ['--options', "spec/spec.opts"] + t.spec_files = FileList['spec/**/*_spec.rb'] + t.rcov = true + t.rcov_dir = "rcov" + end + + RDoc::Task.new do |rdoc| + rdoc.main = "README.rdoc" + rdoc.rdoc_dir = "rdoc" + rdoc.title = GEM_NAME + rdoc.rdoc_files.include(*EXTRA_RDOC_FILES) + rdoc.rdoc_files.include('lib/**/*.rb') + rdoc.options << '--line-numbers' << '--inline-source' + end + + begin + require 'jeweler' + Jeweler::Tasks.new do |s| + s.name = GEM_NAME + s.version = Thor::VERSION + s.rubyforge_project = "textmate" + s.platform = Gem::Platform::RUBY + s.summary = "A scripting framework that replaces rake, sake and rubigen" + s.email = "ruby-thor@googlegroups.com" + s.homepage = "http://yehudakatz.com" + s.description = "A scripting framework that replaces rake, sake and rubigen" + s.authors = ['Yehuda Katz', 'José Valim'] + s.has_rdoc = true + s.extra_rdoc_files = EXTRA_RDOC_FILES + s.require_path = 'lib' + s.bindir = "bin" + s.executables = %w( thor rake2thor ) + s.files = s.extra_rdoc_files + Dir.glob("{bin,lib}/**/*") + s.files.exclude 'spec/sandbox/**/*' + s.test_files.exclude 'spec/sandbox/**/*' + end + + Jeweler::GemcutterTasks.new + rescue LoadError + puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb new file mode 100644 index 0000000000..68944f140d --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb @@ -0,0 +1,242 @@ +require 'thor/base' +require 'thor/group' +require 'thor/actions' + +class Thor + class << self + # Sets the default task when thor is executed without an explicit task to be called. + # + # ==== Parameters + # meth:: name of the defaut task + # + def default_task(meth=nil) + case meth + when :none + @default_task = 'help' + when nil + @default_task ||= from_superclass(:default_task, 'help') + else + @default_task = meth.to_s + end + end + + # Defines the usage and the description of the next task. + # + # ==== Parameters + # usage + # description + # + def desc(usage, description, options={}) + if options[:for] + task = find_and_refresh_task(options[:for]) + task.usage = usage if usage + task.description = description if description + else + @usage, @desc = usage, description + end + end + + # Maps an input to a task. If you define: + # + # map "-T" => "list" + # + # Running: + # + # thor -T + # + # Will invoke the list task. + # + # ==== Parameters + # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task. + # + def map(mappings=nil) + @map ||= from_superclass(:map, {}) + + if mappings + mappings.each do |key, value| + if key.respond_to?(:each) + key.each {|subkey| @map[subkey] = value} + else + @map[key] = value + end + end + end + + @map + end + + # Declares the options for the next task to be declared. + # + # ==== Parameters + # Hash[Symbol => Object]:: The hash key is the name of the option and the value + # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric + # or :required (string). If you give a value, the type of the value is used. + # + def method_options(options=nil) + @method_options ||= {} + build_options(options, @method_options) if options + @method_options + end + + # Adds an option to the set of class options. If :for is given as option, + # it allows you to change the options from a previous defined task. + # + # def previous_task + # # magic + # end + # + # method_options :foo => :bar, :for => :previous_task + # + # def next_task + # # magic + # end + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc - Description for the argument. + # :required - If the argument is required or not. + # :default - Default value for this argument. It cannot be required and have default values. + # :aliases - Aliases for this option. + # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. + # :group - The group for this options. Use by class options to output options in different levels. + # :banner - String to show on usage notes. + # + def method_option(name, options={}) + scope = if options[:for] + find_and_refresh_task(options[:for]).options + else + method_options + end + + build_option(name, options, scope) + end + + # Parses the task and options from the given args, instantiate the class + # and invoke the task. This method is used when the arguments must be parsed + # from an array. If you are inside Ruby and want to use a Thor class, you + # can simply initialize it: + # + # script = MyScript.new(args, options, config) + # script.invoke(:task, first_arg, second_arg, third_arg) + # + def start(given_args=ARGV, config={}) + super do + meth = normalize_task_name(given_args.shift) + task = all_tasks[meth] + + if task + args, opts = Thor::Options.split(given_args) + config.merge!(:task_options => task.options) + else + args, opts = given_args, {} + end + + task ||= Thor::Task::Dynamic.new(meth) + trailing = args[Range.new(arguments.size, -1)] + new(args, opts, config).invoke(task, trailing || []) + end + end + + # Prints help information. If a task name is given, it shows information + # only about the specific task. + # + # ==== Parameters + # meth:: An optional task name to print usage information about. + # + # ==== Options + # namespace:: When true, shows the namespace in the output before the usage. + # skip_inherited:: When true, does not show tasks from superclass. + # + def help(shell, meth=nil, options={}) + meth, options = nil, meth if meth.is_a?(Hash) + + if meth + task = all_tasks[meth] + raise UndefinedTaskError, "task '#{meth}' could not be found in namespace '#{self.namespace}'" unless task + + shell.say "Usage:" + shell.say " #{banner(task, options[:namespace], false)}" + shell.say + class_options_help(shell, "Class", :Method => task.options.map { |_, o| o }) + shell.say task.description + else + list = (options[:short] ? tasks : all_tasks).map do |_, task| + item = [ banner(task, options[:namespace]) ] + item << "# #{task.short_description}" if task.short_description + item << " " + end + + options[:ident] ||= 2 + if options[:short] + shell.print_list(list, :ident => options[:ident]) + else + shell.say "Tasks:" + shell.print_list(list, :ident => options[:ident]) + end + + Thor::Util.thor_classes_in(self).each do |subclass| + namespace = options[:namespace] == true || subclass.namespace.gsub(/^#{self.namespace}:/, '') + subclass.help(shell, options.merge(:short => true, :namespace => namespace)) + end + + class_options_help(shell, "Class") unless options[:short] + end + end + + protected + + # The banner for this class. You can customize it if you are invoking the + # thor class by another ways which is not the Thor::Runner. It receives + # the task that is going to be invoked and a boolean which indicates if + # the namespace should be displayed as arguments. + # + def banner(task, namespace=true, show_options=true) + task.formatted_usage(self, namespace, show_options) + end + + def baseclass #:nodoc: + Thor + end + + def create_task(meth) #:nodoc: + if @usage && @desc + tasks[meth.to_s] = Thor::Task.new(meth, @desc, @usage, method_options) + @usage, @desc, @method_options = nil + true + elsif self.all_tasks[meth.to_s] || meth.to_sym == :method_missing + true + else + puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " << + "Call desc if you want this method to be available as task or declare it inside a " << + "no_tasks{} block. Invoked from #{caller[1].inspect}." + false + end + end + + def initialize_added #:nodoc: + class_options.merge!(method_options) + @method_options = nil + end + + # Receives a task name (can be nil), and try to get a map from it. + # If a map can't be found use the sent name or the default task. + # + def normalize_task_name(meth) #:nodoc: + mapping = map[meth.to_s] + meth = mapping || meth || default_task + meth.to_s.gsub('-','_') # treat foo-bar > foo_bar + end + end + + include Thor::Base + + map HELP_MAPPINGS => :help + + desc "help [TASK]", "Describe available tasks or one specific task" + def help(task=nil) + self.class.help(shell, task, :namespace => task && task.include?(?:)) + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions.rb new file mode 100644 index 0000000000..4bfb7c2870 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions.rb @@ -0,0 +1,273 @@ +require 'fileutils' + +Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action| + require action +end + +class Thor + module Actions + attr_accessor :behavior + + def self.included(base) #:nodoc: + base.extend ClassMethods + end + + module ClassMethods + # Hold source paths for one Thor instance. source_paths_for_search is the + # method responsible to gather source_paths from this current class, + # inherited paths and the source root. + # + def source_paths + @source_paths ||= [] + end + + # Returns the source paths in the following order: + # + # 1) This class source paths + # 2) Source root + # 3) Parents source paths + # + def source_paths_for_search + paths = [] + paths += self.source_paths + paths << self.source_root if self.respond_to?(:source_root) + paths += from_superclass(:source_paths, []) + paths + end + + # Add runtime options that help actions execution. + # + def add_runtime_options! + class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime, + :desc => "Run but do not make any changes" + + class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime, + :desc => "Overwrite files that already exist" + + class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime, + :desc => "Skip files that already exist" + + class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime, + :desc => "Supress status output" + end + end + + # Extends initializer to add more configuration options. + # + # ==== Configuration + # behavior:: The actions default behavior. Can be :invoke or :revoke. + # It also accepts :force, :skip and :pretend to set the behavior + # and the respective option. + # + # destination_root:: The root directory needed for some actions. + # + def initialize(args=[], options={}, config={}) + self.behavior = case config[:behavior].to_s + when "force", "skip" + _cleanup_options_and_set(options, config[:behavior]) + :invoke + when "revoke" + :revoke + else + :invoke + end + + super + self.destination_root = config[:destination_root] + end + + # Wraps an action object and call it accordingly to the thor class behavior. + # + def action(instance) #:nodoc: + if behavior == :revoke + instance.revoke! + else + instance.invoke! + end + end + + # Returns the root for this thor class (also aliased as destination root). + # + def destination_root + @destination_stack.last + end + + # Sets the root for this thor class. Relatives path are added to the + # directory where the script was invoked and expanded. + # + def destination_root=(root) + @destination_stack ||= [] + @destination_stack[0] = File.expand_path(root || '') + end + + # Returns the given path relative to the absolute root (ie, root where + # the script started). + # + def relative_to_original_destination_root(path, remove_dot=true) + path = path.gsub(@destination_stack[0], '.') + remove_dot ? (path[2..-1] || '') : path + end + + # Holds source paths in instance so they can be manipulated. + # + def source_paths + @source_paths ||= self.class.source_paths_for_search + end + + # Receives a file or directory and search for it in the source paths. + # + def find_in_source_paths(file) + relative_root = relative_to_original_destination_root(destination_root, false) + + source_paths.each do |source| + source_file = File.expand_path(file, File.join(source, relative_root)) + return source_file if File.exists?(source_file) + end + + if source_paths.empty? + raise Error, "You don't have any source path defined for class #{self.class.name}. To fix this, " << + "you can define a source_root in your class." + else + raise Error, "Could not find #{file.inspect} in source paths." + end + end + + # Do something in the root or on a provided subfolder. If a relative path + # is given it's referenced from the current root. The full path is yielded + # to the block you provide. The path is set back to the previous path when + # the method exits. + # + # ==== Parameters + # dir:: the directory to move to. + # config:: give :verbose => true to log and use padding. + # + def inside(dir='', config={}, &block) + verbose = config.fetch(:verbose, false) + + say_status :inside, dir, verbose + shell.padding += 1 if verbose + @destination_stack.push File.expand_path(dir, destination_root) + + FileUtils.mkdir_p(destination_root) unless File.exist?(destination_root) + FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield } + + @destination_stack.pop + shell.padding -= 1 if verbose + end + + # Goes to the root and execute the given block. + # + def in_root + inside(@destination_stack.first) { yield } + end + + # Loads an external file and execute it in the instance binding. + # + # ==== Parameters + # path:: The path to the file to execute. Can be a web address or + # a relative path from the source root. + # + # ==== Examples + # + # apply "http://gist.github.com/103208" + # + # apply "recipes/jquery.rb" + # + def apply(path, config={}) + verbose = config.fetch(:verbose, true) + path = find_in_source_paths(path) unless path =~ /^http\:\/\// + + say_status :apply, path, verbose + shell.padding += 1 if verbose + instance_eval(open(path).read) + shell.padding -= 1 if verbose + end + + # Executes a command. + # + # ==== Parameters + # command:: the command to be executed. + # config:: give :verbose => false to not log the status. Specify :with + # to append an executable to command executation. + # + # ==== Example + # + # inside('vendor') do + # run('ln -s ~/edge rails') + # end + # + def run(command, config={}) + return unless behavior == :invoke + + destination = relative_to_original_destination_root(destination_root, false) + desc = "#{command} from #{destination.inspect}" + + if config[:with] + desc = "#{File.basename(config[:with].to_s)} #{desc}" + command = "#{config[:with]} #{command}" + end + + say_status :run, desc, config.fetch(:verbose, true) + system(command) unless options[:pretend] + end + + # Executes a ruby script (taking into account WIN32 platform quirks). + # + # ==== Parameters + # command:: the command to be executed. + # config:: give :verbose => false to not log the status. + # + def run_ruby_script(command, config={}) + return unless behavior == :invoke + run "#{command}", config.merge(:with => Thor::Util.ruby_command) + end + + # Run a thor command. A hash of options can be given and it's converted to + # switches. + # + # ==== Parameters + # task:: the task to be invoked + # args:: arguments to the task + # config:: give :verbose => false to not log the status. Other options + # are given as parameter to Thor. + # + # ==== Examples + # + # thor :install, "http://gist.github.com/103208" + # #=> thor install http://gist.github.com/103208 + # + # thor :list, :all => true, :substring => 'rails' + # #=> thor list --all --substring=rails + # + def thor(task, *args) + config = args.last.is_a?(Hash) ? args.pop : {} + verbose = config.key?(:verbose) ? config.delete(:verbose) : true + + args.unshift task + args.push Thor::Options.to_switches(config) + command = args.join(' ').strip + + run command, :with => :thor, :verbose => verbose + end + + protected + + # Allow current root to be shared between invocations. + # + def _shared_configuration #:nodoc: + super.merge!(:destination_root => self.destination_root) + end + + def _cleanup_options_and_set(options, key) #:nodoc: + case options + when Array + %w(--force -f --skip -s).each { |i| options.delete(i) } + options << "--#{key}" + when Hash + [:force, :skip, "force", "skip"].each { |i| options.delete(i) } + options.merge!(key => true) + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/create_file.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/create_file.rb new file mode 100644 index 0000000000..a3d9296823 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/create_file.rb @@ -0,0 +1,103 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + + # Create a new file relative to the destination root with the given data, + # which is the return value of a block or a data string. + # + # ==== Parameters + # destination:: the relative path to the destination root. + # data:: the data to append to the file. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # create_file "lib/fun_party.rb" do + # hostname = ask("What is the virtual hostname I should use?") + # "vhost.name = #{hostname}" + # end + # + # create_file "config/apach.conf", "your apache config" + # + def create_file(destination, data=nil, config={}, &block) + action CreateFile.new(self, destination, block || data.to_s, config) + end + alias :add_file :create_file + + # AddFile is a subset of Template, which instead of rendering a file with + # ERB, it gets the content from the user. + # + class CreateFile < EmptyDirectory #:nodoc: + attr_reader :data + + def initialize(base, destination, data, config={}) + @data = data + super(base, destination, config) + end + + # Checks if the content of the file at the destination is identical to the rendered result. + # + # ==== Returns + # Boolean:: true if it is identical, false otherwise. + # + def identical? + exists? && File.read(destination) == render + end + + # Holds the content to be added to the file. + # + def render + @render ||= if data.is_a?(Proc) + data.call + else + data + end + end + + def invoke! + invoke_with_conflict_check do + FileUtils.mkdir_p(File.dirname(destination)) + File.open(destination, 'w'){ |f| f.write render } + end + given_destination + end + + protected + + # Now on conflict we check if the file is identical or not. + # + def on_conflict_behavior(&block) + if identical? + say_status :identical, :blue + else + options = base.options.merge(config) + force_or_skip_or_conflict(options[:force], options[:skip], &block) + end + end + + # If force is true, run the action, otherwise check if it's not being + # skipped. If both are false, show the file_collision menu, if the menu + # returns true, force it, otherwise skip. + # + def force_or_skip_or_conflict(force, skip, &block) + if force + say_status :force, :yellow + block.call unless pretend? + elsif skip + say_status :skip, :yellow + else + say_status :conflict, :red + force_or_skip_or_conflict(force_on_collision?, true, &block) + end + end + + # Shows the file collision menu to the user and gets the result. + # + def force_on_collision? + base.shell.file_collision(destination){ render } + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/directory.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/directory.rb new file mode 100644 index 0000000000..2e0b459fa3 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/directory.rb @@ -0,0 +1,91 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + + # Copies recursively the files from source directory to root directory. + # If any of the files finishes with .tt, it's considered to be a template + # and is placed in the destination without the extension .tt. If any + # empty directory is found, it's copied and all .empty_directory files are + # ignored. Remember that file paths can also be encoded, let's suppose a doc + # directory with the following files: + # + # doc/ + # components/.empty_directory + # README + # rdoc.rb.tt + # %app_name%.rb + # + # When invoked as: + # + # directory "doc" + # + # It will create a doc directory in the destination with the following + # files (assuming that the app_name is "blog"): + # + # doc/ + # components/ + # README + # rdoc.rb + # blog.rb + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # If :recursive => false, does not look for paths recursively. + # + # ==== Examples + # + # directory "doc" + # directory "doc", "docs", :recursive => false + # + def directory(source, destination=nil, config={}, &block) + action Directory.new(self, source, destination || source, config, &block) + end + + class Directory < EmptyDirectory #:nodoc: + attr_reader :source + + def initialize(base, source, destination=nil, config={}, &block) + @source = File.expand_path(base.find_in_source_paths(source.to_s)) + @block = block + super(base, destination, { :recursive => true }.merge(config)) + end + + def invoke! + base.empty_directory given_destination, config + execute! + end + + def revoke! + execute! + end + + protected + + def execute! + lookup = config[:recursive] ? File.join(source, '**') : source + lookup = File.join(lookup, '{*,.[a-z]*}') + + Dir[lookup].each do |file_source| + next if File.directory?(file_source) + file_destination = File.join(given_destination, file_source.gsub(source, '.')) + file_destination.gsub!('/./', '/') + + case file_source + when /\.empty_directory$/ + dirname = File.dirname(file_destination).gsub(/\/\.$/, '') + next if dirname == given_destination + base.empty_directory(dirname, config) + when /\.tt$/ + destination = base.template(file_source, file_destination[0..-4], config, &@block) + else + destination = base.copy_file(file_source, file_destination, config, &@block) + end + end + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/empty_directory.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/empty_directory.rb new file mode 100644 index 0000000000..484cb820f8 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/empty_directory.rb @@ -0,0 +1,134 @@ +class Thor + module Actions + + # Creates an empty directory. + # + # ==== Parameters + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # empty_directory "doc" + # + def empty_directory(destination, config={}) + action EmptyDirectory.new(self, destination, config) + end + + # Class which holds create directory logic. This is the base class for + # other actions like create_file and directory. + # + # This implementation is based in Templater actions, created by Jonas Nicklas + # and Michael S. Klishin under MIT LICENSE. + # + class EmptyDirectory #:nodoc: + attr_reader :base, :destination, :given_destination, :relative_destination, :config + + # Initializes given the source and destination. + # + # ==== Parameters + # base:: A Thor::Base instance + # source:: Relative path to the source of this file + # destination:: Relative path to the destination of this file + # config:: give :verbose => false to not log the status. + # + def initialize(base, destination, config={}) + @base, @config = base, { :verbose => true }.merge(config) + self.destination = destination + end + + # Checks if the destination file already exists. + # + # ==== Returns + # Boolean:: true if the file exists, false otherwise. + # + def exists? + ::File.exists?(destination) + end + + def invoke! + invoke_with_conflict_check do + ::FileUtils.mkdir_p(destination) + end + end + + def revoke! + say_status :remove, :red + ::FileUtils.rm_rf(destination) if !pretend? && exists? + given_destination + end + + protected + + # Shortcut for pretend. + # + def pretend? + base.options[:pretend] + end + + # Sets the absolute destination value from a relative destination value. + # It also stores the given and relative destination. Let's suppose our + # script is being executed on "dest", it sets the destination root to + # "dest". The destination, given_destination and relative_destination + # are related in the following way: + # + # inside "bar" do + # empty_directory "baz" + # end + # + # destination #=> dest/bar/baz + # relative_destination #=> bar/baz + # given_destination #=> baz + # + def destination=(destination) + if destination + @given_destination = convert_encoded_instructions(destination.to_s) + @destination = ::File.expand_path(@given_destination, base.destination_root) + @relative_destination = base.relative_to_original_destination_root(@destination) + end + end + + # Filenames in the encoded form are converted. If you have a file: + # + # %class_name%.rb + # + # It gets the class name from the base and replace it: + # + # user.rb + # + def convert_encoded_instructions(filename) + filename.gsub(/%(.*?)%/) do |string| + instruction = $1.strip + base.respond_to?(instruction) ? base.send(instruction) : string + end + end + + # Receives a hash of options and just execute the block if some + # conditions are met. + # + def invoke_with_conflict_check(&block) + if exists? + on_conflict_behavior(&block) + else + say_status :create, :green + block.call unless pretend? + end + + destination + end + + # What to do when the destination file already exists. + # + def on_conflict_behavior(&block) + say_status :exist, :blue + end + + # Shortcut to say_status shell method. + # + def say_status(status, color) + base.shell.say_status status, relative_destination, color if config[:verbose] + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/file_manipulation.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/file_manipulation.rb new file mode 100644 index 0000000000..8a45c83f25 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/file_manipulation.rb @@ -0,0 +1,223 @@ +require 'erb' +require 'open-uri' + +class Thor + module Actions + + # Copies the file from the relative source to the relative destination. If + # the destination is not given it's assumed to be equal to the source. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # copy_file "README", "doc/README" + # + # copy_file "doc/README" + # + def copy_file(source, destination=nil, config={}, &block) + destination ||= source + source = File.expand_path(find_in_source_paths(source.to_s)) + + create_file destination, nil, config do + content = File.read(source) + content = block.call(content) if block + content + end + end + + # Gets the content at the given address and places it at the given relative + # destination. If a block is given instead of destination, the content of + # the url is yielded and used as location. + # + # ==== Parameters + # source:: the address of the given content. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # get "http://gist.github.com/103208", "doc/README" + # + # get "http://gist.github.com/103208" do |content| + # content.split("\n").first + # end + # + def get(source, destination=nil, config={}, &block) + source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^http\:\/\// + render = open(source).read + + destination ||= if block_given? + block.arity == 1 ? block.call(render) : block.call + else + File.basename(source) + end + + create_file destination, render, config + end + + # Gets an ERB template at the relative source, executes it and makes a copy + # at the relative destination. If the destination is not given it's assumed + # to be equal to the source removing .tt from the filename. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # template "README", "doc/README" + # + # template "doc/README" + # + def template(source, destination=nil, config={}, &block) + destination ||= source + source = File.expand_path(find_in_source_paths(source.to_s)) + context = instance_eval('binding') + + create_file destination, nil, config do + content = ERB.new(::File.read(source), nil, '-').result(context) + content = block.call(content) if block + content + end + end + + # Changes the mode of the given file or directory. + # + # ==== Parameters + # mode:: the file mode + # path:: the name of the file to change mode + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # chmod "script/*", 0755 + # + def chmod(path, mode, config={}) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) + FileUtils.chmod_R(mode, path) unless options[:pretend] + end + + # Prepend text to a file. Since it depends on inject_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # data:: the data to prepend to the file, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # prepend_file 'config/environments/test.rb', 'config.gem "rspec"' + # + # prepend_file 'config/environments/test.rb' do + # 'config.gem "rspec"' + # end + # + def prepend_file(path, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:after => /\A/) + inject_into_file(path, *(args << config), &block) + end + + # Append text to a file. Since it depends on inject_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # data:: the data to append to the file, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # append_file 'config/environments/test.rb', 'config.gem "rspec"' + # + # append_file 'config/environments/test.rb' do + # 'config.gem "rspec"' + # end + # + def append_file(path, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:before => /\z/) + inject_into_file(path, *(args << config), &block) + end + + # Injects text right after the class definition. Since it depends on + # inject_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # klass:: the class to be manipulated + # data:: the data to append to the class, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # inject_into_class "app/controllers/application_controller.rb", " filter_parameter :password\n" + # + # inject_into_class "app/controllers/application_controller.rb", ApplicationController do + # " filter_parameter :password\n" + # end + # + def inject_into_class(path, klass, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/) + inject_into_file(path, *(args << config), &block) + end + + # Run a regular expression replacement on a file. + # + # ==== Parameters + # path:: path of the file to be changed + # flag:: the regexp or string to be replaced + # replacement:: the replacement, can be also given as a block + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' + # + # gsub_file 'README', /rake/, :green do |match| + # match << " no more. Use thor!" + # end + # + def gsub_file(path, flag, *args, &block) + return unless behavior == :invoke + config = args.last.is_a?(Hash) ? args.pop : {} + + path = File.expand_path(path, destination_root) + say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) + + unless options[:pretend] + content = File.read(path) + content.gsub!(flag, *args, &block) + File.open(path, 'wb') { |file| file.write(content) } + end + end + + # Removes a file at the given location. + # + # ==== Parameters + # path:: path of the file to be changed + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # remove_file 'README' + # remove_file 'app/controllers/application_controller.rb' + # + def remove_file(path, config={}) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + + say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) + ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path) + end + alias :remove_dir :remove_file + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/inject_into_file.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/inject_into_file.rb new file mode 100644 index 0000000000..6b0b42ea02 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/inject_into_file.rb @@ -0,0 +1,101 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + + # Injects the given content into a file. Different from gsub_file, this + # method is reversible. + # + # ==== Parameters + # destination:: Relative path to the destination root + # data:: Data to add to the file. Can be given as a block. + # config:: give :verbose => false to not log the status and the flag + # for injection (:after or :before). + # + # ==== Examples + # + # inject_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n" + # + # inject_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do + # gems = ask "Which gems would you like to add?" + # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n") + # end + # + def inject_into_file(destination, *args, &block) + if block_given? + data, config = block, args.shift + else + data, config = args.shift, args.shift + end + action InjectIntoFile.new(self, destination, data, config) + end + + class InjectIntoFile < EmptyDirectory #:nodoc: + attr_reader :replacement, :flag, :behavior + + def initialize(base, destination, data, config) + super(base, destination, { :verbose => true }.merge(config)) + + @behavior, @flag = if @config.key?(:after) + [:after, @config.delete(:after)] + else + [:before, @config.delete(:before)] + end + + @replacement = data.is_a?(Proc) ? data.call : data + @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp) + end + + def invoke! + say_status :invoke + + content = if @behavior == :after + '\0' + replacement + else + replacement + '\0' + end + + replace!(/#{flag}/, content) + end + + def revoke! + say_status :revoke + + regexp = if @behavior == :after + content = '\1\2' + /(#{flag})(.*)(#{Regexp.escape(replacement)})/m + else + content = '\2\3' + /(#{Regexp.escape(replacement)})(.*)(#{flag})/m + end + + replace!(regexp, content) + end + + protected + + def say_status(behavior) + status = if flag == /\A/ + behavior == :invoke ? :prepend : :unprepend + elsif flag == /\z/ + behavior == :invoke ? :append : :unappend + else + behavior == :invoke ? :inject : :deinject + end + + super(status, config[:verbose]) + end + + # Adds the content to the file. + # + def replace!(regexp, string) + unless base.options[:pretend] + content = File.read(destination) + content.gsub!(regexp, string) + File.open(destination, 'wb') { |file| file.write(content) } + end + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/base.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/base.rb new file mode 100644 index 0000000000..700d794123 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/base.rb @@ -0,0 +1,517 @@ +require 'thor/core_ext/hash_with_indifferent_access' +require 'thor/core_ext/ordered_hash' +require 'thor/error' +require 'thor/shell' +require 'thor/invocation' +require 'thor/parser' +require 'thor/task' +require 'thor/util' + +class Thor + # Shortcuts for help. + HELP_MAPPINGS = %w(-h -? --help -D) + + # Thor methods that should not be overwritten by the user. + THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root + action add_file create_file in_root inside run run_ruby_script) + + module Base + attr_accessor :options + + # It receives arguments in an Array and two hashes, one for options and + # other for configuration. + # + # Notice that it does not check if all required arguments were supplied. + # It should be done by the parser. + # + # ==== Parameters + # args:: An array of objects. The objects are applied to their + # respective accessors declared with argument. + # + # options:: An options hash that will be available as self.options. + # The hash given is converted to a hash with indifferent + # access, magic predicates (options.skip?) and then frozen. + # + # config:: Configuration for this Thor class. + # + def initialize(args=[], options={}, config={}) + Thor::Arguments.parse(self.class.arguments, args).each do |key, value| + send("#{key}=", value) + end + + parse_options = self.class.class_options + + if options.is_a?(Array) + task_options = config.delete(:task_options) # hook for start + parse_options = parse_options.merge(task_options) if task_options + array_options, hash_options = options, {} + else + array_options, hash_options = [], options + end + + options = Thor::Options.parse(parse_options, array_options) + self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).merge!(hash_options) + self.options.freeze + end + + class << self + def included(base) #:nodoc: + base.send :extend, ClassMethods + base.send :include, Invocation + base.send :include, Shell + end + + # Returns the classes that inherits from Thor or Thor::Group. + # + # ==== Returns + # Array[Class] + # + def subclasses + @subclasses ||= [] + end + + # Returns the files where the subclasses are kept. + # + # ==== Returns + # Hash[path => Class] + # + def subclass_files + @subclass_files ||= Hash.new{ |h,k| h[k] = [] } + end + + # Whenever a class inherits from Thor or Thor::Group, we should track the + # class and the file on Thor::Base. This is the method responsable for it. + # + def register_klass_file(klass) #:nodoc: + file = caller[1].match(/(.*):\d+/)[1] + Thor::Base.subclasses << klass unless Thor::Base.subclasses.include?(klass) + + file_subclasses = Thor::Base.subclass_files[File.expand_path(file)] + file_subclasses << klass unless file_subclasses.include?(klass) + end + end + + module ClassMethods + # Adds an argument to the class and creates an attr_accessor for it. + # + # Arguments are different from options in several aspects. The first one + # is how they are parsed from the command line, arguments are retrieved + # from position: + # + # thor task NAME + # + # Instead of: + # + # thor task --name=NAME + # + # Besides, arguments are used inside your code as an accessor (self.argument), + # while options are all kept in a hash (self.options). + # + # Finally, arguments cannot have type :default or :boolean but can be + # optional (supplying :optional => :true or :required => false), although + # you cannot have a required argument after a non-required argument. If you + # try it, an error is raised. + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc - Description for the argument. + # :required - If the argument is required or not. + # :optional - If the argument is optional or not. + # :type - The type of the argument, can be :string, :hash, :array, :numeric. + # :default - Default value for this argument. It cannot be required and have default values. + # :banner - String to show on usage notes. + # + # ==== Errors + # ArgumentError:: Raised if you supply a required argument after a non required one. + # + def argument(name, options={}) + is_thor_reserved_word?(name, :argument) + no_tasks { attr_accessor name } + + required = if options.key?(:optional) + !options[:optional] + elsif options.key?(:required) + options[:required] + else + options[:default].nil? + end + + remove_argument name + + arguments.each do |argument| + next if argument.required? + raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " << + "the non-required argument #{argument.human_name.inspect}." + end if required + + arguments << Thor::Argument.new(name, options[:desc], required, options[:type], + options[:default], options[:banner]) + end + + # Returns this class arguments, looking up in the ancestors chain. + # + # ==== Returns + # Array[Thor::Argument] + # + def arguments + @arguments ||= from_superclass(:arguments, []) + end + + # Adds a bunch of options to the set of class options. + # + # class_options :foo => false, :bar => :required, :baz => :string + # + # If you prefer more detailed declaration, check class_option. + # + # ==== Parameters + # Hash[Symbol => Object] + # + def class_options(options=nil) + @class_options ||= from_superclass(:class_options, {}) + build_options(options, @class_options) if options + @class_options + end + + # Adds an option to the set of class options + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc - Description for the argument. + # :required - If the argument is required or not. + # :default - Default value for this argument. + # :group - The group for this options. Use by class options to output options in different levels. + # :aliases - Aliases for this option. + # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. + # :banner - String to show on usage notes. + # + def class_option(name, options={}) + build_option(name, options, class_options) + end + + # Removes a previous defined argument. If :undefine is given, undefine + # accessors as well. + # + # ==== Paremeters + # names:: Arguments to be removed + # + # ==== Examples + # + # remove_argument :foo + # remove_argument :foo, :bar, :baz, :undefine => true + # + def remove_argument(*names) + options = names.last.is_a?(Hash) ? names.pop : {} + + names.each do |name| + arguments.delete_if { |a| a.name == name.to_s } + undef_method name, "#{name}=" if options[:undefine] + end + end + + # Removes a previous defined class option. + # + # ==== Paremeters + # names:: Class options to be removed + # + # ==== Examples + # + # remove_class_option :foo + # remove_class_option :foo, :bar, :baz + # + def remove_class_option(*names) + names.each do |name| + class_options.delete(name) + end + end + + # Defines the group. This is used when thor list is invoked so you can specify + # that only tasks from a pre-defined group will be shown. Defaults to standard. + # + # ==== Parameters + # name + # + def group(name=nil) + case name + when nil + @group ||= from_superclass(:group, 'standard') + else + @group = name.to_s + end + end + + # Returns the tasks for this Thor class. + # + # ==== Returns + # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task + # objects as values. + # + def tasks + @tasks ||= Thor::CoreExt::OrderedHash.new + end + + # Returns the tasks for this Thor class and all subclasses. + # + # ==== Returns + # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task + # objects as values. + # + def all_tasks + @all_tasks ||= from_superclass(:all_tasks, Thor::CoreExt::OrderedHash.new) + @all_tasks.merge(tasks) + end + + # Removes a given task from this Thor class. This is usually done if you + # are inheriting from another class and don't want it to be available + # anymore. + # + # By default it only remove the mapping to the task. But you can supply + # :undefine => true to undefine the method from the class as well. + # + # ==== Parameters + # name:: The name of the task to be removed + # options:: You can give :undefine => true if you want tasks the method + # to be undefined from the class as well. + # + def remove_task(*names) + options = names.last.is_a?(Hash) ? names.pop : {} + + names.each do |name| + tasks.delete(name.to_s) + all_tasks.delete(name.to_s) + undef_method name if options[:undefine] + end + end + + # All methods defined inside the given block are not added as tasks. + # + # So you can do: + # + # class MyScript < Thor + # no_tasks do + # def this_is_not_a_task + # end + # end + # end + # + # You can also add the method and remove it from the task list: + # + # class MyScript < Thor + # def this_is_not_a_task + # end + # remove_task :this_is_not_a_task + # end + # + def no_tasks + @no_tasks = true + yield + @no_tasks = false + end + + # Sets the namespace for the Thor or Thor::Group class. By default the + # namespace is retrieved from the class name. If your Thor class is named + # Scripts::MyScript, the help method, for example, will be called as: + # + # thor scripts:my_script -h + # + # If you change the namespace: + # + # namespace :my_scripts + # + # You change how your tasks are invoked: + # + # thor my_scripts -h + # + # Finally, if you change your namespace to default: + # + # namespace :default + # + # Your tasks can be invoked with a shortcut. Instead of: + # + # thor :my_task + # + def namespace(name=nil) + case name + when nil + @namespace ||= Thor::Util.namespace_from_thor_class(self, false) + else + @namespace = name.to_s + end + end + + # Default way to start generators from the command line. + # + def start(given_args=ARGV, config={}) + config[:shell] ||= Thor::Base.shell.new + yield + rescue Thor::Error => e + if given_args.include?("--debug") + raise e + else + config[:shell].error e.message + end + exit(1) if exit_on_failure? + end + + protected + + # Prints the class options per group. If an option does not belong to + # any group, it uses the ungrouped name value. This method provide to + # hooks to add extra options, one of them if the third argument called + # extra_group that should be a hash in the format :group => Array[Options]. + # + # The second is by returning a lambda used to print values. The lambda + # requires two options: the group name and the array of options. + # + def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc: + groups = {} + + class_options.each do |_, value| + groups[value.group] ||= [] + groups[value.group] << value + end + + printer = proc do |group_name, options| + list = [] + padding = options.collect{ |o| o.aliases.size }.max.to_i * 4 + + options.each do |option| + item = [ option.usage(padding) ] + item.push(option.description ? "# #{option.description}" : "") + + list << item + list << [ "", "# Default: #{option.default}" ] if option.show_default? + end + + unless list.empty? + shell.say(group_name ? "#{group_name} options:" : "Options:") + shell.print_table(list, :ident => 2) + shell.say "" + end + end + + # Deal with default group + global_options = groups.delete(nil) || [] + printer.call(ungrouped_name, global_options) if global_options + + # Print all others + groups = extra_group.merge(groups) if extra_group + groups.each(&printer) + printer + end + + # Raises an error if the word given is a Thor reserved word. + # + def is_thor_reserved_word?(word, type) #:nodoc: + return false unless THOR_RESERVED_WORDS.include?(word.to_s) + raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}" + end + + # Build an option and adds it to the given scope. + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described in both class_option and method_option. + # + def build_option(name, options, scope) #:nodoc: + scope[name] = Thor::Option.new(name, options[:desc], options[:required], + options[:type], options[:default], options[:banner], + options[:group], options[:aliases]) + end + + # Receives a hash of options, parse them and add to the scope. This is a + # fast way to set a bunch of options: + # + # build_options :foo => true, :bar => :required, :baz => :string + # + # ==== Parameters + # Hash[Symbol => Object] + # + def build_options(options, scope) #:nodoc: + options.each do |key, value| + scope[key] = Thor::Option.parse(key, value) + end + end + + # Finds a task with the given name. If the task belongs to the current + # class, just return it, otherwise dup it and add the fresh copy to the + # current task hash. + # + def find_and_refresh_task(name) #:nodoc: + task = if task = tasks[name.to_s] + task + elsif task = all_tasks[name.to_s] + tasks[name.to_s] = task.clone + else + raise ArgumentError, "You supplied :for => #{name.inspect}, but the task #{name.inspect} could not be found." + end + end + + # Everytime someone inherits from a Thor class, register the klass + # and file into baseclass. + # + def inherited(klass) + Thor::Base.register_klass_file(klass) + end + + # Fire this callback whenever a method is added. Added methods are + # tracked as tasks by invoking the create_task method. + # + def method_added(meth) + meth = meth.to_s + + if meth == "initialize" + initialize_added + return + end + + # Return if it's not a public instance method + return unless public_instance_methods.include?(meth) || + public_instance_methods.include?(meth.to_sym) + + return if @no_tasks || !create_task(meth) + + is_thor_reserved_word?(meth, :task) + Thor::Base.register_klass_file(self) + end + + # Retrieves a value from superclass. If it reaches the baseclass, + # returns default. + # + def from_superclass(method, default=nil) + if self == baseclass || !superclass.respond_to?(method, true) + default + else + value = superclass.send(method) + value.dup if value + end + end + + # A flag that makes the process exit with status 1 if any error happens. + # + def exit_on_failure? + false + end + + # SIGNATURE: Sets the baseclass. This is where the superclass lookup + # finishes. + def baseclass #:nodoc: + end + + # SIGNATURE: Creates a new task if valid_task? is true. This method is + # called when a new method is added to the class. + def create_task(meth) #:nodoc: + end + + # SIGNATURE: Defines behavior when the initialize method is added to the + # class. + def initialize_added #:nodoc: + end + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/hash_with_indifferent_access.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/hash_with_indifferent_access.rb new file mode 100644 index 0000000000..40d201d9e4 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/hash_with_indifferent_access.rb @@ -0,0 +1,75 @@ +class Thor + module CoreExt #:nodoc: + + # A hash with indifferent access and magic predicates. + # + # hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true + # + # hash[:foo] #=> 'bar' + # hash['foo'] #=> 'bar' + # hash.foo? #=> true + # + class HashWithIndifferentAccess < ::Hash #:nodoc: + + def initialize(hash={}) + super() + hash.each do |key, value| + self[convert_key(key)] = value + end + end + + def [](key) + super(convert_key(key)) + end + + def []=(key, value) + super(convert_key(key), value) + end + + def delete(key) + super(convert_key(key)) + end + + def values_at(*indices) + indices.collect { |key| self[convert_key(key)] } + end + + def merge(other) + dup.merge!(other) + end + + def merge!(other) + other.each do |key, value| + self[convert_key(key)] = value + end + self + end + + protected + + def convert_key(key) + key.is_a?(Symbol) ? key.to_s : key + end + + # Magic predicates. For instance: + # + # options.force? # => !!options['force'] + # options.shebang # => "/usr/lib/local/ruby" + # options.test_framework?(:rspec) # => options[:test_framework] == :rspec + # + def method_missing(method, *args, &block) + method = method.to_s + if method =~ /^(\w+)\?$/ + if args.empty? + !!self[$1] + else + self[$1] == args.first + end + else + self[method] + end + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/ordered_hash.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/ordered_hash.rb new file mode 100644 index 0000000000..27fea5bb35 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/ordered_hash.rb @@ -0,0 +1,100 @@ +class Thor + module CoreExt #:nodoc: + + if RUBY_VERSION >= '1.9' + class OrderedHash < ::Hash + end + else + # This class is based on the Ruby 1.9 ordered hashes. + # + # It keeps the semantics and most of the efficiency of normal hashes + # while also keeping track of the order in which elements were set. + # + class OrderedHash #:nodoc: + include Enumerable + + Node = Struct.new(:key, :value, :next, :prev) + + def initialize + @hash = {} + end + + def [](key) + @hash[key] && @hash[key].value + end + + def []=(key, value) + if node = @hash[key] + node.value = value + else + node = Node.new(key, value) + + if @first.nil? + @first = @last = node + else + node.prev = @last + @last.next = node + @last = node + end + end + + @hash[key] = node + value + end + + def delete(key) + if node = @hash[key] + prev_node = node.prev + next_node = node.next + + next_node.prev = prev_node if next_node + prev_node.next = next_node if prev_node + + @first = next_node if @first == node + @last = prev_node if @last == node + + value = node.value + end + + @hash.delete(key) + value + end + + def keys + self.map { |k, v| k } + end + + def values + self.map { |k, v| v } + end + + def each + return unless @first + yield [@first.key, @first.value] + node = @first + yield [node.key, node.value] while node = node.next + self + end + + def merge(other) + hash = self.class.new + + self.each do |key, value| + hash[key] = value + end + + other.each do |key, value| + hash[key] = value + end + + hash + end + + def empty? + @hash.empty? + end + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/error.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/error.rb new file mode 100644 index 0000000000..f9b31a35d1 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/error.rb @@ -0,0 +1,27 @@ +class Thor + # Thor::Error is raised when it's caused by wrong usage of thor classes. Those + # errors have their backtrace supressed and are nicely shown to the user. + # + # Errors that are caused by the developer, like declaring a method which + # overwrites a thor keyword, it SHOULD NOT raise a Thor::Error. This way, we + # ensure that developer errors are shown with full backtrace. + # + class Error < StandardError + end + + # Raised when a task was not found. + # + class UndefinedTaskError < Error + end + + # Raised when a task was found, but not invoked properly. + # + class InvocationError < Error + end + + class RequiredArgumentMissingError < InvocationError + end + + class MalformattedArgumentError < InvocationError + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/group.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/group.rb new file mode 100644 index 0000000000..021a067a3e --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/group.rb @@ -0,0 +1,263 @@ +# Thor has a special class called Thor::Group. The main difference to Thor class +# is that it invokes all tasks at once. It also include some methods that allows +# invocations to be done at the class method, which are not available to Thor +# tasks. +# +class Thor::Group + class << self + # The descrition for this Thor::Group. If none is provided, but a source root + # exists, tries to find the USAGE one folder above it, otherwise searches + # in the superclass. + # + # ==== Parameters + # description:: The description for this Thor::Group. + # + def desc(description=nil) + case description + when nil + @desc ||= from_superclass(:desc, nil) + else + @desc = description + end + end + + # Start works differently in Thor::Group, it simply invokes all tasks + # inside the class. + # + def start(given_args=ARGV, config={}) + super do + if Thor::HELP_MAPPINGS.include?(given_args.first) + help(config[:shell]) + return + end + + args, opts = Thor::Options.split(given_args) + new(args, opts, config).invoke + end + end + + # Prints help information. + # + # ==== Options + # short:: When true, shows only usage. + # + def help(shell, options={}) + if options[:short] + shell.say banner + else + shell.say "Usage:" + shell.say " #{banner}" + shell.say + class_options_help(shell) + shell.say self.desc if self.desc + end + end + + # Stores invocations for this class merging with superclass values. + # + def invocations #:nodoc: + @invocations ||= from_superclass(:invocations, {}) + end + + # Stores invocation blocks used on invoke_from_option. + # + def invocation_blocks #:nodoc: + @invocation_blocks ||= from_superclass(:invocation_blocks, {}) + end + + # Invoke the given namespace or class given. It adds an instance + # method that will invoke the klass and task. You can give a block to + # configure how it will be invoked. + # + # The namespace/class given will have its options showed on the help + # usage. Check invoke_from_option for more information. + # + def invoke(*names, &block) + options = names.last.is_a?(Hash) ? names.pop : {} + verbose = options.fetch(:verbose, true) + + names.each do |name| + invocations[name] = false + invocation_blocks[name] = block if block_given? + + class_eval <<-METHOD, __FILE__, __LINE__ + def _invoke_#{name.to_s.gsub(/\W/, '_')} + klass, task = self.class.prepare_for_invocation(nil, #{name.inspect}) + + if klass + say_status :invoke, #{name.inspect}, #{verbose.inspect} + block = self.class.invocation_blocks[#{name.inspect}] + _invoke_for_class_method klass, task, &block + else + say_status :error, %(#{name.inspect} [not found]), :red + end + end + METHOD + end + end + + # Invoke a thor class based on the value supplied by the user to the + # given option named "name". A class option must be created before this + # method is invoked for each name given. + # + # ==== Examples + # + # class GemGenerator < Thor::Group + # class_option :test_framework, :type => :string + # invoke_from_option :test_framework + # end + # + # ==== Boolean options + # + # In some cases, you want to invoke a thor class if some option is true or + # false. This is automatically handled by invoke_from_option. Then the + # option name is used to invoke the generator. + # + # ==== Preparing for invocation + # + # In some cases you want to customize how a specified hook is going to be + # invoked. You can do that by overwriting the class method + # prepare_for_invocation. The class method must necessarily return a klass + # and an optional task. + # + # ==== Custom invocations + # + # You can also supply a block to customize how the option is giong to be + # invoked. The block receives two parameters, an instance of the current + # class and the klass to be invoked. + # + def invoke_from_option(*names, &block) + options = names.last.is_a?(Hash) ? names.pop : {} + verbose = options.fetch(:verbose, :white) + + names.each do |name| + unless class_options.key?(name) + raise ArgumentError, "You have to define the option #{name.inspect} " << + "before setting invoke_from_option." + end + + invocations[name] = true + invocation_blocks[name] = block if block_given? + + class_eval <<-METHOD, __FILE__, __LINE__ + def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')} + return unless options[#{name.inspect}] + + value = options[#{name.inspect}] + value = #{name.inspect} if TrueClass === value + klass, task = self.class.prepare_for_invocation(#{name.inspect}, value) + + if klass + say_status :invoke, value, #{verbose.inspect} + block = self.class.invocation_blocks[#{name.inspect}] + _invoke_for_class_method klass, task, &block + else + say_status :error, %(\#{value} [not found]), :red + end + end + METHOD + end + end + + # Remove a previously added invocation. + # + # ==== Examples + # + # remove_invocation :test_framework + # + def remove_invocation(*names) + names.each do |name| + remove_task(name) + remove_class_option(name) + invocations.delete(name) + invocation_blocks.delete(name) + end + end + + # Overwrite class options help to allow invoked generators options to be + # shown recursively when invoking a generator. + # + def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc: + group_options = {} + + get_options_from_invocations(group_options, class_options) do |klass| + klass.send(:get_options_from_invocations, group_options, class_options) + end + + group_options.merge!(extra_group) if extra_group + super(shell, ungrouped_name, group_options) + end + + # Get invocations array and merge options from invocations. Those + # options are added to group_options hash. Options that already exists + # in base_options are not added twice. + # + def get_options_from_invocations(group_options, base_options) #:nodoc: + invocations.each do |name, from_option| + value = if from_option + option = class_options[name] + option.type == :boolean ? name : option.default + else + name + end + next unless value + + klass, task = prepare_for_invocation(name, value) + next unless klass && klass.respond_to?(:class_options) + + value = value.to_s + human_name = value.respond_to?(:classify) ? value.classify : value + + group_options[human_name] ||= [] + group_options[human_name] += klass.class_options.values.select do |option| + base_options[option.name.to_sym].nil? && option.group.nil? && + !group_options.values.flatten.any? { |i| i.name == option.name } + end + + yield klass if block_given? + end + end + + protected + + # The banner for this class. You can customize it if you are invoking the + # thor class by another ways which is not the Thor::Runner. + # + def banner + "#{self.namespace} #{self.arguments.map {|a| a.usage }.join(' ')}" + end + + def baseclass #:nodoc: + Thor::Group + end + + def create_task(meth) #:nodoc: + tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil) + true + end + end + + include Thor::Base + + protected + + # Shortcut to invoke with padding and block handling. Use internally by + # invoke and invoke_from_option class methods. + # + def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc: + shell.padding += 1 + + result = if block_given? + if block.arity == 2 + block.call(self, klass) + else + block.call(self, klass, task) + end + else + invoke klass, task, *args + end + + shell.padding -= 1 + result + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/invocation.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/invocation.rb new file mode 100644 index 0000000000..32e6a72454 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/invocation.rb @@ -0,0 +1,178 @@ +class Thor + module Invocation + def self.included(base) #:nodoc: + base.extend ClassMethods + end + + module ClassMethods + # Prepare for class methods invocations. This method must return a klass to + # have the invoked class options showed in help messages in generators. + # + def prepare_for_invocation(key, name) #:nodoc: + case name + when Symbol, String + Thor::Util.namespace_to_thor_class_and_task(name.to_s, false) + else + name + end + end + end + + # Make initializer aware of invocations and the initializer proc. + # + def initialize(args=[], options={}, config={}, &block) #:nodoc: + @_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] } + @_initializer = [ args, options, config ] + super + end + + # Receives a name and invokes it. The name can be a string (either "task" or + # "namespace:task"), a Thor::Task, a Class or a Thor instance. If the task + # cannot be guessed by name, it can also be supplied as second argument. + # + # You can also supply the arguments, options and configuration values for + # the task to be invoked, if none is given, the same values used to + # initialize the invoker are used to initialize the invoked. + # + # ==== Examples + # + # class A < Thor + # def foo + # invoke :bar + # invoke "b:hello", ["José"] + # end + # + # def bar + # invoke "b:hello", ["José"] + # end + # end + # + # class B < Thor + # def hello(name) + # puts "hello #{name}" + # end + # end + # + # You can notice that the method "foo" above invokes two tasks: "bar", + # which belongs to the same class and "hello" which belongs to the class B. + # + # By using an invocation system you ensure that a task is invoked only once. + # In the example above, invoking "foo" will invoke "b:hello" just once, even + # if it's invoked later by "bar" method. + # + # When class A invokes class B, all arguments used on A initialization are + # supplied to B. This allows lazy parse of options. Let's suppose you have + # some rspec tasks: + # + # class Rspec < Thor::Group + # class_option :mock_framework, :type => :string, :default => :rr + # + # def invoke_mock_framework + # invoke "rspec:#{options[:mock_framework]}" + # end + # end + # + # As you noticed, it invokes the given mock framework, which might have its + # own options: + # + # class Rspec::RR < Thor::Group + # class_option :style, :type => :string, :default => :mock + # end + # + # Since it's not rspec concern to parse mock framework options, when RR + # is invoked all options are parsed again, so RR can extract only the options + # that it's going to use. + # + # If you want Rspec::RR to be initialized with its own set of options, you + # have to do that explicitely: + # + # invoke "rspec:rr", [], :style => :foo + # + # Besides giving an instance, you can also give a class to invoke: + # + # invoke Rspec::RR, [], :style => :foo + # + def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil) + task, args, opts, config = nil, task, args, opts if task.nil? || task.is_a?(Array) + args, opts, config = nil, args, opts if args.is_a?(Hash) + + object, task = _prepare_for_invocation(name, task) + klass, instance = _initialize_klass_with_initializer(object, args, opts, config) + + method_args = [] + current = @_invocations[klass] + + iterator = proc do |_, task| + unless current.include?(task.name) + current << task.name + task.run(instance, method_args) + end + end + + if task + args ||= [] + method_args = args[Range.new(klass.arguments.size, -1)] || [] + iterator.call(nil, task) + else + klass.all_tasks.map(&iterator) + end + end + + protected + + # Configuration values that are shared between invocations. + # + def _shared_configuration #:nodoc: + { :invocations => @_invocations } + end + + # Prepare for invocation in the instance level. In this case, we have to + # take into account that a just a task name from the current class was + # given or even a Thor::Task object. + # + def _prepare_for_invocation(name, sent_task=nil) #:nodoc: + if name.is_a?(Thor::Task) + task = name + elsif task = self.class.all_tasks[name.to_s] + object = self + else + object, task = self.class.prepare_for_invocation(nil, name) + task ||= sent_task + end + + # If the object was not set, use self and use the name as task. + object, task = self, name unless object + return object, _validate_task(object, task) + end + + # Check if the object given is a Thor class object and get a task object + # for it. + # + def _validate_task(object, task) #:nodoc: + klass = object.is_a?(Class) ? object : object.class + raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base + + task ||= klass.default_task if klass <= Thor + task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task) + task + end + + # Initialize klass using values stored in the @_initializer. + # + def _initialize_klass_with_initializer(object, args, opts, config) #:nodoc: + if object.is_a?(Class) + klass = object + + stored_args, stored_opts, stored_config = @_initializer + args ||= stored_args.dup + opts ||= stored_opts.dup + + config ||= {} + config = stored_config.merge(_shared_configuration).merge!(config) + [ klass, klass.new(args, opts, config) ] + else + [ object.class, object ] + end + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser.rb new file mode 100644 index 0000000000..57a3f6e1a5 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser.rb @@ -0,0 +1,4 @@ +require 'thor/parser/argument' +require 'thor/parser/arguments' +require 'thor/parser/option' +require 'thor/parser/options' diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/argument.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/argument.rb new file mode 100644 index 0000000000..aa8ace4719 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/argument.rb @@ -0,0 +1,67 @@ +class Thor + class Argument #:nodoc: + VALID_TYPES = [ :numeric, :hash, :array, :string ] + + attr_reader :name, :description, :required, :type, :default, :banner + alias :human_name :name + + def initialize(name, description=nil, required=true, type=:string, default=nil, banner=nil) + class_name = self.class.name.split("::").last + + raise ArgumentError, "#{class_name} name can't be nil." if name.nil? + raise ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type) + + @name = name.to_s + @description = description + @required = required || false + @type = (type || :string).to_sym + @default = default + @banner = banner || default_banner + + validate! # Trigger specific validations + end + + def usage + required? ? banner : "[#{banner}]" + end + + def required? + required + end + + def show_default? + case default + when Array, String, Hash + !default.empty? + else + default + end + end + + protected + + def validate! + raise ArgumentError, "An argument cannot be required and have default value." if required? && !default.nil? + end + + def valid_type?(type) + VALID_TYPES.include?(type.to_sym) + end + + def default_banner + case type + when :boolean + nil + when :string, :default + human_name.upcase + when :numeric + "N" + when :hash + "key:value" + when :array + "one two three" + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/arguments.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/arguments.rb new file mode 100644 index 0000000000..fb5d965e06 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/arguments.rb @@ -0,0 +1,145 @@ +class Thor + class Arguments #:nodoc: + NUMERIC = /(\d*\.\d+|\d+)/ + + # Receives an array of args and returns two arrays, one with arguments + # and one with switches. + # + def self.split(args) + arguments = [] + + args.each do |item| + break if item =~ /^-/ + arguments << item + end + + return arguments, args[Range.new(arguments.size, -1)] + end + + def self.parse(base, args) + new(base).parse(args) + end + + # Takes an array of Thor::Argument objects. + # + def initialize(arguments=[]) + @assigns, @non_assigned_required = {}, [] + @switches = arguments + + arguments.each do |argument| + if argument.default + @assigns[argument.human_name] = argument.default + elsif argument.required? + @non_assigned_required << argument + end + end + end + + def parse(args) + @pile = args.dup + + @switches.each do |argument| + break unless peek + @non_assigned_required.delete(argument) + @assigns[argument.human_name] = send(:"parse_#{argument.type}", argument.human_name) + end + + check_requirement! + @assigns + end + + private + + def peek + @pile.first + end + + def shift + @pile.shift + end + + def unshift(arg) + unless arg.kind_of?(Array) + @pile.unshift(arg) + else + @pile = arg + @pile + end + end + + def current_is_value? + peek && peek.to_s !~ /^-/ + end + + # Runs through the argument array getting strings that contains ":" and + # mark it as a hash: + # + # [ "name:string", "age:integer" ] + # + # Becomes: + # + # { "name" => "string", "age" => "integer" } + # + def parse_hash(name) + return shift if peek.is_a?(Hash) + hash = {} + + while current_is_value? && peek.include?(?:) + key, value = shift.split(':') + hash[key] = value + end + hash + end + + # Runs through the argument array getting all strings until no string is + # found or a switch is found. + # + # ["a", "b", "c"] + # + # And returns it as an array: + # + # ["a", "b", "c"] + # + def parse_array(name) + return shift if peek.is_a?(Array) + array = [] + + while current_is_value? + array << shift + end + array + end + + # Check if the peel is numeric ofrmat and return a Float or Integer. + # Otherwise raises an error. + # + def parse_numeric(name) + return shift if peek.is_a?(Numeric) + + unless peek =~ NUMERIC && $& == peek + raise MalformattedArgumentError, "expected numeric value for '#{name}'; got #{peek.inspect}" + end + + $&.index('.') ? shift.to_f : shift.to_i + end + + # Parse string, i.e., just return the current value in the pile. + # + def parse_string(name) + shift + end + + # Raises an error if @non_assigned_required array is not empty. + # + def check_requirement! + unless @non_assigned_required.empty? + names = @non_assigned_required.map do |o| + o.respond_to?(:switch_name) ? o.switch_name : o.human_name + end.join("', '") + + class_name = self.class.name.split('::').last.downcase + raise RequiredArgumentMissingError, "no value provided for required #{class_name} '#{names}'" + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/option.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/option.rb new file mode 100644 index 0000000000..e09b4901e2 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/option.rb @@ -0,0 +1,132 @@ +class Thor + class Option < Argument #:nodoc: + attr_reader :aliases, :group + + VALID_TYPES = [:boolean, :numeric, :hash, :array, :string] + + def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, group=nil, aliases=nil) + super(name, description, required, type, default, banner) + @aliases = [*aliases].compact + @group = group.to_s.capitalize if group + end + + # This parse quick options given as method_options. It makes several + # assumptions, but you can be more specific using the option method. + # + # parse :foo => "bar" + # #=> Option foo with default value bar + # + # parse [:foo, :baz] => "bar" + # #=> Option foo with default value bar and alias :baz + # + # parse :foo => :required + # #=> Required option foo without default value + # + # parse :foo => 2 + # #=> Option foo with default value 2 and type numeric + # + # parse :foo => :numeric + # #=> Option foo without default value and type numeric + # + # parse :foo => true + # #=> Option foo with default value true and type boolean + # + # The valid types are :boolean, :numeric, :hash, :array and :string. If none + # is given a default type is assumed. This default type accepts arguments as + # string (--foo=value) or booleans (just --foo). + # + # By default all options are optional, unless :required is given. + # + def self.parse(key, value) + if key.is_a?(Array) + name, *aliases = key + else + name, aliases = key, [] + end + + name = name.to_s + default = value + + type = case value + when Symbol + default = nil + + if VALID_TYPES.include?(value) + value + elsif required = (value == :required) + :string + elsif value == :optional + # TODO Remove this warning in the future. + warn "Optional type is deprecated. Choose :boolean or :string instead. Assumed to be :boolean." + :boolean + end + when TrueClass, FalseClass + :boolean + when Numeric + :numeric + when Hash, Array, String + value.class.name.downcase.to_sym + end + + self.new(name.to_s, nil, required, type, default, nil, nil, aliases) + end + + def switch_name + @switch_name ||= dasherized? ? name : dasherize(name) + end + + def human_name + @human_name ||= dasherized? ? undasherize(name) : name + end + + def usage(padding=0) + sample = if banner && !banner.to_s.empty? + "#{switch_name}=#{banner}" + else + switch_name + end + + sample = "[#{sample}]" unless required? + + if aliases.empty? + (" " * padding) << sample + else + "#{aliases.join(', ')}, #{sample}" + end + end + + # Allow some type predicates as: boolean?, string? and etc. + # + def method_missing(method, *args, &block) + given = method.to_s.sub(/\?$/, '').to_sym + if valid_type?(given) + self.type == given + else + super + end + end + + protected + + def validate! + raise ArgumentError, "An option cannot be boolean and required." if boolean? && required? + end + + def valid_type?(type) + VALID_TYPES.include?(type.to_sym) + end + + def dasherized? + name.index('-') == 0 + end + + def undasherize(str) + str.sub(/^-{1,2}/, '') + end + + def dasherize(str) + (str.length > 1 ? "--" : "-") + str.gsub('_', '-') + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/options.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/options.rb new file mode 100644 index 0000000000..75092308b5 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/options.rb @@ -0,0 +1,142 @@ +class Thor + # This is a modified version of Daniel Berger's Getopt::Long class, licensed + # under Ruby's license. + # + class Options < Arguments #:nodoc: + LONG_RE = /^(--\w+[-\w+]*)$/ + SHORT_RE = /^(-[a-z])$/i + EQ_RE = /^(--\w+[-\w+]*|-[a-z])=(.*)$/i + SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args + SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i + + # Receives a hash and makes it switches. + # + def self.to_switches(options) + options.map do |key, value| + case value + when true + "--#{key}" + when Array + "--#{key} #{value.map{ |v| v.inspect }.join(' ')}" + when Hash + "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}" + when nil, false + "" + else + "--#{key} #{value.inspect}" + end + end.join(" ") + end + + # Takes a hash of Thor::Option objects. + # + def initialize(options={}) + options = options.values + super(options) + @shorts, @switches = {}, {} + + options.each do |option| + @switches[option.switch_name] = option + + option.aliases.each do |short| + @shorts[short.to_s] ||= option.switch_name + end + end + end + + def parse(args) + @pile = args.dup + + while peek + if current_is_switch? + case shift + when SHORT_SQ_RE + unshift($1.split('').map { |f| "-#{f}" }) + next + when EQ_RE, SHORT_NUM + unshift($2) + switch = $1 + when LONG_RE, SHORT_RE + switch = $1 + end + + switch = normalize_switch(switch) + next unless option = switch_option(switch) + + @assigns[option.human_name] = parse_peek(switch, option) + else + shift + end + end + + check_requirement! + @assigns + end + + protected + + # Returns true if the current value in peek is a registered switch. + # + def current_is_switch? + case peek + when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM + switch?($1) + when SHORT_SQ_RE + $1.split('').any? { |f| switch?("-#{f}") } + end + end + + def switch?(arg) + switch_option(arg) || @shorts.key?(arg) + end + + def switch_option(arg) + if match = no_or_skip?(arg) + @switches[arg] || @switches["--#{match}"] + else + @switches[arg] + end + end + + def no_or_skip?(arg) + arg =~ /^--(no|skip)-([-\w]+)$/ + $2 + end + + # Check if the given argument is actually a shortcut. + # + def normalize_switch(arg) + @shorts.key?(arg) ? @shorts[arg] : arg + end + + # Parse boolean values which can be given as --foo=true, --foo or --no-foo. + # + def parse_boolean(switch) + if current_is_value? + ["true", "TRUE", "t", "T", true].include?(shift) + else + @switches.key?(switch) || !no_or_skip?(switch) + end + end + + # Parse the value at the peek analyzing if it requires an input or not. + # + def parse_peek(switch, option) + unless current_is_value? + if option.boolean? + # No problem for boolean types + elsif no_or_skip?(switch) + return nil # User set value to nil + elsif option.string? && !option.required? + return option.human_name # Return the option name + else + raise MalformattedArgumentError, "no value provided for option '#{switch}'" + end + end + + @non_assigned_required.delete(option) + send(:"parse_#{option.type}", switch) + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/rake_compat.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/rake_compat.rb new file mode 100644 index 0000000000..0d0757fdda --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/rake_compat.rb @@ -0,0 +1,66 @@ +require 'rake' + +class Thor + # Adds a compatibility layer to your Thor classes which allows you to use + # rake package tasks. For example, to use rspec rake tasks, one can do: + # + # require 'thor/rake_compat' + # + # class Default < Thor + # include Thor::RakeCompat + # + # Spec::Rake::SpecTask.new(:spec) do |t| + # t.spec_opts = ['--options', "spec/spec.opts"] + # t.spec_files = FileList['spec/**/*_spec.rb'] + # end + # end + # + module RakeCompat + def self.rake_classes + @rake_classes ||= [] + end + + def self.included(base) + # Hack. Make rakefile point to invoker, so rdoc task is generated properly. + rakefile = File.basename(caller[0].match(/(.*):\d+/)[1]) + Rake.application.instance_variable_set(:@rakefile, rakefile) + self.rake_classes << base + end + end +end + +class Object #:nodoc: + alias :rake_task :task + alias :rake_namespace :namespace + + def task(*args, &block) + task = rake_task(*args, &block) + + if klass = Thor::RakeCompat.rake_classes.last + non_namespaced_name = task.name.split(':').last + + description = non_namespaced_name + description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ') + description.strip! + + klass.desc description, task.comment || non_namespaced_name + klass.send :define_method, non_namespaced_name do |*args| + Rake::Task[task.name.to_sym].invoke(*args) + end + end + + task + end + + def namespace(name, &block) + if klass = Thor::RakeCompat.rake_classes.last + const_name = Thor::Util.camel_case(name.to_s).to_sym + klass.const_set(const_name, Class.new(Thor)) + new_klass = klass.const_get(const_name) + Thor::RakeCompat.rake_classes << new_klass + end + + rake_namespace(name, &block) + Thor::RakeCompat.rake_classes.pop + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/runner.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/runner.rb new file mode 100644 index 0000000000..079f9e0c65 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/runner.rb @@ -0,0 +1,299 @@ +require 'fileutils' +require 'open-uri' +require 'yaml' +require 'digest/md5' +require 'pathname' + +class Thor::Runner < Thor #:nodoc: + map "-T" => :list, "-i" => :install, "-u" => :update + + # Override Thor#help so it can give information about any class and any method. + # + def help(meth=nil) + if meth && !self.respond_to?(meth) + initialize_thorfiles(meth) + klass, task = Thor::Util.namespace_to_thor_class_and_task(meth) + # Send mapping -h because it works with Thor::Group too + klass.start(["-h", task].compact, :shell => self.shell) + else + super + end + end + + # If a task is not found on Thor::Runner, method missing is invoked and + # Thor::Runner is then responsable for finding the task in all classes. + # + def method_missing(meth, *args) + meth = meth.to_s + initialize_thorfiles(meth) + klass, task = Thor::Util.namespace_to_thor_class_and_task(meth) + args.unshift(task) if task + klass.start(args, :shell => shell) + end + + desc "install NAME", "Install an optionally named Thor file into your system tasks" + method_options :as => :string, :relative => :boolean + def install(name) + initialize_thorfiles + + # If a directory name is provided as the argument, look for a 'main.thor' + # task in said directory. + begin + if File.directory?(File.expand_path(name)) + base, package = File.join(name, "main.thor"), :directory + contents = open(base).read + else + base, package = name, :file + contents = open(name).read + end + rescue OpenURI::HTTPError + raise Error, "Error opening URI '#{name}'" + rescue Errno::ENOENT + raise Error, "Error opening file '#{name}'" + end + + say "Your Thorfile contains:" + say contents + + return false if no?("Do you wish to continue [y/N]?") + + as = options["as"] || begin + first_line = contents.split("\n")[0] + (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil + end + + unless as + basename = File.basename(name) + as = ask("Please specify a name for #{name} in the system repository [#{basename}]:") + as = basename if as.empty? + end + + location = if options[:relative] || name =~ /^http:\/\// + name + else + File.expand_path(name) + end + + thor_yaml[as] = { + :filename => Digest::MD5.hexdigest(name + as), + :location => location, + :namespaces => Thor::Util.namespaces_in_content(contents, base) + } + + save_yaml(thor_yaml) + say "Storing thor file in your system repository" + destination = File.join(thor_root, thor_yaml[as][:filename]) + + if package == :file + File.open(destination, "w") { |f| f.puts contents } + else + FileUtils.cp_r(name, destination) + end + + thor_yaml[as][:filename] # Indicate success + end + + desc "uninstall NAME", "Uninstall a named Thor module" + def uninstall(name) + raise Error, "Can't find module '#{name}'" unless thor_yaml[name] + say "Uninstalling #{name}." + FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}")) + + thor_yaml.delete(name) + save_yaml(thor_yaml) + + puts "Done." + end + + desc "update NAME", "Update a Thor file from its original location" + def update(name) + raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location] + + say "Updating '#{name}' from #{thor_yaml[name][:location]}" + + old_filename = thor_yaml[name][:filename] + self.options = self.options.merge("as" => name) + filename = install(thor_yaml[name][:location]) + + unless filename == old_filename + File.delete(File.join(thor_root, old_filename)) + end + end + + desc "installed", "List the installed Thor modules and tasks" + method_options :internal => :boolean + def installed + initialize_thorfiles(nil, true) + + klasses = Thor::Base.subclasses + klasses -= [Thor, Thor::Runner] unless options["internal"] + + display_klasses(true, klasses) + end + + desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)" + method_options :substring => :boolean, :group => :string, :all => :boolean + def list(search="") + initialize_thorfiles + + search = ".*#{search}" if options["substring"] + search = /^#{search}.*/i + group = options[:group] || "standard" + + klasses = Thor::Base.subclasses.select do |k| + (options[:all] || k.group == group) && k.namespace =~ search + end + + display_klasses(false, klasses) + end + + private + + def thor_root + Thor::Util.thor_root + end + + def thor_yaml + @thor_yaml ||= begin + yaml_file = File.join(thor_root, "thor.yml") + yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file) + yaml || {} + end + end + + # Save the yaml file. If none exists in thor root, creates one. + # + def save_yaml(yaml) + yaml_file = File.join(thor_root, "thor.yml") + + unless File.exists?(yaml_file) + FileUtils.mkdir_p(thor_root) + yaml_file = File.join(thor_root, "thor.yml") + FileUtils.touch(yaml_file) + end + + File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml } + end + + def self.exit_on_failure? + true + end + + # Load the thorfiles. If relevant_to is supplied, looks for specific files + # in the thor_root instead of loading them all. + # + # By default, it also traverses the current path until find Thor files, as + # described in thorfiles. This look up can be skipped by suppliying + # skip_lookup true. + # + def initialize_thorfiles(relevant_to=nil, skip_lookup=false) + thorfiles(relevant_to, skip_lookup).each do |f| + Thor::Util.load_thorfile(f) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f)) + end + end + + # Finds Thorfiles by traversing from your current directory down to the root + # directory of your system. If at any time we find a Thor file, we stop. + # + # We also ensure that system-wide Thorfiles are loaded first, so local + # Thorfiles can override them. + # + # ==== Example + # + # If we start at /Users/wycats/dev/thor ... + # + # 1. /Users/wycats/dev/thor + # 2. /Users/wycats/dev + # 3. /Users/wycats <-- we find a Thorfile here, so we stop + # + # Suppose we start at c:\Documents and Settings\james\dev\thor ... + # + # 1. c:\Documents and Settings\james\dev\thor + # 2. c:\Documents and Settings\james\dev + # 3. c:\Documents and Settings\james + # 4. c:\Documents and Settings + # 5. c:\ <-- no Thorfiles found! + # + def thorfiles(relevant_to=nil, skip_lookup=false) + # TODO Remove this dealing with deprecated thor when :namespaces: is available as constants + save_yaml(thor_yaml) if Thor::Util.convert_constants_to_namespaces(thor_yaml) + + thorfiles = [] + + unless skip_lookup + Pathname.pwd.ascend do |path| + thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten + break unless thorfiles.empty? + end + end + + files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob) + files += thorfiles + files -= ["#{thor_root}/thor.yml"] + + files.map! do |file| + File.directory?(file) ? File.join(file, "main.thor") : file + end + end + + # Load thorfiles relevant to the given method. If you provide "foo:bar" it + # will load all thor files in the thor.yaml that has "foo" e "foo:bar" + # namespaces registered. + # + def thorfiles_relevant_to(meth) + lookup = [ meth, meth.split(":")[0...-1].join(":") ] + + files = thor_yaml.select do |k, v| + v[:namespaces] && !(v[:namespaces] & lookup).empty? + end + + files.map { |k, v| File.join(thor_root, "#{v[:filename]}") } + end + + # Display information about the given klasses. If with_module is given, + # it shows a table with information extracted from the yaml file. + # + def display_klasses(with_modules=false, klasses=Thor.subclasses) + klasses -= [Thor, Thor::Runner] unless with_modules + raise Error, "No Thor tasks available" if klasses.empty? + + if with_modules && !thor_yaml.empty? + info = [] + labels = ["Modules", "Namespaces"] + + info << labels + info << [ "-" * labels[0].size, "-" * labels[1].size ] + + thor_yaml.each do |name, hash| + info << [ name, hash[:namespaces].join(", ") ] + end + + print_table info + say "" + end + + unless klasses.empty? + klasses.dup.each do |klass| + klasses -= Thor::Util.thor_classes_in(klass) + end + + klasses.each { |k| display_tasks(k) } + else + say "\033[1;34mNo Thor tasks available\033[0m" + end + end + + # Display tasks from the given Thor class. + # + def display_tasks(klass) + unless klass.tasks.empty? + base = klass.namespace + + color = base == "default" ? :magenta : :blue + say shell.set_color(base, color, true) + say "-" * base.length + + klass.help(shell, :short => true, :ident => 0, :namespace => true) + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb new file mode 100644 index 0000000000..1dc8f0e5b4 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb @@ -0,0 +1,78 @@ +require 'rbconfig' +require 'thor/shell/color' + +class Thor + module Base + # Returns the shell used in all Thor classes. If you are in a Unix platform + # it will use a colored log, otherwise it will use a basic one without color. + # + def self.shell + @shell ||= if Config::CONFIG['host_os'] =~ /mswin|mingw/ + Thor::Shell::Basic + else + Thor::Shell::Color + end + end + + # Sets the shell used in all Thor classes. + # + def self.shell=(klass) + @shell = klass + end + end + + module Shell + SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_list, :print_table] + + # Add shell to initialize config values. + # + # ==== Configuration + # shell:: An instance of the shell to be used. + # + # ==== Examples + # + # class MyScript < Thor + # argument :first, :type => :numeric + # end + # + # MyScript.new [1.0], { :foo => :bar }, :shell => Thor::Shell::Basic.new + # + def initialize(args=[], options={}, config={}) + super + self.shell = config[:shell] + self.shell.base ||= self if self.shell.respond_to?(:base) + end + + # Holds the shell for the given Thor instance. If no shell is given, + # it gets a default shell from Thor::Base.shell. + # + def shell + @shell ||= Thor::Base.shell.new + end + + # Sets the shell for this thor class. + # + def shell=(shell) + @shell = shell + end + + # Common methods that are delegated to the shell. + # + SHELL_DELEGATED_METHODS.each do |method| + module_eval <<-METHOD, __FILE__, __LINE__ + def #{method}(*args) + shell.#{method}(*args) + end + METHOD + end + + protected + + # Allow shell to be shared between invocations. + # + def _shared_configuration #:nodoc: + super.merge!(:shell => self.shell) + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/basic.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/basic.rb new file mode 100644 index 0000000000..f6be3575ca --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/basic.rb @@ -0,0 +1,219 @@ +require 'tempfile' + +class Thor + module Shell + class Basic + attr_accessor :base, :padding + + # Initialize base and padding to nil. + # + def initialize #:nodoc: + @base, @padding = nil, 0 + end + + # Sets the output padding, not allowing less than zero values. + # + def padding=(value) + @padding = [0, value].max + end + + # Ask something to the user and receives a response. + # + # ==== Example + # ask("What is your name?") + # + def ask(statement, color=nil) + say("#{statement} ", color) + $stdin.gets.strip + end + + # Say (print) something to the user. If the sentence ends with a whitespace + # or tab character, a new line is not appended (print + flush). Otherwise + # are passed straight to puts (behavior got from Highline). + # + # ==== Example + # say("I know you knew that.") + # + def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/)) + message = message.to_s + message = set_color(message, color) if color + + if force_new_line + $stdout.puts(message) + else + $stdout.print(message) + $stdout.flush + end + end + + # Say a status with the given color and appends the message. Since this + # method is used frequently by actions, it allows nil or false to be given + # in log_status, avoiding the message from being shown. If a Symbol is + # given in log_status, it's used as the color. + # + def say_status(status, message, log_status=true) + return if quiet? || log_status == false + spaces = " " * (padding + 1) + color = log_status.is_a?(Symbol) ? log_status : :green + + status = status.to_s.rjust(12) + status = set_color status, color, true if color + say "#{status}#{spaces}#{message}", nil, true + end + + # Make a question the to user and returns true if the user replies "y" or + # "yes". + # + def yes?(statement, color=nil) + ask(statement, color) =~ is?(:yes) + end + + # Make a question the to user and returns true if the user replies "n" or + # "no". + # + def no?(statement, color=nil) + !yes?(statement, color) + end + + # Prints a list of items. + # + # ==== Parameters + # list + # + # ==== Options + # mode:: Can be :rows or :inline. Defaults to :rows. + # ident:: Ident each item with the value given. + # + def print_list(list, options={}) + return if list.empty? + + ident = " " * (options[:ident] || 0) + content = case options[:mode] + when :inline + last = list.pop + "#{list.join(", ")}, and #{last}" + else # rows + ident + list.join("\n#{ident}") + end + + $stdout.puts content + end + + # Prints a table. + # + # ==== Parameters + # Array[Array[String, String, ...]] + # + # ==== Options + # ident:: Ident the first column by ident value. + # + def print_table(table, options={}) + return if table.empty? + + formats = [] + 0.upto(table.first.length - 2) do |i| + maxima = table.max{ |a,b| a[i].size <=> b[i].size }[i].size + formats << "%-#{maxima + 2}s" + end + + formats[0] = formats[0].insert(0, " " * options[:ident]) if options[:ident] + formats << "%s" + + table.each do |row| + row.each_with_index do |column, i| + $stdout.print formats[i] % column.to_s + end + $stdout.puts + end + end + + # Deals with file collision and returns true if the file should be + # overwriten and false otherwise. If a block is given, it uses the block + # response as the content for the diff. + # + # ==== Parameters + # destination:: the destination file to solve conflicts + # block:: an optional block that returns the value to be used in diff + # + def file_collision(destination) + return true if @always_force + options = block_given? ? "[Ynaqdh]" : "[Ynaqh]" + + while true + answer = ask %[Overwrite #{destination}? (enter "h" for help) #{options}] + + case answer + when is?(:yes), is?(:force), "" + return true + when is?(:no), is?(:skip) + return false + when is?(:always) + return @always_force = true + when is?(:quit) + say 'Aborting...' + raise SystemExit + when is?(:diff) + show_diff(destination, yield) if block_given? + say 'Retrying...' + else + say file_collision_help + end + end + end + + # Called if something goes wrong during the execution. This is used by Thor + # internally and should not be used inside your scripts. If someone went + # wrong, you can always raise an exception. If you raise a Thor::Error, it + # will be rescued and wrapped in the method below. + # + def error(statement) + $stderr.puts statement + end + + # Apply color to the given string with optional bold. Disabled in the + # Thor::Shell::Basic class. + # + def set_color(string, color, bold=false) #:nodoc: + string + end + + protected + + def is?(value) #:nodoc: + value = value.to_s + + if value.size == 1 + /\A#{value}\z/i + else + /\A(#{value}|#{value[0,1]})\z/i + end + end + + def file_collision_help #:nodoc: +< e + parse_argument_error(instance, e, caller) + rescue NoMethodError => e + parse_no_method_error(instance, e) + end + + # Returns the formatted usage. If a class is given, the class arguments are + # injected in the usage. + # + def formatted_usage(klass=nil, namespace=false, show_options=true) + formatted = if namespace.is_a?(String) + "#{namespace}:" + elsif klass && namespace + "#{klass.namespace.gsub(/^default/,'')}:" + else + "" + end + + formatted << formatted_arguments(klass) + formatted << " #{formatted_options}" if show_options + formatted.strip! + formatted + end + + # Injects the class arguments into the task usage. + # + def formatted_arguments(klass) + if klass && !klass.arguments.empty? + usage.to_s.gsub(/^#{name}/) do |match| + match << " " << klass.arguments.map{ |a| a.usage }.join(' ') + end + else + usage.to_s + end + end + + # Returns the options usage for this task. + # + def formatted_options + @formatted_options ||= options.map{ |_, o| o.usage }.sort.join(" ") + end + + protected + + # Given a target, checks if this class name is not a private/protected method. + # + def public_method?(instance) #:nodoc: + collection = instance.private_methods + instance.protected_methods + (collection & [name.to_s, name.to_sym]).empty? + end + + # Clean everything that comes from the Thor gempath and remove the caller. + # + def sans_backtrace(backtrace, caller) #:nodoc: + dirname = /^#{Regexp.escape(File.dirname(__FILE__))}/ + saned = backtrace.reject { |frame| frame =~ dirname } + saned -= caller + end + + def parse_argument_error(instance, e, caller) #:nodoc: + backtrace = sans_backtrace(e.backtrace, caller) + + if backtrace.empty? && e.message =~ /wrong number of arguments/ + if instance.is_a?(Thor::Group) + raise e, "'#{name}' was called incorrectly. Are you sure it has arity equals to 0?" + else + raise InvocationError, "'#{name}' was called incorrectly. Call as " << + "'#{formatted_usage(instance.class, true)}'" + end + else + raise e + end + end + + def parse_no_method_error(instance, e) #:nodoc: + if e.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/ + raise UndefinedTaskError, "The #{instance.class.namespace} namespace " << + "doesn't have a '#{name}' task" + else + raise e + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/util.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/util.rb new file mode 100644 index 0000000000..ebae0a3193 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/util.rb @@ -0,0 +1,251 @@ +require 'rbconfig' + +class Thor + module Sandbox #:nodoc: + end + + # This module holds several utilities: + # + # 1) Methods to convert thor namespaces to constants and vice-versa. + # + # Thor::Utils.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz" + # + # 2) Loading thor files and sandboxing: + # + # Thor::Utils.load_thorfile("~/.thor/foo") + # + module Util + + # Receives a namespace and search for it in the Thor::Base subclasses. + # + # ==== Parameters + # namespace:: The namespace to search for. + # + def self.find_by_namespace(namespace) + namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/ + + Thor::Base.subclasses.find do |klass| + klass.namespace == namespace + end + end + + # Receives a constant and converts it to a Thor namespace. Since Thor tasks + # can be added to a sandbox, this method is also responsable for removing + # the sandbox namespace. + # + # This method should not be used in general because it's used to deal with + # older versions of Thor. On current versions, if you need to get the + # namespace from a class, just call namespace on it. + # + # ==== Parameters + # constant:: The constant to be converted to the thor path. + # + # ==== Returns + # String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz" + # + def self.namespace_from_thor_class(constant, remove_default=true) + constant = constant.to_s.gsub(/^Thor::Sandbox::/, "") + constant = snake_case(constant).squeeze(":") + constant.gsub!(/^default/, '') if remove_default + constant + end + + # Given the contents, evaluate it inside the sandbox and returns the + # namespaces defined in the sandbox. + # + # ==== Parameters + # contents + # + # ==== Returns + # Array[Object] + # + def self.namespaces_in_content(contents, file=__FILE__) + old_constants = Thor::Base.subclasses.dup + Thor::Base.subclasses.clear + + load_thorfile(file, contents) + + new_constants = Thor::Base.subclasses.dup + Thor::Base.subclasses.replace(old_constants) + + new_constants.map!{ |c| c.namespace } + new_constants.compact! + new_constants + end + + # Returns the thor classes declared inside the given class. + # + def self.thor_classes_in(klass) + Thor::Base.subclasses.select do |subclass| + klass.constants.include?(subclass.name.gsub("#{klass.name}::", '')) + end + end + + # Receives a string and convert it to snake case. SnakeCase returns snake_case. + # + # ==== Parameters + # String + # + # ==== Returns + # String + # + def self.snake_case(str) + return str.downcase if str =~ /^[A-Z_]+$/ + str.gsub(/\B[A-Z]/, '_\&').squeeze('_') =~ /_*(.*)/ + return $+.downcase + end + + # Receives a string and convert it to camel case. camel_case returns CamelCase. + # + # ==== Parameters + # String + # + # ==== Returns + # String + # + def self.camel_case(str) + return str if str !~ /_/ && str =~ /[A-Z]+.*/ + str.split('_').map { |i| i.capitalize }.join + end + + # Receives a namespace and tries to retrieve a Thor or Thor::Group class + # from it. It first searches for a class using the all the given namespace, + # if it's not found, removes the highest entry and searches for the class + # again. If found, returns the highest entry as the class name. + # + # ==== Examples + # + # class Foo::Bar < Thor + # def baz + # end + # end + # + # class Baz::Foo < Thor::Group + # end + # + # Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default task + # Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil + # Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz" + # + # ==== Parameters + # namespace + # + # ==== Errors + # Thor::Error:: raised if the namespace cannot be found. + # + # Thor::Error:: raised if the namespace evals to a class which does not + # inherit from Thor or Thor::Group. + # + def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true) + if namespace.include?(?:) + pieces = namespace.split(":") + task = pieces.pop + klass = Thor::Util.find_by_namespace(pieces.join(":")) + end + + unless klass + klass, task = Thor::Util.find_by_namespace(namespace), nil + end + + raise Error, "could not find Thor class or task '#{namespace}'" if raise_if_nil && klass.nil? + return klass, task + end + + # Receives a path and load the thor file in the path. The file is evaluated + # inside the sandbox to avoid namespacing conflicts. + # + def self.load_thorfile(path, content=nil) + content ||= File.read(path) + + begin + Thor::Sandbox.class_eval(content, path) + rescue Exception => e + $stderr.puts "WARNING: unable to load thorfile #{path.inspect}: #{e.message}" + end + end + + # Receives a yaml (hash) and updates all constants entries to namespace. + # This was added to deal with deprecated versions of Thor. + # + # TODO Deprecate this method in the future. + # + # ==== Returns + # TrueClass|FalseClass:: Returns true if any change to the yaml file was made. + # + def self.convert_constants_to_namespaces(yaml) + yaml_changed = false + + yaml.each do |k, v| + next unless v[:constants] && v[:namespaces].nil? + yaml_changed = true + yaml[k][:namespaces] = v[:constants].map{|c| Thor::Util.namespace_from_thor_class(c)} + end + + yaml_changed + end + + def self.user_home + @@user_home ||= if ENV["HOME"] + ENV["HOME"] + elsif ENV["USERPROFILE"] + ENV["USERPROFILE"] + elsif ENV["HOMEDRIVE"] && ENV["HOMEPATH"] + File.join(ENV["HOMEDRIVE"], ENV["HOMEPATH"]) + elsif ENV["APPDATA"] + ENV["APPDATA"] + else + begin + File.expand_path("~") + rescue + if File::ALT_SEPARATOR + "C:/" + else + "/" + end + end + end + end + + # Returns the root where thor files are located, dependending on the OS. + # + def self.thor_root + File.join(user_home, ".thor").gsub(/\\/, '/') + end + + # Returns the files in the thor root. On Windows thor_root will be something + # like this: + # + # C:\Documents and Settings\james\.thor + # + # If we don't #gsub the \ character, Dir.glob will fail. + # + def self.thor_root_glob + files = Dir["#{thor_root}/*"] + + files.map! do |file| + File.directory?(file) ? File.join(file, "main.thor") : file + end + end + + # Where to look for Thor files. + # + def self.globs_for(path) + ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] + end + + # Return the path to the ruby interpreter taking into account multiple + # installations and windows extensions. + # + def self.ruby_command + @ruby_command ||= begin + ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) + ruby << Config::CONFIG['EXEEXT'] + + # escape string in case path to ruby executable contain spaces. + ruby.sub!(/.*\s.*/m, '"\&"') + ruby + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/version.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/version.rb new file mode 100644 index 0000000000..650253d648 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/version.rb @@ -0,0 +1,3 @@ +class Thor + VERSION = "0.12.1".freeze +end -- cgit v1.2.3 From abfc4dad3ebb17eccd32d1f1eb8a3e9c0f6e6e4e Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Mon, 30 Nov 2009 15:58:38 -0800 Subject: Remove global Rails initializers --- railties/lib/rails.rb | 17 ++++++++++++++++- railties/lib/rails/application.rb | 4 ---- railties/lib/rails/initializable.rb | 22 ---------------------- railties/lib/rails/initializer.rb | 2 -- 4 files changed, 16 insertions(+), 29 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index c23b67e321..aeac85f4b3 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -10,4 +10,19 @@ require 'rails/core' require 'rails/configuration' require 'rails/deprecation' require 'rails/initializer' -require 'rails/plugin' \ No newline at end of file +require 'rails/plugin' +require 'rails/ruby_version_check' + +# For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the +# multibyte safe operations. Plugin authors supporting other encodings +# should override this behaviour and set the relevant +default_charset+ +# on ActionController::Base. +# +# For Ruby 1.9, UTF-8 is the default internal and external encoding. +if RUBY_VERSION < '1.9' + $KCODE='u' +else + Encoding.default_external = Encoding::UTF_8 +end + +RAILS_ENV = (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup unless defined?(RAILS_ENV) \ No newline at end of file diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 7ea79aa9c9..41ae3f9687 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -82,10 +82,6 @@ module Rails @app.call(env) end - initializer :initialize_rails do - Rails.run_initializers - end - # Set the $LOAD_PATH based on the value of # Configuration#load_paths. Duplicates are removed. initializer :set_load_path do diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb index 3866b856b2..96234739cf 100644 --- a/railties/lib/rails/initializable.rb +++ b/railties/lib/rails/initializable.rb @@ -106,26 +106,4 @@ module Rails end end end - - include Initializable - - # Check for valid Ruby version (1.8.2 or 1.8.4 or higher). This is done in an - # external file, so we can use it from the `rails` program as well without duplication. - initializer :check_ruby_version, :global => true do - require 'rails/ruby_version_check' - end - - # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the - # multibyte safe operations. Plugin authors supporting other encodings - # should override this behaviour and set the relevant +default_charset+ - # on ActionController::Base. - # - # For Ruby 1.9, UTF-8 is the default internal and external encoding. - initializer :initialize_encoding, :global => true do - if RUBY_VERSION < '1.9' - $KCODE='u' - else - Encoding.default_external = Encoding::UTF_8 - end - end end \ No newline at end of file diff --git a/railties/lib/rails/initializer.rb b/railties/lib/rails/initializer.rb index 44101dcc94..95478428ec 100644 --- a/railties/lib/rails/initializer.rb +++ b/railties/lib/rails/initializer.rb @@ -1,7 +1,5 @@ require "rails" # In case people require this file directly -RAILS_ENV = (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development').dup unless defined?(RAILS_ENV) - module Rails class Initializer class Error < StandardError ; end -- cgit v1.2.3 From 39034997d1bd1fbaf33ddf1d6e3996b3c298a409 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 2 Dec 2009 10:14:02 -0800 Subject: Add support for bare ActiveSupport via config.active_support.bare --- railties/lib/rails.rb | 4 ++++ railties/lib/rails/application.rb | 17 ++--------------- 2 files changed, 6 insertions(+), 15 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index aeac85f4b3..b7cae9a9ac 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -1,5 +1,9 @@ require "pathname" +require 'active_support' +require 'active_support/core_ext/kernel/reporting' +require 'active_support/core_ext/logger' + require 'rails/initializable' require 'rails/application' require 'rails/railties_path' diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 41ae3f9687..be71469752 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -93,18 +93,8 @@ module Rails # list. By default, all frameworks (Active Record, Active Support, # Action Pack, Action Mailer, and Active Resource) are loaded. initializer :require_frameworks do - begin - require 'active_support' - require 'active_support/core_ext/kernel/reporting' - require 'active_support/core_ext/logger' - - # TODO: This is here to make Sam Ruby's tests pass. Needs discussion. - require 'active_support/core_ext/numeric/bytes' - config.frameworks.each { |framework| require(framework.to_s) } - rescue LoadError => e - # Re-raise as RuntimeError because Mongrel would swallow LoadError. - raise e.to_s - end + require 'active_support/all' unless config.active_support.bare + config.frameworks.each { |framework| require(framework.to_s) } end # Set the paths from which Rails will automatically load source files, and @@ -308,9 +298,6 @@ module Rails base_class.send("#{setting}=", value) end end - config.active_support.each do |setting, value| - ActiveSupport.send("#{setting}=", value) - end end # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ -- cgit v1.2.3 From fe41c7030b0a196600378418df4c59588ca1b4f8 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 2 Dec 2009 11:27:02 -0800 Subject: Stop evalling the environment file in favor of require + setting a Kernel#config. This will fix the bug where reopening classes caused them to be overwritten. --- railties/lib/rails/application.rb | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index be71469752..13232783d1 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -82,6 +82,23 @@ module Rails @app.call(env) end + + # Loads the environment specified by Configuration#environment_path, which + # is typically one of development, test, or production. + initializer :load_environment do + next unless File.file?(config.environment_path) + + config = self.config + + Kernel.class_eval do + meth = instance_method(:config) if Object.respond_to?(:config) + define_method(:config) { config } + require config.environment_path + remove_method :config + define_method(:config, &meth) if meth + end + end + # Set the $LOAD_PATH based on the value of # Configuration#load_paths. Duplicates are removed. initializer :set_load_path do @@ -123,24 +140,6 @@ module Rails end end - # Loads the environment specified by Configuration#environment_path, which - # is typically one of development, test, or production. - initializer :load_environment do - silence_warnings do - next if @environment_loaded - next unless File.file?(config.environment_path) - - @environment_loaded = true - constants = self.class.constants - - eval(IO.read(config.environment_path), binding, config.environment_path) - - (self.class.constants - constants).each do |const| - Object.const_set(const, self.class.const_get(const)) - end - end - end - # Preload all frameworks specified by the Configuration#frameworks. # Used by Passenger to ensure everything's loaded before forking and # to avoid autoload race conditions in JRuby. -- cgit v1.2.3 From 6680f9c4d77537807c3e43c7de85e94f75472d5c Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 2 Dec 2009 11:27:42 -0800 Subject: Fix an ivar name conflict in Rails::Server --- railties/lib/rails/commands/server.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 57b7c6a49c..3687b4460e 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -41,9 +41,9 @@ module Rails new(app).start end - def initialize(app) + def initialize(app_const) super() # Call Rack::Server#initialize without passing any options to use. - @app = app + @app_const = app_const end def start @@ -69,7 +69,7 @@ module Rails end def log_path - "#{File.expand_path(@app.root)}/log/#{options[:environment]}.log" + "#{File.expand_path(@app_const.root)}/log/#{options[:environment]}.log" end def default_options @@ -77,10 +77,10 @@ module Rails :Port => 3000, :Host => "0.0.0.0", :environment => (ENV['RAILS_ENV'] || "development").dup, - :rack_file => "#{@app.root}/config.ru", + :rack_file => "#{@app_const.root}/config.ru", :daemonize => false, :debugger => false, - :pid => "#{@app.root}/tmp/pids/server.pid", + :pid => "#{@app_const.root}/tmp/pids/server.pid", :AccessLog => [] } end -- cgit v1.2.3 From 8db038227ca4cbcba01a86ef5fb94cb13c780463 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 2 Dec 2009 14:10:22 -0600 Subject: Move controller namespace tracking into route set so it gets reloaded in dev mode --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 7ea79aa9c9..73198d68ca 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -387,7 +387,7 @@ module Rails initializer :initialize_routing do next unless configuration.frameworks.include?(:action_controller) - ActionController::Routing.controller_paths += configuration.controller_paths + ActionController::Routing::Routes.controller_paths += configuration.controller_paths ActionController::Routing::Routes.add_configuration_file(configuration.routes_configuration_file) ActionController::Routing::Routes.reload! end -- cgit v1.2.3 From c1304098cca8a9247a9ad1461a1a343354650843 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 2 Dec 2009 20:01:01 -0800 Subject: Reorganize autoloads: * A new module (ActiveSupport::Autoload) is provide that extends autoloading with new behavior. * All autoloads in modules that have extended ActiveSupport::Autoload will be eagerly required in threadsafe environments * Autoloads can optionally leave off the path if the path is the same as full_constant_name.underscore * It is possible to specify that a group of autoloads live under an additional path. For instance, all of ActionDispatch's middlewares are ActionDispatch::MiddlewareName, but they live under "action_dispatch/middlewares/middleware_name" * It is possible to specify that a group of autoloads are all found at the same path. For instance, a number of exceptions might all be declared there. * One consequence of this is that testing-related constants are not autoloaded. To get the testing helpers for a given component, require "component_name/test_case". For instance, "action_controller/test_case". * test_help.rb, which is automatically required by a Rails application's test helper, requires the test_case.rb for all active components, so this change will not be disruptive in existing or new applications. --- railties/lib/rails/console_app.rb | 1 + railties/lib/rails/test_help.rb | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/console_app.rb b/railties/lib/rails/console_app.rb index 1ad62e5058..9a51d594d3 100644 --- a/railties/lib/rails/console_app.rb +++ b/railties/lib/rails/console_app.rb @@ -1,6 +1,7 @@ require 'active_support/all' require 'active_support/test_case' require 'action_controller' +require 'action_dispatch/test_case' # work around the at_exit hook in test/unit, which kills IRB Test::Unit.run = true if Test::Unit.respond_to?(:run=) diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 9f6c42945f..0bf5f5c625 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -8,8 +8,14 @@ gem "rack-test", "~> 0.5.0" require 'test/unit' require 'active_support/core_ext/kernel/requires' + +# AP is always present +require 'action_controller/test_case' require 'action_view/test_case' +require 'action_dispatch/test_case' + require 'action_mailer/test_case' if defined?(ActionMailer) +require 'active_model/test_case' if defined?(ActiveModel) if defined?(ActiveRecord) require 'active_record/test_case' -- cgit v1.2.3 From 0fec53f243079a60df817cab55100a136fafc1c9 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 9 Dec 2009 18:57:16 -0600 Subject: Scaffolding generates new routing dsl examples --- .../rails/app/templates/config/routes.rb | 57 ++++++++++++++-------- .../rails/resource/resource_generator.rb | 2 +- railties/lib/rails/generators/rails/scaffold/USAGE | 2 +- 3 files changed, 39 insertions(+), 22 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index ea14ce1bfc..5d110f6a1c 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -1,43 +1,60 @@ ActionController::Routing::Routes.draw do |map| - # The priority is based upon order of creation: first created -> highest priority. + # The priority is based upon order of creation: + # first created -> highest priority. # Sample of regular route: - # map.connect 'products/:id', :controller => 'catalog', :action => 'view' + # match 'products/:id', :to => 'catalog#view' # Keep in mind you can assign values other than :controller and :action # Sample of named route: - # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase' + # match 'products/:id/purchase', :to => 'catalog#purchase', :as => :purchase # This route can be invoked with purchase_url(:id => product.id) # Sample resource route (maps HTTP verbs to controller actions automatically): - # map.resources :products + # resources :products # Sample resource route with options: - # map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get } + # resources :products do + # member do + # get :short + # post :toggle + # end + # + # collection do + # get :sold + # end + # end # Sample resource route with sub-resources: - # map.resources :products, :has_many => [ :comments, :sales ], :has_one => :seller - + # resources :products do + # resources :comments, :sales + # resource :seller + # end + # Sample resource route with more complex sub-resources - # map.resources :products do |products| - # products.resources :comments - # products.resources :sales, :collection => { :recent => :get } + # resources :products do + # resources :comments + # resources :sales do + # get :recent, :on => :collection + # end # end # Sample resource route within a namespace: - # map.namespace :admin do |admin| - # # Directs /admin/products/* to Admin::ProductsController (app/controllers/admin/products_controller.rb) - # admin.resources :products + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products # end - # You can have the root of your site routed with map.root -- just remember to delete public/index.html. - # map.root :controller => "welcome" + # You can have the root of your site routed with map.root + # just remember to delete public/index.html. + # root :to => "welcome" # See how all your routes lay out with "rake routes" - # Install the default routes as the lowest priority. - # Note: These default routes make all actions in every controller accessible via GET requests. You should - # consider removing or commenting them out if you're using named routes and resources. - map.connect ':controller/:action/:id' - map.connect ':controller/:action/:id.:format' + # Install the default route as the lowest priority. + # Note: The default route make all actions in every controller accessible + # via GET requests. You should consider removing or commenting it out if + # you're using named routes and resources. + match ':controller(/:action(/:id(.:format)))' end diff --git a/railties/lib/rails/generators/rails/resource/resource_generator.rb b/railties/lib/rails/generators/rails/resource/resource_generator.rb index e49f9aea1b..a89ce7faed 100644 --- a/railties/lib/rails/generators/rails/resource/resource_generator.rb +++ b/railties/lib/rails/generators/rails/resource/resource_generator.rb @@ -16,7 +16,7 @@ module Rails class_option :singleton, :type => :boolean, :desc => "Supply to create a singleton controller" def add_resource_route - route "map.resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}" + route "resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}" end protected diff --git a/railties/lib/rails/generators/rails/scaffold/USAGE b/railties/lib/rails/generators/rails/scaffold/USAGE index 71edd2f469..530ccdaf0a 100644 --- a/railties/lib/rails/generators/rails/scaffold/USAGE +++ b/railties/lib/rails/generators/rails/scaffold/USAGE @@ -17,7 +17,7 @@ Description: For example, 'scaffold post title:string body:text published:boolean' gives you a model with those three attributes, a controller that handles the create/show/update/destroy, forms to create and edit your posts, and - an index that lists them all, as well as a map.resources :posts + an index that lists them all, as well as a resources :posts declaration in config/routes.rb. If you want to remove all the generated files, run -- cgit v1.2.3 From b2ef6d13f0a0b3d07b8a2f9a1ec64988ba7e4392 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 9 Dec 2009 20:39:42 -0600 Subject: Fixed old routing mapper example in generated routes.rb --- railties/lib/rails/generators/actions.rb | 2 +- railties/lib/rails/generators/rails/app/templates/config/routes.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 57abc151d2..2efdf29127 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -269,7 +269,7 @@ module Rails # # === Example # - # route "map.root :controller => :welcome" + # route "root :to => 'welcome'" # def route(routing_code) log :route, routing_code diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index 5d110f6a1c..e0f9ca8a12 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -46,7 +46,7 @@ ActionController::Routing::Routes.draw do |map| # resources :products # end - # You can have the root of your site routed with map.root + # You can have the root of your site routed with "root" # just remember to delete public/index.html. # root :to => "welcome" -- cgit v1.2.3 From 71cd5b9568ddb3fee52318d79e899979887bc087 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 12 Dec 2009 19:44:52 -0600 Subject: Don't require AD test_case --- railties/lib/rails/console_app.rb | 1 - railties/lib/rails/test_help.rb | 1 - 2 files changed, 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/console_app.rb b/railties/lib/rails/console_app.rb index 9a51d594d3..1ad62e5058 100644 --- a/railties/lib/rails/console_app.rb +++ b/railties/lib/rails/console_app.rb @@ -1,7 +1,6 @@ require 'active_support/all' require 'active_support/test_case' require 'action_controller' -require 'action_dispatch/test_case' # work around the at_exit hook in test/unit, which kills IRB Test::Unit.run = true if Test::Unit.respond_to?(:run=) diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 0bf5f5c625..b89b7b5c27 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -12,7 +12,6 @@ require 'active_support/core_ext/kernel/requires' # AP is always present require 'action_controller/test_case' require 'action_view/test_case' -require 'action_dispatch/test_case' require 'action_mailer/test_case' if defined?(ActionMailer) require 'active_model/test_case' if defined?(ActiveModel) -- cgit v1.2.3 From f70079efb10f6af1187dc55dfbecc87136dc4738 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 14 Dec 2009 15:42:48 -0600 Subject: Fix warnings in railties configuration and initializeable --- railties/lib/rails/configuration.rb | 22 +++++++++++++--------- railties/lib/rails/initializable.rb | 4 ++-- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 3f43a48e2e..0449fe4ce5 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -2,15 +2,19 @@ require 'active_support/ordered_options' module Rails class Configuration - attr_accessor :cache_classes, :load_paths, :load_once_paths, :after_initialize_blocks, - :frameworks, :framework_root_path, :root, :gems, :plugins, - :i18n, :gems, :whiny_nils, :consider_all_requests_local, - :action_controller, :active_record, :action_view, :active_support, - :action_mailer, :active_resource, - :reload_plugins, :log_path, :log_level, :logger, :preload_frameworks, - :database_configuration_file, :cache_store, :time_zone, - :view_path, :metals, :controller_paths, :routes_configuration_file, - :eager_load_paths, :dependency_loading, :paths, :serve_static_assets + attr_accessor :action_controller, :action_mailer, :action_view, + :active_record, :active_resource, :active_support, + :after_initialize_blocks, :cache_classes, + :consider_all_requests_local, :dependency_loading, :gems, + :load_once_paths, :logger, :metals, :plugins, + :preload_frameworks, :reload_plugins, :serve_static_assets, + :time_zone, :whiny_nils + + attr_writer :cache_store, :controller_paths, + :database_configuration_file, :eager_load_paths, + :frameworks, :framework_root_path, :i18n, :load_paths, + :log_level, :log_path, :paths, :routes_configuration_file, + :view_path def initialize @load_once_paths = [] diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb index 96234739cf..add10bd207 100644 --- a/railties/lib/rails/initializable.rb +++ b/railties/lib/rails/initializable.rb @@ -5,7 +5,7 @@ module Rails end class Initializer - attr_reader :name, :before, :after, :global, :block + attr_reader :name, :block def initialize(name, context, options, &block) @name, @context, @options, @block = name, context, options, block @@ -62,7 +62,7 @@ module Rails end def run_initializers(*args) - return if @ran + return if instance_variable_defined?(:@ran) initializers.each do |initializer| initializer.run(*args) end -- cgit v1.2.3 From 5f8e48cbd297aca4add4b48efa2136ba6ac851b1 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 14 Dec 2009 17:54:41 -0600 Subject: Move route reloading into railties --- railties/lib/rails/application.rb | 49 +++++++++++++++++++++++++++++++++++---- railties/lib/rails/console_app.rb | 2 +- railties/lib/rails/plugin.rb | 4 ++-- 3 files changed, 48 insertions(+), 7 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 110311558c..047d252625 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -42,8 +42,13 @@ module Rails end end + attr_reader :route_configuration_files + def initialize Rails.application ||= self + + @route_configuration_files = [] + run_initializers(self) end @@ -65,6 +70,32 @@ module Rails ActionController::Routing::Routes end + def routes_changed_at + routes_changed_at = nil + + route_configuration_files.each do |config| + config_changed_at = File.stat(config).mtime + + if routes_changed_at.nil? || config_changed_at > routes_changed_at + routes_changed_at = config_changed_at + end + end + + routes_changed_at + end + + def reload_routes! + routes.disable_clear_and_finalize = true + + routes.clear! + route_configuration_files.each { |config| load(config) } + routes.finalize! + + nil + ensure + routes.disable_clear_and_finalize = false + end + def initializers initializers = super plugins.each { |p| initializers += p.initializers } @@ -359,6 +390,18 @@ module Rails next unless configuration.frameworks.include?(:action_controller) require 'rails/dispatcher' unless defined?(::Dispatcher) Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) + + unless configuration.cache_classes + # Setup dev mode route reloading + routes_last_modified = routes_changed_at + reload_routes = lambda do + unless routes_changed_at == routes_last_modified + routes_last_modified = routes_changed_at + reload_routes! + end + end + ActionDispatch::Callbacks.before_dispatch { |callbacks| reload_routes } + end end # Routing must be initialized after plugins to allow the former to extend the routes @@ -368,10 +411,8 @@ module Rails # loading module used to lazily load controllers (Configuration#controller_paths). initializer :initialize_routing do next unless configuration.frameworks.include?(:action_controller) - - ActionController::Routing::Routes.controller_paths += configuration.controller_paths - ActionController::Routing::Routes.add_configuration_file(configuration.routes_configuration_file) - ActionController::Routing::Routes.reload! + route_configuration_files << configuration.routes_configuration_file + reload_routes! end # # # Observers are loaded after plugins in case Observers or observed models are modified by plugins. diff --git a/railties/lib/rails/console_app.rb b/railties/lib/rails/console_app.rb index 1ad62e5058..2c4a7a51e8 100644 --- a/railties/lib/rails/console_app.rb +++ b/railties/lib/rails/console_app.rb @@ -27,6 +27,6 @@ end def reload! puts "Reloading..." ActionDispatch::Callbacks.new(lambda {}, true) - ActionController::Routing::Routes.reload + Rails.application.reload_routes! true end diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 86bf032641..8025135a64 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -55,8 +55,8 @@ module Rails initializer :add_routing_file, :after => :initialize_routing do |app| routing_file = "#{path}/config/routes.rb" if File.exist?(routing_file) - app.routes.add_configuration_file(routing_file) - app.routes.reload! + app.route_configuration_files << routing_file + app.reload_routes! end end end -- cgit v1.2.3 From f0bbc647c2086e9536c9d2b4ea7c4c18fe2edd3e Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 15 Dec 2009 10:48:56 -0600 Subject: Procs don't call themselves Fixes dev mode reloading [#3574 state:resolved] --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 047d252625..bc74ac8646 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -400,7 +400,7 @@ module Rails reload_routes! end end - ActionDispatch::Callbacks.before_dispatch { |callbacks| reload_routes } + ActionDispatch::Callbacks.before_dispatch { |callbacks| reload_routes.call } end end -- cgit v1.2.3 From 1b27f5c4f72384081083fa025b6b10e5ab02ae5e Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 15 Dec 2009 22:07:12 -0800 Subject: Add the ability for plugins to set default configuration settings. --- railties/lib/rails.rb | 5 +-- railties/lib/rails/application.rb | 8 ++++- railties/lib/rails/configuration.rb | 68 +++++++++++++++++++++++++++++-------- railties/lib/rails/plugin.rb | 21 ++++++++++++ 4 files changed, 84 insertions(+), 18 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index b7cae9a9ac..85aeb4af24 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -3,9 +3,11 @@ require "pathname" require 'active_support' require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/logger' +require 'action_dispatch' require 'rails/initializable' require 'rails/application' +require 'rails/plugin' require 'rails/railties_path' require 'rails/version' require 'rails/rack' @@ -14,7 +16,6 @@ require 'rails/core' require 'rails/configuration' require 'rails/deprecation' require 'rails/initializer' -require 'rails/plugin' require 'rails/ruby_version_check' # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the @@ -29,4 +30,4 @@ else Encoding.default_external = Encoding::UTF_8 end -RAILS_ENV = (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup unless defined?(RAILS_ENV) \ No newline at end of file +RAILS_ENV = (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup unless defined?(RAILS_ENV) diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index bc74ac8646..9e57354047 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -13,7 +13,11 @@ module Rails end def config - @config ||= Configuration.new + @config ||= begin + config = Configuration.new + Plugin.plugins.each { |p| config.merge(p.config) } + config + end end # TODO: change the plugin loader to use config @@ -104,6 +108,8 @@ module Rails def plugins @plugins ||= begin + plugin_names = config.plugins || [:all] + Plugin.plugins.select { |p| plugin_names.include?(p.plugin_name) } + Plugin::Vendored.all(config.plugins || [:all], config.paths.vendor.plugins) end end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 0449fe4ce5..0fa42091dd 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,10 +1,54 @@ require 'active_support/ordered_options' module Rails - class Configuration - attr_accessor :action_controller, :action_mailer, :action_view, - :active_record, :active_resource, :active_support, - :after_initialize_blocks, :cache_classes, + # Temporarily separate the plugin configuration class from the main + # configuration class while this bit is being cleaned up. + class Plugin::Configuration + + def initialize + @options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } + end + + def middleware + @middleware ||= ActionDispatch::MiddlewareStack.new + end + + def respond_to?(name) + super || name.to_s =~ config_key_regexp + end + + def merge(config) + @options = config.options.merge(@options) + end + + protected + + attr_reader :options + + private + + def method_missing(name, *args, &blk) + if name.to_s =~ config_key_regexp + return $2 == '=' ? @options[$1] = args.first : @options[$1] + end + + super + end + + def config_key_regexp + bits = config_keys.map { |n| Regexp.escape(n.to_s) }.join('|') + /^(#{bits})(?:=)?$/ + end + + def config_keys + ([ :active_support, :active_record, :action_controller, + :action_view, :action_mailer, :active_resource ] + + Plugin.plugin_names).map { |n| n.to_s }.uniq + end + end + + class Configuration < Plugin::Configuration + attr_accessor :after_initialize_blocks, :cache_classes, :consider_all_requests_local, :dependency_loading, :gems, :load_once_paths, :logger, :metals, :plugins, :preload_frameworks, :reload_plugins, :serve_static_assets, @@ -17,15 +61,11 @@ module Rails :view_path def initialize + super @load_once_paths = [] @after_initialize_blocks = [] @dependency_loading = true @serve_static_assets = true - - for framework in frameworks - self.send("#{framework}=", ActiveSupport::OrderedOptions.new) - end - self.active_support = ActiveSupport::OrderedOptions.new end def after_initialize(&blk) @@ -84,7 +124,10 @@ module Rails self.preload_frameworks = true self.cache_classes = true self.dependency_loading = false - self.action_controller.allow_concurrency = true + + if respond_to?(:action_controller) + action_controller.allow_concurrency = true + end self end @@ -103,11 +146,6 @@ module Rails defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root}/vendor/rails" end - def middleware - require 'action_dispatch' - @middleware ||= ActionDispatch::MiddlewareStack.new - end - # Loads and returns the contents of the #database_configuration_file. The # contents of the file are processed via ERB before being sent through # YAML::load. diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 8025135a64..90dc1ad8dd 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -2,6 +2,27 @@ module Rails class Plugin include Initializable + def self.plugin_name + @plugin_name || name.demodulize.underscore + end + + def self.inherited(klass) + @plugins ||= [] + @plugins << klass unless klass == Vendored + end + + def self.plugins + @plugins + end + + def self.plugin_names + plugins.map { |p| p.plugin_name } + end + + def self.config + @config ||= Configuration.new + end + class Vendored < Plugin def self.all(list, paths) plugins = [] -- cgit v1.2.3 From 7ee5843c3cedfe36a680d5b28aa31eef45296c50 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 16 Dec 2009 11:56:51 -0600 Subject: Fully expand relative rails framework paths and make sure we aren't adding any to the load path more than once. --- railties/lib/rails/generators.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index ffb9cfe1cd..0e66c9f58f 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -1,5 +1,6 @@ -activesupport_path = "#{File.dirname(__FILE__)}/../../../activesupport/lib" -$LOAD_PATH.unshift(activesupport_path) if File.directory?(activesupport_path) +activesupport_path = File.expand_path('../../../../activesupport/lib', __FILE__) +$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) + require 'active_support' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/metaclass' -- cgit v1.2.3 From b9d4ceb43c9497fb1c47d8b1e1e6a24a9e157384 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 16 Dec 2009 16:12:04 -0600 Subject: Need to lazy realize middleware options so they can be modified in the environment --- railties/lib/rails/application.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 9e57354047..e65c20de2c 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -210,9 +210,9 @@ module Rails initializer :initialize_middleware_stack do if config.frameworks.include?(:action_controller) - config.middleware.use(::Rack::Lock) unless ActionController::Base.allow_concurrency - config.middleware.use(ActionDispatch::ShowExceptions, ActionController::Base.consider_all_requests_local) - config.middleware.use(ActionDispatch::Callbacks, ActionController::Dispatcher.prepare_each_request) + config.middleware.use(::Rack::Lock, :if => lambda { ActionController::Base.allow_concurrency }) + config.middleware.use(ActionDispatch::ShowExceptions, lambda { ActionController::Base.consider_all_requests_local }) + config.middleware.use(ActionDispatch::Callbacks, lambda { ActionController::Dispatcher.prepare_each_request }) config.middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) config.middleware.use(ActionDispatch::ParamsParser) config.middleware.use(::Rack::MethodOverride) -- cgit v1.2.3 From fa575973b1ad5adb7115a18c4c1c7c31500e73b2 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 17 Dec 2009 16:37:11 -0800 Subject: Added alert/notice from 2-3-stable and refactored redirect_to into just living in Redirector [DHH] --- .../lib/rails/generators/erb/scaffold/templates/layout.html.erb | 2 +- .../generators/rails/scaffold_controller/templates/controller.rb | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/erb/scaffold/templates/layout.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/layout.html.erb index 6460e5b599..51c4ad0e2e 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/layout.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/layout.html.erb @@ -7,7 +7,7 @@ -

<%%= flash[:notice] %>

+

<%%= notice %>

<%%= yield %> diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index 3cc8bbf8e7..874e96a2b4 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -46,8 +46,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| if @<%= orm_instance.save %> - flash[:notice] = '<%= class_name %> was successfully created.' - format.html { redirect_to(@<%= file_name %>) } + format.html { redirect_to(@<%= file_name %>, :notice => '<%= class_name %> was successfully created.') } format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> } else format.html { render :action => "new" } @@ -63,8 +62,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| if @<%= orm_instance.update_attributes("params[:#{file_name}]") %> - flash[:notice] = '<%= class_name %> was successfully updated.' - format.html { redirect_to(@<%= file_name %>) } + format.html { redirect_to(@<%= file_name %>, :notice => '<%= class_name %> was successfully updated.') } format.xml { head :ok } else format.html { render :action => "edit" } -- cgit v1.2.3 From 44fb54fecdab684425bbc3bb15aac9d5c6e34fc8 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 17 Dec 2009 17:53:16 -0800 Subject: Models with no attributes should just have empty hash fixtures [Sam] (Closes #3563) --- .../generators/test_unit/model/templates/fixtures.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml index c21035113e..a30132bc99 100644 --- a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml +++ b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml @@ -11,9 +11,13 @@ two: <%= attribute.name %>: <%= attribute.default %> <% end -%> <% else -%> -# one: -# column: value +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below # -# two: -# column: value -<% end -%> +one: {} +# column: value +# +two: {} +# column: value +<% end -%> \ No newline at end of file -- cgit v1.2.3 From c06aff0a7e42868e9788d6cefe5ce49e93cbf45b Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 14:33:13 -0800 Subject: Added cookies.permanent, cookies.signed, and cookies.permanent.signed accessor for common cookie actions [DHH] --- .../templates/config/initializers/cookie_verification_secret.rb.tt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt new file mode 100644 index 0000000000..9808ea6a2d --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +ActionController::Base.cookie_verification_secret = '<%= app_secret %>'; -- cgit v1.2.3 From 3506cb730b89dee8a5067329b5aac707708426db Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 19:40:18 -0800 Subject: Mark the wild controller route as legacy an comment it out --- .../lib/rails/generators/rails/app/templates/config/routes.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index e0f9ca8a12..635ee8d87a 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -52,9 +52,7 @@ ActionController::Routing::Routes.draw do |map| # See how all your routes lay out with "rake routes" - # Install the default route as the lowest priority. - # Note: The default route make all actions in every controller accessible - # via GET requests. You should consider removing or commenting it out if - # you're using named routes and resources. - match ':controller(/:action(/:id(.:format)))' + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))' end -- cgit v1.2.3 From f9a4cf15627ba0c905bf0ab3de2b49b515ac197d Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 20:45:18 -0800 Subject: Show the new short-form in an example --- railties/lib/rails/generators/rails/app/templates/config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index 635ee8d87a..0d1b6bab4f 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -3,7 +3,7 @@ ActionController::Routing::Routes.draw do |map| # first created -> highest priority. # Sample of regular route: - # match 'products/:id', :to => 'catalog#view' + # match 'products/:id' => 'catalog#view' # Keep in mind you can assign values other than :controller and :action # Sample of named route: -- cgit v1.2.3 From f09ad263cabe2e781c1994b85375fee8deba4317 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 20 Dec 2009 20:50:25 -0800 Subject: Turn filter_parameter_logging on by default for password and password_confirmation and remove contentless comments --- .../rails/app/templates/app/controllers/application_controller.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb index 6635a3f487..e7991fff92 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb +++ b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb @@ -2,9 +2,7 @@ # Likewise, all the methods added will be available for all controllers. class ApplicationController < ActionController::Base - helper :all # include all helpers, all the time - protect_from_forgery # See ActionController::RequestForgeryProtection for details - - # Scrub sensitive parameters from your log - # filter_parameter_logging :password + helper :all + protect_from_forgery + filter_parameter_logging :password, :password_confirmation end -- cgit v1.2.3 From cf66d16bdfcb46c217ea06c05b8e0c5dfff73889 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Dec 2009 15:49:52 -0800 Subject: Its cookie_verifier_secret --- .../app/templates/config/initializers/cookie_verification_secret.rb.tt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt index 9808ea6a2d..9f05cd5a31 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt @@ -4,4 +4,4 @@ # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. -ActionController::Base.cookie_verification_secret = '<%= app_secret %>'; +ActionController::Base.cookie_verifier_secret = '<%= app_secret %>'; -- cgit v1.2.3 From 36624b2c709925bcabb49d12082b9dd9d28c4c5c Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Dec 2009 15:55:59 -0800 Subject: Give the builtin controllers their own routes.rb now that the legacy catch-all is gone --- railties/lib/rails/application.rb | 1 + railties/lib/rails/configuration.rb | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index e65c20de2c..498fd6a723 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -418,6 +418,7 @@ module Rails initializer :initialize_routing do next unless configuration.frameworks.include?(:action_controller) route_configuration_files << configuration.routes_configuration_file + route_configuration_files << configuration.builtin_routes_configuration_file reload_routes! end # diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 0fa42091dd..bf5b9478cc 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -158,6 +158,10 @@ module Rails @routes_configuration_file ||= File.join(root, 'config', 'routes.rb') end + def builtin_routes_configuration_file + @builtin_routes_configuration_file ||= File.join(RAILTIES_PATH, 'builtin', 'routes.rb') + end + def controller_paths @controller_paths ||= begin paths = [File.join(root, 'app', 'controllers')] -- cgit v1.2.3 From b0b4ae970c1cb586235bcfbc669d43475c7fe684 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Mon, 21 Dec 2009 16:03:20 -0800 Subject: test.rb, dev.rb, and production.rb just reopen the Application class; no more hax required --- railties/lib/rails/application.rb | 25 +++++----------- .../templates/config/environments/development.rb | 17 ----------- .../config/environments/development.rb.tt | 19 +++++++++++++ .../templates/config/environments/production.rb | 31 -------------------- .../templates/config/environments/production.rb.tt | 33 ++++++++++++++++++++++ .../app/templates/config/environments/test.rb | 27 ------------------ .../app/templates/config/environments/test.rb.tt | 29 +++++++++++++++++++ 7 files changed, 88 insertions(+), 93 deletions(-) delete mode 100644 railties/lib/rails/generators/rails/app/templates/config/environments/development.rb create mode 100644 railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt delete mode 100644 railties/lib/rails/generators/rails/app/templates/config/environments/production.rb create mode 100644 railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt delete mode 100644 railties/lib/rails/generators/rails/app/templates/config/environments/test.rb create mode 100644 railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 498fd6a723..d83c65da8d 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -9,7 +9,13 @@ module Rails end def new - @instance ||= super + @instance ||= begin + begin + require config.environment_path + rescue LoadError + end + super + end end def config @@ -119,23 +125,6 @@ module Rails @app.call(env) end - - # Loads the environment specified by Configuration#environment_path, which - # is typically one of development, test, or production. - initializer :load_environment do - next unless File.file?(config.environment_path) - - config = self.config - - Kernel.class_eval do - meth = instance_method(:config) if Object.respond_to?(:config) - define_method(:config) { config } - require config.environment_path - remove_method :config - define_method(:config, &meth) if meth - end - end - # Set the $LOAD_PATH based on the value of # Configuration#load_paths. Duplicates are removed. initializer :set_load_path do diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb deleted file mode 100644 index 85c9a6080e..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb +++ /dev/null @@ -1,17 +0,0 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# In the development environment your application's code is reloaded on -# every request. This slows down response time but is perfect for development -# since you don't have to restart the webserver when you make code changes. -config.cache_classes = false - -# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true - -# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_view.debug_rjs = true -config.action_controller.perform_caching = false - -# Don't care if the mailer can't send -config.action_mailer.raise_delivery_errors = false \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt new file mode 100644 index 0000000000..2b3940d47f --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -0,0 +1,19 @@ +class <%= app_const %> + # Settings specified here will take precedence over those in config/environment.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the webserver when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.action_controller.consider_all_requests_local = true + config.action_view.debug_rjs = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false +end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb deleted file mode 100644 index 377b9207c7..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb +++ /dev/null @@ -1,31 +0,0 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# The production environment is meant for finished, "live" apps. -# Code is not reloaded between requests -config.cache_classes = true - -# Full error reports are disabled and caching is turned on -config.action_controller.consider_all_requests_local = false -config.action_controller.perform_caching = true - -# See everything in the log (default is :info) -# config.log_level = :debug - -# Use a different logger for distributed setups -# config.logger = SyslogLogger.new - -# Use a different cache store in production -# config.cache_store = :mem_cache_store - -# Disable Rails's static asset server -# In production, Apache or nginx will already do this -config.serve_static_assets = false - -# Enable serving of images, stylesheets, and javascripts from an asset server -# config.action_controller.asset_host = "http://assets.example.com" - -# Disable delivery errors, bad email addresses will be ignored -# config.action_mailer.raise_delivery_errors = false - -# Enable threaded mode -# config.threadsafe! diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt new file mode 100644 index 0000000000..eff5801526 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -0,0 +1,33 @@ +class <%= app_const %> + # Settings specified here will take precedence over those in config/environment.rb + + # The production environment is meant for finished, "live" apps. + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.action_controller.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Disable Rails's static asset server + # In production, Apache or nginx will already do this + config.serve_static_assets = false + + # Enable serving of images, stylesheets, and javascripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! +end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb deleted file mode 100644 index 496eb9572b..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb +++ /dev/null @@ -1,27 +0,0 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# The test environment is used exclusively to run your application's -# test suite. You never need to work with it otherwise. Remember that -# your test database is "scratch space" for the test suite and is wiped -# and recreated between test runs. Don't rely on the data there! -config.cache_classes = true - -# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true - -# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_controller.perform_caching = false - -# Disable request forgery protection in test environment -config.action_controller.allow_forgery_protection = false - -# Tell Action Mailer not to deliver emails to the real world. -# The :test delivery method accumulates sent emails in the -# ActionMailer::Base.deliveries array. -config.action_mailer.delivery_method = :test - -# Use SQL instead of Active Record's schema dumper when creating the test database. -# This is necessary if your schema can't be completely dumped by the schema dumper, -# like if you have constraints or database-specific column types -# config.active_record.schema_format = :sql \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt new file mode 100644 index 0000000000..3246c7b5f5 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt @@ -0,0 +1,29 @@ +class <%= app_const %> + # Settings specified here will take precedence over those in config/environment.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.action_controller.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql +end \ No newline at end of file -- cgit v1.2.3 From d982fe2b2fcc4e197087901774e2f21467c3cec1 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Mon, 21 Dec 2009 16:35:54 -0800 Subject: Replace reopening the class with App.configure as an alias to class_eval --- railties/lib/rails/application.rb | 4 ++++ .../rails/app/templates/config/environments/development.rb.tt | 2 +- .../rails/app/templates/config/environments/production.rb.tt | 2 +- .../generators/rails/app/templates/config/environments/test.rb.tt | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index d83c65da8d..695a1d7c87 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -66,6 +66,10 @@ module Rails self.class.config end + class << self + alias configure class_eval + end + def root config.root end diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index 2b3940d47f..b10103b436 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -1,4 +1,4 @@ -class <%= app_const %> +<%= app_const %>.configure do # Settings specified here will take precedence over those in config/environment.rb # In the development environment your application's code is reloaded on diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index eff5801526..543a40108c 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -1,4 +1,4 @@ -class <%= app_const %> +<%= app_const %>.configure do # Settings specified here will take precedence over those in config/environment.rb # The production environment is meant for finished, "live" apps. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt index 3246c7b5f5..428fa35633 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt @@ -1,4 +1,4 @@ -class <%= app_const %> +<%= app_const %>.configure do # Settings specified here will take precedence over those in config/environment.rb # The test environment is used exclusively to run your application's -- cgit v1.2.3 From a43a9c81cf3d85e8dca6afdd92307ce153643ebe Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Dec 2009 16:41:02 -0800 Subject: Dont need to specify password_confirmation, that happens automatically --- .../rails/app/templates/app/controllers/application_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb index e7991fff92..9889b52893 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb +++ b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb @@ -4,5 +4,5 @@ class ApplicationController < ActionController::Base helper :all protect_from_forgery - filter_parameter_logging :password, :password_confirmation + filter_parameter_logging :password end -- cgit v1.2.3 From 76e732a7be690f09d1e5d6c97138a6eb7d263423 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 21 Dec 2009 16:53:52 -0800 Subject: Fix the documentation for root :to. It should use a fully qualified controller#action syntax (Closes #3606) --- railties/lib/rails/generators/rails/app/templates/config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index 0d1b6bab4f..e28ff42bdd 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -48,7 +48,7 @@ ActionController::Routing::Routes.draw do |map| # You can have the root of your site routed with "root" # just remember to delete public/index.html. - # root :to => "welcome" + # root :to => "welcome#index" # See how all your routes lay out with "rake routes" -- cgit v1.2.3 From 2e571e8f99e5e2712c0bc2558df8d62996204b03 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 21 Dec 2009 16:57:23 -0800 Subject: Blog -> Blog::Application. Leave the toplevel module up for grabs. --- .../rails/generators/rails/app/app_generator.rb | 2 +- .../rails/app/templates/config/application.rb | 62 +++++++++++----------- 2 files changed, 33 insertions(+), 31 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index ae18fa843b..6f71f7005f 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -182,7 +182,7 @@ module Rails::Generators end def app_const - @app_const ||= app_name.classify + @app_const ||= "#{app_name.classify}::Application" end def app_secret diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 2c17de2a23..15dc553e53 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -1,41 +1,43 @@ require File.expand_path('../boot', __FILE__) -class <%= app_const %> < Rails::Application - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. +module <%= app_name.classify %> + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. - # Add additional load paths for your own custom dirs - # config.load_paths += %W( #{root}/extras ) + # Add additional load paths for your own custom dirs + # config.load_paths += %W( #{root}/extras ) - # Only load the plugins named here, in the order given (default is alphabetical). - # :all can be used as a placeholder for all plugins not explicitly named - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - # Skip frameworks you're not going to use. To use Rails without a database, - # you must remove the Active Record framework. + # Skip frameworks you're not going to use. To use Rails without a database, + # you must remove the Active Record framework. <% if options[:skip_activerecord] -%> - config.frameworks -= [ :active_record ] + config.frameworks -= [ :active_record ] <% else -%> - # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] + # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] - # Activate observers that should always be running - # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + # Activate observers that should always be running + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer <% end -%> - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. - config.time_zone = 'UTC' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] - # config.i18n.default_locale = :de - - # Configure generators values. Many other options are available, be sure to - # check the documentation. - # config.generators do |g| - # g.orm :active_record - # g.template_engine :erb - # g.test_framework :test_unit, :fixture => true - # end + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. + config.time_zone = 'UTC' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] + # config.i18n.default_locale = :de + + # Configure generators values. Many other options are available, be sure to + # check the documentation. + # config.generators do |g| + # g.orm :active_record + # g.template_engine :erb + # g.test_framework :test_unit, :fixture => true + # end + end end -- cgit v1.2.3 From 426348b48403f664cc10e8ec545b640e56c1c090 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 21 Dec 2009 20:15:27 -0600 Subject: Update routes.rb template to use App name --- railties/lib/rails/application.rb | 4 ++++ railties/lib/rails/generators/actions.rb | 2 +- railties/lib/rails/generators/rails/app/app_generator.rb | 6 +++--- railties/lib/rails/generators/rails/app/templates/config/routes.rb | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 498fd6a723..4e21287496 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -41,6 +41,10 @@ module Rails end end + def routes + ActionController::Routing::Routes + end + def call(env) new.call(env) end diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 2efdf29127..f95b15acce 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -273,7 +273,7 @@ module Rails # def route(routing_code) log :route, routing_code - sentinel = "ActionController::Routing::Routes.draw do |map|" + sentinel = "routes.draw do |map|" in_root do inject_into_file 'config/routes.rb', "\n #{routing_code}\n", { :after => sentinel, :verbose => false } diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index ae18fa843b..b8f2911021 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -62,9 +62,9 @@ module Rails::Generators empty_directory "config" inside "config" do - copy_file "routes.rb" - template "application.rb" - template "environment.rb" + template "routes.rb" + template "application.rb" + template "environment.rb" directory "environments" directory "initializers" diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index 0d1b6bab4f..1959d3387f 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -1,4 +1,4 @@ -ActionController::Routing::Routes.draw do |map| +<%= app_const %>.routes.draw do |map| # The priority is based upon order of creation: # first created -> highest priority. -- cgit v1.2.3 From 2d0c703c922758dc36df8a20a56894484013b0f1 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Dec 2009 16:18:22 -0600 Subject: Use Rack::Runtime middleware so the reported time includes the entire middleware stack --- railties/lib/rails/application.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index e6f2d30429..d7a89ba2be 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -208,6 +208,7 @@ module Rails initializer :initialize_middleware_stack do if config.frameworks.include?(:action_controller) config.middleware.use(::Rack::Lock, :if => lambda { ActionController::Base.allow_concurrency }) + config.middleware.use(::Rack::Runtime) config.middleware.use(ActionDispatch::ShowExceptions, lambda { ActionController::Base.consider_all_requests_local }) config.middleware.use(ActionDispatch::Callbacks, lambda { ActionController::Dispatcher.prepare_each_request }) config.middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) -- cgit v1.2.3 From ec095456d859da4a09c7401585c211dc0f01fccd Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 22 Dec 2009 17:29:25 -0800 Subject: Dont auto require rubygems, move dep on rack-test to Gemfile --- railties/lib/rails/test_help.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index b89b7b5c27..2601765065 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -2,9 +2,8 @@ # so fixtures are loaded to the right database silence_warnings { RAILS_ENV = "test" } -require 'rubygems' -gem "rack", "~> 1.0.0" -gem "rack-test", "~> 0.5.0" +require 'rack' +require 'rack/test' require 'test/unit' require 'active_support/core_ext/kernel/requires' -- cgit v1.2.3 From dc677f7665e5ec74b5a313ba656bba19dc0f853d Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Tue, 22 Dec 2009 17:03:23 -0800 Subject: tests pass with requiring the frameworks in rails.rb --- railties/lib/rails.rb | 42 ++++++---------------------- railties/lib/rails/application.rb | 58 +++++++++++++++++++++++---------------- railties/lib/rails/core.rb | 34 +++++++++++++++++++++++ 3 files changed, 77 insertions(+), 57 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index 85aeb4af24..9fb3cd9f94 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -1,33 +1,9 @@ -require "pathname" - -require 'active_support' -require 'active_support/core_ext/kernel/reporting' -require 'active_support/core_ext/logger' -require 'action_dispatch' - -require 'rails/initializable' -require 'rails/application' -require 'rails/plugin' -require 'rails/railties_path' -require 'rails/version' -require 'rails/rack' -require 'rails/paths' -require 'rails/core' -require 'rails/configuration' -require 'rails/deprecation' -require 'rails/initializer' -require 'rails/ruby_version_check' - -# For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the -# multibyte safe operations. Plugin authors supporting other encodings -# should override this behaviour and set the relevant +default_charset+ -# on ActionController::Base. -# -# For Ruby 1.9, UTF-8 is the default internal and external encoding. -if RUBY_VERSION < '1.9' - $KCODE='u' -else - Encoding.default_external = Encoding::UTF_8 -end - -RAILS_ENV = (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup unless defined?(RAILS_ENV) +require "rails/core" + +%w(active_model active_record action_controller action_view action_mailer active_resource).each do |framework| + begin + require framework + require "#{framework}/rails" + rescue LoadError + end +end \ No newline at end of file diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index d7a89ba2be..97f72b106b 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,3 +1,5 @@ +require "fileutils" + module Rails class Application include Initializable @@ -140,13 +142,13 @@ module Rails $LOAD_PATH.uniq! end - # Requires all frameworks specified by the Configuration#frameworks - # list. By default, all frameworks (Active Record, Active Support, - # Action Pack, Action Mailer, and Active Resource) are loaded. - initializer :require_frameworks do - require 'active_support/all' unless config.active_support.bare - config.frameworks.each { |framework| require(framework.to_s) } - end + # # Requires all frameworks specified by the Configuration#frameworks + # # list. By default, all frameworks (Active Record, Active Support, + # # Action Pack, Action Mailer, and Active Resource) are loaded. + # initializer :require_frameworks do + # require 'active_support/all' unless config.active_support.bare + # config.frameworks.each { |framework| require(framework.to_s) } + # end # Set the paths from which Rails will automatically load source files, and # the load_once paths. @@ -192,7 +194,7 @@ module Rails # this sets the database configuration from Configuration#database_configuration # and then establishes the connection. initializer :initialize_database do - if config.frameworks.include?(:active_record) + if defined?(ActiveRecord) ActiveRecord::Base.configurations = config.database_configuration ActiveRecord::Base.establish_connection end @@ -206,7 +208,7 @@ module Rails end initializer :initialize_middleware_stack do - if config.frameworks.include?(:action_controller) + if defined?(ActionController) config.middleware.use(::Rack::Lock, :if => lambda { ActionController::Base.allow_concurrency }) config.middleware.use(::Rack::Runtime) config.middleware.use(ActionDispatch::ShowExceptions, lambda { ActionController::Base.consider_all_requests_local }) @@ -231,7 +233,7 @@ module Rails end initializer :initialize_framework_caches do - if config.frameworks.include?(:action_controller) + if defined?(ActionController) ActionController::Base.cache_store ||= RAILS_CACHE end end @@ -266,8 +268,12 @@ module Rails # logger is already set, it is not changed, otherwise it is set to use # RAILS_DEFAULT_LOGGER. initializer :initialize_framework_logging do - for framework in ([ :active_record, :action_controller, :action_mailer ] & config.frameworks) - framework.to_s.camelize.constantize.const_get("Base").logger ||= Rails.logger + for framework in [ :active_record, :action_controller, :action_mailer ] + # TODO BEFORE PUSHING: REMOVEZ + begin + framework.to_s.camelize.constantize.const_get("Base").logger ||= Rails.logger + rescue Exception + end end ActiveSupport::Dependencies.logger ||= Rails.logger @@ -302,7 +308,7 @@ module Rails Time.zone_default = zone_default - if config.frameworks.include?(:active_record) + if defined?(ActiveRecord) ActiveRecord::Base.time_zone_aware_attributes = true ActiveRecord::Base.default_timezone = :utc end @@ -326,10 +332,14 @@ module Rails # on each of the corresponding Base classes. initializer :initialize_framework_settings do config.frameworks.each do |framework| - base_class = framework.to_s.camelize.constantize.const_get("Base") + # TODO BEFORE PUSHING: This needs to work differently + begin + base_class = framework.to_s.camelize.constantize.const_get("Base") - config.send(framework).each do |setting, value| - base_class.send("#{setting}=", value) + config.send(framework).each do |setting, value| + base_class.send("#{setting}=", value) + end + rescue Exception end end end @@ -339,16 +349,16 @@ module Rails # paths have already been set, it is not changed, otherwise it is # set to use Configuration#view_path. initializer :initialize_framework_views do - if config.frameworks.include?(:action_view) + if defined?(ActionView) view_path = ActionView::PathSet.type_cast(config.view_path, config.cache_classes) - ActionMailer::Base.template_root = view_path if config.frameworks.include?(:action_mailer) && ActionMailer::Base.view_paths.blank? - ActionController::Base.view_paths = view_path if config.frameworks.include?(:action_controller) && ActionController::Base.view_paths.blank? + + ActionMailer::Base.template_root = view_path if defined?(ActionMailer) && ActionMailer::Base.view_paths.blank? + ActionController::Base.view_paths = view_path if defined?(ActionController) && ActionController::Base.view_paths.blank? end end initializer :initialize_metal do - # TODO: Make Rails and metal work without ActionController - if config.frameworks.include?(:action_controller) + if defined?(ActionController) Rails::Rack::Metal.requested_metals = config.metals config.middleware.insert_before( @@ -375,8 +385,8 @@ module Rails # # Setup database middleware after initializers have run initializer :initialize_database_middleware do - if configuration.frameworks.include?(:active_record) - if configuration.frameworks.include?(:action_controller) && ActionController::Base.session_store && + if defined?(ActiveRecord) + if defined?(ActionController) && ActionController::Base.session_store && ActionController::Base.session_store.name == 'ActiveRecord::SessionStore' configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache @@ -422,7 +432,7 @@ module Rails # # # Observers are loaded after plugins in case Observers or observed models are modified by plugins. initializer :load_observers do - if configuration.frameworks.include?(:active_record) + if defined?(ActiveRecord) ActiveRecord::Base.instantiate_observers end end diff --git a/railties/lib/rails/core.rb b/railties/lib/rails/core.rb index a5e51ad04a..da16c5816c 100644 --- a/railties/lib/rails/core.rb +++ b/railties/lib/rails/core.rb @@ -1,3 +1,37 @@ +require "pathname" + +require 'active_support' +require 'active_support/core_ext/kernel/reporting' +require 'active_support/core_ext/logger' +require 'action_dispatch' + +require 'rails/initializable' +require 'rails/application' +require 'rails/plugin' +require 'rails/railties_path' +require 'rails/version' +require 'rails/rack' +require 'rails/paths' +require 'rails/core' +require 'rails/configuration' +require 'rails/deprecation' +require 'rails/initializer' +require 'rails/ruby_version_check' + +# For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the +# multibyte safe operations. Plugin authors supporting other encodings +# should override this behaviour and set the relevant +default_charset+ +# on ActionController::Base. +# +# For Ruby 1.9, UTF-8 is the default internal and external encoding. +if RUBY_VERSION < '1.9' + $KCODE='u' +else + Encoding.default_external = Encoding::UTF_8 +end + +RAILS_ENV = (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup unless defined?(RAILS_ENV) + module Rails # Needs to be duplicated from Active Support since its needed before Active # Support is available. Here both Options and Hash are namespaced to prevent -- cgit v1.2.3 From fa8dfc7d014f6768599077b79a874894e13d317f Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 23 Dec 2009 13:45:55 -0800 Subject: Raise an exception if an initializer is defined without a block --- railties/lib/rails/initializable.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb index add10bd207..8fcb254590 100644 --- a/railties/lib/rails/initializable.rb +++ b/railties/lib/rails/initializable.rb @@ -93,6 +93,7 @@ module Rails end def initializer(name, opts = {}, &blk) + raise ArgumentError, "A block must be passed when defining an initializer" unless blk @initializers ||= [] @initializers << Initializer.new(name, nil, opts, &blk) end -- cgit v1.2.3 From 38aeb1528c376f7a058beea6db0a328720b85f01 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 23 Dec 2009 14:55:12 -0800 Subject: Moving out some framework specific initializers into the framework libraries. --- railties/lib/rails/application.rb | 66 ++++--------------------------------- railties/lib/rails/configuration.rb | 25 +++++++------- railties/lib/rails/plugin.rb | 8 +++-- 3 files changed, 26 insertions(+), 73 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 97f72b106b..9a5656fb1d 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -21,11 +21,7 @@ module Rails end def config - @config ||= begin - config = Configuration.new - Plugin.plugins.each { |p| config.merge(p.config) } - config - end + @config ||= Configuration.new(Plugin::Configuration.default) end # TODO: change the plugin loader to use config @@ -122,10 +118,11 @@ module Rails initializers end + # TODO: Fix this method def plugins @plugins ||= begin plugin_names = config.plugins || [:all] - Plugin.plugins.select { |p| plugin_names.include?(p.plugin_name) } + + Plugin.plugins.select { |p| plugin_names.include?(:all) || plugin_names.include?(p.plugin_name) } + Plugin::Vendored.all(config.plugins || [:all], config.paths.vendor.plugins) end end @@ -189,20 +186,9 @@ module Rails end end - # This initialization routine does nothing unless :active_record - # is one of the frameworks to load (Configuration#frameworks). If it is, - # this sets the database configuration from Configuration#database_configuration - # and then establishes the connection. - initializer :initialize_database do - if defined?(ActiveRecord) - ActiveRecord::Base.configurations = config.database_configuration - ActiveRecord::Base.establish_connection - end - end - # Include middleware to serve up static assets initializer :initialize_static_server do - if config.frameworks.include?(:action_controller) && config.serve_static_assets + if defined?(ActionController) && config.serve_static_assets config.middleware.use(ActionDispatch::Static, Rails.public_path) end end @@ -268,7 +254,7 @@ module Rails # logger is already set, it is not changed, otherwise it is set to use # RAILS_DEFAULT_LOGGER. initializer :initialize_framework_logging do - for framework in [ :active_record, :action_controller, :action_mailer ] + for framework in [ :action_controller, :action_mailer ] # TODO BEFORE PUSHING: REMOVEZ begin framework.to_s.camelize.constantize.const_get("Base").logger ||= Rails.logger @@ -293,7 +279,7 @@ module Rails require('active_support/whiny_nil') if config.whiny_nils end - # Sets the default value for Time.zone, and turns on ActiveRecord::Base#time_zone_aware_attributes. + # Sets the default value for Time.zone # If assigned value cannot be matched to a TimeZone, an exception will be raised. initializer :initialize_time_zone do if config.time_zone @@ -307,11 +293,6 @@ module Rails end Time.zone_default = zone_default - - if defined?(ActiveRecord) - ActiveRecord::Base.time_zone_aware_attributes = true - ActiveRecord::Base.default_timezone = :utc - end end end @@ -331,7 +312,7 @@ module Rails # (Configuration#frameworks). The available settings map to the accessors # on each of the corresponding Base classes. initializer :initialize_framework_settings do - config.frameworks.each do |framework| + (config.frameworks - [:active_record, :action_controller]).each do |framework| # TODO BEFORE PUSHING: This needs to work differently begin base_class = framework.to_s.camelize.constantize.const_get("Base") @@ -383,20 +364,6 @@ module Rails end end - # # Setup database middleware after initializers have run - initializer :initialize_database_middleware do - if defined?(ActiveRecord) - if defined?(ActionController) && ActionController::Base.session_store && - ActionController::Base.session_store.name == 'ActiveRecord::SessionStore' - configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement - configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache - else - configuration.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement - configuration.middleware.use ActiveRecord::QueryCache - end - end - end - # TODO: Make a DSL way to limit an initializer to a particular framework # # Prepare dispatcher callbacks and run 'prepare' callbacks @@ -418,25 +385,6 @@ module Rails end end - # Routing must be initialized after plugins to allow the former to extend the routes - # --- - # If Action Controller is not one of the loaded frameworks (Configuration#frameworks) - # this does nothing. Otherwise, it loads the routing definitions and sets up - # loading module used to lazily load controllers (Configuration#controller_paths). - initializer :initialize_routing do - next unless configuration.frameworks.include?(:action_controller) - route_configuration_files << configuration.routes_configuration_file - route_configuration_files << configuration.builtin_routes_configuration_file - reload_routes! - end - # - # # Observers are loaded after plugins in case Observers or observed models are modified by plugins. - initializer :load_observers do - if defined?(ActiveRecord) - ActiveRecord::Base.instantiate_observers - end - end - # Eager load application classes initializer :load_application_classes do next if $rails_rake_task diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index bf5b9478cc..086f67a419 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -5,22 +5,26 @@ module Rails # configuration class while this bit is being cleaned up. class Plugin::Configuration - def initialize - @options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } + def self.default + @default ||= new end - def middleware - @middleware ||= ActionDispatch::MiddlewareStack.new + attr_reader :middleware + + def initialize(base = nil) + if base + @options = base.options.dup + @middleware = base.middleware.dup + else + @options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } + @middleware = ActionDispatch::MiddlewareStack.new + end end def respond_to?(name) super || name.to_s =~ config_key_regexp end - def merge(config) - @options = config.options.merge(@options) - end - protected attr_reader :options @@ -41,8 +45,7 @@ module Rails end def config_keys - ([ :active_support, :active_record, :action_controller, - :action_view, :action_mailer, :active_resource ] + + ([ :active_support, :action_view, :action_mailer, :active_resource ] + Plugin.plugin_names).map { |n| n.to_s }.uniq end end @@ -60,7 +63,7 @@ module Rails :log_level, :log_path, :paths, :routes_configuration_file, :view_path - def initialize + def initialize(base = nil) super @load_once_paths = [] @after_initialize_blocks = [] diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 90dc1ad8dd..0699affea7 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -2,8 +2,10 @@ module Rails class Plugin include Initializable - def self.plugin_name - @plugin_name || name.demodulize.underscore + def self.plugin_name(plugin_name = nil) + @plugin_name ||= name.demodulize.underscore + @plugin_name = plugin_name if plugin_name + @plugin_name end def self.inherited(klass) @@ -20,7 +22,7 @@ module Rails end def self.config - @config ||= Configuration.new + Configuration.default end class Vendored < Plugin -- cgit v1.2.3 From 94bb3316353ace661a83563f44a9c47baf438f26 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 23 Dec 2009 17:11:17 -0800 Subject: Shift more responsibility from application class to its singleton instance. Treat instantiation and boot as separate steps. Use app.config rather than app.configuration. --- railties/lib/rails/application.rb | 123 ++++++++------------- railties/lib/rails/commands/server.rb | 10 +- .../rails/generators/rails/app/templates/config.ru | 2 +- .../rails/app/templates/script/console.tt | 2 +- .../rails/app/templates/script/dbconsole.tt | 2 +- .../rails/app/templates/script/server.tt | 2 +- 6 files changed, 55 insertions(+), 86 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index d7a89ba2be..c594b8a31d 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,21 +1,17 @@ +require 'active_support/core_ext/module/delegation' + module Rails class Application include Initializable class << self - # Stub out App initialize - def initialize! - new - end + attr_writer :config + alias configure class_eval + delegate :initialize!, :load_tasks, :to => :instance - def new - @instance ||= begin - begin - require config.environment_path - rescue LoadError - end - super - end + private :new + def instance + @instance ||= new end def config @@ -26,66 +22,29 @@ module Rails end end - # TODO: change the plugin loader to use config - alias configuration config - - def config=(config) - @config = config - end - - def root - config.root - end - - def load_tasks - require "rails/tasks" - Dir["#{root}/vendor/plugins/*/**/tasks/**/*.rake"].sort.each { |ext| load ext } - Dir["#{root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } - task :environment do - $rails_rake_task = true - initialize! - end - end - def routes ActionController::Routing::Routes end - - def call(env) - new.call(env) - end end + delegate :config, :routes, :to => :'self.class' + delegate :root, :middleware, :to => :config attr_reader :route_configuration_files def initialize + require_environment Rails.application ||= self - @route_configuration_files = [] - - run_initializers(self) - end - - def config - self.class.config - end - - class << self - alias configure class_eval - end - - def root - config.root end - alias configuration config - - def middleware - config.middleware + def initialize! + run_initializers(self) + self end - def routes - ActionController::Routing::Routes + def require_environment + require config.environment_path + rescue LoadError end def routes_changed_at @@ -114,6 +73,16 @@ module Rails routes.disable_clear_and_finalize = false end + def load_tasks + require "rails/tasks" + Dir["#{root}/vendor/plugins/*/**/tasks/**/*.rake"].sort.each { |ext| load ext } + Dir["#{root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } + task :environment do + $rails_rake_task = true + initialize! + end + end + def initializers initializers = super plugins.each { |p| initializers += p.initializers } @@ -170,7 +139,7 @@ module Rails # Create tmp directories initializer :ensure_tmp_directories_exist do %w(cache pids sessions sockets).each do |dir_to_make| - FileUtils.mkdir_p(File.join(config.root, 'tmp', dir_to_make)) + FileUtils.mkdir_p(File.join(root, 'tmp', dir_to_make)) end end @@ -361,28 +330,28 @@ module Rails # # already called abort() unless $gems_rake_task is set # return unless gems_dependencies_loaded initializer :load_application_initializers do - Dir["#{configuration.root}/config/initializers/**/*.rb"].sort.each do |initializer| + Dir["#{root}/config/initializers/**/*.rb"].sort.each do |initializer| load(initializer) end end # Fires the user-supplied after_initialize block (Configuration#after_initialize) initializer :after_initialize do - configuration.after_initialize_blocks.each do |block| + config.after_initialize_blocks.each do |block| block.call end end # # Setup database middleware after initializers have run initializer :initialize_database_middleware do - if configuration.frameworks.include?(:active_record) - if configuration.frameworks.include?(:action_controller) && ActionController::Base.session_store && + if config.frameworks.include?(:active_record) + if config.frameworks.include?(:action_controller) && ActionController::Base.session_store && ActionController::Base.session_store.name == 'ActiveRecord::SessionStore' - configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement - configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache + config.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement + config.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache else - configuration.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement - configuration.middleware.use ActiveRecord::QueryCache + config.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement + config.middleware.use ActiveRecord::QueryCache end end end @@ -391,11 +360,11 @@ module Rails # # Prepare dispatcher callbacks and run 'prepare' callbacks initializer :prepare_dispatcher do - next unless configuration.frameworks.include?(:action_controller) + next unless config.frameworks.include?(:action_controller) require 'rails/dispatcher' unless defined?(::Dispatcher) - Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) + Dispatcher.define_dispatcher_callbacks(config.cache_classes) - unless configuration.cache_classes + unless config.cache_classes # Setup dev mode route reloading routes_last_modified = routes_changed_at reload_routes = lambda do @@ -414,15 +383,15 @@ module Rails # this does nothing. Otherwise, it loads the routing definitions and sets up # loading module used to lazily load controllers (Configuration#controller_paths). initializer :initialize_routing do - next unless configuration.frameworks.include?(:action_controller) - route_configuration_files << configuration.routes_configuration_file - route_configuration_files << configuration.builtin_routes_configuration_file + next unless config.frameworks.include?(:action_controller) + route_configuration_files << config.routes_configuration_file + route_configuration_files << config.builtin_routes_configuration_file reload_routes! end # # # Observers are loaded after plugins in case Observers or observed models are modified by plugins. initializer :load_observers do - if configuration.frameworks.include?(:active_record) + if config.frameworks.include?(:active_record) ActiveRecord::Base.instantiate_observers end end @@ -431,8 +400,8 @@ module Rails initializer :load_application_classes do next if $rails_rake_task - if configuration.cache_classes - configuration.eager_load_paths.each do |load_path| + if config.cache_classes + config.eager_load_paths.each do |load_path| matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/ Dir.glob("#{load_path}/**/*.rb").sort.each do |file| require_dependency file.sub(matcher, '\1') @@ -443,7 +412,7 @@ module Rails # Disable dependency loading during request cycle initializer :disable_dependency_loading do - if configuration.cache_classes && !configuration.dependency_loading + if config.cache_classes && !config.dependency_loading ActiveSupport::Dependencies.unhook! end end diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 3687b4460e..57b7c6a49c 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -41,9 +41,9 @@ module Rails new(app).start end - def initialize(app_const) + def initialize(app) super() # Call Rack::Server#initialize without passing any options to use. - @app_const = app_const + @app = app end def start @@ -69,7 +69,7 @@ module Rails end def log_path - "#{File.expand_path(@app_const.root)}/log/#{options[:environment]}.log" + "#{File.expand_path(@app.root)}/log/#{options[:environment]}.log" end def default_options @@ -77,10 +77,10 @@ module Rails :Port => 3000, :Host => "0.0.0.0", :environment => (ENV['RAILS_ENV'] || "development").dup, - :rack_file => "#{@app_const.root}/config.ru", + :rack_file => "#{@app.root}/config.ru", :daemonize => false, :debugger => false, - :pid => "#{@app_const.root}/tmp/pids/server.pid", + :pid => "#{@app.root}/tmp/pids/server.pid", :AccessLog => [] } end diff --git a/railties/lib/rails/generators/rails/app/templates/config.ru b/railties/lib/rails/generators/rails/app/templates/config.ru index f3bf3d6117..acb8435446 100644 --- a/railties/lib/rails/generators/rails/app/templates/config.ru +++ b/railties/lib/rails/generators/rails/app/templates/config.ru @@ -2,4 +2,4 @@ require ::File.expand_path('../config/environment', __FILE__) # Dispatch the request -run <%= app_const%> +run <%= app_const %>.instance diff --git a/railties/lib/rails/generators/rails/app/templates/script/console.tt b/railties/lib/rails/generators/rails/app/templates/script/console.tt index 4262439e52..9ddd4cfe62 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/console.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/console.tt @@ -1,3 +1,3 @@ require File.expand_path('../../config/application', __FILE__) require 'rails/commands/console' -Rails::Console.start(<%= app_const %>) +Rails::Console.start(<%= app_const %>.instance) diff --git a/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt b/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt index 9dfa24c378..96e0bc191b 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt @@ -1,3 +1,3 @@ require File.expand_path('../../config/application', __FILE__) require 'rails/commands/dbconsole' -Rails::DBConsole.start(<%= app_const %>) \ No newline at end of file +Rails::DBConsole.start(<%= app_const %>.instance) diff --git a/railties/lib/rails/generators/rails/app/templates/script/server.tt b/railties/lib/rails/generators/rails/app/templates/script/server.tt index d98f677475..380dc42cb5 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/server.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/server.tt @@ -1,3 +1,3 @@ require File.expand_path('../../config/application', __FILE__) require 'rails/commands/server' -Rails::Server.start(<%= app_const %>) +Rails::Server.start(<%= app_const %>.instance) -- cgit v1.2.3 From 1ee50e58f6eb429872dfeabeb0708a8065ff34de Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 23 Dec 2009 17:14:21 -0800 Subject: Fix Rack::Lock middleware condition: use *unless* we allow concurrency --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index c594b8a31d..e950d72586 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -176,7 +176,7 @@ module Rails initializer :initialize_middleware_stack do if config.frameworks.include?(:action_controller) - config.middleware.use(::Rack::Lock, :if => lambda { ActionController::Base.allow_concurrency }) + config.middleware.use(::Rack::Lock, :if => lambda { !ActionController::Base.allow_concurrency }) config.middleware.use(::Rack::Runtime) config.middleware.use(ActionDispatch::ShowExceptions, lambda { ActionController::Base.consider_all_requests_local }) config.middleware.use(ActionDispatch::Callbacks, lambda { ActionController::Dispatcher.prepare_each_request }) -- cgit v1.2.3 From d2bd71a145ddc5e3e3750edc9a09eab742aaf02a Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 23 Dec 2009 17:01:07 -0800 Subject: Finish moving config.frameworks-dependent code to the framework plugin --- railties/lib/rails/application.rb | 112 +------------------------------------- 1 file changed, 1 insertion(+), 111 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 9a5656fb1d..8ba24af793 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -139,14 +139,6 @@ module Rails $LOAD_PATH.uniq! end - # # Requires all frameworks specified by the Configuration#frameworks - # # list. By default, all frameworks (Active Record, Active Support, - # # Action Pack, Action Mailer, and Active Resource) are loaded. - # initializer :require_frameworks do - # require 'active_support/all' unless config.active_support.bare - # config.frameworks.each { |framework| require(framework.to_s) } - # end - # Set the paths from which Rails will automatically load source files, and # the load_once paths. initializer :set_autoload_paths do @@ -177,34 +169,7 @@ module Rails # Used by Passenger to ensure everything's loaded before forking and # to avoid autoload race conditions in JRuby. initializer :preload_frameworks do - if config.preload_frameworks - config.frameworks.each do |framework| - # String#classify and #constantize aren't available yet. - toplevel = Object.const_get(framework.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }) - toplevel.load_all! if toplevel.respond_to?(:load_all!) - end - end - end - - # Include middleware to serve up static assets - initializer :initialize_static_server do - if defined?(ActionController) && config.serve_static_assets - config.middleware.use(ActionDispatch::Static, Rails.public_path) - end - end - - initializer :initialize_middleware_stack do - if defined?(ActionController) - config.middleware.use(::Rack::Lock, :if => lambda { ActionController::Base.allow_concurrency }) - config.middleware.use(::Rack::Runtime) - config.middleware.use(ActionDispatch::ShowExceptions, lambda { ActionController::Base.consider_all_requests_local }) - config.middleware.use(ActionDispatch::Callbacks, lambda { ActionController::Dispatcher.prepare_each_request }) - config.middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) - config.middleware.use(ActionDispatch::ParamsParser) - config.middleware.use(::Rack::MethodOverride) - config.middleware.use(::Rack::Head) - config.middleware.use(ActionDispatch::StringCoercion) - end + ActiveSupport::Autoload.eager_load! if config.preload_frameworks end initializer :initialize_cache do @@ -218,12 +183,6 @@ module Rails end end - initializer :initialize_framework_caches do - if defined?(ActionController) - ActionController::Base.cache_store ||= RAILS_CACHE - end - end - initializer :initialize_logger do # if the environment has explicitly defined a logger, use it next if Rails.logger @@ -254,14 +213,6 @@ module Rails # logger is already set, it is not changed, otherwise it is set to use # RAILS_DEFAULT_LOGGER. initializer :initialize_framework_logging do - for framework in [ :action_controller, :action_mailer ] - # TODO BEFORE PUSHING: REMOVEZ - begin - framework.to_s.camelize.constantize.const_get("Base").logger ||= Rails.logger - rescue Exception - end - end - ActiveSupport::Dependencies.logger ||= Rails.logger Rails.cache.logger ||= Rails.logger end @@ -308,46 +259,6 @@ module Rails end end - # Initializes framework-specific settings for each of the loaded frameworks - # (Configuration#frameworks). The available settings map to the accessors - # on each of the corresponding Base classes. - initializer :initialize_framework_settings do - (config.frameworks - [:active_record, :action_controller]).each do |framework| - # TODO BEFORE PUSHING: This needs to work differently - begin - base_class = framework.to_s.camelize.constantize.const_get("Base") - - config.send(framework).each do |setting, value| - base_class.send("#{setting}=", value) - end - rescue Exception - end - end - end - - # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ - # (but only for those frameworks that are to be loaded). If the framework's - # paths have already been set, it is not changed, otherwise it is - # set to use Configuration#view_path. - initializer :initialize_framework_views do - if defined?(ActionView) - view_path = ActionView::PathSet.type_cast(config.view_path, config.cache_classes) - - ActionMailer::Base.template_root = view_path if defined?(ActionMailer) && ActionMailer::Base.view_paths.blank? - ActionController::Base.view_paths = view_path if defined?(ActionController) && ActionController::Base.view_paths.blank? - end - end - - initializer :initialize_metal do - if defined?(ActionController) - Rails::Rack::Metal.requested_metals = config.metals - - config.middleware.insert_before( - :"ActionDispatch::ParamsParser", - Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) - end - end - # # bail out if gems are missing - note that check_gem_dependencies will have # # already called abort() unless $gems_rake_task is set # return unless gems_dependencies_loaded @@ -364,27 +275,6 @@ module Rails end end - # TODO: Make a DSL way to limit an initializer to a particular framework - - # # Prepare dispatcher callbacks and run 'prepare' callbacks - initializer :prepare_dispatcher do - next unless configuration.frameworks.include?(:action_controller) - require 'rails/dispatcher' unless defined?(::Dispatcher) - Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) - - unless configuration.cache_classes - # Setup dev mode route reloading - routes_last_modified = routes_changed_at - reload_routes = lambda do - unless routes_changed_at == routes_last_modified - routes_last_modified = routes_changed_at - reload_routes! - end - end - ActionDispatch::Callbacks.before_dispatch { |callbacks| reload_routes.call } - end - end - # Eager load application classes initializer :load_application_classes do next if $rails_rake_task -- cgit v1.2.3 From af5c3c852e43fc95b4c4344f61c9c8fc2210b0ca Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 23 Dec 2009 19:00:20 -0800 Subject: Require active_support/all unless specifically requested to be left out. --- railties/lib/rails/application.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 8ba24af793..711509738d 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -132,6 +132,10 @@ module Rails @app.call(env) end + initializer :load_all_active_support do + require "active_support/all" unless config.active_support.bare + end + # Set the $LOAD_PATH based on the value of # Configuration#load_paths. Duplicates are removed. initializer :set_load_path do -- cgit v1.2.3 From b9c0a1665531d797e890efdf2fcace8a03961fe0 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 24 Dec 2009 16:08:03 -0800 Subject: The new routes shortform now also works for :as --- railties/lib/rails/generators/rails/app/templates/config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index ac916e9d90..d6c0365c04 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -7,7 +7,7 @@ # Keep in mind you can assign values other than :controller and :action # Sample of named route: - # match 'products/:id/purchase', :to => 'catalog#purchase', :as => :purchase + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase # This route can be invoked with purchase_url(:id => product.id) # Sample resource route (maps HTTP verbs to controller actions automatically): -- cgit v1.2.3 From bdf8ee44c54dec181827c02c2b74ea329bdab931 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 26 Dec 2009 18:21:36 -0600 Subject: script/server should init Rails by loading config.ru Fixes "Rails 3.0 doesn't fucking work" --- railties/lib/rails/commands/server.rb | 20 ++++---------------- .../generators/rails/app/templates/script/server.tt | 6 ++++-- 2 files changed, 8 insertions(+), 18 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 57b7c6a49c..09d7207d51 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -37,15 +37,6 @@ module Rails Options.new end - def self.start(app) - new(app).start - end - - def initialize(app) - super() # Call Rack::Server#initialize without passing any options to use. - @app = app - end - def start puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}" @@ -69,20 +60,17 @@ module Rails end def log_path - "#{File.expand_path(@app.root)}/log/#{options[:environment]}.log" + "log/#{options[:environment]}.log" end def default_options - { + super.merge({ :Port => 3000, - :Host => "0.0.0.0", :environment => (ENV['RAILS_ENV'] || "development").dup, - :rack_file => "#{@app.root}/config.ru", :daemonize => false, :debugger => false, - :pid => "#{@app.root}/tmp/pids/server.pid", - :AccessLog => [] - } + :pid => "tmp/pids/server.pid" + }) end end end diff --git a/railties/lib/rails/generators/rails/app/templates/script/server.tt b/railties/lib/rails/generators/rails/app/templates/script/server.tt index 380dc42cb5..4fd0cc7832 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/server.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/server.tt @@ -1,3 +1,5 @@ -require File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) require 'rails/commands/server' -Rails::Server.start(<%= app_const %>.instance) + +Dir.chdir(File.expand_path('../..', __FILE__)) +Rails::Server.start -- cgit v1.2.3 From 7e8b7f46bfc086a36db996420fbee93348c5268e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 27 Dec 2009 13:31:36 +0100 Subject: Add config.action_controller.include behavior to plugins. --- railties/lib/rails/configuration.rb | 20 +++++++++++++++++++- railties/lib/rails/plugin.rb | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 086f67a419..cb321536d2 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,6 +1,24 @@ require 'active_support/ordered_options' module Rails + # Create a Plugin::Options from ActiveSuppot::OrderedOptions, + # which support the following syntax: + # + # controller.action_controller.include FooBar + # + class Plugin::Options < ActiveSupport::OrderedOptions #:nodoc: + attr_reader :includes + + def initialize(*args) + @includes = [] + super + end + + def include(*args) + @includes.concat(args) + end + end + # Temporarily separate the plugin configuration class from the main # configuration class while this bit is being cleaned up. class Plugin::Configuration @@ -16,7 +34,7 @@ module Rails @options = base.options.dup @middleware = base.middleware.dup else - @options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } + @options = Hash.new { |h,k| h[k] = Rails::Plugin::Options.new } @middleware = ActionDispatch::MiddlewareStack.new end end diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 0699affea7..aa325c6f76 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -25,6 +25,24 @@ module Rails Configuration.default end + # Creates an initializer which includes all given modules to the given class. + # + # module Rails + # class ActionController < Rails::Plugin + # plugin_name :action_controller + # include_modules_in "ActionController::Base" + # end + # end + # + def self.include_modules_in(klass, from=plugin_name) + self.initializer :"#{from}.include_modules" do |app| + klass = klass.constantize if klass.is_a?(String) + app.config.send(from).includes.each do |mod| + klass.send(:include, mod.is_a?(String) ? mod.constantize : mod) + end + end + end + class Vendored < Plugin def self.all(list, paths) plugins = [] -- cgit v1.2.3 From 1cd949006a419807d5ae3400442942b752780ca2 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 27 Dec 2009 14:43:06 -0800 Subject: Fix the i18n dependency problem --- railties/lib/rails/generators.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 0e66c9f58f..16b28dd295 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -4,8 +4,7 @@ $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.inc require 'active_support' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/metaclass' -require 'active_support/core_ext/array' -require 'active_support/core_ext/hash' +require 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/string/inflections' @@ -95,7 +94,7 @@ module Rails end def self.plugins_generators_paths #:nodoc: - return [] unless Rails.root + return [] unless defined?(Rails.root) Dir[File.join(Rails.root, "vendor", "plugins", "*", "lib", "{generators,rails_generators}")] end @@ -136,7 +135,7 @@ module Rails def self.load_paths @load_paths ||= begin paths = [] - paths += Dir[File.join(Rails.root, "lib", "{generators,rails_generators}")] if Rails.root + paths += Dir[File.join(Rails.root, "lib", "{generators,rails_generators}")] if defined?(Rails.root) paths += Dir[File.join(Thor::Util.user_home, ".rails", "{generators,rails_generators}")] paths += self.plugins_generators_paths paths += self.gems_generators_paths -- cgit v1.2.3 From a176263ebc53682133ccb6d5c8ad5705c7058f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 28 Dec 2009 00:17:14 +0100 Subject: Fix generators tests. Signed-off-by: Jeremy Kemper --- railties/lib/rails/generators.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 16b28dd295..2ba56bc3c5 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -5,6 +5,7 @@ require 'active_support' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/metaclass' require 'active_support/core_ext/array/extract_options' +require 'active_support/core_ext/hash/deep_merge' require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/string/inflections' @@ -94,7 +95,7 @@ module Rails end def self.plugins_generators_paths #:nodoc: - return [] unless defined?(Rails.root) + return [] unless defined?(Rails.root) && Rails.root Dir[File.join(Rails.root, "vendor", "plugins", "*", "lib", "{generators,rails_generators}")] end @@ -135,7 +136,7 @@ module Rails def self.load_paths @load_paths ||= begin paths = [] - paths += Dir[File.join(Rails.root, "lib", "{generators,rails_generators}")] if defined?(Rails.root) + paths += Dir[File.join(Rails.root, "lib", "{generators,rails_generators}")] if defined?(Rails.root) && Rails.root paths += Dir[File.join(Thor::Util.user_home, ".rails", "{generators,rails_generators}")] paths += self.plugins_generators_paths paths += self.gems_generators_paths -- cgit v1.2.3 From a642edbef31fe96fad488accf0052653c573e8db Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 27 Dec 2009 17:48:11 -0800 Subject: Added default .gitignore (this is just recognizing Git market share, don't throw a hissy if you use another SCM) [DHH] --- railties/lib/rails/generators/rails/app/app_generator.rb | 1 + railties/lib/rails/generators/rails/app/templates/gitignore | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 railties/lib/rails/generators/rails/app/templates/gitignore (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 30272ed9b2..ef5399e48f 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -49,6 +49,7 @@ module Rails::Generators def create_root_files copy_file "README" + copy_file "gitignore", ".gitignore" template "Rakefile" template "config.ru" template "Gemfile" diff --git a/railties/lib/rails/generators/rails/app/templates/gitignore b/railties/lib/rails/generators/rails/app/templates/gitignore new file mode 100644 index 0000000000..a4f05d101d --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/gitignore @@ -0,0 +1,3 @@ +db/*.sqlite3 +log/*.log +tmp/**/* -- cgit v1.2.3 From c02f2782631a1893e2e880e3ccc65fb9a734567a Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Mon, 28 Dec 2009 16:21:48 -0800 Subject: Add the ability to have plugins load rake tasks. --- railties/lib/rails/application.rb | 5 +++++ railties/lib/rails/plugin.rb | 10 ++++++++++ 2 files changed, 15 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index cd579a1c0d..4c1f36f537 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -72,7 +72,12 @@ module Rails def load_tasks require "rails/tasks" + # Load all extension rake tasks + plugins.each(&:load_tasks) + # Load all plugin tasks Dir["#{root}/vendor/plugins/*/**/tasks/**/*.rake"].sort.each { |ext| load ext } + # Load all application tasks + # TODO: extract out the path to the rake tasks Dir["#{root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } task :environment do $rails_rake_task = true diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index aa325c6f76..be6cdec3fa 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -25,6 +25,16 @@ module Rails Configuration.default end + def self.rake_tasks(&blk) + @rake_tasks ||= [] + @rake_tasks << blk + end + + def self.load_tasks + return unless @rake_tasks + @rake_tasks.each { |blk| blk.call } + end + # Creates an initializer which includes all given modules to the given class. # # module Rails -- cgit v1.2.3 From 49c800b6bdf10af4e3f07eee33c4e6d23e7a946d Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Mon, 28 Dec 2009 17:37:18 -0800 Subject: Move the ActiveRecord related rake tasks into the AR gem. --- railties/lib/rails/tasks.rb | 1 - railties/lib/rails/tasks/databases.rake | 469 -------------------------------- 2 files changed, 470 deletions(-) delete mode 100644 railties/lib/rails/tasks/databases.rake (limited to 'railties/lib') diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index dc886f4a4d..44c014efe8 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -3,7 +3,6 @@ $VERBOSE = nil # Load Rails rakefile extensions %w( annotations - databases documentation framework log diff --git a/railties/lib/rails/tasks/databases.rake b/railties/lib/rails/tasks/databases.rake deleted file mode 100644 index a35a6c156b..0000000000 --- a/railties/lib/rails/tasks/databases.rake +++ /dev/null @@ -1,469 +0,0 @@ -namespace :db do - task :load_config => :rails_env do - require 'active_record' - ActiveRecord::Base.configurations = Rails::Configuration.new.database_configuration - end - - namespace :create do - desc 'Create all the local databases defined in config/database.yml' - task :all => :load_config do - ActiveRecord::Base.configurations.each_value do |config| - # Skip entries that don't have a database key, such as the first entry here: - # - # defaults: &defaults - # adapter: mysql - # username: root - # password: - # host: localhost - # - # development: - # database: blog_development - # <<: *defaults - next unless config['database'] - # Only connect to local databases - local_database?(config) { create_database(config) } - end - end - end - - desc 'Create the database defined in config/database.yml for the current RAILS_ENV' - task :create => :load_config do - create_database(ActiveRecord::Base.configurations[RAILS_ENV]) - end - - def create_database(config) - begin - if config['adapter'] =~ /sqlite/ - if File.exist?(config['database']) - $stderr.puts "#{config['database']} already exists" - else - begin - # Create the SQLite database - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection - rescue - $stderr.puts $!, *($!.backtrace) - $stderr.puts "Couldn't create database for #{config.inspect}" - end - end - return # Skip the else clause of begin/rescue - else - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection - end - rescue - case config['adapter'] - when 'mysql' - @charset = ENV['CHARSET'] || 'utf8' - @collation = ENV['COLLATION'] || 'utf8_unicode_ci' - creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)} - begin - ActiveRecord::Base.establish_connection(config.merge('database' => nil)) - ActiveRecord::Base.connection.create_database(config['database'], creation_options) - ActiveRecord::Base.establish_connection(config) - rescue Mysql::Error => sqlerr - if sqlerr.errno == Mysql::Error::ER_ACCESS_DENIED_ERROR - print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>" - root_password = $stdin.gets.strip - grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \ - "TO '#{config['username']}'@'localhost' " \ - "IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;" - ActiveRecord::Base.establish_connection(config.merge( - 'database' => nil, 'username' => 'root', 'password' => root_password)) - ActiveRecord::Base.connection.create_database(config['database'], creation_options) - ActiveRecord::Base.connection.execute grant_statement - ActiveRecord::Base.establish_connection(config) - else - $stderr.puts sqlerr.error - $stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}" - $stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset'] - end - end - when 'postgresql' - @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8' - begin - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding)) - ActiveRecord::Base.establish_connection(config) - rescue - $stderr.puts $!, *($!.backtrace) - $stderr.puts "Couldn't create database for #{config.inspect}" - end - end - else - $stderr.puts "#{config['database']} already exists" - end - end - - namespace :drop do - desc 'Drops all the local databases defined in config/database.yml' - task :all => :load_config do - ActiveRecord::Base.configurations.each_value do |config| - # Skip entries that don't have a database key - next unless config['database'] - begin - # Only connect to local databases - local_database?(config) { drop_database(config) } - rescue Exception => e - puts "Couldn't drop #{config['database']} : #{e.inspect}" - end - end - end - end - - desc 'Drops the database for the current RAILS_ENV' - task :drop => :load_config do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - begin - drop_database(config) - rescue Exception => e - puts "Couldn't drop #{config['database']} : #{e.inspect}" - end - end - - def local_database?(config, &block) - if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank? - yield - else - puts "This task only modifies local databases. #{config['database']} is on a remote host." - end - end - - - desc "Migrate the database through scripts in db/migrate and update db/schema.rb by invoking db:schema:dump. Target specific version with VERSION=x. Turn off output with VERBOSE=false." - task :migrate => :environment do - ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true - ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - namespace :migrate do - desc 'Rollbacks the database one migration and re migrate up. If you want to rollback more than one step, define STEP=x. Target specific version with VERSION=x.' - task :redo => :environment do - if ENV["VERSION"] - Rake::Task["db:migrate:down"].invoke - Rake::Task["db:migrate:up"].invoke - else - Rake::Task["db:rollback"].invoke - Rake::Task["db:migrate"].invoke - end - end - - desc 'Resets your database using your migrations for the current environment' - task :reset => ["db:drop", "db:create", "db:migrate"] - - desc 'Runs the "up" for a given migration VERSION.' - task :up => :environment do - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:up, "db/migrate/", version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - desc 'Runs the "down" for a given migration VERSION.' - task :down => :environment do - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:down, "db/migrate/", version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - end - - desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n' - task :rollback => :environment do - step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.rollback('db/migrate/', step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - desc 'Pushes the schema to the next version. Specify the number of steps with STEP=n' - task :forward => :environment do - step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.forward('db/migrate/', step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.' - task :reset => [ 'db:drop', 'db:setup' ] - - desc "Retrieves the charset for the current environment's database" - task :charset => :environment do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.charset - when 'postgresql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.encoding - else - puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' - end - end - - desc "Retrieves the collation for the current environment's database" - task :collation => :environment do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.collation - else - puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' - end - end - - desc "Retrieves the current schema version number" - task :version => :environment do - puts "Current version: #{ActiveRecord::Migrator.current_version}" - end - - desc "Raises an error if there are pending migrations" - task :abort_if_pending_migrations => :environment do - if defined? ActiveRecord - pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations - - if pending_migrations.any? - puts "You have #{pending_migrations.size} pending migrations:" - pending_migrations.each do |pending_migration| - puts ' %4d %s' % [pending_migration.version, pending_migration.name] - end - abort %{Run "rake db:migrate" to update your database then try again.} - end - end - end - - desc 'Create the database, load the schema, and initialize with the seed data' - task :setup => [ 'db:create', 'db:schema:load', 'db:seed' ] - - desc 'Load the seed data from db/seeds.rb' - task :seed => :environment do - seed_file = File.join(Rails.root, 'db', 'seeds.rb') - load(seed_file) if File.exist?(seed_file) - end - - namespace :fixtures do - desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures." - task :load => :environment do - require 'active_record/fixtures' - ActiveRecord::Base.establish_connection(Rails.env) - base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') - fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir - - (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file| - Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*')) - end - end - - desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures." - task :identify => :environment do - require "active_record/fixtures" - - label, id = ENV["LABEL"], ENV["ID"] - raise "LABEL or ID required" if label.blank? && id.blank? - - puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label - - base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') - Dir["#{base_dir}/**/*.yml"].each do |file| - if data = YAML::load(ERB.new(IO.read(file)).result) - data.keys.each do |key| - key_id = Fixtures.identify(key) - - if key == label || key_id == id.to_i - puts "#{file}: #{key} (#{key_id})" - end - end - end - end - end - end - - namespace :schema do - desc "Create a db/schema.rb file that can be portably used against any DB supported by AR" - task :dump => :environment do - require 'active_record/schema_dumper' - File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", "w") do |file| - ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) - end - Rake::Task["db:schema:dump"].reenable - end - - desc "Load a schema.rb file into the database" - task :load => :environment do - file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb" - if File.exists?(file) - load(file) - else - abort %{#{file} doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to prevent active_record from loading: config.frameworks -= [ :active_record ]} - end - end - end - - namespace :structure do - desc "Dump the database structure to a SQL file" - task :dump => :environment do - abcs = ActiveRecord::Base.configurations - case abcs[RAILS_ENV]["adapter"] - when "mysql", "oci", "oracle" - ActiveRecord::Base.establish_connection(abcs[RAILS_ENV]) - File.open("#{Rails.root}/db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump } - when "postgresql" - ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"] - ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"] - ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"] - search_path = abcs[RAILS_ENV]["schema_search_path"] - unless search_path.blank? - search_path = search_path.split(",").map{|search_path| "--schema=#{search_path.strip}" }.join(" ") - end - `pg_dump -i -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{search_path} #{abcs[RAILS_ENV]["database"]}` - raise "Error dumping database" if $?.exitstatus == 1 - when "sqlite", "sqlite3" - dbfile = abcs[RAILS_ENV]["database"] || abcs[RAILS_ENV]["dbfile"] - `#{abcs[RAILS_ENV]["adapter"]} #{dbfile} .schema > db/#{RAILS_ENV}_structure.sql` - when "sqlserver" - `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r` - `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r` - when "firebird" - set_firebird_env(abcs[RAILS_ENV]) - db_string = firebird_db_string(abcs[RAILS_ENV]) - sh "isql -a #{db_string} > #{Rails.root}/db/#{RAILS_ENV}_structure.sql" - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - - if ActiveRecord::Base.connection.supports_migrations? - File.open("#{Rails.root}/db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information } - end - end - end - - namespace :test do - desc "Recreate the test database from the current schema.rb" - task :load => 'db:test:purge' do - ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) - ActiveRecord::Schema.verbose = false - Rake::Task["db:schema:load"].invoke - end - - desc "Recreate the test database from the current environment's database schema" - task :clone => %w(db:schema:dump db:test:load) - - desc "Recreate the test databases from the development structure" - task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do - abcs = ActiveRecord::Base.configurations - case abcs["test"]["adapter"] - when "mysql" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') - IO.readlines("#{Rails.root}/db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table| - ActiveRecord::Base.connection.execute(table) - end - when "postgresql" - ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"] - ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"] - ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"] - `psql -U "#{abcs["test"]["username"]}" -f #{Rails.root}/db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}` - when "sqlite", "sqlite3" - dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] - `#{abcs["test"]["adapter"]} #{dbfile} < #{Rails.root}/db/#{RAILS_ENV}_structure.sql` - when "sqlserver" - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` - when "oci", "oracle" - ActiveRecord::Base.establish_connection(:test) - IO.readlines("#{Rails.root}/db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl| - ActiveRecord::Base.connection.execute(ddl) - end - when "firebird" - set_firebird_env(abcs["test"]) - db_string = firebird_db_string(abcs["test"]) - sh "isql -i #{Rails.root}/db/#{RAILS_ENV}_structure.sql #{db_string}" - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - end - - desc "Empty the test database" - task :purge => :environment do - abcs = ActiveRecord::Base.configurations - case abcs["test"]["adapter"] - when "mysql" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"], abcs["test"]) - when "postgresql" - ActiveRecord::Base.clear_active_connections! - drop_database(abcs['test']) - create_database(abcs['test']) - when "sqlite","sqlite3" - dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] - File.delete(dbfile) if File.exist?(dbfile) - when "sqlserver" - dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-') - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}` - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` - when "oci", "oracle" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl| - ActiveRecord::Base.connection.execute(ddl) - end - when "firebird" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.recreate_database! - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - end - - desc 'Check for pending migrations and load the test schema' - task :prepare => 'db:abort_if_pending_migrations' do - if defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank? - Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:load" }[ActiveRecord::Base.schema_format]].invoke - end - end - end - - namespace :sessions do - desc "Creates a sessions migration for use with ActiveRecord::SessionStore" - task :create => :environment do - raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations? - require 'rails/generators' - require 'rails/generators/rails/session_migration/session_migration_generator' - Rails::Generators::SessionMigrationGenerator.start [ ENV["MIGRATION"] || "add_sessions_table" ] - end - - desc "Clear the sessions table" - task :clear => :environment do - ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}" - end - end -end - -def drop_database(config) - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection.drop_database config['database'] - when /^sqlite/ - require 'pathname' - path = Pathname.new(config['database']) - file = path.absolute? ? path.to_s : File.join(Rails.root, path) - - FileUtils.rm(file) - when 'postgresql' - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.drop_database config['database'] - end -end - -def session_table_name - ActiveRecord::SessionStore::Session.table_name -end - -def set_firebird_env(config) - ENV["ISC_USER"] = config["username"].to_s if config["username"] - ENV["ISC_PASSWORD"] = config["password"].to_s if config["password"] -end - -def firebird_db_string(config) - FireRuby::Database.db_string_for(config.symbolize_keys) -end -- cgit v1.2.3 From 4ee70643b3c352a582069267ddb02186da8a86f7 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Mon, 28 Dec 2009 17:45:17 -0800 Subject: Don't require initializer.rb in core.rb --- railties/lib/rails/core.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/core.rb b/railties/lib/rails/core.rb index da16c5816c..c819e90dd7 100644 --- a/railties/lib/rails/core.rb +++ b/railties/lib/rails/core.rb @@ -15,7 +15,6 @@ require 'rails/paths' require 'rails/core' require 'rails/configuration' require 'rails/deprecation' -require 'rails/initializer' require 'rails/ruby_version_check' # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the -- cgit v1.2.3 From aa1b32ae9774e3f2a95faa0ec9efdf295958106d Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 29 Dec 2009 10:49:01 -0800 Subject: Check to see if the plugin object responds to load_tasks (vendor/plugin/* does not yet) Fixes Sam Ruby's tests. --- railties/lib/rails/application.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 4c1f36f537..2d0892282e 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -73,7 +73,10 @@ module Rails def load_tasks require "rails/tasks" # Load all extension rake tasks - plugins.each(&:load_tasks) + # TODO: Make all plugin objects respond to :load_tasks + plugins.each do |plugin| + plugin.load_tasks if plugin.respond_to? :load_tasks + end # Load all plugin tasks Dir["#{root}/vendor/plugins/*/**/tasks/**/*.rake"].sort.each { |ext| load ext } # Load all application tasks -- cgit v1.2.3 From 3cb7e047637e57349ed9e4c81d4f7b3157045661 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 29 Dec 2009 13:20:10 -0800 Subject: Finally remove rails/initializer.rb --- railties/lib/rails/initializer.rb | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 railties/lib/rails/initializer.rb (limited to 'railties/lib') diff --git a/railties/lib/rails/initializer.rb b/railties/lib/rails/initializer.rb deleted file mode 100644 index 95478428ec..0000000000 --- a/railties/lib/rails/initializer.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "rails" # In case people require this file directly - -module Rails - class Initializer - class Error < StandardError ; end - def self.run(initializer = nil, config = nil) - if initializer - # Deprecated - else - Rails.application = Class.new(Application) - yield Rails.application.config if block_given? - end - end - end -end -- cgit v1.2.3 From cbce027669ded4e951af3124cae23d6707357aea Mon Sep 17 00:00:00 2001 From: Sam Pohlenz Date: Sun, 27 Dec 2009 11:16:34 +1030 Subject: Application object should instantiate non-vendored plugins Signed-off-by: Carl Lerche --- railties/lib/rails/application.rb | 2 +- railties/lib/rails/plugin.rb | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 2d0892282e..91c866d0c9 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -98,7 +98,7 @@ module Rails def plugins @plugins ||= begin plugin_names = config.plugins || [:all] - Plugin.plugins.select { |p| plugin_names.include?(:all) || plugin_names.include?(p.plugin_name) } + + Plugin.plugins.select { |p| plugin_names.include?(:all) || plugin_names.include?(p.plugin_name) }.map { |p| p.new } + Plugin::Vendored.all(config.plugins || [:all], config.paths.vendor.plugins) end end diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index be6cdec3fa..b5e6953fef 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -27,12 +27,17 @@ module Rails def self.rake_tasks(&blk) @rake_tasks ||= [] - @rake_tasks << blk + @rake_tasks << blk if blk + @rake_tasks end - def self.load_tasks - return unless @rake_tasks - @rake_tasks.each { |blk| blk.call } + def rake_tasks + self.class.rake_tasks + end + + def load_tasks + return unless rake_tasks + rake_tasks.each { |blk| blk.call } end # Creates an initializer which includes all given modules to the given class. -- cgit v1.2.3 From 468bdb3ed8ee20fe4215e62f0f27513c70e2398c Mon Sep 17 00:00:00 2001 From: Sam Pohlenz Date: Mon, 28 Dec 2009 08:48:07 +1030 Subject: Make plugins responsible for loading their own rake tasks Signed-off-by: Carl Lerche --- railties/lib/rails/application.rb | 8 +------- railties/lib/rails/plugin.rb | 4 ++++ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 91c866d0c9..d714c5ac41 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -72,13 +72,7 @@ module Rails def load_tasks require "rails/tasks" - # Load all extension rake tasks - # TODO: Make all plugin objects respond to :load_tasks - plugins.each do |plugin| - plugin.load_tasks if plugin.respond_to? :load_tasks - end - # Load all plugin tasks - Dir["#{root}/vendor/plugins/*/**/tasks/**/*.rake"].sort.each { |ext| load ext } + plugins.each { |p| p.load_tasks } # Load all application tasks # TODO: extract out the path to the rake tasks Dir["#{root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index b5e6953fef..c64042cf7d 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -85,6 +85,10 @@ module Rails Dir["#{path}/{lib}", "#{path}/app/{models,controllers,helpers}"] end + def load_tasks + Dir["#{path}/**/tasks/**/*.rake"].sort.each { |ext| load ext } + end + initializer :add_to_load_path, :after => :set_autoload_paths do |app| load_paths.each do |path| $LOAD_PATH << path -- cgit v1.2.3 From 66604b2e0e8d3aba25cab673c7a3d7831a68490c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 29 Dec 2009 10:40:42 +0100 Subject: Add default respond_to formats to ApplicationController. --- .../rails/app/templates/app/controllers/application_controller.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb index 9889b52893..95b6a0af6d 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb +++ b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb @@ -4,5 +4,6 @@ class ApplicationController < ActionController::Base helper :all protect_from_forgery + respond_to :html, :js, :xml, :json filter_parameter_logging :password end -- cgit v1.2.3 From 1a4d909c6845c091a04e2533ab89502de4130c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 29 Dec 2009 11:52:06 +0100 Subject: Add rails app --edge and rails app --dev --- .../rails/generators/rails/app/app_generator.rb | 24 ++++++++++++++++------ .../rails/generators/rails/app/templates/Gemfile | 9 ++++++-- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index ef5399e48f..22a27fdac2 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -3,6 +3,10 @@ require 'active_support/secure_random' require 'rails/version' unless defined?(Rails::VERSION) module Rails::Generators + # We need to store the RAILS_DEV_PATH in a constant, otherwise the path + # can change in Ruby 1.8.7 when we FileUtils.cd. + RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__)) + class AppGenerator < Base DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) add_shebang_option! @@ -15,17 +19,22 @@ module Rails::Generators class_option :template, :type => :string, :aliases => "-m", :desc => "Path to an application template (can be a filesystem path or URL)." + class_option :dev, :type => :boolean, :default => false, + :desc => "Setup the application with Gemfile pointing to your Rails checkout" + + class_option :edge, :type => :boolean, :default => false, + :desc => "Setup the application with Gemfile pointing to Rails repository" + class_option :skip_activerecord, :type => :boolean, :aliases => "-O", :default => false, - :desc => "Skip ActiveRecord files" + :desc => "Skip ActiveRecord files" class_option :skip_testunit, :type => :boolean, :aliases => "-T", :default => false, - :desc => "Skip TestUnit files" + :desc => "Skip TestUnit files" class_option :skip_prototype, :type => :boolean, :aliases => "-J", :default => false, - :desc => "Skip Prototype files" + :desc => "Skip Prototype files" - # Add Rails options - # + # Add bin/rails options class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, :desc => "Show Rails version number and quit" @@ -173,7 +182,6 @@ module Rails::Generators end # Define file as an alias to create_file for backwards compatibility. - # def file(*args, &block) create_file(*args, &block) end @@ -190,6 +198,10 @@ module Rails::Generators ActiveSupport::SecureRandom.hex(64) end + def dev_or_edge? + options.dev? || options.edge? + end + def self.banner "#{$0} #{self.arguments.map(&:usage).join(' ')} [options]" end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 8e851a64e7..59c6d333e2 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -1,9 +1,14 @@ # Edit this Gemfile to bundle your application's dependencies. - +<% if !dev_or_edge? %> gem "rails", "<%= Rails::VERSION::STRING %>" +<% end -%> ## Bundle edge rails: -# gem "rails", :git => "git://github.com/rails/rails.git" +<%- if options.dev? -%> +gem "rails", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" +<%- else -%> +<%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" +<%- end -%> ## Bundle the gems you use: # gem "bj" -- cgit v1.2.3 From e5c88434dbb7dc0690a474ae7c913453bf289328 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Tue, 29 Dec 2009 19:04:14 -0800 Subject: Use the correct method for eager loading autoloads --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index d714c5ac41..5419b46f19 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -143,7 +143,7 @@ module Rails # Used by Passenger to ensure everything's loaded before forking and # to avoid autoload race conditions in JRuby. initializer :preload_frameworks do - ActiveSupport::Autoload.eager_load! if config.preload_frameworks + ActiveSupport::Autoload.eager_autoload! if config.preload_frameworks end initializer :initialize_cache do -- cgit v1.2.3 From 79550e8995e97bd0278bfe5c05151ac94495e9b1 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 29 Dec 2009 19:10:26 -0800 Subject: Revert "Add default respond_to formats to ApplicationController." (Needs consensus that these are appropriate defaults.) This reverts commit 66604b2e0e8d3aba25cab673c7a3d7831a68490c. --- .../rails/app/templates/app/controllers/application_controller.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb index 95b6a0af6d..9889b52893 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb +++ b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb @@ -4,6 +4,5 @@ class ApplicationController < ActionController::Base helper :all protect_from_forgery - respond_to :html, :js, :xml, :json filter_parameter_logging :password end -- cgit v1.2.3 From d349b22097e6b50a9593ba5ba4c028070688342a Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 19:00:12 -0800 Subject: Remove self-require --- railties/lib/rails/core.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/core.rb b/railties/lib/rails/core.rb index c819e90dd7..ab95edc676 100644 --- a/railties/lib/rails/core.rb +++ b/railties/lib/rails/core.rb @@ -12,7 +12,6 @@ require 'rails/railties_path' require 'rails/version' require 'rails/rack' require 'rails/paths' -require 'rails/core' require 'rails/configuration' require 'rails/deprecation' require 'rails/ruby_version_check' @@ -103,4 +102,4 @@ module Rails @@public_path = path end end -end \ No newline at end of file +end -- cgit v1.2.3 From 1fbd02e44618f1f56e1d9d0af85c6a4108a66532 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 19:33:32 -0800 Subject: Revert "Add config.action_controller.include behavior to plugins." This reverts commit 7e8b7f46bfc086a36db996420fbee93348c5268e. Conflicts: railties/lib/rails/plugin.rb --- railties/lib/rails/configuration.rb | 20 +------------------- railties/lib/rails/plugin.rb | 20 +------------------- 2 files changed, 2 insertions(+), 38 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index cb321536d2..086f67a419 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,24 +1,6 @@ require 'active_support/ordered_options' module Rails - # Create a Plugin::Options from ActiveSuppot::OrderedOptions, - # which support the following syntax: - # - # controller.action_controller.include FooBar - # - class Plugin::Options < ActiveSupport::OrderedOptions #:nodoc: - attr_reader :includes - - def initialize(*args) - @includes = [] - super - end - - def include(*args) - @includes.concat(args) - end - end - # Temporarily separate the plugin configuration class from the main # configuration class while this bit is being cleaned up. class Plugin::Configuration @@ -34,7 +16,7 @@ module Rails @options = base.options.dup @middleware = base.middleware.dup else - @options = Hash.new { |h,k| h[k] = Rails::Plugin::Options.new } + @options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } @middleware = ActionDispatch::MiddlewareStack.new end end diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index c64042cf7d..e154e9b706 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -40,24 +40,6 @@ module Rails rake_tasks.each { |blk| blk.call } end - # Creates an initializer which includes all given modules to the given class. - # - # module Rails - # class ActionController < Rails::Plugin - # plugin_name :action_controller - # include_modules_in "ActionController::Base" - # end - # end - # - def self.include_modules_in(klass, from=plugin_name) - self.initializer :"#{from}.include_modules" do |app| - klass = klass.constantize if klass.is_a?(String) - app.config.send(from).includes.each do |mod| - klass.send(:include, mod.is_a?(String) ? mod.constantize : mod) - end - end - end - class Vendored < Plugin def self.all(list, paths) plugins = [] @@ -121,4 +103,4 @@ module Rails end end end -end \ No newline at end of file +end -- cgit v1.2.3 From 5eb3ceca01d532e5303b4283c691adb953576ff4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 30 Dec 2009 22:55:52 -0500 Subject: Orphan experiment no longer needed --- railties/lib/rails/commands/ncgi/tracker | 69 -------------------------------- 1 file changed, 69 deletions(-) delete mode 100755 railties/lib/rails/commands/ncgi/tracker (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/ncgi/tracker b/railties/lib/rails/commands/ncgi/tracker deleted file mode 100755 index 4ca12d779b..0000000000 --- a/railties/lib/rails/commands/ncgi/tracker +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env ruby - -require 'drb' -require 'thread' - -def message(s) - $stderr.puts "tracker: #{s}" if ENV && ENV["DEBUG_GATEWAY"] -end - -class Tracker - include DRbUndumped - - def initialize(instances, socket_path) - @instances = instances - @socket = File.expand_path(socket_path) - @active = false - - @listeners = [] - @instances.times { @listeners << Mutex.new } - - message "using #{@listeners.length} listeners" - message "opening socket at #{@socket}" - - @service = DRb.start_service("drbunix://#{@socket}", self) - end - - def with_listener - message "listener requested" - - mutex = has_lock = index = nil - 3.times do - @listeners.each_with_index do |mutex, index| - has_lock = mutex.try_lock - break if has_lock - end - break if has_lock - sleep 0.05 - end - - if has_lock - message "obtained listener #{index}" - @active = true - begin yield index - ensure - mutex.unlock - message "released listener #{index}" - end - else - message "dropping request because no listeners are available!" - end - end - - def background(check_interval = nil) - if check_interval - loop do - sleep check_interval - message "Idle for #{check_interval}, shutting down" unless @active - @active = false - Kernel.exit 0 - end - else DRb.thread.join - end - end -end - -socket_path = ARGV.shift -instances = ARGV.shift.to_i -t = Tracker.new(instances, socket_path) -t.background(ARGV.first ? ARGV.shift.to_i : 90) -- cgit v1.2.3 From 5d8342cc325bc9f46bfe61bf3534248b6ad3216f Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 31 Dec 2009 01:14:23 -0500 Subject: Added .gitkeep to empty directories and --skip-git to skip gitignore/gitkeep files --- .../lib/rails/generators/rails/app/app_generator.rb | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 22a27fdac2..c03836ed91 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -34,6 +34,9 @@ module Rails::Generators class_option :skip_prototype, :type => :boolean, :aliases => "-J", :default => false, :desc => "Skip Prototype files" + class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, + :desc => "Skip Git ignores and keeps" + # Add bin/rails options class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, :desc => "Show Rails version number and quit" @@ -58,7 +61,7 @@ module Rails::Generators def create_root_files copy_file "README" - copy_file "gitignore", ".gitignore" + copy_file "gitignore", ".gitignore" unless options[:skip_git] template "Rakefile" template "config.ru" template "Gemfile" @@ -101,7 +104,7 @@ module Rails::Generators def create_lib_files empty_directory "lib" - empty_directory "lib/tasks" + empty_directory_with_gitkeep "lib/tasks" end def create_log_files @@ -124,7 +127,7 @@ module Rails::Generators end def create_public_stylesheets_files - directory "public/stylesheets" + empty_directory_with_gitkeep "public/stylesheets" end def create_prototype_files @@ -149,13 +152,13 @@ module Rails::Generators inside "tmp" do %w(sessions sockets cache pids).each do |dir| - empty_directory dir + empty_directory_with_gitkeep(dir) end end end def create_vendor_files - empty_directory "vendor/plugins" + empty_directory_with_gitkeep "vendor/plugins" end def apply_rails_template @@ -165,7 +168,6 @@ module Rails::Generators end protected - attr_accessor :rails_template def set_default_accessors! @@ -219,5 +221,10 @@ module Rails::Generators "/opt/lampp/var/mysql/mysql.sock" # xampp for linux ].find { |f| File.exist?(f) } unless RUBY_PLATFORM =~ /(:?mswin|mingw)/ end + + def empty_directory_with_gitkeep(destination, config = {}) + empty_directory(destination, config) + create_file("#{destination}/.gitkeep") unless options[:skip_git] + end end end -- cgit v1.2.3 From ea41a757aab86206278b99deb86e93a760833819 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 31 Dec 2009 11:09:10 -0500 Subject: Dont gitkeep things that are gitignored --- railties/lib/rails/generators/rails/app/app_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index c03836ed91..ee401b1fde 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -152,7 +152,7 @@ module Rails::Generators inside "tmp" do %w(sessions sockets cache pids).each do |dir| - empty_directory_with_gitkeep(dir) + empty_directory(dir) end end end -- cgit v1.2.3 From 1e41097294b6f966f65909db5c56c9fc21b665f7 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 31 Dec 2009 10:36:24 -0800 Subject: Fully remove config.frameworks in favor of requires in boot.rb --- railties/lib/rails/application.rb | 4 +++- railties/lib/rails/configuration.rb | 21 +-------------------- .../rails/app/templates/config/application.rb | 8 -------- .../generators/rails/app/templates/config/boot.rb | 9 +++++++++ 4 files changed, 13 insertions(+), 29 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 5419b46f19..88f10727c5 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -273,7 +273,9 @@ module Rails # For each framework, search for instrument file with Notifications hooks. # initializer :load_notifications_hooks do - config.frameworks.each do |framework| + frameworks = [ :active_record, :action_controller, :action_view, + :action_mailer, :active_resource ] + frameworks.each do |framework| begin require "#{framework}/notifications" rescue LoadError => e diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 086f67a419..12bf076f61 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -59,7 +59,7 @@ module Rails attr_writer :cache_store, :controller_paths, :database_configuration_file, :eager_load_paths, - :frameworks, :framework_root_path, :i18n, :load_paths, + :i18n, :load_paths, :log_level, :log_path, :paths, :routes_configuration_file, :view_path @@ -134,21 +134,6 @@ module Rails self end - def framework_paths - paths = %w(railties railties/lib activesupport/lib) - paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) - - [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework| - paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework) - end - - paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } - end - - def framework_root_path - defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root}/vendor/rails" - end - # Loads and returns the contents of the #database_configuration_file. The # contents of the file are processed via ERB before being sent through # YAML::load. @@ -239,10 +224,6 @@ module Rails @log_level ||= RAILS_ENV == 'production' ? :info : :debug end - def frameworks - @frameworks ||= [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] - end - def i18n @i18n ||= begin i18n = ActiveSupport::OrderedOptions.new diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 15dc553e53..ec0729db04 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -13,16 +13,8 @@ module <%= app_name.classify %> # :all can be used as a placeholder for all plugins not explicitly named # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - # Skip frameworks you're not going to use. To use Rails without a database, - # you must remove the Active Record framework. -<% if options[:skip_activerecord] -%> - config.frameworks -= [ :active_record ] -<% else -%> - # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] - # Activate observers that should always be running # config.active_record.observers = :cacher, :garbage_collector, :forum_observer -<% end -%> # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. diff --git a/railties/lib/rails/generators/rails/app/templates/config/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb index 5aa49ca5e6..221421855c 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb @@ -14,3 +14,12 @@ else end require 'rails' +# To skip frameworks you're not going to use, remove require "rails" and +# list the frameworks that you are going to use. +# +# require "active_model/rails" +# require "active_record/rails" +# require "action_controller/rails" +# require "action_view/rails" +# require "action_mailer/rails" +# require "active_resource/rails" \ No newline at end of file -- cgit v1.2.3 From a23f4b6aeed6b49f90f5c544c818798840f090b7 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 31 Dec 2009 11:46:56 -0800 Subject: Add a /rails.rb for each framework for consistency --- railties/lib/rails.rb | 10 ++++++++-- .../lib/rails/generators/rails/app/templates/config/boot.rb | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index 9fb3cd9f94..68b451d813 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -1,8 +1,14 @@ require "rails/core" -%w(active_model active_record action_controller action_view action_mailer active_resource).each do |framework| +%w( + active_model + active_record + action_controller + action_view + action_mailer + active_resource +).each do |framework| begin - require framework require "#{framework}/rails" rescue LoadError end diff --git a/railties/lib/rails/generators/rails/app/templates/config/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb index 221421855c..e4ecd2dcde 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb @@ -14,9 +14,11 @@ else end require 'rails' -# To skip frameworks you're not going to use, remove require "rails" and -# list the frameworks that you are going to use. +# To skip frameworks you're not going to use, change require "rails" +# to require "rails/core" and list the frameworks that you are going +# to use. # +# require "rails/core" # require "active_model/rails" # require "active_record/rails" # require "action_controller/rails" -- cgit v1.2.3 From 2f8643955a780f0c2fe46d0ae68db8d51b76fbbf Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 31 Dec 2009 11:57:48 -0800 Subject: Raise a helpful error if config.frameworks is used --- railties/lib/rails/configuration.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 12bf076f61..adb11e8257 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -119,6 +119,13 @@ module Rails end end + def frameworks(*args) + raise "config.frameworks in no longer supported. See the generated" \ + "config/boot.rb for steps on how to limit the frameworks that" \ + "will be loaded" + end + alias frameworks= frameworks + # Enable threaded mode. Allows concurrent requests to controller actions and # multiple database connections. Also disables automatic dependency loading # after boot, and disables reloading code on every request, as these are -- cgit v1.2.3 From e749424dfa38a0300a621b772eae96f9cc5d2555 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 31 Dec 2009 12:28:48 -0800 Subject: Rename rails.rb -> rails/all.rb and rails/core.rb -> rails.rb --- railties/lib/rails.rb | 118 ++++++++++++++++++--- railties/lib/rails/all.rb | 15 +++ railties/lib/rails/core.rb | 105 ------------------ .../generators/rails/app/templates/config/boot.rb | 9 +- 4 files changed, 123 insertions(+), 124 deletions(-) create mode 100644 railties/lib/rails/all.rb delete mode 100644 railties/lib/rails/core.rb (limited to 'railties/lib') diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index 68b451d813..ab95edc676 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -1,15 +1,105 @@ -require "rails/core" - -%w( - active_model - active_record - action_controller - action_view - action_mailer - active_resource -).each do |framework| - begin - require "#{framework}/rails" - rescue LoadError +require "pathname" + +require 'active_support' +require 'active_support/core_ext/kernel/reporting' +require 'active_support/core_ext/logger' +require 'action_dispatch' + +require 'rails/initializable' +require 'rails/application' +require 'rails/plugin' +require 'rails/railties_path' +require 'rails/version' +require 'rails/rack' +require 'rails/paths' +require 'rails/configuration' +require 'rails/deprecation' +require 'rails/ruby_version_check' + +# For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the +# multibyte safe operations. Plugin authors supporting other encodings +# should override this behaviour and set the relevant +default_charset+ +# on ActionController::Base. +# +# For Ruby 1.9, UTF-8 is the default internal and external encoding. +if RUBY_VERSION < '1.9' + $KCODE='u' +else + Encoding.default_external = Encoding::UTF_8 +end + +RAILS_ENV = (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup unless defined?(RAILS_ENV) + +module Rails + # Needs to be duplicated from Active Support since its needed before Active + # Support is available. Here both Options and Hash are namespaced to prevent + # conflicts with other implementations AND with the classes residing in Active Support. + # --- + # TODO: w0t? + class << self + def application + @@application ||= nil + end + + def application=(application) + @@application = application + end + + # The Configuration instance used to configure the Rails environment + def configuration + application.configuration + end + + def initialize! + application.initialize! + end + + def initialized? + @initialized || false + end + + def initialized=(initialized) + @initialized ||= initialized + end + + def logger + if defined?(RAILS_DEFAULT_LOGGER) + RAILS_DEFAULT_LOGGER + else + nil + end + end + + def backtrace_cleaner + @@backtrace_cleaner ||= begin + # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded + require 'rails/backtrace_cleaner' + Rails::BacktraceCleaner.new + end + end + + def root + application && application.config.root + end + + def env + @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) + end + + def cache + RAILS_CACHE + end + + def version + VERSION::STRING + end + + def public_path + @@public_path ||= self.root ? File.join(self.root, "public") : "public" + end + + def public_path=(path) + @@public_path = path + end end -end \ No newline at end of file +end diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb new file mode 100644 index 0000000000..a1ad72e98d --- /dev/null +++ b/railties/lib/rails/all.rb @@ -0,0 +1,15 @@ +require "rails" + +%w( + active_model + active_record + action_controller + action_view + action_mailer + active_resource +).each do |framework| + begin + require "#{framework}/rails" + rescue LoadError + end +end \ No newline at end of file diff --git a/railties/lib/rails/core.rb b/railties/lib/rails/core.rb deleted file mode 100644 index ab95edc676..0000000000 --- a/railties/lib/rails/core.rb +++ /dev/null @@ -1,105 +0,0 @@ -require "pathname" - -require 'active_support' -require 'active_support/core_ext/kernel/reporting' -require 'active_support/core_ext/logger' -require 'action_dispatch' - -require 'rails/initializable' -require 'rails/application' -require 'rails/plugin' -require 'rails/railties_path' -require 'rails/version' -require 'rails/rack' -require 'rails/paths' -require 'rails/configuration' -require 'rails/deprecation' -require 'rails/ruby_version_check' - -# For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the -# multibyte safe operations. Plugin authors supporting other encodings -# should override this behaviour and set the relevant +default_charset+ -# on ActionController::Base. -# -# For Ruby 1.9, UTF-8 is the default internal and external encoding. -if RUBY_VERSION < '1.9' - $KCODE='u' -else - Encoding.default_external = Encoding::UTF_8 -end - -RAILS_ENV = (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup unless defined?(RAILS_ENV) - -module Rails - # Needs to be duplicated from Active Support since its needed before Active - # Support is available. Here both Options and Hash are namespaced to prevent - # conflicts with other implementations AND with the classes residing in Active Support. - # --- - # TODO: w0t? - class << self - def application - @@application ||= nil - end - - def application=(application) - @@application = application - end - - # The Configuration instance used to configure the Rails environment - def configuration - application.configuration - end - - def initialize! - application.initialize! - end - - def initialized? - @initialized || false - end - - def initialized=(initialized) - @initialized ||= initialized - end - - def logger - if defined?(RAILS_DEFAULT_LOGGER) - RAILS_DEFAULT_LOGGER - else - nil - end - end - - def backtrace_cleaner - @@backtrace_cleaner ||= begin - # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded - require 'rails/backtrace_cleaner' - Rails::BacktraceCleaner.new - end - end - - def root - application && application.config.root - end - - def env - @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) - end - - def cache - RAILS_CACHE - end - - def version - VERSION::STRING - end - - def public_path - @@public_path ||= self.root ? File.join(self.root, "public") : "public" - end - - def public_path=(path) - @@public_path = path - end - end -end diff --git a/railties/lib/rails/generators/rails/app/templates/config/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb index e4ecd2dcde..6051a8104f 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb @@ -13,12 +13,11 @@ else require 'rubygems' end -require 'rails' -# To skip frameworks you're not going to use, change require "rails" -# to require "rails/core" and list the frameworks that you are going -# to use. +require 'rails/all' +# To pick the frameworks you want, remove 'require "rails/all"' +# and list the frameworks that you want: # -# require "rails/core" +# require "rails" # require "active_model/rails" # require "active_record/rails" # require "action_controller/rails" -- cgit v1.2.3 From ae7ada1fde1648a5c81b9e6adf74d515e0bbe0a5 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 31 Dec 2009 13:11:54 -0800 Subject: Some railties cleanup: * Rename /rails.rb -> /railtie.rb * Rails::Plugin -> Rails::Railtie * Rails::Plugin::Vendored -> Rails::Plugin --- railties/lib/rails.rb | 1 + railties/lib/rails/all.rb | 2 +- railties/lib/rails/application.rb | 4 +- railties/lib/rails/configuration.rb | 8 +- .../generators/rails/app/templates/config/boot.rb | 15 ++- railties/lib/rails/plugin.rb | 126 +++++++-------------- railties/lib/rails/railtie.rb | 43 +++++++ 7 files changed, 100 insertions(+), 99 deletions(-) create mode 100644 railties/lib/rails/railtie.rb (limited to 'railties/lib') diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index ab95edc676..d69e3eea6a 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -7,6 +7,7 @@ require 'action_dispatch' require 'rails/initializable' require 'rails/application' +require 'rails/railtie' require 'rails/plugin' require 'rails/railties_path' require 'rails/version' diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb index a1ad72e98d..7dfe2b8b63 100644 --- a/railties/lib/rails/all.rb +++ b/railties/lib/rails/all.rb @@ -9,7 +9,7 @@ require "rails" active_resource ).each do |framework| begin - require "#{framework}/rails" + require "#{framework}/railtie" rescue LoadError end end \ No newline at end of file diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 88f10727c5..457eef648c 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -92,8 +92,8 @@ module Rails def plugins @plugins ||= begin plugin_names = config.plugins || [:all] - Plugin.plugins.select { |p| plugin_names.include?(:all) || plugin_names.include?(p.plugin_name) }.map { |p| p.new } + - Plugin::Vendored.all(config.plugins || [:all], config.paths.vendor.plugins) + Railtie.plugins.select { |p| plugin_names.include?(:all) || plugin_names.include?(p.plugin_name) }.map { |p| p.new } + + Plugin.all(config.plugins || [:all], config.paths.vendor.plugins) end end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index adb11e8257..f0a0d5e55e 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -3,7 +3,7 @@ require 'active_support/ordered_options' module Rails # Temporarily separate the plugin configuration class from the main # configuration class while this bit is being cleaned up. - class Plugin::Configuration + class Railtie::Configuration def self.default @default ||= new @@ -45,12 +45,12 @@ module Rails end def config_keys - ([ :active_support, :action_view, :action_mailer, :active_resource ] + - Plugin.plugin_names).map { |n| n.to_s }.uniq + ([ :active_support, :action_view ] + + Railtie.plugin_names).map { |n| n.to_s }.uniq end end - class Configuration < Plugin::Configuration + class Configuration < Railtie::Configuration attr_accessor :after_initialize_blocks, :cache_classes, :consider_all_requests_local, :dependency_loading, :gems, :load_once_paths, :logger, :metals, :plugins, diff --git a/railties/lib/rails/generators/rails/app/templates/config/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb index 6051a8104f..6de1725260 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb @@ -15,12 +15,11 @@ end require 'rails/all' # To pick the frameworks you want, remove 'require "rails/all"' -# and list the frameworks that you want: +# and list the framework railties that you want: # -# require "rails" -# require "active_model/rails" -# require "active_record/rails" -# require "action_controller/rails" -# require "action_view/rails" -# require "action_mailer/rails" -# require "active_resource/rails" \ No newline at end of file +# require "active_model/railtie" +# require "active_record/railtie" +# require "action_controller/railtie" +# require "action_view/railtie" +# require "action_mailer/railtie" +# require "active_resource/railtie" \ No newline at end of file diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index e154e9b706..9cc6b9c35b 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -1,106 +1,64 @@ module Rails - class Plugin - include Initializable - - def self.plugin_name(plugin_name = nil) - @plugin_name ||= name.demodulize.underscore - @plugin_name = plugin_name if plugin_name - @plugin_name - end - - def self.inherited(klass) - @plugins ||= [] - @plugins << klass unless klass == Vendored - end - - def self.plugins - @plugins - end + class Plugin < Railtie + def self.all(list, paths) + plugins = [] + paths.each do |path| + Dir["#{path}/*"].each do |plugin_path| + plugin = new(plugin_path) + next unless list.include?(plugin.name) || list.include?(:all) + plugins << plugin + end + end - def self.plugin_names - plugins.map { |p| p.plugin_name } + plugins.sort_by do |p| + [list.index(p.name) || list.index(:all), p.name.to_s] + end end - def self.config - Configuration.default - end + attr_reader :name, :path - def self.rake_tasks(&blk) - @rake_tasks ||= [] - @rake_tasks << blk if blk - @rake_tasks + def initialize(path) + @name = File.basename(path).to_sym + @path = path end - def rake_tasks - self.class.rake_tasks + def load_paths + Dir["#{path}/{lib}", "#{path}/app/{models,controllers,helpers}"] end def load_tasks - return unless rake_tasks - rake_tasks.each { |blk| blk.call } + Dir["#{path}/**/tasks/**/*.rake"].sort.each { |ext| load ext } end - class Vendored < Plugin - def self.all(list, paths) - plugins = [] - paths.each do |path| - Dir["#{path}/*"].each do |plugin_path| - plugin = new(plugin_path) - next unless list.include?(plugin.name) || list.include?(:all) - plugins << plugin - end - end - - plugins.sort_by do |p| - [list.index(p.name) || list.index(:all), p.name.to_s] - end - end - - attr_reader :name, :path - - def initialize(path) - @name = File.basename(path).to_sym - @path = path - end - - def load_paths - Dir["#{path}/{lib}", "#{path}/app/{models,controllers,helpers}"] - end - - def load_tasks - Dir["#{path}/**/tasks/**/*.rake"].sort.each { |ext| load ext } - end - - initializer :add_to_load_path, :after => :set_autoload_paths do |app| - load_paths.each do |path| - $LOAD_PATH << path - require "active_support/dependencies" + initializer :add_to_load_path, :after => :set_autoload_paths do |app| + load_paths.each do |path| + $LOAD_PATH << path + require "active_support/dependencies" - ActiveSupport::Dependencies.load_paths << path + ActiveSupport::Dependencies.load_paths << path - unless app.config.reload_plugins - ActiveSupport::Dependencies.load_once_paths << path - end + unless app.config.reload_plugins + ActiveSupport::Dependencies.load_once_paths << path end end + end - initializer :load_init_rb, :before => :load_application_initializers do |app| - file = "#{@path}/init.rb" - config = app.config - eval File.read(file), binding, file if File.file?(file) - end + initializer :load_init_rb, :before => :load_application_initializers do |app| + file = "#{@path}/init.rb" + config = app.config + eval File.read(file), binding, file if File.file?(file) + end - initializer :add_view_paths, :after => :initialize_framework_views do - ActionController::Base.view_paths.concat ["#{path}/app/views"] if File.directory?("#{path}/app/views") - end + initializer :add_view_paths, :after => :initialize_framework_views do + ActionController::Base.view_paths.concat ["#{path}/app/views"] if File.directory?("#{path}/app/views") + end - initializer :add_routing_file, :after => :initialize_routing do |app| - routing_file = "#{path}/config/routes.rb" - if File.exist?(routing_file) - app.route_configuration_files << routing_file - app.reload_routes! - end + initializer :add_routing_file, :after => :initialize_routing do |app| + routing_file = "#{path}/config/routes.rb" + if File.exist?(routing_file) + app.route_configuration_files << routing_file + app.reload_routes! end end end -end +end \ No newline at end of file diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb new file mode 100644 index 0000000000..ff28ade35d --- /dev/null +++ b/railties/lib/rails/railtie.rb @@ -0,0 +1,43 @@ +module Rails + class Railtie + include Initializable + + def self.plugin_name(plugin_name = nil) + @plugin_name ||= name.demodulize.underscore + @plugin_name = plugin_name if plugin_name + @plugin_name + end + + def self.inherited(klass) + @plugins ||= [] + @plugins << klass unless klass == Plugin + end + + def self.plugins + @plugins + end + + def self.plugin_names + plugins.map { |p| p.plugin_name } + end + + def self.config + Configuration.default + end + + def self.rake_tasks(&blk) + @rake_tasks ||= [] + @rake_tasks << blk if blk + @rake_tasks + end + + def rake_tasks + self.class.rake_tasks + end + + def load_tasks + return unless rake_tasks + rake_tasks.each { |blk| blk.call } + end + end +end -- cgit v1.2.3 From fd719d7ecfabfa3b235308437397d55fc9155dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Jan 2010 19:41:00 +0100 Subject: Update vendored Thor. --- railties/lib/rails/generators.rb | 2 +- .../lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc | 82 ---- railties/lib/rails/vendor/thor-0.12.1/LICENSE | 20 - railties/lib/rails/vendor/thor-0.12.1/README.rdoc | 234 ---------- railties/lib/rails/vendor/thor-0.12.1/Thorfile | 63 --- railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb | 242 ---------- .../rails/vendor/thor-0.12.1/lib/thor/actions.rb | 273 ----------- .../thor-0.12.1/lib/thor/actions/create_file.rb | 103 ---- .../thor-0.12.1/lib/thor/actions/directory.rb | 91 ---- .../lib/thor/actions/empty_directory.rb | 134 ------ .../lib/thor/actions/file_manipulation.rb | 223 --------- .../lib/thor/actions/inject_into_file.rb | 101 ---- .../lib/rails/vendor/thor-0.12.1/lib/thor/base.rb | 517 --------------------- .../thor/core_ext/hash_with_indifferent_access.rb | 75 --- .../thor-0.12.1/lib/thor/core_ext/ordered_hash.rb | 100 ---- .../lib/rails/vendor/thor-0.12.1/lib/thor/error.rb | 27 -- .../lib/rails/vendor/thor-0.12.1/lib/thor/group.rb | 263 ----------- .../vendor/thor-0.12.1/lib/thor/invocation.rb | 178 ------- .../rails/vendor/thor-0.12.1/lib/thor/parser.rb | 4 - .../vendor/thor-0.12.1/lib/thor/parser/argument.rb | 67 --- .../thor-0.12.1/lib/thor/parser/arguments.rb | 145 ------ .../vendor/thor-0.12.1/lib/thor/parser/option.rb | 132 ------ .../vendor/thor-0.12.1/lib/thor/parser/options.rb | 142 ------ .../vendor/thor-0.12.1/lib/thor/rake_compat.rb | 66 --- .../rails/vendor/thor-0.12.1/lib/thor/runner.rb | 299 ------------ .../lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb | 78 ---- .../vendor/thor-0.12.1/lib/thor/shell/basic.rb | 219 --------- .../vendor/thor-0.12.1/lib/thor/shell/color.rb | 108 ----- .../lib/rails/vendor/thor-0.12.1/lib/thor/task.rb | 122 ----- .../lib/rails/vendor/thor-0.12.1/lib/thor/util.rb | 251 ---------- .../rails/vendor/thor-0.12.1/lib/thor/version.rb | 3 - .../lib/rails/vendor/thor-0.12.3/CHANGELOG.rdoc | 80 ++++ railties/lib/rails/vendor/thor-0.12.3/LICENSE | 20 + railties/lib/rails/vendor/thor-0.12.3/README.rdoc | 234 ++++++++++ railties/lib/rails/vendor/thor-0.12.3/Thorfile | 63 +++ railties/lib/rails/vendor/thor-0.12.3/lib/thor.rb | 240 ++++++++++ .../rails/vendor/thor-0.12.3/lib/thor/actions.rb | 274 +++++++++++ .../thor-0.12.3/lib/thor/actions/create_file.rb | 103 ++++ .../thor-0.12.3/lib/thor/actions/directory.rb | 91 ++++ .../lib/thor/actions/empty_directory.rb | 134 ++++++ .../lib/thor/actions/file_manipulation.rb | 223 +++++++++ .../lib/thor/actions/inject_into_file.rb | 101 ++++ .../lib/rails/vendor/thor-0.12.3/lib/thor/base.rb | 515 ++++++++++++++++++++ .../lib/thor/core_ext/file_binary_read.rb | 9 + .../thor/core_ext/hash_with_indifferent_access.rb | 75 +++ .../thor-0.12.3/lib/thor/core_ext/ordered_hash.rb | 100 ++++ .../lib/rails/vendor/thor-0.12.3/lib/thor/error.rb | 27 ++ .../lib/rails/vendor/thor-0.12.3/lib/thor/group.rb | 267 +++++++++++ .../vendor/thor-0.12.3/lib/thor/invocation.rb | 178 +++++++ .../rails/vendor/thor-0.12.3/lib/thor/parser.rb | 4 + .../vendor/thor-0.12.3/lib/thor/parser/argument.rb | 67 +++ .../thor-0.12.3/lib/thor/parser/arguments.rb | 145 ++++++ .../vendor/thor-0.12.3/lib/thor/parser/option.rb | 132 ++++++ .../vendor/thor-0.12.3/lib/thor/parser/options.rb | 142 ++++++ .../vendor/thor-0.12.3/lib/thor/rake_compat.rb | 66 +++ .../rails/vendor/thor-0.12.3/lib/thor/runner.rb | 303 ++++++++++++ .../lib/rails/vendor/thor-0.12.3/lib/thor/shell.rb | 78 ++++ .../vendor/thor-0.12.3/lib/thor/shell/basic.rb | 239 ++++++++++ .../vendor/thor-0.12.3/lib/thor/shell/color.rb | 108 +++++ .../lib/rails/vendor/thor-0.12.3/lib/thor/task.rb | 111 +++++ .../lib/rails/vendor/thor-0.12.3/lib/thor/util.rb | 233 ++++++++++ .../rails/vendor/thor-0.12.3/lib/thor/version.rb | 3 + 62 files changed, 4366 insertions(+), 4363 deletions(-) delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/LICENSE delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/README.rdoc delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/Thorfile delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/create_file.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/directory.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/empty_directory.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/file_manipulation.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/inject_into_file.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/base.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/hash_with_indifferent_access.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/ordered_hash.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/error.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/group.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/invocation.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/argument.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/arguments.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/option.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/options.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/rake_compat.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/runner.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/basic.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/color.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/task.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/util.rb delete mode 100644 railties/lib/rails/vendor/thor-0.12.1/lib/thor/version.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/CHANGELOG.rdoc create mode 100644 railties/lib/rails/vendor/thor-0.12.3/LICENSE create mode 100644 railties/lib/rails/vendor/thor-0.12.3/README.rdoc create mode 100644 railties/lib/rails/vendor/thor-0.12.3/Thorfile create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/create_file.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/directory.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/empty_directory.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/file_manipulation.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/inject_into_file.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/base.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/file_binary_read.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/hash_with_indifferent_access.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/ordered_hash.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/error.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/group.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/invocation.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/argument.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/arguments.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/option.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/options.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/rake_compat.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/runner.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/basic.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/color.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/task.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/util.rb create mode 100644 railties/lib/rails/vendor/thor-0.12.3/lib/thor/version.rb (limited to 'railties/lib') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 2ba56bc3c5..6419961415 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -10,7 +10,7 @@ require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/string/inflections' # TODO: Do not always push on vendored thor -$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.12.1/lib") +$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.12.3/lib") require 'rails/generators/base' require 'rails/generators/named_base' diff --git a/railties/lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc b/railties/lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc deleted file mode 100644 index 606a0cdb52..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/CHANGELOG.rdoc +++ /dev/null @@ -1,82 +0,0 @@ -== TODO - -* Improve spec coverage for Thor::Runner - -== 0.12, released 2009-11-06 - -* [#7] Do not force white color on status -* [#8] Yield a block with the filename on directory - -== 0.11, released 2009-07-01 - -* Added a rake compatibility layer. It allows you to use spec and rdoc tasks on - Thor classes. - -* BACKWARDS INCOMPATIBLE: aliases are not generated automatically anymore - since it wrong behavior to the invocation system. - -* thor help now show information about any class/task. All those calls are - possible: - - thor help describe - thor help describe:amazing - - Or even with default namespaces: - - thor help :spec - -* Thor::Runner now invokes the default task if none is supplied: - - thor describe # invokes the default task, usually help - -* Thor::Runner now works with mappings: - - thor describe -h - -* Added some documentation and code refactoring. - -== 0.9.8, released 2008-10-20 - -* Fixed some tiny issues that were introduced lately. - -== 0.9.7, released 2008-10-13 - -* Setting global method options on the initialize method works as expected: - All other tasks will accept these global options in addition to their own. -* Added 'group' notion to Thor task sets (class Thor); by default all tasks - are in the 'standard' group. Running 'thor -T' will only show the standard - tasks - adding --all will show all tasks. You can also filter on a specific - group using the --group option: thor -T --group advanced - -== 0.9.6, released 2008-09-13 - -* Generic improvements - -== 0.9.5, released 2008-08-27 - -* Improve Windows compatibility -* Update (incorrect) README and task.thor sample file -* Options hash is now frozen (once returned) -* Allow magic predicates on options object. For instance: `options.force?` -* Add support for :numeric type -* BACKWARDS INCOMPATIBLE: Refactor Thor::Options. You cannot access shorthand forms in options hash anymore (for instance, options[:f]) -* Allow specifying optional args with default values: method_options(:user => "mislav") -* Don't write options for nil or false values. This allows, for example, turning color off when running specs. -* Exit with the status of the spec command to help CI stuff out some. - -== 0.9.4, released 2008-08-13 - -* Try to add Windows compatibility. -* BACKWARDS INCOMPATIBLE: options hash is now accessed as a property in your class and is not passed as last argument anymore -* Allow options at the beginning of the argument list as well as the end. -* Make options available with symbol keys in addition to string keys. -* Allow true to be passed to Thor#method_options to denote a boolean option. -* If loading a thor file fails, don't give up, just print a warning and keep going. -* Make sure that we re-raise errors if they happened further down the pipe than we care about. -* Only delete the old file on updating when the installation of the new one is a success -* Make it Ruby 1.8.5 compatible. -* Don't raise an error if a boolean switch is defined multiple times. -* Thor::Options now doesn't parse through things that look like options but aren't. -* Add URI detection to install task, and make sure we don't append ".thor" to URIs -* Add rake2thor to the gem binfiles. -* Make sure local Thorfiles override system-wide ones. diff --git a/railties/lib/rails/vendor/thor-0.12.1/LICENSE b/railties/lib/rails/vendor/thor-0.12.1/LICENSE deleted file mode 100644 index 98722da459..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008 Yehuda Katz - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/railties/lib/rails/vendor/thor-0.12.1/README.rdoc b/railties/lib/rails/vendor/thor-0.12.1/README.rdoc deleted file mode 100644 index ee545f3d97..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/README.rdoc +++ /dev/null @@ -1,234 +0,0 @@ -= thor - -Map options to a class. Simply create a class with the appropriate annotations -and have options automatically map to functions and parameters. - -Example: - - class App < Thor # [1] - map "-L" => :list # [2] - - desc "install APP_NAME", "install one of the available apps" # [3] - method_options :force => :boolean, :alias => :string # [4] - def install(name) - user_alias = options[:alias] - if options.force? - # do something - end - # other code - end - - desc "list [SEARCH]", "list all of the available apps, limited by SEARCH" - def list(search="") - # list everything - end - end - -Thor automatically maps commands as such: - - thor app:install myname --force - -That gets converted to: - - App.new.install("myname") - # with {'force' => true} as options hash - -1. Inherit from Thor to turn a class into an option mapper -2. Map additional non-valid identifiers to specific methods. In this case, convert -L to :list -3. Describe the method immediately below. The first parameter is the usage information, and the second parameter is the description -4. Provide any additional options that will be available the instance method options. - -== Types for method_options - -* :boolean - is parsed as --option or --option=true -* :string - is parsed as --option=VALUE -* :numeric - is parsed as --option=N -* :array - is parsed as --option=one two three -* :hash - is parsed as --option=name:string age:integer - -Besides, method_option allows a default value to be given, examples: - - method_options :force => false - #=> Creates a boolean option with default value false - - method_options :alias => "bar" - #=> Creates a string option with default value "bar" - - method_options :threshold => 3.0 - #=> Creates a numeric option with default value 3.0 - -You can also supply :option => :required to mark an option as required. The -type is assumed to be string. If you want a required hash with default values -as option, you can use method_option which uses a more declarative style: - - method_option :attributes, :type => :hash, :default => {}, :required => true - -All arguments can be set to nil (except required arguments), by suppling a no or -skip variant. For example: - - thor app name --no-attributes - -In previous versions, aliases for options were created automatically, but now -they should be explicit. You can supply aliases in both short and declarative -styles: - - method_options %w( force -f ) => :boolean - -Or: - - method_option :force, :type => :boolean, :aliases => "-f" - -You can supply as many aliases as you want. - -NOTE: Type :optional available in Thor 0.9.0 was deprecated. Use :string or :boolean instead. - -== Namespaces - -By default, your Thor tasks are invoked using Ruby namespace. In the example -above, tasks are invoked as: - - thor app:install name --force - -However, you could namespace your class as: - - module Sinatra - class App < Thor - # tasks - end - end - -And then you should invoke your tasks as: - - thor sinatra:app:install name --force - -If desired, you can change the namespace: - - module Sinatra - class App < Thor - namespace :myapp - # tasks - end - end - -And then your tasks hould be invoked as: - - thor myapp:install name --force - -== Invocations - -Thor comes with a invocation-dependency system as well which allows a task to be -invoked only once. For example: - - class Counter < Thor - desc "one", "Prints 1, 2, 3" - def one - puts 1 - invoke :two - invoke :three - end - - desc "two", "Prints 2, 3" - def two - puts 2 - invoke :three - end - - desc "three", "Prints 3" - def three - puts 3 - end - end - -When invoking the task one: - - thor counter:one - -The output is "1 2 3", which means that the three task was invoked only once. -You can even invoke tasks from another class, so be sure to check the -documentation. - -== Thor::Group - -Thor has a special class called Thor::Group. The main difference to Thor class -is that it invokes all tasks at once. The example above could be rewritten in -Thor::Group as this: - - class Counter < Thor::Group - desc "Prints 1, 2, 3" - - def one - puts 1 - end - - def two - puts 2 - end - - def three - puts 3 - end - end - -When invoked: - - thor counter - -It prints "1 2 3" as well. Notice you should describe (using the method desc) -only the class and not each task anymore. Thor::Group is a great tool to create -generators, since you can define several steps which are invoked in the order they -are defined (Thor::Group is the tool use in generators in Rails 3.0). - -Besides, Thor::Group can parse arguments and options as Thor tasks: - - class Counter < Thor::Group - # number will be available as attr_accessor - argument :number, :type => :numeric, :desc => "The number to start counting" - desc "Prints the 'number' given upto 'number+2'" - - def one - puts number + 0 - end - - def two - puts number + 1 - end - - def three - puts number + 2 - end - end - -The counter above expects one parameter and has the folling outputs: - - thor counter 5 - # Prints "5 6 7" - - thor counter 11 - # Prints "11 12 13" - -You can also give options to Thor::Group, but instead of using method_option -and method_options, you should use class_option and class_options. -Both argument and class_options methods are available to Thor class as well. - -== Actions - -Thor comes with several actions which helps with script and generator tasks. You -might be familiar with them since some came from Rails Templates. They are: -say, ask, yes?, no?, add_file, -remove_file, copy_file, template, directory, -inside, run, inject_into_file and a couple more. - -To use them, you just need to include Thor::Actions in your Thor classes: - - class App < Thor - include Thor::Actions - # tasks - end - -Some actions like copy file requires that a class method called source_root is -defined in your class. This is the directory where your templates should be -placed. Be sure to check the documentation. - -== License - -See MIT LICENSE. diff --git a/railties/lib/rails/vendor/thor-0.12.1/Thorfile b/railties/lib/rails/vendor/thor-0.12.1/Thorfile deleted file mode 100644 index ff1cb4498a..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/Thorfile +++ /dev/null @@ -1,63 +0,0 @@ -# enconding: utf-8 - -require File.join(File.dirname(__FILE__), "lib", "thor", "version") -require 'thor/rake_compat' -require 'spec/rake/spectask' -require 'rdoc/task' - -GEM_NAME = 'thor' -EXTRA_RDOC_FILES = ["README.rdoc", "LICENSE", "CHANGELOG.rdoc", "VERSION", "Thorfile"] - -class Default < Thor - include Thor::RakeCompat - - Spec::Rake::SpecTask.new(:spec) do |t| - t.libs << 'lib' - t.spec_opts = ['--options', "spec/spec.opts"] - t.spec_files = FileList['spec/**/*_spec.rb'] - end - - Spec::Rake::SpecTask.new(:rcov) do |t| - t.libs << 'lib' - t.spec_opts = ['--options', "spec/spec.opts"] - t.spec_files = FileList['spec/**/*_spec.rb'] - t.rcov = true - t.rcov_dir = "rcov" - end - - RDoc::Task.new do |rdoc| - rdoc.main = "README.rdoc" - rdoc.rdoc_dir = "rdoc" - rdoc.title = GEM_NAME - rdoc.rdoc_files.include(*EXTRA_RDOC_FILES) - rdoc.rdoc_files.include('lib/**/*.rb') - rdoc.options << '--line-numbers' << '--inline-source' - end - - begin - require 'jeweler' - Jeweler::Tasks.new do |s| - s.name = GEM_NAME - s.version = Thor::VERSION - s.rubyforge_project = "textmate" - s.platform = Gem::Platform::RUBY - s.summary = "A scripting framework that replaces rake, sake and rubigen" - s.email = "ruby-thor@googlegroups.com" - s.homepage = "http://yehudakatz.com" - s.description = "A scripting framework that replaces rake, sake and rubigen" - s.authors = ['Yehuda Katz', 'José Valim'] - s.has_rdoc = true - s.extra_rdoc_files = EXTRA_RDOC_FILES - s.require_path = 'lib' - s.bindir = "bin" - s.executables = %w( thor rake2thor ) - s.files = s.extra_rdoc_files + Dir.glob("{bin,lib}/**/*") - s.files.exclude 'spec/sandbox/**/*' - s.test_files.exclude 'spec/sandbox/**/*' - end - - Jeweler::GemcutterTasks.new - rescue LoadError - puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb deleted file mode 100644 index 68944f140d..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor.rb +++ /dev/null @@ -1,242 +0,0 @@ -require 'thor/base' -require 'thor/group' -require 'thor/actions' - -class Thor - class << self - # Sets the default task when thor is executed without an explicit task to be called. - # - # ==== Parameters - # meth:: name of the defaut task - # - def default_task(meth=nil) - case meth - when :none - @default_task = 'help' - when nil - @default_task ||= from_superclass(:default_task, 'help') - else - @default_task = meth.to_s - end - end - - # Defines the usage and the description of the next task. - # - # ==== Parameters - # usage - # description - # - def desc(usage, description, options={}) - if options[:for] - task = find_and_refresh_task(options[:for]) - task.usage = usage if usage - task.description = description if description - else - @usage, @desc = usage, description - end - end - - # Maps an input to a task. If you define: - # - # map "-T" => "list" - # - # Running: - # - # thor -T - # - # Will invoke the list task. - # - # ==== Parameters - # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task. - # - def map(mappings=nil) - @map ||= from_superclass(:map, {}) - - if mappings - mappings.each do |key, value| - if key.respond_to?(:each) - key.each {|subkey| @map[subkey] = value} - else - @map[key] = value - end - end - end - - @map - end - - # Declares the options for the next task to be declared. - # - # ==== Parameters - # Hash[Symbol => Object]:: The hash key is the name of the option and the value - # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric - # or :required (string). If you give a value, the type of the value is used. - # - def method_options(options=nil) - @method_options ||= {} - build_options(options, @method_options) if options - @method_options - end - - # Adds an option to the set of class options. If :for is given as option, - # it allows you to change the options from a previous defined task. - # - # def previous_task - # # magic - # end - # - # method_options :foo => :bar, :for => :previous_task - # - # def next_task - # # magic - # end - # - # ==== Parameters - # name:: The name of the argument. - # options:: Described below. - # - # ==== Options - # :desc - Description for the argument. - # :required - If the argument is required or not. - # :default - Default value for this argument. It cannot be required and have default values. - # :aliases - Aliases for this option. - # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. - # :group - The group for this options. Use by class options to output options in different levels. - # :banner - String to show on usage notes. - # - def method_option(name, options={}) - scope = if options[:for] - find_and_refresh_task(options[:for]).options - else - method_options - end - - build_option(name, options, scope) - end - - # Parses the task and options from the given args, instantiate the class - # and invoke the task. This method is used when the arguments must be parsed - # from an array. If you are inside Ruby and want to use a Thor class, you - # can simply initialize it: - # - # script = MyScript.new(args, options, config) - # script.invoke(:task, first_arg, second_arg, third_arg) - # - def start(given_args=ARGV, config={}) - super do - meth = normalize_task_name(given_args.shift) - task = all_tasks[meth] - - if task - args, opts = Thor::Options.split(given_args) - config.merge!(:task_options => task.options) - else - args, opts = given_args, {} - end - - task ||= Thor::Task::Dynamic.new(meth) - trailing = args[Range.new(arguments.size, -1)] - new(args, opts, config).invoke(task, trailing || []) - end - end - - # Prints help information. If a task name is given, it shows information - # only about the specific task. - # - # ==== Parameters - # meth:: An optional task name to print usage information about. - # - # ==== Options - # namespace:: When true, shows the namespace in the output before the usage. - # skip_inherited:: When true, does not show tasks from superclass. - # - def help(shell, meth=nil, options={}) - meth, options = nil, meth if meth.is_a?(Hash) - - if meth - task = all_tasks[meth] - raise UndefinedTaskError, "task '#{meth}' could not be found in namespace '#{self.namespace}'" unless task - - shell.say "Usage:" - shell.say " #{banner(task, options[:namespace], false)}" - shell.say - class_options_help(shell, "Class", :Method => task.options.map { |_, o| o }) - shell.say task.description - else - list = (options[:short] ? tasks : all_tasks).map do |_, task| - item = [ banner(task, options[:namespace]) ] - item << "# #{task.short_description}" if task.short_description - item << " " - end - - options[:ident] ||= 2 - if options[:short] - shell.print_list(list, :ident => options[:ident]) - else - shell.say "Tasks:" - shell.print_list(list, :ident => options[:ident]) - end - - Thor::Util.thor_classes_in(self).each do |subclass| - namespace = options[:namespace] == true || subclass.namespace.gsub(/^#{self.namespace}:/, '') - subclass.help(shell, options.merge(:short => true, :namespace => namespace)) - end - - class_options_help(shell, "Class") unless options[:short] - end - end - - protected - - # The banner for this class. You can customize it if you are invoking the - # thor class by another ways which is not the Thor::Runner. It receives - # the task that is going to be invoked and a boolean which indicates if - # the namespace should be displayed as arguments. - # - def banner(task, namespace=true, show_options=true) - task.formatted_usage(self, namespace, show_options) - end - - def baseclass #:nodoc: - Thor - end - - def create_task(meth) #:nodoc: - if @usage && @desc - tasks[meth.to_s] = Thor::Task.new(meth, @desc, @usage, method_options) - @usage, @desc, @method_options = nil - true - elsif self.all_tasks[meth.to_s] || meth.to_sym == :method_missing - true - else - puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " << - "Call desc if you want this method to be available as task or declare it inside a " << - "no_tasks{} block. Invoked from #{caller[1].inspect}." - false - end - end - - def initialize_added #:nodoc: - class_options.merge!(method_options) - @method_options = nil - end - - # Receives a task name (can be nil), and try to get a map from it. - # If a map can't be found use the sent name or the default task. - # - def normalize_task_name(meth) #:nodoc: - mapping = map[meth.to_s] - meth = mapping || meth || default_task - meth.to_s.gsub('-','_') # treat foo-bar > foo_bar - end - end - - include Thor::Base - - map HELP_MAPPINGS => :help - - desc "help [TASK]", "Describe available tasks or one specific task" - def help(task=nil) - self.class.help(shell, task, :namespace => task && task.include?(?:)) - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions.rb deleted file mode 100644 index 4bfb7c2870..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions.rb +++ /dev/null @@ -1,273 +0,0 @@ -require 'fileutils' - -Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action| - require action -end - -class Thor - module Actions - attr_accessor :behavior - - def self.included(base) #:nodoc: - base.extend ClassMethods - end - - module ClassMethods - # Hold source paths for one Thor instance. source_paths_for_search is the - # method responsible to gather source_paths from this current class, - # inherited paths and the source root. - # - def source_paths - @source_paths ||= [] - end - - # Returns the source paths in the following order: - # - # 1) This class source paths - # 2) Source root - # 3) Parents source paths - # - def source_paths_for_search - paths = [] - paths += self.source_paths - paths << self.source_root if self.respond_to?(:source_root) - paths += from_superclass(:source_paths, []) - paths - end - - # Add runtime options that help actions execution. - # - def add_runtime_options! - class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime, - :desc => "Run but do not make any changes" - - class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime, - :desc => "Overwrite files that already exist" - - class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime, - :desc => "Skip files that already exist" - - class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime, - :desc => "Supress status output" - end - end - - # Extends initializer to add more configuration options. - # - # ==== Configuration - # behavior:: The actions default behavior. Can be :invoke or :revoke. - # It also accepts :force, :skip and :pretend to set the behavior - # and the respective option. - # - # destination_root:: The root directory needed for some actions. - # - def initialize(args=[], options={}, config={}) - self.behavior = case config[:behavior].to_s - when "force", "skip" - _cleanup_options_and_set(options, config[:behavior]) - :invoke - when "revoke" - :revoke - else - :invoke - end - - super - self.destination_root = config[:destination_root] - end - - # Wraps an action object and call it accordingly to the thor class behavior. - # - def action(instance) #:nodoc: - if behavior == :revoke - instance.revoke! - else - instance.invoke! - end - end - - # Returns the root for this thor class (also aliased as destination root). - # - def destination_root - @destination_stack.last - end - - # Sets the root for this thor class. Relatives path are added to the - # directory where the script was invoked and expanded. - # - def destination_root=(root) - @destination_stack ||= [] - @destination_stack[0] = File.expand_path(root || '') - end - - # Returns the given path relative to the absolute root (ie, root where - # the script started). - # - def relative_to_original_destination_root(path, remove_dot=true) - path = path.gsub(@destination_stack[0], '.') - remove_dot ? (path[2..-1] || '') : path - end - - # Holds source paths in instance so they can be manipulated. - # - def source_paths - @source_paths ||= self.class.source_paths_for_search - end - - # Receives a file or directory and search for it in the source paths. - # - def find_in_source_paths(file) - relative_root = relative_to_original_destination_root(destination_root, false) - - source_paths.each do |source| - source_file = File.expand_path(file, File.join(source, relative_root)) - return source_file if File.exists?(source_file) - end - - if source_paths.empty? - raise Error, "You don't have any source path defined for class #{self.class.name}. To fix this, " << - "you can define a source_root in your class." - else - raise Error, "Could not find #{file.inspect} in source paths." - end - end - - # Do something in the root or on a provided subfolder. If a relative path - # is given it's referenced from the current root. The full path is yielded - # to the block you provide. The path is set back to the previous path when - # the method exits. - # - # ==== Parameters - # dir:: the directory to move to. - # config:: give :verbose => true to log and use padding. - # - def inside(dir='', config={}, &block) - verbose = config.fetch(:verbose, false) - - say_status :inside, dir, verbose - shell.padding += 1 if verbose - @destination_stack.push File.expand_path(dir, destination_root) - - FileUtils.mkdir_p(destination_root) unless File.exist?(destination_root) - FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield } - - @destination_stack.pop - shell.padding -= 1 if verbose - end - - # Goes to the root and execute the given block. - # - def in_root - inside(@destination_stack.first) { yield } - end - - # Loads an external file and execute it in the instance binding. - # - # ==== Parameters - # path:: The path to the file to execute. Can be a web address or - # a relative path from the source root. - # - # ==== Examples - # - # apply "http://gist.github.com/103208" - # - # apply "recipes/jquery.rb" - # - def apply(path, config={}) - verbose = config.fetch(:verbose, true) - path = find_in_source_paths(path) unless path =~ /^http\:\/\// - - say_status :apply, path, verbose - shell.padding += 1 if verbose - instance_eval(open(path).read) - shell.padding -= 1 if verbose - end - - # Executes a command. - # - # ==== Parameters - # command:: the command to be executed. - # config:: give :verbose => false to not log the status. Specify :with - # to append an executable to command executation. - # - # ==== Example - # - # inside('vendor') do - # run('ln -s ~/edge rails') - # end - # - def run(command, config={}) - return unless behavior == :invoke - - destination = relative_to_original_destination_root(destination_root, false) - desc = "#{command} from #{destination.inspect}" - - if config[:with] - desc = "#{File.basename(config[:with].to_s)} #{desc}" - command = "#{config[:with]} #{command}" - end - - say_status :run, desc, config.fetch(:verbose, true) - system(command) unless options[:pretend] - end - - # Executes a ruby script (taking into account WIN32 platform quirks). - # - # ==== Parameters - # command:: the command to be executed. - # config:: give :verbose => false to not log the status. - # - def run_ruby_script(command, config={}) - return unless behavior == :invoke - run "#{command}", config.merge(:with => Thor::Util.ruby_command) - end - - # Run a thor command. A hash of options can be given and it's converted to - # switches. - # - # ==== Parameters - # task:: the task to be invoked - # args:: arguments to the task - # config:: give :verbose => false to not log the status. Other options - # are given as parameter to Thor. - # - # ==== Examples - # - # thor :install, "http://gist.github.com/103208" - # #=> thor install http://gist.github.com/103208 - # - # thor :list, :all => true, :substring => 'rails' - # #=> thor list --all --substring=rails - # - def thor(task, *args) - config = args.last.is_a?(Hash) ? args.pop : {} - verbose = config.key?(:verbose) ? config.delete(:verbose) : true - - args.unshift task - args.push Thor::Options.to_switches(config) - command = args.join(' ').strip - - run command, :with => :thor, :verbose => verbose - end - - protected - - # Allow current root to be shared between invocations. - # - def _shared_configuration #:nodoc: - super.merge!(:destination_root => self.destination_root) - end - - def _cleanup_options_and_set(options, key) #:nodoc: - case options - when Array - %w(--force -f --skip -s).each { |i| options.delete(i) } - options << "--#{key}" - when Hash - [:force, :skip, "force", "skip"].each { |i| options.delete(i) } - options.merge!(key => true) - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/create_file.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/create_file.rb deleted file mode 100644 index a3d9296823..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/create_file.rb +++ /dev/null @@ -1,103 +0,0 @@ -require 'thor/actions/empty_directory' - -class Thor - module Actions - - # Create a new file relative to the destination root with the given data, - # which is the return value of a block or a data string. - # - # ==== Parameters - # destination:: the relative path to the destination root. - # data:: the data to append to the file. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # create_file "lib/fun_party.rb" do - # hostname = ask("What is the virtual hostname I should use?") - # "vhost.name = #{hostname}" - # end - # - # create_file "config/apach.conf", "your apache config" - # - def create_file(destination, data=nil, config={}, &block) - action CreateFile.new(self, destination, block || data.to_s, config) - end - alias :add_file :create_file - - # AddFile is a subset of Template, which instead of rendering a file with - # ERB, it gets the content from the user. - # - class CreateFile < EmptyDirectory #:nodoc: - attr_reader :data - - def initialize(base, destination, data, config={}) - @data = data - super(base, destination, config) - end - - # Checks if the content of the file at the destination is identical to the rendered result. - # - # ==== Returns - # Boolean:: true if it is identical, false otherwise. - # - def identical? - exists? && File.read(destination) == render - end - - # Holds the content to be added to the file. - # - def render - @render ||= if data.is_a?(Proc) - data.call - else - data - end - end - - def invoke! - invoke_with_conflict_check do - FileUtils.mkdir_p(File.dirname(destination)) - File.open(destination, 'w'){ |f| f.write render } - end - given_destination - end - - protected - - # Now on conflict we check if the file is identical or not. - # - def on_conflict_behavior(&block) - if identical? - say_status :identical, :blue - else - options = base.options.merge(config) - force_or_skip_or_conflict(options[:force], options[:skip], &block) - end - end - - # If force is true, run the action, otherwise check if it's not being - # skipped. If both are false, show the file_collision menu, if the menu - # returns true, force it, otherwise skip. - # - def force_or_skip_or_conflict(force, skip, &block) - if force - say_status :force, :yellow - block.call unless pretend? - elsif skip - say_status :skip, :yellow - else - say_status :conflict, :red - force_or_skip_or_conflict(force_on_collision?, true, &block) - end - end - - # Shows the file collision menu to the user and gets the result. - # - def force_on_collision? - base.shell.file_collision(destination){ render } - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/directory.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/directory.rb deleted file mode 100644 index 2e0b459fa3..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/directory.rb +++ /dev/null @@ -1,91 +0,0 @@ -require 'thor/actions/empty_directory' - -class Thor - module Actions - - # Copies recursively the files from source directory to root directory. - # If any of the files finishes with .tt, it's considered to be a template - # and is placed in the destination without the extension .tt. If any - # empty directory is found, it's copied and all .empty_directory files are - # ignored. Remember that file paths can also be encoded, let's suppose a doc - # directory with the following files: - # - # doc/ - # components/.empty_directory - # README - # rdoc.rb.tt - # %app_name%.rb - # - # When invoked as: - # - # directory "doc" - # - # It will create a doc directory in the destination with the following - # files (assuming that the app_name is "blog"): - # - # doc/ - # components/ - # README - # rdoc.rb - # blog.rb - # - # ==== Parameters - # source:: the relative path to the source root. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # If :recursive => false, does not look for paths recursively. - # - # ==== Examples - # - # directory "doc" - # directory "doc", "docs", :recursive => false - # - def directory(source, destination=nil, config={}, &block) - action Directory.new(self, source, destination || source, config, &block) - end - - class Directory < EmptyDirectory #:nodoc: - attr_reader :source - - def initialize(base, source, destination=nil, config={}, &block) - @source = File.expand_path(base.find_in_source_paths(source.to_s)) - @block = block - super(base, destination, { :recursive => true }.merge(config)) - end - - def invoke! - base.empty_directory given_destination, config - execute! - end - - def revoke! - execute! - end - - protected - - def execute! - lookup = config[:recursive] ? File.join(source, '**') : source - lookup = File.join(lookup, '{*,.[a-z]*}') - - Dir[lookup].each do |file_source| - next if File.directory?(file_source) - file_destination = File.join(given_destination, file_source.gsub(source, '.')) - file_destination.gsub!('/./', '/') - - case file_source - when /\.empty_directory$/ - dirname = File.dirname(file_destination).gsub(/\/\.$/, '') - next if dirname == given_destination - base.empty_directory(dirname, config) - when /\.tt$/ - destination = base.template(file_source, file_destination[0..-4], config, &@block) - else - destination = base.copy_file(file_source, file_destination, config, &@block) - end - end - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/empty_directory.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/empty_directory.rb deleted file mode 100644 index 484cb820f8..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/empty_directory.rb +++ /dev/null @@ -1,134 +0,0 @@ -class Thor - module Actions - - # Creates an empty directory. - # - # ==== Parameters - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # empty_directory "doc" - # - def empty_directory(destination, config={}) - action EmptyDirectory.new(self, destination, config) - end - - # Class which holds create directory logic. This is the base class for - # other actions like create_file and directory. - # - # This implementation is based in Templater actions, created by Jonas Nicklas - # and Michael S. Klishin under MIT LICENSE. - # - class EmptyDirectory #:nodoc: - attr_reader :base, :destination, :given_destination, :relative_destination, :config - - # Initializes given the source and destination. - # - # ==== Parameters - # base:: A Thor::Base instance - # source:: Relative path to the source of this file - # destination:: Relative path to the destination of this file - # config:: give :verbose => false to not log the status. - # - def initialize(base, destination, config={}) - @base, @config = base, { :verbose => true }.merge(config) - self.destination = destination - end - - # Checks if the destination file already exists. - # - # ==== Returns - # Boolean:: true if the file exists, false otherwise. - # - def exists? - ::File.exists?(destination) - end - - def invoke! - invoke_with_conflict_check do - ::FileUtils.mkdir_p(destination) - end - end - - def revoke! - say_status :remove, :red - ::FileUtils.rm_rf(destination) if !pretend? && exists? - given_destination - end - - protected - - # Shortcut for pretend. - # - def pretend? - base.options[:pretend] - end - - # Sets the absolute destination value from a relative destination value. - # It also stores the given and relative destination. Let's suppose our - # script is being executed on "dest", it sets the destination root to - # "dest". The destination, given_destination and relative_destination - # are related in the following way: - # - # inside "bar" do - # empty_directory "baz" - # end - # - # destination #=> dest/bar/baz - # relative_destination #=> bar/baz - # given_destination #=> baz - # - def destination=(destination) - if destination - @given_destination = convert_encoded_instructions(destination.to_s) - @destination = ::File.expand_path(@given_destination, base.destination_root) - @relative_destination = base.relative_to_original_destination_root(@destination) - end - end - - # Filenames in the encoded form are converted. If you have a file: - # - # %class_name%.rb - # - # It gets the class name from the base and replace it: - # - # user.rb - # - def convert_encoded_instructions(filename) - filename.gsub(/%(.*?)%/) do |string| - instruction = $1.strip - base.respond_to?(instruction) ? base.send(instruction) : string - end - end - - # Receives a hash of options and just execute the block if some - # conditions are met. - # - def invoke_with_conflict_check(&block) - if exists? - on_conflict_behavior(&block) - else - say_status :create, :green - block.call unless pretend? - end - - destination - end - - # What to do when the destination file already exists. - # - def on_conflict_behavior(&block) - say_status :exist, :blue - end - - # Shortcut to say_status shell method. - # - def say_status(status, color) - base.shell.say_status status, relative_destination, color if config[:verbose] - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/file_manipulation.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/file_manipulation.rb deleted file mode 100644 index 8a45c83f25..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/file_manipulation.rb +++ /dev/null @@ -1,223 +0,0 @@ -require 'erb' -require 'open-uri' - -class Thor - module Actions - - # Copies the file from the relative source to the relative destination. If - # the destination is not given it's assumed to be equal to the source. - # - # ==== Parameters - # source:: the relative path to the source root. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # copy_file "README", "doc/README" - # - # copy_file "doc/README" - # - def copy_file(source, destination=nil, config={}, &block) - destination ||= source - source = File.expand_path(find_in_source_paths(source.to_s)) - - create_file destination, nil, config do - content = File.read(source) - content = block.call(content) if block - content - end - end - - # Gets the content at the given address and places it at the given relative - # destination. If a block is given instead of destination, the content of - # the url is yielded and used as location. - # - # ==== Parameters - # source:: the address of the given content. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # get "http://gist.github.com/103208", "doc/README" - # - # get "http://gist.github.com/103208" do |content| - # content.split("\n").first - # end - # - def get(source, destination=nil, config={}, &block) - source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^http\:\/\// - render = open(source).read - - destination ||= if block_given? - block.arity == 1 ? block.call(render) : block.call - else - File.basename(source) - end - - create_file destination, render, config - end - - # Gets an ERB template at the relative source, executes it and makes a copy - # at the relative destination. If the destination is not given it's assumed - # to be equal to the source removing .tt from the filename. - # - # ==== Parameters - # source:: the relative path to the source root. - # destination:: the relative path to the destination root. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # template "README", "doc/README" - # - # template "doc/README" - # - def template(source, destination=nil, config={}, &block) - destination ||= source - source = File.expand_path(find_in_source_paths(source.to_s)) - context = instance_eval('binding') - - create_file destination, nil, config do - content = ERB.new(::File.read(source), nil, '-').result(context) - content = block.call(content) if block - content - end - end - - # Changes the mode of the given file or directory. - # - # ==== Parameters - # mode:: the file mode - # path:: the name of the file to change mode - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # chmod "script/*", 0755 - # - def chmod(path, mode, config={}) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) - FileUtils.chmod_R(mode, path) unless options[:pretend] - end - - # Prepend text to a file. Since it depends on inject_into_file, it's reversible. - # - # ==== Parameters - # path:: path of the file to be changed - # data:: the data to prepend to the file, can be also given as a block. - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # prepend_file 'config/environments/test.rb', 'config.gem "rspec"' - # - # prepend_file 'config/environments/test.rb' do - # 'config.gem "rspec"' - # end - # - def prepend_file(path, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config.merge!(:after => /\A/) - inject_into_file(path, *(args << config), &block) - end - - # Append text to a file. Since it depends on inject_into_file, it's reversible. - # - # ==== Parameters - # path:: path of the file to be changed - # data:: the data to append to the file, can be also given as a block. - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # append_file 'config/environments/test.rb', 'config.gem "rspec"' - # - # append_file 'config/environments/test.rb' do - # 'config.gem "rspec"' - # end - # - def append_file(path, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config.merge!(:before => /\z/) - inject_into_file(path, *(args << config), &block) - end - - # Injects text right after the class definition. Since it depends on - # inject_into_file, it's reversible. - # - # ==== Parameters - # path:: path of the file to be changed - # klass:: the class to be manipulated - # data:: the data to append to the class, can be also given as a block. - # config:: give :verbose => false to not log the status. - # - # ==== Examples - # - # inject_into_class "app/controllers/application_controller.rb", " filter_parameter :password\n" - # - # inject_into_class "app/controllers/application_controller.rb", ApplicationController do - # " filter_parameter :password\n" - # end - # - def inject_into_class(path, klass, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/) - inject_into_file(path, *(args << config), &block) - end - - # Run a regular expression replacement on a file. - # - # ==== Parameters - # path:: path of the file to be changed - # flag:: the regexp or string to be replaced - # replacement:: the replacement, can be also given as a block - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' - # - # gsub_file 'README', /rake/, :green do |match| - # match << " no more. Use thor!" - # end - # - def gsub_file(path, flag, *args, &block) - return unless behavior == :invoke - config = args.last.is_a?(Hash) ? args.pop : {} - - path = File.expand_path(path, destination_root) - say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) - - unless options[:pretend] - content = File.read(path) - content.gsub!(flag, *args, &block) - File.open(path, 'wb') { |file| file.write(content) } - end - end - - # Removes a file at the given location. - # - # ==== Parameters - # path:: path of the file to be changed - # config:: give :verbose => false to not log the status. - # - # ==== Example - # - # remove_file 'README' - # remove_file 'app/controllers/application_controller.rb' - # - def remove_file(path, config={}) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - - say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) - ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path) - end - alias :remove_dir :remove_file - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/inject_into_file.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/inject_into_file.rb deleted file mode 100644 index 6b0b42ea02..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/actions/inject_into_file.rb +++ /dev/null @@ -1,101 +0,0 @@ -require 'thor/actions/empty_directory' - -class Thor - module Actions - - # Injects the given content into a file. Different from gsub_file, this - # method is reversible. - # - # ==== Parameters - # destination:: Relative path to the destination root - # data:: Data to add to the file. Can be given as a block. - # config:: give :verbose => false to not log the status and the flag - # for injection (:after or :before). - # - # ==== Examples - # - # inject_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n" - # - # inject_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do - # gems = ask "Which gems would you like to add?" - # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n") - # end - # - def inject_into_file(destination, *args, &block) - if block_given? - data, config = block, args.shift - else - data, config = args.shift, args.shift - end - action InjectIntoFile.new(self, destination, data, config) - end - - class InjectIntoFile < EmptyDirectory #:nodoc: - attr_reader :replacement, :flag, :behavior - - def initialize(base, destination, data, config) - super(base, destination, { :verbose => true }.merge(config)) - - @behavior, @flag = if @config.key?(:after) - [:after, @config.delete(:after)] - else - [:before, @config.delete(:before)] - end - - @replacement = data.is_a?(Proc) ? data.call : data - @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp) - end - - def invoke! - say_status :invoke - - content = if @behavior == :after - '\0' + replacement - else - replacement + '\0' - end - - replace!(/#{flag}/, content) - end - - def revoke! - say_status :revoke - - regexp = if @behavior == :after - content = '\1\2' - /(#{flag})(.*)(#{Regexp.escape(replacement)})/m - else - content = '\2\3' - /(#{Regexp.escape(replacement)})(.*)(#{flag})/m - end - - replace!(regexp, content) - end - - protected - - def say_status(behavior) - status = if flag == /\A/ - behavior == :invoke ? :prepend : :unprepend - elsif flag == /\z/ - behavior == :invoke ? :append : :unappend - else - behavior == :invoke ? :inject : :deinject - end - - super(status, config[:verbose]) - end - - # Adds the content to the file. - # - def replace!(regexp, string) - unless base.options[:pretend] - content = File.read(destination) - content.gsub!(regexp, string) - File.open(destination, 'wb') { |file| file.write(content) } - end - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/base.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/base.rb deleted file mode 100644 index 700d794123..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/base.rb +++ /dev/null @@ -1,517 +0,0 @@ -require 'thor/core_ext/hash_with_indifferent_access' -require 'thor/core_ext/ordered_hash' -require 'thor/error' -require 'thor/shell' -require 'thor/invocation' -require 'thor/parser' -require 'thor/task' -require 'thor/util' - -class Thor - # Shortcuts for help. - HELP_MAPPINGS = %w(-h -? --help -D) - - # Thor methods that should not be overwritten by the user. - THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root - action add_file create_file in_root inside run run_ruby_script) - - module Base - attr_accessor :options - - # It receives arguments in an Array and two hashes, one for options and - # other for configuration. - # - # Notice that it does not check if all required arguments were supplied. - # It should be done by the parser. - # - # ==== Parameters - # args:: An array of objects. The objects are applied to their - # respective accessors declared with argument. - # - # options:: An options hash that will be available as self.options. - # The hash given is converted to a hash with indifferent - # access, magic predicates (options.skip?) and then frozen. - # - # config:: Configuration for this Thor class. - # - def initialize(args=[], options={}, config={}) - Thor::Arguments.parse(self.class.arguments, args).each do |key, value| - send("#{key}=", value) - end - - parse_options = self.class.class_options - - if options.is_a?(Array) - task_options = config.delete(:task_options) # hook for start - parse_options = parse_options.merge(task_options) if task_options - array_options, hash_options = options, {} - else - array_options, hash_options = [], options - end - - options = Thor::Options.parse(parse_options, array_options) - self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).merge!(hash_options) - self.options.freeze - end - - class << self - def included(base) #:nodoc: - base.send :extend, ClassMethods - base.send :include, Invocation - base.send :include, Shell - end - - # Returns the classes that inherits from Thor or Thor::Group. - # - # ==== Returns - # Array[Class] - # - def subclasses - @subclasses ||= [] - end - - # Returns the files where the subclasses are kept. - # - # ==== Returns - # Hash[path => Class] - # - def subclass_files - @subclass_files ||= Hash.new{ |h,k| h[k] = [] } - end - - # Whenever a class inherits from Thor or Thor::Group, we should track the - # class and the file on Thor::Base. This is the method responsable for it. - # - def register_klass_file(klass) #:nodoc: - file = caller[1].match(/(.*):\d+/)[1] - Thor::Base.subclasses << klass unless Thor::Base.subclasses.include?(klass) - - file_subclasses = Thor::Base.subclass_files[File.expand_path(file)] - file_subclasses << klass unless file_subclasses.include?(klass) - end - end - - module ClassMethods - # Adds an argument to the class and creates an attr_accessor for it. - # - # Arguments are different from options in several aspects. The first one - # is how they are parsed from the command line, arguments are retrieved - # from position: - # - # thor task NAME - # - # Instead of: - # - # thor task --name=NAME - # - # Besides, arguments are used inside your code as an accessor (self.argument), - # while options are all kept in a hash (self.options). - # - # Finally, arguments cannot have type :default or :boolean but can be - # optional (supplying :optional => :true or :required => false), although - # you cannot have a required argument after a non-required argument. If you - # try it, an error is raised. - # - # ==== Parameters - # name:: The name of the argument. - # options:: Described below. - # - # ==== Options - # :desc - Description for the argument. - # :required - If the argument is required or not. - # :optional - If the argument is optional or not. - # :type - The type of the argument, can be :string, :hash, :array, :numeric. - # :default - Default value for this argument. It cannot be required and have default values. - # :banner - String to show on usage notes. - # - # ==== Errors - # ArgumentError:: Raised if you supply a required argument after a non required one. - # - def argument(name, options={}) - is_thor_reserved_word?(name, :argument) - no_tasks { attr_accessor name } - - required = if options.key?(:optional) - !options[:optional] - elsif options.key?(:required) - options[:required] - else - options[:default].nil? - end - - remove_argument name - - arguments.each do |argument| - next if argument.required? - raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " << - "the non-required argument #{argument.human_name.inspect}." - end if required - - arguments << Thor::Argument.new(name, options[:desc], required, options[:type], - options[:default], options[:banner]) - end - - # Returns this class arguments, looking up in the ancestors chain. - # - # ==== Returns - # Array[Thor::Argument] - # - def arguments - @arguments ||= from_superclass(:arguments, []) - end - - # Adds a bunch of options to the set of class options. - # - # class_options :foo => false, :bar => :required, :baz => :string - # - # If you prefer more detailed declaration, check class_option. - # - # ==== Parameters - # Hash[Symbol => Object] - # - def class_options(options=nil) - @class_options ||= from_superclass(:class_options, {}) - build_options(options, @class_options) if options - @class_options - end - - # Adds an option to the set of class options - # - # ==== Parameters - # name:: The name of the argument. - # options:: Described below. - # - # ==== Options - # :desc - Description for the argument. - # :required - If the argument is required or not. - # :default - Default value for this argument. - # :group - The group for this options. Use by class options to output options in different levels. - # :aliases - Aliases for this option. - # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. - # :banner - String to show on usage notes. - # - def class_option(name, options={}) - build_option(name, options, class_options) - end - - # Removes a previous defined argument. If :undefine is given, undefine - # accessors as well. - # - # ==== Paremeters - # names:: Arguments to be removed - # - # ==== Examples - # - # remove_argument :foo - # remove_argument :foo, :bar, :baz, :undefine => true - # - def remove_argument(*names) - options = names.last.is_a?(Hash) ? names.pop : {} - - names.each do |name| - arguments.delete_if { |a| a.name == name.to_s } - undef_method name, "#{name}=" if options[:undefine] - end - end - - # Removes a previous defined class option. - # - # ==== Paremeters - # names:: Class options to be removed - # - # ==== Examples - # - # remove_class_option :foo - # remove_class_option :foo, :bar, :baz - # - def remove_class_option(*names) - names.each do |name| - class_options.delete(name) - end - end - - # Defines the group. This is used when thor list is invoked so you can specify - # that only tasks from a pre-defined group will be shown. Defaults to standard. - # - # ==== Parameters - # name - # - def group(name=nil) - case name - when nil - @group ||= from_superclass(:group, 'standard') - else - @group = name.to_s - end - end - - # Returns the tasks for this Thor class. - # - # ==== Returns - # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task - # objects as values. - # - def tasks - @tasks ||= Thor::CoreExt::OrderedHash.new - end - - # Returns the tasks for this Thor class and all subclasses. - # - # ==== Returns - # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task - # objects as values. - # - def all_tasks - @all_tasks ||= from_superclass(:all_tasks, Thor::CoreExt::OrderedHash.new) - @all_tasks.merge(tasks) - end - - # Removes a given task from this Thor class. This is usually done if you - # are inheriting from another class and don't want it to be available - # anymore. - # - # By default it only remove the mapping to the task. But you can supply - # :undefine => true to undefine the method from the class as well. - # - # ==== Parameters - # name:: The name of the task to be removed - # options:: You can give :undefine => true if you want tasks the method - # to be undefined from the class as well. - # - def remove_task(*names) - options = names.last.is_a?(Hash) ? names.pop : {} - - names.each do |name| - tasks.delete(name.to_s) - all_tasks.delete(name.to_s) - undef_method name if options[:undefine] - end - end - - # All methods defined inside the given block are not added as tasks. - # - # So you can do: - # - # class MyScript < Thor - # no_tasks do - # def this_is_not_a_task - # end - # end - # end - # - # You can also add the method and remove it from the task list: - # - # class MyScript < Thor - # def this_is_not_a_task - # end - # remove_task :this_is_not_a_task - # end - # - def no_tasks - @no_tasks = true - yield - @no_tasks = false - end - - # Sets the namespace for the Thor or Thor::Group class. By default the - # namespace is retrieved from the class name. If your Thor class is named - # Scripts::MyScript, the help method, for example, will be called as: - # - # thor scripts:my_script -h - # - # If you change the namespace: - # - # namespace :my_scripts - # - # You change how your tasks are invoked: - # - # thor my_scripts -h - # - # Finally, if you change your namespace to default: - # - # namespace :default - # - # Your tasks can be invoked with a shortcut. Instead of: - # - # thor :my_task - # - def namespace(name=nil) - case name - when nil - @namespace ||= Thor::Util.namespace_from_thor_class(self, false) - else - @namespace = name.to_s - end - end - - # Default way to start generators from the command line. - # - def start(given_args=ARGV, config={}) - config[:shell] ||= Thor::Base.shell.new - yield - rescue Thor::Error => e - if given_args.include?("--debug") - raise e - else - config[:shell].error e.message - end - exit(1) if exit_on_failure? - end - - protected - - # Prints the class options per group. If an option does not belong to - # any group, it uses the ungrouped name value. This method provide to - # hooks to add extra options, one of them if the third argument called - # extra_group that should be a hash in the format :group => Array[Options]. - # - # The second is by returning a lambda used to print values. The lambda - # requires two options: the group name and the array of options. - # - def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc: - groups = {} - - class_options.each do |_, value| - groups[value.group] ||= [] - groups[value.group] << value - end - - printer = proc do |group_name, options| - list = [] - padding = options.collect{ |o| o.aliases.size }.max.to_i * 4 - - options.each do |option| - item = [ option.usage(padding) ] - item.push(option.description ? "# #{option.description}" : "") - - list << item - list << [ "", "# Default: #{option.default}" ] if option.show_default? - end - - unless list.empty? - shell.say(group_name ? "#{group_name} options:" : "Options:") - shell.print_table(list, :ident => 2) - shell.say "" - end - end - - # Deal with default group - global_options = groups.delete(nil) || [] - printer.call(ungrouped_name, global_options) if global_options - - # Print all others - groups = extra_group.merge(groups) if extra_group - groups.each(&printer) - printer - end - - # Raises an error if the word given is a Thor reserved word. - # - def is_thor_reserved_word?(word, type) #:nodoc: - return false unless THOR_RESERVED_WORDS.include?(word.to_s) - raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}" - end - - # Build an option and adds it to the given scope. - # - # ==== Parameters - # name:: The name of the argument. - # options:: Described in both class_option and method_option. - # - def build_option(name, options, scope) #:nodoc: - scope[name] = Thor::Option.new(name, options[:desc], options[:required], - options[:type], options[:default], options[:banner], - options[:group], options[:aliases]) - end - - # Receives a hash of options, parse them and add to the scope. This is a - # fast way to set a bunch of options: - # - # build_options :foo => true, :bar => :required, :baz => :string - # - # ==== Parameters - # Hash[Symbol => Object] - # - def build_options(options, scope) #:nodoc: - options.each do |key, value| - scope[key] = Thor::Option.parse(key, value) - end - end - - # Finds a task with the given name. If the task belongs to the current - # class, just return it, otherwise dup it and add the fresh copy to the - # current task hash. - # - def find_and_refresh_task(name) #:nodoc: - task = if task = tasks[name.to_s] - task - elsif task = all_tasks[name.to_s] - tasks[name.to_s] = task.clone - else - raise ArgumentError, "You supplied :for => #{name.inspect}, but the task #{name.inspect} could not be found." - end - end - - # Everytime someone inherits from a Thor class, register the klass - # and file into baseclass. - # - def inherited(klass) - Thor::Base.register_klass_file(klass) - end - - # Fire this callback whenever a method is added. Added methods are - # tracked as tasks by invoking the create_task method. - # - def method_added(meth) - meth = meth.to_s - - if meth == "initialize" - initialize_added - return - end - - # Return if it's not a public instance method - return unless public_instance_methods.include?(meth) || - public_instance_methods.include?(meth.to_sym) - - return if @no_tasks || !create_task(meth) - - is_thor_reserved_word?(meth, :task) - Thor::Base.register_klass_file(self) - end - - # Retrieves a value from superclass. If it reaches the baseclass, - # returns default. - # - def from_superclass(method, default=nil) - if self == baseclass || !superclass.respond_to?(method, true) - default - else - value = superclass.send(method) - value.dup if value - end - end - - # A flag that makes the process exit with status 1 if any error happens. - # - def exit_on_failure? - false - end - - # SIGNATURE: Sets the baseclass. This is where the superclass lookup - # finishes. - def baseclass #:nodoc: - end - - # SIGNATURE: Creates a new task if valid_task? is true. This method is - # called when a new method is added to the class. - def create_task(meth) #:nodoc: - end - - # SIGNATURE: Defines behavior when the initialize method is added to the - # class. - def initialize_added #:nodoc: - end - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/hash_with_indifferent_access.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/hash_with_indifferent_access.rb deleted file mode 100644 index 40d201d9e4..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/hash_with_indifferent_access.rb +++ /dev/null @@ -1,75 +0,0 @@ -class Thor - module CoreExt #:nodoc: - - # A hash with indifferent access and magic predicates. - # - # hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true - # - # hash[:foo] #=> 'bar' - # hash['foo'] #=> 'bar' - # hash.foo? #=> true - # - class HashWithIndifferentAccess < ::Hash #:nodoc: - - def initialize(hash={}) - super() - hash.each do |key, value| - self[convert_key(key)] = value - end - end - - def [](key) - super(convert_key(key)) - end - - def []=(key, value) - super(convert_key(key), value) - end - - def delete(key) - super(convert_key(key)) - end - - def values_at(*indices) - indices.collect { |key| self[convert_key(key)] } - end - - def merge(other) - dup.merge!(other) - end - - def merge!(other) - other.each do |key, value| - self[convert_key(key)] = value - end - self - end - - protected - - def convert_key(key) - key.is_a?(Symbol) ? key.to_s : key - end - - # Magic predicates. For instance: - # - # options.force? # => !!options['force'] - # options.shebang # => "/usr/lib/local/ruby" - # options.test_framework?(:rspec) # => options[:test_framework] == :rspec - # - def method_missing(method, *args, &block) - method = method.to_s - if method =~ /^(\w+)\?$/ - if args.empty? - !!self[$1] - else - self[$1] == args.first - end - else - self[method] - end - end - - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/ordered_hash.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/ordered_hash.rb deleted file mode 100644 index 27fea5bb35..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/core_ext/ordered_hash.rb +++ /dev/null @@ -1,100 +0,0 @@ -class Thor - module CoreExt #:nodoc: - - if RUBY_VERSION >= '1.9' - class OrderedHash < ::Hash - end - else - # This class is based on the Ruby 1.9 ordered hashes. - # - # It keeps the semantics and most of the efficiency of normal hashes - # while also keeping track of the order in which elements were set. - # - class OrderedHash #:nodoc: - include Enumerable - - Node = Struct.new(:key, :value, :next, :prev) - - def initialize - @hash = {} - end - - def [](key) - @hash[key] && @hash[key].value - end - - def []=(key, value) - if node = @hash[key] - node.value = value - else - node = Node.new(key, value) - - if @first.nil? - @first = @last = node - else - node.prev = @last - @last.next = node - @last = node - end - end - - @hash[key] = node - value - end - - def delete(key) - if node = @hash[key] - prev_node = node.prev - next_node = node.next - - next_node.prev = prev_node if next_node - prev_node.next = next_node if prev_node - - @first = next_node if @first == node - @last = prev_node if @last == node - - value = node.value - end - - @hash.delete(key) - value - end - - def keys - self.map { |k, v| k } - end - - def values - self.map { |k, v| v } - end - - def each - return unless @first - yield [@first.key, @first.value] - node = @first - yield [node.key, node.value] while node = node.next - self - end - - def merge(other) - hash = self.class.new - - self.each do |key, value| - hash[key] = value - end - - other.each do |key, value| - hash[key] = value - end - - hash - end - - def empty? - @hash.empty? - end - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/error.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/error.rb deleted file mode 100644 index f9b31a35d1..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/error.rb +++ /dev/null @@ -1,27 +0,0 @@ -class Thor - # Thor::Error is raised when it's caused by wrong usage of thor classes. Those - # errors have their backtrace supressed and are nicely shown to the user. - # - # Errors that are caused by the developer, like declaring a method which - # overwrites a thor keyword, it SHOULD NOT raise a Thor::Error. This way, we - # ensure that developer errors are shown with full backtrace. - # - class Error < StandardError - end - - # Raised when a task was not found. - # - class UndefinedTaskError < Error - end - - # Raised when a task was found, but not invoked properly. - # - class InvocationError < Error - end - - class RequiredArgumentMissingError < InvocationError - end - - class MalformattedArgumentError < InvocationError - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/group.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/group.rb deleted file mode 100644 index 021a067a3e..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/group.rb +++ /dev/null @@ -1,263 +0,0 @@ -# Thor has a special class called Thor::Group. The main difference to Thor class -# is that it invokes all tasks at once. It also include some methods that allows -# invocations to be done at the class method, which are not available to Thor -# tasks. -# -class Thor::Group - class << self - # The descrition for this Thor::Group. If none is provided, but a source root - # exists, tries to find the USAGE one folder above it, otherwise searches - # in the superclass. - # - # ==== Parameters - # description:: The description for this Thor::Group. - # - def desc(description=nil) - case description - when nil - @desc ||= from_superclass(:desc, nil) - else - @desc = description - end - end - - # Start works differently in Thor::Group, it simply invokes all tasks - # inside the class. - # - def start(given_args=ARGV, config={}) - super do - if Thor::HELP_MAPPINGS.include?(given_args.first) - help(config[:shell]) - return - end - - args, opts = Thor::Options.split(given_args) - new(args, opts, config).invoke - end - end - - # Prints help information. - # - # ==== Options - # short:: When true, shows only usage. - # - def help(shell, options={}) - if options[:short] - shell.say banner - else - shell.say "Usage:" - shell.say " #{banner}" - shell.say - class_options_help(shell) - shell.say self.desc if self.desc - end - end - - # Stores invocations for this class merging with superclass values. - # - def invocations #:nodoc: - @invocations ||= from_superclass(:invocations, {}) - end - - # Stores invocation blocks used on invoke_from_option. - # - def invocation_blocks #:nodoc: - @invocation_blocks ||= from_superclass(:invocation_blocks, {}) - end - - # Invoke the given namespace or class given. It adds an instance - # method that will invoke the klass and task. You can give a block to - # configure how it will be invoked. - # - # The namespace/class given will have its options showed on the help - # usage. Check invoke_from_option for more information. - # - def invoke(*names, &block) - options = names.last.is_a?(Hash) ? names.pop : {} - verbose = options.fetch(:verbose, true) - - names.each do |name| - invocations[name] = false - invocation_blocks[name] = block if block_given? - - class_eval <<-METHOD, __FILE__, __LINE__ - def _invoke_#{name.to_s.gsub(/\W/, '_')} - klass, task = self.class.prepare_for_invocation(nil, #{name.inspect}) - - if klass - say_status :invoke, #{name.inspect}, #{verbose.inspect} - block = self.class.invocation_blocks[#{name.inspect}] - _invoke_for_class_method klass, task, &block - else - say_status :error, %(#{name.inspect} [not found]), :red - end - end - METHOD - end - end - - # Invoke a thor class based on the value supplied by the user to the - # given option named "name". A class option must be created before this - # method is invoked for each name given. - # - # ==== Examples - # - # class GemGenerator < Thor::Group - # class_option :test_framework, :type => :string - # invoke_from_option :test_framework - # end - # - # ==== Boolean options - # - # In some cases, you want to invoke a thor class if some option is true or - # false. This is automatically handled by invoke_from_option. Then the - # option name is used to invoke the generator. - # - # ==== Preparing for invocation - # - # In some cases you want to customize how a specified hook is going to be - # invoked. You can do that by overwriting the class method - # prepare_for_invocation. The class method must necessarily return a klass - # and an optional task. - # - # ==== Custom invocations - # - # You can also supply a block to customize how the option is giong to be - # invoked. The block receives two parameters, an instance of the current - # class and the klass to be invoked. - # - def invoke_from_option(*names, &block) - options = names.last.is_a?(Hash) ? names.pop : {} - verbose = options.fetch(:verbose, :white) - - names.each do |name| - unless class_options.key?(name) - raise ArgumentError, "You have to define the option #{name.inspect} " << - "before setting invoke_from_option." - end - - invocations[name] = true - invocation_blocks[name] = block if block_given? - - class_eval <<-METHOD, __FILE__, __LINE__ - def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')} - return unless options[#{name.inspect}] - - value = options[#{name.inspect}] - value = #{name.inspect} if TrueClass === value - klass, task = self.class.prepare_for_invocation(#{name.inspect}, value) - - if klass - say_status :invoke, value, #{verbose.inspect} - block = self.class.invocation_blocks[#{name.inspect}] - _invoke_for_class_method klass, task, &block - else - say_status :error, %(\#{value} [not found]), :red - end - end - METHOD - end - end - - # Remove a previously added invocation. - # - # ==== Examples - # - # remove_invocation :test_framework - # - def remove_invocation(*names) - names.each do |name| - remove_task(name) - remove_class_option(name) - invocations.delete(name) - invocation_blocks.delete(name) - end - end - - # Overwrite class options help to allow invoked generators options to be - # shown recursively when invoking a generator. - # - def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc: - group_options = {} - - get_options_from_invocations(group_options, class_options) do |klass| - klass.send(:get_options_from_invocations, group_options, class_options) - end - - group_options.merge!(extra_group) if extra_group - super(shell, ungrouped_name, group_options) - end - - # Get invocations array and merge options from invocations. Those - # options are added to group_options hash. Options that already exists - # in base_options are not added twice. - # - def get_options_from_invocations(group_options, base_options) #:nodoc: - invocations.each do |name, from_option| - value = if from_option - option = class_options[name] - option.type == :boolean ? name : option.default - else - name - end - next unless value - - klass, task = prepare_for_invocation(name, value) - next unless klass && klass.respond_to?(:class_options) - - value = value.to_s - human_name = value.respond_to?(:classify) ? value.classify : value - - group_options[human_name] ||= [] - group_options[human_name] += klass.class_options.values.select do |option| - base_options[option.name.to_sym].nil? && option.group.nil? && - !group_options.values.flatten.any? { |i| i.name == option.name } - end - - yield klass if block_given? - end - end - - protected - - # The banner for this class. You can customize it if you are invoking the - # thor class by another ways which is not the Thor::Runner. - # - def banner - "#{self.namespace} #{self.arguments.map {|a| a.usage }.join(' ')}" - end - - def baseclass #:nodoc: - Thor::Group - end - - def create_task(meth) #:nodoc: - tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil) - true - end - end - - include Thor::Base - - protected - - # Shortcut to invoke with padding and block handling. Use internally by - # invoke and invoke_from_option class methods. - # - def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc: - shell.padding += 1 - - result = if block_given? - if block.arity == 2 - block.call(self, klass) - else - block.call(self, klass, task) - end - else - invoke klass, task, *args - end - - shell.padding -= 1 - result - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/invocation.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/invocation.rb deleted file mode 100644 index 32e6a72454..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/invocation.rb +++ /dev/null @@ -1,178 +0,0 @@ -class Thor - module Invocation - def self.included(base) #:nodoc: - base.extend ClassMethods - end - - module ClassMethods - # Prepare for class methods invocations. This method must return a klass to - # have the invoked class options showed in help messages in generators. - # - def prepare_for_invocation(key, name) #:nodoc: - case name - when Symbol, String - Thor::Util.namespace_to_thor_class_and_task(name.to_s, false) - else - name - end - end - end - - # Make initializer aware of invocations and the initializer proc. - # - def initialize(args=[], options={}, config={}, &block) #:nodoc: - @_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] } - @_initializer = [ args, options, config ] - super - end - - # Receives a name and invokes it. The name can be a string (either "task" or - # "namespace:task"), a Thor::Task, a Class or a Thor instance. If the task - # cannot be guessed by name, it can also be supplied as second argument. - # - # You can also supply the arguments, options and configuration values for - # the task to be invoked, if none is given, the same values used to - # initialize the invoker are used to initialize the invoked. - # - # ==== Examples - # - # class A < Thor - # def foo - # invoke :bar - # invoke "b:hello", ["José"] - # end - # - # def bar - # invoke "b:hello", ["José"] - # end - # end - # - # class B < Thor - # def hello(name) - # puts "hello #{name}" - # end - # end - # - # You can notice that the method "foo" above invokes two tasks: "bar", - # which belongs to the same class and "hello" which belongs to the class B. - # - # By using an invocation system you ensure that a task is invoked only once. - # In the example above, invoking "foo" will invoke "b:hello" just once, even - # if it's invoked later by "bar" method. - # - # When class A invokes class B, all arguments used on A initialization are - # supplied to B. This allows lazy parse of options. Let's suppose you have - # some rspec tasks: - # - # class Rspec < Thor::Group - # class_option :mock_framework, :type => :string, :default => :rr - # - # def invoke_mock_framework - # invoke "rspec:#{options[:mock_framework]}" - # end - # end - # - # As you noticed, it invokes the given mock framework, which might have its - # own options: - # - # class Rspec::RR < Thor::Group - # class_option :style, :type => :string, :default => :mock - # end - # - # Since it's not rspec concern to parse mock framework options, when RR - # is invoked all options are parsed again, so RR can extract only the options - # that it's going to use. - # - # If you want Rspec::RR to be initialized with its own set of options, you - # have to do that explicitely: - # - # invoke "rspec:rr", [], :style => :foo - # - # Besides giving an instance, you can also give a class to invoke: - # - # invoke Rspec::RR, [], :style => :foo - # - def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil) - task, args, opts, config = nil, task, args, opts if task.nil? || task.is_a?(Array) - args, opts, config = nil, args, opts if args.is_a?(Hash) - - object, task = _prepare_for_invocation(name, task) - klass, instance = _initialize_klass_with_initializer(object, args, opts, config) - - method_args = [] - current = @_invocations[klass] - - iterator = proc do |_, task| - unless current.include?(task.name) - current << task.name - task.run(instance, method_args) - end - end - - if task - args ||= [] - method_args = args[Range.new(klass.arguments.size, -1)] || [] - iterator.call(nil, task) - else - klass.all_tasks.map(&iterator) - end - end - - protected - - # Configuration values that are shared between invocations. - # - def _shared_configuration #:nodoc: - { :invocations => @_invocations } - end - - # Prepare for invocation in the instance level. In this case, we have to - # take into account that a just a task name from the current class was - # given or even a Thor::Task object. - # - def _prepare_for_invocation(name, sent_task=nil) #:nodoc: - if name.is_a?(Thor::Task) - task = name - elsif task = self.class.all_tasks[name.to_s] - object = self - else - object, task = self.class.prepare_for_invocation(nil, name) - task ||= sent_task - end - - # If the object was not set, use self and use the name as task. - object, task = self, name unless object - return object, _validate_task(object, task) - end - - # Check if the object given is a Thor class object and get a task object - # for it. - # - def _validate_task(object, task) #:nodoc: - klass = object.is_a?(Class) ? object : object.class - raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base - - task ||= klass.default_task if klass <= Thor - task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task) - task - end - - # Initialize klass using values stored in the @_initializer. - # - def _initialize_klass_with_initializer(object, args, opts, config) #:nodoc: - if object.is_a?(Class) - klass = object - - stored_args, stored_opts, stored_config = @_initializer - args ||= stored_args.dup - opts ||= stored_opts.dup - - config ||= {} - config = stored_config.merge(_shared_configuration).merge!(config) - [ klass, klass.new(args, opts, config) ] - else - [ object.class, object ] - end - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser.rb deleted file mode 100644 index 57a3f6e1a5..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'thor/parser/argument' -require 'thor/parser/arguments' -require 'thor/parser/option' -require 'thor/parser/options' diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/argument.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/argument.rb deleted file mode 100644 index aa8ace4719..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/argument.rb +++ /dev/null @@ -1,67 +0,0 @@ -class Thor - class Argument #:nodoc: - VALID_TYPES = [ :numeric, :hash, :array, :string ] - - attr_reader :name, :description, :required, :type, :default, :banner - alias :human_name :name - - def initialize(name, description=nil, required=true, type=:string, default=nil, banner=nil) - class_name = self.class.name.split("::").last - - raise ArgumentError, "#{class_name} name can't be nil." if name.nil? - raise ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type) - - @name = name.to_s - @description = description - @required = required || false - @type = (type || :string).to_sym - @default = default - @banner = banner || default_banner - - validate! # Trigger specific validations - end - - def usage - required? ? banner : "[#{banner}]" - end - - def required? - required - end - - def show_default? - case default - when Array, String, Hash - !default.empty? - else - default - end - end - - protected - - def validate! - raise ArgumentError, "An argument cannot be required and have default value." if required? && !default.nil? - end - - def valid_type?(type) - VALID_TYPES.include?(type.to_sym) - end - - def default_banner - case type - when :boolean - nil - when :string, :default - human_name.upcase - when :numeric - "N" - when :hash - "key:value" - when :array - "one two three" - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/arguments.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/arguments.rb deleted file mode 100644 index fb5d965e06..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/arguments.rb +++ /dev/null @@ -1,145 +0,0 @@ -class Thor - class Arguments #:nodoc: - NUMERIC = /(\d*\.\d+|\d+)/ - - # Receives an array of args and returns two arrays, one with arguments - # and one with switches. - # - def self.split(args) - arguments = [] - - args.each do |item| - break if item =~ /^-/ - arguments << item - end - - return arguments, args[Range.new(arguments.size, -1)] - end - - def self.parse(base, args) - new(base).parse(args) - end - - # Takes an array of Thor::Argument objects. - # - def initialize(arguments=[]) - @assigns, @non_assigned_required = {}, [] - @switches = arguments - - arguments.each do |argument| - if argument.default - @assigns[argument.human_name] = argument.default - elsif argument.required? - @non_assigned_required << argument - end - end - end - - def parse(args) - @pile = args.dup - - @switches.each do |argument| - break unless peek - @non_assigned_required.delete(argument) - @assigns[argument.human_name] = send(:"parse_#{argument.type}", argument.human_name) - end - - check_requirement! - @assigns - end - - private - - def peek - @pile.first - end - - def shift - @pile.shift - end - - def unshift(arg) - unless arg.kind_of?(Array) - @pile.unshift(arg) - else - @pile = arg + @pile - end - end - - def current_is_value? - peek && peek.to_s !~ /^-/ - end - - # Runs through the argument array getting strings that contains ":" and - # mark it as a hash: - # - # [ "name:string", "age:integer" ] - # - # Becomes: - # - # { "name" => "string", "age" => "integer" } - # - def parse_hash(name) - return shift if peek.is_a?(Hash) - hash = {} - - while current_is_value? && peek.include?(?:) - key, value = shift.split(':') - hash[key] = value - end - hash - end - - # Runs through the argument array getting all strings until no string is - # found or a switch is found. - # - # ["a", "b", "c"] - # - # And returns it as an array: - # - # ["a", "b", "c"] - # - def parse_array(name) - return shift if peek.is_a?(Array) - array = [] - - while current_is_value? - array << shift - end - array - end - - # Check if the peel is numeric ofrmat and return a Float or Integer. - # Otherwise raises an error. - # - def parse_numeric(name) - return shift if peek.is_a?(Numeric) - - unless peek =~ NUMERIC && $& == peek - raise MalformattedArgumentError, "expected numeric value for '#{name}'; got #{peek.inspect}" - end - - $&.index('.') ? shift.to_f : shift.to_i - end - - # Parse string, i.e., just return the current value in the pile. - # - def parse_string(name) - shift - end - - # Raises an error if @non_assigned_required array is not empty. - # - def check_requirement! - unless @non_assigned_required.empty? - names = @non_assigned_required.map do |o| - o.respond_to?(:switch_name) ? o.switch_name : o.human_name - end.join("', '") - - class_name = self.class.name.split('::').last.downcase - raise RequiredArgumentMissingError, "no value provided for required #{class_name} '#{names}'" - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/option.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/option.rb deleted file mode 100644 index e09b4901e2..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/option.rb +++ /dev/null @@ -1,132 +0,0 @@ -class Thor - class Option < Argument #:nodoc: - attr_reader :aliases, :group - - VALID_TYPES = [:boolean, :numeric, :hash, :array, :string] - - def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, group=nil, aliases=nil) - super(name, description, required, type, default, banner) - @aliases = [*aliases].compact - @group = group.to_s.capitalize if group - end - - # This parse quick options given as method_options. It makes several - # assumptions, but you can be more specific using the option method. - # - # parse :foo => "bar" - # #=> Option foo with default value bar - # - # parse [:foo, :baz] => "bar" - # #=> Option foo with default value bar and alias :baz - # - # parse :foo => :required - # #=> Required option foo without default value - # - # parse :foo => 2 - # #=> Option foo with default value 2 and type numeric - # - # parse :foo => :numeric - # #=> Option foo without default value and type numeric - # - # parse :foo => true - # #=> Option foo with default value true and type boolean - # - # The valid types are :boolean, :numeric, :hash, :array and :string. If none - # is given a default type is assumed. This default type accepts arguments as - # string (--foo=value) or booleans (just --foo). - # - # By default all options are optional, unless :required is given. - # - def self.parse(key, value) - if key.is_a?(Array) - name, *aliases = key - else - name, aliases = key, [] - end - - name = name.to_s - default = value - - type = case value - when Symbol - default = nil - - if VALID_TYPES.include?(value) - value - elsif required = (value == :required) - :string - elsif value == :optional - # TODO Remove this warning in the future. - warn "Optional type is deprecated. Choose :boolean or :string instead. Assumed to be :boolean." - :boolean - end - when TrueClass, FalseClass - :boolean - when Numeric - :numeric - when Hash, Array, String - value.class.name.downcase.to_sym - end - - self.new(name.to_s, nil, required, type, default, nil, nil, aliases) - end - - def switch_name - @switch_name ||= dasherized? ? name : dasherize(name) - end - - def human_name - @human_name ||= dasherized? ? undasherize(name) : name - end - - def usage(padding=0) - sample = if banner && !banner.to_s.empty? - "#{switch_name}=#{banner}" - else - switch_name - end - - sample = "[#{sample}]" unless required? - - if aliases.empty? - (" " * padding) << sample - else - "#{aliases.join(', ')}, #{sample}" - end - end - - # Allow some type predicates as: boolean?, string? and etc. - # - def method_missing(method, *args, &block) - given = method.to_s.sub(/\?$/, '').to_sym - if valid_type?(given) - self.type == given - else - super - end - end - - protected - - def validate! - raise ArgumentError, "An option cannot be boolean and required." if boolean? && required? - end - - def valid_type?(type) - VALID_TYPES.include?(type.to_sym) - end - - def dasherized? - name.index('-') == 0 - end - - def undasherize(str) - str.sub(/^-{1,2}/, '') - end - - def dasherize(str) - (str.length > 1 ? "--" : "-") + str.gsub('_', '-') - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/options.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/options.rb deleted file mode 100644 index 75092308b5..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/parser/options.rb +++ /dev/null @@ -1,142 +0,0 @@ -class Thor - # This is a modified version of Daniel Berger's Getopt::Long class, licensed - # under Ruby's license. - # - class Options < Arguments #:nodoc: - LONG_RE = /^(--\w+[-\w+]*)$/ - SHORT_RE = /^(-[a-z])$/i - EQ_RE = /^(--\w+[-\w+]*|-[a-z])=(.*)$/i - SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args - SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i - - # Receives a hash and makes it switches. - # - def self.to_switches(options) - options.map do |key, value| - case value - when true - "--#{key}" - when Array - "--#{key} #{value.map{ |v| v.inspect }.join(' ')}" - when Hash - "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}" - when nil, false - "" - else - "--#{key} #{value.inspect}" - end - end.join(" ") - end - - # Takes a hash of Thor::Option objects. - # - def initialize(options={}) - options = options.values - super(options) - @shorts, @switches = {}, {} - - options.each do |option| - @switches[option.switch_name] = option - - option.aliases.each do |short| - @shorts[short.to_s] ||= option.switch_name - end - end - end - - def parse(args) - @pile = args.dup - - while peek - if current_is_switch? - case shift - when SHORT_SQ_RE - unshift($1.split('').map { |f| "-#{f}" }) - next - when EQ_RE, SHORT_NUM - unshift($2) - switch = $1 - when LONG_RE, SHORT_RE - switch = $1 - end - - switch = normalize_switch(switch) - next unless option = switch_option(switch) - - @assigns[option.human_name] = parse_peek(switch, option) - else - shift - end - end - - check_requirement! - @assigns - end - - protected - - # Returns true if the current value in peek is a registered switch. - # - def current_is_switch? - case peek - when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM - switch?($1) - when SHORT_SQ_RE - $1.split('').any? { |f| switch?("-#{f}") } - end - end - - def switch?(arg) - switch_option(arg) || @shorts.key?(arg) - end - - def switch_option(arg) - if match = no_or_skip?(arg) - @switches[arg] || @switches["--#{match}"] - else - @switches[arg] - end - end - - def no_or_skip?(arg) - arg =~ /^--(no|skip)-([-\w]+)$/ - $2 - end - - # Check if the given argument is actually a shortcut. - # - def normalize_switch(arg) - @shorts.key?(arg) ? @shorts[arg] : arg - end - - # Parse boolean values which can be given as --foo=true, --foo or --no-foo. - # - def parse_boolean(switch) - if current_is_value? - ["true", "TRUE", "t", "T", true].include?(shift) - else - @switches.key?(switch) || !no_or_skip?(switch) - end - end - - # Parse the value at the peek analyzing if it requires an input or not. - # - def parse_peek(switch, option) - unless current_is_value? - if option.boolean? - # No problem for boolean types - elsif no_or_skip?(switch) - return nil # User set value to nil - elsif option.string? && !option.required? - return option.human_name # Return the option name - else - raise MalformattedArgumentError, "no value provided for option '#{switch}'" - end - end - - @non_assigned_required.delete(option) - send(:"parse_#{option.type}", switch) - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/rake_compat.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/rake_compat.rb deleted file mode 100644 index 0d0757fdda..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/rake_compat.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'rake' - -class Thor - # Adds a compatibility layer to your Thor classes which allows you to use - # rake package tasks. For example, to use rspec rake tasks, one can do: - # - # require 'thor/rake_compat' - # - # class Default < Thor - # include Thor::RakeCompat - # - # Spec::Rake::SpecTask.new(:spec) do |t| - # t.spec_opts = ['--options', "spec/spec.opts"] - # t.spec_files = FileList['spec/**/*_spec.rb'] - # end - # end - # - module RakeCompat - def self.rake_classes - @rake_classes ||= [] - end - - def self.included(base) - # Hack. Make rakefile point to invoker, so rdoc task is generated properly. - rakefile = File.basename(caller[0].match(/(.*):\d+/)[1]) - Rake.application.instance_variable_set(:@rakefile, rakefile) - self.rake_classes << base - end - end -end - -class Object #:nodoc: - alias :rake_task :task - alias :rake_namespace :namespace - - def task(*args, &block) - task = rake_task(*args, &block) - - if klass = Thor::RakeCompat.rake_classes.last - non_namespaced_name = task.name.split(':').last - - description = non_namespaced_name - description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ') - description.strip! - - klass.desc description, task.comment || non_namespaced_name - klass.send :define_method, non_namespaced_name do |*args| - Rake::Task[task.name.to_sym].invoke(*args) - end - end - - task - end - - def namespace(name, &block) - if klass = Thor::RakeCompat.rake_classes.last - const_name = Thor::Util.camel_case(name.to_s).to_sym - klass.const_set(const_name, Class.new(Thor)) - new_klass = klass.const_get(const_name) - Thor::RakeCompat.rake_classes << new_klass - end - - rake_namespace(name, &block) - Thor::RakeCompat.rake_classes.pop - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/runner.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/runner.rb deleted file mode 100644 index 079f9e0c65..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/runner.rb +++ /dev/null @@ -1,299 +0,0 @@ -require 'fileutils' -require 'open-uri' -require 'yaml' -require 'digest/md5' -require 'pathname' - -class Thor::Runner < Thor #:nodoc: - map "-T" => :list, "-i" => :install, "-u" => :update - - # Override Thor#help so it can give information about any class and any method. - # - def help(meth=nil) - if meth && !self.respond_to?(meth) - initialize_thorfiles(meth) - klass, task = Thor::Util.namespace_to_thor_class_and_task(meth) - # Send mapping -h because it works with Thor::Group too - klass.start(["-h", task].compact, :shell => self.shell) - else - super - end - end - - # If a task is not found on Thor::Runner, method missing is invoked and - # Thor::Runner is then responsable for finding the task in all classes. - # - def method_missing(meth, *args) - meth = meth.to_s - initialize_thorfiles(meth) - klass, task = Thor::Util.namespace_to_thor_class_and_task(meth) - args.unshift(task) if task - klass.start(args, :shell => shell) - end - - desc "install NAME", "Install an optionally named Thor file into your system tasks" - method_options :as => :string, :relative => :boolean - def install(name) - initialize_thorfiles - - # If a directory name is provided as the argument, look for a 'main.thor' - # task in said directory. - begin - if File.directory?(File.expand_path(name)) - base, package = File.join(name, "main.thor"), :directory - contents = open(base).read - else - base, package = name, :file - contents = open(name).read - end - rescue OpenURI::HTTPError - raise Error, "Error opening URI '#{name}'" - rescue Errno::ENOENT - raise Error, "Error opening file '#{name}'" - end - - say "Your Thorfile contains:" - say contents - - return false if no?("Do you wish to continue [y/N]?") - - as = options["as"] || begin - first_line = contents.split("\n")[0] - (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil - end - - unless as - basename = File.basename(name) - as = ask("Please specify a name for #{name} in the system repository [#{basename}]:") - as = basename if as.empty? - end - - location = if options[:relative] || name =~ /^http:\/\// - name - else - File.expand_path(name) - end - - thor_yaml[as] = { - :filename => Digest::MD5.hexdigest(name + as), - :location => location, - :namespaces => Thor::Util.namespaces_in_content(contents, base) - } - - save_yaml(thor_yaml) - say "Storing thor file in your system repository" - destination = File.join(thor_root, thor_yaml[as][:filename]) - - if package == :file - File.open(destination, "w") { |f| f.puts contents } - else - FileUtils.cp_r(name, destination) - end - - thor_yaml[as][:filename] # Indicate success - end - - desc "uninstall NAME", "Uninstall a named Thor module" - def uninstall(name) - raise Error, "Can't find module '#{name}'" unless thor_yaml[name] - say "Uninstalling #{name}." - FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}")) - - thor_yaml.delete(name) - save_yaml(thor_yaml) - - puts "Done." - end - - desc "update NAME", "Update a Thor file from its original location" - def update(name) - raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location] - - say "Updating '#{name}' from #{thor_yaml[name][:location]}" - - old_filename = thor_yaml[name][:filename] - self.options = self.options.merge("as" => name) - filename = install(thor_yaml[name][:location]) - - unless filename == old_filename - File.delete(File.join(thor_root, old_filename)) - end - end - - desc "installed", "List the installed Thor modules and tasks" - method_options :internal => :boolean - def installed - initialize_thorfiles(nil, true) - - klasses = Thor::Base.subclasses - klasses -= [Thor, Thor::Runner] unless options["internal"] - - display_klasses(true, klasses) - end - - desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)" - method_options :substring => :boolean, :group => :string, :all => :boolean - def list(search="") - initialize_thorfiles - - search = ".*#{search}" if options["substring"] - search = /^#{search}.*/i - group = options[:group] || "standard" - - klasses = Thor::Base.subclasses.select do |k| - (options[:all] || k.group == group) && k.namespace =~ search - end - - display_klasses(false, klasses) - end - - private - - def thor_root - Thor::Util.thor_root - end - - def thor_yaml - @thor_yaml ||= begin - yaml_file = File.join(thor_root, "thor.yml") - yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file) - yaml || {} - end - end - - # Save the yaml file. If none exists in thor root, creates one. - # - def save_yaml(yaml) - yaml_file = File.join(thor_root, "thor.yml") - - unless File.exists?(yaml_file) - FileUtils.mkdir_p(thor_root) - yaml_file = File.join(thor_root, "thor.yml") - FileUtils.touch(yaml_file) - end - - File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml } - end - - def self.exit_on_failure? - true - end - - # Load the thorfiles. If relevant_to is supplied, looks for specific files - # in the thor_root instead of loading them all. - # - # By default, it also traverses the current path until find Thor files, as - # described in thorfiles. This look up can be skipped by suppliying - # skip_lookup true. - # - def initialize_thorfiles(relevant_to=nil, skip_lookup=false) - thorfiles(relevant_to, skip_lookup).each do |f| - Thor::Util.load_thorfile(f) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f)) - end - end - - # Finds Thorfiles by traversing from your current directory down to the root - # directory of your system. If at any time we find a Thor file, we stop. - # - # We also ensure that system-wide Thorfiles are loaded first, so local - # Thorfiles can override them. - # - # ==== Example - # - # If we start at /Users/wycats/dev/thor ... - # - # 1. /Users/wycats/dev/thor - # 2. /Users/wycats/dev - # 3. /Users/wycats <-- we find a Thorfile here, so we stop - # - # Suppose we start at c:\Documents and Settings\james\dev\thor ... - # - # 1. c:\Documents and Settings\james\dev\thor - # 2. c:\Documents and Settings\james\dev - # 3. c:\Documents and Settings\james - # 4. c:\Documents and Settings - # 5. c:\ <-- no Thorfiles found! - # - def thorfiles(relevant_to=nil, skip_lookup=false) - # TODO Remove this dealing with deprecated thor when :namespaces: is available as constants - save_yaml(thor_yaml) if Thor::Util.convert_constants_to_namespaces(thor_yaml) - - thorfiles = [] - - unless skip_lookup - Pathname.pwd.ascend do |path| - thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten - break unless thorfiles.empty? - end - end - - files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob) - files += thorfiles - files -= ["#{thor_root}/thor.yml"] - - files.map! do |file| - File.directory?(file) ? File.join(file, "main.thor") : file - end - end - - # Load thorfiles relevant to the given method. If you provide "foo:bar" it - # will load all thor files in the thor.yaml that has "foo" e "foo:bar" - # namespaces registered. - # - def thorfiles_relevant_to(meth) - lookup = [ meth, meth.split(":")[0...-1].join(":") ] - - files = thor_yaml.select do |k, v| - v[:namespaces] && !(v[:namespaces] & lookup).empty? - end - - files.map { |k, v| File.join(thor_root, "#{v[:filename]}") } - end - - # Display information about the given klasses. If with_module is given, - # it shows a table with information extracted from the yaml file. - # - def display_klasses(with_modules=false, klasses=Thor.subclasses) - klasses -= [Thor, Thor::Runner] unless with_modules - raise Error, "No Thor tasks available" if klasses.empty? - - if with_modules && !thor_yaml.empty? - info = [] - labels = ["Modules", "Namespaces"] - - info << labels - info << [ "-" * labels[0].size, "-" * labels[1].size ] - - thor_yaml.each do |name, hash| - info << [ name, hash[:namespaces].join(", ") ] - end - - print_table info - say "" - end - - unless klasses.empty? - klasses.dup.each do |klass| - klasses -= Thor::Util.thor_classes_in(klass) - end - - klasses.each { |k| display_tasks(k) } - else - say "\033[1;34mNo Thor tasks available\033[0m" - end - end - - # Display tasks from the given Thor class. - # - def display_tasks(klass) - unless klass.tasks.empty? - base = klass.namespace - - color = base == "default" ? :magenta : :blue - say shell.set_color(base, color, true) - say "-" * base.length - - klass.help(shell, :short => true, :ident => 0, :namespace => true) - end - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb deleted file mode 100644 index 1dc8f0e5b4..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell.rb +++ /dev/null @@ -1,78 +0,0 @@ -require 'rbconfig' -require 'thor/shell/color' - -class Thor - module Base - # Returns the shell used in all Thor classes. If you are in a Unix platform - # it will use a colored log, otherwise it will use a basic one without color. - # - def self.shell - @shell ||= if Config::CONFIG['host_os'] =~ /mswin|mingw/ - Thor::Shell::Basic - else - Thor::Shell::Color - end - end - - # Sets the shell used in all Thor classes. - # - def self.shell=(klass) - @shell = klass - end - end - - module Shell - SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_list, :print_table] - - # Add shell to initialize config values. - # - # ==== Configuration - # shell:: An instance of the shell to be used. - # - # ==== Examples - # - # class MyScript < Thor - # argument :first, :type => :numeric - # end - # - # MyScript.new [1.0], { :foo => :bar }, :shell => Thor::Shell::Basic.new - # - def initialize(args=[], options={}, config={}) - super - self.shell = config[:shell] - self.shell.base ||= self if self.shell.respond_to?(:base) - end - - # Holds the shell for the given Thor instance. If no shell is given, - # it gets a default shell from Thor::Base.shell. - # - def shell - @shell ||= Thor::Base.shell.new - end - - # Sets the shell for this thor class. - # - def shell=(shell) - @shell = shell - end - - # Common methods that are delegated to the shell. - # - SHELL_DELEGATED_METHODS.each do |method| - module_eval <<-METHOD, __FILE__, __LINE__ - def #{method}(*args) - shell.#{method}(*args) - end - METHOD - end - - protected - - # Allow shell to be shared between invocations. - # - def _shared_configuration #:nodoc: - super.merge!(:shell => self.shell) - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/basic.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/basic.rb deleted file mode 100644 index f6be3575ca..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/shell/basic.rb +++ /dev/null @@ -1,219 +0,0 @@ -require 'tempfile' - -class Thor - module Shell - class Basic - attr_accessor :base, :padding - - # Initialize base and padding to nil. - # - def initialize #:nodoc: - @base, @padding = nil, 0 - end - - # Sets the output padding, not allowing less than zero values. - # - def padding=(value) - @padding = [0, value].max - end - - # Ask something to the user and receives a response. - # - # ==== Example - # ask("What is your name?") - # - def ask(statement, color=nil) - say("#{statement} ", color) - $stdin.gets.strip - end - - # Say (print) something to the user. If the sentence ends with a whitespace - # or tab character, a new line is not appended (print + flush). Otherwise - # are passed straight to puts (behavior got from Highline). - # - # ==== Example - # say("I know you knew that.") - # - def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/)) - message = message.to_s - message = set_color(message, color) if color - - if force_new_line - $stdout.puts(message) - else - $stdout.print(message) - $stdout.flush - end - end - - # Say a status with the given color and appends the message. Since this - # method is used frequently by actions, it allows nil or false to be given - # in log_status, avoiding the message from being shown. If a Symbol is - # given in log_status, it's used as the color. - # - def say_status(status, message, log_status=true) - return if quiet? || log_status == false - spaces = " " * (padding + 1) - color = log_status.is_a?(Symbol) ? log_status : :green - - status = status.to_s.rjust(12) - status = set_color status, color, true if color - say "#{status}#{spaces}#{message}", nil, true - end - - # Make a question the to user and returns true if the user replies "y" or - # "yes". - # - def yes?(statement, color=nil) - ask(statement, color) =~ is?(:yes) - end - - # Make a question the to user and returns true if the user replies "n" or - # "no". - # - def no?(statement, color=nil) - !yes?(statement, color) - end - - # Prints a list of items. - # - # ==== Parameters - # list - # - # ==== Options - # mode:: Can be :rows or :inline. Defaults to :rows. - # ident:: Ident each item with the value given. - # - def print_list(list, options={}) - return if list.empty? - - ident = " " * (options[:ident] || 0) - content = case options[:mode] - when :inline - last = list.pop - "#{list.join(", ")}, and #{last}" - else # rows - ident + list.join("\n#{ident}") - end - - $stdout.puts content - end - - # Prints a table. - # - # ==== Parameters - # Array[Array[String, String, ...]] - # - # ==== Options - # ident:: Ident the first column by ident value. - # - def print_table(table, options={}) - return if table.empty? - - formats = [] - 0.upto(table.first.length - 2) do |i| - maxima = table.max{ |a,b| a[i].size <=> b[i].size }[i].size - formats << "%-#{maxima + 2}s" - end - - formats[0] = formats[0].insert(0, " " * options[:ident]) if options[:ident] - formats << "%s" - - table.each do |row| - row.each_with_index do |column, i| - $stdout.print formats[i] % column.to_s - end - $stdout.puts - end - end - - # Deals with file collision and returns true if the file should be - # overwriten and false otherwise. If a block is given, it uses the block - # response as the content for the diff. - # - # ==== Parameters - # destination:: the destination file to solve conflicts - # block:: an optional block that returns the value to be used in diff - # - def file_collision(destination) - return true if @always_force - options = block_given? ? "[Ynaqdh]" : "[Ynaqh]" - - while true - answer = ask %[Overwrite #{destination}? (enter "h" for help) #{options}] - - case answer - when is?(:yes), is?(:force), "" - return true - when is?(:no), is?(:skip) - return false - when is?(:always) - return @always_force = true - when is?(:quit) - say 'Aborting...' - raise SystemExit - when is?(:diff) - show_diff(destination, yield) if block_given? - say 'Retrying...' - else - say file_collision_help - end - end - end - - # Called if something goes wrong during the execution. This is used by Thor - # internally and should not be used inside your scripts. If someone went - # wrong, you can always raise an exception. If you raise a Thor::Error, it - # will be rescued and wrapped in the method below. - # - def error(statement) - $stderr.puts statement - end - - # Apply color to the given string with optional bold. Disabled in the - # Thor::Shell::Basic class. - # - def set_color(string, color, bold=false) #:nodoc: - string - end - - protected - - def is?(value) #:nodoc: - value = value.to_s - - if value.size == 1 - /\A#{value}\z/i - else - /\A(#{value}|#{value[0,1]})\z/i - end - end - - def file_collision_help #:nodoc: -< e - parse_argument_error(instance, e, caller) - rescue NoMethodError => e - parse_no_method_error(instance, e) - end - - # Returns the formatted usage. If a class is given, the class arguments are - # injected in the usage. - # - def formatted_usage(klass=nil, namespace=false, show_options=true) - formatted = if namespace.is_a?(String) - "#{namespace}:" - elsif klass && namespace - "#{klass.namespace.gsub(/^default/,'')}:" - else - "" - end - - formatted << formatted_arguments(klass) - formatted << " #{formatted_options}" if show_options - formatted.strip! - formatted - end - - # Injects the class arguments into the task usage. - # - def formatted_arguments(klass) - if klass && !klass.arguments.empty? - usage.to_s.gsub(/^#{name}/) do |match| - match << " " << klass.arguments.map{ |a| a.usage }.join(' ') - end - else - usage.to_s - end - end - - # Returns the options usage for this task. - # - def formatted_options - @formatted_options ||= options.map{ |_, o| o.usage }.sort.join(" ") - end - - protected - - # Given a target, checks if this class name is not a private/protected method. - # - def public_method?(instance) #:nodoc: - collection = instance.private_methods + instance.protected_methods - (collection & [name.to_s, name.to_sym]).empty? - end - - # Clean everything that comes from the Thor gempath and remove the caller. - # - def sans_backtrace(backtrace, caller) #:nodoc: - dirname = /^#{Regexp.escape(File.dirname(__FILE__))}/ - saned = backtrace.reject { |frame| frame =~ dirname } - saned -= caller - end - - def parse_argument_error(instance, e, caller) #:nodoc: - backtrace = sans_backtrace(e.backtrace, caller) - - if backtrace.empty? && e.message =~ /wrong number of arguments/ - if instance.is_a?(Thor::Group) - raise e, "'#{name}' was called incorrectly. Are you sure it has arity equals to 0?" - else - raise InvocationError, "'#{name}' was called incorrectly. Call as " << - "'#{formatted_usage(instance.class, true)}'" - end - else - raise e - end - end - - def parse_no_method_error(instance, e) #:nodoc: - if e.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/ - raise UndefinedTaskError, "The #{instance.class.namespace} namespace " << - "doesn't have a '#{name}' task" - else - raise e - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/util.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/util.rb deleted file mode 100644 index ebae0a3193..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/util.rb +++ /dev/null @@ -1,251 +0,0 @@ -require 'rbconfig' - -class Thor - module Sandbox #:nodoc: - end - - # This module holds several utilities: - # - # 1) Methods to convert thor namespaces to constants and vice-versa. - # - # Thor::Utils.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz" - # - # 2) Loading thor files and sandboxing: - # - # Thor::Utils.load_thorfile("~/.thor/foo") - # - module Util - - # Receives a namespace and search for it in the Thor::Base subclasses. - # - # ==== Parameters - # namespace:: The namespace to search for. - # - def self.find_by_namespace(namespace) - namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/ - - Thor::Base.subclasses.find do |klass| - klass.namespace == namespace - end - end - - # Receives a constant and converts it to a Thor namespace. Since Thor tasks - # can be added to a sandbox, this method is also responsable for removing - # the sandbox namespace. - # - # This method should not be used in general because it's used to deal with - # older versions of Thor. On current versions, if you need to get the - # namespace from a class, just call namespace on it. - # - # ==== Parameters - # constant:: The constant to be converted to the thor path. - # - # ==== Returns - # String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz" - # - def self.namespace_from_thor_class(constant, remove_default=true) - constant = constant.to_s.gsub(/^Thor::Sandbox::/, "") - constant = snake_case(constant).squeeze(":") - constant.gsub!(/^default/, '') if remove_default - constant - end - - # Given the contents, evaluate it inside the sandbox and returns the - # namespaces defined in the sandbox. - # - # ==== Parameters - # contents - # - # ==== Returns - # Array[Object] - # - def self.namespaces_in_content(contents, file=__FILE__) - old_constants = Thor::Base.subclasses.dup - Thor::Base.subclasses.clear - - load_thorfile(file, contents) - - new_constants = Thor::Base.subclasses.dup - Thor::Base.subclasses.replace(old_constants) - - new_constants.map!{ |c| c.namespace } - new_constants.compact! - new_constants - end - - # Returns the thor classes declared inside the given class. - # - def self.thor_classes_in(klass) - Thor::Base.subclasses.select do |subclass| - klass.constants.include?(subclass.name.gsub("#{klass.name}::", '')) - end - end - - # Receives a string and convert it to snake case. SnakeCase returns snake_case. - # - # ==== Parameters - # String - # - # ==== Returns - # String - # - def self.snake_case(str) - return str.downcase if str =~ /^[A-Z_]+$/ - str.gsub(/\B[A-Z]/, '_\&').squeeze('_') =~ /_*(.*)/ - return $+.downcase - end - - # Receives a string and convert it to camel case. camel_case returns CamelCase. - # - # ==== Parameters - # String - # - # ==== Returns - # String - # - def self.camel_case(str) - return str if str !~ /_/ && str =~ /[A-Z]+.*/ - str.split('_').map { |i| i.capitalize }.join - end - - # Receives a namespace and tries to retrieve a Thor or Thor::Group class - # from it. It first searches for a class using the all the given namespace, - # if it's not found, removes the highest entry and searches for the class - # again. If found, returns the highest entry as the class name. - # - # ==== Examples - # - # class Foo::Bar < Thor - # def baz - # end - # end - # - # class Baz::Foo < Thor::Group - # end - # - # Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default task - # Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil - # Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz" - # - # ==== Parameters - # namespace - # - # ==== Errors - # Thor::Error:: raised if the namespace cannot be found. - # - # Thor::Error:: raised if the namespace evals to a class which does not - # inherit from Thor or Thor::Group. - # - def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true) - if namespace.include?(?:) - pieces = namespace.split(":") - task = pieces.pop - klass = Thor::Util.find_by_namespace(pieces.join(":")) - end - - unless klass - klass, task = Thor::Util.find_by_namespace(namespace), nil - end - - raise Error, "could not find Thor class or task '#{namespace}'" if raise_if_nil && klass.nil? - return klass, task - end - - # Receives a path and load the thor file in the path. The file is evaluated - # inside the sandbox to avoid namespacing conflicts. - # - def self.load_thorfile(path, content=nil) - content ||= File.read(path) - - begin - Thor::Sandbox.class_eval(content, path) - rescue Exception => e - $stderr.puts "WARNING: unable to load thorfile #{path.inspect}: #{e.message}" - end - end - - # Receives a yaml (hash) and updates all constants entries to namespace. - # This was added to deal with deprecated versions of Thor. - # - # TODO Deprecate this method in the future. - # - # ==== Returns - # TrueClass|FalseClass:: Returns true if any change to the yaml file was made. - # - def self.convert_constants_to_namespaces(yaml) - yaml_changed = false - - yaml.each do |k, v| - next unless v[:constants] && v[:namespaces].nil? - yaml_changed = true - yaml[k][:namespaces] = v[:constants].map{|c| Thor::Util.namespace_from_thor_class(c)} - end - - yaml_changed - end - - def self.user_home - @@user_home ||= if ENV["HOME"] - ENV["HOME"] - elsif ENV["USERPROFILE"] - ENV["USERPROFILE"] - elsif ENV["HOMEDRIVE"] && ENV["HOMEPATH"] - File.join(ENV["HOMEDRIVE"], ENV["HOMEPATH"]) - elsif ENV["APPDATA"] - ENV["APPDATA"] - else - begin - File.expand_path("~") - rescue - if File::ALT_SEPARATOR - "C:/" - else - "/" - end - end - end - end - - # Returns the root where thor files are located, dependending on the OS. - # - def self.thor_root - File.join(user_home, ".thor").gsub(/\\/, '/') - end - - # Returns the files in the thor root. On Windows thor_root will be something - # like this: - # - # C:\Documents and Settings\james\.thor - # - # If we don't #gsub the \ character, Dir.glob will fail. - # - def self.thor_root_glob - files = Dir["#{thor_root}/*"] - - files.map! do |file| - File.directory?(file) ? File.join(file, "main.thor") : file - end - end - - # Where to look for Thor files. - # - def self.globs_for(path) - ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] - end - - # Return the path to the ruby interpreter taking into account multiple - # installations and windows extensions. - # - def self.ruby_command - @ruby_command ||= begin - ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) - ruby << Config::CONFIG['EXEEXT'] - - # escape string in case path to ruby executable contain spaces. - ruby.sub!(/.*\s.*/m, '"\&"') - ruby - end - end - - end -end diff --git a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/version.rb b/railties/lib/rails/vendor/thor-0.12.1/lib/thor/version.rb deleted file mode 100644 index 650253d648..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.1/lib/thor/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Thor - VERSION = "0.12.1".freeze -end diff --git a/railties/lib/rails/vendor/thor-0.12.3/CHANGELOG.rdoc b/railties/lib/rails/vendor/thor-0.12.3/CHANGELOG.rdoc new file mode 100644 index 0000000000..d02fc43e84 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/CHANGELOG.rdoc @@ -0,0 +1,80 @@ +== 0.12, released 2010-01-02 + +* Removed rr in favor to rspec mock framework +* Improved output for thor -T +* [#7] Do not force white color on status +* [#8] Yield a block with the filename on directory + +== 0.11, released 2009-07-01 + +* Added a rake compatibility layer. It allows you to use spec and rdoc tasks on + Thor classes. + +* BACKWARDS INCOMPATIBLE: aliases are not generated automatically anymore + since it wrong behavior to the invocation system. + +* thor help now show information about any class/task. All those calls are + possible: + + thor help describe + thor help describe:amazing + + Or even with default namespaces: + + thor help :spec + +* Thor::Runner now invokes the default task if none is supplied: + + thor describe # invokes the default task, usually help + +* Thor::Runner now works with mappings: + + thor describe -h + +* Added some documentation and code refactoring. + +== 0.9.8, released 2008-10-20 + +* Fixed some tiny issues that were introduced lately. + +== 0.9.7, released 2008-10-13 + +* Setting global method options on the initialize method works as expected: + All other tasks will accept these global options in addition to their own. +* Added 'group' notion to Thor task sets (class Thor); by default all tasks + are in the 'standard' group. Running 'thor -T' will only show the standard + tasks - adding --all will show all tasks. You can also filter on a specific + group using the --group option: thor -T --group advanced + +== 0.9.6, released 2008-09-13 + +* Generic improvements + +== 0.9.5, released 2008-08-27 + +* Improve Windows compatibility +* Update (incorrect) README and task.thor sample file +* Options hash is now frozen (once returned) +* Allow magic predicates on options object. For instance: `options.force?` +* Add support for :numeric type +* BACKWARDS INCOMPATIBLE: Refactor Thor::Options. You cannot access shorthand forms in options hash anymore (for instance, options[:f]) +* Allow specifying optional args with default values: method_options(:user => "mislav") +* Don't write options for nil or false values. This allows, for example, turning color off when running specs. +* Exit with the status of the spec command to help CI stuff out some. + +== 0.9.4, released 2008-08-13 + +* Try to add Windows compatibility. +* BACKWARDS INCOMPATIBLE: options hash is now accessed as a property in your class and is not passed as last argument anymore +* Allow options at the beginning of the argument list as well as the end. +* Make options available with symbol keys in addition to string keys. +* Allow true to be passed to Thor#method_options to denote a boolean option. +* If loading a thor file fails, don't give up, just print a warning and keep going. +* Make sure that we re-raise errors if they happened further down the pipe than we care about. +* Only delete the old file on updating when the installation of the new one is a success +* Make it Ruby 1.8.5 compatible. +* Don't raise an error if a boolean switch is defined multiple times. +* Thor::Options now doesn't parse through things that look like options but aren't. +* Add URI detection to install task, and make sure we don't append ".thor" to URIs +* Add rake2thor to the gem binfiles. +* Make sure local Thorfiles override system-wide ones. diff --git a/railties/lib/rails/vendor/thor-0.12.3/LICENSE b/railties/lib/rails/vendor/thor-0.12.3/LICENSE new file mode 100644 index 0000000000..98722da459 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008 Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/railties/lib/rails/vendor/thor-0.12.3/README.rdoc b/railties/lib/rails/vendor/thor-0.12.3/README.rdoc new file mode 100644 index 0000000000..ee545f3d97 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/README.rdoc @@ -0,0 +1,234 @@ += thor + +Map options to a class. Simply create a class with the appropriate annotations +and have options automatically map to functions and parameters. + +Example: + + class App < Thor # [1] + map "-L" => :list # [2] + + desc "install APP_NAME", "install one of the available apps" # [3] + method_options :force => :boolean, :alias => :string # [4] + def install(name) + user_alias = options[:alias] + if options.force? + # do something + end + # other code + end + + desc "list [SEARCH]", "list all of the available apps, limited by SEARCH" + def list(search="") + # list everything + end + end + +Thor automatically maps commands as such: + + thor app:install myname --force + +That gets converted to: + + App.new.install("myname") + # with {'force' => true} as options hash + +1. Inherit from Thor to turn a class into an option mapper +2. Map additional non-valid identifiers to specific methods. In this case, convert -L to :list +3. Describe the method immediately below. The first parameter is the usage information, and the second parameter is the description +4. Provide any additional options that will be available the instance method options. + +== Types for method_options + +* :boolean - is parsed as --option or --option=true +* :string - is parsed as --option=VALUE +* :numeric - is parsed as --option=N +* :array - is parsed as --option=one two three +* :hash - is parsed as --option=name:string age:integer + +Besides, method_option allows a default value to be given, examples: + + method_options :force => false + #=> Creates a boolean option with default value false + + method_options :alias => "bar" + #=> Creates a string option with default value "bar" + + method_options :threshold => 3.0 + #=> Creates a numeric option with default value 3.0 + +You can also supply :option => :required to mark an option as required. The +type is assumed to be string. If you want a required hash with default values +as option, you can use method_option which uses a more declarative style: + + method_option :attributes, :type => :hash, :default => {}, :required => true + +All arguments can be set to nil (except required arguments), by suppling a no or +skip variant. For example: + + thor app name --no-attributes + +In previous versions, aliases for options were created automatically, but now +they should be explicit. You can supply aliases in both short and declarative +styles: + + method_options %w( force -f ) => :boolean + +Or: + + method_option :force, :type => :boolean, :aliases => "-f" + +You can supply as many aliases as you want. + +NOTE: Type :optional available in Thor 0.9.0 was deprecated. Use :string or :boolean instead. + +== Namespaces + +By default, your Thor tasks are invoked using Ruby namespace. In the example +above, tasks are invoked as: + + thor app:install name --force + +However, you could namespace your class as: + + module Sinatra + class App < Thor + # tasks + end + end + +And then you should invoke your tasks as: + + thor sinatra:app:install name --force + +If desired, you can change the namespace: + + module Sinatra + class App < Thor + namespace :myapp + # tasks + end + end + +And then your tasks hould be invoked as: + + thor myapp:install name --force + +== Invocations + +Thor comes with a invocation-dependency system as well which allows a task to be +invoked only once. For example: + + class Counter < Thor + desc "one", "Prints 1, 2, 3" + def one + puts 1 + invoke :two + invoke :three + end + + desc "two", "Prints 2, 3" + def two + puts 2 + invoke :three + end + + desc "three", "Prints 3" + def three + puts 3 + end + end + +When invoking the task one: + + thor counter:one + +The output is "1 2 3", which means that the three task was invoked only once. +You can even invoke tasks from another class, so be sure to check the +documentation. + +== Thor::Group + +Thor has a special class called Thor::Group. The main difference to Thor class +is that it invokes all tasks at once. The example above could be rewritten in +Thor::Group as this: + + class Counter < Thor::Group + desc "Prints 1, 2, 3" + + def one + puts 1 + end + + def two + puts 2 + end + + def three + puts 3 + end + end + +When invoked: + + thor counter + +It prints "1 2 3" as well. Notice you should describe (using the method desc) +only the class and not each task anymore. Thor::Group is a great tool to create +generators, since you can define several steps which are invoked in the order they +are defined (Thor::Group is the tool use in generators in Rails 3.0). + +Besides, Thor::Group can parse arguments and options as Thor tasks: + + class Counter < Thor::Group + # number will be available as attr_accessor + argument :number, :type => :numeric, :desc => "The number to start counting" + desc "Prints the 'number' given upto 'number+2'" + + def one + puts number + 0 + end + + def two + puts number + 1 + end + + def three + puts number + 2 + end + end + +The counter above expects one parameter and has the folling outputs: + + thor counter 5 + # Prints "5 6 7" + + thor counter 11 + # Prints "11 12 13" + +You can also give options to Thor::Group, but instead of using method_option +and method_options, you should use class_option and class_options. +Both argument and class_options methods are available to Thor class as well. + +== Actions + +Thor comes with several actions which helps with script and generator tasks. You +might be familiar with them since some came from Rails Templates. They are: +say, ask, yes?, no?, add_file, +remove_file, copy_file, template, directory, +inside, run, inject_into_file and a couple more. + +To use them, you just need to include Thor::Actions in your Thor classes: + + class App < Thor + include Thor::Actions + # tasks + end + +Some actions like copy file requires that a class method called source_root is +defined in your class. This is the directory where your templates should be +placed. Be sure to check the documentation. + +== License + +See MIT LICENSE. diff --git a/railties/lib/rails/vendor/thor-0.12.3/Thorfile b/railties/lib/rails/vendor/thor-0.12.3/Thorfile new file mode 100644 index 0000000000..ff1cb4498a --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/Thorfile @@ -0,0 +1,63 @@ +# enconding: utf-8 + +require File.join(File.dirname(__FILE__), "lib", "thor", "version") +require 'thor/rake_compat' +require 'spec/rake/spectask' +require 'rdoc/task' + +GEM_NAME = 'thor' +EXTRA_RDOC_FILES = ["README.rdoc", "LICENSE", "CHANGELOG.rdoc", "VERSION", "Thorfile"] + +class Default < Thor + include Thor::RakeCompat + + Spec::Rake::SpecTask.new(:spec) do |t| + t.libs << 'lib' + t.spec_opts = ['--options', "spec/spec.opts"] + t.spec_files = FileList['spec/**/*_spec.rb'] + end + + Spec::Rake::SpecTask.new(:rcov) do |t| + t.libs << 'lib' + t.spec_opts = ['--options', "spec/spec.opts"] + t.spec_files = FileList['spec/**/*_spec.rb'] + t.rcov = true + t.rcov_dir = "rcov" + end + + RDoc::Task.new do |rdoc| + rdoc.main = "README.rdoc" + rdoc.rdoc_dir = "rdoc" + rdoc.title = GEM_NAME + rdoc.rdoc_files.include(*EXTRA_RDOC_FILES) + rdoc.rdoc_files.include('lib/**/*.rb') + rdoc.options << '--line-numbers' << '--inline-source' + end + + begin + require 'jeweler' + Jeweler::Tasks.new do |s| + s.name = GEM_NAME + s.version = Thor::VERSION + s.rubyforge_project = "textmate" + s.platform = Gem::Platform::RUBY + s.summary = "A scripting framework that replaces rake, sake and rubigen" + s.email = "ruby-thor@googlegroups.com" + s.homepage = "http://yehudakatz.com" + s.description = "A scripting framework that replaces rake, sake and rubigen" + s.authors = ['Yehuda Katz', 'José Valim'] + s.has_rdoc = true + s.extra_rdoc_files = EXTRA_RDOC_FILES + s.require_path = 'lib' + s.bindir = "bin" + s.executables = %w( thor rake2thor ) + s.files = s.extra_rdoc_files + Dir.glob("{bin,lib}/**/*") + s.files.exclude 'spec/sandbox/**/*' + s.test_files.exclude 'spec/sandbox/**/*' + end + + Jeweler::GemcutterTasks.new + rescue LoadError + puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor.rb new file mode 100644 index 0000000000..d4d8fbd64d --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor.rb @@ -0,0 +1,240 @@ +require 'thor/base' +require 'thor/group' +require 'thor/actions' + +class Thor + class << self + # Sets the default task when thor is executed without an explicit task to be called. + # + # ==== Parameters + # meth:: name of the defaut task + # + def default_task(meth=nil) + case meth + when :none + @default_task = 'help' + when nil + @default_task ||= from_superclass(:default_task, 'help') + else + @default_task = meth.to_s + end + end + + # Defines the usage and the description of the next task. + # + # ==== Parameters + # usage + # description + # + def desc(usage, description, options={}) + if options[:for] + task = find_and_refresh_task(options[:for]) + task.usage = usage if usage + task.description = description if description + else + @usage, @desc = usage, description + end + end + + # Maps an input to a task. If you define: + # + # map "-T" => "list" + # + # Running: + # + # thor -T + # + # Will invoke the list task. + # + # ==== Parameters + # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task. + # + def map(mappings=nil) + @map ||= from_superclass(:map, {}) + + if mappings + mappings.each do |key, value| + if key.respond_to?(:each) + key.each {|subkey| @map[subkey] = value} + else + @map[key] = value + end + end + end + + @map + end + + # Declares the options for the next task to be declared. + # + # ==== Parameters + # Hash[Symbol => Object]:: The hash key is the name of the option and the value + # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric + # or :required (string). If you give a value, the type of the value is used. + # + def method_options(options=nil) + @method_options ||= {} + build_options(options, @method_options) if options + @method_options + end + + # Adds an option to the set of method options. If :for is given as option, + # it allows you to change the options from a previous defined task. + # + # def previous_task + # # magic + # end + # + # method_option :foo => :bar, :for => :previous_task + # + # def next_task + # # magic + # end + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc - Description for the argument. + # :required - If the argument is required or not. + # :default - Default value for this argument. It cannot be required and have default values. + # :aliases - Aliases for this option. + # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. + # :banner - String to show on usage notes. + # + def method_option(name, options={}) + scope = if options[:for] + find_and_refresh_task(options[:for]).options + else + method_options + end + + build_option(name, options, scope) + end + + # Parses the task and options from the given args, instantiate the class + # and invoke the task. This method is used when the arguments must be parsed + # from an array. If you are inside Ruby and want to use a Thor class, you + # can simply initialize it: + # + # script = MyScript.new(args, options, config) + # script.invoke(:task, first_arg, second_arg, third_arg) + # + def start(given_args=ARGV, config={}) + super do + meth = normalize_task_name(given_args.shift) + task = all_tasks[meth] + + if task + args, opts = Thor::Options.split(given_args) + config.merge!(:task_options => task.options) + else + args, opts = given_args, {} + end + + task ||= Thor::Task::Dynamic.new(meth) + trailing = args[Range.new(arguments.size, -1)] + new(args, opts, config).invoke(task, trailing || []) + end + end + + # Prints help information for the given task. + # + # ==== Parameters + # shell + # task_name + # + def task_help(shell, task_name) + task = all_tasks[task_name] + raise UndefinedTaskError, "task '#{task_name}' could not be found in namespace '#{self.namespace}'" unless task + + shell.say "Usage:" + shell.say " #{banner(task)}" + shell.say + class_options_help(shell, nil => task.options.map { |_, o| o }) + shell.say task.description + end + + # Prints help information for this class. + # + # ==== Parameters + # shell + # + def help(shell) + list = printable_tasks + Thor::Util.thor_classes_in(self).each do |klass| + list += klass.printable_tasks(false) + end + list.sort!{ |a,b| a[0] <=> b[0] } + + shell.say "Tasks:" + shell.print_table(list, :ident => 2, :truncate => true) + shell.say + class_options_help(shell) + end + + # Returns tasks ready to be printed. + def printable_tasks(all=true) + (all ? all_tasks : tasks).map do |_, task| + item = [] + item << banner(task) + item << (task.description ? "# #{task.description.gsub(/\s+/m,' ')}" : "") + item + end + end + + protected + + # The banner for this class. You can customize it if you are invoking the + # thor class by another ways which is not the Thor::Runner. It receives + # the task that is going to be invoked and a boolean which indicates if + # the namespace should be displayed as arguments. + # + def banner(task) + "thor " + task.formatted_usage(self) + end + + def baseclass #:nodoc: + Thor + end + + def create_task(meth) #:nodoc: + if @usage && @desc + tasks[meth.to_s] = Thor::Task.new(meth, @desc, @usage, method_options) + @usage, @desc, @method_options = nil + true + elsif self.all_tasks[meth.to_s] || meth.to_sym == :method_missing + true + else + puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " << + "Call desc if you want this method to be available as task or declare it inside a " << + "no_tasks{} block. Invoked from #{caller[1].inspect}." + false + end + end + + def initialize_added #:nodoc: + class_options.merge!(method_options) + @method_options = nil + end + + # Receives a task name (can be nil), and try to get a map from it. + # If a map can't be found use the sent name or the default task. + # + def normalize_task_name(meth) #:nodoc: + mapping = map[meth.to_s] + meth = mapping || meth || default_task + meth.to_s.gsub('-','_') # treat foo-bar > foo_bar + end + end + + include Thor::Base + + map HELP_MAPPINGS => :help + + desc "help [TASK]", "Describe available tasks or one specific task" + def help(task=nil) + task ? self.class.task_help(shell, task) : self.class.help(shell) + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions.rb new file mode 100644 index 0000000000..da98444bf2 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions.rb @@ -0,0 +1,274 @@ +require 'fileutils' +require 'thor/core_ext/file_binary_read' + +Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action| + require action +end + +class Thor + module Actions + attr_accessor :behavior + + def self.included(base) #:nodoc: + base.extend ClassMethods + end + + module ClassMethods + # Hold source paths for one Thor instance. source_paths_for_search is the + # method responsible to gather source_paths from this current class, + # inherited paths and the source root. + # + def source_paths + @source_paths ||= [] + end + + # Returns the source paths in the following order: + # + # 1) This class source paths + # 2) Source root + # 3) Parents source paths + # + def source_paths_for_search + paths = [] + paths += self.source_paths + paths << self.source_root if self.respond_to?(:source_root) + paths += from_superclass(:source_paths, []) + paths + end + + # Add runtime options that help actions execution. + # + def add_runtime_options! + class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime, + :desc => "Overwrite files that already exist" + + class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime, + :desc => "Run but do not make any changes" + + class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime, + :desc => "Supress status output" + + class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime, + :desc => "Skip files that already exist" + end + end + + # Extends initializer to add more configuration options. + # + # ==== Configuration + # behavior:: The actions default behavior. Can be :invoke or :revoke. + # It also accepts :force, :skip and :pretend to set the behavior + # and the respective option. + # + # destination_root:: The root directory needed for some actions. + # + def initialize(args=[], options={}, config={}) + self.behavior = case config[:behavior].to_s + when "force", "skip" + _cleanup_options_and_set(options, config[:behavior]) + :invoke + when "revoke" + :revoke + else + :invoke + end + + super + self.destination_root = config[:destination_root] + end + + # Wraps an action object and call it accordingly to the thor class behavior. + # + def action(instance) #:nodoc: + if behavior == :revoke + instance.revoke! + else + instance.invoke! + end + end + + # Returns the root for this thor class (also aliased as destination root). + # + def destination_root + @destination_stack.last + end + + # Sets the root for this thor class. Relatives path are added to the + # directory where the script was invoked and expanded. + # + def destination_root=(root) + @destination_stack ||= [] + @destination_stack[0] = File.expand_path(root || '') + end + + # Returns the given path relative to the absolute root (ie, root where + # the script started). + # + def relative_to_original_destination_root(path, remove_dot=true) + path = path.gsub(@destination_stack[0], '.') + remove_dot ? (path[2..-1] || '') : path + end + + # Holds source paths in instance so they can be manipulated. + # + def source_paths + @source_paths ||= self.class.source_paths_for_search + end + + # Receives a file or directory and search for it in the source paths. + # + def find_in_source_paths(file) + relative_root = relative_to_original_destination_root(destination_root, false) + + source_paths.each do |source| + source_file = File.expand_path(file, File.join(source, relative_root)) + return source_file if File.exists?(source_file) + end + + if source_paths.empty? + raise Error, "You don't have any source path defined for class #{self.class.name}. To fix this, " << + "you can define a source_root in your class." + else + raise Error, "Could not find #{file.inspect} in source paths." + end + end + + # Do something in the root or on a provided subfolder. If a relative path + # is given it's referenced from the current root. The full path is yielded + # to the block you provide. The path is set back to the previous path when + # the method exits. + # + # ==== Parameters + # dir:: the directory to move to. + # config:: give :verbose => true to log and use padding. + # + def inside(dir='', config={}, &block) + verbose = config.fetch(:verbose, false) + + say_status :inside, dir, verbose + shell.padding += 1 if verbose + @destination_stack.push File.expand_path(dir, destination_root) + + FileUtils.mkdir_p(destination_root) unless File.exist?(destination_root) + FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield } + + @destination_stack.pop + shell.padding -= 1 if verbose + end + + # Goes to the root and execute the given block. + # + def in_root + inside(@destination_stack.first) { yield } + end + + # Loads an external file and execute it in the instance binding. + # + # ==== Parameters + # path:: The path to the file to execute. Can be a web address or + # a relative path from the source root. + # + # ==== Examples + # + # apply "http://gist.github.com/103208" + # + # apply "recipes/jquery.rb" + # + def apply(path, config={}) + verbose = config.fetch(:verbose, true) + path = find_in_source_paths(path) unless path =~ /^http\:\/\// + + say_status :apply, path, verbose + shell.padding += 1 if verbose + instance_eval(open(path).read) + shell.padding -= 1 if verbose + end + + # Executes a command. + # + # ==== Parameters + # command:: the command to be executed. + # config:: give :verbose => false to not log the status. Specify :with + # to append an executable to command executation. + # + # ==== Example + # + # inside('vendor') do + # run('ln -s ~/edge rails') + # end + # + def run(command, config={}) + return unless behavior == :invoke + + destination = relative_to_original_destination_root(destination_root, false) + desc = "#{command} from #{destination.inspect}" + + if config[:with] + desc = "#{File.basename(config[:with].to_s)} #{desc}" + command = "#{config[:with]} #{command}" + end + + say_status :run, desc, config.fetch(:verbose, true) + system(command) unless options[:pretend] + end + + # Executes a ruby script (taking into account WIN32 platform quirks). + # + # ==== Parameters + # command:: the command to be executed. + # config:: give :verbose => false to not log the status. + # + def run_ruby_script(command, config={}) + return unless behavior == :invoke + run "#{command}", config.merge(:with => Thor::Util.ruby_command) + end + + # Run a thor command. A hash of options can be given and it's converted to + # switches. + # + # ==== Parameters + # task:: the task to be invoked + # args:: arguments to the task + # config:: give :verbose => false to not log the status. Other options + # are given as parameter to Thor. + # + # ==== Examples + # + # thor :install, "http://gist.github.com/103208" + # #=> thor install http://gist.github.com/103208 + # + # thor :list, :all => true, :substring => 'rails' + # #=> thor list --all --substring=rails + # + def thor(task, *args) + config = args.last.is_a?(Hash) ? args.pop : {} + verbose = config.key?(:verbose) ? config.delete(:verbose) : true + + args.unshift task + args.push Thor::Options.to_switches(config) + command = args.join(' ').strip + + run command, :with => :thor, :verbose => verbose + end + + protected + + # Allow current root to be shared between invocations. + # + def _shared_configuration #:nodoc: + super.merge!(:destination_root => self.destination_root) + end + + def _cleanup_options_and_set(options, key) #:nodoc: + case options + when Array + %w(--force -f --skip -s).each { |i| options.delete(i) } + options << "--#{key}" + when Hash + [:force, :skip, "force", "skip"].each { |i| options.delete(i) } + options.merge!(key => true) + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/create_file.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/create_file.rb new file mode 100644 index 0000000000..6e0eeb43e2 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/create_file.rb @@ -0,0 +1,103 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + + # Create a new file relative to the destination root with the given data, + # which is the return value of a block or a data string. + # + # ==== Parameters + # destination:: the relative path to the destination root. + # data:: the data to append to the file. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # create_file "lib/fun_party.rb" do + # hostname = ask("What is the virtual hostname I should use?") + # "vhost.name = #{hostname}" + # end + # + # create_file "config/apach.conf", "your apache config" + # + def create_file(destination, data=nil, config={}, &block) + action CreateFile.new(self, destination, block || data.to_s, config) + end + alias :add_file :create_file + + # AddFile is a subset of Template, which instead of rendering a file with + # ERB, it gets the content from the user. + # + class CreateFile < EmptyDirectory #:nodoc: + attr_reader :data + + def initialize(base, destination, data, config={}) + @data = data + super(base, destination, config) + end + + # Checks if the content of the file at the destination is identical to the rendered result. + # + # ==== Returns + # Boolean:: true if it is identical, false otherwise. + # + def identical? + exists? && File.binread(destination) == render + end + + # Holds the content to be added to the file. + # + def render + @render ||= if data.is_a?(Proc) + data.call + else + data + end + end + + def invoke! + invoke_with_conflict_check do + FileUtils.mkdir_p(File.dirname(destination)) + File.open(destination, 'wb') { |f| f.write render } + end + given_destination + end + + protected + + # Now on conflict we check if the file is identical or not. + # + def on_conflict_behavior(&block) + if identical? + say_status :identical, :blue + else + options = base.options.merge(config) + force_or_skip_or_conflict(options[:force], options[:skip], &block) + end + end + + # If force is true, run the action, otherwise check if it's not being + # skipped. If both are false, show the file_collision menu, if the menu + # returns true, force it, otherwise skip. + # + def force_or_skip_or_conflict(force, skip, &block) + if force + say_status :force, :yellow + block.call unless pretend? + elsif skip + say_status :skip, :yellow + else + say_status :conflict, :red + force_or_skip_or_conflict(force_on_collision?, true, &block) + end + end + + # Shows the file collision menu to the user and gets the result. + # + def force_on_collision? + base.shell.file_collision(destination){ render } + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/directory.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/directory.rb new file mode 100644 index 0000000000..2e0b459fa3 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/directory.rb @@ -0,0 +1,91 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + + # Copies recursively the files from source directory to root directory. + # If any of the files finishes with .tt, it's considered to be a template + # and is placed in the destination without the extension .tt. If any + # empty directory is found, it's copied and all .empty_directory files are + # ignored. Remember that file paths can also be encoded, let's suppose a doc + # directory with the following files: + # + # doc/ + # components/.empty_directory + # README + # rdoc.rb.tt + # %app_name%.rb + # + # When invoked as: + # + # directory "doc" + # + # It will create a doc directory in the destination with the following + # files (assuming that the app_name is "blog"): + # + # doc/ + # components/ + # README + # rdoc.rb + # blog.rb + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # If :recursive => false, does not look for paths recursively. + # + # ==== Examples + # + # directory "doc" + # directory "doc", "docs", :recursive => false + # + def directory(source, destination=nil, config={}, &block) + action Directory.new(self, source, destination || source, config, &block) + end + + class Directory < EmptyDirectory #:nodoc: + attr_reader :source + + def initialize(base, source, destination=nil, config={}, &block) + @source = File.expand_path(base.find_in_source_paths(source.to_s)) + @block = block + super(base, destination, { :recursive => true }.merge(config)) + end + + def invoke! + base.empty_directory given_destination, config + execute! + end + + def revoke! + execute! + end + + protected + + def execute! + lookup = config[:recursive] ? File.join(source, '**') : source + lookup = File.join(lookup, '{*,.[a-z]*}') + + Dir[lookup].each do |file_source| + next if File.directory?(file_source) + file_destination = File.join(given_destination, file_source.gsub(source, '.')) + file_destination.gsub!('/./', '/') + + case file_source + when /\.empty_directory$/ + dirname = File.dirname(file_destination).gsub(/\/\.$/, '') + next if dirname == given_destination + base.empty_directory(dirname, config) + when /\.tt$/ + destination = base.template(file_source, file_destination[0..-4], config, &@block) + else + destination = base.copy_file(file_source, file_destination, config, &@block) + end + end + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/empty_directory.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/empty_directory.rb new file mode 100644 index 0000000000..484cb820f8 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/empty_directory.rb @@ -0,0 +1,134 @@ +class Thor + module Actions + + # Creates an empty directory. + # + # ==== Parameters + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # empty_directory "doc" + # + def empty_directory(destination, config={}) + action EmptyDirectory.new(self, destination, config) + end + + # Class which holds create directory logic. This is the base class for + # other actions like create_file and directory. + # + # This implementation is based in Templater actions, created by Jonas Nicklas + # and Michael S. Klishin under MIT LICENSE. + # + class EmptyDirectory #:nodoc: + attr_reader :base, :destination, :given_destination, :relative_destination, :config + + # Initializes given the source and destination. + # + # ==== Parameters + # base:: A Thor::Base instance + # source:: Relative path to the source of this file + # destination:: Relative path to the destination of this file + # config:: give :verbose => false to not log the status. + # + def initialize(base, destination, config={}) + @base, @config = base, { :verbose => true }.merge(config) + self.destination = destination + end + + # Checks if the destination file already exists. + # + # ==== Returns + # Boolean:: true if the file exists, false otherwise. + # + def exists? + ::File.exists?(destination) + end + + def invoke! + invoke_with_conflict_check do + ::FileUtils.mkdir_p(destination) + end + end + + def revoke! + say_status :remove, :red + ::FileUtils.rm_rf(destination) if !pretend? && exists? + given_destination + end + + protected + + # Shortcut for pretend. + # + def pretend? + base.options[:pretend] + end + + # Sets the absolute destination value from a relative destination value. + # It also stores the given and relative destination. Let's suppose our + # script is being executed on "dest", it sets the destination root to + # "dest". The destination, given_destination and relative_destination + # are related in the following way: + # + # inside "bar" do + # empty_directory "baz" + # end + # + # destination #=> dest/bar/baz + # relative_destination #=> bar/baz + # given_destination #=> baz + # + def destination=(destination) + if destination + @given_destination = convert_encoded_instructions(destination.to_s) + @destination = ::File.expand_path(@given_destination, base.destination_root) + @relative_destination = base.relative_to_original_destination_root(@destination) + end + end + + # Filenames in the encoded form are converted. If you have a file: + # + # %class_name%.rb + # + # It gets the class name from the base and replace it: + # + # user.rb + # + def convert_encoded_instructions(filename) + filename.gsub(/%(.*?)%/) do |string| + instruction = $1.strip + base.respond_to?(instruction) ? base.send(instruction) : string + end + end + + # Receives a hash of options and just execute the block if some + # conditions are met. + # + def invoke_with_conflict_check(&block) + if exists? + on_conflict_behavior(&block) + else + say_status :create, :green + block.call unless pretend? + end + + destination + end + + # What to do when the destination file already exists. + # + def on_conflict_behavior(&block) + say_status :exist, :blue + end + + # Shortcut to say_status shell method. + # + def say_status(status, color) + base.shell.say_status status, relative_destination, color if config[:verbose] + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/file_manipulation.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/file_manipulation.rb new file mode 100644 index 0000000000..44d6836c10 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/file_manipulation.rb @@ -0,0 +1,223 @@ +require 'erb' +require 'open-uri' + +class Thor + module Actions + + # Copies the file from the relative source to the relative destination. If + # the destination is not given it's assumed to be equal to the source. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # copy_file "README", "doc/README" + # + # copy_file "doc/README" + # + def copy_file(source, destination=nil, config={}, &block) + destination ||= source + source = File.expand_path(find_in_source_paths(source.to_s)) + + create_file destination, nil, config do + content = File.binread(source) + content = block.call(content) if block + content + end + end + + # Gets the content at the given address and places it at the given relative + # destination. If a block is given instead of destination, the content of + # the url is yielded and used as location. + # + # ==== Parameters + # source:: the address of the given content. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # get "http://gist.github.com/103208", "doc/README" + # + # get "http://gist.github.com/103208" do |content| + # content.split("\n").first + # end + # + def get(source, destination=nil, config={}, &block) + source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^http\:\/\// + render = File.binread(source) + + destination ||= if block_given? + block.arity == 1 ? block.call(render) : block.call + else + File.basename(source) + end + + create_file destination, render, config + end + + # Gets an ERB template at the relative source, executes it and makes a copy + # at the relative destination. If the destination is not given it's assumed + # to be equal to the source removing .tt from the filename. + # + # ==== Parameters + # source:: the relative path to the source root. + # destination:: the relative path to the destination root. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # template "README", "doc/README" + # + # template "doc/README" + # + def template(source, destination=nil, config={}, &block) + destination ||= source + source = File.expand_path(find_in_source_paths(source.to_s)) + context = instance_eval('binding') + + create_file destination, nil, config do + content = ERB.new(::File.binread(source), nil, '-').result(context) + content = block.call(content) if block + content + end + end + + # Changes the mode of the given file or directory. + # + # ==== Parameters + # mode:: the file mode + # path:: the name of the file to change mode + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # chmod "script/*", 0755 + # + def chmod(path, mode, config={}) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) + FileUtils.chmod_R(mode, path) unless options[:pretend] + end + + # Prepend text to a file. Since it depends on inject_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # data:: the data to prepend to the file, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # prepend_file 'config/environments/test.rb', 'config.gem "rspec"' + # + # prepend_file 'config/environments/test.rb' do + # 'config.gem "rspec"' + # end + # + def prepend_file(path, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:after => /\A/) + inject_into_file(path, *(args << config), &block) + end + + # Append text to a file. Since it depends on inject_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # data:: the data to append to the file, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # append_file 'config/environments/test.rb', 'config.gem "rspec"' + # + # append_file 'config/environments/test.rb' do + # 'config.gem "rspec"' + # end + # + def append_file(path, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:before => /\z/) + inject_into_file(path, *(args << config), &block) + end + + # Injects text right after the class definition. Since it depends on + # inject_into_file, it's reversible. + # + # ==== Parameters + # path:: path of the file to be changed + # klass:: the class to be manipulated + # data:: the data to append to the class, can be also given as a block. + # config:: give :verbose => false to not log the status. + # + # ==== Examples + # + # inject_into_class "app/controllers/application_controller.rb", " filter_parameter :password\n" + # + # inject_into_class "app/controllers/application_controller.rb", ApplicationController do + # " filter_parameter :password\n" + # end + # + def inject_into_class(path, klass, *args, &block) + config = args.last.is_a?(Hash) ? args.pop : {} + config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/) + inject_into_file(path, *(args << config), &block) + end + + # Run a regular expression replacement on a file. + # + # ==== Parameters + # path:: path of the file to be changed + # flag:: the regexp or string to be replaced + # replacement:: the replacement, can be also given as a block + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' + # + # gsub_file 'README', /rake/, :green do |match| + # match << " no more. Use thor!" + # end + # + def gsub_file(path, flag, *args, &block) + return unless behavior == :invoke + config = args.last.is_a?(Hash) ? args.pop : {} + + path = File.expand_path(path, destination_root) + say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) + + unless options[:pretend] + content = File.binread(path) + content.gsub!(flag, *args, &block) + File.open(path, 'wb') { |file| file.write(content) } + end + end + + # Removes a file at the given location. + # + # ==== Parameters + # path:: path of the file to be changed + # config:: give :verbose => false to not log the status. + # + # ==== Example + # + # remove_file 'README' + # remove_file 'app/controllers/application_controller.rb' + # + def remove_file(path, config={}) + return unless behavior == :invoke + path = File.expand_path(path, destination_root) + + say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) + ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path) + end + alias :remove_dir :remove_file + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/inject_into_file.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/inject_into_file.rb new file mode 100644 index 0000000000..350ab73862 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/inject_into_file.rb @@ -0,0 +1,101 @@ +require 'thor/actions/empty_directory' + +class Thor + module Actions + + # Injects the given content into a file. Different from gsub_file, this + # method is reversible. + # + # ==== Parameters + # destination:: Relative path to the destination root + # data:: Data to add to the file. Can be given as a block. + # config:: give :verbose => false to not log the status and the flag + # for injection (:after or :before). + # + # ==== Examples + # + # inject_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n" + # + # inject_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do + # gems = ask "Which gems would you like to add?" + # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n") + # end + # + def inject_into_file(destination, *args, &block) + if block_given? + data, config = block, args.shift + else + data, config = args.shift, args.shift + end + action InjectIntoFile.new(self, destination, data, config) + end + + class InjectIntoFile < EmptyDirectory #:nodoc: + attr_reader :replacement, :flag, :behavior + + def initialize(base, destination, data, config) + super(base, destination, { :verbose => true }.merge(config)) + + @behavior, @flag = if @config.key?(:after) + [:after, @config.delete(:after)] + else + [:before, @config.delete(:before)] + end + + @replacement = data.is_a?(Proc) ? data.call : data + @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp) + end + + def invoke! + say_status :invoke + + content = if @behavior == :after + '\0' + replacement + else + replacement + '\0' + end + + replace!(/#{flag}/, content) + end + + def revoke! + say_status :revoke + + regexp = if @behavior == :after + content = '\1\2' + /(#{flag})(.*)(#{Regexp.escape(replacement)})/m + else + content = '\2\3' + /(#{Regexp.escape(replacement)})(.*)(#{flag})/m + end + + replace!(regexp, content) + end + + protected + + def say_status(behavior) + status = if flag == /\A/ + behavior == :invoke ? :prepend : :unprepend + elsif flag == /\z/ + behavior == :invoke ? :append : :unappend + else + behavior == :invoke ? :inject : :deinject + end + + super(status, config[:verbose]) + end + + # Adds the content to the file. + # + def replace!(regexp, string) + unless base.options[:pretend] + content = File.binread(destination) + content.gsub!(regexp, string) + File.open(destination, 'wb') { |file| file.write(content) } + end + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/base.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/base.rb new file mode 100644 index 0000000000..aae4cdb89c --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/base.rb @@ -0,0 +1,515 @@ +require 'thor/core_ext/hash_with_indifferent_access' +require 'thor/core_ext/ordered_hash' +require 'thor/error' +require 'thor/shell' +require 'thor/invocation' +require 'thor/parser' +require 'thor/task' +require 'thor/util' + +class Thor + # Shortcuts for help. + HELP_MAPPINGS = %w(-h -? --help -D) + + # Thor methods that should not be overwritten by the user. + THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root + action add_file create_file in_root inside run run_ruby_script) + + module Base + attr_accessor :options + + # It receives arguments in an Array and two hashes, one for options and + # other for configuration. + # + # Notice that it does not check if all required arguments were supplied. + # It should be done by the parser. + # + # ==== Parameters + # args:: An array of objects. The objects are applied to their + # respective accessors declared with argument. + # + # options:: An options hash that will be available as self.options. + # The hash given is converted to a hash with indifferent + # access, magic predicates (options.skip?) and then frozen. + # + # config:: Configuration for this Thor class. + # + def initialize(args=[], options={}, config={}) + Thor::Arguments.parse(self.class.arguments, args).each do |key, value| + send("#{key}=", value) + end + + parse_options = self.class.class_options + + if options.is_a?(Array) + task_options = config.delete(:task_options) # hook for start + parse_options = parse_options.merge(task_options) if task_options + array_options, hash_options = options, {} + else + array_options, hash_options = [], options + end + + options = Thor::Options.parse(parse_options, array_options) + self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).merge!(hash_options) + self.options.freeze + end + + class << self + def included(base) #:nodoc: + base.send :extend, ClassMethods + base.send :include, Invocation + base.send :include, Shell + end + + # Returns the classes that inherits from Thor or Thor::Group. + # + # ==== Returns + # Array[Class] + # + def subclasses + @subclasses ||= [] + end + + # Returns the files where the subclasses are kept. + # + # ==== Returns + # Hash[path => Class] + # + def subclass_files + @subclass_files ||= Hash.new{ |h,k| h[k] = [] } + end + + # Whenever a class inherits from Thor or Thor::Group, we should track the + # class and the file on Thor::Base. This is the method responsable for it. + # + def register_klass_file(klass) #:nodoc: + file = caller[1].match(/(.*):\d+/)[1] + Thor::Base.subclasses << klass unless Thor::Base.subclasses.include?(klass) + + file_subclasses = Thor::Base.subclass_files[File.expand_path(file)] + file_subclasses << klass unless file_subclasses.include?(klass) + end + end + + module ClassMethods + attr_accessor :debugging + + # Adds an argument to the class and creates an attr_accessor for it. + # + # Arguments are different from options in several aspects. The first one + # is how they are parsed from the command line, arguments are retrieved + # from position: + # + # thor task NAME + # + # Instead of: + # + # thor task --name=NAME + # + # Besides, arguments are used inside your code as an accessor (self.argument), + # while options are all kept in a hash (self.options). + # + # Finally, arguments cannot have type :default or :boolean but can be + # optional (supplying :optional => :true or :required => false), although + # you cannot have a required argument after a non-required argument. If you + # try it, an error is raised. + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc - Description for the argument. + # :required - If the argument is required or not. + # :optional - If the argument is optional or not. + # :type - The type of the argument, can be :string, :hash, :array, :numeric. + # :default - Default value for this argument. It cannot be required and have default values. + # :banner - String to show on usage notes. + # + # ==== Errors + # ArgumentError:: Raised if you supply a required argument after a non required one. + # + def argument(name, options={}) + is_thor_reserved_word?(name, :argument) + no_tasks { attr_accessor name } + + required = if options.key?(:optional) + !options[:optional] + elsif options.key?(:required) + options[:required] + else + options[:default].nil? + end + + remove_argument name + + arguments.each do |argument| + next if argument.required? + raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " << + "the non-required argument #{argument.human_name.inspect}." + end if required + + arguments << Thor::Argument.new(name, options[:desc], required, options[:type], + options[:default], options[:banner]) + end + + # Returns this class arguments, looking up in the ancestors chain. + # + # ==== Returns + # Array[Thor::Argument] + # + def arguments + @arguments ||= from_superclass(:arguments, []) + end + + # Adds a bunch of options to the set of class options. + # + # class_options :foo => false, :bar => :required, :baz => :string + # + # If you prefer more detailed declaration, check class_option. + # + # ==== Parameters + # Hash[Symbol => Object] + # + def class_options(options=nil) + @class_options ||= from_superclass(:class_options, {}) + build_options(options, @class_options) if options + @class_options + end + + # Adds an option to the set of class options + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described below. + # + # ==== Options + # :desc - Description for the argument. + # :required - If the argument is required or not. + # :default - Default value for this argument. + # :group - The group for this options. Use by class options to output options in different levels. + # :aliases - Aliases for this option. + # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. + # :banner - String to show on usage notes. + # + def class_option(name, options={}) + build_option(name, options, class_options) + end + + # Removes a previous defined argument. If :undefine is given, undefine + # accessors as well. + # + # ==== Paremeters + # names:: Arguments to be removed + # + # ==== Examples + # + # remove_argument :foo + # remove_argument :foo, :bar, :baz, :undefine => true + # + def remove_argument(*names) + options = names.last.is_a?(Hash) ? names.pop : {} + + names.each do |name| + arguments.delete_if { |a| a.name == name.to_s } + undef_method name, "#{name}=" if options[:undefine] + end + end + + # Removes a previous defined class option. + # + # ==== Paremeters + # names:: Class options to be removed + # + # ==== Examples + # + # remove_class_option :foo + # remove_class_option :foo, :bar, :baz + # + def remove_class_option(*names) + names.each do |name| + class_options.delete(name) + end + end + + # Defines the group. This is used when thor list is invoked so you can specify + # that only tasks from a pre-defined group will be shown. Defaults to standard. + # + # ==== Parameters + # name + # + def group(name=nil) + case name + when nil + @group ||= from_superclass(:group, 'standard') + else + @group = name.to_s + end + end + + # Returns the tasks for this Thor class. + # + # ==== Returns + # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task + # objects as values. + # + def tasks + @tasks ||= Thor::CoreExt::OrderedHash.new + end + + # Returns the tasks for this Thor class and all subclasses. + # + # ==== Returns + # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task + # objects as values. + # + def all_tasks + @all_tasks ||= from_superclass(:all_tasks, Thor::CoreExt::OrderedHash.new) + @all_tasks.merge(tasks) + end + + # Removes a given task from this Thor class. This is usually done if you + # are inheriting from another class and don't want it to be available + # anymore. + # + # By default it only remove the mapping to the task. But you can supply + # :undefine => true to undefine the method from the class as well. + # + # ==== Parameters + # name:: The name of the task to be removed + # options:: You can give :undefine => true if you want tasks the method + # to be undefined from the class as well. + # + def remove_task(*names) + options = names.last.is_a?(Hash) ? names.pop : {} + + names.each do |name| + tasks.delete(name.to_s) + all_tasks.delete(name.to_s) + undef_method name if options[:undefine] + end + end + + # All methods defined inside the given block are not added as tasks. + # + # So you can do: + # + # class MyScript < Thor + # no_tasks do + # def this_is_not_a_task + # end + # end + # end + # + # You can also add the method and remove it from the task list: + # + # class MyScript < Thor + # def this_is_not_a_task + # end + # remove_task :this_is_not_a_task + # end + # + def no_tasks + @no_tasks = true + yield + @no_tasks = false + end + + # Sets the namespace for the Thor or Thor::Group class. By default the + # namespace is retrieved from the class name. If your Thor class is named + # Scripts::MyScript, the help method, for example, will be called as: + # + # thor scripts:my_script -h + # + # If you change the namespace: + # + # namespace :my_scripts + # + # You change how your tasks are invoked: + # + # thor my_scripts -h + # + # Finally, if you change your namespace to default: + # + # namespace :default + # + # Your tasks can be invoked with a shortcut. Instead of: + # + # thor :my_task + # + def namespace(name=nil) + case name + when nil + @namespace ||= Thor::Util.namespace_from_thor_class(self, false) + else + @namespace = name.to_s + end + end + + # Default way to start generators from the command line. + # + def start(given_args=ARGV, config={}) + self.debugging = given_args.include?("--debug") + config[:shell] ||= Thor::Base.shell.new + yield + rescue Thor::Error => e + if debugging + raise e + else + config[:shell].error e.message + end + exit(1) if exit_on_failure? + end + + protected + + # Prints the class options per group. If an option does not belong to + # any group, it's printed as Class option. + # + def class_options_help(shell, groups={}) #:nodoc: + # Group options by group + class_options.each do |_, value| + groups[value.group] ||= [] + groups[value.group] << value + end + + # Deal with default group + global_options = groups.delete(nil) || [] + print_options(shell, global_options) + + # Print all others + groups.each do |group_name, options| + print_options(shell, options, group_name) + end + end + + # Receives a set of options and print them. + def print_options(shell, options, group_name=nil) + return if options.empty? + + list = [] + padding = options.collect{ |o| o.aliases.size }.max.to_i * 4 + + options.each do |option| + item = [ option.usage(padding) ] + item.push(option.description ? "# #{option.description}" : "") + + list << item + list << [ "", "# Default: #{option.default}" ] if option.show_default? + end + + shell.say(group_name ? "#{group_name} options:" : "Options:") + shell.print_table(list, :ident => 2) + shell.say "" + end + + # Raises an error if the word given is a Thor reserved word. + # + def is_thor_reserved_word?(word, type) #:nodoc: + return false unless THOR_RESERVED_WORDS.include?(word.to_s) + raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}" + end + + # Build an option and adds it to the given scope. + # + # ==== Parameters + # name:: The name of the argument. + # options:: Described in both class_option and method_option. + # + def build_option(name, options, scope) #:nodoc: + scope[name] = Thor::Option.new(name, options[:desc], options[:required], + options[:type], options[:default], options[:banner], + options[:group], options[:aliases]) + end + + # Receives a hash of options, parse them and add to the scope. This is a + # fast way to set a bunch of options: + # + # build_options :foo => true, :bar => :required, :baz => :string + # + # ==== Parameters + # Hash[Symbol => Object] + # + def build_options(options, scope) #:nodoc: + options.each do |key, value| + scope[key] = Thor::Option.parse(key, value) + end + end + + # Finds a task with the given name. If the task belongs to the current + # class, just return it, otherwise dup it and add the fresh copy to the + # current task hash. + # + def find_and_refresh_task(name) #:nodoc: + task = if task = tasks[name.to_s] + task + elsif task = all_tasks[name.to_s] + tasks[name.to_s] = task.clone + else + raise ArgumentError, "You supplied :for => #{name.inspect}, but the task #{name.inspect} could not be found." + end + end + + # Everytime someone inherits from a Thor class, register the klass + # and file into baseclass. + # + def inherited(klass) + Thor::Base.register_klass_file(klass) + end + + # Fire this callback whenever a method is added. Added methods are + # tracked as tasks by invoking the create_task method. + # + def method_added(meth) + meth = meth.to_s + + if meth == "initialize" + initialize_added + return + end + + # Return if it's not a public instance method + return unless public_instance_methods.include?(meth) || + public_instance_methods.include?(meth.to_sym) + + return if @no_tasks || !create_task(meth) + + is_thor_reserved_word?(meth, :task) + Thor::Base.register_klass_file(self) + end + + # Retrieves a value from superclass. If it reaches the baseclass, + # returns default. + # + def from_superclass(method, default=nil) + if self == baseclass || !superclass.respond_to?(method, true) + default + else + value = superclass.send(method) + value.dup if value + end + end + + # A flag that makes the process exit with status 1 if any error happens. + # + def exit_on_failure? + false + end + + # SIGNATURE: Sets the baseclass. This is where the superclass lookup + # finishes. + def baseclass #:nodoc: + end + + # SIGNATURE: Creates a new task if valid_task? is true. This method is + # called when a new method is added to the class. + def create_task(meth) #:nodoc: + end + + # SIGNATURE: Defines behavior when the initialize method is added to the + # class. + def initialize_added #:nodoc: + end + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/file_binary_read.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/file_binary_read.rb new file mode 100644 index 0000000000..d6af7e44b0 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/file_binary_read.rb @@ -0,0 +1,9 @@ +class File #:nodoc: + + unless File.respond_to?(:binread) + def self.binread(file) + File.open(file, 'rb') { |f| f.read } + end + end + +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/hash_with_indifferent_access.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/hash_with_indifferent_access.rb new file mode 100644 index 0000000000..78bc5cf4bf --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/hash_with_indifferent_access.rb @@ -0,0 +1,75 @@ +class Thor + module CoreExt #:nodoc: + + # A hash with indifferent access and magic predicates. + # + # hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true + # + # hash[:foo] #=> 'bar' + # hash['foo'] #=> 'bar' + # hash.foo? #=> true + # + class HashWithIndifferentAccess < ::Hash #:nodoc: + + def initialize(hash={}) + super() + hash.each do |key, value| + self[convert_key(key)] = value + end + end + + def [](key) + super(convert_key(key)) + end + + def []=(key, value) + super(convert_key(key), value) + end + + def delete(key) + super(convert_key(key)) + end + + def values_at(*indices) + indices.collect { |key| self[convert_key(key)] } + end + + def merge(other) + dup.merge!(other) + end + + def merge!(other) + other.each do |key, value| + self[convert_key(key)] = value + end + self + end + + protected + + def convert_key(key) + key.is_a?(Symbol) ? key.to_s : key + end + + # Magic predicates. For instance: + # + # options.force? # => !!options['force'] + # options.shebang # => "/usr/lib/local/ruby" + # options.test_framework?(:rspec) # => options[:test_framework] == :rspec + # + def method_missing(method, *args, &block) + method = method.to_s + if method =~ /^(\w+)\?$/ + if args.empty? + !!self[$1] + else + self[$1] == args.first + end + else + self[method] + end + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/ordered_hash.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/ordered_hash.rb new file mode 100644 index 0000000000..27fea5bb35 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/ordered_hash.rb @@ -0,0 +1,100 @@ +class Thor + module CoreExt #:nodoc: + + if RUBY_VERSION >= '1.9' + class OrderedHash < ::Hash + end + else + # This class is based on the Ruby 1.9 ordered hashes. + # + # It keeps the semantics and most of the efficiency of normal hashes + # while also keeping track of the order in which elements were set. + # + class OrderedHash #:nodoc: + include Enumerable + + Node = Struct.new(:key, :value, :next, :prev) + + def initialize + @hash = {} + end + + def [](key) + @hash[key] && @hash[key].value + end + + def []=(key, value) + if node = @hash[key] + node.value = value + else + node = Node.new(key, value) + + if @first.nil? + @first = @last = node + else + node.prev = @last + @last.next = node + @last = node + end + end + + @hash[key] = node + value + end + + def delete(key) + if node = @hash[key] + prev_node = node.prev + next_node = node.next + + next_node.prev = prev_node if next_node + prev_node.next = next_node if prev_node + + @first = next_node if @first == node + @last = prev_node if @last == node + + value = node.value + end + + @hash.delete(key) + value + end + + def keys + self.map { |k, v| k } + end + + def values + self.map { |k, v| v } + end + + def each + return unless @first + yield [@first.key, @first.value] + node = @first + yield [node.key, node.value] while node = node.next + self + end + + def merge(other) + hash = self.class.new + + self.each do |key, value| + hash[key] = value + end + + other.each do |key, value| + hash[key] = value + end + + hash + end + + def empty? + @hash.empty? + end + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/error.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/error.rb new file mode 100644 index 0000000000..f9b31a35d1 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/error.rb @@ -0,0 +1,27 @@ +class Thor + # Thor::Error is raised when it's caused by wrong usage of thor classes. Those + # errors have their backtrace supressed and are nicely shown to the user. + # + # Errors that are caused by the developer, like declaring a method which + # overwrites a thor keyword, it SHOULD NOT raise a Thor::Error. This way, we + # ensure that developer errors are shown with full backtrace. + # + class Error < StandardError + end + + # Raised when a task was not found. + # + class UndefinedTaskError < Error + end + + # Raised when a task was found, but not invoked properly. + # + class InvocationError < Error + end + + class RequiredArgumentMissingError < InvocationError + end + + class MalformattedArgumentError < InvocationError + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/group.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/group.rb new file mode 100644 index 0000000000..a585b37b73 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/group.rb @@ -0,0 +1,267 @@ +# Thor has a special class called Thor::Group. The main difference to Thor class +# is that it invokes all tasks at once. It also include some methods that allows +# invocations to be done at the class method, which are not available to Thor +# tasks. +# +class Thor::Group + class << self + # The descrition for this Thor::Group. If none is provided, but a source root + # exists, tries to find the USAGE one folder above it, otherwise searches + # in the superclass. + # + # ==== Parameters + # description:: The description for this Thor::Group. + # + def desc(description=nil) + case description + when nil + @desc ||= from_superclass(:desc, nil) + else + @desc = description + end + end + + # Start works differently in Thor::Group, it simply invokes all tasks + # inside the class. + # + def start(given_args=ARGV, config={}) + super do + if Thor::HELP_MAPPINGS.include?(given_args.first) + help(config[:shell]) + return + end + + args, opts = Thor::Options.split(given_args) + new(args, opts, config).invoke + end + end + + # Prints help information. + # + # ==== Options + # short:: When true, shows only usage. + # + def help(shell) + shell.say "Usage:" + shell.say " #{banner}\n" + shell.say + class_options_help(shell) + shell.say self.desc if self.desc + end + + # Stores invocations for this class merging with superclass values. + # + def invocations #:nodoc: + @invocations ||= from_superclass(:invocations, {}) + end + + # Stores invocation blocks used on invoke_from_option. + # + def invocation_blocks #:nodoc: + @invocation_blocks ||= from_superclass(:invocation_blocks, {}) + end + + # Invoke the given namespace or class given. It adds an instance + # method that will invoke the klass and task. You can give a block to + # configure how it will be invoked. + # + # The namespace/class given will have its options showed on the help + # usage. Check invoke_from_option for more information. + # + def invoke(*names, &block) + options = names.last.is_a?(Hash) ? names.pop : {} + verbose = options.fetch(:verbose, true) + + names.each do |name| + invocations[name] = false + invocation_blocks[name] = block if block_given? + + class_eval <<-METHOD, __FILE__, __LINE__ + def _invoke_#{name.to_s.gsub(/\W/, '_')} + klass, task = self.class.prepare_for_invocation(nil, #{name.inspect}) + + if klass + say_status :invoke, #{name.inspect}, #{verbose.inspect} + block = self.class.invocation_blocks[#{name.inspect}] + _invoke_for_class_method klass, task, &block + else + say_status :error, %(#{name.inspect} [not found]), :red + end + end + METHOD + end + end + + # Invoke a thor class based on the value supplied by the user to the + # given option named "name". A class option must be created before this + # method is invoked for each name given. + # + # ==== Examples + # + # class GemGenerator < Thor::Group + # class_option :test_framework, :type => :string + # invoke_from_option :test_framework + # end + # + # ==== Boolean options + # + # In some cases, you want to invoke a thor class if some option is true or + # false. This is automatically handled by invoke_from_option. Then the + # option name is used to invoke the generator. + # + # ==== Preparing for invocation + # + # In some cases you want to customize how a specified hook is going to be + # invoked. You can do that by overwriting the class method + # prepare_for_invocation. The class method must necessarily return a klass + # and an optional task. + # + # ==== Custom invocations + # + # You can also supply a block to customize how the option is giong to be + # invoked. The block receives two parameters, an instance of the current + # class and the klass to be invoked. + # + def invoke_from_option(*names, &block) + options = names.last.is_a?(Hash) ? names.pop : {} + verbose = options.fetch(:verbose, :white) + + names.each do |name| + unless class_options.key?(name) + raise ArgumentError, "You have to define the option #{name.inspect} " << + "before setting invoke_from_option." + end + + invocations[name] = true + invocation_blocks[name] = block if block_given? + + class_eval <<-METHOD, __FILE__, __LINE__ + def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')} + return unless options[#{name.inspect}] + + value = options[#{name.inspect}] + value = #{name.inspect} if TrueClass === value + klass, task = self.class.prepare_for_invocation(#{name.inspect}, value) + + if klass + say_status :invoke, value, #{verbose.inspect} + block = self.class.invocation_blocks[#{name.inspect}] + _invoke_for_class_method klass, task, &block + else + say_status :error, %(\#{value} [not found]), :red + end + end + METHOD + end + end + + # Remove a previously added invocation. + # + # ==== Examples + # + # remove_invocation :test_framework + # + def remove_invocation(*names) + names.each do |name| + remove_task(name) + remove_class_option(name) + invocations.delete(name) + invocation_blocks.delete(name) + end + end + + # Overwrite class options help to allow invoked generators options to be + # shown recursively when invoking a generator. + # + def class_options_help(shell, groups={}) #:nodoc: + get_options_from_invocations(groups, class_options) do |klass| + klass.send(:get_options_from_invocations, groups, class_options) + end + super(shell, groups) + end + + # Get invocations array and merge options from invocations. Those + # options are added to group_options hash. Options that already exists + # in base_options are not added twice. + # + def get_options_from_invocations(group_options, base_options) #:nodoc: + invocations.each do |name, from_option| + value = if from_option + option = class_options[name] + option.type == :boolean ? name : option.default + else + name + end + next unless value + + klass, task = prepare_for_invocation(name, value) + next unless klass && klass.respond_to?(:class_options) + + value = value.to_s + human_name = value.respond_to?(:classify) ? value.classify : value + + group_options[human_name] ||= [] + group_options[human_name] += klass.class_options.values.select do |option| + base_options[option.name.to_sym].nil? && option.group.nil? && + !group_options.values.flatten.any? { |i| i.name == option.name } + end + + yield klass if block_given? + end + end + + # Returns tasks ready to be printed. + def printable_tasks(*) + item = [] + item << banner + item << (desc ? "# #{desc.gsub(/\s+/m,' ')}" : "") + [item] + end + + protected + + # The banner for this class. You can customize it if you are invoking the + # thor class by another ways which is not the Thor::Runner. + # + def banner + "thor #{self_task.formatted_usage(self, false)}" + end + + # Represents the whole class as a task. + def self_task #:nodoc: + Thor::Task::Dynamic.new(self.namespace, class_options) + end + + def baseclass #:nodoc: + Thor::Group + end + + def create_task(meth) #:nodoc: + tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil) + true + end + end + + include Thor::Base + + protected + + # Shortcut to invoke with padding and block handling. Use internally by + # invoke and invoke_from_option class methods. + def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc: + shell.padding += 1 + + result = if block_given? + if block.arity == 2 + block.call(self, klass) + else + block.call(self, klass, task) + end + else + invoke klass, task, *args + end + + shell.padding -= 1 + result + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/invocation.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/invocation.rb new file mode 100644 index 0000000000..32e6a72454 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/invocation.rb @@ -0,0 +1,178 @@ +class Thor + module Invocation + def self.included(base) #:nodoc: + base.extend ClassMethods + end + + module ClassMethods + # Prepare for class methods invocations. This method must return a klass to + # have the invoked class options showed in help messages in generators. + # + def prepare_for_invocation(key, name) #:nodoc: + case name + when Symbol, String + Thor::Util.namespace_to_thor_class_and_task(name.to_s, false) + else + name + end + end + end + + # Make initializer aware of invocations and the initializer proc. + # + def initialize(args=[], options={}, config={}, &block) #:nodoc: + @_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] } + @_initializer = [ args, options, config ] + super + end + + # Receives a name and invokes it. The name can be a string (either "task" or + # "namespace:task"), a Thor::Task, a Class or a Thor instance. If the task + # cannot be guessed by name, it can also be supplied as second argument. + # + # You can also supply the arguments, options and configuration values for + # the task to be invoked, if none is given, the same values used to + # initialize the invoker are used to initialize the invoked. + # + # ==== Examples + # + # class A < Thor + # def foo + # invoke :bar + # invoke "b:hello", ["José"] + # end + # + # def bar + # invoke "b:hello", ["José"] + # end + # end + # + # class B < Thor + # def hello(name) + # puts "hello #{name}" + # end + # end + # + # You can notice that the method "foo" above invokes two tasks: "bar", + # which belongs to the same class and "hello" which belongs to the class B. + # + # By using an invocation system you ensure that a task is invoked only once. + # In the example above, invoking "foo" will invoke "b:hello" just once, even + # if it's invoked later by "bar" method. + # + # When class A invokes class B, all arguments used on A initialization are + # supplied to B. This allows lazy parse of options. Let's suppose you have + # some rspec tasks: + # + # class Rspec < Thor::Group + # class_option :mock_framework, :type => :string, :default => :rr + # + # def invoke_mock_framework + # invoke "rspec:#{options[:mock_framework]}" + # end + # end + # + # As you noticed, it invokes the given mock framework, which might have its + # own options: + # + # class Rspec::RR < Thor::Group + # class_option :style, :type => :string, :default => :mock + # end + # + # Since it's not rspec concern to parse mock framework options, when RR + # is invoked all options are parsed again, so RR can extract only the options + # that it's going to use. + # + # If you want Rspec::RR to be initialized with its own set of options, you + # have to do that explicitely: + # + # invoke "rspec:rr", [], :style => :foo + # + # Besides giving an instance, you can also give a class to invoke: + # + # invoke Rspec::RR, [], :style => :foo + # + def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil) + task, args, opts, config = nil, task, args, opts if task.nil? || task.is_a?(Array) + args, opts, config = nil, args, opts if args.is_a?(Hash) + + object, task = _prepare_for_invocation(name, task) + klass, instance = _initialize_klass_with_initializer(object, args, opts, config) + + method_args = [] + current = @_invocations[klass] + + iterator = proc do |_, task| + unless current.include?(task.name) + current << task.name + task.run(instance, method_args) + end + end + + if task + args ||= [] + method_args = args[Range.new(klass.arguments.size, -1)] || [] + iterator.call(nil, task) + else + klass.all_tasks.map(&iterator) + end + end + + protected + + # Configuration values that are shared between invocations. + # + def _shared_configuration #:nodoc: + { :invocations => @_invocations } + end + + # Prepare for invocation in the instance level. In this case, we have to + # take into account that a just a task name from the current class was + # given or even a Thor::Task object. + # + def _prepare_for_invocation(name, sent_task=nil) #:nodoc: + if name.is_a?(Thor::Task) + task = name + elsif task = self.class.all_tasks[name.to_s] + object = self + else + object, task = self.class.prepare_for_invocation(nil, name) + task ||= sent_task + end + + # If the object was not set, use self and use the name as task. + object, task = self, name unless object + return object, _validate_task(object, task) + end + + # Check if the object given is a Thor class object and get a task object + # for it. + # + def _validate_task(object, task) #:nodoc: + klass = object.is_a?(Class) ? object : object.class + raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base + + task ||= klass.default_task if klass <= Thor + task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task) + task + end + + # Initialize klass using values stored in the @_initializer. + # + def _initialize_klass_with_initializer(object, args, opts, config) #:nodoc: + if object.is_a?(Class) + klass = object + + stored_args, stored_opts, stored_config = @_initializer + args ||= stored_args.dup + opts ||= stored_opts.dup + + config ||= {} + config = stored_config.merge(_shared_configuration).merge!(config) + [ klass, klass.new(args, opts, config) ] + else + [ object.class, object ] + end + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser.rb new file mode 100644 index 0000000000..57a3f6e1a5 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser.rb @@ -0,0 +1,4 @@ +require 'thor/parser/argument' +require 'thor/parser/arguments' +require 'thor/parser/option' +require 'thor/parser/options' diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/argument.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/argument.rb new file mode 100644 index 0000000000..aa8ace4719 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/argument.rb @@ -0,0 +1,67 @@ +class Thor + class Argument #:nodoc: + VALID_TYPES = [ :numeric, :hash, :array, :string ] + + attr_reader :name, :description, :required, :type, :default, :banner + alias :human_name :name + + def initialize(name, description=nil, required=true, type=:string, default=nil, banner=nil) + class_name = self.class.name.split("::").last + + raise ArgumentError, "#{class_name} name can't be nil." if name.nil? + raise ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type) + + @name = name.to_s + @description = description + @required = required || false + @type = (type || :string).to_sym + @default = default + @banner = banner || default_banner + + validate! # Trigger specific validations + end + + def usage + required? ? banner : "[#{banner}]" + end + + def required? + required + end + + def show_default? + case default + when Array, String, Hash + !default.empty? + else + default + end + end + + protected + + def validate! + raise ArgumentError, "An argument cannot be required and have default value." if required? && !default.nil? + end + + def valid_type?(type) + VALID_TYPES.include?(type.to_sym) + end + + def default_banner + case type + when :boolean + nil + when :string, :default + human_name.upcase + when :numeric + "N" + when :hash + "key:value" + when :array + "one two three" + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/arguments.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/arguments.rb new file mode 100644 index 0000000000..fb5d965e06 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/arguments.rb @@ -0,0 +1,145 @@ +class Thor + class Arguments #:nodoc: + NUMERIC = /(\d*\.\d+|\d+)/ + + # Receives an array of args and returns two arrays, one with arguments + # and one with switches. + # + def self.split(args) + arguments = [] + + args.each do |item| + break if item =~ /^-/ + arguments << item + end + + return arguments, args[Range.new(arguments.size, -1)] + end + + def self.parse(base, args) + new(base).parse(args) + end + + # Takes an array of Thor::Argument objects. + # + def initialize(arguments=[]) + @assigns, @non_assigned_required = {}, [] + @switches = arguments + + arguments.each do |argument| + if argument.default + @assigns[argument.human_name] = argument.default + elsif argument.required? + @non_assigned_required << argument + end + end + end + + def parse(args) + @pile = args.dup + + @switches.each do |argument| + break unless peek + @non_assigned_required.delete(argument) + @assigns[argument.human_name] = send(:"parse_#{argument.type}", argument.human_name) + end + + check_requirement! + @assigns + end + + private + + def peek + @pile.first + end + + def shift + @pile.shift + end + + def unshift(arg) + unless arg.kind_of?(Array) + @pile.unshift(arg) + else + @pile = arg + @pile + end + end + + def current_is_value? + peek && peek.to_s !~ /^-/ + end + + # Runs through the argument array getting strings that contains ":" and + # mark it as a hash: + # + # [ "name:string", "age:integer" ] + # + # Becomes: + # + # { "name" => "string", "age" => "integer" } + # + def parse_hash(name) + return shift if peek.is_a?(Hash) + hash = {} + + while current_is_value? && peek.include?(?:) + key, value = shift.split(':') + hash[key] = value + end + hash + end + + # Runs through the argument array getting all strings until no string is + # found or a switch is found. + # + # ["a", "b", "c"] + # + # And returns it as an array: + # + # ["a", "b", "c"] + # + def parse_array(name) + return shift if peek.is_a?(Array) + array = [] + + while current_is_value? + array << shift + end + array + end + + # Check if the peel is numeric ofrmat and return a Float or Integer. + # Otherwise raises an error. + # + def parse_numeric(name) + return shift if peek.is_a?(Numeric) + + unless peek =~ NUMERIC && $& == peek + raise MalformattedArgumentError, "expected numeric value for '#{name}'; got #{peek.inspect}" + end + + $&.index('.') ? shift.to_f : shift.to_i + end + + # Parse string, i.e., just return the current value in the pile. + # + def parse_string(name) + shift + end + + # Raises an error if @non_assigned_required array is not empty. + # + def check_requirement! + unless @non_assigned_required.empty? + names = @non_assigned_required.map do |o| + o.respond_to?(:switch_name) ? o.switch_name : o.human_name + end.join("', '") + + class_name = self.class.name.split('::').last.downcase + raise RequiredArgumentMissingError, "no value provided for required #{class_name} '#{names}'" + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/option.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/option.rb new file mode 100644 index 0000000000..9e40ec73fa --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/option.rb @@ -0,0 +1,132 @@ +class Thor + class Option < Argument #:nodoc: + attr_reader :aliases, :group + + VALID_TYPES = [:boolean, :numeric, :hash, :array, :string] + + def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, group=nil, aliases=nil) + super(name, description, required, type, default, banner) + @aliases = [*aliases].compact + @group = group.to_s.capitalize if group + end + + # This parse quick options given as method_options. It makes several + # assumptions, but you can be more specific using the option method. + # + # parse :foo => "bar" + # #=> Option foo with default value bar + # + # parse [:foo, :baz] => "bar" + # #=> Option foo with default value bar and alias :baz + # + # parse :foo => :required + # #=> Required option foo without default value + # + # parse :foo => 2 + # #=> Option foo with default value 2 and type numeric + # + # parse :foo => :numeric + # #=> Option foo without default value and type numeric + # + # parse :foo => true + # #=> Option foo with default value true and type boolean + # + # The valid types are :boolean, :numeric, :hash, :array and :string. If none + # is given a default type is assumed. This default type accepts arguments as + # string (--foo=value) or booleans (just --foo). + # + # By default all options are optional, unless :required is given. + # + def self.parse(key, value) + if key.is_a?(Array) + name, *aliases = key + else + name, aliases = key, [] + end + + name = name.to_s + default = value + + type = case value + when Symbol + default = nil + + if VALID_TYPES.include?(value) + value + elsif required = (value == :required) + :string + elsif value == :optional + # TODO Remove this warning in the future. + warn "Optional type is deprecated. Choose :boolean or :string instead. Assumed to be :boolean." + :boolean + end + when TrueClass, FalseClass + :boolean + when Numeric + :numeric + when Hash, Array, String + value.class.name.downcase.to_sym + end + + self.new(name.to_s, nil, required, type, default, nil, nil, aliases) + end + + def switch_name + @switch_name ||= dasherized? ? name : dasherize(name) + end + + def human_name + @human_name ||= dasherized? ? undasherize(name) : name + end + + def usage(padding=0) + sample = if banner && !banner.to_s.empty? + "#{switch_name}=#{banner}" + else + switch_name + end + + sample = "[#{sample}]" unless required? + + if aliases.empty? + (" " * padding) << sample + else + "#{aliases.join(', ')}, #{sample}" + end + end + + # Allow some type predicates as: boolean?, string? and etc. + # + def method_missing(method, *args, &block) + given = method.to_s.sub(/\?$/, '').to_sym + if valid_type?(given) + self.type == given + else + super + end + end + + protected + + def validate! + raise ArgumentError, "An option cannot be boolean and required." if boolean? && required? + end + + def valid_type?(type) + VALID_TYPES.include?(type.to_sym) + end + + def dasherized? + name.index('-') == 0 + end + + def undasherize(str) + str.sub(/^-{1,2}/, '') + end + + def dasherize(str) + (str.length > 1 ? "--" : "-") + str.gsub('_', '-') + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/options.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/options.rb new file mode 100644 index 0000000000..75092308b5 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/options.rb @@ -0,0 +1,142 @@ +class Thor + # This is a modified version of Daniel Berger's Getopt::Long class, licensed + # under Ruby's license. + # + class Options < Arguments #:nodoc: + LONG_RE = /^(--\w+[-\w+]*)$/ + SHORT_RE = /^(-[a-z])$/i + EQ_RE = /^(--\w+[-\w+]*|-[a-z])=(.*)$/i + SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args + SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i + + # Receives a hash and makes it switches. + # + def self.to_switches(options) + options.map do |key, value| + case value + when true + "--#{key}" + when Array + "--#{key} #{value.map{ |v| v.inspect }.join(' ')}" + when Hash + "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}" + when nil, false + "" + else + "--#{key} #{value.inspect}" + end + end.join(" ") + end + + # Takes a hash of Thor::Option objects. + # + def initialize(options={}) + options = options.values + super(options) + @shorts, @switches = {}, {} + + options.each do |option| + @switches[option.switch_name] = option + + option.aliases.each do |short| + @shorts[short.to_s] ||= option.switch_name + end + end + end + + def parse(args) + @pile = args.dup + + while peek + if current_is_switch? + case shift + when SHORT_SQ_RE + unshift($1.split('').map { |f| "-#{f}" }) + next + when EQ_RE, SHORT_NUM + unshift($2) + switch = $1 + when LONG_RE, SHORT_RE + switch = $1 + end + + switch = normalize_switch(switch) + next unless option = switch_option(switch) + + @assigns[option.human_name] = parse_peek(switch, option) + else + shift + end + end + + check_requirement! + @assigns + end + + protected + + # Returns true if the current value in peek is a registered switch. + # + def current_is_switch? + case peek + when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM + switch?($1) + when SHORT_SQ_RE + $1.split('').any? { |f| switch?("-#{f}") } + end + end + + def switch?(arg) + switch_option(arg) || @shorts.key?(arg) + end + + def switch_option(arg) + if match = no_or_skip?(arg) + @switches[arg] || @switches["--#{match}"] + else + @switches[arg] + end + end + + def no_or_skip?(arg) + arg =~ /^--(no|skip)-([-\w]+)$/ + $2 + end + + # Check if the given argument is actually a shortcut. + # + def normalize_switch(arg) + @shorts.key?(arg) ? @shorts[arg] : arg + end + + # Parse boolean values which can be given as --foo=true, --foo or --no-foo. + # + def parse_boolean(switch) + if current_is_value? + ["true", "TRUE", "t", "T", true].include?(shift) + else + @switches.key?(switch) || !no_or_skip?(switch) + end + end + + # Parse the value at the peek analyzing if it requires an input or not. + # + def parse_peek(switch, option) + unless current_is_value? + if option.boolean? + # No problem for boolean types + elsif no_or_skip?(switch) + return nil # User set value to nil + elsif option.string? && !option.required? + return option.human_name # Return the option name + else + raise MalformattedArgumentError, "no value provided for option '#{switch}'" + end + end + + @non_assigned_required.delete(option) + send(:"parse_#{option.type}", switch) + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/rake_compat.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/rake_compat.rb new file mode 100644 index 0000000000..0d0757fdda --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/rake_compat.rb @@ -0,0 +1,66 @@ +require 'rake' + +class Thor + # Adds a compatibility layer to your Thor classes which allows you to use + # rake package tasks. For example, to use rspec rake tasks, one can do: + # + # require 'thor/rake_compat' + # + # class Default < Thor + # include Thor::RakeCompat + # + # Spec::Rake::SpecTask.new(:spec) do |t| + # t.spec_opts = ['--options', "spec/spec.opts"] + # t.spec_files = FileList['spec/**/*_spec.rb'] + # end + # end + # + module RakeCompat + def self.rake_classes + @rake_classes ||= [] + end + + def self.included(base) + # Hack. Make rakefile point to invoker, so rdoc task is generated properly. + rakefile = File.basename(caller[0].match(/(.*):\d+/)[1]) + Rake.application.instance_variable_set(:@rakefile, rakefile) + self.rake_classes << base + end + end +end + +class Object #:nodoc: + alias :rake_task :task + alias :rake_namespace :namespace + + def task(*args, &block) + task = rake_task(*args, &block) + + if klass = Thor::RakeCompat.rake_classes.last + non_namespaced_name = task.name.split(':').last + + description = non_namespaced_name + description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ') + description.strip! + + klass.desc description, task.comment || non_namespaced_name + klass.send :define_method, non_namespaced_name do |*args| + Rake::Task[task.name.to_sym].invoke(*args) + end + end + + task + end + + def namespace(name, &block) + if klass = Thor::RakeCompat.rake_classes.last + const_name = Thor::Util.camel_case(name.to_s).to_sym + klass.const_set(const_name, Class.new(Thor)) + new_klass = klass.const_get(const_name) + Thor::RakeCompat.rake_classes << new_klass + end + + rake_namespace(name, &block) + Thor::RakeCompat.rake_classes.pop + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/runner.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/runner.rb new file mode 100644 index 0000000000..f197081e3f --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/runner.rb @@ -0,0 +1,303 @@ +require 'fileutils' +require 'open-uri' +require 'yaml' +require 'digest/md5' +require 'pathname' + +class Thor::Runner < Thor #:nodoc: + map "-T" => :list, "-i" => :install, "-u" => :update + + # Override Thor#help so it can give information about any class and any method. + # + def help(meth=nil) + if meth && !self.respond_to?(meth) + initialize_thorfiles(meth) + klass, task = Thor::Util.namespace_to_thor_class_and_task(meth) + # Send mapping -h because it works with Thor::Group too + klass.start(["-h", task].compact, :shell => self.shell) + else + super + end + end + + # If a task is not found on Thor::Runner, method missing is invoked and + # Thor::Runner is then responsable for finding the task in all classes. + # + def method_missing(meth, *args) + meth = meth.to_s + initialize_thorfiles(meth) + klass, task = Thor::Util.namespace_to_thor_class_and_task(meth) + args.unshift(task) if task + klass.start(args, :shell => shell) + end + + desc "install NAME", "Install an optionally named Thor file into your system tasks" + method_options :as => :string, :relative => :boolean + def install(name) + initialize_thorfiles + + # If a directory name is provided as the argument, look for a 'main.thor' + # task in said directory. + begin + if File.directory?(File.expand_path(name)) + base, package = File.join(name, "main.thor"), :directory + contents = open(base).read + else + base, package = name, :file + contents = open(name).read + end + rescue OpenURI::HTTPError + raise Error, "Error opening URI '#{name}'" + rescue Errno::ENOENT + raise Error, "Error opening file '#{name}'" + end + + say "Your Thorfile contains:" + say contents + + return false if no?("Do you wish to continue [y/N]?") + + as = options["as"] || begin + first_line = contents.split("\n")[0] + (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil + end + + unless as + basename = File.basename(name) + as = ask("Please specify a name for #{name} in the system repository [#{basename}]:") + as = basename if as.empty? + end + + location = if options[:relative] || name =~ /^http:\/\// + name + else + File.expand_path(name) + end + + thor_yaml[as] = { + :filename => Digest::MD5.hexdigest(name + as), + :location => location, + :namespaces => Thor::Util.namespaces_in_content(contents, base) + } + + save_yaml(thor_yaml) + say "Storing thor file in your system repository" + destination = File.join(thor_root, thor_yaml[as][:filename]) + + if package == :file + File.open(destination, "w") { |f| f.puts contents } + else + FileUtils.cp_r(name, destination) + end + + thor_yaml[as][:filename] # Indicate success + end + + desc "uninstall NAME", "Uninstall a named Thor module" + def uninstall(name) + raise Error, "Can't find module '#{name}'" unless thor_yaml[name] + say "Uninstalling #{name}." + FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}")) + + thor_yaml.delete(name) + save_yaml(thor_yaml) + + puts "Done." + end + + desc "update NAME", "Update a Thor file from its original location" + def update(name) + raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location] + + say "Updating '#{name}' from #{thor_yaml[name][:location]}" + + old_filename = thor_yaml[name][:filename] + self.options = self.options.merge("as" => name) + filename = install(thor_yaml[name][:location]) + + unless filename == old_filename + File.delete(File.join(thor_root, old_filename)) + end + end + + desc "installed", "List the installed Thor modules and tasks" + method_options :internal => :boolean + def installed + initialize_thorfiles(nil, true) + display_klasses(true, options["internal"]) + end + + desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)" + method_options :substring => :boolean, :group => :string, :all => :boolean + def list(search="") + initialize_thorfiles + + search = ".*#{search}" if options["substring"] + search = /^#{search}.*/i + group = options[:group] || "standard" + + klasses = Thor::Base.subclasses.select do |k| + (options[:all] || k.group == group) && k.namespace =~ search + end + + display_klasses(false, false, klasses) + end + + private + + def self.banner(task) + "thor " + task.formatted_usage(self, false) + end + + def thor_root + Thor::Util.thor_root + end + + def thor_yaml + @thor_yaml ||= begin + yaml_file = File.join(thor_root, "thor.yml") + yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file) + yaml || {} + end + end + + # Save the yaml file. If none exists in thor root, creates one. + # + def save_yaml(yaml) + yaml_file = File.join(thor_root, "thor.yml") + + unless File.exists?(yaml_file) + FileUtils.mkdir_p(thor_root) + yaml_file = File.join(thor_root, "thor.yml") + FileUtils.touch(yaml_file) + end + + File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml } + end + + def self.exit_on_failure? + true + end + + # Load the thorfiles. If relevant_to is supplied, looks for specific files + # in the thor_root instead of loading them all. + # + # By default, it also traverses the current path until find Thor files, as + # described in thorfiles. This look up can be skipped by suppliying + # skip_lookup true. + # + def initialize_thorfiles(relevant_to=nil, skip_lookup=false) + thorfiles(relevant_to, skip_lookup).each do |f| + Thor::Util.load_thorfile(f) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f)) + end + end + + # Finds Thorfiles by traversing from your current directory down to the root + # directory of your system. If at any time we find a Thor file, we stop. + # + # We also ensure that system-wide Thorfiles are loaded first, so local + # Thorfiles can override them. + # + # ==== Example + # + # If we start at /Users/wycats/dev/thor ... + # + # 1. /Users/wycats/dev/thor + # 2. /Users/wycats/dev + # 3. /Users/wycats <-- we find a Thorfile here, so we stop + # + # Suppose we start at c:\Documents and Settings\james\dev\thor ... + # + # 1. c:\Documents and Settings\james\dev\thor + # 2. c:\Documents and Settings\james\dev + # 3. c:\Documents and Settings\james + # 4. c:\Documents and Settings + # 5. c:\ <-- no Thorfiles found! + # + def thorfiles(relevant_to=nil, skip_lookup=false) + thorfiles = [] + + unless skip_lookup + Pathname.pwd.ascend do |path| + thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten + break unless thorfiles.empty? + end + end + + files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob) + files += thorfiles + files -= ["#{thor_root}/thor.yml"] + + files.map! do |file| + File.directory?(file) ? File.join(file, "main.thor") : file + end + end + + # Load thorfiles relevant to the given method. If you provide "foo:bar" it + # will load all thor files in the thor.yaml that has "foo" e "foo:bar" + # namespaces registered. + # + def thorfiles_relevant_to(meth) + lookup = [ meth, meth.split(":")[0...-1].join(":") ] + + files = thor_yaml.select do |k, v| + v[:namespaces] && !(v[:namespaces] & lookup).empty? + end + + files.map { |k, v| File.join(thor_root, "#{v[:filename]}") } + end + + # Display information about the given klasses. If with_module is given, + # it shows a table with information extracted from the yaml file. + # + def display_klasses(with_modules=false, show_internal=false, klasses=Thor::Base.subclasses) + klasses -= [Thor, Thor::Runner, Thor::Group] unless show_internal + + raise Error, "No Thor tasks available" if klasses.empty? + show_modules if with_modules && !thor_yaml.empty? + + # Remove subclasses + klasses.dup.each do |klass| + klasses -= Thor::Util.thor_classes_in(klass) + end + + list = Hash.new { |h,k| h[k] = [] } + groups = klasses.select { |k| k.ancestors.include?(Thor::Group) } + + # Get classes which inherit from Thor + (klasses - groups).each { |k| list[k.namespace] += k.printable_tasks(false) } + + # Get classes which inherit from Thor::Base + groups.map! { |k| k.printable_tasks(false).first } + list["root"] = groups + + # Order namespaces with default coming first + list = list.sort{ |a,b| a[0].sub(/^default/, '') <=> b[0].sub(/^default/, '') } + list.each { |n, tasks| display_tasks(n, tasks) unless tasks.empty? } + end + + def display_tasks(namespace, list) #:nodoc: + list.sort!{ |a,b| a[0] <=> b[0] } + + say shell.set_color(namespace, :blue, true) + say "-" * namespace.size + + print_table(list, :truncate => true) + say + end + + def show_modules #:nodoc: + info = [] + labels = ["Modules", "Namespaces"] + + info << labels + info << [ "-" * labels[0].size, "-" * labels[1].size ] + + thor_yaml.each do |name, hash| + info << [ name, hash[:namespaces].join(", ") ] + end + + print_table info + say "" + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell.rb new file mode 100644 index 0000000000..64a173de83 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell.rb @@ -0,0 +1,78 @@ +require 'rbconfig' +require 'thor/shell/color' + +class Thor + module Base + # Returns the shell used in all Thor classes. If you are in a Unix platform + # it will use a colored log, otherwise it will use a basic one without color. + # + def self.shell + @shell ||= if Config::CONFIG['host_os'] =~ /mswin|mingw/ + Thor::Shell::Basic + else + Thor::Shell::Color + end + end + + # Sets the shell used in all Thor classes. + # + def self.shell=(klass) + @shell = klass + end + end + + module Shell + SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_table] + + # Add shell to initialize config values. + # + # ==== Configuration + # shell:: An instance of the shell to be used. + # + # ==== Examples + # + # class MyScript < Thor + # argument :first, :type => :numeric + # end + # + # MyScript.new [1.0], { :foo => :bar }, :shell => Thor::Shell::Basic.new + # + def initialize(args=[], options={}, config={}) + super + self.shell = config[:shell] + self.shell.base ||= self if self.shell.respond_to?(:base) + end + + # Holds the shell for the given Thor instance. If no shell is given, + # it gets a default shell from Thor::Base.shell. + # + def shell + @shell ||= Thor::Base.shell.new + end + + # Sets the shell for this thor class. + # + def shell=(shell) + @shell = shell + end + + # Common methods that are delegated to the shell. + # + SHELL_DELEGATED_METHODS.each do |method| + module_eval <<-METHOD, __FILE__, __LINE__ + def #{method}(*args) + shell.#{method}(*args) + end + METHOD + end + + protected + + # Allow shell to be shared between invocations. + # + def _shared_configuration #:nodoc: + super.merge!(:shell => self.shell) + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/basic.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/basic.rb new file mode 100644 index 0000000000..a11f45b4e9 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/basic.rb @@ -0,0 +1,239 @@ +require 'tempfile' + +class Thor + module Shell + class Basic + attr_accessor :base, :padding + + # Initialize base and padding to nil. + # + def initialize #:nodoc: + @base, @padding = nil, 0 + end + + # Sets the output padding, not allowing less than zero values. + # + def padding=(value) + @padding = [0, value].max + end + + # Ask something to the user and receives a response. + # + # ==== Example + # ask("What is your name?") + # + def ask(statement, color=nil) + say("#{statement} ", color) + $stdin.gets.strip + end + + # Say (print) something to the user. If the sentence ends with a whitespace + # or tab character, a new line is not appended (print + flush). Otherwise + # are passed straight to puts (behavior got from Highline). + # + # ==== Example + # say("I know you knew that.") + # + def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/)) + message = message.to_s + message = set_color(message, color) if color + + if force_new_line + $stdout.puts(message) + else + $stdout.print(message) + $stdout.flush + end + end + + # Say a status with the given color and appends the message. Since this + # method is used frequently by actions, it allows nil or false to be given + # in log_status, avoiding the message from being shown. If a Symbol is + # given in log_status, it's used as the color. + # + def say_status(status, message, log_status=true) + return if quiet? || log_status == false + spaces = " " * (padding + 1) + color = log_status.is_a?(Symbol) ? log_status : :green + + status = status.to_s.rjust(12) + status = set_color status, color, true if color + say "#{status}#{spaces}#{message}", nil, true + end + + # Make a question the to user and returns true if the user replies "y" or + # "yes". + # + def yes?(statement, color=nil) + ask(statement, color) =~ is?(:yes) + end + + # Make a question the to user and returns true if the user replies "n" or + # "no". + # + def no?(statement, color=nil) + !yes?(statement, color) + end + + # Prints a table. + # + # ==== Parameters + # Array[Array[String, String, ...]] + # + # ==== Options + # ident:: Ident the first column by ident value. + # + def print_table(table, options={}) + return if table.empty? + + formats, ident = [], options[:ident].to_i + options[:truncate] = terminal_width if options[:truncate] == true + + 0.upto(table.first.length - 2) do |i| + maxima = table.max{ |a,b| a[i].size <=> b[i].size }[i].size + formats << "%-#{maxima + 2}s" + end + + formats[0] = formats[0].insert(0, " " * ident) + formats << "%s" + + table.each do |row| + sentence = "" + + row.each_with_index do |column, i| + sentence << formats[i] % column.to_s + end + + sentence = truncate(sentence, options[:truncate]) if options[:truncate] + $stdout.puts sentence + end + end + + # Deals with file collision and returns true if the file should be + # overwriten and false otherwise. If a block is given, it uses the block + # response as the content for the diff. + # + # ==== Parameters + # destination:: the destination file to solve conflicts + # block:: an optional block that returns the value to be used in diff + # + def file_collision(destination) + return true if @always_force + options = block_given? ? "[Ynaqdh]" : "[Ynaqh]" + + while true + answer = ask %[Overwrite #{destination}? (enter "h" for help) #{options}] + + case answer + when is?(:yes), is?(:force), "" + return true + when is?(:no), is?(:skip) + return false + when is?(:always) + return @always_force = true + when is?(:quit) + say 'Aborting...' + raise SystemExit + when is?(:diff) + show_diff(destination, yield) if block_given? + say 'Retrying...' + else + say file_collision_help + end + end + end + + # Called if something goes wrong during the execution. This is used by Thor + # internally and should not be used inside your scripts. If someone went + # wrong, you can always raise an exception. If you raise a Thor::Error, it + # will be rescued and wrapped in the method below. + # + def error(statement) + $stderr.puts statement + end + + # Apply color to the given string with optional bold. Disabled in the + # Thor::Shell::Basic class. + # + def set_color(string, color, bold=false) #:nodoc: + string + end + + protected + + def is?(value) #:nodoc: + value = value.to_s + + if value.size == 1 + /\A#{value}\z/i + else + /\A(#{value}|#{value[0,1]})\z/i + end + end + + def file_collision_help #:nodoc: +</dev/null}.split[1].to_i + end + + def dynamic_width_tput + %x{tput cols 2>/dev/null}.to_i + end + + def unix? + RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i + end + + def truncate(string, width) + if string.length <= width + string + else + ( string[0, width-3] || "" ) + "..." + end + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/color.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/color.rb new file mode 100644 index 0000000000..b2bc66dfba --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/color.rb @@ -0,0 +1,108 @@ +require 'thor/shell/basic' + +class Thor + module Shell + # Inherit from Thor::Shell::Basic and add set_color behavior. Check + # Thor::Shell::Basic to see all available methods. + # + class Color < Basic + # Embed in a String to clear all previous ANSI sequences. + CLEAR = "\e[0m" + # The start of an ANSI bold sequence. + BOLD = "\e[1m" + + # Set the terminal's foreground ANSI color to black. + BLACK = "\e[30m" + # Set the terminal's foreground ANSI color to red. + RED = "\e[31m" + # Set the terminal's foreground ANSI color to green. + GREEN = "\e[32m" + # Set the terminal's foreground ANSI color to yellow. + YELLOW = "\e[33m" + # Set the terminal's foreground ANSI color to blue. + BLUE = "\e[34m" + # Set the terminal's foreground ANSI color to magenta. + MAGENTA = "\e[35m" + # Set the terminal's foreground ANSI color to cyan. + CYAN = "\e[36m" + # Set the terminal's foreground ANSI color to white. + WHITE = "\e[37m" + + # Set the terminal's background ANSI color to black. + ON_BLACK = "\e[40m" + # Set the terminal's background ANSI color to red. + ON_RED = "\e[41m" + # Set the terminal's background ANSI color to green. + ON_GREEN = "\e[42m" + # Set the terminal's background ANSI color to yellow. + ON_YELLOW = "\e[43m" + # Set the terminal's background ANSI color to blue. + ON_BLUE = "\e[44m" + # Set the terminal's background ANSI color to magenta. + ON_MAGENTA = "\e[45m" + # Set the terminal's background ANSI color to cyan. + ON_CYAN = "\e[46m" + # Set the terminal's background ANSI color to white. + ON_WHITE = "\e[47m" + + # Set color by using a string or one of the defined constants. If a third + # option is set to true, it also adds bold to the string. This is based + # on Highline implementation and it automatically appends CLEAR to the end + # of the returned String. + # + def set_color(string, color, bold=false) + color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol) + bold = bold ? BOLD : "" + "#{bold}#{color}#{string}#{CLEAR}" + end + + protected + + # Overwrite show_diff to show diff with colors if Diff::LCS is + # available. + # + def show_diff(destination, content) #:nodoc: + if diff_lcs_loaded? && ENV['THOR_DIFF'].nil? && ENV['RAILS_DIFF'].nil? + actual = File.binread(destination).to_s.split("\n") + content = content.to_s.split("\n") + + Diff::LCS.sdiff(actual, content).each do |diff| + output_diff_line(diff) + end + else + super + end + end + + def output_diff_line(diff) #:nodoc: + case diff.action + when '-' + say "- #{diff.old_element.chomp}", :red, true + when '+' + say "+ #{diff.new_element.chomp}", :green, true + when '!' + say "- #{diff.old_element.chomp}", :red, true + say "+ #{diff.new_element.chomp}", :green, true + else + say " #{diff.old_element.chomp}", nil, true + end + end + + # Check if Diff::LCS is loaded. If it is, use it to create pretty output + # for diff. + # + def diff_lcs_loaded? #:nodoc: + return true if defined?(Diff::LCS) + return @diff_lcs_loaded unless @diff_lcs_loaded.nil? + + @diff_lcs_loaded = begin + require 'diff/lcs' + true + rescue LoadError + false + end + end + + end + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/task.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/task.rb new file mode 100644 index 0000000000..5c8877591b --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/task.rb @@ -0,0 +1,111 @@ +class Thor + class Task < Struct.new(:name, :description, :usage, :options) + FILE_REGEXP = /^#{Regexp.escape(File.expand_path(__FILE__))}:[\w:]+ `run'$/ + + # A dynamic task that handles method missing scenarios. + class Dynamic < Task + def initialize(name, options=nil) + super(name.to_s, "A dynamically-generated task", name.to_s, options) + end + + def run(instance, args=[]) + unless (instance.methods & [name.to_s, name.to_sym]).empty? + raise Error, "could not find Thor class or task '#{name}'" + end + super + end + end + + def initialize(name, description, usage, options=nil) + super(name.to_s, description, usage, options || {}) + end + + def initialize_copy(other) #:nodoc: + super(other) + self.options = other.options.dup if other.options + end + + # By default, a task invokes a method in the thor class. You can change this + # implementation to create custom tasks. + def run(instance, args=[]) + raise UndefinedTaskError, "the '#{name}' task of #{instance.class} is private" unless public_method?(instance) + instance.send(name, *args) + rescue ArgumentError => e + raise e if instance.class.respond_to?(:debugging) && instance.class.debugging + parse_argument_error(instance, e, caller) + rescue NoMethodError => e + raise e if instance.class.respond_to?(:debugging) && instance.class.debugging + parse_no_method_error(instance, e) + end + + # Returns the formatted usage by injecting given required arguments + # and required options into the given usage. + def formatted_usage(klass, namespace=nil) + namespace = klass.namespace if namespace.nil? + + # Add namespace + formatted = if namespace + "#{namespace.gsub(/^(default|thor:runner:)/,'')}:" + else + "" + end + + # Add usage with required arguments + formatted << if klass && !klass.arguments.empty? + usage.to_s.gsub(/^#{name}/) do |match| + match << " " << klass.arguments.map{ |a| a.usage }.compact.join(' ') + end + else + usage.to_s + end + + # Add required options + formatted << " #{required_options}" + + # Strip and go! + formatted.strip + end + + protected + + def required_options + @required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ") + end + + # Given a target, checks if this class name is not a private/protected method. + def public_method?(instance) #:nodoc: + collection = instance.private_methods + instance.protected_methods + (collection & [name.to_s, name.to_sym]).empty? + end + + # For Ruby <= 1.8.7, we have to match the method name that we are trying to call. + # In Ruby >= 1.9.1, we have to match the method run in this file. + def backtrace_match?(backtrace) #:nodoc: + method_name = /`#{Regexp.escape(name.split(':').last)}'/ + backtrace =~ method_name || backtrace =~ FILE_REGEXP + end + + def parse_argument_error(instance, e, caller) #:nodoc: + if e.message =~ /wrong number of arguments/ && backtrace_match?(e.backtrace.first.to_s) + if instance.is_a?(Thor::Group) + raise e, "'#{name}' was called incorrectly. Are you sure it has arity equals to 0?" + else + raise InvocationError, "'#{name}' was called incorrectly. Call as " << + "'#{formatted_usage(instance.class)}'" + end + else + raise e + end + end + + def parse_no_method_error(instance, e) #:nodoc: + if e.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/ + raise UndefinedTaskError, "The #{instance.class.namespace} namespace " << + "doesn't have a '#{name}' task" + else + raise e + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/util.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/util.rb new file mode 100644 index 0000000000..c2aed89ccf --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/util.rb @@ -0,0 +1,233 @@ +require 'rbconfig' + +class Thor + module Sandbox #:nodoc: + end + + # This module holds several utilities: + # + # 1) Methods to convert thor namespaces to constants and vice-versa. + # + # Thor::Utils.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz" + # + # 2) Loading thor files and sandboxing: + # + # Thor::Utils.load_thorfile("~/.thor/foo") + # + module Util + + # Receives a namespace and search for it in the Thor::Base subclasses. + # + # ==== Parameters + # namespace:: The namespace to search for. + # + def self.find_by_namespace(namespace) + namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/ + + Thor::Base.subclasses.find do |klass| + klass.namespace == namespace + end + end + + # Receives a constant and converts it to a Thor namespace. Since Thor tasks + # can be added to a sandbox, this method is also responsable for removing + # the sandbox namespace. + # + # This method should not be used in general because it's used to deal with + # older versions of Thor. On current versions, if you need to get the + # namespace from a class, just call namespace on it. + # + # ==== Parameters + # constant:: The constant to be converted to the thor path. + # + # ==== Returns + # String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz" + # + def self.namespace_from_thor_class(constant, remove_default=true) + constant = constant.to_s.gsub(/^Thor::Sandbox::/, "") + constant = snake_case(constant).squeeze(":") + constant.gsub!(/^default/, '') if remove_default + constant + end + + # Given the contents, evaluate it inside the sandbox and returns the + # namespaces defined in the sandbox. + # + # ==== Parameters + # contents + # + # ==== Returns + # Array[Object] + # + def self.namespaces_in_content(contents, file=__FILE__) + old_constants = Thor::Base.subclasses.dup + Thor::Base.subclasses.clear + + load_thorfile(file, contents) + + new_constants = Thor::Base.subclasses.dup + Thor::Base.subclasses.replace(old_constants) + + new_constants.map!{ |c| c.namespace } + new_constants.compact! + new_constants + end + + # Returns the thor classes declared inside the given class. + # + def self.thor_classes_in(klass) + stringfied_constants = klass.constants.map { |c| c.to_s } + Thor::Base.subclasses.select do |subclass| + next unless subclass.name + stringfied_constants.include?(subclass.name.gsub("#{klass.name}::", '')) + end + end + + # Receives a string and convert it to snake case. SnakeCase returns snake_case. + # + # ==== Parameters + # String + # + # ==== Returns + # String + # + def self.snake_case(str) + return str.downcase if str =~ /^[A-Z_]+$/ + str.gsub(/\B[A-Z]/, '_\&').squeeze('_') =~ /_*(.*)/ + return $+.downcase + end + + # Receives a string and convert it to camel case. camel_case returns CamelCase. + # + # ==== Parameters + # String + # + # ==== Returns + # String + # + def self.camel_case(str) + return str if str !~ /_/ && str =~ /[A-Z]+.*/ + str.split('_').map { |i| i.capitalize }.join + end + + # Receives a namespace and tries to retrieve a Thor or Thor::Group class + # from it. It first searches for a class using the all the given namespace, + # if it's not found, removes the highest entry and searches for the class + # again. If found, returns the highest entry as the class name. + # + # ==== Examples + # + # class Foo::Bar < Thor + # def baz + # end + # end + # + # class Baz::Foo < Thor::Group + # end + # + # Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default task + # Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil + # Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz" + # + # ==== Parameters + # namespace + # + # ==== Errors + # Thor::Error:: raised if the namespace cannot be found. + # + # Thor::Error:: raised if the namespace evals to a class which does not + # inherit from Thor or Thor::Group. + # + def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true) + if namespace.include?(?:) + pieces = namespace.split(":") + task = pieces.pop + klass = Thor::Util.find_by_namespace(pieces.join(":")) + end + + unless klass + klass, task = Thor::Util.find_by_namespace(namespace), nil + end + + raise Error, "could not find Thor class or task '#{namespace}'" if raise_if_nil && klass.nil? + return klass, task + end + + # Receives a path and load the thor file in the path. The file is evaluated + # inside the sandbox to avoid namespacing conflicts. + # + def self.load_thorfile(path, content=nil) + content ||= File.binread(path) + + begin + Thor::Sandbox.class_eval(content, path) + rescue Exception => e + $stderr.puts "WARNING: unable to load thorfile #{path.inspect}: #{e.message}" + end + end + + def self.user_home + @@user_home ||= if ENV["HOME"] + ENV["HOME"] + elsif ENV["USERPROFILE"] + ENV["USERPROFILE"] + elsif ENV["HOMEDRIVE"] && ENV["HOMEPATH"] + File.join(ENV["HOMEDRIVE"], ENV["HOMEPATH"]) + elsif ENV["APPDATA"] + ENV["APPDATA"] + else + begin + File.expand_path("~") + rescue + if File::ALT_SEPARATOR + "C:/" + else + "/" + end + end + end + end + + # Returns the root where thor files are located, dependending on the OS. + # + def self.thor_root + File.join(user_home, ".thor").gsub(/\\/, '/') + end + + # Returns the files in the thor root. On Windows thor_root will be something + # like this: + # + # C:\Documents and Settings\james\.thor + # + # If we don't #gsub the \ character, Dir.glob will fail. + # + def self.thor_root_glob + files = Dir["#{thor_root}/*"] + + files.map! do |file| + File.directory?(file) ? File.join(file, "main.thor") : file + end + end + + # Where to look for Thor files. + # + def self.globs_for(path) + ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] + end + + # Return the path to the ruby interpreter taking into account multiple + # installations and windows extensions. + # + def self.ruby_command + @ruby_command ||= begin + ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) + ruby << Config::CONFIG['EXEEXT'] + + # escape string in case path to ruby executable contain spaces. + ruby.sub!(/.*\s.*/m, '"\&"') + ruby + end + end + + end +end diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/version.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/version.rb new file mode 100644 index 0000000000..3c9dd6f808 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/version.rb @@ -0,0 +1,3 @@ +class Thor + VERSION = "0.12.3".freeze +end -- cgit v1.2.3 From 4c5b5024c36cfc6dabfdfed656d04d3c4e032e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Jan 2010 22:25:51 +0100 Subject: Rails notifications are set through Railtie in each framework. --- railties/lib/rails/application.rb | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 457eef648c..26ffbe5a58 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -269,18 +269,5 @@ module Rails ActiveSupport::Dependencies.unhook! end end - - # For each framework, search for instrument file with Notifications hooks. - # - initializer :load_notifications_hooks do - frameworks = [ :active_record, :action_controller, :action_view, - :action_mailer, :active_resource ] - frameworks.each do |framework| - begin - require "#{framework}/notifications" - rescue LoadError => e - end - end - end end end -- cgit v1.2.3 From c3d19eb950578ff4a20692bd1b20ee074789818e Mon Sep 17 00:00:00 2001 From: Steve Agalloco Date: Wed, 30 Dec 2009 01:05:30 -0500 Subject: app_generator option should be skip_activerecord not no_activerecord MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (Thor actually accepts both, the patch was applied to improve readability) Signed-off-by: José Valim --- railties/lib/rails/generators/rails/app/app_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index ee401b1fde..0073c6ba26 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -46,7 +46,7 @@ module Rails::Generators def initialize(*args) super - if !options[:no_activerecord] && !DATABASES.include?(options[:database]) + if !options[:skip_activerecord] && !DATABASES.include?(options[:database]) raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}." end end -- cgit v1.2.3 From f1cd3a98f3c2ff3446c637ad706faf7dbfef268e Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 2 Jan 2010 22:45:56 -0800 Subject: Doc fix --- railties/lib/rails/generators/rails/app/templates/config/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index ec0729db04..4097f766a6 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -7,7 +7,7 @@ module <%= app_name.classify %> # -- all .rb files in that directory are automatically loaded. # Add additional load paths for your own custom dirs - # config.load_paths += %W( #{root}/extras ) + # config.load_paths += %W( #{config.root}/extras ) # Only load the plugins named here, in the order given (default is alphabetical). # :all can be used as a placeholder for all plugins not explicitly named -- cgit v1.2.3 From 106d8f76888e76096f83e884f55dbcd536a0c1d7 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 2 Jan 2010 22:49:40 -0800 Subject: AppName::Application.root should work --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 26ffbe5a58..5401251397 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -8,7 +8,7 @@ module Rails class << self attr_writer :config alias configure class_eval - delegate :initialize!, :load_tasks, :to => :instance + delegate :initialize!, :load_tasks, :root, :to => :instance private :new def instance -- cgit v1.2.3 From 6716e4bc0c201d9375fa07b44c1a96b6948fc6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 3 Jan 2010 12:01:29 +0100 Subject: Use regexp in lookups instead of traversing namespaces. This removes the need of special cases. --- railties/lib/rails/generators.rb | 148 +++++++++++++--------------------- railties/lib/rails/generators/base.rb | 60 +++++++------- 2 files changed, 88 insertions(+), 120 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 6419961415..3713a38b33 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -117,11 +117,15 @@ module Rails end # Remove the color from output. - # def self.no_color! Thor::Base.shell = Thor::Shell::Basic end + # Track all generators subclasses. + def self.subclasses + @subclasses ||= [] + end + # Generators load paths used on lookup. The lookup happens as: # # 1) lib generators @@ -147,18 +151,10 @@ module Rails end load_paths # Cache load paths. Needed to avoid __FILE__ pointing to wrong paths. - # Rails finds namespaces exactly as thor, with three conveniences: - # - # 1) If your generator name ends with generator, as WebratGenerator, it sets - # its namespace to "webrat", so it can be invoked as "webrat" and not - # "webrat_generator"; + # Rails finds namespaces similar to thor, it only adds one rule: # - # 2) If your generator has a generators namespace, as Rails::Generators::WebratGenerator, - # the namespace is set to "rails:generators:webrat", but Rails allows it - # to be invoked simply as "rails:webrat". The "generators" is added - # automatically when doing the lookup; - # - # 3) Rails looks in load paths and loads the generator just before it's going to be used. + # Generators names must end with "_generator.rb". This is required because Rails + # looks in load paths and loads the generator just before it's going to be used. # # ==== Examples # @@ -166,113 +162,81 @@ module Rails # # Will search for the following generators: # - # "rails:generators:webrat", "webrat:generators:integration", "webrat" - # - # On the other hand, if "rails:webrat" is given, it will search for: + # "rails:webrat", "webrat:integration", "webrat" # - # "rails:generators:webrat", "rails:webrat" - # - # Notice that the "generators" namespace is handled automatically by Rails, - # so you don't need to type it when you want to invoke a generator in specific. + # Notice that "rails:generators:webrat" could be loaded as well, what + # Rails looks for is the first and last parts of the namespace. # def self.find_by_namespace(name, base=nil, context=nil) #:nodoc: - name, attempts = name.to_s, [ ] - - case name.count(':') - when 1 - base, name = name.split(':') - return find_by_namespace(name, base) - when 0 - attempts += generator_names(base, name) if base - attempts += generator_names(name, context) if context - end - - attempts << name - attempts += generator_names(name, name) unless name.include?(?:) - attempts.uniq! - - unloaded = attempts - namespaces - lookup(unloaded) + # Mount regexps to lookup + regexps = [] + regexps << /^#{base}:[\w:]*#{name}$/ if base + regexps << /^#{name}:[\w:]*#{context}$/ if context + regexps << /^[(#{name}):]+$/ + regexps.uniq! + + # Check if generator happens to be loaded + checked = subclasses.dup + klass = find_by_regexps(regexps, checked) + return klass if klass + + # Try to require other generators by looking in load_paths + lookup(name, context) + unchecked = subclasses - checked + klass = find_by_regexps(regexps, unchecked) + return klass if klass + + # Invoke fallbacks + invoke_fallbacks_for(name, base) || invoke_fallbacks_for(context, name) + end - attempts.each do |namespace| - klass = Thor::Util.find_by_namespace(namespace) - return klass if klass + # Tries to find a generator which the namespace match the regexp. + def self.find_by_regexps(regexps, klasses) + klasses.find do |klass| + namespace = klass.namespace + regexps.find { |r| namespace =~ r } end - - invoke_fallbacks_for(name, base) || invoke_fallbacks_for(context, name) end # Receives a namespace, arguments and the behavior to invoke the generator. # It's used as the default entry point for generate, destroy and update # commands. - # def self.invoke(namespace, args=ARGV, config={}) - if klass = find_by_namespace(namespace, "rails") + names = namespace.to_s.split(':') + + if klass = find_by_namespace(names.pop, names.shift || "rails") args << "--help" if klass.arguments.any? { |a| a.required? } && args.empty? - klass.start args, config + klass.start(args, config) else puts "Could not find generator #{namespace}." end end # Show help message with available generators. - # def self.help - rails = Rails::Generators.builtin.map do |group, name| - name if group == "rails" - end - rails.compact! - rails.sort! - - puts "Please select a generator." - puts "Builtin: #{rails.join(', ')}." - - # Load paths and remove builtin - paths, others = load_paths.dup, [] - paths.pop - - paths.each do |path| - tail = [ "*", "*", "*_generator.rb" ] - - until tail.empty? - others += Dir[File.join(path, *tail)].collect do |file| - name = file.split('/')[-tail.size, 2] - name.last.sub!(/_generator\.rb$/, '') - name.uniq! - name.join(':') - end - tail.shift - end - end + builtin = Rails::Generators.builtin.each { |n| n.sub!(/^rails:/, '') } + builtin.sort! + lookup("*") + others = subclasses.map{ |k| k.namespace.gsub(':generators:', ':') } + others -= Rails::Generators.builtin others.sort! + + puts "Please select a generator." + puts "Builtin: #{builtin.join(', ')}." puts "Others: #{others.join(', ')}." unless others.empty? end protected - # Return all defined namespaces. - # - def self.namespaces #:nodoc: - Thor::Base.subclasses.map { |klass| klass.namespace } - end - - # Keep builtin generators in an Array[Array[group, name]]. - # + # Keep builtin generators in an Array. def self.builtin #:nodoc: Dir[File.dirname(__FILE__) + '/generators/*/*'].collect do |file| - file.split('/')[-2, 2] + file.split('/')[-2, 2].join(':') end end - # By default, Rails strips the generator namespace to make invocations - # easier. This method generaters the both possibilities names. - def self.generator_names(first, second) #:nodoc: - [ "#{first}:generators:#{second}", "#{first}:#{second}" ] - end - - # Try callbacks for the given base. - # + # Try fallbacks for the given base. def self.invoke_fallbacks_for(name, base) #:nodoc: return nil unless base && fallbacks[base.to_sym] invoked_fallbacks = [] @@ -290,10 +254,10 @@ module Rails # Receives namespaces in an array and tries to find matching generators # in the load path. - # - def self.lookup(attempts) #:nodoc: - attempts = attempts.map { |a| "#{a.split(":").last}_generator" }.uniq - attempts = "{#{attempts.join(',')}}.rb" + def self.lookup(*attempts) #:nodoc: + attempts.compact! + attempts.uniq! + attempts = "{#{attempts.join(',')}}_generator.rb" self.load_paths.each do |path| Dir[File.join(path, '**', attempts)].each do |file| diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 226ae63963..a10d1c9fce 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -76,17 +76,18 @@ module Rails # # The controller generator will then try to invoke the following generators: # - # "rails:generators:test_unit", "test_unit:generators:controller", "test_unit" + # "rails:test_unit", "test_unit:controller", "test_unit" # - # In this case, the "test_unit:generators:controller" is available and is - # invoked. This allows any test framework to hook into Rails as long as it - # provides any of the hooks above. + # Notice that "rails:generators:test_unit" could be loaded as well, what + # Rails looks for is the first and last parts of the namespace. This is what + # allows any test framework to hook into Rails as long as it provides any + # of the hooks above. # # ==== Options # - # This lookup can be customized with two options: :base and :as. The first - # is the root module value and in the example above defaults to "rails". - # The later defaults to the generator name, without the "Generator" ending. + # The first and last part used to find the generator to be invoked are + # guessed based on class invokes hook_for, as noticed in the example above. + # This can be customized with two options: :base and :as. # # Let's suppose you are creating a generator that needs to invoke the # controller generator from test unit. Your first attempt is: @@ -97,7 +98,7 @@ module Rails # # The lookup in this case for test_unit as input is: # - # "test_unit:generators:awesome", "test_unit" + # "test_unit:awesome", "test_unit" # # Which is not the desired the lookup. You can change it by providing the # :as option: @@ -108,18 +109,18 @@ module Rails # # And now it will lookup at: # - # "test_unit:generators:awesome", "test_unit" + # "test_unit:controller", "test_unit" # # Similarly, if you want it to also lookup in the rails namespace, you just # need to provide the :base value: # # class AwesomeGenerator < Rails::Generators::Base - # hook_for :test_framework, :base => :rails, :as => :controller + # hook_for :test_framework, :in => :rails, :as => :controller # end # # And the lookup is exactly the same as previously: # - # "rails:generators:test_unit", "test_unit:generators:controller", "test_unit" + # "rails:test_unit", "test_unit:controller", "test_unit" # # ==== Switches # @@ -151,11 +152,11 @@ module Rails # ==== Custom invocations # # You can also supply a block to hook_for to customize how the hook is - # going to be invoked. The block receives two parameters, an instance + # going to be invoked. The block receives two arguments, an instance # of the current class and the klass to be invoked. # # For example, in the resource generator, the controller should be invoked - # with a pluralized class name. By default, it is invoked with the same + # with a pluralized class name. But by default it is invoked with the same # name as the resource generator, which is singular. To change this, we # can give a block to customize how the controller can be invoked. # @@ -178,11 +179,11 @@ module Rails end unless class_options.key?(name) - class_option name, defaults.merge!(options) + class_option(name, defaults.merge!(options)) end hooks[name] = [ in_base, as_hook ] - invoke_from_option name, options, &block + invoke_from_option(name, options, &block) end end @@ -193,7 +194,7 @@ module Rails # remove_hook_for :orm # def self.remove_hook_for(*names) - remove_invocation *names + remove_invocation(*names) names.each do |name| hooks.delete(name) @@ -219,12 +220,16 @@ module Rails # and can point to wrong directions when inside an specified directory. base.source_root - if base.name && base.name !~ /Base$/ && base.base_name && base.generator_name && defined?(Rails.root) && Rails.root - path = File.expand_path(File.join(Rails.root, 'lib', 'templates')) - if base.name.include?('::') - base.source_paths << File.join(path, base.base_name, base.generator_name) - else - base.source_paths << File.join(path, base.generator_name) + if base.name && base.name !~ /Base$/ + Rails::Generators.subclasses << base + + if defined?(Rails.root) && Rails.root + path = File.expand_path(File.join(Rails.root, 'lib', 'templates')) + if base.name.include?('::') + base.source_paths << File.join(path, base.base_name, base.generator_name) + else + base.source_paths << File.join(path, base.generator_name) + end end end end @@ -290,12 +295,10 @@ module Rails # Rails::Generators::MetalGenerator will return "metal" as generator name. # def self.generator_name - if name - @generator_name ||= begin - if klass_name = name.to_s.split('::').last - klass_name.sub!(/Generator$/, '') - klass_name.underscore - end + @generator_name ||= begin + if generator = name.to_s.split('::').last + generator.sub!(/Generator$/, '') + generator.underscore end end end @@ -339,6 +342,7 @@ module Rails # def self.prepare_for_invocation(name, value) #:nodoc: if value && constants = self.hooks[name] + value = name if TrueClass === value Rails::Generators.find_by_namespace(value, *constants) else super -- cgit v1.2.3 From e88ea3255ff90baa28d30908e1fcb5fa7f7133a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 3 Jan 2010 13:01:18 +0100 Subject: Assert for valid application names. [#3556 status:resolved] --- railties/lib/rails/generators/rails/app/app_generator.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 0073c6ba26..fc6a3cdee8 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -53,8 +53,9 @@ module Rails::Generators def create_root self.destination_root = File.expand_path(app_path, destination_root) - empty_directory '.' + valid_app_const? + empty_directory '.' set_default_accessors! FileUtils.cd(destination_root) end @@ -193,7 +194,14 @@ module Rails::Generators end def app_const - @app_const ||= "#{app_name.classify}::Application" + @app_const ||= "#{app_name.gsub(/\W/, '_').squeeze('_').classify}::Application" + end + + def valid_app_const? + case app_const + when /^\d/ + raise Error, "Invalid application name #{app_name}. Please give a name which does not start with numbers." + end end def app_secret -- cgit v1.2.3 From 441227a10f42fcd28b65ab416495ff8f4fc45b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 3 Jan 2010 15:13:54 +0100 Subject: Create Rails::Generators::TestCase. --- railties/lib/rails/generators/base.rb | 2 +- railties/lib/rails/generators/test_case.rb | 224 +++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 railties/lib/rails/generators/test_case.rb (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index a10d1c9fce..5e8c2730fd 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -272,7 +272,7 @@ module Rails # parameters. # def invoked?(args) - args.last.is_a?(Hash) && args.last.key?(:invocations) + args.last.is_a?(Hash) && (args.last.key?(:invocations) || args.last.key?(:destination_root)) end # Use Rails default banner. diff --git a/railties/lib/rails/generators/test_case.rb b/railties/lib/rails/generators/test_case.rb new file mode 100644 index 0000000000..8918a4eb42 --- /dev/null +++ b/railties/lib/rails/generators/test_case.rb @@ -0,0 +1,224 @@ +require 'active_support/test_case' +require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/hash/reverse_merge' +require 'rails/generators' +require 'fileutils' + +module Rails + module Generators + # Disable color in output. Easier to debug. + no_color! + + # This class provides a TestCase for testing generators. To setup, you need + # just to configure the destination and set which generator is being tested: + # + # class AppGeneratorTest < Rails::Generators::TestCase + # tests AppGenerator + # destination File.expand_path("../tmp", File.dirname(__FILE__)) + # end + # + # If you want to ensure your destination root is clean before running each test, + # you can set a setup callback: + # + # class AppGeneratorTest < Rails::Generators::TestCase + # tests AppGenerator + # destination File.expand_path("../tmp", File.dirname(__FILE__)) + # setup :prepare_destination + # end + # + class TestCase < ActiveSupport::TestCase + include FileUtils + + extlib_inheritable_accessor :destination_root, :current_path, :instance_writer => false + extlib_inheritable_accessor :generator_class + + # Generators frequently change the current path using +FileUtils.cd+. + # So we need to store the path at file load and revert back to it after each test. + self.current_path = File.expand_path(Dir.pwd) + + setup :destination_root_is_set?, :ensure_current_path + teardown :ensure_current_path + + # Sets which generator should be tested: + # + # tests AppGenerator + # + def self.tests(klass) + self.generator_class = klass + end + + # Sets the destination of generator files: + # + # destination File.expand_path("../tmp", File.dirname(__FILE__)) + # + def self.destination(path) + self.destination_root = path + end + + # Captures the given stream and returns it: + # + # stream = capture(:stdout){ puts "Cool" } + # stream #=> "Cool\n" + # + def capture(stream) + begin + stream = stream.to_s + eval "$#{stream} = StringIO.new" + yield + result = eval("$#{stream}").string + ensure + eval("$#{stream} = #{stream.upcase}") + end + + result + end + alias :silence :capture + + # Asserts a given file exists. You need to supply an absolute path or a path relative + # to the configured destination: + # + # assert_file "config/environment.rb" + # + # You can also give extra arguments. If the argument is a regexp, it will check if the + # regular expression matches the given file content. If it's a string, it compares the + # file with the given string: + # + # assert_file "config/environment.rb", /initialize/ + # + # Finally, when a block is given, it yields the file content: + # + # assert_file "app/controller/products_controller.rb" do |controller| + # assert_instance_method :index, content do |index| + # assert_match /Product\.all/, index + # end + # end + # + def assert_file(relative, *contents) + absolute = File.expand_path(relative, destination_root) + assert File.exists?(absolute), "Expected file #{relative.inspect} to exist, but does not" + + read = File.read(absolute) if block_given? || !contents.empty? + yield read if block_given? + + contents.each do |content| + case content + when String + assert_equal content, read + when Regexp + assert_match content, read + end + end + end + alias :assert_directory :assert_file + + # Asserts a given file does not exist. You need to supply an absolute path or a + # path relative to the configured destination: + # + # assert_no_file "config/random.rb" + # + def assert_no_file(relative) + absolute = File.expand_path(relative, destination_root) + assert !File.exists?(absolute), "Expected file #{relative.inspect} to not exist, but does" + end + alias :assert_no_directory :assert_no_file + + # Asserts a given file does not exist. You need to supply an absolute path or a + # path relative to the configured destination: + # + # assert_migration "db/migrate/create_products.rb" + # + # This method manipulates the given path and tries to find any migration which + # matches the migration name. For example, the call above is converted to: + # + # assert_file "db/migrate/003_create_products.rb" + # + # Consequently, assert_migration accepts the same arguments has assert_file. + # + def assert_migration(relative, *contents, &block) + file_name = migration_file_name(relative) + assert file_name, "Expected migration #{relative} to exist, but was not found" + assert_file file_name, *contents, &block + end + + # Asserts a given migration does not exist. You need to supply an absolute path or a + # path relative to the configured destination: + # + # assert_no_file "config/random.rb" + # + def assert_no_migration(relative) + file_name = migration_file_name(relative) + assert_nil file_name, "Expected migration #{relative} to not exist, but found #{file_name}" + end + + # Asserts the given class method exists in the given content. This method does not detect + # class methods inside (class << self), only class methods which starts with "self.". + # When a block is given, it yields the content of the method. + # + # assert_migration "db/migrate/create_products.rb" do |migration| + # assert_class_method :up, migration do |up| + # assert_match /create_table/, up + # end + # end + # + def assert_class_method(method, content, &block) + assert_instance_method "self.#{method}", content, &block + end + + # Asserts the given method exists in the given content. When a block is given, + # it yields the content of the method. + # + # assert_file "app/controller/products_controller.rb" do |controller| + # assert_instance_method :index, content do |index| + # assert_match /Product\.all/, index + # end + # end + # + def assert_instance_method(method, content) + assert content =~ /def #{method}(\(.+\))?(.*?)\n end/m, "Expected to have method #{method}" + yield $2.strip if block_given? + end + alias :assert_method :assert_instance_method + + # Runs the generator configured for this class. The first argument is an array like + # command line arguments: + # + # class AppGeneratorTest < Rails::Generators::TestCase + # tests AppGenerator + # destination File.expand_path("../tmp", File.dirname(__FILE__)) + # teardown :cleanup_destination_root + # + # test "database.yml is not created when skipping activerecord" do + # run_generator %w(myapp --skip-activerecord) + # assert_no_file "config/database.yml" + # end + # end + # + # You can provide a configuration hash as second argument. This method returns the output + # printed by the generator. + def run_generator(args=[], config={}) + capture(:stdout) { self.generator_class.start args, config.reverse_merge(:destination_root => destination_root) } + end + + protected + + def destination_root_is_set? #:nodoc: + raise "You need to configure your Rails::Generators::TestCase destination root." unless destination_root + end + + def ensure_current_path #:nodoc: + cd current_path + end + + def prepare_destination + rm_rf(destination_root) + mkdir_p(destination_root) + end + + def migration_file_name(relative) #:nodoc: + absolute = File.expand_path(relative, destination_root) + dirname, file_name = File.dirname(absolute), File.basename(absolute).sub(/\.rb$/, '') + Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first + end + end + end +end \ No newline at end of file -- cgit v1.2.3 From 271e7c803f116b77f0df48115036421242eb9b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 3 Jan 2010 16:34:32 +0100 Subject: Move all generators tests to use new test case syntax. --- railties/lib/rails/generators/test_case.rb | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/test_case.rb b/railties/lib/rails/generators/test_case.rb index 8918a4eb42..643d7856c5 100644 --- a/railties/lib/rails/generators/test_case.rb +++ b/railties/lib/rails/generators/test_case.rb @@ -29,12 +29,13 @@ module Rails class TestCase < ActiveSupport::TestCase include FileUtils - extlib_inheritable_accessor :destination_root, :current_path, :instance_writer => false - extlib_inheritable_accessor :generator_class + extlib_inheritable_accessor :destination_root, :current_path, :generator_class, + :default_arguments, :instance_writer => false # Generators frequently change the current path using +FileUtils.cd+. # So we need to store the path at file load and revert back to it after each test. self.current_path = File.expand_path(Dir.pwd) + self.default_arguments = [] setup :destination_root_is_set?, :ensure_current_path teardown :ensure_current_path @@ -47,6 +48,15 @@ module Rails self.generator_class = klass end + # Sets default arguments on generator invocation. This can be overwritten when + # invoking it. + # + # arguments %w(app_name --skip-activerecord) + # + def self.arguments(array) + self.default_arguments = array + end + # Sets the destination of generator files: # # destination File.expand_path("../tmp", File.dirname(__FILE__)) @@ -195,8 +205,13 @@ module Rails # # You can provide a configuration hash as second argument. This method returns the output # printed by the generator. - def run_generator(args=[], config={}) - capture(:stdout) { self.generator_class.start args, config.reverse_merge(:destination_root => destination_root) } + def run_generator(args=self.default_arguments, config={}) + capture(:stdout) { self.generator_class.start(args, config.reverse_merge(:destination_root => destination_root)) } + end + + # Instantiate the generator. + def generator(args=self.default_arguments, options={}, config={}) + @generator ||= self.generator_class.new(args, options, config.reverse_merge(:destination_root => destination_root)) end protected -- cgit v1.2.3