tap 0.9.1 → 0.10.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 (244) hide show
  1. data/History +37 -30
  2. data/MIT-LICENSE +1 -1
  3. data/README +92 -44
  4. data/bin/tap +62 -75
  5. data/cmd/console.rb +42 -0
  6. data/cmd/destroy.rb +16 -0
  7. data/cmd/generate.rb +16 -0
  8. data/cmd/run.rb +126 -0
  9. data/doc/Class Reference +362 -0
  10. data/doc/Command Reference +153 -0
  11. data/doc/Tutorial +237 -0
  12. data/lib/tap.rb +6 -45
  13. data/lib/tap/app.rb +126 -500
  14. data/lib/tap/constants.rb +2 -29
  15. data/lib/tap/env.rb +555 -250
  16. data/lib/tap/file_task.rb +60 -103
  17. data/lib/tap/generator/base.rb +109 -0
  18. data/lib/tap/generator/destroy.rb +37 -0
  19. data/lib/tap/generator/generate.rb +61 -0
  20. data/lib/tap/generator/generators/command/command_generator.rb +16 -12
  21. data/lib/tap/generator/generators/command/templates/command.erb +13 -19
  22. data/lib/tap/generator/generators/config/config_generator.rb +18 -27
  23. data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
  24. data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
  25. data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -11
  26. data/lib/tap/generator/generators/file_task/templates/file.txt +11 -2
  27. data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
  28. data/lib/tap/generator/generators/file_task/templates/task.erb +24 -31
  29. data/lib/tap/generator/generators/file_task/templates/test.erb +18 -22
  30. data/lib/tap/generator/generators/root/root_generator.rb +45 -31
  31. data/lib/tap/generator/generators/root/templates/Rakefile +64 -41
  32. data/lib/tap/generator/generators/root/templates/gemspec +27 -0
  33. data/lib/tap/generator/generators/root/templates/tapfile +8 -0
  34. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -0
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  36. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +21 -28
  38. data/lib/tap/generator/generators/task/templates/task.erb +13 -23
  39. data/lib/tap/generator/generators/task/templates/test.erb +15 -18
  40. data/lib/tap/generator/manifest.rb +14 -0
  41. data/lib/tap/patches/rake/rake_test_loader.rb +0 -0
  42. data/lib/tap/patches/rake/testtask.rb +0 -0
  43. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -0
  44. data/lib/tap/patches/ruby19/parsedate.rb +0 -0
  45. data/lib/tap/root.rb +260 -21
  46. data/lib/tap/support/aggregator.rb +11 -11
  47. data/lib/tap/support/assignments.rb +172 -0
  48. data/lib/tap/support/audit.rb +20 -18
  49. data/lib/tap/support/batchable.rb +21 -10
  50. data/lib/tap/support/batchable_class.rb +107 -0
  51. data/lib/tap/support/class_configuration.rb +154 -239
  52. data/lib/tap/support/command_line.rb +97 -102
  53. data/lib/tap/support/comment.rb +270 -0
  54. data/lib/tap/support/configurable.rb +86 -65
  55. data/lib/tap/support/configurable_class.rb +296 -0
  56. data/lib/tap/support/configuration.rb +122 -0
  57. data/lib/tap/support/constant.rb +70 -0
  58. data/lib/tap/support/constant_utils.rb +127 -0
  59. data/lib/tap/support/declarations.rb +111 -0
  60. data/lib/tap/support/executable.rb +30 -17
  61. data/lib/tap/support/executable_queue.rb +0 -0
  62. data/lib/tap/support/framework.rb +71 -0
  63. data/lib/tap/support/framework_class.rb +199 -0
  64. data/lib/tap/support/instance_configuration.rb +147 -0
  65. data/lib/tap/support/lazydoc.rb +428 -0
  66. data/lib/tap/support/manifest.rb +89 -0
  67. data/lib/tap/support/run_error.rb +0 -0
  68. data/lib/tap/support/shell_utils.rb +33 -9
  69. data/lib/tap/support/summary.rb +30 -0
  70. data/lib/tap/support/tdoc.rb +339 -134
  71. data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -0
  72. data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -0
  73. data/lib/tap/support/templater.rb +180 -0
  74. data/lib/tap/support/validation.rb +409 -76
  75. data/lib/tap/support/versions.rb +5 -3
  76. data/lib/tap/task.rb +78 -174
  77. data/lib/tap/tasks/dump.rb +56 -0
  78. data/lib/tap/tasks/rake.rb +93 -0
  79. data/lib/tap/test.rb +3 -3
  80. data/lib/tap/test/env_vars.rb +2 -2
  81. data/lib/tap/test/file_methods.rb +19 -20
  82. data/lib/tap/test/script_methods.rb +144 -0
  83. data/lib/tap/test/subset_methods.rb +1 -1
  84. data/lib/tap/test/tap_methods.rb +28 -62
  85. data/lib/tap/workflow.rb +22 -39
  86. metadata +48 -179
  87. data/Basic Overview +0 -151
  88. data/Command Reference +0 -99
  89. data/Rakefile +0 -127
  90. data/Tutorial +0 -287
  91. data/lib/tap/cmd/console.rb +0 -31
  92. data/lib/tap/cmd/destroy.rb +0 -20
  93. data/lib/tap/cmd/generate.rb +0 -20
  94. data/lib/tap/cmd/run.rb +0 -151
  95. data/lib/tap/dump.rb +0 -57
  96. data/lib/tap/generator.rb +0 -91
  97. data/lib/tap/generator/generators/command/USAGE +0 -6
  98. data/lib/tap/generator/generators/config/USAGE +0 -21
  99. data/lib/tap/generator/generators/config/templates/config.erb +0 -1
  100. data/lib/tap/generator/generators/file_task/USAGE +0 -3
  101. data/lib/tap/generator/generators/file_task/templates/file.yml +0 -3
  102. data/lib/tap/generator/generators/generator/USAGE +0 -0
  103. data/lib/tap/generator/generators/generator/generator_generator.rb +0 -21
  104. data/lib/tap/generator/generators/generator/templates/generator.erb +0 -32
  105. data/lib/tap/generator/generators/generator/templates/usage.erb +0 -1
  106. data/lib/tap/generator/generators/root/USAGE +0 -0
  107. data/lib/tap/generator/generators/root/templates/ReadMe.txt +0 -0
  108. data/lib/tap/generator/generators/root/templates/tap.yml +0 -80
  109. data/lib/tap/generator/generators/task/USAGE +0 -3
  110. data/lib/tap/generator/generators/workflow/USAGE +0 -0
  111. data/lib/tap/generator/generators/workflow/templates/task.erb +0 -16
  112. data/lib/tap/generator/generators/workflow/templates/test.erb +0 -7
  113. data/lib/tap/generator/generators/workflow/workflow_generator.rb +0 -6
  114. data/lib/tap/generator/options.rb +0 -26
  115. data/lib/tap/generator/usage.rb +0 -26
  116. data/lib/tap/support/batchable_methods.rb +0 -34
  117. data/lib/tap/support/command_line_methods.rb +0 -76
  118. data/lib/tap/support/configurable_methods.rb +0 -224
  119. data/lib/tap/support/logger.rb +0 -88
  120. data/lib/tap/support/rake.rb +0 -43
  121. data/lib/tap/support/tdoc/config_attr.rb +0 -362
  122. data/test/app/config/another/task.yml +0 -1
  123. data/test/app/config/batch.yml +0 -2
  124. data/test/app/config/empty.yml +0 -0
  125. data/test/app/config/erb.yml +0 -2
  126. data/test/app/config/some/task.yml +0 -1
  127. data/test/app/config/template.yml +0 -2
  128. data/test/app/config/version-0.1.yml +0 -1
  129. data/test/app/config/version.yml +0 -1
  130. data/test/app/lib/app_test_task.rb +0 -3
  131. data/test/app_test.rb +0 -1849
  132. data/test/env/test_configure/recurse_a.yml +0 -2
  133. data/test/env/test_configure/recurse_b.yml +0 -2
  134. data/test/env/test_configure/tap.yml +0 -23
  135. data/test/env/test_load_env_config/dir/tap.yml +0 -3
  136. data/test/env/test_load_env_config/recurse_a.yml +0 -2
  137. data/test/env/test_load_env_config/recurse_b.yml +0 -2
  138. data/test/env/test_load_env_config/tap.yml +0 -3
  139. data/test/env_test.rb +0 -198
  140. data/test/file_task/config/batch.yml +0 -2
  141. data/test/file_task/config/configured.yml +0 -1
  142. data/test/file_task/old_file_one.txt +0 -0
  143. data/test/file_task/old_file_two.txt +0 -0
  144. data/test/file_task_test.rb +0 -1291
  145. data/test/root/alt_lib/alt_module.rb +0 -4
  146. data/test/root/file.txt +0 -0
  147. data/test/root/glob/one.txt +0 -0
  148. data/test/root/glob/two.txt +0 -0
  149. data/test/root/lib/absolute_alt_filepath.rb +0 -2
  150. data/test/root/lib/alternative_filepath.rb +0 -2
  151. data/test/root/lib/another_module.rb +0 -2
  152. data/test/root/lib/nested/some_module.rb +0 -4
  153. data/test/root/lib/no_module_included.rb +0 -0
  154. data/test/root/lib/some/module.rb +0 -4
  155. data/test/root/lib/some_class.rb +0 -2
  156. data/test/root/lib/some_module.rb +0 -3
  157. data/test/root/load_path/load_path_module.rb +0 -2
  158. data/test/root/load_path/skip_module.rb +0 -2
  159. data/test/root/mtime/older.txt +0 -0
  160. data/test/root/unload/full_path.rb +0 -2
  161. data/test/root/unload/loaded_by_nested.rb +0 -2
  162. data/test/root/unload/nested/nested_load.rb +0 -6
  163. data/test/root/unload/nested/nested_with_ext.rb +0 -4
  164. data/test/root/unload/nested/relative_path.rb +0 -4
  165. data/test/root/unload/older.rb +0 -2
  166. data/test/root/unload/unload_base.rb +0 -9
  167. data/test/root/versions/another.yml +0 -0
  168. data/test/root/versions/file-0.1.2.yml +0 -0
  169. data/test/root/versions/file-0.1.yml +0 -0
  170. data/test/root/versions/file.yml +0 -0
  171. data/test/root_test.rb +0 -718
  172. data/test/support/aggregator_test.rb +0 -99
  173. data/test/support/audit_test.rb +0 -445
  174. data/test/support/batchable_test.rb +0 -74
  175. data/test/support/class_configuration_test.rb +0 -331
  176. data/test/support/command_line_test.rb +0 -58
  177. data/test/support/configurable/config/configured.yml +0 -2
  178. data/test/support/configurable_test.rb +0 -295
  179. data/test/support/executable_queue_test.rb +0 -103
  180. data/test/support/executable_test.rb +0 -38
  181. data/test/support/logger_test.rb +0 -31
  182. data/test/support/rake_test.rb +0 -37
  183. data/test/support/shell_utils_test.rb +0 -24
  184. data/test/support/tdoc_test.rb +0 -370
  185. data/test/support/validation_test.rb +0 -54
  186. data/test/support/versions_test.rb +0 -103
  187. data/test/tap_test_helper.rb +0 -57
  188. data/test/tap_test_suite.rb +0 -7
  189. data/test/task/config/batch.yml +0 -2
  190. data/test/task/config/batched.yml +0 -2
  191. data/test/task/config/configured.yml +0 -1
  192. data/test/task/config/example.yml +0 -1
  193. data/test/task_base_test.rb +0 -24
  194. data/test/task_syntax_test.rb +0 -300
  195. data/test/task_test.rb +0 -320
  196. data/test/test/env_vars_test.rb +0 -48
  197. data/test/test/file_methods/test_assert_files/expected/one.txt +0 -1
  198. data/test/test/file_methods/test_assert_files/expected/two.txt +0 -1
  199. data/test/test/file_methods/test_assert_files/input/one.txt +0 -1
  200. data/test/test/file_methods/test_assert_files/input/two.txt +0 -1
  201. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/one.txt +0 -1
  202. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/two.txt +0 -1
  203. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +0 -1
  204. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/two.txt +0 -1
  205. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +0 -1
  206. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +0 -1
  207. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/expected/one.txt +0 -1
  208. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +0 -1
  209. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +0 -1
  210. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +0 -1
  211. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +0 -1
  212. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +0 -1
  213. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +0 -1
  214. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +0 -1
  215. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +0 -1
  216. data/test/test/file_methods/test_method_glob/expected/file.yml +0 -0
  217. data/test/test/file_methods/test_method_glob/expected/file_1.txt +0 -0
  218. data/test/test/file_methods/test_method_glob/expected/file_2.txt +0 -0
  219. data/test/test/file_methods_doc/test_sub/expected/one.txt +0 -1
  220. data/test/test/file_methods_doc/test_sub/expected/two.txt +0 -1
  221. data/test/test/file_methods_doc/test_sub/input/one.txt +0 -1
  222. data/test/test/file_methods_doc/test_sub/input/two.txt +0 -1
  223. data/test/test/file_methods_doc_test.rb +0 -29
  224. data/test/test/file_methods_test.rb +0 -275
  225. data/test/test/subset_methods_test.rb +0 -171
  226. data/test/test/tap_methods/test_assert_files/expected/task/name/a.txt +0 -1
  227. data/test/test/tap_methods/test_assert_files/expected/task/name/b.txt +0 -1
  228. data/test/test/tap_methods/test_assert_files/input/a.txt +0 -1
  229. data/test/test/tap_methods/test_assert_files/input/b.txt +0 -1
  230. data/test/test/tap_methods_test.rb +0 -399
  231. data/test/workflow_test.rb +0 -120
  232. data/vendor/rails_generator.rb +0 -56
  233. data/vendor/rails_generator/base.rb +0 -263
  234. data/vendor/rails_generator/commands.rb +0 -581
  235. data/vendor/rails_generator/generated_attribute.rb +0 -42
  236. data/vendor/rails_generator/lookup.rb +0 -209
  237. data/vendor/rails_generator/manifest.rb +0 -53
  238. data/vendor/rails_generator/options.rb +0 -143
  239. data/vendor/rails_generator/scripts.rb +0 -83
  240. data/vendor/rails_generator/scripts/destroy.rb +0 -7
  241. data/vendor/rails_generator/scripts/generate.rb +0 -7
  242. data/vendor/rails_generator/scripts/update.rb +0 -12
  243. data/vendor/rails_generator/simple_logger.rb +0 -46
  244. data/vendor/rails_generator/spec.rb +0 -44
data/lib/tap/file_task.rb CHANGED
@@ -1,10 +1,10 @@
1
+ require 'tap/support/shell_utils'
2
+ autoload(:FileUtils, "fileutils")
3
+
1
4
  module Tap
2
5
 
3
- # == Overview
4
- #
5
6
  # FileTask provides methods for creating/modifying files such that you can
6
- # rollback changes if an error occurs. In addition, FileTask provides a
7
- # method to infer filepaths within the standard Tap directory structure.
7
+ # rollback changes if an error occurs.
8
8
  #
9
9
  # === Creating Files/Rolling Back Changes
10
10
  #
@@ -46,11 +46,6 @@ module Tap
46
46
  class FileTask < Task
47
47
  include Tap::Support::ShellUtils
48
48
 
49
- autoload(:FileUtils, "fileutils")
50
-
51
- # A block used to infer filepaths. (see FileTask#filepath)
52
- attr_reader :inference_block
53
-
54
49
  # A hash of backup (source, target) pairs, such that the
55
50
  # backed-up files are backed_up_files.keys and the actual
56
51
  # backup files are backed_up_files.values. All filepaths
@@ -59,40 +54,37 @@ module Tap
59
54
 
60
55
  # An array of files added during task execution.
61
56
  attr_reader :added_files
57
+
58
+ # The backup directory, defaults to the class backup_dir
59
+ config_attr :backup_dir, 'backup' # the backup directory
62
60
 
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
61
+ # A timestamp format used to mark backup files, defaults
62
+ # to the class backup_timestamp
63
+ config :timestamp, "%Y%m%d_%H%M%S" # the backup timestamp format
68
64
 
69
- # The backup directory, defaults to the class backup_dir
70
- config :backup_dir, :backup
65
+ # A flag indicating whether or not to rollback changes on
66
+ # error, defaults to the class rollback_on_error
67
+ config :rollback_on_error, true, &c.switch # rollback changes on error
71
68
 
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
79
-
80
- def initialize(*args)
69
+ def initialize(config={}, name=nil, app=App.instance, &task_block)
81
70
  super
82
71
 
83
- batch.each do |task|
84
- task.dirname = task.default_dirname
85
- task.backed_up_files = {}
86
- task.added_files = []
87
- task.inference_block = nil
88
- end
72
+ @backed_up_files = {}
73
+ @added_files = []
74
+ end
75
+
76
+ def initialize_copy(orig)
77
+ super
78
+ @backed_up_files = {}
79
+ @added_files = []
89
80
  end
90
81
 
91
82
  # A batch File.open method. If a block is given, each file in the list will be
92
83
  # opened the open files passed to the block. Files are automatically closed when
93
84
  # the block returns. If no block is given, the open files are returned.
94
85
  #
95
- # task.open(["one.txt", "two.txt"], "w") do |one, two|
86
+ # t = FileTask.new
87
+ # t.open(["one.txt", "two.txt"], "w") do |one, two|
96
88
  # one << "one"
97
89
  # two << "two"
98
90
  # end
@@ -104,11 +96,12 @@ module Tap
104
96
  # a single argument, it will be translated into an Array, and passed AS AN ARRAY
105
97
  # to the block.
106
98
  #
107
- # task.open("file.txt", "w") do |array|
99
+ # t.open("file.txt", "w") do |array|
108
100
  # array.first << "content"
109
101
  # end
110
102
  #
111
103
  # File.read("file.txt") # => "content"
104
+ #
112
105
  def open(list, mode="rb")
113
106
  open_files = []
114
107
  begin
@@ -125,8 +118,10 @@ module Tap
125
118
  # Returns the basename of path, exchanging the extension
126
119
  # with extname, if provided.
127
120
  #
128
- # task.basename('path/to/file.txt') # => 'file.txt'
129
- # task.basename('path/to/file.txt', '.html') # => 'file.html'
121
+ # t = FileTask.new
122
+ # t.basename('path/to/file.txt') # => 'file.txt'
123
+ # t.basename('path/to/file.txt', '.html') # => 'file.html'
124
+ #
130
125
  def basename(path, extname=nil)
131
126
  basename = File.basename(path)
132
127
  unless extname == nil
@@ -136,78 +131,49 @@ module Tap
136
131
  basename
137
132
  end
138
133
 
139
- # Sets a block to perform path inference. Raises an error if inference_block
140
- # is already set, unless override = true.
141
- def inference(override=false, &block) # :yields: app[dir], dirname, *paths
142
- raise "Inference block for task already set: #{name}" unless inference_block.nil? || override
143
- self.inference_block = block
144
- end
145
-
146
- # Infers a path using the inference block, or by using app.filepath if
147
- # no inference block is given. Note the actual inputs to the inference
148
- # block are the application directory identified by dir, the dirname
149
- # for the task, and the provided paths.
134
+ # Constructs a filepath using the dir, name, and the specified paths.
150
135
  #
151
136
  # t = FileTask.new
152
- # t.app[:data] # => "/data"
153
- # t.dirname # => "tap/file_task"
137
+ # t.app[:data, true] = "/data"
138
+ # t.name # => "tap/file_task"
154
139
  # t.filepath(:data, "result.txt") # => "/data/tap/file_task/result.txt"
155
140
  #
156
- # t.inference do |root, dir, path|
157
- # File.join(root, dir, path.chomp(".txt") + ".yml")
158
- # end
159
- #
160
- # t.filepath(:data, "result.txt") # => "/data/tap/file_task/result.yml"
161
- #
162
141
  def filepath(dir, *paths)
163
- inference_block ?
164
- inference_block.call(app[dir], dirname, *paths) :
165
- app.filepath(dir, dirname, *paths)
142
+ app.filepath(dir, name, *paths)
166
143
  end
167
144
 
168
- # Makes a backup filepath relative to backup_dir by translating the input
169
- # filepath and inserting a timestamp formatted using backup_timestamp.
170
- # The filepath used during translation will be the filepath relative
171
- # to dirname (if the input filepath is relative to dirname) or just
172
- # the basename of the filepath.
173
- #
174
- # t = FileTask.new("dir/name", :backup_dir => :backup, :backup_timestamp => "%Y%m%d")
175
- # t.dirname # => "dir/name"
176
- # t.app[:backup] # => "/backup"
177
- # Date.today.to_s # => "2007-08-08"
178
- #
179
- # # uses path relative to dirname, if possible
180
- # t.backup_filepath("dir/name/folder/file.txt") # => "/backup/folder/file_20070808.txt"
181
- #
182
- # # otherwise uses basename
183
- # t.backup_filepath("path/to/folder/file.txt") # => "/backup/file_20070808.txt"
145
+ # Makes a backup filepath relative to backup_dir by using self.name, the
146
+ # basename of filepath plus a timestamp.
147
+ #
148
+ # t = FileTask.new({:timestamp => "%Y%m%d"}, 'name')
149
+ # t.app['backup', true] = "/backup"
150
+ # time = Time.utc(2008,8,8)
151
+ #
152
+ # t.backup_filepath("path/to/file.txt", time) # => "/backup/name/file_20080808.txt"
184
153
  #
185
- def backup_filepath(filepath)
154
+ def backup_filepath(filepath, time=Time.now)
186
155
  extname = File.extname(filepath)
187
- backup_path = File.expand_path("#{filepath.chomp(extname)}_#{Time.now.strftime(backup_timestamp)}#{extname}")
188
-
189
- split_index = backup_path.index(dirname + "/")
190
- backup_path = split_index ?
191
- backup_path[(split_index + dirname.length + 1)..-1] :
192
- File.basename(backup_path)
193
-
156
+ backup_path = "#{File.basename(filepath).chomp(extname)}_#{time.strftime(timestamp)}#{extname}"
194
157
  filepath(backup_dir, backup_path)
195
158
  end
196
159
 
197
- # Returns true if all of the targets are up to date relative to all of the sources
198
- # AND the task config_file, if it exists. Single values or arrays can be provided
199
- # for both targets and sources. Used to check if any work needs to be done for
200
- # a given set of sources and configurations.
160
+ # Returns true if all of the targets are up to date relative to all of the listed
161
+ # sources AND date_reference. Single values or arrays can be provided for both
162
+ # targets and sources.
201
163
  #
164
+ #---
202
165
  # Returns false (ie 'not up to date') if +force?+ is true.
203
166
  def uptodate?(targets, sources=[])
204
- if app.options.force
167
+ if app.force
205
168
  log_basename(:force, *targets)
206
169
  false
207
170
  else
208
171
  targets = [targets] unless targets.kind_of?(Array)
209
172
  sources = [sources] unless sources.kind_of?(Array)
210
- sources << config_file unless config_file == nil
173
+
174
+ # should be able to specify this somehow, externally set
175
+ # sources << config_file unless config_file == nil
176
+
211
177
  targets.each do |target|
212
178
  return false unless FileUtils.uptodate?(target, sources)
213
179
  end
@@ -379,7 +345,7 @@ module Tap
379
345
  # remove directories and parents until the
380
346
  # directory was not made by the task
381
347
  while added_files.include?(dir)
382
- break unless Dir.entries(dir).delete_if {|d| d == "." || d == ".."}.empty?
348
+ break unless dir_empty?(dir)
383
349
 
384
350
  if File.exists?(dir)
385
351
  log :rmdir, dir, Logger::DEBUG
@@ -393,6 +359,10 @@ module Tap
393
359
  removed
394
360
  end
395
361
 
362
+ def dir_empty?(dir)
363
+ Dir.entries(dir).delete_if {|d| d == "." || d == ".."}.empty?
364
+ end
365
+
396
366
  # Prepares the input list of files by backing them up (if they exist),
397
367
  # ensuring that the parent directory for the file exists, and adding
398
368
  # each file to added_files. As a result the files can be removed
@@ -459,7 +429,7 @@ module Tap
459
429
  # File.exists?("path") # => false
460
430
  # FileUtils.mkdir("path") # will not be removed
461
431
  #
462
- # t.make("path/to/file.txt")
432
+ # t.prepare("path/to/file.txt")
463
433
  # FileUtils.touch("path/to/file.txt")
464
434
  # File.exists?("path/to/file.txt") # => true
465
435
  #
@@ -541,20 +511,7 @@ module Tap
541
511
 
542
512
  protected
543
513
 
544
- attr_writer :inference_block, :backed_up_files, :added_files
545
-
546
- # The default_dirname is based on the name of the task, and the
547
- # index of the task in batch (if the task is batched):
548
- #
549
- # t = FileTask.new "name"
550
- # t.default_dirname # => "name"
551
- #
552
- # t = FileTask.new "batched"
553
- # t.batch[0].default_dirname # => "name_0"
554
- # t.batch[1].default_dirname # => "name_1"
555
- def default_dirname
556
- batched? ? "#{name}_#{batch_index}" : name
557
- end
514
+ attr_writer :backed_up_files, :added_files
558
515
 
559
516
  # Clears added_files and backed_up_files so that
560
517
  # a failure will not affect previous executions
@@ -0,0 +1,109 @@
1
+ require 'tap/generator/manifest'
2
+
3
+ module Tap
4
+ module Generator
5
+ class Base < Tap::Task
6
+ class << self
7
+ def lazydoc(resolve=false, args_method=:manifest)
8
+ if resolve
9
+ lazydoc = super(false)
10
+ lazydoc.resolve(nil, /^\s*def\s+#{args_method}(\((.*?)\))?/) do |comment, match|
11
+ args = match[2].to_s.split(',').collect do |arg|
12
+ arg = arg.strip.upcase
13
+ case arg
14
+ when /^&/ then nil
15
+ when /^\*/ then arg[1..-1] + "..."
16
+ else arg
17
+ end
18
+ end
19
+ args.shift
20
+
21
+ comment.subject = args.join(', ')
22
+ lazydoc.default_attributes['args'] ||= comment
23
+ end
24
+ end
25
+
26
+ super(false)
27
+ end
28
+
29
+ def help
30
+ Tap::Support::Templater.new(DEFAULT_HELP_TEMPLATE,
31
+ :task_class => self,
32
+ :manifest => lazydoc(true)[to_s]['generator'] || Tap::Support::Comment.new
33
+ ).build
34
+ end
35
+ end
36
+
37
+ Constant = Tap::Support::Constant
38
+
39
+ config :pretend, false, &c.flag # Run but rollback any changes.
40
+ config :force, false, &c.flag # Overwrite files that already exist.
41
+ config :skip, false, &c.flag # Skip files that already exist.
42
+
43
+ attr_accessor :file_task, :template_dir, :target_dir
44
+
45
+ def initialize(config={}, name=nil, app=App.instance)
46
+ super(config, name, app)
47
+
48
+ @file_task = Tap::FileTask.new
49
+ @template_dir = File.dirname(self.class.source_file) + '/templates'
50
+ end
51
+
52
+ def process(*argv)
53
+ actions = []
54
+ manifest(Manifest.new(actions), *argv)
55
+
56
+ iterate(actions) do |action, args, block|
57
+ send(action, *args, &block)
58
+ end
59
+
60
+ @target_dir = nil
61
+ file_task.added_files
62
+ end
63
+
64
+ def log_relative(action, path)
65
+ log(action, app.relative_filepath(Dir.pwd, path))
66
+ end
67
+
68
+ def manifest(m, *argv)
69
+ raise NotImplementedError
70
+ end
71
+
72
+ def iterate(action)
73
+ raise NotImplementedError
74
+ end
75
+
76
+ def directory(target, options={})
77
+ raise NotImplementedError
78
+ end
79
+
80
+ def file(target, options={})
81
+ raise NotImplementedError
82
+ end
83
+
84
+ def directories(root, targets, options={})
85
+ directory(root)
86
+ targets.each do |target|
87
+ directory(File.join(root, target), options)
88
+ end
89
+ end
90
+
91
+ def template(target, source, attributes={}, options={})
92
+ template_path = File.expand_path(source, template_dir)
93
+ templater = Support::Templater.new(File.read(template_path), attributes)
94
+
95
+ file(target, options) do |file|
96
+ file << templater.build
97
+ end
98
+ end
99
+
100
+ def template_files
101
+ Dir.glob(template_dir + "/**/*").sort.each do |source|
102
+ target = Tap::Root.relative_filepath(template_dir, source)
103
+ yield(source, target)
104
+ end
105
+ end
106
+
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,37 @@
1
+ module Tap
2
+ module Generator
3
+ module Destroy
4
+ def iterate(actions)
5
+ actions.reverse_each {|action| yield(action) }
6
+ end
7
+
8
+ def directory(target, options={})
9
+ target = File.expand_path(target, target_dir)
10
+
11
+ case
12
+ when !File.exists?(target)
13
+ log_relative :missing, target
14
+ when !file_task.dir_empty?(target)
15
+ log_relative 'not empty', target
16
+ else
17
+ log_relative :rm, target
18
+ file_task.added_files << File.expand_path(target)
19
+ file_task.rmdir(target) unless pretend
20
+ end
21
+ end
22
+
23
+ def file(target, options={})
24
+ target = File.expand_path(target, target_dir)
25
+
26
+ if File.exists?(target)
27
+ log_relative :rm, target
28
+ file_task.added_files << File.expand_path(target)
29
+ file_task.rm(target) unless pretend
30
+ else
31
+ log_relative :missing, target
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,61 @@
1
+ module Tap
2
+ module Generator
3
+ module Generate
4
+ def iterate(actions)
5
+ actions.each {|action| yield(action) }
6
+ end
7
+
8
+ def directory(target, options={})
9
+ target = File.expand_path(target, target_dir)
10
+
11
+ if File.exists?(target)
12
+ log_relative :exists, target
13
+ else
14
+ log_relative :create, target
15
+ file_task.mkdir(target) unless pretend
16
+ end
17
+ end
18
+
19
+ def file(target, options={})
20
+ target = File.expand_path(target, target_dir)
21
+
22
+ case
23
+ when !File.exists?(target)
24
+ log_relative :create, target
25
+ # should check for identical...
26
+ when force_file_collision?(target)
27
+ log_relative :force, target
28
+ else
29
+ log_relative :skip, target
30
+ return
31
+ end
32
+
33
+ unless pretend
34
+ file_task.prepare(target)
35
+ File.open(target, "wb") {|file| yield(file) if block_given? }
36
+ end
37
+ end
38
+
39
+ # Ask the user interactively whether to force collision.
40
+ def force_file_collision?(target)
41
+ return false if skip
42
+ return true if force
43
+
44
+ $stdout.print "overwrite #{target}? [Ynaiq] "
45
+ $stdout.flush
46
+ case $stdin.gets
47
+ when /a/i
48
+ self.force = true
49
+ when /i/i
50
+ self.skip = true
51
+ when /q/i
52
+ $stdout.puts "aborting #{name}"
53
+ raise SystemExit
54
+ when /n/i then false
55
+ when /y/i then true
56
+ else force_file_collision?(destination)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end