Files
starship/install/install.sh
T

519 lines
13 KiB
Bash
Raw Normal View History

#!/usr/bin/env sh
set -eu
printf '\n'
BOLD="$(tput bold 2>/dev/null || printf '')"
GREY="$(tput setaf 0 2>/dev/null || printf '')"
UNDERLINE="$(tput smul 2>/dev/null || printf '')"
RED="$(tput setaf 1 2>/dev/null || printf '')"
GREEN="$(tput setaf 2 2>/dev/null || printf '')"
YELLOW="$(tput setaf 3 2>/dev/null || printf '')"
BLUE="$(tput setaf 4 2>/dev/null || printf '')"
MAGENTA="$(tput setaf 5 2>/dev/null || printf '')"
NO_COLOR="$(tput sgr0 2>/dev/null || printf '')"
SUPPORTED_TARGETS="x86_64-unknown-linux-gnu x86_64-unknown-linux-musl \
i686-unknown-linux-musl aarch64-unknown-linux-musl \
arm-unknown-linux-musleabihf x86_64-apple-darwin \
aarch64-apple-darwin x86_64-pc-windows-msvc \
2021-01-30 12:50:38 +01:00
i686-pc-windows-msvc aarch64-pc-windows-msvc \
x86_64-unknown-freebsd"
info() {
printf '%s\n' "${BOLD}${GREY}>${NO_COLOR} $*"
}
warn() {
printf '%s\n' "${YELLOW}! $*${NO_COLOR}"
}
error() {
printf '%s\n' "${RED}x $*${NO_COLOR}" >&2
}
completed() {
printf '%s\n' "${GREEN}${NO_COLOR} $*"
}
has() {
command -v "$1" 1>/dev/null 2>&1
}
# Make sure user is not using zsh or non-POSIX-mode bash, which can cause issues
verify_shell_is_posix_or_exit() {
if [ -n "${ZSH_VERSION+x}" ]; then
error "Running installation script with \`zsh\` is known to cause errors."
error "Please use \`sh\` instead."
exit 1
elif [ -n "${BASH_VERSION+x}" ] && [ -z "${POSIXLY_CORRECT+x}" ]; then
error "Running installation script with non-POSIX \`bash\` may cause errors."
error "Please use \`sh\` instead."
exit 1
else
true # No-op: no issues detected
fi
}
# Gets path to a temporary file, even if
get_tmpfile() {
2020-06-09 17:21:35 -05:00
suffix="$1"
if has mktemp; then
printf "%s.%s" "$(mktemp)" "${suffix}"
2020-06-09 17:21:35 -05:00
else
# No really good options here--let's pick a default + hope
printf "/tmp/starship.%s" "${suffix}"
fi
}
# Test if a location is writeable by trying to write to it. Windows does not let
# you test writeability other than by writing: https://stackoverflow.com/q/1999988
test_writeable() {
2020-06-09 17:21:35 -05:00
path="${1:-}/test.txt"
if touch "${path}" 2>/dev/null; then
2020-06-09 17:21:35 -05:00
rm "${path}"
return 0
else
return 1
fi
}
download() {
file="$1"
url="$2"
if has curl; then
cmd="curl --fail --silent --location --output $file $url"
elif has wget; then
cmd="wget --quiet --output-document=$file $url"
elif has fetch; then
cmd="fetch --quiet --output=$file $url"
else
error "No HTTP download program (curl, wget, fetch) found, exiting…"
return 1
fi
$cmd && return 0 || rc=$?
error "Command failed (exit code $rc): ${BLUE}${cmd}${NO_COLOR}"
printf "\n" >&2
info "This is likely due to Starship not yet supporting your configuration."
info "If you would like to see a build for your configuration,"
info "please create an issue requesting a build for ${MAGENTA}${TARGET}${NO_COLOR}:"
info "${BOLD}${UNDERLINE}https://github.com/starship/starship/issues/new/${NO_COLOR}"
return $rc
}
unpack() {
archive=$1
bin_dir=$2
sudo=${3-}
case "$archive" in
*.tar.gz)
flags=$(test -n "${VERBOSE-}" && echo "-xzvf" || echo "-xzf")
${sudo} tar "${flags}" "${archive}" -C "${bin_dir}"
return 0
;;
*.zip)
flags=$(test -z "${VERBOSE-}" && echo "-qqo" || echo "-o")
UNZIP="${flags}" ${sudo} unzip "${archive}" -d "${bin_dir}"
return 0
;;
esac
error "Unknown package extension."
printf "\n"
info "This almost certainly results from a bug in this script--please file a"
info "bug report at https://github.com/starship/starship/issues"
return 1
2020-06-09 17:21:35 -05:00
}
usage() {
printf "%s\n" \
"install.sh [option]" \
"" \
"Fetch and install the latest version of starship, if starship is already" \
"installed it will be updated to the latest version."
printf "\n%s\n" "Options"
printf "\t%s\n\t\t%s\n\n" \
"-V, --verbose" "Enable verbose output for the installer" \
"-f, -y, --force, --yes" "Skip the confirmation prompt during installation" \
"-p, --platform" "Override the platform identified by the installer [default: ${PLATFORM}]" \
"-b, --bin-dir" "Override the bin installation directory [default: ${BIN_DIR}]" \
"-a, --arch" "Override the architecture identified by the installer [default: ${ARCH}]" \
"-B, --base-url" "Override the base URL used for downloading releases [default: ${BASE_URL}]" \
"-h, --help" "Display this help message"
}
elevate_priv() {
if ! has sudo; then
error 'Could not find the command "sudo", needed to get permissions for install.'
2020-06-09 17:21:35 -05:00
info "If you are on Windows, please run your shell as an administrator, then"
info "rerun this script. Otherwise, please run this script as root, or install"
info "sudo."
exit 1
fi
if ! sudo -v; then
error "Superuser not granted, aborting installation"
exit 1
fi
}
install() {
ext="$1"
2020-06-09 17:21:35 -05:00
if test_writeable "${BIN_DIR}"; then
2020-06-09 17:21:35 -05:00
sudo=""
msg="Installing Starship, please wait…"
else
warn "Escalated permissions are required to install to ${BIN_DIR}"
2020-06-09 17:21:35 -05:00
elevate_priv
sudo="sudo"
msg="Installing Starship as root, please wait…"
fi
info "$msg"
archive=$(get_tmpfile "$ext")
# download to the temp file
download "${archive}" "${URL}"
# unpack the temp file to the bin dir, using sudo if required
unpack "${archive}" "${BIN_DIR}" "${sudo}"
}
# Currently supporting:
# - win (Git Bash)
# - darwin
# - linux
# - linux_musl (Alpine)
2021-01-30 12:50:38 +01:00
# - freebsd
detect_platform() {
platform="$(uname -s | tr '[:upper:]' '[:lower:]')"
case "${platform}" in
msys_nt*) platform="pc-windows-msvc" ;;
cygwin_nt*) platform="pc-windows-msvc";;
# mingw is Git-Bash
mingw*) platform="pc-windows-msvc" ;;
# use the statically compiled musl bins on linux to avoid linking issues.
linux) platform="unknown-linux-musl" ;;
darwin) platform="apple-darwin" ;;
2021-01-30 12:50:38 +01:00
freebsd) platform="unknown-freebsd" ;;
esac
printf '%s' "${platform}"
}
# Currently supporting:
# - x86_64
# - i386
# - arm
# - arm64
detect_arch() {
arch="$(uname -m | tr '[:upper:]' '[:lower:]')"
case "${arch}" in
2021-01-30 12:50:38 +01:00
amd64) arch="x86_64" ;;
armv*) arch="arm" ;;
arm64) arch="aarch64" ;;
esac
# `uname -m` in some cases mis-reports 32-bit OS as 64-bit, so double check
if [ "${arch}" = "x86_64" ] && [ "$(getconf LONG_BIT)" -eq 32 ]; then
arch=i686
elif [ "${arch}" = "aarch64" ] && [ "$(getconf LONG_BIT)" -eq 32 ]; then
arch=arm
fi
printf '%s' "${arch}"
}
detect_target() {
arch="$1"
platform="$2"
target="$arch-$platform"
if [ "${target}" = "arm-unknown-linux-musl" ]; then
target="${target}eabihf"
fi
printf '%s' "${target}"
}
confirm() {
if [ -z "${FORCE-}" ]; then
printf "%s " "${MAGENTA}?${NO_COLOR} $* ${BOLD}[y/N]${NO_COLOR}"
set +e
read -r yn </dev/tty
rc=$?
set -e
if [ $rc -ne 0 ]; then
error "Error reading from prompt (please re-run with the '--yes' option)"
exit 1
fi
if [ "$yn" != "y" ] && [ "$yn" != "yes" ]; then
error 'Aborting (please answer "yes" to continue)'
exit 1
fi
fi
}
check_bin_dir() {
bin_dir="${1%/}"
2020-06-09 17:21:35 -05:00
if [ ! -d "$BIN_DIR" ]; then
error "Installation location $BIN_DIR does not appear to be a directory"
info "Make sure the location exists and is a directory, then try again."
usage
exit 1
2020-06-09 17:21:35 -05:00
fi
# https://stackoverflow.com/a/11655875
good=$(
IFS=:
for path in $PATH; do
if [ "${path%/}" = "${bin_dir}" ]; then
printf 1
break
fi
done
)
if [ "${good}" != "1" ]; then
warn "Bin directory ${bin_dir} is not in your \$PATH"
fi
}
print_install() {
# if the shell does not fit the default case change the config file
# and or the config cmd variable
for s in "bash" "zsh" "ion" "tcsh" "xonsh" "fish"
do
# shellcheck disable=SC2088
# we don't want these '~' expanding
config_file="~/.${s}rc"
config_cmd="eval \"\$(starship init ${s})\""
case ${s} in
ion )
# shellcheck disable=SC2088
config_file="~/.config/ion/initrc"
config_cmd="eval \$(starship init ${s})"
;;
fish )
# shellcheck disable=SC2088
config_file="~/.config/fish/config.fish"
config_cmd="starship init fish | source"
;;
tcsh )
config_cmd="eval \`starship init ${s}\`"
;;
xonsh )
config_cmd="execx(\$(starship init xonsh))"
;;
esac
printf " %s\n Add the following to the end of %s:\n\n\t%s\n\n" \
"${BOLD}${UNDERLINE}${s}${NO_COLOR}" \
"${BOLD}${config_file}${NO_COLOR}" \
"${config_cmd}"
done
for s in "elvish" "nushell"
do
warning="${BOLD}Warning${NO_COLOR}"
case ${s} in
elvish )
# shellcheck disable=SC2088
config_file="~/.elvish/rc.elv"
config_cmd="eval (starship init elvish)"
warning="${warning} Only elvish v0.17 or higher is supported."
;;
nushell )
# shellcheck disable=SC2088
config_file="${BOLD}your nu config file${NO_COLOR} (find it by running ${BOLD}\$nu.config-path${NO_COLOR} in Nushell)"
config_cmd="mkdir ~/.cache/starship
starship init nu | save ~/.cache/starship/init.nu
source ~/.cache/starship/init.nu"
warning="${warning} This will change in the future.
Only Nushell v0.61 or higher is supported.
Add the following to the end of ${BOLD}your Nushell env file${NO_COLOR} (find it by running ${BOLD}\$nu.env-path${NO_COLOR} in Nushell): \"mkdir ~/.cache/starship; starship init nu | save ~/.cache/starship/init.nu\""
;;
esac
printf " %s\n %s\n And add the following to the end of %s:\n\n\t%s\n\n" \
"${BOLD}${UNDERLINE}${s}${NO_COLOR}" \
"${warning}" \
"${config_file}" \
"${config_cmd}"
done
printf " %s\n Add the following to the end of %s:\n %s\n\n\t%s\n\n" \
"${BOLD}${UNDERLINE}PowerShell${NO_COLOR}" \
"${BOLD}Microsoft.PowerShell_profile.ps1${NO_COLOR}" \
"You can check the location of this file by querying the \$PROFILE variable in PowerShell.
Typically the path is ~\Documents\PowerShell\Microsoft.PowerShell_profile.ps1 or ~/.config/powershell/Microsoft.PowerShell_profile.ps1 on -Nix." \
"Invoke-Expression (&starship init powershell)"
2022-01-10 11:17:53 +05:30
printf " %s\n You need to use Clink (v1.2.30+) with Cmd. Add the following to a file %s and place this file in Clink scripts directory:\n\n\t%s\n\n" \
"${BOLD}${UNDERLINE}Cmd${NO_COLOR}" \
"${BOLD}starship.lua${NO_COLOR}" \
"load(io.popen('starship init cmd'):read(\"*a\"))()"
printf "\n"
}
is_build_available() {
arch="$1"
platform="$2"
target="$3"
good=$(
IFS=" "
for t in $SUPPORTED_TARGETS; do
if [ "${t}" = "${target}" ]; then
printf 1
break
fi
done
)
if [ "${good}" != "1" ]; then
error "${arch} builds for ${platform} are not yet available for Starship"
printf "\n" >&2
info "If you would like to see a build for your configuration,"
info "please create an issue requesting a build for ${MAGENTA}${target}${NO_COLOR}:"
info "${BOLD}${UNDERLINE}https://github.com/starship/starship/issues/new/${NO_COLOR}"
printf "\n"
exit 1
fi
}
# defaults
if [ -z "${PLATFORM-}" ]; then
PLATFORM="$(detect_platform)"
fi
if [ -z "${BIN_DIR-}" ]; then
BIN_DIR=/usr/local/bin
fi
if [ -z "${ARCH-}" ]; then
ARCH="$(detect_arch)"
fi
if [ -z "${BASE_URL-}" ]; then
BASE_URL="https://github.com/starship/starship/releases"
fi
# Non-POSIX shells can break once executing code due to semantic differences
verify_shell_is_posix_or_exit
# parse argv variables
while [ "$#" -gt 0 ]; do
case "$1" in
-p | --platform)
PLATFORM="$2"
shift 2
;;
-b | --bin-dir)
BIN_DIR="$2"
shift 2
;;
-a | --arch)
ARCH="$2"
shift 2
;;
-B | --base-url)
BASE_URL="$2"
shift 2
;;
-V | --verbose)
VERBOSE=1
shift 1
;;
-f | -y | --force | --yes)
FORCE=1
shift 1
;;
-h | --help)
usage
exit
;;
-p=* | --platform=*)
PLATFORM="${1#*=}"
shift 1
;;
-b=* | --bin-dir=*)
BIN_DIR="${1#*=}"
shift 1
;;
-a=* | --arch=*)
ARCH="${1#*=}"
shift 1
;;
-B=* | --base-url=*)
BASE_URL="${1#*=}"
shift 1
;;
-V=* | --verbose=*)
VERBOSE="${1#*=}"
shift 1
;;
-f=* | -y=* | --force=* | --yes=*)
FORCE="${1#*=}"
shift 1
;;
*)
error "Unknown option: $1"
usage
exit 1
;;
esac
done
TARGET="$(detect_target "${ARCH}" "${PLATFORM}")"
is_build_available "${ARCH}" "${PLATFORM}" "${TARGET}"
printf " %s\n" "${UNDERLINE}Configuration${NO_COLOR}"
info "${BOLD}Bin directory${NO_COLOR}: ${GREEN}${BIN_DIR}${NO_COLOR}"
info "${BOLD}Platform${NO_COLOR}: ${GREEN}${PLATFORM}${NO_COLOR}"
info "${BOLD}Arch${NO_COLOR}: ${GREEN}${ARCH}${NO_COLOR}"
# non-empty VERBOSE enables verbose untarring
if [ -n "${VERBOSE-}" ]; then
VERBOSE=v
info "${BOLD}Verbose${NO_COLOR}: yes"
else
VERBOSE=
fi
printf '\n'
EXT=tar.gz
2020-06-09 17:21:35 -05:00
if [ "${PLATFORM}" = "pc-windows-msvc" ]; then
EXT=zip
fi
URL="${BASE_URL}/latest/download/starship-${TARGET}.${EXT}"
info "Tarball URL: ${UNDERLINE}${BLUE}${URL}${NO_COLOR}"
confirm "Install Starship ${GREEN}latest${NO_COLOR} to ${BOLD}${GREEN}${BIN_DIR}${NO_COLOR}?"
2020-06-09 17:21:35 -05:00
check_bin_dir "${BIN_DIR}"
install "${EXT}"
completed "Starship installed"
printf '\n'
info "Please follow the steps for your shell to complete the installation:"
2021-07-16 12:25:01 -07:00
print_install
2021-07-16 12:25:01 -07:00