ratch 1.1.0 → 1.2.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 (86) hide show
  1. data/.ruby +99 -0
  2. data/COPYING +203 -21
  3. data/History.rdoc +35 -0
  4. data/License.txt +204 -0
  5. data/README.rdoc +113 -0
  6. data/Version +1 -0
  7. data/bin/ludo +16 -0
  8. data/bin/ratch +1 -8
  9. data/lib/ratch.rb +28 -0
  10. data/lib/ratch.yml +99 -0
  11. data/lib/ratch/batch.rb +500 -0
  12. data/lib/ratch/console.rb +199 -0
  13. data/lib/ratch/core_ext.rb +1 -4
  14. data/lib/ratch/core_ext/facets.rb +15 -1
  15. data/lib/ratch/core_ext/filetest.rb +29 -0
  16. data/lib/ratch/core_ext/{string.rb → to_actual_filename.rb} +0 -23
  17. data/lib/ratch/core_ext/to_console.rb +30 -12
  18. data/lib/ratch/core_ext/{object.rb → to_yamlfrag.rb} +1 -0
  19. data/lib/ratch/core_ext/unfold_paragraphs.rb +27 -0
  20. data/lib/ratch/file_list.rb +411 -0
  21. data/lib/ratch/script.rb +99 -5
  22. data/lib/ratch/script/help.rb +84 -0
  23. data/lib/ratch/shell.rb +783 -0
  24. data/lib/ratch/system.rb +15 -0
  25. data/lib/ratch/utils/cli.rb +49 -0
  26. data/lib/ratch/utils/config.rb +52 -0
  27. data/lib/ratch/{emailer.rb → utils/email.rb} +43 -6
  28. data/lib/ratch/utils/ftp.rb +134 -0
  29. data/lib/ratch/utils/pom.rb +22 -0
  30. data/lib/ratch/utils/rdoc.rb +48 -0
  31. data/lib/ratch/utils/tar.rb +88 -0
  32. data/lib/ratch/utils/xdg.rb +39 -0
  33. data/lib/ratch/utils/zlib.rb +54 -0
  34. data/spec/01_shell.rdoc +198 -0
  35. data/spec/02_script.rdoc +34 -0
  36. data/spec/03_batch.rdoc +71 -0
  37. data/spec/04_system.rdoc +3 -0
  38. data/spec/applique/array.rb +8 -0
  39. data/spec/applique/setup.rb +20 -0
  40. data/test/case_batch.rb +63 -0
  41. data/test/case_shell.rb +46 -0
  42. data/test/core_ext/case_pathname.rb +361 -0
  43. data/test/helper.rb +4 -0
  44. data/test/utils/case_cli.rb +6 -0
  45. data/test/utils/case_config.rb +12 -0
  46. data/test/utils/case_email.rb +10 -0
  47. data/test/utils/case_ftp.rb +6 -0
  48. data/test/utils/case_pom.rb +17 -0
  49. data/test/utils/case_rdoc.rb +23 -0
  50. data/test/utils/case_tar.rb +6 -0
  51. data/test/utils/case_zlib.rb +11 -0
  52. data/test/utils/fixtures/pom_sample/Profile +4 -0
  53. data/test/utils/fixtures/rdoc_sample/README.rdoc +4 -0
  54. data/test/utils/fixtures/rdoc_sample/lib/rdoc_sample/rdoc_sample.rb +9 -0
  55. metadata +139 -82
  56. data/HISTORY +0 -6
  57. data/MANIFEST +0 -53
  58. data/NEWS +0 -12
  59. data/README +0 -87
  60. data/VERSION +0 -1
  61. data/demo/tryme-task.ratch +0 -12
  62. data/demo/tryme1.ratch +0 -6
  63. data/doc/log/basic_stats/index.html +0 -39
  64. data/doc/log/notes.xml +0 -18
  65. data/doc/log/stats.log +0 -14
  66. data/doc/log/syntax.log +0 -0
  67. data/doc/log/testunit.log +0 -156
  68. data/lib/ratch/commandline.rb +0 -16
  69. data/lib/ratch/core_ext/pathname.rb +0 -38
  70. data/lib/ratch/dsl.rb +0 -420
  71. data/lib/ratch/index.rb +0 -4
  72. data/lib/ratch/io.rb +0 -116
  73. data/lib/ratch/plugin.rb +0 -65
  74. data/lib/ratch/service.rb +0 -33
  75. data/lib/ratch/task.rb +0 -249
  76. data/lib/ratch/task2.rb +0 -298
  77. data/meta/abstract +0 -4
  78. data/meta/author +0 -1
  79. data/meta/contact +0 -1
  80. data/meta/homepage +0 -1
  81. data/meta/name +0 -1
  82. data/meta/requires +0 -4
  83. data/meta/summary +0 -1
  84. data/test/README +0 -1
  85. data/test/test_helper.rb +0 -4
  86. data/test/test_task.rb +0 -46
@@ -0,0 +1,113 @@
1
+ = Ratch
2
+
3
+ Ruby-based Batch Scripts
4
+
5
+
6
+ == Introduction
7
+
8
+ Ratch is Ruby-based DSL for building batch scripts. It's intent
9
+ is to ease the burden of batch script writers by supplementing
10
+ the standard ruby environment to be more conducive to the needs
11
+ of batch scripting.
12
+
13
+ In addition to using Ratch to write stand-alone batch scripts,
14
+ it makes a very powerful library for other applications that
15
+ require batch-like functionality. In general any program that
16
+ access the file system extensively could benefit from it's use.
17
+
18
+
19
+ == Resources
20
+
21
+ * home: http://rubyworks.github.com/ratch
22
+ * code: http://github.com/rubyworks/ratch
23
+ * talk: http://googlegroups.com/
24
+
25
+ == Usage
26
+
27
+ === Batch Scripting
28
+
29
+ To use for your own scripts, simply add a bang line.
30
+
31
+ #!/usr/bin/env ratch
32
+
33
+ On Windows, of course, you will want to associate the .ratch extension
34
+ name to the ratch executable instead.
35
+
36
+ === As a Library
37
+
38
+ To use Ratch as a library, require 'ratch' and create an instance of
39
+ Ratch::Shell.
40
+
41
+ If you wish to extend Ratch::Shell for your application, it is recommend
42
+ that you either subclass Ratch::Shell, e.g.
43
+
44
+ require 'ratch'
45
+
46
+ class MyClass < Ratch::Shell
47
+
48
+
49
+ end
50
+
51
+ Or delegate to a Ratch::Shell instance, e.g.
52
+
53
+ require 'ratch'
54
+
55
+ class MyClass
56
+
57
+ def initialize(path)
58
+ @shell = Ratch::Shell.new(path)
59
+ end
60
+
61
+ end
62
+
63
+ For details on all the functionality Ratch provides, please refer to
64
+ the API documentation.
65
+
66
+
67
+ == Bonus Feature
68
+
69
+ Ratch also includes the `ludo` command, which stands for "lookup and do".
70
+ It will ascend up the directory tree searching for a matching executable
71
+ script. If it finds one it will execute the script relative the currently
72
+ ascended directory.
73
+
74
+
75
+ == Installation
76
+
77
+ Standard installation procedure apply.
78
+
79
+ $ gem install ratch
80
+
81
+ or manually using Setup.rb
82
+
83
+ $ tar -xzf ratch-1.0.0.tgz
84
+ $ cd ratch-1.0.0
85
+ $ setup.rb
86
+
87
+
88
+ == Development
89
+
90
+ Ratch is hosted on GitHub.
91
+
92
+ To pull the 'ratch' repository anonymously, use:
93
+
94
+ git clone git://github.com/rubyworks/ratch.git
95
+
96
+
97
+ == Copying
98
+
99
+ Copyright (c) 2008 Thomas Sawyer
100
+
101
+ Licensed under the Apache License, Version 2.0 (the "License");
102
+ you may not use this program except in compliance with the License.
103
+ You may obtain a copy of the License at
104
+
105
+ http://www.apache.org/licenses/LICENSE-2.0
106
+
107
+ Unless required by applicable law or agreed to in writing, software
108
+ distributed under the License is distributed on an "AS IS" BASIS,
109
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
110
+ See the License for the specific language governing permissions and
111
+ limitations under the License.
112
+
113
+
data/Version ADDED
@@ -0,0 +1 @@
1
+ 1.2.0
@@ -0,0 +1,16 @@
1
+ #! /usr/bin/ruby1.8
2
+
3
+ # for FileTest.root?
4
+ require 'facets/filetest'
5
+
6
+ name = ARGV[0]
7
+
8
+ if name
9
+ Dir.chdir '..' until FileTest.executable?(name) or FileTest.root?(Dir.pwd)
10
+ if FileTest.executable?( name )
11
+ system name
12
+ end
13
+ else
14
+ puts "Script #{name} not found."
15
+ end
16
+
data/bin/ratch CHANGED
@@ -1,10 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
-
3
- $0 = ARGV.shift
4
-
5
2
  require 'ratch/script'
6
-
7
- script = Ratch::Script.new
8
-
9
- script.instance_eval(File.read($0))
10
-
3
+ Ratch::Script.execute(ARGV.shift)
@@ -0,0 +1,28 @@
1
+ module Ratch
2
+ # Access to project metadata.
3
+ def self.metadata
4
+ @metadata ||= (
5
+ require 'yaml'
6
+ YAML.load(File.dirname(__FILE__) + '/ratch.yml')
7
+ )
8
+ end
9
+
10
+ # Access to project metadata via constants.
11
+ def self.const_missing(name)
12
+ metadata[name.to_s.downcase] || super(name)
13
+ end
14
+
15
+ # TODO: Only here b/c of issue with Ruby 1.8.x.
16
+ VERSION = metadata['version']
17
+ end
18
+
19
+ require 'ratch/script'
20
+
21
+ # Load utility extension modules.
22
+ require 'ratch/utils/cli'
23
+ require 'ratch/utils/pom'
24
+ require 'ratch/utils/rdoc'
25
+ #require 'ratch/utils/email'
26
+ #require 'ratch/utils/tar'
27
+ #require 'ratch/utils/zlib'
28
+
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: ratch
3
+ spec_version: 1.0.0
4
+ repositories:
5
+ public: git://github.com/rubyworks/ratch.git
6
+ title: Ratch
7
+ contact: trans <transfire@gmail.com>
8
+ requires:
9
+ - group: []
10
+
11
+ name: facets
12
+ version: 2.9.1+
13
+ - group: []
14
+
15
+ name: minitar
16
+ version: 0.5.3+
17
+ - group:
18
+ - test
19
+ name: ko
20
+ version: 1.2.0~
21
+ - group:
22
+ - test
23
+ name: qed
24
+ version: 0+
25
+ - group:
26
+ - build
27
+ name: syckle
28
+ version: 0+
29
+ resources:
30
+ code: http://github.org/rubyworks/ratch
31
+ mail: http://groups.gooogle.com/group/rubyworks-mailinglist
32
+ home: http://rubyworks.github.org/ratch
33
+ manifest:
34
+ - .ruby
35
+ - bin/ludo
36
+ - bin/ratch
37
+ - lib/ratch/batch.rb
38
+ - lib/ratch/console.rb
39
+ - lib/ratch/core_ext/facets.rb
40
+ - lib/ratch/core_ext/filetest.rb
41
+ - lib/ratch/core_ext/to_actual_filename.rb
42
+ - lib/ratch/core_ext/to_console.rb
43
+ - lib/ratch/core_ext/to_list.rb
44
+ - lib/ratch/core_ext/to_yamlfrag.rb
45
+ - lib/ratch/core_ext/unfold_paragraphs.rb
46
+ - lib/ratch/core_ext.rb
47
+ - lib/ratch/file_list.rb
48
+ - lib/ratch/script/help.rb
49
+ - lib/ratch/script.rb
50
+ - lib/ratch/shell.rb
51
+ - lib/ratch/system.rb
52
+ - lib/ratch/utils/cli.rb
53
+ - lib/ratch/utils/config.rb
54
+ - lib/ratch/utils/email.rb
55
+ - lib/ratch/utils/ftp.rb
56
+ - lib/ratch/utils/pom.rb
57
+ - lib/ratch/utils/rdoc.rb
58
+ - lib/ratch/utils/tar.rb
59
+ - lib/ratch/utils/xdg.rb
60
+ - lib/ratch/utils/zlib.rb
61
+ - lib/ratch.rb
62
+ - lib/ratch.yml
63
+ - man/ratch.1
64
+ - spec/01_shell.rdoc
65
+ - spec/02_script.rdoc
66
+ - spec/03_batch.rdoc
67
+ - spec/04_system.rdoc
68
+ - spec/applique/array.rb
69
+ - spec/applique/setup.rb
70
+ - test/case_batch.rb
71
+ - test/case_shell.rb
72
+ - test/core_ext/case_pathname.rb
73
+ - test/helper.rb
74
+ - test/utils/case_cli.rb
75
+ - test/utils/case_config.rb
76
+ - test/utils/case_email.rb
77
+ - test/utils/case_ftp.rb
78
+ - test/utils/case_pom.rb
79
+ - test/utils/case_rdoc.rb
80
+ - test/utils/case_tar.rb
81
+ - test/utils/case_zlib.rb
82
+ - test/utils/fixtures/pom_sample/Profile
83
+ - test/utils/fixtures/rdoc_sample/README.rdoc
84
+ - test/utils/fixtures/rdoc_sample/lib/rdoc_sample/rdoc_sample.rb
85
+ - README.rdoc
86
+ - History.rdoc
87
+ - Version
88
+ - License.txt
89
+ - COPYING
90
+ version: 1.2.0
91
+ licenses:
92
+ - Apache 2.0
93
+ copyright: Copyright (c) 2009 Thomas Sawyer
94
+ description: Ratch is a Ruby-based batch scripting language. It's a DSL over regular Ruby to make the life of the batch script writter easier.
95
+ summary: Ruby-based Batch Scripting
96
+ organization: RubyWorks
97
+ authors:
98
+ - Trans <transfire@gmail.com>
99
+ created: 2009-09-22
@@ -0,0 +1,500 @@
1
+ require 'ratch/core_ext'
2
+ require 'ratch/file_list'
3
+
4
+ module Ratch
5
+
6
+ # Proccess a list of files in batch.
7
+ #
8
+ # The Batch interface mimics the Shell class in most respects.
9
+ #
10
+ # TODO: Should FileList use Pathname, or only in Batch?
11
+ class Batch
12
+ include Enumerable
13
+
14
+ #
15
+ def self.[](*patterns)
16
+ new('.', *patterns)
17
+ end
18
+
19
+ #
20
+ def initialize(local, *patterns)
21
+ @local = Pathname.new(local)
22
+ @options = (Hash === patterns.last ? patterns.pop : {}).rekey(&:to_sym)
23
+
24
+ @file_list = FileList.all
25
+
26
+ patterns.each do |pattern|
27
+ if @local == Pathname.new('.')
28
+ @file_list.add(pattern)
29
+ else
30
+ @file_list.add(File.join(local,pattern))
31
+ end
32
+ end
33
+ end
34
+
35
+ #
36
+ attr :local
37
+
38
+ # Returns the the underlying FileList object.
39
+ def file_list
40
+ @file_list
41
+ end
42
+
43
+ # Iterate over pathnames.
44
+ def each(&block)
45
+ @file_list.each{ |file| block.call(Pathname.new(file)) }
46
+ end
47
+
48
+ # Returns the Integer size of the list of files.
49
+ def size
50
+ @file_list.size
51
+ end
52
+
53
+ # Return the list of files as Pathname objects.
54
+ def to_a
55
+ @file_list.map{ |file| Pathname.new(file) }
56
+ end
57
+
58
+ # Return the list of files as Pathname objects.
59
+ alias_method :pathnames, :to_a
60
+
61
+ # Returns the list of files as Strings, rather than Pathname objects.
62
+ def list
63
+ @file_list.to_a
64
+ end
65
+ alias_method :filenames, :list
66
+
67
+ # Returns an Array of file paths relative to +local+.
68
+ def entries
69
+ map{ |entry| entry.sub(local.to_s+'/','') }
70
+ end
71
+
72
+ # Limit list to files.
73
+ def file!
74
+ @file_list = @file_list.select{ |f| File.file?(f) }
75
+ end
76
+
77
+ # Limit list to directories.
78
+ def directory!
79
+ @file_list = @file_list.select{ |f| File.directory?(f) }
80
+ end
81
+
82
+ # Limit list to selection block.
83
+ def select!(&block)
84
+ #@file_list = FileList.all(*to_a.select{ |f| block.call(f) })
85
+ @file_list = @file_list.select{ |f| block.call(f) }
86
+ end
87
+
88
+ #############
89
+ # FileTest #
90
+ #############
91
+
92
+ # This is called #size in FileTest but must be renamed to
93
+ # avoid the clash with the Enumerable mixin.
94
+ def byte_size
95
+ inject(0){ |sum, path| sum + FileTest.size(path) }
96
+ end
97
+
98
+ # An alias for #byte_size.
99
+ alias_method :size?, :byte_size
100
+
101
+ def directory? ; all?{ |path| FileTest.directory?(path) } ; end
102
+ def symlink? ; all?{ |path| FileTest.symlink?(path) } ; end
103
+ def readable? ; all?{ |path| FileTest.readable?(path) } ; end
104
+ def chardev? ; all?{ |path| FileTest.chardev?(path) } ; end
105
+ def exist? ; all?{ |path| FileTest.exist?(path) } ; end
106
+ def exists? ; all?{ |path| FileTest.exists?(path) } ; end
107
+ def zero? ; all?{ |path| FileTest.zero?(path) } ; end
108
+ def pipe? ; all?{ |path| FileTest.pipe?(path) } ; end
109
+ def file? ; all?{ |path| FileTest.file?(path) } ; end
110
+ def sticky? ; all?{ |path| FileTest.sticky?(path) } ; end
111
+ def blockdev? ; all?{ |path| FileTest.blockdev?(path) } ; end
112
+ def grpowned? ; all?{ |path| FileTest.grpowned?(path) } ; end
113
+ def setgid? ; all?{ |path| FileTest.setgid?(path) } ; end
114
+ def setuid? ; all?{ |path| FileTest.setuid?(path) } ; end
115
+ def socket? ; all?{ |path| FileTest.socket?(path) } ; end
116
+ def owned? ; all?{ |path| FileTest.owned?(path) } ; end
117
+ def writable? ; all?{ |path| FileTest.writable?(path) } ; end
118
+ def executable? ; all?{ |path| FileTest.executable?(path) } ; end
119
+ def safe? ; all?{ |path| FileTest.safe?(path) } ; end
120
+
121
+ # TODO: Will this work since all paths are localized?
122
+ def relative? ; all?{ |path| FileTest.relative?(path) } ; end
123
+ def absolute? ; all?{ |path| FileTest.absolute?(path) } ; end
124
+
125
+ def writable_real? ; all?{ |path| FileTest.writable_real?(path) } ; end
126
+ def executable_real? ; all?{ |path| FileTest.executable_real?(path) } ; end
127
+ def readable_real? ; all?{ |path| FileTest.readable_real?(path) } ; end
128
+
129
+ alias_method :dir?, :directory?
130
+
131
+ def identical?(other)
132
+ all?{ |path| FileTest.identical?(path, other) }
133
+ end
134
+
135
+ # TODO: Really?
136
+ alias_method :compare_file, :identical?
137
+ alias_method :cmp, :identical?
138
+
139
+
140
+ #############
141
+ # FileUtils #
142
+ #############
143
+
144
+ # Low-level Methods Omitted
145
+ # -------------------------
146
+ # getwd -> pwd
147
+ # compare_file -> cmp
148
+ # remove_file -> rm
149
+ # copy_file -> cp
150
+ # remove_dir -> rmdir
151
+ # safe_unlink -> rm_f
152
+ # makedirs -> mkdir_p
153
+ # rmtree -> rm_rf
154
+ # copy_stream
155
+ # remove_entry
156
+ # copy_entry
157
+ # remove_entry_secure
158
+ # compare_stream
159
+
160
+ # Present working directory.
161
+ # TODO: Does this make sense?
162
+ def pwd
163
+ @local
164
+ end
165
+
166
+ # Make a directory for every entry.
167
+ def mkdir(options={})
168
+ list.each do |dir|
169
+ if File.exist?(dir)
170
+ raise Errno::EEXIST, "File exists - #{dir}"
171
+ end
172
+ end
173
+ list.map{ |dir| fileutils.mkdir(dir, options) }
174
+ end
175
+
176
+ # Make a directory for every entry.
177
+ def mkdir_p(options={})
178
+ list.each do |dir|
179
+ if File.exist?(dir) && !File.directory?(dir)
180
+ raise Errno::EEXIST, "File exists - #{dir}"
181
+ end
182
+ end
183
+ list.map{ |dir| fileutils.mkdir_p(dir, options) }
184
+ end
185
+ alias_method :mkpath, :mkdir_p
186
+
187
+ # Remove every directory.
188
+ def rmdir(options={})
189
+ list.map{ |dir| fileutils.rmdir(dir, options) }
190
+ end
191
+
192
+ # ln(list, destdir, options={})
193
+ def ln(dir, options={})
194
+ #src = list.to_a
195
+ #new = localize(new)
196
+ fileutils.ln(list, dir, options)
197
+ end
198
+ alias_method :link, :ln
199
+
200
+ # ln_s(list, destdir, options={})
201
+ def ln_s(dir, options={})
202
+ #src = list.to_a
203
+ #new = localize(new)
204
+ fileutils.ln_s(list, dir, options)
205
+ end
206
+ alias_method :symlink, :ln_s
207
+
208
+ def ln_sf(dir, options={})
209
+ #src = list.to_a
210
+ #new = localize(new)
211
+ fileutils.ln_sf(list, dir, options)
212
+ end
213
+
214
+ # cp(list, dir, options={})
215
+ def cp(dir, options={})
216
+ #src = list.to_a
217
+ #dest = localize(dest)
218
+ fileutils.cp(list, dir, options)
219
+ end
220
+ alias_method :copy, :cp
221
+
222
+ # cp_r(list, dir, options={})
223
+ def cp_r(dir, options={})
224
+ #src = list.to_a
225
+ #dest = localize(dest)
226
+ fileutils.cp_r(list, dir, options)
227
+ end
228
+
229
+ # mv(list, dir, options={})
230
+ def mv(dir, options={})
231
+ #src = list.to_a
232
+ #dest = localize(dest)
233
+ fileutils.mv(list, dir, options)
234
+ end
235
+ alias_method :move, :mv
236
+
237
+ #
238
+ def rm(options={})
239
+ list = list.to_a
240
+ fileutils.rm(list, options)
241
+ end
242
+
243
+ # Alias for #rm.
244
+ alias_method :remove, :rm
245
+
246
+ # Remove, recursively removing the contents of directories.
247
+ def rm_r(options={})
248
+ #list = list.to_a
249
+ fileutils.rm_r(list, options)
250
+ end
251
+
252
+ # Remove, with force option.
253
+ def rm_f(options={})
254
+ #list = list.to_a
255
+ fileutils.rm_f(list, options)
256
+ end
257
+
258
+ # Remove with force option, recursively removing the contents of directories.
259
+ def rm_rf(options={})
260
+ #list = list.to_a
261
+ fileutils.rm_rf(list, options)
262
+ end
263
+
264
+ # Install files to a directory with given mode. Unlike #cp, this will
265
+ # not copy the file if an up-to-date copy already exists.
266
+ def install(dir, mode, options={})
267
+ #src = list.to_a
268
+ #dest = localize(dest)
269
+ fileutils.install(list, dir, mode, options)
270
+ end
271
+
272
+ # Change mode of files.
273
+ def chmod(mode, options={})
274
+ #list = list.to_a
275
+ fileutils.chmod(mode, list, options)
276
+ end
277
+
278
+ # Change mode of files, following directories recursively.
279
+ def chmod_r(mode, options={})
280
+ #list = list.to_a
281
+ fileutils.chmod_r(mode, list, options)
282
+ end
283
+ #alias_method :chmod_R, :chmod_r
284
+
285
+ # Change owner of files.
286
+ def chown(user, group, options={})
287
+ #list = list.to_a
288
+ fileutils.chown(user, group, list, options)
289
+ end
290
+
291
+ # Change owner of files, following directories recursively.
292
+ def chown_r(user, group, options={})
293
+ #list = list.to_a
294
+ fileutils.chown_r(user, group, list, options)
295
+ end
296
+ #alias_method :chown_R, :chown_r
297
+
298
+ # Touch each file.
299
+ def touch(options={})
300
+ #list = list.to_a
301
+ fileutils.touch(list, options)
302
+ end
303
+
304
+ # Stage files. This is like #install but uses hardlinks.
305
+ def stage(dir)
306
+ #dir = localize(directory)
307
+ #files = localize(files)
308
+ #list = list.to_a
309
+ fileutils.stage(dir, local, list)
310
+ end
311
+
312
+ # Convenient alias for #map_mv.
313
+ def rename(options={}, &block)
314
+ map_mv(options, &block)
315
+ end
316
+
317
+ # Rename the list of files in batch, using a block to determine the new
318
+ # names. If the block returns nil, the file will not be renamed.
319
+ #
320
+ # This is similar to #mv, but allows for detailed control over the renaming.
321
+ #
322
+ # Unlike the other `map_*` methods, this changes the Batch list in-place,
323
+ # since the files renamed no loner exist.
324
+ #
325
+ # Returns the changed FileList instance.
326
+ def map_mv(options={}, &block)
327
+ @file_list = map_send(:mv, options={}, &block)
328
+ end
329
+
330
+ # Hard link the list of files in batch, using a block to determine the new
331
+ # names. If the block returns nil, the file will not be linked.
332
+ #
333
+ # This is similar to #ln, but allows for detailed control over the link names.
334
+ def map_ln(options={}, &block)
335
+ map_send(:ln, options={}, &block)
336
+ end
337
+
338
+ # Soft link the list of files in batch, using a block to determine the new
339
+ # names. If the block returns nil, the file will not be linked.
340
+ #
341
+ # This is similar to #ln_s, but allows for detailed control over the link names.
342
+ def map_ln_s(options={}, &block)
343
+ map_send(:ln_s, options={}, &block)
344
+ end
345
+
346
+ # Force soft linking of the list of files in batch, using a block to
347
+ # determine the new names. If the block returns nil, the file will not
348
+ # be linked.
349
+ #
350
+ # This is similar to #ln_sf, but allows for detailed control over the
351
+ # link names.
352
+ def map_ln_sf(options={}, &block)
353
+ map_send(:ln_sf, options={}, &block)
354
+ end
355
+
356
+ # Copy the list of files in batch, using a block to determine the new
357
+ # file names. If the block returns nil, the file will not be copied.
358
+ #
359
+ # This is similar to #cp, but allows for detailed control over the new
360
+ # file names.
361
+ def map_cp(options={}, &block)
362
+ map_send(:cp, options={}, &block)
363
+ end
364
+
365
+ # Copy the list of files recursively in batch, using a block to determine
366
+ # the new file names. If the block returns nil, the file will not be copied.
367
+ #
368
+ # This is similar to #cp_r, but allows for detailed control over the new
369
+ # file names.
370
+ def map_cp_r(options={}, &block)
371
+ map_send(:cp_r, options={}, &block)
372
+ end
373
+
374
+ # # Force copy the list of files recursively in batch, using a block to
375
+ # # determine the new file names. If the block returns nil, the file will not
376
+ # # be copied.
377
+ # #
378
+ # # This is similar to #cp_rf, but allows for detailed control over the new
379
+ # # file names.
380
+ # def map_cp_rf(options={}, &block)
381
+ # map_send(:cp_rf, options={}, &block)
382
+ # end
383
+
384
+ private
385
+
386
+ SAFE_METHODS = [:ln]
387
+
388
+ # Generic name mapping procedure which can be used for any
389
+ # FileUtils method that has a `src, dest` interface.
390
+ #--
391
+ # TODO: Make public?
392
+ #++
393
+ def map_send(method, options={}, &block)
394
+
395
+ map = {}
396
+ list.each do |file|
397
+ if dest = block.call(file)
398
+ map[file] = dest
399
+ end
400
+ end
401
+
402
+ if options[:safe] or !options[:force] or SAFE_METHODS.include?(method)
403
+ ensure_safe(map)
404
+ end
405
+
406
+ map.each do |src, dest|
407
+ fileutils.__send__(method, src, dest, options)
408
+ end
409
+ FileList.all(*map.values)
410
+ end
411
+
412
+ # Given a map of source to destination, this method ensures
413
+ # a FileUtils operation can is "safe" --that the destination does not
414
+ # yet and exist and/or the source and destination are compatible.
415
+ # If nota file rrror is raised.
416
+ def ensure_safe(map)
417
+ map.each do |src, dest|
418
+ raise unless File.exist?(src)
419
+ if File.directory?(src)
420
+ if File.directory?(dest)
421
+ new_map = {}
422
+ Dir.entries(src).each do |e|
423
+ next if e == '.' or e == '..'
424
+ new_map[File.join(src, e)] = File.join(dest, e)
425
+ end
426
+ ensure_safe_destination(new_map)
427
+ else
428
+ raise Errno::EISDIR, "Is a directory - #{src}"
429
+ end
430
+ else
431
+ if File.directory?(dest)
432
+ check = File.join(dest, src)
433
+ if File.exist?(check)
434
+ raise Errno::EEXIST, "File exists - #{check}"
435
+ end
436
+ else
437
+ raise Errno::EEXIST, "File exists - #{dest}" if File.exist?(dest)
438
+ end
439
+ end
440
+ end
441
+ end
442
+
443
+ public
444
+
445
+ # An intergrated glob like method that takes a set of include globs,
446
+ # exclude globs and ignore globs to produce a collection of paths.
447
+ #
448
+ # Ignore_globs differ from exclude_globs in that they match by
449
+ # the basename of the path rather than the whole pathname.
450
+ #
451
+ #def amass(include_globs, exclude_globs=[], ignore_globs=[])
452
+ # locally do
453
+ # fileutils.amass(include_globs, exclude_globs, ignore_globs)
454
+ # end
455
+ #end
456
+
457
+ # Is +path+ out-of-date in comparsion to all files in batch.
458
+ def outofdate?(path)
459
+ fileutils.outofdate?(path, to_a)
460
+ end
461
+
462
+ # Is +path+ up-to-date in comparsion to all files in batch.
463
+ def uptodate?(path)
464
+ fileutils.uptodate?(path, to_a)
465
+ end
466
+
467
+ #
468
+ def noop?
469
+ @options[:noop] or @options[:dryrun]
470
+ end
471
+
472
+ #
473
+ def verbose?
474
+ @options[:verbose] or @options[:dryrun]
475
+ end
476
+
477
+ #
478
+ def dryrun?
479
+ noop? && verbose?
480
+ end
481
+
482
+ private
483
+
484
+ # Returns FileUtils module based on mode.
485
+ def fileutils
486
+ if dryrun?
487
+ ::FileUtils::DryRun
488
+ elsif noop?
489
+ ::FileUtils::Noop
490
+ elsif verbose?
491
+ ::FileUtils::Verbose
492
+ else
493
+ ::FileUtils
494
+ end
495
+ end
496
+
497
+ end
498
+
499
+ end
500
+