#!/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" "$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" "$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