rant 0.3.2 → 0.3.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 +22 -1
- data/README +9 -12
- data/Rantfile +32 -9
- data/devel-notes +16 -0
- data/doc/advanced.rdoc +55 -0
- data/doc/rant.rdoc +27 -2
- data/doc/rantfile.rdoc +104 -30
- data/install.rb +6 -0
- data/lib/rant.rb +5 -1
- data/lib/rant/import.rb +12 -4
- data/lib/rant/import/rubydoc.rb +1 -1
- data/lib/rant/import/rubypackage.rb +2 -2
- data/lib/rant/import/rubytest.rb +3 -2
- data/lib/rant/plugin/csharp.rb +5 -9
- data/lib/rant/rantenv.rb +1 -0
- data/lib/rant/rantfile.rb +184 -68
- data/lib/rant/rantlib.rb +203 -195
- data/lib/rant/rantsys.rb +87 -44
- data/lib/rant/rantvar.rb +236 -17
- data/rantmethods.rb +9 -4
- data/run_rant +1 -1
- data/test/Rantfile +16 -0
- data/test/plugin/csharp/test_csharp.rb +2 -1
- data/test/plugin/rantfile +1 -0
- data/test/project1/Rantfile +8 -4
- data/test/rule.rf +27 -0
- data/test/subdirs/Rantfile +2 -0
- data/test/subdirs/sub2/sub/rantfile +17 -0
- data/test/subdirs/test_subdirs.rb +46 -2
- data/test/test_dirtask.rb +33 -0
- data/test/test_filelist.rb +81 -0
- data/test/test_filetask.rb +6 -6
- data/test/test_rant_interface.rb +4 -3
- data/test/test_rule.rb +67 -0
- data/test/test_source.rb +26 -0
- data/test/test_task.rb +27 -6
- data/test/test_var.rb +102 -0
- data/test/toplevel.rf +1 -1
- data/test/var.rf +19 -0
- metadata +11 -2
data/lib/rant/rantlib.rb
CHANGED
@@ -13,38 +13,6 @@ require 'rant/rantenv'
|
|
13
13
|
require 'rant/rantfile'
|
14
14
|
require 'rant/rantsys'
|
15
15
|
|
16
|
-
module Rant
|
17
|
-
VERSION = '0.3.2'
|
18
|
-
|
19
|
-
# Those are the filenames for rantfiles.
|
20
|
-
# Case matters!
|
21
|
-
RANTFILES = [ "Rantfile",
|
22
|
-
"rantfile",
|
23
|
-
"Rantfile.rb",
|
24
|
-
"rantfile.rb",
|
25
|
-
]
|
26
|
-
|
27
|
-
# Names of plugins and imports for which code was loaded.
|
28
|
-
# Files that where loaded with the `import' commant are directly
|
29
|
-
# added; files loaded with the `plugin' command are prefixed with
|
30
|
-
# "plugin/".
|
31
|
-
CODE_IMPORTS = []
|
32
|
-
|
33
|
-
class RantAbortException < StandardError
|
34
|
-
end
|
35
|
-
|
36
|
-
class RantDoneException < StandardError
|
37
|
-
end
|
38
|
-
|
39
|
-
class RantfileException < StandardError
|
40
|
-
end
|
41
|
-
|
42
|
-
# This module is a namespace for generator classes.
|
43
|
-
module Generators
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
16
|
# There is one problem with executing Rantfiles in a special context:
|
49
17
|
# In the top-level execution environment, there are some methods
|
50
18
|
# available which are not available to all objects. One example is the
|
@@ -56,6 +24,9 @@ end
|
|
56
24
|
Rant::MAIN_OBJECT = self
|
57
25
|
|
58
26
|
class Array
|
27
|
+
|
28
|
+
# Concatenates all elements like #join(' ') but also puts quotes
|
29
|
+
# around strings that contain a space.
|
59
30
|
def arglist
|
60
31
|
self.shell_pathes.join(' ')
|
61
32
|
end
|
@@ -82,6 +53,16 @@ class Array
|
|
82
53
|
end
|
83
54
|
end
|
84
55
|
|
56
|
+
class String
|
57
|
+
def sub_ext(ext, new_ext = nil)
|
58
|
+
if new_ext
|
59
|
+
self.sub(/#{Regexp.escape ext}$/, new_ext)
|
60
|
+
else
|
61
|
+
self.sub(/\.[^.]+$/, ".#{ext}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
85
66
|
module Rant::Lib
|
86
67
|
|
87
68
|
# Parses one string (elem) as it occurs in the array
|
@@ -89,51 +70,13 @@ module Rant::Lib
|
|
89
70
|
# E.g.:
|
90
71
|
# p parse_caller_elem "/usr/local/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding'"
|
91
72
|
# prints:
|
92
|
-
# {:
|
73
|
+
# {:ln=>52, :file=>"/usr/local/lib/ruby/1.8/irb/workspace.rb"}
|
93
74
|
def parse_caller_elem elem
|
94
75
|
parts = elem.split(":")
|
95
|
-
|
96
|
-
:ln => parts[1].to_i
|
97
|
-
}
|
98
|
-
=begin
|
99
|
-
# commented for better performance
|
100
|
-
meth = parts[2]
|
101
|
-
if meth && meth =~ /\`(\w+)'/
|
102
|
-
meth = $1
|
103
|
-
end
|
104
|
-
rh[:method] = meth
|
105
|
-
=end
|
106
|
-
rh
|
76
|
+
{ :file => parts[0], :ln => parts[1].to_i }
|
107
77
|
end
|
108
|
-
|
109
78
|
module_function :parse_caller_elem
|
110
79
|
|
111
|
-
# currently unused
|
112
|
-
class Caller
|
113
|
-
def self.[](i)
|
114
|
-
new(caller[i+1])
|
115
|
-
end
|
116
|
-
def initialize(clr)
|
117
|
-
@clr = clr
|
118
|
-
@file = @ln = nil
|
119
|
-
end
|
120
|
-
def file
|
121
|
-
unless @file
|
122
|
-
ca = Lib.parse_caller_elem(clr)
|
123
|
-
@file = ca[:file]
|
124
|
-
@ln = ca[:ln]
|
125
|
-
end
|
126
|
-
@file
|
127
|
-
end
|
128
|
-
def ln
|
129
|
-
unless @ln
|
130
|
-
ca = Lib.parse_caller_elem(clr)
|
131
|
-
@file = ca[:file]
|
132
|
-
@ln = ca[:ln]
|
133
|
-
end
|
134
|
-
@ln
|
135
|
-
end
|
136
|
-
end
|
137
80
|
end
|
138
81
|
|
139
82
|
# The methods in this module are the public interface to Rant that can
|
@@ -141,62 +84,69 @@ end
|
|
141
84
|
module RantContext
|
142
85
|
include Rant::Generators
|
143
86
|
|
87
|
+
Env = Rant::Env
|
88
|
+
FileList = Rant::FileList
|
89
|
+
|
144
90
|
# Define a basic task.
|
145
91
|
def task targ, &block
|
146
|
-
|
92
|
+
rac.task(targ, &block)
|
147
93
|
end
|
148
94
|
|
149
95
|
# Define a file task.
|
150
96
|
def file targ, &block
|
151
|
-
|
97
|
+
rac.file(targ, &block)
|
152
98
|
end
|
153
99
|
|
154
100
|
# Add code and/or prerequisites to existing task.
|
155
101
|
def enhance targ, &block
|
156
|
-
|
102
|
+
rac.enhance(targ, &block)
|
157
103
|
end
|
158
104
|
|
159
105
|
def desc(*args)
|
160
|
-
|
106
|
+
rac.desc(*args)
|
161
107
|
end
|
162
108
|
|
163
109
|
def gen(*args, &block)
|
164
|
-
|
110
|
+
rac.gen(*args, &block)
|
165
111
|
end
|
166
112
|
|
167
113
|
def import(*args, &block)
|
168
|
-
|
114
|
+
rac.import(*args, &block)
|
169
115
|
end
|
170
116
|
|
171
117
|
def plugin(*args, &block)
|
172
|
-
|
118
|
+
rac.plugin(*args, &block)
|
173
119
|
end
|
174
120
|
|
175
121
|
# Look in the subdirectories, given by args,
|
176
122
|
# for rantfiles.
|
177
123
|
def subdirs *args
|
178
|
-
|
124
|
+
rac.subdirs(*args)
|
179
125
|
end
|
180
126
|
|
181
127
|
def source rantfile
|
182
|
-
|
128
|
+
rac.source(rantfile)
|
129
|
+
end
|
130
|
+
|
131
|
+
def sys(*args, &block)
|
132
|
+
rac.sys(*args)
|
183
133
|
end
|
184
134
|
|
185
|
-
def
|
186
|
-
|
135
|
+
def var(*args, &block)
|
136
|
+
rac.var(*args, &block)
|
187
137
|
end
|
188
138
|
end # module RantContext
|
189
139
|
|
190
140
|
class RantAppContext
|
191
|
-
include Rant
|
192
141
|
include RantContext
|
193
142
|
|
194
143
|
def initialize(app)
|
195
|
-
@
|
144
|
+
@rac = app
|
196
145
|
end
|
197
146
|
|
198
|
-
|
199
|
-
|
147
|
+
# +rac+ stands for "rant compiler"
|
148
|
+
def rac
|
149
|
+
@rac
|
200
150
|
end
|
201
151
|
|
202
152
|
def method_missing(sym, *args)
|
@@ -212,11 +162,10 @@ class RantAppContext
|
|
212
162
|
end
|
213
163
|
|
214
164
|
module Rant
|
215
|
-
include RantContext
|
216
165
|
|
217
166
|
# In the class definition of Rant::RantApp, this will be set to a
|
218
167
|
# new application object.
|
219
|
-
@@
|
168
|
+
@@rac = nil
|
220
169
|
|
221
170
|
class << self
|
222
171
|
|
@@ -246,42 +195,30 @@ module Rant
|
|
246
195
|
def run(first_arg=nil, *other_args)
|
247
196
|
other_args = other_args.flatten
|
248
197
|
args = first_arg.nil? ? ARGV.dup : ([first_arg] + other_args)
|
249
|
-
if @@
|
250
|
-
@@
|
251
|
-
@@
|
198
|
+
if @@rac && !@@rac.ran?
|
199
|
+
@@rac.args.replace(args.flatten)
|
200
|
+
@@rac.run
|
252
201
|
else
|
253
|
-
@@
|
254
|
-
@@
|
202
|
+
@@rac = Rant::RantApp.new(args)
|
203
|
+
@@rac.run
|
255
204
|
end
|
256
205
|
end
|
257
206
|
|
258
|
-
def
|
259
|
-
@@
|
207
|
+
def rac
|
208
|
+
@@rac
|
260
209
|
end
|
261
210
|
|
262
|
-
def
|
263
|
-
@@
|
211
|
+
def rac=(app)
|
212
|
+
@@rac = app
|
264
213
|
end
|
265
214
|
|
266
215
|
# "Clear" the current Rant application. After this call,
|
267
216
|
# Rant has the same state as immediately after startup.
|
268
217
|
def reset
|
269
|
-
@@
|
218
|
+
@@rac = nil
|
270
219
|
end
|
271
220
|
end
|
272
221
|
|
273
|
-
def rantapp
|
274
|
-
@@rantapp
|
275
|
-
end
|
276
|
-
|
277
|
-
# Pre 0.2.7: Manually making necessary methods module
|
278
|
-
# functions. Note that it caused problems with caller
|
279
|
-
# parsing when the Rantfile did a `require "rant"' (irb!).
|
280
|
-
#module_function :task, :file, :desc, :subdirs,
|
281
|
-
# :gen, :source, :enhance, :sys, :plugin
|
282
|
-
|
283
|
-
extend self
|
284
|
-
|
285
222
|
end # module Rant
|
286
223
|
|
287
224
|
class Rant::RantApp
|
@@ -290,6 +227,9 @@ class Rant::RantApp
|
|
290
227
|
# Important: We try to synchronize all tasks referenced indirectly
|
291
228
|
# by @rantfiles with the task hash @tasks. The task hash is
|
292
229
|
# intended for fast task lookup per task name.
|
230
|
+
#
|
231
|
+
# All tasks are registered to the system by the +prepare_task+
|
232
|
+
# method.
|
293
233
|
|
294
234
|
# The RantApp class has no own state.
|
295
235
|
|
@@ -323,6 +263,8 @@ class Rant::RantApp
|
|
323
263
|
[ "--trace-abort", GetoptLong::NO_ARGUMENT, nil ],
|
324
264
|
]
|
325
265
|
|
266
|
+
# Reference project's root directory in task names by preceding
|
267
|
+
# them with this character.
|
326
268
|
ROOT_DIR_ID = "#"
|
327
269
|
ESCAPE_ID = "\\"
|
328
270
|
|
@@ -342,16 +284,14 @@ class Rant::RantApp
|
|
342
284
|
# may be called through an instance_eval on this object (e.g. from
|
343
285
|
# plugins).
|
344
286
|
attr_reader :context
|
345
|
-
|
346
|
-
# object (like a hash). It is intended to let the different
|
347
|
-
# modules, plugins and tasks to communicate to each other.
|
348
|
-
attr_reader :var
|
287
|
+
alias cx context
|
349
288
|
# A hash with all tasks. For fast task lookup use this hash with
|
350
289
|
# the taskname as key.
|
351
290
|
attr_reader :tasks
|
352
|
-
# A list
|
291
|
+
# A list of all imports (code loaded with +import+).
|
353
292
|
attr_reader :imports
|
354
|
-
|
293
|
+
# Current subdirectory relative to project's root directory
|
294
|
+
# (#rootdir).
|
355
295
|
attr_reader :current_subdir
|
356
296
|
|
357
297
|
def initialize *args
|
@@ -359,7 +299,7 @@ class Rant::RantApp
|
|
359
299
|
# Rantfiles will be loaded in the context of this object.
|
360
300
|
@context = RantAppContext.new(self)
|
361
301
|
@sys = ::Rant::SysObject.new(self)
|
362
|
-
Rant.
|
302
|
+
Rant.rac ||= self
|
363
303
|
@rantfiles = []
|
364
304
|
@tasks = {}
|
365
305
|
@opts = {
|
@@ -373,6 +313,7 @@ class Rant::RantApp
|
|
373
313
|
@done = false
|
374
314
|
@plugins = []
|
375
315
|
@var = Rant::RantVar::Space.new
|
316
|
+
@var.query :ignore, :AutoList, []
|
376
317
|
@imports = []
|
377
318
|
|
378
319
|
@task_show = nil
|
@@ -380,7 +321,7 @@ class Rant::RantApp
|
|
380
321
|
|
381
322
|
@orig_pwd = nil
|
382
323
|
@current_subdir = ""
|
383
|
-
|
324
|
+
@resolve_hooks = []
|
384
325
|
end
|
385
326
|
|
386
327
|
def [](opt)
|
@@ -412,22 +353,6 @@ class Rant::RantApp
|
|
412
353
|
### experimental support for subdirectories ######################
|
413
354
|
def expand_project_path(path)
|
414
355
|
expand_path(@current_subdir, path)
|
415
|
-
=begin
|
416
|
-
case path
|
417
|
-
when nil: @current_subdir.dup
|
418
|
-
when "": @current_subdir.dup
|
419
|
-
when /^#/: path.sub(/^#/, '')
|
420
|
-
when /^\\#/: path.sub(/^\\/, '')
|
421
|
-
else
|
422
|
-
#puts "epp: current_subdir: #@current_subdir"
|
423
|
-
if @current_subdir.empty?
|
424
|
-
# we are in project's root directory
|
425
|
-
path
|
426
|
-
else
|
427
|
-
File.join(@current_subdir, path)
|
428
|
-
end
|
429
|
-
end
|
430
|
-
=end
|
431
356
|
end
|
432
357
|
def expand_path(subdir, path)
|
433
358
|
case path
|
@@ -456,7 +381,8 @@ class Rant::RantApp
|
|
456
381
|
def goto(dir)
|
457
382
|
# TODO: optimize
|
458
383
|
p_dir = expand_project_path(dir)
|
459
|
-
|
384
|
+
base = rootdir.empty? ? Dir.pwd : rootdir
|
385
|
+
abs_path = p_dir.empty? ? base : File.join(base, p_dir)
|
460
386
|
@current_subdir = p_dir
|
461
387
|
unless Dir.pwd == abs_path
|
462
388
|
#puts "pwd: #{Dir.pwd}; abs_path: #{abs_path}"
|
@@ -466,6 +392,7 @@ class Rant::RantApp
|
|
466
392
|
#STDERR.puts "rant: in #{p_dir}"
|
467
393
|
end
|
468
394
|
end
|
395
|
+
# +dir+ is a path relative to +rootdir+
|
469
396
|
def goto_project_dir(dir)
|
470
397
|
# TODO: optimize
|
471
398
|
goto "##{dir}"
|
@@ -512,6 +439,7 @@ class Rant::RantApp
|
|
512
439
|
end
|
513
440
|
# run tasks
|
514
441
|
run_tasks
|
442
|
+
goto "#"
|
515
443
|
raise Rant::RantDoneException
|
516
444
|
rescue Rant::RantDoneException
|
517
445
|
@done = true
|
@@ -522,6 +450,10 @@ class Rant::RantApp
|
|
522
450
|
err_msg "Invalid Rantfile: " + $!.message
|
523
451
|
$stderr.puts "rant aborted!"
|
524
452
|
return 1
|
453
|
+
rescue Rant::RantError
|
454
|
+
err_msg $!.message, $!.backtrace[0..4]
|
455
|
+
$stderr.puts "rant aborted!"
|
456
|
+
return 1
|
525
457
|
rescue Rant::RantAbortException
|
526
458
|
$stderr.puts "rant aborted!"
|
527
459
|
return 1
|
@@ -535,7 +467,7 @@ class Rant::RantApp
|
|
535
467
|
@plugins.each { |plugin| plugin.rant_quit }
|
536
468
|
# restore pwd
|
537
469
|
Dir.pwd != @orig_pwd && Dir.chdir(@orig_pwd)
|
538
|
-
Rant.
|
470
|
+
Rant.rac = self.class.new
|
539
471
|
end
|
540
472
|
|
541
473
|
###### methods accessible through RantContext ####################
|
@@ -573,14 +505,6 @@ class Rant::RantApp
|
|
573
505
|
file = ch[:file]
|
574
506
|
# validate args
|
575
507
|
generator = args.shift
|
576
|
-
# Let modules/classes from the Generator namespace override
|
577
|
-
# other generators.
|
578
|
-
begin
|
579
|
-
if generator.is_a? Module
|
580
|
-
generator = ::Rant::Generators.const_get(generator.to_s)
|
581
|
-
end
|
582
|
-
rescue NameError, ArgumentError
|
583
|
-
end
|
584
508
|
unless generator.respond_to? :rant_generate
|
585
509
|
abort(pos_text(file, ln),
|
586
510
|
"First argument to `gen' has to be a task-generator.")
|
@@ -591,20 +515,23 @@ class Rant::RantApp
|
|
591
515
|
|
592
516
|
# Currently ignores block.
|
593
517
|
def import(*args, &block)
|
518
|
+
ch = Rant::Lib::parse_caller_elem(caller[1])
|
594
519
|
if block
|
595
|
-
warn_msg
|
520
|
+
warn_msg pos_text(ch[:file], ch[:ln]),
|
521
|
+
"import: ignoring block"
|
596
522
|
end
|
597
523
|
args.flatten.each { |arg|
|
598
524
|
unless String === arg
|
599
|
-
abort(
|
600
|
-
"only strings
|
525
|
+
abort(pos_text(ch[:file], ch[:ln]),
|
526
|
+
"import: only strings allowed as arguments")
|
601
527
|
end
|
602
528
|
unless @imports.include? arg
|
603
529
|
unless Rant::CODE_IMPORTS.include? arg
|
604
530
|
begin
|
605
531
|
require "rant/import/#{arg}"
|
606
532
|
rescue LoadError => e
|
607
|
-
abort(
|
533
|
+
abort(pos_text(ch[:file], ch[:ln]),
|
534
|
+
"No such import - #{arg}")
|
608
535
|
end
|
609
536
|
Rant::CODE_IMPORTS << arg.dup
|
610
537
|
end
|
@@ -683,9 +610,11 @@ class Rant::RantApp
|
|
683
610
|
def source rantfile
|
684
611
|
rf, is_new = rantfile_for_path(rantfile)
|
685
612
|
return false unless is_new
|
613
|
+
build rantfile
|
686
614
|
unless rf.exist?
|
687
|
-
abort("source: No such file
|
615
|
+
abort("source: No such file - #{rantfile}")
|
688
616
|
end
|
617
|
+
|
689
618
|
load_file rf
|
690
619
|
true
|
691
620
|
end
|
@@ -704,7 +633,7 @@ class Rant::RantApp
|
|
704
633
|
end
|
705
634
|
unless arg.is_a? String
|
706
635
|
abort(pos_text(file, ln),
|
707
|
-
"
|
636
|
+
"subdirs: arguments must be strings")
|
708
637
|
end
|
709
638
|
loaded = false
|
710
639
|
prev_subdir = @current_subdir
|
@@ -727,22 +656,32 @@ class Rant::RantApp
|
|
727
656
|
goto_project_dir prev_subdir
|
728
657
|
end
|
729
658
|
unless loaded || quiet?
|
730
|
-
warn_msg(pos_text(file, ln)
|
731
|
-
"No Rantfile in subdir `#{arg}'.")
|
659
|
+
warn_msg(pos_text(file, ln),
|
660
|
+
"subdirs: No Rantfile in subdir `#{arg}'.")
|
732
661
|
end
|
733
662
|
}
|
734
663
|
rescue SystemCallError => e
|
735
|
-
abort(pos_text(file, ln),
|
736
|
-
"in `subdirs' command: " + e.message)
|
664
|
+
abort(pos_text(file, ln), "subdirs: " + e.message)
|
737
665
|
end
|
738
666
|
|
739
|
-
def sys(*args)
|
667
|
+
def sys(*args, &block)
|
740
668
|
if args.empty?
|
741
669
|
@sys
|
742
670
|
else
|
743
671
|
@sys.sh(*args)
|
744
672
|
end
|
745
673
|
end
|
674
|
+
|
675
|
+
# The [] and []= operators may be used to set/get values from this
|
676
|
+
# object (like a hash). It is intended to let the different
|
677
|
+
# modules, plugins and tasks to communicate with each other.
|
678
|
+
def var(*args, &block)
|
679
|
+
if args.empty?
|
680
|
+
@var
|
681
|
+
else
|
682
|
+
@var.query(*args, &block)
|
683
|
+
end
|
684
|
+
end
|
746
685
|
##################################################################
|
747
686
|
|
748
687
|
# Pop (remove and return) current pending task description.
|
@@ -759,6 +698,12 @@ class Rant::RantApp
|
|
759
698
|
raise Rant::RantAbortException
|
760
699
|
end
|
761
700
|
|
701
|
+
def abort_at(ch, *msg)
|
702
|
+
err_msg(pos_text(ch[:file], ch[:ln]), msg)
|
703
|
+
$stderr.puts caller if @opts[:trace_abort]
|
704
|
+
raise Rant::RantAbortException
|
705
|
+
end
|
706
|
+
|
762
707
|
def help
|
763
708
|
puts "rant [-f RANTFILE] [OPTIONS] tasks..."
|
764
709
|
puts
|
@@ -769,27 +714,56 @@ class Rant::RantApp
|
|
769
714
|
|
770
715
|
def show_descriptions
|
771
716
|
tlist = select_tasks { |t| t.description }
|
717
|
+
# +target_list+ aborts if no task defined, so we can be sure
|
718
|
+
# that +default+ is not nil
|
719
|
+
def_target = target_list.first
|
772
720
|
if tlist.empty?
|
773
|
-
|
721
|
+
puts "rant # => " + list_task_names(
|
722
|
+
resolve(def_target)).join(', ')
|
723
|
+
msg "No described tasks."
|
774
724
|
return
|
775
725
|
end
|
776
726
|
prefix = "rant "
|
777
727
|
infix = " # "
|
778
728
|
name_length = 0
|
779
729
|
tlist.each { |t|
|
780
|
-
if t.
|
781
|
-
name_length = t.
|
730
|
+
if t.full_name.length > name_length
|
731
|
+
name_length = t.full_name.length
|
782
732
|
end
|
783
733
|
}
|
784
734
|
name_length < 7 && name_length = 7
|
785
735
|
cmd_length = prefix.length + name_length
|
736
|
+
# TODO: show what's done if rant is invoked without argument
|
737
|
+
unless tlist.first.full_name == def_target
|
738
|
+
defaults = list_task_names(
|
739
|
+
resolve(def_target)).join(', ')
|
740
|
+
puts "#{prefix}#{' ' * name_length}#{infix}=> #{defaults}"
|
741
|
+
end
|
786
742
|
tlist.each { |t|
|
787
|
-
print(prefix + t.
|
743
|
+
print(prefix + t.full_name.ljust(name_length) + infix)
|
788
744
|
dt = t.description.sub(/\s+$/, "")
|
789
745
|
puts dt.sub("\n", "\n" + ' ' * cmd_length + infix + " ")
|
790
746
|
}
|
791
747
|
true
|
792
748
|
end
|
749
|
+
def list_task_names(*tasks)
|
750
|
+
rsl = []
|
751
|
+
tasks.flatten.each { |t|
|
752
|
+
if t.respond_to?(:has_actions?) && t.has_actions?
|
753
|
+
rsl << t
|
754
|
+
elsif t.respond_to? :prerequisites
|
755
|
+
if t.prerequisites.empty?
|
756
|
+
rsl << t
|
757
|
+
else
|
758
|
+
rsl.concat(list_task_names(t.prerequisites))
|
759
|
+
end
|
760
|
+
else
|
761
|
+
rsl << t
|
762
|
+
end
|
763
|
+
}
|
764
|
+
rsl
|
765
|
+
end
|
766
|
+
private :list_task_names
|
793
767
|
|
794
768
|
# Increase verbosity.
|
795
769
|
def more_verbose
|
@@ -864,8 +838,8 @@ class Rant::RantApp
|
|
864
838
|
not @rantfiles.all? { |f| f.tasks.empty? }
|
865
839
|
end
|
866
840
|
|
867
|
-
def
|
868
|
-
|
841
|
+
def target_list
|
842
|
+
if !have_any_task? && @resolve_hooks.empty?
|
869
843
|
abort("No tasks defined for this rant application!")
|
870
844
|
end
|
871
845
|
|
@@ -876,49 +850,81 @@ class Rant::RantApp
|
|
876
850
|
target_list = @force_targets + @arg_targets
|
877
851
|
# The target list is a list of strings, not Task objects!
|
878
852
|
if target_list.empty?
|
879
|
-
|
880
|
-
|
881
|
-
}
|
882
|
-
|
853
|
+
def_tasks = resolve "default"
|
854
|
+
#have_default = @rantfiles.any? { |f|
|
855
|
+
# f.tasks.any? { |t| t.name == "default" }
|
856
|
+
#}
|
857
|
+
unless def_tasks.empty?
|
883
858
|
target_list << "default"
|
884
859
|
else
|
885
860
|
first = nil
|
886
861
|
@rantfiles.each { |f|
|
887
862
|
unless f.tasks.empty?
|
888
|
-
first = f.tasks.first.
|
863
|
+
first = f.tasks.first.full_name
|
889
864
|
break
|
890
865
|
end
|
891
866
|
}
|
892
867
|
target_list << first
|
893
868
|
end
|
894
869
|
end
|
870
|
+
target_list
|
871
|
+
end
|
872
|
+
|
873
|
+
def run_tasks
|
895
874
|
# Now, run all specified tasks in all rantfiles,
|
896
875
|
# rantfiles in reverse order.
|
897
876
|
opt = {}
|
898
877
|
matching_tasks = 0
|
899
878
|
target_list.each do |target|
|
900
|
-
|
901
|
-
if
|
902
|
-
opt[:force] = true
|
903
|
-
@force_targets.delete(target)
|
904
|
-
end
|
905
|
-
### pre 0.3.1 ###
|
906
|
-
#(select_tasks { |t| t.name == target }).each { |t|
|
907
|
-
select_tasks_by_name(target).each { |t|
|
908
|
-
matching_tasks += 1
|
909
|
-
begin
|
910
|
-
t.invoke(opt)
|
911
|
-
rescue Rant::TaskFail => e
|
912
|
-
# TODO: Report failed dependancy.
|
913
|
-
abort("Task `#{e.tname}' fail.")
|
914
|
-
end
|
915
|
-
}
|
916
|
-
if matching_tasks == 0
|
879
|
+
goto "#"
|
880
|
+
if build(target) == 0
|
917
881
|
abort("Don't know how to build `#{target}'.")
|
918
882
|
end
|
919
883
|
end
|
920
884
|
end
|
921
885
|
|
886
|
+
# Invoke all tasks necessary to build +target+. Returns the number
|
887
|
+
# of tasks invoked.
|
888
|
+
def build target, opt = {}
|
889
|
+
opt[:force] = true if @force_targets.delete(target)
|
890
|
+
matching_tasks = 0
|
891
|
+
resolve(target).each { |t|
|
892
|
+
matching_tasks += 1
|
893
|
+
begin
|
894
|
+
t.invoke(opt)
|
895
|
+
rescue Rant::TaskFail => e
|
896
|
+
# TODO: Report failed dependancy.
|
897
|
+
abort("Task `#{e.tname}' fail.")
|
898
|
+
end
|
899
|
+
}
|
900
|
+
matching_tasks
|
901
|
+
end
|
902
|
+
|
903
|
+
def resolve task_name, rel_project_dir = @current_subdir
|
904
|
+
#select_tasks_by_name task_name, rel_project_dir
|
905
|
+
# Note: first lines copied from +select_tasks_by_name+
|
906
|
+
# for efficiency reasons
|
907
|
+
s = @tasks[expand_path(rel_project_dir, task_name)]
|
908
|
+
case s
|
909
|
+
when nil
|
910
|
+
@resolve_hooks.each { |s|
|
911
|
+
# Note: will probably change to get more params
|
912
|
+
s = s[task_name]
|
913
|
+
return s if s
|
914
|
+
}
|
915
|
+
[]
|
916
|
+
when Rant::Worker: [s]
|
917
|
+
else # assuming MetaTask
|
918
|
+
s
|
919
|
+
end
|
920
|
+
end
|
921
|
+
public :resolve
|
922
|
+
|
923
|
+
def at_resolve &block
|
924
|
+
@resolve_hooks << block if block
|
925
|
+
end
|
926
|
+
public :at_resolve
|
927
|
+
|
922
928
|
# Returns a list with all tasks for which yield
|
923
929
|
# returns true.
|
924
930
|
def select_tasks
|
@@ -1074,8 +1080,8 @@ class Rant::RantApp
|
|
1074
1080
|
ARGV.replace(old_argv)
|
1075
1081
|
rem_args.each { |ra|
|
1076
1082
|
if ra =~ /(^[^=]+)=([^=]+)$/
|
1077
|
-
msg 2, "
|
1078
|
-
|
1083
|
+
msg 2, "var: #$1=#$2"
|
1084
|
+
@var[$1] = $2
|
1079
1085
|
else
|
1080
1086
|
@arg_targets << ra
|
1081
1087
|
end
|
@@ -1165,13 +1171,15 @@ class Rant::RantApp
|
|
1165
1171
|
name = normalize_task_name(k, file, ln)
|
1166
1172
|
pre = v
|
1167
1173
|
}
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1174
|
+
unless ::Rant::FileList === pre
|
1175
|
+
if pre.respond_to? :to_ary
|
1176
|
+
pre = pre.to_ary.dup
|
1177
|
+
pre.map! { |elem|
|
1178
|
+
normalize_task_name(elem, file, ln)
|
1179
|
+
}
|
1180
|
+
else
|
1181
|
+
pre = [normalize_task_name(pre, file, ln)]
|
1182
|
+
end
|
1175
1183
|
end
|
1176
1184
|
else
|
1177
1185
|
name = normalize_task_name(targ, file, ln)
|
@@ -1216,9 +1224,9 @@ class Rant::RantApp
|
|
1216
1224
|
end
|
1217
1225
|
end
|
1218
1226
|
|
1219
|
-
# Just ensure that Rant.
|
1227
|
+
# Just ensure that Rant.rac holds an RantApp after loading
|
1220
1228
|
# this file. The code in initialize will register the new app with
|
1221
|
-
# Rant.
|
1229
|
+
# Rant.rac= if necessary.
|
1222
1230
|
self.new
|
1223
1231
|
|
1224
1232
|
end # class Rant::RantApp
|