rant 0.4.2 → 0.4.4
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.
- 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
|