jimweirich-rake 0.8.4.99 → 0.8.5

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.
@@ -0,0 +1,25 @@
1
+ module Rake
2
+ # ##########################################################################
3
+ # Mixin for creating easily cloned objects.
4
+ #
5
+ module Cloneable
6
+ # Clone an object by making a new object and setting all the instance
7
+ # variables to the same values.
8
+ def dup
9
+ sibling = self.class.new
10
+ instance_variables.each do |ivar|
11
+ value = self.instance_variable_get(ivar)
12
+ new_value = value.clone rescue value
13
+ sibling.instance_variable_set(ivar, new_value)
14
+ end
15
+ sibling.taint if tainted?
16
+ sibling
17
+ end
18
+
19
+ def clone
20
+ sibling = dup
21
+ sibling.freeze if frozen?
22
+ sibling
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ module Rake
2
+
3
+ # Default Rakefile loader used by +import+.
4
+ class DefaultLoader
5
+ def load(fn)
6
+ Kernel.load(File.expand_path(fn))
7
+ end
8
+ end
9
+
10
+ end
data/lib/rake/dsl.rb ADDED
@@ -0,0 +1,117 @@
1
+ # Rake DSL functions.
2
+
3
+ # Declare a basic task.
4
+ #
5
+ # Example:
6
+ # task :clobber => [:clean] do
7
+ # rm_rf "html"
8
+ # end
9
+ #
10
+ def task(*args, &block)
11
+ Rake::Task.define_task(*args, &block)
12
+ end
13
+
14
+
15
+ # Declare a file task.
16
+ #
17
+ # Example:
18
+ # file "config.cfg" => ["config.template"] do
19
+ # open("config.cfg", "w") do |outfile|
20
+ # open("config.template") do |infile|
21
+ # while line = infile.gets
22
+ # outfile.puts line
23
+ # end
24
+ # end
25
+ # end
26
+ # end
27
+ #
28
+ def file(*args, &block)
29
+ Rake::FileTask.define_task(*args, &block)
30
+ end
31
+
32
+ # Declare a file creation task.
33
+ # (Mainly used for the directory command).
34
+ def file_create(args, &block)
35
+ Rake::FileCreationTask.define_task(args, &block)
36
+ end
37
+
38
+ # Declare a set of files tasks to create the given directories on demand.
39
+ #
40
+ # Example:
41
+ # directory "testdata/doc"
42
+ #
43
+ def directory(dir)
44
+ Rake.each_dir_parent(dir) do |d|
45
+ file_create d do |t|
46
+ mkdir_p t.name if ! File.exist?(t.name)
47
+ end
48
+ end
49
+ end
50
+
51
+ # Declare a task that performs its prerequisites in parallel. Multitasks does
52
+ # *not* guarantee that its prerequisites will execute in any given order
53
+ # (which is obvious when you think about it)
54
+ #
55
+ # Example:
56
+ # multitask :deploy => [:deploy_gem, :deploy_rdoc]
57
+ #
58
+ def multitask(args, &block)
59
+ Rake::MultiTask.define_task(args, &block)
60
+ end
61
+
62
+ # Create a new rake namespace and use it for evaluating the given block.
63
+ # Returns a NameSpace object that can be used to lookup tasks defined in the
64
+ # namespace.
65
+ #
66
+ # E.g.
67
+ #
68
+ # ns = namespace "nested" do
69
+ # task :run
70
+ # end
71
+ # task_run = ns[:run] # find :run in the given namespace.
72
+ #
73
+ def namespace(name=nil, &block)
74
+ Rake.application.in_namespace(name, &block)
75
+ end
76
+
77
+ # Declare a rule for auto-tasks.
78
+ #
79
+ # Example:
80
+ # rule '.o' => '.c' do |t|
81
+ # sh %{cc -o #{t.name} #{t.source}}
82
+ # end
83
+ #
84
+ def rule(*args, &block)
85
+ Rake::Task.create_rule(*args, &block)
86
+ end
87
+
88
+ # Describe the next rake task.
89
+ #
90
+ # Example:
91
+ # desc "Run the Unit Tests"
92
+ # task :test => [:build]
93
+ # runtests
94
+ # end
95
+ #
96
+ def desc(description)
97
+ Rake.application.last_description = description
98
+ end
99
+
100
+ # Import the partial Rakefiles +fn+. Imported files are loaded _after_ the
101
+ # current file is completely loaded. This allows the import statement to
102
+ # appear anywhere in the importing file, and yet allowing the imported files
103
+ # to depend on objects defined in the importing file.
104
+ #
105
+ # A common use of the import statement is to include files containing
106
+ # dependency declarations.
107
+ #
108
+ # See also the --rakelibdir command line option.
109
+ #
110
+ # Example:
111
+ # import ".depend", "my_rules"
112
+ #
113
+ def import(*fns)
114
+ fns.each do |fn|
115
+ Rake.application.add_import(fn)
116
+ end
117
+ end
@@ -0,0 +1,18 @@
1
+ module Rake
2
+
3
+ # EarlyTime is a fake timestamp that occurs _before_ any other time value.
4
+ class EarlyTime
5
+ include Comparable
6
+ include Singleton
7
+
8
+ def <=>(other)
9
+ -1
10
+ end
11
+
12
+ def to_s
13
+ "<EARLY TIME>"
14
+ end
15
+ end
16
+
17
+ EARLY = EarlyTime.instance
18
+ end
@@ -0,0 +1,60 @@
1
+ require 'rake/task'
2
+ require 'rake/file_task'
3
+ require 'rake/file_creation_task'
4
+ require 'rake/application'
5
+ require 'rake/task_manager'
6
+
7
+ ######################################################################
8
+ # Rake extensions to Module.
9
+ #
10
+ class Module
11
+ # Check for an existing method in the current class before extending. IF
12
+ # the method already exists, then a warning is printed and the extension is
13
+ # not added. Otherwise the block is yielded and any definitions in the
14
+ # block will take effect.
15
+ #
16
+ # Usage:
17
+ #
18
+ # class String
19
+ # rake_extension("xyz") do
20
+ # def xyz
21
+ # ...
22
+ # end
23
+ # end
24
+ # end
25
+ #
26
+ def rake_extension(method)
27
+ if method_defined?(method)
28
+ $stderr.puts "WARNING: Possible conflict with Rake extension: #{self}##{method} already exists"
29
+ else
30
+ yield
31
+ end
32
+ end
33
+
34
+ # Rename the original handler to make it available.
35
+ alias :rake_original_const_missing :const_missing
36
+
37
+ # Check for deprecated uses of top level (i.e. in Object) uses of
38
+ # Rake class names. If someone tries to reference the constant
39
+ # name, display a warning and return the proper object. Using the
40
+ # --classic-namespace command line option will define these
41
+ # constants in Object and avoid this handler.
42
+ def const_missing(const_name)
43
+ case const_name
44
+ when :Task
45
+ Rake.application.const_warning(const_name)
46
+ Rake::Task
47
+ when :FileTask
48
+ Rake.application.const_warning(const_name)
49
+ Rake::FileTask
50
+ when :FileCreationTask
51
+ Rake.application.const_warning(const_name)
52
+ Rake::FileCreationTask
53
+ when :RakeApp
54
+ Rake.application.const_warning(const_name)
55
+ Rake::Application
56
+ else
57
+ rake_original_const_missing(const_name)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,165 @@
1
+ ######################################################################
2
+ # Rake extension methods for String.
3
+ #
4
+ class String
5
+ rake_extension("ext") do
6
+ # Replace the file extension with +newext+. If there is no extension on
7
+ # the string, append the new extension to the end. If the new extension
8
+ # is not given, or is the empty string, remove any existing extension.
9
+ #
10
+ # +ext+ is a user added method for the String class.
11
+ def ext(newext='')
12
+ return self.dup if ['.', '..'].include? self
13
+ if newext != ''
14
+ newext = (newext =~ /^\./) ? newext : ("." + newext)
15
+ end
16
+ self.chomp(File.extname(self)) << newext
17
+ end
18
+ end
19
+
20
+ rake_extension("pathmap") do
21
+ # Explode a path into individual components. Used by +pathmap+.
22
+ def pathmap_explode
23
+ head, tail = File.split(self)
24
+ return [self] if head == self
25
+ return [tail] if head == '.' || tail == '/'
26
+ return [head, tail] if head == '/'
27
+ return head.pathmap_explode + [tail]
28
+ end
29
+ protected :pathmap_explode
30
+
31
+ # Extract a partial path from the path. Include +n+ directories from the
32
+ # front end (left hand side) if +n+ is positive. Include |+n+|
33
+ # directories from the back end (right hand side) if +n+ is negative.
34
+ def pathmap_partial(n)
35
+ dirs = File.dirname(self).pathmap_explode
36
+ partial_dirs =
37
+ if n > 0
38
+ dirs[0...n]
39
+ elsif n < 0
40
+ dirs.reverse[0...-n].reverse
41
+ else
42
+ "."
43
+ end
44
+ File.join(partial_dirs)
45
+ end
46
+ protected :pathmap_partial
47
+
48
+ # Preform the pathmap replacement operations on the given path. The
49
+ # patterns take the form 'pat1,rep1;pat2,rep2...'.
50
+ def pathmap_replace(patterns, &block)
51
+ result = self
52
+ patterns.split(';').each do |pair|
53
+ pattern, replacement = pair.split(',')
54
+ pattern = Regexp.new(pattern)
55
+ if replacement == '*' && block_given?
56
+ result = result.sub(pattern, &block)
57
+ elsif replacement
58
+ result = result.sub(pattern, replacement)
59
+ else
60
+ result = result.sub(pattern, '')
61
+ end
62
+ end
63
+ result
64
+ end
65
+ protected :pathmap_replace
66
+
67
+ # Map the path according to the given specification. The specification
68
+ # controls the details of the mapping. The following special patterns are
69
+ # recognized:
70
+ #
71
+ # * <b>%p</b> -- The complete path.
72
+ # * <b>%f</b> -- The base file name of the path, with its file extension,
73
+ # but without any directories.
74
+ # * <b>%n</b> -- The file name of the path without its file extension.
75
+ # * <b>%d</b> -- The directory list of the path.
76
+ # * <b>%x</b> -- The file extension of the path. An empty string if there
77
+ # is no extension.
78
+ # * <b>%X</b> -- Everything *but* the file extension.
79
+ # * <b>%s</b> -- The alternate file separater if defined, otherwise use
80
+ # the standard file separator.
81
+ # * <b>%%</b> -- A percent sign.
82
+ #
83
+ # The %d specifier can also have a numeric prefix (e.g. '%2d'). If the
84
+ # number is positive, only return (up to) +n+ directories in the path,
85
+ # starting from the left hand side. If +n+ is negative, return (up to)
86
+ # |+n+| directories from the right hand side of the path.
87
+ #
88
+ # Examples:
89
+ #
90
+ # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b'
91
+ # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d'
92
+ #
93
+ # Also the %d, %p, %f, %n, %x, and %X operators can take a
94
+ # pattern/replacement argument to perform simple string substititions on a
95
+ # particular part of the path. The pattern and replacement are speparated
96
+ # by a comma and are enclosed by curly braces. The replacement spec comes
97
+ # after the % character but before the operator letter. (e.g.
98
+ # "%{old,new}d"). Muliple replacement specs should be separated by
99
+ # semi-colons (e.g. "%{old,new;src,bin}d").
100
+ #
101
+ # Regular expressions may be used for the pattern, and back refs may be
102
+ # used in the replacement text. Curly braces, commas and semi-colons are
103
+ # excluded from both the pattern and replacement text (let's keep parsing
104
+ # reasonable).
105
+ #
106
+ # For example:
107
+ #
108
+ # "src/org/onestepback/proj/A.java".pathmap("%{^src,bin}X.class")
109
+ #
110
+ # returns:
111
+ #
112
+ # "bin/org/onestepback/proj/A.class"
113
+ #
114
+ # If the replacement text is '*', then a block may be provided to perform
115
+ # some arbitrary calculation for the replacement.
116
+ #
117
+ # For example:
118
+ #
119
+ # "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext|
120
+ # ext.downcase
121
+ # }
122
+ #
123
+ # Returns:
124
+ #
125
+ # "/path/to/file.txt"
126
+ #
127
+ def pathmap(spec=nil, &block)
128
+ return self if spec.nil?
129
+ result = ''
130
+ spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
131
+ case frag
132
+ when '%f'
133
+ result << File.basename(self)
134
+ when '%n'
135
+ result << File.basename(self).ext
136
+ when '%d'
137
+ result << File.dirname(self)
138
+ when '%x'
139
+ result << File.extname(self)
140
+ when '%X'
141
+ result << self.ext
142
+ when '%p'
143
+ result << self
144
+ when '%s'
145
+ result << (File::ALT_SEPARATOR || File::SEPARATOR)
146
+ when '%-'
147
+ # do nothing
148
+ when '%%'
149
+ result << "%"
150
+ when /%(-?\d+)d/
151
+ result << pathmap_partial($1.to_i)
152
+ when /^%\{([^}]*)\}(\d*[dpfnxX])/
153
+ patterns, operator = $1, $2
154
+ result << pathmap('%' + operator).pathmap_replace(patterns, &block)
155
+ when /^%/
156
+ fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
157
+ else
158
+ result << frag
159
+ end
160
+ end
161
+ result
162
+ end
163
+ end
164
+ end # class String
165
+
@@ -0,0 +1,14 @@
1
+ # ###########################################################################
2
+ # Extensions to time to allow comparisons with an early time class.
3
+ #
4
+ class Time
5
+ alias rake_original_time_compare :<=>
6
+ def <=>(other)
7
+ if Rake::EarlyTime === other
8
+ - other.<=>(self)
9
+ else
10
+ rake_original_time_compare(other)
11
+ end
12
+ end
13
+ end # class Time
14
+
@@ -0,0 +1,24 @@
1
+ require 'rake/file_task'
2
+ require 'rake/early_time'
3
+
4
+ module Rake
5
+
6
+ # A FileCreationTask is a file task that when used as a dependency will be
7
+ # needed if and only if the file has not been created. Once created, it is
8
+ # not re-triggered if any of its dependencies are newer, nor does trigger
9
+ # any rebuilds of tasks that depend on it whenever it is updated.
10
+ #
11
+ class FileCreationTask < FileTask
12
+ # Is this file task needed? Yes if it doesn't exist.
13
+ def needed?
14
+ ! File.exist?(name)
15
+ end
16
+
17
+ # Time stamp for file creation task. This time stamp is earlier
18
+ # than any other time stamp.
19
+ def timestamp
20
+ Rake::EARLY
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,410 @@
1
+ require 'rake/cloneable'
2
+ require 'rake/rake_file_utils'
3
+
4
+ ######################################################################
5
+ module Rake
6
+
7
+ # #########################################################################
8
+ # A FileList is essentially an array with a few helper methods defined to
9
+ # make file manipulation a bit easier.
10
+ #
11
+ # FileLists are lazy. When given a list of glob patterns for possible files
12
+ # to be included in the file list, instead of searching the file structures
13
+ # to find the files, a FileList holds the pattern for latter use.
14
+ #
15
+ # This allows us to define a number of FileList to match any number of
16
+ # files, but only search out the actual files when then FileList itself is
17
+ # actually used. The key is that the first time an element of the
18
+ # FileList/Array is requested, the pending patterns are resolved into a real
19
+ # list of file names.
20
+ #
21
+ class FileList
22
+
23
+ include Cloneable
24
+
25
+ # == Method Delegation
26
+ #
27
+ # The lazy evaluation magic of FileLists happens by implementing all the
28
+ # array specific methods to call +resolve+ before delegating the heavy
29
+ # lifting to an embedded array object (@items).
30
+ #
31
+ # In addition, there are two kinds of delegation calls. The regular kind
32
+ # delegates to the @items array and returns the result directly. Well,
33
+ # almost directly. It checks if the returned value is the @items object
34
+ # itself, and if so will return the FileList object instead.
35
+ #
36
+ # The second kind of delegation call is used in methods that normally
37
+ # return a new Array object. We want to capture the return value of these
38
+ # methods and wrap them in a new FileList object. We enumerate these
39
+ # methods in the +SPECIAL_RETURN+ list below.
40
+
41
+ # List of array methods (that are not in +Object+) that need to be
42
+ # delegated.
43
+ ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
44
+
45
+ # List of additional methods that must be delegated.
46
+ MUST_DEFINE = %w[to_a inspect]
47
+
48
+ # List of methods that should not be delegated here (we define special
49
+ # versions of them explicitly below).
50
+ MUST_NOT_DEFINE = %w[to_a to_ary partition *]
51
+
52
+ # List of delegated methods that return new array values which need
53
+ # wrapping.
54
+ SPECIAL_RETURN = %w[
55
+ map collect sort sort_by select find_all reject grep
56
+ compact flatten uniq values_at
57
+ + - & |
58
+ ]
59
+
60
+ DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).collect{ |s| s.to_s }.sort.uniq
61
+
62
+ # Now do the delegation.
63
+ DELEGATING_METHODS.each_with_index do |sym, i|
64
+ if SPECIAL_RETURN.include?(sym)
65
+ ln = __LINE__+1
66
+ class_eval %{
67
+ def #{sym}(*args, &block)
68
+ resolve
69
+ result = @items.send(:#{sym}, *args, &block)
70
+ FileList.new.import(result)
71
+ end
72
+ }, __FILE__, ln
73
+ else
74
+ ln = __LINE__+1
75
+ class_eval %{
76
+ def #{sym}(*args, &block)
77
+ resolve
78
+ result = @items.send(:#{sym}, *args, &block)
79
+ result.object_id == @items.object_id ? self : result
80
+ end
81
+ }, __FILE__, ln
82
+ end
83
+ end
84
+
85
+ # Create a file list from the globbable patterns given. If you wish to
86
+ # perform multiple includes or excludes at object build time, use the
87
+ # "yield self" pattern.
88
+ #
89
+ # Example:
90
+ # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb')
91
+ #
92
+ # pkg_files = FileList.new('lib/**/*') do |fl|
93
+ # fl.exclude(/\bCVS\b/)
94
+ # end
95
+ #
96
+ def initialize(*patterns)
97
+ @pending_add = []
98
+ @pending = false
99
+ @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
100
+ @exclude_procs = DEFAULT_IGNORE_PROCS.dup
101
+ @exclude_re = nil
102
+ @items = []
103
+ patterns.each { |pattern| include(pattern) }
104
+ yield self if block_given?
105
+ end
106
+
107
+ # Add file names defined by glob patterns to the file list. If an array
108
+ # is given, add each element of the array.
109
+ #
110
+ # Example:
111
+ # file_list.include("*.java", "*.cfg")
112
+ # file_list.include %w( math.c lib.h *.o )
113
+ #
114
+ def include(*filenames)
115
+ # TODO: check for pending
116
+ filenames.each do |fn|
117
+ if fn.respond_to? :to_ary
118
+ include(*fn.to_ary)
119
+ else
120
+ @pending_add << fn
121
+ end
122
+ end
123
+ @pending = true
124
+ self
125
+ end
126
+ alias :add :include
127
+
128
+ # Register a list of file name patterns that should be excluded from the
129
+ # list. Patterns may be regular expressions, glob patterns or regular
130
+ # strings. In addition, a block given to exclude will remove entries that
131
+ # return true when given to the block.
132
+ #
133
+ # Note that glob patterns are expanded against the file system. If a file
134
+ # is explicitly added to a file list, but does not exist in the file
135
+ # system, then an glob pattern in the exclude list will not exclude the
136
+ # file.
137
+ #
138
+ # Examples:
139
+ # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c']
140
+ # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c']
141
+ #
142
+ # If "a.c" is a file, then ...
143
+ # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c']
144
+ #
145
+ # If "a.c" is not a file, then ...
146
+ # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c']
147
+ #
148
+ def exclude(*patterns, &block)
149
+ patterns.each do |pat|
150
+ @exclude_patterns << pat
151
+ end
152
+ if block_given?
153
+ @exclude_procs << block
154
+ end
155
+ resolve_exclude if ! @pending
156
+ self
157
+ end
158
+
159
+
160
+ # Clear all the exclude patterns so that we exclude nothing.
161
+ def clear_exclude
162
+ @exclude_patterns = []
163
+ @exclude_procs = []
164
+ calculate_exclude_regexp if ! @pending
165
+ self
166
+ end
167
+
168
+ # Define equality.
169
+ def ==(array)
170
+ to_ary == array
171
+ end
172
+
173
+ # Return the internal array object.
174
+ def to_a
175
+ resolve
176
+ @items
177
+ end
178
+
179
+ # Return the internal array object.
180
+ def to_ary
181
+ to_a
182
+ end
183
+
184
+ # Lie about our class.
185
+ def is_a?(klass)
186
+ klass == Array || super(klass)
187
+ end
188
+ alias kind_of? is_a?
189
+
190
+ # Redefine * to return either a string or a new file list.
191
+ def *(other)
192
+ result = @items * other
193
+ case result
194
+ when Array
195
+ FileList.new.import(result)
196
+ else
197
+ result
198
+ end
199
+ end
200
+
201
+ # Resolve all the pending adds now.
202
+ def resolve
203
+ if @pending
204
+ @pending = false
205
+ @pending_add.each do |fn| resolve_add(fn) end
206
+ @pending_add = []
207
+ resolve_exclude
208
+ end
209
+ self
210
+ end
211
+
212
+ def calculate_exclude_regexp
213
+ ignores = []
214
+ @exclude_patterns.each do |pat|
215
+ case pat
216
+ when Regexp
217
+ ignores << pat
218
+ when /[*?]/
219
+ Dir[pat].each do |p| ignores << p end
220
+ else
221
+ ignores << Regexp.quote(pat)
222
+ end
223
+ end
224
+ if ignores.empty?
225
+ @exclude_re = /^$/
226
+ else
227
+ re_str = ignores.collect { |p| "(" + p.to_s + ")" }.join("|")
228
+ @exclude_re = Regexp.new(re_str)
229
+ end
230
+ end
231
+
232
+ def resolve_add(fn)
233
+ case fn
234
+ when %r{[*?\[\{]}
235
+ add_matching(fn)
236
+ else
237
+ self << fn
238
+ end
239
+ end
240
+ private :resolve_add
241
+
242
+ def resolve_exclude
243
+ calculate_exclude_regexp
244
+ reject! { |fn| exclude?(fn) }
245
+ self
246
+ end
247
+ private :resolve_exclude
248
+
249
+ # Return a new FileList with the results of running +sub+ against each
250
+ # element of the oringal list.
251
+ #
252
+ # Example:
253
+ # FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o']
254
+ #
255
+ def sub(pat, rep)
256
+ inject(FileList.new) { |res, fn| res << fn.sub(pat,rep) }
257
+ end
258
+
259
+ # Return a new FileList with the results of running +gsub+ against each
260
+ # element of the original list.
261
+ #
262
+ # Example:
263
+ # FileList['lib/test/file', 'x/y'].gsub(/\//, "\\")
264
+ # => ['lib\\test\\file', 'x\\y']
265
+ #
266
+ def gsub(pat, rep)
267
+ inject(FileList.new) { |res, fn| res << fn.gsub(pat,rep) }
268
+ end
269
+
270
+ # Same as +sub+ except that the oringal file list is modified.
271
+ def sub!(pat, rep)
272
+ each_with_index { |fn, i| self[i] = fn.sub(pat,rep) }
273
+ self
274
+ end
275
+
276
+ # Same as +gsub+ except that the original file list is modified.
277
+ def gsub!(pat, rep)
278
+ each_with_index { |fn, i| self[i] = fn.gsub(pat,rep) }
279
+ self
280
+ end
281
+
282
+ # Apply the pathmap spec to each of the included file names, returning a
283
+ # new file list with the modified paths. (See String#pathmap for
284
+ # details.)
285
+ def pathmap(spec=nil)
286
+ collect { |fn| fn.pathmap(spec) }
287
+ end
288
+
289
+ # Return a new FileList with <tt>String#ext</tt> method applied
290
+ # to each member of the array.
291
+ #
292
+ # This method is a shortcut for:
293
+ #
294
+ # array.collect { |item| item.ext(newext) }
295
+ #
296
+ # +ext+ is a user added method for the Array class.
297
+ def ext(newext='')
298
+ collect { |fn| fn.ext(newext) }
299
+ end
300
+
301
+
302
+ # Grep each of the files in the filelist using the given pattern. If a
303
+ # block is given, call the block on each matching line, passing the file
304
+ # name, line number, and the matching line of text. If no block is given,
305
+ # a standard emac style file:linenumber:line message will be printed to
306
+ # standard out.
307
+ def egrep(pattern, *options)
308
+ each do |fn|
309
+ open(fn, "rb", *options) do |inf|
310
+ count = 0
311
+ inf.each do |line|
312
+ count += 1
313
+ if pattern.match(line)
314
+ if block_given?
315
+ yield fn, count, line
316
+ else
317
+ puts "#{fn}:#{count}:#{line}"
318
+ end
319
+ end
320
+ end
321
+ end
322
+ end
323
+ end
324
+
325
+ # Return a new file list that only contains file names from the current
326
+ # file list that exist on the file system.
327
+ def existing
328
+ select { |fn| File.exist?(fn) }
329
+ end
330
+
331
+ # Modify the current file list so that it contains only file name that
332
+ # exist on the file system.
333
+ def existing!
334
+ resolve
335
+ @items = @items.select { |fn| File.exist?(fn) }
336
+ self
337
+ end
338
+
339
+ # FileList version of partition. Needed because the nested arrays should
340
+ # be FileLists in this version.
341
+ def partition(&block) # :nodoc:
342
+ resolve
343
+ result = @items.partition(&block)
344
+ [
345
+ FileList.new.import(result[0]),
346
+ FileList.new.import(result[1]),
347
+ ]
348
+ end
349
+
350
+ # Convert a FileList to a string by joining all elements with a space.
351
+ def to_s
352
+ resolve
353
+ self.join(' ')
354
+ end
355
+
356
+ # Add matching glob patterns.
357
+ def add_matching(pattern)
358
+ Dir[pattern].each do |fn|
359
+ self << fn unless exclude?(fn)
360
+ end
361
+ end
362
+ private :add_matching
363
+
364
+ # Should the given file name be excluded?
365
+ def exclude?(fn)
366
+ calculate_exclude_regexp unless @exclude_re
367
+ fn =~ @exclude_re || @exclude_procs.any? { |p| p.call(fn) }
368
+ end
369
+
370
+ DEFAULT_IGNORE_PATTERNS = [
371
+ /(^|[\/\\])CVS([\/\\]|$)/,
372
+ /(^|[\/\\])\.svn([\/\\]|$)/,
373
+ /\.bak$/,
374
+ /~$/
375
+ ]
376
+ DEFAULT_IGNORE_PROCS = [
377
+ proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) }
378
+ ]
379
+ # @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
380
+
381
+ def import(array)
382
+ @items = array
383
+ self
384
+ end
385
+
386
+ class << self
387
+ # Create a new file list including the files listed. Similar to:
388
+ #
389
+ # FileList.new(*args)
390
+ def [](*args)
391
+ new(*args)
392
+ end
393
+ end
394
+ end # FileList
395
+ end
396
+
397
+ module Rake
398
+ class << self
399
+
400
+ # Yield each file or directory component.
401
+ def each_dir_parent(dir) # :nodoc:
402
+ old_length = nil
403
+ while dir != '.' && dir.length != old_length
404
+ yield(dir)
405
+ old_length = dir.length
406
+ dir = File.dirname(dir)
407
+ end
408
+ end
409
+ end
410
+ end # module Rake