#!/usr/bin/ruby require 'pathname' CURL_VERSION = '7.58.0-1' VENDOR_STASH_URL = 'https://archive.org/download/tigerbrew/' CFILE_PPC_NAME = "portable-curl-#{CURL_VERSION}.tiger_g3.bottle.tar.gz" CFILE_PPC_SHA1 = '4ffee9895f2172ff05ba085ce929add46dddc15b' CFILE_INTEL_NAME = "portable-curl-#{CURL_VERSION}.tiger_i386.bottle.tar.gz" CFILE_INTEL_SHA1 = '6e6e7989adb20856c0473aedecd623f443a6ac55' DEFAULT_PREFIX = ENV['HOMEBREW_PREFIX'] || '/usr/local' DEFAULT_REPO = ENV['HOMEBREW_REPOSITORY'] || '/Users/Shared/Brewery' DOWNLOADS_DIR = "#{ENV['HOME']}/Downloads/" TEMP_CURL_DIR = '/tmp/portable-curl' UNPACKED_CURL = "#{TEMP_CURL_DIR}/#{CURL_VERSION}/bin/curl" GITHUB_REPO = 'https://github.com/gsteemso/leopardbrew' GITHUB_BRANCH = 'master' GIT_FETCH_ORIGIN = "#{GITHUB_BRANCH}:refs/remotes/origin/#{GITHUB_BRANCH}" LBREW_GITHUB_URL = "#{GITHUB_REPO}/archive/refs/heads/#{GITHUB_BRANCH}.zip" GIT_ARCHIVE_DIR = "leopardbrew-#{GITHUB_BRANCH}" GIT_ARCHIVE_NAME = "#{GIT_ARCHIVE_DIR}.zip" class Array def shell_s; cp = dup; first = cp.shift; cp.map{ |arg| arg.gsub ' ', "\\ " }.unshift(first) * ' ' end end class String def choke; s = chomp; s unless s.empty?; end end class Pathname def /(arg); Pathname.new("#{self}/#{arg}"); end end module Trm extend self #“Terminal”: ANSI control sequences def csi; "\033["; end # “Control Sequence Introducer” def set_grcm_cumulative ; "#{csi}21h" ; end # “Graphic Rendition Combination Mode” def sgr(*list); "#{csi}#{list * ';'}m"; end # “Select Graphic Rendition” def rst; '0'; end # reset def bld; '1'; end def uln; '4'; end def blk; '30'; end # black } def red; '31'; end # red } def grn; '32'; end # green } def ylw; '33'; end # yellow } def blu; '34'; end # blue } "display" (foreground) colours. def mag; '35'; end # magenta} def cyn; '36'; end # cyan } def wht; '37'; end # white } def dft; '39'; end # default} def on_blk; '40'; end # black background colour. def _rst(clr = grn); sgr(rst, clr, on_blk); end # reset def _bld(clr = nil); clr ? sgr(bld, clr) : sgr(bld); end def _uln(clr = nil); clr ? sgr(uln, clr) : sgr(uln); end def _blk; sgr(blk); end def _red; sgr(red); end def _grn; sgr(grn); end def _ylw; sgr(ylw); end def _blu; sgr(blu); end def _mag; sgr(mag); end def _cyn; sgr(cyn); end def _wht; sgr(wht); end def _dft; sgr(dft); end end # Trm include Trm def curl return @curl if defined? @curl fetch_vendor_curl! @curl = UNPACKED_CURL end def fetch_vendor_curl! if `uname -m`.chomp == "Power Macintosh" fname = CFILE_PPC_NAME; sha = CFILE_PPC_SHA1 else fname = CFILE_INTEL_NAME; sha = CFILE_INTEL_SHA1 end downloaded_curl = "#{DOWNLOADS_DIR}#{fname}" begin # We must use TenFourFox or some such, because a stock system is now too outdated to # download anything. We’ll then move the downloaded tarball to “/tmp/curl.tar.gz”. puts <<-_ Your system will be asked to open a URL to a gzip’d tar archive. It will probably try to do so using your web browser. When the tarball finishes downloading, you will need to make sure it is in your Downloads folder with the correct name before installation can proceed. _ wait_for_user system %W[open #{VENDOR_STASH_URL}#{fname}], true puts <<-_ As described above, use the Finder to make certain that the file has ended up in your home folder’s Downloads folder, and has this exact name (don’t worry, it will usually have the correct name by default): #{_wht}#{fname}#{_rst} – installation cannot proceed until that file is in that location under that name. DO NOT ATTEMPT TO PROCEED UNTIL IT IS IN PLACE. _ wait_for_user end unless File.file?(downloaded_curl) system %W[cp -fp #{downloaded_curl} /tmp/curl.tar.gz] our_hash = `openssl sha1 /tmp/curl.tar.gz`.chomp.split(' ').last if our_hash != sha abort <<-_ Unable to verify the integrity of the downloaded curl utility. The downloaded file’s SHA1 is “#{our_hash}” but the expected hash is “#{sha}”. _ end Dir.chdir('/tmp') do system %w[/usr/bin/tar -xzf curl.tar.gz] unless File.file?(UNPACKED_CURL) system %w[rm curl.tar.gz] s = IO.read(UNPACKED_CURL).sub('#!/bin/sh', '#!/bin/bash') system %W[/bin/chmod +w #{UNPACKED_CURL}] f = File.open(UNPACKED_CURL, 'wb') f.write(s) f.close system %W[/bin/chmod -w #{UNPACKED_CURL}] end end # fetch_vendor_curl! def getc system %w[/bin/stty raw -echo] RUBY_VERSION >= '1.8.7' ? STDIN.getbyte : STDIN.getc ensure system %w[/bin/stty -raw echo] end # getc def git @git ||= ((g = ENV['GIT'] and File.executable?(g)) ? g : ((g = which 'git') ? g : nil)) return unless @git # Github needs git ≥ 1.7.10 for HTTPS fetches: https://help.github.com/articles/https-cloning-errors `#{@git} --version` =~ /git version (\d\.\d+\.\d+)/ return if $1 < '1.7.10' @git end # git def macos_version @macos_version ||= /(\d\d\.\d+)(\.\d+)?/.match(`/usr/bin/sw_vers -productVersion`).captures.first.to_f end def ohai(arg, *args); oho(arg); puts *args; end def oho(*args); puts "#{_bld(cyn)}==> #{_wht}#{args * ' '}#{_rst}"; end def sudo(*args); args.unshift '/usr/bin/sudo'; system args, true; end def system(args, loud = false); oho *args if loud; abort "Failed during: #{args * ' '}" unless Kernel.system *args.map{ |a| a.to_s }; end def wait_for_user puts "\nPress the space bar to continue, or any other key to abort."; abort unless getc == 32 end def which cmd dir = ENV['PATH'].split(':').find {|p| File.executable? File.join(p, cmd)} File.join(dir, cmd) unless dir.nil? end def recursive_mv(src_pn, src_root, dst_root) src_pn = Pathname.new(src_pn) unless src_pn.is_a? Pathname dst_root = Pathname.new(dst_root) unless dst_root.is_a? Pathname relative = src_pn.to_s.sub(%r{^#{src_root}/}, '') dst_pn = dst_root/relative if dst_pn.exist? and not dst_pn.symlink? if src_pn.directory? and not src_pn.symlink? if dst_pn.directory? and not dst_pn.symlink? # they’re both real directories; process the children src_pn.children.each{ |ch| recursive_mv(ch, src_root, dst_root) } else # destination has replaced directory with a file # do nothing, assume the new version is correct end else # source is not a directory, or at least not a real directory if dst_pn.directory? and not dst_pn.symlink? # destination has been turned into a directory # do nothing, assume the new version is correct else # neither source nor destination are directories, or at least not real ones if src_pn.lstat.mtime > dst_pn.lstat.mtime system %W[mv -f #{src_pn} #{dst_pn}] else # the local version is newer, assume it is correct and do nothing end end end else system %W[mv -f #{src_pn} #{dst_pn}] end end ####################################################################### script # Dir.chdir{&block} 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' puts set_grcm_cumulative, _rst abort "#{_bld(red)}Don’t run this as root!#{_rst}" if Process.uid == 0 ohai 'Welcome to the Leopardbrew installer!', <<_ You must choose two important locations in order to proceed: a /prefix/, and a /repository/. (In the ancestor ’brew projects, Homebrew and Tigerbrew, both were “/usr/local” by default.) Neither is allowed to be at the root level of your filesystem. • The prefix is where the software you install will be put. Unless you have unusual requirements, “/usr/local” is still the best choice. • The repository holds the inner workings of Leopardbrew. We hold that the guts of #{_uln}this#{_rst} software should not clutter a well-known directory also used by #{_uln}other#{_rst} software, so advise against using “/usr/local”; if nothing else, the many other legitimate uses of /usr/local can obfuscate contributions to Leopardbrew. Instead, we recommend using either “/Users/Shared/Brewery” or “/usr/local/Brewery”. _ begin puts "Where do you want your prefix? [hit “return” to keep “#{DEFAULT_PREFIX}”]" pfx = STDIN.gets.choke || DEFAULT_PREFIX end while pfx =~ %r{^/[^/]*$} pfx = Pathname.new(pfx) sudo '/bin/mkdir', '-p', pfx unless pfx.directory? sudo '/bin/chmod', 'g+rwx', pfx sudo '/usr/bin/chgrp', 'admin', pfx # /usr/local defaults to group “wheel” for some reason puts "Using “#{pfx}” for the prefix.\n\n" begin puts "Where do you want to keep the repository? [hit “return” to keep\n“#{DEFAULT_REPO}”]" repo = STDIN.gets.choke || DEFAULT_REPO end while repo =~ %r{^/[^/]*$} repo = Pathname.new(repo) sudo '/bin/mkdir', '-p', repo.to_s unless repo.directory? sudo '/bin/chmod', 'g+rwx', repo.to_s sudo '/usr/sbin/chown', "#{Process.uid}:admin", repo.to_s # the user and/or group may have odd defaults puts "Using “#{repo}” for the repository.\n\n" abort <|#{repo}/Library/Homebrew/vendor/portable-curl-version] system %w[touch ./install-time-marker] end # chdir repo warn "#{pfx}/bin is not in your PATH." unless ENV['PATH'].split(':').include? "#{pfx}/bin" if macos_version < 10.7 warn 'Now install Xcode: https://developer.apple.com/xcode/' unless File.exist? '/usr/bin/cc' else `/usr/bin/cc --version 2> /dev/null` =~ %r[clang-(\d{2,})] version = $1.to_i warn %{Install the “Command Line Tools for Xcode”: http://connect.apple.com} if version and version < 425 end ohai 'Installation successful!', <<_ You should run “brew doctor” #{_bld}before#{_rst} you install anything. Now type: #{_wht}brew help#{_rst} _