lib/java/artifact.rb in buildr-1.1.3 vs lib/java/artifact.rb in buildr-1.2.0

- old
+ new

@@ -1,7 +1,8 @@ require "core/project" require "core/transports" +require "builder" module Buildr desc "Download all artifacts" task "artifacts" @@ -71,10 +72,56 @@ def pom() return self if type == :pom Buildr.artifact(:group=>group, :id=>id, :version=>version, :type=>:pom, :classifier=>classifier) end + # :call-seq: + # pom_xml() => string + # + # Creates POM XML for this artifact. + def pom_xml() + xml = Builder::XmlMarkup.new(:indent=>2) + xml.instruct! + xml.project do + xml.modelVersion "4.0.0" + xml.groupId group + xml.artifactId id + xml.version version + xml.classifier classifier if classifier + end + end + + # :call-seq: + # upload() + # upload(url) + # upload(options) + # + # Uploads the artifact, its POM and digital signatures to remote server. + # + # In the first form, uses the upload options specified by repositories.release_to. + # In the second form, uses a URL that includes all the relevant information. + # In the third form, uses a hash with the options :url, :username, :password, + # :proxy and :permissions. All but :url are optional. + def upload(upload_to = nil) + # Where do we release to? + upload_to ||= Buildr.repositories.release_to + upload_to = { :url=>upload_to } unless Hash === upload_to + raise ArgumentError, "Don't know where to upload, perhaps you forgot to set repositories.release_to" if upload_to[:url].blank? + + # Set the upload URI, including mandatory slash (we expect it to be the base directory). + # Username/password may be part of URI, or separate entities. + uri = URI.parse(upload_to[:url].clone) + uri.path = uri.path + "/" unless uri.path[-1] == "/" + uri.user = upload_to[:username] if upload_to[:username] + uri.password = upload_to[:password] if upload_to[:password] + + # Upload artifact relative to base URL, need to create path before uploading. + puts "Deploying #{to_spec}" if verbose + path = group.gsub(".", "/") + "/#{id}/#{version}/#{File.basename(name)}" + URI.upload uri + path, name, :proxy=>Buildr.options.proxy, :permissions=>upload_to[:permissions] + end + protected # Apply specification to this artifact. def apply_spec(spec) spec = Artifact.to_hash(spec) @@ -101,43 +148,27 @@ include ActsAsArtifact class << self # :call-seq: - # force_download() => boolean - # force_download(value) => value - # force.download(value) { ... } - # - # In the first form, returns the value of the force download flag. This flag is set - # to force downloading of artifacts, even if those artifacts already exist in the local - # repository. (Used by the artifacts task). - # - # In the second form sets the value of the force download flag. In the third form, sets - # the value of the flag, yields to the block, and resets the flag to its previous value. - def force_download(value = @force_download) - if block_given? - begin - old_value, @force_download = @force_download, value - yield - ensure - @force_download = old_value - end - else - @force_download = value - end - end - - # :call-seq: # lookup(spec) => Artifact # # Lookup a previously registered artifact task based on its specification (String or Hash). def lookup(spec) @artifacts ||= {} @artifacts[to_spec(spec)] end # :call-seq: + # list() => specs + # + # Returns an array of specs for all the registered artifacts. (Anything created from artifact, or package). + def list() + @artifacts.keys + end + + # :call-seq: # register(artifacts) => artifacts # # Register an artifact task(s) for later lookup (see #lookup). def register(*tasks) @artifacts ||= {} @@ -208,47 +239,65 @@ end def initialize(*args) #:nodoc: super enhance do |task| - # Default behavior: download the artifact from one of the remote - # repositories if the file does not exist. But this default behavior - # is counter useful if the artifact knows how to build itself - # (e.g. download from a different location), so don't perform it - # if the task found a different way to create the artifact. - # For that, we need to be the last piece of code run by the task. - if @actions.size == 1 - task.enhance do - begin - puts "Downloading #{to_spec}" if verbose - Buildr.repositories.download(to_spec) - rescue Exception=>error - if File.exist?(name) - puts error - else - raise - end - end + # Default behavior: download the artifact from one of the remote repositories + # if the file does not exist. But this default behavior is counter productive + # if the artifact knows how to build itself (e.g. download from a different location), + # so don't perform it if the task found a different way to create the artifact. + task.enhance do + unless File.exist?(name) + puts "Downloading #{to_spec}" if verbose + download + pom.invoke rescue nil if pom && pom != self end end end end - def needed?() - Artifact.force_download || super + protected + + # :call-seq: + # download() + # + # Downloads an artifact from one of the remote repositories, and stores it in the local + # repository. Accepts a String or Hash artifact specification, and returns a path to the + # artifact 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. It always downloads the POM first. + def download() + puts "Downloading #{to_spec}" if Rake.application.options.trace + remote = Buildr.repositories.remote + remote.find do |repo_url| + repo_url = URI.parse(repo_url) unless URI === repo_url + repo_url.path += "/" unless repo_url.path[-1] == "/" + begin + path = group.gsub(".", "/") + "/#{id}/#{version}/#{File.basename(name)}" + mkpath File.dirname(name), :verbose=>false + URI.download repo_url + path, name, :proxy=>Buildr.options.proxy + true + rescue URI::NotFoundError + false + rescue Exception=>error + puts error if verbose + puts error.backtrace.join("\n") if Rake.application.options.trace + false + end + end or fail "Failed to download #{to_spec}, tried the following repositories:\n#{remote.join("\n")}" end end - # Holds the path to the local repository, URLs for remote repositories, and - # settings for the deployment repository. + # Holds the path to the local repository, URLs for remote repositories, and settings for release server. # # You can access this object from the #repositories method. For example: # puts repositories.local # repositories.remote << "http://example.com/repo" - # repositories.deploy_to = "sftp://example.com/var/www/public/repo" + # repositories.release_to = "sftp://example.com/var/www/public/repo" class Repositories include Singleton # :call-seq: # local() => path @@ -317,81 +366,42 @@ else @remote = [urls.to_s] end end - # :call-seq: - # proxy() => Hash - # - # Returns the proxy settings used when downloading from remote repositories. + # *Deprecated* Please use options.proxy.http instead of repositories.proxy. def proxy() - @proxy ||= {} + warn_deprecated "Please use options.proxy.http instead of repositories.proxy" + Buildr.options.proxy.http end - # :call-seq: - # proxy = Hash - # proxy = String - # proxy = URI - # proxy = nil - # - # Sets the proxy settings used when downloading from remote repositories. - # You can specify proxy settings using a Hash with values for :host, :port, - # :user and :password. - # - # You can also pass a URL as a string or URI object. The settings are converted - # to a hash. - # - # For example: - # repositories.proxy = { :host=>"proxy.acme.com", :port=>8080 } - # repositories.proxy = "proxy.acme.com:8080" + # *Deprecated* Please use options.proxy.http = <url> instead of repositories.proxy. def proxy=(proxy) - case proxy - when Hash, nil - @proxy = proxy || {} - when String - proxy = "http://#{proxy}" unless proxy =~ /^http(s?)/i - proxy = URI.parse(proxy) - @proxy = { :host=>proxy.host, :port=>proxy.port, :user=>proxy.user, :password=>proxy.password } - when URI - @proxy = { :host=>proxy.host, :port=>proxy.port, :user=>proxy.user, :password=>proxy.password } - else - fail "Expecting a Hash, String or URI." - end + warn_deprecated "Please use options.proxy.http = <url> instead of repositories.proxy" + Buildr.options.proxy.http = proxy end - - # :call-seq: - # download(spec) => boolean - # - # Downloads an artifact from one of the remote repositories, and stores it in the local - # repository. Accepts a String or Hash artifact specification, and returns a path to the - # artifact 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. If you want to download an - # artifact only if not already installed in the local repository, create an #artifact - # task and invoke it directly. + + # *Deprecated* Just create an artifact and invoke it. def download(spec) + warn_deprecated "Just create and artifact and invoke it." spec = Artifact.to_hash(spec) unless Hash === spec - path = locate(spec) + filename = locate(spec) puts "Downloading #{Artifact.to_spec(spec)}" if Rake.application.options.trace - return path if remote.any? do |repo_url| + return filename if remote.any? do |repo_url| + repo_url = URI.parse(repo_url) unless URI === repo_url + repo_url.path += "/" unless repo_url.path[-1] == "/" begin - rel_path = spec[:group].gsub(".", "/") + + path = spec[:group].gsub(".", "/") + "/#{spec[:id]}/#{spec[:version]}/#{Artifact.hash_to_file_name(spec)}" - Transports.perform URI.parse(repo_url.to_s), :proxy=>proxy do |http| - mkpath File.dirname(path), :verbose=>false - http.download(rel_path, path) - end - Transports.perform URI.parse(repo_url.to_s), :proxy=>proxy do |http| - begin - http.download(rel_path.ext("pom"), path.ext("pom")) - rescue Transports::NotFound - end - end + mkpath File.dirname(filename), :verbose=>false + # We absolutely need the POM, so make sure we download it before the artifact + # (unless the artifact is a POM). + URI.download repo_url + path.ext("pom"), name.ext("pom"), :proxy=>Buildr.options.proxy unless type == :pom + URI.download repo_url + path, filename, :proxy=>Buildr.options.proxy true - rescue Transports::NotFound + rescue URI::NotFoundError false rescue Exception=>error puts error if verbose puts error.backtrace.join("\n") if Rake.application.options.trace false @@ -399,52 +409,61 @@ end fail "Failed to download #{Artifact.to_spec(spec)}, tried the following repositories:\n#{remote.join("\n")}" end # :call-seq: - # deploy_to = url - # deploy_to = hash + # release_to = url + # release_to = hash # - # Specifies the deployment repository. Accepts a Hash with different repository settings + # Specifies the release server. Accepts a Hash with different repository settings # (e.g. url, username, password), or a String to only set the repository URL. # - # Besides the URL, all other settings depend on the transport protocol in use. See #Transports - # for more details. Common settings include username and password. + # Besides the URL, all other settings depend on the transport protocol in use. # # For example: - # repositories.deploy_to = { :url=>"sftp://example.com/var/www/repo/", - # :username="john", :password=>"secret" } - # or: - # repositories.deploy_to = "sftp://john:secret@example.com/var/www/repo/" - def deploy_to=(options) + # repositories.release_to = "sftp://john:secret@example.com/var/www/repo/" + # repositories.release_to = { :url=>"sftp://example.com/var/www/repo/", + # :username="john", :password=>"secret" } + def release_to=(options) options = { :url=>options } unless Hash === options - @deploy_to = options + @release_to = options end # :call-seq: - # deploy_to() => hash + # release_to() => hash # - # Returns the current deployment repository setting as a Hash. This is a more convenient - # way to specify the deployment repository, as it allows you to specify the settings - # progressively. + # Returns the current release server setting as a Hash. This is a more convenient way to + # configure the settings, as it allows you to specify the settings progressively. # - # For example, the Rakefile will contain the repository URL used by all developers: - # repositories.deploy_to[:url] ||= "sftp://example.com/var/www/repo" + # For example, the Buildfile will contain the repository URL used by all developers: + # repositories.release_to[:url] ||= "sftp://example.com/var/www/repo" # Your private buildr.rb will contain your credentials: - # repositories.deploy_to[:username] = "john" - # repositories.deploy_to[:password] = "secret" + # repositories.release_to[:username] = "john" + # repositories.release_to[:password] = "secret" + def release_to() + @release_to ||= {} + end + + # *Deprecated* See release_to. + def deploy_to=(options) + warn_deprecated "Please use release_to instead." + self.release_to = options + end + + # *Deprecated* See release_to. def deploy_to() - @deploy_to ||= {} + warn_deprecated "Please use release_to instead." + self.release_to end end # :call-seq: # repositories() => Repositories # # Returns an object you can use for setting the local repository path, remote repositories - # URL and deployment repository settings. + # URL and release server settings. # # See Repositories. def repositories() Repositories.instance end @@ -476,11 +495,10 @@ spec = Artifact.to_hash(spec) unless task = Artifact.lookup(spec) task = Artifact.define_task(repositories.locate(spec)) task.send :apply_spec, spec Rake::Task["rake:artifacts"].enhance [task] - Rake::Task["rake:artifacts:refresh"].enhance { Artifact.force_download(true) { task.invoke } } Artifact.register(task) end task.enhance &block end @@ -493,11 +511,11 @@ # You can pass any number of arguments, each of which can be: # * An artifact specification (String or Hash). Returns the appropriate Artifact task. # * An artifact of any other task. Returns the task as is. # * A project. Returns all artifacts created (packaged) by that project. # * A string. Returns that string, assumed to be a file name. - # * An array of artifacts. Calls #artifacts on the array, flattens the result. + # * An array of artifacts or a Struct. # # For example, handling a collection of artifacts: # xml = [ xerces, xalan, jaxp ] # ws = [ axis, jax-ws, jaxb ] # db = [ jpa, mysql, sqltools ] @@ -517,10 +535,12 @@ set |= [File.expand_path(spec)] when Project set |= artifacts(spec.packages) when Rake::Task set |= [spec] + when Struct + set |= artifacts(spec.values) else fail "Invalid artifact specification in: #{specs.to_s}" end end end @@ -540,46 +560,38 @@ def group(*args) hash = args.pop args.flatten.map { |id| artifact :group=>hash[:under], :version=>hash[:version], :id=>id } end - # :call-seq: - # deploy(*files) - # deploy(*files, deploy_options) - # - # Deploys all the specified artifacts/files. If the last argument is a Hash, it is used to - # specify the deployment repository. Otherwise, obtains the deployment repository by calling - # Repositories#deploy_to. - # - # When deploying files, you can specify a path relative to the deployment URL. Artifacts are - # always deployed to a path that combined the group identifier, artifact identifier and - # version number. - # - # For example: - # deploy(foo.packages, :url=>"sftp://example.com/var/www/repo") - # deploy(file("LICENSE"), :path=>group.tr(".", "/")) + # *Deprecated* For artifact, call it's upload method; for anything else, use URI.upload. def deploy(*args) + warn_deprecated "If it's an artifact, call it's upload method directly. Otherwise, use URI.upload." # Where do we release to? options = Hash === args.last ? args.pop : {} - deploy_to = options[:url] ? options : repositories.deploy_to + deploy_to = options[:url] ? options : repositories.release_to fail "Don't know where to deploy, perhaps you forgot to set repositories.deploy_to" if deploy_to[:url].blank? args.flatten.each { |arg| arg.invoke if arg.respond_to?(:invoke) } - # Strip :url and :path, in case the transport checks for valid options. - Transports.perform deploy_to[:url], deploy_to.reject{ |k,v| k == :url || k == :path } do |session| - args.flatten.each do |artifact| - if artifact.respond_to?(:to_spec) - # Upload artifact relative to base URL, need to create path before uploading. - puts "Deploying #{artifact.to_spec}" if verbose - spec = artifact.to_spec_hash - path = spec[:group].gsub(".", "/") + "/#{spec[:id]}/#{spec[:version]}/" - session.mkpath path - session.upload artifact.to_s, path + Artifact.hash_to_file_name(spec) - else - # Upload artifact to URL. - puts "Deploying #{artifact}" if verbose - session.upload artifact.to_s, File.join(*(options[:path].to_a + [File.basename(artifact.to_s)]).compact) - end + # Set the upload URI, including mandatory slash (we expect it to be the base directory). + # Username/password may be part of URI, or separate entities. + uri = URI.parse(deploy_to[:url].clone) + uri.path = uri.path + "/" unless uri.path[-1] == "/" + uri.user = deploy_to[:username] if deploy_to[:username] + uri.password = deploy_to[:password] if deploy_to[:password] + + args.each do |arg| + if arg.respond_to?(:to_spec) + # Upload artifact relative to base URL, need to create path before uploading. + puts "Deploying #{arg.to_spec}" if verbose + spec = arg.to_spec_hash + path = spec[:group].gsub(".", "/") + "/#{spec[:id]}/#{spec[:version]}/" + Artifact.hash_to_file_name(spec) + URI.upload uri + path, arg.to_s, :proxy=>Buildr.options.proxy, :permissions=>deploy_to[:permissions] + else + # Upload file to URL. + puts "Deploying #{arg}" if verbose + path = File.basename(args.to_s) + path = File.join(options[:path], path) if options[:path] + URI.upload uri + path, arg.to_s, :proxy=>Buildr.options.proxy, :permissions=>deploy_to[:permissions] end end end end