bahuvrihi-tap 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +69 -0
- data/MIT-LICENSE +21 -0
- data/README +119 -0
- data/bin/tap +114 -0
- data/cmd/console.rb +42 -0
- data/cmd/destroy.rb +16 -0
- data/cmd/generate.rb +16 -0
- data/cmd/run.rb +126 -0
- data/doc/Class Reference +362 -0
- data/doc/Command Reference +153 -0
- data/doc/Tutorial +237 -0
- data/lib/tap.rb +32 -0
- data/lib/tap/app.rb +720 -0
- data/lib/tap/constants.rb +8 -0
- data/lib/tap/env.rb +640 -0
- data/lib/tap/file_task.rb +547 -0
- data/lib/tap/generator/base.rb +109 -0
- data/lib/tap/generator/destroy.rb +37 -0
- data/lib/tap/generator/generate.rb +61 -0
- data/lib/tap/generator/generators/command/command_generator.rb +21 -0
- data/lib/tap/generator/generators/command/templates/command.erb +32 -0
- data/lib/tap/generator/generators/config/config_generator.rb +26 -0
- data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
- data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +27 -0
- data/lib/tap/generator/generators/file_task/templates/file.txt +11 -0
- data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
- data/lib/tap/generator/generators/file_task/templates/task.erb +33 -0
- data/lib/tap/generator/generators/file_task/templates/test.erb +29 -0
- data/lib/tap/generator/generators/root/root_generator.rb +55 -0
- data/lib/tap/generator/generators/root/templates/Rakefile +86 -0
- data/lib/tap/generator/generators/root/templates/gemspec +27 -0
- data/lib/tap/generator/generators/root/templates/tapfile +8 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +3 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +5 -0
- data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
- data/lib/tap/generator/generators/task/task_generator.rb +27 -0
- data/lib/tap/generator/generators/task/templates/task.erb +14 -0
- data/lib/tap/generator/generators/task/templates/test.erb +21 -0
- data/lib/tap/generator/manifest.rb +14 -0
- data/lib/tap/patches/rake/rake_test_loader.rb +8 -0
- data/lib/tap/patches/rake/testtask.rb +55 -0
- data/lib/tap/patches/ruby19/backtrace_filter.rb +51 -0
- data/lib/tap/patches/ruby19/parsedate.rb +16 -0
- data/lib/tap/root.rb +581 -0
- data/lib/tap/support/aggregator.rb +55 -0
- data/lib/tap/support/assignments.rb +172 -0
- data/lib/tap/support/audit.rb +418 -0
- data/lib/tap/support/batchable.rb +47 -0
- data/lib/tap/support/batchable_class.rb +107 -0
- data/lib/tap/support/class_configuration.rb +194 -0
- data/lib/tap/support/command_line.rb +98 -0
- data/lib/tap/support/comment.rb +270 -0
- data/lib/tap/support/configurable.rb +114 -0
- data/lib/tap/support/configurable_class.rb +296 -0
- data/lib/tap/support/configuration.rb +122 -0
- data/lib/tap/support/constant.rb +70 -0
- data/lib/tap/support/constant_utils.rb +127 -0
- data/lib/tap/support/declarations.rb +111 -0
- data/lib/tap/support/executable.rb +111 -0
- data/lib/tap/support/executable_queue.rb +82 -0
- data/lib/tap/support/framework.rb +71 -0
- data/lib/tap/support/framework_class.rb +199 -0
- data/lib/tap/support/instance_configuration.rb +147 -0
- data/lib/tap/support/lazydoc.rb +428 -0
- data/lib/tap/support/manifest.rb +89 -0
- data/lib/tap/support/run_error.rb +39 -0
- data/lib/tap/support/shell_utils.rb +71 -0
- data/lib/tap/support/summary.rb +30 -0
- data/lib/tap/support/tdoc.rb +404 -0
- data/lib/tap/support/tdoc/tdoc_html_generator.rb +38 -0
- data/lib/tap/support/tdoc/tdoc_html_template.rb +42 -0
- data/lib/tap/support/templater.rb +180 -0
- data/lib/tap/support/validation.rb +410 -0
- data/lib/tap/support/versions.rb +97 -0
- data/lib/tap/task.rb +259 -0
- data/lib/tap/tasks/dump.rb +56 -0
- data/lib/tap/tasks/rake.rb +93 -0
- data/lib/tap/test.rb +37 -0
- data/lib/tap/test/env_vars.rb +29 -0
- data/lib/tap/test/file_methods.rb +377 -0
- data/lib/tap/test/script_methods.rb +144 -0
- data/lib/tap/test/subset_methods.rb +420 -0
- data/lib/tap/test/tap_methods.rb +237 -0
- data/lib/tap/workflow.rb +187 -0
- metadata +145 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
module Tap
|
2
|
+
module Support
|
3
|
+
|
4
|
+
# Version provides methods for adding, removing, and incrementing versions
|
5
|
+
# at the end of filepaths. Versions are all formatted like:
|
6
|
+
# 'filepath-version.extension'.
|
7
|
+
#
|
8
|
+
module Versions
|
9
|
+
|
10
|
+
# Adds a version to the filepath. Versioned filepaths follow the format:
|
11
|
+
# 'path-version.extension'. If no version is specified, then the filepath
|
12
|
+
# is returned.
|
13
|
+
#
|
14
|
+
# version("path/to/file.txt", 1.0) # => "path/to/file-1.0.txt"
|
15
|
+
#
|
16
|
+
def version(path, version)
|
17
|
+
version = version.to_s.strip
|
18
|
+
if version.empty?
|
19
|
+
path
|
20
|
+
else
|
21
|
+
extname = File.extname(path)
|
22
|
+
path.chomp(extname) + '-' + version + extname
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Increments the version of the filepath by the specified increment.
|
27
|
+
#
|
28
|
+
# increment("path/to/file-1.0.txt", "0.0.1") # => "path/to/file-1.0.1.txt"
|
29
|
+
# increment("path/to/file.txt", 1.0) # => "path/to/file-1.0.txt"
|
30
|
+
#
|
31
|
+
def increment(path, increment)
|
32
|
+
path, version = deversion(path)
|
33
|
+
|
34
|
+
# split the version and increment into integer arrays of equal length
|
35
|
+
increment, version = [increment, version].collect do |vstr|
|
36
|
+
begin
|
37
|
+
vstr.to_s.split(/\./).collect {|v| v.to_i}
|
38
|
+
rescue
|
39
|
+
raise "Bad version or increment: #{vstr}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
version.concat Array.new(increment.length - version.length, 0) if increment.length > version.length
|
43
|
+
|
44
|
+
# add the increment to version
|
45
|
+
0.upto(version.length-1) do |i|
|
46
|
+
version[i] += (increment[i] || 0)
|
47
|
+
end
|
48
|
+
|
49
|
+
self.version(path, version.join("."))
|
50
|
+
end
|
51
|
+
|
52
|
+
# Splits the version from the input path, then returns the path and version.
|
53
|
+
# If no version is specified, then the returned version will be nil.
|
54
|
+
#
|
55
|
+
# deversion("path/to/file-1.0.txt") # => ["path/to/file.txt", "1.0"]
|
56
|
+
# deversion("path/to/file.txt") # => ["path/to/file.txt", nil]
|
57
|
+
#
|
58
|
+
def deversion(path)
|
59
|
+
extname = File.extname(path)
|
60
|
+
extname = '' if extname =~ /^\.\d+$/
|
61
|
+
path =~ /^(.*)-(\d(\.?\d)*)#{extname}$/ ? [$1 + extname, $2] : [path, nil]
|
62
|
+
end
|
63
|
+
|
64
|
+
# A <=> comparison for versions. compare_versions can take strings,
|
65
|
+
# integers, or even arrays representing the parts of a version.
|
66
|
+
#
|
67
|
+
# compare_versions("1.0.0", "0.9.9") # => 1
|
68
|
+
# compare_versions(1.1, 1.1) # => 0
|
69
|
+
# compare_versions([0,9], [0,9,1]) # => -1
|
70
|
+
def compare_versions(a,b)
|
71
|
+
a, b = [a,b].collect {|item| to_integer_array(item) }
|
72
|
+
|
73
|
+
# equalize the lengths of the integer arrays
|
74
|
+
d = b.length - a.length
|
75
|
+
case
|
76
|
+
when d < 0 then b.concat Array.new(-d, 0)
|
77
|
+
when d > 0 then a.concat Array.new(d, 0)
|
78
|
+
end
|
79
|
+
|
80
|
+
a <=> b
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# Converts an input argument (typically a string or an array)
|
86
|
+
# to an array of integers. Splits version string on "."
|
87
|
+
def to_integer_array(arg)
|
88
|
+
arr = case arg
|
89
|
+
when Array then arg
|
90
|
+
else arg.to_s.split('.')
|
91
|
+
end
|
92
|
+
arr.collect {|i| i.to_i}
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/tap/task.rb
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
require 'tap/support/framework'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
|
5
|
+
# Tasks are the basic organizational unit of Tap. Tasks provide
|
6
|
+
# a standard backbone for creating the working parts of an application
|
7
|
+
# by facilitating configuration, batched execution of methods, and
|
8
|
+
# documentation.
|
9
|
+
#
|
10
|
+
# The functionality of Task is built from several base modules:
|
11
|
+
# - Tap::Support::Batchable
|
12
|
+
# - Tap::Support::Configurable
|
13
|
+
# - Tap::Support::Executable
|
14
|
+
#
|
15
|
+
# Tap::Workflow is built on the same foundations; the sectons on
|
16
|
+
# configuration and batching apply equally to Workflows as Tasks.
|
17
|
+
#
|
18
|
+
# === Task Definition
|
19
|
+
#
|
20
|
+
# Tasks are instantiated with a task block; when the task is run
|
21
|
+
# the block gets called with the enqued inputs. As such, the block
|
22
|
+
# should specify the same number of inputs as you enque (plus the
|
23
|
+
# task itself, which is a standard input).
|
24
|
+
#
|
25
|
+
# no_inputs = Task.new {|task| }
|
26
|
+
# one_input = Task.new {|task, input| }
|
27
|
+
# mixed_inputs = Task.new {|task, a, b, *args| }
|
28
|
+
#
|
29
|
+
# no_inputs.enq
|
30
|
+
# one_input.enq(:a)
|
31
|
+
# mixed_inputs.enq(:a, :b)
|
32
|
+
# mixed_inputs.enq(:a, :b, 1, 2, 3)
|
33
|
+
#
|
34
|
+
# Subclasses of Task specify executable code by overridding the process
|
35
|
+
# method. In this case the number of enqued inputs should correspond to
|
36
|
+
# process (passing the task would be redundant).
|
37
|
+
#
|
38
|
+
# class NoInput < Tap::Task
|
39
|
+
# def process() end
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# class OneInput < Tap::Task
|
43
|
+
# def process(input) end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# class MixedInputs < Tap::Task
|
47
|
+
# def process(a, b, *args) end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# NoInput.new.enq
|
51
|
+
# OneInput.new.enq(:a)
|
52
|
+
# MixedInputs.new.enq(:a, :b)
|
53
|
+
# MixedInputs.new.enq(:a, :b, 1, 2, 3)
|
54
|
+
#
|
55
|
+
# === Configuration
|
56
|
+
#
|
57
|
+
# Tasks are configurable. By default each task will be configured
|
58
|
+
# with the default class configurations, which can be set when the
|
59
|
+
# class is defined.
|
60
|
+
#
|
61
|
+
# class ConfiguredTask < Tap::Task
|
62
|
+
# config :one, 'one'
|
63
|
+
# config :two, 'two'
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# t = ConfiguredTask.new
|
67
|
+
# t.name # => "configured_task"
|
68
|
+
# t.config # => {:one => 'one', :two => 'two'}
|
69
|
+
#
|
70
|
+
# Configurations can be validated or processed using an optional
|
71
|
+
# block. Tap::Support::Validation pre-packages several common
|
72
|
+
# validation/processing blocks, and can be accessed through the
|
73
|
+
# class method 'c':
|
74
|
+
#
|
75
|
+
# class ValidatingTask < Tap::Task
|
76
|
+
# # string config validated to be a string
|
77
|
+
# config :string, 'str', &c.check(String)
|
78
|
+
#
|
79
|
+
# # integer config; string inputs are converted using YAML
|
80
|
+
# config :integer, 1, &c.yaml(Integer)
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# t = ValidatingTask.new
|
84
|
+
# t.string = 1 # !> ValidationError
|
85
|
+
# t.integer = 1.1 # !> ValidationError
|
86
|
+
#
|
87
|
+
# t.integer = "1"
|
88
|
+
# t.integer == 1 # => true
|
89
|
+
#
|
90
|
+
# Tasks have a name that gets used in auditing, and as a relative
|
91
|
+
# filepath to find associated files (for instance config files).
|
92
|
+
# By default the task name is based on the task class, such that
|
93
|
+
# Tap::Task has the default name 'tap/task'. Configurations
|
94
|
+
# and custom names can be provided when a task is initialized.
|
95
|
+
#
|
96
|
+
# t = ConfiguredTask.new({:one => 'ONE', :three => 'three'}, "example")
|
97
|
+
# t.name # => "example"
|
98
|
+
# t.config # => {:one => 'ONE', :two => 'two', :three => 'three'}
|
99
|
+
#
|
100
|
+
# === Batches
|
101
|
+
#
|
102
|
+
# Tasks can be assembled into batches that enque and execute collectively.
|
103
|
+
# Batched tasks are often alternatively-configured derivatives of one
|
104
|
+
# parent task, although they can be manually assembled using Task.batch.
|
105
|
+
#
|
106
|
+
# app = Tap::App.instance
|
107
|
+
# t1 = Tap::Task.new(:key => 'one') do |task, input|
|
108
|
+
# input + task.config[:key]
|
109
|
+
# end
|
110
|
+
# t1.batch # => [t1]
|
111
|
+
#
|
112
|
+
# t2 = t1.initialize_batch_obj(:key => 'two')
|
113
|
+
# t1.batch # => [t1, t2]
|
114
|
+
# t2.batch # => [t1, t2]
|
115
|
+
#
|
116
|
+
# t1.enq 't1_by_'
|
117
|
+
# t2.enq 't2_by_'
|
118
|
+
# app.run
|
119
|
+
#
|
120
|
+
# app.results(t1) # => ["t1_by_one", "t2_by_one"]
|
121
|
+
# app.results(t2) # => ["t1_by_two", "t2_by_two"]
|
122
|
+
#
|
123
|
+
# Here the results reflects that t1 and t2 were run in succession with the
|
124
|
+
# input to t1, and then the input to t2.
|
125
|
+
#
|
126
|
+
# === Subclassing
|
127
|
+
# Tasks can be subclassed normally, with one reminder related to batching.
|
128
|
+
#
|
129
|
+
# Batched tasks are generated by duplicating an existing instance, hence
|
130
|
+
# all instance variables will point to the same object in the batched
|
131
|
+
# and original task. At times (as with configurations), this is
|
132
|
+
# undesirable; the batched task should have it's own copy of an
|
133
|
+
# instance variable.
|
134
|
+
#
|
135
|
+
# In these cases, the <tt>initialize_copy</tt> should be overridden
|
136
|
+
# and should re-initialize the appropriate variables. Be sure to call
|
137
|
+
# super to invoke the default <tt>initialize_copy</tt>:
|
138
|
+
#
|
139
|
+
# class SubclassTask < Tap::Task
|
140
|
+
# attr_accessor :array
|
141
|
+
# def initialize(*args)
|
142
|
+
# @array = []
|
143
|
+
# super
|
144
|
+
# end
|
145
|
+
#
|
146
|
+
# def initialize_copy(orig)
|
147
|
+
# @array = orig.array.dup
|
148
|
+
# super
|
149
|
+
# end
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# t1 = SubclassTask.new
|
153
|
+
# t2 = t1.initialize_batch_obj
|
154
|
+
# t1.array == t2.array # => true
|
155
|
+
# t1.array.object_id == t2.array.object_id # => false
|
156
|
+
#
|
157
|
+
class Task
|
158
|
+
include Support::Executable
|
159
|
+
include Support::Framework
|
160
|
+
|
161
|
+
attr_reader :task_block
|
162
|
+
|
163
|
+
def initialize(config={}, name=nil, app=App.instance, &task_block)
|
164
|
+
super(config, name, app)
|
165
|
+
|
166
|
+
@task_block = (task_block == nil ? default_task_block : task_block)
|
167
|
+
@multithread = false
|
168
|
+
@on_complete_block = nil
|
169
|
+
@_method_name = :execute
|
170
|
+
end
|
171
|
+
|
172
|
+
# Enqueues self and self.batch to app with the inputs.
|
173
|
+
# The number of inputs provided should match the number
|
174
|
+
# of inputs specified by the arity of the _method_name method.
|
175
|
+
def enq(*inputs)
|
176
|
+
app.queue.enq(self, inputs)
|
177
|
+
end
|
178
|
+
|
179
|
+
batch_function :enq, :multithread=
|
180
|
+
batch_function(:on_complete) {}
|
181
|
+
|
182
|
+
# Executes self with the given inputs. Execute provides hooks for subclasses
|
183
|
+
# to insert standard execution code: before_execute, on_execute_error,
|
184
|
+
# and after_execute. Override any/all of these methods as needed.
|
185
|
+
#
|
186
|
+
# Execute passes the inputs to process and returns the result.
|
187
|
+
def execute(*inputs)
|
188
|
+
before_execute
|
189
|
+
begin
|
190
|
+
result = process(*inputs)
|
191
|
+
rescue
|
192
|
+
on_execute_error($!)
|
193
|
+
end
|
194
|
+
after_execute
|
195
|
+
|
196
|
+
result
|
197
|
+
end
|
198
|
+
|
199
|
+
# The method for processing inputs into outputs. Override this method in
|
200
|
+
# subclasses to provide class-specific process logic. The number of
|
201
|
+
# arguments specified by process corresponds to the number of arguments
|
202
|
+
# the task should have when enqued.
|
203
|
+
#
|
204
|
+
# class TaskWithTwoInputs < Tap::Task
|
205
|
+
# def process(a, b)
|
206
|
+
# [b,a]
|
207
|
+
# end
|
208
|
+
# end
|
209
|
+
#
|
210
|
+
# t = TaskWithTwoInputs.new
|
211
|
+
# t.enq(1,2).enq(3,4)
|
212
|
+
# t.app.run
|
213
|
+
# t.app.results(t) # => [[2,1], [4,3]]
|
214
|
+
#
|
215
|
+
# By default process passes self and the input(s) to the task_block
|
216
|
+
# provided during initialization. In this case the task block dictates
|
217
|
+
# the number of arguments enq should receive. Simply returns the inputs
|
218
|
+
# if no task_block is set.
|
219
|
+
#
|
220
|
+
# # two arguments in addition to task are specified
|
221
|
+
# # so this Task must be enqued with two inputs...
|
222
|
+
# t = Task.new {|task, a, b| [b,a] }
|
223
|
+
# t.enq(1,2).enq(3,4)
|
224
|
+
# t.app.run
|
225
|
+
# t.app.results(t) # => [[2,1], [4,3]]
|
226
|
+
#
|
227
|
+
def process(*inputs)
|
228
|
+
return inputs if task_block == nil
|
229
|
+
inputs.unshift(self)
|
230
|
+
|
231
|
+
arity = task_block.arity
|
232
|
+
n = inputs.length
|
233
|
+
unless n == arity || (arity < 0 && (-1-n) <= arity)
|
234
|
+
raise ArgumentError.new("wrong number of arguments (#{n} for #{arity})")
|
235
|
+
end
|
236
|
+
|
237
|
+
task_block.call(*inputs)
|
238
|
+
end
|
239
|
+
|
240
|
+
protected
|
241
|
+
|
242
|
+
# Hook to set a default task block. By default, nil.
|
243
|
+
def default_task_block
|
244
|
+
nil
|
245
|
+
end
|
246
|
+
|
247
|
+
# Hook to execute code before inputs are processed.
|
248
|
+
def before_execute() end
|
249
|
+
|
250
|
+
# Hook to execute code after inputs are processed.
|
251
|
+
def after_execute() end
|
252
|
+
|
253
|
+
# Hook to handle unhandled errors from processing inputs on a task level.
|
254
|
+
# By default on_execute_error simply re-raises the unhandled error.
|
255
|
+
def on_execute_error(err)
|
256
|
+
raise err
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Tap
|
2
|
+
module Tasks
|
3
|
+
# :startdoc::manifest the default dump task
|
4
|
+
#
|
5
|
+
# A dump task to print application results to a file or IO. The results are
|
6
|
+
# printed in a format allowing dumped results to be reloaded and used as
|
7
|
+
# inputs to other tasks. See Tap::Load for more details.
|
8
|
+
#
|
9
|
+
# Often dump is used as the final task in a round of tasks; if no filepath is
|
10
|
+
# specified, the results are printed to stdout.
|
11
|
+
#
|
12
|
+
# % tap run -- [your tasks] --+ dump FILEPATH
|
13
|
+
#
|
14
|
+
class Dump < Tap::FileTask
|
15
|
+
|
16
|
+
config :date_format, '%Y-%m-%d %H:%M:%S' # the date format
|
17
|
+
config :audit, true, &c.switch # include the audit trails
|
18
|
+
config :date, true, &c.switch # include a date
|
19
|
+
|
20
|
+
def process(target=$stdout)
|
21
|
+
case target
|
22
|
+
when IO then dump_to(target)
|
23
|
+
else
|
24
|
+
log_basename(:dump, target)
|
25
|
+
prepare(target)
|
26
|
+
File.open(target, "wb") {|file| dump_to(file) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Dumps the current results in app.aggregator to the io.
|
31
|
+
# The dump will include the result audits and a date,
|
32
|
+
# as specified in config.
|
33
|
+
def dump_to(io)
|
34
|
+
trails = []
|
35
|
+
results = {}
|
36
|
+
app.aggregator.to_hash.each_pair do |src, _results|
|
37
|
+
name = src.respond_to?(:name) ? src.name : ''
|
38
|
+
|
39
|
+
results["#{name} (#{src.object_id})"] = _results.collect {|_audit| _audit._current }
|
40
|
+
_results.each {|_audit| trails << _audit._to_s }
|
41
|
+
end
|
42
|
+
|
43
|
+
if audit
|
44
|
+
io.puts "# audit:"
|
45
|
+
trails.each {|trail| io.puts "# #{trail.gsub("\n", "\n# ")}"}
|
46
|
+
end
|
47
|
+
|
48
|
+
if date
|
49
|
+
io.puts "# date: #{Time.now.strftime(date_format)}"
|
50
|
+
end
|
51
|
+
|
52
|
+
YAML::dump(results, io)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
# :startdoc::manifest run rake tasks
|
6
|
+
#
|
7
|
+
# Simply enques the specified rake task(s) for execution. Useful when a
|
8
|
+
# rake task needs to be executed within a workflow. For example these
|
9
|
+
# are equivalent:
|
10
|
+
#
|
11
|
+
# % tap run -- rake test
|
12
|
+
# % rake test
|
13
|
+
#
|
14
|
+
# The only exeception is in the use of the --help option. Use --rake-help
|
15
|
+
# to access the rake help, and --help to access this help.
|
16
|
+
#
|
17
|
+
class Rake < Tap::Task
|
18
|
+
|
19
|
+
# Modifies Rake::Application by adding a hook to the standard_exception_handling
|
20
|
+
# method. This allows more fine-grained use of Rake::Applications by Tap.
|
21
|
+
module Application
|
22
|
+
def enq_top_level(app)
|
23
|
+
# takes the place of rake.top_level
|
24
|
+
if options.show_tasks
|
25
|
+
display_tasks_and_comments
|
26
|
+
exit
|
27
|
+
elsif options.show_prereqs
|
28
|
+
display_prerequisites
|
29
|
+
exit
|
30
|
+
else
|
31
|
+
top_level_tasks.each do |task_string|
|
32
|
+
name, args = parse_task_string(task_string)
|
33
|
+
task = self[name]
|
34
|
+
|
35
|
+
unless task.kind_of?(Tap::Support::Executable)
|
36
|
+
Tap::Support::Executable.initialize(task, :invoke)
|
37
|
+
end
|
38
|
+
|
39
|
+
app.enq(task, *args)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class << self
|
46
|
+
|
47
|
+
# Overrides Tap::Support::FrameworkClass#instantiate to do
|
48
|
+
# nothing so that all args get passed forward to rake.
|
49
|
+
def instantiate(argv, app=Tap::App.instance) # => instance, argv
|
50
|
+
if argv.include?('--help')
|
51
|
+
puts help
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
[new({}, default_name, app), argv.collect {|arg| arg == '--rake-help' ? '--help' : arg}]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#--
|
59
|
+
# def on_complete(override=false, &block)
|
60
|
+
# @rake_tasks.each do |task|
|
61
|
+
# task.on_complete(override, &block)
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#++
|
65
|
+
|
66
|
+
def enq(*argv)
|
67
|
+
rake = ::Rake.application
|
68
|
+
unless rake.kind_of?(Application)
|
69
|
+
rake.extend Application
|
70
|
+
end
|
71
|
+
|
72
|
+
# run as if from command line using argv
|
73
|
+
current_argv = ARGV.dup
|
74
|
+
begin
|
75
|
+
ARGV.clear
|
76
|
+
ARGV.concat(argv)
|
77
|
+
|
78
|
+
# now follow the same protocol as
|
79
|
+
# in run, handling options
|
80
|
+
rake.init
|
81
|
+
rake.load_rakefile
|
82
|
+
ensure
|
83
|
+
ARGV.clear
|
84
|
+
ARGV.concat(current_argv)
|
85
|
+
end
|
86
|
+
|
87
|
+
rake.enq_top_level(app)
|
88
|
+
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|