diff --git a/install-origin.sh b/install-origin.sh new file mode 100755 index 0000000..6d3596b --- /dev/null +++ b/install-origin.sh @@ -0,0 +1,727 @@ +#!/bin/bash +set -u + +# Check if script is run non-interactively (e.g. CI) +# If it is run non-interactively we should not prompt for passwords. +if [[ ! -t 0 || -n "${CI-}" ]]; then + NONINTERACTIVE=1 +fi + +abort() { + printf "%s\n" "$1" + exit 1 +} + +# First check OS. +OS="$(uname)" +if [[ "$OS" == "Linux" ]]; then + HOMEBREW_ON_LINUX=1 +elif [[ "$OS" != "Darwin" ]]; then + abort "Homebrew is only supported on macOS and Linux." +fi + +UNAME_MACHINE="$(uname -m)" + +# Required installation paths. To install elsewhere (which is unsupported) +# you can untar https://github.com/Homebrew/brew/tarball/master +# anywhere you like. +if [[ -z "${HOMEBREW_ON_LINUX-}" ]]; then + if [[ "$UNAME_MACHINE" == "arm64" ]]; then + # On ARM macOS, this script installs to /opt/homebrew only + HOMEBREW_PREFIX="/opt/homebrew" + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}" + else + # On Intel macOS, this script installs to /usr/local only + HOMEBREW_PREFIX="/usr/local" + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}/Homebrew" + fi + HOMEBREW_CACHE="${HOME}/Library/Caches/Homebrew" + HOMEBREW_CORE_GIT_REMOTE="https://github.com/Homebrew/homebrew-core" + + STAT="stat -f" + CHOWN="/usr/sbin/chown" + CHGRP="/usr/bin/chgrp" + GROUP="admin" + TOUCH="/usr/bin/touch" +else + # On Linux, it installs to /home/linuxbrew/.linuxbrew if you have sudo access + # and ~/.linuxbrew (which is unsupported) if run interactively. + HOMEBREW_PREFIX_DEFAULT="/home/linuxbrew/.linuxbrew" + HOMEBREW_CACHE="${HOME}/.cache/Homebrew" + HOMEBREW_CORE_GIT_REMOTE="https://github.com/Homebrew/linuxbrew-core" + + STAT="stat --printf" + CHOWN="/bin/chown" + CHGRP="/bin/chgrp" + GROUP="$(id -gn)" + TOUCH="/bin/touch" +fi +HOMEBREW_BREW_GIT_REMOTE="https://github.com/Homebrew/brew" + +# TODO: bump version when new macOS is released or announced +MACOS_NEWEST_UNSUPPORTED="12.0" +# TODO: bump version when new macOS is released +MACOS_OLDEST_SUPPORTED="10.14" + +# For Homebrew on Linux +REQUIRED_RUBY_VERSION=2.6 # https://github.com/Homebrew/brew/pull/6556 +REQUIRED_GLIBC_VERSION=2.13 # https://docs.brew.sh/Homebrew-on-Linux#requirements + +# no analytics during installation +export HOMEBREW_NO_ANALYTICS_THIS_RUN=1 +export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1 + +# string formatters +if [[ -t 1 ]]; then + tty_escape() { printf "\033[%sm" "$1"; } +else + tty_escape() { :; } +fi +tty_mkbold() { tty_escape "1;$1"; } +tty_underline="$(tty_escape "4;39")" +tty_blue="$(tty_mkbold 34)" +tty_red="$(tty_mkbold 31)" +tty_bold="$(tty_mkbold 39)" +tty_reset="$(tty_escape 0)" + +have_sudo_access() { + local -a args + if [[ -n "${SUDO_ASKPASS-}" ]]; then + args=("-A") + elif [[ -n "${NONINTERACTIVE-}" ]]; then + args=("-n") + fi + + if [[ -z "${HAVE_SUDO_ACCESS-}" ]]; then + if [[ -n "${args[*]-}" ]]; then + SUDO="/usr/bin/sudo ${args[*]}" + else + SUDO="/usr/bin/sudo" + fi + if [[ -n "${NONINTERACTIVE-}" ]]; then + ${SUDO} -l mkdir &>/dev/null + else + ${SUDO} -v && ${SUDO} -l mkdir &>/dev/null + fi + HAVE_SUDO_ACCESS="$?" + fi + + if [[ -z "${HOMEBREW_ON_LINUX-}" ]] && [[ "$HAVE_SUDO_ACCESS" -ne 0 ]]; then + abort "Need sudo access on macOS (e.g. the user $USER to be an Administrator)!" + fi + + return "$HAVE_SUDO_ACCESS" +} + +shell_join() { + local arg + printf "%s" "$1" + shift + for arg in "$@"; do + printf " " + printf "%s" "${arg// /\ }" + done +} + +chomp() { + printf "%s" "${1/"$'\n'"/}" +} + +ohai() { + printf "${tty_blue}==>${tty_bold} %s${tty_reset}\n" "$(shell_join "$@")" +} + +warn() { + printf "${tty_red}Warning${tty_reset}: %s\n" "$(chomp "$1")" +} + +execute() { + if ! "$@"; then + abort "$(printf "Failed during: %s" "$(shell_join "$@")")" + fi +} + +execute_sudo() { + local -a args=("$@") + if have_sudo_access; then + if [[ -n "${SUDO_ASKPASS-}" ]]; then + args=("-A" "${args[@]}") + fi + ohai "/usr/bin/sudo" "${args[@]}" + execute "/usr/bin/sudo" "${args[@]}" + else + ohai "${args[@]}" + execute "${args[@]}" + fi +} + +getc() { + local save_state + save_state=$(/bin/stty -g) + /bin/stty raw -echo + IFS= read -r -n 1 -d '' "$@" + /bin/stty "$save_state" +} + +wait_for_user() { + local c + echo + echo "Press RETURN to continue or any other key to abort" + getc c + # we test for \r and \n because some stuff does \r instead + if ! [[ "$c" == $'\r' || "$c" == $'\n' ]]; then + exit 1 + fi +} + +major_minor() { + echo "${1%%.*}.$(x="${1#*.}"; echo "${x%%.*}")" +} + +version_gt() { + [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -gt "${2#*.}" ]] +} +version_ge() { + [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -ge "${2#*.}" ]] +} +version_lt() { + [[ "${1%.*}" -lt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -lt "${2#*.}" ]] +} + +should_install_command_line_tools() { + if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + return 1 + fi + + if version_gt "$macos_version" "10.13"; then + ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] + else + ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] || + ! [[ -e "/usr/include/iconv.h" ]] + fi +} + +get_permission() { + $STAT "%A" "$1" +} + +user_only_chmod() { + [[ -d "$1" ]] && [[ "$(get_permission "$1")" != "755" ]] +} + +exists_but_not_writable() { + [[ -e "$1" ]] && ! [[ -r "$1" && -w "$1" && -x "$1" ]] +} + +get_owner() { + $STAT "%u" "$1" +} + +file_not_owned() { + [[ "$(get_owner "$1")" != "$(id -u)" ]] +} + +get_group() { + $STAT "%g" "$1" +} + +file_not_grpowned() { + [[ " $(id -G "$USER") " != *" $(get_group "$1") "* ]] +} + +# Please sync with 'test_ruby()' in 'Library/Homebrew/utils/ruby.sh' from Homebrew/brew repository. +test_ruby() { + if [[ ! -x $1 ]] + then + return 1 + fi + + "$1" --enable-frozen-string-literal --disable=gems,did_you_mean,rubyopt -rrubygems -e \ + "abort if Gem::Version.new(RUBY_VERSION.to_s.dup).to_s.split('.').first(2) != \ + Gem::Version.new('$REQUIRED_RUBY_VERSION').to_s.split('.').first(2)" 2>/dev/null +} + +no_usable_ruby() { + local ruby_exec + IFS=$'\n' # Do word splitting on new lines only + for ruby_exec in $(which -a ruby); do + if test_ruby "$ruby_exec"; then + IFS=$' \t\n' # Restore IFS to its default value + return 1 + fi + done + IFS=$' \t\n' # Restore IFS to its default value + return 0 +} + +outdated_glibc() { + local glibc_version + glibc_version=$(ldd --version | head -n1 | grep -o '[0-9.]*$' | grep -o '^[0-9]\+\.[0-9]\+') + version_lt "$glibc_version" "$REQUIRED_GLIBC_VERSION" +} + +if [[ -n "${HOMEBREW_ON_LINUX-}" ]] && no_usable_ruby && outdated_glibc +then + abort "$(cat <<-EOFABORT + Homebrew requires Ruby $REQUIRED_RUBY_VERSION which was not found on your system. + Homebrew portable Ruby requires Glibc version $REQUIRED_GLIBC_VERSION or newer, + and your Glibc version is too old. + See ${tty_underline}https://docs.brew.sh/Homebrew-on-Linux#requirements${tty_reset} + Install Ruby $REQUIRED_RUBY_VERSION and add its location to your PATH. + EOFABORT + )" +fi + +# USER isn't always set so provide a fall back for the installer and subprocesses. +if [[ -z "${USER-}" ]]; then + USER="$(chomp "$(id -un)")" + export USER +fi + +# Invalidate sudo timestamp before exiting (if it wasn't active before). +if ! /usr/bin/sudo -n -v 2>/dev/null; then + trap '/usr/bin/sudo -k' EXIT +fi + +# Things can fail later if `pwd` doesn't exist. +# Also sudo prints a warning message for no good reason +cd "/usr" || exit 1 + +####################################################################### script +if ! command -v git >/dev/null; then + abort "$(cat </dev/null; then + abort "$(cat </dev/null; then + ohai "Select the Homebrew installation directory" + echo "- ${tty_bold}Enter your password${tty_reset} to install to ${tty_underline}${HOMEBREW_PREFIX_DEFAULT}${tty_reset} (${tty_bold}recommended${tty_reset})" + echo "- ${tty_bold}Press Control-D${tty_reset} to install to ${tty_underline}$HOME/.linuxbrew${tty_reset}" + echo "- ${tty_bold}Press Control-C${tty_reset} to cancel installation" + fi + if have_sudo_access; then + HOMEBREW_PREFIX="$HOMEBREW_PREFIX_DEFAULT" + else + HOMEBREW_PREFIX="$HOME/.linuxbrew" + fi + trap - SIGINT + fi + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}/Homebrew" +fi +HOMEBREW_CORE="${HOMEBREW_REPOSITORY}/Library/Taps/homebrew/homebrew-core" + +if [[ "${EUID:-${UID}}" == "0" ]]; then + abort "Don't run this as root!" +elif [[ -d "${HOMEBREW_PREFIX}" && ! -x "${HOMEBREW_PREFIX}" ]]; then + abort "$(cat </dev/null || return + + # we do it in four steps to avoid merge errors when reinstalling + execute "git" "init" "-q" + + # "git remote add" will fail if the remote is defined in the global config + execute "git" "config" "remote.origin.url" "${HOMEBREW_BREW_GIT_REMOTE}" + execute "git" "config" "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*" + + # ensure we don't munge line endings on checkout + execute "git" "config" "core.autocrlf" "false" + + execute "git" "fetch" "--force" "origin" + execute "git" "fetch" "--force" "--tags" "origin" + + execute "git" "reset" "--hard" "origin/master" + + if [[ "${HOMEBREW_REPOSITORY}" != "${HOMEBREW_PREFIX}" ]]; then + execute "ln" "-sf" "${HOMEBREW_REPOSITORY}/bin/brew" "${HOMEBREW_PREFIX}/bin/brew" + fi + + if [[ ! -d "${HOMEBREW_CORE}" ]]; then + ohai "Tapping homebrew/core" + ( + execute "/bin/mkdir" "-p" "${HOMEBREW_CORE}" + cd "${HOMEBREW_CORE}" >/dev/null || return + + execute "git" "init" "-q" + execute "git" "config" "remote.origin.url" "${HOMEBREW_CORE_GIT_REMOTE}" + execute "git" "config" "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*" + execute "git" "config" "core.autocrlf" "false" + execute "git" "fetch" "--force" "origin" "refs/heads/master:refs/remotes/origin/master" + execute "git" "remote" "set-head" "origin" "--auto" >/dev/null + execute "git" "reset" "--hard" "origin/master" + + cd "${HOMEBREW_REPOSITORY}" >/dev/null || return + ) || exit 1 + fi + + execute "${HOMEBREW_PREFIX}/bin/brew" "update" "--force" "--quiet" +) || exit 1 + +if [[ ":${PATH}:" != *":${HOMEBREW_PREFIX}/bin:"* ]]; then + warn "${HOMEBREW_PREFIX}/bin is not in your PATH." +fi + +ohai "Installation successful!" +echo + +# Use the shell's audible bell. +if [[ -t 1 ]]; then + printf "\a" +fi + +# Use an extra newline and bold to avoid this being missed. +ohai "Homebrew has enabled anonymous aggregate formulae and cask analytics." +echo "$(cat </dev/null || return + execute "git" "config" "--replace-all" "homebrew.analyticsmessage" "true" + execute "git" "config" "--replace-all" "homebrew.caskanalyticsmessage" "true" +) || exit 1 + +ohai "Next steps:" +if [[ "$UNAME_MACHINE" == "arm64" ]] || [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + case "$SHELL" in + */bash*) + if [[ -r "$HOME/.bash_profile" ]]; then + shell_profile="$HOME/.bash_profile" + else + shell_profile="$HOME/.profile" + fi + ;; + */zsh*) + shell_profile="$HOME/.zprofile" + ;; + *) + shell_profile="$HOME/.profile" + ;; + esac + + cat <> ${shell_profile} + eval \$(${HOMEBREW_PREFIX}/bin/brew shellenv) +EOS +fi + +echo "- Run \`brew help\` to get started" +echo "- Further documentation: " +echo " ${tty_underline}https://docs.brew.sh${tty_reset}" + +if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + echo "- Install the Homebrew dependencies if you have sudo access:" + + if [[ $(command -v apt-get) ]]; then + echo " sudo apt-get install build-essential" + elif [[ $(command -v yum) ]]; then + echo " sudo yum groupinstall 'Development Tools'" + elif [[ $(command -v pacman) ]]; then + echo " sudo pacman -S base-devel" + elif [[ $(command -v apk) ]]; then + echo " sudo apk add build-base" + fi + + cat <