rake 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rake might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/CHANGES +24 -0
- data/README +28 -11
- data/Rakefile +22 -30
- data/bin/rake +1 -1
- data/doc/jamis.rb +132 -105
- data/doc/release_notes/rake-0.6.0.rdoc +141 -0
- data/lib/rake.rb +661 -455
- data/lib/rake/classic_namespace.rb +8 -0
- data/lib/rake/gempackagetask.rb +5 -3
- data/lib/rake/packagetask.rb +0 -2
- data/lib/rake/rake_test_loader.rb +1 -1
- data/lib/rake/testtask.rb +8 -2
- data/test/data/chains/Rakefile +15 -0
- data/test/data/default/Rakefile +19 -0
- data/test/data/dryrun/Rakefile +22 -0
- data/test/data/file_creation_task/Rakefile +30 -0
- data/test/data/imports/Rakefile +19 -0
- data/test/data/imports/deps.mf +1 -0
- data/test/data/multidesc/Rakefile +14 -0
- data/test/data/sample.mf +9 -0
- data/test/filecreation.rb +18 -9
- data/test/functional.rb +2 -130
- data/test/session_functional.rb +159 -0
- data/test/{testclean.rb → test_clean.rb} +1 -0
- data/test/test_definitions.rb +82 -0
- data/test/test_earlytime.rb +31 -0
- data/test/test_file_creation_task.rb +56 -0
- data/test/test_file_task.rb +140 -0
- data/test/{testfilelist.rb → test_filelist.rb} +17 -2
- data/test/{testfileutils.rb → test_fileutils.rb} +10 -2
- data/test/{testftp.rb → test_ftp.rb} +0 -0
- data/test/test_makefile_loader.rb +2 -0
- data/test/{testpackagetask.rb → test_package_task.rb} +45 -0
- data/test/test_rake.rb +21 -0
- data/test/test_rules.rb +206 -0
- data/test/test_tasks.rb +77 -0
- data/test/{testtesttask.rb → test_test_task.rb} +5 -0
- metadata +72 -12
- metadata.gz.sig +2 -0
- data/TAGS +0 -126
- data/test/testtasks.rb +0 -400
@@ -0,0 +1,141 @@
|
|
1
|
+
= Rake 0.6.0 Released
|
2
|
+
|
3
|
+
Its time for some long requested enhancements and lots of bug fixes
|
4
|
+
... And a whole new web page.
|
5
|
+
|
6
|
+
== New Web Page
|
7
|
+
|
8
|
+
The primary documentation for rake has moved from the RubyForge based
|
9
|
+
wiki to its own Hieraki based web site. Constant spam on the wiki
|
10
|
+
made it a difficult to keep clean. The new site will be easier to
|
11
|
+
update and organize.
|
12
|
+
|
13
|
+
Check out the new documentation at: http://docs.rubyrake.org
|
14
|
+
|
15
|
+
We will be adding new documentation to the site as time goes on.
|
16
|
+
|
17
|
+
In addition to the new docs page, make sure you check out Martin
|
18
|
+
Fowlers article on rake at http://martinfowler.com/articles/rake.html
|
19
|
+
|
20
|
+
== Changes
|
21
|
+
|
22
|
+
=== New Features
|
23
|
+
|
24
|
+
* Multiple prerequisites on Rake rules now allowed. However, keep the
|
25
|
+
following in mind:
|
26
|
+
|
27
|
+
1. All the prerequisites of a rule must be available before a rule
|
28
|
+
is triggered, where "enabled" means (a) an existing file, (b) a
|
29
|
+
defined rule, or (c) another rule which also must be
|
30
|
+
trigger-able.
|
31
|
+
2. Rules are checked in order of definition, so it is important to
|
32
|
+
order your rules properly. If a file can be created by two
|
33
|
+
different rules, put the more specific rule first (otherwise the
|
34
|
+
more general rule will trigger first and the specific one will
|
35
|
+
never be triggered).
|
36
|
+
3. The <tt>source</tt> method now returns the name of the first
|
37
|
+
prerequisite listed in the rule. <tt>sources</tt> returns the
|
38
|
+
names of all the rule prerequisites, ordered as they are defined
|
39
|
+
in the rule. If the task has other prerequisites not defined in
|
40
|
+
the rule (but defined in an explicit task definition), then they
|
41
|
+
will _not_ be included in the sources list.
|
42
|
+
|
43
|
+
* FileLists may now use the egrep command. This popular enhancement
|
44
|
+
is now a core part of the FileList object. If you want to get a
|
45
|
+
list of all your to-dos, fixmes and TBD comments, add the following
|
46
|
+
to your Rakefile.
|
47
|
+
|
48
|
+
desc "Look for TODO and FIXME tags in the code"
|
49
|
+
task :todo do
|
50
|
+
FileList['**/*.rb'].egrep /#.*(FIXME|TODO|TBD)/
|
51
|
+
end
|
52
|
+
|
53
|
+
* The <tt>investigation</tt> method was added to task object to dump
|
54
|
+
out some important values. This makes it a bit easier to debug Rake
|
55
|
+
tasks.
|
56
|
+
|
57
|
+
For example, if you are having problems with a particular task, just
|
58
|
+
print it out:
|
59
|
+
|
60
|
+
task :huh do
|
61
|
+
puts Rake::Task['huh'].investigation
|
62
|
+
end
|
63
|
+
|
64
|
+
* The Rake::TestTask class now supports a "ruby_opts" option to pass
|
65
|
+
arbitrary ruby options to a test subprocess.
|
66
|
+
|
67
|
+
=== Some Incompatibilities
|
68
|
+
|
69
|
+
* When using the <tt>ruby</tt> command to start a Ruby subprocess, the
|
70
|
+
Ruby interpreter that is currently running rake is used by default.
|
71
|
+
This makes it easier to use rake in an environment with multiple
|
72
|
+
ruby installation. (Previously, the first ruby command found in the
|
73
|
+
PATH was used).
|
74
|
+
|
75
|
+
If you wish to chose a different Ruby interpreter, you can
|
76
|
+
explicitly choose the interpreter via the <tt>sh</tt> command.
|
77
|
+
|
78
|
+
* The major rake classes (Task, FileTask, FileCreationTask, RakeApp)
|
79
|
+
have been moved out of the toplevel scope and are now accessible as
|
80
|
+
Rake::Task, Rake::FileTask, Rake::FileCreationTask and
|
81
|
+
Rake::Application. If your Rakefile
|
82
|
+
directly references any one of these tasks, you may:
|
83
|
+
|
84
|
+
1. Update your Rakefile to use the new classnames
|
85
|
+
2. Use the --classic-namespace option on the rake command to get the
|
86
|
+
old behavior,
|
87
|
+
3. Add <code>require 'rake/classic_namespace'</code> to the
|
88
|
+
Rakefile to get the old behavior.
|
89
|
+
|
90
|
+
<tt>rake</tt> will print a rather annoying warning whenever a
|
91
|
+
deprecated class name is referenced without enabling classic
|
92
|
+
namespace.
|
93
|
+
|
94
|
+
=== Bug Fixes
|
95
|
+
|
96
|
+
* Several unit tests and functional tests were fixed to run better
|
97
|
+
under windows.
|
98
|
+
|
99
|
+
* Directory tasks are now a specialized version of a File task. A
|
100
|
+
directory task will only be triggered if it doesn't exist. It will
|
101
|
+
not be triggered if it is out of date w.r.t. any of its
|
102
|
+
prerequisites.
|
103
|
+
|
104
|
+
* Fixed a bug in the Rake::GemPackageTask class so that the gem now
|
105
|
+
properly contains the platform name.
|
106
|
+
|
107
|
+
* Fixed a bug where a prerequisite on a <tt>file</tt> task would cause
|
108
|
+
an exception if the prerequisite did not exist.
|
109
|
+
|
110
|
+
== What is Rake
|
111
|
+
|
112
|
+
Rake is a build tool similar to the make program in many ways. But
|
113
|
+
instead of cryptic make recipes, Rake uses standard Ruby code to
|
114
|
+
declare tasks and dependencies. You have the full power of a modern
|
115
|
+
scripting language built right into your build tool.
|
116
|
+
|
117
|
+
== Availability
|
118
|
+
|
119
|
+
The easiest way to get and install rake is via RubyGems ...
|
120
|
+
|
121
|
+
gem install rake (you may need root/admin privileges)
|
122
|
+
|
123
|
+
Otherwise, you can get it from the more traditional places:
|
124
|
+
|
125
|
+
Home Page:: http://rake.rubyforge.org/
|
126
|
+
Download:: http://rubyforge.org/project/showfiles.php?group_id=50
|
127
|
+
|
128
|
+
== Thanks
|
129
|
+
|
130
|
+
As usual, it was input from users that drove a alot of these changes.
|
131
|
+
The following people either contributed patches, made suggestions or
|
132
|
+
made otherwise helpful comments. Thanks to ...
|
133
|
+
|
134
|
+
* Greg Fast (better ruby_opt test options)
|
135
|
+
* Kelly Felkins (requested by better namespace support)
|
136
|
+
* Martin Fowler (suggested Task.investigation)
|
137
|
+
* Stuart Jansen (send initial patch for multiple prerequisites).
|
138
|
+
* Masao Mutch (better support for non-ruby Gem platforms)
|
139
|
+
* Philipp Neubeck (patch for file task exception fix)
|
140
|
+
|
141
|
+
-- Jim Weirich
|
data/lib/rake.rb
CHANGED
@@ -29,12 +29,13 @@
|
|
29
29
|
# referenced as a library via a require statement, but it can be
|
30
30
|
# distributed independently as an application.
|
31
31
|
|
32
|
-
RAKEVERSION = '0.
|
32
|
+
RAKEVERSION = '0.6.0'
|
33
33
|
|
34
34
|
require 'rbconfig'
|
35
35
|
require 'ftools'
|
36
36
|
require 'getoptlong'
|
37
37
|
require 'fileutils'
|
38
|
+
require 'singleton'
|
38
39
|
|
39
40
|
$last_comment = nil
|
40
41
|
$show_tasks = nil
|
@@ -91,13 +92,15 @@ module Rake
|
|
91
92
|
class << self
|
92
93
|
# Current Rake Application
|
93
94
|
def application
|
94
|
-
@application ||=
|
95
|
+
@application ||= Rake::Application.new
|
95
96
|
end
|
96
97
|
|
98
|
+
# Set the current Rake application object.
|
97
99
|
def application=(app)
|
98
|
-
fail "
|
100
|
+
fail "Rake::Application already exists" if defined?(@application)
|
99
101
|
@application = app
|
100
102
|
end
|
103
|
+
|
101
104
|
end
|
102
105
|
|
103
106
|
module Cloneable
|
@@ -113,257 +116,326 @@ module Rake
|
|
113
116
|
end
|
114
117
|
end
|
115
118
|
|
116
|
-
|
117
|
-
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# Create a task named +task_name+ with no actions or prerequisites..
|
141
|
-
# use +enhance+ to add actions and prerequisites.
|
142
|
-
def initialize(task_name)
|
143
|
-
@name = task_name
|
144
|
-
@prerequisites = FileList[]
|
145
|
-
@actions = []
|
146
|
-
@already_invoked = false
|
147
|
-
@comment = nil
|
148
|
-
end
|
149
|
-
|
150
|
-
# Enhance a task with prerequisites or actions. Returns self.
|
151
|
-
def enhance(deps=nil, &block)
|
152
|
-
@prerequisites |= deps if deps
|
153
|
-
@actions << block if block_given?
|
154
|
-
self
|
155
|
-
end
|
156
|
-
|
157
|
-
# Name of the task.
|
158
|
-
def name
|
159
|
-
@name.to_s
|
160
|
-
end
|
161
|
-
|
162
|
-
# Invoke the task if it is needed. Prerequites are invoked first.
|
163
|
-
def invoke
|
164
|
-
if $trace
|
165
|
-
puts "** Invoke #{name} #{format_trace_flags}"
|
119
|
+
module Rake
|
120
|
+
######################################################################
|
121
|
+
# A Task is the basic unit of work in a Rakefile. Tasks have
|
122
|
+
# associated actions (possibly more than one) and a list of
|
123
|
+
# prerequisites. When invoked, a task will first ensure that all of
|
124
|
+
# its prerequisites have an opportunity to run and then it will
|
125
|
+
# execute its own actions.
|
126
|
+
#
|
127
|
+
# Tasks are not usually created directly using the new method, but
|
128
|
+
# rather use the +file+ and +task+ convenience methods.
|
129
|
+
#
|
130
|
+
class Task
|
131
|
+
TASKS = Hash.new
|
132
|
+
RULES = Array.new
|
133
|
+
|
134
|
+
# List of prerequisites for a task.
|
135
|
+
attr_reader :prerequisites
|
136
|
+
|
137
|
+
# Comment for this task.
|
138
|
+
attr_accessor :comment
|
139
|
+
|
140
|
+
attr_writer :sources
|
141
|
+
def sources
|
142
|
+
@sources ||= []
|
166
143
|
end
|
167
|
-
return if @already_invoked
|
168
|
-
@already_invoked = true
|
169
|
-
@prerequisites.each { |n| Task[n].invoke }
|
170
|
-
execute if needed?
|
171
|
-
end
|
172
|
-
|
173
|
-
# Format the trace flags for display.
|
174
|
-
def format_trace_flags
|
175
|
-
flags = []
|
176
|
-
flags << "first_time" unless @already_invoked
|
177
|
-
flags << "not_needed" unless needed?
|
178
|
-
flags.empty? ? "" : "(" + flags.join(", ") + ")"
|
179
|
-
end
|
180
|
-
private :format_trace_flags
|
181
144
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
puts "** Execute (dry run) #{name}"
|
186
|
-
return
|
145
|
+
# First source from a rule (nil if no sources)
|
146
|
+
def source
|
147
|
+
@sources.first if defined?(@sources)
|
187
148
|
end
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
true
|
198
|
-
end
|
199
|
-
|
200
|
-
# Timestamp for this task. Basic tasks return the current time for
|
201
|
-
# their time stamp. Other tasks can be more sophisticated.
|
202
|
-
def timestamp
|
203
|
-
@prerequisites.collect { |p| Task[p].timestamp }.max || Time.now
|
204
|
-
end
|
205
|
-
|
206
|
-
# Add a comment to the task. If a comment alread exists, separate
|
207
|
-
# the new comment with " / ".
|
208
|
-
def add_comment(comment)
|
209
|
-
return if ! $last_comment
|
210
|
-
if @comment
|
211
|
-
@comment << " / "
|
212
|
-
else
|
213
|
-
@comment = ''
|
149
|
+
|
150
|
+
# Create a task named +task_name+ with no actions or prerequisites..
|
151
|
+
# use +enhance+ to add actions and prerequisites.
|
152
|
+
def initialize(task_name)
|
153
|
+
@name = task_name
|
154
|
+
@prerequisites = FileList[]
|
155
|
+
@actions = []
|
156
|
+
@already_invoked = false
|
157
|
+
@comment = nil
|
214
158
|
end
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
class << self
|
222
|
-
|
223
|
-
# Clear the task list. This cause rake to immediately forget all
|
224
|
-
# the tasks that have been assigned. (Normally used in the unit
|
225
|
-
# tests.)
|
226
|
-
def clear
|
227
|
-
TASKS.clear
|
228
|
-
RULES.clear
|
159
|
+
|
160
|
+
# Enhance a task with prerequisites or actions. Returns self.
|
161
|
+
def enhance(deps=nil, &block)
|
162
|
+
@prerequisites |= deps if deps
|
163
|
+
@actions << block if block_given?
|
164
|
+
self
|
229
165
|
end
|
230
|
-
|
231
|
-
#
|
232
|
-
def
|
233
|
-
|
166
|
+
|
167
|
+
# Name of the task.
|
168
|
+
def name
|
169
|
+
@name.to_s
|
234
170
|
end
|
235
|
-
|
236
|
-
#
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
def [](task_name)
|
241
|
-
task_name = task_name.to_s
|
242
|
-
if task = TASKS[task_name]
|
243
|
-
return task
|
171
|
+
|
172
|
+
# Invoke the task if it is needed. Prerequites are invoked first.
|
173
|
+
def invoke
|
174
|
+
if $trace
|
175
|
+
puts "** Invoke #{name} #{format_trace_flags}"
|
244
176
|
end
|
245
|
-
if
|
246
|
-
|
177
|
+
return if @already_invoked
|
178
|
+
@already_invoked = true
|
179
|
+
@prerequisites.each { |n| Rake::Task[n].invoke }
|
180
|
+
execute if needed?
|
181
|
+
end
|
182
|
+
|
183
|
+
# Format the trace flags for display.
|
184
|
+
def format_trace_flags
|
185
|
+
flags = []
|
186
|
+
flags << "first_time" unless @already_invoked
|
187
|
+
flags << "not_needed" unless needed?
|
188
|
+
flags.empty? ? "" : "(" + flags.join(", ") + ")"
|
189
|
+
end
|
190
|
+
private :format_trace_flags
|
191
|
+
|
192
|
+
# Execute the actions associated with this task.
|
193
|
+
def execute
|
194
|
+
if $dryrun
|
195
|
+
puts "** Execute (dry run) #{name}"
|
196
|
+
return
|
247
197
|
end
|
248
|
-
if
|
249
|
-
|
198
|
+
if $trace
|
199
|
+
puts "** Execute #{name}"
|
250
200
|
end
|
251
|
-
|
201
|
+
self.class.enhance_with_matching_rule(name) if @actions.empty?
|
202
|
+
@actions.each { |act| result = act.call(self) }
|
252
203
|
end
|
253
|
-
|
254
|
-
#
|
255
|
-
def
|
256
|
-
|
257
|
-
TASKS[task_name]
|
204
|
+
|
205
|
+
# Is this task needed?
|
206
|
+
def needed?
|
207
|
+
true
|
258
208
|
end
|
259
|
-
|
260
|
-
#
|
261
|
-
#
|
262
|
-
|
263
|
-
|
264
|
-
task_name, deps = resolve_args(args)
|
265
|
-
deps = [deps] if (Symbol === deps) || (String === deps)
|
266
|
-
deps = deps.collect {|d| d.to_s }
|
267
|
-
t = lookup(task_name)
|
268
|
-
t.add_comment($last_comment)
|
269
|
-
t.enhance(deps, &block)
|
209
|
+
|
210
|
+
# Timestamp for this task. Basic tasks return the current time for
|
211
|
+
# their time stamp. Other tasks can be more sophisticated.
|
212
|
+
def timestamp
|
213
|
+
@prerequisites.collect { |p| Rake::Task[p].timestamp }.max || Time.now
|
270
214
|
end
|
271
|
-
|
272
|
-
#
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
215
|
+
|
216
|
+
# Add a comment to the task. If a comment alread exists, separate
|
217
|
+
# the new comment with " / ".
|
218
|
+
def add_comment(comment)
|
219
|
+
return if ! $last_comment
|
220
|
+
if @comment
|
221
|
+
@comment << " / "
|
222
|
+
else
|
223
|
+
@comment = ''
|
224
|
+
end
|
225
|
+
@comment << $last_comment
|
226
|
+
$last_comment = nil
|
278
227
|
end
|
279
|
-
|
280
228
|
|
281
|
-
#
|
282
|
-
#
|
283
|
-
def
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
"Rule Recursion Too Deep" if level >= 16
|
295
|
-
RULES.each do |pattern, extensions, block|
|
296
|
-
if md = pattern.match(task_name)
|
297
|
-
ext = extensions.first
|
298
|
-
case ext
|
299
|
-
when String
|
300
|
-
source = task_name.sub(/\.[^.]*$/, ext)
|
301
|
-
when Proc
|
302
|
-
source = ext.call(task_name)
|
303
|
-
else
|
304
|
-
fail "Don't know how to handle rule dependent: #{ext.inspect}"
|
305
|
-
end
|
306
|
-
if File.exist?(source) || Task.task_defined?(source)
|
307
|
-
task = FileTask.define_task({task_name => [source]}, &block)
|
308
|
-
task.source = source
|
309
|
-
return task
|
310
|
-
elsif parent = enhance_with_matching_rule(source, level+1)
|
311
|
-
task = FileTask.define_task({task_name => [parent.name]}, &block)
|
312
|
-
task.source = parent.name
|
313
|
-
return task
|
314
|
-
end
|
315
|
-
end
|
229
|
+
# Return a string describing the internal state of a task. Useful
|
230
|
+
# for debugging.
|
231
|
+
def investigation
|
232
|
+
result = "------------------------------\n"
|
233
|
+
result << "Investigating #{name}\n"
|
234
|
+
result << "class: #{self.class}\n"
|
235
|
+
result << "task needed: #{needed?}\n"
|
236
|
+
result << "timestamp: #{timestamp}\n"
|
237
|
+
result << "pre-requisites: \n"
|
238
|
+
prereqs = @prerequisites.collect {|name| Rake::Task[name]}
|
239
|
+
prereqs.sort! {|a,b| a.timestamp <=> b.timestamp}
|
240
|
+
prereqs.each do |p|
|
241
|
+
result << "--#{p.name} (#{p.timestamp})\n"
|
316
242
|
end
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
243
|
+
latest_prereq = @prerequisites.collect{|n| Rake::Task[n].timestamp}.max
|
244
|
+
result << "latest-prerequisite time: #{latest_prereq}\n"
|
245
|
+
result << "................................\n\n"
|
246
|
+
return result
|
321
247
|
end
|
322
248
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
249
|
+
# Rake Module Methods ----------------------------------------------
|
250
|
+
|
251
|
+
class << self
|
252
|
+
|
253
|
+
# Clear the task list. This cause rake to immediately forget all
|
254
|
+
# the tasks that have been assigned. (Normally used in the unit
|
255
|
+
# tests.)
|
256
|
+
def clear
|
257
|
+
TASKS.clear
|
258
|
+
RULES.clear
|
259
|
+
end
|
260
|
+
|
261
|
+
# List of all defined tasks.
|
262
|
+
def tasks
|
263
|
+
TASKS.keys.sort.collect { |tn| Rake::Task[tn] }
|
264
|
+
end
|
265
|
+
|
266
|
+
# Return a task with the given name. If the task is not currently
|
267
|
+
# known, try to synthesize one from the defined rules. If no
|
268
|
+
# rules are found, but an existing file matches the task name,
|
269
|
+
# assume it is a file task with no dependencies or actions.
|
270
|
+
def [](task_name)
|
271
|
+
task_name = task_name.to_s
|
272
|
+
if task = TASKS[task_name]
|
273
|
+
return task
|
274
|
+
end
|
275
|
+
if task = enhance_with_matching_rule(task_name)
|
276
|
+
return task
|
277
|
+
end
|
278
|
+
if File.exist?(task_name)
|
279
|
+
return Rake::FileTask.define_task(task_name)
|
280
|
+
end
|
281
|
+
fail "Don't know how to build task '#{task_name}'"
|
282
|
+
end
|
283
|
+
|
284
|
+
# TRUE if the task name is already defined.
|
285
|
+
def task_defined?(task_name)
|
286
|
+
task_name = task_name.to_s
|
287
|
+
TASKS[task_name]
|
288
|
+
end
|
289
|
+
|
290
|
+
# Define a task given +args+ and an option block. If a rule with
|
291
|
+
# the given name already exists, the prerequisites and actions are
|
292
|
+
# added to the existing task. Returns the defined task.
|
293
|
+
def define_task(args, &block)
|
294
|
+
task_name, deps = resolve_args(args)
|
295
|
+
deps = [deps] if (Symbol === deps) || (String === deps)
|
296
|
+
deps = deps.collect {|d| d.to_s }
|
297
|
+
t = lookup(task_name)
|
298
|
+
t.add_comment($last_comment)
|
299
|
+
t.enhance(deps, &block)
|
300
|
+
end
|
301
|
+
|
302
|
+
# Define a rule for synthesizing tasks.
|
303
|
+
def create_rule(args, &block)
|
304
|
+
pattern, deps = resolve_args(args)
|
305
|
+
pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
|
306
|
+
RULES << [pattern, deps, block]
|
307
|
+
end
|
308
|
+
|
309
|
+
# Lookup a task. Return an existing task if found, otherwise
|
310
|
+
# create a task of the current type.
|
311
|
+
def lookup(task_name)
|
312
|
+
name = task_name.to_s
|
313
|
+
TASKS[name] ||= self.new(task_name)
|
314
|
+
end
|
315
|
+
|
316
|
+
# If a rule can be found that matches the task name, enhance the
|
317
|
+
# task with the prerequisites and actions from the rule. Set the
|
318
|
+
# source attribute of the task appropriately for the rule. Return
|
319
|
+
# the enhanced task or nil of no rule was found.
|
320
|
+
def enhance_with_matching_rule(task_name, level=0)
|
321
|
+
fail Rake::RuleRecursionOverflowError,
|
322
|
+
"Rule Recursion Too Deep" if level >= 16
|
323
|
+
RULES.each do |pattern, extensions, block|
|
324
|
+
if md = pattern.match(task_name)
|
325
|
+
task = attempt_rule(task_name, extensions, block, level)
|
326
|
+
return task if task
|
327
|
+
end
|
328
|
+
end
|
329
|
+
nil
|
330
|
+
rescue Rake::RuleRecursionOverflowError => ex
|
331
|
+
ex.add_target(task_name)
|
332
|
+
fail ex
|
333
|
+
end
|
334
|
+
|
335
|
+
private
|
336
|
+
|
337
|
+
# Attempt to create a rule given the list of prerequisites.
|
338
|
+
def attempt_rule(task_name, extensions, block, level)
|
339
|
+
sources = make_sources(task_name, extensions)
|
340
|
+
prereqs = sources.collect { |source|
|
341
|
+
if File.exist?(source) || Rake::Task.task_defined?(source)
|
342
|
+
source
|
343
|
+
elsif parent = enhance_with_matching_rule(sources.first, level+1)
|
344
|
+
parent.name
|
345
|
+
else
|
346
|
+
return nil
|
347
|
+
end
|
348
|
+
}
|
349
|
+
task = FileTask.define_task({task_name => prereqs}, &block)
|
350
|
+
task.sources = prereqs
|
351
|
+
task
|
352
|
+
end
|
353
|
+
|
354
|
+
# Make a list of sources from the list of file name extensions /
|
355
|
+
# translation procs.
|
356
|
+
def make_sources(task_name, extensions)
|
357
|
+
extensions.collect { |ext|
|
358
|
+
case ext
|
359
|
+
when String
|
360
|
+
source = task_name.sub(/\.[^.]*$/, ext)
|
361
|
+
when Proc
|
362
|
+
source = ext.call(task_name)
|
363
|
+
else
|
364
|
+
fail "Don't know how to handle rule dependent: #{ext.inspect}"
|
365
|
+
end
|
366
|
+
}
|
367
|
+
end
|
368
|
+
|
369
|
+
# Resolve the arguments for a task/rule.
|
370
|
+
def resolve_args(args)
|
371
|
+
case args
|
372
|
+
when Hash
|
373
|
+
fail "Too Many Task Names: #{args.keys.join(' ')}" if args.size > 1
|
374
|
+
fail "No Task Name Given" if args.size < 1
|
375
|
+
task_name = args.keys[0]
|
376
|
+
deps = args[task_name]
|
377
|
+
deps = [deps] if (String===deps) || (Regexp===deps) || (Proc===deps)
|
378
|
+
else
|
379
|
+
task_name = args
|
380
|
+
deps = []
|
381
|
+
end
|
382
|
+
[task_name, deps]
|
337
383
|
end
|
338
|
-
[task_name, deps]
|
339
384
|
end
|
340
385
|
end
|
341
|
-
|
386
|
+
|
387
|
+
|
388
|
+
######################################################################
|
389
|
+
# A FileTask is a task that includes time based dependencies. If
|
390
|
+
# any of a FileTask's prerequisites have a timestamp that is later
|
391
|
+
# than the file represented by this task, then the file must be
|
392
|
+
# rebuilt (using the supplied actions).
|
393
|
+
#
|
394
|
+
class FileTask < Task
|
395
|
+
|
396
|
+
# Is this file task needed? Yes if it doesn't exist, or if its time
|
397
|
+
# stamp is out of date.
|
398
|
+
def needed?
|
399
|
+
return true unless File.exist?(name)
|
400
|
+
return true if out_of_date?(timestamp)
|
401
|
+
false
|
402
|
+
end
|
403
|
+
|
404
|
+
# Time stamp for file task.
|
405
|
+
def timestamp
|
406
|
+
if File.exist?(name)
|
407
|
+
File.mtime(name.to_s)
|
408
|
+
else
|
409
|
+
Rake::EARLY
|
410
|
+
end
|
411
|
+
end
|
342
412
|
|
413
|
+
private
|
343
414
|
|
344
|
-
|
345
|
-
#
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
#
|
350
|
-
class FileTask < Task
|
351
|
-
|
352
|
-
# Is this file task needed? Yes if it doesn't exist, or if its time
|
353
|
-
# stamp is out of date.
|
354
|
-
def needed?
|
355
|
-
return true unless File.exist?(name)
|
356
|
-
latest_prereq = @prerequisites.collect{|n| Task[n].timestamp}.max
|
357
|
-
return false if latest_prereq.nil?
|
358
|
-
timestamp < latest_prereq
|
359
|
-
rescue Errno::ENOENT => ex # one of the prereqs does not exist
|
360
|
-
raise unless $dryrun or $trace
|
361
|
-
true
|
415
|
+
# Are there any prerequisites with a later time than the given
|
416
|
+
# time stamp?
|
417
|
+
def out_of_date?(stamp)
|
418
|
+
@prerequisites.any? { |n| Rake::Task[n].timestamp > stamp}
|
419
|
+
end
|
362
420
|
end
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
421
|
+
|
422
|
+
######################################################################
|
423
|
+
# A FileCreationTask is a file task that when used as a dependency
|
424
|
+
# will be needed if and only if the file has not been created. Once
|
425
|
+
# created, it is not re-triggered if any of its dependencies are
|
426
|
+
# newer, nor does trigger any rebuilds of tasks that depend on it
|
427
|
+
# whenever it is updated.
|
428
|
+
class FileCreationTask < FileTask
|
429
|
+
# Is this file task needed? Yes if it doesn't exist.
|
430
|
+
def needed?
|
431
|
+
! File.exist?(name)
|
432
|
+
end
|
433
|
+
|
434
|
+
# Time stamp for file creation task. This time stamp is earlier
|
435
|
+
# than any other time stamp.
|
436
|
+
def timestamp
|
437
|
+
Rake::EARLY
|
438
|
+
end
|
367
439
|
end
|
368
440
|
end
|
369
441
|
|
@@ -378,7 +450,7 @@ end
|
|
378
450
|
# end
|
379
451
|
#
|
380
452
|
def task(args, &block)
|
381
|
-
Task.define_task(args, &block)
|
453
|
+
Rake::Task.define_task(args, &block)
|
382
454
|
end
|
383
455
|
|
384
456
|
|
@@ -396,7 +468,13 @@ end
|
|
396
468
|
# end
|
397
469
|
#
|
398
470
|
def file(args, &block)
|
399
|
-
FileTask.define_task(args, &block)
|
471
|
+
Rake::FileTask.define_task(args, &block)
|
472
|
+
end
|
473
|
+
|
474
|
+
# Declare a file creation task.
|
475
|
+
# (Mainly used for the directory command).
|
476
|
+
def file_create(args, &block)
|
477
|
+
Rake::FileCreationTask.define_task(args, &block)
|
400
478
|
end
|
401
479
|
|
402
480
|
# Declare a set of files tasks to create the given directories on
|
@@ -406,11 +484,10 @@ end
|
|
406
484
|
# directory "testdata/doc"
|
407
485
|
#
|
408
486
|
def directory(dir)
|
409
|
-
|
410
|
-
|
487
|
+
Rake.each_dir_parent(dir) do |d|
|
488
|
+
file_create d do |t|
|
411
489
|
mkdir_p t.name if ! File.exist?(t.name)
|
412
490
|
end
|
413
|
-
dir = File.dirname(dir)
|
414
491
|
end
|
415
492
|
end
|
416
493
|
|
@@ -422,7 +499,7 @@ end
|
|
422
499
|
# end
|
423
500
|
#
|
424
501
|
def rule(args, &block)
|
425
|
-
Task.create_rule(args, &block)
|
502
|
+
Rake::Task.create_rule(args, &block)
|
426
503
|
end
|
427
504
|
|
428
505
|
# Describe the next rake task.
|
@@ -451,7 +528,7 @@ end
|
|
451
528
|
# to be added to the FileUtils utility functions.
|
452
529
|
#
|
453
530
|
module FileUtils
|
454
|
-
RUBY = Config::CONFIG['ruby_install_name']
|
531
|
+
RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
|
455
532
|
|
456
533
|
OPT_TABLE['sh'] = %w(noop verbose)
|
457
534
|
OPT_TABLE['ruby'] = %w(noop verbose)
|
@@ -962,6 +1039,29 @@ module Rake
|
|
962
1039
|
end
|
963
1040
|
|
964
1041
|
|
1042
|
+
# Grep each of the files in the filelist using the given pattern.
|
1043
|
+
# If a block is given, call the block on each matching line,
|
1044
|
+
# passing the file name, line number, and the matching line of
|
1045
|
+
# text. If no block is given, a standard emac style
|
1046
|
+
# file:linenumber:line message will be printed to standard out.
|
1047
|
+
def egrep(pattern)
|
1048
|
+
each do |fn|
|
1049
|
+
open(fn) do |inf|
|
1050
|
+
count = 0
|
1051
|
+
inf.each do |line|
|
1052
|
+
count += 1
|
1053
|
+
if pattern.match(line)
|
1054
|
+
if block_given?
|
1055
|
+
yield fn, count, line
|
1056
|
+
else
|
1057
|
+
puts "#{fn}:#{count}:#{line}"
|
1058
|
+
end
|
1059
|
+
end
|
1060
|
+
end
|
1061
|
+
end
|
1062
|
+
end
|
1063
|
+
end
|
1064
|
+
|
965
1065
|
# FileList version of partition. Needed because the nested arrays
|
966
1066
|
# should be FileLists in this version.
|
967
1067
|
def partition(&block) # :nodoc:
|
@@ -1035,6 +1135,21 @@ module Rake
|
|
1035
1135
|
@exclude_patterns = [ /^$/ ]
|
1036
1136
|
end
|
1037
1137
|
end
|
1138
|
+
end # FileList
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
module Rake
|
1142
|
+
class << self
|
1143
|
+
|
1144
|
+
# Yield each file or directory component.
|
1145
|
+
def each_dir_parent(dir)
|
1146
|
+
old_length = nil
|
1147
|
+
while dir != '.' && dir.length != old_length
|
1148
|
+
yield(dir)
|
1149
|
+
old_length = dir.length
|
1150
|
+
dir = File.dirname(dir)
|
1151
|
+
end
|
1152
|
+
end
|
1038
1153
|
end
|
1039
1154
|
end
|
1040
1155
|
|
@@ -1050,251 +1165,342 @@ module Rake
|
|
1050
1165
|
Kernel.load fn
|
1051
1166
|
end
|
1052
1167
|
end
|
1053
|
-
end
|
1054
1168
|
|
1055
|
-
|
1056
|
-
#
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
RAKEFILES = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb']
|
1061
|
-
|
1062
|
-
OPTIONS = [
|
1063
|
-
['--dry-run', '-n', GetoptLong::NO_ARGUMENT,
|
1064
|
-
"Do a dry run without executing actions."],
|
1065
|
-
['--help', '-H', GetoptLong::NO_ARGUMENT,
|
1066
|
-
"Display this help message."],
|
1067
|
-
['--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT,
|
1068
|
-
"Include LIBDIR in the search path for required modules."],
|
1069
|
-
['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
|
1070
|
-
"Do not search parent directories for the Rakefile."],
|
1071
|
-
['--prereqs', '-P', GetoptLong::NO_ARGUMENT,
|
1072
|
-
"Display the tasks and dependencies, then exit."],
|
1073
|
-
['--quiet', '-q', GetoptLong::NO_ARGUMENT,
|
1074
|
-
"Do not log messages to standard output."],
|
1075
|
-
['--rakefile', '-f', GetoptLong::REQUIRED_ARGUMENT,
|
1076
|
-
"Use FILE as the rakefile."],
|
1077
|
-
['--require', '-r', GetoptLong::REQUIRED_ARGUMENT,
|
1078
|
-
"Require MODULE before executing rakefile."],
|
1079
|
-
['--silent', '-s', GetoptLong::NO_ARGUMENT,
|
1080
|
-
"Like --quiet, but also suppresses the 'in directory' announcement."],
|
1081
|
-
['--tasks', '-T', GetoptLong::NO_ARGUMENT,
|
1082
|
-
"Display the tasks and dependencies, then exit."],
|
1083
|
-
['--trace', '-t', GetoptLong::NO_ARGUMENT,
|
1084
|
-
"Turn on invoke/execute tracing, enable full backtrace."],
|
1085
|
-
['--usage', '-h', GetoptLong::NO_ARGUMENT,
|
1086
|
-
"Display usage."],
|
1087
|
-
['--verbose', '-v', GetoptLong::NO_ARGUMENT,
|
1088
|
-
"Log message to standard output (default)."],
|
1089
|
-
['--version', '-V', GetoptLong::NO_ARGUMENT,
|
1090
|
-
"Display the program version."],
|
1091
|
-
]
|
1092
|
-
|
1093
|
-
# Create a RakeApp object.
|
1094
|
-
def initialize
|
1095
|
-
@rakefile = nil
|
1096
|
-
@pending_imports = []
|
1097
|
-
@imported = []
|
1098
|
-
@nosearch = false
|
1099
|
-
@loaders = {}
|
1100
|
-
@default_loader = Rake::DefaultLoader.new
|
1101
|
-
Rake.application = self
|
1102
|
-
end
|
1169
|
+
# EarlyTime is a fake timestamp that occurs _before_ any other time
|
1170
|
+
# value.
|
1171
|
+
class EarlyTime
|
1172
|
+
include Comparable
|
1173
|
+
include Singleton
|
1103
1174
|
|
1104
|
-
|
1105
|
-
|
1106
|
-
def have_rakefile
|
1107
|
-
RAKEFILES.each do |fn|
|
1108
|
-
if File.exist?(fn)
|
1109
|
-
@rakefile = fn
|
1110
|
-
return true
|
1111
|
-
end
|
1175
|
+
def <=>(other)
|
1176
|
+
-1
|
1112
1177
|
end
|
1113
|
-
return false
|
1114
|
-
end
|
1115
1178
|
|
1116
|
-
|
1117
|
-
|
1118
|
-
puts "rake [-f rakefile] {options} targets..."
|
1119
|
-
end
|
1120
|
-
|
1121
|
-
# Display the rake command line help.
|
1122
|
-
def help
|
1123
|
-
usage
|
1124
|
-
puts
|
1125
|
-
puts "Options are ..."
|
1126
|
-
puts
|
1127
|
-
OPTIONS.sort.each do |long, short, mode, desc|
|
1128
|
-
if mode == GetoptLong::REQUIRED_ARGUMENT
|
1129
|
-
if desc =~ /\b([A-Z]{2,})\b/
|
1130
|
-
long = long + "=#{$1}"
|
1131
|
-
end
|
1132
|
-
end
|
1133
|
-
printf " %-20s (%s)\n", long, short
|
1134
|
-
printf " %s\n", desc
|
1179
|
+
def to_s
|
1180
|
+
"<EARLY TIME>"
|
1135
1181
|
end
|
1136
1182
|
end
|
1137
1183
|
|
1138
|
-
|
1139
|
-
|
1140
|
-
width = Task.tasks.select { |t|
|
1141
|
-
t.comment
|
1142
|
-
}.collect { |t|
|
1143
|
-
t.name.length
|
1144
|
-
}.max
|
1145
|
-
Task.tasks.each do |t|
|
1146
|
-
if t.comment
|
1147
|
-
printf "rake %-#{width}s # %s\n", t.name, t.comment
|
1148
|
-
end
|
1149
|
-
end
|
1150
|
-
end
|
1184
|
+
EARLY = EarlyTime.instance
|
1185
|
+
end
|
1151
1186
|
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1187
|
+
######################################################################
|
1188
|
+
# Extensions to time to allow comparisons with an early time class.
|
1189
|
+
class Time
|
1190
|
+
alias pre_early_time_compare :<=>
|
1191
|
+
def <=>(other)
|
1192
|
+
if Rake::EarlyTime === other
|
1193
|
+
- other.<=>(self)
|
1194
|
+
else
|
1195
|
+
pre_early_time_compare(other)
|
1157
1196
|
end
|
1158
|
-
end
|
1197
|
+
end
|
1198
|
+
end
|
1159
1199
|
|
1160
|
-
|
1161
|
-
# program.
|
1162
|
-
def command_line_options
|
1163
|
-
OPTIONS.collect { |lst| lst[0..-2] }
|
1164
|
-
end
|
1200
|
+
module Rake
|
1165
1201
|
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1202
|
+
######################################################################
|
1203
|
+
# Rake main application object. When invoking +rake+ from the
|
1204
|
+
# command line, a Rake::Application object is created and run.
|
1205
|
+
#
|
1206
|
+
class Application
|
1207
|
+
RAKEFILES = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb']
|
1208
|
+
|
1209
|
+
OPTIONS = [
|
1210
|
+
['--dry-run', '-n', GetoptLong::NO_ARGUMENT,
|
1211
|
+
"Do a dry run without executing actions."],
|
1212
|
+
['--help', '-H', GetoptLong::NO_ARGUMENT,
|
1213
|
+
"Display this help message."],
|
1214
|
+
['--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT,
|
1215
|
+
"Include LIBDIR in the search path for required modules."],
|
1216
|
+
['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
|
1217
|
+
"Do not search parent directories for the Rakefile."],
|
1218
|
+
['--prereqs', '-P', GetoptLong::NO_ARGUMENT,
|
1219
|
+
"Display the tasks and dependencies, then exit."],
|
1220
|
+
['--quiet', '-q', GetoptLong::NO_ARGUMENT,
|
1221
|
+
"Do not log messages to standard output."],
|
1222
|
+
['--rakefile', '-f', GetoptLong::REQUIRED_ARGUMENT,
|
1223
|
+
"Use FILE as the rakefile."],
|
1224
|
+
['--require', '-r', GetoptLong::REQUIRED_ARGUMENT,
|
1225
|
+
"Require MODULE before executing rakefile."],
|
1226
|
+
['--silent', '-s', GetoptLong::NO_ARGUMENT,
|
1227
|
+
"Like --quiet, but also suppresses the 'in directory' announcement."],
|
1228
|
+
['--tasks', '-T', GetoptLong::NO_ARGUMENT,
|
1229
|
+
"Display the tasks and dependencies, then exit."],
|
1230
|
+
['--trace', '-t', GetoptLong::NO_ARGUMENT,
|
1231
|
+
"Turn on invoke/execute tracing, enable full backtrace."],
|
1232
|
+
['--usage', '-h', GetoptLong::NO_ARGUMENT,
|
1233
|
+
"Display usage."],
|
1234
|
+
['--verbose', '-v', GetoptLong::NO_ARGUMENT,
|
1235
|
+
"Log message to standard output (default)."],
|
1236
|
+
['--version', '-V', GetoptLong::NO_ARGUMENT,
|
1237
|
+
"Display the program version."],
|
1238
|
+
['--classic-namespace', '-C', GetoptLong::NO_ARGUMENT,
|
1239
|
+
"Put Task and FileTask in the top level namespace"],
|
1240
|
+
]
|
1241
|
+
|
1242
|
+
# Create a Rake::Application object.
|
1243
|
+
def initialize
|
1244
|
+
@rakefile = nil
|
1245
|
+
@pending_imports = []
|
1246
|
+
@imported = []
|
1247
|
+
@nosearch = false
|
1248
|
+
@loaders = {}
|
1249
|
+
@default_loader = Rake::DefaultLoader.new
|
1250
|
+
Rake.application = self
|
1251
|
+
end
|
1252
|
+
|
1253
|
+
# True if one of the files in RAKEFILES is in the current directory.
|
1254
|
+
# If a match is found, it is copied into @rakefile.
|
1255
|
+
def have_rakefile
|
1256
|
+
RAKEFILES.each do |fn|
|
1257
|
+
if File.exist?(fn)
|
1258
|
+
@rakefile = fn
|
1259
|
+
return true
|
1260
|
+
end
|
1261
|
+
end
|
1262
|
+
return false
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
# Display the program usage line.
|
1266
|
+
def usage
|
1267
|
+
puts "rake [-f rakefile] {options} targets..."
|
1268
|
+
end
|
1269
|
+
|
1270
|
+
# Display the rake command line help.
|
1271
|
+
def help
|
1199
1272
|
usage
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1273
|
+
puts
|
1274
|
+
puts "Options are ..."
|
1275
|
+
puts
|
1276
|
+
OPTIONS.sort.each do |long, short, mode, desc|
|
1277
|
+
if mode == GetoptLong::REQUIRED_ARGUMENT
|
1278
|
+
if desc =~ /\b([A-Z]{2,})\b/
|
1279
|
+
long = long + "=#{$1}"
|
1280
|
+
end
|
1281
|
+
end
|
1282
|
+
printf " %-20s (%s)\n", long, short
|
1283
|
+
printf " %s\n", desc
|
1284
|
+
end
|
1208
1285
|
end
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
if Dir.pwd == here || @nosearch
|
1222
|
-
fail "No Rakefile found (looking for: #{RAKEFILES.join(', ')})"
|
1286
|
+
|
1287
|
+
# Display the tasks and dependencies.
|
1288
|
+
def display_tasks_and_comments
|
1289
|
+
width = Rake::Task.tasks.select { |t|
|
1290
|
+
t.comment
|
1291
|
+
}.collect { |t|
|
1292
|
+
t.name.length
|
1293
|
+
}.max
|
1294
|
+
Rake::Task.tasks.each do |t|
|
1295
|
+
if t.comment
|
1296
|
+
printf "rake %-#{width}s # %s\n", t.name, t.comment
|
1297
|
+
end
|
1223
1298
|
end
|
1224
|
-
here = Dir.pwd
|
1225
1299
|
end
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1300
|
+
|
1301
|
+
# Display the tasks and prerequisites
|
1302
|
+
def display_prerequisites
|
1303
|
+
Rake::Task.tasks.each do |t|
|
1304
|
+
puts "rake #{t.name}"
|
1305
|
+
t.prerequisites.each { |pre| puts " #{pre}" }
|
1306
|
+
end
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
# Return a list of the command line options supported by the
|
1310
|
+
# program.
|
1311
|
+
def command_line_options
|
1312
|
+
OPTIONS.collect { |lst| lst[0..-2] }
|
1313
|
+
end
|
1314
|
+
|
1315
|
+
# Do the option defined by +opt+ and +value+.
|
1316
|
+
def do_option(opt, value)
|
1317
|
+
case opt
|
1318
|
+
when '--dry-run'
|
1319
|
+
verbose(true)
|
1320
|
+
nowrite(true)
|
1321
|
+
$dryrun = true
|
1322
|
+
$trace = true
|
1323
|
+
when '--help'
|
1324
|
+
help
|
1325
|
+
exit
|
1326
|
+
when '--libdir'
|
1327
|
+
$:.push(value)
|
1328
|
+
when '--nosearch'
|
1329
|
+
@nosearch = true
|
1330
|
+
when '--prereqs'
|
1331
|
+
$show_prereqs = true
|
1332
|
+
when '--quiet'
|
1333
|
+
verbose(false)
|
1334
|
+
when '--rakefile'
|
1335
|
+
RAKEFILES.clear
|
1336
|
+
RAKEFILES << value
|
1337
|
+
when '--require'
|
1338
|
+
require value
|
1339
|
+
when '--silent'
|
1340
|
+
verbose(false)
|
1341
|
+
$silent = true
|
1342
|
+
when '--tasks'
|
1343
|
+
$show_tasks = true
|
1344
|
+
when '--trace'
|
1345
|
+
$trace = true
|
1346
|
+
verbose(true)
|
1347
|
+
when '--usage'
|
1348
|
+
usage
|
1349
|
+
exit
|
1350
|
+
when '--verbose'
|
1351
|
+
verbose(true)
|
1352
|
+
when '--version'
|
1353
|
+
puts "rake, version #{RAKEVERSION}"
|
1354
|
+
exit
|
1355
|
+
when '--classic-namespace'
|
1356
|
+
require 'rake/classic_namespace'
|
1240
1357
|
else
|
1241
|
-
|
1358
|
+
fail "Unknown option: #{opt}"
|
1242
1359
|
end
|
1243
1360
|
end
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1361
|
+
|
1362
|
+
# Read and handle the command line options.
|
1363
|
+
def handle_options
|
1364
|
+
opts = GetoptLong.new(*command_line_options)
|
1365
|
+
opts.each { |opt, value| do_option(opt, value) }
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
def load_rakefile
|
1369
|
+
here = Dir.pwd
|
1370
|
+
while ! have_rakefile
|
1371
|
+
Dir.chdir("..")
|
1372
|
+
if Dir.pwd == here || @nosearch
|
1373
|
+
fail "No Rakefile found (looking for: #{RAKEFILES.join(', ')})"
|
1374
|
+
end
|
1375
|
+
here = Dir.pwd
|
1376
|
+
end
|
1377
|
+
puts "(in #{Dir.pwd})" unless $silent
|
1378
|
+
$rakefile = @rakefile
|
1379
|
+
load @rakefile
|
1380
|
+
load_imports
|
1381
|
+
end
|
1382
|
+
|
1383
|
+
# Collect the list of tasks on the command line. If no tasks are
|
1384
|
+
# give, return a list containing only the default task.
|
1385
|
+
# Environmental assignments are processed at this time as well.
|
1386
|
+
def collect_tasks
|
1387
|
+
tasks = []
|
1388
|
+
ARGV.each do |arg|
|
1389
|
+
if arg =~ /^(\w+)=(.*)$/
|
1390
|
+
ENV[$1] = $2
|
1391
|
+
else
|
1392
|
+
tasks << arg
|
1393
|
+
end
|
1394
|
+
end
|
1395
|
+
tasks.push("default") if tasks.size == 0
|
1396
|
+
tasks
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
# Add a file to the list of files to be imported.
|
1400
|
+
def add_import(fn)
|
1401
|
+
@pending_imports << fn
|
1402
|
+
end
|
1403
|
+
|
1404
|
+
# Load the pending list of imported files.
|
1405
|
+
def load_imports
|
1406
|
+
while fn = @pending_imports.shift
|
1407
|
+
next if @imported.member?(fn)
|
1408
|
+
Rake::Task[fn].invoke if Rake::Task.task_defined?(fn)
|
1409
|
+
ext = File.extname(fn)
|
1410
|
+
loader = @loaders[ext] || @default_loader
|
1411
|
+
loader.load(fn)
|
1412
|
+
@imported << fn
|
1413
|
+
end
|
1414
|
+
end
|
1415
|
+
|
1416
|
+
# Add a loader to handle imported files ending in the extension
|
1417
|
+
# +ext+.
|
1418
|
+
def add_loader(ext, loader)
|
1419
|
+
ext = ".#{ext}" unless ext =~ /^\./
|
1420
|
+
@loaders[ext] = loader
|
1421
|
+
end
|
1422
|
+
|
1423
|
+
# Warn about deprecated use of top level constant names.
|
1424
|
+
def const_warning(const_name)
|
1425
|
+
@const_warning ||= false
|
1426
|
+
if ! @const_warning
|
1427
|
+
puts %{WARNING: Deprecated reference to top-level constant '#{const_name}'} +
|
1428
|
+
%{found at: #{rakefile_location}}
|
1429
|
+
puts %{ Use --classic-namespace on rake command}
|
1430
|
+
puts %{ or 'require "rake/classic_namespace"' in Rakefile}
|
1431
|
+
end
|
1432
|
+
@const_warning = true
|
1433
|
+
end
|
1247
1434
|
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1435
|
+
def rakefile_location
|
1436
|
+
begin
|
1437
|
+
fail
|
1438
|
+
rescue RuntimeError => ex
|
1439
|
+
ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
1440
|
+
end
|
1441
|
+
end
|
1252
1442
|
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1443
|
+
# Run the +rake+ application.
|
1444
|
+
def run
|
1445
|
+
handle_options
|
1446
|
+
begin
|
1447
|
+
tasks = collect_tasks
|
1448
|
+
load_rakefile
|
1449
|
+
if $show_tasks
|
1450
|
+
display_tasks_and_comments
|
1451
|
+
elsif $show_prereqs
|
1452
|
+
display_prerequisites
|
1453
|
+
else
|
1454
|
+
tasks.each { |task_name| Rake::Task[task_name].invoke }
|
1455
|
+
end
|
1456
|
+
rescue Exception => ex
|
1457
|
+
puts "rake aborted!"
|
1458
|
+
puts ex.message
|
1459
|
+
if $trace
|
1460
|
+
puts ex.backtrace.join("\n")
|
1461
|
+
else
|
1462
|
+
puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
1463
|
+
end
|
1464
|
+
exit(1)
|
1465
|
+
end
|
1262
1466
|
end
|
1263
1467
|
end
|
1264
1468
|
|
1265
|
-
|
1266
|
-
# +ext+.
|
1267
|
-
def add_loader(ext, loader)
|
1268
|
-
ext = ".#{ext}" unless ext =~ /^\./
|
1269
|
-
@loaders[ext] = loader
|
1270
|
-
end
|
1469
|
+
end
|
1271
1470
|
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1471
|
+
|
1472
|
+
class Object
|
1473
|
+
class << self
|
1474
|
+
|
1475
|
+
# Rename the original handler to make it available.
|
1476
|
+
alias :rake_original_const_missing :const_missing
|
1477
|
+
|
1478
|
+
# Check for deprecated uses of top level (i.e. in Object) uses of
|
1479
|
+
# Rake class names. If someone tries to reference the constant
|
1480
|
+
# name, display a warning and return the proper object. Using
|
1481
|
+
# --class-namespace will define these constants in Object and
|
1482
|
+
# avoid this handler.
|
1483
|
+
def const_missing(const_name)
|
1484
|
+
case const_name
|
1485
|
+
when :Task
|
1486
|
+
Rake.application.const_warning(const_name)
|
1487
|
+
Rake::Task
|
1488
|
+
when :FileTask
|
1489
|
+
Rake.application.const_warning(const_name)
|
1490
|
+
Rake::FileTask
|
1491
|
+
when :FileCreationTask
|
1492
|
+
Rake.application.const_warning(const_name)
|
1493
|
+
Rake::FileCreationTask
|
1494
|
+
when :RakeApp
|
1495
|
+
Rake.application.const_warning(const_name)
|
1496
|
+
Rake::Application
|
1290
1497
|
else
|
1291
|
-
|
1498
|
+
rake_original_const_missing(const_name)
|
1292
1499
|
end
|
1293
|
-
|
1294
|
-
end
|
1500
|
+
end
|
1295
1501
|
end
|
1296
1502
|
end
|
1297
1503
|
|
1298
1504
|
if __FILE__ == $0 then
|
1299
|
-
|
1505
|
+
Rake::Application.new.run
|
1300
1506
|
end
|