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
@@ -0,0 +1,490 @@
|
|
1
|
+
|
2
|
+
# default.rb - Default node types for Rant.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
module Rant
|
7
|
+
|
8
|
+
def self.init_import_nodes__default(rac, *rest)
|
9
|
+
rac.node_factory = DefaultNodeFactory.new
|
10
|
+
end
|
11
|
+
|
12
|
+
class DefaultNodeFactory
|
13
|
+
def new_task(rac, name, pre, blk)
|
14
|
+
Task.new(rac, name, pre, &blk)
|
15
|
+
end
|
16
|
+
def new_file(rac, name, pre, blk)
|
17
|
+
FileTask.new(rac, name, pre, &blk)
|
18
|
+
end
|
19
|
+
def new_dir(rac, name, pre, blk)
|
20
|
+
DirTask.new(rac, name, pre, &blk)
|
21
|
+
end
|
22
|
+
def new_source(rac, name, pre, blk)
|
23
|
+
SourceNode.new(rac, name, pre, &blk)
|
24
|
+
end
|
25
|
+
def new_custom(rac, name, pre, blk)
|
26
|
+
UserTask.new(rac, name, pre, &blk)
|
27
|
+
end
|
28
|
+
def new_auto_subfile(rac, name, pre, blk)
|
29
|
+
AutoSubFileTask.new(rac, name, pre, &blk)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Task
|
34
|
+
include Node
|
35
|
+
include Console
|
36
|
+
|
37
|
+
def initialize(rac, name, prerequisites = [], &block)
|
38
|
+
super()
|
39
|
+
@rac = rac || Rant.rac
|
40
|
+
@name = name or raise ArgumentError, "name not given"
|
41
|
+
@pre = prerequisites || []
|
42
|
+
@pre_resolved = false
|
43
|
+
@block = block
|
44
|
+
@run = false
|
45
|
+
# success has one of three values:
|
46
|
+
# nil no invoke
|
47
|
+
# false invoked, but fail
|
48
|
+
# true invoked and run successfully
|
49
|
+
@success = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get a list of the *names* of all prerequisites. The
|
53
|
+
# underlying list of prerequisites can't be modified by the
|
54
|
+
# value returned by this method.
|
55
|
+
def prerequisites
|
56
|
+
@pre.collect { |pre| pre.to_s }
|
57
|
+
end
|
58
|
+
alias deps prerequisites
|
59
|
+
|
60
|
+
# First prerequisite.
|
61
|
+
def source
|
62
|
+
@pre.first.to_s
|
63
|
+
end
|
64
|
+
|
65
|
+
# True if this task has at least one action (block to be
|
66
|
+
# executed) associated.
|
67
|
+
def has_actions?
|
68
|
+
!!@block
|
69
|
+
end
|
70
|
+
|
71
|
+
# Add a prerequisite.
|
72
|
+
def <<(pre)
|
73
|
+
@pre_resolved = false
|
74
|
+
@pre << pre
|
75
|
+
end
|
76
|
+
|
77
|
+
# Was this task ever invoked? If this is true, it doesn't
|
78
|
+
# necessarily mean that the run was successfull!
|
79
|
+
def invoked?
|
80
|
+
!@success.nil?
|
81
|
+
end
|
82
|
+
|
83
|
+
# True if last task run fail.
|
84
|
+
def fail?
|
85
|
+
@success == false
|
86
|
+
end
|
87
|
+
|
88
|
+
# Task was run and didn't fail.
|
89
|
+
def done?
|
90
|
+
@success
|
91
|
+
end
|
92
|
+
|
93
|
+
# Enhance this task with the given dependencies and blk.
|
94
|
+
def enhance(deps = nil, &blk)
|
95
|
+
if deps
|
96
|
+
@pre_resolved = false
|
97
|
+
@pre.concat deps
|
98
|
+
end
|
99
|
+
if @block
|
100
|
+
if blk
|
101
|
+
first_block = @block
|
102
|
+
@block = lambda { |t|
|
103
|
+
first_block[t]
|
104
|
+
blk[t]
|
105
|
+
}
|
106
|
+
end
|
107
|
+
else
|
108
|
+
@block = blk
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def needed?
|
113
|
+
invoke(:needed? => true)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns a true value if task was acutally run.
|
117
|
+
# Raises Rant::TaskFail to signal task (or prerequiste) failure.
|
118
|
+
def invoke(opt = INVOKE_OPT)
|
119
|
+
return circular_dep if @run
|
120
|
+
@run = true
|
121
|
+
begin
|
122
|
+
return if done?
|
123
|
+
internal_invoke opt
|
124
|
+
ensure
|
125
|
+
@run = false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def internal_invoke opt, ud_init = true
|
130
|
+
goto_task_home
|
131
|
+
update = ud_init || opt[:force]
|
132
|
+
dep = nil
|
133
|
+
uf = false
|
134
|
+
each_dep { |dep|
|
135
|
+
if dep.respond_to? :timestamp
|
136
|
+
handle_timestamped(dep, opt) && update = true
|
137
|
+
elsif Node === dep
|
138
|
+
handle_node(dep, opt) && update = true
|
139
|
+
else
|
140
|
+
dep, uf = handle_non_node(dep, opt)
|
141
|
+
uf && update = true
|
142
|
+
dep
|
143
|
+
end
|
144
|
+
}
|
145
|
+
# Never run a task block for a "needed?" query.
|
146
|
+
return update if opt[:needed?]
|
147
|
+
run if update
|
148
|
+
@success = true
|
149
|
+
# IMPORTANT: return update flag
|
150
|
+
update
|
151
|
+
rescue StandardError => e
|
152
|
+
@success = false
|
153
|
+
self.fail(nil, e)
|
154
|
+
end
|
155
|
+
private :internal_invoke
|
156
|
+
|
157
|
+
# Called from internal_invoke. +dep+ is a prerequisite which
|
158
|
+
# is_a? Node, but not a FileTask. +opt+ are opts as given to
|
159
|
+
# Node#invoke.
|
160
|
+
#
|
161
|
+
# Override this method in subclasses to modify behaviour of
|
162
|
+
# prerequisite handling.
|
163
|
+
#
|
164
|
+
# See also: handle_timestamped, handle_non_node
|
165
|
+
def handle_node(dep, opt)
|
166
|
+
dep.invoke opt
|
167
|
+
end
|
168
|
+
|
169
|
+
# Called from internal_invoke. +dep+ is a prerequisite which
|
170
|
+
# is_a? FileTask. +opt+ are opts as given to Node#invoke.
|
171
|
+
#
|
172
|
+
# Override this method in subclasses to modify behaviour of
|
173
|
+
# prerequisite handling.
|
174
|
+
#
|
175
|
+
# See also: handle_node, handle_non_node
|
176
|
+
def handle_timestamped(dep, opt)
|
177
|
+
dep.invoke opt
|
178
|
+
end
|
179
|
+
|
180
|
+
# Override in subclass if specific task can handle
|
181
|
+
# non-task-prerequisites.
|
182
|
+
#
|
183
|
+
# Notes for overriding:
|
184
|
+
# This method should do one of the two following:
|
185
|
+
# [1] Fail with an exception.
|
186
|
+
# [2] Return two values: replacement_for_dep, update_required
|
187
|
+
#
|
188
|
+
# See also: handle_node, handle_timestamped
|
189
|
+
def handle_non_node(dep, opt)
|
190
|
+
err_msg "Unknown task `#{dep}',",
|
191
|
+
"referenced in `#{rantfile.path}', line #{@line_number}!"
|
192
|
+
self.fail
|
193
|
+
end
|
194
|
+
|
195
|
+
# For each non-worker prerequiste, the value returned from yield
|
196
|
+
# will replace the original prerequisite (of course only if
|
197
|
+
# @pre_resolved is false).
|
198
|
+
def each_dep
|
199
|
+
t = nil
|
200
|
+
if @pre_resolved
|
201
|
+
return @pre.each { |t| yield(t) }
|
202
|
+
end
|
203
|
+
my_full_name = full_name
|
204
|
+
my_project_subdir = project_subdir
|
205
|
+
@pre.map! { |t|
|
206
|
+
if Node === t
|
207
|
+
# Remove references to self from prerequisites!
|
208
|
+
if t.full_name == my_full_name
|
209
|
+
nil
|
210
|
+
else
|
211
|
+
yield(t)
|
212
|
+
t
|
213
|
+
end
|
214
|
+
else
|
215
|
+
t = t.to_s if Symbol === t
|
216
|
+
if t == my_full_name #TODO
|
217
|
+
nil
|
218
|
+
else
|
219
|
+
#STDERR.puts "selecting `#{t}'"
|
220
|
+
selection = @rac.resolve t,
|
221
|
+
my_project_subdir
|
222
|
+
#STDERR.puts selection.size
|
223
|
+
if selection.empty?
|
224
|
+
# use return value of yield
|
225
|
+
yield(t)
|
226
|
+
else
|
227
|
+
selection.each { |st| yield(st) }
|
228
|
+
selection
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
}
|
233
|
+
@pre.flatten!
|
234
|
+
@pre.compact!
|
235
|
+
@pre_resolved = true
|
236
|
+
end
|
237
|
+
end # class Task
|
238
|
+
|
239
|
+
# A UserTask is equivalent to a Task, but it additionally takes a
|
240
|
+
# block (see #needed) which is used to determine if it is needed?.
|
241
|
+
class UserTask < Task
|
242
|
+
|
243
|
+
def initialize(*args)
|
244
|
+
super
|
245
|
+
# super will set @block to a given block, but the block is
|
246
|
+
# used for initialization, not ment as action
|
247
|
+
@block = nil
|
248
|
+
@needed = nil
|
249
|
+
# allow setting of @block and @needed
|
250
|
+
yield self if block_given?
|
251
|
+
end
|
252
|
+
|
253
|
+
def act(&block)
|
254
|
+
@block = block
|
255
|
+
end
|
256
|
+
|
257
|
+
def needed(&block)
|
258
|
+
@needed = block
|
259
|
+
end
|
260
|
+
|
261
|
+
# We simply override this method and call internal_invoke with
|
262
|
+
# the +ud_init+ flag according to the result of a call to the
|
263
|
+
# +needed+ block.
|
264
|
+
def invoke(opt = INVOKE_OPT)
|
265
|
+
return circular_dep if @run
|
266
|
+
@run = true
|
267
|
+
begin
|
268
|
+
return if done?
|
269
|
+
internal_invoke(opt, ud_init_by_needed)
|
270
|
+
ensure
|
271
|
+
@run = false
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
private
|
276
|
+
def ud_init_by_needed
|
277
|
+
if @needed
|
278
|
+
goto_task_home
|
279
|
+
@needed.arity == 0 ? @needed.call : @needed[self]
|
280
|
+
#else: true #??
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end # class UserTask
|
284
|
+
|
285
|
+
class FileTask < Task
|
286
|
+
|
287
|
+
def initialize(*args)
|
288
|
+
super
|
289
|
+
@ts = T0
|
290
|
+
end
|
291
|
+
|
292
|
+
def needed?
|
293
|
+
return false if done?
|
294
|
+
invoke(:needed? => true)
|
295
|
+
end
|
296
|
+
|
297
|
+
def invoke(opt = INVOKE_OPT)
|
298
|
+
return circular_dep if @run
|
299
|
+
@run = true
|
300
|
+
begin
|
301
|
+
return if done?
|
302
|
+
goto_task_home
|
303
|
+
if File.exist? @name
|
304
|
+
@ts = File.mtime @name
|
305
|
+
internal_invoke opt, false
|
306
|
+
else
|
307
|
+
@ts = T0
|
308
|
+
internal_invoke opt, true
|
309
|
+
end
|
310
|
+
ensure
|
311
|
+
@run = false
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def timestamp
|
316
|
+
File.exist?(@name) ? File.mtime(@name) : T0
|
317
|
+
end
|
318
|
+
|
319
|
+
def handle_timestamped(dep, opt)
|
320
|
+
return true if dep.invoke opt
|
321
|
+
#puts "***`#{dep.name}' requires update" if dep.timestamp > @ts
|
322
|
+
dep.timestamp > @ts
|
323
|
+
end
|
324
|
+
|
325
|
+
def handle_non_node(dep, opt)
|
326
|
+
goto_task_home # !!??
|
327
|
+
unless File.exist? dep
|
328
|
+
err_msg @rac.pos_text(rantfile.path, line_number),
|
329
|
+
"in prerequisites: no such file or task: `#{dep}'"
|
330
|
+
self.fail
|
331
|
+
end
|
332
|
+
[dep, File.mtime(dep) > @ts]
|
333
|
+
end
|
334
|
+
|
335
|
+
def each_target
|
336
|
+
goto_task_home
|
337
|
+
yield name
|
338
|
+
end
|
339
|
+
end # class FileTask
|
340
|
+
|
341
|
+
module AutoInvokeDirNode
|
342
|
+
private
|
343
|
+
def run
|
344
|
+
goto_task_home
|
345
|
+
dir = File.dirname(name)
|
346
|
+
@rac.build dir unless dir == "."
|
347
|
+
return unless @block
|
348
|
+
@block.arity == 0 ? @block.call : @block[self]
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
class AutoSubFileTask < FileTask
|
353
|
+
include AutoInvokeDirNode
|
354
|
+
end
|
355
|
+
|
356
|
+
# An instance of this class is a task to create a _single_
|
357
|
+
# directory.
|
358
|
+
class DirTask < Task
|
359
|
+
|
360
|
+
def initialize(*args)
|
361
|
+
super
|
362
|
+
@ts = T0
|
363
|
+
@isdir = nil
|
364
|
+
end
|
365
|
+
|
366
|
+
def invoke(opt = INVOKE_OPT)
|
367
|
+
return circular_dep if @run
|
368
|
+
@run = true
|
369
|
+
begin
|
370
|
+
return if done?
|
371
|
+
goto_task_home
|
372
|
+
@isdir = test(?d, @name)
|
373
|
+
if @isdir
|
374
|
+
@ts = @block ? test(?M, @name) : Time.now
|
375
|
+
internal_invoke opt, false
|
376
|
+
else
|
377
|
+
@ts = T0
|
378
|
+
internal_invoke opt, true
|
379
|
+
end
|
380
|
+
ensure
|
381
|
+
@run = false
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def handle_timestamped(dep, opt)
|
386
|
+
return @block if dep.invoke opt
|
387
|
+
@block && dep.timestamp > @ts
|
388
|
+
end
|
389
|
+
|
390
|
+
def handle_non_node(dep, opt)
|
391
|
+
goto_task_home
|
392
|
+
unless File.exist? dep
|
393
|
+
err_msg @rac.pos_text(rantfile.path, line_number),
|
394
|
+
"in prerequisites: no such file or task: `#{dep}'"
|
395
|
+
self.fail
|
396
|
+
end
|
397
|
+
[dep, @block && File.mtime(dep) > @ts]
|
398
|
+
end
|
399
|
+
|
400
|
+
def run
|
401
|
+
@rac.sys.mkdir @name unless @isdir
|
402
|
+
if @block
|
403
|
+
@block.arity == 0 ? @block.call : @block[self]
|
404
|
+
goto_task_home
|
405
|
+
@rac.sys.touch @name
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
def each_target
|
410
|
+
goto_task_home
|
411
|
+
yield name
|
412
|
+
end
|
413
|
+
end # class DirTask
|
414
|
+
|
415
|
+
# A SourceNode describes dependencies between source files. Thus
|
416
|
+
# there is no action attached to a SourceNode. The target should
|
417
|
+
# be an existing file as well as all dependencies.
|
418
|
+
#
|
419
|
+
# An example would be a C source file which depends on other C
|
420
|
+
# source files because of <tt>#include</tt> statements.
|
421
|
+
#
|
422
|
+
# Rantfile usage:
|
423
|
+
# gen SourceNode, "myext.c" => %w(ruby.h myext.h)
|
424
|
+
class SourceNode
|
425
|
+
include Node
|
426
|
+
def initialize(rac, name, prerequisites = [])
|
427
|
+
super()
|
428
|
+
@rac = rac
|
429
|
+
@name = name or raise ArgumentError, "name not given"
|
430
|
+
@pre = prerequisites
|
431
|
+
@run = false
|
432
|
+
# The timestamp is the latest of this file and all
|
433
|
+
# dependencies:
|
434
|
+
@ts = nil
|
435
|
+
end
|
436
|
+
# Use this readonly!
|
437
|
+
def prerequisites
|
438
|
+
@pre
|
439
|
+
end
|
440
|
+
# Note: The timestamp will only be calculated once!
|
441
|
+
def timestamp
|
442
|
+
# Circular dependencies don't generate endless
|
443
|
+
# recursion/loops because before calling the timestamp
|
444
|
+
# method of any other node, we set @ts to some non-nil
|
445
|
+
# value.
|
446
|
+
return @ts if @ts
|
447
|
+
goto_task_home
|
448
|
+
if File.exist?(@name)
|
449
|
+
@ts = File.mtime @name
|
450
|
+
else
|
451
|
+
rac.abort(rac.pos_text(@rantfile, @line_number),
|
452
|
+
"SourceNode: no such file -- #@name")
|
453
|
+
end
|
454
|
+
sd = project_subdir
|
455
|
+
@pre.each { |f|
|
456
|
+
nodes = rac.resolve f, sd
|
457
|
+
if nodes.empty?
|
458
|
+
if File.exist? f
|
459
|
+
mtime = File.mtime f
|
460
|
+
@ts = mtime if mtime > @ts
|
461
|
+
else
|
462
|
+
rac.abort(rac.pos_text(@rantfile, @line_number),
|
463
|
+
"SourceNode: no such file -- #{f}")
|
464
|
+
end
|
465
|
+
else
|
466
|
+
nodes.each { |node|
|
467
|
+
if node.respond_to? :timestamp
|
468
|
+
node_ts = node.timestamp
|
469
|
+
goto_task_home
|
470
|
+
@ts = node_ts if node_ts > @ts
|
471
|
+
else
|
472
|
+
rac.abort(rac.pos_text(@rantfile, @line_number),
|
473
|
+
"SourceNode can't depend on #{node.name}")
|
474
|
+
end
|
475
|
+
}
|
476
|
+
end
|
477
|
+
}
|
478
|
+
@ts
|
479
|
+
end
|
480
|
+
def needed?
|
481
|
+
false
|
482
|
+
end
|
483
|
+
def invoke(opt = INVOKE_OPT)
|
484
|
+
false
|
485
|
+
end
|
486
|
+
def related_sources
|
487
|
+
@pre
|
488
|
+
end
|
489
|
+
end # class SourceNode
|
490
|
+
end # module Rant
|
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
# signed.rb - "Signed" node types for Rant.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
require 'rant/import/signedfile'
|
7
|
+
|
8
|
+
module Rant
|
9
|
+
def self.init_import_nodes__signed(rac, *rest)
|
10
|
+
rac.node_factory = SignedNodeFactory.new
|
11
|
+
end
|
12
|
+
class SignedNodeFactory < DefaultNodeFactory
|
13
|
+
def new_file(rac, name, pre, blk)
|
14
|
+
Generators::SignedFile.new(rac, name, pre, &blk)
|
15
|
+
end
|
16
|
+
def new_dir(rac, name, pre, blk)
|
17
|
+
Generators::SignedDirectory.new(rac, name, pre, &blk)
|
18
|
+
end
|
19
|
+
def new_auto_subfile(rac, name, pre, blk)
|
20
|
+
Generators::AutoSubSignedFile.new(rac, name, pre, &blk)
|
21
|
+
end
|
22
|
+
def new_source(rac, name, pre, blk)
|
23
|
+
SignedSourceNode.new(rac, name, pre, &blk)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
class SignedSourceNode < SourceNode
|
27
|
+
def initialize(*args)
|
28
|
+
super
|
29
|
+
@signature = nil
|
30
|
+
end
|
31
|
+
# Invokes prerequisites and returns a signature of the source
|
32
|
+
# file and all related source files.
|
33
|
+
# Note: The signature will only be calculated once.
|
34
|
+
def signature(opt = INVOKE_OPT)
|
35
|
+
return circular_dep if @run
|
36
|
+
@run = true
|
37
|
+
begin
|
38
|
+
return @signature if @signature
|
39
|
+
goto_task_home
|
40
|
+
sig_list = []
|
41
|
+
sig = @rac.var._get("__signature__")
|
42
|
+
if test(?f, @name)
|
43
|
+
@signature = sig.signature_for_file(@name)
|
44
|
+
else
|
45
|
+
@rac.abort(rac.pos_text(@rantfile, @line_number),
|
46
|
+
"SourceNode: no such file -- #@name")
|
47
|
+
end
|
48
|
+
sd = project_subdir
|
49
|
+
handled = {@name => true}
|
50
|
+
@pre.each { |f|
|
51
|
+
f = f.to_rant_target
|
52
|
+
next if handled.include? f
|
53
|
+
nodes = rac.resolve f, sd
|
54
|
+
if nodes.empty?
|
55
|
+
if test(?f, f)
|
56
|
+
sig_list << sig.signature_for_file(f)
|
57
|
+
else
|
58
|
+
rac.abort(rac.pos_text(@rantfile, @line_number),
|
59
|
+
"SourceNode: no such file -- #{f}")
|
60
|
+
end
|
61
|
+
else
|
62
|
+
file_sig = nil
|
63
|
+
nodes.each { |node|
|
64
|
+
node.invoke(opt)
|
65
|
+
if node.respond_to? :signature
|
66
|
+
sig_list << node.signature
|
67
|
+
goto_task_home
|
68
|
+
else
|
69
|
+
rac.abort(rac.pos_text(@rantfile, @line_number),
|
70
|
+
"SourceNode can't depend on #{node.name}")
|
71
|
+
end
|
72
|
+
}
|
73
|
+
sig_list << file_sig if file_sig
|
74
|
+
end
|
75
|
+
handled[f] = true
|
76
|
+
}
|
77
|
+
sig_list.sort!
|
78
|
+
@signature << sig_list.join
|
79
|
+
ensure
|
80
|
+
@run = false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end # class SignedSourceNode
|
84
|
+
end # module Rant
|
@@ -12,6 +12,8 @@ module Rant::Generators::Package
|
|
12
12
|
fn = @dist_dirname + (@extension ? @extension : "")
|
13
13
|
old_pwd = Dir.pwd
|
14
14
|
Dir.chdir @dist_root
|
15
|
+
# zip adds to existing archive
|
16
|
+
@rac.cx.sys.rm_f fn if test ?e, fn
|
15
17
|
# zip options:
|
16
18
|
# y: store symlinks instead of referenced files
|
17
19
|
# r: recurse into directories
|
data/lib/rant/import/rubydoc.rb
CHANGED
@@ -65,7 +65,11 @@ module Rant
|
|
65
65
|
# We delay the require of the RDoc code until it is
|
66
66
|
# actually needed, so it will be only loaded if the
|
67
67
|
# rdoc task has to be run.
|
68
|
-
|
68
|
+
begin
|
69
|
+
require 'rdoc/rdoc'
|
70
|
+
rescue LoadError
|
71
|
+
app.abort_at(ch, "RDoc not available.")
|
72
|
+
end
|
69
73
|
args = self.rdoc_args
|
70
74
|
app.cmd_msg "rdoc #{args.join(' ')}" if @verbose
|
71
75
|
begin
|
@@ -201,7 +201,8 @@ class Rant::Generators::RubyPackage
|
|
201
201
|
|
202
202
|
def pkg_dir_task
|
203
203
|
return if @pkg_dir_task
|
204
|
-
@pkg_dir_task =
|
204
|
+
@pkg_dir_task =
|
205
|
+
Rant::Generators::Directory.rant_gen(@app, @ch, [@pkg_dir])
|
205
206
|
end
|
206
207
|
|
207
208
|
# Create task for gem building. If tname is a true value, a
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
# md5.rb - Recognize file changes by md5 checksums.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
require 'digest/md5'
|
7
|
+
|
8
|
+
module Rant
|
9
|
+
def self.init_import_signature__md5(rac, *rest)
|
10
|
+
sig = Signature::MD5.new(rac)
|
11
|
+
rac.var._set("__signature_md5__", sig)
|
12
|
+
rac.var._init("__signature__", sig)
|
13
|
+
end
|
14
|
+
module Signature
|
15
|
+
class MD5
|
16
|
+
def initialize(rac)
|
17
|
+
#@rac = rac
|
18
|
+
end
|
19
|
+
def name
|
20
|
+
"md5"
|
21
|
+
end
|
22
|
+
def signature_for_file(filename)
|
23
|
+
signature_for_string(File.read(filename))
|
24
|
+
end
|
25
|
+
def signature_for_dir(dirname)
|
26
|
+
entries = Dir.entries(dirname)
|
27
|
+
entries.sort!
|
28
|
+
signature_for_string(entries.join << entries.size.to_s)
|
29
|
+
end
|
30
|
+
def signature_for_io(io)
|
31
|
+
signature_for_string(io.read)
|
32
|
+
end
|
33
|
+
def signature_for_string(str)
|
34
|
+
Digest::MD5.hexdigest(str)
|
35
|
+
end
|
36
|
+
end # class MD5
|
37
|
+
end # module Signature
|
38
|
+
end # module Rant
|