bundler 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bundler might be problematic. Click here for more details.
- data/CHANGELOG.md +26 -2
- data/bin/bundle +1 -3
- data/bundler.gemspec +1 -1
- data/lib/bundler/cli.rb +2 -4
- data/lib/bundler/fetcher.rb +13 -12
- data/lib/bundler/installer.rb +9 -36
- data/lib/bundler/parallel_workers/unix_worker.rb +12 -4
- data/lib/bundler/parallel_workers/worker.rb +1 -0
- data/lib/bundler/rubygems_ext.rb +1 -1
- data/lib/bundler/rubygems_integration.rb +15 -8
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
- data/lib/bundler/vendor/thor.rb +63 -56
- data/lib/bundler/vendor/thor/actions.rb +52 -51
- data/lib/bundler/vendor/thor/actions/create_file.rb +35 -37
- data/lib/bundler/vendor/thor/actions/create_link.rb +1 -2
- data/lib/bundler/vendor/thor/actions/directory.rb +36 -37
- data/lib/bundler/vendor/thor/actions/empty_directory.rb +67 -69
- data/lib/bundler/vendor/thor/actions/file_manipulation.rb +11 -12
- data/lib/bundler/vendor/thor/actions/inject_into_file.rb +41 -43
- data/lib/bundler/vendor/thor/base.rb +180 -178
- data/lib/bundler/vendor/thor/command.rb +22 -25
- data/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb +21 -24
- data/lib/bundler/vendor/thor/core_ext/io_binary_read.rb +1 -3
- data/lib/bundler/vendor/thor/core_ext/ordered_hash.rb +8 -10
- data/lib/bundler/vendor/thor/error.rb +2 -2
- data/lib/bundler/vendor/thor/group.rb +59 -60
- data/lib/bundler/vendor/thor/invocation.rb +39 -38
- data/lib/bundler/vendor/thor/line_editor.rb +17 -0
- data/lib/bundler/vendor/thor/line_editor/basic.rb +35 -0
- data/lib/bundler/vendor/thor/line_editor/readline.rb +88 -0
- data/lib/bundler/vendor/thor/parser/argument.rb +29 -30
- data/lib/bundler/vendor/thor/parser/arguments.rb +102 -98
- data/lib/bundler/vendor/thor/parser/option.rb +25 -25
- data/lib/bundler/vendor/thor/parser/options.rb +85 -85
- data/lib/bundler/vendor/thor/rake_compat.rb +6 -7
- data/lib/bundler/vendor/thor/runner.rb +154 -154
- data/lib/bundler/vendor/thor/shell.rb +23 -30
- data/lib/bundler/vendor/thor/shell/basic.rb +66 -57
- data/lib/bundler/vendor/thor/shell/color.rb +44 -43
- data/lib/bundler/vendor/thor/shell/html.rb +43 -44
- data/lib/bundler/vendor/thor/util.rb +37 -40
- data/lib/bundler/vendor/thor/version.rb +1 -1
- data/lib/bundler/version.rb +1 -1
- data/man/bundle-install.ronn +1 -1
- data/man/gemfile.5.ronn +1 -2
- data/spec/commands/binstubs_spec.rb +13 -0
- data/spec/install/gemfile/git_spec.rb +2 -2
- data/spec/install/gems/dependency_api_spec.rb +34 -0
- data/spec/install/gems/packed_spec.rb +2 -4
- data/spec/quality_spec.rb +2 -2
- data/spec/realworld/parallel_spec.rb +69 -0
- data/spec/runtime/setup_spec.rb +3 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/support/artifice/endpoint_host_redirect.rb +15 -0
- data/spec/support/permissions.rb +11 -0
- metadata +11 -6
- data/spec/realworld/parallel_install_spec.rb +0 -23
- data/spec/realworld/parallel_update_spec.rb +0 -31
@@ -19,9 +19,9 @@ class Thor
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Make initializer aware of invocations and the initialization args.
|
22
|
-
def initialize(args=[], options={}, config={}, &block) #:nodoc:
|
23
|
-
@_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] }
|
24
|
-
@_initializer = [
|
22
|
+
def initialize(args = [], options = {}, config = {}, &block) #:nodoc:
|
23
|
+
@_invocations = config[:invocations] || Hash.new { |h, k| h[k] = [] }
|
24
|
+
@_initializer = [args, options, config]
|
25
25
|
super
|
26
26
|
end
|
27
27
|
|
@@ -40,11 +40,11 @@ class Thor
|
|
40
40
|
# class A < Thor
|
41
41
|
# def foo
|
42
42
|
# invoke :bar
|
43
|
-
# invoke "b:hello", ["
|
43
|
+
# invoke "b:hello", ["Erik"]
|
44
44
|
# end
|
45
45
|
#
|
46
46
|
# def bar
|
47
|
-
# invoke "b:hello", ["
|
47
|
+
# invoke "b:hello", ["Erik"]
|
48
48
|
# end
|
49
49
|
# end
|
50
50
|
#
|
@@ -93,17 +93,18 @@ class Thor
|
|
93
93
|
#
|
94
94
|
# invoke Rspec::RR, [], :style => :foo
|
95
95
|
#
|
96
|
-
def invoke(name=nil, *args)
|
96
|
+
def invoke(name = nil, *args)
|
97
97
|
if name.nil?
|
98
98
|
warn "[Thor] Calling invoke() without argument is deprecated. Please use invoke_all instead.\n#{caller.join("\n")}"
|
99
99
|
return invoke_all
|
100
100
|
end
|
101
101
|
|
102
|
-
args.unshift(nil) if
|
102
|
+
args.unshift(nil) if args.first.is_a?(Array) || args.first.nil?
|
103
103
|
command, args, opts, config = args
|
104
104
|
|
105
105
|
klass, command = _retrieve_class_and_command(name, command)
|
106
|
-
|
106
|
+
fail "Missing Thor class for invoke #{name}" unless klass
|
107
|
+
fail "Expected Thor class, got #{klass}" unless klass <= Thor::Base
|
107
108
|
|
108
109
|
args, opts, config = _parse_initialization_options(args, opts, config)
|
109
110
|
klass.send(:dispatch, command, args, opts, config) do |instance|
|
@@ -120,7 +121,7 @@ class Thor
|
|
120
121
|
command.run(self, *args)
|
121
122
|
end
|
122
123
|
end
|
123
|
-
|
124
|
+
alias_method :invoke_task, :invoke_command
|
124
125
|
|
125
126
|
# Invoke all commands for the current instance.
|
126
127
|
def invoke_all #:nodoc:
|
@@ -132,41 +133,41 @@ class Thor
|
|
132
133
|
with_padding { invoke(*args) }
|
133
134
|
end
|
134
135
|
|
135
|
-
|
136
|
+
protected
|
136
137
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
# Configuration values that are shared between invocations.
|
139
|
+
def _shared_configuration #:nodoc:
|
140
|
+
{:invocations => @_invocations}
|
141
|
+
end
|
141
142
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
143
|
+
# This method simply retrieves the class and command to be invoked.
|
144
|
+
# If the name is nil or the given name is a command in the current class,
|
145
|
+
# use the given name and return self as class. Otherwise, call
|
146
|
+
# prepare_for_invocation in the current class.
|
147
|
+
def _retrieve_class_and_command(name, sent_command = nil) #:nodoc:
|
148
|
+
case
|
149
|
+
when name.nil?
|
150
|
+
[self.class, nil]
|
151
|
+
when self.class.all_commands[name.to_s]
|
152
|
+
[self.class, name.to_s]
|
153
|
+
else
|
154
|
+
klass, command = self.class.prepare_for_invocation(nil, name)
|
155
|
+
[klass, command || sent_command]
|
156
156
|
end
|
157
|
-
|
157
|
+
end
|
158
|
+
alias_method :_retrieve_class_and_task, :_retrieve_class_and_command
|
158
159
|
|
159
|
-
|
160
|
-
|
161
|
-
|
160
|
+
# Initialize klass using values stored in the @_initializer.
|
161
|
+
def _parse_initialization_options(args, opts, config) #:nodoc:
|
162
|
+
stored_args, stored_opts, stored_config = @_initializer
|
162
163
|
|
163
|
-
|
164
|
-
|
164
|
+
args ||= stored_args.dup
|
165
|
+
opts ||= stored_opts.dup
|
165
166
|
|
166
|
-
|
167
|
-
|
167
|
+
config ||= {}
|
168
|
+
config = stored_config.merge(_shared_configuration).merge!(config)
|
168
169
|
|
169
|
-
|
170
|
-
|
170
|
+
[args, opts, config]
|
171
|
+
end
|
171
172
|
end
|
172
173
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'thor/line_editor/basic'
|
2
|
+
require 'thor/line_editor/readline'
|
3
|
+
|
4
|
+
class Thor
|
5
|
+
module LineEditor
|
6
|
+
def self.readline(prompt, options={})
|
7
|
+
best_available.new(prompt, options).readline
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.best_available
|
11
|
+
[
|
12
|
+
Thor::LineEditor::Readline,
|
13
|
+
Thor::LineEditor::Basic
|
14
|
+
].detect(&:available?)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Thor
|
2
|
+
module LineEditor
|
3
|
+
class Basic
|
4
|
+
attr_reader :prompt, :options
|
5
|
+
|
6
|
+
def self.available?
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(prompt, options)
|
11
|
+
@prompt = prompt
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def readline
|
16
|
+
$stdout.print(prompt)
|
17
|
+
get_input
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def get_input
|
23
|
+
if echo?
|
24
|
+
$stdin.gets
|
25
|
+
else
|
26
|
+
$stdin.noecho(&:gets)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def echo?
|
31
|
+
options.fetch(:echo, true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
begin
|
2
|
+
require 'readline'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
class Thor
|
7
|
+
module LineEditor
|
8
|
+
class Readline < Basic
|
9
|
+
def self.available?
|
10
|
+
Object.const_defined?(:Readline)
|
11
|
+
end
|
12
|
+
|
13
|
+
def readline
|
14
|
+
if echo?
|
15
|
+
::Readline.completion_append_character = nil
|
16
|
+
# Ruby 1.8.7 does not allow Readline.completion_proc= to receive nil.
|
17
|
+
if complete = completion_proc
|
18
|
+
::Readline.completion_proc = complete
|
19
|
+
end
|
20
|
+
::Readline.readline(prompt, add_to_history?)
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def add_to_history?
|
29
|
+
options.fetch(:add_to_history, true)
|
30
|
+
end
|
31
|
+
|
32
|
+
def completion_proc
|
33
|
+
if use_path_completion?
|
34
|
+
Proc.new { |text| PathCompletion.new(text).matches }
|
35
|
+
elsif completion_options.any?
|
36
|
+
Proc.new do |text|
|
37
|
+
completion_options.select { |option| option.start_with?(text) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def completion_options
|
43
|
+
options.fetch(:limited_to, [])
|
44
|
+
end
|
45
|
+
|
46
|
+
def use_path_completion?
|
47
|
+
options.fetch(:path, false)
|
48
|
+
end
|
49
|
+
|
50
|
+
class PathCompletion
|
51
|
+
attr_reader :text
|
52
|
+
private :text
|
53
|
+
|
54
|
+
def initialize(text)
|
55
|
+
@text = text
|
56
|
+
end
|
57
|
+
|
58
|
+
def matches
|
59
|
+
relative_matches
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def relative_matches
|
65
|
+
absolute_matches.map { |path| path.sub(base_path, '') }
|
66
|
+
end
|
67
|
+
|
68
|
+
def absolute_matches
|
69
|
+
Dir[glob_pattern].map do |path|
|
70
|
+
if File.directory?(path)
|
71
|
+
"#{path}/"
|
72
|
+
else
|
73
|
+
path
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def glob_pattern
|
79
|
+
"#{base_path}#{text}*"
|
80
|
+
end
|
81
|
+
|
82
|
+
def base_path
|
83
|
+
"#{Dir.pwd}/"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
class Thor
|
2
2
|
class Argument #:nodoc:
|
3
|
-
VALID_TYPES = [
|
3
|
+
VALID_TYPES = [:numeric, :hash, :array, :string]
|
4
4
|
|
5
5
|
attr_reader :name, :description, :enum, :required, :type, :default, :banner
|
6
|
-
|
6
|
+
alias_method :human_name, :name
|
7
7
|
|
8
|
-
def initialize(name, options={})
|
9
|
-
class_name = self.class.name.split(
|
8
|
+
def initialize(name, options = {})
|
9
|
+
class_name = self.class.name.split('::').last
|
10
10
|
|
11
11
|
type = options[:type]
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
fail ArgumentError, "#{class_name} name can't be nil." if name.nil?
|
14
|
+
fail ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type)
|
15
15
|
|
16
16
|
@name = name.to_s
|
17
17
|
@description = options[:desc]
|
@@ -41,34 +41,33 @@ class Thor
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
protected
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
46
|
+
def validate!
|
47
|
+
if required? && !default.nil?
|
48
|
+
fail ArgumentError, 'An argument cannot be required and have default value.'
|
49
|
+
elsif @enum && !@enum.is_a?(Array)
|
50
|
+
fail ArgumentError, 'An argument cannot have an enum other than an array.'
|
52
51
|
end
|
52
|
+
end
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
def valid_type?(type)
|
55
|
+
self.class::VALID_TYPES.include?(type.to_sym)
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
58
|
+
def default_banner
|
59
|
+
case type
|
60
|
+
when :boolean
|
61
|
+
nil
|
62
|
+
when :string, :default
|
63
|
+
human_name.upcase
|
64
|
+
when :numeric
|
65
|
+
'N'
|
66
|
+
when :hash
|
67
|
+
'key:value'
|
68
|
+
when :array
|
69
|
+
'one two three'
|
71
70
|
end
|
72
|
-
|
71
|
+
end
|
73
72
|
end
|
74
73
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Thor
|
2
|
-
class Arguments #:nodoc:
|
2
|
+
class Arguments #:nodoc: # rubocop:disable ClassLength
|
3
3
|
NUMERIC = /(\d*\.\d+|\d+)/
|
4
4
|
|
5
5
|
# Receives an array of args and returns two arrays, one with arguments
|
@@ -13,7 +13,7 @@ class Thor
|
|
13
13
|
arguments << item
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
[arguments, args[Range.new(arguments.size, -1)]]
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.parse(*args)
|
@@ -23,12 +23,12 @@ class Thor
|
|
23
23
|
|
24
24
|
# Takes an array of Thor::Argument objects.
|
25
25
|
#
|
26
|
-
def initialize(arguments=[])
|
26
|
+
def initialize(arguments = [])
|
27
27
|
@assigns, @non_assigned_required = {}, []
|
28
28
|
@switches = arguments
|
29
29
|
|
30
30
|
arguments.each do |argument|
|
31
|
-
if argument.default
|
31
|
+
if !argument.default.nil?
|
32
32
|
@assigns[argument.human_name] = argument.default
|
33
33
|
elsif argument.required?
|
34
34
|
@non_assigned_required << argument
|
@@ -49,123 +49,127 @@ class Thor
|
|
49
49
|
@assigns
|
50
50
|
end
|
51
51
|
|
52
|
-
def remaining
|
52
|
+
def remaining # rubocop:disable TrivialAccessors
|
53
53
|
@pile
|
54
54
|
end
|
55
55
|
|
56
|
-
|
56
|
+
private
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
def no_or_skip?(arg)
|
59
|
+
arg =~ /^--(no|skip)-([-\w]+)$/
|
60
|
+
$2
|
61
|
+
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
def last?
|
64
|
+
@pile.empty?
|
65
|
+
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
def peek
|
68
|
+
@pile.first
|
69
|
+
end
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
def shift
|
72
|
+
@pile.shift
|
73
|
+
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
75
|
+
def unshift(arg)
|
76
|
+
if arg.kind_of?(Array)
|
77
|
+
@pile = arg + @pile
|
78
|
+
else
|
79
|
+
@pile.unshift(arg)
|
81
80
|
end
|
81
|
+
end
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
def current_is_value?
|
84
|
+
peek && peek.to_s !~ /^-/
|
85
|
+
end
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
while current_is_value? && peek.include?(?:)
|
101
|
-
key, value = shift.split(':',2)
|
102
|
-
hash[key] = value
|
103
|
-
end
|
104
|
-
hash
|
105
|
-
end
|
87
|
+
# Runs through the argument array getting strings that contains ":" and
|
88
|
+
# mark it as a hash:
|
89
|
+
#
|
90
|
+
# [ "name:string", "age:integer" ]
|
91
|
+
#
|
92
|
+
# Becomes:
|
93
|
+
#
|
94
|
+
# { "name" => "string", "age" => "integer" }
|
95
|
+
#
|
96
|
+
def parse_hash(name)
|
97
|
+
return shift if peek.is_a?(Hash)
|
98
|
+
hash = {}
|
106
99
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# ["a", "b", "c"]
|
111
|
-
#
|
112
|
-
# And returns it as an array:
|
113
|
-
#
|
114
|
-
# ["a", "b", "c"]
|
115
|
-
#
|
116
|
-
def parse_array(name)
|
117
|
-
return shift if peek.is_a?(Array)
|
118
|
-
array = []
|
119
|
-
|
120
|
-
while current_is_value?
|
121
|
-
array << shift
|
122
|
-
end
|
123
|
-
array
|
100
|
+
while current_is_value? && peek.include?(':')
|
101
|
+
key, value = shift.split(':', 2)
|
102
|
+
hash[key] = value
|
124
103
|
end
|
104
|
+
hash
|
105
|
+
end
|
125
106
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
107
|
+
# Runs through the argument array getting all strings until no string is
|
108
|
+
# found or a switch is found.
|
109
|
+
#
|
110
|
+
# ["a", "b", "c"]
|
111
|
+
#
|
112
|
+
# And returns it as an array:
|
113
|
+
#
|
114
|
+
# ["a", "b", "c"]
|
115
|
+
#
|
116
|
+
def parse_array(name)
|
117
|
+
return shift if peek.is_a?(Array)
|
118
|
+
array = []
|
119
|
+
array << shift while current_is_value?
|
120
|
+
array
|
121
|
+
end
|
131
122
|
|
132
|
-
|
133
|
-
|
134
|
-
|
123
|
+
# Check if the peek is numeric format and return a Float or Integer.
|
124
|
+
# Check if the peek is included in enum if enum is provided.
|
125
|
+
# Otherwise raises an error.
|
126
|
+
#
|
127
|
+
def parse_numeric(name)
|
128
|
+
return shift if peek.is_a?(Numeric)
|
135
129
|
|
136
|
-
|
130
|
+
unless peek =~ NUMERIC && $& == peek
|
131
|
+
fail MalformattedArgumentError, "Expected numeric value for '#{name}'; got #{peek.inspect}"
|
137
132
|
end
|
138
133
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
def parse_string(name)
|
144
|
-
if no_or_skip?(name)
|
145
|
-
nil
|
146
|
-
else
|
147
|
-
value = shift
|
148
|
-
if @switches.is_a?(Hash) && switch = @switches[name]
|
149
|
-
if switch.enum && !switch.enum.include?(value)
|
150
|
-
raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}"
|
151
|
-
end
|
134
|
+
value = $&.index('.') ? shift.to_f : shift.to_i
|
135
|
+
if @switches.is_a?(Hash) && switch = @switches[name]
|
136
|
+
if switch.enum && !switch.enum.include?(value)
|
137
|
+
raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}"
|
152
138
|
end
|
153
|
-
value
|
154
139
|
end
|
155
|
-
|
156
|
-
|
157
|
-
# Raises an error if @non_assigned_required array is not empty.
|
158
|
-
#
|
159
|
-
def check_requirement!
|
160
|
-
unless @non_assigned_required.empty?
|
161
|
-
names = @non_assigned_required.map do |o|
|
162
|
-
o.respond_to?(:switch_name) ? o.switch_name : o.human_name
|
163
|
-
end.join("', '")
|
140
|
+
value
|
141
|
+
end
|
164
142
|
|
165
|
-
|
166
|
-
|
143
|
+
# Parse string:
|
144
|
+
# for --string-arg, just return the current value in the pile
|
145
|
+
# for --no-string-arg, nil
|
146
|
+
# Check if the peek is included in enum if enum is provided. Otherwise raises an error.
|
147
|
+
#
|
148
|
+
def parse_string(name)
|
149
|
+
if no_or_skip?(name)
|
150
|
+
nil
|
151
|
+
else
|
152
|
+
value = shift
|
153
|
+
if @switches.is_a?(Hash) && switch = @switches[name] # rubocop:disable AssignmentInCondition
|
154
|
+
if switch.enum && !switch.enum.include?(value)
|
155
|
+
fail MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}"
|
156
|
+
end
|
167
157
|
end
|
158
|
+
value
|
168
159
|
end
|
160
|
+
end
|
169
161
|
|
162
|
+
# Raises an error if @non_assigned_required array is not empty.
|
163
|
+
#
|
164
|
+
def check_requirement!
|
165
|
+
unless @non_assigned_required.empty?
|
166
|
+
names = @non_assigned_required.map do |o|
|
167
|
+
o.respond_to?(:switch_name) ? o.switch_name : o.human_name
|
168
|
+
end.join("', '")
|
169
|
+
|
170
|
+
class_name = self.class.name.split('::').last.downcase
|
171
|
+
fail RequiredArgumentMissingError, "No value provided for required #{class_name} '#{names}'"
|
172
|
+
end
|
173
|
+
end
|
170
174
|
end
|
171
175
|
end
|