tap 0.18.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +21 -0
- data/MIT-LICENSE +17 -15
- data/README +13 -30
- data/bin/tap +19 -24
- data/cmd/console.rb +1 -12
- data/cmd/manifest.rb +14 -19
- data/cmd/run.rb +96 -86
- data/doc/API +194 -54
- data/doc/Examples/Command Line +27 -1
- data/lib/tap.rb +2 -1
- data/lib/tap/app.rb +613 -166
- data/lib/tap/app/api.rb +115 -0
- data/lib/tap/app/queue.rb +36 -37
- data/lib/tap/app/state.rb +2 -1
- data/lib/tap/env.rb +454 -270
- data/lib/tap/env/constant.rb +83 -33
- data/lib/tap/env/context.rb +61 -0
- data/lib/tap/env/manifest.rb +140 -50
- data/lib/tap/env/minimap.rb +55 -39
- data/lib/tap/join.rb +71 -53
- data/lib/tap/joins/sync.rb +3 -1
- data/lib/tap/middleware.rb +4 -25
- data/lib/tap/middlewares/debugger.rb +75 -0
- data/lib/tap/parser.rb +268 -0
- data/lib/tap/prompt.rb +36 -0
- data/lib/tap/root.rb +3 -3
- data/lib/tap/signals.rb +26 -0
- data/lib/tap/signals/class_methods.rb +222 -0
- data/lib/tap/signals/help.rb +40 -0
- data/lib/tap/signals/module_methods.rb +20 -0
- data/lib/tap/signals/signal.rb +68 -0
- data/lib/tap/task.rb +28 -79
- data/lib/tap/tasks/dump.rb +6 -0
- data/lib/tap/tasks/load.rb +9 -37
- data/lib/tap/templater.rb +12 -1
- data/lib/tap/version.rb +1 -1
- metadata +22 -16
- data/doc/Class Reference +0 -330
- data/lib/tap/exe.rb +0 -130
- data/lib/tap/schema.rb +0 -374
- data/lib/tap/schema/parser.rb +0 -425
- data/lib/tap/schema/utils.rb +0 -56
data/History
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
== 0.19.0 / 2009-12-05
|
2
|
+
|
3
|
+
Significant rework of Tap internals.
|
4
|
+
|
5
|
+
* extracted task/join/middleware code to make Api base class
|
6
|
+
* some changes to semantics of Minimap; entry_to_minikey is
|
7
|
+
now entry_to_path. Likewise entries now specify their own
|
8
|
+
path using entry.path rather than entry.minikey
|
9
|
+
* added Signals implemented with the Dsl pattern
|
10
|
+
|
11
|
+
== 0.18.1
|
12
|
+
|
13
|
+
* updated API to allow nodes that do not respond to joins
|
14
|
+
* fixed bug in reassigning Sync joins
|
15
|
+
* added quick-queue option to run
|
16
|
+
* added short options to app configs
|
17
|
+
* added blocks to app.log
|
18
|
+
* added --help flag for joins, middleware
|
19
|
+
* removed recurrent loading hooks from load
|
20
|
+
(see tap-tasks:tap/tasks/stream)
|
21
|
+
|
1
22
|
== 0.18.0 / 2009-06-17
|
2
23
|
|
3
24
|
Several updates to simplify Tap. Most significantly,
|
data/MIT-LICENSE
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
Copyright (c) 2006-2009, Regents of the University of Colorado.
|
2
2
|
|
3
|
-
|
4
|
-
software and associated documentation files (the "Software"), to deal in the Software
|
5
|
-
without restriction, including without limitation the rights to use, copy, modify, merge,
|
6
|
-
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
7
|
-
to whom the Software is furnished to do so, subject to the following conditions:
|
3
|
+
Copyright (c) 2009, Simon Chiang.
|
8
4
|
|
9
|
-
|
10
|
-
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README
CHANGED
@@ -14,15 +14,10 @@ Tap is the core of the
|
|
14
14
|
{Tap-Suite}[http://tap.rubyforge.org/tap-suite/index.html]
|
15
15
|
which provides a standard library of
|
16
16
|
{tasks}[http://tap.rubyforge.org/tap-tasks/index.html],
|
17
|
-
{generators}[http://tap.rubyforge.org/tap-gen/index.html],
|
18
|
-
{test utilities}[http://tap.rubyforge.org/tap-test/index.html]
|
19
|
-
and a
|
20
|
-
{server}[http://tap.rubyforge.org/tap-server/index.html]
|
21
|
-
to execute workflows via HTTP.
|
17
|
+
{generators}[http://tap.rubyforge.org/tap-gen/index.html], and
|
18
|
+
{test utilities}[http://tap.rubyforge.org/tap-test/index.html].
|
22
19
|
|
23
|
-
* {Tutorial}[http://tap.rubyforge.org/tap-suite/files/doc/Tutorial.html], {API}[link:files/doc/API.html], {Structure}[link:files/doc/Class%20Reference.html]
|
24
20
|
* Website[http://tap.rubyforge.org]
|
25
|
-
* Lighthouse[http://bahuvrihi.lighthouseapp.com/projects/9908-tap-task-application/tickets]
|
26
21
|
* Github[http://github.com/bahuvrihi/tap/tree/master]
|
27
22
|
* {Google Group}[http://groups.google.com/group/ruby-on-tap]
|
28
23
|
|
@@ -51,7 +46,7 @@ Tap automatically discovers tasks.
|
|
51
46
|
dump # the default dump task
|
52
47
|
load # the default load task
|
53
48
|
|
54
|
-
And generates documentation.
|
49
|
+
And generates command line documentation.
|
55
50
|
|
56
51
|
% tap run -- goodnight --help
|
57
52
|
Goodnight -- your basic goodnight moon task
|
@@ -65,24 +60,24 @@ And generates documentation.
|
|
65
60
|
|
66
61
|
options:
|
67
62
|
--help Print this help
|
68
|
-
--
|
63
|
+
--enque Manually enques self
|
69
64
|
--config FILE Specifies a config file
|
70
65
|
|
71
|
-
Tasks are immediately available for use in workflows
|
66
|
+
Tasks are immediately available for use in workflows, and may be configured as
|
67
|
+
if they were individual executables. This workflow joins the goodnight task to
|
68
|
+
a dump task, which prints the message to stdout.
|
72
69
|
|
73
70
|
% tap run -- goodnight moon --: dump
|
74
71
|
goodnight moon
|
75
72
|
|
76
|
-
Tasks may be configured as if they were individual executables.
|
77
|
-
|
78
73
|
% tap run -- goodnight world --message hello --: dump
|
79
74
|
hello world
|
80
75
|
|
81
76
|
=== Workflow Syntax
|
82
77
|
|
83
78
|
Workflows are specified on the command line using argument vectors separated
|
84
|
-
by option breaks. The vectors define the tasks
|
85
|
-
specify joins.
|
79
|
+
by option breaks (ie '--'). The argument vectors define the tasks while
|
80
|
+
modifications to the breaks specify joins.
|
86
81
|
|
87
82
|
A simple sequence.
|
88
83
|
|
@@ -106,30 +101,18 @@ A merge (note that dump receives the inputs in serial).
|
|
106
101
|
goodnight
|
107
102
|
moon
|
108
103
|
|
109
|
-
A synchronized merge (the printout is ['goodnight', 'moon'].to_s).
|
104
|
+
A synchronized merge (the printout is <tt>['goodnight', 'moon'].to_s</tt>).
|
110
105
|
|
111
106
|
% tap run -- load goodnight -- load moon -- dump --[0,1][2].sync
|
112
107
|
goodnightmoon
|
113
108
|
|
114
|
-
== Known Issues
|
115
|
-
|
116
|
-
Tap::Env and Tap::Schema are still in flux and have poor documentation. Neither should be treated as stable.
|
117
|
-
|
118
109
|
== Installation
|
119
110
|
|
120
|
-
Tap is available as a gem on
|
111
|
+
Tap is available as a gem on Gemcutter[http://gemcutter.org/gems/tap].
|
121
112
|
|
122
113
|
% gem install tap
|
123
114
|
|
124
|
-
Tap requires an updated version of RubyGems[http://docs.rubygems.org/]
|
125
|
-
(>= 1.2.0). To check the version and update RubyGems:
|
126
|
-
|
127
|
-
% gem --version
|
128
|
-
% gem --update system
|
129
|
-
|
130
115
|
== Info
|
131
116
|
|
132
|
-
|
133
|
-
|
134
|
-
Support:: CU Denver School of Medicine Deans Academic Enrichment Fund
|
135
|
-
License:: {MIT-Style}[link:files/MIT-LICENSE.html]
|
117
|
+
Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com]
|
118
|
+
License:: {MIT-Style}[link:files/MIT-LICENSE.html]
|
data/bin/tap
CHANGED
@@ -15,11 +15,11 @@
|
|
15
15
|
require "#{File.dirname(__FILE__)}/../lib/tap.rb"
|
16
16
|
|
17
17
|
#
|
18
|
-
# setup the
|
18
|
+
# setup the application
|
19
19
|
#
|
20
20
|
|
21
21
|
begin
|
22
|
-
|
22
|
+
app = Tap::App.setup
|
23
23
|
rescue(Tap::Env::ConfigError)
|
24
24
|
# catch errors and exit gracefully
|
25
25
|
# (errors usu from gem loading errors)
|
@@ -28,40 +28,35 @@ rescue(Tap::Env::ConfigError)
|
|
28
28
|
end
|
29
29
|
|
30
30
|
#
|
31
|
-
# launch
|
31
|
+
# launch the command
|
32
32
|
#
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
commands = app.env.manifest do |env|
|
35
|
+
env.root.glob(:cmd, "**/*.rb")
|
36
|
+
end
|
37
|
+
|
38
|
+
case command = ARGV.shift.to_s
|
39
|
+
when '', '--help'
|
40
|
+
template = %Q{<% unless minimap.empty? || count <= 1 %>
|
37
41
|
<%= env_key %>:
|
38
42
|
<% end %>
|
39
|
-
<%
|
43
|
+
<% minimap.each do |key, path| %>
|
40
44
|
<%= key.ljust(width) %>
|
41
45
|
<% end %>}
|
42
46
|
|
43
|
-
commands = exe.manifest(:command).inspect(template,
|
44
|
-
:count => 0,
|
45
|
-
:width => 10
|
46
|
-
) do |templater, globals|
|
47
|
-
entries = templater.manifest.minimap
|
48
|
-
templater.entries = entries
|
49
|
-
|
50
|
-
# determine width, count
|
51
|
-
width = globals[:width]
|
52
|
-
entries.each do |key, path|
|
53
|
-
width = key.length if width < key.length
|
54
|
-
end
|
55
|
-
globals[:width] = width
|
56
|
-
globals[:count] += 1 unless entries.empty?
|
57
|
-
end
|
58
|
-
|
59
47
|
puts Lazydoc.usage(__FILE__)
|
60
48
|
puts
|
61
49
|
puts "available commands:"
|
62
|
-
puts commands
|
50
|
+
puts commands.summarize(template)
|
63
51
|
puts
|
64
52
|
puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
|
53
|
+
else
|
54
|
+
if path = commands.seek(command)
|
55
|
+
load path
|
56
|
+
else
|
57
|
+
puts "Unknown command: '#{command}'"
|
58
|
+
puts "Type 'tap --help' for usage information."
|
59
|
+
end
|
65
60
|
end
|
66
61
|
|
67
62
|
exit(0)
|
data/cmd/console.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
# environment through 'env'. For example:
|
6
6
|
#
|
7
7
|
# % tap console
|
8
|
-
# >> env[:
|
8
|
+
# >> app.env[:dump]
|
9
9
|
# => Tap::Tasks::Dump
|
10
10
|
# >> app.info
|
11
11
|
# => "state: 0 (READY) queue: 0"
|
@@ -29,17 +29,6 @@ def app
|
|
29
29
|
@app ||= Tap::App.instance
|
30
30
|
end
|
31
31
|
|
32
|
-
def env
|
33
|
-
@env ||= Tap::Env.instance
|
34
|
-
end
|
35
|
-
|
36
|
-
def run(cmd, reset=true)
|
37
|
-
app.reset if reset
|
38
|
-
schema = Tap::Schema.parse(cmd)
|
39
|
-
env.run(schema, app)
|
40
|
-
nil
|
41
|
-
end
|
42
|
-
|
43
32
|
IRB.start
|
44
33
|
|
45
34
|
# Handles a bug in IRB that causes exit to throw :IRB_EXIT
|
data/cmd/manifest.rb
CHANGED
@@ -24,15 +24,15 @@ template = %Q{<% unless manifests.empty? %>
|
|
24
24
|
<%= (env_key + ':').ljust(width) %> (<%= env.root.root %>)
|
25
25
|
<% manifests.each do |type, entries| %>
|
26
26
|
<%= type %>
|
27
|
-
<% entries.each do |key,
|
28
|
-
<%= key.ljust(width
|
27
|
+
<% entries.each do |key, paths| %>
|
28
|
+
<%= key.ljust(width) %> (<%= paths.join(', ') %>)
|
29
29
|
<% end %>
|
30
30
|
<% end %>
|
31
31
|
<% end %>
|
32
32
|
}
|
33
33
|
|
34
34
|
# filter envs to manifest
|
35
|
-
env = Tap::
|
35
|
+
env = Tap::App.instance.env
|
36
36
|
env_keys = env.minihash(true)
|
37
37
|
filter = if ARGV.empty?
|
38
38
|
env_keys.keys
|
@@ -43,6 +43,7 @@ else
|
|
43
43
|
end
|
44
44
|
|
45
45
|
# build the summary
|
46
|
+
constants = env.constants
|
46
47
|
summary = env.inspect(template, :width => 10) do |templater, globals|
|
47
48
|
current = templater.env
|
48
49
|
manifests = []
|
@@ -56,26 +57,20 @@ summary = env.inspect(template, :width => 10) do |templater, globals|
|
|
56
57
|
width = env_key.length if width < env_key.length
|
57
58
|
|
58
59
|
# build up the entries for each type of resource
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
types = {}
|
61
|
+
constants.entries(current).minimap.each do |key, const|
|
62
|
+
paths = const.require_paths.collect do |path|
|
63
|
+
current.root.relative_path(:root, path) || path
|
64
|
+
end.uniq
|
63
65
|
|
64
|
-
|
65
|
-
entries = entries.minimap.collect do |key, entry|
|
66
|
-
path = if entry.kind_of?(Tap::Env::Constant)
|
67
|
-
entry.require_path
|
68
|
-
else
|
69
|
-
entry
|
70
|
-
end
|
71
|
-
|
72
|
-
width = key.length if width < key.length
|
73
|
-
[key, current.root.relative_path(:root, path) || path]
|
74
|
-
end
|
66
|
+
width = key.length if width < key.length
|
75
67
|
|
76
|
-
|
68
|
+
const.types.keys.each do |type|
|
69
|
+
(types[type] ||= []) << [key, paths]
|
70
|
+
end
|
77
71
|
end
|
78
72
|
|
73
|
+
manifests.concat types.to_a.sort_by {|type, minimap| type }
|
79
74
|
globals[:width] = width
|
80
75
|
end
|
81
76
|
puts summary
|
data/cmd/run.rb
CHANGED
@@ -6,128 +6,138 @@
|
|
6
6
|
# tap run -- load hello --: dump Say hello
|
7
7
|
#
|
8
8
|
|
9
|
-
|
10
|
-
app = Tap::App.new
|
9
|
+
app = Tap::App.instance
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
# separate out argv schema
|
17
|
-
argv = []
|
18
|
-
while !ARGV.empty? && ARGV[0] !~ Tap::Schema::Parser::BREAK
|
19
|
-
argv << ARGV.shift
|
20
|
-
end
|
21
|
-
schema = ARGV.empty? ? nil : Tap::Schema.parse(ARGV)
|
22
|
-
ARGV.replace(argv)
|
23
|
-
|
24
|
-
# parse options
|
25
|
-
mode = :run
|
26
|
-
ConfigParser.new(app.config) do |opts|
|
27
|
-
opts.separator ""
|
28
|
-
opts.separator "configurations:"
|
11
|
+
opts = {}
|
12
|
+
parser = ConfigParser.bind(app.config) do |psr|
|
13
|
+
psr.separator ""
|
14
|
+
psr.separator "configurations:"
|
29
15
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
opts.separator ""
|
37
|
-
opts.separator "options:"
|
16
|
+
psr.add Tap::App.configurations
|
17
|
+
|
18
|
+
psr.separator ""
|
19
|
+
psr.separator "options:"
|
38
20
|
|
39
|
-
|
40
|
-
Tap::App.lazydoc.resolve
|
21
|
+
psr.on("-h", "--help", "Show this message") do
|
41
22
|
puts Lazydoc.usage(__FILE__)
|
42
|
-
puts
|
23
|
+
puts psr
|
43
24
|
exit(0)
|
44
25
|
end
|
45
26
|
|
46
|
-
|
47
|
-
|
48
|
-
puts "An inline schema cannot be specified with a file schema."
|
49
|
-
exit(0)
|
50
|
-
end
|
51
|
-
|
52
|
-
schema = Tap::Schema.load_file(file)
|
27
|
+
psr.on('-s', '--serialize', 'Serialize the workflow') do
|
28
|
+
opts[:serialize] = true
|
53
29
|
end
|
54
30
|
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
opts.on('-t', '--manifest', 'Print a list of available resources') do
|
60
|
-
tasks = env.manifest(:task)
|
61
|
-
tasks_found = !tasks.all_empty?
|
31
|
+
psr.on('-t', '--manifest', 'Print a list of available resources') do
|
32
|
+
constants = app.env.constants
|
62
33
|
|
63
|
-
joins =
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
34
|
+
tasks, joins, middleware = %w{task join middleware}.collect do |type|
|
35
|
+
constants.summarize do |constant|
|
36
|
+
constant.types[type]
|
37
|
+
end
|
38
|
+
end
|
68
39
|
|
69
|
-
|
70
|
-
puts "=== tasks ==="
|
71
|
-
puts tasks
|
40
|
+
unless tasks.empty?
|
41
|
+
puts "=== tasks ===" unless middleware.empty? && joins.empty?
|
42
|
+
puts tasks
|
72
43
|
end
|
73
44
|
|
74
|
-
|
75
|
-
puts "=== joins ==="
|
76
|
-
puts joins
|
45
|
+
unless joins.empty?
|
46
|
+
puts "=== joins ===" unless tasks.empty? && middleware.empty?
|
47
|
+
puts joins
|
77
48
|
end
|
78
49
|
|
79
|
-
|
80
|
-
puts "=== middleware ==="
|
81
|
-
puts middleware
|
50
|
+
unless middleware.empty?
|
51
|
+
puts "=== middleware ===" unless tasks.empty? && joins.empty?
|
52
|
+
puts middleware
|
82
53
|
end
|
83
54
|
|
84
55
|
exit(0)
|
85
56
|
end
|
86
57
|
|
87
|
-
|
88
|
-
|
58
|
+
psr.on('-T', '--tasks', 'Print a list of available tasks') do
|
59
|
+
constants = app.env.constants
|
60
|
+
tasks = constants.summarize do |constant|
|
61
|
+
constant.types['task']
|
62
|
+
end
|
63
|
+
|
64
|
+
puts tasks
|
89
65
|
exit(0)
|
90
66
|
end
|
91
67
|
|
92
|
-
|
68
|
+
psr.on('-u', '--quick-queue', 'Removes thread-safety from queue') do
|
69
|
+
mod = Module.new do
|
70
|
+
def synchronize
|
71
|
+
yield
|
72
|
+
end
|
73
|
+
end
|
74
|
+
app.queue.extend(mod)
|
75
|
+
end
|
76
|
+
end
|
93
77
|
|
94
78
|
#
|
95
79
|
# build and run
|
96
80
|
#
|
97
81
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
82
|
+
# Traps interrupt the normal flow of the program and so I assume thread safety
|
83
|
+
# is an issue (ex if the INT occurs during an enque and a signal specifies
|
84
|
+
# another enque). A safer way to go is to enque the prompt... when the prompt
|
85
|
+
# is executed the app won't be be doing anything else so thread safety
|
86
|
+
# shouldn't be an issue.
|
87
|
+
Signal.trap('INT') do
|
88
|
+
puts
|
89
|
+
puts "Interrupt! Signals from an interruption are not thread-safe."
|
90
|
+
|
91
|
+
require 'tap/prompt'
|
92
|
+
prompt = Tap::Prompt.new
|
93
|
+
call_prompt = true
|
94
|
+
3.times do
|
95
|
+
print "Wait for thread-safe break? (y/n): "
|
96
|
+
|
97
|
+
case gets.strip
|
98
|
+
when /^y(es)?$/i
|
99
|
+
puts "waiting for break..."
|
100
|
+
app.queue.unshift(prompt, [])
|
101
|
+
call_prompt = false
|
102
|
+
break
|
103
|
+
|
104
|
+
when /^no?$/i
|
105
|
+
break
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if call_prompt
|
110
|
+
prompt.call
|
104
111
|
end
|
105
|
-
|
106
|
-
puts msg
|
107
|
-
exit(0)
|
108
112
|
end
|
109
113
|
|
110
114
|
begin
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
app.to_schema do |type, resources|
|
120
|
-
resources.each do |resource|
|
121
|
-
const_name = resource.delete(:class).to_s
|
122
|
-
resource[:id] = env.reverse_seek(type, false) do |const|
|
123
|
-
const.const_name == const_name
|
124
|
-
end
|
115
|
+
loop do
|
116
|
+
break if ARGV.empty?
|
117
|
+
parser.scan(ARGV,
|
118
|
+
:option_break => Tap::Parser::BREAK,
|
119
|
+
:keep_break => true
|
120
|
+
) do |path|
|
121
|
+
YAML.load_file(path).each do |spec|
|
122
|
+
app.call(spec)
|
125
123
|
end
|
126
|
-
end
|
124
|
+
end
|
125
|
+
|
126
|
+
break if ARGV.empty?
|
127
|
+
ARGV.replace app.call('sig' => 'parse', 'args' => ARGV)
|
127
128
|
end
|
128
129
|
|
130
|
+
if opts[:serialize]
|
131
|
+
YAML.dump(app.serialize, $stdout)
|
132
|
+
exit(0)
|
133
|
+
end
|
134
|
+
|
135
|
+
opts = nil
|
136
|
+
parser = nil
|
137
|
+
app.run
|
138
|
+
|
129
139
|
rescue
|
130
|
-
raise if
|
140
|
+
raise if app.debug?
|
131
141
|
puts $!.message
|
132
142
|
exit(1)
|
133
143
|
end
|