Last active
November 3, 2016 07:36
-
-
Save frankel/78b95bc682a44916c45acc30b85eca5d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# This script installs only to /usr/local on Mac or ~/.linuxbrew on Linux. | |
# To install elsewhere you can just untar | |
# https://github.com/Homebrew/homebrew/tarball/master anywhere you like or | |
# change the value of HOMEBREW_PREFIX. | |
def mac? | |
/darwin/i === RUBY_PLATFORM | |
end | |
def linux? | |
/linux/i === RUBY_PLATFORM | |
end | |
if mac? | |
HOMEBREW_NAME = "Homebrew" | |
HOMEBREW_PREFIX = "/usr/local" | |
HOMEBREW_CACHE = "/Library/Caches/Homebrew" | |
HOMEBREW_REPO = "https://github.com/Homebrew/brew" | |
else | |
HOMEBREW_NAME = "Linuxbrew" | |
HOMEBREW_PREFIX = "#{ENV["HOME"]}/.linuxbrew" | |
HOMEBREW_CACHE = "#{ENV["HOME"]}/.cache/Homebrew" | |
HOMEBREW_REPO = "https://github.com/Linuxbrew/brew" | |
end | |
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 | |
ohai "/usr/bin/sudo", *args | |
system "/usr/bin/sudo", *args | |
end | |
def getc # NOTE only tested on OS X | |
system "/bin/stty raw -echo" | |
if STDIN.respond_to?(:getbyte) | |
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 | |
class Version | |
include Comparable | |
attr_reader :parts | |
def initialize(str) | |
@parts = str.split(".").map { |i| i.to_i } | |
end | |
def <=>(other) | |
parts <=> self.class.new(other).parts | |
end | |
end | |
def macos_version | |
return nil unless mac? | |
@macos_version ||= Version.new(`/usr/bin/sw_vers -productVersion`.chomp[/10\.\d+/]) | |
end | |
def should_install_command_line_tools? | |
return false if !mac? || macos_version < "10.9" | |
developer_dir = `/usr/bin/xcode-select -print-path 2>/dev/null`.chomp | |
developer_dir.empty? || !File.exist?("#{developer_dir}/usr/bin/git") | |
end | |
def git | |
@git ||= if ENV['GIT'] and File.executable? ENV['GIT'] | |
ENV['GIT'] | |
elsif Kernel.system '/usr/bin/which git >/dev/null' | |
'git' | |
else | |
exe = `xcrun -find git 2>/dev/null`.chomp | |
exe if $? && $?.success? && !exe.empty? && File.executable?(exe) | |
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 Version.new($1) < "1.7.10" | |
@git | |
end | |
def chmod?(d) | |
File.directory?(d) && !(File.readable?(d) && File.writable?(d) && File.executable?(d)) | |
end | |
def chown?(d) | |
!File.owned?(d) | |
end | |
def chgrp?(d) | |
!File.grpowned?(d) | |
end | |
# return the shell profile file based on users' preference shell | |
def shell_profile | |
case ENV["SHELL"] | |
when %r{/(ba)?sh} then "~/.bash_profile" | |
when %r{/zsh} then "~/.zshrc" | |
when %r{/ksh} then "~/.kshrc" | |
else "~/.bash_profile" | |
end | |
end | |
# Invalidate sudo timestamp before exiting | |
at_exit { Kernel.system "/usr/bin/sudo", "-k" } | |
# 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 mac? && macos_version < "10.6" | |
#abort "Don't run this as root!" if Process.uid == 0 | |
abort <<-EOABORT unless !mac? || `dsmemberutil checkmembership -U "#{ENV['USER']}" -G admin`.include?("user is a member") | |
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 | |
contents = Dir.glob(HOMEBREW_PREFIX+"*/{*,.git*}").join(" ").gsub!(%r{#{HOMEBREW_PREFIX}/}, "") | |
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: | |
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/#{HOMEBREW_NAME}/install/master/uninstall)" | |
The current contents of #{HOMEBREW_PREFIX} are #{contents} | |
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 775 #{HOMEBREW_PREFIX} | |
EOABORT | |
abort <<-EOABORT if `/usr/bin/xcrun clang 2>&1` =~ /license/ && !$?.success? | |
You have not agreed to the Xcode license. | |
Before running the installer again please agree to the license by opening | |
Xcode.app or running: | |
sudo xcodebuild -license | |
EOABORT | |
ohai "This script will install:" | |
puts "#{HOMEBREW_PREFIX}/bin/brew" | |
puts "#{HOMEBREW_PREFIX}/Library/..." | |
puts "#{HOMEBREW_PREFIX}/share/doc/homebrew" | |
puts "#{HOMEBREW_PREFIX}/share/man/man1/brew.1" | |
puts "#{HOMEBREW_PREFIX}/share/zsh/site-functions/_brew" | |
puts "#{HOMEBREW_PREFIX}/etc/bash_completion.d/brew" | |
puts "#{HOMEBREW_CACHE}/" | |
chmods = %w( . bin etc etc/bash_completion.d 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 share/zsh share/zsh/site-functions ). | |
map { |d| File.join(HOMEBREW_PREFIX, d) }.select { |d| chmod?(d) } | |
chowns = chmods.select { |d| chown?(d) } | |
chgrps = chmods.select { |d| chgrp?(d) } | |
unless chmods.empty? | |
ohai "The following directories will be made group writable:" | |
puts(*chmods) | |
end | |
unless chowns.empty? | |
ohai "The following directories will have their owner set to #{Tty.underline 39}#{ENV['USER']}#{Tty.reset}:" | |
puts(*chowns) | |
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 !mac? | |
system "/bin/mkdir", "-p", HOMEBREW_PREFIX | |
elsif File.directory? HOMEBREW_PREFIX | |
sudo "/bin/chmod", "g+rwx", *chmods unless chmods.empty? | |
sudo "/usr/sbin/chown", ENV['USER'], *chowns unless chowns.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/sbin/chown", "#{ENV['USER']}:admin", HOMEBREW_PREFIX | |
end | |
if !mac? | |
system "/bin/mkdir", "-p", HOMEBREW_CACHE | |
else | |
sudo "/bin/mkdir", HOMEBREW_CACHE unless File.directory? HOMEBREW_CACHE | |
sudo "/bin/chmod", "g+rwx", HOMEBREW_CACHE if chmod? HOMEBREW_CACHE | |
sudo "/usr/sbin/chown", ENV['USER'], HOMEBREW_CACHE if chown? HOMEBREW_CACHE | |
sudo "/usr/bin/chgrp", "admin", HOMEBREW_CACHE if chgrp? HOMEBREW_CACHE | |
end | |
if should_install_command_line_tools? | |
ohai "Searching online for the Command Line Tools" | |
# This temporary file prompts the 'softwareupdate' utility to list the Command Line Tools | |
clt_placeholder = "/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress" | |
sudo "/usr/bin/touch", clt_placeholder | |
clt_label = `softwareupdate -l | grep -B 1 -E "Command Line (Developer|Tools)" | awk -F"*" '/^ +\\*/ {print $2}' | sed 's/^ *//' | head -n1`.chomp | |
ohai "Installing #{clt_label}" | |
sudo "/usr/sbin/softwareupdate", "-i", clt_label | |
sudo "/bin/rm", "-f", clt_placeholder | |
end | |
# Headless install may have failed, so fallback to original 'xcode-select' method | |
if should_install_command_line_tools? | |
if STDIN.tty? | |
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 | |
else | |
abort "Error: Cannot proceed with manual Command Line Tools install without user input!" | |
end | |
end | |
ohai "Downloading and installing #{HOMEBREW_NAME}..." | |
Dir.chdir HOMEBREW_PREFIX do | |
if git | |
# we do it in four steps to avoid merge errors when reinstalling | |
system git, "init", "-q" | |
# "git remote add" will fail if the remote is defined in the global config | |
system git, "config", "remote.origin.url", HOMEBREW_REPO | |
system git, "config", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*" | |
# ensure we don't munge line endings on checkout | |
system git, "config", "core.autocrlf", "false" | |
args = git, "fetch", "origin", "master:refs/remotes/origin/master", "-n" | |
args << "--depth=1" unless ARGV.include?("--full") || !ENV["HOMEBREW_DEVELOPER"].nil? | |
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 propagate if it fails | |
curl_flags = "fsSL" | |
system "/bin/bash -o pipefail -c '/usr/bin/curl -#{curl_flags} #{HOMEBREW_REPO}/tarball/master | tar xz -m --strip 1'" | |
end | |
end | |
# no analytics during installation | |
ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1" | |
system "#{HOMEBREW_PREFIX}/bin/brew", "tap", "homebrew/core" | |
warn "#{HOMEBREW_PREFIX}/bin is not in your PATH." unless ENV['PATH'].split(':').include? "#{HOMEBREW_PREFIX}/bin" | |
ohai "Installation successful!" | |
ohai "Next steps" | |
if !mac? | |
puts <<-EOS | |
Install the Linuxbrew dependencies: | |
#{Tty.white}Debian, Ubuntu, etc.:#{Tty.reset} | |
`sudo apt-get install build-essential` | |
#{Tty.white}Fedora, Red Hat, CentOS, etc.:#{Tty.reset} | |
`sudo yum groupinstall 'Development Tools'` | |
See http://linuxbrew.sh/#dependencies for more information. | |
Add to your #{Tty.white}#{shell_profile}#{Tty.reset} by running | |
echo 'export PATH="#{HOMEBREW_PREFIX}/bin:$PATH"' >>#{shell_profile} | |
echo 'export MANPATH="#{HOMEBREW_PREFIX}/share/man:$MANPATH"' >>#{shell_profile} | |
echo 'export INFOPATH="#{HOMEBREW_PREFIX}/share/info:$INFOPATH"' >>#{shell_profile} | |
EOS | |
elsif macos_version < "10.9" && macos_version > "10.6" | |
`/usr/bin/cc --version 2> /dev/null` =~ %r[clang-(\d{2,})] | |
version = $1.to_i | |
puts "Install the #{Tty.white}Command Line Tools for Xcode#{Tty.reset}: https://developer.apple.com/downloads" if mac? && version < 425 | |
else | |
puts "Install #{Tty.white}Xcode#{Tty.reset}: https://developer.apple.com/xcode" unless File.exist? "/usr/bin/cc" | |
end | |
puts "Run `brew help` to get started" | |
puts "Further documentation: https://git.io/brew-docs" | |
ohai "Homebrew has enabled anonymous aggregate user behaviour analytics" | |
puts "Read the analytics documentation (and how to opt-out) here:" | |
puts " https://git.io/brew-analytics" | |
if git | |
Dir.chdir HOMEBREW_PREFIX do | |
system git, "config", "--local", "--replace-all", "homebrew.analyticsmessage", "true" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment