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
@@ -1,15 +1,17 @@
1
1
  module Tap
2
2
 
3
+ # == Overview
4
+ #
3
5
  # FileTask provides methods for creating/modifying files such that you can
4
6
  # rollback changes if an error occurs. In addition, FileTask provides a
5
7
  # method to infer filepaths within the standard Tap directory structure.
6
8
  #
7
- # == Creating Files/Rolling Back Changes
9
+ # === Creating Files/Rolling Back Changes
8
10
  #
9
11
  # FileTask tracks which files to roll back using the added_files array
10
12
  # and the backed_up_files hash. On an execute error, all added files are
11
- # removed and then all backed up files (backed_up_files keys) are restored
12
- # using the corrsponding backup files (backed_up_files values).
13
+ # removed and then all backed up files (backed_up_files.keys) are restored
14
+ # using the corresponding backup files (backed_up_files.values).
13
15
  #
14
16
  # For consistency, all filepaths in added_files and backed_up_files should
15
17
  # be expanded using File.expand_path. The easiest way to ensure files are
@@ -19,7 +21,7 @@ module Tap
19
21
  # # this file will be backed up and restored
20
22
  # File.open("file.txt", "w") {|f| f << "original content"}
21
23
  #
22
- # t = FileTask.new do |task, inputs|
24
+ # t = FileTask.new do |task|
23
25
  # task.mkdir("some/dir") # marked for rollback
24
26
  # task.prepare("file.txt", "path/to/file.txt") # marked for rollback
25
27
  #
@@ -41,71 +43,39 @@ module Tap
41
43
  # File.read("file.txt") # => "original content"
42
44
  # end
43
45
  #
44
- #--
45
- # TODO - make cleanup into remove_backup_files and simply remove this
46
- # configuration. People will figure it out themselves if they want that to happen.
47
- #
48
- # The FileTask configurations modify the default backup and restore behavior.
49
- #
50
- # backup_dir:: The app directory alias for backups (default :backup)
51
- # backup_timestamp:: A strftime format string used as a timestamp for backup
52
- # files (default "%Y%m%d_%H%M%S")
53
- # rollback_on_error:: Controls whether or not added and backed up files are
54
- # rolled back on error (default true)
55
- # cleanup_after_execute:: If true, backed up files will be removed after a
56
- # successful execution (default false)
57
- #++
58
46
  class FileTask < Task
47
+ include Tap::Support::ShellUtils
48
+
59
49
  autoload(:FileUtils, "fileutils")
60
50
 
61
- class << self
62
-
63
- # A batch File.open method. If a block is given, each file in the list will be
64
- # opened the open files passed to the block. Files are automatically closed when
65
- # the block returns. If no block is given, the open files are returned.
66
- #
67
- # FileTask.open(["one.txt", "two.txt"], "w") do |one, two|
68
- # one << "one"
69
- # two << "two"
70
- # end
71
- #
72
- # File.read("one.txt") # => "one"
73
- # File.read("two.txt") # => "two"
74
- #
75
- # Note that open normally takes and passes a list (ie an Array). If you provide
76
- # a single argument, it will be translated into an Array, and passed AS AN ARRAY
77
- # to the block.
78
- #
79
- # FileTask.open("file.txt", "w") do |array|
80
- # array.first << "content"
81
- # end
82
- #
83
- # File.read("file.txt") # => "content"
84
- def open(list, mode="rb")
85
- open_files = []
86
- begin
87
- [list].flatten.map {|path| path.to_str }.each do |filepath|
88
- open_files << File.open(filepath, mode)
89
- end
90
-
91
- block_given? ? yield(open_files) : open_files
92
- ensure
93
- open_files.each {|file| file.close } if block_given?
94
- end
95
- end
96
- end
97
-
98
- write_inheritable_attribute(:backup_dir, :backup)
99
- class_inheritable_accessor(:backup_dir)
51
+ # A block used to infer filepaths. (see FileTask#filepath)
52
+ attr_reader :inference_block
100
53
 
101
- write_inheritable_attribute(:backup_timestamp, "%Y%m%d_%H%M%S")
102
- class_inheritable_accessor(:backup_timestamp)
54
+ # A hash of backup (source, target) pairs, such that the
55
+ # backed-up files are backed_up_files.keys and the actual
56
+ # backup files are backed_up_files.values. All filepaths
57
+ # in backed_up_files should be expanded.
58
+ attr_reader :backed_up_files
103
59
 
104
- write_inheritable_attribute(:rollback_on_error, true)
105
- class_inheritable_accessor(:rollback_on_error)
60
+ # An array of files added during task execution.
61
+ attr_reader :added_files
106
62
 
107
- attr_reader :inference_block, :backed_up_files, :added_files
108
- attr_accessor :dirname, :backup_dir, :backup_timestamp, :rollback_on_error
63
+ # The directory name used when infering filepaths. By
64
+ # default dirname for an unbatched task is task.name,
65
+ # or "#{task.name}_#{batch_index}" for a batched task.
66
+ # (see FileTask#default_dirname)
67
+ attr_accessor :dirname
68
+
69
+ # The backup directory, defaults to the class backup_dir
70
+ config :backup_dir, :backup
71
+
72
+ # A timestamp format used to mark backup files, defaults
73
+ # to the class backup_timestamp
74
+ config :backup_timestamp, "%Y%m%d_%H%M%S"
75
+
76
+ # A flag indicating whether or not to rollback changes on
77
+ # error, defaults to the class rollback_on_error
78
+ config :rollback_on_error, true
109
79
 
110
80
  def initialize(*args)
111
81
  super
@@ -114,10 +84,56 @@ module Tap
114
84
  task.dirname = task.default_dirname
115
85
  task.backed_up_files = {}
116
86
  task.added_files = []
117
- task.backup_dir = self.class.backup_dir
118
- task.backup_timestamp = self.class.backup_timestamp
119
- task.rollback_on_error = self.class.rollback_on_error
87
+ task.inference_block = nil
88
+ end
89
+ end
90
+
91
+ # A batch File.open method. If a block is given, each file in the list will be
92
+ # opened the open files passed to the block. Files are automatically closed when
93
+ # the block returns. If no block is given, the open files are returned.
94
+ #
95
+ # task.open(["one.txt", "two.txt"], "w") do |one, two|
96
+ # one << "one"
97
+ # two << "two"
98
+ # end
99
+ #
100
+ # File.read("one.txt") # => "one"
101
+ # File.read("two.txt") # => "two"
102
+ #
103
+ # Note that open normally takes and passes a list (ie an Array). If you provide
104
+ # a single argument, it will be translated into an Array, and passed AS AN ARRAY
105
+ # to the block.
106
+ #
107
+ # task.open("file.txt", "w") do |array|
108
+ # array.first << "content"
109
+ # end
110
+ #
111
+ # File.read("file.txt") # => "content"
112
+ def open(list, mode="rb")
113
+ open_files = []
114
+ begin
115
+ [list].flatten.map {|path| path.to_str }.each do |filepath|
116
+ open_files << File.open(filepath, mode)
117
+ end
118
+
119
+ block_given? ? yield(open_files) : open_files
120
+ ensure
121
+ open_files.each {|file| file.close } if block_given?
122
+ end
123
+ end
124
+
125
+ # Returns the basename of path, exchanging the extension
126
+ # with extname, if provided.
127
+ #
128
+ # task.basename('path/to/file.txt') # => 'file.txt'
129
+ # task.basename('path/to/file.txt', '.html') # => 'file.html'
130
+ def basename(path, extname=nil)
131
+ basename = File.basename(path)
132
+ unless extname == nil
133
+ extname = $1 if extname =~ /^\.?(.*)/
134
+ basename = "#{basename.chomp(File.extname(basename))}.#{extname}"
120
135
  end
136
+ basename
121
137
  end
122
138
 
123
139
  # Sets a block to perform path inference. Raises an error if inference_block
@@ -191,7 +207,7 @@ module Tap
191
207
  else
192
208
  targets = [targets] unless targets.kind_of?(Array)
193
209
  sources = [sources] unless sources.kind_of?(Array)
194
- sources << config_file
210
+ sources << config_file unless config_file == nil
195
211
  targets.each do |target|
196
212
  return false unless FileUtils.uptodate?(target, sources)
197
213
  end
@@ -330,10 +346,10 @@ module Tap
330
346
  dir = File.dirname(dir)
331
347
  end
332
348
 
333
- make_paths.reverse_each do |dir|
334
- log :mkdir, dir, Logger::DEBUG
335
- FileUtils.mkdir(dir)
336
- added_files << dir
349
+ make_paths.reverse_each do |path|
350
+ log :mkdir, path, Logger::DEBUG
351
+ FileUtils.mkdir(path)
352
+ added_files << path
337
353
  end
338
354
  end
339
355
  end
@@ -467,8 +483,12 @@ module Tap
467
483
  end
468
484
  removed
469
485
  end
470
-
471
- def rollback
486
+
487
+ # Rolls back changes by removing added_files and restoring backed_up_files.
488
+ # Rollback is performed on an execute error if rollback_on_error == true,
489
+ # but is provided as a separate method for flexibility when needed.
490
+ # Yields errors to the block, which must be provided.
491
+ def rollback # :yields: error
472
492
  added_files.dup.each do |filepath|
473
493
  begin
474
494
  case
@@ -495,9 +515,10 @@ module Tap
495
515
  end
496
516
  end
497
517
 
498
- def cleanup(pattern=nil)
518
+ # Removes backed-up files matching the pattern.
519
+ def cleanup(pattern=/.*/)
499
520
  backed_up_files.each do |filepath, target|
500
- next unless pattern == nil || target =~ pattern
521
+ next unless target =~ pattern
501
522
 
502
523
  # the filepath needs to be added to added_files
503
524
  # before it can be removed by rm
@@ -507,39 +528,17 @@ module Tap
507
528
  end
508
529
  end
509
530
 
510
- # Run the system command +cmd+. If multiple arguments are given the command
511
- # is not run with the shell (same semantics as Kernel::exec and Kernel::system).
512
- #
513
- # Example:
514
- # sh %{ls -ltr}
515
- #
516
- # sh 'ls', 'file with spaces'
517
- #
518
- # # check exit status after command runs
519
- # sh %{grep pattern file} do |ok, res|
520
- # if ! ok
521
- # puts "pattern not found (status = #{res.exitstatus})"
522
- # end
523
- # end
524
- #
525
- def sh(*cmd, &block)
526
- # based on sh from Rake
527
- unless block_given?
528
- block = lambda { |ok, status|
529
- ok or raise "Command failed with status (#{status.exitstatus}): [#{cmd.join(" ")}]"
530
- }
531
- end
532
- log :sh, cmd.join(" ")
533
- res = system(*cmd)
534
- block.call(res, $?)
535
- end
536
-
537
531
  # Logs the given action, with the basenames of the input filepaths.
538
532
  def log_basename(action, filepaths, level=Logger::INFO)
539
- msg = filepaths.collect {|filepath| File.basename(filepath) }.join(',')
533
+ msg = case filepaths
534
+ when Array then filepaths.collect {|filepath| File.basename(filepath) }.join(',')
535
+ else
536
+ File.basename(filepaths)
537
+ end
538
+
540
539
  log(action, msg, level)
541
540
  end
542
-
541
+
543
542
  protected
544
543
 
545
544
  attr_writer :inference_block, :backed_up_files, :added_files
@@ -574,17 +573,15 @@ module Tap
574
573
  end
575
574
 
576
575
  # Re-raise the error if no rollback errors occured,
577
- # otherwise, raise a RunError tracking the restore
578
- # errors.
576
+ # otherwise, raise a RunError tracking the errors.
579
577
  if rollback_errors.empty?
580
578
  raise original_error
581
579
  else
582
- raise Support::RunError.new(original_error, rollback_errors)
580
+ rollback_errors.unshift(original_error)
581
+ raise Support::RunError.new(rollback_errors)
583
582
  end
584
583
  end
585
584
 
586
- protected
587
-
588
585
  # Lifted from FileUtils
589
586
  def fu_list(arg)
590
587
  [arg].flatten.map {|path| path.to_str }
@@ -21,7 +21,10 @@ module Rails # :nodoc:
21
21
  def self.use_tap_sources!
22
22
  reset_sources
23
23
  sources << PathSource.new(:builtin, "#{File.dirname(__FILE__)}/generator/generators")
24
- sources << PathSource.new(:builtin, Tap::App.instance.filepath(:generators))
24
+
25
+ Tap::Env.instance.config['generator_paths'].each do |path|
26
+ sources << PathSource.new(:builtin, path)
27
+ end
25
28
  end
26
29
  end
27
30
 
@@ -0,0 +1,6 @@
1
+ Description:
2
+ Generates a new Tap command under the cmd directory. Pass
3
+ the command name, either CamelCased or under_scored. The
4
+ new command can be run from the command line using:
5
+
6
+ % tap run <command name>
@@ -0,0 +1,17 @@
1
+ module Tap::Generator::Generators
2
+ class CommandGenerator < 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
+ command_path = @app.relative_filepath(:root, @app[:cmd])
12
+ m.directory class_path.empty? ? command_path : File.join(command_path, class_path)
13
+ m.template "command.erb", File.join(command_path, class_name.underscore + ".rb")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,16 +1,12 @@
1
1
  # = Usage
2
- # tap <%= file_name %> {options} OTHER_ARGS...
2
+ # tap <%= file_name %> {options} ARGS...
3
3
  #
4
4
  # = Description
5
- # Some informative description...
6
- #
7
- # = Information
8
- #
9
- # Developer:: <your name>
10
- # Homepage:: <your homepage>
11
- # Copyright (c):: <%= Time.now.strftime("%Y") %>, <copyright holders>
12
- # License:: MIT-LICENSE (http://www.opensource.org/licenses/mit-license.php) <or some other license...>
5
+ # The default command simply prints the input arguments
6
+ # and application information, then exits.
13
7
  #
8
+
9
+ require 'tap'
14
10
  require 'tap/script'
15
11
 
16
12
  app = Tap::App.instance
@@ -21,13 +17,14 @@ app = Tap::App.instance
21
17
 
22
18
  opts = [
23
19
  ['--help', '-h', GetoptLong::NO_ARGUMENT, "Print this help."],
24
- ['--debug', nil, GetoptLong::NO_ARGUMENT, "Specifes debug mode."]]
20
+ ['--debug', nil, GetoptLong::NO_ARGUMENT, "Specifies debug mode."]]
25
21
 
26
22
  Tap::Script.handle_options(*opts) do |opt, value|
27
23
  case opt
28
24
  when '--help'
29
25
  puts Tap::Script.usage(__FILE__, "Usage", "Description", "Information", :keep_headers => false)
30
26
  puts
27
+ puts "Options:"
31
28
  puts Tap::Script.usage_options(opts)
32
29
  exit
33
30
 
@@ -40,3 +37,6 @@ end
40
37
  #
41
38
  # add your script code here
42
39
  #
40
+
41
+ puts "Received: #{ARGV.join(', ')}"
42
+ puts app.info
@@ -0,0 +1,21 @@
1
+ Description:
2
+ Generates a new config file for a Task. The configurations, defaults,
3
+ and documentation is determined from the task.rb file. Pass the task
4
+ name, either CamelCased or under_scored.
5
+
6
+ Versioned config files can be generated as well. Specify a version by
7
+ appending the version to the task name.
8
+
9
+ Examples:
10
+ # generates the config file 'config/sample_task'
11
+ # for SampleTask from 'lib/sample_task.rb'
12
+ % tap generate config SampleTask
13
+
14
+ # same, with alternate syntax
15
+ % tap generate config sample_task
16
+
17
+ # now with a version, the output config
18
+ # file is 'config/sample_task-0.1.yml'
19
+ % tap generate config sample_task-0.1
20
+
21
+
@@ -2,24 +2,34 @@ module Tap::Generator::Generators
2
2
  class ConfigGenerator < Rails::Generator::NamedBase # :nodoc:
3
3
  attr_accessor :formatted_yaml
4
4
 
5
- def initialize(*args)
6
- super(*args)
7
- @destination_root = Tap::App.instance[:root]
5
+ def initialize(argv, options)
8
6
  @app = Tap::App.instance
7
+ name, @version = @app.deversion(argv[0])
8
+ argv[0] = name
9
+
10
+ super(argv, options)
11
+
12
+ @destination_root = Tap::App.instance[:root]
9
13
  end
10
14
 
11
15
  def manifest
12
16
  record do |m|
13
- task_name = class_path.empty? ? class_name : File.join(class_path, class_name)
14
- task = @app.task(task_name)
17
+ task = @app.task(class_name)
15
18
  self.formatted_yaml = task.class.configurations.format_yaml
16
19
 
17
20
  config_path = @app.relative_filepath(:root, @app[:config])
21
+
22
+ if @version == nil
23
+ # then get the next increment?
24
+ # Tap::App.vglob(File.join(config_path, class_name.underscore + '.yml'))
25
+ end
26
+ version = @version == nil ? '' : "-#{@version}"
27
+
18
28
  m.directory File.join(config_path, class_path)
19
- m.template "config.erb", File.join(config_path, class_name.underscore + ".yml")
29
+ m.template "config.erb", File.join(config_path, class_name.underscore + "#{version}.yml")
20
30
 
21
- # TODO -- add versioning
22
31
  end
23
32
  end
33
+
24
34
  end
25
35
  end