tap 0.9.1 → 0.10.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.
Files changed (244) hide show
  1. data/History +37 -30
  2. data/MIT-LICENSE +1 -1
  3. data/README +92 -44
  4. data/bin/tap +62 -75
  5. data/cmd/console.rb +42 -0
  6. data/cmd/destroy.rb +16 -0
  7. data/cmd/generate.rb +16 -0
  8. data/cmd/run.rb +126 -0
  9. data/doc/Class Reference +362 -0
  10. data/doc/Command Reference +153 -0
  11. data/doc/Tutorial +237 -0
  12. data/lib/tap.rb +6 -45
  13. data/lib/tap/app.rb +126 -500
  14. data/lib/tap/constants.rb +2 -29
  15. data/lib/tap/env.rb +555 -250
  16. data/lib/tap/file_task.rb +60 -103
  17. data/lib/tap/generator/base.rb +109 -0
  18. data/lib/tap/generator/destroy.rb +37 -0
  19. data/lib/tap/generator/generate.rb +61 -0
  20. data/lib/tap/generator/generators/command/command_generator.rb +16 -12
  21. data/lib/tap/generator/generators/command/templates/command.erb +13 -19
  22. data/lib/tap/generator/generators/config/config_generator.rb +18 -27
  23. data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
  24. data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
  25. data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -11
  26. data/lib/tap/generator/generators/file_task/templates/file.txt +11 -2
  27. data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
  28. data/lib/tap/generator/generators/file_task/templates/task.erb +24 -31
  29. data/lib/tap/generator/generators/file_task/templates/test.erb +18 -22
  30. data/lib/tap/generator/generators/root/root_generator.rb +45 -31
  31. data/lib/tap/generator/generators/root/templates/Rakefile +64 -41
  32. data/lib/tap/generator/generators/root/templates/gemspec +27 -0
  33. data/lib/tap/generator/generators/root/templates/tapfile +8 -0
  34. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -0
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  36. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +21 -28
  38. data/lib/tap/generator/generators/task/templates/task.erb +13 -23
  39. data/lib/tap/generator/generators/task/templates/test.erb +15 -18
  40. data/lib/tap/generator/manifest.rb +14 -0
  41. data/lib/tap/patches/rake/rake_test_loader.rb +0 -0
  42. data/lib/tap/patches/rake/testtask.rb +0 -0
  43. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -0
  44. data/lib/tap/patches/ruby19/parsedate.rb +0 -0
  45. data/lib/tap/root.rb +260 -21
  46. data/lib/tap/support/aggregator.rb +11 -11
  47. data/lib/tap/support/assignments.rb +172 -0
  48. data/lib/tap/support/audit.rb +20 -18
  49. data/lib/tap/support/batchable.rb +21 -10
  50. data/lib/tap/support/batchable_class.rb +107 -0
  51. data/lib/tap/support/class_configuration.rb +154 -239
  52. data/lib/tap/support/command_line.rb +97 -102
  53. data/lib/tap/support/comment.rb +270 -0
  54. data/lib/tap/support/configurable.rb +86 -65
  55. data/lib/tap/support/configurable_class.rb +296 -0
  56. data/lib/tap/support/configuration.rb +122 -0
  57. data/lib/tap/support/constant.rb +70 -0
  58. data/lib/tap/support/constant_utils.rb +127 -0
  59. data/lib/tap/support/declarations.rb +111 -0
  60. data/lib/tap/support/executable.rb +30 -17
  61. data/lib/tap/support/executable_queue.rb +0 -0
  62. data/lib/tap/support/framework.rb +71 -0
  63. data/lib/tap/support/framework_class.rb +199 -0
  64. data/lib/tap/support/instance_configuration.rb +147 -0
  65. data/lib/tap/support/lazydoc.rb +428 -0
  66. data/lib/tap/support/manifest.rb +89 -0
  67. data/lib/tap/support/run_error.rb +0 -0
  68. data/lib/tap/support/shell_utils.rb +33 -9
  69. data/lib/tap/support/summary.rb +30 -0
  70. data/lib/tap/support/tdoc.rb +339 -134
  71. data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -0
  72. data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -0
  73. data/lib/tap/support/templater.rb +180 -0
  74. data/lib/tap/support/validation.rb +409 -76
  75. data/lib/tap/support/versions.rb +5 -3
  76. data/lib/tap/task.rb +78 -174
  77. data/lib/tap/tasks/dump.rb +56 -0
  78. data/lib/tap/tasks/rake.rb +93 -0
  79. data/lib/tap/test.rb +3 -3
  80. data/lib/tap/test/env_vars.rb +2 -2
  81. data/lib/tap/test/file_methods.rb +19 -20
  82. data/lib/tap/test/script_methods.rb +144 -0
  83. data/lib/tap/test/subset_methods.rb +1 -1
  84. data/lib/tap/test/tap_methods.rb +28 -62
  85. data/lib/tap/workflow.rb +22 -39
  86. metadata +48 -179
  87. data/Basic Overview +0 -151
  88. data/Command Reference +0 -99
  89. data/Rakefile +0 -127
  90. data/Tutorial +0 -287
  91. data/lib/tap/cmd/console.rb +0 -31
  92. data/lib/tap/cmd/destroy.rb +0 -20
  93. data/lib/tap/cmd/generate.rb +0 -20
  94. data/lib/tap/cmd/run.rb +0 -151
  95. data/lib/tap/dump.rb +0 -57
  96. data/lib/tap/generator.rb +0 -91
  97. data/lib/tap/generator/generators/command/USAGE +0 -6
  98. data/lib/tap/generator/generators/config/USAGE +0 -21
  99. data/lib/tap/generator/generators/config/templates/config.erb +0 -1
  100. data/lib/tap/generator/generators/file_task/USAGE +0 -3
  101. data/lib/tap/generator/generators/file_task/templates/file.yml +0 -3
  102. data/lib/tap/generator/generators/generator/USAGE +0 -0
  103. data/lib/tap/generator/generators/generator/generator_generator.rb +0 -21
  104. data/lib/tap/generator/generators/generator/templates/generator.erb +0 -32
  105. data/lib/tap/generator/generators/generator/templates/usage.erb +0 -1
  106. data/lib/tap/generator/generators/root/USAGE +0 -0
  107. data/lib/tap/generator/generators/root/templates/ReadMe.txt +0 -0
  108. data/lib/tap/generator/generators/root/templates/tap.yml +0 -80
  109. data/lib/tap/generator/generators/task/USAGE +0 -3
  110. data/lib/tap/generator/generators/workflow/USAGE +0 -0
  111. data/lib/tap/generator/generators/workflow/templates/task.erb +0 -16
  112. data/lib/tap/generator/generators/workflow/templates/test.erb +0 -7
  113. data/lib/tap/generator/generators/workflow/workflow_generator.rb +0 -6
  114. data/lib/tap/generator/options.rb +0 -26
  115. data/lib/tap/generator/usage.rb +0 -26
  116. data/lib/tap/support/batchable_methods.rb +0 -34
  117. data/lib/tap/support/command_line_methods.rb +0 -76
  118. data/lib/tap/support/configurable_methods.rb +0 -224
  119. data/lib/tap/support/logger.rb +0 -88
  120. data/lib/tap/support/rake.rb +0 -43
  121. data/lib/tap/support/tdoc/config_attr.rb +0 -362
  122. data/test/app/config/another/task.yml +0 -1
  123. data/test/app/config/batch.yml +0 -2
  124. data/test/app/config/empty.yml +0 -0
  125. data/test/app/config/erb.yml +0 -2
  126. data/test/app/config/some/task.yml +0 -1
  127. data/test/app/config/template.yml +0 -2
  128. data/test/app/config/version-0.1.yml +0 -1
  129. data/test/app/config/version.yml +0 -1
  130. data/test/app/lib/app_test_task.rb +0 -3
  131. data/test/app_test.rb +0 -1849
  132. data/test/env/test_configure/recurse_a.yml +0 -2
  133. data/test/env/test_configure/recurse_b.yml +0 -2
  134. data/test/env/test_configure/tap.yml +0 -23
  135. data/test/env/test_load_env_config/dir/tap.yml +0 -3
  136. data/test/env/test_load_env_config/recurse_a.yml +0 -2
  137. data/test/env/test_load_env_config/recurse_b.yml +0 -2
  138. data/test/env/test_load_env_config/tap.yml +0 -3
  139. data/test/env_test.rb +0 -198
  140. data/test/file_task/config/batch.yml +0 -2
  141. data/test/file_task/config/configured.yml +0 -1
  142. data/test/file_task/old_file_one.txt +0 -0
  143. data/test/file_task/old_file_two.txt +0 -0
  144. data/test/file_task_test.rb +0 -1291
  145. data/test/root/alt_lib/alt_module.rb +0 -4
  146. data/test/root/file.txt +0 -0
  147. data/test/root/glob/one.txt +0 -0
  148. data/test/root/glob/two.txt +0 -0
  149. data/test/root/lib/absolute_alt_filepath.rb +0 -2
  150. data/test/root/lib/alternative_filepath.rb +0 -2
  151. data/test/root/lib/another_module.rb +0 -2
  152. data/test/root/lib/nested/some_module.rb +0 -4
  153. data/test/root/lib/no_module_included.rb +0 -0
  154. data/test/root/lib/some/module.rb +0 -4
  155. data/test/root/lib/some_class.rb +0 -2
  156. data/test/root/lib/some_module.rb +0 -3
  157. data/test/root/load_path/load_path_module.rb +0 -2
  158. data/test/root/load_path/skip_module.rb +0 -2
  159. data/test/root/mtime/older.txt +0 -0
  160. data/test/root/unload/full_path.rb +0 -2
  161. data/test/root/unload/loaded_by_nested.rb +0 -2
  162. data/test/root/unload/nested/nested_load.rb +0 -6
  163. data/test/root/unload/nested/nested_with_ext.rb +0 -4
  164. data/test/root/unload/nested/relative_path.rb +0 -4
  165. data/test/root/unload/older.rb +0 -2
  166. data/test/root/unload/unload_base.rb +0 -9
  167. data/test/root/versions/another.yml +0 -0
  168. data/test/root/versions/file-0.1.2.yml +0 -0
  169. data/test/root/versions/file-0.1.yml +0 -0
  170. data/test/root/versions/file.yml +0 -0
  171. data/test/root_test.rb +0 -718
  172. data/test/support/aggregator_test.rb +0 -99
  173. data/test/support/audit_test.rb +0 -445
  174. data/test/support/batchable_test.rb +0 -74
  175. data/test/support/class_configuration_test.rb +0 -331
  176. data/test/support/command_line_test.rb +0 -58
  177. data/test/support/configurable/config/configured.yml +0 -2
  178. data/test/support/configurable_test.rb +0 -295
  179. data/test/support/executable_queue_test.rb +0 -103
  180. data/test/support/executable_test.rb +0 -38
  181. data/test/support/logger_test.rb +0 -31
  182. data/test/support/rake_test.rb +0 -37
  183. data/test/support/shell_utils_test.rb +0 -24
  184. data/test/support/tdoc_test.rb +0 -370
  185. data/test/support/validation_test.rb +0 -54
  186. data/test/support/versions_test.rb +0 -103
  187. data/test/tap_test_helper.rb +0 -57
  188. data/test/tap_test_suite.rb +0 -7
  189. data/test/task/config/batch.yml +0 -2
  190. data/test/task/config/batched.yml +0 -2
  191. data/test/task/config/configured.yml +0 -1
  192. data/test/task/config/example.yml +0 -1
  193. data/test/task_base_test.rb +0 -24
  194. data/test/task_syntax_test.rb +0 -300
  195. data/test/task_test.rb +0 -320
  196. data/test/test/env_vars_test.rb +0 -48
  197. data/test/test/file_methods/test_assert_files/expected/one.txt +0 -1
  198. data/test/test/file_methods/test_assert_files/expected/two.txt +0 -1
  199. data/test/test/file_methods/test_assert_files/input/one.txt +0 -1
  200. data/test/test/file_methods/test_assert_files/input/two.txt +0 -1
  201. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/one.txt +0 -1
  202. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/two.txt +0 -1
  203. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +0 -1
  204. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/two.txt +0 -1
  205. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +0 -1
  206. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +0 -1
  207. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/expected/one.txt +0 -1
  208. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +0 -1
  209. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +0 -1
  210. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +0 -1
  211. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +0 -1
  212. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +0 -1
  213. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +0 -1
  214. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +0 -1
  215. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +0 -1
  216. data/test/test/file_methods/test_method_glob/expected/file.yml +0 -0
  217. data/test/test/file_methods/test_method_glob/expected/file_1.txt +0 -0
  218. data/test/test/file_methods/test_method_glob/expected/file_2.txt +0 -0
  219. data/test/test/file_methods_doc/test_sub/expected/one.txt +0 -1
  220. data/test/test/file_methods_doc/test_sub/expected/two.txt +0 -1
  221. data/test/test/file_methods_doc/test_sub/input/one.txt +0 -1
  222. data/test/test/file_methods_doc/test_sub/input/two.txt +0 -1
  223. data/test/test/file_methods_doc_test.rb +0 -29
  224. data/test/test/file_methods_test.rb +0 -275
  225. data/test/test/subset_methods_test.rb +0 -171
  226. data/test/test/tap_methods/test_assert_files/expected/task/name/a.txt +0 -1
  227. data/test/test/tap_methods/test_assert_files/expected/task/name/b.txt +0 -1
  228. data/test/test/tap_methods/test_assert_files/input/a.txt +0 -1
  229. data/test/test/tap_methods/test_assert_files/input/b.txt +0 -1
  230. data/test/test/tap_methods_test.rb +0 -399
  231. data/test/workflow_test.rb +0 -120
  232. data/vendor/rails_generator.rb +0 -56
  233. data/vendor/rails_generator/base.rb +0 -263
  234. data/vendor/rails_generator/commands.rb +0 -581
  235. data/vendor/rails_generator/generated_attribute.rb +0 -42
  236. data/vendor/rails_generator/lookup.rb +0 -209
  237. data/vendor/rails_generator/manifest.rb +0 -53
  238. data/vendor/rails_generator/options.rb +0 -143
  239. data/vendor/rails_generator/scripts.rb +0 -83
  240. data/vendor/rails_generator/scripts/destroy.rb +0 -7
  241. data/vendor/rails_generator/scripts/generate.rb +0 -7
  242. data/vendor/rails_generator/scripts/update.rb +0 -12
  243. data/vendor/rails_generator/simple_logger.rb +0 -46
  244. data/vendor/rails_generator/spec.rb +0 -44
@@ -0,0 +1,122 @@
1
+ module Tap
2
+ module Support
3
+ class Configuration
4
+ class << self
5
+ SHORT_REGEXP = /^-[A-z]$/
6
+
7
+ # Turns the input string into a short-format option. Raises
8
+ # an error if the option does not match SHORT_REGEXP.
9
+ #
10
+ # Configuration.shortify("-o") # => '-o'
11
+ # Configuration.shortify(:o) # => '-o'
12
+ #
13
+ def shortify(str)
14
+ str = str.to_s
15
+ str = "-#{str}" unless str[0] == ?-
16
+ raise "invalid short option: #{str}" unless str =~ SHORT_REGEXP
17
+ str
18
+ end
19
+
20
+ LONG_REGEXP = /^--(\[no-\])?([A-z][\w-]*)$/
21
+
22
+ # Turns the input string into a long-format option. Raises
23
+ # an error if the option does not match LONG_REGEXP.
24
+ #
25
+ # Configuration.longify("--opt") # => '--opt'
26
+ # Configuration.longify(:opt) # => '--opt'
27
+ # Configuration.longify(:opt, true) # => '--[no-]opt'
28
+ # Configuration.longify(:opt_ion) # => '--opt-ion'
29
+ # Configuration.longify(:opt_ion, false, false) # => '--opt_ion'
30
+ #
31
+ def longify(str, switch_notation=false, hyphenize=true)
32
+ str = str.to_s
33
+ str = "--#{str}" unless str.index("--")
34
+ str.gsub!(/_/, '-') if hyphenize
35
+
36
+ raise "invalid long option: #{str}" unless str =~ LONG_REGEXP
37
+
38
+ if switch_notation && $1.nil?
39
+ str = "--[no-]#{$2}"
40
+ end
41
+
42
+ str
43
+ end
44
+ end
45
+
46
+ attr_reader :name
47
+ attr_reader :reader
48
+ attr_reader :writer
49
+ attr_reader :duplicable
50
+ attr_reader :attributes
51
+
52
+ def initialize(name, default=nil, options={})
53
+ @name = name
54
+ self.default = default
55
+
56
+ self.reader = options.delete(:reader) || name
57
+ self.writer = options.delete(:writer) || "#{name}="
58
+ @attributes = options
59
+ end
60
+
61
+ # Sets the default value for self and determines if the
62
+ # default is duplicable (ie not nil, true, false, Symbol,
63
+ # Numeric, and responds_to?(:dup)).
64
+ def default=(value)
65
+ @duplicable = case value
66
+ when nil, true, false, Symbol, Numeric then false
67
+ else value.respond_to?(:dup)
68
+ end
69
+
70
+ @default = value.freeze
71
+ end
72
+
73
+ # Returns the default value, or a duplicate of the default
74
+ # value if specified and the default value is duplicable.
75
+ def default(duplicate=true)
76
+ duplicate && duplicable ? @default.dup : @default
77
+ end
78
+
79
+ # Sets the reader for self. The reader is symbolized.
80
+ def reader=(value)
81
+ @reader = value.to_sym
82
+ end
83
+
84
+ # Sets the writer for self. The writer is symbolized.
85
+ def writer=(value)
86
+ @writer = value.to_sym
87
+ end
88
+
89
+ def arg_name
90
+ attributes[:arg_name] || name.to_s.upcase
91
+ end
92
+
93
+ def arg_type
94
+ attributes[:arg_type] || :mandatory
95
+ end
96
+
97
+ def long(switch_notation=false, hyphenize=true)
98
+ Configuration.longify(attributes[:long] || name.to_s, switch_notation, hyphenize)
99
+ end
100
+
101
+ def short
102
+ attributes[:short] ? Configuration.shortify(attributes[:short]) : nil
103
+ end
104
+
105
+ def desc
106
+ attributes[:desc]
107
+ end
108
+
109
+ # True if another is a kind of Configuration with the same name,
110
+ # default value, reader and writer; other attributes are NOT
111
+ # taken into account.
112
+ def ==(another)
113
+ another.kind_of?(Configuration) &&
114
+ self.name == another.name &&
115
+ self.reader == another.reader &&
116
+ self.writer == another.writer &&
117
+ self.default(false) == another.default(false)
118
+ end
119
+
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,70 @@
1
+ require 'tap/support/constant_utils'
2
+ class String # :nodoc:
3
+ include Tap::Support::ConstantUtils
4
+ end
5
+
6
+ module Tap
7
+ module Support
8
+ class Constant
9
+
10
+ # The camelized name for self.
11
+ attr_reader :name
12
+
13
+ # The path to load to initialize the constant name.
14
+ attr_reader :require_path
15
+
16
+ def initialize(name, require_path=nil)
17
+ @name = name
18
+ @require_path = require_path
19
+ end
20
+
21
+ # Returns the underscored name.
22
+ def path
23
+ @path ||= name.underscore
24
+ end
25
+
26
+ # Returns the basename of path.
27
+ def basename
28
+ @basename ||= File.basename(path)
29
+ end
30
+
31
+ # Returns the path, minus the basename of path.
32
+ def dirname
33
+ @dirname ||= (dirname = File.dirname(path)) == "." ? "" : dirname
34
+ end
35
+
36
+ # Returns the name of the constant, minus nesting.
37
+ def const_name
38
+ @const_name ||= (name =~ /.*::(.*)$/ ? $1 : name)
39
+ end
40
+
41
+ # Returns an array of the nesting constants of name.
42
+ def nesting
43
+ @nesting ||= (name =~ /(.*)::.*$/ ? $1 : '')
44
+ end
45
+
46
+ # Returns the number of constants in nesting.
47
+ def nesting_depth
48
+ @nesting_depth ||= nesting.split(/::/).length
49
+ end
50
+
51
+ # Returns the document for require_path, if set, or nil otherwise.
52
+ def document
53
+ require_path ? Support::Lazydoc[require_path] : nil
54
+ end
55
+
56
+ def ==(another)
57
+ another.kind_of?(Constant) &&
58
+ another.name == self.name &&
59
+ another.require_path == self.require_path
60
+ end
61
+
62
+ def constantize
63
+ name.try_constantize do |const_name|
64
+ require require_path
65
+ name.constantize
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,127 @@
1
+ module Tap
2
+ module Support
3
+
4
+ # ConstantUtils provides methods for transforming strings into constants.
5
+ # Several methods are directly taken from or based heavily on the
6
+ # ActiveSupport {Inflections}[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
7
+ # module and should not cause conflicts if ActiveSupport is loaded
8
+ # alongside Tap.
9
+ #
10
+ # ActiveSupport is distributed with an MIT-LICENSE:
11
+ #
12
+ # Copyright (c) 2004-2008 David Heinemeier Hansson
13
+ #
14
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
15
+ # associated documentation files (the "Software"), to deal in the Software without restriction,
16
+ # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
17
+ # and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
18
+ # subject to the following conditions:
19
+ #
20
+ # The above copyright notice and this permission notice shall be included in all copies or substantial
21
+ # portions of the Software.
22
+ #
23
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24
+ # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
25
+ # NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ #
29
+ module ConstantUtils
30
+
31
+ # camelize converts self to UpperCamelCase. If the argument to
32
+ # camelize is set to :lower then camelize produces lowerCamelCase.
33
+ # camelize will also convert '/' to '::' which is useful for
34
+ # converting paths to namespaces.
35
+ def camelize(first_letter = :upper)
36
+ case first_letter
37
+ when :upper then self.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
38
+ when :lower then self.first + camelize[1..-1]
39
+ end
40
+ end
41
+
42
+ # The reverse of camelize. Makes an underscored, lowercase form
43
+ # from self. underscore will also change '::' to '/' to convert
44
+ # namespaces to paths.
45
+ def underscore
46
+ self.gsub(/::/, '/').
47
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
48
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
49
+ tr("-", "_").
50
+ downcase
51
+ end
52
+
53
+ # constantize tries to find a declared constant with the name specified
54
+ # by self. It raises a NameError when the name is not in CamelCase
55
+ # or is not initialized.
56
+ def constantize
57
+ case RUBY_VERSION
58
+ when /^1.9/
59
+
60
+ # a check is necessary to maintain the 1.8 behavior
61
+ # in 1.9, where ancestor constants may be returned
62
+ # by a direct evaluation
63
+ const_name.split("::").inject(Object) do |current, const|
64
+ const = const.to_sym
65
+
66
+ current.const_get(const).tap do |c|
67
+ unless current.const_defined?(const, false)
68
+ raise NameError.new("uninitialized constant #{const_name}")
69
+ end
70
+ end
71
+ end
72
+
73
+ else
74
+ Object.module_eval("::#{const_name}", __FILE__, __LINE__)
75
+ end
76
+ end
77
+
78
+ # Tries to constantize self; if a NameError is raised, try_constantize
79
+ # passes control to the block. Control is only passed if the NameError
80
+ # is for one of the constants in self.
81
+ def try_constantize
82
+ begin
83
+ constantize
84
+ rescue(NameError)
85
+ error_name = $!.name.to_s
86
+ missing_const = const_name.split(/::/).inject(Object) do |current, const|
87
+ if current.const_defined?(const)
88
+ current.const_get(const)
89
+ else
90
+ break(const)
91
+ end
92
+ end
93
+
94
+ # check that the error_name is the first missing constant
95
+ raise $! unless missing_const == error_name
96
+ yield(const_name)
97
+ end
98
+ end
99
+
100
+ def constants_split
101
+ camel_cased_word = camelize
102
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
103
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
104
+ end
105
+
106
+ constants = $1.split(/::/)
107
+ current = Object
108
+ while !constants.empty?
109
+ break unless current.const_defined?(constants[0])
110
+ current = current.const_get(constants.shift)
111
+ end
112
+
113
+ [current, constants]
114
+ end
115
+
116
+ protected
117
+
118
+ def const_name
119
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
120
+ raise NameError, "#{inspect} is not a valid constant name!"
121
+ end
122
+ $1
123
+ end
124
+
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,111 @@
1
+ module Tap
2
+ module Support
3
+ module Declarations
4
+ def self.set_declaration_base(base)
5
+ # TODO -- warn if base is Object -- conflict with Rake
6
+ declaration_base = base.to_s
7
+ declaration_base = "" if ["Object", "Tap"].include?(declaration_base)
8
+
9
+ base.instance_variable_set(:@tap_declaration_base, declaration_base.underscore)
10
+ end
11
+
12
+ def self.included(base)
13
+ set_declaration_base(base)
14
+ end
15
+
16
+ def self.extended(base)
17
+ set_declaration_base(base)
18
+ end
19
+
20
+ def tasc(name, configs={}, options={}, &block)
21
+ Tap::Task.subclass(nest(name), configs, options, &block)
22
+ end
23
+
24
+ def task(name, configs={}, options={}, &block)
25
+ options[:arity] = arity(block)
26
+ tasc(name, configs, options, &task_block(block)).new
27
+ end
28
+
29
+ def file_tasc(name, configs={}, options={}, &block)
30
+ Tap::FileTask.subclass(nest(name), configs, options, &block)
31
+ end
32
+
33
+ def file_task(name, configs={}, options={}, &block)
34
+ options[:arity] = arity(block)
35
+ file_tasc(nest(name), configs, options, &task_block(block)).new
36
+ end
37
+
38
+ def worcflow(name, configs={}, options={}, &block)
39
+ Tap::Workflow.subclass(nest(name), configs, options, &block)
40
+ end
41
+
42
+ def workflow(name, configs={}, options={}, &block)
43
+ options[:arity] = arity(block)
44
+ worcflow(name, configs, options, &task_block(block)).new
45
+ end
46
+
47
+ protected
48
+
49
+ def config(key, value=nil, options={}, &block)
50
+ caller.each_with_index do |line, index|
51
+ case line
52
+ when /^(([A-z]:)?[^:]+):(\d+)/
53
+ options[:desc] = Support::Lazydoc.register($1, $3.to_i - 1)
54
+ break
55
+ end
56
+ end if options[:desc] == nil
57
+
58
+ [:config, key, value, options, block]
59
+ end
60
+
61
+ def config_attr(key, value=nil, options={}, &block)
62
+ caller.each_with_index do |line, index|
63
+ case line
64
+ when /^(([A-z]:)?[^:]+):(\d+)/
65
+ options[:desc] = Support::Lazydoc.register($1, $3.to_i - 1)
66
+ break
67
+ end
68
+ end if options[:desc] == nil
69
+
70
+ [:config_attr, key, value, options, block]
71
+ end
72
+
73
+ def c
74
+ Support::Validation
75
+ end
76
+
77
+ private
78
+
79
+ def nest(name)
80
+ # use self if self is a Module or Class,
81
+ # or self.class if self is an instance.
82
+ File.join((self.kind_of?(Module) ? self : self.class).instance_variable_get(:@tap_declaration_base), name.to_s)
83
+ end
84
+
85
+ def arity(block)
86
+ arity = block.arity
87
+
88
+ case
89
+ when arity > 0 then arity -= 1
90
+ when arity < 0 then arity += 1
91
+ end
92
+
93
+ arity
94
+ end
95
+
96
+ def task_block(block)
97
+ lambda do |*inputs|
98
+ inputs.unshift(self)
99
+
100
+ arity = block.arity
101
+ n = inputs.length
102
+ unless n == arity || (arity < 0 && (-1-n) <= arity)
103
+ raise ArgumentError.new("wrong number of arguments (#{n} for #{arity})")
104
+ end
105
+
106
+ block.call(*inputs)
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,23 +1,25 @@
1
+ require 'tap/support/audit'
2
+
1
3
  module Tap
2
4
  module Support
3
- # Executable wraps methods to make them executable by App.
5
+ # Executable wraps methods to make them executable by App. Methods are
6
+ # wrapped by extending the object that receives them; the easiest way
7
+ # to make an object executable is to use Object#_method.
4
8
  module Executable
5
9
 
6
10
  # The method called when an Executable is executed via _execute
7
11
  attr_reader :_method_name
8
12
 
9
- # Indicates whether or not to call in multithread mode. Default false.
13
+ # Indicates whether or not to execute in multithread mode.
10
14
  attr_accessor :multithread
11
15
 
12
- # Stores the on complete block. Default is Executable.default_on_complete_block.
16
+ # Stores the on complete block.
13
17
  attr_reader :on_complete_block
14
18
 
15
- protected
16
-
17
- attr_writer :_method_name
18
-
19
19
  public
20
-
20
+
21
+ # Extends obj with Executable and sets up all required variables. The
22
+ # specified method will be called on _execute.
21
23
  def self.initialize(obj, method_name, multithread=false, &on_complete_block)
22
24
  obj.extend Executable
23
25
  obj.instance_variable_set(:@_method_name, method_name)
@@ -26,8 +28,9 @@ module Tap
26
28
  obj
27
29
  end
28
30
 
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
+ # Sets a block to receive the results of _execute. Raises an error
32
+ # if an on_complete block is already set. Override an existing
33
+ # on_complete block by specifying override = true.
31
34
  #
32
35
  # Note the block recieves an audited result and not
33
36
  # the result itself (see Audit for more information).
@@ -82,15 +85,25 @@ module Tap
82
85
  end
83
86
  end
84
87
 
85
- # Tap extends Object with a convenience method to generate methods
86
- # that can be enqued by App and incorporated into workflows.
88
+ # Tap extends Object with <tt>_method</tt> to generate executable methods
89
+ # that can be enqued by Tap::App and incorporated into workflows.
90
+ #
91
+ # array = []
92
+ # push_to_array = array._method(:push)
93
+ #
94
+ # task = Tap::Task.new
95
+ # task.app.sequence(task, push_to_array)
96
+ #
97
+ # task.enq(1).enq(2,3)
98
+ # task.app.run
99
+ #
100
+ # array # => [[1],[2,3]]
101
+ #
87
102
  class Object
88
103
 
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.
104
+ # Initializes a Tap::Support::Executable using the Method returned by
105
+ # Object#method(method_name), setting multithread and the on_complete
106
+ # block as specified. Returns nil if Object#method returns nil.
94
107
  def _method(method_name, multithread=false, &on_complete_block) # :yields: _result
95
108
  return nil unless m = method(method_name)
96
109
  Tap::Support::Executable.initialize(m, :call, multithread, &on_complete_block)