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 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
|
#!/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}
We recommend you install #{Tty.white}GCC#{Tty.reset} by running `brew install gcc`.
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
|