rant 0.4.2 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS +14 -0
- data/README +13 -7
- data/Rantfile +11 -0
- data/doc/md5.rdoc +49 -0
- data/doc/rantfile.rdoc +1 -1
- data/lib/rant/coregen.rb +193 -0
- data/lib/rant/import/archive/zip.rb +2 -0
- data/lib/rant/import/archive.rb +10 -2
- data/lib/rant/import/autoclean.rb +16 -7
- data/lib/rant/import/c/dependencies.rb +1 -1
- data/lib/rant/import/directedrule.rb +2 -2
- data/lib/rant/import/md5.rb +16 -0
- data/lib/rant/import/metadata.rb +162 -0
- data/lib/rant/import/nodes/default.rb +490 -0
- data/lib/rant/import/nodes/signed.rb +84 -0
- data/lib/rant/import/package/zip.rb +2 -0
- data/lib/rant/import/rubydoc.rb +5 -1
- data/lib/rant/import/rubypackage.rb +2 -1
- data/lib/rant/import/signature/md5.rb +38 -0
- data/lib/rant/import/signedfile.rb +235 -0
- data/lib/rant/import/subfile.rb +1 -1
- data/lib/rant/import.rb +5 -1
- data/lib/rant/node.rb +165 -0
- data/lib/rant/plugin/csharp.rb +2 -0
- data/lib/rant/rantlib.rb +64 -9
- data/lib/rant/rantsys.rb +39 -27
- data/lib/rant/rantvar.rb +32 -2
- data/misc/TODO +66 -0
- data/test/import/c/dependencies/test_on_the_fly.rb +52 -0
- data/test/import/metadata/Rantfile +16 -0
- data/test/import/metadata/sub/Rantfile +17 -0
- data/test/import/metadata/test_metadata.rb +126 -0
- data/test/import/nodes/signed/Rantfile +89 -0
- data/test/import/nodes/signed/sub1/Rantfile +6 -0
- data/test/import/nodes/signed/test_signed.rb +455 -0
- data/test/import/package/md5.rf +10 -0
- data/test/import/package/test_package.rb +127 -1
- data/test/import/signeddirectory/Rantfile +15 -0
- data/test/import/signeddirectory/test_signeddirectory.rb +84 -0
- data/test/import/signedfile/Rantfile +90 -0
- data/test/import/signedfile/sub1/Rantfile +4 -0
- data/test/import/signedfile/test_signedfile.rb +338 -0
- data/test/project1/Rantfile +0 -9
- data/test/project1/test_project.rb +2 -0
- data/test/project_rb1/test_project_rb1.rb +27 -10
- data/test/rant-import/test_rant-import.rb +46 -9
- data/test/subdirs/sub2/sub/rantfile +0 -5
- data/test/subdirs/test_subdirs.rb +0 -9
- data/test/test_examples.rb +131 -3
- data/test/test_filelist.rb +44 -0
- data/test/test_sys.rb +19 -1
- data/test/test_task.rb +2 -2
- data/test/tutil.rb +9 -3
- metadata +34 -4
- data/lib/rant/rantfile.rb +0 -897
- data/test/test_lighttask.rb +0 -68
@@ -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
|