tap 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Basic Overview +151 -0
- data/Command Reference +99 -0
- data/History +24 -0
- data/MIT-LICENSE +1 -1
- data/README +29 -57
- data/Rakefile +30 -37
- data/Tutorial +243 -191
- data/bin/tap +66 -35
- data/lib/tap.rb +47 -29
- data/lib/tap/app.rb +700 -342
- data/lib/tap/{script → cmd}/console.rb +0 -0
- data/lib/tap/{script → cmd}/destroy.rb +0 -0
- data/lib/tap/{script → cmd}/generate.rb +0 -0
- data/lib/tap/cmd/run.rb +156 -0
- data/lib/tap/constants.rb +4 -0
- data/lib/tap/dump.rb +57 -0
- data/lib/tap/env.rb +316 -0
- data/lib/tap/file_task.rb +106 -109
- data/lib/tap/generator.rb +4 -1
- data/lib/tap/generator/generators/command/USAGE +6 -0
- data/lib/tap/generator/generators/command/command_generator.rb +17 -0
- data/lib/tap/generator/generators/{script/templates/script.erb → command/templates/command.erb} +10 -10
- data/lib/tap/generator/generators/config/USAGE +21 -0
- data/lib/tap/generator/generators/config/config_generator.rb +17 -7
- data/lib/tap/generator/generators/file_task/USAGE +3 -0
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -0
- data/lib/tap/generator/generators/file_task/templates/file.txt +2 -0
- data/lib/tap/generator/generators/file_task/templates/file.yml +3 -0
- data/lib/tap/generator/generators/file_task/templates/task.erb +26 -20
- data/lib/tap/generator/generators/file_task/templates/test.erb +20 -10
- data/lib/tap/generator/generators/generator/generator_generator.rb +1 -1
- data/lib/tap/generator/generators/generator/templates/generator.erb +21 -12
- data/lib/tap/generator/generators/root/templates/Rakefile +33 -24
- data/lib/tap/generator/generators/root/templates/tap.yml +28 -31
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +1 -0
- data/lib/tap/generator/generators/task/USAGE +3 -0
- data/lib/tap/generator/generators/task/task_generator.rb +18 -5
- data/lib/tap/generator/generators/task/templates/task.erb +7 -12
- data/lib/tap/generator/generators/task/templates/test.erb +10 -11
- data/lib/tap/generator/generators/workflow/templates/task.erb +1 -1
- data/lib/tap/generator/generators/workflow/templates/test.erb +1 -1
- 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 +172 -67
- data/lib/tap/script.rb +70 -336
- data/lib/tap/support/aggregator.rb +55 -0
- data/lib/tap/support/audit.rb +281 -280
- data/lib/tap/support/batchable.rb +59 -0
- data/lib/tap/support/class_configuration.rb +279 -0
- data/lib/tap/support/configurable.rb +92 -0
- data/lib/tap/support/configurable_methods.rb +296 -0
- data/lib/tap/support/executable.rb +98 -0
- data/lib/tap/support/executable_queue.rb +82 -0
- data/lib/tap/support/logger.rb +9 -15
- data/lib/tap/support/rake.rb +43 -54
- data/lib/tap/support/run_error.rb +32 -13
- data/lib/tap/support/shell_utils.rb +47 -0
- data/lib/tap/support/tdoc.rb +9 -8
- data/lib/tap/support/tdoc/config_attr.rb +40 -16
- data/lib/tap/support/validation.rb +77 -0
- data/lib/tap/support/versions.rb +36 -36
- data/lib/tap/task.rb +276 -482
- data/lib/tap/test.rb +20 -261
- data/lib/tap/test/env_vars.rb +7 -5
- data/lib/tap/test/file_methods.rb +126 -121
- data/lib/tap/test/subset_methods.rb +86 -45
- data/lib/tap/test/tap_methods.rb +271 -0
- data/lib/tap/workflow.rb +174 -46
- data/test/app/config/another/task.yml +1 -0
- data/test/app/config/erb.yml +2 -1
- data/test/app/config/some/task.yml +1 -0
- data/test/app/config/template.yml +2 -6
- data/test/app_test.rb +1241 -1008
- data/test/env/test_configure/recurse_a.yml +2 -0
- data/test/env/test_configure/recurse_b.yml +2 -0
- data/test/env/test_configure/tap.yml +23 -0
- data/test/env/test_load_env_config/dir/tap.yml +3 -0
- data/test/env/test_load_env_config/recurse_a.yml +2 -0
- data/test/env/test_load_env_config/recurse_b.yml +2 -0
- data/test/env/test_load_env_config/tap.yml +3 -0
- data/test/env_test.rb +198 -0
- data/test/file_task_test.rb +70 -53
- data/{lib/tap/generator/generators/package/USAGE → test/root/file.txt} +0 -0
- data/test/root_test.rb +621 -454
- data/test/script_test.rb +38 -174
- data/test/support/aggregator_test.rb +99 -0
- data/test/support/audit_test.rb +409 -416
- data/test/support/batchable_test.rb +74 -0
- data/test/support/{task_configuration_test.rb → class_configuration_test.rb} +106 -47
- data/test/{task/config/overriding.yml → support/configurable/config/configured.yml} +0 -0
- data/test/support/configurable_test.rb +295 -0
- data/test/support/executable_queue_test.rb +103 -0
- data/test/support/executable_test.rb +38 -0
- data/test/support/logger_test.rb +17 -17
- data/test/support/rake_test.rb +4 -2
- data/test/support/shell_utils_test.rb +24 -0
- data/test/support/tdoc_test.rb +265 -258
- data/test/support/validation_test.rb +54 -0
- data/test/support/versions_test.rb +38 -38
- data/test/tap_test_helper.rb +19 -5
- data/test/tap_test_suite.rb +5 -2
- data/test/task_base_test.rb +13 -104
- data/test/task_syntax_test.rb +300 -0
- data/test/task_test.rb +258 -381
- data/test/test/env_vars_test.rb +40 -40
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/expected/one.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/expected/two.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/input/one.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/input/two.txt +0 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_can_have_no_expected_files_if_specified}/input/one.txt +0 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_can_have_no_expected_files_if_specified}/input/two.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +1 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_fails_for_different_content}/expected/two.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +1 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_fails_for_missing_expected_file}/expected/one.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +1 -0
- data/test/test/file_methods_doc/test_sub/expected/one.txt +1 -0
- data/test/test/file_methods_doc/test_sub/expected/two.txt +1 -0
- data/test/test/file_methods_doc/test_sub/input/one.txt +1 -0
- data/test/test/file_methods_doc/test_sub/input/two.txt +1 -0
- data/test/test/file_methods_doc_test.rb +29 -0
- data/test/test/file_methods_test.rb +214 -143
- data/test/test/subset_methods_test.rb +111 -115
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/expected/task/name/a.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/expected/task/name/b.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/input/a.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/input/b.txt +0 -0
- data/test/test/tap_methods_test.rb +399 -0
- data/test/workflow_test.rb +101 -91
- metadata +86 -70
- data/lib/tap/generator/generators/package/package_generator.rb +0 -38
- data/lib/tap/generator/generators/package/templates/package.erb +0 -186
- data/lib/tap/generator/generators/script/USAGE +0 -0
- data/lib/tap/generator/generators/script/script_generator.rb +0 -17
- data/lib/tap/script/run.rb +0 -154
- data/lib/tap/support/batch_queue.rb +0 -162
- data/lib/tap/support/combinator.rb +0 -114
- data/lib/tap/support/task_configuration.rb +0 -169
- data/lib/tap/support/template.rb +0 -81
- data/lib/tap/support/templater.rb +0 -155
- data/lib/tap/version.rb +0 -4
- data/test/app/config/addition_template.yml +0 -6
- data/test/app_class_test.rb +0 -33
- data/test/check/binding_eval.rb +0 -23
- data/test/check/define_method_check.rb +0 -22
- data/test/check/dependencies_check.rb +0 -175
- data/test/check/inheritance_check.rb +0 -22
- data/test/support/batch_queue_test.rb +0 -320
- data/test/support/combinator_test.rb +0 -249
- data/test/support/template_test.rb +0 -122
- data/test/support/templater/erb.txt +0 -2
- data/test/support/templater/erb.yml +0 -2
- data/test/support/templater/somefile.txt +0 -2
- data/test/support/templater_test.rb +0 -192
- data/test/task/config/template.yml +0 -4
- data/test/task_class_test.rb +0 -170
- data/test/task_execute_test.rb +0 -262
- data/test/test/file_methods/test_assert_expected/expected/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/expected/folder/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/input/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/input/folder/file.txt +0 -1
- data/test/test/file_methods/test_assert_files_exist/input/input_1.txt +0 -0
- data/test/test/file_methods/test_assert_files_exist/input/input_2.txt +0 -0
- data/test/test/file_methods/test_file_compare/expected/output_1.txt +0 -3
- data/test/test/file_methods/test_file_compare/expected/output_2.txt +0 -1
- data/test/test/file_methods/test_file_compare/input/input_1.txt +0 -3
- data/test/test/file_methods/test_file_compare/input/input_2.txt +0 -3
- data/test/test/file_methods/test_infer_glob/expected/file.yml +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file_1.txt +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file_2.txt +0 -0
- data/test/test/file_methods/test_yml_compare/expected/output_1.yml +0 -6
- data/test/test/file_methods/test_yml_compare/expected/output_2.yml +0 -6
- data/test/test/file_methods/test_yml_compare/input/input_1.yml +0 -4
- data/test/test/file_methods/test_yml_compare/input/input_2.yml +0 -4
- data/test/test_test.rb +0 -373
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'shellwords'
|
2
|
-
require 'pp'
|
3
|
-
|
4
|
-
module Tap::Generator::Generators
|
5
|
-
class PackageGenerator < Rails::Generator::NamedBase # :nodoc:
|
6
|
-
include Shellwords
|
7
|
-
|
8
|
-
attr_accessor :config, :argv, :package_file
|
9
|
-
|
10
|
-
def initialize(*args)
|
11
|
-
super(*args)
|
12
|
-
@destination_root = Tap::App.instance[:root]
|
13
|
-
@app = Tap::App.instance
|
14
|
-
end
|
15
|
-
|
16
|
-
def manifest
|
17
|
-
record do |m|
|
18
|
-
# read the config for the current root
|
19
|
-
@config = File.read Tap::Script.config_filepath(@app[:root])
|
20
|
-
|
21
|
-
# at this point ARGV still includes the package name,
|
22
|
-
# ie the commands should be argument 1
|
23
|
-
# Note: it's important to setup argv this way, from a single argument,
|
24
|
-
# so that options can be included in the packaged arguments:
|
25
|
-
# generate package raw_to_mgf "run --debug some/task"
|
26
|
-
# vs
|
27
|
-
# generate package raw_to_mgf run --debug some/task
|
28
|
-
# where '--debug' is applied to generate rather than run
|
29
|
-
@argv = PP.singleline_pp(shellwords(ARGV[1].to_s), '')
|
30
|
-
|
31
|
-
@package_file = class_path.empty? ? file_name : File.join(class_path, file_name)
|
32
|
-
filepath = "pkg/#{@package_file}.rb"
|
33
|
-
m.directory File.dirname(filepath)
|
34
|
-
m.template "package.erb", filepath
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,186 +0,0 @@
|
|
1
|
-
#############################################
|
2
|
-
# HOW TO PACKAGE YOUR SCRIPT:
|
3
|
-
# 1. Attend to the parts marked TODO
|
4
|
-
# 2. Run rubyscript2exe as described below:
|
5
|
-
#
|
6
|
-
# % rubyscript2exe <%= package_file %>.rb
|
7
|
-
#
|
8
|
-
# NOTES:
|
9
|
-
# The 'rubyscript2exe' gem is required for packaging -- install using:
|
10
|
-
# % gem install rubyscript2exe
|
11
|
-
#
|
12
|
-
# The inputs you used when creating this script will supplied before
|
13
|
-
# the inputs you provide to the executable. Hence if you used:
|
14
|
-
# % tap generate package "run --quiet some/task"
|
15
|
-
#
|
16
|
-
# These will be equivalent commands:
|
17
|
-
# % tap run --quiet some/task INPUT1 INPUT2
|
18
|
-
# % <%= package_file %>.exe INPUT1 INPUT2
|
19
|
-
#
|
20
|
-
# Feel free to adjust this script to behave as you like -- whatever this
|
21
|
-
# script does will be packaged into the executable.
|
22
|
-
#
|
23
|
-
#############################################
|
24
|
-
#
|
25
|
-
# = Prompt Instructions
|
26
|
-
# Enter an empty line to continue.
|
27
|
-
|
28
|
-
require "tap"
|
29
|
-
require "tap/script"
|
30
|
-
|
31
|
-
# = TODO: add script requires
|
32
|
-
#
|
33
|
-
# Only what this script does will be packaged into the executable.
|
34
|
-
# You MUST specify tasks and other files that are not loaded during
|
35
|
-
# the 'rubyscript2exe' execution of this script. Usually this means
|
36
|
-
# require-ing any tasks that may get used.
|
37
|
-
#
|
38
|
-
# require 'some/task'
|
39
|
-
|
40
|
-
app = Tap::App.instance
|
41
|
-
script = Tap::Script.instance
|
42
|
-
|
43
|
-
# = TODO: check arguments
|
44
|
-
# Make sure these are what you want later in this script they're unshifted
|
45
|
-
# onto ARGV, ie they'll be hard-coded into the executable.
|
46
|
-
script_argv = <%= argv %>
|
47
|
-
|
48
|
-
# = TODO: check configurations
|
49
|
-
#
|
50
|
-
# This configures the packaged app the same as the current tap.yml
|
51
|
-
# Check that the configurations look the way you want them to, or
|
52
|
-
# set the executable to load it's own configurations, as by:
|
53
|
-
# config_file = Tap::Script.config_filepath(Dir.pwd)
|
54
|
-
# config = Tap::Script.read_config(config_file)
|
55
|
-
#
|
56
|
-
app_config = %Q{<%= config.gsub(/^\s*$|^#.*$/m, '') %>}
|
57
|
-
|
58
|
-
# = TODO: decide if you want to prompt when you get no inputs
|
59
|
-
# This can be handy if you want to be able to interact with the
|
60
|
-
# packaged script.
|
61
|
-
if ARGV.select {|arg| arg !~ /^-|^--/ }.empty?
|
62
|
-
puts Tap::Script.usage(__FILE__, "Prompt Instructions", :keep_headers => false)
|
63
|
-
|
64
|
-
while true
|
65
|
-
print "glob: "
|
66
|
-
line = gets.strip
|
67
|
-
break if line.empty?
|
68
|
-
|
69
|
-
line = line[1..-2] if line =~ /^".*"$/
|
70
|
-
ARGV << line
|
71
|
-
end
|
72
|
-
puts
|
73
|
-
end
|
74
|
-
|
75
|
-
# nice give the user a second before you exit, especially if you have a prompt
|
76
|
-
def exit(*args)
|
77
|
-
puts
|
78
|
-
puts "Hit enter to exit."
|
79
|
-
ARGV.clear
|
80
|
-
gets
|
81
|
-
super
|
82
|
-
end
|
83
|
-
|
84
|
-
#############################################
|
85
|
-
# These sections generally needs far less customization
|
86
|
-
#############################################
|
87
|
-
|
88
|
-
#
|
89
|
-
# configure the app
|
90
|
-
#
|
91
|
-
begin
|
92
|
-
config = YAML.load(app_config)
|
93
|
-
config = {} if config == false
|
94
|
-
script.configure_app(config)
|
95
|
-
rescue(Exception)
|
96
|
-
# catch errors and exit gracefully
|
97
|
-
# (errors usu from gem loading errors)
|
98
|
-
puts "Configuration error: #{$!.message}"
|
99
|
-
exit(1)
|
100
|
-
end
|
101
|
-
|
102
|
-
#
|
103
|
-
# add modifications for rubyscript2exe
|
104
|
-
#
|
105
|
-
require "rubyscript2exe"
|
106
|
-
if RUBYSCRIPT2EXE.is_compiling?
|
107
|
-
module Kernel
|
108
|
-
def exit_with_load_path_rewriting
|
109
|
-
[$", REQUIRE2LIB::LOADED].each do |loaded_files|
|
110
|
-
loaded_files.collect! do |load_path|
|
111
|
-
if File.expand_path(load_path) == load_path
|
112
|
-
$:.each do |root|
|
113
|
-
relative_load_path = Tap::Root.relative_filepath(File.expand_path(root), load_path, false)
|
114
|
-
unless relative_load_path == load_path
|
115
|
-
load_path = relative_load_path
|
116
|
-
break
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
load_path
|
122
|
-
end
|
123
|
-
end
|
124
|
-
exit_without_load_path_rewriting
|
125
|
-
end
|
126
|
-
|
127
|
-
alias exit_without_load_path_rewriting exit
|
128
|
-
alias exit exit_with_load_path_rewriting
|
129
|
-
end
|
130
|
-
|
131
|
-
else
|
132
|
-
script.config.script_paths.unshift RUBYSCRIPT2EXE.appdir("../lib/script")
|
133
|
-
Dependencies.load_paths.unshift RUBYSCRIPT2EXE.appdir("../lib")
|
134
|
-
Dir.chdir(RUBYSCRIPT2EXE.exedir)
|
135
|
-
end
|
136
|
-
|
137
|
-
#
|
138
|
-
# run before script
|
139
|
-
#
|
140
|
-
begin
|
141
|
-
eval(script.config.before.to_s)
|
142
|
-
rescue
|
143
|
-
puts "Error in before script."
|
144
|
-
if app.options.debug
|
145
|
-
raise
|
146
|
-
else
|
147
|
-
puts $!.message
|
148
|
-
exit(1)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
# This is where the inputs used to create this script are unshifted
|
153
|
-
# onto ARGV, ahead of the user inputs.
|
154
|
-
script_argv.reverse_each {|arg| ARGV.unshift arg}
|
155
|
-
|
156
|
-
#
|
157
|
-
# run the script -- note that the first argument
|
158
|
-
# to ARGV is the script that gets run.
|
159
|
-
#
|
160
|
-
begin
|
161
|
-
load script.config.scripts[ARGV.shift]
|
162
|
-
rescue
|
163
|
-
if app.options.debug
|
164
|
-
raise
|
165
|
-
else
|
166
|
-
puts "Error."
|
167
|
-
puts $!.message
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
#
|
172
|
-
# run after script
|
173
|
-
#
|
174
|
-
begin
|
175
|
-
eval(script.config.after.to_s)
|
176
|
-
rescue
|
177
|
-
puts "Error in after script."
|
178
|
-
if app.options.debug
|
179
|
-
raise
|
180
|
-
else
|
181
|
-
puts $!.message
|
182
|
-
exit(1)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
exit(0)
|
File without changes
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Tap::Generator::Generators
|
2
|
-
class ScriptGenerator < Rails::Generator::NamedBase # :nodoc:
|
3
|
-
def initialize(*args)
|
4
|
-
super(*args)
|
5
|
-
@destination_root = Tap::App.instance[:root]
|
6
|
-
@app = Tap::App.instance
|
7
|
-
end
|
8
|
-
|
9
|
-
def manifest
|
10
|
-
record do |m|
|
11
|
-
script_path = @app.relative_filepath(:root, @app[:script])
|
12
|
-
m.directory class_path.empty? ? script_path : File.join(script_path, class_path)
|
13
|
-
m.template "script.erb", File.join(script_path, class_name.underscore + ".rb")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/tap/script/run.rb
DELETED
@@ -1,154 +0,0 @@
|
|
1
|
-
# = Usage
|
2
|
-
# tap run {options} -- {task options} task INPUTS...
|
3
|
-
#
|
4
|
-
# examples:
|
5
|
-
# tap run --help Prints this help
|
6
|
-
# tap run -- task --help Prints help for task
|
7
|
-
#
|
8
|
-
|
9
|
-
require 'tap/script'
|
10
|
-
|
11
|
-
app = Tap::App.instance
|
12
|
-
script = Tap::Script.instance
|
13
|
-
|
14
|
-
#
|
15
|
-
# handle options
|
16
|
-
#
|
17
|
-
|
18
|
-
opts = [
|
19
|
-
['--help', '-h', GetoptLong::NO_ARGUMENT, "Print this help"],
|
20
|
-
['--debug', '-d', GetoptLong::NO_ARGUMENT, "Trace execution and debug"],
|
21
|
-
['--force', '-f', GetoptLong::NO_ARGUMENT, "Force execution at checkpoints"],
|
22
|
-
['--quiet', '-q', GetoptLong::NO_ARGUMENT, "Suppress logging"]]
|
23
|
-
|
24
|
-
Tap::Script.handle_options(*opts) do |opt, value|
|
25
|
-
case opt
|
26
|
-
when '--help'
|
27
|
-
puts Tap::Script.usage(__FILE__, "Usage", :keep_headers => false)
|
28
|
-
puts
|
29
|
-
puts Tap::Script.usage_options(opts)
|
30
|
-
exit
|
31
|
-
|
32
|
-
when '--quiet', '--force', '--debug'
|
33
|
-
# simply track these have been set
|
34
|
-
opt =~ /^-+(\w+)/
|
35
|
-
app.options.send("#{$1}=", true)
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
#
|
41
|
-
# handle options for each specified task
|
42
|
-
#
|
43
|
-
argv = Tap::Script.split_arguments(ARGV)
|
44
|
-
if argv.empty?
|
45
|
-
puts "no task specified"
|
46
|
-
exit
|
47
|
-
end
|
48
|
-
|
49
|
-
argv.each do |args|
|
50
|
-
ARGV.clear
|
51
|
-
ARGV.concat(args)
|
52
|
-
|
53
|
-
td = Tap::Script.next_arg(ARGV)
|
54
|
-
if td == 'rake'
|
55
|
-
# interpret 'rake' tds as specifications for
|
56
|
-
# rake tasks and/or inputs:
|
57
|
-
# tap run rake -T
|
58
|
-
# tap run rake test
|
59
|
-
#
|
60
|
-
app.extend Tap::Support::Rake
|
61
|
-
|
62
|
-
rake = Rake.application
|
63
|
-
options = rake.options
|
64
|
-
|
65
|
-
# merge options down from app
|
66
|
-
app.options.marshal_dump.each_pair do |key, value|
|
67
|
-
options.send("#{key}=", value)
|
68
|
-
end
|
69
|
-
options.silent = true
|
70
|
-
|
71
|
-
# now follow the same protocol as
|
72
|
-
# in run, handling options
|
73
|
-
rake.init
|
74
|
-
rake.load_rakefile
|
75
|
-
|
76
|
-
# takes the place of rake.top_level
|
77
|
-
if options.show_tasks
|
78
|
-
rake.display_tasks_and_comments
|
79
|
-
exit
|
80
|
-
elsif options.show_prereqs
|
81
|
-
rake.display_prerequisites
|
82
|
-
exit
|
83
|
-
else
|
84
|
-
rake.top_level_tasks.each do |task_name|
|
85
|
-
task = app.task(task_name)
|
86
|
-
app.queue.enq(task)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
next
|
91
|
-
end
|
92
|
-
|
93
|
-
# lookup the task
|
94
|
-
begin
|
95
|
-
task = (td.nil? ? nil : app.task(td))
|
96
|
-
rescue(Tap::App::LookupError)
|
97
|
-
end
|
98
|
-
|
99
|
-
# unless a Tap::Task was found, treat the
|
100
|
-
# args as a specification for Rake.
|
101
|
-
unless task.kind_of?(Tap::Task)
|
102
|
-
args.unshift(td) unless task == nil
|
103
|
-
args.unshift('rake')
|
104
|
-
redo
|
105
|
-
end
|
106
|
-
|
107
|
-
# handle task configuration options
|
108
|
-
Tap::Script.handle_task_options(task)
|
109
|
-
|
110
|
-
# queue the task with the remaining inputs
|
111
|
-
args = ARGV.collect! {|arg| Tap::App.parse_yaml(arg) }
|
112
|
-
app.queue.enq(task, *args)
|
113
|
-
end
|
114
|
-
ARGV.clear
|
115
|
-
|
116
|
-
#
|
117
|
-
# set signals and run!
|
118
|
-
#
|
119
|
-
|
120
|
-
# info signal -- Note: windows does
|
121
|
-
# not support the INFO signal
|
122
|
-
if RUBY_PLATFORM.index('mswin').nil?
|
123
|
-
Signal.trap("INFO") do
|
124
|
-
puts app.info
|
125
|
-
end
|
126
|
-
|
127
|
-
puts "ctl-i prints information"
|
128
|
-
end
|
129
|
-
|
130
|
-
# interuption signal
|
131
|
-
Signal.trap("INT") do
|
132
|
-
puts " interrupted!"
|
133
|
-
# prompt for decision
|
134
|
-
while true
|
135
|
-
print "stop, terminate, or resume? (s/t/r):"
|
136
|
-
case gets.strip
|
137
|
-
when /s(top)?/i
|
138
|
-
app.stop
|
139
|
-
break
|
140
|
-
when /t(erminate)?/i
|
141
|
-
app.terminate
|
142
|
-
break
|
143
|
-
when /r(esume)?/i
|
144
|
-
break
|
145
|
-
else
|
146
|
-
puts "unexpected response..."
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
puts "ctl-c interupts execution"
|
152
|
-
puts "beginning run..."
|
153
|
-
|
154
|
-
app.run
|
@@ -1,162 +0,0 @@
|
|
1
|
-
module Tap
|
2
|
-
module Support
|
3
|
-
|
4
|
-
# BatchQueue allows thread-safe enqueing and dequeing of tasks and inputs for
|
5
|
-
# execution. Until the task is dequeued, additional enqueuements will aggregate
|
6
|
-
# the inputs into a batch. The queue order is determined solely by the task;
|
7
|
-
# all accumulated inputs are dequeued at once.
|
8
|
-
#
|
9
|
-
# # given tasks t1 and t2:
|
10
|
-
# q = BatchQueue.new
|
11
|
-
# q.enq t1, 1
|
12
|
-
# q.enq t2, :a,:b,:c
|
13
|
-
# q.enq t1, 2,3
|
14
|
-
#
|
15
|
-
# q.deq # => [t1, [1,2,3]]
|
16
|
-
# q.deq # => [t2, [:a,:b,:c]]
|
17
|
-
# q.deq # => nil
|
18
|
-
#
|
19
|
-
# All BatchQueue methods are monitored such that they may only be accessed
|
20
|
-
# by one thread at a time, in order to ensure that transactions are atomic.
|
21
|
-
class BatchQueue
|
22
|
-
include MonitorMixin
|
23
|
-
|
24
|
-
# creates a new BatchQueue
|
25
|
-
def initialize
|
26
|
-
super
|
27
|
-
self.clear
|
28
|
-
end
|
29
|
-
|
30
|
-
# Clears the BatchQueue of all tasks and inputs.
|
31
|
-
def clear
|
32
|
-
synchronize do
|
33
|
-
self.inputs = {}
|
34
|
-
self.tasks = []
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Returns the number of enqueued tasks (same as length)
|
39
|
-
def size
|
40
|
-
tasks.length
|
41
|
-
end
|
42
|
-
|
43
|
-
# Returns the number of enqueued tasks (same as size)
|
44
|
-
def length
|
45
|
-
size
|
46
|
-
end
|
47
|
-
|
48
|
-
# True if no tasks are enqueued
|
49
|
-
def empty?
|
50
|
-
tasks.empty?
|
51
|
-
end
|
52
|
-
|
53
|
-
# Enqueues the inputs to the task. If the task has not already been added to the
|
54
|
-
# queue, then the task will be pushed onto the queue and the inputs registered.
|
55
|
-
# Otherwise, the inputs will be added to the registered inputs; the task will
|
56
|
-
# not be added to the queue twice. If the task is batched, then each task in the
|
57
|
-
# batch will be enqueued in order, with the same inputs (Audit inputs will be forked
|
58
|
-
# for each task).
|
59
|
-
def enq(task, *inputs)
|
60
|
-
synchronize do
|
61
|
-
batch = task.batch
|
62
|
-
batch.each do |t|
|
63
|
-
tasks << t unless tasks.include?(t)
|
64
|
-
|
65
|
-
inputs = inputs.collect do |result|
|
66
|
-
result.kind_of?(Support::Audit) ? result._fork : result
|
67
|
-
end if batch.length > 1
|
68
|
-
|
69
|
-
self.inputs[t] = [] unless self.inputs[t]
|
70
|
-
self.inputs[t].concat(inputs)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Enqueues the task and input, then prioritizes the task to the front of the queue.
|
76
|
-
def priority_enq(task, *inputs)
|
77
|
-
synchronize do
|
78
|
-
enq(task, *inputs)
|
79
|
-
prioritize(task)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Moves the task to the front of the queue. Does not queue a task if the task is not
|
84
|
-
# already in the queue. If the task is batched, then each task in the batch will be
|
85
|
-
# prioritized in order.
|
86
|
-
def prioritize(task)
|
87
|
-
synchronize do
|
88
|
-
task.batch.reverse_each do |t|
|
89
|
-
tasks.unshift(t) if tasks.delete(t)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# Moves the task to the back of the queue. Does not queue a task if the task is not
|
95
|
-
# already in the queue. If the task is batched, then each task in the batch will be
|
96
|
-
# marginalized in order.
|
97
|
-
def marginalize(task)
|
98
|
-
synchronize do
|
99
|
-
task.batch.each do |t|
|
100
|
-
tasks.push(t) if tasks.delete(t)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# Returns true if the task is executable with the currently registered inputs
|
106
|
-
# (as determined by task.executable?).
|
107
|
-
def executable?(task)
|
108
|
-
synchronize do
|
109
|
-
task.executable?(inputs[task])
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Dequeues the next executable task, or the specified task (even if it is not
|
114
|
-
# executable). The task and the current inputs for the task are returned in
|
115
|
-
# an array like: [task, inputs]. Returns nil if the task is not in the queue.
|
116
|
-
def deq(task=nil)
|
117
|
-
synchronize do
|
118
|
-
task = peek if task.nil?
|
119
|
-
|
120
|
-
if tasks.include?(task)
|
121
|
-
[tasks.delete(task), inputs.delete(task)]
|
122
|
-
else
|
123
|
-
nil
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
# Returns the next executable task, or nil if no queued tasks are executable.
|
129
|
-
# The task is not dequeued.
|
130
|
-
def peek
|
131
|
-
synchronize do
|
132
|
-
tasks.each do |task|
|
133
|
-
next unless executable?(task)
|
134
|
-
return task
|
135
|
-
end
|
136
|
-
nil
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# Returns the number of executable tasks in the queue.
|
141
|
-
def num_executable
|
142
|
-
synchronize do
|
143
|
-
tasks.inject(0) do |count, task|
|
144
|
-
executable?(task) ? count + 1 : count
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
# Returns the number of non-executable tasks in the queue.
|
150
|
-
def num_not_executable
|
151
|
-
synchronize do
|
152
|
-
size - num_executable
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
protected
|
157
|
-
|
158
|
-
attr_accessor :inputs, :tasks
|
159
|
-
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|