tap 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. data/Basic Overview +151 -0
  2. data/Command Reference +99 -0
  3. data/History +24 -0
  4. data/MIT-LICENSE +1 -1
  5. data/README +29 -57
  6. data/Rakefile +30 -37
  7. data/Tutorial +243 -191
  8. data/bin/tap +66 -35
  9. data/lib/tap.rb +47 -29
  10. data/lib/tap/app.rb +700 -342
  11. data/lib/tap/{script → cmd}/console.rb +0 -0
  12. data/lib/tap/{script → cmd}/destroy.rb +0 -0
  13. data/lib/tap/{script → cmd}/generate.rb +0 -0
  14. data/lib/tap/cmd/run.rb +156 -0
  15. data/lib/tap/constants.rb +4 -0
  16. data/lib/tap/dump.rb +57 -0
  17. data/lib/tap/env.rb +316 -0
  18. data/lib/tap/file_task.rb +106 -109
  19. data/lib/tap/generator.rb +4 -1
  20. data/lib/tap/generator/generators/command/USAGE +6 -0
  21. data/lib/tap/generator/generators/command/command_generator.rb +17 -0
  22. data/lib/tap/generator/generators/{script/templates/script.erb → command/templates/command.erb} +10 -10
  23. data/lib/tap/generator/generators/config/USAGE +21 -0
  24. data/lib/tap/generator/generators/config/config_generator.rb +17 -7
  25. data/lib/tap/generator/generators/file_task/USAGE +3 -0
  26. data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -0
  27. data/lib/tap/generator/generators/file_task/templates/file.txt +2 -0
  28. data/lib/tap/generator/generators/file_task/templates/file.yml +3 -0
  29. data/lib/tap/generator/generators/file_task/templates/task.erb +26 -20
  30. data/lib/tap/generator/generators/file_task/templates/test.erb +20 -10
  31. data/lib/tap/generator/generators/generator/generator_generator.rb +1 -1
  32. data/lib/tap/generator/generators/generator/templates/generator.erb +21 -12
  33. data/lib/tap/generator/generators/root/templates/Rakefile +33 -24
  34. data/lib/tap/generator/generators/root/templates/tap.yml +28 -31
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +1 -0
  36. data/lib/tap/generator/generators/task/USAGE +3 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +18 -5
  38. data/lib/tap/generator/generators/task/templates/task.erb +7 -12
  39. data/lib/tap/generator/generators/task/templates/test.erb +10 -11
  40. data/lib/tap/generator/generators/workflow/templates/task.erb +1 -1
  41. data/lib/tap/generator/generators/workflow/templates/test.erb +1 -1
  42. data/lib/tap/patches/rake/rake_test_loader.rb +8 -0
  43. data/lib/tap/patches/rake/testtask.rb +55 -0
  44. data/lib/tap/patches/ruby19/backtrace_filter.rb +51 -0
  45. data/lib/tap/patches/ruby19/parsedate.rb +16 -0
  46. data/lib/tap/root.rb +172 -67
  47. data/lib/tap/script.rb +70 -336
  48. data/lib/tap/support/aggregator.rb +55 -0
  49. data/lib/tap/support/audit.rb +281 -280
  50. data/lib/tap/support/batchable.rb +59 -0
  51. data/lib/tap/support/class_configuration.rb +279 -0
  52. data/lib/tap/support/configurable.rb +92 -0
  53. data/lib/tap/support/configurable_methods.rb +296 -0
  54. data/lib/tap/support/executable.rb +98 -0
  55. data/lib/tap/support/executable_queue.rb +82 -0
  56. data/lib/tap/support/logger.rb +9 -15
  57. data/lib/tap/support/rake.rb +43 -54
  58. data/lib/tap/support/run_error.rb +32 -13
  59. data/lib/tap/support/shell_utils.rb +47 -0
  60. data/lib/tap/support/tdoc.rb +9 -8
  61. data/lib/tap/support/tdoc/config_attr.rb +40 -16
  62. data/lib/tap/support/validation.rb +77 -0
  63. data/lib/tap/support/versions.rb +36 -36
  64. data/lib/tap/task.rb +276 -482
  65. data/lib/tap/test.rb +20 -261
  66. data/lib/tap/test/env_vars.rb +7 -5
  67. data/lib/tap/test/file_methods.rb +126 -121
  68. data/lib/tap/test/subset_methods.rb +86 -45
  69. data/lib/tap/test/tap_methods.rb +271 -0
  70. data/lib/tap/workflow.rb +174 -46
  71. data/test/app/config/another/task.yml +1 -0
  72. data/test/app/config/erb.yml +2 -1
  73. data/test/app/config/some/task.yml +1 -0
  74. data/test/app/config/template.yml +2 -6
  75. data/test/app_test.rb +1241 -1008
  76. data/test/env/test_configure/recurse_a.yml +2 -0
  77. data/test/env/test_configure/recurse_b.yml +2 -0
  78. data/test/env/test_configure/tap.yml +23 -0
  79. data/test/env/test_load_env_config/dir/tap.yml +3 -0
  80. data/test/env/test_load_env_config/recurse_a.yml +2 -0
  81. data/test/env/test_load_env_config/recurse_b.yml +2 -0
  82. data/test/env/test_load_env_config/tap.yml +3 -0
  83. data/test/env_test.rb +198 -0
  84. data/test/file_task_test.rb +70 -53
  85. data/{lib/tap/generator/generators/package/USAGE → test/root/file.txt} +0 -0
  86. data/test/root_test.rb +621 -454
  87. data/test/script_test.rb +38 -174
  88. data/test/support/aggregator_test.rb +99 -0
  89. data/test/support/audit_test.rb +409 -416
  90. data/test/support/batchable_test.rb +74 -0
  91. data/test/support/{task_configuration_test.rb → class_configuration_test.rb} +106 -47
  92. data/test/{task/config/overriding.yml → support/configurable/config/configured.yml} +0 -0
  93. data/test/support/configurable_test.rb +295 -0
  94. data/test/support/executable_queue_test.rb +103 -0
  95. data/test/support/executable_test.rb +38 -0
  96. data/test/support/logger_test.rb +17 -17
  97. data/test/support/rake_test.rb +4 -2
  98. data/test/support/shell_utils_test.rb +24 -0
  99. data/test/support/tdoc_test.rb +265 -258
  100. data/test/support/validation_test.rb +54 -0
  101. data/test/support/versions_test.rb +38 -38
  102. data/test/tap_test_helper.rb +19 -5
  103. data/test/tap_test_suite.rb +5 -2
  104. data/test/task_base_test.rb +13 -104
  105. data/test/task_syntax_test.rb +300 -0
  106. data/test/task_test.rb +258 -381
  107. data/test/test/env_vars_test.rb +40 -40
  108. data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/expected/one.txt +0 -0
  109. data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/expected/two.txt +0 -0
  110. data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/input/one.txt +0 -0
  111. data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/input/two.txt +0 -0
  112. data/test/test/{test_file_task_test → file_methods/test_assert_files_can_have_no_expected_files_if_specified}/input/one.txt +0 -0
  113. data/test/test/{test_file_task_test → file_methods/test_assert_files_can_have_no_expected_files_if_specified}/input/two.txt +0 -0
  114. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +1 -0
  115. data/test/test/{test_file_task_test → file_methods/test_assert_files_fails_for_different_content}/expected/two.txt +0 -0
  116. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +1 -0
  117. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +1 -0
  118. data/test/test/{test_file_task_test → file_methods/test_assert_files_fails_for_missing_expected_file}/expected/one.txt +0 -0
  119. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +1 -0
  120. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +1 -0
  121. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +1 -0
  122. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +1 -0
  123. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +1 -0
  124. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +1 -0
  125. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +1 -0
  126. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +1 -0
  127. data/test/test/file_methods_doc/test_sub/expected/one.txt +1 -0
  128. data/test/test/file_methods_doc/test_sub/expected/two.txt +1 -0
  129. data/test/test/file_methods_doc/test_sub/input/one.txt +1 -0
  130. data/test/test/file_methods_doc/test_sub/input/two.txt +1 -0
  131. data/test/test/file_methods_doc_test.rb +29 -0
  132. data/test/test/file_methods_test.rb +214 -143
  133. data/test/test/subset_methods_test.rb +111 -115
  134. data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/expected/task/name/a.txt +0 -0
  135. data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/expected/task/name/b.txt +0 -0
  136. data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/input/a.txt +0 -0
  137. data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/input/b.txt +0 -0
  138. data/test/test/tap_methods_test.rb +399 -0
  139. data/test/workflow_test.rb +101 -91
  140. metadata +86 -70
  141. data/lib/tap/generator/generators/package/package_generator.rb +0 -38
  142. data/lib/tap/generator/generators/package/templates/package.erb +0 -186
  143. data/lib/tap/generator/generators/script/USAGE +0 -0
  144. data/lib/tap/generator/generators/script/script_generator.rb +0 -17
  145. data/lib/tap/script/run.rb +0 -154
  146. data/lib/tap/support/batch_queue.rb +0 -162
  147. data/lib/tap/support/combinator.rb +0 -114
  148. data/lib/tap/support/task_configuration.rb +0 -169
  149. data/lib/tap/support/template.rb +0 -81
  150. data/lib/tap/support/templater.rb +0 -155
  151. data/lib/tap/version.rb +0 -4
  152. data/test/app/config/addition_template.yml +0 -6
  153. data/test/app_class_test.rb +0 -33
  154. data/test/check/binding_eval.rb +0 -23
  155. data/test/check/define_method_check.rb +0 -22
  156. data/test/check/dependencies_check.rb +0 -175
  157. data/test/check/inheritance_check.rb +0 -22
  158. data/test/support/batch_queue_test.rb +0 -320
  159. data/test/support/combinator_test.rb +0 -249
  160. data/test/support/template_test.rb +0 -122
  161. data/test/support/templater/erb.txt +0 -2
  162. data/test/support/templater/erb.yml +0 -2
  163. data/test/support/templater/somefile.txt +0 -2
  164. data/test/support/templater_test.rb +0 -192
  165. data/test/task/config/template.yml +0 -4
  166. data/test/task_class_test.rb +0 -170
  167. data/test/task_execute_test.rb +0 -262
  168. data/test/test/file_methods/test_assert_expected/expected/file.txt +0 -1
  169. data/test/test/file_methods/test_assert_expected/expected/folder/file.txt +0 -1
  170. data/test/test/file_methods/test_assert_expected/input/file.txt +0 -1
  171. data/test/test/file_methods/test_assert_expected/input/folder/file.txt +0 -1
  172. data/test/test/file_methods/test_assert_files_exist/input/input_1.txt +0 -0
  173. data/test/test/file_methods/test_assert_files_exist/input/input_2.txt +0 -0
  174. data/test/test/file_methods/test_file_compare/expected/output_1.txt +0 -3
  175. data/test/test/file_methods/test_file_compare/expected/output_2.txt +0 -1
  176. data/test/test/file_methods/test_file_compare/input/input_1.txt +0 -3
  177. data/test/test/file_methods/test_file_compare/input/input_2.txt +0 -3
  178. data/test/test/file_methods/test_infer_glob/expected/file.yml +0 -0
  179. data/test/test/file_methods/test_infer_glob/expected/file_1.txt +0 -0
  180. data/test/test/file_methods/test_infer_glob/expected/file_2.txt +0 -0
  181. data/test/test/file_methods/test_yml_compare/expected/output_1.yml +0 -6
  182. data/test/test/file_methods/test_yml_compare/expected/output_2.yml +0 -6
  183. data/test/test/file_methods/test_yml_compare/input/input_1.yml +0 -4
  184. data/test/test/file_methods/test_yml_compare/input/input_2.yml +0 -4
  185. data/test/test_test.rb +0 -373
data/Tutorial CHANGED
@@ -1,235 +1,287 @@
1
- = Tutorial
1
+ = Quick Start Tutorial
2
2
 
3
- <b>Under Construction!</b>
3
+ This tutorial demonstrates the basic use of tap from the command line, how to:
4
4
 
5
- == Overview
5
+ * generate and run a task
6
+ * generate and run a command
6
7
 
7
- === Tasks
8
+ === Task Basics
8
9
 
9
- # insert task image
10
+ Begin by creating a tap root directory structure:
10
11
 
11
- Tap tasks are designed to be modular: they can be configured, they take inputs, and they
12
- produce results. On a programatic level this system is convenient for joining tasks into
13
- workflows using condition and decision blocks. On an application level, the task structure
14
- makes it easy to incorporate tasks into configurable, user-ready scripts.
12
+ % tap generate root /path/to/root_dir
13
+ % cd /path/to/root_dir
14
+
15
+ Make a task:
16
+
17
+ % tap generate task sample/task
15
18
 
16
- A task is structured like this:
19
+ Test the task (in fact using the rake test task):
20
+
21
+ % tap run test
22
+
23
+ Get help for the task:
24
+
25
+ % tap run -- sample/task --help
26
+ Sample::Task
27
+
28
+ Replace with a description. The default task simply
29
+ demonstrates the use of a config and logging.
30
+ Usage:
31
+ Replace with usage instructions
32
+
33
+ Options:
34
+ --key a sample config ('value')
35
+ --help Print this help.
36
+ --debug Trace execution and debug
37
+ --use Loads inputs from file.
38
+ --iterate Iterates over inputs.
39
+
40
+ Run the task in the most basic way:
41
+
42
+ % tap run sample/task input_one
43
+ ctl-i prints information
44
+ ctl-c interupts execution
45
+ beginning run...
46
+ I[21:32:28] sample/task input_one was processed with value
47
+
48
+ Run the task, setting the 'key' configuration and iterating over several inputs:
17
49
 
50
+ % tap run -- sample/task --key='the new value' --iterate one two three
51
+ ctl-i prints information
52
+ ctl-c interupts execution
53
+ beginning run...
54
+ I[21:33:31] sample/task one was processed with the new value
55
+ I[21:33:31] sample/task two was processed with the new value
56
+ I[21:33:31] sample/task three was processed with the new value
57
+
58
+ Run multiple tasks, or in this case the same task twice, followed by a dump task. The tasks are separated into 'rounds' of execution, where the rounds are indicated by '--' and '--+' respectively. The sample tasks in the first round run to completion before tap runs the dump task. Normally the dump task saves results to a file you specify, but with no specified file (as below) the dump is to the console:
59
+
60
+ % tap run -- sample/task one -- sample/task two --+ tap/dump
61
+ ctl-i prints information
62
+ ctl-c interupts execution
63
+ beginning run...
64
+ I[21:50:40] sample/task one was processed with value
65
+ I[21:50:40] sample/task two was processed with value
66
+ # audit:
67
+ # o-[] "two"
68
+ # o-[sample/task] "two was processed with value"
69
+ #
70
+ # o-[] "one"
71
+ # o-[sample/task] "one was processed with value"
72
+ #
73
+ # date: 2008-04-08 21:50:40
74
+ ---
75
+ sample/task (8603460):
76
+ - one was processed with value
77
+ sample/task (8602320):
78
+ - two was processed with value
79
+
80
+ Don't be thrown by the shuffled order in the dump -- the dump is valid YAML and represents the results hashed by task.
81
+
82
+ Now navigate to and open the 'lib/sample/task.rb' file. Inside you can see the class definition, with comments indicating how to define additional configurations, add command line documentation, log activity, and define the process method. Let's change it up a bit:
83
+
84
+ [lib/sample/task.rb]
18
85
  module Sample
19
- # == Documentation
20
- # This documentation is available in RDoc, as well as from the
21
- # command line, if you were to run it through tap, like this:
22
- # % tap run -- sample/task --help
23
- #
86
+ # == Description
87
+ # A simple math task that multiplies an input by a
88
+ # factor. Remember, strings can be multipled too!
24
89
  # === Usage
25
- # By default, usage info comes up as well...
90
+ # % tap run -- sample/task INPUT
26
91
  #
27
92
  class Task < Tap::Task
28
-
29
- # Configurations are defined like this. In this format,
30
- # this comment is used in generating customized RDoc
31
- # documenting the configurations and any accessors created
32
- # for them. The default 'config' creates a config reader
33
- # and writer.
34
- config :config_name, "default value" #-- a command line comment
93
+
94
+ # The sum of the inputs is multiplied by this
95
+ # factor. String factors are converted to
96
+ # an integer.
97
+ config(:factor, 2) do |value| # a factor
98
+ value.to_i
99
+ end
35
100
 
36
- # Process receives each input from the command line
37
- # and can do arbitrary work to make an output.
38
101
  def process(input)
39
- # ... log a message and return the input plus one ...
40
- log "#{self.name} recieved #{input}"
41
- input + 1
102
+ result = input * factor
103
+ log self.name, result
104
+
105
+ result
42
106
  end
107
+
43
108
  end
44
109
  end
45
110
 
46
- Once instantiated, tasks can be joined into a workflow by the Tap application, which is
47
- made to work with a standard directory structure. The basics looks like this:
111
+ The new configurations and documentation are immediately available:
48
112
 
49
- tap
50
- |- Rakefile
51
- |- ReadMe.txt
52
- |- config
53
- | `- sample
54
- | `- task.yml # a default config file for Sample::Task
55
- |- lib
56
- | `- sample
57
- | `- task.rb # a class file like above
58
- |- tap.yml # a configuration file for Tap::App
59
- `- test
60
- |- sample
61
- | `- task_test.rb # a test file for Sample::Task
62
- |- tap_test_helper.rb
63
- `- tap_test_suite.rb
113
+ % tap run -- sample/task --help
114
+ Sample::Task
64
115
 
65
- All task instances have a name, which by default serves as the relative filepath from an
66
- application directory to assoicated files. So for instance when the application instantiates
67
- a task by the name 'sample/task' it sets the task configs from 'config/sample/task.yml'.
68
- Any number of configurations can exist for a single task class. In addition, Tap knows
69
- how to load unknown task classes by name or via mapping...
116
+ A simple math task that multiplies an input by a
117
+ factor. Remember, strings can be multipled too!
118
+ Usage:
119
+ % tap run -- sample/task INPUT
70
120
 
71
- app = Tap:App.instance
72
- app.root = '/path/to/tap'
73
-
74
- # set up a mapping between a name and a task class
75
- app.map("two" => Sample::Task)
121
+ Options:
122
+ --factor a factor (2)
123
+ --help Print this help.
124
+ --debug Trace execution and debug
125
+ --use Loads inputs from file.
126
+ --iterate Iterates over inputs.
76
127
 
77
- # the task method looks up and instantiates the proper
78
- # task, with the input name and configuration (if the
79
- # config file exists)
80
-
81
- t1 = app.task("sample/task") # configured from 'config/sample/task.yml'
82
- t2 = app.task("task_two") # configured from 'config/task_two.yml'
83
-
84
- # the idea is the same if you manually make a task...
85
- # t3 is configured from 'config/task_three.yml'
86
-
87
- t3 = Tap::Task.new("task_three") do |task, input|
88
- log "#{task.name} recieved #{input}"
89
- input + 1
90
- end
91
-
92
- t1.class # => Sample::Task
93
- t2.class # => Sample::Task
94
- t3.class # => Tap::Task
128
+ And the task is ready to go:
95
129
 
96
- === Workflows
130
+ % tap run -- sample/task "yo"
131
+ ctl-i prints information
132
+ ctl-c interupts execution
133
+ beginning run...
134
+ I[22:22:13] sample/task yo yo
135
+
136
+ Make a configuration file for the task:
97
137
 
98
- # insert workflow image
138
+ % tap generate config sample/task
139
+
140
+ You get documentation in the configuration file as well. We can set configurations here and have them be used by the task:
99
141
 
100
- Once tasks are instantiated, they can be joined into workflows, and run with inputs.
101
- Tasks are joined using a condition block and a decision (on_complete) block that runs
102
- when the task finishes. Arbitrary workflow logic can be used to join tasks in this
103
- way, but by default Tap supports sequencing, forking, and merging.
142
+ [config/sample/task.yml]
143
+ # Sample::Task configuration
104
144
 
105
- --
106
- ...and multithread execution of tasks.
107
- Add this when multithreading works properly.
108
- ++
145
+ # The sum of the inputs is multiplied by this
146
+ # factor. String factors are converted to
147
+ # an integer.
148
+ # a factor (2)
149
+ factor: 3
109
150
 
110
- # using the same tasks as above...
111
-
112
- app.sequence(t1, t2, t3)
113
- app.run(t1, 0)
151
+ As can be seen here:
114
152
 
115
- # the log output is like this:
116
- #
117
- # I[10:38:06] sample/task recieved 0
118
- # I[10:38:06] task_two recieved 1
119
- # I[10:38:06] task_three recieved 2
120
- # I[10:38:06] sample/task recieved 3
153
+ % tap run -- sample/task yo
154
+ ctl-i prints information
155
+ ctl-c interupts execution
156
+ beginning run...
157
+ I[22:26:41] sample/task yo yo yo
158
+
159
+ If you need to batch run the same task with the same inputs, but multiple sets of configurations, simply define an array of configurations in the config file:
160
+
161
+ [config/sample/task.yml]
162
+ # Sample::Task configuration
163
+ - factor: 1
164
+ - factor: 2
165
+ - factor: 3
121
166
 
122
- Workflows can be constructed as tasks themselves, and joined with other tasks and
123
- workflows in the same fashion.
167
+ % tap run -- sample/task yo
168
+ ctl-i prints information
169
+ ctl-c interupts execution
170
+ beginning run...
171
+ I[22:37:46] sample/task yo
172
+ I[22:37:46] sample/task yo yo
173
+ I[22:37:46] sample/task yo yo yo
124
174
 
125
- == Running Tap from the Command Line
175
+ === Command Basics
126
176
 
127
- The tap command is a gateway for the execution of other subcommands. To
128
- get general help for tap, type:
177
+ Now say you want to do something fancier than the basic execution provided by the run command. First, generate a new command:
129
178
 
130
- % tap --help
179
+ % tap generate command echo
131
180
 
132
- The tap command does only a few things. It's main responsibility is configuring
133
- Tap::App.instance with 'tap.yml' from the present working directory, if it exists,
134
- running any before/after scripts specified therein, and passing control to the
135
- specifed subcommand. Subcommand help can be obtained using:
181
+ The new command is now available from tap:
136
182
 
137
- % tap [subcommand] --help
183
+ % tap echo --help
184
+ tap echo {options} ARGS...
138
185
 
139
- === run
186
+ The default command simply prints the input arguments
187
+ and application information, then exits.
140
188
 
141
- The run subcommand configures, enqueues, and executes tasks. Run has a rich
142
- syntax allowing the full specification of any number of tasks which simplifies
143
- under most circumstances. Several examples illustrate the key points:
189
+ Options:
190
+ --help (-h) Print this help.
191
+ --debug Specifies debug mode.
192
+
193
+ % tap echo one two three
194
+ Received: one, two, three
195
+ state: 0 (READY) queue: 0 thread_queue: 0 threads: 0 results: 0
144
196
 
145
- % tap run sample/task
146
- % tap run -- sample/task
147
-
148
- Both of these commands are equivalent but the second statement is a more
149
- formally correct syntax. The option break '--' signifies the start of a task (or
150
- equivalently a break in processing statements) and is essential to pass options
151
- to the task:
197
+ The command script itself is very general and can be run through ruby directly. The tap command basically just sets up the environment using tap.yml and then loads the command script, hence you can do whatever you like within the command script. Lets open it up and change a few things:
152
198
 
153
- % tap run --debug -- sample/task --key=value
199
+ [cmd/echo.rb]
200
+ # = Usage
201
+ # tap echo {options} ARGS...
202
+ #
203
+ # = Description
204
+ # Formats the inputs, then echoes them to the
205
+ # 'echo/output.txt' file and to the console.
206
+ #
154
207
 
155
- Here run recieves the '--debug' option and sample/task recieves the
156
- '--key=value' option'. Inputs work the same way. By default task options
157
- are used to set configurations, and inputs enqued to the task. For example:
158
-
159
- % tap run -- sample/task --key=value one -- another/task two three
208
+ require 'tap'
209
+ require 'tap/script'
160
210
 
161
- Specifies the following:
162
-
163
- t1 = app.task('sample/task', :key => 'value')
164
- app.queue.enq(t1, 'one')
211
+ app = Tap::App.instance
165
212
 
166
- t2 = app.task('another/task')
167
- app.queue.enq(t2, 'two', 'three')
213
+ #
214
+ # handle options
215
+ #
168
216
 
169
- Any number of tasks, configurations, and inputs may be specified in this
170
- way. As a special note, rake tasks can be specifed as well. If the app cannot
171
- find a tap task by the specified name, rake is loaded (using the same loading
172
- rules as the rake command) and run tries to find a corresponding rake task.
173
- ENV options can be specified in the rake statement.
174
-
175
- % tap run -- sample/task --key=value one -- rake_task KEY=value
217
+ opts = [
218
+ ['--help', '-h', GetoptLong::NO_ARGUMENT, "Print this help."],
219
+ ['--debug', nil, GetoptLong::NO_ARGUMENT, "Specifies debug mode."]]
220
+
221
+ Tap::Script.handle_options(*opts) do |opt, value|
222
+ case opt
223
+ when '--help'
224
+ puts Tap::Script.usage(__FILE__, "Usage", "Description", "Information", :keep_headers => false)
225
+ puts
226
+ puts "Options:"
227
+ puts Tap::Script.usage_options(opts)
228
+ exit
229
+
230
+ when '--debug'
231
+ app.options.debug = true
176
232
 
177
- Non-string inputs can be provided as well. If the input begins with "---\n"
178
- then it will be loaded as YAML into an object before being passed to a task.
179
- The syntax can be a lot to type, but is very handy to have around especially
180
- when tap is lauched automatically or from some other program. The following
181
- enques 'sample/task' with a hash input, {'number' => 1}.
182
-
183
- % tap -- sample/task "---
184
- > number: 1"
185
-
186
- On Windows, you need to pull some tricks to get newlines into your argument.
187
- Cleverly use a caret to ignore the next line feed:
188
-
189
- % tap -- sample/task '---^
190
- More?
191
- More? key: value'
233
+ end
234
+ end
235
+
236
+ #
237
+ # initialize some tasks
238
+ #
239
+
240
+ # transform the inputs
241
+ t1 = Tap::Task.new do |task, *inputs|
242
+ inputs.collect {|input| "echo #{input}" }.join("\n")
243
+ end
244
+
245
+ # write to a file
246
+ t2 = Tap::FileTask.new do |task, input|
247
+ target = "echo/output.txt"
248
+
249
+ # backup existing files, and ensure the directory exists
250
+ task.prepare(target)
251
+
252
+ File.open(target, "wb") {|f| f << input }
253
+ target
254
+ end
255
+
256
+ # now make a simple workflow
257
+ app.sequence(t1, t2)
258
+
259
+ #
260
+ # enque, run, and print out the results
261
+ #
262
+
263
+ t1.enq(*ARGV)
264
+ app.run
265
+
266
+ app.results(t2).each do |target|
267
+ puts "[#{target}]"
268
+ puts File.read(target)
269
+ end
270
+
271
+ Now run the command a few times:
272
+
273
+ % tap echo one two three
274
+ [echo/output.txt]
275
+ echo one
276
+ echo two
277
+ echo three
278
+
279
+ % tap echo tip top tap
280
+ [echo/output.txt]
281
+ echo tip
282
+ echo top
283
+ echo tap
284
+
285
+ You should find that the 'echo/output.txt' file exists with the 'tip top tap' result. Moreover a backup directory will exist with the 'one two three' result, due to the FileTask#prepare method.
192
286
 
193
- Notice that hitting enter every other line is what actually puts the "\n" into the
194
- parameter. Keep using carets to enter more lines. The syntax on Windows isn't
195
- exactly pretty, but it works.
196
-
197
- === generate/destroy
198
-
199
- Generate and destory are subcommands launching generators. They use the
200
- same back-end code as Rails generators, and are used identically. By default
201
- Tap provides generators for:
202
-
203
- - root (creating the basic Tap directory structure)
204
- - task
205
- - file_task
206
- - workflow
207
- - config
208
- - script
209
- - package
210
-
211
- --
212
- Consult the help for each of these generators:
213
-
214
- % tap [generate/destroy] [generator] --help
215
287
 
216
- ++
217
-
218
- === console
219
-
220
- Console opens an irb session with Tap loaded. Here you can directly interact
221
- with your code. Console defines a variable 'app' referencing Tap::App.instance,
222
- for easy access.
223
-
224
- % tap console
225
- irb(main):001:0> app.log(:hello)
226
- I[17:18:53] hello
227
- => true
228
- irb(main):002:0>
229
-
230
- For actively testing your code, remember that many of your files will be loaded
231
- using Dependencies (from ActiveSupport). You can modify your code, clear the
232
- dependencies, and observe the changes within a single session. The irb
233
- command is:
234
-
235
- irb(main):001:0>Dependencies.clear