==> Creating package staging root using Homebrew prefix /usr/local
11 | ==> Staging formula nginx
12 | ==> Plist found at homebrew.mxcl.nginx, staging for /Library/LaunchDaemons/homebrew.mxcl.nginx.plist
13 | ==> Building package nginx-1.2.6.pkg
14 |
15 | It can also automatically include the formula's dependencies:
16 |
17 | `brew pkg --with-deps --without-kegs ffmpeg`
18 | ==> Creating package staging root using Homebrew prefix /usr/local
19 | ==> Staging formula ffmpeg
20 | ==> Staging formula pkg-config
21 | ==> Staging formula texi2html
22 | ==> Staging formula yasm
23 | ==> Staging formula x264
24 | ==> Staging formula faac
25 | ==> Staging formula lame
26 | ==> Staging formula xvid
27 | ==> Building package ffmpeg-1.1.pkg
28 |
29 | By default behaviour brew pkg include all package kegs located in /usr/local/Cellar/packagename. If you need to exclude it, specify option --without-kegs
30 |
31 | ## Installing it
32 |
33 | brew-pkg is available from my [formulae tap](https://github.com/timsutton/homebrew-formulae). Add the tap:
34 |
35 | `brew tap timsutton/formulae`
36 |
37 | Then install as any other formula:
38 |
39 | `brew install brew-pkg`
40 |
41 | ## Extras
42 |
43 | If a formula has defined a launchd plist, brew-pkg will also install this to the package's root in `/Library/LaunchDaemons`.
44 |
45 | You can also define a custom identifier prefix in the reverse-domain convention with the `--identifier-prefix` option, ie. `brew pkg --identifier-prefix org.nagios nrpe`. If there is a launchd plist defined, this same prefix is currently _not_ applied to the plist.
46 |
47 | You can set the path to custom preinstall and postinstall scripts with the `--scripts` option which is just literally passed through to the `pkgbuild` command.
48 | For more information refer to `man pkgbuild` which explains that *`--scripts scripts_path` archive the entire contents of scripts-path as the package scripts. If this directory contains scripts named preinstall and/or postinstall, these will be run as the top-level scripts of the package [...]*.
49 |
50 | ## License
51 |
52 | brew-pkg is [MIT-licensed](https://github.com/timsutton/brew-pkg/blob/master/LICENSE.md).
53 |
--------------------------------------------------------------------------------
/brew-pkg.rb:
--------------------------------------------------------------------------------
1 | # Builds an OS X installer package from an installed formula.
2 | require 'formula'
3 | require 'optparse'
4 | require 'tmpdir'
5 |
6 | module HomebrewArgvExtension extend self
7 | def with_deps?
8 | flag? '--with-deps'
9 | end
10 | end
11 |
12 | # cribbed Homebrew module code from brew-unpack.rb
13 | module Homebrew extend self
14 | def pkg
15 | unpack_usage = <<-EOS
16 | Usage: brew pkg [--identifier-prefix] [--with-deps] [--without-kegs] formula
17 |
18 | Build an OS X installer package from a formula. It must be already
19 | installed; 'brew pkg' doesn't handle this for you automatically. The
20 | '--identifier-prefix' option is strongly recommended in order to follow
21 | the conventions of OS X installer packages.
22 |
23 | Options:
24 | --identifier-prefix set a custom identifier prefix to be prepended
25 | to the built package's identifier, ie. 'org.nagios'
26 | makes a package identifier called 'org.nagios.nrpe'
27 | --with-deps include all the package's dependencies in the built package
28 | --without-kegs exclude package contents at /usr/local/Cellar/packagename
29 | --scripts set the path to custom preinstall and postinstall scripts
30 | EOS
31 |
32 | abort unpack_usage if ARGV.empty?
33 | identifier_prefix = if ARGV.include? '--identifier-prefix'
34 | ARGV.next.chomp(".")
35 | else
36 | 'org.homebrew'
37 | end
38 |
39 | f = Formulary.factory ARGV.last
40 | # raise FormulaUnspecifiedError if formulae.empty?
41 | # formulae.each do |f|
42 | name = f.name
43 | identifier = identifier_prefix + ".#{name}"
44 | version = f.version.to_s
45 | version += "_#{f.revision}" if f.revision.to_s != '0'
46 |
47 | # Make sure it's installed first
48 | if not f.any_version_installed?
49 | onoe "#{f.name} is not installed. First install it with 'brew install #{f.name}'."
50 | abort
51 | end
52 |
53 | # Setup staging dir
54 | pkg_root = Dir.mktmpdir 'brew-pkg'
55 | staging_root = pkg_root + HOMEBREW_PREFIX
56 | ohai "Creating package staging root using Homebrew prefix #{HOMEBREW_PREFIX}"
57 | FileUtils.mkdir_p staging_root
58 |
59 |
60 | pkgs = [f]
61 |
62 | # Add deps if we specified --with-deps
63 | pkgs += f.recursive_dependencies if ARGV.include? '--with-deps'
64 |
65 | pkgs.each do |pkg|
66 | formula = Formulary.factory(pkg.to_s)
67 | dep_version = formula.version.to_s
68 | dep_version += "_#{formula.revision}" if formula.revision.to_s != '0'
69 |
70 |
71 | ohai "Staging formula #{formula.name}"
72 | # Get all directories for this keg, rsync to the staging root
73 |
74 | if File.exist?(File.join(HOMEBREW_CELLAR, formula.name, dep_version))
75 |
76 | dirs = Pathname.new(File.join(HOMEBREW_CELLAR, formula.name, dep_version)).children.select { |c| c.directory? }.collect { |p| p.to_s }
77 |
78 |
79 | dirs.each {|d| safe_system "rsync", "-a", "#{d}", "#{staging_root}/" }
80 |
81 |
82 | if File.exist?("#{HOMEBREW_CELLAR}/#{formula.name}/#{dep_version}") and not ARGV.include? '--without-kegs'
83 |
84 | ohai "Staging directory #{HOMEBREW_CELLAR}/#{formula.name}/#{dep_version}"
85 |
86 | safe_system "mkdir", "-p", "#{staging_root}/Cellar/#{formula.name}/"
87 | safe_system "rsync", "-a", "#{HOMEBREW_CELLAR}/#{formula.name}/#{dep_version}", "#{staging_root}/Cellar/#{formula.name}/"
88 | end
89 |
90 | end
91 |
92 | # Write out a LaunchDaemon plist if we have one
93 | if formula.service?
94 | ohai "Plist found at #{formula.plist_name}, staging for /Library/LaunchDaemons/#{formula.plist_name}.plist"
95 | launch_daemon_dir = File.join staging_root, "Library", "LaunchDaemons"
96 | FileUtils.mkdir_p launch_daemon_dir
97 | fd = File.new(File.join(launch_daemon_dir, "#{formula.plist_name}.plist"), "w")
98 | fd.write formula.service.to_plist
99 | fd.close
100 | end
101 | end
102 |
103 | # Add scripts if we specified --scripts
104 | found_scripts = false
105 | if ARGV.include? '--scripts'
106 | scripts_path = ARGV.next
107 | if File.directory?(scripts_path)
108 | pre = File.join(scripts_path,"preinstall")
109 | post = File.join(scripts_path,"postinstall")
110 | if File.exist?(pre)
111 | File.chmod(0755, pre)
112 | found_scripts = true
113 | ohai "Adding preinstall script"
114 | end
115 | if File.exist?(post)
116 | File.chmod(0755, post)
117 | found_scripts = true
118 | ohai "Adding postinstall script"
119 | end
120 | end
121 | if not found_scripts
122 | opoo "No scripts found in #{scripts_path}"
123 | end
124 | end
125 |
126 | # Custom ownership
127 | found_ownership = false
128 | if ARGV.include? '--ownership'
129 | custom_ownership = ARGV.next
130 | if ['recommended', 'preserve', 'preserve-other'].include? custom_ownership
131 | found_ownership = true
132 | ohai "Setting pkgbuild option --ownership with value #{custom_ownership}"
133 | else
134 | opoo "#{custom_ownership} is not a valid value for pkgbuild --ownership option, ignoring"
135 | end
136 | end
137 |
138 | # Build it
139 | pkgfile = "#{name}-#{version}.pkg"
140 | ohai "Building package #{pkgfile}"
141 | args = [
142 | "--quiet",
143 | "--root", "#{pkg_root}",
144 | "--identifier", identifier,
145 | "--version", version
146 | ]
147 | if found_scripts
148 | args << "--scripts"
149 | args << scripts_path
150 | end
151 | if found_ownership
152 | args << "--ownership"
153 | args << custom_ownership
154 | end
155 | args << "#{pkgfile}"
156 | safe_system "pkgbuild", *args
157 |
158 | FileUtils.rm_rf pkg_root
159 | end
160 | end
161 |
162 | Homebrew.pkg
163 |
--------------------------------------------------------------------------------