powerlevel10k/install
romkatv d23b2c3792 Squashed 'gitstatus/' changes from 901c366b..f81313e2
f81313e2 move gitee disable higher
8cfb83f3 print [ok] after download when stderr is not tty
d185a2ab disable gitee mirror until there is sha256 verification in place
fb88a401 show progress when downloading gitstatusd
ae988158 add a mirror for gitstatusd release files
c673d327 disable aliases before calling zcompile

git-subtree-dir: gitstatus
git-subtree-split: f81313e27271ee1fb3fd22b8e72382e9516776ef
2020-05-12 21:55:25 +02:00

364 lines
10 KiB
Bash
Executable File

#!/bin/sh
#
# This script does not have a stable API.
_gitstatus_install_main() {
if [ -n "${ZSH_VERSION:-}" ]; then
emulate -L sh -o no_unset
else
set -u
fi
local argv1=$1
shift
local no_check= no_install= uname_s= uname_m= gitstatus_dir= dl_status=
local opt= OPTARG= OPTIND=1
while getopts ':s:m:d:p:fnh' opt "$@"; do
case "$opt" in
h)
command cat <<\END
Usage: install [-s KERNEL] [-m ARCH] [-d DIR] [-p CMD] [-f|-n] [-- CMD [ARG]...]
If positional arguments are specified, call this on success:
CMD [ARG]... DAEMON VERSION INSTALLED
DAEMON is path to gitstatusd. VERSION is a glob pattern for the
version this daemon should support; it's supposed to be passed as
-G to gitstatusd. INSTALLED is 1 if gitstatusd has just been
downloaded and 0 otherwise.
Options:
-s KERNEL use this instead of lowercase `uname -s`
-m ARCH use this instead of lowercase `uname -m`
-d DIR use this instead of `dirname "$0"`
-p CMD eval this every second while downloading gitstatusd
-f download gitstatusd even if there is one locally
-n do not download gitstatusd (fail instead)
END
return
;;
n)
if [ -n "$no_install" ]; then
>&2 echo "[gitstatus] error: duplicate option: -$opt"
return 1
fi
no_install=1
;;
f)
if [ -n "$no_check" ]; then
>&2 echo "[gitstatus] error: duplicate option: -$opt"
return 1
fi
no_check=1
;;
d)
if [ -n "$gitstatus_dir" ]; then
>&2 echo "[gitstatus] error: duplicate option: -$opt"
return 1
fi
if [ -z "$OPTARG" ]; then
>&2 echo "[error] incorrect value of -$opt: $OPTARG"
return 1
fi
gitstatus_dir="$OPTARG"
;;
p)
if [ -n "$dl_status" ]; then
>&2 echo "[gitstatus] error: duplicate option: -$opt"
return 1
fi
if [ -z "$OPTARG" ]; then
>&2 echo "[error] incorrect value of -$opt: $OPTARG"
return 1
fi
dl_status="$OPTARG"
;;
m)
if [ -n "$uname_m" ]; then
>&2 echo "[gitstatus] error: duplicate option: -$opt"
return 1
fi
if [ -z "$OPTARG" ]; then
>&2 echo "[error] incorrect value of -$opt: $OPTARG"
return 1
fi
uname_m="$OPTARG"
;;
s)
if [ -n "$uname_s" ]; then
>&2 echo "[gitstatus] error: duplicate option: -$opt"
return 1
fi
if [ -z "$OPTARG" ]; then
>&2 echo "[error] incorrect value of -$opt: $OPTARG"
return 1
fi
uname_s="$OPTARG"
;;
\?) >&2 echo "[gitstatus] error: invalid option: -$OPTARG" ; return 1;;
:) >&2 echo "[gitstatus] error: missing required argument: -$OPTARG"; return 1;;
*) >&2 echo "[gitstatus] internal error: unhandled option: -$opt" ; return 1;;
esac
done
shift "$((OPTIND - 1))"
: "${gitstatus_dir:=$argv1}"
if [ -n "$no_check" -a -n "$no_install" ]; then
>&2 echo "[gitstatus] error: incompatible options: -f, -n"
return 1
fi
if [ -z "$uname_s" ]; then
uname_s="$(command uname -s)" || return
uname_s="$(printf '%s' "$uname_s" | command tr '[A-Z]' '[a-z]')" || return
fi
if [ -z "$uname_m" ]; then
uname_m="$(command uname -m)" || return
uname_m="$(printf '%s' "$uname_m" | command tr '[A-Z]' '[a-z]')" || return
fi
local daemon="${GITSTATUS_DAEMON:-}"
local cache_dir="${GITSTATUS_CACHE_DIR:-${XDG_CACHE_HOME:-$HOME/.cache}/gitstatus}"
if [ -z "$no_check" ]; then
if [ -n "${daemon##/*}" ]; then
>&2 echo "[gitstatus] error: GITSTATUS_DAEMON is not absolute path: $daemon"
return 1
fi
if [ -z "$daemon" ]; then
daemon="$gitstatus_dir"/usrbin/gitstatusd
if [ ! -e "$daemon" ]; then
daemon="$daemon"-"$uname_s"-"$uname_m"
if [ ! -e "$daemon" ]; then
daemon=
fi
fi
fi
if [ -n "$daemon" ]; then
local gitstatus_version= libgit2_version=
if ! . "$gitstatus_dir"/build.info; then
>&2 echo "[gitstatus] internal error: failed to source build.info"
return 1
fi
if [ -z "$gitstatus_version" ]; then
>&2 echo "[gitstatus] internal error: empty gitstatus_version in build.info"
return 1
fi
[ $# = 0 ] || "$@" "$daemon" "$gitstatus_version" 0
return
fi
fi
while IFS= read -r line; do
line="${line###*}"
[ -n "$line" ] || continue
local uname_s_glob= uname_m_glob= file= version=
eval "$line" || return
if [ -z "$uname_s_glob" -o -z "$uname_m_glob" -o -z "$file" -o -z "$version" ]; then
>&2 echo "[gitstatus] internal error: invalid install.info line: $line"
return 1
fi
case "$uname_s" in
$uname_s_glob) ;;
*) continue;;
esac
case "$uname_m" in
$uname_m_glob) ;;
*) continue;;
esac
# Found a match. The while loop will terminate during this iteration.
if [ -z "$no_check" ]; then
# Check if a suitable gitstatusd already exists.
local daemon="$cache_dir"/"$file"
if [ -e "$daemon" ]; then
[ $# = 0 ] || "$@" "$daemon" "$version" 0
return
fi
daemon="$daemon"-"$uname_s"-"$uname_m"
if [ -e "$daemon" ]; then
local gitstatus_version= libgit2_version=
if ! . "$gitstatus_dir"/build.info; then
>&2 echo "[gitstatus] internal error: failed to source build.info"
return 1
fi
if [ -z "$gitstatus_version" ]; then
>&2 echo "[gitstatus] internal error: empty gitstatus_version in build.info"
return 1
fi
[ $# = 0 ] || "$@" "$daemon" "$gitstatus_version" 0
return
fi
fi
# No suitable gitstatusd exists. Need to download.
if [ -n "$no_install" ]; then
>&2 echo "[gitstatus] error: no gitstatusd found and installation is disabled"
return 1
fi
local daemon="$cache_dir"/"$file"
if [ -n "${cache_dir##/*}" ]; then
>&2 echo "[gitstatus] error: GITSTATUS_CACHE_DIR is not absolute: $cache_dir"
return 1
fi
[ -d "$cache_dir" ] || mkdir -p -- "$cache_dir" || return
(
local fetch
if command -v curl >/dev/null 2>&1; then
fetch="command curl -fsSLo"
elif command -v wget >/dev/null 2>&1; then
fetch="command wget -O"
else
>&2 echo "[gitstatus] error: please install curl or wget"
exit 1
fi
local url1="https://github.com/romkatv/gitstatus/releases/download/$version/$file.tar.gz"
local url2="https://gitee.com/romkatv/gitstatus/raw/release-$version/release/$file.tar.gz"
local tmp="$file".tmp.$$
if [ -n "${ZSH_VERSION:-}" ]; then
builtin cd -q -- "$cache_dir" || exit
else
cd -- "$cache_dir" || exit
fi
cleanup() {
local n
for n in "$@"; do
command rm -rf -- "$tmp"."$n".tar.gz "$tmp"."$n".status || return
done
}
local sig='INT QUIT TERM ILL PIPE'
fetch() {
local trapped=
trap 'trapped=1' $sig
# TODO: enable this after adding sha256 verification.
[ "$1" = 1 ] || return
if [ "$1" != 1 ] && command -v sleep >/dev/null 2>/dev/null; then
sleep "$1"
fi
$fetch "$tmp"."$1".tar.gz -- "$2" 2>/dev/null &
local pid=$!
local die="trap - $sig; kill -- $pid 2>/dev/null; cleanup $1; exit 1"
trap "$die" $sig
[ -z "$trapped" ] || eval "$die"
wait -- "$pid" 2>/dev/null
local ret="$?"
echo -n >"$tmp"."$1".status
trap - $sig
return "$ret"
}
local trapped=
trap 'trapped=1' $sig
fetch 1 "$url1" &
local pid1=$!
fetch 2 "$url2" &
local pid2=$!
local die="trap - $sig; kill -- $pid1 $pid2 2>/dev/null; cleanup 1 2; exit 1"
trap "$die" $sig
[ -z "$trapped" ] || eval "$die"
local n=
while true; do
[ -z "$dl_status" ] || eval "$dl_status" || eval "$die"
if command -v sleep >/dev/null 2>/dev/null; then
command sleep 1
elif command -v true >/dev/null 2>/dev/null; then
command true
fi
if [ -n "$pid1" -a -e "$tmp".1.status ]; then
wait -- "$pid1" 2>/dev/null
local ret="$?"
pid1=
if [ "$ret" = 0 ]; then
[ -z "$pid2" ] || kill -- "$pid2" 2>/dev/null
n=1
break
elif [ -z "$pid2" ]; then
break
fi
elif [ -n "$pid2" -a -e "$tmp".2.status ]; then
wait -- "$pid2" 2>/dev/null
local ret="$?"
pid2=
if [ "$ret" = 0 ]; then
[ -z "$pid1" ] || kill -- "$pid1" 2>/dev/null
n=2
break
elif [ -z "$pid1" ]; then
break
fi
fi
done
trap - $sig
if [ -z "$n" ]; then
>&2 echo "[gitstatus] error: failed to download gitstatusd from any mirror"
>&2 echo ""
>&2 echo " 1. $url1"
>&2 echo " 2. $url2"
cleanup 1 2
exit 1
fi
local old=
if [ -e "$daemon" ]; then
local i=1
while :; do
old="$daemon"."$i"
[ -e "$old" ] || break
i="$((i+1))"
done
if ! command mv -f -- "$daemon" "$old"; then
cleanup 1 2
exit 1
fi
fi
command tar -xzf "$tmp"."$n".tar.gz
local ret=$?
cleanup 1 2
if [ -n "$old" ]; then
if [ "$ret" = 0 ]; then
command rm -f -- "$old" 2>/dev/null
else
command mv -f -- "$old" "$daemon"
fi
fi
exit "$ret"
) || return
[ $# = 0 ] || "$@" "$daemon" "$version" 1
return
done <"$gitstatus_dir"/install.info
>&2 echo "[gitstatus] error: no gitstatusd found for $uname_s $uname_m"
return 1
}
if [ -z "${0##*/*}" ]; then
_gitstatus_install_main "${0%/*}" "$@"
else
_gitstatus_install_main . "$@"
fi