diff --git a/lib/fpm/package.rb b/lib/fpm/package.rb index 1bbbd5d7af..38f7239c13 100644 --- a/lib/fpm/package.rb +++ b/lib/fpm/package.rb @@ -109,6 +109,11 @@ def to_s attr_accessor :directories + # Strings that contain the shell code for building/installing a package. These + # are needed by source-based package types. + attr_accessor :build_procedure + attr_accessor :install_procedure + # Any other attributes specific to this package. # This is where you'd put rpm, deb, or other specific attributes. attr_accessor :attributes @@ -190,6 +195,13 @@ def type self.class.type end # def type + # Source-based package types (such as SRPM and SDEB) should override this method to return true + public + def source_pkg? + return nil + end # def source_pkg? + private + # Convert this package to a new package type def convert(klass) logger.info("Converting #{self.type} to #{klass.type}") @@ -206,6 +218,18 @@ def convert(klass) :@name, :@provides, :@replaces, :@scripts, :@url, :@vendor, :@version, :@directories, :@staging_path, :@attrs ] + + # source packages dont need to actually build the source, instead they need + # the shell code for the build and install procedures. + if pkg.source_pkg?() + h = shell_code() # h is a two elem hash ... + @build_procedure = h[:build_procedure] + @install_procedure = h[:install_procedure] + ivars += [:@build_procedure, :@install_procedure] + else # binary packages need to be built and installed to the staging_path + build_and_install + end + ivars.each do |ivar| #logger.debug("Copying ivar", :ivar => ivar, :value => instance_variable_get(ivar), #:from => self.type, :to => pkg.type) @@ -240,9 +264,12 @@ def converted_from(origin) # The idea is that you can keep pumping in new things to a package # for later conversion or output. # - # Implementations are expected to put files relevant to the 'input' in the - # staging_path - def input(thing_to_input) + # Implementations are expected to leave their prepared files in the + # staging_path. + # + # It is important to note that the build/installation of the + # package now happens in the convert() method, not input(). + def input(thing_to_prepare) raise NotImplementedError.new("#{self.class.name} does not yet support " \ "reading #{self.type} packages") end # def input @@ -253,6 +280,15 @@ def output(path) "creating #{self.type} packages") end # def output + def shell_code + raise NotImplementedError.new("#{self.class.name} does not yet know how to produce " \ + "shell code for its build/install procedures") + end # def shell_code + + def build_and_install + raise NotImplementedError.new("TODO") + end # def build_and_install + def staging_path(path=nil) @staging_path ||= Stud::Temporary.directory("package-#{type}-staging") diff --git a/lib/fpm/package/cpan.rb b/lib/fpm/package/cpan.rb index a541efc18f..1eb13080c1 100644 --- a/lib/fpm/package/cpan.rb +++ b/lib/fpm/package/cpan.rb @@ -51,25 +51,25 @@ def input(package) require "json" if File.exist?(package) - moduledir = package + @moduledir = package result = {} else result = search(package) tarball = download(result, version) - moduledir = unpack(tarball) + @moduledir = unpack(tarball) end # Read package metadata (name, version, etc) - if File.exist?(File.join(moduledir, "META.json")) - local_metadata = JSON.parse(File.read(File.join(moduledir, ("META.json")))) - elsif File.exist?(File.join(moduledir, ("META.yml"))) + if File.exist?(File.join(@moduledir, "META.json")) + local_metadata = JSON.parse(File.read(File.join(@moduledir, ("META.json")))) + elsif File.exist?(File.join(@moduledir, ("META.yml"))) require "yaml" - local_metadata = YAML.load_file(File.join(moduledir, ("META.yml"))) - elsif File.exist?(File.join(moduledir, "MYMETA.json")) - local_metadata = JSON.parse(File.read(File.join(moduledir, ("MYMETA.json")))) - elsif File.exist?(File.join(moduledir, ("MYMETA.yml"))) + local_metadata = YAML.load_file(File.join(@moduledir, ("META.yml"))) + elsif File.exist?(File.join(@moduledir, "MYMETA.json")) + local_metadata = JSON.parse(File.read(File.join(@moduledir, ("MYMETA.json")))) + elsif File.exist?(File.join(@moduledir, ("MYMETA.yml"))) require "yaml" - local_metadata = YAML.load_file(File.join(moduledir, ("MYMETA.yml"))) + local_metadata = YAML.load_file(File.join(@moduledir, ("MYMETA.yml"))) end # Merge the MetaCPAN query result and the metadata pulled from the local @@ -128,9 +128,9 @@ def input(package) logger.info("Installing any build or configure dependencies") if attributes[:cpan_sandbox_non_core?] - cpanm_flags = ["-L", build_path("cpan"), moduledir] + cpanm_flags = ["-L", build_path("cpan"), @moduledir] else - cpanm_flags = ["-l", build_path("cpan"), moduledir] + cpanm_flags = ["-l", build_path("cpan"), @moduledir] end # This flag causes cpanm to ONLY download dependencies, skipping the target @@ -195,8 +195,10 @@ def input(package) end end end #no_auto_depends + end # def input - ::Dir.chdir(moduledir) do + def build_and_install + ::Dir.chdir(@moduledir) do # TODO(sissel): install build and config dependencies to resolve # build/configure requirements. # META.yml calls it 'configure_requires' and 'build_requires' @@ -279,7 +281,7 @@ def input(package) if ::Dir.entries(parent).sort == ['.', '..'].sort FileUtils.rmdir parent else - break + end end end @@ -299,7 +301,20 @@ def input(package) self.architecture = "native" end end - end + end # def build_and_install + + def shell_code + build_procedure = "" + install_procedure = "" + if File.exist?("Build.PL") # Module::Build + build_procedure = "perl Build.PL\n./Build\n#{attributes[:cpan_test?] ? "./Build test\n" : "" }" + install_procedure = "./Build install\n" + elsif File.exist?("Makefile.PL") # ExtUtils::MakeMaker + build_procedure = "perl Makefile.PL\nmake\n#{attributes[:cpan_test?] ? "make test\n" : "" }" + install_procedure = "make install\n" + end + return { :build_procedure => build_procedure, :install_procedure => install_procedure } + end # def shell_code def unpack(tarball) directory = build_path("module") diff --git a/lib/fpm/package/gem.rb b/lib/fpm/package/gem.rb index 26a45ad419..fa763f616c 100644 --- a/lib/fpm/package/gem.rb +++ b/lib/fpm/package/gem.rb @@ -76,16 +76,25 @@ def staging_path(path=nil) def input(gem) # 'arg' is the name of the rubygem we should unpack. - path_to_gem = download_if_necessary(gem, version) + @path_to_gem = download_if_necessary(gem, version) # Got a good gem now (downloaded or otherwise) # # 1. unpack it into staging_path # 2. take the metadata from it and update our wonderful package with it. - load_package_info(path_to_gem) - install_to_staging(path_to_gem) + load_package_info(@path_to_gem) end # def input + def build_and_install + install_to_staging(@path_to_gem) + end # def build_and_install + + def shell_code + build_procedure = "" + install_procedure = "gem install #{File.basename(@path_to_gem)}" + return { :build_procedure => build_procedure, :install_procedure => install_procedure } + end # def shell_code + def download_if_necessary(gem, gem_version) path = gem if !File.exist?(path)