bundler 1.3.6 → 1.4.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -3
  3. data/CHANGELOG.md +27 -14
  4. data/CONTRIBUTING.md +2 -2
  5. data/{CONTRIBUTE.md → DEVELOPMENT.md} +31 -12
  6. data/ISSUES.md +1 -1
  7. data/README.md +6 -4
  8. data/Rakefile +1 -15
  9. data/bin/bundle +5 -8
  10. data/bundler.gemspec +1 -1
  11. data/lib/bundler.rb +37 -21
  12. data/lib/bundler/cli.rb +33 -21
  13. data/lib/bundler/constants.rb +5 -0
  14. data/lib/bundler/current_ruby.rb +88 -0
  15. data/lib/bundler/definition.rb +35 -11
  16. data/lib/bundler/dependency.rb +7 -78
  17. data/lib/bundler/dsl.rb +1 -1
  18. data/lib/bundler/fetcher.rb +37 -24
  19. data/lib/bundler/gem_helper.rb +2 -2
  20. data/lib/bundler/gem_installer.rb +9 -0
  21. data/lib/bundler/installer.rb +76 -7
  22. data/lib/bundler/parallel_workers.rb +18 -0
  23. data/lib/bundler/parallel_workers/thread_worker.rb +27 -0
  24. data/lib/bundler/parallel_workers/unix_worker.rb +88 -0
  25. data/lib/bundler/parallel_workers/worker.rb +68 -0
  26. data/lib/bundler/resolver.rb +17 -11
  27. data/lib/bundler/rubygems_ext.rb +2 -2
  28. data/lib/bundler/rubygems_integration.rb +37 -25
  29. data/lib/bundler/runtime.rb +8 -1
  30. data/lib/bundler/safe_catch.rb +101 -0
  31. data/lib/bundler/shared_helpers.rb +27 -1
  32. data/lib/bundler/source/git.rb +2 -1
  33. data/lib/bundler/source/git/git_proxy.rb +3 -3
  34. data/lib/bundler/source/path.rb +3 -2
  35. data/lib/bundler/source/rubygems.rb +5 -17
  36. data/lib/bundler/spec_set.rb +16 -1
  37. data/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
  38. data/lib/bundler/vendor/net/http/persistent.rb +136 -38
  39. data/lib/bundler/vendor/thor.rb +211 -188
  40. data/lib/bundler/vendor/thor/actions.rb +19 -19
  41. data/lib/bundler/vendor/thor/actions/create_link.rb +3 -0
  42. data/lib/bundler/vendor/thor/actions/directory.rb +30 -10
  43. data/lib/bundler/vendor/thor/actions/empty_directory.rb +3 -19
  44. data/lib/bundler/vendor/thor/actions/file_manipulation.rb +6 -3
  45. data/lib/bundler/vendor/thor/base.rb +101 -97
  46. data/lib/bundler/vendor/thor/{task.rb → command.rb} +17 -13
  47. data/lib/bundler/vendor/thor/core_ext/io_binary_read.rb +12 -0
  48. data/lib/bundler/vendor/thor/error.rb +8 -11
  49. data/lib/bundler/vendor/thor/group.rb +35 -38
  50. data/lib/bundler/vendor/thor/invocation.rb +28 -26
  51. data/lib/bundler/vendor/thor/parser/options.rb +21 -19
  52. data/lib/bundler/vendor/thor/rake_compat.rb +3 -2
  53. data/lib/bundler/vendor/thor/runner.rb +22 -21
  54. data/lib/bundler/vendor/thor/shell/basic.rb +44 -22
  55. data/lib/bundler/vendor/thor/shell/color.rb +13 -9
  56. data/lib/bundler/vendor/thor/shell/html.rb +13 -9
  57. data/lib/bundler/vendor/thor/util.rb +214 -210
  58. data/lib/bundler/vendor/thor/version.rb +1 -1
  59. data/lib/bundler/version.rb +1 -1
  60. data/man/bundle-install.ronn +5 -1
  61. data/man/gemfile.5.ronn +10 -2
  62. data/spec/bundler/dsl_spec.rb +3 -3
  63. data/spec/bundler/gem_helper_spec.rb +14 -17
  64. data/spec/bundler/safe_catch_spec.rb +37 -0
  65. data/spec/install/gems/dependency_api_spec.rb +1 -36
  66. data/spec/install/gems/packed_spec.rb +4 -2
  67. data/spec/install/gems/resolving_spec.rb +37 -0
  68. data/spec/install/gems/simple_case_spec.rb +18 -16
  69. data/spec/install/git_spec.rb +1 -1
  70. data/spec/other/binstubs_spec.rb +24 -13
  71. data/spec/other/exec_spec.rb +24 -2
  72. data/spec/other/help_spec.rb +6 -6
  73. data/spec/other/outdated_spec.rb +3 -3
  74. data/spec/quality_spec.rb +3 -2
  75. data/spec/realworld/dependency_api_spec.rb +1 -1
  76. data/spec/realworld/edgecases_spec.rb +3 -3
  77. data/spec/realworld/parallel_install_spec.rb +19 -0
  78. data/spec/resolver/basic_spec.rb +11 -0
  79. data/spec/runtime/require_spec.rb +9 -0
  80. data/spec/runtime/setup_spec.rb +2 -3
  81. data/spec/spec_helper.rb +0 -1
  82. data/spec/support/builders.rb +2 -4
  83. data/spec/support/helpers.rb +4 -8
  84. data/spec/support/indexes.rb +18 -0
  85. data/spec/support/streams.rb +13 -0
  86. metadata +19 -11
  87. data/lib/bundler/vendor/thor/core_ext/dir_escape.rb +0 -0
  88. data/lib/bundler/vendor/thor/core_ext/file_binary_read.rb +0 -9
  89. data/spec/support/artifice/endpoint_host_redirect.rb +0 -15
  90. data/spec/support/permissions.rb +0 -11
@@ -1,5 +1,5 @@
1
1
  class Thor
2
- class Task < Struct.new(:name, :description, :long_description, :usage, :options)
2
+ class Command < Struct.new(:name, :description, :long_description, :usage, :options)
3
3
  FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
4
4
 
5
5
  def initialize(name, description, long_description, usage, options=nil)
@@ -15,27 +15,27 @@ class Thor
15
15
  false
16
16
  end
17
17
 
18
- # By default, a task invokes a method in the thor class. You can change this
19
- # implementation to create custom tasks.
18
+ # By default, a command invokes a method in the thor class. You can change this
19
+ # implementation to create custom commands.
20
20
  def run(instance, args=[])
21
21
  arity = nil
22
22
 
23
23
  if private_method?(instance)
24
- instance.class.handle_no_task_error(name)
24
+ instance.class.handle_no_command_error(name)
25
25
  elsif public_method?(instance)
26
26
  arity = instance.method(name).arity
27
27
  instance.__send__(name, *args)
28
28
  elsif local_method?(instance, :method_missing)
29
29
  instance.__send__(:method_missing, name.to_sym, *args)
30
30
  else
31
- instance.class.handle_no_task_error(name)
31
+ instance.class.handle_no_command_error(name)
32
32
  end
33
33
  rescue ArgumentError => e
34
34
  handle_argument_error?(instance, e, caller) ?
35
- instance.class.handle_argument_error(self, e, arity) : (raise e)
35
+ instance.class.handle_argument_error(self, e, args, arity) : (raise e)
36
36
  rescue NoMethodError => e
37
37
  handle_no_method_error?(instance, e, caller) ?
38
- instance.class.handle_no_task_error(name) : (raise e)
38
+ instance.class.handle_no_command_error(name) : (raise e)
39
39
  end
40
40
 
41
41
  # Returns the formatted usage by injecting given required arguments
@@ -107,26 +107,30 @@ class Thor
107
107
  error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
108
108
  end
109
109
  end
110
+ Task = Command
110
111
 
111
- # A task that is hidden in help messages but still invocable.
112
- class HiddenTask < Task
112
+ # A command that is hidden in help messages but still invocable.
113
+ class HiddenCommand < Command
113
114
  def hidden?
114
115
  true
115
116
  end
116
117
  end
118
+ HiddenTask = HiddenCommand
117
119
 
118
- # A dynamic task that handles method missing scenarios.
119
- class DynamicTask < Task
120
+ # A dynamic command that handles method missing scenarios.
121
+ class DynamicCommand < Command
120
122
  def initialize(name, options=nil)
121
- super(name.to_s, "A dynamically-generated task", name.to_s, name.to_s, options)
123
+ super(name.to_s, "A dynamically-generated command", name.to_s, name.to_s, options)
122
124
  end
123
125
 
124
126
  def run(instance, args=[])
125
127
  if (instance.methods & [name.to_s, name.to_sym]).empty?
126
128
  super
127
129
  else
128
- instance.class.handle_no_task_error(name)
130
+ instance.class.handle_no_command_error(name)
129
131
  end
130
132
  end
131
133
  end
134
+ DynamicTask = DynamicCommand
135
+
132
136
  end
@@ -0,0 +1,12 @@
1
+ class IO #:nodoc:
2
+ class << self
3
+
4
+ def binread(file, *args)
5
+ raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3
6
+ File.open(file, 'rb') do |f|
7
+ f.read(*args)
8
+ end
9
+ end unless method_defined? :binread
10
+
11
+ end
12
+ end
@@ -5,17 +5,19 @@ class Thor
5
5
  # Errors that are caused by the developer, like declaring a method which
6
6
  # overwrites a thor keyword, it SHOULD NOT raise a Thor::Error. This way, we
7
7
  # ensure that developer errors are shown with full backtrace.
8
- #
9
8
  class Error < StandardError
10
9
  end
11
10
 
12
- # Raised when a task was not found.
13
- #
14
- class UndefinedTaskError < Error
11
+ # Raised when a command was not found.
12
+ class UndefinedCommandError < Error
15
13
  end
14
+ UndefinedTaskError = UndefinedCommandError
16
15
 
17
- # Raised when a task was found, but not invoked properly.
18
- #
16
+ class AmbiguousCommandError < Error
17
+ end
18
+ AmbiguousTaskError = AmbiguousCommandError
19
+
20
+ # Raised when a command was found, but not invoked properly.
19
21
  class InvocationError < Error
20
22
  end
21
23
 
@@ -27,9 +29,4 @@ class Thor
27
29
 
28
30
  class MalformattedArgumentError < InvocationError
29
31
  end
30
-
31
- # Raised when a user tries to call a private method encoded in templated filename.
32
- #
33
- class PrivateMethodEncodedError < Error
34
- end
35
32
  end
@@ -1,9 +1,9 @@
1
1
  require 'thor/base'
2
2
 
3
3
  # Thor has a special class called Thor::Group. The main difference to Thor class
4
- # is that it invokes all tasks at once. It also include some methods that allows
4
+ # is that it invokes all commands at once. It also include some methods that allows
5
5
  # invocations to be done at the class method, which are not available to Thor
6
- # tasks.
6
+ # commands.
7
7
  class Thor::Group
8
8
  class << self
9
9
  # The description for this Thor::Group. If none is provided, but a source root
@@ -14,11 +14,11 @@ class Thor::Group
14
14
  # description<String>:: The description for this Thor::Group.
15
15
  #
16
16
  def desc(description=nil)
17
- case description
18
- when nil
19
- @desc ||= from_superclass(:desc, nil)
20
- else
21
- @desc = description
17
+ @desc = case description
18
+ when nil
19
+ @desc || from_superclass(:desc, nil)
20
+ else
21
+ description
22
22
  end
23
23
  end
24
24
 
@@ -48,7 +48,7 @@ class Thor::Group
48
48
  end
49
49
 
50
50
  # Invoke the given namespace or class given. It adds an instance
51
- # method that will invoke the klass and task. You can give a block to
51
+ # method that will invoke the klass and command. You can give a block to
52
52
  # configure how it will be invoked.
53
53
  #
54
54
  # The namespace/class given will have its options showed on the help
@@ -64,12 +64,12 @@ class Thor::Group
64
64
 
65
65
  class_eval <<-METHOD, __FILE__, __LINE__
66
66
  def _invoke_#{name.to_s.gsub(/\W/, '_')}
67
- klass, task = self.class.prepare_for_invocation(nil, #{name.inspect})
67
+ klass, command = self.class.prepare_for_invocation(nil, #{name.inspect})
68
68
 
69
69
  if klass
70
70
  say_status :invoke, #{name.inspect}, #{verbose.inspect}
71
71
  block = self.class.invocation_blocks[#{name.inspect}]
72
- _invoke_for_class_method klass, task, &block
72
+ _invoke_for_class_method klass, command, &block
73
73
  else
74
74
  say_status :error, %(#{name.inspect} [not found]), :red
75
75
  end
@@ -100,7 +100,7 @@ class Thor::Group
100
100
  # In some cases you want to customize how a specified hook is going to be
101
101
  # invoked. You can do that by overwriting the class method
102
102
  # prepare_for_invocation. The class method must necessarily return a klass
103
- # and an optional task.
103
+ # and an optional command.
104
104
  #
105
105
  # ==== Custom invocations
106
106
  #
@@ -127,12 +127,12 @@ class Thor::Group
127
127
 
128
128
  value = options[#{name.inspect}]
129
129
  value = #{name.inspect} if TrueClass === value
130
- klass, task = self.class.prepare_for_invocation(#{name.inspect}, value)
130
+ klass, command = self.class.prepare_for_invocation(#{name.inspect}, value)
131
131
 
132
132
  if klass
133
133
  say_status :invoke, value, #{verbose.inspect}
134
134
  block = self.class.invocation_blocks[#{name.inspect}]
135
- _invoke_for_class_method klass, task, &block
135
+ _invoke_for_class_method klass, command, &block
136
136
  else
137
137
  say_status :error, %(\#{value} [not found]), :red
138
138
  end
@@ -149,7 +149,7 @@ class Thor::Group
149
149
  #
150
150
  def remove_invocation(*names)
151
151
  names.each do |name|
152
- remove_task(name)
152
+ remove_command(name)
153
153
  remove_class_option(name)
154
154
  invocations.delete(name)
155
155
  invocation_blocks.delete(name)
@@ -196,30 +196,26 @@ class Thor::Group
196
196
  end
197
197
  end
198
198
 
199
- # Returns tasks ready to be printed.
200
- def printable_tasks(*)
199
+ # Returns commands ready to be printed.
200
+ def printable_commands(*)
201
201
  item = []
202
202
  item << banner
203
203
  item << (desc ? "# #{desc.gsub(/\s+/m,' ')}" : "")
204
204
  [item]
205
205
  end
206
+ alias printable_tasks printable_commands
206
207
 
207
- def handle_argument_error(task, error, arity=nil) #:nodoc:
208
- if arity > 0
209
- msg = "#{basename} #{task.name} takes #{arity} argument"
210
- msg << "s" if arity > 1
211
- msg << ", but it should not."
212
- else
213
- msg = "You should not pass arguments to #{basename} #{task.name}."
214
- end
215
-
208
+ def handle_argument_error(command, error, args, arity) #:nodoc:
209
+ msg = "#{basename} #{command.name} takes #{arity} argument"
210
+ msg << "s" if arity > 1
211
+ msg << ", but it should not."
216
212
  raise error, msg
217
213
  end
218
214
 
219
215
  protected
220
216
 
221
217
  # The method responsible for dispatching given the args.
222
- def dispatch(task, given_args, given_opts, config) #:nodoc:
218
+ def dispatch(command, given_args, given_opts, config) #:nodoc:
223
219
  if Thor::HELP_MAPPINGS.include?(given_args.first)
224
220
  help(config[:shell])
225
221
  return
@@ -230,10 +226,9 @@ class Thor::Group
230
226
 
231
227
  instance = new(args, opts, config)
232
228
  yield instance if block_given?
233
- args = instance.args
234
229
 
235
- if task
236
- instance.invoke_task(all_tasks[task])
230
+ if command
231
+ instance.invoke_command(all_commands[command])
237
232
  else
238
233
  instance.invoke_all
239
234
  end
@@ -242,22 +237,24 @@ class Thor::Group
242
237
  # The banner for this class. You can customize it if you are invoking the
243
238
  # thor class by another ways which is not the Thor::Runner.
244
239
  def banner
245
- "#{basename} #{self_task.formatted_usage(self, false)}"
240
+ "#{basename} #{self_command.formatted_usage(self, false)}"
246
241
  end
247
242
 
248
- # Represents the whole class as a task.
249
- def self_task #:nodoc:
250
- Thor::DynamicTask.new(self.namespace, class_options)
243
+ # Represents the whole class as a command.
244
+ def self_command #:nodoc:
245
+ Thor::DynamicCommand.new(self.namespace, class_options)
251
246
  end
247
+ alias self_task self_command
252
248
 
253
249
  def baseclass #:nodoc:
254
250
  Thor::Group
255
251
  end
256
252
 
257
- def create_task(meth) #:nodoc:
258
- tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil, nil)
253
+ def create_command(meth) #:nodoc:
254
+ commands[meth.to_s] = Thor::Command.new(meth, nil, nil, nil, nil)
259
255
  true
260
256
  end
257
+ alias create_task create_command
261
258
  end
262
259
 
263
260
  include Thor::Base
@@ -266,19 +263,19 @@ class Thor::Group
266
263
 
267
264
  # Shortcut to invoke with padding and block handling. Use internally by
268
265
  # invoke and invoke_from_option class methods.
269
- def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc:
266
+ def _invoke_for_class_method(klass, command=nil, *args, &block) #:nodoc:
270
267
  with_padding do
271
268
  if block
272
269
  case block.arity
273
270
  when 3
274
- block.call(self, klass, task)
271
+ block.call(self, klass, command)
275
272
  when 2
276
273
  block.call(self, klass)
277
274
  when 1
278
275
  instance_exec(klass, &block)
279
276
  end
280
277
  else
281
- invoke klass, task, *args
278
+ invoke klass, command, *args
282
279
  end
283
280
  end
284
281
  end
@@ -6,12 +6,12 @@ class Thor
6
6
 
7
7
  module ClassMethods
8
8
  # This method is responsible for receiving a name and find the proper
9
- # class and task for it. The key is an optional parameter which is
9
+ # class and command for it. The key is an optional parameter which is
10
10
  # available only in class methods invocations (i.e. in Thor::Group).
11
11
  def prepare_for_invocation(key, name) #:nodoc:
12
12
  case name
13
13
  when Symbol, String
14
- Thor::Util.find_class_and_task_by_namespace(name.to_s, !key)
14
+ Thor::Util.find_class_and_command_by_namespace(name.to_s, !key)
15
15
  else
16
16
  name
17
17
  end
@@ -25,15 +25,15 @@ class Thor
25
25
  super
26
26
  end
27
27
 
28
- # Receives a name and invokes it. The name can be a string (either "task" or
29
- # "namespace:task"), a Thor::Task, a Class or a Thor instance. If the task
30
- # cannot be guessed by name, it can also be supplied as second argument.
28
+ # Receives a name and invokes it. The name can be a string (either "command" or
29
+ # "namespace:command"), a Thor::Command, a Class or a Thor instance. If the
30
+ # command cannot be guessed by name, it can also be supplied as second argument.
31
31
  #
32
32
  # You can also supply the arguments, options and configuration values for
33
- # the task to be invoked, if none is given, the same values used to
33
+ # the command to be invoked, if none is given, the same values used to
34
34
  # initialize the invoker are used to initialize the invoked.
35
35
  #
36
- # When no name is given, it will invoke the default task of the current class.
36
+ # When no name is given, it will invoke the default command of the current class.
37
37
  #
38
38
  # ==== Examples
39
39
  #
@@ -54,16 +54,16 @@ class Thor
54
54
  # end
55
55
  # end
56
56
  #
57
- # You can notice that the method "foo" above invokes two tasks: "bar",
57
+ # You can notice that the method "foo" above invokes two commands: "bar",
58
58
  # which belongs to the same class and "hello" which belongs to the class B.
59
59
  #
60
- # By using an invocation system you ensure that a task is invoked only once.
60
+ # By using an invocation system you ensure that a command is invoked only once.
61
61
  # In the example above, invoking "foo" will invoke "b:hello" just once, even
62
62
  # if it's invoked later by "bar" method.
63
63
  #
64
64
  # When class A invokes class B, all arguments used on A initialization are
65
65
  # supplied to B. This allows lazy parse of options. Let's suppose you have
66
- # some rspec tasks:
66
+ # some rspec commands:
67
67
  #
68
68
  # class Rspec < Thor::Group
69
69
  # class_option :mock_framework, :type => :string, :default => :rr
@@ -100,30 +100,31 @@ class Thor
100
100
  end
101
101
 
102
102
  args.unshift(nil) if Array === args.first || NilClass === args.first
103
- task, args, opts, config = args
103
+ command, args, opts, config = args
104
104
 
105
- klass, task = _retrieve_class_and_task(name, task)
105
+ klass, command = _retrieve_class_and_command(name, command)
106
106
  raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
107
107
 
108
108
  args, opts, config = _parse_initialization_options(args, opts, config)
109
- klass.send(:dispatch, task, args, opts, config) do |instance|
109
+ klass.send(:dispatch, command, args, opts, config) do |instance|
110
110
  instance.parent_options = options
111
111
  end
112
112
  end
113
113
 
114
- # Invoke the given task if the given args.
115
- def invoke_task(task, *args) #:nodoc:
114
+ # Invoke the given command if the given args.
115
+ def invoke_command(command, *args) #:nodoc:
116
116
  current = @_invocations[self.class]
117
117
 
118
- unless current.include?(task.name)
119
- current << task.name
120
- task.run(self, *args)
118
+ unless current.include?(command.name)
119
+ current << command.name
120
+ command.run(self, *args)
121
121
  end
122
122
  end
123
+ alias invoke_task invoke_command
123
124
 
124
- # Invoke all tasks for the current instance.
125
+ # Invoke all commands for the current instance.
125
126
  def invoke_all #:nodoc:
126
- self.class.all_tasks.map { |_, task| invoke_task(task) }
127
+ self.class.all_commands.map { |_, command| invoke_command(command) }
127
128
  end
128
129
 
129
130
  # Invokes using shell padding.
@@ -138,21 +139,22 @@ class Thor
138
139
  { :invocations => @_invocations }
139
140
  end
140
141
 
141
- # This method simply retrieves the class and task to be invoked.
142
- # If the name is nil or the given name is a task in the current class,
142
+ # This method simply retrieves the class and command to be invoked.
143
+ # If the name is nil or the given name is a command in the current class,
143
144
  # use the given name and return self as class. Otherwise, call
144
145
  # prepare_for_invocation in the current class.
145
- def _retrieve_class_and_task(name, sent_task=nil) #:nodoc:
146
+ def _retrieve_class_and_command(name, sent_command=nil) #:nodoc:
146
147
  case
147
148
  when name.nil?
148
149
  [self.class, nil]
149
- when self.class.all_tasks[name.to_s]
150
+ when self.class.all_commands[name.to_s]
150
151
  [self.class, name.to_s]
151
152
  else
152
- klass, task = self.class.prepare_for_invocation(nil, name)
153
- [klass, task || sent_task]
153
+ klass, command = self.class.prepare_for_invocation(nil, name)
154
+ [klass, command || sent_command]
154
155
  end
155
156
  end
157
+ alias _retrieve_class_and_task _retrieve_class_and_command
156
158
 
157
159
  # Initialize klass using values stored in the @_initializer.
158
160
  def _parse_initialization_options(args, opts, config) #:nodoc:
@@ -11,16 +11,16 @@ class Thor
11
11
  def self.to_switches(options)
12
12
  options.map do |key, value|
13
13
  case value
14
- when true
15
- "--#{key}"
16
- when Array
17
- "--#{key} #{value.map{ |v| v.inspect }.join(' ')}"
18
- when Hash
19
- "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}"
20
- when nil, false
21
- ""
22
- else
23
- "--#{key} #{value.inspect}"
14
+ when true
15
+ "--#{key}"
16
+ when Array
17
+ "--#{key} #{value.map{ |v| v.inspect }.join(' ')}"
18
+ when Hash
19
+ "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}"
20
+ when nil, false
21
+ ""
22
+ else
23
+ "--#{key} #{value.inspect}"
24
24
  end
25
25
  end.join(" ")
26
26
  end
@@ -46,7 +46,8 @@ class Thor
46
46
  @switches[option.switch_name] = option
47
47
 
48
48
  option.aliases.each do |short|
49
- @shorts[short.to_s] ||= option.switch_name
49
+ name = short.to_s.sub(/^(?!\-)/, '-')
50
+ @shorts[name] ||= option.switch_name
50
51
  end
51
52
  end
52
53
  end
@@ -79,20 +80,21 @@ class Thor
79
80
 
80
81
  if is_switch
81
82
  case shifted
82
- when SHORT_SQ_RE
83
- unshift($1.split('').map { |f| "-#{f}" })
84
- next
85
- when EQ_RE, SHORT_NUM
86
- unshift($2)
87
- switch = $1
88
- when LONG_RE, SHORT_RE
89
- switch = $1
83
+ when SHORT_SQ_RE
84
+ unshift($1.split('').map { |f| "-#{f}" })
85
+ next
86
+ when EQ_RE, SHORT_NUM
87
+ unshift($2)
88
+ switch = $1
89
+ when LONG_RE, SHORT_RE
90
+ switch = $1
90
91
  end
91
92
 
92
93
  switch = normalize_switch(switch)
93
94
  option = switch_option(switch)
94
95
  @assigns[option.human_name] = parse_peek(switch, option)
95
96
  elsif @stop_on_unknown
97
+ @parsing_options = false
96
98
  @extra << shifted
97
99
  @extra << shift while peek
98
100
  break