tap 0.7.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. data/MIT-LICENSE +21 -0
  2. data/README +71 -0
  3. data/Rakefile +117 -0
  4. data/bin/tap +63 -0
  5. data/lib/tap.rb +15 -0
  6. data/lib/tap/app.rb +739 -0
  7. data/lib/tap/file_task.rb +354 -0
  8. data/lib/tap/generator.rb +29 -0
  9. data/lib/tap/generator/generators/config/USAGE +0 -0
  10. data/lib/tap/generator/generators/config/config_generator.rb +23 -0
  11. data/lib/tap/generator/generators/config/templates/config.erb +2 -0
  12. data/lib/tap/generator/generators/file_task/USAGE +0 -0
  13. data/lib/tap/generator/generators/file_task/file_task_generator.rb +21 -0
  14. data/lib/tap/generator/generators/file_task/templates/task.erb +27 -0
  15. data/lib/tap/generator/generators/file_task/templates/test.erb +12 -0
  16. data/lib/tap/generator/generators/root/USAGE +0 -0
  17. data/lib/tap/generator/generators/root/root_generator.rb +36 -0
  18. data/lib/tap/generator/generators/root/templates/Rakefile +48 -0
  19. data/lib/tap/generator/generators/root/templates/app.yml +19 -0
  20. data/lib/tap/generator/generators/root/templates/config/process_tap_request.yml +4 -0
  21. data/lib/tap/generator/generators/root/templates/lib/process_tap_request.rb +26 -0
  22. data/lib/tap/generator/generators/root/templates/public/images/nav.jpg +0 -0
  23. data/lib/tap/generator/generators/root/templates/public/stylesheets/color.css +57 -0
  24. data/lib/tap/generator/generators/root/templates/public/stylesheets/layout.css +108 -0
  25. data/lib/tap/generator/generators/root/templates/public/stylesheets/normalize.css +40 -0
  26. data/lib/tap/generator/generators/root/templates/public/stylesheets/typography.css +21 -0
  27. data/lib/tap/generator/generators/root/templates/server/config/environment.rb +60 -0
  28. data/lib/tap/generator/generators/root/templates/server/lib/tasks/clear_database_prerequisites.rake +5 -0
  29. data/lib/tap/generator/generators/root/templates/server/test/test_helper.rb +53 -0
  30. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +3 -0
  31. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +4 -0
  32. data/lib/tap/generator/generators/task/USAGE +0 -0
  33. data/lib/tap/generator/generators/task/task_generator.rb +21 -0
  34. data/lib/tap/generator/generators/task/templates/task.erb +21 -0
  35. data/lib/tap/generator/generators/task/templates/test.erb +29 -0
  36. data/lib/tap/generator/generators/workflow/USAGE +0 -0
  37. data/lib/tap/generator/generators/workflow/templates/task.erb +16 -0
  38. data/lib/tap/generator/generators/workflow/templates/test.erb +7 -0
  39. data/lib/tap/generator/generators/workflow/workflow_generator.rb +21 -0
  40. data/lib/tap/generator/options.rb +26 -0
  41. data/lib/tap/generator/usage.rb +26 -0
  42. data/lib/tap/root.rb +275 -0
  43. data/lib/tap/script/console.rb +7 -0
  44. data/lib/tap/script/destroy.rb +8 -0
  45. data/lib/tap/script/generate.rb +8 -0
  46. data/lib/tap/script/run.rb +111 -0
  47. data/lib/tap/script/server.rb +12 -0
  48. data/lib/tap/support/audit.rb +415 -0
  49. data/lib/tap/support/batch_queue.rb +165 -0
  50. data/lib/tap/support/combinator.rb +114 -0
  51. data/lib/tap/support/logger.rb +91 -0
  52. data/lib/tap/support/rap.rb +38 -0
  53. data/lib/tap/support/run_error.rb +20 -0
  54. data/lib/tap/support/template.rb +81 -0
  55. data/lib/tap/support/templater.rb +155 -0
  56. data/lib/tap/support/versions.rb +63 -0
  57. data/lib/tap/task.rb +448 -0
  58. data/lib/tap/test.rb +320 -0
  59. data/lib/tap/test/env_vars.rb +16 -0
  60. data/lib/tap/test/inference_methods.rb +298 -0
  61. data/lib/tap/test/subset_methods.rb +260 -0
  62. data/lib/tap/version.rb +3 -0
  63. data/lib/tap/workflow.rb +73 -0
  64. data/test/app/config/addition_template.yml +6 -0
  65. data/test/app/config/batch.yml +2 -0
  66. data/test/app/config/empty.yml +0 -0
  67. data/test/app/config/erb.yml +1 -0
  68. data/test/app/config/template.yml +6 -0
  69. data/test/app/config/version-0.1.yml +1 -0
  70. data/test/app/config/version.yml +1 -0
  71. data/test/app/lib/app_test_task.rb +2 -0
  72. data/test/app_class_test.rb +33 -0
  73. data/test/app_test.rb +1372 -0
  74. data/test/file_task/config/batch.yml +2 -0
  75. data/test/file_task/config/configured.yml +1 -0
  76. data/test/file_task/old_file_one.txt +0 -0
  77. data/test/file_task/old_file_two.txt +0 -0
  78. data/test/file_task_test.rb +1041 -0
  79. data/test/root/alt_lib/alt_module.rb +4 -0
  80. data/test/root/lib/absolute_alt_filepath.rb +2 -0
  81. data/test/root/lib/alternative_filepath.rb +2 -0
  82. data/test/root/lib/another_module.rb +2 -0
  83. data/test/root/lib/nested/some_module.rb +4 -0
  84. data/test/root/lib/no_module_included.rb +0 -0
  85. data/test/root/lib/some/module.rb +4 -0
  86. data/test/root/lib/some_class.rb +2 -0
  87. data/test/root/lib/some_module.rb +3 -0
  88. data/test/root/load_path/load_path_module.rb +2 -0
  89. data/test/root/load_path/skip_module.rb +2 -0
  90. data/test/root/mtime/older.txt +0 -0
  91. data/test/root/unload/full_path.rb +2 -0
  92. data/test/root/unload/loaded_by_nested.rb +2 -0
  93. data/test/root/unload/nested/nested_load.rb +6 -0
  94. data/test/root/unload/nested/nested_with_ext.rb +4 -0
  95. data/test/root/unload/nested/relative_path.rb +4 -0
  96. data/test/root/unload/older.rb +2 -0
  97. data/test/root/unload/unload_base.rb +9 -0
  98. data/test/root/versions/another.yml +0 -0
  99. data/test/root/versions/file-0.1.2.yml +0 -0
  100. data/test/root/versions/file-0.1.yml +0 -0
  101. data/test/root/versions/file.yml +0 -0
  102. data/test/root_test.rb +483 -0
  103. data/test/support/audit_test.rb +449 -0
  104. data/test/support/batch_queue_test.rb +320 -0
  105. data/test/support/combinator_test.rb +249 -0
  106. data/test/support/logger_test.rb +31 -0
  107. data/test/support/template_test.rb +122 -0
  108. data/test/support/templater/erb.txt +2 -0
  109. data/test/support/templater/erb.yml +2 -0
  110. data/test/support/templater/somefile.txt +2 -0
  111. data/test/support/templater_test.rb +192 -0
  112. data/test/support/versions_test.rb +71 -0
  113. data/test/tap_test_helper.rb +4 -0
  114. data/test/tap_test_suite.rb +4 -0
  115. data/test/task/config/batch.yml +2 -0
  116. data/test/task/config/batched.yml +2 -0
  117. data/test/task/config/configured.yml +1 -0
  118. data/test/task/config/example.yml +1 -0
  119. data/test/task/config/overriding.yml +2 -0
  120. data/test/task/config/task_with_config.yml +1 -0
  121. data/test/task/config/template.yml +4 -0
  122. data/test/task_class_test.rb +118 -0
  123. data/test/task_execute_test.rb +233 -0
  124. data/test/task_test.rb +424 -0
  125. data/test/test/inference_methods/test_assert_expected/expected/file.txt +1 -0
  126. data/test/test/inference_methods/test_assert_expected/expected/folder/file.txt +1 -0
  127. data/test/test/inference_methods/test_assert_expected/input/file.txt +1 -0
  128. data/test/test/inference_methods/test_assert_expected/input/folder/file.txt +1 -0
  129. data/test/test/inference_methods/test_assert_files_exist/input/input_1.txt +0 -0
  130. data/test/test/inference_methods/test_assert_files_exist/input/input_2.txt +0 -0
  131. data/test/test/inference_methods/test_file_compare/expected/output_1.txt +3 -0
  132. data/test/test/inference_methods/test_file_compare/expected/output_2.txt +1 -0
  133. data/test/test/inference_methods/test_file_compare/input/input_1.txt +3 -0
  134. data/test/test/inference_methods/test_file_compare/input/input_2.txt +3 -0
  135. data/test/test/inference_methods/test_infer_glob/expected/file.yml +0 -0
  136. data/test/test/inference_methods/test_infer_glob/expected/file_1.txt +0 -0
  137. data/test/test/inference_methods/test_infer_glob/expected/file_2.txt +0 -0
  138. data/test/test/inference_methods/test_yml_compare/expected/output_1.yml +6 -0
  139. data/test/test/inference_methods/test_yml_compare/expected/output_2.yml +6 -0
  140. data/test/test/inference_methods/test_yml_compare/input/input_1.yml +4 -0
  141. data/test/test/inference_methods/test_yml_compare/input/input_2.yml +4 -0
  142. data/test/test/inference_methods_test.rb +311 -0
  143. data/test/test/subset_methods_test.rb +115 -0
  144. data/test/test_test.rb +233 -0
  145. data/test/workflow_test.rb +108 -0
  146. metadata +274 -0
@@ -0,0 +1,354 @@
1
+ module Tap
2
+
3
+ # FileTask provides methods for making files
4
+
5
+ # FileTask process adds error handling code to restore any files marked
6
+ # for backup or files that were made (using make or mkdir) if an unhandled
7
+ # error occurs during processing. Set +restore_on_error+ to false to
8
+ # turn off automatic restore. In addtion, backed-up files can be removed
9
+ # when process completes by setting +remove_backed_up_files+ to true.
10
+ class FileTask < Task
11
+ set_default_config({
12
+ :backup_dir => :backup,
13
+ :backup_timestamp => "%Y%m%d_%H%M%S",
14
+ :restore_on_error => true,
15
+ :remove_backed_up_files => false},
16
+ :make_accessors => true)
17
+
18
+ attr_reader :inference_block, :backed_up_files, :made_files
19
+ attr_accessor :dirname
20
+
21
+ def initialize(*args)
22
+ super
23
+
24
+ batch.each do |task|
25
+ task.dirname = task.default_dirname
26
+ task.backed_up_files = {}
27
+ task.made_files = []
28
+ end
29
+ end
30
+
31
+ # Sets a block to perform path inference. Raises an error if inference_block
32
+ # is already set, unless override = true.
33
+ def inference(override=false, &block) # :yields: app[dir], dirname, *paths
34
+ raise "Inference block for task already set: #{name}" unless inference_block.nil? || override
35
+ self.inference_block = block
36
+ end
37
+
38
+ # Infers a path using the inference block, or by using app.filepath if
39
+ # no inference block is given. Note the actual inputs to the inference
40
+ # block are the application directory identified by dir, the dirname
41
+ # for the task, and the provided paths.
42
+ #
43
+ # t = FileTask.new
44
+ # t.app[:data] # => "/data"
45
+ # t.dirname # => "tap/file_task"
46
+ # t.infer_filepath(:data, "result.txt") # => "/data/tap/file_task/result.txt"
47
+ #
48
+ # t.inference do |root, dir, path|
49
+ # File.join(root, dir, path.chomp(".txt") + ".yml")
50
+ # end
51
+ #
52
+ # t.infer_filepath(:data, "result.txt") # => "/data/tap/file_task/result.yml"
53
+ #
54
+ def infer_filepath(dir, *paths) # :yields: app[dir], dirname, *paths
55
+ inference_block ?
56
+ inference_block.call(app[dir], dirname, *paths) :
57
+ app.filepath(dir, dirname, *paths)
58
+ end
59
+
60
+ # Makes a backup filepath for input filepath by doing the following:
61
+ # - insert a timestamp between the basename and extname of the filepath
62
+ # - identify a backup path as the part of the filepath relative to
63
+ # dirname, or the basename if the filepath is not relative to dirname
64
+ # - infer_filepath using the backup_dir and this backup path
65
+ #
66
+ # t = FileTask.new("dir/name", :backup_dir => :backup, :backup_timestamp => "%Y%m%d")
67
+ # t.app[:backup] # => "/backup"
68
+ # Date.today.to_s # => "2007-08-08"
69
+ #
70
+ # t.backup_filepath("path/to/folder/file.txt") # => "/backup/file_20070808.txt"
71
+ # t.backup_filepath("dir/name/folder/file.txt") # => "/backup/folder/file_20070808.txt"
72
+ #
73
+ def backup_filepath(filepath)
74
+ extname = File.extname(filepath)
75
+ backup_path = File.expand_path("#{filepath.chomp(extname)}_#{Time.now.strftime(backup_timestamp)}#{extname}")
76
+
77
+ split_index = backup_path.index(dirname + "/")
78
+ backup_path = split_index ?
79
+ backup_path[(split_index + dirname.length + 1)..-1] :
80
+ File.basename(backup_path)
81
+
82
+ infer_filepath(backup_dir, backup_path)
83
+ end
84
+
85
+ # A batch File.open method. If a block is given, each file in the list will be
86
+ # opened the open files passed to the block. Files are automatically closed when
87
+ # the block returns. If no block is given, the open files are returned.
88
+ def open(list, mode="rb")
89
+ open_files = []
90
+ begin
91
+ fu_list(list).each do |filepath|
92
+ open_files << File.open(filepath, mode)
93
+ end
94
+
95
+ block_given? ? yield(open_files) : open_files
96
+ ensure
97
+ open_files.each {|file| file.close } if block_given?
98
+ end
99
+ end
100
+
101
+ # Returns true if all of the targets are up to date relative to all of the sources
102
+ # AND the task config_file (if it exists). Single values or arrays can be provided
103
+ # for both targets and sources.
104
+ #
105
+ # Returns false if +force?+ is true.
106
+ def uptodate?(targets, sources=[])
107
+ if app.options.force
108
+ log_filepaths(:force, *targets)
109
+ false
110
+ else
111
+ targets = [targets] unless targets.kind_of?(Array)
112
+ sources = [sources] unless sources.kind_of?(Array)
113
+ sources << config_file
114
+ targets.each do |target|
115
+ return false unless FileUtils.uptodate?(target, sources)
116
+ end
117
+ true
118
+ end
119
+ end
120
+
121
+ # Makes a backup of each file in list to backup_filepath(file) and registers
122
+ # the files so that they can be restored using restore. If copy is true, the
123
+ # files will be copied to backup_filepath, otherwise the file is moved to
124
+ # backup_filepath. Raises an error if the file is already backed up.
125
+ #
126
+ # Returns a list of the backup_filepaths.
127
+ def backup(list, copy=true)
128
+ fu_list(list).collect do |filepath|
129
+ next unless File.exists?(filepath)
130
+
131
+ filepath = File.expand_path(filepath)
132
+ if backed_up_files.include?(filepath)
133
+ raise "Backup for #{filepath} already exists."
134
+ end
135
+
136
+ target = File.expand_path(backup_filepath(filepath))
137
+ dir = File.dirname(target)
138
+ mkdir(dir)
139
+
140
+ if copy
141
+ log :cp, "#{filepath} to #{target}", Logger::DEBUG
142
+ FileUtils.cp(filepath, target)
143
+ else
144
+ log :mv, "#{filepath} to #{target}", Logger::DEBUG
145
+ FileUtils.mv(filepath, target)
146
+ end
147
+
148
+ # track the target for restores
149
+ backed_up_files[filepath] = target
150
+ target
151
+ end
152
+ end
153
+
154
+ # Restores a backed-up file to its original location and removes the
155
+ # directory of the backup if it is empty. Returns the restored files.
156
+ def restore(list)
157
+ fu_list(list).collect do |filepath|
158
+ filepath = File.expand_path(filepath)
159
+ raise "No backed up file for: #{filepath}" unless backed_up_files.has_key?(filepath)
160
+
161
+ target = backed_up_files.delete(filepath)
162
+
163
+ dir = File.dirname(filepath)
164
+ mkdir(dir)
165
+
166
+ log :restore, "#{target} to #{filepath}", Logger::DEBUG
167
+ FileUtils.mv(target, filepath, :force => true)
168
+
169
+ dir = File.dirname(target)
170
+ rmdir(dir)
171
+
172
+ filepath
173
+ end
174
+ end
175
+
176
+ # Creates the directories in list if they do not exist and adds
177
+ # them to made_files so they can be removed using rmdir.
178
+ #
179
+ # Returns the made directories.
180
+ def mkdir(list)
181
+ fu_list(list).each do |dir|
182
+ dir = File.expand_path(dir)
183
+
184
+ make_paths = []
185
+ while !File.exists?(dir)
186
+ make_paths << dir
187
+ dir = File.dirname(dir)
188
+ end
189
+
190
+ make_paths.reverse_each do |dir|
191
+ log :mkdir, dir, Logger::DEBUG
192
+ FileUtils.mkdir(dir)
193
+ made_files << dir
194
+ end
195
+ end
196
+ end
197
+
198
+ # Removes each directory in the input list, provided the directory is in
199
+ # made_files and the directory is empty. When checking if the directory
200
+ # is empty, rmdir checks for regular files and hidden files. Removed
201
+ # directories are removed from made_files.
202
+ #
203
+ # Returns a list of the removed directories.
204
+ def rmdir(list)
205
+ removed = []
206
+ fu_list(list).each do |dir|
207
+ dir = File.expand_path(dir)
208
+
209
+ # remove directories and parents until the
210
+ # directory was not made by the task
211
+ while made_files.include?(dir)
212
+ break unless Dir.entries(dir).delete_if {|d| d == "." || d == ".."}.empty?
213
+
214
+ if File.exists?(dir)
215
+ log :rmdir, dir, Logger::DEBUG
216
+ FileUtils.rmdir(dir)
217
+ end
218
+
219
+ removed << made_files.delete(dir)
220
+ dir = File.dirname(dir)
221
+ end
222
+ end
223
+ removed
224
+ end
225
+
226
+ # Make prepares the input list of files by backing them up (if they exist),
227
+ # ensuring that the parent directory for the file exists, and adds each file
228
+ # to made_files. As a result the files can be removed using rm, and
229
+ # the original files restored using restore.
230
+ #
231
+ # Returns the made files.
232
+ def make(list) # :yields: list
233
+ list = fu_list(list)
234
+ existing_files, non_existant_files = list.partition do |filepath|
235
+ File.exists?(filepath)
236
+ end
237
+
238
+ # backup existing files
239
+ existing_files.each do |filepath|
240
+ backup(filepath, false)
241
+ made_files << File.expand_path(filepath)
242
+ end
243
+
244
+ # ensure the parent directory exists
245
+ # for non-existant files
246
+ non_existant_files.each do |filepath|
247
+ dir = File.dirname(filepath)
248
+ mkdir(dir)
249
+ made_files << File.expand_path(filepath)
250
+ end
251
+
252
+ yield list if block_given?
253
+
254
+ list
255
+ end
256
+
257
+ # Removes each file in the input list, provided the file is in made_files.
258
+ # The parent directory of each file is removed using rmdir. Removed files
259
+ # are removed from made_files.
260
+ #
261
+ # Returns the removed files and directories.
262
+ def rm(list)
263
+ removed = []
264
+ fu_list(list).each do |filepath|
265
+ filepath = File.expand_path(filepath)
266
+ next unless made_files.include?(filepath)
267
+
268
+ # if the file exists, remove it
269
+ if File.exists?(filepath)
270
+ log :rm, filepath, Logger::DEBUG
271
+ FileUtils.rm(filepath, :force => true)
272
+ end
273
+
274
+ removed << made_files.delete(filepath)
275
+ removed.concat rmdir(File.dirname(filepath))
276
+ end
277
+ removed
278
+ end
279
+
280
+ # Logs the given action, with the basenames of the input filepaths.
281
+ def log_filepaths(action, *filepaths)
282
+ msg = filepaths.collect {|filepath| File.basename(filepath) }.join(',')
283
+ log(action , msg)
284
+ end
285
+
286
+ protected
287
+
288
+ attr_writer :inference_block, :backed_up_files, :made_files
289
+
290
+ # The default_dirname is based on the name of the task, and the
291
+ # index of the task in batch (if the task is batched):
292
+ #
293
+ # t = FileTask.new "name"
294
+ # t.default_dirname # => "name"
295
+ #
296
+ # t = FileTask.new "batched"
297
+ # t.batch[0].default_dirname # => "name_0"
298
+ # t.batch[1].default_dirname # => "name_1"
299
+ def default_dirname
300
+ batched? ? "#{name}_#{batch_index}" : name
301
+ end
302
+
303
+ def after_execute
304
+ backed_up_files.values.each do |filepath|
305
+ # the filepath needs to be added to made_files
306
+ # before it can be removed by rm
307
+ made_files << filepath
308
+ rm(filepath)
309
+ end if remove_backed_up_files
310
+ end
311
+
312
+ def on_execute_error(original_error)
313
+ restore_errors = []
314
+
315
+ if restore_on_error
316
+ made_files.dup.each do |filepath|
317
+ begin
318
+ case
319
+ when File.file?(filepath)
320
+ rm(filepath)
321
+ when File.directory?(filepath)
322
+ rmdir(filepath)
323
+ end
324
+ rescue
325
+ restore_errors << $!
326
+ end
327
+ end
328
+
329
+ backed_up_files.keys.each do |filepath|
330
+ begin
331
+ restore(filepath)
332
+ rescue
333
+ restore_errors << $!
334
+ end
335
+ end
336
+ end
337
+
338
+ # Re-raise an error unless the original error was due
339
+ # to task termination and no restore errors occured
340
+ if restore_errors.empty?
341
+ raise original_error
342
+ else
343
+ raise Support::RunError.new(original_error, restore_errors)
344
+ end
345
+ end
346
+
347
+ private
348
+
349
+ # Lifted from FileUtils
350
+ def fu_list(arg)
351
+ [arg].flatten.map {|path| path.to_str }
352
+ end
353
+ end
354
+ end
@@ -0,0 +1,29 @@
1
+ require 'active_record' # required by rails_generator, for some reason
2
+ require 'rails_generator'
3
+ require 'tap/generator/options'
4
+ require 'tap/generator/usage'
5
+
6
+ module Tap
7
+ module Generator
8
+ module Generators # :nodoc:
9
+ end
10
+ end
11
+ end
12
+
13
+ # These modifications are to make the rails generators work for Tap
14
+ module Rails # :nodoc:
15
+ module Generator # :nodoc:
16
+ class Base # :nodoc:
17
+ include Tap::Generator::Options
18
+
19
+ # Used to discover generators within tap. Adapted from code
20
+ # in 'rails/rails_generator/lookup.rb'
21
+ def self.use_tap_sources!
22
+ reset_sources
23
+ sources << PathSource.new(:builtin, "#{File.dirname(__FILE__)}/generator/generators")
24
+ sources << PathSource.new(:builtin, Tap::App.instance.filepath(:generators))
25
+ end
26
+ end
27
+ end
28
+ end
29
+
File without changes
@@ -0,0 +1,23 @@
1
+ module Tap::Generator::Generators
2
+ class ConfigGenerator < Rails::Generator::NamedBase # :nodoc:
3
+ attr_accessor :default_config
4
+
5
+ def initialize(*args)
6
+ super(*args)
7
+ @destination_root = Tap::App.instance[:root]
8
+ @app = Tap::App.instance
9
+ end
10
+
11
+ def manifest
12
+ record do |m|
13
+ task_name = class_path.empty? ? class_name : File.join(class_path, class_name)
14
+ task = @app.task(task_name)
15
+ self.default_config = task.class.default_config
16
+
17
+ config_path = @app.relative_filepath(:root, @app[:config])
18
+ m.directory File.join(config_path, class_path)
19
+ m.template "config.erb", File.join(config_path, class_name.underscore + ".yml")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,2 @@
1
+ # Configurations for <%= class_name %>
2
+ <%= default_config.stringify_keys.to_yaml %>
File without changes
@@ -0,0 +1,21 @@
1
+ module Tap::Generator::Generators
2
+ class FileTaskGenerator < Rails::Generator::NamedBase # :nodoc:
3
+ def initialize(*args)
4
+ super(*args)
5
+ @destination_root = Tap::App.instance[:root]
6
+ @app = Tap::App.instance
7
+ end
8
+
9
+ def manifest
10
+ record do |m|
11
+ lib_path = @app.relative_filepath(:root, @app[:lib])
12
+ m.directory File.join(lib_path, class_path)
13
+ m.template "task.erb", File.join(lib_path, class_name.underscore + ".rb")
14
+
15
+ test_path = @app.relative_filepath(:root, @app[:test])
16
+ m.directory File.join(test_path, class_path)
17
+ m.template "test.erb", File.join(test_path, class_name.underscore + "_test.rb")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # == Documentation
2
+ #
3
+ # === Command Line Usage
4
+ # Replace with your command line usage instructions
5
+ #
6
+ class <%= class_name %> < Tap::FileTask
7
+
8
+ def process(input)
9
+ # The process logic goes here. You don't have to use transform.
10
+ # Do whatever works!
11
+ output = infer_filepath(:data, input)
12
+
13
+ make(output)
14
+
15
+ File.open(input) do |source|
16
+ File.open(output, "w") do |target|
17
+ target.write "<root>\n"
18
+ while line = source.gets
19
+ next unless line =~ /(\w+): (\w+)/
20
+ target.write " <#{$1}>#{$2}</#{$1}>\n"
21
+ end
22
+ target.write "</root>"
23
+ end
24
+ end
25
+ end
26
+
27
+ end