gli 2.11.0 → 2.12.0
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.
- checksums.yaml +4 -4
- data/bin/gli +7 -1
- data/features/gli_executable.feature +1 -1
- data/features/todo.feature +6 -6
- data/lib/gli/app.rb +7 -0
- data/lib/gli/app_support.rb +7 -1
- data/lib/gli/commands/help.rb +2 -1
- data/lib/gli/commands/scaffold.rb +3 -0
- data/lib/gli/gli_option_parser.rb +41 -4
- data/lib/gli/version.rb +1 -1
- data/test/apps/todo/bin/todo +6 -0
- data/test/apps/todo/lib/todo/commands/list.rb +3 -0
- data/test/apps/todo/lib/todo/commands/make.rb +2 -1
- data/test/tc_subcommand_parsing.rb +102 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3051959ac78b44c2e6c7d8be0701aebcb375700
|
4
|
+
data.tar.gz: 5ef912011fd093bf0afc55b7642d7eaa85f84d4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 464e43336b07485f3824dbacdeb8fbe5f5ebce4bd41af6f2dbc06406560b6c1b2d4b6ea1dc413de364ddba2d0d37576e121dcc0bebf962fef2f4d1c57221f4d8
|
7
|
+
data.tar.gz: 03296c0c993306c51903bc142cd8478348cd616aa735b4799c27dfb7b53bd048e115b32434644c3462f63742bd4b46730cb227936baafbef7ceed4d0bf9ad62b
|
data/bin/gli
CHANGED
@@ -9,6 +9,10 @@ program_desc 'create scaffolding for a GLI-powered application'
|
|
9
9
|
|
10
10
|
version GLI::VERSION
|
11
11
|
|
12
|
+
# Can't use these without changing the current behavior of gli
|
13
|
+
# arguments :strict
|
14
|
+
# subcommand_option_handling :normal
|
15
|
+
|
12
16
|
switch :v, :desc => 'Be verbose'
|
13
17
|
|
14
18
|
switch :n, :desc => 'Dry run; don''t change the disk'
|
@@ -29,7 +33,9 @@ for command line processing. Specifically, this will create
|
|
29
33
|
an executable ready to go, as well as a lib and test directory, all
|
30
34
|
inside the directory named for your project
|
31
35
|
EOS
|
32
|
-
|
36
|
+
arg :project_name
|
37
|
+
arg :command_name, [:optional, :multiple]
|
38
|
+
arg_name "project_name [command_name][, [command_name]]*"
|
33
39
|
command [:init,:scaffold] do |c|
|
34
40
|
|
35
41
|
c.switch :e,:ext, :desc => 'Create an ext dir'
|
@@ -49,7 +49,7 @@ Feature: The GLI executable works as intended
|
|
49
49
|
init - Create a new GLI-based project
|
50
50
|
|
51
51
|
SYNOPSIS
|
52
|
-
gli [global options] init [command options] project_name [
|
52
|
+
gli [global options] init [command options] project_name [command_name][, [command_name]]*
|
53
53
|
|
54
54
|
DESCRIPTION
|
55
55
|
This will create a scaffold command line project that uses GLI for command
|
data/features/todo.feature
CHANGED
@@ -185,7 +185,7 @@ Feature: The todo app has a nice user interface
|
|
185
185
|
list - List things, such as tasks or contexts
|
186
186
|
|
187
187
|
SYNOPSIS
|
188
|
-
todo [global options] list [command options] [tasks] [--flag arg] [-x arg]
|
188
|
+
todo [global options] list [command options] [tasks] [--flag arg] [-x arg] [task][, [task]]*
|
189
189
|
todo [global options] list [command options] contexts [--otherflag arg] [-b] [-f|--foobar]
|
190
190
|
|
191
191
|
DESCRIPTION
|
@@ -233,7 +233,7 @@ Feature: The todo app has a nice user interface
|
|
233
233
|
list - List things, such as tasks or contexts
|
234
234
|
|
235
235
|
SYNOPSIS
|
236
|
-
todo [global options] list [command options] [tasks] [--flag arg] [-x arg]
|
236
|
+
todo [global options] list [command options] [tasks] [--flag arg] [-x arg] [task][, [task]]*
|
237
237
|
todo [global options] list [command options] contexts [--otherflag arg] [-b] [-f|--foobar]
|
238
238
|
|
239
239
|
DESCRIPTION
|
@@ -258,7 +258,7 @@ Feature: The todo app has a nice user interface
|
|
258
258
|
list - List things, such as tasks or contexts
|
259
259
|
|
260
260
|
SYNOPSIS
|
261
|
-
todo [global options] list [command options] [tasks] [--flag arg] [-x arg]
|
261
|
+
todo [global options] list [command options] [tasks] [--flag arg] [-x arg] [task][, [task]]*
|
262
262
|
todo [global options] list [command options] contexts [--otherflag arg] [-b] [-f|--foobar]
|
263
263
|
|
264
264
|
DESCRIPTION
|
@@ -291,7 +291,7 @@ Feature: The todo app has a nice user interface
|
|
291
291
|
list - List things, such as tasks or contexts
|
292
292
|
|
293
293
|
SYNOPSIS
|
294
|
-
todo [global options] list [command options] [tasks] [--flag arg] [-x arg]
|
294
|
+
todo [global options] list [command options] [tasks] [--flag arg] [-x arg] [task][, [task]]*
|
295
295
|
todo [global options] list [command options] contexts [--otherflag arg] [-b] [-f|--foobar]
|
296
296
|
|
297
297
|
DESCRIPTION
|
@@ -315,7 +315,7 @@ Feature: The todo app has a nice user interface
|
|
315
315
|
tasks - List tasks
|
316
316
|
|
317
317
|
SYNOPSIS
|
318
|
-
todo [global options] list tasks [command options]
|
318
|
+
todo [global options] list tasks [command options] [task][, [task]]*
|
319
319
|
todo [global options] list tasks [command options] open
|
320
320
|
|
321
321
|
DESCRIPTION
|
@@ -502,7 +502,7 @@ Feature: The todo app has a nice user interface
|
|
502
502
|
list - List things, such as tasks or contexts
|
503
503
|
|
504
504
|
SYNOPSIS
|
505
|
-
todo [global options] list [command options] [tasks] [subcommand options]
|
505
|
+
todo [global options] list [command options] [tasks] [subcommand options] [task][, [task]]*
|
506
506
|
todo [global options] list [command options] contexts [subcommand options]
|
507
507
|
|
508
508
|
DESCRIPTION
|
data/lib/gli/app.rb
CHANGED
@@ -291,6 +291,13 @@ module GLI
|
|
291
291
|
@subcommand_option_handling_strategy = handling_strategy
|
292
292
|
end
|
293
293
|
|
294
|
+
# How to handle argument validation. Either +:loose+ (which does not validate argument at all)
|
295
|
+
# or +:strict+ (which will validate the number of arguments).
|
296
|
+
# If nothing is specified, +:loose+ is assumed
|
297
|
+
def arguments(handling_strategy)
|
298
|
+
@argument_handling_strategy = handling_strategy
|
299
|
+
end
|
300
|
+
|
294
301
|
private
|
295
302
|
|
296
303
|
def load_commands(path)
|
data/lib/gli/app_support.rb
CHANGED
@@ -28,6 +28,7 @@ module GLI
|
|
28
28
|
@default_command = :help
|
29
29
|
@around_block = nil
|
30
30
|
@subcommand_option_handling_strategy = :legacy
|
31
|
+
@argument_handling_strategy = :loose
|
31
32
|
clear_nexts
|
32
33
|
end
|
33
34
|
|
@@ -68,7 +69,8 @@ module GLI
|
|
68
69
|
switches,
|
69
70
|
accepts,
|
70
71
|
@default_command,
|
71
|
-
self.subcommand_option_handling_strategy
|
72
|
+
self.subcommand_option_handling_strategy,
|
73
|
+
self.argument_handling_strategy)
|
72
74
|
|
73
75
|
parsing_result = gli_option_parser.parse_options(args)
|
74
76
|
parsing_result.convert_to_openstruct! if @use_openstruct
|
@@ -201,6 +203,10 @@ module GLI
|
|
201
203
|
end
|
202
204
|
end
|
203
205
|
|
206
|
+
def argument_handling_strategy
|
207
|
+
@argument_handling_strategy || :loose
|
208
|
+
end
|
209
|
+
|
204
210
|
def subcommand_option_handling_strategy
|
205
211
|
@subcommand_option_handling_strategy || :legacy
|
206
212
|
end
|
data/lib/gli/commands/help.rb
CHANGED
@@ -59,7 +59,8 @@ module GLI
|
|
59
59
|
super(:names => :help,
|
60
60
|
:description => 'Shows a list of commands or help for one command',
|
61
61
|
:arguments_name => 'command',
|
62
|
-
:long_desc => 'Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function'
|
62
|
+
:long_desc => 'Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function',
|
63
|
+
:arguments => [Argument.new(:command_name, [:multiple, :optional])])
|
63
64
|
@app = app
|
64
65
|
@parent = app
|
65
66
|
@sorter = SORTERS[@app.help_sort_type]
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module GLI
|
2
2
|
# Parses the command-line options using an actual +OptionParser+
|
3
3
|
class GLIOptionParser
|
4
|
-
def initialize(commands,flags,switches,accepts,default_command = nil,subcommand_option_handling_strategy=:legacy)
|
4
|
+
def initialize(commands,flags,switches,accepts,default_command = nil,subcommand_option_handling_strategy=:legacy,argument_handling_strategy=:loose)
|
5
5
|
command_finder = CommandFinder.new(commands,default_command || "help")
|
6
6
|
@global_option_parser = GlobalOptionParser.new(OptionParserFactory.new(flags,switches,accepts),command_finder,flags)
|
7
7
|
@accepts = accepts
|
8
8
|
@subcommand_option_handling_strategy = subcommand_option_handling_strategy
|
9
|
+
@argument_handling_strategy = argument_handling_strategy
|
9
10
|
end
|
10
11
|
|
11
12
|
# Given the command-line argument array, returns an OptionParsingResult
|
@@ -14,7 +15,7 @@ module GLI
|
|
14
15
|
OptionParsingResult.new.tap { |parsing_result|
|
15
16
|
parsing_result.arguments = args
|
16
17
|
parsing_result = @global_option_parser.parse!(parsing_result)
|
17
|
-
option_parser_class.new(@accepts).parse!(parsing_result)
|
18
|
+
option_parser_class.new(@accepts).parse!(parsing_result, @argument_handling_strategy)
|
18
19
|
}
|
19
20
|
end
|
20
21
|
|
@@ -43,6 +44,38 @@ module GLI
|
|
43
44
|
end
|
44
45
|
|
45
46
|
protected
|
47
|
+
def verify_arguments!(arguments, command)
|
48
|
+
# Lets assume that if the user sets a 'arg_name' for the command it is for a complex scenario
|
49
|
+
# and we should not validate the arguments
|
50
|
+
return unless command.arguments_description.empty?
|
51
|
+
|
52
|
+
# Go through all declared arguments for the command, counting the min and max number
|
53
|
+
# of arguments
|
54
|
+
min_number_of_arguments = 0
|
55
|
+
max_number_of_arguments = 0
|
56
|
+
command.arguments.each do |arg|
|
57
|
+
if arg.optional?
|
58
|
+
max_number_of_arguments = max_number_of_arguments + 1
|
59
|
+
else
|
60
|
+
min_number_of_arguments = min_number_of_arguments + 1
|
61
|
+
max_number_of_arguments = max_number_of_arguments + 1
|
62
|
+
end
|
63
|
+
|
64
|
+
# Special case, as soon as we have a 'multiple' arguments, all bets are off for the
|
65
|
+
# maximum number of arguments !
|
66
|
+
if arg.multiple?
|
67
|
+
max_number_of_arguments = 99999
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Now validate the number of arguments
|
72
|
+
if arguments.size < min_number_of_arguments
|
73
|
+
raise MissingRequiredArgumentsException.new("Not enough arguments for command", command)
|
74
|
+
end
|
75
|
+
if arguments.size > max_number_of_arguments
|
76
|
+
raise MissingRequiredArgumentsException.new("Too many arguments for command", command)
|
77
|
+
end
|
78
|
+
end
|
46
79
|
|
47
80
|
def verify_required_options!(flags, command, options)
|
48
81
|
missing_required_options = flags.values.
|
@@ -70,7 +103,7 @@ module GLI
|
|
70
103
|
}
|
71
104
|
end
|
72
105
|
|
73
|
-
def parse!(parsing_result)
|
106
|
+
def parse!(parsing_result,argument_handling_strategy)
|
74
107
|
parsed_command_options = {}
|
75
108
|
command = parsing_result.command
|
76
109
|
arguments = nil
|
@@ -121,13 +154,17 @@ module GLI
|
|
121
154
|
parsing_result.command_options = command_options
|
122
155
|
parsing_result.command = command
|
123
156
|
parsing_result.arguments = Array(arguments.compact)
|
157
|
+
|
158
|
+
# Lets validate the arguments now that we know for sure the command that is invoked
|
159
|
+
verify_arguments!(parsing_result.arguments, parsing_result.command) if argument_handling_strategy == :strict
|
160
|
+
|
124
161
|
parsing_result
|
125
162
|
end
|
126
163
|
|
127
164
|
end
|
128
165
|
|
129
166
|
class LegacyCommandOptionParser < NormalCommandOptionParser
|
130
|
-
def parse!(parsing_result)
|
167
|
+
def parse!(parsing_result,argument_handling_strategy)
|
131
168
|
command = parsing_result.command
|
132
169
|
option_parser_factory = OptionParserFactory.for_command(command,@accepts)
|
133
170
|
option_block_parser = LegacyCommandOptionBlockParser.new(option_parser_factory, self.error_handler)
|
data/lib/gli/version.rb
CHANGED
data/test/apps/todo/bin/todo
CHANGED
@@ -20,6 +20,7 @@ synopsis_format (ENV['SYNOPSES'] || 'full').to_sym
|
|
20
20
|
hide_commands_without_desc ENV['HIDE_COMMANDS_WITHOUT_DESC'] === 'true'
|
21
21
|
|
22
22
|
subcommand_option_handling :normal
|
23
|
+
arguments :strict
|
23
24
|
|
24
25
|
program_desc 'Manages tasks'
|
25
26
|
program_long_desc "A test program that has a sophisticated UI that can be used to exercise a lot of GLI's power"
|
@@ -41,7 +42,12 @@ command :first do |c| c.action { |g,o,a| puts "first: #{a.join(',')}" } end
|
|
41
42
|
arg :argument, :optional
|
42
43
|
command :second do |c| c.action { |g,o,a| puts "second: #{a.join(',')}" } end
|
43
44
|
|
45
|
+
arg :first
|
46
|
+
arg :second
|
44
47
|
command :chained => [ :first, :second ]
|
48
|
+
|
49
|
+
arg :first
|
50
|
+
arg :second
|
45
51
|
command [:chained2,:ch2] => [ :second, :first ]
|
46
52
|
|
47
53
|
pre do |global,command,options,args|
|
@@ -8,6 +8,7 @@ long_desc %(
|
|
8
8
|
stored in
|
9
9
|
your todo databases.
|
10
10
|
)
|
11
|
+
|
11
12
|
command [:list] do |c|
|
12
13
|
c.default_command :tasks
|
13
14
|
|
@@ -22,6 +23,8 @@ command [:list] do |c|
|
|
22
23
|
Lists all of your tasks that you have, in varying orders, and
|
23
24
|
all that stuff. Yes, this is long, but I need a long description.
|
24
25
|
)
|
26
|
+
|
27
|
+
c.arg :task, [:optional, :multiple]
|
25
28
|
c.command :tasks do |tasks|
|
26
29
|
tasks.desc "blah blah crud x whatever"
|
27
30
|
tasks.flag [:x], :must_match => Array
|
@@ -4,6 +4,30 @@ require 'pp'
|
|
4
4
|
class TC_testSubCommandParsing < Clean::Test::TestCase
|
5
5
|
include TestHelper
|
6
6
|
|
7
|
+
def setup
|
8
|
+
@fake_stdout = FakeStdOut.new
|
9
|
+
@fake_stderr = FakeStdOut.new
|
10
|
+
|
11
|
+
@original_stdout = $stdout
|
12
|
+
$stdout = @fake_stdout
|
13
|
+
@original_stderr = $stderr
|
14
|
+
$stderr = @fake_stderr
|
15
|
+
|
16
|
+
@app = CLIApp.new
|
17
|
+
@app.reset
|
18
|
+
@app.subcommand_option_handling :legacy
|
19
|
+
@app.error_device=@fake_stderr
|
20
|
+
ENV.delete('GLI_DEBUG')
|
21
|
+
|
22
|
+
@results = {}
|
23
|
+
@exit_code = 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def teardown
|
27
|
+
$stdout = @original_stdout
|
28
|
+
$stderr = @original_stderr
|
29
|
+
end
|
30
|
+
|
7
31
|
test_that "commands options may clash with globals and it gets sorted out" do
|
8
32
|
Given :app_with_subcommands_storing_results
|
9
33
|
When {
|
@@ -24,7 +48,7 @@ class TC_testSubCommandParsing < Clean::Test::TestCase
|
|
24
48
|
@app.run(%w(-f global command1 -f command -s subcommand10 -f sub))
|
25
49
|
}
|
26
50
|
Then {
|
27
|
-
with_clue
|
51
|
+
with_clue {
|
28
52
|
assert_equal 'subcommand10',@results[:command_name]
|
29
53
|
assert_equal 'global', @results[:global_options][:f],'global'
|
30
54
|
assert !@results[:global_options][:s]
|
@@ -42,7 +66,7 @@ class TC_testSubCommandParsing < Clean::Test::TestCase
|
|
42
66
|
@app.run(%w(-f global command1 -f command -s subcommand10 -f sub))
|
43
67
|
}
|
44
68
|
Then {
|
45
|
-
with_clue
|
69
|
+
with_clue {
|
46
70
|
assert_equal 'subcommand10',@results[:command_name]
|
47
71
|
assert_equal 'global', @results[:global_options][:f],'global'
|
48
72
|
assert !@results[:global_options][:s]
|
@@ -54,18 +78,68 @@ class TC_testSubCommandParsing < Clean::Test::TestCase
|
|
54
78
|
}
|
55
79
|
end
|
56
80
|
|
81
|
+
test_that "in loose mode, argument validation is ignored" do
|
82
|
+
Given :app_with_arguments, 1, 1, false, :loose
|
83
|
+
When :run_app_with_X_arguments, 0
|
84
|
+
Then {
|
85
|
+
with_clue {
|
86
|
+
assert_equal 0, @results[:nbargs]
|
87
|
+
assert_equal 0, @exit_code
|
88
|
+
}
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
ix = -1
|
93
|
+
[
|
94
|
+
[1, 1, false, 0, :not_enough], [1, 1, false, 1, :success],
|
95
|
+
[1, 1, false, 2, :success], [1, 1, false, 3, :too_many],
|
96
|
+
[1, 1, true, 0, :not_enough], [1, 1, true, 1, :success],
|
97
|
+
[1, 1, true, 2, :success], [1, 1, true, 3, :success],
|
98
|
+
[1, 1, true, 30, :success], [0, 0, false, 0, :success],
|
99
|
+
[0, 0, false, 1, :too_many], [0, 1, false, 1, :success],
|
100
|
+
[0, 1, false, 0, :success], [1, 0, false, 1, :success],
|
101
|
+
[1, 0, false, 0, :not_enough], [0, 0, true, 0, :success],
|
102
|
+
[0, 0, true, 10, :success]
|
103
|
+
].each do |nb_required, nb_optional, has_multiple, nb_generated, status|
|
104
|
+
ix = ix + 1
|
105
|
+
test_that "in strict mode, number of arguments is validated -- #{ix}" do
|
106
|
+
Given :app_with_arguments, nb_required, nb_optional, has_multiple, :strict
|
107
|
+
When :run_app_with_X_arguments, nb_generated
|
108
|
+
Then {
|
109
|
+
with_clue {
|
110
|
+
if status == :success then
|
111
|
+
assert_equal nb_generated, @results[:nbargs]
|
112
|
+
assert_equal 0, @exit_code
|
113
|
+
assert !@fake_stderr.contained?(/Not enough arguments for command/)
|
114
|
+
assert !@fake_stderr.contained?(/Too many arguments for command/)
|
115
|
+
elsif status == :not_enough then
|
116
|
+
assert_equal nil, @results[:nbargs]
|
117
|
+
assert_equal 64, @exit_code
|
118
|
+
assert @fake_stderr.contained?(/Not enough arguments for command/)
|
119
|
+
elsif status == :too_many then
|
120
|
+
assert_equal nil, @results[:nbargs]
|
121
|
+
assert_equal 64, @exit_code
|
122
|
+
assert @fake_stderr.contained?(/Too many arguments for command/)
|
123
|
+
else
|
124
|
+
assert false
|
125
|
+
end
|
126
|
+
}
|
127
|
+
}
|
128
|
+
end
|
129
|
+
end
|
57
130
|
private
|
58
|
-
def with_clue(
|
131
|
+
def with_clue(&block)
|
59
132
|
block.call
|
60
133
|
rescue Exception
|
61
|
-
|
62
|
-
|
134
|
+
dump = ""
|
135
|
+
PP.pp "\nRESULTS---#{@results}", dump unless @results.empty?
|
136
|
+
PP.pp "\nSTDERR---\n#{@fake_stderr.to_s}", dump
|
137
|
+
PP.pp "\nSTDOUT---\n#{@fake_stdout.to_s}", dump
|
138
|
+
@original_stdout.puts dump
|
63
139
|
raise
|
64
140
|
end
|
65
141
|
|
66
142
|
def app_with_subcommands_storing_results(subcommand_option_handling_strategy = :legacy)
|
67
|
-
@results = {}
|
68
|
-
@app = CLIApp.new
|
69
143
|
@app.subcommand_option_handling subcommand_option_handling_strategy
|
70
144
|
@app.flag ['f','flag']
|
71
145
|
@app.switch ['s','switch']
|
@@ -101,4 +175,25 @@ private
|
|
101
175
|
end
|
102
176
|
end
|
103
177
|
end
|
178
|
+
|
179
|
+
def app_with_arguments(nb_required_arguments, nb_optional_arguments, has_argument_multiple, arguments_handling_strategy = :loose)
|
180
|
+
@app.arguments arguments_handling_strategy
|
181
|
+
@app.subcommand_option_handling :normal
|
182
|
+
|
183
|
+
nb_required_arguments.times { |i| @app.arg("needed#{i}") }
|
184
|
+
nb_optional_arguments.times { |i| @app.arg("optional#{i}", :optional) }
|
185
|
+
@app.arg :multiple, [:multiple, :optional] if has_argument_multiple
|
186
|
+
|
187
|
+
@app.command :cmd do |c|
|
188
|
+
c.action do |g,o,a|
|
189
|
+
@results = {
|
190
|
+
:nbargs => a.size
|
191
|
+
}
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def run_app_with_X_arguments(nb_arguments)
|
197
|
+
@exit_code = @app.run [].tap{|args| args << "cmd"; nb_arguments.times {|i| args << "arg#{i}"}}
|
198
|
+
end
|
104
199
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Copeland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|