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
@@ -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
|