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 398
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
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 329
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 320
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 466
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 338
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 357
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
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 387
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 452
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 430
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 534
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 490
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
download_m2_snapshot(remote_uris) click to toggle source
# File lib/buildr/packaging/artifact.rb, line 518
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 553
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 478
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 563
def needed?
  return true if snapshot? && File.exist?(name) && (update_snapshot? || old?)
  super
end

Private Instance Methods

download_artifact click to toggle source

Downloads artifact from given repository, supports downloading snapshot artifact with relocation on succeed to local repository

# File lib/buildr/packaging/artifact.rb, line 575
def download_artifact(path)
  download_file = "#{name}.#{Time.new.to_i}"
  begin
    URI.download path, download_file
    if File.exist?(download_file)
      FileUtils.mkdir_p(File.dirname(name))
      FileUtils.mv(download_file, name)
    end
  ensure
    File.delete(download_file) if File.exist?(download_file)
  end
end
:download_needed? click to toggle source

Validates whether artifact is required to be downloaded from repository

# File lib/buildr/packaging/artifact.rb, line 592
def download_needed?(task)
  return true if !File.exist?(name)

  if snapshot?
    return false if offline? && File.exist?(name)
    return true if update_snapshot? || old?
  end

  return false
end
offline?() click to toggle source
# File lib/buildr/packaging/artifact.rb, line 607
def offline?
  Buildr.application.options.work_offline
end
old? click to toggle source

Checks whether existing artifact is older than period from build settings or one day

# File lib/buildr/packaging/artifact.rb, line 615
def old?
  settings = Buildr.application.settings
  time_to_be_old = settings.user[:expire_time] || settings.build[:expire_time] || 60 * 60 * 24
  File.mtime(name).to_i < (Time.new.to_i - time_to_be_old)
end
update_snapshot?() click to toggle source
# File lib/buildr/packaging/artifact.rb, line 603
def update_snapshot?
  Buildr.application.options.update_snapshots
end