github_cli 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +14 -3
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +41 -44
- data/README.md +77 -14
- data/Rakefile +4 -2
- data/features/assignee.feature +1 -0
- data/features/blob.feature +1 -0
- data/features/collaborator.feature +1 -0
- data/features/commit.feature +2 -1
- data/features/config.feature +27 -28
- data/features/event.feature +1 -0
- data/features/init.feature +20 -23
- data/features/key.feature +5 -5
- data/features/milestone.feature +3 -2
- data/features/reference.feature +3 -2
- data/features/starring.feature +1 -0
- data/features/support/hooks.rb +1 -1
- data/features/tag.feature +2 -1
- data/features/tree.feature +17 -0
- data/features/watching.feature +1 -0
- data/fixtures/simple_config +3 -5
- data/github_cli.gemspec +1 -1
- data/lib/github_cli/api.rb +11 -6
- data/lib/github_cli/apis/event.rb +8 -8
- data/lib/github_cli/apis/label.rb +0 -12
- data/lib/github_cli/apis/starring.rb +5 -5
- data/lib/github_cli/apis/watching.rb +5 -5
- data/lib/github_cli/cli.rb +21 -30
- data/lib/github_cli/command.rb +1 -1
- data/lib/github_cli/commands/authorizations.rb +28 -2
- data/lib/github_cli/commands/collaborators.rb +12 -12
- data/lib/github_cli/commands/commits.rb +18 -2
- data/lib/github_cli/commands/events.rb +6 -8
- data/lib/github_cli/commands/followers.rb +1 -1
- data/lib/github_cli/commands/labels.rb +22 -20
- data/lib/github_cli/commands/milestones.rb +43 -13
- data/lib/github_cli/commands/references.rb +21 -6
- data/lib/github_cli/commands/starring.rb +3 -2
- data/lib/github_cli/commands/tags.rb +16 -1
- data/lib/github_cli/commands/trees.rb +11 -5
- data/lib/github_cli/commands/watching.rb +3 -2
- data/lib/github_cli/config.rb +15 -6
- data/lib/github_cli/dsl.rb +2 -2
- data/lib/github_cli/formatter.rb +2 -3
- data/lib/github_cli/formatters/csv.rb +29 -14
- data/lib/github_cli/formatters/table.rb +2 -3
- data/lib/github_cli/man/gcli-config.1 +17 -13
- data/lib/github_cli/man/gcli-config.1.txt +23 -21
- data/lib/github_cli/vendor/thor/actions/create_link.rb +3 -0
- data/lib/github_cli/vendor/thor/actions/directory.rb +29 -10
- data/lib/github_cli/vendor/thor/actions/file_manipulation.rb +9 -3
- data/lib/github_cli/vendor/thor/actions.rb +18 -18
- data/lib/github_cli/vendor/thor/base.rb +97 -89
- data/lib/github_cli/vendor/thor/{task.rb → command.rb} +16 -12
- data/lib/github_cli/vendor/thor/core_ext/hash_with_indifferent_access.rb +5 -0
- data/lib/github_cli/vendor/thor/core_ext/io_binary_read.rb +12 -0
- data/lib/github_cli/vendor/thor/error.rb +4 -7
- data/lib/github_cli/vendor/thor/group.rb +34 -32
- data/lib/github_cli/vendor/thor/invocation.rb +28 -26
- data/lib/github_cli/vendor/thor/parser/options.rb +66 -26
- data/lib/github_cli/vendor/thor/rake_compat.rb +3 -2
- data/lib/github_cli/vendor/thor/runner.rb +21 -20
- data/lib/github_cli/vendor/thor/shell/basic.rb +20 -16
- data/lib/github_cli/vendor/thor/shell/color.rb +13 -9
- data/lib/github_cli/vendor/thor/shell/html.rb +13 -9
- data/lib/github_cli/vendor/thor/util.rb +214 -210
- data/lib/github_cli/vendor/thor/version.rb +1 -1
- data/lib/github_cli/vendor/thor.rb +232 -153
- data/lib/github_cli/version.rb +1 -1
- data/man/gcli-config.1.ronn +14 -11
- data/spec/github_cli/commands/assignees_spec.rb +20 -0
- data/spec/github_cli/commands/blobs_spec.rb +21 -0
- data/spec/github_cli/commands/collaborators_spec.rb +31 -0
- data/spec/github_cli/commands/commits_spec.rb +26 -0
- data/spec/github_cli/commands/emails_spec.rb +24 -0
- data/spec/github_cli/commands/events_spec.rb +56 -0
- data/spec/github_cli/commands/followers_spec.rb +44 -0
- data/spec/github_cli/commands/keys_spec.rb +36 -0
- data/spec/github_cli/commands/labels_spec.rb +61 -0
- data/spec/github_cli/commands/milestones_spec.rb +47 -0
- data/spec/github_cli/commands/references_spec.rb +42 -0
- data/spec/github_cli/commands/starring_spec.rb +40 -0
- data/spec/github_cli/commands/tags_spec.rb +26 -0
- data/spec/github_cli/commands/trees_spec.rb +32 -0
- data/spec/github_cli/commands/watching_spec.rb +40 -0
- data/spec/github_cli/config_spec.rb +109 -116
- data/spec/github_cli/util/convert_value_spec.rb +19 -0
- data/spec/github_cli/util/convert_values_spec.rb +14 -0
- data/spec/github_cli/util_spec.rb +0 -29
- metadata +51 -19
- data/lib/github_cli/vendor/thor/core_ext/dir_escape.rb +0 -0
- data/lib/github_cli/vendor/thor/core_ext/file_binary_read.rb +0 -9
- data/lib/github_cli/vendor/thor/empty.txt +0 -0
@@ -10,7 +10,9 @@ class Thor
|
|
10
10
|
# ==== Parameters
|
11
11
|
# source<String>:: the relative path to the source root.
|
12
12
|
# destination<String>:: the relative path to the destination root.
|
13
|
-
# config<Hash>:: give :verbose => false to not log the status
|
13
|
+
# config<Hash>:: give :verbose => false to not log the status, and
|
14
|
+
# :mode => :preserve, to preserve the file mode from the source.
|
15
|
+
|
14
16
|
#
|
15
17
|
# ==== Examples
|
16
18
|
#
|
@@ -28,6 +30,10 @@ class Thor
|
|
28
30
|
content = block.call(content) if block
|
29
31
|
content
|
30
32
|
end
|
33
|
+
if config[:mode] == :preserve
|
34
|
+
mode = File.stat(source).mode
|
35
|
+
chmod(destination, mode, config)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
39
|
# Links the file from the relative source to the relative destination. If
|
@@ -123,7 +129,7 @@ class Thor
|
|
123
129
|
#
|
124
130
|
# ==== Example
|
125
131
|
#
|
126
|
-
# chmod "script
|
132
|
+
# chmod "script/server", 0755
|
127
133
|
#
|
128
134
|
def chmod(path, mode, config={})
|
129
135
|
return unless behavior == :invoke
|
@@ -245,7 +251,7 @@ class Thor
|
|
245
251
|
def uncomment_lines(path, flag, *args)
|
246
252
|
flag = flag.respond_to?(:source) ? flag.source : flag
|
247
253
|
|
248
|
-
gsub_file(path, /^(\s*)
|
254
|
+
gsub_file(path, /^(\s*)#[[:blank:]]*(.*#{flag})/, '\1\2', *args)
|
249
255
|
end
|
250
256
|
|
251
257
|
# Comment all lines matching a given regex. It will leave the space
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'uri'
|
3
|
-
require 'thor/core_ext/
|
3
|
+
require 'thor/core_ext/io_binary_read'
|
4
4
|
require 'thor/actions/create_file'
|
5
5
|
require 'thor/actions/create_link'
|
6
6
|
require 'thor/actions/directory'
|
@@ -73,13 +73,13 @@ class Thor
|
|
73
73
|
#
|
74
74
|
def initialize(args=[], options={}, config={})
|
75
75
|
self.behavior = case config[:behavior].to_s
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
76
|
+
when "force", "skip"
|
77
|
+
_cleanup_options_and_set(options, config[:behavior])
|
78
|
+
:invoke
|
79
|
+
when "revoke"
|
80
|
+
:revoke
|
81
|
+
else
|
82
|
+
:invoke
|
83
83
|
end
|
84
84
|
|
85
85
|
super
|
@@ -268,8 +268,8 @@ class Thor
|
|
268
268
|
# switches.
|
269
269
|
#
|
270
270
|
# ==== Parameters
|
271
|
-
#
|
272
|
-
# args<Array>:: arguments to the
|
271
|
+
# command<String>:: the command to be invoked
|
272
|
+
# args<Array>:: arguments to the command
|
273
273
|
# config<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output.
|
274
274
|
# Other options are given as parameter to Thor.
|
275
275
|
#
|
@@ -282,13 +282,13 @@ class Thor
|
|
282
282
|
# thor :list, :all => true, :substring => 'rails'
|
283
283
|
# #=> thor list --all --substring=rails
|
284
284
|
#
|
285
|
-
def thor(
|
285
|
+
def thor(command, *args)
|
286
286
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
287
287
|
verbose = config.key?(:verbose) ? config.delete(:verbose) : true
|
288
288
|
pretend = config.key?(:pretend) ? config.delete(:pretend) : false
|
289
289
|
capture = config.key?(:capture) ? config.delete(:capture) : false
|
290
290
|
|
291
|
-
args.unshift
|
291
|
+
args.unshift(command)
|
292
292
|
args.push Thor::Options.to_switches(config)
|
293
293
|
command = args.join(' ').strip
|
294
294
|
|
@@ -305,12 +305,12 @@ class Thor
|
|
305
305
|
|
306
306
|
def _cleanup_options_and_set(options, key) #:nodoc:
|
307
307
|
case options
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
308
|
+
when Array
|
309
|
+
%w(--force -f --skip -s).each { |i| options.delete(i) }
|
310
|
+
options << "--#{key}"
|
311
|
+
when Hash
|
312
|
+
[:force, :skip, "force", "skip"].each { |i| options.delete(i) }
|
313
|
+
options.merge!(key => true)
|
314
314
|
end
|
315
315
|
end
|
316
316
|
|
@@ -1,15 +1,16 @@
|
|
1
|
+
require 'thor/command'
|
1
2
|
require 'thor/core_ext/hash_with_indifferent_access'
|
2
3
|
require 'thor/core_ext/ordered_hash'
|
3
4
|
require 'thor/error'
|
4
|
-
require 'thor/shell'
|
5
5
|
require 'thor/invocation'
|
6
6
|
require 'thor/parser'
|
7
|
-
require 'thor/
|
7
|
+
require 'thor/shell'
|
8
8
|
require 'thor/util'
|
9
9
|
|
10
10
|
class Thor
|
11
11
|
autoload :Actions, 'thor/actions'
|
12
12
|
autoload :RakeCompat, 'thor/rake_compat'
|
13
|
+
autoload :Group, 'thor/group'
|
13
14
|
|
14
15
|
# Shortcuts for help.
|
15
16
|
HELP_MAPPINGS = %w(-h -? --help -D)
|
@@ -46,8 +47,8 @@ class Thor
|
|
46
47
|
# first two parameters.
|
47
48
|
|
48
49
|
if options.is_a?(Array)
|
49
|
-
|
50
|
-
parse_options = parse_options.merge(
|
50
|
+
command_options = config.delete(:command_options) # hook for start
|
51
|
+
parse_options = parse_options.merge(command_options) if command_options
|
51
52
|
array_options, hash_options = options, {}
|
52
53
|
else
|
53
54
|
# Handle the case where the class was explicitly instantiated
|
@@ -58,8 +59,10 @@ class Thor
|
|
58
59
|
# Let Thor::Options parse the options first, so it can remove
|
59
60
|
# declared options from the array. This will leave us with
|
60
61
|
# a list of arguments that weren't declared.
|
61
|
-
|
62
|
+
stop_on_unknown = self.class.stop_on_unknown_option? config[:current_command]
|
63
|
+
opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown)
|
62
64
|
self.options = opts.parse(array_options)
|
65
|
+
self.options = config[:class_options].merge(self.options) if config[:class_options]
|
63
66
|
|
64
67
|
# If unknown options are disallowed, make sure that none of the
|
65
68
|
# remaining arguments looks like an option.
|
@@ -116,18 +119,6 @@ class Thor
|
|
116
119
|
end
|
117
120
|
|
118
121
|
module ClassMethods
|
119
|
-
def attr_reader(*) #:nodoc:
|
120
|
-
no_tasks { super }
|
121
|
-
end
|
122
|
-
|
123
|
-
def attr_writer(*) #:nodoc:
|
124
|
-
no_tasks { super }
|
125
|
-
end
|
126
|
-
|
127
|
-
def attr_accessor(*) #:nodoc:
|
128
|
-
no_tasks { super }
|
129
|
-
end
|
130
|
-
|
131
122
|
# If you want to raise an error for unknown options, call check_unknown_options!
|
132
123
|
# This is disabled by default to allow dynamic invocations.
|
133
124
|
def check_unknown_options!
|
@@ -142,6 +133,13 @@ class Thor
|
|
142
133
|
!!check_unknown_options
|
143
134
|
end
|
144
135
|
|
136
|
+
# If true, option parsing is suspended as soon as an unknown option or a
|
137
|
+
# regular argument is encountered. All remaining arguments are passed to
|
138
|
+
# the command as regular arguments.
|
139
|
+
def stop_on_unknown_option?(command_name) #:nodoc:
|
140
|
+
false
|
141
|
+
end
|
142
|
+
|
145
143
|
# If you want only strict string args (useful when cascading thor classes),
|
146
144
|
# call strict_args_position! This is disabled by default to allow dynamic
|
147
145
|
# invocations.
|
@@ -163,11 +161,11 @@ class Thor
|
|
163
161
|
# is how they are parsed from the command line, arguments are retrieved
|
164
162
|
# from position:
|
165
163
|
#
|
166
|
-
# thor
|
164
|
+
# thor command NAME
|
167
165
|
#
|
168
166
|
# Instead of:
|
169
167
|
#
|
170
|
-
# thor
|
168
|
+
# thor command --name=NAME
|
171
169
|
#
|
172
170
|
# Besides, arguments are used inside your code as an accessor (self.argument),
|
173
171
|
# while options are all kept in a hash (self.options).
|
@@ -194,7 +192,7 @@ class Thor
|
|
194
192
|
#
|
195
193
|
def argument(name, options={})
|
196
194
|
is_thor_reserved_word?(name, :argument)
|
197
|
-
|
195
|
+
no_commands { attr_accessor name }
|
198
196
|
|
199
197
|
required = if options.key?(:optional)
|
200
198
|
!options[:optional]
|
@@ -298,88 +296,92 @@ class Thor
|
|
298
296
|
end
|
299
297
|
|
300
298
|
# Defines the group. This is used when thor list is invoked so you can specify
|
301
|
-
# that only
|
299
|
+
# that only commands from a pre-defined group will be shown. Defaults to standard.
|
302
300
|
#
|
303
301
|
# ==== Parameters
|
304
302
|
# name<String|Symbol>
|
305
303
|
#
|
306
304
|
def group(name=nil)
|
307
|
-
case name
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
305
|
+
@group = case name
|
306
|
+
when nil
|
307
|
+
@group || from_superclass(:group, 'standard')
|
308
|
+
else
|
309
|
+
name.to_s
|
312
310
|
end
|
313
311
|
end
|
314
312
|
|
315
|
-
# Returns the
|
313
|
+
# Returns the commands for this Thor class.
|
316
314
|
#
|
317
315
|
# ==== Returns
|
318
|
-
# OrderedHash:: An ordered hash with
|
316
|
+
# OrderedHash:: An ordered hash with commands names as keys and Thor::Command
|
319
317
|
# objects as values.
|
320
318
|
#
|
321
|
-
def
|
322
|
-
@
|
319
|
+
def commands
|
320
|
+
@commands ||= Thor::CoreExt::OrderedHash.new
|
323
321
|
end
|
322
|
+
alias tasks commands
|
324
323
|
|
325
|
-
# Returns the
|
324
|
+
# Returns the commands for this Thor class and all subclasses.
|
326
325
|
#
|
327
326
|
# ==== Returns
|
328
|
-
# OrderedHash:: An ordered hash with
|
327
|
+
# OrderedHash:: An ordered hash with commands names as keys and Thor::Command
|
329
328
|
# objects as values.
|
330
329
|
#
|
331
|
-
def
|
332
|
-
@
|
333
|
-
@
|
330
|
+
def all_commands
|
331
|
+
@all_commands ||= from_superclass(:all_commands, Thor::CoreExt::OrderedHash.new)
|
332
|
+
@all_commands.merge(commands)
|
334
333
|
end
|
334
|
+
alias all_tasks all_commands
|
335
335
|
|
336
|
-
# Removes a given
|
336
|
+
# Removes a given command from this Thor class. This is usually done if you
|
337
337
|
# are inheriting from another class and don't want it to be available
|
338
338
|
# anymore.
|
339
339
|
#
|
340
|
-
# By default it only remove the mapping to the
|
340
|
+
# By default it only remove the mapping to the command. But you can supply
|
341
341
|
# :undefine => true to undefine the method from the class as well.
|
342
342
|
#
|
343
343
|
# ==== Parameters
|
344
|
-
# name<Symbol|String>:: The name of the
|
345
|
-
# options<Hash>:: You can give :undefine => true if you want
|
344
|
+
# name<Symbol|String>:: The name of the command to be removed
|
345
|
+
# options<Hash>:: You can give :undefine => true if you want commands the method
|
346
346
|
# to be undefined from the class as well.
|
347
347
|
#
|
348
|
-
def
|
348
|
+
def remove_command(*names)
|
349
349
|
options = names.last.is_a?(Hash) ? names.pop : {}
|
350
350
|
|
351
351
|
names.each do |name|
|
352
|
-
|
353
|
-
|
352
|
+
commands.delete(name.to_s)
|
353
|
+
all_commands.delete(name.to_s)
|
354
354
|
undef_method name if options[:undefine]
|
355
355
|
end
|
356
356
|
end
|
357
|
+
alias remove_task remove_command
|
357
358
|
|
358
|
-
# All methods defined inside the given block are not added as
|
359
|
+
# All methods defined inside the given block are not added as commands.
|
359
360
|
#
|
360
361
|
# So you can do:
|
361
362
|
#
|
362
363
|
# class MyScript < Thor
|
363
|
-
#
|
364
|
-
# def
|
364
|
+
# no_commands do
|
365
|
+
# def this_is_not_a_command
|
365
366
|
# end
|
366
367
|
# end
|
367
368
|
# end
|
368
369
|
#
|
369
|
-
# You can also add the method and remove it from the
|
370
|
+
# You can also add the method and remove it from the command list:
|
370
371
|
#
|
371
372
|
# class MyScript < Thor
|
372
|
-
# def
|
373
|
+
# def this_is_not_a_command
|
373
374
|
# end
|
374
|
-
#
|
375
|
+
# remove_command :this_is_not_a_command
|
375
376
|
# end
|
376
377
|
#
|
377
|
-
def
|
378
|
-
@
|
378
|
+
def no_commands
|
379
|
+
@no_commands = true
|
379
380
|
yield
|
380
381
|
ensure
|
381
|
-
@
|
382
|
+
@no_commands = false
|
382
383
|
end
|
384
|
+
alias no_tasks no_commands
|
383
385
|
|
384
386
|
# Sets the namespace for the Thor or Thor::Group class. By default the
|
385
387
|
# namespace is retrieved from the class name. If your Thor class is named
|
@@ -391,7 +393,7 @@ class Thor
|
|
391
393
|
#
|
392
394
|
# namespace :my_scripts
|
393
395
|
#
|
394
|
-
# You change how your
|
396
|
+
# You change how your commands are invoked:
|
395
397
|
#
|
396
398
|
# thor my_scripts -h
|
397
399
|
#
|
@@ -399,26 +401,26 @@ class Thor
|
|
399
401
|
#
|
400
402
|
# namespace :default
|
401
403
|
#
|
402
|
-
# Your
|
404
|
+
# Your commands can be invoked with a shortcut. Instead of:
|
403
405
|
#
|
404
|
-
# thor :
|
406
|
+
# thor :my_command
|
405
407
|
#
|
406
408
|
def namespace(name=nil)
|
407
|
-
case name
|
409
|
+
@namespace = case name
|
408
410
|
when nil
|
409
|
-
@namespace
|
411
|
+
@namespace || Thor::Util.namespace_from_thor_class(self)
|
410
412
|
else
|
411
413
|
@namespace = name.to_s
|
412
414
|
end
|
413
415
|
end
|
414
416
|
|
415
|
-
# Parses the
|
416
|
-
# and invoke the
|
417
|
+
# Parses the command and options from the given args, instantiate the class
|
418
|
+
# and invoke the command. This method is used when the arguments must be parsed
|
417
419
|
# from an array. If you are inside Ruby and want to use a Thor class, you
|
418
420
|
# can simply initialize it:
|
419
421
|
#
|
420
422
|
# script = MyScript.new(args, options, config)
|
421
|
-
# script.invoke(:
|
423
|
+
# script.invoke(:command, first_arg, second_arg, third_arg)
|
422
424
|
#
|
423
425
|
def start(given_args=ARGV, config={})
|
424
426
|
config[:shell] ||= Thor::Base.shell.new
|
@@ -427,40 +429,42 @@ class Thor
|
|
427
429
|
ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
|
428
430
|
exit(1) if exit_on_failure?
|
429
431
|
rescue Errno::EPIPE
|
430
|
-
# This happens if a thor
|
432
|
+
# This happens if a thor command is piped to something like `head`,
|
431
433
|
# which closes the pipe when it's done reading. This will also
|
432
434
|
# mean that if the pipe is closed, further unnecessary
|
433
435
|
# computation will not occur.
|
434
436
|
exit(0)
|
435
437
|
end
|
436
438
|
|
437
|
-
# Allows to use private methods from parent in child classes as
|
439
|
+
# Allows to use private methods from parent in child classes as commands.
|
438
440
|
#
|
439
441
|
# ==== Parameters
|
440
|
-
# names<Array>:: Method names to be used as
|
442
|
+
# names<Array>:: Method names to be used as commands
|
441
443
|
#
|
442
444
|
# ==== Examples
|
443
445
|
#
|
444
|
-
#
|
445
|
-
#
|
446
|
+
# public_command :foo
|
447
|
+
# public_command :foo, :bar, :baz
|
446
448
|
#
|
447
|
-
def
|
449
|
+
def public_command(*names)
|
448
450
|
names.each do |name|
|
449
451
|
class_eval "def #{name}(*); super end"
|
450
452
|
end
|
451
453
|
end
|
454
|
+
alias public_task public_command
|
452
455
|
|
453
|
-
def
|
456
|
+
def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc:
|
454
457
|
if has_namespace
|
455
|
-
raise
|
458
|
+
raise UndefinedCommandError, "Could not find command #{command.inspect} in #{namespace.inspect} namespace."
|
456
459
|
else
|
457
|
-
raise
|
460
|
+
raise UndefinedCommandError, "Could not find command #{command.inspect}."
|
458
461
|
end
|
459
462
|
end
|
463
|
+
alias handle_no_task_error handle_no_command_error
|
460
464
|
|
461
|
-
def handle_argument_error(
|
462
|
-
msg = "#{basename} #{
|
463
|
-
if arity
|
465
|
+
def handle_argument_error(command, error, arity=nil) #:nodoc:
|
466
|
+
msg = "#{basename} #{command.name}"
|
467
|
+
if arity && arity != 0
|
464
468
|
required = arity < 0 ? (-1 - arity) : arity
|
465
469
|
msg << " requires at least #{required} argument"
|
466
470
|
msg << "s" if required > 1
|
@@ -468,7 +472,7 @@ class Thor
|
|
468
472
|
msg = "call #{msg} as"
|
469
473
|
end
|
470
474
|
|
471
|
-
msg << ": #{self.banner(
|
475
|
+
msg << ": #{self.banner(command).inspect}."
|
472
476
|
raise InvocationError, msg
|
473
477
|
end
|
474
478
|
|
@@ -546,28 +550,29 @@ class Thor
|
|
546
550
|
end
|
547
551
|
end
|
548
552
|
|
549
|
-
# Finds a
|
553
|
+
# Finds a command with the given name. If the command belongs to the current
|
550
554
|
# class, just return it, otherwise dup it and add the fresh copy to the
|
551
|
-
# current
|
552
|
-
def
|
553
|
-
|
554
|
-
|
555
|
-
elsif
|
556
|
-
|
555
|
+
# current command hash.
|
556
|
+
def find_and_refresh_command(name) #:nodoc:
|
557
|
+
command = if command = commands[name.to_s]
|
558
|
+
command
|
559
|
+
elsif command = all_commands[name.to_s]
|
560
|
+
commands[name.to_s] = command.clone
|
557
561
|
else
|
558
|
-
raise ArgumentError, "You supplied :for => #{name.inspect}, but the
|
562
|
+
raise ArgumentError, "You supplied :for => #{name.inspect}, but the command #{name.inspect} could not be found."
|
559
563
|
end
|
560
564
|
end
|
565
|
+
alias find_and_refresh_task find_and_refresh_command
|
561
566
|
|
562
567
|
# Everytime someone inherits from a Thor class, register the klass
|
563
568
|
# and file into baseclass.
|
564
569
|
def inherited(klass)
|
565
570
|
Thor::Base.register_klass_file(klass)
|
566
|
-
klass.instance_variable_set(:@
|
571
|
+
klass.instance_variable_set(:@no_commands, false)
|
567
572
|
end
|
568
573
|
|
569
574
|
# Fire this callback whenever a method is added. Added methods are
|
570
|
-
# tracked as
|
575
|
+
# tracked as commands by invoking the create_command method.
|
571
576
|
def method_added(meth)
|
572
577
|
meth = meth.to_s
|
573
578
|
|
@@ -577,12 +582,14 @@ class Thor
|
|
577
582
|
end
|
578
583
|
|
579
584
|
# Return if it's not a public instance method
|
580
|
-
return unless
|
581
|
-
|
585
|
+
return unless public_method_defined?(meth.to_sym)
|
586
|
+
|
587
|
+
# Return if attr_* added the method
|
588
|
+
return if caller.first.to_s[/`attr_(reader|writer|accessor)'/]
|
582
589
|
|
583
|
-
return if @
|
590
|
+
return if @no_commands || !create_command(meth)
|
584
591
|
|
585
|
-
is_thor_reserved_word?(meth, :
|
592
|
+
is_thor_reserved_word?(meth, :command)
|
586
593
|
Thor::Base.register_klass_file(self)
|
587
594
|
end
|
588
595
|
|
@@ -621,10 +628,11 @@ class Thor
|
|
621
628
|
def baseclass #:nodoc:
|
622
629
|
end
|
623
630
|
|
624
|
-
# SIGNATURE: Creates a new
|
631
|
+
# SIGNATURE: Creates a new command if valid_command? is true. This method is
|
625
632
|
# called when a new method is added to the class.
|
626
|
-
def
|
633
|
+
def create_command(meth) #:nodoc:
|
627
634
|
end
|
635
|
+
alias create_task create_command
|
628
636
|
|
629
637
|
# SIGNATURE: Defines behavior when the initialize method is added to the
|
630
638
|
# class.
|
@@ -632,7 +640,7 @@ class Thor
|
|
632
640
|
end
|
633
641
|
|
634
642
|
# SIGNATURE: The hook invoked by start.
|
635
|
-
def dispatch(
|
643
|
+
def dispatch(command, given_args, given_opts, config) #:nodoc:
|
636
644
|
raise NotImplementedError
|
637
645
|
end
|
638
646
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Thor
|
2
|
-
class
|
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
|
19
|
-
# implementation to create custom
|
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.
|
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.
|
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
35
|
instance.class.handle_argument_error(self, e, arity) : (raise e)
|
36
36
|
rescue NoMethodError => e
|
37
37
|
handle_no_method_error?(instance, e, caller) ?
|
38
|
-
instance.class.
|
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
|
112
|
-
class
|
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
|
119
|
-
class
|
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
|
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.
|
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,15 @@ 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
|
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
|
18
|
-
#
|
16
|
+
# Raised when a command was found, but not invoked properly.
|
19
17
|
class InvocationError < Error
|
20
18
|
end
|
21
19
|
|
@@ -29,7 +27,6 @@ class Thor
|
|
29
27
|
end
|
30
28
|
|
31
29
|
# Raised when a user tries to call a private method encoded in templated filename.
|
32
|
-
#
|
33
30
|
class PrivateMethodEncodedError < Error
|
34
31
|
end
|
35
32
|
end
|