tap 0.8.0 → 0.9.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/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
data/lib/tap/script.rb
CHANGED
|
@@ -1,362 +1,96 @@
|
|
|
1
1
|
require 'getoptlong'
|
|
2
|
-
require 'singleton'
|
|
3
2
|
autoload(:PP, "pp")
|
|
4
3
|
|
|
5
4
|
module Tap
|
|
6
|
-
module Support
|
|
7
|
-
autoload(:TDoc, 'tap/support/tdoc')
|
|
8
|
-
end
|
|
9
|
-
|
|
10
5
|
# == UNDER CONSTRUCTION
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
:load_paths => ["lib"],
|
|
17
|
-
:script_paths => ["script"]}
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def spec_filepath(dir=nil)
|
|
21
|
-
dir == nil ? "tapspec.yml" : File.join(dir, "tapspec.yml")
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def initialize(config={}, app=Tap::App.instance)
|
|
26
|
-
super(
|
|
27
|
-
:gemspecs => [],
|
|
28
|
-
:load_once_paths => [],
|
|
29
|
-
:load_paths => [],
|
|
30
|
-
:script_paths => [])
|
|
31
|
-
|
|
32
|
-
config = ScriptConfig.defaults.merge(config)
|
|
33
|
-
resolve_paths(config, app)
|
|
34
|
-
collect_gem_paths(config)
|
|
35
|
-
|
|
36
|
-
# add additional configurations
|
|
37
|
-
config.each_pair do |key, value|
|
|
38
|
-
next if self.respond_to?(key)
|
|
39
|
-
self.send("#{key}=", value)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
self.load_once_paths.uniq!
|
|
43
|
-
self.load_paths.uniq!
|
|
44
|
-
self.script_paths.uniq!
|
|
45
|
-
end
|
|
6
|
+
#
|
|
7
|
+
# Script is a mixed bag of methods encapsulating many scripting
|
|
8
|
+
# functions like handling options and assembling usage information.
|
|
9
|
+
module Script
|
|
10
|
+
module_function
|
|
46
11
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# allow gem scripts to overrride default scripts
|
|
58
|
-
# (hence do this second)
|
|
59
|
-
script_dir = File.expand_path(File.join( File.dirname(__FILE__), "script"))
|
|
60
|
-
Dir.glob( script_dir + "/**/*.rb" ).each do |file|
|
|
61
|
-
script = Tap::App.relative_filepath(script_dir, file).chomp(".rb")
|
|
62
|
-
scripts[script] = file unless scripts.include?(script)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
scripts
|
|
12
|
+
# Parses the input string as YAML, if the string matches the YAML document
|
|
13
|
+
# specifier (ie it begins with "---\s*\n"). Otherwise returns the string.
|
|
14
|
+
#
|
|
15
|
+
# str = {'key' => 'value'}.to_yaml # => "--- \nkey: value\n"
|
|
16
|
+
# Tap::Script.parse_yaml(str) # => {'key' => 'value'}
|
|
17
|
+
# Tap::Script.parse_yaml("str") # => "str"
|
|
18
|
+
def parse_yaml(str)
|
|
19
|
+
str =~ /\A---\s*\n/ ? YAML.load(str) : str
|
|
66
20
|
end
|
|
67
21
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
when Tap::App
|
|
81
|
-
app_or_gemspec.filepath(path)
|
|
82
|
-
when Gem::Specification
|
|
83
|
-
expanded = File.expand_path(path, app_or_gemspec.full_gem_path)
|
|
84
|
-
unless expanded.index(app_or_gemspec.full_gem_path) == 0
|
|
85
|
-
raise "'#{path}' for '#{app_or_gemspec.name}' resolves to a non-gem directory"
|
|
86
|
-
end
|
|
87
|
-
expanded
|
|
88
|
-
end
|
|
22
|
+
def split_argv(argv)
|
|
23
|
+
current = []
|
|
24
|
+
current_split = []
|
|
25
|
+
splits = [current_split]
|
|
26
|
+
|
|
27
|
+
argv.each do |arg|
|
|
28
|
+
if arg =~ /\A-{2}(\+*)\z/
|
|
29
|
+
current_split << current unless current.empty?
|
|
30
|
+
current = []
|
|
31
|
+
current_split = (splits[$1.length] ||= [])
|
|
32
|
+
else
|
|
33
|
+
current << arg
|
|
89
34
|
end
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
current_split << current unless current.empty?
|
|
38
|
+
splits.delete_if {|split| split.nil? || split.empty? }
|
|
39
|
+
splits
|
|
93
40
|
end
|
|
94
|
-
|
|
95
|
-
# Recursively collects paths from the gems specfied in config[:gems],
|
|
96
|
-
# using tap specification file for the gem as determined by
|
|
97
|
-
# ScriptConfig#spec_filepath
|
|
98
|
-
def collect_gem_paths(config) # :nodoc:
|
|
99
|
-
arrayify(config[:gems]).each do |string|
|
|
100
|
-
# figure the version of the gem, by default >= 0.0.0
|
|
101
|
-
string =~ /^([^<=>]*)(.*)$/
|
|
102
|
-
gem_name, version = $1, $2
|
|
103
|
-
version = ">= 0.0.0" if version.empty?
|
|
104
|
-
|
|
105
|
-
# load the gem and get the spec
|
|
106
|
-
gem(gem_name, version)
|
|
107
|
-
spec = Gem.loaded_specs[gem_name]
|
|
108
41
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
tap_spec_file = ScriptConfig.spec_filepath(spec.full_gem_path)
|
|
116
|
-
gem_config = if File.exists?(tap_spec_file)
|
|
117
|
-
YAML.load_file(tap_spec_file).symbolize_keys
|
|
118
|
-
else
|
|
119
|
-
ScriptConfig.defaults
|
|
42
|
+
def next_arg(argv)
|
|
43
|
+
index = nil
|
|
44
|
+
argv.each_with_index do |arg, i|
|
|
45
|
+
if arg !~ /\A-/
|
|
46
|
+
index = i
|
|
47
|
+
break
|
|
120
48
|
end
|
|
121
|
-
|
|
122
|
-
resolve_paths(gem_config, spec)
|
|
123
|
-
collect_gem_paths(gem_config)
|
|
124
49
|
end
|
|
50
|
+
index == nil ? nil : argv.delete_at(index)
|
|
125
51
|
end
|
|
126
52
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
53
|
+
# Handles options using GetoptLong, and passes each option and
|
|
54
|
+
# value in ARGV to the block.
|
|
55
|
+
#
|
|
56
|
+
#--
|
|
57
|
+
# expect [long, <short>, type, desc]
|
|
58
|
+
#++
|
|
59
|
+
def handle_options(*options)
|
|
60
|
+
options = options.collect do |opt|
|
|
61
|
+
opt = opt[0..-2]
|
|
62
|
+
opt.compact
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
opts = GetoptLong.new(*options)
|
|
66
|
+
opts.quiet = true
|
|
67
|
+
opts.each do |opt, value|
|
|
68
|
+
yield(opt, value)
|
|
133
69
|
end
|
|
134
70
|
end
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
# == UNDER CONSTRUCTION
|
|
138
|
-
#
|
|
139
|
-
# Script is a mixed bag of methods encapsulating many scripting
|
|
140
|
-
# functions like reconfiguring an application, handling options
|
|
141
|
-
# and assembling usage information.
|
|
142
|
-
class Script
|
|
143
71
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def read_config(config_file)
|
|
150
|
-
config = if File.exists?(config_file)
|
|
151
|
-
config_str = ERB.new( File.read(config_file) ).result
|
|
152
|
-
config = config_str.empty? ? {} : YAML.load(config_str)
|
|
153
|
-
config == false ? {} : config
|
|
154
|
-
else
|
|
155
|
-
{}
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
unless config.kind_of?(Hash)
|
|
159
|
-
raise "cannot parse file contents into a hash using YAML: #{config_file}"
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
config.symbolize_keys
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def split_arguments(argv, separator_regexp=/^-{2}$/)
|
|
166
|
-
splits = []
|
|
167
|
-
current = []
|
|
168
|
-
argv.each do |arg|
|
|
169
|
-
if arg =~ separator_regexp
|
|
170
|
-
splits << current unless current.empty?
|
|
171
|
-
current = []
|
|
172
|
-
else
|
|
173
|
-
current << arg
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
splits << current unless current.empty?
|
|
177
|
-
splits
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def next_arg(argv)
|
|
181
|
-
index = nil
|
|
182
|
-
argv.each_with_index do |arg, i|
|
|
183
|
-
if arg !~ /^-/
|
|
184
|
-
index = i
|
|
185
|
-
break
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
index == nil ? nil : argv.delete_at(index)
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
def usage(program_file, *sections)
|
|
192
|
-
options = sections.last.kind_of?(Hash) ? sections.pop : {}
|
|
193
|
-
options = {:keep_headers => true}.merge(options)
|
|
194
|
-
comment = Support::TDoc.usage(program_file, sections, options[:keep_headers])
|
|
195
|
-
comment.rstrip + "\n"
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def usage_options(opts)
|
|
199
|
-
opt_lines = ["Options:\n"]
|
|
200
|
-
opts.each do |long, short, mode, desc|
|
|
201
|
-
short = short == nil ? " " : "(#{short})"
|
|
202
|
-
opt_lines << " %-25s %s %s" % [long, short, desc]
|
|
203
|
-
end
|
|
204
|
-
opt_lines.join("\n")
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
# Handles options using GetoptLong, and passes each option and
|
|
208
|
-
# value in ARGV to the block.
|
|
209
|
-
#
|
|
210
|
-
#--
|
|
211
|
-
# expect [long, <short>, type, desc]
|
|
212
|
-
#++
|
|
213
|
-
def handle_options(*options)
|
|
214
|
-
options = options.collect do |opt|
|
|
215
|
-
opt = opt[0..-2]
|
|
216
|
-
opt.compact
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
opts = GetoptLong.new(*options)
|
|
220
|
-
opts.each do |opt, value|
|
|
221
|
-
yield(opt, value)
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
def handle_task_options(task)
|
|
226
|
-
return task.handle_options if task.respond_to?(:handle_options)
|
|
227
|
-
|
|
228
|
-
config = {}
|
|
229
|
-
opt_map = {}
|
|
230
|
-
opts = task.class.configurations.collect do |declaration_class, key, value, attributes|
|
|
231
|
-
long, short, opt_type, desc = config_to_opt(key, value, attributes)
|
|
232
|
-
opt_map[long] = key
|
|
233
|
-
[long, short, opt_type, desc]
|
|
234
|
-
end
|
|
235
|
-
opts << ['--help', '-h', GetoptLong::NO_ARGUMENT, "Print this help."]
|
|
236
|
-
|
|
237
|
-
handle_options(*opts) do |opt, value|
|
|
238
|
-
case opt
|
|
239
|
-
when '--help'
|
|
240
|
-
class_doc = Tap::Support::TDoc[task.class]
|
|
241
|
-
if class_doc == nil
|
|
242
|
-
puts "could not find help for '#{task.class}'"
|
|
243
|
-
exit
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
sections = class_doc.comment_sections(/Description|Usage/i, true)
|
|
247
|
-
opt_lines = opts.collect do |long, short, opt_type, desc|
|
|
248
|
-
key = opt_map[long]
|
|
249
|
-
default = PP.singleline_pp(task.class.configurations.default[key], "")
|
|
250
|
-
config_attr = class_doc.find_configuration_named(key.to_s)
|
|
251
|
-
|
|
252
|
-
short = "(#{short})" unless short.to_s.empty?
|
|
253
|
-
if desc == nil && config_attr != nil
|
|
254
|
-
desc = config_attr.desc + " (#{default})"
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
" %-25s %-5s %s" % [long, short, desc]
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
puts %Q{#{task.class.to_s}
|
|
261
|
-
#{sections["Description"]}
|
|
262
|
-
|
|
263
|
-
Usage:
|
|
264
|
-
#{sections["Usage"]}
|
|
265
|
-
|
|
266
|
-
Options:
|
|
267
|
-
#{opt_lines.join("\n")}}
|
|
268
|
-
exit
|
|
269
|
-
|
|
270
|
-
else
|
|
271
|
-
key = opt_map[opt]
|
|
272
|
-
config[key] = YAML.load(value)
|
|
273
|
-
end
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
# reconfigure task
|
|
277
|
-
task.batch.each do |t|
|
|
278
|
-
t.config = config
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
protected
|
|
283
|
-
|
|
284
|
-
def config_to_opt(key, value, attributes)
|
|
285
|
-
attributes = {
|
|
286
|
-
:long => key,
|
|
287
|
-
:short => nil,
|
|
288
|
-
:opt_type => GetoptLong::REQUIRED_ARGUMENT,
|
|
289
|
-
:desc => nil
|
|
290
|
-
}.merge(attributes)
|
|
291
|
-
|
|
292
|
-
long = attributes[:long]
|
|
293
|
-
attributes[:long] = "--#{long}" unless long =~ /^-{2}/
|
|
294
|
-
|
|
295
|
-
short = attributes[:short].to_s
|
|
296
|
-
attributes[:short] = "-#{short}" unless short.empty? || short =~ /^-/
|
|
297
|
-
|
|
298
|
-
[attributes[:long], attributes[:short], attributes[:opt_type], attributes[:desc]]
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
include Singleton
|
|
303
|
-
|
|
304
|
-
attr_accessor :config
|
|
305
|
-
|
|
306
|
-
def reset
|
|
307
|
-
self.config = nil
|
|
72
|
+
def usage(program_file, *sections)
|
|
73
|
+
options = sections.last.kind_of?(Hash) ? sections.pop : {}
|
|
74
|
+
options = {:keep_headers => true}.merge(options)
|
|
75
|
+
comment = Support::TDoc.usage(program_file, sections, options[:keep_headers])
|
|
76
|
+
comment.rstrip + "\n"
|
|
308
77
|
end
|
|
309
|
-
|
|
310
|
-
# Configures the app with the input configurations.
|
|
311
|
-
def configure_app(app_config={}, app=Tap::App.instance)
|
|
312
|
-
app_config = app_config ? app_config.symbolize_keys : {}
|
|
313
78
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
app_config.delete_if do |key, value|
|
|
318
|
-
if script_config_keys.include?(key)
|
|
319
|
-
script_config[key] = value
|
|
320
|
-
true
|
|
321
|
-
else
|
|
322
|
-
false
|
|
323
|
-
end
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
# reconfigure the current app with remaining keys
|
|
327
|
-
# this must be done first so load paths can be
|
|
328
|
-
# resolved using the most current app config
|
|
329
|
-
app.reconfigure(app_config) do |key, value|
|
|
330
|
-
# collect unknown options
|
|
331
|
-
script_config[key] = value
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
# define the config, using the newly configured app
|
|
335
|
-
self.config = ScriptConfig.new(script_config, app)
|
|
79
|
+
def usage_options(opts)
|
|
80
|
+
opt_lines = []
|
|
81
|
+
opts.each do |long, short, mode, desc|
|
|
336
82
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
end
|
|
344
|
-
$LOAD_PATH.uniq!
|
|
345
|
-
|
|
346
|
-
# set Dependencies load paths and freeze setting of load_paths
|
|
347
|
-
# echos Rail::Initializer.set_autoload_paths
|
|
348
|
-
Dependencies.load_once_paths = config.load_once_paths
|
|
349
|
-
Dependencies.load_paths = config.load_paths
|
|
83
|
+
if desc.kind_of?(Class) && desc.include?(Tap::Support::Configurable)
|
|
84
|
+
key = desc.configurations.opt_map(long)
|
|
85
|
+
default = PP.singleline_pp(desc.configurations.default[key], "")
|
|
86
|
+
config_attr = desc.tdoc.find_configuration_named(key.to_s)
|
|
87
|
+
desc = config_attr.desc
|
|
88
|
+
end
|
|
350
89
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
raise(
|
|
354
|
-
"load_once_paths must be a subset of the load_paths.\n" +
|
|
355
|
-
"Extra items in load_once_paths: #{extra * ','}")
|
|
90
|
+
short = short == nil ? " " : "(#{short})"
|
|
91
|
+
opt_lines << " %-25s %s %s" % [long, short, desc]
|
|
356
92
|
end
|
|
357
|
-
|
|
358
|
-
config
|
|
93
|
+
opt_lines.join("\n")
|
|
359
94
|
end
|
|
360
|
-
|
|
361
95
|
end
|
|
362
96
|
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Tap
|
|
2
|
+
module Support
|
|
3
|
+
|
|
4
|
+
# Aggregator allows thread-safe collection of Audits, organized
|
|
5
|
+
# by Audit#_current_source.
|
|
6
|
+
class Aggregator < Monitor
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
super
|
|
10
|
+
clear
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Clears self of all audits.
|
|
14
|
+
def clear
|
|
15
|
+
synchronize { self.hash = Hash.new }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# The total number of audits recorded in self.
|
|
19
|
+
def size
|
|
20
|
+
synchronize { hash.values.inject(0) {|sum, array| sum + array.length} }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# True if size == 0
|
|
24
|
+
def empty?
|
|
25
|
+
synchronize { hash.empty? }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Stores the Audit according to _result._current_source
|
|
29
|
+
def store(_result)
|
|
30
|
+
synchronize { (hash[_result._current_source] ||= []) << _result }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Retreives all aggregated audits for the specified source.
|
|
34
|
+
def retrieve(source)
|
|
35
|
+
synchronize { hash[source] }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Retreives all audits for the input sources, joined into an array.
|
|
39
|
+
def retrieve_all(*sources)
|
|
40
|
+
synchronize do
|
|
41
|
+
sources.collect {|src| hash[src] }.flatten.compact
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Converts self to a hash of (source, audits) pairs.
|
|
46
|
+
def to_hash
|
|
47
|
+
hash.dup
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
protected
|
|
51
|
+
|
|
52
|
+
attr_accessor :hash
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|