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,235 @@
|
|
1
|
+
|
2
|
+
# signedfile.rb - File tasks with checksum change recognition.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
module Rant
|
7
|
+
def self.init_import_signedfile(rac, *rest)
|
8
|
+
rac.import "signature/md5" unless rac.var._get("__signature__")
|
9
|
+
rac.import "metadata" unless rac.var._get("__metadata__")
|
10
|
+
end
|
11
|
+
module Generators
|
12
|
+
class SignedFile
|
13
|
+
include Node
|
14
|
+
|
15
|
+
def self.rant_gen(rac, ch, args, &block)
|
16
|
+
unless args.size == 1
|
17
|
+
rac.abort_at(ch, "SignedFile: too many arguments")
|
18
|
+
end
|
19
|
+
rac.prepare_task(args.first, block, ch) { |name,pre,blk|
|
20
|
+
self.new(rac, name, pre, &blk)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(rac, name, prerequisites, &block)
|
25
|
+
super()
|
26
|
+
@rac = rac
|
27
|
+
@name = name
|
28
|
+
@pre = prerequisites or
|
29
|
+
raise ArgumentError, "prerequisites required"
|
30
|
+
@block = block
|
31
|
+
@run = false
|
32
|
+
@success = nil
|
33
|
+
@needed_blk = nil
|
34
|
+
end
|
35
|
+
def prerequisites
|
36
|
+
@pre
|
37
|
+
end
|
38
|
+
alias deps prerequisites
|
39
|
+
# first prerequisite
|
40
|
+
def source
|
41
|
+
@pre.first.to_s
|
42
|
+
end
|
43
|
+
def has_actions?
|
44
|
+
!!@block
|
45
|
+
end
|
46
|
+
def <<(pre)
|
47
|
+
@pre << pre
|
48
|
+
end
|
49
|
+
def invoked?
|
50
|
+
!@success.nil?
|
51
|
+
end
|
52
|
+
def fail?
|
53
|
+
@success == false
|
54
|
+
end
|
55
|
+
def done?
|
56
|
+
@success
|
57
|
+
end
|
58
|
+
def enhance(deps = nil, &blk)
|
59
|
+
@pre.concat(deps) if deps
|
60
|
+
if @block
|
61
|
+
if blk
|
62
|
+
first_block = @block
|
63
|
+
@block = lambda { |t|
|
64
|
+
first_block[t]
|
65
|
+
blk[t]
|
66
|
+
}
|
67
|
+
end
|
68
|
+
else
|
69
|
+
@block = blk
|
70
|
+
end
|
71
|
+
end
|
72
|
+
def needed?
|
73
|
+
invoke(:needed? => true)
|
74
|
+
end
|
75
|
+
def needed(&blk)
|
76
|
+
@needed_blk = blk
|
77
|
+
end
|
78
|
+
def invoke(opt = INVOKE_OPT)
|
79
|
+
return circular_dep if @run
|
80
|
+
@run = true
|
81
|
+
begin
|
82
|
+
return if done?
|
83
|
+
goto_task_home
|
84
|
+
@cur_checksums = []
|
85
|
+
@sigs = @rac.var._get("__signature__")
|
86
|
+
key = "prerequisites_sig_#{@sigs.name}"
|
87
|
+
target_key = "target_sig_#{@sigs.name}"
|
88
|
+
up = signed_process_prerequisites(opt)
|
89
|
+
up ||= opt[:force]
|
90
|
+
if @needed_blk
|
91
|
+
up = true if @needed_blk.call(self)
|
92
|
+
end
|
93
|
+
@cur_checksums.sort!
|
94
|
+
check_str = @cur_checksums.join
|
95
|
+
@cur_checksums = nil
|
96
|
+
metadata = @rac.var._get("__metadata__")
|
97
|
+
old_check_str = metadata.fetch(key, @name)
|
98
|
+
old_target_str = metadata.fetch(target_key, @name)
|
99
|
+
# check explicitely for plain file, thus allow the
|
100
|
+
# target of a SignedFile to be a directory ;)
|
101
|
+
if test(?f, @name)
|
102
|
+
target_str = @sigs.signature_for_file(@name)
|
103
|
+
else
|
104
|
+
target_str = ""
|
105
|
+
up ||= !File.exist?(@name)
|
106
|
+
end
|
107
|
+
check_str_changed = old_check_str != check_str
|
108
|
+
target_changed = old_target_str != target_str
|
109
|
+
up ||= check_str_changed || target_changed
|
110
|
+
return up if opt[:needed?]
|
111
|
+
return false unless up
|
112
|
+
# run action and save checksums
|
113
|
+
run
|
114
|
+
goto_task_home
|
115
|
+
target_str = test(?f, @name) ?
|
116
|
+
@sigs.signature_for_file(@name) : ""
|
117
|
+
target_changed = target_str != old_target_str
|
118
|
+
if target_changed
|
119
|
+
metadata.set(target_key, target_str, @name)
|
120
|
+
end
|
121
|
+
if check_str_changed
|
122
|
+
metadata.set(key, check_str, @name)
|
123
|
+
end
|
124
|
+
return target_changed
|
125
|
+
rescue TaskFail => e
|
126
|
+
raise
|
127
|
+
rescue Exception => e
|
128
|
+
self.fail(nil, e)
|
129
|
+
ensure
|
130
|
+
@sigs = nil
|
131
|
+
@run = false
|
132
|
+
end
|
133
|
+
end
|
134
|
+
def each_target
|
135
|
+
goto_task_home
|
136
|
+
yield @name
|
137
|
+
end
|
138
|
+
def timestamp
|
139
|
+
File.exist?(@name) ? File.mtime(@name) : T0
|
140
|
+
end
|
141
|
+
def signature
|
142
|
+
goto_task_home
|
143
|
+
sigs = @rac.var._get("__signature__")
|
144
|
+
md = @rac.var._get("__metadata__")
|
145
|
+
key = "target_sig_#{sigs.name}"
|
146
|
+
md.fetch(key, @name)
|
147
|
+
end
|
148
|
+
private
|
149
|
+
# returns true if update required
|
150
|
+
def signed_process_prerequisites(opt)
|
151
|
+
up = false
|
152
|
+
# set with already handled prerequisites, don't
|
153
|
+
# handle on prerequisite multiple times
|
154
|
+
handled = {@name => true}
|
155
|
+
my_subdir = project_subdir
|
156
|
+
@pre.each { |dep|
|
157
|
+
dep_str = dep.to_rant_target
|
158
|
+
next if handled.include? dep_str
|
159
|
+
if Node === dep
|
160
|
+
up = true if handle_node(dep, dep_str, opt)
|
161
|
+
else
|
162
|
+
tasks = @rac.resolve(dep_str, my_subdir)
|
163
|
+
if tasks.empty?
|
164
|
+
if test(?d, dep_str)
|
165
|
+
handle_dir(dep_str)
|
166
|
+
elsif File.exist?(dep_str)
|
167
|
+
handle_file(dep_str)
|
168
|
+
else
|
169
|
+
rac.err_msg @rac.pos_text(rantfile.path, line_number),
|
170
|
+
"in prerequisites: no such file or task: `#{dep_str}'"
|
171
|
+
self.fail
|
172
|
+
end
|
173
|
+
else
|
174
|
+
tasks.each { |t|
|
175
|
+
up = true if handle_node(t, dep_str, opt)
|
176
|
+
}
|
177
|
+
end
|
178
|
+
end
|
179
|
+
handled[dep_str] = true
|
180
|
+
}
|
181
|
+
up
|
182
|
+
end
|
183
|
+
def handle_node(node, dep_str, opt)
|
184
|
+
up = node.invoke(opt)
|
185
|
+
if node.respond_to? :signature
|
186
|
+
@cur_checksums << node.signature
|
187
|
+
elsif test(?f, dep_str)
|
188
|
+
# calculate checksum for plain file
|
189
|
+
handle_file(dep_str)
|
190
|
+
elsif File.exist?(dep_str)
|
191
|
+
@cur_checksums << @sigs.signature_for_string(dep_str)
|
192
|
+
end
|
193
|
+
goto_task_home
|
194
|
+
up
|
195
|
+
end
|
196
|
+
def handle_file(path)
|
197
|
+
@cur_checksums << @sigs.signature_for_file(path)
|
198
|
+
end
|
199
|
+
def handle_dir(path)
|
200
|
+
@cur_checksums << @sigs.signature_for_string(path)
|
201
|
+
end
|
202
|
+
end # class SignedFile
|
203
|
+
|
204
|
+
class AutoSubSignedFile < SignedFile
|
205
|
+
include AutoInvokeDirNode
|
206
|
+
end
|
207
|
+
|
208
|
+
class SignedDirectory < SignedFile
|
209
|
+
def respond_to?(meth)
|
210
|
+
if meth == :signature
|
211
|
+
@block
|
212
|
+
else
|
213
|
+
super
|
214
|
+
end
|
215
|
+
end
|
216
|
+
def signature
|
217
|
+
goto_task_home
|
218
|
+
sigs = @rac.var._get("__signature__")
|
219
|
+
md = @rac.var._get("__metadata__")
|
220
|
+
key = "prerequisites_sig_#{sigs.name}"
|
221
|
+
md.fetch(key, @name)
|
222
|
+
end
|
223
|
+
private
|
224
|
+
def run
|
225
|
+
@rac.cx.sys.mkdir @name unless test ?d, @name
|
226
|
+
if @block
|
227
|
+
@block.arity == 0 ? @block.call : @block[self]
|
228
|
+
goto_task_home
|
229
|
+
# for compatibility with mtime based tasks
|
230
|
+
@rac.cx.sys.touch @name
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end # class SignedDirectory
|
234
|
+
end # module Generators
|
235
|
+
end # module Rant
|
data/lib/rant/import/subfile.rb
CHANGED
data/lib/rant/import.rb
CHANGED
@@ -103,6 +103,10 @@ module Rant
|
|
103
103
|
@imports.concat(@rantapp.imports)
|
104
104
|
@plugins.concat(@rantapp.plugins.map { |p| p.name })
|
105
105
|
end
|
106
|
+
|
107
|
+
#unless @imports.include? "nodes/default"
|
108
|
+
#@imports.unshift "nodes/default"
|
109
|
+
#end
|
106
110
|
|
107
111
|
if File.exist?(@mono_fn) && !@force
|
108
112
|
abort("#{@mono_fn} exists. Rant won't overwrite this file.",
|
@@ -298,7 +302,7 @@ EOF
|
|
298
302
|
next if line =~ /^#! ?(\/|\\)?\w/
|
299
303
|
# uncomment line if +uncomment+ directive given
|
300
304
|
if line =~ /^\s*#.*#\s?rant-import:\s?uncomment\s*$/
|
301
|
-
line.sub! '
|
305
|
+
line.sub!(/#/, '')
|
302
306
|
end
|
303
307
|
# skip line if +remove+ directive given
|
304
308
|
next if line =~ /#\s?rant-import:\s?remove\s*$/
|
data/lib/rant/node.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
|
2
|
+
# node.rb - Base of Rant nodes.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
module Rant
|
7
|
+
|
8
|
+
class TaskFail < StandardError
|
9
|
+
def initialize(task, orig, msg)
|
10
|
+
@task = task
|
11
|
+
@orig = orig
|
12
|
+
@msg = msg
|
13
|
+
end
|
14
|
+
def exception
|
15
|
+
self
|
16
|
+
end
|
17
|
+
def task
|
18
|
+
@task
|
19
|
+
end
|
20
|
+
def tname
|
21
|
+
@task ? @task.name : nil
|
22
|
+
end
|
23
|
+
# the exception which caused the task to fail
|
24
|
+
def orig
|
25
|
+
@orig
|
26
|
+
end
|
27
|
+
def msg
|
28
|
+
@msg
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Rantfile
|
33
|
+
attr_reader :tasks, :path
|
34
|
+
attr_accessor :project_subdir
|
35
|
+
def initialize(path)
|
36
|
+
@path = path or raise ArgumentError, "path required"
|
37
|
+
@tasks = []
|
38
|
+
@project_subdir = nil
|
39
|
+
end
|
40
|
+
def to_s
|
41
|
+
@path
|
42
|
+
end
|
43
|
+
end # class Rantfile
|
44
|
+
|
45
|
+
# Any +object+ is considered a _task_ if
|
46
|
+
# <tt>Rant::Node === object</tt> is true.
|
47
|
+
#
|
48
|
+
# Most important classes including this module are the Rant::Task
|
49
|
+
# class and the Rant::FileTask class.
|
50
|
+
module Node
|
51
|
+
|
52
|
+
INVOKE_OPT = {}.freeze
|
53
|
+
|
54
|
+
T0 = Time.at(0).freeze
|
55
|
+
|
56
|
+
# Name of the task, this is always a string.
|
57
|
+
attr_reader :name
|
58
|
+
# A reference to the Rant compiler this task belongs to.
|
59
|
+
attr_reader :rac
|
60
|
+
# Description for this task.
|
61
|
+
attr_accessor :description
|
62
|
+
# The rantfile this task was defined in.
|
63
|
+
# Should be a Rant::Rantfile instance.
|
64
|
+
attr_accessor :rantfile
|
65
|
+
# The linenumber in rantfile where this task was defined.
|
66
|
+
attr_accessor :line_number
|
67
|
+
# The directory in which this task was defined, relative to
|
68
|
+
# the projects root directory.
|
69
|
+
attr_accessor :project_subdir
|
70
|
+
|
71
|
+
def initialize
|
72
|
+
@description = nil
|
73
|
+
@rantfile = nil
|
74
|
+
@line_number = nil
|
75
|
+
@run = false
|
76
|
+
@project_subdir = ""
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the name of this task.
|
80
|
+
def to_s
|
81
|
+
name
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_rant_target
|
85
|
+
name
|
86
|
+
end
|
87
|
+
|
88
|
+
# Basically project_subdir/name
|
89
|
+
#
|
90
|
+
# The Rant compiler (or application) references tasks by their
|
91
|
+
# full_name.
|
92
|
+
def full_name
|
93
|
+
sd = project_subdir
|
94
|
+
sd.empty? ? name : File.join(sd, name)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Change current working directory to the directory this task
|
98
|
+
# was defined in.
|
99
|
+
#
|
100
|
+
# Important for subclasses: Call this method always before
|
101
|
+
# invoking code from Rantfiles (e.g. task action blocks).
|
102
|
+
def goto_task_home
|
103
|
+
@rac.goto_project_dir project_subdir
|
104
|
+
end
|
105
|
+
|
106
|
+
def done?
|
107
|
+
@done
|
108
|
+
end
|
109
|
+
|
110
|
+
def needed?
|
111
|
+
!done?
|
112
|
+
end
|
113
|
+
|
114
|
+
# True during invoke. Used to encounter circular dependencies.
|
115
|
+
def run?
|
116
|
+
@run
|
117
|
+
end
|
118
|
+
|
119
|
+
# +opt+ is a Hash and shouldn't be modified.
|
120
|
+
# All objects implementing the Rant::Node protocol should
|
121
|
+
# know about the following +opt+ values:
|
122
|
+
# <tt>:needed?</tt>::
|
123
|
+
# Just check if this task is needed. Should do the same
|
124
|
+
# as calling Node#needed?
|
125
|
+
# <tt>:force</tt>::
|
126
|
+
# Run task action even if needed? is false.
|
127
|
+
# Returns true if task action was run.
|
128
|
+
def invoke(opt = INVOKE_OPT)
|
129
|
+
return circular_dep if run?
|
130
|
+
@run = true
|
131
|
+
begin
|
132
|
+
return needed? if opt[:needed?]
|
133
|
+
self.run if opt[:force] || self.needed?
|
134
|
+
ensure
|
135
|
+
@run = false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Cause task to fail. Usually called from inside the block
|
140
|
+
# given to +act+.
|
141
|
+
def fail msg = nil, orig = nil
|
142
|
+
raise TaskFail.new(self, orig, msg)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Change pwd to task home directory and yield for each created
|
146
|
+
# file/directory.
|
147
|
+
#
|
148
|
+
# Override in subclasses if your task instances create files.
|
149
|
+
def each_target
|
150
|
+
end
|
151
|
+
|
152
|
+
def run
|
153
|
+
return unless @block
|
154
|
+
goto_task_home
|
155
|
+
@block.arity == 0 ? @block.call : @block[self]
|
156
|
+
end
|
157
|
+
private :run
|
158
|
+
|
159
|
+
def circular_dep
|
160
|
+
rac.warn_msg "Circular dependency on task `#{full_name}'."
|
161
|
+
false
|
162
|
+
end
|
163
|
+
private :circular_dep
|
164
|
+
end # module Node
|
165
|
+
end
|
data/lib/rant/plugin/csharp.rb
CHANGED
data/lib/rant/rantlib.rb
CHANGED
@@ -10,8 +10,10 @@
|
|
10
10
|
require 'getoptlong'
|
11
11
|
require 'rant/rantvar'
|
12
12
|
require 'rant/rantenv'
|
13
|
-
require 'rant/rantfile'
|
14
13
|
require 'rant/rantsys'
|
14
|
+
require 'rant/node'
|
15
|
+
require 'rant/import/nodes/default' # could be optimized away
|
16
|
+
require 'rant/coregen'
|
15
17
|
|
16
18
|
# There is one problem with executing Rantfiles in a special context:
|
17
19
|
# In the top-level execution environment, there are some methods
|
@@ -23,11 +25,19 @@ require 'rant/rantsys'
|
|
23
25
|
# this object.
|
24
26
|
Rant::MAIN_OBJECT = self
|
25
27
|
|
26
|
-
unless Process::Status.method_defined?(:success?)
|
28
|
+
unless Process::Status.method_defined?(:success?) # new in 1.8.2
|
27
29
|
class Process::Status
|
28
30
|
def success?; exitstatus == 0; end
|
29
31
|
end
|
30
32
|
end
|
33
|
+
unless Regexp.respond_to? :union # new in 1.8.1
|
34
|
+
def Regexp.union(*patterns)
|
35
|
+
# let's hope it comes close to ruby-1.8.1 and upwards...
|
36
|
+
return /(?!)/ if patterns.empty?
|
37
|
+
# i guess the options are lost
|
38
|
+
Regexp.new(patterns.join("|"))
|
39
|
+
end
|
40
|
+
end
|
31
41
|
if RUBY_VERSION < "1.8.2"
|
32
42
|
class Array
|
33
43
|
def flatten
|
@@ -54,6 +64,13 @@ if RUBY_VERSION < "1.8.2"
|
|
54
64
|
end
|
55
65
|
end
|
56
66
|
end
|
67
|
+
if RUBY_VERSION < "1.8.1"
|
68
|
+
module FileUtils
|
69
|
+
def fu_list(arg)
|
70
|
+
arg.respond_to?(:to_ary) ? arg.to_ary : [arg]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
57
74
|
|
58
75
|
class Array
|
59
76
|
|
@@ -194,12 +211,12 @@ class RantAppContext
|
|
194
211
|
include RantContext
|
195
212
|
|
196
213
|
def initialize(app)
|
197
|
-
@
|
214
|
+
@__rac__ = app
|
198
215
|
end
|
199
216
|
|
200
217
|
# +rac+ stands for "rant compiler"
|
201
218
|
def rac
|
202
|
-
@
|
219
|
+
@__rac__
|
203
220
|
end
|
204
221
|
|
205
222
|
def method_missing(sym, *args)
|
@@ -271,6 +288,16 @@ end # module Rant
|
|
271
288
|
class Rant::RantApp
|
272
289
|
include Rant::Console
|
273
290
|
|
291
|
+
class AutoLoadNodeFactory
|
292
|
+
def initialize(rac)
|
293
|
+
@rac = rac
|
294
|
+
end
|
295
|
+
def method_missing(sym, *args, &block)
|
296
|
+
@rac.import "nodes/default"
|
297
|
+
@rac.node_factory.send(sym, *args, &block)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
274
301
|
# Important: We try to synchronize all tasks referenced indirectly
|
275
302
|
# by @rantfiles with the task hash @tasks. The task hash is
|
276
303
|
# intended for fast task lookup per task name.
|
@@ -305,6 +332,7 @@ class Rant::RantApp
|
|
305
332
|
# internal use. A private option is distuingished from others
|
306
333
|
# by having +nil+ as description!
|
307
334
|
|
335
|
+
[ "--import", "-i", GetoptLong::REQUIRED_ARGUMENT, nil ],
|
308
336
|
[ "--stop-after-load", GetoptLong::NO_ARGUMENT, nil ],
|
309
337
|
# Print caller to $stderr on abort.
|
310
338
|
[ "--trace-abort", GetoptLong::NO_ARGUMENT, nil ],
|
@@ -347,6 +375,8 @@ class Rant::RantApp
|
|
347
375
|
# Note: Might change before 1.0
|
348
376
|
attr_reader :resolve_hooks
|
349
377
|
|
378
|
+
attr_accessor :node_factory
|
379
|
+
|
350
380
|
def initialize(*args)
|
351
381
|
unless args.empty?
|
352
382
|
STDERR.puts caller[0]
|
@@ -381,6 +411,8 @@ class Rant::RantApp
|
|
381
411
|
@orig_pwd = nil
|
382
412
|
@current_subdir = ""
|
383
413
|
@resolve_hooks = []
|
414
|
+
|
415
|
+
@node_factory = AutoLoadNodeFactory.new(self)
|
384
416
|
end
|
385
417
|
|
386
418
|
def [](opt)
|
@@ -531,6 +563,8 @@ class Rant::RantApp
|
|
531
563
|
return 1
|
532
564
|
ensure
|
533
565
|
# TODO: exception handling!
|
566
|
+
hooks = var._get("__at_return__")
|
567
|
+
hooks.each { |hook| hook.call } if hooks
|
534
568
|
@plugins.each { |plugin| plugin.rant_plugin_stop }
|
535
569
|
@plugins.each { |plugin| plugin.rant_quit }
|
536
570
|
# restore pwd
|
@@ -550,13 +584,13 @@ class Rant::RantApp
|
|
550
584
|
|
551
585
|
def task(targ, &block)
|
552
586
|
prepare_task(targ, block) { |name,pre,blk|
|
553
|
-
|
587
|
+
@node_factory.new_task(self, name, pre, blk)
|
554
588
|
}
|
555
589
|
end
|
556
590
|
|
557
591
|
def file(targ, &block)
|
558
592
|
prepare_task(targ, block) { |name,pre,blk|
|
559
|
-
|
593
|
+
@node_factory.new_file(self, name, pre, blk)
|
560
594
|
}
|
561
595
|
end
|
562
596
|
|
@@ -594,6 +628,8 @@ class Rant::RantApp
|
|
594
628
|
end
|
595
629
|
Rant::CODE_IMPORTS << arg.dup
|
596
630
|
end
|
631
|
+
init_msg = "init_import_#{arg.gsub(/[^\w]/, '__')}"
|
632
|
+
Rant.send init_msg, self if Rant.respond_to? init_msg
|
597
633
|
@imports << arg.dup
|
598
634
|
end
|
599
635
|
}
|
@@ -661,7 +697,7 @@ class Rant::RantApp
|
|
661
697
|
end
|
662
698
|
warn_msg "enhance \"#{name}\": no such task",
|
663
699
|
"Generating a new file task with the given name."
|
664
|
-
|
700
|
+
@node_factory.new_file(self, name, pre, blk)
|
665
701
|
}
|
666
702
|
end
|
667
703
|
|
@@ -924,7 +960,7 @@ class Rant::RantApp
|
|
924
960
|
tn = nil
|
925
961
|
prepare_task(targ, block, ch) { |name,pre,blk|
|
926
962
|
tn = name
|
927
|
-
|
963
|
+
@node_factory.new_file(self, name, pre, blk)
|
928
964
|
}
|
929
965
|
build(tn)
|
930
966
|
elsif target.respond_to? :to_rant_target
|
@@ -938,7 +974,7 @@ class Rant::RantApp
|
|
938
974
|
# create a file task
|
939
975
|
ch ||= Rant::Lib.parse_caller_elem(caller[1])
|
940
976
|
prepare_task(rt, block, ch) { |name,pre,blk|
|
941
|
-
|
977
|
+
@node_factory.new_file(self, name, pre, blk)
|
942
978
|
}
|
943
979
|
build(rt)
|
944
980
|
else
|
@@ -1017,6 +1053,18 @@ class Rant::RantApp
|
|
1017
1053
|
end
|
1018
1054
|
public :at_resolve
|
1019
1055
|
|
1056
|
+
# block will be called before this rac returns from #run
|
1057
|
+
# pwd will be the projects root directory
|
1058
|
+
def at_return(&block)
|
1059
|
+
hooks = var._get("__at_return__")
|
1060
|
+
if hooks
|
1061
|
+
hooks << block
|
1062
|
+
else
|
1063
|
+
var._set("__at_return__", [block])
|
1064
|
+
end
|
1065
|
+
end
|
1066
|
+
public :at_return
|
1067
|
+
|
1020
1068
|
# Returns a list with all tasks for which yield
|
1021
1069
|
# returns true.
|
1022
1070
|
def select_tasks
|
@@ -1130,6 +1178,8 @@ class Rant::RantApp
|
|
1130
1178
|
@arg_rantfiles << value
|
1131
1179
|
when "--force-run"
|
1132
1180
|
@force_targets << value
|
1181
|
+
when "--import"
|
1182
|
+
import value
|
1133
1183
|
else
|
1134
1184
|
# simple switch
|
1135
1185
|
@opts[opt.sub(/^--/, '').tr('-', "_").to_sym] = true
|
@@ -1305,6 +1355,11 @@ class Rant::RantApp
|
|
1305
1355
|
msg << orig.backtrace[0..4] unless ch
|
1306
1356
|
end
|
1307
1357
|
end
|
1358
|
+
if e.msg && !e.msg.empty?
|
1359
|
+
ch = get_ch_from_backtrace(e.backtrace)
|
1360
|
+
t_msg.unshift(e.msg)
|
1361
|
+
t_msg.unshift(pos_text(ch[:file], ch[:ln])) if ch
|
1362
|
+
end
|
1308
1363
|
err_msg msg unless msg.empty?
|
1309
1364
|
err_msg t_msg
|
1310
1365
|
end
|