rant 0.4.2 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS +14 -0
- data/README +13 -7
- data/Rantfile +11 -0
- data/doc/md5.rdoc +49 -0
- data/doc/rantfile.rdoc +1 -1
- data/lib/rant/coregen.rb +193 -0
- data/lib/rant/import/archive/zip.rb +2 -0
- data/lib/rant/import/archive.rb +10 -2
- data/lib/rant/import/autoclean.rb +16 -7
- data/lib/rant/import/c/dependencies.rb +1 -1
- data/lib/rant/import/directedrule.rb +2 -2
- data/lib/rant/import/md5.rb +16 -0
- data/lib/rant/import/metadata.rb +162 -0
- data/lib/rant/import/nodes/default.rb +490 -0
- data/lib/rant/import/nodes/signed.rb +84 -0
- data/lib/rant/import/package/zip.rb +2 -0
- data/lib/rant/import/rubydoc.rb +5 -1
- data/lib/rant/import/rubypackage.rb +2 -1
- data/lib/rant/import/signature/md5.rb +38 -0
- data/lib/rant/import/signedfile.rb +235 -0
- data/lib/rant/import/subfile.rb +1 -1
- data/lib/rant/import.rb +5 -1
- data/lib/rant/node.rb +165 -0
- data/lib/rant/plugin/csharp.rb +2 -0
- data/lib/rant/rantlib.rb +64 -9
- data/lib/rant/rantsys.rb +39 -27
- data/lib/rant/rantvar.rb +32 -2
- data/misc/TODO +66 -0
- data/test/import/c/dependencies/test_on_the_fly.rb +52 -0
- data/test/import/metadata/Rantfile +16 -0
- data/test/import/metadata/sub/Rantfile +17 -0
- data/test/import/metadata/test_metadata.rb +126 -0
- data/test/import/nodes/signed/Rantfile +89 -0
- data/test/import/nodes/signed/sub1/Rantfile +6 -0
- data/test/import/nodes/signed/test_signed.rb +455 -0
- data/test/import/package/md5.rf +10 -0
- data/test/import/package/test_package.rb +127 -1
- data/test/import/signeddirectory/Rantfile +15 -0
- data/test/import/signeddirectory/test_signeddirectory.rb +84 -0
- data/test/import/signedfile/Rantfile +90 -0
- data/test/import/signedfile/sub1/Rantfile +4 -0
- data/test/import/signedfile/test_signedfile.rb +338 -0
- data/test/project1/Rantfile +0 -9
- data/test/project1/test_project.rb +2 -0
- data/test/project_rb1/test_project_rb1.rb +27 -10
- data/test/rant-import/test_rant-import.rb +46 -9
- data/test/subdirs/sub2/sub/rantfile +0 -5
- data/test/subdirs/test_subdirs.rb +0 -9
- data/test/test_examples.rb +131 -3
- data/test/test_filelist.rb +44 -0
- data/test/test_sys.rb +19 -1
- data/test/test_task.rb +2 -2
- data/test/tutil.rb +9 -3
- metadata +34 -4
- data/lib/rant/rantfile.rb +0 -897
- data/test/test_lighttask.rb +0 -68
data/NEWS
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
|
2
2
|
= Rant NEWS
|
3
3
|
|
4
|
+
== Rant 0.4.4
|
5
|
+
|
6
|
+
Besides internal changes, this release is backwards compatible to
|
7
|
+
0.4.2.
|
8
|
+
|
9
|
+
Fixes and minor improvements:
|
10
|
+
* Rant is Ruby 1.8.0 compatible now.
|
11
|
+
* Fixes for filelists.
|
12
|
+
* A fix for Directory generator (and thus dependent features).
|
13
|
+
|
14
|
+
New features:
|
15
|
+
* Optional recognition of file changes based on MD5 checksums.
|
16
|
+
Read doc/md5.rdoc[link:files/doc/md5_rdoc.html] for documentation.
|
17
|
+
|
4
18
|
== Rant 0.4.2
|
5
19
|
|
6
20
|
This is mainly a bugfix release and thus fully backwards compatible to
|
data/README
CHANGED
@@ -16,6 +16,8 @@ Rant currently features:
|
|
16
16
|
so you don't depend on an rant installation anymore.
|
17
17
|
* Creating gzipped tar and zip archives -- without installing
|
18
18
|
additional software.
|
19
|
+
* Optional recognition of file changes based on MD5 checksums instead
|
20
|
+
of file modification times.
|
19
21
|
* Primitive support for compiling C# sources portably with csc, cscc
|
20
22
|
and mcs.
|
21
23
|
* Dependency checking for C/C++ source files.
|
@@ -28,7 +30,7 @@ basic example of rant usage:
|
|
28
30
|
A file called +Rantfile+ contains the code:
|
29
31
|
|
30
32
|
file "backup/data" => "data" do |t|
|
31
|
-
sys.cp
|
33
|
+
sys.cp t.source, t.name
|
32
34
|
end
|
33
35
|
|
34
36
|
Running rant in the directory of this file:
|
@@ -39,7 +41,7 @@ Running rant in the directory of this file:
|
|
39
41
|
will ensure that the "data" file in the "backup" directory is up to
|
40
42
|
date.
|
41
43
|
|
42
|
-
This document was written for version 0.4.
|
44
|
+
This document was written for version 0.4.4 of Rant. Most things
|
43
45
|
described here will work for older/newer versions of Rant, but look at
|
44
46
|
the README file in the Rant distribution you've installed for exact
|
45
47
|
documentation of your Rant version.
|
@@ -49,9 +51,10 @@ documentation of your Rant version.
|
|
49
51
|
The newest version of this document can be found at
|
50
52
|
http://make.rubyforge.org.
|
51
53
|
|
52
|
-
For further information, feature requests, bugreports or comments
|
53
|
-
|
54
|
-
{
|
54
|
+
For further information, feature requests, bugreports or comments join
|
55
|
+
the mailing list
|
56
|
+
{make-cafe}[http://rubyforge.org/mailman/listinfo/make-cafe] or visit
|
57
|
+
the {RubyForge site for Rant}[http://rubyforge.org/projects/make/].
|
55
58
|
|
56
59
|
Also feel free to contact the author directly by sending an email to
|
57
60
|
mailto:langstefan@gmx.at.
|
@@ -74,6 +77,8 @@ Advanced Rantfiles::
|
|
74
77
|
read doc/advanced.rdoc[link:files/doc/advanced_rdoc.html]
|
75
78
|
Packaging (creating zip/tgz archives)::
|
76
79
|
read doc/package.rdoc[link:files/doc/package_rdoc.html]
|
80
|
+
Using MD5 checksums instead of file modification times::
|
81
|
+
read doc/md5.rdoc[link:files/doc/md5_rdoc.html]
|
77
82
|
Compiling C/C++::
|
78
83
|
read doc/c.rdoc[link:files/doc/c_rdoc.html]
|
79
84
|
Using the Configure plugin::
|
@@ -204,7 +209,8 @@ Rant was tested on:
|
|
204
209
|
|
205
210
|
System Ruby version
|
206
211
|
=======================================================
|
207
|
-
Linux 1.8.
|
212
|
+
Linux 1.8.0
|
213
|
+
1.8.1
|
208
214
|
1.8.2
|
209
215
|
1.8.3 preview 1
|
210
216
|
1.9
|
@@ -215,7 +221,7 @@ Rant was tested on:
|
|
215
221
|
It *should* run on most platforms where Ruby runs, but you never
|
216
222
|
know...
|
217
223
|
|
218
|
-
If you encounter problems with Rant on any platform (with Ruby 1.8.
|
224
|
+
If you encounter problems with Rant on any platform (with Ruby 1.8.0
|
219
225
|
or higher) please write a bugreport!
|
220
226
|
|
221
227
|
=== Why did you write another build tool?
|
data/Rantfile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
|
2
2
|
# Rantfile for Rant :)
|
3
3
|
|
4
|
+
import "md5"
|
4
5
|
import %w(rubytest rubydoc rubypackage autoclean win32/rubycmdwrapper)
|
5
6
|
|
6
7
|
task :default => :test
|
@@ -8,6 +9,10 @@ task :default => :test
|
|
8
9
|
dist_files = sys["{bin,lib,test,doc,misc}/**/*"]
|
9
10
|
dist_files.shun("html", "coverage")
|
10
11
|
dist_files += sys["*"].no_dir.exclude("InstalledFiles", "Session.vim")
|
12
|
+
|
13
|
+
# remove when compiler stuff is getting useful...
|
14
|
+
dist_files.exclude "lib/rant/compiler*", "lib/rant/import/c/program.rb"
|
15
|
+
|
11
16
|
rdoc_opts = %w(-S -c UTF-8 --title Rant --main README)
|
12
17
|
|
13
18
|
gen RubyPackage, "rant" do |t|
|
@@ -103,6 +108,12 @@ gen RubyTest, :tall do |g|
|
|
103
108
|
g.test_files = sys["test/**/test_*.rb"]
|
104
109
|
end
|
105
110
|
|
111
|
+
task :t180 do |t|
|
112
|
+
# my installed testrb version doesn't work with ruby-1.8.0
|
113
|
+
sys.cd "test"
|
114
|
+
sys "ruby180 ts_all.rb"
|
115
|
+
end
|
116
|
+
|
106
117
|
desc "Remove autogenerated files."
|
107
118
|
gen AutoClean, :clean
|
108
119
|
var[:clean].include %w(
|
data/doc/md5.rdoc
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
== Using MD5 checksums to detect file changes
|
3
|
+
|
4
|
+
Most build tools rely on the modification time of a file which is
|
5
|
+
updated usually when a program writes to the file. But this is not
|
6
|
+
always as accurate as one would like, e.g. when you edit a C source
|
7
|
+
file to simple change/add a comment, the compiler will probably
|
8
|
+
produce the same object file as before. The build tool recognizes that
|
9
|
+
the file modification time of the object file is newer than that of
|
10
|
+
the target program and rebuilds the target program.
|
11
|
+
|
12
|
+
With MD5 checksums instead of file modification times, the build tool
|
13
|
+
recognizes that the object file didn't change and thus the target
|
14
|
+
program doesn't need to be rebuilt.
|
15
|
+
|
16
|
+
Even worse is the case where the file modification time isn't updated
|
17
|
+
or is corrupted and the build tool thinks a source file hasn't changed
|
18
|
+
were in fact it has! In other words, with MD5 checksums, the build
|
19
|
+
tool recognizes when the *contents* of a file changes.
|
20
|
+
|
21
|
+
To enable this nice feature for your project, put this single line at
|
22
|
+
the top (before other +import+, +task+, +file+ or +gen+ statements) of
|
23
|
+
the Rantfile:
|
24
|
+
|
25
|
+
import "md5"
|
26
|
+
|
27
|
+
Note that Rant saves the checksums after a build in a file called
|
28
|
+
<tt>.rant.meta</tt>. If you remove this file, Rant looses all
|
29
|
+
information about the last builds, and so will rebuild all targets on
|
30
|
+
invocation.
|
31
|
+
|
32
|
+
If you want to switch back to modification time based builds, simply
|
33
|
+
remove the <tt>import "md5"</tt> statement and remove the file
|
34
|
+
<tt>.rant.meta</tt>.
|
35
|
+
|
36
|
+
== See also
|
37
|
+
|
38
|
+
Writing an Rantfile::
|
39
|
+
doc/rantfile.rdoc[link:files/doc/rantfile_rdoc.html]
|
40
|
+
Advanced Rantfiles::
|
41
|
+
doc/advanced.rdoc[link:files/doc/advanced_rdoc.html]
|
42
|
+
Support for C/C++::
|
43
|
+
doc/c.rdoc[link:files/doc/c_rdoc.html]
|
44
|
+
Packaging::
|
45
|
+
doc/package.rdoc[link:files/doc/package_rdoc.html]
|
46
|
+
Ruby project howto::
|
47
|
+
doc/rubyproject.rdoc[link:files/doc/rubyproject_rdoc.html]
|
48
|
+
Rant Overview::
|
49
|
+
README[link:files/README.html]
|
data/doc/rantfile.rdoc
CHANGED
data/lib/rant/coregen.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
|
2
|
+
# coregen.rb - Generators available in all Rantfiles.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
module Rant
|
7
|
+
module Generators
|
8
|
+
class Task
|
9
|
+
def self.rant_gen(rac, ch, args, &block)
|
10
|
+
unless args.size == 1
|
11
|
+
rac.abort("Task takes only one argument " +
|
12
|
+
"which has to be like one given to the " +
|
13
|
+
"`task' function")
|
14
|
+
end
|
15
|
+
rac.prepare_task(args.first, nil, ch) { |name,pre,blk|
|
16
|
+
rac.node_factory.new_custom(rac, name, pre, block)
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
class Directory
|
21
|
+
# Generate a task for making a directory path.
|
22
|
+
# Prerequisites can be given, which will be added as
|
23
|
+
# prerequistes for the _last_ directory.
|
24
|
+
#
|
25
|
+
# A special feature is used if you provide a block: The
|
26
|
+
# block will be called after complete directory creation.
|
27
|
+
# After the block execution, the modification time of the
|
28
|
+
# directory will be updated.
|
29
|
+
def self.rant_gen(rac, ch, args, &block)
|
30
|
+
case args.size
|
31
|
+
when 1
|
32
|
+
name, pre = rac.normalize_task_arg(args.first, ch)
|
33
|
+
self.task(rac, ch, name, pre, &block)
|
34
|
+
when 2
|
35
|
+
basedir = args.shift
|
36
|
+
if basedir.respond_to? :to_str
|
37
|
+
basedir = basedir.to_str
|
38
|
+
else
|
39
|
+
rac.abort_at(ch,
|
40
|
+
"Directory: basedir argument has to be a string.")
|
41
|
+
end
|
42
|
+
name, pre = rac.normalize_task_arg(args.first, ch)
|
43
|
+
self.task(rac, ch, name, pre, basedir, &block)
|
44
|
+
else
|
45
|
+
rac.abort_at(ch, "Directory takes one argument, " +
|
46
|
+
"which should be like one given to the `task' command.")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the task which creates the last directory
|
51
|
+
# element (and has all other necessary directories as
|
52
|
+
# prerequisites).
|
53
|
+
def self.task(rac, ch, name, prerequisites=[], basedir=nil, &block)
|
54
|
+
dirs = ::Rant::Sys.split_path(name)
|
55
|
+
if dirs.empty?
|
56
|
+
rac.abort_at(ch,
|
57
|
+
"Not a valid directory name: `#{name}'")
|
58
|
+
end
|
59
|
+
path = basedir
|
60
|
+
last_task = nil
|
61
|
+
task_block = nil
|
62
|
+
desc_for_last = rac.pop_desc
|
63
|
+
dirs.each { |dir|
|
64
|
+
pre = [path]
|
65
|
+
pre.compact!
|
66
|
+
if dir.equal?(dirs.last)
|
67
|
+
rac.cx.desc desc_for_last
|
68
|
+
|
69
|
+
# add prerequisites to pre
|
70
|
+
# if prerequisites is a FileList: there is
|
71
|
+
# only one save (no later removal) way to add
|
72
|
+
# an entry: with <<
|
73
|
+
dp = prerequisites.dup
|
74
|
+
pre.each { |elem| dp << elem }
|
75
|
+
pre = dp
|
76
|
+
|
77
|
+
task_block = block
|
78
|
+
end
|
79
|
+
path = path.nil? ? dir : File.join(path, dir)
|
80
|
+
last_task = rac.prepare_task({:__caller__ => ch,
|
81
|
+
path => pre}, task_block) { |name,pre,blk|
|
82
|
+
rac.node_factory.new_dir(rac, name, pre, blk)
|
83
|
+
}
|
84
|
+
}
|
85
|
+
last_task
|
86
|
+
end
|
87
|
+
end # class Directory
|
88
|
+
class SourceNode
|
89
|
+
def self.rant_gen(rac, ch, args)
|
90
|
+
unless args.size == 1
|
91
|
+
rac.abort_at(ch, "SourceNode takes one argument.")
|
92
|
+
end
|
93
|
+
if block_given?
|
94
|
+
rac.abort_at(ch, "SourceNode doesn't take a block.")
|
95
|
+
end
|
96
|
+
rac.prepare_task(args.first, nil, ch) { |name, pre, blk|
|
97
|
+
rac.node_factory.new_source(rac, name, pre, blk)
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
class Rule < ::Proc
|
102
|
+
# Generate a rule by installing an at_resolve hook for
|
103
|
+
# +rac+.
|
104
|
+
def self.rant_gen(rac, ch, args, &block)
|
105
|
+
unless args.size == 1
|
106
|
+
rac.abort_at(ch, "Rule takes only one argument.")
|
107
|
+
end
|
108
|
+
arg = args.first
|
109
|
+
target = nil
|
110
|
+
src_arg = nil
|
111
|
+
if Symbol === arg
|
112
|
+
target = ".#{arg}"
|
113
|
+
elsif arg.respond_to? :to_str
|
114
|
+
target = arg.to_str
|
115
|
+
elsif Regexp === arg
|
116
|
+
target = arg
|
117
|
+
elsif Hash === arg && arg.size == 1
|
118
|
+
arg.each_pair { |target, src_arg| }
|
119
|
+
src_arg = src_arg.to_str if src_arg.respond_to? :to_str
|
120
|
+
target = target.to_str if target.respond_to? :to_str
|
121
|
+
src_arg = ".#{src_arg}" if Symbol === src_arg
|
122
|
+
target = ".#{target}" if Symbol === target
|
123
|
+
else
|
124
|
+
rac.abort_at(ch, "Rule argument " +
|
125
|
+
"has to be a hash with one key-value pair.")
|
126
|
+
end
|
127
|
+
esc_target = nil
|
128
|
+
target_rx = case target
|
129
|
+
when String
|
130
|
+
esc_target = Regexp.escape(target)
|
131
|
+
/#{esc_target}$/
|
132
|
+
when Regexp
|
133
|
+
target
|
134
|
+
else
|
135
|
+
rac.abort_at(ch, "rule target has " +
|
136
|
+
"to be a string or regular expression")
|
137
|
+
end
|
138
|
+
src_proc = case src_arg
|
139
|
+
when String
|
140
|
+
unless String === target
|
141
|
+
rac.abort(ch, "rule target has to be a string " +
|
142
|
+
"if source is a string")
|
143
|
+
end
|
144
|
+
lambda { |name| name.sub(/#{esc_target}$/, src_arg) }
|
145
|
+
when Proc: src_arg
|
146
|
+
when nil: lambda { |name| [] }
|
147
|
+
else
|
148
|
+
rac.abort_at(ch, "rule source has to be " +
|
149
|
+
"String or Proc")
|
150
|
+
end
|
151
|
+
blk = self.new { |task_name|
|
152
|
+
if target_rx =~ task_name
|
153
|
+
have_src = true
|
154
|
+
src = src_proc[task_name]
|
155
|
+
if src.respond_to? :to_ary
|
156
|
+
src.each { |f|
|
157
|
+
if rac.resolve(f).empty? && !test(?e, f)
|
158
|
+
have_src = false
|
159
|
+
break
|
160
|
+
end
|
161
|
+
}
|
162
|
+
else
|
163
|
+
if rac.resolve(src).empty? && !test(?e, src)
|
164
|
+
have_src = false
|
165
|
+
end
|
166
|
+
end
|
167
|
+
if have_src
|
168
|
+
t = rac.file(:__caller__ => ch,
|
169
|
+
task_name => src_proc[task_name], &block)
|
170
|
+
t.project_subdir = rac.current_subdir
|
171
|
+
[t]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
}
|
175
|
+
blk.target_rx = target_rx
|
176
|
+
rac.resolve_hooks << blk
|
177
|
+
nil
|
178
|
+
end
|
179
|
+
attr_accessor :target_rx
|
180
|
+
end # class Rule
|
181
|
+
class Action
|
182
|
+
def self.rant_gen(rac, ch, args, &block)
|
183
|
+
unless args.empty?
|
184
|
+
rac.warn_msg(rac.pos_text(ch[:file], ch[:ln]),
|
185
|
+
"Action doesn't take arguments.")
|
186
|
+
end
|
187
|
+
unless (rac[:tasks] || rac[:stop_after_load])
|
188
|
+
yield
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end # module Generators
|
193
|
+
end # module Rant
|
@@ -42,6 +42,8 @@ module Rant::Generators::Archive
|
|
42
42
|
end
|
43
43
|
def rubyzip fn, files, opts = {:recurse => false}
|
44
44
|
require 'rant/archive/rubyzip'
|
45
|
+
# rubyzip creates only a new file if fn doesn't exist
|
46
|
+
@rac.sys.rm_f fn if test ?e, fn
|
45
47
|
@rac.cmd_msg "rubyzip #{fn}"
|
46
48
|
Rant::Archive::Rubyzip::ZipFile.open fn,
|
47
49
|
Rant::Archive::Rubyzip::ZipFile::CREATE do |z|
|
data/lib/rant/import/archive.rb
CHANGED
@@ -160,6 +160,14 @@ module Rant::Generators::Archive
|
|
160
160
|
end
|
161
161
|
# remove leading `./' relicts
|
162
162
|
@res_files = fl.lazy_map! { |fn| fn.sub(/^\.\/(?=.)/,'') }
|
163
|
+
if defined?(@dist_path) && @dist_path
|
164
|
+
# Remove entries from the dist_path directory, which
|
165
|
+
# would create some sort of weird recursion.
|
166
|
+
#
|
167
|
+
# Normally, the Rantfile writer should care himself,
|
168
|
+
# but since I tapped into this trap frequently now...
|
169
|
+
@res_files.exclude(/^#{Regexp.escape @dist_path}/)
|
170
|
+
end
|
163
171
|
@res_files.lazy_uniq!.lazy_sort!
|
164
172
|
end
|
165
173
|
|
@@ -187,7 +195,7 @@ module Rant::Generators::Archive
|
|
187
195
|
def define_manifest_task
|
188
196
|
return @manifest_task if @manifest_task
|
189
197
|
@manifest_task =
|
190
|
-
@rac.gen ::Rant::Task, @manifest do |t|
|
198
|
+
@rac.gen ::Rant::Generators::Task, @manifest do |t|
|
191
199
|
def t.each_target
|
192
200
|
goto_task_home
|
193
201
|
yield name
|
@@ -249,12 +257,12 @@ module Rant::Generators::Archive
|
|
249
257
|
def define_task_for_dir(&block)
|
250
258
|
return @pkg_task if @pkg_task
|
251
259
|
|
252
|
-
get_files # set @res_files
|
253
260
|
@dist_dirname = File.split(name).last
|
254
261
|
@dist_dirname << "-#@version" if @version
|
255
262
|
@dist_root, = File.split path
|
256
263
|
@dist_path = (@dist_root == "." ?
|
257
264
|
@dist_dirname : File.join(@dist_root, @dist_dirname))
|
265
|
+
get_files # set @res_files
|
258
266
|
|
259
267
|
targ = {get_archive_path => [@dist_path]}
|
260
268
|
#STDERR.puts "basedir: #{basedir}, fn: #@archive_path"
|
@@ -58,15 +58,24 @@ class Rant::Generators::AutoClean
|
|
58
58
|
end
|
59
59
|
}
|
60
60
|
end
|
61
|
+
common = rac.var._get("__autoclean_common__")
|
62
|
+
if common
|
63
|
+
rac.rantfiles.each{ |rf|
|
64
|
+
sd = rf.project_subdir
|
65
|
+
common.each { |fn|
|
66
|
+
path = sd.empty? ? fn : File.join(sd, fn)
|
67
|
+
clean rac, path
|
68
|
+
}
|
69
|
+
}
|
70
|
+
end
|
71
|
+
t.goto_task_home
|
61
72
|
end
|
62
73
|
end
|
63
74
|
def self.clean(rac, entry)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
75
|
+
if test ?f, entry
|
76
|
+
rac.cx.sys.rm_f entry
|
77
|
+
elsif test ?e, entry
|
78
|
+
rac.cx.sys.rm_rf entry
|
79
|
+
end
|
71
80
|
end
|
72
81
|
end
|
@@ -91,7 +91,7 @@ class Rant::Generators::C::Dependencies
|
|
91
91
|
f_task = tmp_rac.tasks[cf.to_str]
|
92
92
|
deps = f_task ? f_task.prerequisites : nil
|
93
93
|
if !deps or File.mtime(cf) > depfile_ts
|
94
|
-
rac.cmd_msg "
|
94
|
+
rac.cmd_msg "scanning #{cf}"
|
95
95
|
std_includes, local_includes =
|
96
96
|
::Rant::C::Include.parse_includes(File.read(cf))
|
97
97
|
deps = []
|
@@ -93,7 +93,7 @@ class Rant::Generators::DirectedRule
|
|
93
93
|
# pre 0.3.7
|
94
94
|
#[@rac.file(:__caller__ => @ch, name => src, &@block)]
|
95
95
|
[@rac.prepare_task({name => src}, @block, @ch) { |name,pre,blk|
|
96
|
-
|
96
|
+
@rac.node_factory.new_auto_subfile(@rac, name, pre, blk)
|
97
97
|
}]
|
98
98
|
else
|
99
99
|
nil
|
@@ -105,7 +105,7 @@ class Rant::Generators::DirectedRule
|
|
105
105
|
def define_hook
|
106
106
|
@rac.resolve_hooks << self
|
107
107
|
end
|
108
|
-
def each_target
|
108
|
+
def each_target(&block)
|
109
109
|
@rac.cx.sys["#@target_dir/*"].each { |entry|
|
110
110
|
yield entry if entry =~ @target_rx
|
111
111
|
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
# md5.rb - Use md5 checksums to recognize source changes.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
#require 'rant/import/signature/md5' #rant-import:uncomment
|
7
|
+
#require 'rant/import/metadata' #rant-import:uncomment
|
8
|
+
#require 'rant/import/nodes/signed' #rant-import:uncomment
|
9
|
+
|
10
|
+
module Rant
|
11
|
+
def self.init_import_md5(rac, *rest)
|
12
|
+
rac.import "signature/md5"
|
13
|
+
rac.import "metadata"
|
14
|
+
rac.import "nodes/signed"
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
|
2
|
+
# metadata.rb - Management of meta-information for Rant targets.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
module Rant
|
7
|
+
|
8
|
+
def self.init_import_metadata(rac, *rest)
|
9
|
+
mi = MetaData::Interface.new(rac)
|
10
|
+
rac.var._set("__metadata__", mi)
|
11
|
+
rac.at_return(&mi.method(:save))
|
12
|
+
rac.var._init("__autoclean_common__", []) << MetaData::META_FN
|
13
|
+
end
|
14
|
+
|
15
|
+
module MetaData
|
16
|
+
|
17
|
+
META_FN = ".rant.meta"
|
18
|
+
|
19
|
+
class Interface
|
20
|
+
|
21
|
+
def initialize(rac)
|
22
|
+
@rac = rac
|
23
|
+
# the keys in this hash are project directory names,
|
24
|
+
# the corresponding values are again hashes and their
|
25
|
+
# keys are target names
|
26
|
+
@store = {}
|
27
|
+
# just a set
|
28
|
+
@modified_dirs = {}
|
29
|
+
# just a set
|
30
|
+
@read_dirs = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Fetch the meta value associated with the given key for
|
34
|
+
# target in dir. Note that the value will probably end in
|
35
|
+
# a newline. Very important is, that the +dir+ (third
|
36
|
+
# argument, relative to the projects root directory) has
|
37
|
+
# to be the current working directory! An example:
|
38
|
+
# project root directory: /home/foo/myproject
|
39
|
+
# dir: bar
|
40
|
+
# => Dir.pwd has to be: /home/foo/myproject/bar
|
41
|
+
#
|
42
|
+
# Returns nil only if the value doesn't exist.
|
43
|
+
def fetch(key, target, dir=@rac.current_subdir)
|
44
|
+
# first check if a value for the given key, target and
|
45
|
+
# dir already exists
|
46
|
+
dstore = @store[dir]
|
47
|
+
if dstore
|
48
|
+
tstore = dstore[target]
|
49
|
+
if tstore
|
50
|
+
val = tstore[key]
|
51
|
+
return val if val
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# check if the meta file in dir was already read
|
55
|
+
unless @read_dirs.include? dir
|
56
|
+
read_meta_file_in_dir(dir)
|
57
|
+
end
|
58
|
+
tstore = @store[dir][target]
|
59
|
+
tstore[key] if tstore
|
60
|
+
end
|
61
|
+
|
62
|
+
# Set the key-value pair for the given target in dir. Note
|
63
|
+
# that if value.class is not String, the value will be
|
64
|
+
# replaced with a newline! key should also be a string and
|
65
|
+
# mustn't contain a newline.
|
66
|
+
#
|
67
|
+
# Returns nil.
|
68
|
+
def set(key, value, target, dir=@rac.current_subdir)
|
69
|
+
value = "\n" unless value.class == String
|
70
|
+
@modified_dirs[dir] ||= true
|
71
|
+
dstore = @store[dir]
|
72
|
+
unless dstore
|
73
|
+
@store[dir] = {target => {key => value}}
|
74
|
+
return
|
75
|
+
end
|
76
|
+
tstore = dstore[target]
|
77
|
+
if tstore
|
78
|
+
tstore[key] = value
|
79
|
+
else
|
80
|
+
dstore[target] = {key => value}
|
81
|
+
end
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
|
85
|
+
# Assumes to be called from the projects root directory.
|
86
|
+
def save
|
87
|
+
@modified_dirs.each_key { |dir|
|
88
|
+
write_dstore(@store[dir], dir)
|
89
|
+
}
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
# assumes that dir is already the current working
|
95
|
+
# directory
|
96
|
+
def read_meta_file_in_dir(dir)
|
97
|
+
#puts "in dir: #{dir}, pwd: #{Dir.pwd}"
|
98
|
+
@read_dirs[dir] = true
|
99
|
+
#fn = dir.empty? ? META_FN : File.join(dir, META_FN)
|
100
|
+
fn = META_FN
|
101
|
+
dstore = @store[dir]
|
102
|
+
@store[dir] = dstore = {} unless dstore
|
103
|
+
return unless File.exist? fn
|
104
|
+
open fn do |f|
|
105
|
+
# first line should only contain "Rant", later
|
106
|
+
# Rant versions can add version and other
|
107
|
+
# information
|
108
|
+
invalid_format(fn) unless f.readline == "Rant\n"
|
109
|
+
until f.eof?
|
110
|
+
target_name = f.readline.chomp!
|
111
|
+
dstore[target_name] = read_target_data(f)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
rescue
|
115
|
+
invalid_format(fn)
|
116
|
+
end
|
117
|
+
|
118
|
+
def read_target_data(file)
|
119
|
+
h = {}
|
120
|
+
num_of_entries = file.readline.to_i
|
121
|
+
num_of_entries.times { |i|
|
122
|
+
key = file.readline.chomp!
|
123
|
+
value = ""
|
124
|
+
file.readline.to_i.times { |j|
|
125
|
+
value << file.readline
|
126
|
+
}
|
127
|
+
value.chomp!
|
128
|
+
h[key] = value
|
129
|
+
}
|
130
|
+
h
|
131
|
+
end
|
132
|
+
|
133
|
+
# assumes to be called from the projects root directory
|
134
|
+
def write_dstore(dstore, dir)
|
135
|
+
fn = dir.empty? ? META_FN : File.join(dir, META_FN)
|
136
|
+
target = sigs = key = value = lines = nil
|
137
|
+
open fn, "w" do |f|
|
138
|
+
f.puts "Rant"
|
139
|
+
dstore.each { |target, sigs|
|
140
|
+
f.puts target
|
141
|
+
f.puts sigs.size
|
142
|
+
sigs.each { |key, value|
|
143
|
+
f.puts key
|
144
|
+
lines = value.split(/\n/)
|
145
|
+
f.puts lines.size
|
146
|
+
f.puts lines
|
147
|
+
}
|
148
|
+
}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def invalid_format(fn)
|
153
|
+
raise Rant::Error, "The file `#{fn}' is used by " +
|
154
|
+
"Rant to store meta information, it is in an " +
|
155
|
+
"invalid state. Check that it doesn't contain " +
|
156
|
+
"important data, remove it and retry."
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end # module MetaData
|
162
|
+
end # module Rant
|