summaryrefslogtreecommitdiff
path: root/gitstatus/install
diff options
context:
space:
mode:
Diffstat (limited to 'gitstatus/install')
-rwxr-xr-xgitstatus/install269
1 files changed, 269 insertions, 0 deletions
diff --git a/gitstatus/install b/gitstatus/install
new file mode 100755
index 00000000..f747015c
--- /dev/null
+++ b/gitstatus/install
@@ -0,0 +1,269 @@
+#!/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=
+ local opt= OPTARG= OPTIND=1
+
+ while getopts ':s:m:d:fnh' opt "$@"; do
+ case "$opt" in
+ h)
+ command cat <<\END
+Usage: install [-s KERNEL] [-m ARCH] [-d DIR] [-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"`
+ -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"
+ ;;
+ 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 url="https://github.com/romkatv/gitstatus/releases/download/$version/$file.tar.gz"
+ local archive="$cache_dir"/"$file".tmp.$$.tar.gz
+ if command -v curl >/dev/null 2>&1; then
+ if ! err="$(command curl -fsSLo "$archive" -- "$url" 2>&1)"; then
+ >&2 echo "[gitstatus] error: failed to download gitstatusd: $url"
+ >&2 printf "%s\n" "$err"
+ return 1
+ fi
+ elif command -v wget >/dev/null 2>&1; then
+ if ! err="$(command wget -O "$archive" -- "$url" 2>&1)"; then
+ >&2 echo "[gitstatus] error: failed to download gitstatusd: $url"
+ >&2 printf "%s\n" "$err"
+ return 1
+ fi
+ else
+ >&2 echo "[gitstatus] error: please install curl or wget"
+ return 1
+ fi
+
+ (
+ if [ -n "${ZSH_VERSION:-}" ]; then
+ builtin cd -q -- "$cache_dir" || return
+ else
+ cd -- "$cache_dir" || return
+ fi
+
+ local old=
+ if [ -e "$daemon" ]; then
+ local i=1
+ while :; do
+ old="$daemon"."$i"
+ [ -e "$old" ] || break
+ i="$((i+1))"
+ done
+ command mv -f -- "$daemon" "$old" || return
+ fi
+
+ command tar -xzf "$archive"
+ local ret=$?
+ command rm -f -- "$archive"
+ 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