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
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
module Tap
|
|
2
|
+
module Support
|
|
3
|
+
# Executable wraps methods to make them executable by App.
|
|
4
|
+
module Executable
|
|
5
|
+
|
|
6
|
+
# The method called when an Executable is executed via _execute
|
|
7
|
+
attr_reader :_method_name
|
|
8
|
+
|
|
9
|
+
# Indicates whether or not to call in multithread mode. Default false.
|
|
10
|
+
attr_accessor :multithread
|
|
11
|
+
|
|
12
|
+
# Stores the on complete block. Default is Executable.default_on_complete_block.
|
|
13
|
+
attr_reader :on_complete_block
|
|
14
|
+
|
|
15
|
+
protected
|
|
16
|
+
|
|
17
|
+
attr_writer :_method_name
|
|
18
|
+
|
|
19
|
+
public
|
|
20
|
+
|
|
21
|
+
def self.initialize(obj, method_name, multithread=false, &on_complete_block)
|
|
22
|
+
obj.extend Executable
|
|
23
|
+
obj.instance_variable_set(:@_method_name, method_name)
|
|
24
|
+
obj.instance_variable_set(:@multithread, multithread)
|
|
25
|
+
obj.instance_variable_set(:@on_complete_block, on_complete_block)
|
|
26
|
+
obj
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Sets a block to receive the results of _call. Raises an error
|
|
30
|
+
# if on_complete_block is already set, unless override = true.
|
|
31
|
+
#
|
|
32
|
+
# Note the block recieves an audited result and not
|
|
33
|
+
# the result itself (see Audit for more information).
|
|
34
|
+
def on_complete(override=false, &block) # :yields: _result
|
|
35
|
+
unless on_complete_block == nil || override
|
|
36
|
+
raise "on_complete_block already set: #{self}"
|
|
37
|
+
end
|
|
38
|
+
@on_complete_block = block
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Auditing method call. Executes _method_name for self, but audits
|
|
42
|
+
# the result. Sends the audited result to the on_complete_block if set.
|
|
43
|
+
#
|
|
44
|
+
# Audits are initialized in the follwing manner:
|
|
45
|
+
# no inputs:: create a new, empty Audit. The first value of the audit
|
|
46
|
+
# will be the result of call
|
|
47
|
+
# one input:: forks the input if it is an audit, otherwise initializes
|
|
48
|
+
# a new audit using the input
|
|
49
|
+
# multiple inputs:: merges the inputs into a new Audit.
|
|
50
|
+
#
|
|
51
|
+
def _execute(*inputs)
|
|
52
|
+
audit = case inputs.length
|
|
53
|
+
when 0 then Audit.new
|
|
54
|
+
when 1
|
|
55
|
+
audit = inputs.first
|
|
56
|
+
if audit.kind_of?(Audit)
|
|
57
|
+
inputs = [audit._current]
|
|
58
|
+
audit._fork
|
|
59
|
+
else
|
|
60
|
+
Audit.new(audit)
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
sources = []
|
|
64
|
+
inputs.collect! do |input|
|
|
65
|
+
if input.kind_of?(Audit)
|
|
66
|
+
sources << input._fork
|
|
67
|
+
input._current
|
|
68
|
+
else
|
|
69
|
+
sources << nil
|
|
70
|
+
input
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
Audit.new(inputs, sources)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
audit._record(self, send(_method_name, *inputs))
|
|
77
|
+
on_complete_block.call(audit) if on_complete_block
|
|
78
|
+
|
|
79
|
+
audit
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Tap extends Object with a convenience method to generate methods
|
|
86
|
+
# that can be enqued by App and incorporated into workflows.
|
|
87
|
+
class Object
|
|
88
|
+
|
|
89
|
+
# Makes a Tap::Support::Executable for the Method returned by
|
|
90
|
+
# Object#method, setting multithread and the on_complete block
|
|
91
|
+
# as specified. The method will be called on _execute.
|
|
92
|
+
#
|
|
93
|
+
# Returns nil if Object#method returns nil.
|
|
94
|
+
def _method(method_name, multithread=false, &on_complete_block) # :yields: _result
|
|
95
|
+
return nil unless m = method(method_name)
|
|
96
|
+
Tap::Support::Executable.initialize(m, :call, multithread, &on_complete_block)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module Tap
|
|
2
|
+
module Support
|
|
3
|
+
|
|
4
|
+
# ExecutableQueue allows thread-safe enqueing and dequeing of
|
|
5
|
+
# Executable methods and inputs for execution.
|
|
6
|
+
class ExecutableQueue
|
|
7
|
+
include MonitorMixin
|
|
8
|
+
|
|
9
|
+
# Creates a new ExecutableQueue
|
|
10
|
+
def initialize
|
|
11
|
+
# required for MonitorMixin
|
|
12
|
+
super()
|
|
13
|
+
@queue = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Clears all methods and inputs. Returns the existing queue as an array.
|
|
17
|
+
def clear
|
|
18
|
+
synchronize do
|
|
19
|
+
current = self.queue
|
|
20
|
+
self.queue = []
|
|
21
|
+
current
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Returns the number of enqueued methods
|
|
26
|
+
def size
|
|
27
|
+
queue.length
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# True if no methods are enqueued
|
|
31
|
+
def empty?
|
|
32
|
+
queue.empty?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Enqueues the method and inputs. Raises an error if the
|
|
36
|
+
# method is not an Executable.
|
|
37
|
+
def enq(method, inputs)
|
|
38
|
+
synchronize do
|
|
39
|
+
check_method(method)
|
|
40
|
+
queue.push [method, inputs]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Enqueues the method and inputs, but to the top of the queue.
|
|
45
|
+
# Raises an error if the method is not an Executable.
|
|
46
|
+
def unshift(method, inputs)
|
|
47
|
+
synchronize do
|
|
48
|
+
check_method(method)
|
|
49
|
+
queue.unshift [method, inputs]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Dequeues the next method and inputs as an array like
|
|
54
|
+
# [method, inputs]. Returns nil if the queue is empty.
|
|
55
|
+
def deq
|
|
56
|
+
synchronize { queue.shift }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def concat(array)
|
|
60
|
+
synchronize do
|
|
61
|
+
array.each do |method, inputs|
|
|
62
|
+
enq(method, inputs)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Converts self to an array.
|
|
68
|
+
def to_a
|
|
69
|
+
queue.dup
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
protected
|
|
73
|
+
|
|
74
|
+
attr_accessor :queue
|
|
75
|
+
|
|
76
|
+
# Checks if the input method is extended with Executable
|
|
77
|
+
def check_method(method) # :nodoc:
|
|
78
|
+
raise "not Executable: #{method}" unless method.kind_of?(Executable)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/tap/support/logger.rb
CHANGED
|
@@ -19,6 +19,12 @@ module Tap
|
|
|
19
19
|
# Typed logging occurs through +method_missing+. Any type is possible so long as the logger doesn't
|
|
20
20
|
# already have a method of the input type.
|
|
21
21
|
#++
|
|
22
|
+
#
|
|
23
|
+
#--
|
|
24
|
+
# TODO
|
|
25
|
+
# multiplex logger so that logging can be directed to two locations; a log file and the console for
|
|
26
|
+
# example, or log files in multiple locations.
|
|
27
|
+
#++
|
|
22
28
|
module Logger
|
|
23
29
|
Format = " %s[%s] %18s %s\n"
|
|
24
30
|
|
|
@@ -39,20 +45,8 @@ module Tap
|
|
|
39
45
|
@logdev
|
|
40
46
|
end
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def monitor(action="beginning", msg="", &block)
|
|
47
|
-
begin_time = Time.now
|
|
48
|
-
format_add(INFO, msg, action) {|format| format.chomp("\n")}
|
|
49
|
-
|
|
50
|
-
result = yield
|
|
51
|
-
|
|
52
|
-
format_add(INFO, "#{Time.now-begin_time}s", "completed") {|format| "\n" + format}
|
|
53
|
-
result
|
|
54
|
-
end
|
|
55
|
-
|
|
48
|
+
# Same as add, but uses the format provided by the block.
|
|
49
|
+
# BUG: not thread safe
|
|
56
50
|
def format_add(level, msg, action=nil, &block)
|
|
57
51
|
current_format = self.format
|
|
58
52
|
self.format = yield(current_format)
|
|
@@ -65,7 +59,7 @@ module Tap
|
|
|
65
59
|
# I[H:M:S] type message
|
|
66
60
|
#
|
|
67
61
|
# If no progname is specified, '--' is used.
|
|
68
|
-
def format_message(severity, timestamp, progname, msg)
|
|
62
|
+
def format_message(severity, timestamp, progname, msg, format=self.format)
|
|
69
63
|
if timestamp.respond_to?(:strftime) && self.datetime_format
|
|
70
64
|
timestamp = timestamp.strftime(self.datetime_format)
|
|
71
65
|
end
|
data/lib/tap/support/rake.rb
CHANGED
|
@@ -1,54 +1,43 @@
|
|
|
1
|
-
require 'rake'
|
|
2
|
-
|
|
3
|
-
module
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
module Tap
|
|
45
|
-
module Support
|
|
46
|
-
# == UNDER CONSTRUCTION
|
|
47
|
-
module Rake
|
|
48
|
-
|
|
49
|
-
def task(td, config=nil)
|
|
50
|
-
Object::Rake.application.lookup(td) || super
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
1
|
+
require 'rake'
|
|
2
|
+
|
|
3
|
+
module Tap
|
|
4
|
+
module Support
|
|
5
|
+
|
|
6
|
+
# Used to modify an App so that it will lookup Rake tasks as well as Tap tasks. Simply use:
|
|
7
|
+
# app.extend(RakeLookup)
|
|
8
|
+
#--
|
|
9
|
+
# Note: Do not refactor Tap:Support::Rake without attending to the line in 'script/run' that
|
|
10
|
+
# extends app. As it stands, this module is loaded as needed using Dependencies.
|
|
11
|
+
module Rake
|
|
12
|
+
def task(td, config={}, &block)
|
|
13
|
+
Object::Rake.application.lookup(td) || super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Modifies Rake::Task to behave like Tap::Task. The essential code is this:
|
|
17
|
+
#
|
|
18
|
+
# module Tap::Support::Rake::Task
|
|
19
|
+
# def new(*args)
|
|
20
|
+
# task = super
|
|
21
|
+
# Tap::Task::Base.initialize(task, :invoke)
|
|
22
|
+
# task
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# Here the new method creates a new Rake task as normal, then initializes the
|
|
27
|
+
# Rake task based on the invoke method. The modifed code is applied to Rake
|
|
28
|
+
# in the following fashion:
|
|
29
|
+
#
|
|
30
|
+
# Rake::Task.extend(Tap::Support::Rake::Task)
|
|
31
|
+
#
|
|
32
|
+
module Task
|
|
33
|
+
def new(*args)
|
|
34
|
+
task = super
|
|
35
|
+
Tap::Task::Base.initialize(task, :invoke)
|
|
36
|
+
task
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Rake::Task.extend(Tap::Support::Rake::Task)
|
|
@@ -1,20 +1,39 @@
|
|
|
1
1
|
module Tap
|
|
2
|
-
module Support
|
|
2
|
+
module Support
|
|
3
|
+
# Raised when an exception is raised during App#run. All errors generated during
|
|
4
|
+
# termination are collected into the RunError.
|
|
3
5
|
class RunError < RuntimeError
|
|
4
|
-
attr_reader :
|
|
6
|
+
attr_reader :errors
|
|
5
7
|
|
|
6
|
-
def initialize(
|
|
7
|
-
@
|
|
8
|
-
@
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
def initialize(errors)
|
|
9
|
+
@errors = errors
|
|
10
|
+
@backtrace = nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
#The join of all the error messages.
|
|
14
|
+
def message
|
|
15
|
+
lines = []
|
|
16
|
+
errors.each_with_index do |error, i|
|
|
17
|
+
lines << "\nRunError [#{i}] #{error.class} #{error.message}"
|
|
18
|
+
end
|
|
19
|
+
lines.join + "\n"
|
|
17
20
|
end
|
|
21
|
+
|
|
22
|
+
#The join of all the error backtraces.
|
|
23
|
+
def backtrace
|
|
24
|
+
# backtrace gets called every time RunError is re-raised, leading to multiple
|
|
25
|
+
# repeats of the error backtraces. This ensures the additional backtrace
|
|
26
|
+
# information is only added once.
|
|
27
|
+
return @backtrace unless @backtrace == nil
|
|
28
|
+
return nil unless @backtrace = super
|
|
29
|
+
|
|
30
|
+
errors.each_with_index do |error, i|
|
|
31
|
+
@backtrace [-1] += "\n\n---------------------- RunError [#{i}] ----------------------\n#{error.class} #{error.message}"
|
|
32
|
+
@backtrace.concat(error.backtrace || ["missing backtrace"])
|
|
33
|
+
end
|
|
34
|
+
@backtrace
|
|
35
|
+
end
|
|
36
|
+
|
|
18
37
|
end
|
|
19
38
|
end
|
|
20
39
|
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
|
|
3
|
+
module Tap
|
|
4
|
+
module Support
|
|
5
|
+
# Provides several shell utility methods for calling programs.
|
|
6
|
+
module ShellUtils
|
|
7
|
+
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
# Run the system command +cmd+, passing the result to the block, if given.
|
|
11
|
+
# Raises an error if the command fails. Uses the same semantics as
|
|
12
|
+
# Kernel::exec and Kernel::system.
|
|
13
|
+
#
|
|
14
|
+
# Based on FileUtils#sh from Rake.
|
|
15
|
+
def sh(*cmd) # :yields: ok, status
|
|
16
|
+
ok = system(*cmd)
|
|
17
|
+
|
|
18
|
+
if block_given?
|
|
19
|
+
yield(ok, $?)
|
|
20
|
+
else
|
|
21
|
+
ok or raise "Command failed with status (#{$?.exitstatus}): [#{ cmd.join(' ')}]"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Runs the system command +cmd+ using sh, redirecting the output to the
|
|
26
|
+
# specified file path. Uses the redirection command:
|
|
27
|
+
#
|
|
28
|
+
# "> \"#{path}\" 2>&1 #{cmd}"
|
|
29
|
+
#
|
|
30
|
+
# This redirection has been tested on Windows, OS X, and Fedora. See
|
|
31
|
+
# http://www.robvanderwoude.com/redirection.html for pointers on
|
|
32
|
+
# redirection. The website notes that this style of redirection SHOULD
|
|
33
|
+
# NOT be used with commands that contain other redirections.
|
|
34
|
+
def redirect_sh(cmd, path, &block) # :yields: ok, status
|
|
35
|
+
sh( "> \"#{path}\" 2>&1 #{cmd}", &block)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Runs the system command +cmd+ and returns the output as a string.
|
|
39
|
+
def capture_sh(cmd, quiet=false, &block) # :yields: ok, status
|
|
40
|
+
tempfile = Tempfile.new('shell_utils')
|
|
41
|
+
tempfile.close
|
|
42
|
+
redirect_sh(cmd, tempfile.path, &block)
|
|
43
|
+
quiet == true ? "" : File.read(tempfile.path)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/tap/support/tdoc.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Tap
|
|
|
10
10
|
# documentation for Task configurations, when they are present. TDoc provides an extension
|
|
11
11
|
# to the standard RDoc HTMLGenerator and template.
|
|
12
12
|
#
|
|
13
|
-
#
|
|
13
|
+
# === Usage
|
|
14
14
|
# To generate task documentation with configuration information, TDoc must be loaded and
|
|
15
15
|
# the appropriate flags passed to rdoc . Essentially what you want is:
|
|
16
16
|
#
|
|
@@ -40,7 +40,7 @@ module Tap
|
|
|
40
40
|
# TDoc may also be utilized programatically, but you should be aware that RDoc in Ruby
|
|
41
41
|
# can raise errors and/or cause namespace conflicts (see below).
|
|
42
42
|
#
|
|
43
|
-
#
|
|
43
|
+
# === Implementation
|
|
44
44
|
# RDoc is a beast to utilize in a non-standard way. One way to make RDoc parse unexpected
|
|
45
45
|
# flags like 'config_accessor' or the 'c' config specifier is to use the '--accessor' option
|
|
46
46
|
# (see 'rdoc --help' or the RDoc documentation for more details).
|
|
@@ -54,7 +54,7 @@ module Tap
|
|
|
54
54
|
# Similarly, the configuration attributes will not appear in the output unless you specify a
|
|
55
55
|
# template that utilizes them.
|
|
56
56
|
#
|
|
57
|
-
#
|
|
57
|
+
# === Namespace conflicts
|
|
58
58
|
# RDoc creates a namespace conflict with other libraries that define RubyToken and RubyLex
|
|
59
59
|
# in the Object namespace (the prime example being IRB). TDoc checks for such a conflict
|
|
60
60
|
# and redfines the RDoc RubyToken and RubyLex within the RDoc namespace. Essentially:
|
|
@@ -90,7 +90,7 @@ module Tap
|
|
|
90
90
|
@stats = RDoc::Stats.new
|
|
91
91
|
@options = Options.instance
|
|
92
92
|
@options.parse(argv, RDoc::RDoc::GENERATORS)
|
|
93
|
-
@load_paths = $:
|
|
93
|
+
@load_paths = ($: + Dependencies.load_paths + Dependencies.load_once_paths).uniq
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
class << self
|
|
@@ -106,11 +106,12 @@ module Tap
|
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
def search_for_source_files(klass)
|
|
109
|
-
source_files =
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
source_files = []
|
|
110
|
+
# searches back for all configurable source files, so that
|
|
111
|
+
# inherited configs can be documented.
|
|
112
|
+
while klass.include?(Tap::Support::Configurable)
|
|
113
113
|
source_files.concat(search_for_files(klass.to_s.underscore))
|
|
114
|
+
klass = klass.superclass
|
|
114
115
|
end
|
|
115
116
|
|
|
116
117
|
source_files.uniq
|