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

hash_to_file_name(spec_hash) → file_name click to toggle source

Convert a hash spec to a file name.

# File lib/buildr/packaging/artifact.rb, line 333
def hash_to_file_name(hash)
  version = "-#{hash[:version]}" if hash[:version]
  classifier = "-#{hash[:classifier]}" if hash[:classifier]
  "#{hash[:id]}#{version}#{classifier}.#{hash[:type] || DEFAULT_TYPE}"
end
list → specs click to toggle source

Returns an array of specs for all the registered artifacts. (Anything created from artifact, or package).

# File lib/buildr/packaging/artifact.rb, line 264
def list
  @artifacts ||= {}
  @artifacts.keys
end
lookup(spec) → Artifact click to toggle source

Lookup a previously registered artifact task based on its specification (String or Hash).

# File lib/buildr/packaging/artifact.rb, line 255
def lookup(spec)
  @artifacts ||= {}
  @artifacts[to_spec(spec)]
end
needed?() click to toggle source

Force overwriting target since we don’t have source file to check for timestamp modification

# File lib/buildr/packaging/artifact.rb, line 401
def needed?
  true
end
register(artifacts) → artifacts click to toggle source

Register an artifact task(s) for later lookup (see lookup).

# File lib/buildr/packaging/artifact.rb, line 273
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
to_hash(spec_hash) → spec_hash click to toggle source
to_hash(spec_string) → spec_hash
to_hash(artifact) → spec_hash

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 292
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
    # 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
to_spec(spec_hash) → spec_string click to toggle source

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 322
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

content(string) → self click to toggle source
content(Proc) → self

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 387
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
from(path) → self click to toggle source

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 365
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

current_snapshot_repo_url(repo_url) click to toggle source
# File lib/buildr/packaging/artifact.rb, line 469
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
download click to toggle source

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 425
def download
  trace "Downloading #{to_spec}"
  remote = Buildr.repositories.remote.map { |repo_url| URI === repo_url ? repo_url : URI.parse(repo_url) }
  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
download_m2_snapshot(remote_uris) click to toggle source
# File lib/buildr/packaging/artifact.rb, line 453
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
fail_download(remote_uris) click to toggle source
# File lib/buildr/packaging/artifact.rb, line 488
def fail_download(remote_uris)
  fail "Failed to download #{to_spec}, tried the following repositories:\n#{remote_uris.join("\n")}"
end
has_content?() click to toggle source
# File lib/buildr/packaging/artifact.rb, line 413
def has_content?
  @from || @content
end
needed? click to toggle source

Validates whether artifact is required to be downloaded from repository

Calls superclass method
# File lib/buildr/packaging/artifact.rb, line 498
def needed?
  return true if snapshot? && File.exist?(name) && (update_snapshot? || old?)
  super
end