C0 code coverage information
Generated on Wed Oct 07 08:34:04 -0700 2009 with rcov 0.8.2.1
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with this
3 # work for additional information regarding copyright ownership. The ASF
4 # licenses this file to you under the Apache License, Version 2.0 (the
5 # "License"); you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations under
14 # the License.
15
16
17 require 'buildr/core/project'
18 require 'buildr/core/transports'
19 require 'buildr/packaging/artifact_namespace'
20
21
22 module Buildr
23
24 desc 'Download all artifacts'
25 task 'artifacts'
26
27 desc "Download all artifacts' sources"
28 task 'artifacts:sources'
29
30 # Mixin with a task to make it behave like an artifact. Implemented by the packaging tasks.
31 #
32 # An artifact has an identifier, group identifier, type, version number and
33 # optional classifier. All can be used to locate it in the local repository,
34 # download from or upload to a remote repository.
35 #
36 # The #to_spec and #to_hash methods allow it to be used everywhere an artifact is
37 # accepted.
38 module ActsAsArtifact
39
40 ARTIFACT_ATTRIBUTES = [:group, :id, :type, :classifier, :version]
41
42 class << self
43 private
44 def included(mod)
45 mod.extend self
46 end
47 end
48
49 # The artifact identifier.
50 attr_reader :id
51 # The group identifier.
52 attr_reader :group
53 # The file type. (Symbol)
54 attr_reader :type
55 # The version number.
56 attr_reader :version
57 # Optional artifact classifier.
58 attr_reader :classifier
59
60 def snapshot?
61 version =~ /-SNAPSHOT$/
62 end
63
64 # :call-seq:
65 # to_spec_hash => Hash
66 #
67 # Returns the artifact specification as a hash. For example:
68 # com.example:app:jar:1.2
69 # becomes:
70 # { :group=>'com.example',
71 # :id=>'app',
72 # :type=>:jar,
73 # :version=>'1.2' }
74 def to_spec_hash
75 base = { :group=>group, :id=>id, :type=>type, :version=>version }
76 classifier ? base.merge(:classifier=>classifier) : base
77 end
78 alias_method :to_hash, :to_spec_hash
79
80 # :call-seq:
81 # to_spec => String
82 #
83 # Returns the artifact specification, in the structure:
84 # <group>:<artifact>:<type>:<version>
85 # or
86 # <group>:<artifact>:<type>:<classifier>:<version>
87 def to_spec
88 classifier ? "#{group}:#{id}:#{type}:#{classifier}:#{version}" : "#{group}:#{id}:#{type}:#{version}"
89 end
90
91 # :call-seq:
92 # pom => Artifact
93 #
94 # Convenience method that returns a POM artifact.
95 def pom
96 return self if type == :pom
97 Buildr.artifact(:group=>group, :id=>id, :version=>version, :type=>:pom)
98 end
99
100 # :call-seq:
101 # sources_artifact => Artifact
102 #
103 # Convenience method that returns a sources artifact.
104 def sources_artifact
105 sources_spec = to_spec_hash.merge(:classifier=>'sources')
106 sources_task = OptionalArtifact.define_task(Buildr.repositories.locate(sources_spec))
107 sources_task.send :apply_spec, sources_spec
108 sources_task
109 end
110
111 # :call-seq:
112 # pom_xml => string
113 #
114 # Creates POM XML for this artifact.
115 def pom_xml
116 xml = Builder::XmlMarkup.new(:indent=>2)
117 xml.instruct!
118 xml.project do
119 xml.modelVersion '4.0.0'
120 xml.groupId group
121 xml.artifactId id
122 xml.version version
123 xml.classifier classifier if classifier
124 end
125 end
126
127 def install
128 pom.install if pom && pom != self
129 invoke
130 installed = Buildr.repositories.locate(self)
131 unless installed == name # If not already in local repository.
132 mkpath File.dirname(installed)
133 cp name, installed
134 info "Installed #{installed}"
135 end
136 end
137
138 def uninstall
139 installed = Buildr.repositories.locate(self)
140 rm installed if File.exist?(installed)
141 pom.uninstall if pom && pom != self
142 end
143
144 # :call-seq:
145 # upload
146 # upload(url)
147 # upload(options)
148 #
149 # Uploads the artifact, its POM and digital signatures to remote server.
150 #
151 # In the first form, uses the upload options specified by repositories.release_to.
152 # In the second form, uses a URL that includes all the relevant information.
153 # In the third form, uses a hash with the options :url, :username, :password,
154 # and :permissions. All but :url are optional.
155 def upload(upload_to = nil)
156 # Where do we release to?
157 upload_to ||= Buildr.repositories.release_to
158 upload_to = { :url=>upload_to } unless Hash === upload_to
159 raise ArgumentError, 'Don\'t know where to upload, perhaps you forgot to set repositories.release_to' unless upload_to[:url]
160 invoke # Make sure we exist.
161
162 # Upload POM ahead of package, so we don't fail and find POM-less package (the horror!)
163 pom.upload(upload_to) if pom && pom != self
164
165 # Set the upload URI, including mandatory slash (we expect it to be the base directory).
166 # Username/password may be part of URI, or separate entities.
167 uri = URI.parse(upload_to[:url].clone)
168 uri.path = uri.path + '/' unless uri.path[-1] == '/'
169 uri.user = upload_to[:username] if upload_to[:username]
170 uri.password = upload_to[:password] if upload_to[:password]
171
172 # Upload artifact relative to base URL, need to create path before uploading.
173 info "Deploying #{to_spec}"
174 path = group.gsub('.', '/') + "/#{id}/#{version}/#{File.basename(name)}"
175 URI.upload uri + path, name, :permissions=>upload_to[:permissions]
176 end
177
178 protected
179
180 # Apply specification to this artifact.
181 def apply_spec(spec)
182 spec = Artifact.to_hash(spec)
183 ARTIFACT_ATTRIBUTES.each { |key| instance_variable_set("@#{key}", spec[key]) }
184 self
185 end
186
187 def group_path
188 group.gsub('.', '/')
189 end
190
191 end
192
193
194 # A file task referencing an artifact in the local repository.
195 #
196 # This task includes all the artifact attributes (group, id, version, etc). It points
197 # to the artifact's path in the local repository. When invoked, it will download the
198 # artifact into the local repository if the artifact does not already exist.
199 #
200 # Note: You can enhance this task to create the artifact yourself, e.g. download it from
201 # a site that doesn't have a remote repository structure, copy it from a different disk, etc.
202 class Artifact < Rake::FileCreationTask
203
204 # The default artifact type.
205 DEFAULT_TYPE = :jar
206
207 include ActsAsArtifact
208
209 class << self
210
211 # :call-seq:
212 # lookup(spec) => Artifact
213 #
214 # Lookup a previously registered artifact task based on its specification (String or Hash).
215 def lookup(spec)
216 @artifacts ||= {}
217 @artifacts[to_spec(spec)]
218 end
219
220 # :call-seq:
221 # list => specs
222 #
223 # Returns an array of specs for all the registered artifacts. (Anything created from artifact, or package).
224 def list
225 @artifacts ||= {}
226 @artifacts.keys
227 end
228
229 # :call-seq:
230 # register(artifacts) => artifacts
231 #
232 # Register an artifact task(s) for later lookup (see #lookup).
233 def register(*tasks)
234 @artifacts ||= {}
235 fail 'You can only register an artifact task, one of the arguments is not a Task that responds to to_spec' unless
236 tasks.all? { |task| task.respond_to?(:to_spec) && task.respond_to?(:invoke) }
237 tasks.each { |task| @artifacts[task.to_spec] = task }
238 tasks
239 end
240
241 # :call-seq:
242 # to_hash(spec_hash) => spec_hash
243 # to_hash(spec_string) => spec_hash
244 # to_hash(artifact) => spec_hash
245 #
246 # Turn a spec into a hash. This method accepts a String, Hash or any object that responds to
247 # the method to_spec. There are several reasons to use this method:
248 # * You can pass anything that could possibly be a spec, and get a hash.
249 # * It will check that the spec includes the group identifier, artifact
250 # identifier and version number and set the file type, if missing.
251 # * It will always return a new specs hash.
252 def to_hash(spec)
253 if spec.respond_to?(:to_spec)
254 to_hash spec.to_spec
255 elsif Hash === spec
256 rake_check_options spec, :id, :group, :type, :classifier, :version
257 # Sanitize the hash and check it's valid.
258 spec = ARTIFACT_ATTRIBUTES.inject({}) { |h, k| h[k] = spec[k].to_s if spec[k] ; h }
259 fail "Missing group identifier for #{spec.inspect}" unless spec[:group]
260 fail "Missing artifact identifier for #{spec.inspect}" unless spec[:id]
261 fail "Missing version for #{spec.inspect}" unless spec[:version]
262 spec[:type] = (spec[:type] || DEFAULT_TYPE).to_sym
263 spec
264 elsif String === spec
265 group, id, type, version, *rest = spec.split(':').map { |part| part.empty? ? nil : part }
266 unless rest.empty?
267 # Optional classifier comes before version.
268 classifier, version = version, rest.shift
269 fail "Expecting <group:id:type:version> or <group:id:type:classifier:version>, found <#{spec}>" unless rest.empty?
270 end
271 to_hash :group=>group, :id=>id, :type=>type, :version=>version, :classifier=>classifier
272 else
273 fail 'Expecting a String, Hash or object that responds to to_spec'
274 end
275 end
276
277 # :call-seq:
278 # to_spec(spec_hash) => spec_string
279 #
280 # Convert a hash back to a spec string. This method accepts
281 # a string, hash or any object that responds to to_spec.
282 def to_spec(hash)
283 hash = to_hash(hash) unless Hash === hash
284 version = ":#{hash[:version]}" if hash[:version]
285 classifier = ":#{hash[:classifier]}" if hash[:classifier]
286 "#{hash[:group]}:#{hash[:id]}:#{hash[:type] || DEFAULT_TYPE}#{classifier}#{version}"
287 end
288
289 # :call-seq:
290 # hash_to_file_name(spec_hash) => file_name
291 #
292 # Convert a hash spec to a file name.
293 def hash_to_file_name(hash)
294 version = "-#{hash[:version]}" if hash[:version]
295 classifier = "-#{hash[:classifier]}" if hash[:classifier]
296 "#{hash[:id]}#{version}#{classifier}.#{hash[:type] || DEFAULT_TYPE}"
297 end
298
299 end
300
301 def initialize(*args) #:nodoc:
302 super
303 enhance do |task|
304 # Default behavior: download the artifact from one of the remote repositories
305 # if the file does not exist. But this default behavior is counter productive
306 # if the artifact knows how to build itself (e.g. download from a different location),
307 # so don't perform it if the task found a different way to create the artifact.
308 task.enhance do
309 unless File.exist?(name)
310 info "Downloading #{to_spec}"
311 download
312 pom.invoke rescue nil if pom && pom != self
313 end
314 end
315 end
316 end
317
318 # :call-seq:
319 # from(path) => self
320 #
321 # Use this when you want to install or upload an artifact from a given file, for example:
322 # test = artifact('group:id:jar:1.0').from('test.jar')
323 # install test
324 # See also Buildr#install and Buildr#upload.
325 def from(path)
326 path = File.expand_path(path.to_s)
327 enhance [path] do
328 mkpath File.dirname(name)
329 pom.invoke unless type == :pom
330 cp path, name
331 info "Installed #{path} as #{to_spec}"
332 end
333 unless type == :pom
334 pom.enhance do
335 mkpath File.dirname(pom.name)
336 File.open(pom.name, 'w') { |file| file.write pom.pom_xml }
337 end
338 end
339 self
340 end
341
342 protected
343
344 # :call-seq:
345 # download
346 #
347 # Downloads an artifact from one of the remote repositories, and stores it in the local
348 # repository. Raises an exception if the artifact is not found.
349 #
350 # This method attempts to download the artifact from each repository in the order in
351 # which they are returned from #remote, until successful.
352 def download
353 trace "Downloading #{to_spec}"
354 remote = Buildr.repositories.remote.map { |repo_url| URI === repo_url ? repo_url : URI.parse(repo_url) }
355 remote = remote.each { |repo_url| repo_url.path += '/' unless repo_url.path[-1] == '/' }
356 fail 'No remote repositories defined!' if remote.empty?
357 exact_success = remote.find do |repo_url|
358 begin
359 path = "#{group_path}/#{id}/#{version}/#{File.basename(name)}"
360 URI.download repo_url + path, name
361 true
362 rescue URI::NotFoundError
363 false
364 rescue Exception=>error
365 info error
366 trace error.backtrace.join("\n")
367 false
368 end
369 end
370
371 if exact_success
372 return
373 elsif snapshot?
374 download_m2_snapshot(remote)
375 else
376 fail_download(remote)
377 end
378 end
379
380 def download_m2_snapshot(remote_uris)
381 remote_uris.find do |repo_url|
382 snapshot_url = current_snapshot_repo_url(repo_url)
383 if snapshot_url
384 begin
385 URI.download snapshot_url, name
386 rescue URI::NotFoundError
387 false
388 end
389 else
390 false
391 end
392 end or fail_download(remote_uris)
393 end
394
395 def current_snapshot_repo_url(repo_url)
396 begin
397 metadata_path = "#{group_path}/#{id}/#{version}/maven-metadata.xml"
398 metadata_xml = StringIO.new
399 URI.download repo_url + metadata_path, metadata_xml
400 metadata = REXML::Document.new(metadata_xml.string).root
401 timestamp = REXML::XPath.first(metadata, '//timestamp').text
402 build_number = REXML::XPath.first(metadata, '//buildNumber').text
403 snapshot_of = version[0, version.size - 9]
404 repo_url + "#{group_path}/#{id}/#{version}/#{id}-#{snapshot_of}-#{timestamp}-#{build_number}.#{type}"
405 rescue URI::NotFoundError
406 nil
407 end
408 end
409
410 def fail_download(remote_uris)
411 fail "Failed to download #{to_spec}, tried the following repositories:\n#{remote_uris.join("\n")}"
412 end
413 end
414
415
416 # An artifact that is optional.
417 # If downloading fails, the user will be informed but it will not raise an exception.
418 class OptionalArtifact < Artifact
419
420 protected
421
422 # If downloading fails, the user will be informed but it will not raise an exception.
423 def download
424 super
425 rescue
426 info "Failed to download #{to_spec}. Skipping it."
427 end
428
429 end
430
431
432 # Holds the path to the local repository, URLs for remote repositories, and settings for release server.
433 #
434 # You can access this object from the #repositories method. For example:
435 # puts repositories.local
436 # repositories.remote << 'http://example.com/repo'
437 # repositories.release_to = 'sftp://example.com/var/www/public/repo'
438 class Repositories
439 include Singleton
440
441 # :call-seq:
442 # local => path
443 #
444 # Returns the path to the local repository.
445 #
446 # The default path is .m2/repository relative to the home directory.
447 # You can set this using the M2_REPO environment variable or the repositories/local
448 # value in your settings.yaml file.
449 def local
450 @local ||= File.expand_path(ENV['M2_REPO'] || ENV['local_repo'] ||
451 (Buildr.settings.user['repositories'] && Buildr.settings.user['repositories']['local']) ||
452 File.join(ENV['HOME'], '.m2/repository'))
453 end
454
455 # :call-seq:
456 # local = path
457 #
458 # Sets the path to the local repository.
459 #
460 # The best place to set the local repository path is from a buildr.rb file
461 # located in your home directory. That way all your projects will share the same
462 # path, without affecting other developers collaborating on these projects.
463 def local=(dir)
464 @local = dir ? File.expand_path(dir) : nil
465 end
466
467 # :call-seq:
468 # locate(spec) => path
469 #
470 # Locates an artifact in the local repository based on its specification, and returns
471 # a file path.
472 #
473 # For example:
474 # locate :group=>'log4j', :id=>'log4j', :version=>'1.1'
475 # => ~/.m2/repository/log4j/log4j/1.1/log4j-1.1.jar
476 def locate(spec)
477 spec = Artifact.to_hash(spec)
478 File.join(local, spec[:group].split('.'), spec[:id], spec[:version], Artifact.hash_to_file_name(spec))
479 end
480
481 # :call-seq:
482 # remote => Array
483 #
484 # Returns an array of all the remote repository URLs.
485 #
486 # When downloading artifacts, repositories are accessed in the order in which they appear here.
487 # The best way is to add repositories individually, for example:
488 # repositories.remote << 'http://example.com/repo'
489 #
490 # You can also specify remote repositories in the settings.yaml (per user) and build.yaml (per build)
491 # files. Both sets of URLs are loaded by default into this array, URLs from the personal setting
492 # showing first.
493 #
494 # For example:
495 # repositories:
496 # remote:
497 # - http://example.com/repo
498 # - http://elsewhere.com/repo
499 def remote
500 unless @remote
501 @remote = [Buildr.settings.user, Buildr.settings.build].inject([]) { |repos, hash|
502 repos | Array(hash['repositories'] && hash['repositories']['remote'])
503 }
504 end
505 @remote
506 end
507
508 # :call-seq:
509 # remote = Array
510 # remote = url
511 # remote = nil
512 #
513 # With a String argument, clears the array and set it to that single URL.
514 #
515 # With an Array argument, clears the array and set it to these specific URLs.
516 #
517 # With nil, clears the array.
518 def remote=(urls)
519 case urls
520 when nil then @remote = nil
521 when Array then @remote = urls.dup
522 else @remote = [urls.to_s]
523 end
524 end
525
526 # :call-seq:
527 # release_to = url
528 # release_to = hash
529 #
530 # Specifies the release server. Accepts a Hash with different repository settings
531 # (e.g. url, username, password), or a String to only set the repository URL.
532 #
533 # Besides the URL, all other settings depend on the transport protocol in use.
534 #
535 # For example:
536 # repositories.release_to = 'sftp://john:secret@example.com/var/www/repo/'
537 #
538 # repositories.release_to = { :url=>'sftp://example.com/var/www/repo/',
539 # :username='john', :password=>'secret' }
540 # Or in the settings.yaml file:
541 # repositories:
542 # release_to: sftp://john:secret@example.com/var/www/repo/
543 #
544 # repositories:
545 # release_to:
546 # url: sftp://example.com/var/www/repo/
547 # username: john
548 # password: secret
549 def release_to=(options)
550 options = { :url=>options } unless Hash === options
551 @release_to = options
552 end
553
554 # :call-seq:
555 # release_to => hash
556 #
557 # Returns the current release server setting as a Hash. This is a more convenient way to
558 # configure the settings, as it allows you to specify the settings progressively.
559 #
560 # For example, the Buildfile will contain the repository URL used by all developers:
561 # repositories.release_to[:url] ||= 'sftp://example.com/var/www/repo'
562 # Your private buildr.rb will contain your credentials:
563 # repositories.release_to[:username] = 'john'
564 # repositories.release_to[:password] = 'secret'
565 def release_to
566 unless @release_to
567 value = Buildr.settings.user['repositories'] && Buildr.settings.user['repositories']['release_to']
568 @release_to = Hash === value ? value.inject({}) { |hash, (key, value)| hash.update(key.to_sym=>value) } : { :url=>Array(value).first }
569 end
570 @release_to
571 end
572
573 end
574
575 # :call-seq:
576 # repositories => Repositories
577 #
578 # Returns an object you can use for setting the local repository path, remote repositories
579 # URL and release server settings.
580 #
581 # See Repositories.
582 def repositories
583 Repositories.instance
584 end
585
586 # :call-seq:
587 # artifact(spec) => Artifact
588 # artifact(spec) { |task| ... } => Artifact
589 #
590 # Creates a file task to download and install the specified artifact in the local repository.
591 #
592 # You can use a String or a Hash for the artifact specification. The file task will point at
593 # the artifact's path inside the local repository. You can then use this tasks as a prerequisite
594 # for other tasks.
595 #
596 # This task will download and install the artifact only once. In fact, it will download and
597 # install the artifact if the artifact does not already exist. You can enhance it if you have
598 # a different way of creating the artifact in the local repository. See Artifact for more details.
599 #
600 # For example, to specify an artifact:
601 # artifact('log4j:log4j:jar:1.1')
602 #
603 # To use the artifact in a task:
604 # compile.with artifact('log4j:log4j:jar:1.1')
605 #
606 # To specify an artifact and the means for creating it:
607 # download(artifact('dojo:dojo-widget:zip:2.0')=>
608 # 'http://download.dojotoolkit.org/release-2.0/dojo-2.0-widget.zip')
609 def artifact(spec, &block) #:yields:task
610 spec = artifact_ns.fetch(spec) if spec.kind_of?(Symbol)
611 spec = Artifact.to_hash(spec)
612 unless task = Artifact.lookup(spec)
613 task = Artifact.define_task(repositories.locate(spec))
614 task.send :apply_spec, spec
615 Rake::Task['rake:artifacts'].enhance [task]
616 Artifact.register(task)
617 Rake::Task['artifacts:sources'].enhance [task.sources_artifact] unless spec[:type] == :pom
618 end
619 task.enhance &block
620 end
621
622 # :call-seq:
623 # artifacts(*spec) => artifacts
624 #
625 # Handles multiple artifacts at a time. This method is the plural equivalent of
626 # #artifact, but can do more things.
627 #
628 # Returns an array of artifacts built using the supplied
629 # specifications, each of which can be:
630 # * An artifact specification (String or Hash). Returns the appropriate Artifact task.
631 # * An artifact of any other task. Returns the task as is.
632 # * A project. Returns all artifacts created (packaged) by that project.
633 # * A string. Returns that string, assumed to be a file name.
634 # * An array of artifacts or a Struct.
635 # * A symbol. Returns the named artifact from the current ArtifactNamespace
636 #
637 # For example, handling a collection of artifacts:
638 # xml = [ xerces, xalan, jaxp ]
639 # ws = [ axis, jax-ws, jaxb ]
640 # db = [ jpa, mysql, sqltools ]
641 # artifacts(xml, ws, db)
642 #
643 # Using artifacts created by a project:
644 # artifacts project('my-app') # All packages
645 # artifacts project('my-app').package(:war) # Only the WAR
646 def artifacts(*specs, &block)
647 specs.flatten.inject([]) do |set, spec|
648 case spec
649 when ArtifactNamespace
650 set |= spec.artifacts
651 when Symbol, Hash
652 set |= [artifact(spec)]
653 when /([^:]+:){2,4}/ # A spec as opposed to a file name.
654 set |= [artifact(spec)]
655 when String # Must always expand path.
656 set |= [File.expand_path(spec)]
657 when Project
658 set |= artifacts(spec.packages)
659 when Rake::Task
660 set |= [spec]
661 when Struct
662 set |= artifacts(spec.values)
663 else
664 fail "Invalid artifact specification in #{specs.inspect}"
665 end
666 end
667 end
668
669 def transitive(*specs)
670 specs.flatten.inject([]) do |set, spec|
671 case spec
672 when /([^:]+:){2,4}/ # A spec as opposed to a file name.
673 artifact = artifact(spec)
674 set |= [artifact] unless artifact.type == :pom
675 set |= POM.load(artifact.pom).dependencies.map { |spec| artifact(spec) }
676 when Hash
677 set |= [transitive(spec)]
678 when String # Must always expand path.
679 set |= transitive(file(File.expand_path(spec)))
680 when Project
681 set |= transitive(spec.packages)
682 when Rake::Task
683 set |= spec.respond_to?(:to_spec) ? transitive(spec.to_spec) : [spec]
684 when Struct
685 set |= transitive(spec.values)
686 else
687 fail "Invalid artifact specification in: #{specs.to_s}"
688 end
689 end
690 end
691
692 # :call-seq:
693 # group(ids, :under=>group_name, :version=>number) => artifacts
694 #
695 # Convenience method for defining multiple artifacts that belong to the same group, type and version.
696 # Accepts multiple artifact identifiers followed by two or three hash values:
697 # * :under -- The group identifier
698 # * :version -- The version number
699 # * :type -- The artifact type (optional)
700 #
701 # For example:
702 # group 'xbean', 'xbean_xpath', 'xmlpublic', :under=>'xmlbeans', :version=>'2.1.0'
703 # Or:
704 # group %w{xbean xbean_xpath xmlpublic}, :under=>'xmlbeans', :version=>'2.1.0'
705 def group(*args)
706 hash = args.pop
707 args.flatten.map { |id| artifact :group=>hash[:under], :type=>hash[:type], :version=>hash[:version], :id=>id }
708 end
709
710 # :call-seq:
711 # install(artifacts)
712 #
713 # Installs the specified artifacts in the local repository as part of the install task.
714 #
715 # You can use this to install various files in the local repository, for example:
716 # install artifact('group:id:jar:1.0').from('some_jar.jar')
717 # $ buildr install
718 def install(*args, &block)
719 artifacts = artifacts(args)
720 raise ArgumentError, 'This method can only install artifacts' unless artifacts.all? { |f| f.respond_to?(:to_spec) }
721 all = (artifacts + artifacts.map { |artifact| artifact.pom }).uniq
722 task('install').tap do |task|
723 task.enhance all, &block
724 task 'uninstall' do
725 all.map(&:to_s ).each { |file| rm file if File.exist?(file) }
726 end
727 end
728 end
729
730 # :call-seq:
731 # upload(artifacts)
732 #
733 # Uploads the specified artifacts to the release server as part of the upload task.
734 #
735 # You can use this to upload various files to the release server, for example:
736 # upload artifact('group:id:jar:1.0').from('some_jar.jar')
737 # $ buildr upload
738 def upload(*args, &block)
739 artifacts = artifacts(args)
740 raise ArgumentError, 'This method can only upload artifacts' unless artifacts.all? { |f| f.respond_to?(:to_spec) }
741 task('upload').tap do |task|
742 task.enhance &block if block
743 task.enhance artifacts do
744 artifacts.each { |artifact| artifact.upload }
745 end
746 end
747 end
748
749 end
Generated using the rcov code coverage analysis tool for Ruby
version 0.8.2.1.