| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with this |
| # work for additional information regarding copyright ownership. The ASF |
| # licenses this file to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| |
| module Buildr #:nodoc: |
| # Methods added to Project to support packaging and tasks for packaging, |
| # installing and uploading packages. |
| module Package |
| |
| include Extension |
| |
| first_time do |
| desc 'Create packages' |
| Project.local_task('package'=>'build') { |name| "Packaging #{name}" } |
| desc 'Install packages created by the project' |
| Project.local_task('install'=>'package') { |name| "Installing packages from #{name}" } |
| desc 'Remove previously installed packages' |
| Project.local_task('uninstall') { |name| "Uninstalling packages from #{name}" } |
| desc 'Upload packages created by the project' |
| Project.local_task('upload'=>'package') { |name| "Deploying packages from #{name}" } |
| # Anything that comes after local packaging (install, upload) executes the integration tests, |
| # which do not conflict with integration invoking the project's own packaging (package=> |
| # integration=>foo:package is not circular, just confusing to debug.) |
| task 'package' do |
| task('integration').invoke if Buildr.options.test && Buildr.application.original_dir == Dir.pwd |
| end |
| end |
| |
| before_define(:package => :build) do |project| |
| [ :package, :install, :uninstall, :upload ].each { |name| project.recursive_task name } |
| # Need to run build before package, since package is often used as a dependency by tasks that |
| # expect build to happen. |
| project.task('package'=>project.task('build')) |
| project.group ||= project.parent && project.parent.group || project.name |
| project.version ||= project.parent && project.parent.version |
| end |
| |
| after_define(:package) |
| |
| # The project's identifier. Same as the project name, with colons replaced by dashes. |
| # The ID for project foo:bar is foo-bar. |
| def id |
| name.gsub(':', '-') |
| end |
| |
| # Group used for packaging. Inherited from parent project. Defaults to the top-level project name. |
| attr_accessor :group |
| |
| # Version used for packaging. Inherited from parent project. |
| attr_accessor :version |
| |
| # :call-seq: |
| # package(type, spec?) => task |
| # |
| # Defines and returns a package created by this project. |
| # |
| # The first argument declares the package type. For example, :jar to create a JAR file. |
| # The package is an artifact that takes its artifact specification from the project. |
| # You can override the artifact specification by passing various options in the second |
| # argument, for example: |
| # package(:zip, :classifier=>'sources') |
| # |
| # Packages that are ZIP files provides various ways to include additional files, directories, |
| # and even merge ZIPs together. Have a look at ZipTask for more information. In case you're |
| # wondering, JAR and WAR packages are ZIP files. |
| # |
| # You can also enhance a JAR package using the ZipTask#with method that accepts the following options: |
| # * :manifest -- Specifies how to create the MANIFEST.MF. By default, uses the project's |
| # #manifest property. |
| # * :meta_inf -- Specifies files to be included in the META-INF directory. By default, |
| # uses the project's #meta-inf property. |
| # |
| # The WAR package supports the same options and adds a few more: |
| # * :classes -- Directories of class files to include in WEB-INF/classes. Includes the compile |
| # target directory by default. |
| # * :libs -- Artifacts and files to include in WEB-INF/libs. Includes the compile classpath |
| # dependencies by default. |
| # |
| # For example: |
| # define 'project' do |
| # define 'beans' do |
| # package :jar |
| # end |
| # define 'webapp' do |
| # compile.with project('beans') |
| # package(:war).with :libs=>MYSQL_JDBC |
| # end |
| # package(:zip, :classifier=>'sources').include path_to('.') |
| # end |
| # |
| # Two other packaging types are: |
| # * package :sources -- Creates a JAR file with the source code and classifier 'sources', for use by IDEs. |
| # * package :javadoc -- Creates a ZIP file with the Javadocs and classifier 'javadoc'. You can use the |
| # javadoc method to further customize it. |
| # |
| # A package is also an artifact. The following tasks operate on packages created by the project: |
| # buildr upload # Upload packages created by the project |
| # buildr install # Install packages created by the project |
| # buildr package # Create packages |
| # buildr uninstall # Remove previously installed packages |
| # |
| # If you want to add additional packaging types, implement a method with the name package_as_[type] |
| # that accepts a file name and returns an appropriate Rake task. For example: |
| # def package_as_zip(file_name) #:nodoc: |
| # ZipTask.define_task(file_name) |
| # end |
| # |
| # The file name is determined from the specification passed to the package method, however, some |
| # packagers need to override this. For example, package(:sources) produces a file with the extension |
| # 'jar' and the classifier 'sources'. If you need to overwrite the default implementation, you should |
| # also include a method named package_as_[type]_spec. For example: |
| # def package_as_sources_spec(spec) #:nodoc: |
| # # Change the source distribution to .zip extension |
| # spec.merge({ :type=>:zip, :classifier=>'sources' }) |
| # end |
| def package(*args) |
| spec = Hash === args.last ? args.pop.dup : {} |
| no_options = spec.empty? # since spec is mutated |
| if spec[:file] |
| rake_check_options spec, :file, :type |
| spec[:type] = args.shift || spec[:type] || spec[:file].split('.').last.to_sym |
| file_name = spec[:file] |
| else |
| rake_check_options spec, *ActsAsArtifact::ARTIFACT_ATTRIBUTES |
| spec[:id] ||= self.id |
| spec[:group] ||= self.group |
| spec[:version] ||= self.version |
| spec[:type] = args.shift || spec[:type] || compile.packaging || :zip |
| end |
| |
| packager = method("package_as_#{spec[:type]}") rescue fail("Don't know how to create a package of type #{spec[:type]}") |
| if packager.arity == 1 |
| unless file_name |
| spec = send("package_as_#{spec[:type]}_spec", spec) if respond_to?("package_as_#{spec[:type]}_spec") |
| file_name = path_to(:target, Artifact.hash_to_file_name(spec)) |
| end |
| package = (no_options && packages.detect { |pkg| pkg.type == spec[:type] && (pkg.id.nil? || pkg.id == spec[:id]) && |
| (pkg.respond_to?(:classifier) ? pkg.classifier : nil) == spec[:classifier]}) || |
| packages.find { |pkg| pkg.name == file_name } || |
| packager.call(file_name) |
| else |
| Buildr.application.deprecated "We changed the way package_as methods are implemented. See the package method documentation for more details." |
| file_name ||= path_to(:target, Artifact.hash_to_file_name(spec)) |
| package = packager.call(file_name, spec) |
| end |
| |
| # First time: prepare package for install, uninstall and upload tasks. |
| unless packages.include?(package) |
| # We already run build before package, but we also need to do so if the package itself is |
| # used as a dependency, before we get to run the package task. |
| task 'package'=>package |
| package.enhance [task('build')] |
| package.enhance { info "Packaging #{File.basename(file_name)}" } |
| if spec[:file] |
| class << package ; self ; end.send(:define_method, :type) { spec[:type] } |
| class << package ; self ; end.send(:define_method, :id) { nil } |
| else |
| # Make it an artifact using the specifications, and tell it how to create a POM. |
| package.extend ActsAsArtifact |
| package.buildr_project = self |
| package.send :apply_spec, spec.only(*Artifact::ARTIFACT_ATTRIBUTES) |
| |
| # Create pom associated with package |
| class << package |
| def pom |
| unless @pom |
| pom_filename = Util.replace_extension(self.name, 'pom') |
| spec = {:group=>group, :id=>id, :version=>version, :type=>:pom} |
| @pom = Buildr.artifact(spec, pom_filename) |
| @pom.content Buildr::CustomPom.pom_xml(self.buildr_project, self) |
| end |
| @pom |
| end |
| end if package.classifier.nil? |
| |
| file(Buildr.repositories.locate(package)=>package) { package.install } |
| |
| # Add the package to the list of packages created by this project, and |
| # register it as an artifact. The later is required so if we look up the spec |
| # we find the package in the project's target directory, instead of finding it |
| # in the local repository and attempting to install it. |
| Artifact.register package |
| Artifact.register package.pom if package.classifier.nil? |
| end |
| |
| task('install') { package.install if package.respond_to?(:install) } |
| task('uninstall') { package.uninstall if package.respond_to?(:uninstall) } |
| task('upload') { package.upload if package.respond_to?(:upload) } |
| |
| packages << package |
| end |
| package |
| end |
| |
| # :call-seq: |
| # packages => tasks |
| # |
| # Returns all packages created by this project. A project may create any number of packages. |
| # |
| # This method is used whenever you pass a project to Buildr#artifact or any other method |
| # that accepts artifact specifications and projects. You can use it to list all packages |
| # created by the project. If you want to return a specific package, it is often more |
| # convenient to call #package with the type. |
| def packages |
| @packages ||= [] |
| end |
| |
| def package_as_zip(file_name) #:nodoc: |
| ZipTask.define_task(file_name) |
| end |
| |
| def package_as_tar(file_name) #:nodoc: |
| TarTask.define_task(file_name) |
| end |
| alias :package_as_tgz :package_as_tar |
| |
| def package_as_sources_spec(spec) #:nodoc: |
| spec.merge(:type=>:jar, :classifier=>'sources') |
| end |
| |
| def package_as_sources(file_name) #:nodoc: |
| ZipTask.define_task(file_name).tap do |zip| |
| zip.include :from=>[compile.sources, resources.target].compact |
| end |
| end |
| |
| end |
| end |
| |
| class Buildr::Project |
| include Buildr::Package |
| end |