Permalink
Browse files

Update vendored thor.

  • Loading branch information...
josevalim committed Aug 30, 2009
1 parent d8e7ff1 commit 72c6ea1022e9819eda667f209660a5cf143b72d3
Showing with 138 additions and 73 deletions.
  1. +1 −1 railties/lib/generators.rb
  2. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/CHANGELOG.rdoc
  3. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/LICENSE
  4. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/README.rdoc
  5. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/bin/rake2thor
  6. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/bin/thor
  7. +1 −1 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor.rb
  8. +16 −15 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/actions.rb
  9. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/actions/create_file.rb
  10. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/actions/directory.rb
  11. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/actions/empty_directory.rb
  12. +41 −17 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/actions/file_manipulation.rb
  13. +43 −20 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/actions/inject_into_file.rb
  14. +7 −0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/base.rb
  15. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/core_ext/hash_with_indifferent_access.rb
  16. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/core_ext/ordered_hash.rb
  17. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/error.rb
  18. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/group.rb
  19. +1 −1 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/invocation.rb
  20. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/parser.rb
  21. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/parser/argument.rb
  22. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/parser/arguments.rb
  23. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/parser/option.rb
  24. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/parser/options.rb
  25. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/rake_compat.rb
  26. +4 −0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/runner.rb
  27. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/shell.rb
  28. +2 −3 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/shell/basic.rb
  29. 0 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/shell/color.rb
  30. +13 −7 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/task.rb
  31. +9 −8 railties/lib/vendor/{thor-0.11.5 → thor-0.11.6}/lib/thor/util.rb
@@ -11,7 +11,7 @@
$:.unshift(File.dirname(__FILE__))
-require 'vendor/thor-0.11.5/lib/thor'
+require 'vendor/thor-0.11.6/lib/thor'
require 'generators/base'
require 'generators/named_base'
@@ -135,7 +135,7 @@ def start(given_args=ARGV, config={})
args, opts = given_args, {}
end
- task ||= Task.dynamic(meth)
+ task ||= Thor::Task::Dynamic.new(meth)
trailing = args[Range.new(arguments.size, -1)]
new(args, opts, config).invoke(task, trailing || [])
end
@@ -8,23 +8,8 @@ class Thor
module Actions
attr_accessor :behavior
- # On inclusion, add some options to base.
- #
def self.included(base) #:nodoc:
base.extend ClassMethods
- return unless base.respond_to?(:class_option)
-
- base.class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime,
- :desc => "Run but do not make any changes"
-
- base.class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime,
- :desc => "Overwrite files that already exist"
-
- base.class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime,
- :desc => "Skip files that already exist"
-
- base.class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime,
- :desc => "Supress status output"
end
module ClassMethods
@@ -49,6 +34,22 @@ def source_paths_for_search
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.
@@ -100,7 +100,7 @@ def chmod(path, mode, config={})
FileUtils.chmod_R(mode, path) unless options[:pretend]
end
- # Prepend text to a file.
+ # Prepend text to a file. Since it depends on inject_into_file, it's reversible.
#
# ==== Parameters
# path<String>:: path of the file to be changed
@@ -111,19 +111,17 @@ def chmod(path, mode, config={})
#
# prepend_file 'config/environments/test.rb', 'config.gem "rspec"'
#
- def prepend_file(path, data=nil, config={}, &block)
- return unless behavior == :invoke
- path = File.expand_path(path, destination_root)
- say_status :prepend, relative_to_original_destination_root(path), config.fetch(:verbose, true)
-
- unless options[:pretend]
- content = data || block.call
- content << File.read(path)
- File.open(path, 'wb') { |file| file.write(content) }
- end
+ # 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.
+ # Append text to a file. Since it depends on inject_into_file, it's reversible.
#
# ==== Parameters
# path<String>:: path of the file to be changed
@@ -134,11 +132,37 @@ def prepend_file(path, data=nil, config={}, &block)
#
# append_file 'config/environments/test.rb', 'config.gem "rspec"'
#
- def append_file(path, data=nil, config={}, &block)
- return unless behavior == :invoke
- path = File.expand_path(path, destination_root)
- say_status :append, relative_to_original_destination_root(path), config.fetch(:verbose, true)
- File.open(path, 'ab') { |file| file.write(data || block.call) } unless options[:pretend]
+ # 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<String>:: path of the file to be changed
+ # klass<String|Class>:: the class to be manipulated
+ # data<String>:: the data to append to the class, can be also given as a block.
+ # config<Hash>:: 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.
@@ -3,10 +3,8 @@
class Thor
module Actions
- # Injects the given content into a file. Different from append_file,
- # prepend_file and gsub_file, this method is reversible. By this reason,
- # the flag can only be strings. gsub_file is your friend if you need to
- # deal with more complex cases.
+ # Injects the given content into a file. Different from gsub_file, this
+ # method is reversible.
#
# ==== Parameters
# destination<String>:: Relative path to the destination root
@@ -16,11 +14,11 @@ module Actions
#
# ==== Examples
#
- # inject_into_file "config/environment.rb", "config.gem thor", :after => "Rails::Initializer.run do |config|\n"
+ # 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")
+ # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n")
# end
#
def inject_into_file(destination, *args, &block)
@@ -29,40 +27,65 @@ def inject_into_file(destination, *args, &block)
else
data, config = args.shift, args.shift
end
-
- log_status = args.empty? || args.pop
action InjectIntoFile.new(self, destination, data, config)
end
class InjectIntoFile < EmptyDirectory #:nodoc:
- attr_reader :flag, :replacement
+ attr_reader :replacement, :flag, :behavior
def initialize(base, destination, data, config)
super(base, destination, { :verbose => true }.merge(config))
- data = data.call if data.is_a?(Proc)
-
- @replacement = if @config.key?(:after)
- @flag = @config.delete(:after)
- @flag + data
+ @behavior, @flag = if @config.key?(:after)
+ [:after, @config.delete(:after)]
else
- @flag = @config.delete(:before)
- data + @flag
+ [: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 :inject, config[:verbose]
- replace!(flag, replacement)
+ say_status :invoke
+
+ content = if @behavior == :after
+ '\0' + replacement
+ else
+ replacement + '\0'
+ end
+
+ replace!(/#{flag}/, content)
end
def revoke!
- say_status :deinject, config[:verbose]
- replace!(replacement, flag)
+ 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)
@@ -355,6 +355,7 @@ def start(given_args=ARGV, config={})
else
config[:shell].error e.message
end
+ exit(1) if exit_on_failure?
end
protected
@@ -491,6 +492,12 @@ def from_superclass(method, default=nil)
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:
@@ -153,7 +153,7 @@ def _validate_task(object, task) #:nodoc:
raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
task ||= klass.default_task if klass <= Thor
- task = klass.all_tasks[task.to_s] || Task.dynamic(task) if task && !task.is_a?(Thor::Task)
+ task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task)
task
end
@@ -175,6 +175,10 @@ def save_yaml(yaml)
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.
#
@@ -34,12 +34,11 @@ def ask(statement, color=nil)
# ==== Example
# say("I know you knew that.")
#
- def say(message="", color=nil, force_new_line=false)
+ def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/))
message = message.to_s
- new_line = force_new_line || !(message[-1, 1] == " " || message[-1, 1] == "\t")
message = set_color(message, color) if color
- if new_line
+ if force_new_line
$stdout.puts(message)
else
$stdout.print(message)
@@ -1,11 +1,19 @@
class Thor
class Task < Struct.new(:name, :description, :usage, :options)
- # Creates a dynamic task. Dynamic tasks are created on demand to allow method
- # missing calls (since a method missing does not have a task object for it).
+ # A dynamic task that handles method missing scenarios.
#
- def self.dynamic(name)
- new(name, "A dynamically-generated task", name.to_s)
+ class Dynamic < Task
+ def initialize(name)
+ super(name.to_s, "A dynamically-generated task", name.to_s)
+ 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)
@@ -37,8 +45,6 @@ def run(instance, args=[])
# injected in the usage.
#
def formatted_usage(klass=nil, namespace=false, show_options=true)
- formatted = ''
-
formatted = if namespace.is_a?(String)
"#{namespace}:"
elsif klass && namespace
@@ -77,7 +83,7 @@ def formatted_options
#
def public_method?(instance) #:nodoc:
collection = instance.private_methods + instance.protected_methods
- !(collection).include?(name.to_s) && !(collection).include?(name.to_sym) # For Ruby 1.9
+ (collection & [name.to_s, name.to_sym]).empty?
end
# Clean everything that comes from the Thor gempath and remove the caller.
@@ -22,7 +22,7 @@ module Util
# namespace<String>:: The namespace to search for.
#
def self.find_by_namespace(namespace)
- namespace = 'default' if namespace.empty?
+ namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/
Thor::Base.subclasses.find do |klass|
klass.namespace == namespace
@@ -137,17 +137,18 @@ def self.camel_case(str)
# inherit from Thor or Thor::Group.
#
def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true)
- klass, task_name = Thor::Util.find_by_namespace(namespace), nil
+ if namespace.include?(?:)
+ pieces = namespace.split(":")
+ task = pieces.pop
+ klass = Thor::Util.find_by_namespace(pieces.join(":"))
+ end
- if klass.nil? && namespace.include?(?:)
- namespace = namespace.split(":")
- task_name = namespace.pop
- klass = Thor::Util.find_by_namespace(namespace.join(":"))
+ 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_name
+ return klass, task
end
# Receives a path and load the thor file in the path. The file is evaluated

0 comments on commit 72c6ea1

Please sign in to comment.