Skip to content

Instantly share code, notes, and snippets.

@alebcay
Last active October 25, 2023 23:48
Show Gist options
  • Save alebcay/9199899 to your computer and use it in GitHub Desktop.
Save alebcay/9199899 to your computer and use it in GitHub Desktop.
Quickly export your Homebrew and Homebrew-Cask settings: the configured taps, installed formulae, and installed casks.
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "COOLER" "7" "February 2014" "" ""
.
.SH "NAME"
\fBcooler\fR \- import and export homebrew settings
.
.SH "SYNOPSIS"
\fBname import name_of_cooler_bundle\fR
.
.P
\fBname export name_of_cooler_bundle\fR
.
.SH "EXAMPLES"
\fBname import /subDirectory/bundle\fR
.
.P
\fBname import /subDirectory/bundle\fR
.
.P
where the bundle file is named \fBbundle\.cb\fR located in a subdirectory named \fBsubDirectory\fR\.
.
.SH "DESCRIPTION"
cooler is a tool for importing and exporting the list of Homebrew taps, Homebrew packages currently installed, and Homebrew Cask applications\. Three records containing this information is then compressed with with GZip and the resulting file with \fB\.cb\fR extension can be transferred to another computer, and then be imported to install the packages on the first computer onto other computers\.
.
.SH "INTERNAL PACKAGE STRUCTURE"
cooler bundles are stored in \fB\.cb\fR files (short for \fBC\fRooler \fBB\fRundle), which are secretly just \fB\.tar\.gz\fR archives, but a custom extension is used to avoid accidental decompression and tampering\. cooler bundles contain three \fB\.cr\fR files: \fBbrew\.cr\fR, \fBcask\.cr\fR, and \fBtap\.cr\fR (\fB\.cr\fR is short for \fBC\fRooler \fBR\fResource)\. Each contains a list of packages (or taps) installed on the machine at export time\. The files are then compressed and bundled\.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='content-type' value='text/html;charset=utf8'>
<meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
<title>cooler(7) - import and export homebrew settings</title>
<style type='text/css' media='all'>
/* style: man */
body#manpage {margin:0}
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
.mp h2 {margin:10px 0 0 0}
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
.mp h3 {margin:0 0 0 4ex}
.mp dt {margin:0;clear:left}
.mp dt.flush {float:left;width:8ex}
.mp dd {margin:0 0 0 9ex}
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
.mp pre {margin-bottom:20px}
.mp pre+h2,.mp pre+h3 {margin-top:22px}
.mp h2+pre,.mp h3+pre {margin-top:5px}
.mp img {display:block;margin:auto}
.mp h1.man-title {display:none}
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
.mp h2 {font-size:16px;line-height:1.25}
.mp h1 {font-size:20px;line-height:2}
.mp {text-align:justify;background:#fff}
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
.mp u {text-decoration:underline}
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
.mp b.man-ref {font-weight:normal;color:#434241}
.mp pre {padding:0 4ex}
.mp pre code {font-weight:normal;color:#434241}
.mp h2+pre,h3+pre {padding-left:0}
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
ol.man-decor {width:100%}
ol.man-decor li.tl {text-align:left}
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
ol.man-decor li.tr {text-align:right;float:right}
</style>
</head>
<!--
The following styles are deprecated and will be removed at some point:
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
.man-navigation should be used instead.
-->
<body id='manpage'>
<div class='mp' id='man'>
<div class='man-navigation' style='display:none'>
<a href="#NAME">NAME</a>
<a href="#SYNOPSIS">SYNOPSIS</a>
<a href="#EXAMPLES">EXAMPLES</a>
<a href="#DESCRIPTION">DESCRIPTION</a>
<a href="#INTERNAL-PACKAGE-STRUCTURE">INTERNAL PACKAGE STRUCTURE</a>
</div>
<ol class='man-decor man-head man head'>
<li class='tl'>cooler(7)</li>
<li class='tc'></li>
<li class='tr'>cooler(7)</li>
</ol>
<h2 id="NAME">NAME</h2>
<p class="man-name">
<code>cooler</code> - <span class="man-whatis">import and export homebrew settings</span>
</p>
<h2 id="SYNOPSIS">SYNOPSIS</h2>
<p><code>name import name_of_cooler_bundle</code></p>
<p><code>name export name_of_cooler_bundle</code></p>
<h2 id="EXAMPLES">EXAMPLES</h2>
<p><code>name import /subDirectory/bundle</code></p>
<p><code>name import /subDirectory/bundle</code></p>
<p>where the bundle file is named <code>bundle.cb</code> located in a subdirectory named <code>subDirectory</code>.</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
<p>cooler is a tool for importing and exporting the list of Homebrew taps, Homebrew packages currently installed, and Homebrew Cask applications. Three records containing this information is then compressed with with GZip and the resulting file with <code>.cb</code> extension can be transferred to another computer, and then be imported to install the packages on the first computer onto other computers.</p>
<h2 id="INTERNAL-PACKAGE-STRUCTURE">INTERNAL PACKAGE STRUCTURE</h2>
<p>cooler bundles are stored in <code>.cb</code> files (short for <strong>C</strong>ooler <strong>B</strong>undle), which are secretly just <code>.tar.gz</code> archives, but a custom extension is used to avoid accidental decompression and tampering. cooler bundles contain three <code>.cr</code> files: <code>brew.cr</code>, <code>cask.cr</code>, and <code>tap.cr</code> (<code>.cr</code> is short for <strong>C</strong>ooler <strong>R</strong>esource). Each contains a list of packages (or taps) installed on the machine at export time. The files are then compressed and bundled.</p>
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>February 2014</li>
<li class='tr'>cooler(7)</li>
</ol>
</div>
</body>
</html>
#!/bin/bash
importTaps()
{
while read p; do
echo -ne "[ \033[1;34mINSTALLING\033[22;0m ] Configuring tap: $p"
( brew tap $p >/dev/null 2>&1 && echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Configuring tap: $p" ) || echo -e "\r\033[K[ \033[1;31mFAILED\033[22;0m ] Configuring tap: $p"
done < "$ARCDIR/tap.cr"
}
importCasks()
{
while read p; do
echo -ne "[ \033[1;34mINSTALLING\033[22;0m ] Installing cask: $p"
( brew cask install $p >/dev/null 2>&1 && echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Installing cask: $p" ) || echo -e "\r\033[K[ \033[1;31mFAILED\033[22;0m ] Installing cask: $p"
done < "$ARCDIR/cask.cr"
}
importBrews()
{
while read p; do
success=false
echo -ne "[ \033[1;34mINSTALLING\033[22;0m ] Installing formula: $p"
brew install "$p" > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Installing formula: $p" && success=true
else
while read q; do
brew install "$q/$p" >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Installing formula: $q/$p" && success=true
fi
done < "$ARCDIR/tap.cr"
fi
if [ "$success" = "false" ]; then
echo -e "\r\033[K[ \033[1;31mFAILED\033[22;0m ] Installing formula: $p"
fi
done < "$ARCDIR/brew.cr"
}
if [ "$1" == "export" ]
then
echo -e "Creating working directory..."
rm -rf "./$2" >/dev/null ; mkdir "$2"
echo -e "Reading configured taps..."
brew tap > "$2/tap.cr"
echo -e "Reading installed formulae..."
brew list | tr " " "\n" > "$2/brew.cr"
echo -e "Reading installed casks..."
brew cask list | tr " " "\n" > "$2/cask.cr"
tar -czf "$2.cb" "./$2" >/dev/null
rm -rf "./$2" >/dev/null
exit 0;
fi
if [ "$1" == "import" ]
then
echo -ne "[ \033[1;33mINSTALLING\033[22;0m ] Installing dependency: Homebrew"
( command -v brew >/dev/null 2>&1 && echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Installing dependency: Homebrew" ) || (rm -rf /usr/local/Cellar /usr/local/.git ; brew cleanup >/dev/null 2>&1; yes | ruby -e "$(curl -fsSL https://gist.githubusercontent.com/alebcay/9199899/raw/3dcb12b566f124af96d696b6394e649f441fda98/installbrew)" >/dev/null 2>&1)
if [ "$?" == 0 ]
then
echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Installing dependency: Homebrew"
else
echo -e "\r\033[K[ \033[1;31mFAILED\033[22;0m ] Installing dependency: Homebrew"
fi
echo -ne "[ \033[1;33mINSTALLING\033[22;0m ] Updating Homebrew"
( brew update >/dev/null 2>&1 && echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Updating Homebrew" ) || echo -e "\r\033[K[ \033[1;31mFAILED\033[22;0m ] Updating Homebrew"
echo -ne "[ \033[1;33mINSTALLING\033[22;0m ] Upgrading isntalled formulae"
( brew upgrade >/dev/null 2>&1 && echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Upgrading installed formulae" ) || echo -e "\r\033[K[ \033[1;31mFAILED\033[22;0m ] Upgrading installed formulae"
ARCDIR="$2"
tar xzf "$2.cb"
importTaps
importBrews
[ -s "$2/cask.cr" ] && ( echo -ne "[ \033[1;33mINSTALLING\033[22;0m ] Installing dependency: Homebrew-Cask" && ( brew install phinze/cask/brew-cask >/dev/null 2>&1 && echo -e "\r\033[K[ \033[1;32mDONE\033[22;0m ] Installing dependency: Homebrew-Cask" ) || echo -e "\r\033[K[ \033[1;31mFAILED\033[22;0m ] Installing dependency: Homebrew-Cask")
importCasks
rm -rf "$ARCDIR"
fi
#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
# This script installs to /usr/local only. To install elsewhere you can just
# untar https://github.com/Homebrew/homebrew/tarball/master anywhere you like or
# change the value of HOMEBREW_PREFIX.
HOMEBREW_PREFIX = '/usr/local'
module Tty extend self
def blue; bold 34; end
def white; bold 39; end
def red; underline 31; end
def reset; escape 0; end
def bold n; escape "1;#{n}" end
def underline n; escape "4;#{n}" end
def escape n; "\033[#{n}m" if STDOUT.tty? end
end
class Array
def shell_s
cp = dup
first = cp.shift
cp.map{ |arg| arg.gsub " ", "\\ " }.unshift(first) * " "
end
end
def ohai *args
puts "#{Tty.blue}==>#{Tty.white} #{args.shell_s}#{Tty.reset}"
end
def warn warning
puts "#{Tty.red}Warning#{Tty.reset}: #{warning.chomp}"
end
def system *args
abort "Failed during: #{args.shell_s}" unless Kernel.system *args
end
def sudo *args
args = if args.length > 1
args.unshift "/usr/bin/sudo"
else
"/usr/bin/sudo #{args.first}"
end
ohai *args
system *args
end
def getc # NOTE only tested on OS X
system "/bin/stty raw -echo"
if RUBY_VERSION >= '1.8.7'
STDIN.getbyte
else
STDIN.getc
end
ensure
system "/bin/stty -raw echo"
end
def wait_for_user
puts
puts "Press RETURN to continue or any other key to abort"
# c = getc
# we test for \r and \n because some stuff does \r instead
# abort unless c == 13 or c == 10
end
module Version
def <=>(other)
split(".").map { |i| i.to_i } <=> other.split(".").map { |i| i.to_i }
end
end
def macos_version
@macos_version ||= `/usr/bin/sw_vers -productVersion`.chomp[/10\.\d+/].extend(Version)
end
def git
@git ||= if ENV['GIT'] and File.executable? ENV['GIT']
ENV['GIT']
elsif Kernel.system '/usr/bin/which -s git'
'git'
else
s = `xcrun -find git 2>/dev/null`.chomp
s if $? and not s.empty?
end
return unless @git
# Github only supports HTTPS fetches on 1.7.10 or later:
# https://help.github.com/articles/https-cloning-errors
`#{@git} --version` =~ /git version (\d\.\d+\.\d+)/
return if $1.nil? or $1 < "1.7.10"
@git
end
# The block form of Dir.chdir fails later if Dir.CWD doesn't exist which I
# guess is fair enough. Also sudo prints a warning message for no good reason
Dir.chdir "/usr"
####################################################################### script
abort "MacOS too old, see: https://github.com/mistydemeo/tigerbrew" if macos_version < "10.5"
abort "Don't run this as root!" if Process.uid == 0
abort <<-EOABORT unless `groups`.split.include? "admin"
This script requires the user #{ENV['USER']} to be an Administrator. If this
sucks for you then you can install Homebrew in your home directory or however
you please; please refer to our homepage. If you still want to use this script
set your user to be an Administrator in System Preferences or `su' to a
non-root user with Administrator privileges.
EOABORT
abort <<-EOABORT unless Dir["#{HOMEBREW_PREFIX}/.git/*"].empty?
It appears Homebrew is already installed. If your intent is to reinstall you
should do the following before running this installer again:
rm -rf #{HOMEBREW_PREFIX}/Cellar #{HOMEBREW_PREFIX}/.git && brew cleanup
EOABORT
# Tests will fail if the prefix exists, but we don't have execution
# permissions. Abort in this case.
abort <<-EOABORT if File.directory? HOMEBREW_PREFIX and not File.executable? HOMEBREW_PREFIX
The Homebrew prefix, #{HOMEBREW_PREFIX}, exists but is not searchable. If this is
not intentional, please restore the default permissions and try running the
installer again:
sudo chmod 755 #{HOMEBREW_PREFIX}
EOABORT
ohai "This script will install:"
puts "#{HOMEBREW_PREFIX}/bin/brew"
puts "#{HOMEBREW_PREFIX}/Library/..."
puts "#{HOMEBREW_PREFIX}/share/man/man1/brew.1"
chmods = %w( . bin etc include lib lib/pkgconfig Library sbin share var var/log share/locale share/man
share/man/man1 share/man/man2 share/man/man3 share/man/man4
share/man/man5 share/man/man6 share/man/man7 share/man/man8
share/info share/doc share/aclocal ).
map{ |d| "#{HOMEBREW_PREFIX}/#{d}" }.
select{ |d| File.directory? d and (not File.readable? d or not File.writable? d or not File.executable? d) }
chgrps = chmods.reject{ |d| File.stat(d).grpowned? }
unless chmods.empty?
ohai "The following directories will be made group writable:"
puts *chmods
end
unless chgrps.empty?
ohai "The following directories will have their group set to #{Tty.underline 39}admin#{Tty.reset}:"
puts *chgrps
end
wait_for_user if STDIN.tty?
if File.directory? HOMEBREW_PREFIX
sudo "/bin/chmod", "g+rwx", *chmods unless chmods.empty?
sudo "/usr/bin/chgrp", "admin", *chgrps unless chgrps.empty?
else
sudo "/bin/mkdir #{HOMEBREW_PREFIX}"
sudo "/bin/chmod g+rwx #{HOMEBREW_PREFIX}"
# the group is set to wheel by default for some reason
sudo "/usr/bin/chgrp admin #{HOMEBREW_PREFIX}"
end
if macos_version > "10.8"
unless File.exist? "/Library/Developer/CommandLineTools/usr/bin/clang"
ohai "Installing the Command Line Tools (expect a GUI popup):"
sudo "/usr/bin/xcode-select", "--install"
puts "Press any key when the installation has completed."
getc
end
end
ohai "Downloading and installing Homebrew..."
Dir.chdir HOMEBREW_PREFIX do
if git
# we do it in four steps to avoid merge errors when reinstalling
system git, "init", "-q"
system git, "remote", "add", "origin", "https://github.com/Homebrew/homebrew"
args = git, "fetch", "origin", "master:refs/remotes/origin/master", "-n"
args << "--depth=1" if ARGV.include? "--fast"
system *args
system git, "reset", "--hard", "origin/master"
else
# -m to stop tar erroring out if it can't modify the mtime for root owned directories
# pipefail to cause the exit status from curl to propogate if it fails
# we use -k for curl because Leopard has a bunch of bad SSL certificates
curl_flags = "fsSL"
curl_flags << "k" if macos_version <= "10.5"
system "/bin/bash -o pipefail -c '/usr/bin/curl -#{curl_flags} https://github.com/Homebrew/homebrew/tarball/master | /usr/bin/tar xz -m --strip 1'"
end
end
warn "#{HOMEBREW_PREFIX}/bin is not in your PATH." unless ENV['PATH'].split(':').include? "#{HOMEBREW_PREFIX}/bin"
if macos_version < "10.9" and macos_version > "10.6"
`/usr/bin/cc --version 2> /dev/null` =~ %r[clang-(\d{2,})]
version = $1.to_i
warn %{Install the "Command Line Tools for Xcode": https://developer.apple.com/downloads/} if version < 425
else
warn "Now install Xcode: https://developer.apple.com/xcode/" unless File.exist? "/usr/bin/cc"
end
ohai "Installation successful!"
puts "You should run `brew doctor' *before* you install anything."
puts "Now type: brew help"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment