tap 0.19.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +100 -45
- data/MIT-LICENSE +1 -1
- data/README +95 -51
- data/bin/tap +11 -57
- data/bin/tapexe +84 -0
- data/doc/API +91 -139
- data/doc/Configuration +93 -0
- data/doc/Examples/Command Line +10 -42
- data/doc/Examples/Tapfile +124 -0
- data/doc/Ruby to Ruby +87 -0
- data/doc/Workflow Syntax +185 -0
- data/lib/tap.rb +74 -5
- data/lib/tap/app.rb +217 -310
- data/lib/tap/app/api.rb +44 -23
- data/lib/tap/app/queue.rb +11 -12
- data/lib/tap/app/stack.rb +4 -4
- data/lib/tap/declarations.rb +200 -0
- data/lib/tap/declarations/context.rb +31 -0
- data/lib/tap/declarations/description.rb +33 -0
- data/lib/tap/env.rb +133 -779
- data/lib/tap/env/cache.rb +87 -0
- data/lib/tap/env/constant.rb +94 -39
- data/lib/tap/env/path.rb +71 -0
- data/lib/tap/join.rb +42 -78
- data/lib/tap/joins/gate.rb +85 -0
- data/lib/tap/joins/switch.rb +4 -2
- data/lib/tap/joins/sync.rb +3 -3
- data/lib/tap/middleware.rb +5 -5
- data/lib/tap/middlewares/debugger.rb +18 -58
- data/lib/tap/parser.rb +115 -183
- data/lib/tap/root.rb +162 -239
- data/lib/tap/signal.rb +72 -0
- data/lib/tap/signals.rb +20 -2
- data/lib/tap/signals/class_methods.rb +38 -43
- data/lib/tap/signals/configure.rb +19 -0
- data/lib/tap/signals/help.rb +5 -7
- data/lib/tap/signals/load.rb +49 -0
- data/lib/tap/signals/module_methods.rb +1 -0
- data/lib/tap/task.rb +46 -275
- data/lib/tap/tasks/dump.rb +21 -16
- data/lib/tap/tasks/list.rb +184 -0
- data/lib/tap/tasks/load.rb +4 -4
- data/lib/tap/tasks/prompt.rb +128 -0
- data/lib/tap/tasks/signal.rb +42 -0
- data/lib/tap/tasks/singleton.rb +35 -0
- data/lib/tap/tasks/stream.rb +64 -0
- data/lib/tap/utils.rb +83 -0
- data/lib/tap/version.rb +2 -2
- data/lib/tap/workflow.rb +124 -0
- data/tap.yml +0 -0
- metadata +59 -24
- data/cmd/console.rb +0 -43
- data/cmd/manifest.rb +0 -118
- data/cmd/run.rb +0 -145
- data/doc/Examples/Workflow +0 -40
- data/lib/tap/app/node.rb +0 -29
- data/lib/tap/env/context.rb +0 -61
- data/lib/tap/env/gems.rb +0 -63
- data/lib/tap/env/manifest.rb +0 -179
- data/lib/tap/env/minimap.rb +0 -308
- data/lib/tap/intern.rb +0 -50
- data/lib/tap/joins.rb +0 -9
- data/lib/tap/prompt.rb +0 -36
- data/lib/tap/root/utils.rb +0 -220
- data/lib/tap/root/versions.rb +0 -138
- data/lib/tap/signals/signal.rb +0 -68
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'tap/task'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
class Singleton < Tap::Task
|
6
|
+
class << self
|
7
|
+
def cache
|
8
|
+
@cache ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def new(*args)
|
12
|
+
obj = super
|
13
|
+
cache[obj.signature] ||= obj
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :cache
|
18
|
+
attr_reader :signature
|
19
|
+
|
20
|
+
def initialize(config={}, app=Tap::App.current)
|
21
|
+
@signature = [config.dup, app].freeze
|
22
|
+
super(config, app)
|
23
|
+
reset
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(input)
|
27
|
+
cache.has_key?(input) ? cache[input] : cache[input] = super
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset
|
31
|
+
@cache = {}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'tap/tasks/load'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
|
6
|
+
# Stream recurrently loads data from $stdin by requeing self until an
|
7
|
+
# end-of-file is reached. This behavior is useful for creating tasks
|
8
|
+
# that load a bit of data from an IO, send it into a workflow, and then
|
9
|
+
# repeat.
|
10
|
+
#
|
11
|
+
# The eof cutoff can be modified using complete? method. Streaming will
|
12
|
+
# stop when complete? returns true. For instance, this is a prompt task:
|
13
|
+
#
|
14
|
+
# class Prompt < Tap::Tasks::Stream
|
15
|
+
# config :exit_seq, "\n"
|
16
|
+
#
|
17
|
+
# def load(io)
|
18
|
+
# if io.eof?
|
19
|
+
# nil
|
20
|
+
# else
|
21
|
+
# io.readline
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# def complete?(io, line)
|
26
|
+
# line == nil || line == exit_seq
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
class Stream < Load
|
31
|
+
|
32
|
+
# Loads data from io. Process will open the input io object, load
|
33
|
+
# a result, then check to see if the loading is complete (using the
|
34
|
+
# complete? method). Unless loading is complete, process will enque
|
35
|
+
# io to self. Process will close io when loading is complete, provided
|
36
|
+
# use_close or file is specified.
|
37
|
+
def process(io=$stdin)
|
38
|
+
io = open(io)
|
39
|
+
result = load(io)
|
40
|
+
|
41
|
+
if complete?(io, result)
|
42
|
+
if use_close || file
|
43
|
+
close(io)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
reque(io)
|
47
|
+
end
|
48
|
+
|
49
|
+
result
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns true by default. Override in subclasses to allow recurrent
|
53
|
+
# loading (see process).
|
54
|
+
def complete?(io, last)
|
55
|
+
io.eof?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Reques self with io to the top of the queue.
|
59
|
+
def reque(io)
|
60
|
+
app.pq(self, [io])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/tap/utils.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
|
5
|
+
#
|
6
|
+
# == Windows
|
7
|
+
# MSDOS has command line length limits specific to the version of Windows being
|
8
|
+
# run (from http://www.ss64.com/nt/cmd.html):
|
9
|
+
#
|
10
|
+
# Windows NT:: 256 characters
|
11
|
+
# Windows 2000:: 2046 characters
|
12
|
+
# Windows XP:: 8190 characters
|
13
|
+
#
|
14
|
+
# Commands longer than these limits fail, usually with something like: 'the input
|
15
|
+
# line is too long'
|
16
|
+
module Utils
|
17
|
+
module_function
|
18
|
+
|
19
|
+
def shellsplit(line, comment="#")
|
20
|
+
words = []
|
21
|
+
field = ''
|
22
|
+
line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
|
23
|
+
|word, sq, dq, esc, garbage, sep|
|
24
|
+
raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage
|
25
|
+
break if word == comment
|
26
|
+
field << (word || sq || (dq || esc).gsub(/\\(?=.)/, ''))
|
27
|
+
if sep
|
28
|
+
words << field
|
29
|
+
field = ''
|
30
|
+
end
|
31
|
+
end
|
32
|
+
words
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sets the specified ENV variables and returns the *current* env.
|
36
|
+
# If replace is true, current ENV variables are replaced; otherwise
|
37
|
+
# the new env variables are simply added to the existing set.
|
38
|
+
def set_env(env={}, replace=false)
|
39
|
+
current_env = {}
|
40
|
+
ENV.each_pair do |key, value|
|
41
|
+
current_env[key] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
ENV.clear if replace
|
45
|
+
|
46
|
+
env.each_pair do |key, value|
|
47
|
+
if value.nil?
|
48
|
+
ENV.delete(key)
|
49
|
+
else
|
50
|
+
ENV[key] = value
|
51
|
+
end
|
52
|
+
end if env
|
53
|
+
|
54
|
+
current_env
|
55
|
+
end
|
56
|
+
|
57
|
+
# Sets the specified ENV variables for the duration of the block.
|
58
|
+
# If replace is true, current ENV variables are replaced; otherwise
|
59
|
+
# the new env variables are simply added to the existing set.
|
60
|
+
#
|
61
|
+
# Returns the block return.
|
62
|
+
def with_env(env={}, replace=false)
|
63
|
+
current_env = nil
|
64
|
+
begin
|
65
|
+
current_env = set_env(env, replace)
|
66
|
+
yield
|
67
|
+
ensure
|
68
|
+
if current_env
|
69
|
+
set_env(current_env, true)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def sh_escape(str)
|
75
|
+
str.to_s.gsub("'", "\\\\'").gsub(";", '\\;')
|
76
|
+
end
|
77
|
+
|
78
|
+
# Run the command with system and raise an error if it fails.
|
79
|
+
def sh(*cmd)
|
80
|
+
system(*cmd) or raise "Command failed with status (#{$?.exitstatus}): [#{cmd.join(' ')}]"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/tap/version.rb
CHANGED
data/lib/tap/workflow.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'tap/task'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
class Workflow < Task
|
5
|
+
class << self
|
6
|
+
protected
|
7
|
+
|
8
|
+
# Defines a task subclass with the specified configurations and process
|
9
|
+
# block. During initialization the subclass is instantiated and made
|
10
|
+
# accessible through the name method.
|
11
|
+
#
|
12
|
+
# Defined tasks may be configured during through config, or directly
|
13
|
+
# through the instance; in effect you get tasks with nested configs which
|
14
|
+
# can greatly facilitate workflows.
|
15
|
+
#
|
16
|
+
# class AddALetter < Tap::Task
|
17
|
+
# config :letter, 'a'
|
18
|
+
# def process(input); input << letter; end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# class AlphabetSoup < Tap::Task
|
22
|
+
# define :a, AddALetter, {:letter => 'a'}
|
23
|
+
# define :b, AddALetter, {:letter => 'b'}
|
24
|
+
# define :c, AddALetter, {:letter => 'c'}
|
25
|
+
#
|
26
|
+
# def process
|
27
|
+
# sequence(a, b, c)
|
28
|
+
# [a, c]
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# AlphabetSoup.new.process # => 'abc'
|
33
|
+
#
|
34
|
+
# i = AlphabetSoup.new(:a => {:letter => 'x'}, :b => {:letter => 'y'}, :c => {:letter => 'z'})
|
35
|
+
# i.process # => 'xyz'
|
36
|
+
#
|
37
|
+
# i.config[:a] = {:letter => 'p'}
|
38
|
+
# i.config[:b][:letter] = 'q'
|
39
|
+
# i.c.letter = 'r'
|
40
|
+
# i.process # => 'pqr'
|
41
|
+
#
|
42
|
+
# ==== Usage
|
43
|
+
#
|
44
|
+
# Define is basically the equivalent of:
|
45
|
+
#
|
46
|
+
# class Sample < Tap::Task
|
47
|
+
# Name = baseclass.subclass(config, &block)
|
48
|
+
#
|
49
|
+
# # accesses an instance of Name
|
50
|
+
# attr_reader :name
|
51
|
+
#
|
52
|
+
# # register name as a config, but with a
|
53
|
+
# # non-standard reader and writer
|
54
|
+
# config :name, {}, {:reader => :name_config, :writer => :name_config=}.merge(options)
|
55
|
+
#
|
56
|
+
# # reader for name.config
|
57
|
+
# def name_config; ...; end
|
58
|
+
#
|
59
|
+
# # reconfigures name with input
|
60
|
+
# def name_config=(input); ...; end
|
61
|
+
#
|
62
|
+
# def initialize(*args)
|
63
|
+
# super
|
64
|
+
# @name = Name.new(config[:name])
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# Note the following:
|
69
|
+
# * define will set a constant like name.camelize
|
70
|
+
# * the block defines the process method in the subclass
|
71
|
+
# * three methods are created by define: name, name_config, name_config=
|
72
|
+
#
|
73
|
+
def define(name, baseclass=Tap::Task, configs={}, options={}, &block)
|
74
|
+
# define the subclass
|
75
|
+
subclass = Class.new(baseclass)
|
76
|
+
configs.each_pair do |key, value|
|
77
|
+
subclass.send(:config, key, value)
|
78
|
+
end
|
79
|
+
|
80
|
+
if block_given?
|
81
|
+
# prevent lazydoc registration of the process method
|
82
|
+
subclass.registered_methods.delete(:process)
|
83
|
+
subclass.send(:define_method, :process, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
# register documentation
|
87
|
+
# TODO: register subclass in documentation
|
88
|
+
options[:desc] ||= Lazydoc.register_caller(Lazydoc::Trailer, 1)
|
89
|
+
|
90
|
+
# add the configuration
|
91
|
+
nest(name, subclass, {:const_name => name.to_s.camelize}.merge!(options))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
attr_reader :entry_point
|
96
|
+
attr_reader :exit_point
|
97
|
+
|
98
|
+
def initialize(config={}, app=Tap::App.current)
|
99
|
+
super
|
100
|
+
@entry_point, @exit_point = process
|
101
|
+
end
|
102
|
+
|
103
|
+
def call(input)
|
104
|
+
output = nil
|
105
|
+
|
106
|
+
if exit_point
|
107
|
+
joins = exit_point.joins
|
108
|
+
|
109
|
+
collector = lambda do |result|
|
110
|
+
output = result
|
111
|
+
joins.delete(collector)
|
112
|
+
end
|
113
|
+
|
114
|
+
joins << collector
|
115
|
+
end
|
116
|
+
|
117
|
+
if entry_point
|
118
|
+
app.exe(entry_point, input)
|
119
|
+
end
|
120
|
+
|
121
|
+
output
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/tap.yml
ADDED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 1.3.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Simon Chiang
|
@@ -9,19 +14,37 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-05-02 00:00:00 -06:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: configurable
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 7
|
30
|
+
- 0
|
31
|
+
version: 0.7.0
|
17
32
|
type: :runtime
|
18
|
-
|
19
|
-
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: tap-test
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
20
38
|
requirements:
|
21
39
|
- - ">="
|
22
40
|
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 6
|
44
|
+
- 0
|
23
45
|
version: 0.6.0
|
24
|
-
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
25
48
|
description:
|
26
49
|
email: simon.a.chiang@gmail.com
|
27
50
|
executables:
|
@@ -33,54 +56,64 @@ extra_rdoc_files:
|
|
33
56
|
- MIT-LICENSE
|
34
57
|
- History
|
35
58
|
- doc/API
|
59
|
+
- doc/Workflow Syntax
|
60
|
+
- doc/Ruby to Ruby
|
36
61
|
- doc/Examples/Command Line
|
37
|
-
- doc/Examples/
|
62
|
+
- doc/Examples/Tapfile
|
63
|
+
- doc/Configuration
|
38
64
|
files:
|
39
|
-
-
|
40
|
-
- cmd/manifest.rb
|
41
|
-
- cmd/run.rb
|
65
|
+
- bin/tapexe
|
42
66
|
- lib/tap.rb
|
43
67
|
- lib/tap/app.rb
|
44
68
|
- lib/tap/app/api.rb
|
45
|
-
- lib/tap/app/node.rb
|
46
69
|
- lib/tap/app/queue.rb
|
47
70
|
- lib/tap/app/stack.rb
|
48
71
|
- lib/tap/app/state.rb
|
72
|
+
- lib/tap/declarations.rb
|
73
|
+
- lib/tap/declarations/context.rb
|
74
|
+
- lib/tap/declarations/description.rb
|
49
75
|
- lib/tap/env.rb
|
76
|
+
- lib/tap/env/cache.rb
|
50
77
|
- lib/tap/env/constant.rb
|
51
|
-
- lib/tap/env/
|
52
|
-
- lib/tap/env/gems.rb
|
53
|
-
- lib/tap/env/manifest.rb
|
54
|
-
- lib/tap/env/minimap.rb
|
78
|
+
- lib/tap/env/path.rb
|
55
79
|
- lib/tap/env/string_ext.rb
|
56
|
-
- lib/tap/intern.rb
|
57
80
|
- lib/tap/join.rb
|
58
|
-
- lib/tap/joins.rb
|
81
|
+
- lib/tap/joins/gate.rb
|
59
82
|
- lib/tap/joins/switch.rb
|
60
83
|
- lib/tap/joins/sync.rb
|
61
84
|
- lib/tap/middleware.rb
|
62
85
|
- lib/tap/middlewares/debugger.rb
|
63
86
|
- lib/tap/parser.rb
|
64
|
-
- lib/tap/prompt.rb
|
65
87
|
- lib/tap/root.rb
|
66
|
-
- lib/tap/
|
67
|
-
- lib/tap/root/versions.rb
|
88
|
+
- lib/tap/signal.rb
|
68
89
|
- lib/tap/signals.rb
|
69
90
|
- lib/tap/signals/class_methods.rb
|
91
|
+
- lib/tap/signals/configure.rb
|
70
92
|
- lib/tap/signals/help.rb
|
93
|
+
- lib/tap/signals/load.rb
|
71
94
|
- lib/tap/signals/module_methods.rb
|
72
|
-
- lib/tap/signals/signal.rb
|
73
95
|
- lib/tap/task.rb
|
74
96
|
- lib/tap/tasks/dump.rb
|
75
97
|
- lib/tap/tasks/load.rb
|
98
|
+
- lib/tap/tasks/list.rb
|
99
|
+
- lib/tap/tasks/prompt.rb
|
100
|
+
- lib/tap/tasks/singleton.rb
|
101
|
+
- lib/tap/tasks/signal.rb
|
102
|
+
- lib/tap/tasks/stream.rb
|
76
103
|
- lib/tap/templater.rb
|
104
|
+
- lib/tap/utils.rb
|
77
105
|
- lib/tap/version.rb
|
106
|
+
- lib/tap/workflow.rb
|
107
|
+
- tap.yml
|
78
108
|
- README
|
79
109
|
- MIT-LICENSE
|
80
110
|
- History
|
81
111
|
- doc/API
|
112
|
+
- doc/Workflow Syntax
|
113
|
+
- doc/Ruby to Ruby
|
82
114
|
- doc/Examples/Command Line
|
83
|
-
- doc/Examples/
|
115
|
+
- doc/Examples/Tapfile
|
116
|
+
- doc/Configuration
|
84
117
|
has_rdoc: true
|
85
118
|
homepage: http://tap.rubyforge.org
|
86
119
|
licenses: []
|
@@ -99,18 +132,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
99
132
|
requirements:
|
100
133
|
- - ">="
|
101
134
|
- !ruby/object:Gem::Version
|
135
|
+
segments:
|
136
|
+
- 0
|
102
137
|
version: "0"
|
103
|
-
version:
|
104
138
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
139
|
requirements:
|
106
140
|
- - ">="
|
107
141
|
- !ruby/object:Gem::Version
|
142
|
+
segments:
|
143
|
+
- 0
|
108
144
|
version: "0"
|
109
|
-
version:
|
110
145
|
requirements: []
|
111
146
|
|
112
147
|
rubyforge_project: tap
|
113
|
-
rubygems_version: 1.3.
|
148
|
+
rubygems_version: 1.3.6
|
114
149
|
signing_key:
|
115
150
|
specification_version: 3
|
116
151
|
summary: A configurable, distributable workflow framework.
|