From 3e98625d9112396e9a95a1bc075783025f18ebe9 Mon Sep 17 00:00:00 2001 From: neo Date: Fri, 15 Jan 2021 01:06:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install-tsinghua.sh | 730 ++++++++++++++++++++++++++++++++++++++++++++ install.sh | 4 +- lib/install.sh | 727 +++++++++++++++++++++++++++++++++++++++++++ lib/uninstall.sh | 399 ++++++++++++++++++++++++ uninstall.sh | 6 +- 5 files changed, 1863 insertions(+), 3 deletions(-) create mode 100755 install-tsinghua.sh create mode 100755 lib/install.sh create mode 100755 lib/uninstall.sh diff --git a/install-tsinghua.sh b/install-tsinghua.sh new file mode 100755 index 0000000..878fd75 --- /dev/null +++ b/install-tsinghua.sh @@ -0,0 +1,730 @@ +#!/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" + #changed HOMEBREW_CORE_GIT_REMOTE="https://github.com/Homebrew/homebrew-core" + HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git" + + 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" + #changed HOMEBREW_CORE_GIT_REMOTE="https://github.com/Homebrew/linuxbrew-core" + HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git" + + STAT="stat --printf" + CHOWN="/bin/chown" + CHGRP="/bin/chgrp" + GROUP="$(id -gn)" + TOUCH="/bin/touch" +fi +#changed HOMEBREW_BREW_GIT_REMOTE="https://github.com/Homebrew/brew" +HOMEBREW_BREW_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git" + +# 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 </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 </dev/null + else + /usr/bin/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 +} + +resolved_pathname() { realpath "$1"; } + +pretty_print_pathnames() { + local p + for p in "$@"; do + if [[ -h $p ]]; then + printf '%s -> %s\n' "$p" "$(resolved_pathname "$p")" + elif [[ -d $p ]]; then + echo "$p/" + else + echo "$p" + fi + 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 [[ -n "${SUDO_ASKPASS-}" ]]; then + args=("-A" "${args[@]}") + fi + if have_sudo_access; then + ohai "/usr/bin/sudo" "${args[@]}" + system "/usr/bin/sudo" "${args[@]}" + else + ohai "${args[@]}" + system "${args[@]}" + fi +} + +system() { + if ! "$@"; then + warn "Failed during: $(shell_join "$@")" + failed=true + fi +} + +####################################################################### script + +homebrew_prefix_candidates=() + +usage() { + cat <&2 && continue + echo "$HOMEBREW_REPOSITORY/$l" + done <<<"$gitignore" + + if [[ $HOMEBREW_PREFIX != "$HOMEBREW_REPOSITORY" ]]; then + echo "$HOMEBREW_REPOSITORY" + for p in \ + bin/brew \ + etc/bash_completion.d/brew \ + share/doc/homebrew \ + share/man/man1/brew.1 \ + share/man/man1/brew-cask.1 \ + share/zsh/site-functions/_brew \ + share/zsh/site-functions/_brew_cask \ + var/homebrew \ + ; do + echo "$HOMEBREW_PREFIX/$p" + done + else + echo "$HOMEBREW_REPOSITORY/.git" + fi + echo "$HOMEBREW_CELLAR" + echo "$HOMEBREW_PREFIX/Caskroom" + + [[ -n $opt_skip_cache_and_logs ]] || cat <<-EOS + $HOME/Library/Caches/Homebrew + $HOME/Library/Logs/Homebrew + /Library/Caches/Homebrew + $HOME/.cache/Homebrew + ${HOMEBREW_CACHE:-} + ${HOMEBREW_LOGS:-} + EOS + + if [[ $ostype == macos ]]; then + dir_children "/Applications" "$HOME/Applications" | while read -r p2; do + [[ $(resolved_pathname "$p2") == $HOMEBREW_CELLAR/* ]] && echo "$p2" + done + fi +} | while read -r l; do + [[ -e $l ]] && echo "$l" +done | sort -u > "$tmpdir/homebrew_files" +homebrew_files=() +while read -r l; do + homebrew_files+=("$l") +done < "$tmpdir/homebrew_files" + +if [[ -z $opt_quiet ]]; then + dry_str=${opt_dry_run:+would} + warn "This script ${dry_str:-will} remove:" + pretty_print_pathnames "${homebrew_files[@]}" +fi + +if [[ -t 0 && -z $opt_force && -z $opt_dry_run ]]; then + read -rp "Are you sure you want to uninstall Homebrew? This will remove your installed packages! [y/N] " + [[ $REPLY == [yY]* ]] || abort +fi + +[[ -n $opt_quiet ]] || ohai "Removing Homebrew installation..." +paths=() +for p in Frameworks bin etc include lib opt sbin share var; do + p=$HOMEBREW_PREFIX/$p + [[ -e $p ]] && paths+=("$p") +done +if [[ ${#paths[@]} -gt 0 ]]; then + if [[ $ostype == macos ]]; then + args=(-E "${paths[@]}" -regex '.*/info/([^.][^/]*\.info|dir)') + else + args=("${paths[@]}" -regextype posix-extended -regex '.*/info/([^.][^/]*\.info|dir)') + fi + if [[ -n $opt_dry_run ]]; then + args+=(-print) + echo "Would delete:" + else + args+=(-exec /bin/bash -c) + args+=("/usr/bin/install-info --delete --quiet {} \"\$(dirname {})/dir\"") + args+=(';') + fi + system /usr/bin/find "${args[@]}" + args=("${paths[@]}" -type l -lname '*/Cellar/*') + if [[ -n $opt_dry_run ]]; then + args+=(-print) + else + args+=(-exec unlink '{}' ';') + fi + [[ -n $opt_dry_run ]] && echo "Would delete:" + system /usr/bin/find "${args[@]}" +fi + +for file in "${homebrew_files[@]}"; do + if [[ -n $opt_dry_run ]]; then + echo "Would delete ${file}" + else + if ! err=$(rm -fr "$file" 2>&1); then + warn "Failed to delete ${file}" + echo "$err" + fi + fi +done + +sudo() { + ohai "/usr/bin/sudo" "$@" + system /usr/bin/sudo "$@" +} + +[[ -n $opt_quiet ]] || ohai "Removing empty directories..." +paths=() +for p in bin etc include lib opt sbin share var \ + Caskroom Cellar Homebrew Frameworks; do + p=$HOMEBREW_PREFIX/$p + [[ -e $p ]] && paths+=("$p") +done +if [[ ${#paths[@]} -gt 0 ]]; then + if [[ $ostype == macos ]]; then + args=("${paths[@]}" -name .DS_Store) + if [[ -n $opt_dry_run ]]; then + args+=(-print) + echo "Would delete:" + else + args+=(-delete) + fi + execute_sudo /usr/bin/find "${args[@]}" + fi + args=("${paths[@]}" -depth -type d -empty) + if [[ -n $opt_dry_run ]]; then + args+=(-print) + echo "Would remove directories:" + else + args+=(-exec rmdir '{}' ';') + fi + execute_sudo /usr/bin/find "${args[@]}" +fi + +[[ -n $opt_dry_run ]] && exit +if [[ $HOMEBREW_PREFIX != "$homebrew_prefix_default" && -e $HOMEBREW_PREFIX ]]; then + execute_sudo rmdir "$HOMEBREW_PREFIX" +fi +if [[ $HOMEBREW_PREFIX != "$HOMEBREW_REPOSITORY" && -e $HOMEBREW_REPOSITORY ]]; then + execute_sudo rmdir "$HOMEBREW_REPOSITORY" +fi + +if [[ -z $opt_quiet ]]; then + if [[ $failed == true ]]; then + warn "Homebrew partially uninstalled (but there were steps that failed)!" + echo "To finish uninstalling rerun this script with \`sudo\`." + else + ohai "Homebrew uninstalled!" + fi +fi + +dir_children "$HOMEBREW_REPOSITORY" "$HOMEBREW_PREFIX" \ + | sort -u > "$tmpdir/residual_files" + +if [[ -s $tmpdir/residual_files && -z $opt_quiet ]]; then + echo "The following possible Homebrew files were not deleted:" + while read -r f; do + pretty_print_pathnames "$f" + done <"$tmpdir/residual_files" + echo -e "You may wish to remove them yourself.\n" +fi + +[[ $failed != true ]] diff --git a/uninstall.sh b/uninstall.sh index 74d80cd..42b1fae 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -49,7 +49,11 @@ case "$un" in ;; Darwin) ostype=macos - homebrew_prefix_default=/usr/local + if [[ "$(uname -m)" == "arm64" ]]; then + homebrew_prefix_default=/opt/homebrew + else + homebrew_prefix_default=/usr/local + fi realpath() { cd "$(dirname "$1")" && echo "$(pwd -P)/$(basename "$1")" }