summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Arko <andre@arko.net>2010-02-17 18:33:36 -0800
committerAndre Arko <andre@arko.net>2010-02-17 21:33:56 -0800
commit749214d04ea3d5bd262e2f43141108f4bdac3367 (patch)
tree91a2981b3fb0e39aea603e615c7e4e2859c90c7f
parent44b5c801350d7c29e7ee52ec9a438e49b9c07814 (diff)
downloadbundler-749214d04ea3d5bd262e2f43141108f4bdac3367.tar.gz
Update vendored Thor to 0.13.3
-rw-r--r--lib/bundler/vendor/thor.rb16
-rw-r--r--lib/bundler/vendor/thor/base.rb50
-rw-r--r--lib/bundler/vendor/thor/error.rb3
-rw-r--r--lib/bundler/vendor/thor/invocation.rb31
-rw-r--r--lib/bundler/vendor/thor/parser/arguments.rb9
-rw-r--r--lib/bundler/vendor/thor/parser/option.rb4
-rw-r--r--lib/bundler/vendor/thor/parser/options.rb33
-rw-r--r--lib/bundler/vendor/thor/task.rb49
-rw-r--r--lib/bundler/vendor/thor/util.rb25
-rw-r--r--lib/bundler/vendor/thor/version.rb2
10 files changed, 117 insertions, 105 deletions
diff --git a/lib/bundler/vendor/thor.rb b/lib/bundler/vendor/thor.rb
index 6bc533adf0..df6ea7bf35 100644
--- a/lib/bundler/vendor/thor.rb
+++ b/lib/bundler/vendor/thor.rb
@@ -120,8 +120,8 @@ class Thor
# script = MyScript.new(args, options, config)
# script.invoke(:task, first_arg, second_arg, third_arg)
#
- def start(given_args=ARGV, config={})
- super do
+ def start(original_args=ARGV, config={})
+ super do |given_args|
meth = normalize_task_name(given_args.shift)
task = all_tasks[meth]
@@ -145,8 +145,9 @@ class Thor
# task_name<String>
#
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
+ meth = normalize_task_name(task_name)
+ task = all_tasks[meth]
+ handle_no_task_error(meth) unless task
shell.say "Usage:"
shell.say " #{banner(task)}"
@@ -183,6 +184,10 @@ class Thor
end
end
+ def handle_argument_error(task, error) #:nodoc:
+ raise InvocationError, "#{task.name.inspect} was called incorrectly. Call as #{task.formatted_usage(self, banner_base == "thor").inspect}."
+ end
+
protected
# The banner for this class. You can customize it if you are invoking the
@@ -191,8 +196,7 @@ class Thor
# the namespace should be displayed as arguments.
#
def banner(task)
- base = $thor_runner ? "thor" : File.basename($0.split(" ").first)
- "#{base} #{task.formatted_usage(self, base == "thor")}"
+ "#{banner_base} #{task.formatted_usage(self, banner_base == "thor")}"
end
def baseclass #:nodoc:
diff --git a/lib/bundler/vendor/thor/base.rb b/lib/bundler/vendor/thor/base.rb
index 6e6c840427..8d0312c9ce 100644
--- a/lib/bundler/vendor/thor/base.rb
+++ b/lib/bundler/vendor/thor/base.rb
@@ -38,9 +38,8 @@ class Thor
# config<Hash>:: 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
+ args = Thor::Arguments.parse(self.class.arguments, args)
+ args.each { |key, value| send("#{key}=", value) }
parse_options = self.class.class_options
@@ -52,9 +51,9 @@ class Thor
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
+ opts = Thor::Options.new(parse_options, hash_options)
+ self.options = opts.parse(array_options)
+ opts.check_unknown! if self.class.check_unknown_options?
end
class << self
@@ -109,6 +108,16 @@ class Thor
no_tasks { super }
end
+ # If you want to raise an error for unknown options, call check_unknown_options!
+ # This is disabled by default to allow dynamic invocations.
+ def check_unknown_options!
+ @check_unknown_options = true
+ end
+
+ def check_unknown_options? #:nodoc:
+ @check_unknown_options || false
+ end
+
# Adds an argument to the class and creates an attr_accessor for it.
#
# Arguments are different from options in several aspects. The first one
@@ -355,7 +364,7 @@ class Thor
def namespace(name=nil)
case name
when nil
- @namespace ||= Thor::Util.namespace_from_thor_class(self, false)
+ @namespace ||= Thor::Util.namespace_from_thor_class(self)
else
@namespace = name.to_s
end
@@ -366,14 +375,18 @@ class Thor
def start(given_args=ARGV, config={})
self.debugging = given_args.include?("--debug")
config[:shell] ||= Thor::Base.shell.new
- yield
+ yield(given_args.dup)
rescue Thor::Error => e
- if debugging
- raise e
+ debugging ? (raise e) : config[:shell].error(e.message)
+ exit(1) if exit_on_failure?
+ end
+
+ def handle_no_task_error(task) #:nodoc:
+ if self.banner_base == "thor"
+ raise UndefinedTaskError, "Could not find task #{task.inspect} in #{namespace.inspect} namespace."
else
- config[:shell].error e.message
+ raise UndefinedTaskError, "Could not find task #{task.inspect}."
end
- exit(1) if exit_on_failure?
end
protected
@@ -419,7 +432,6 @@ class Thor
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}"
@@ -430,7 +442,6 @@ class Thor
# ==== Parameters
# name<Symbol>:: The name of the argument.
# options<Hash>:: 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],
@@ -444,7 +455,6 @@ class Thor
#
# ==== Parameters
# Hash[Symbol => Object]
- #
def build_options(options, scope) #:nodoc:
options.each do |key, value|
scope[key] = Thor::Option.parse(key, value)
@@ -454,7 +464,6 @@ class Thor
# 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
@@ -467,14 +476,12 @@ class Thor
# 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
@@ -495,7 +502,6 @@ class Thor
# 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
@@ -506,11 +512,15 @@ class Thor
end
# A flag that makes the process exit with status 1 if any error happens.
- #
def exit_on_failure?
false
end
+ # Returns the base for banner.
+ def banner_base
+ @banner_base ||= $thor_runner ? "thor" : File.basename($0.split(" ").first)
+ end
+
# SIGNATURE: Sets the baseclass. This is where the superclass lookup
# finishes.
def baseclass #:nodoc:
diff --git a/lib/bundler/vendor/thor/error.rb b/lib/bundler/vendor/thor/error.rb
index f9b31a35d1..9746b88245 100644
--- a/lib/bundler/vendor/thor/error.rb
+++ b/lib/bundler/vendor/thor/error.rb
@@ -19,6 +19,9 @@ class Thor
class InvocationError < Error
end
+ class UnknownArgumentError < Error
+ end
+
class RequiredArgumentMissingError < InvocationError
end
diff --git a/lib/bundler/vendor/thor/invocation.rb b/lib/bundler/vendor/thor/invocation.rb
index 32e6a72454..3f74e3458e 100644
--- a/lib/bundler/vendor/thor/invocation.rb
+++ b/lib/bundler/vendor/thor/invocation.rb
@@ -5,21 +5,20 @@ class Thor
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.
- #
+ # This method is responsible for receiving a name and find the proper
+ # class and task for it. The key is an optional parameter which is
+ # available only in class methods invocations (i.e. in Thor::Group).
def prepare_for_invocation(key, name) #:nodoc:
case name
when Symbol, String
- Thor::Util.namespace_to_thor_class_and_task(name.to_s, false)
+ Thor::Util.find_class_and_task_by_namespace(name.to_s)
else
name
end
end
end
- # Make initializer aware of invocations and the initializer proc.
- #
+ # Make initializer aware of invocations and the initialization args.
def initialize(args=[], options={}, config={}, &block) #:nodoc:
@_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] }
@_initializer = [ args, options, config ]
@@ -34,6 +33,8 @@ class Thor
# the task to be invoked, if none is given, the same values used to
# initialize the invoker are used to initialize the invoked.
#
+ # When no name is given, it will invoke the default task of the current class.
+ #
# ==== Examples
#
# class A < Thor
@@ -92,9 +93,9 @@ class Thor
#
# 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)
+ def invoke(name=nil, *args)
+ args.unshift(nil) if Array === args.first || NilClass === args.first
+ task, args, opts, config = args
object, task = _prepare_for_invocation(name, task)
klass, instance = _initialize_klass_with_initializer(object, args, opts, config)
@@ -121,15 +122,13 @@ class Thor
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.
- #
+ # This method can receive several different types of arguments and it's then
+ # responsible to normalize them by returning the object where the task should
+ # be invoked and a Thor::Task object.
def _prepare_for_invocation(name, sent_task=nil) #:nodoc:
if name.is_a?(Thor::Task)
task = name
@@ -147,18 +146,16 @@ class Thor
# 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.default_task if klass.respond_to?(:default_task)
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
diff --git a/lib/bundler/vendor/thor/parser/arguments.rb b/lib/bundler/vendor/thor/parser/arguments.rb
index fb5d965e06..1fb1f03b31 100644
--- a/lib/bundler/vendor/thor/parser/arguments.rb
+++ b/lib/bundler/vendor/thor/parser/arguments.rb
@@ -16,8 +16,9 @@ class Thor
return arguments, args[Range.new(arguments.size, -1)]
end
- def self.parse(base, args)
- new(base).parse(args)
+ def self.parse(*args)
+ to_parse = args.pop
+ new(*args).parse(to_parse)
end
# Takes an array of Thor::Argument objects.
@@ -116,7 +117,7 @@ class Thor
return shift if peek.is_a?(Numeric)
unless peek =~ NUMERIC && $& == peek
- raise MalformattedArgumentError, "expected numeric value for '#{name}'; got #{peek.inspect}"
+ raise MalformattedArgumentError, "Expected numeric value for '#{name}'; got #{peek.inspect}"
end
$&.index('.') ? shift.to_f : shift.to_i
@@ -137,7 +138,7 @@ class Thor
end.join("', '")
class_name = self.class.name.split('::').last.downcase
- raise RequiredArgumentMissingError, "no value provided for required #{class_name} '#{names}'"
+ raise RequiredArgumentMissingError, "No value provided for required #{class_name} '#{names}'"
end
end
diff --git a/lib/bundler/vendor/thor/parser/option.rb b/lib/bundler/vendor/thor/parser/option.rb
index 9e40ec73fa..fee89067b8 100644
--- a/lib/bundler/vendor/thor/parser/option.rb
+++ b/lib/bundler/vendor/thor/parser/option.rb
@@ -55,10 +55,6 @@ class Thor
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
diff --git a/lib/bundler/vendor/thor/parser/options.rb b/lib/bundler/vendor/thor/parser/options.rb
index 75092308b5..d557ce5bda 100644
--- a/lib/bundler/vendor/thor/parser/options.rb
+++ b/lib/bundler/vendor/thor/parser/options.rb
@@ -10,7 +10,6 @@ class Thor
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
@@ -28,12 +27,18 @@ class Thor
end.join(" ")
end
- # Takes a hash of Thor::Option objects.
- #
- def initialize(options={})
- options = options.values
+ # Takes a hash of Thor::Option and a hash with defaults.
+ def initialize(hash_options={}, defaults={})
+ options = hash_options.values
super(options)
- @shorts, @switches = {}, {}
+
+ # Add defaults
+ defaults.each do |key, value|
+ @assigns[key.to_s] = value
+ @non_assigned_required.delete(hash_options[key])
+ end
+
+ @shorts, @switches, @unknown = {}, {}, []
options.each do |option|
@switches[option.switch_name] = option
@@ -61,16 +66,24 @@ class Thor
end
switch = normalize_switch(switch)
- next unless option = switch_option(switch)
-
+ option = switch_option(switch)
@assigns[option.human_name] = parse_peek(switch, option)
+ elsif peek =~ /^\-/
+ @unknown << shift
else
shift
end
end
check_requirement!
- @assigns
+
+ assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns)
+ assigns.freeze
+ assigns
+ end
+
+ def check_unknown!
+ raise UnknownArgumentError, "Unknown switches '#{@unknown.join(', ')}'" unless @unknown.empty?
end
protected
@@ -130,7 +143,7 @@ class Thor
elsif option.string? && !option.required?
return option.human_name # Return the option name
else
- raise MalformattedArgumentError, "no value provided for option '#{switch}'"
+ raise MalformattedArgumentError, "No value provided for option '#{switch}'"
end
end
diff --git a/lib/bundler/vendor/thor/task.rb b/lib/bundler/vendor/thor/task.rb
index f0522d807a..856ef16a22 100644
--- a/lib/bundler/vendor/thor/task.rb
+++ b/lib/bundler/vendor/thor/task.rb
@@ -9,10 +9,11 @@ class Thor
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}'"
+ if (instance.methods & [name.to_s, name.to_sym]).empty?
+ super
+ else
+ instance.class.handle_no_task_error(name)
end
- super
end
end
@@ -28,14 +29,14 @@ class Thor
# 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)
+ public_method?(instance) ?
+ instance.send(name, *args) : instance.class.handle_no_task_error(name)
rescue ArgumentError => e
- raise e if instance.class.respond_to?(:debugging) && instance.class.debugging
- parse_argument_error(instance, e, caller)
+ handle_argument_error?(instance, e, caller) ?
+ instance.class.handle_argument_error(self, e) : (raise e)
rescue NoMethodError => e
- raise e if instance.class.respond_to?(:debugging) && instance.class.debugging
- parse_no_method_error(instance, e)
+ handle_no_method_error?(instance, e, caller) ?
+ instance.class.handle_no_task_error(name) : (raise e)
end
# Returns the formatted usage by injecting given required arguments
@@ -68,6 +69,10 @@ class Thor
protected
+ def not_debugging?(instance)
+ !(instance.class.respond_to?(:debugging) && instance.class.debugging)
+ end
+
def required_options
@required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ")
end
@@ -83,28 +88,14 @@ class Thor
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)}'"
- end
- else
- raise e
- end
+ def handle_argument_error?(instance, error, caller)
+ not_debugging?(instance) && error.message =~ /wrong number of arguments/ &&
+ sans_backtrace(error.backtrace, caller).empty?
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
+ def handle_no_method_error?(instance, error, caller)
+ not_debugging?(instance) &&
+ error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
end
end
diff --git a/lib/bundler/vendor/thor/util.rb b/lib/bundler/vendor/thor/util.rb
index c2aed89ccf..d2c6a150c8 100644
--- a/lib/bundler/vendor/thor/util.rb
+++ b/lib/bundler/vendor/thor/util.rb
@@ -23,10 +23,7 @@ class Thor
#
def self.find_by_namespace(namespace)
namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/
-
- Thor::Base.subclasses.find do |klass|
- klass.namespace == namespace
- end
+ Thor::Base.subclasses.find { |klass| klass.namespace == namespace }
end
# Receives a constant and converts it to a Thor namespace. Since Thor tasks
@@ -43,10 +40,9 @@ class Thor
# ==== Returns
# String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz"
#
- def self.namespace_from_thor_class(constant, remove_default=true)
+ def self.namespace_from_thor_class(constant)
constant = constant.to_s.gsub(/^Thor::Sandbox::/, "")
constant = snake_case(constant).squeeze(":")
- constant.gsub!(/^default/, '') if remove_default
constant
end
@@ -132,13 +128,7 @@ class Thor
# ==== Parameters
# namespace<String>
#
- # ==== 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)
+ def self.find_class_and_task_by_namespace(namespace)
if namespace.include?(?:)
pieces = namespace.split(":")
task = pieces.pop
@@ -149,7 +139,14 @@ class Thor
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
+
+ # The same as namespace_to_thor_class_and_task!, but raises an error if a klass
+ # could not be found.
+ def self.find_class_and_task_by_namespace!(namespace)
+ klass, task = find_class_and_task_by_namespace(namespace)
+ raise Error, "Could not find namespace or task #{namespace.inspect}." unless klass
return klass, task
end
diff --git a/lib/bundler/vendor/thor/version.rb b/lib/bundler/vendor/thor/version.rb
index 8ffab9d42c..b95dbbce4b 100644
--- a/lib/bundler/vendor/thor/version.rb
+++ b/lib/bundler/vendor/thor/version.rb
@@ -1,3 +1,3 @@
class Thor
- VERSION = "0.12.4".freeze
+ VERSION = "0.13.3".freeze
end