buildr 0.21.0 → 0.22.0

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.
@@ -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