rant 0.5.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS +30 -0
- data/README +4 -1
- data/Rantfile +28 -8
- data/doc/advanced.rdoc +19 -70
- data/doc/filelist.rdoc +963 -0
- data/doc/homepage/index.html +8 -2
- data/doc/rantfile.rdoc +7 -25
- data/doc/rubylib.rdoc +27 -0
- data/doc/sys.rdoc +15 -2
- data/doc/sys_filelist.rdoc +118 -0
- data/lib/rant.rb +1 -1
- data/lib/rant/cs_compiler.rb +4 -4
- data/lib/rant/filelist.rb +8 -0
- data/lib/rant/import/archive.rb +6 -6
- data/lib/rant/import/filelist/core.rb +429 -0
- data/lib/rant/import/filelist/inspect.rb +57 -0
- data/lib/rant/import/filelist/std.rb +64 -0
- data/lib/rant/import/nodes/default.rb +6 -2
- data/lib/rant/import/rubypackage.rb +10 -0
- data/lib/rant/init.rb +200 -0
- data/lib/rant/rantlib.rb +98 -111
- data/lib/rant/rantsys.rb +86 -455
- data/lib/rant/rantvar.rb +1 -7
- data/test/import/directedrule/Rantfile +1 -1
- data/test/lib/test_filelist.rb +481 -0
- data/test/test_filelist.rb +135 -13
- data/test/test_sys.rb +4 -0
- data/test/test_sys_methods.rb +9 -0
- data/test/tutil.rb +37 -15
- metadata +18 -7
- data/lib/rant/rantenv.rb +0 -184
- data/test/deprecated/test_0_5_2.rb +0 -61
data/doc/homepage/index.html
CHANGED
@@ -105,6 +105,12 @@
|
|
105
105
|
before installing a newer version of Rant. It describes
|
106
106
|
non-backwards compatible changes and new features.
|
107
107
|
</p>
|
108
|
+
<h2>Rant libraries</h2>
|
109
|
+
<p>
|
110
|
+
You can reuse code written for the Rant build tool as
|
111
|
+
"normal" Ruby library. Read <a
|
112
|
+
href="files/doc/rubylib_rdoc.html">Rant libraries</a>
|
113
|
+
</p>
|
108
114
|
<h2>Rant vs. Rake</h2>
|
109
115
|
<p>
|
110
116
|
<a href="files/doc/rant_vs_rake_rdoc.html">Read comparison</a>
|
@@ -118,8 +124,8 @@
|
|
118
124
|
<a href="http://developer.berlios.de" title="BerliOS
|
119
125
|
Developer"> <img
|
120
126
|
src="http://developer.berlios.de/bslogo.php?group_id=5046"
|
121
|
-
width="124px" height="32px"
|
122
|
-
Developer Logo"
|
127
|
+
width="124px" height="32px" alt="BerliOS
|
128
|
+
Developer Logo" /></a>
|
123
129
|
</p>
|
124
130
|
|
125
131
|
<!-- BlueRobot was here. -->
|
data/doc/rantfile.rdoc
CHANGED
@@ -209,31 +209,11 @@ explain it a little bit. It can be used in three ways:
|
|
209
209
|
|
210
210
|
file "program" => sys["*.o"]
|
211
211
|
|
212
|
-
The task "program" depends on all files ending in ".o".
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
From now on we'll call <tt>sys[...]</tt> the <em>glob
|
219
|
-
operator</em>.
|
220
|
-
|
221
|
-
You can give more patterns:
|
222
|
-
|
223
|
-
c_files = sys["**/*.h", "**/*.c"]
|
224
|
-
|
225
|
-
gives a list of all files ending in ".h" or ".c" in the current
|
226
|
-
directory and all subdirectories.
|
227
|
-
|
228
|
-
The object returned by the glob operator _behaves_ like an array of
|
229
|
-
strings, so it is possible to pass it to methods expecting an array.
|
230
|
-
If you're getting errors or experience strange behaviour convert
|
231
|
-
the list explicetely to an array:
|
232
|
-
|
233
|
-
# method foo_bar is hardcoded to check for an object of class
|
234
|
-
# Array
|
235
|
-
foo_bar(c_files.to_a)
|
236
|
-
|
212
|
+
The task "program" depends on all files ending in ".o".
|
213
|
+
|
214
|
+
For extensive documentation read
|
215
|
+
doc/sys_filelist.rdoc[link:files/doc/sys_filelist_rdoc.html].
|
216
|
+
|
237
217
|
=== Generators
|
238
218
|
|
239
219
|
The *gen* function takes a generator which usually creates one or more
|
@@ -469,5 +449,7 @@ Packaging::
|
|
469
449
|
doc/package.rdoc[link:files/doc/package_rdoc.html]
|
470
450
|
Ruby project howto::
|
471
451
|
doc/rubyproject.rdoc[link:files/doc/rubyproject_rdoc.html]
|
452
|
+
Using filelists in Rantfiles::
|
453
|
+
doc/sys_filelist.rdoc[link:files/doc/sys_filelist_rdoc.html]
|
472
454
|
Rant Overview::
|
473
455
|
README[link:files/README.html]
|
data/doc/rubylib.rdoc
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
== Rant libraries
|
3
|
+
|
4
|
+
The Rant build tool contains much code that can be reused in other
|
5
|
+
Ruby applications or libraries. This document provides an overview of
|
6
|
+
what is "officially" supported.
|
7
|
+
|
8
|
+
As Rant matures, more classes will be provided to drive Rant
|
9
|
+
programmatically or just to allow reuse of library code.
|
10
|
+
|
11
|
+
=== Rant::FileList class
|
12
|
+
|
13
|
+
This class provides an abstraction over the <tt>Dir.glob</tt> and
|
14
|
+
<tt>File.fnmatch</tt> methods. In many cases it can be used instead of
|
15
|
+
the +Find+ module in Ruby's standard library.
|
16
|
+
|
17
|
+
Read doc/filelist.rdoc[link:files/doc/filelist_rdoc.html] for full
|
18
|
+
documentation of the <tt>Rant::FileList</tt> class.
|
19
|
+
|
20
|
+
== See also
|
21
|
+
|
22
|
+
Rant Homepage::
|
23
|
+
http://make.ruby-co.de
|
24
|
+
Rant Overview::
|
25
|
+
README[link:files/README.html]
|
26
|
+
Rant::FileList documentation::
|
27
|
+
doc/filelist.rdoc[link:files/doc/filelist_rdoc.html]
|
data/doc/sys.rdoc
CHANGED
@@ -536,13 +536,26 @@ standard output:
|
|
536
536
|
# on windows: 'dmd "foo bar.d" util.d -offoo -I"/home/user/program files/d"'
|
537
537
|
# other systems: 'dmd foo\ bar.d util.d -offoo -I/home/user/program\ files/d'
|
538
538
|
|
539
|
+
* <b>regular_filename(path)</b>
|
540
|
+
|
541
|
+
Replaces all platform dependent filename separators with a slash,
|
542
|
+
thus returning a platform independent filename.
|
543
|
+
|
544
|
+
Examples:
|
545
|
+
|
546
|
+
# on windows:
|
547
|
+
sys.regular_filename('foo\bar') # "foo/bar"
|
548
|
+
|
549
|
+
# on all platforms:
|
550
|
+
sys.regular_filename('foo//bar') # "foo/bar"
|
551
|
+
|
539
552
|
* <b>glob(pattern1, pattern2, ...)</b>
|
540
553
|
|
541
554
|
<b>[pattern1, pattern2, ...]</b>
|
542
555
|
|
543
556
|
Returns a filelist including the given patterns. For a discussion of
|
544
|
-
filelists, read
|
545
|
-
doc/
|
557
|
+
filelists, read
|
558
|
+
doc/sys_filelist.rdoc[link:files/doc/sys_filelist_rdoc.html].
|
546
559
|
|
547
560
|
Examples:
|
548
561
|
|
@@ -0,0 +1,118 @@
|
|
1
|
+
|
2
|
+
== Using filelists in Rantfiles
|
3
|
+
|
4
|
+
You can find documentation for Rant's +FileList+ class in the file
|
5
|
+
doc/filelist.rdoc[link:files/doc/filelist_rdoc.html]. This document
|
6
|
+
describes how you can use filelists in your Rant build scripts
|
7
|
+
(Rantfiles).
|
8
|
+
|
9
|
+
First of all, you don't need to <tt>require</tt> or <tt>import</tt>
|
10
|
+
anything to use filelists in Rantfiles. Additionally the
|
11
|
+
<tt>Rant::FileList</tt> class is directly available as +FileList+.
|
12
|
+
Thus, for example, instead of typing:
|
13
|
+
|
14
|
+
c_files = Rant::FileList["*.c"]
|
15
|
+
|
16
|
+
you can type:
|
17
|
+
|
18
|
+
c_files = FileList["*.c"]
|
19
|
+
|
20
|
+
Again, you don't need to <tt>require "rant/filelist"</tt>. But if you
|
21
|
+
want to use one of the methods +no_dir+, +files+ or +dirs+ <tt>import
|
22
|
+
"filelist/std"</tt> is required.
|
23
|
+
|
24
|
+
Often there are files/directories you want to always ignore when using
|
25
|
+
filelists. This could be the "CVS" directories if you are using the
|
26
|
+
CVS version control system or simply all backup files.
|
27
|
+
|
28
|
+
Rant allows you to specify a set of patterns once for your project
|
29
|
+
with the <tt>sys.ignore</tt> method.
|
30
|
+
|
31
|
+
E.g. place the following line of code in your Rantfile:
|
32
|
+
|
33
|
+
sys.ignore "CVS", /~$/
|
34
|
+
|
35
|
+
In the Rant::FileList documentation there are five ways to create a
|
36
|
+
filelist documented. In Rantfiles:
|
37
|
+
|
38
|
+
instead of | use
|
39
|
+
-----------------------------------------------------------------
|
40
|
+
Rant::FileList.new | sys.filelist
|
41
|
+
Rant::FileList[*patterns] | sys[*patterns]
|
42
|
+
Rant::FileList.glob(*patterns) | sys.glob(*patterns)
|
43
|
+
Rant::FileList.glob_all(*patterns) | sys.glob_all(*patterns)
|
44
|
+
Rant::FileList(list) | sys.filelist(list)
|
45
|
+
|
46
|
+
The <tt>sys</tt> variants of filelist creation all honour the project
|
47
|
+
wide ignore patterns set by <tt>sys.ignore</tt>.
|
48
|
+
|
49
|
+
Let's look at an example. First an Rantfile using the "normal"
|
50
|
+
filelist constructors:
|
51
|
+
|
52
|
+
all_files = FileList["**/*"].ignore("CVS", /~$/)
|
53
|
+
lib_files = FileList["lib/**/*.rb"].ignore("CVS")
|
54
|
+
pkg_files = FileList["bin/*", "lib/**/*.rb", "test/**/*"].ignore("CVS", /~$/)
|
55
|
+
backup_files = FileList["**/*~"]
|
56
|
+
|
57
|
+
# define tasks
|
58
|
+
|
59
|
+
I admit that the example is a bit exaggerated, but in essence you
|
60
|
+
always have to care that you don't accidently include a backup file or
|
61
|
+
some file living under a "CVS" directory. Now look at the equivalent
|
62
|
+
Rantfile using <tt>sys</tt> to create filelists.
|
63
|
+
|
64
|
+
sys.ignore "CVS", /~$/
|
65
|
+
all_files = sys["**/*"]
|
66
|
+
lib_files = sys["lib/**/*.rb"]
|
67
|
+
pkg_files = sys["bin/*", "lib/**/*.rb", "test/**/*"]
|
68
|
+
backup_files = FileList["**/*~"]
|
69
|
+
|
70
|
+
# define tasks
|
71
|
+
|
72
|
+
Now, per default CVS directories and backup files won't appear in
|
73
|
+
filelists. We use a "stateless" filelist for +backup_files+, since all
|
74
|
+
backup files would be ignored otherwise.
|
75
|
+
|
76
|
+
== Where to use filelists?
|
77
|
+
|
78
|
+
Basically, you can use a filelist wherever you can use an array. The
|
79
|
+
following is a list of use cases where filelists are handy.
|
80
|
+
|
81
|
+
* As prerequisite list for a task. Example:
|
82
|
+
|
83
|
+
# get a list of all c files
|
84
|
+
c_files = sys["**/*.c"]
|
85
|
+
# get a list of all resulting object files
|
86
|
+
obj_files = c_files.ext("o")
|
87
|
+
|
88
|
+
# static library "foo" depends on all object files
|
89
|
+
file "libfoo.a" => obj_files do |t|
|
90
|
+
# build t.name from t.prerequisites (obj_files)
|
91
|
+
end
|
92
|
+
|
93
|
+
* As argument to file system operations. Example:
|
94
|
+
|
95
|
+
task :clean do
|
96
|
+
# remove all backup files
|
97
|
+
sys.rm_f FileList["**/*~"]
|
98
|
+
end
|
99
|
+
|
100
|
+
* If you want to apply an operation to a list of files, e.g.
|
101
|
+
substituting a variable in text files. Example:
|
102
|
+
|
103
|
+
# Do something with all files in the project
|
104
|
+
import "filelist/std"
|
105
|
+
sys["**/*"].files.each { |filename|
|
106
|
+
# do something with the file "filename"
|
107
|
+
}
|
108
|
+
|
109
|
+
== See also
|
110
|
+
|
111
|
+
Rant Overview::
|
112
|
+
README[link:files/README.html]
|
113
|
+
Rant::FileList documentation::
|
114
|
+
doc/filelist.rdoc[link:files/doc/filelist_rdoc.html]
|
115
|
+
Rantfile basics::
|
116
|
+
doc/rantfile.rdoc[link:files/doc/rantfile_rdoc.html]
|
117
|
+
Advanced Rantfiles::
|
118
|
+
doc/advanced.rdoc[link:files/doc/advanced_rdoc.html]
|
data/lib/rant.rb
CHANGED
@@ -13,7 +13,7 @@ module Rant
|
|
13
13
|
def inspect
|
14
14
|
# what's the right encoding for object_id ?
|
15
15
|
s = "#<#{self.class}:0x#{"%x" % object_id} "
|
16
|
-
s << "#{@actions.size} actions, #{@
|
16
|
+
s << "#{@actions.size} actions, #{@items.size} entries"
|
17
17
|
if @ignore_rx
|
18
18
|
is = @ignore_rx.inspect.gsub(/\n|\t/, ' ')
|
19
19
|
s << ", ignore#{is.squeeze ' '}"
|
data/lib/rant/cs_compiler.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
require 'rant/
|
2
|
+
require 'rant/init'
|
3
3
|
|
4
4
|
module Rant
|
5
5
|
# An object extending this module acts as an
|
@@ -277,7 +277,7 @@ module Rant
|
|
277
277
|
resources.each { |p|
|
278
278
|
cc_args << " -fresources=#{Env.shell_path(p)}"
|
279
279
|
}
|
280
|
-
cc_args << " " << sources
|
280
|
+
cc_args << " " << Rant::Sys.sp(sources) if sources
|
281
281
|
cc_args
|
282
282
|
end
|
283
283
|
|
@@ -302,7 +302,7 @@ module Rant
|
|
302
302
|
resources.each { |p|
|
303
303
|
cc_args << " /res:#{Env.shell_path(p)}"
|
304
304
|
}
|
305
|
-
cc_args << " " << sources
|
305
|
+
cc_args << " " << Rant::Sys.sp(sources) if sources
|
306
306
|
cc_args
|
307
307
|
end
|
308
308
|
|
@@ -328,7 +328,7 @@ module Rant
|
|
328
328
|
resources.each { |p|
|
329
329
|
cc_args << " -resource:#{Env.shell_path(p)}"
|
330
330
|
}
|
331
|
-
cc_args << " " << sources
|
331
|
+
cc_args << " " << Rant::Sys.sp(sources) if sources
|
332
332
|
cc_args
|
333
333
|
end
|
334
334
|
|
data/lib/rant/import/archive.rb
CHANGED
@@ -154,16 +154,16 @@ module Rant::Generators::Archive
|
|
154
154
|
fl = @files ? @files.dup : []
|
155
155
|
if @manifest
|
156
156
|
fl = read_manifest unless @files
|
157
|
-
fl = Rant::
|
158
|
-
fl
|
157
|
+
fl = Rant::FileList(fl)
|
158
|
+
fl.keep(@manifest)
|
159
159
|
elsif @files_only
|
160
|
-
fl = Rant::
|
160
|
+
fl = Rant::FileList(fl)
|
161
161
|
fl.no_dirs
|
162
162
|
else
|
163
|
-
fl = Rant::
|
163
|
+
fl = Rant::FileList(fl)
|
164
164
|
end
|
165
165
|
# remove leading `./' relicts
|
166
|
-
@res_files = fl.
|
166
|
+
@res_files = fl.map! { |fn| fn.sub(/^\.\/(?=.)/,'') }
|
167
167
|
if defined?(@dist_path) && @dist_path
|
168
168
|
# Remove entries from the dist_path directory, which
|
169
169
|
# would create some sort of weird recursion.
|
@@ -172,7 +172,7 @@ module Rant::Generators::Archive
|
|
172
172
|
# but since I tapped into this trap frequently now...
|
173
173
|
@res_files.exclude(/^#{Regexp.escape @dist_path}/)
|
174
174
|
end
|
175
|
-
@res_files.
|
175
|
+
@res_files.uniq!.sort!
|
176
176
|
end
|
177
177
|
|
178
178
|
# Creates an (eventually) temporary manifest file and yields
|
@@ -0,0 +1,429 @@
|
|
1
|
+
|
2
|
+
# core.rb - Core functionality for the Rant::FileList class.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
module Rant
|
7
|
+
def FileList(arg)
|
8
|
+
if arg.respond_to?(:to_rant_filelist)
|
9
|
+
arg.to_rant_filelist
|
10
|
+
elsif arg.respond_to?(:to_ary)
|
11
|
+
FileList.new(arg.to_ary)
|
12
|
+
# or?
|
13
|
+
#FileList.new.concat(arg.to_ary)
|
14
|
+
else
|
15
|
+
raise TypeError,
|
16
|
+
"cannot convert #{arg.class} into Rant::FileList"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
module_function :FileList
|
20
|
+
class FileList
|
21
|
+
include Enumerable
|
22
|
+
|
23
|
+
ESC_SEPARATOR = Regexp.escape(File::SEPARATOR)
|
24
|
+
ESC_ALT_SEPARATOR = File::ALT_SEPARATOR ?
|
25
|
+
Regexp.escape(File::ALT_SEPARATOR) : nil
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def [](*patterns)
|
29
|
+
new.hide_dotfiles.include(*patterns)
|
30
|
+
end
|
31
|
+
def glob(*patterns)
|
32
|
+
fl = new.hide_dotfiles.ignore(".", "..").include(*patterns)
|
33
|
+
if block_given? then yield fl else fl end
|
34
|
+
end
|
35
|
+
def glob_all(*patterns)
|
36
|
+
fl = new.ignore(".", "..").include(*patterns)
|
37
|
+
if block_given? then yield fl else fl end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(store = [])
|
42
|
+
@pending = false
|
43
|
+
@def_glob_dotfiles = true
|
44
|
+
@items = store
|
45
|
+
@ignore_rx = nil
|
46
|
+
@keep = {}
|
47
|
+
@actions = []
|
48
|
+
end
|
49
|
+
alias _object_dup dup
|
50
|
+
private :_object_dup
|
51
|
+
def dup
|
52
|
+
c = _object_dup
|
53
|
+
c.items = @items.dup
|
54
|
+
c.actions = @actions.dup
|
55
|
+
c.ignore_rx = @ignore_rx.dup if @ignore_rx
|
56
|
+
c.instance_variable_set(:@keep, @keep.dup)
|
57
|
+
c
|
58
|
+
end
|
59
|
+
def copy
|
60
|
+
c = _object_dup
|
61
|
+
c.items = @items.map { |entry| entry.dup }
|
62
|
+
c.actions = @actions.dup
|
63
|
+
c.ignore_rx = @ignore_rx.dup if @ignore_rx
|
64
|
+
# alternative approach: copy & freeze "keep" entries on
|
65
|
+
# inclusion in the keep hash
|
66
|
+
h_keep = {}
|
67
|
+
@keep.each_key { |entry| h_keep[entry] = true }
|
68
|
+
c.instance_variable_set(:@keep, h_keep)
|
69
|
+
c
|
70
|
+
end
|
71
|
+
# Currently for Rant internal use only. Might go in future
|
72
|
+
# releases.
|
73
|
+
def glob_dotfiles?
|
74
|
+
@def_glob_dotfiles
|
75
|
+
end
|
76
|
+
# Currently for Rant internal use only. Might go in future
|
77
|
+
# releases.
|
78
|
+
def glob_dotfiles=(flag)
|
79
|
+
@def_glob_dotfiles = flag ? true : false
|
80
|
+
end
|
81
|
+
# Has the same effect as <tt>glob_dotfiles = false</tt>.
|
82
|
+
#
|
83
|
+
# Returns self.
|
84
|
+
#
|
85
|
+
# Currently for Rant internal use only. Might go in future
|
86
|
+
# releases.
|
87
|
+
def hide_dotfiles
|
88
|
+
@def_glob_dotfiles = false
|
89
|
+
self
|
90
|
+
end
|
91
|
+
# Has the same effect as <tt>glob_dotfiles = true</tt>.
|
92
|
+
#
|
93
|
+
# Returns self.
|
94
|
+
#
|
95
|
+
# Currently for Rant internal use only. Might go in future
|
96
|
+
# releases.
|
97
|
+
def glob_dotfiles
|
98
|
+
@def_glob_dotfiles = true
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
attr_accessor :actions, :items
|
104
|
+
attr_accessor :pending
|
105
|
+
attr_accessor :ignore_rx
|
106
|
+
|
107
|
+
public
|
108
|
+
def each(&block)
|
109
|
+
resolve if @pending
|
110
|
+
@items.each(&block)
|
111
|
+
self
|
112
|
+
end
|
113
|
+
def to_ary
|
114
|
+
resolve if @pending
|
115
|
+
@items
|
116
|
+
end
|
117
|
+
alias to_a to_ary
|
118
|
+
alias entries to_ary # entries: defined in Enumerable
|
119
|
+
def to_rant_filelist
|
120
|
+
self
|
121
|
+
end
|
122
|
+
def +(other)
|
123
|
+
if other.respond_to? :to_rant_filelist
|
124
|
+
c = other.to_rant_filelist.dup
|
125
|
+
c.actions.concat(@actions)
|
126
|
+
c.items.concat(@items)
|
127
|
+
c.pending = !c.actions.empty?
|
128
|
+
c
|
129
|
+
elsif other.respond_to? :to_ary
|
130
|
+
c = dup
|
131
|
+
c.actions <<
|
132
|
+
[:apply_ary_method_1, :concat, other.to_ary.dup]
|
133
|
+
c.pending = true
|
134
|
+
c
|
135
|
+
else
|
136
|
+
raise TypeError,
|
137
|
+
"cannot add #{other.class} to Rant::FileList"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
# Use this method to append +file+ to this list. +file+ will
|
141
|
+
# stay in this list even if it matches an exclude or ignore
|
142
|
+
# pattern.
|
143
|
+
#
|
144
|
+
# Returns self.
|
145
|
+
def <<(file)
|
146
|
+
@actions << [:apply_ary_method_1, :push, file]
|
147
|
+
@keep[file] = true
|
148
|
+
@pending = true
|
149
|
+
self
|
150
|
+
end
|
151
|
+
# Add +entry+ to this filelist. Position of +entry+ in this
|
152
|
+
# list is undefined. More efficient than #<<. +entry+ will
|
153
|
+
# stay in this list even if it matches an exclude or ignore
|
154
|
+
# pattern.
|
155
|
+
#
|
156
|
+
# Returns self.
|
157
|
+
def keep(entry)
|
158
|
+
@keep[entry] = true
|
159
|
+
@items << entry
|
160
|
+
self
|
161
|
+
end
|
162
|
+
# Append the entries of +ary+ (an array like object) to
|
163
|
+
# this list.
|
164
|
+
def concat(ary)
|
165
|
+
if @pending
|
166
|
+
ary = ary.to_ary.dup
|
167
|
+
@actions << [:apply_ary_method_1, :concat, ary]
|
168
|
+
else
|
169
|
+
ix = ignore_rx and ary = ary.to_ary.reject { |f| f =~ ix }
|
170
|
+
@items.concat(ary)
|
171
|
+
end
|
172
|
+
self
|
173
|
+
end
|
174
|
+
# Number of entries in this filelist.
|
175
|
+
def size
|
176
|
+
resolve if @pending
|
177
|
+
@items.size
|
178
|
+
end
|
179
|
+
alias length size
|
180
|
+
def empty?
|
181
|
+
resolve if @pending
|
182
|
+
@items.empty?
|
183
|
+
end
|
184
|
+
def join(sep = ' ')
|
185
|
+
resolve if @pending
|
186
|
+
@items.join(sep)
|
187
|
+
end
|
188
|
+
def pop
|
189
|
+
resolve if @pending
|
190
|
+
@items.pop
|
191
|
+
end
|
192
|
+
def push(entry)
|
193
|
+
resolve if @pending
|
194
|
+
@items.push(entry) if entry !~ ignore_rx
|
195
|
+
self
|
196
|
+
end
|
197
|
+
def shift
|
198
|
+
resolve if @pending
|
199
|
+
@items.shift
|
200
|
+
end
|
201
|
+
def unshift(entry)
|
202
|
+
resolve if @pending
|
203
|
+
@items.unshift(entry) if entry !~ ignore_rx
|
204
|
+
self
|
205
|
+
end
|
206
|
+
if Object.method_defined?(:fcall) || Object.method_defined?(:funcall) # in Ruby 1.9 like __send__
|
207
|
+
@@__send_private__ = Object.method_defined?(:fcall) ? :fcall : :funcall
|
208
|
+
def resolve
|
209
|
+
@pending = false
|
210
|
+
@actions.each{ |action| self.__send__(@@__send_private__, *action) }.clear
|
211
|
+
ix = ignore_rx
|
212
|
+
if ix
|
213
|
+
@items.reject! { |f| f =~ ix && !@keep[f] }
|
214
|
+
end
|
215
|
+
self
|
216
|
+
end
|
217
|
+
else
|
218
|
+
# Force evaluation of all patterns.
|
219
|
+
def resolve
|
220
|
+
@pending = false
|
221
|
+
@actions.each{ |action| self.__send__(*action) }.clear
|
222
|
+
ix = ignore_rx
|
223
|
+
if ix
|
224
|
+
@items.reject! { |f| f =~ ix && !@keep[f] }
|
225
|
+
end
|
226
|
+
self
|
227
|
+
end
|
228
|
+
end
|
229
|
+
# Include entries matching one of +patterns+ in this filelist.
|
230
|
+
def include(*pats)
|
231
|
+
@def_glob_dotfiles ? glob_all(*pats) : glob_unix(*pats)
|
232
|
+
end
|
233
|
+
alias glob include
|
234
|
+
# Unix style glob: hide files starting with a dot
|
235
|
+
def glob_unix(*patterns)
|
236
|
+
patterns.flatten.each { |pat|
|
237
|
+
@actions << [:apply_glob_unix, pat]
|
238
|
+
}
|
239
|
+
@pending = true
|
240
|
+
self
|
241
|
+
end
|
242
|
+
def glob_all(*patterns)
|
243
|
+
patterns.flatten.each { |pat|
|
244
|
+
@actions << [:apply_glob_all, pat]
|
245
|
+
}
|
246
|
+
@pending = true
|
247
|
+
self
|
248
|
+
end
|
249
|
+
if RUBY_VERSION < "1.8.2"
|
250
|
+
# Dir.glob of Ruby releases before 1.8.2 returned dotfiles
|
251
|
+
# even if File::FNM_DOTMATCH was not set.
|
252
|
+
FN_DOTFILE_RX_ = ESC_ALT_SEPARATOR ?
|
253
|
+
/(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)\..*
|
254
|
+
((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x :
|
255
|
+
/(^|#{ESC_SEPARATOR}+)\..* (#{ESC_SEPARATOR}+|$)/x
|
256
|
+
def apply_glob_unix(pattern)
|
257
|
+
inc_files = Dir.glob(pattern)
|
258
|
+
# it's not 100% correct, but it works for most use
|
259
|
+
# cases
|
260
|
+
unless pattern =~ /(^|\/)\./
|
261
|
+
inc_files.reject! { |fn| fn =~ FN_DOTFILE_RX_ }
|
262
|
+
end
|
263
|
+
@items.concat(inc_files)
|
264
|
+
end
|
265
|
+
else
|
266
|
+
def apply_glob_unix(pattern)
|
267
|
+
@items.concat(Dir.glob(pattern))
|
268
|
+
end
|
269
|
+
end
|
270
|
+
private :apply_glob_unix
|
271
|
+
def apply_glob_all(pattern)
|
272
|
+
@items.concat(Dir.glob(pattern, File::FNM_DOTMATCH))
|
273
|
+
end
|
274
|
+
private :apply_glob_all
|
275
|
+
# Exclude all entries matching one of +patterns+ from this
|
276
|
+
# filelist.
|
277
|
+
#
|
278
|
+
# Note: Only applies to entries previousely included.
|
279
|
+
def exclude(*patterns)
|
280
|
+
patterns.each { |pat|
|
281
|
+
if Regexp === pat
|
282
|
+
@actions << [:apply_exclude_rx, pat]
|
283
|
+
else
|
284
|
+
@actions << [:apply_exclude, pat]
|
285
|
+
end
|
286
|
+
}
|
287
|
+
@pending = true
|
288
|
+
self
|
289
|
+
end
|
290
|
+
def ignore(*patterns)
|
291
|
+
patterns.each { |pat|
|
292
|
+
add_ignore_rx(Regexp === pat ? pat : mk_all_rx(pat))
|
293
|
+
}
|
294
|
+
@pending = true
|
295
|
+
self
|
296
|
+
end
|
297
|
+
def add_ignore_rx(rx)
|
298
|
+
@ignore_rx =
|
299
|
+
if @ignore_rx
|
300
|
+
Regexp.union(@ignore_rx, rx)
|
301
|
+
else
|
302
|
+
rx
|
303
|
+
end
|
304
|
+
end
|
305
|
+
private :add_ignore_rx
|
306
|
+
def apply_exclude(pattern)
|
307
|
+
@items.reject! { |elem|
|
308
|
+
File.fnmatch?(pattern, elem, File::FNM_DOTMATCH) && !@keep[elem]
|
309
|
+
}
|
310
|
+
end
|
311
|
+
private :apply_exclude
|
312
|
+
def apply_exclude_rx(rx)
|
313
|
+
@items.reject! { |elem|
|
314
|
+
elem =~ rx && !@keep[elem]
|
315
|
+
}
|
316
|
+
end
|
317
|
+
private :apply_exclude_rx
|
318
|
+
def exclude_name(*names)
|
319
|
+
names.each { |name|
|
320
|
+
@actions << [:apply_exclude_rx, mk_all_rx(name)]
|
321
|
+
}
|
322
|
+
@pending = true
|
323
|
+
self
|
324
|
+
end
|
325
|
+
alias shun exclude_name
|
326
|
+
if File::ALT_SEPARATOR
|
327
|
+
# TODO: check for FS case sensitivity?
|
328
|
+
def mk_all_rx(file)
|
329
|
+
/(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)#{Regexp.escape(file)}
|
330
|
+
((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x
|
331
|
+
end
|
332
|
+
else
|
333
|
+
def mk_all_rx(file)
|
334
|
+
/(^|#{ESC_SEPARATOR}+)#{Regexp.escape(file)}
|
335
|
+
(#{ESC_SEPARATOR}+|$)/x
|
336
|
+
end
|
337
|
+
end
|
338
|
+
private :mk_all_rx
|
339
|
+
def exclude_path(*patterns)
|
340
|
+
patterns.each { |pat|
|
341
|
+
@actions << [:apply_exclude_path, pat]
|
342
|
+
}
|
343
|
+
@pending = true
|
344
|
+
self
|
345
|
+
end
|
346
|
+
def apply_exclude_path(pattern)
|
347
|
+
flags = File::FNM_DOTMATCH|File::FNM_PATHNAME
|
348
|
+
@items.reject! { |elem|
|
349
|
+
File.fnmatch?(pattern, elem, flags) && !@keep[elem]
|
350
|
+
}
|
351
|
+
end
|
352
|
+
private :apply_exclude
|
353
|
+
def select(&block)
|
354
|
+
d = dup
|
355
|
+
d.actions << [:apply_select, block]
|
356
|
+
d.pending = true
|
357
|
+
d
|
358
|
+
end
|
359
|
+
alias find_all select
|
360
|
+
def apply_select blk
|
361
|
+
@items = @items.select(&blk)
|
362
|
+
end
|
363
|
+
private :apply_select
|
364
|
+
def map(&block)
|
365
|
+
d = dup
|
366
|
+
d.actions << [:apply_ary_method, :map!, block]
|
367
|
+
d.pending = true
|
368
|
+
d
|
369
|
+
end
|
370
|
+
alias collect map
|
371
|
+
def sub_ext(ext, new_ext=nil)
|
372
|
+
map { |f| f._rant_sub_ext ext, new_ext }
|
373
|
+
end
|
374
|
+
def ext(ext_str)
|
375
|
+
sub_ext(ext_str)
|
376
|
+
end
|
377
|
+
# Get a string with all entries. This is very usefull
|
378
|
+
# if you invoke a shell:
|
379
|
+
# files # => ["foo/bar", "with space"]
|
380
|
+
# sh "rdoc #{files.arglist}"
|
381
|
+
# will result on windows:
|
382
|
+
# rdoc foo\bar "with space"
|
383
|
+
# on other systems:
|
384
|
+
# rdoc foo/bar with\ space
|
385
|
+
def arglist
|
386
|
+
Rant::Sys.sp to_ary
|
387
|
+
end
|
388
|
+
alias to_s arglist
|
389
|
+
alias object_inspect inspect
|
390
|
+
# Same as #uniq! but evaluation is delayed until the next read
|
391
|
+
# access (e.g. by calling #each). Always returns self.
|
392
|
+
def uniq!
|
393
|
+
@actions << [:apply_ary_method, :uniq!]
|
394
|
+
@pending = true
|
395
|
+
self
|
396
|
+
end
|
397
|
+
# Same as #sort! but evaluation is delayed until the next read
|
398
|
+
# access (e.g. by calling #each). Always returns self.
|
399
|
+
def sort!
|
400
|
+
@actions << [:apply_ary_method, :sort!]
|
401
|
+
@pending = true
|
402
|
+
self
|
403
|
+
end
|
404
|
+
# Same as #map! but evaluation is delayed until the next read
|
405
|
+
# access (e.g. by calling #each). Always returns self.
|
406
|
+
def map!(&block)
|
407
|
+
@actions << [:apply_ary_method, :map!, block]
|
408
|
+
@pending = true
|
409
|
+
self
|
410
|
+
end
|
411
|
+
def reject!(&block)
|
412
|
+
@actions << [:apply_ary_method, :reject!, block]
|
413
|
+
@pending = true
|
414
|
+
self
|
415
|
+
end
|
416
|
+
private
|
417
|
+
def apply_ary_method(meth, block=nil)
|
418
|
+
@items.send meth, &block
|
419
|
+
end
|
420
|
+
def apply_ary_method_1(meth, arg1, block=nil)
|
421
|
+
@items.send meth, arg1, &block
|
422
|
+
end
|
423
|
+
=begin
|
424
|
+
def apply_lazy_operation(meth, args, block)
|
425
|
+
@items.send(meth, *args, &block)
|
426
|
+
end
|
427
|
+
=end
|
428
|
+
end # class FileList
|
429
|
+
end # module Rant
|