tap 0.12.4 → 0.17.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.
- data/History +34 -0
- data/README +62 -41
- data/bin/tap +36 -40
- data/cmd/console.rb +14 -6
- data/cmd/manifest.rb +62 -58
- data/cmd/run.rb +49 -31
- data/doc/API +84 -0
- data/doc/Class Reference +83 -115
- data/doc/Examples/Command Line +36 -0
- data/doc/Examples/Workflow +40 -0
- data/lib/tap/app.rb +293 -214
- data/lib/tap/app/node.rb +43 -0
- data/lib/tap/app/queue.rb +77 -0
- data/lib/tap/app/stack.rb +16 -0
- data/lib/tap/app/state.rb +22 -0
- data/lib/tap/constants.rb +2 -2
- data/lib/tap/env.rb +400 -314
- data/lib/tap/env/constant.rb +227 -0
- data/lib/tap/env/gems.rb +63 -0
- data/lib/tap/env/manifest.rb +89 -0
- data/lib/tap/env/minimap.rb +292 -0
- data/lib/tap/{support → env}/string_ext.rb +2 -2
- data/lib/tap/exe.rb +113 -125
- data/lib/tap/join.rb +175 -0
- data/lib/tap/joins.rb +9 -0
- data/lib/tap/joins/switch.rb +44 -0
- data/lib/tap/joins/sync.rb +99 -0
- data/lib/tap/root.rb +100 -491
- data/lib/tap/root/utils.rb +220 -0
- data/lib/tap/{support → root}/versions.rb +31 -29
- data/lib/tap/schema.rb +248 -0
- data/lib/tap/schema/parser.rb +413 -0
- data/lib/tap/schema/utils.rb +82 -0
- data/lib/tap/support/intern.rb +19 -6
- data/lib/tap/support/templater.rb +8 -3
- data/lib/tap/task.rb +175 -171
- data/lib/tap/tasks/dump.rb +58 -0
- data/lib/tap/tasks/load.rb +62 -0
- metadata +30 -73
- data/cmd/destroy.rb +0 -27
- data/cmd/generate.rb +0 -27
- data/doc/Command Reference +0 -105
- data/doc/Syntax Reference +0 -234
- data/doc/Tutorial +0 -348
- data/lib/tap/dump.rb +0 -142
- data/lib/tap/file_task.rb +0 -384
- data/lib/tap/generator/arguments.rb +0 -13
- data/lib/tap/generator/base.rb +0 -176
- data/lib/tap/generator/destroy.rb +0 -60
- data/lib/tap/generator/generate.rb +0 -93
- data/lib/tap/generator/generators/command/command_generator.rb +0 -21
- data/lib/tap/generator/generators/command/templates/command.erb +0 -32
- data/lib/tap/generator/generators/config/config_generator.rb +0 -98
- data/lib/tap/generator/generators/generator/generator_generator.rb +0 -37
- data/lib/tap/generator/generators/generator/templates/task.erb +0 -27
- data/lib/tap/generator/generators/generator/templates/test.erb +0 -26
- data/lib/tap/generator/generators/root/root_generator.rb +0 -84
- data/lib/tap/generator/generators/root/templates/MIT-LICENSE +0 -22
- data/lib/tap/generator/generators/root/templates/README +0 -14
- data/lib/tap/generator/generators/root/templates/Rakefile +0 -84
- data/lib/tap/generator/generators/root/templates/Rapfile +0 -11
- data/lib/tap/generator/generators/root/templates/gemspec +0 -27
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -3
- data/lib/tap/generator/generators/task/task_generator.rb +0 -25
- data/lib/tap/generator/generators/task/templates/task.erb +0 -14
- data/lib/tap/generator/generators/task/templates/test.erb +0 -19
- data/lib/tap/generator/manifest.rb +0 -20
- data/lib/tap/generator/preview.rb +0 -69
- data/lib/tap/load.rb +0 -64
- data/lib/tap/spec.rb +0 -41
- data/lib/tap/support/aggregator.rb +0 -65
- data/lib/tap/support/audit.rb +0 -333
- data/lib/tap/support/constant.rb +0 -143
- data/lib/tap/support/constant_manifest.rb +0 -126
- data/lib/tap/support/dependencies.rb +0 -54
- data/lib/tap/support/dependency.rb +0 -44
- data/lib/tap/support/executable.rb +0 -198
- data/lib/tap/support/executable_queue.rb +0 -125
- data/lib/tap/support/gems.rb +0 -43
- data/lib/tap/support/join.rb +0 -144
- data/lib/tap/support/joins.rb +0 -12
- data/lib/tap/support/joins/switch.rb +0 -27
- data/lib/tap/support/joins/sync_merge.rb +0 -38
- data/lib/tap/support/manifest.rb +0 -171
- data/lib/tap/support/minimap.rb +0 -90
- data/lib/tap/support/node.rb +0 -176
- data/lib/tap/support/parser.rb +0 -450
- data/lib/tap/support/schema.rb +0 -385
- data/lib/tap/support/shell_utils.rb +0 -67
- data/lib/tap/test.rb +0 -77
- data/lib/tap/test/assertions.rb +0 -38
- data/lib/tap/test/env_vars.rb +0 -29
- data/lib/tap/test/extensions.rb +0 -73
- data/lib/tap/test/file_test.rb +0 -362
- data/lib/tap/test/file_test_class.rb +0 -15
- data/lib/tap/test/regexp_escape.rb +0 -87
- data/lib/tap/test/script_test.rb +0 -46
- data/lib/tap/test/script_tester.rb +0 -115
- data/lib/tap/test/subset_test.rb +0 -260
- data/lib/tap/test/subset_test_class.rb +0 -99
- data/lib/tap/test/tap_test.rb +0 -109
- data/lib/tap/test/utils.rb +0 -231
@@ -1,5 +1,5 @@
|
|
1
1
|
module Tap
|
2
|
-
|
2
|
+
class Env
|
3
3
|
|
4
4
|
# StringExt provides two common string transformations, camelize and
|
5
5
|
# underscore. StringExt is automatically included in String.
|
@@ -56,5 +56,5 @@ module Tap
|
|
56
56
|
end
|
57
57
|
|
58
58
|
class String # :nodoc:
|
59
|
-
include Tap::
|
59
|
+
include Tap::Env::StringExt
|
60
60
|
end
|
data/lib/tap/exe.rb
CHANGED
@@ -1,106 +1,91 @@
|
|
1
1
|
require 'tap/env'
|
2
|
-
require 'tap/
|
3
|
-
require 'tap/
|
2
|
+
require 'tap/task'
|
3
|
+
require 'tap/schema'
|
4
4
|
|
5
5
|
module Tap
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
module Exe
|
7
|
+
|
8
|
+
# Adapted from Gem.find_home
|
9
|
+
# def self.user_home
|
10
|
+
# ['HOME', 'USERPROFILE'].each do |homekey|
|
11
|
+
# return ENV[homekey] if ENV[homekey]
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
|
15
|
+
# return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# begin
|
19
|
+
# File.expand_path("~")
|
20
|
+
# rescue
|
21
|
+
# File::ALT_SEPARATOR ? "C:/" : "/"
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
|
25
|
+
# Setup an execution environment.
|
26
|
+
def self.setup(options={}, argv=ARGV, env=ENV)
|
27
|
+
if argv[-1] == "-d-"
|
28
|
+
argv.pop
|
29
|
+
$DEBUG = true
|
15
30
|
end
|
16
31
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
exe.gems = :all if !File.exists?(Tap::Env::DEFAULT_CONFIG_FILE)
|
22
|
-
|
23
|
-
# add the default tap instance
|
24
|
-
exe.push Env.instantiate("#{File.dirname(__FILE__)}/../..")
|
25
|
-
exe
|
26
|
-
end
|
32
|
+
options = {
|
33
|
+
:dir => Dir.pwd,
|
34
|
+
:config_file => CONFIG_FILE
|
35
|
+
}.merge(options)
|
27
36
|
|
28
|
-
|
29
|
-
|
30
|
-
|
37
|
+
# load configurations
|
38
|
+
dir = options.delete(:dir)
|
39
|
+
config_file = options.delete(:config_file)
|
40
|
+
user_config_file = config_file ? File.join(dir, config_file) : nil
|
31
41
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
42
|
+
user = Env.load_config(user_config_file)
|
43
|
+
global = {}
|
44
|
+
env.each_pair do |key, value|
|
45
|
+
if key =~ /\ATAP_(.*)\z/
|
46
|
+
global[$1.downcase] = value
|
36
47
|
end
|
48
|
+
end
|
37
49
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
50
|
+
config = {
|
51
|
+
'root' => dir,
|
52
|
+
'gems' => :all
|
53
|
+
}.merge(global).merge(user).merge(options)
|
54
|
+
|
55
|
+
# keys must be symbolize as they are immediately
|
56
|
+
# used to initialize the Env configs
|
57
|
+
config = config.inject({}) do |options, (key, value)|
|
58
|
+
options[key.to_sym || key] = value
|
59
|
+
options
|
47
60
|
end
|
48
|
-
end
|
49
|
-
|
50
|
-
config :before, nil
|
51
|
-
config :after, nil
|
52
|
-
|
53
|
-
# Specify files to require when self is activated.
|
54
|
-
config :requires, [], &c.array_or_nil
|
55
|
-
|
56
|
-
# Specify files to load when self is activated.
|
57
|
-
config :loads, [], &c.array_or_nil
|
58
|
-
config :aliases, {}, &c.hash_or_nil
|
59
|
-
|
60
|
-
# The global home directory
|
61
|
-
GLOBAL_HOME = File.join(Exe.user_home, ".tap")
|
62
|
-
|
63
|
-
# The global config file path
|
64
|
-
GLOBAL_CONFIG_FILE = File.join(GLOBAL_HOME, "tap.yml")
|
65
|
-
|
66
|
-
def activate
|
67
|
-
if super
|
68
61
|
|
69
|
-
|
70
|
-
|
71
|
-
require path
|
72
|
-
end
|
62
|
+
# instantiate
|
63
|
+
exe = Env.new(config, :basename => config_file).extend(Exe)
|
73
64
|
|
74
|
-
|
75
|
-
|
76
|
-
load path
|
77
|
-
end
|
65
|
+
exe.register('command') do |env|
|
66
|
+
env.root.glob(:cmd, "**/*.rb")
|
78
67
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
when $DEBUG
|
84
|
-
puts err.message
|
85
|
-
puts
|
86
|
-
puts err.backtrace
|
87
|
-
else puts err.message
|
68
|
+
|
69
|
+
# add the tap env if necessary
|
70
|
+
unless exe.any? {|env| env.root.root == TAP_HOME }
|
71
|
+
exe.push Env.new(TAP_HOME, exe.context)
|
88
72
|
end
|
73
|
+
|
74
|
+
exe
|
89
75
|
end
|
90
76
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
case command
|
77
|
+
# The config file path
|
78
|
+
CONFIG_FILE = "tap.yml"
|
79
|
+
|
80
|
+
# The home directory for Tap
|
81
|
+
TAP_HOME = File.expand_path("#{File.dirname(__FILE__)}/../..")
|
82
|
+
|
83
|
+
def launch(argv=ARGV)
|
84
|
+
case command = argv.shift.to_s
|
100
85
|
when '', '--help'
|
101
86
|
yield
|
102
87
|
else
|
103
|
-
if path =
|
88
|
+
if path = seek('command', command)
|
104
89
|
load path # run the command, if it exists
|
105
90
|
else
|
106
91
|
puts "Unknown command: '#{command}'"
|
@@ -110,61 +95,64 @@ module Tap
|
|
110
95
|
end
|
111
96
|
|
112
97
|
def build(schema, app=Tap::App.instance)
|
113
|
-
schema.
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
task_class = case
|
118
|
-
when const then const.constantize
|
119
|
-
when block_given?
|
120
|
-
args.unshift(task)
|
121
|
-
yield(args)
|
122
|
-
else nil
|
98
|
+
schema.resolve! do |type, id, data|
|
99
|
+
klass = self[type][id]
|
100
|
+
if !klass && block_given?
|
101
|
+
klass = yield(type, id, data)
|
123
102
|
end
|
124
103
|
|
125
|
-
|
126
|
-
task_class.parse(args, app) do |help|
|
127
|
-
puts help
|
128
|
-
exit
|
129
|
-
end
|
104
|
+
klass || id
|
130
105
|
end
|
106
|
+
schema.validate!
|
107
|
+
schema.build(app)
|
131
108
|
end
|
132
109
|
|
133
|
-
def set_signals(app
|
110
|
+
def set_signals(app)
|
134
111
|
# info signal -- Note: some systems do
|
135
112
|
# not support the INFO signal
|
136
113
|
# (windows, fedora, at least)
|
137
114
|
signals = Signal.list.keys
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
142
|
-
end
|
115
|
+
Signal.trap("INFO") do
|
116
|
+
puts app.info
|
117
|
+
end if signals.include?("INFO")
|
143
118
|
|
144
119
|
# interuption signal
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
puts "unexpected response..."
|
164
|
-
end
|
120
|
+
Signal.trap("INT") do
|
121
|
+
puts " interrupted!"
|
122
|
+
# prompt for decision
|
123
|
+
while true
|
124
|
+
print "stop, terminate, exit, or resume? (s/t/e/r):"
|
125
|
+
case gets.strip
|
126
|
+
when /s(top)?/i
|
127
|
+
app.stop
|
128
|
+
break
|
129
|
+
when /t(erminate)?/i
|
130
|
+
app.terminate
|
131
|
+
break
|
132
|
+
when /e(xit)?/i
|
133
|
+
exit
|
134
|
+
when /r(esume)?/i
|
135
|
+
break
|
136
|
+
else
|
137
|
+
puts "unexpected response..."
|
165
138
|
end
|
166
139
|
end
|
140
|
+
end if signals.include?("INT")
|
141
|
+
end
|
142
|
+
|
143
|
+
def run(schemas, app=Tap::App.instance, &block)
|
144
|
+
schemas = [schemas] unless schemas.kind_of?(Array)
|
145
|
+
schemas.each do |schema|
|
146
|
+
build(schema, app, &block)
|
147
|
+
end
|
148
|
+
|
149
|
+
if app.queue.empty?
|
150
|
+
raise "no nodes specified"
|
167
151
|
end
|
152
|
+
|
153
|
+
set_signals(app)
|
154
|
+
app.run
|
168
155
|
end
|
156
|
+
|
169
157
|
end
|
170
158
|
end
|
data/lib/tap/join.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'tap/app'
|
2
|
+
require 'tap/support/intern'
|
3
|
+
|
4
|
+
module Tap
|
5
|
+
class App
|
6
|
+
# Generates a join between the inputs and outputs.
|
7
|
+
def join(inputs, outputs, config={}, klass=Join, &block)
|
8
|
+
klass.new(config, self).join(inputs, outputs, &block)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# :startdoc::join a simple, unsyncrhonized, multi-way join
|
13
|
+
#
|
14
|
+
# Join defines an unsynchronized, multi-way join where n inputs send their
|
15
|
+
# results to m outputs. Flags can augment how the results are passed, in
|
16
|
+
# particular for array results.
|
17
|
+
#
|
18
|
+
class Join
|
19
|
+
class << self
|
20
|
+
def inherited(child) # :nodoc:
|
21
|
+
unless child.instance_variable_defined?(:@source_file)
|
22
|
+
caller[0] =~ Lazydoc::CALLER_REGEXP
|
23
|
+
child.instance_variable_set(:@source_file, File.expand_path($1))
|
24
|
+
end
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
# Parses the argv into an array like [inputs, outputs, instance] where
|
29
|
+
# inputs and outputs implicitly define the inputs and output for the
|
30
|
+
# instance. By default parse parses an argh then calls instantiate,
|
31
|
+
# but there is no requirement that this occurs in subclasses.
|
32
|
+
def parse(argv=ARGV, app=Tap::App.instance)
|
33
|
+
parse!(argv.dup, app)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Same as parse, but removes arguments destructively.
|
37
|
+
def parse!(argv=ARGV, app=Tap::App.instance)
|
38
|
+
opts = ConfigParser.new
|
39
|
+
opts.separator "configurations:"
|
40
|
+
opts.add(configurations)
|
41
|
+
|
42
|
+
args = opts.parse!(argv, :add_defaults => false)
|
43
|
+
|
44
|
+
instantiate({
|
45
|
+
:config => opts.nested_config,
|
46
|
+
:args => args
|
47
|
+
}, app)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Instantiates an instance of self and return an array like [inputs,
|
51
|
+
# outputs, instance].
|
52
|
+
def instantiate(argh, app=Tap::App.instance)
|
53
|
+
new(argh[:config] || {}, app)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Instantiates a new join with the input arguments and overrides
|
57
|
+
# call with the block. The block will be called with the join
|
58
|
+
# instance and result.
|
59
|
+
#
|
60
|
+
# Simply instantiates a new join if no block is given.
|
61
|
+
def intern(config={}, app=Tap::App.instance, &block) # :yields: join, result
|
62
|
+
instance = new(config, app)
|
63
|
+
if block_given?
|
64
|
+
instance.extend Support::Intern(:call)
|
65
|
+
instance.call_block = block
|
66
|
+
end
|
67
|
+
instance
|
68
|
+
end
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def parse_array(obj) # :nodoc:
|
73
|
+
case obj
|
74
|
+
when nil then []
|
75
|
+
when Array then obj
|
76
|
+
else
|
77
|
+
obj.split(",").collect {|str| str.to_i }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
include Configurable
|
82
|
+
|
83
|
+
lazy_attr :desc, 'join'
|
84
|
+
|
85
|
+
# Causes the targets to be enqued rather than executed immediately.
|
86
|
+
config :enq, false, :short => 'q', &c.flag
|
87
|
+
|
88
|
+
# Splats the result to the outputs, allowing a many-to-one join
|
89
|
+
# from the perspective of the results.
|
90
|
+
#
|
91
|
+
# # results: [1,2,3]
|
92
|
+
# # outputs: call(*inputs)
|
93
|
+
# app.execute(output, *result)
|
94
|
+
#
|
95
|
+
config :splat, false, :short => 's', &c.flag
|
96
|
+
|
97
|
+
# Iterates the results to the outputs, allowing a many-to-one join
|
98
|
+
# from the perspective of the results. Non-array results are converted
|
99
|
+
# to arrays using to_ary:
|
100
|
+
#
|
101
|
+
# # results: [1,2,3]
|
102
|
+
# # outputs: call(input)
|
103
|
+
# result.to_ary.each {|r| app.execute(output, r) }
|
104
|
+
#
|
105
|
+
# Iterate may be combined with splat:
|
106
|
+
#
|
107
|
+
# # results: [[1,2],3]
|
108
|
+
# # outputs: call(*inputs)
|
109
|
+
# result.to_ary.each {|r| app.execute(output, *r) }
|
110
|
+
#
|
111
|
+
config :iterate, false, :short => 'i', &c.flag
|
112
|
+
|
113
|
+
# The App receiving self during enq
|
114
|
+
attr_accessor :app
|
115
|
+
|
116
|
+
# An array of input nodes, or nil if the join has not been set.
|
117
|
+
attr_reader :inputs
|
118
|
+
|
119
|
+
# An array of output nodes, or nil if the join has not been set.
|
120
|
+
attr_reader :outputs
|
121
|
+
|
122
|
+
# Initializes a new join with the specified configuration.
|
123
|
+
def initialize(config={}, app=Tap::App.instance)
|
124
|
+
@app = app
|
125
|
+
@inputs = nil
|
126
|
+
@outputs = nil
|
127
|
+
initialize_config(config)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Sets self as a join between the inputs and outputs.
|
131
|
+
def join(inputs, outputs)
|
132
|
+
@inputs.each do |input|
|
133
|
+
input.joins.delete(self)
|
134
|
+
end if @inputs
|
135
|
+
|
136
|
+
@inputs = inputs
|
137
|
+
|
138
|
+
inputs.each do |input|
|
139
|
+
input.joins << self
|
140
|
+
end if inputs
|
141
|
+
|
142
|
+
@outputs = outputs
|
143
|
+
self
|
144
|
+
end
|
145
|
+
|
146
|
+
# Executes the join logic for self, which by default passes the result to
|
147
|
+
# each output.
|
148
|
+
def call(result)
|
149
|
+
outputs.each do |output|
|
150
|
+
dispatch(output, result)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
protected
|
155
|
+
|
156
|
+
# Dispatches the results to the node.
|
157
|
+
def dispatch(node, result) # :nodoc:
|
158
|
+
mode = enq ? :enq : :execute
|
159
|
+
if iterate
|
160
|
+
result.to_ary.each {|r| execute(mode, node, r) }
|
161
|
+
else
|
162
|
+
execute(mode, node, result)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Executes the node with the input results.
|
167
|
+
def execute(mode, node, result) # :nodoc:
|
168
|
+
if splat
|
169
|
+
app.send(mode, node, *result)
|
170
|
+
else
|
171
|
+
app.send(mode, node, result)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|