tap 0.7.9
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +21 -0
- data/README +71 -0
- data/Rakefile +117 -0
- data/bin/tap +63 -0
- data/lib/tap.rb +15 -0
- data/lib/tap/app.rb +739 -0
- data/lib/tap/file_task.rb +354 -0
- data/lib/tap/generator.rb +29 -0
- data/lib/tap/generator/generators/config/USAGE +0 -0
- data/lib/tap/generator/generators/config/config_generator.rb +23 -0
- data/lib/tap/generator/generators/config/templates/config.erb +2 -0
- data/lib/tap/generator/generators/file_task/USAGE +0 -0
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +21 -0
- data/lib/tap/generator/generators/file_task/templates/task.erb +27 -0
- data/lib/tap/generator/generators/file_task/templates/test.erb +12 -0
- data/lib/tap/generator/generators/root/USAGE +0 -0
- data/lib/tap/generator/generators/root/root_generator.rb +36 -0
- data/lib/tap/generator/generators/root/templates/Rakefile +48 -0
- data/lib/tap/generator/generators/root/templates/app.yml +19 -0
- data/lib/tap/generator/generators/root/templates/config/process_tap_request.yml +4 -0
- data/lib/tap/generator/generators/root/templates/lib/process_tap_request.rb +26 -0
- data/lib/tap/generator/generators/root/templates/public/images/nav.jpg +0 -0
- data/lib/tap/generator/generators/root/templates/public/stylesheets/color.css +57 -0
- data/lib/tap/generator/generators/root/templates/public/stylesheets/layout.css +108 -0
- data/lib/tap/generator/generators/root/templates/public/stylesheets/normalize.css +40 -0
- data/lib/tap/generator/generators/root/templates/public/stylesheets/typography.css +21 -0
- data/lib/tap/generator/generators/root/templates/server/config/environment.rb +60 -0
- data/lib/tap/generator/generators/root/templates/server/lib/tasks/clear_database_prerequisites.rake +5 -0
- data/lib/tap/generator/generators/root/templates/server/test/test_helper.rb +53 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +3 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +4 -0
- data/lib/tap/generator/generators/task/USAGE +0 -0
- data/lib/tap/generator/generators/task/task_generator.rb +21 -0
- data/lib/tap/generator/generators/task/templates/task.erb +21 -0
- data/lib/tap/generator/generators/task/templates/test.erb +29 -0
- data/lib/tap/generator/generators/workflow/USAGE +0 -0
- data/lib/tap/generator/generators/workflow/templates/task.erb +16 -0
- data/lib/tap/generator/generators/workflow/templates/test.erb +7 -0
- data/lib/tap/generator/generators/workflow/workflow_generator.rb +21 -0
- data/lib/tap/generator/options.rb +26 -0
- data/lib/tap/generator/usage.rb +26 -0
- data/lib/tap/root.rb +275 -0
- data/lib/tap/script/console.rb +7 -0
- data/lib/tap/script/destroy.rb +8 -0
- data/lib/tap/script/generate.rb +8 -0
- data/lib/tap/script/run.rb +111 -0
- data/lib/tap/script/server.rb +12 -0
- data/lib/tap/support/audit.rb +415 -0
- data/lib/tap/support/batch_queue.rb +165 -0
- data/lib/tap/support/combinator.rb +114 -0
- data/lib/tap/support/logger.rb +91 -0
- data/lib/tap/support/rap.rb +38 -0
- data/lib/tap/support/run_error.rb +20 -0
- data/lib/tap/support/template.rb +81 -0
- data/lib/tap/support/templater.rb +155 -0
- data/lib/tap/support/versions.rb +63 -0
- data/lib/tap/task.rb +448 -0
- data/lib/tap/test.rb +320 -0
- data/lib/tap/test/env_vars.rb +16 -0
- data/lib/tap/test/inference_methods.rb +298 -0
- data/lib/tap/test/subset_methods.rb +260 -0
- data/lib/tap/version.rb +3 -0
- data/lib/tap/workflow.rb +73 -0
- data/test/app/config/addition_template.yml +6 -0
- data/test/app/config/batch.yml +2 -0
- data/test/app/config/empty.yml +0 -0
- data/test/app/config/erb.yml +1 -0
- data/test/app/config/template.yml +6 -0
- data/test/app/config/version-0.1.yml +1 -0
- data/test/app/config/version.yml +1 -0
- data/test/app/lib/app_test_task.rb +2 -0
- data/test/app_class_test.rb +33 -0
- data/test/app_test.rb +1372 -0
- data/test/file_task/config/batch.yml +2 -0
- data/test/file_task/config/configured.yml +1 -0
- data/test/file_task/old_file_one.txt +0 -0
- data/test/file_task/old_file_two.txt +0 -0
- data/test/file_task_test.rb +1041 -0
- data/test/root/alt_lib/alt_module.rb +4 -0
- data/test/root/lib/absolute_alt_filepath.rb +2 -0
- data/test/root/lib/alternative_filepath.rb +2 -0
- data/test/root/lib/another_module.rb +2 -0
- data/test/root/lib/nested/some_module.rb +4 -0
- data/test/root/lib/no_module_included.rb +0 -0
- data/test/root/lib/some/module.rb +4 -0
- data/test/root/lib/some_class.rb +2 -0
- data/test/root/lib/some_module.rb +3 -0
- data/test/root/load_path/load_path_module.rb +2 -0
- data/test/root/load_path/skip_module.rb +2 -0
- data/test/root/mtime/older.txt +0 -0
- data/test/root/unload/full_path.rb +2 -0
- data/test/root/unload/loaded_by_nested.rb +2 -0
- data/test/root/unload/nested/nested_load.rb +6 -0
- data/test/root/unload/nested/nested_with_ext.rb +4 -0
- data/test/root/unload/nested/relative_path.rb +4 -0
- data/test/root/unload/older.rb +2 -0
- data/test/root/unload/unload_base.rb +9 -0
- data/test/root/versions/another.yml +0 -0
- data/test/root/versions/file-0.1.2.yml +0 -0
- data/test/root/versions/file-0.1.yml +0 -0
- data/test/root/versions/file.yml +0 -0
- data/test/root_test.rb +483 -0
- data/test/support/audit_test.rb +449 -0
- data/test/support/batch_queue_test.rb +320 -0
- data/test/support/combinator_test.rb +249 -0
- data/test/support/logger_test.rb +31 -0
- data/test/support/template_test.rb +122 -0
- data/test/support/templater/erb.txt +2 -0
- data/test/support/templater/erb.yml +2 -0
- data/test/support/templater/somefile.txt +2 -0
- data/test/support/templater_test.rb +192 -0
- data/test/support/versions_test.rb +71 -0
- data/test/tap_test_helper.rb +4 -0
- data/test/tap_test_suite.rb +4 -0
- data/test/task/config/batch.yml +2 -0
- data/test/task/config/batched.yml +2 -0
- data/test/task/config/configured.yml +1 -0
- data/test/task/config/example.yml +1 -0
- data/test/task/config/overriding.yml +2 -0
- data/test/task/config/task_with_config.yml +1 -0
- data/test/task/config/template.yml +4 -0
- data/test/task_class_test.rb +118 -0
- data/test/task_execute_test.rb +233 -0
- data/test/task_test.rb +424 -0
- data/test/test/inference_methods/test_assert_expected/expected/file.txt +1 -0
- data/test/test/inference_methods/test_assert_expected/expected/folder/file.txt +1 -0
- data/test/test/inference_methods/test_assert_expected/input/file.txt +1 -0
- data/test/test/inference_methods/test_assert_expected/input/folder/file.txt +1 -0
- data/test/test/inference_methods/test_assert_files_exist/input/input_1.txt +0 -0
- data/test/test/inference_methods/test_assert_files_exist/input/input_2.txt +0 -0
- data/test/test/inference_methods/test_file_compare/expected/output_1.txt +3 -0
- data/test/test/inference_methods/test_file_compare/expected/output_2.txt +1 -0
- data/test/test/inference_methods/test_file_compare/input/input_1.txt +3 -0
- data/test/test/inference_methods/test_file_compare/input/input_2.txt +3 -0
- data/test/test/inference_methods/test_infer_glob/expected/file.yml +0 -0
- data/test/test/inference_methods/test_infer_glob/expected/file_1.txt +0 -0
- data/test/test/inference_methods/test_infer_glob/expected/file_2.txt +0 -0
- data/test/test/inference_methods/test_yml_compare/expected/output_1.yml +6 -0
- data/test/test/inference_methods/test_yml_compare/expected/output_2.yml +6 -0
- data/test/test/inference_methods/test_yml_compare/input/input_1.yml +4 -0
- data/test/test/inference_methods/test_yml_compare/input/input_2.yml +4 -0
- data/test/test/inference_methods_test.rb +311 -0
- data/test/test/subset_methods_test.rb +115 -0
- data/test/test_test.rb +233 -0
- data/test/workflow_test.rb +108 -0
- 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
|
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
|