tap 0.19.0 → 1.3.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 +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.
|