tap 0.12.4 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/History +34 -0
  2. data/README +62 -41
  3. data/bin/tap +36 -40
  4. data/cmd/console.rb +14 -6
  5. data/cmd/manifest.rb +62 -58
  6. data/cmd/run.rb +49 -31
  7. data/doc/API +84 -0
  8. data/doc/Class Reference +83 -115
  9. data/doc/Examples/Command Line +36 -0
  10. data/doc/Examples/Workflow +40 -0
  11. data/lib/tap/app.rb +293 -214
  12. data/lib/tap/app/node.rb +43 -0
  13. data/lib/tap/app/queue.rb +77 -0
  14. data/lib/tap/app/stack.rb +16 -0
  15. data/lib/tap/app/state.rb +22 -0
  16. data/lib/tap/constants.rb +2 -2
  17. data/lib/tap/env.rb +400 -314
  18. data/lib/tap/env/constant.rb +227 -0
  19. data/lib/tap/env/gems.rb +63 -0
  20. data/lib/tap/env/manifest.rb +89 -0
  21. data/lib/tap/env/minimap.rb +292 -0
  22. data/lib/tap/{support → env}/string_ext.rb +2 -2
  23. data/lib/tap/exe.rb +113 -125
  24. data/lib/tap/join.rb +175 -0
  25. data/lib/tap/joins.rb +9 -0
  26. data/lib/tap/joins/switch.rb +44 -0
  27. data/lib/tap/joins/sync.rb +99 -0
  28. data/lib/tap/root.rb +100 -491
  29. data/lib/tap/root/utils.rb +220 -0
  30. data/lib/tap/{support → root}/versions.rb +31 -29
  31. data/lib/tap/schema.rb +248 -0
  32. data/lib/tap/schema/parser.rb +413 -0
  33. data/lib/tap/schema/utils.rb +82 -0
  34. data/lib/tap/support/intern.rb +19 -6
  35. data/lib/tap/support/templater.rb +8 -3
  36. data/lib/tap/task.rb +175 -171
  37. data/lib/tap/tasks/dump.rb +58 -0
  38. data/lib/tap/tasks/load.rb +62 -0
  39. metadata +30 -73
  40. data/cmd/destroy.rb +0 -27
  41. data/cmd/generate.rb +0 -27
  42. data/doc/Command Reference +0 -105
  43. data/doc/Syntax Reference +0 -234
  44. data/doc/Tutorial +0 -348
  45. data/lib/tap/dump.rb +0 -142
  46. data/lib/tap/file_task.rb +0 -384
  47. data/lib/tap/generator/arguments.rb +0 -13
  48. data/lib/tap/generator/base.rb +0 -176
  49. data/lib/tap/generator/destroy.rb +0 -60
  50. data/lib/tap/generator/generate.rb +0 -93
  51. data/lib/tap/generator/generators/command/command_generator.rb +0 -21
  52. data/lib/tap/generator/generators/command/templates/command.erb +0 -32
  53. data/lib/tap/generator/generators/config/config_generator.rb +0 -98
  54. data/lib/tap/generator/generators/generator/generator_generator.rb +0 -37
  55. data/lib/tap/generator/generators/generator/templates/task.erb +0 -27
  56. data/lib/tap/generator/generators/generator/templates/test.erb +0 -26
  57. data/lib/tap/generator/generators/root/root_generator.rb +0 -84
  58. data/lib/tap/generator/generators/root/templates/MIT-LICENSE +0 -22
  59. data/lib/tap/generator/generators/root/templates/README +0 -14
  60. data/lib/tap/generator/generators/root/templates/Rakefile +0 -84
  61. data/lib/tap/generator/generators/root/templates/Rapfile +0 -11
  62. data/lib/tap/generator/generators/root/templates/gemspec +0 -27
  63. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -3
  64. data/lib/tap/generator/generators/task/task_generator.rb +0 -25
  65. data/lib/tap/generator/generators/task/templates/task.erb +0 -14
  66. data/lib/tap/generator/generators/task/templates/test.erb +0 -19
  67. data/lib/tap/generator/manifest.rb +0 -20
  68. data/lib/tap/generator/preview.rb +0 -69
  69. data/lib/tap/load.rb +0 -64
  70. data/lib/tap/spec.rb +0 -41
  71. data/lib/tap/support/aggregator.rb +0 -65
  72. data/lib/tap/support/audit.rb +0 -333
  73. data/lib/tap/support/constant.rb +0 -143
  74. data/lib/tap/support/constant_manifest.rb +0 -126
  75. data/lib/tap/support/dependencies.rb +0 -54
  76. data/lib/tap/support/dependency.rb +0 -44
  77. data/lib/tap/support/executable.rb +0 -198
  78. data/lib/tap/support/executable_queue.rb +0 -125
  79. data/lib/tap/support/gems.rb +0 -43
  80. data/lib/tap/support/join.rb +0 -144
  81. data/lib/tap/support/joins.rb +0 -12
  82. data/lib/tap/support/joins/switch.rb +0 -27
  83. data/lib/tap/support/joins/sync_merge.rb +0 -38
  84. data/lib/tap/support/manifest.rb +0 -171
  85. data/lib/tap/support/minimap.rb +0 -90
  86. data/lib/tap/support/node.rb +0 -176
  87. data/lib/tap/support/parser.rb +0 -450
  88. data/lib/tap/support/schema.rb +0 -385
  89. data/lib/tap/support/shell_utils.rb +0 -67
  90. data/lib/tap/test.rb +0 -77
  91. data/lib/tap/test/assertions.rb +0 -38
  92. data/lib/tap/test/env_vars.rb +0 -29
  93. data/lib/tap/test/extensions.rb +0 -73
  94. data/lib/tap/test/file_test.rb +0 -362
  95. data/lib/tap/test/file_test_class.rb +0 -15
  96. data/lib/tap/test/regexp_escape.rb +0 -87
  97. data/lib/tap/test/script_test.rb +0 -46
  98. data/lib/tap/test/script_tester.rb +0 -115
  99. data/lib/tap/test/subset_test.rb +0 -260
  100. data/lib/tap/test/subset_test_class.rb +0 -99
  101. data/lib/tap/test/tap_test.rb +0 -109
  102. data/lib/tap/test/utils.rb +0 -231
@@ -1,5 +1,5 @@
1
1
  module Tap
2
- module Support
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::Support::StringExt
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/app'
3
- require 'tap/support/schema'
2
+ require 'tap/task'
3
+ require 'tap/schema'
4
4
 
5
5
  module Tap
6
- class Exe < Env
7
- class << self
8
- def setup(argv=ARGV)
9
- if argv[-1] == '-d-'
10
- argv.pop
11
- $DEBUG = true
12
- end
13
-
14
- instantiate
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
- def instantiate(path_or_root=Dir.pwd)
18
- exe = super
19
-
20
- # add all gems if no gems are specified (Note this is VERY SLOW ~ 1/3 the overhead for tap)
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
- def load_config(path)
29
- super(GLOBAL_CONFIG_FILE).merge super(path)
30
- end
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
- # Adapted from Gem.find_home
33
- def user_home
34
- ['HOME', 'USERPROFILE'].each do |homekey|
35
- return ENV[homekey] if ENV[homekey]
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
- if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
39
- return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
40
- end
41
-
42
- begin
43
- File.expand_path("~")
44
- rescue
45
- File::ALT_SEPARATOR ? "C:/" : "/"
46
- end
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
- # perform requires
70
- requires.each do |path|
71
- require path
72
- end
62
+ # instantiate
63
+ exe = Env.new(config, :basename => config_file).extend(Exe)
73
64
 
74
- # perform loads
75
- loads.each do |path|
76
- load path
77
- end
65
+ exe.register('command') do |env|
66
+ env.root.glob(:cmd, "**/*.rb")
78
67
  end
79
- end
80
-
81
- def handle_error(err)
82
- case
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
- def execute(argv=ARGV)
92
- command = argv.shift.to_s
93
-
94
- if aliases && aliases.has_key?(command)
95
- aliases[command].reverse_each {|arg| argv.unshift(arg)}
96
- command = argv.shift
97
- end
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 = commands.search(command)
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.build(app) do |args|
114
- task = args.shift
115
- const = tasks.search(task)
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
- task_class or raise ArgumentError, "unknown task: #{task}"
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=Tap::App.instance)
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
- if signals.include?("INFO")
139
- Signal.trap("INFO") do
140
- puts app.info
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
- if signals.include?("INT")
146
- Signal.trap("INT") do
147
- puts " interrupted!"
148
- # prompt for decision
149
- while true
150
- print "stop, terminate, exit, or resume? (s/t/e/r):"
151
- case gets.strip
152
- when /s(top)?/i
153
- app.stop
154
- break
155
- when /t(erminate)?/i
156
- app.terminate
157
- break
158
- when /e(xit)?/i
159
- exit
160
- when /r(esume)?/i
161
- break
162
- else
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