Check-in [a80b102103]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Initial OS X package support, #317. Basic support for OS X flat packages (.pkg) - input/output - output supports scripts, postinstall actions (using --info option), ownership option and bundle-id-prefix option - requires pkgbuild (therefore OS X 10.7+ only), pkgutil for input - no tests yet ignore .DS_Store ignore .pkg identifier gets its own method first few osxpkg spec tests osxpkg: extract name and version from PackageInfo on input osxpkg: rename option bundle-id-prefix to identifier-prefix - 'bundle-id' is ambiguous, given the various 'bundle'-related logic possible with OS X packages osxpkg: fix old 'osx_' attribute prefix to 'osxpkg' in osxpkg.erb New option: --osxpkg-dont-obsolete, to add files to 'dont-obsolete' element in PackageInfo. osxpkg: Define public/private methods. osxpkg_spec: Tests for basic attributes through input/output |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a80b102103fa26aeb13701bb858b4c11 |
User & Date: | tim@synthist.net 2013-01-07 17:28:03 |
Context
2013-01-07
| ||
18:06 | Merge pull request #332 from timsutton/4df9617b8a3e71ac82b4dadb8cad28cded66159f OS X package support check-in: d4fcb347a0 user: jls@semicomplete.com tags: trunk | |
17:28 | Initial OS X package support, #317. Basic support for OS X flat packages (.pkg) - input/output - output supports scripts, postinstall actions (using --info option), ownership option and bundle-id-prefix option - requires pkgbuild (therefore OS X 10.7+ only), pkgutil for input - no tests yet ignore .DS_Store ignore .pkg identifier gets its own method first few osxpkg spec tests osxpkg: extract name and version from PackageInfo on input osxpkg: rename option bundle-id-prefix to identifier-prefix - 'bundle-id' is ambiguous, given the various 'bundle'-related logic possible with OS X packages osxpkg: fix old 'osx_' attribute prefix to 'osxpkg' in osxpkg.erb New option: --osxpkg-dont-obsolete, to add files to 'dont-obsolete' element in PackageInfo. osxpkg: Define public/private methods. osxpkg_spec: Tests for basic attributes through input/output check-in: a80b102103 user: tim@synthist.net tags: trunk | |
2012-12-10
| ||
21:29 | Merge pull request #315 from mashion/target-os-fix Respect rpmbuild's argument ordering for #309 check-in: 9904d60a54 user: jls@semicomplete.com tags: trunk | |
Changes
Changes to .gitignore.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # vim .*.sw[a-z] # build byproducts build-*/* fpm.wiki *.gem # python *.pyc # RVM .rvmrc .yardoc coverage test/tmp Gemfile.lock | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # vim .*.sw[a-z] # build byproducts build-*/* fpm.wiki *.gem *.pkg # python *.pyc # RVM .rvmrc .yardoc coverage test/tmp Gemfile.lock # OS X .DS_Store |
Changes to lib/fpm.rb.
1 2 3 4 5 6 7 8 | require "fpm/namespace" require "fpm/package" require "fpm/package/dir" require "fpm/package/gem" require "fpm/package/deb" require "fpm/package/rpm" require "fpm/package/python" | > | 1 2 3 4 5 6 7 8 9 | require "fpm/namespace" require "fpm/package" require "fpm/package/dir" require "fpm/package/gem" require "fpm/package/deb" require "fpm/package/rpm" require "fpm/package/python" require "fpm/package/osxpkg" |
Added lib/fpm/package/osxpkg.rb.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | require "fpm/package" require "fpm/util" require "fileutils" require "fpm/package/dir" require 'tempfile' # stdlib require 'pathname' # stdlib require 'rexml/document' # stdlib # Use an OS X pkg built with pkgbuild. # # Supports input and output. Requires pkgbuild and (for input) pkgutil, part of a # standard OS X install in 10.7 and higher. class FPM::Package::OSXpkg < FPM::Package # Map of what scripts are named. SCRIPT_MAP = { :before_install => "preinstall", :after_install => "postinstall", } unless defined?(SCRIPT_MAP) POSTINSTALL_ACTIONS = [ "logout", "restart", "shutdown" ] OWNERSHIP_OPTIONS = ["recommended", "preserve", "preserve-other"] option "--identifier-prefix", "IDENTIFIER_PREFIX", "Reverse domain prefix prepended to package identifier, " \ "ie. 'org.great.my'. If this is omitted, the identifer " \ "will be the package name." option "--payload-free", :flag, "Define no payload, assumes use of script options.", :default => false option "--ownership", "OWNERSHIP", "--ownership option passed to pkgbuild. Defaults to 'recommended'. " \ "See pkgbuild(1).", :default => 'recommended' do |value| if !OWNERSHIP_OPTIONS.include?(value) raise ArgumentError, "osxpkg-ownership value of '#{value}' is invalid. " \ "Must be one of #{OWNERSHIP_OPTIONS.join(", ")}" end value end option "--postinstall-action", "POSTINSTALL_ACTION", "Post-install action provided in package metadata. " \ "Optionally one of '#{POSTINSTALL_ACTIONS.join("', '")}'." do |value| if !POSTINSTALL_ACTIONS.include?(value) raise ArgumentError, "osxpkg-postinstall-action value of '#{value}' is invalid. " \ "Must be one of #{POSTINSTALL_ACTIONS.join(", ")}" end value end dont_obsolete_paths = [] option "--dont-obsolete", "DONT_OBSOLETE_PATH", "A file path for which to 'dont-obsolete' in the built PackageInfo. " \ "Can be specified multiple times." do |path| dont_obsolete_paths << path end private # return the identifier by prepending the reverse-domain prefix # to the package name, else return just the name def identifier identifier = name.dup if self.attributes[:osxpkg_identifier_prefix] identifier.insert(0, "#{self.attributes[:osxpkg_identifier_prefix]}.") end identifier end # def identifier # scripts_path and write_scripts cribbed from deb.rb def scripts_path(path=nil) @scripts_path ||= build_path("Scripts") FileUtils.mkdir(@scripts_path) if !File.directory?(@scripts_path) if path.nil? return @scripts_path else return File.join(@scripts_path, path) end end # def scripts_path def write_scripts SCRIPT_MAP.each do |scriptname, filename| next unless script?(scriptname) with(scripts_path(filename)) do |pkgscript| @logger.info("Writing pkg script", :source => filename, :target => pkgscript) File.write(pkgscript, script(scriptname)) # scripts are required to be executable File.chmod(0755, pkgscript) end end end # def write_scripts # Returns path of a processed template PackageInfo given to 'pkgbuild --info' # note: '--info' is undocumented: # http://managingosx.wordpress.com/2012/07/05/stupid-tricks-with-pkgbuild def pkginfo_template_path pkginfo_template = Tempfile.open("fpm-PackageInfo") pkginfo_data = template("osxpkg.erb").result(binding) pkginfo_template.write(pkginfo_data) pkginfo_template.close pkginfo_template.path end # def write_pkginfo_template # Extract name and version from PackageInfo XML def extract_info(package) with(build_path("expand")) do |path| doc = REXML::Document.new File.open(File.join(path, "PackageInfo")) pkginfo_elem = doc.elements["pkg-info"] identifier = pkginfo_elem.attribute("identifier").value self.version = pkginfo_elem.attribute("version").value # set name to the last dot element of the identifier self.name = identifier.split(".").last @logger.info("inferring name #{self.name} from pkg-id #{identifier}") end end # def extract_info # Take a flat package as input def input(input_path) # TODO: Fail if it's a Distribution pkg or old-fashioned expand_dir = File.join(build_path, "expand") # expand_dir must not already exist for pkgutil --expand safesystem("pkgutil --expand #{input_path} #{expand_dir}") extract_info(input_path) # extract Payload safesystem("tar -xz -f #{expand_dir}/Payload -C #{staging_path}") end # def input # Output a pkgbuild pkg. def output(output_path) output_check(output_path) raise FileAlreadyExists.new(output_path) if File.exists?(output_path) temp_info = pkginfo_template_path args = ["--identifier", identifier, "--info", temp_info, "--version", version.to_s, "--ownership", attributes[:osxpkg_ownership]] if self.attributes[:osxpkg_payload_free?] args << "--nopayload" else args += ["--root", staging_path] end if attributes[:before_install_given?] or attributes[:after_install_given?] write_scripts args += ["--scripts", scripts_path] end args << output_path safesystem("pkgbuild", *args) FileUtils.remove_file(temp_info) end # def output def to_s(format=nil) return super("NAME-VERSION.pkg") if format.nil? return super(format) end # def to_s public(:input, :output, :identifier, :to_s) end # class FPM::Package::OSXpkg |
Added spec/fpm/package/osxpkg_spec.rb.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | require "spec_setup" require "fpm" # local require "fpm/package/osxpkg" # local describe FPM::Package::OSXpkg do if %x{uname -s}.chomp != "Darwin" Cabin::Channel.get("rspec").warn("Skipping OS X tests because " \ "this system is #{%x{uname -s}.chomp}, Darwin required") end describe "#identifier" do it "should be of the form reverse.domain.pkgname" do subject.name = "name" subject.attributes[:osxpkg_identifier_prefix] = "org.great" insist { subject.identifier } == \ "#{subject.attributes[:osxpkg_identifier_prefix]}.#{subject.name}" end it "should be the name only if a prefix was not given" do subject.name = "name" subject.attributes[:osxpkg_identifier_prefix] = nil insist { subject.identifier } == subject.name end end describe "#to_s" do it "should have a default output usable as a filename" do subject.name = "name" subject.version = "123" # We like the format 'name-version.pkg' insist { subject.to_s } == "name-123.pkg" end end describe "#output" do before :all do # output a package, use it as the input, set the subject to that input # package. This helps ensure that we can write and read packages # properly. tmpfile = Tempfile.new("fpm-test-osxpkg") @target = tmpfile.path # The target file must not exist. tmpfile.unlink @original = FPM::Package::OSXpkg.new @original.name = "name" @original.version = "123" @original.attributes[:osxpkg_identifier_prefix] = "org.my" @original.output(@target) @input = FPM::Package::OSXpkg.new @input.input(@target) end after :all do @original.cleanup @input.cleanup end # after context "package attributes" do it "should have the correct name" do insist { @input.name } == @original.name end it "should have the correct version" do insist { @input.version } == @original.version end end # package attributes end # #output end # describe FPM::Package:OSXpkg |
Added templates/osxpkg.erb.
> > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 | <pkg-info <% if !attributes[:osxpkg_postinstall_action].nil? -%>postinstall-action="<%= attributes[:osxpkg_postinstall_action] %>"<% end -%> > <% if !attributes[:osxpkg_dont_obsolete].nil? -%> <dont-obsolete> <% attributes[:osxpkg_dont_obsolete].each do |filepath| -%> <file path="<%= filepath %>"/> <% end -%> </dont-obsolete> <% end -%> </pkg-info> |