class Buildr::Artifact
A file task referencing an artifact in the local repository.
This task includes all the artifact attributes (group, id, version, etc). It points to the artifact's path in the local repository. When invoked, it will download the artifact into the local repository if the artifact does not already exist.
Note: You can enhance this task to create the artifact yourself, e.g. download it from a site that doesn't have a remote repository structure, copy it from a different disk, etc.
Constants
- DEFAULT_TYPE
The default artifact type.
Public Class Methods
Convert a hash spec to a file name.
# File lib/buildr/packaging/artifact.rb, line 382 def hash_to_file_name(hash) version = "-#{hash[:version]}" if hash[:version] classifier = "-#{hash[:classifier]}" if hash[:classifier] "#{hash[:id]}#{version}#{classifier}.#{extract_type(hash[:type]) || DEFAULT_TYPE}" end
Returns an array of specs for all the registered artifacts. (Anything created from artifact, or package).
# File lib/buildr/packaging/artifact.rb, line 313 def list @artifacts ||= {} @artifacts.keys end
Lookup a previously registered artifact task based on its specification (String or Hash).
# File lib/buildr/packaging/artifact.rb, line 304 def lookup(spec) @artifacts ||= {} @artifacts[to_spec(spec)] end
Force overwriting target since we don't have source file to check for timestamp modification
# File lib/buildr/packaging/artifact.rb, line 450 def needed? true end
Register an artifact task(s) for later lookup (see lookup).
# File lib/buildr/packaging/artifact.rb, line 322 def register(*tasks) @artifacts ||= {} fail 'You can only register an artifact task, one of the arguments is not a Task that responds to to_spec' unless tasks.all? { |task| task.respond_to?(:to_spec) && task.respond_to?(:invoke) } tasks.each { |task| @artifacts[task.to_spec] = task } tasks end
Turn a spec into a hash. This method accepts a String, Hash or any object that responds to the method to_spec. There are several reasons to use this method:
-
You can pass anything that could possibly be a spec, and get a hash.
-
It will check that the spec includes the group identifier, artifact identifier and version number and set the file type, if missing.
-
It will always return a new specs hash.
# File lib/buildr/packaging/artifact.rb, line 341 def to_hash(spec) if spec.respond_to?(:to_spec) to_hash spec.to_spec elsif Hash === spec rake_check_options spec, :id, :group, :type, :classifier, :version, :scope # Sanitize the hash and check it's valid. spec = ARTIFACT_ATTRIBUTES.inject({}) { |h, k| h[k] = spec[k].to_s if spec[k] ; h } fail "Missing group identifier for #{spec.inspect}" unless spec[:group] fail "Missing artifact identifier for #{spec.inspect}" unless spec[:id] fail "Missing version for #{spec.inspect}" unless spec[:version] spec[:type] = (spec[:type] || DEFAULT_TYPE).to_sym spec elsif String === spec group, id, type, version, *rest = spec.split(':').map { |part| part.empty? ? nil : part } unless rest.empty? # Optional classifier comes before version. classifier, version = version, rest.shift fail "Expecting <group:id:type:version> or <group:id:type:classifier:version>, found <#{spec}>" unless rest.empty? end to_hash :group=>group, :id=>id, :type=>type, :version=>version, :classifier=>classifier else fail 'Expecting a String, Hash or object that responds to to_spec' end end
Convert a hash back to a spec string. This method accepts a string, hash or any object that responds to to_spec.
# File lib/buildr/packaging/artifact.rb, line 371 def to_spec(hash) hash = to_hash(hash) unless Hash === hash version = ":#{hash[:version]}" if hash[:version] classifier = ":#{hash[:classifier]}" if hash[:classifier] "#{hash[:group]}:#{hash[:id]}:#{hash[:type] || DEFAULT_TYPE}#{classifier}#{version}" end
Public Instance Methods
Use this when you want to install or upload an artifact from a given content, for example:
readme = artifact('com.example:readme:txt:1.0').content(<<-EOF Please visit our website at http://example.com/readme <<EOF install readme
If the argument is a Proc the it will be called when the artifact is written out. If the result is not a proc and not a string, it will be converted to a string using to_s
# File lib/buildr/packaging/artifact.rb, line 436 def content(string = nil) unless string @content = @content.call if @content.is_a?(Proc) return @content end unless @content enhance do write name, self.content end class << self # Force overwriting target since we don't have source file # to check for timestamp modification def needed? true end end end @content = string pom.content pom_xml unless pom == self || pom.has_content? self end
Use this when you want to install or upload an artifact from a given file, for example:
test = artifact('group:id:jar:1.0').from('test.jar') install test
See also Buildr#install and Buildr#upload.
# File lib/buildr/packaging/artifact.rb, line 414 def from(path) @from = path.is_a?(Rake::Task) ? path : File.expand_path(path.to_s) enhance [@from] do mkpath File.dirname(name) cp @from.to_s, name end pom.content pom_xml unless pom == self || pom.has_content? self end
Protected Instance Methods
# File lib/buildr/packaging/artifact.rb, line 518 def current_snapshot_repo_url(repo_url) begin metadata_path = "#{group_path}/#{id}/#{version}/maven-metadata.xml" metadata_xml = StringIO.new URI.download repo_url + metadata_path, metadata_xml metadata = REXML::Document.new(metadata_xml.string).root timestamp = REXML::XPath.first(metadata, '//timestamp') build_number = REXML::XPath.first(metadata, '//buildNumber') error "No timestamp provided for the snapshot #{to_spec}" if timestamp.nil? error "No build number provided for the snapshot #{to_spec}" if build_number.nil? return nil if timestamp.nil? || build_number.nil? snapshot_of = version[0, version.size - 9] classifier_snippet = (classifier != nil) ? "-#{classifier}" : "" repo_url + "#{group_path}/#{id}/#{version}/#{id}-#{snapshot_of}-#{timestamp.text}-#{build_number.text}#{classifier_snippet}.#{type}" rescue URI::NotFoundError nil end end
Downloads an artifact from one of the remote repositories, and stores it in the local repository. Raises an exception if the artifact is not found.
This method attempts to download the artifact from each repository in the order in which they are returned from remote, until successful.
# File lib/buildr/packaging/artifact.rb, line 474 def download trace "Downloading #{to_spec}" remote = Buildr.repositories.remote_uri remote = remote.each { |repo_url| repo_url.path += '/' unless repo_url.path[-1] == '/' } fail "Unable to download #{to_spec}. No remote repositories defined." if remote.empty? exact_success = remote.find do |repo_url| begin path = "#{group_path}/#{id}/#{version}/#{File.basename(name)}" download_artifact(repo_url + path) true rescue URI::NotFoundError false rescue Exception=>error info error trace error.backtrace.join("\n") false end end if exact_success return elsif snapshot? download_m2_snapshot(remote) else fail_download(remote) end end
# File lib/buildr/packaging/artifact.rb, line 502 def download_m2_snapshot(remote_uris) remote_uris.find do |repo_url| snapshot_url = current_snapshot_repo_url(repo_url) if snapshot_url begin download_artifact snapshot_url true rescue URI::NotFoundError false end else false end end or fail_download(remote_uris) end
# File lib/buildr/packaging/artifact.rb, line 537 def fail_download(remote_uris) fail "Failed to download #{to_spec}, tried the following repositories:\n#{remote_uris.join("\n")}" end
# File lib/buildr/packaging/artifact.rb, line 462 def has_content? @from || @content end
Validates whether artifact is required to be downloaded from repository
# File lib/buildr/packaging/artifact.rb, line 547 def needed? return true if snapshot? && File.exist?(name) && (update_snapshot? || old?) super end