buildr 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -161,12 +161,17 @@ module Buildr
161
161
 
162
162
  # See Buildr#projects.
163
163
  def projects(*names) #:nodoc:
164
+ options = names.pop if Hash === names.last
164
165
  @projects ||= {}
165
- if names.empty?
166
- @projects.keys.map { |name| project(name) }.sort_by(&:name)
166
+ names = @projects.keys if names.empty?
167
+ if options && options[:in]
168
+ parent = @projects[options[:in].to_s] or raise "No such project #{options[:in].to_s}"
169
+ names.uniq.map { |name| @projects[name] or raise "No such project #{name}" }.
170
+ select { |project| project.parent == parent }.
171
+ each { |project| project.invoke }.sort_by(&:name)
167
172
  else
168
- names.map { |name| project(name) or raise "No such project #{name}" }.uniq.sort_by(&:name)
169
- end
173
+ names.uniq.map { |name| project(name) or raise "No such project #{name}" }.sort_by(&:name)
174
+ end
170
175
  end
171
176
 
172
177
  # :call-seq:
@@ -325,18 +330,20 @@ module Buildr
325
330
  # Essentially, joins all the supplied names and expands the path relative to #base_dir.
326
331
  # Symbol arguments are converted to paths by calling the attribute accessor on the project.
327
332
  #
328
- # For example:
333
+ # Keep in mind that all tasks are defined and executed relative to the Rakefile directory,
334
+ # so you want to use #path_to to get the actual path within the project as a matter of practice.
329
335
  #
330
336
  # For example:
331
337
  # path_to("foo", "bar")
332
338
  # => /home/project1/foo/bar
333
339
  # path_to("/tmp")
334
340
  # => /tmp
335
- # path_to(:base_dir, "foo")
341
+ # path_to(:base_dir, "foo") # same as path_to("foo")
336
342
  # => /home/project1/foo
337
343
  def path_to(*names)
338
344
  File.expand_path(File.join(names.map { |name| Symbol === name ? send(name) : name.to_s }), base_dir)
339
345
  end
346
+ alias :_ :path_to
340
347
 
341
348
  # :call-seq:
342
349
  # define(name, properties?) { |project| ... } => project
@@ -382,12 +389,8 @@ module Buildr
382
389
  # => "/home/foo/bar/src"
383
390
  def file(args, &block)
384
391
  task_name, deps = Rake.application.resolve_args(args)
385
- unless task = Rake.application.lookup(task_name, [])
386
- task = Rake::FileTask.define_task(File.expand_path(task_name, base_dir))
387
- task.base_dir = base_dir
388
- end
389
392
  deps = [deps] unless deps.respond_to?(:to_ary)
390
- task.enhance deps, &block
393
+ Rake::FileTask.define_task(path_to(task_name)=>deps, &block)
391
394
  end
392
395
 
393
396
  # :call-seq:
@@ -445,21 +448,14 @@ module Buildr
445
448
  def recursive_task(args, &block)
446
449
  task_name, deps = Rake.application.resolve_args(args)
447
450
  deps = [deps] unless deps.respond_to?(:to_ary)
448
- task(task_name=>deps).tap do |task|
449
- if parent
450
- Rake.application.lookup(task_name, parent.name.split(":")).enhance [task]
451
- #Rake::Task["^#{name}"].enhance([ task ])
452
- end
453
- task.enhance &block
454
- end
451
+ task = ENV["PARALLEL"] =~ /(yes|on|true)/ ? multitask(task_name) : task(task_name)
452
+ Rake.application.lookup(task_name, parent.name.split(":")).enhance [task] if parent
453
+ task.enhance deps, &block
455
454
  end
456
455
 
457
456
  def execute() #:nodoc:
458
457
  # Reset the namespace, so all tasks are automatically defined in the project's namespace.
459
- Rake.application.in_namespace ":#{name}" do
460
- # Everything we do inside the project is relative to its working directory.
461
- Dir.chdir(base_dir) { super }
462
- end
458
+ Rake.application.in_namespace(":#{name}") { super }
463
459
  end
464
460
 
465
461
  end
@@ -536,6 +532,7 @@ module Buildr
536
532
 
537
533
  # :call-seq:
538
534
  # projects(*names) => projects
535
+ # projects(:in=>parent) => projects
539
536
  #
540
537
  # With no arguments, returns a list of all projects defined so far. With arguments,
541
538
  # returns a list of these projects, fails on undefined projects.
@@ -543,11 +540,15 @@ module Buildr
543
540
  # Like #project, this method evaluates the definition of each project before returning it.
544
541
  # Be advised of circular dependencies.
545
542
  #
543
+ # Use the :in option if you only want the sub-projects of a given parent project.
544
+ #
546
545
  # For example:
547
546
  # files = projects.map { |prj| FileList[prj.path_to("src/**/*.java") }.flatten
548
547
  # puts "There are #{files.size} source files in #{projects.size} projects"
549
548
  #
550
- # puts projects("project1", "project2").map(&:base_dir)
549
+ # puts projects("myapp:beans", "myapp:webapp").map(&:name)
550
+ # Same as:
551
+ # puts projects(:in=>"mayapp").map(&:name)
551
552
  def projects(*names)
552
553
  Project.projects *names
553
554
  end
@@ -1,17 +1,6 @@
1
1
  module Rake #:nodoc:
2
2
  class Task
3
3
 
4
- # Access the base directory. The base directory is set when the class
5
- # is defined from the current directory. The current directory is set
6
- # to the base directory when the class is executed.
7
- attr_accessor :base_dir
8
-
9
- def initialize_with_base_dir(*args) #:nodoc:
10
- @base_dir = Dir.pwd
11
- initialize_without_base_dir *args
12
- end
13
- alias_method_chain :initialize, :base_dir
14
-
15
4
  def invoke #:nodoc:
16
5
  tasks = (Thread.current[:tasks] || [])
17
6
  if tasks.include?(name)
@@ -25,10 +14,8 @@ module Rake #:nodoc:
25
14
  begin
26
15
  Thread.current[:tasks] = tasks + [name]
27
16
  @already_invoked = true
28
- Dir.chdir(@base_dir || Dir.pwd) do
29
- invoke_prerequisites
30
- execute if needed?
31
- end
17
+ invoke_prerequisites
18
+ execute if needed?
32
19
  ensure
33
20
  Thread.current[:tasks] = tasks
34
21
  end
@@ -1,3 +1,4 @@
1
+ require "cgi"
1
2
  require "net/http"
2
3
  require "net/ssh"
3
4
  require "net/sftp"
@@ -114,9 +115,9 @@ module Buildr
114
115
  @options = options || {}
115
116
  end
116
117
 
117
- # Downloads a file from the specified path, relative to the
118
- # server URI. Downloads to either the target file, or by
119
- # calling the block with each chunk of the file.
118
+ # Downloads a file from the specified path, relative to the server URI.
119
+ # Downloads to either the target file, or by calling the block with each
120
+ # chunk of the file. Returns the file's modified timestamp, or now.
120
121
  #
121
122
  # For example:
122
123
  # Transports.perform("http://server/libs") do |http|
@@ -272,16 +273,24 @@ module Buildr
272
273
  end
273
274
 
274
275
  def download(path, target = nil, &block)
275
- puts "Requesting #{path} from #{@uri}" if Rake.application.options.trace
276
- @http.request_get(@base_path + path) do |response|
276
+ puts "Requesting #{@uri}/#{path} " if Rake.application.options.trace
277
+ last_modified = File.stat(target).mtime.utc if target && File.exist?(target)
278
+ headers = {}
279
+ headers["If-Modified-Since"] = CGI.rfc1123_date(last_modified) if last_modified
280
+ @http.request_get(@base_path + path, headers) do |response|
277
281
  case response
282
+ when Net::HTTPNotModified
283
+ # No modification, nothing to do.
284
+ puts "Not modified since last download" if Rake.application.options.trace
285
+
278
286
  when Net::HTTPRedirection
279
287
  # Try to download from the new URI, handle relative redirects.
280
- puts "Redirected" if Rake.application.options.trace
281
- Transports.download(@uri + URI.parse(response["location"]), target, @options)
288
+ puts "Redirected to #{response['Location']}" if Rake.application.options.trace
289
+ last_modified = Transports.download(@uri + URI.parse(response["location"]), target, @options)
282
290
 
283
291
  when Net::HTTPOK
284
292
  puts "Downloading #{@uri}/#{path}" if verbose
293
+ last_modified = Time.parse(response["Last-Modified"] || "")
285
294
  with_progress_bar path.split("/").last, response.content_length do |progress|
286
295
  with_digests(@options[:digests]) do |digester|
287
296
 
@@ -311,7 +320,8 @@ module Buildr
311
320
  temp = Tempfile.new(File.basename(target))
312
321
  download[ proc { |chunk| temp.write chunk } ]
313
322
  temp.close
314
- File.move temp.path, target if target
323
+ File.move temp.path, target
324
+ File.utime last_modified, last_modified, target
315
325
  else
316
326
  download[ block ]
317
327
  end
@@ -324,6 +334,7 @@ module Buildr
324
334
  fail "Failed to download #{@uri}/#{path}: #{response.message}"
325
335
  end
326
336
  end
337
+ last_modified
327
338
  end
328
339
 
329
340
  def close()
@@ -2,77 +2,76 @@ require "core/project"
2
2
  require "java/java"
3
3
 
4
4
  module Buildr
5
- module Java
6
- module Ant
5
+ module Ant
7
6
 
8
- # Libraries used by #ant.
9
- REQUIRES = [ "ant:ant:jar:1.6.5", "ant:ant-launcher:jar:1.6.5", "xerces:xercesImpl:jar:2.6.2" ]
7
+ # Libraries used by #ant.
8
+ REQUIRES = [ "ant:ant:jar:1.6.5", "ant:ant-launcher:jar:1.6.5", "xerces:xercesImpl:jar:2.6.2" ]
10
9
 
11
- # Make sure Ant and friends show on the classpath. Antwrap must only be loaded after RJB.
10
+ # Make sure Ant and friends show on the classpath. Antwrap must only be loaded after RJB.
11
+ Java.rjb.onload do
12
12
  Java.rjb.classpath += REQUIRES
13
13
  Java.rjb.onload { require "antwrap" }
14
+ end
14
15
 
15
- class << self
16
-
17
- # :call-seq:
18
- # declarative(name, options?) => AntProject
19
- # declarative(name, options?) { |AntProject| ... } => AntProject
20
- #
21
- # Returns a declarative AntProject with the specified name. Ant tasks created in this project
22
- # are not executed until you tell them to.
23
- #
24
- # See #ant for more information about options and the block.
25
- def declarative(name, options = nil, &block)
26
- options ||= {}
27
- options = (options || {}).merge(:name=>name, :base_dir=>Dir.pwd, :declarative=>false)
28
- Java.rjb { AntProject.new(options).tap { |project| yield project if block_given? } }
29
- end
16
+ class << self
30
17
 
31
- # :call-seq:
32
- # executable(name, options?) => AntProject
33
- # executable(name, options?) { |AntProject| ... } => AntProject
34
- #
35
- # Returns an executable AntProject with the specified name. Ant tasks created in this project
36
- # are executed immediately.
37
- #
38
- # See #ant for more information about options and the block.
39
- def executable(name, options = nil, &block)
40
- options ||= {}
41
- options = (options || {}).merge(:name=>name, :base_dir=>Dir.pwd, :declarative=>true)
42
- Java.rjb { AntProject.new(options).tap { |project| yield project if block_given? } }
43
- end
18
+ # :call-seq:
19
+ # declarative(name, options?) => AntProject
20
+ # declarative(name, options?) { |AntProject| ... } => AntProject
21
+ #
22
+ # Returns a declarative AntProject with the specified name. Ant tasks created in this project
23
+ # are not executed until you tell them to.
24
+ #
25
+ # See #ant for more information about options and the block.
26
+ def declarative(name, options = nil, &block)
27
+ options ||= {}
28
+ options = (options || {}).merge(:name=>name, :base_dir=>Dir.pwd, :declarative=>false)
29
+ Java.rjb { AntProject.new(options).tap { |project| yield project if block_given? } }
44
30
  end
45
31
 
46
32
  # :call-seq:
47
- # ant(name, options?) => AntProject
48
- # ant(name, options?) { |AntProject| ... } => AntProject
49
- #
50
- # Returns a new AntProject with the specified name. Ant tasks created in this project are
51
- # executed immediately.
33
+ # executable(name, options?) => AntProject
34
+ # executable(name, options?) { |AntProject| ... } => AntProject
52
35
  #
53
- # The options hash is passed to the Ant project definition, along with the current directory.
54
- # When used in a Buildr project, the Ant project will have the same base directory.
55
- # If you pass a block, yields to the block with the Ant project.
36
+ # Returns an executable AntProject with the specified name. Ant tasks created in this project
37
+ # are executed immediately.
56
38
  #
57
- # For example:
58
- # ant("hibernatedoclet") do |doclet|
59
- # doclet.taskdef :name=>"hibernatedoclet",
60
- # :classname=>"xdoclet.modules.hibernate.HibernateDocletTask", :classpath=>DOCLET
61
- # doclet.hibernatedoclet :destdir=>dest_dir, :force=>"true" do
62
- # hibernate :version=>"3.0"
63
- # fileset :dir=>source, :includes=>"**/*.java"
64
- # end
65
- # end
66
- def ant(name, options=nil, &block)
67
- Java::Ant.executable(name, options, &block)
39
+ # See #ant for more information about options and the block.
40
+ def executable(name, options = nil, &block)
41
+ options ||= {}
42
+ options = (options || {}).merge(:name=>name, :base_dir=>Dir.pwd, :declarative=>true)
43
+ Java.rjb { AntProject.new(options).tap { |project| yield project if block_given? } }
68
44
  end
45
+ end
69
46
 
47
+ # :call-seq:
48
+ # ant(name, options?) => AntProject
49
+ # ant(name, options?) { |AntProject| ... } => AntProject
50
+ #
51
+ # Returns a new AntProject with the specified name. Ant tasks created in this project are
52
+ # executed immediately.
53
+ #
54
+ # The options hash is passed to the Ant project definition, along with the current directory.
55
+ # When used in a Buildr project, the Ant project will have the same base directory.
56
+ # If you pass a block, yields to the block with the Ant project.
57
+ #
58
+ # For example:
59
+ # ant("hibernatedoclet") do |doclet|
60
+ # doclet.taskdef :name=>"hibernatedoclet",
61
+ # :classname=>"xdoclet.modules.hibernate.HibernateDocletTask", :classpath=>DOCLET
62
+ # doclet.hibernatedoclet :destdir=>dest_dir, :force=>"true" do
63
+ # hibernate :version=>"3.0"
64
+ # fileset :dir=>source, :includes=>"**/*.java"
65
+ # end
66
+ # end
67
+ def ant(name, options=nil, &block)
68
+ Ant.executable(name, options, &block)
70
69
  end
71
70
 
72
71
  end
73
72
 
74
73
  class Project
75
- include Java::Ant
74
+ include Ant
76
75
  end
77
76
 
78
77
  end
@@ -5,6 +5,7 @@ module Buildr
5
5
 
6
6
  desc "Download all artifacts"
7
7
  task "artifacts"
8
+ task "artifacts:refresh"
8
9
 
9
10
  # Mixin with a task to make it behave like an artifact. Implemented by the packaging tasks.
10
11
  #
@@ -69,7 +70,7 @@ module Buildr
69
70
  # Convenience method that returns a POM artifact.
70
71
  def pom()
71
72
  return self if type == :pom
72
- artifact(:group=>group, :id=>id, :version=>version, :type=>:pom, :classifier=>classifier)
73
+ Buildr.artifact(:group=>group, :id=>id, :version=>version, :type=>:pom, :classifier=>classifier)
73
74
  end
74
75
 
75
76
  protected
@@ -101,6 +102,30 @@ module Buildr
101
102
 
102
103
  class << self
103
104
 
105
+ # :call-seq:
106
+ # force_download() => boolean
107
+ # force_download(value) => value
108
+ # force.download(value) { ... }
109
+ #
110
+ # In the first form, returns the value of the force download flag. This flag is set
111
+ # to force downloading of artifacts, even if those artifacts already exist in the local
112
+ # repository. (Used by the artifacts task).
113
+ #
114
+ # In the second form sets the value of the force download flag. In the third form, sets
115
+ # the value of the flag, yields to the block, and resets the flag to its previous value.
116
+ def force_download(value = @force_download)
117
+ if block_given?
118
+ begin
119
+ old_value, @force_download = @force_download, value
120
+ yield
121
+ ensure
122
+ @force_download = old_value
123
+ end
124
+ else
125
+ @force_download = value
126
+ end
127
+ end
128
+
104
129
  # :call-seq:
105
130
  # lookup(spec) => Artifact
106
131
  #
@@ -190,14 +215,27 @@ module Buildr
190
215
  # (e.g. download from a different location), so don't perform it
191
216
  # if the task found a different way to create the artifact.
192
217
  # For that, we need to be the last piece of code run by the task.
193
- task.enhance do
194
- unless Rake.application.options.dryrun || File.exist?(name)
195
- repositories.download(to_spec)
218
+ if @actions.size == 1
219
+ task.enhance do
220
+ begin
221
+ puts "Downloading #{to_spec}" if verbose
222
+ Buildr.repositories.download(to_spec)
223
+ rescue Exception=>error
224
+ if File.exist?(name)
225
+ puts error
226
+ else
227
+ raise
228
+ end
229
+ end
196
230
  end
197
231
  end
198
232
  end
199
233
  end
200
234
 
235
+ def needed?()
236
+ Artifact.force_download || super
237
+ end
238
+
201
239
  end
202
240
 
203
241
 
@@ -310,12 +348,15 @@ module Buildr
310
348
  end
311
349
  end
312
350
  true
351
+ rescue Transports::NotFound
352
+ false
313
353
  rescue Exception=>error
314
- warn error if Rake.application.options.trace
354
+ puts error if verbose
355
+ puts error.backtrace.join("\n") if Rake.application.options.trace
315
356
  false
316
357
  end
317
358
  end
318
- fail "Failed to download #{Artifact.to_spec(spec)}, tried the following repositories:\n#{repositories.remote.join("\n")}"
359
+ fail "Failed to download #{Artifact.to_spec(spec)}, tried the following repositories:\n#{remote.join("\n")}"
319
360
  end
320
361
 
321
362
  # :call-seq:
@@ -356,7 +397,6 @@ module Buildr
356
397
 
357
398
  end
358
399
 
359
-
360
400
  # :call-seq:
361
401
  # repositories() => Repositories
362
402
  #
@@ -396,7 +436,8 @@ module Buildr
396
436
  unless task = Artifact.lookup(spec)
397
437
  task = Artifact.define_task(repositories.locate(spec))
398
438
  task.send :apply_spec, spec
399
- Rake::Task["rake:artifacts"].enhance [ task ]
439
+ Rake::Task["rake:artifacts"].enhance [task]
440
+ Rake::Task["rake:artifacts:refresh"].enhance { Artifact.force_download(true) { task.invoke } }
400
441
  Artifact.register(task)
401
442
  end
402
443
  task.enhance &block
@@ -440,7 +481,7 @@ module Buildr
440
481
  when Rake::Task
441
482
  set |= [spec]
442
483
  else
443
- fail "Invalid artifact specification in: #{specs.inspect}"
484
+ fail "Invalid artifact specification in: #{specs.to_s}"
444
485
  end
445
486
  end
446
487
  end