tap 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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