From d23b2c3792712662408c332a52547dc903cc5c43 Mon Sep 17 00:00:00 2001 From: romkatv Date: Tue, 12 May 2020 21:55:25 +0200 Subject: [PATCH] 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 --- README.md | 2 +- gitstatus.plugin.sh | 46 ++++++++++++--- gitstatus.plugin.zsh | 68 +++++++++++++++++++--- install | 135 ++++++++++++++++++++++++++++++++++++------- install.info | 5 ++ 5 files changed, 217 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index f6a00bf1..0063dca9 100644 --- a/README.md +++ b/README.md @@ -489,7 +489,7 @@ cd gitstatus-1.0.0 ./build rm deps/libgit2-*.tar.gz for file in *.zsh install; do - zsh -fc "zcompile -R -- $file.zwc $file" + zsh -fc "emulate zsh -o no_aliases && zcompile -R -- $file.zwc $file" done ``` diff --git a/gitstatus.plugin.sh b/gitstatus.plugin.sh index 75bc2688..c05f6cca 100644 --- a/gitstatus.plugin.sh +++ b/gitstatus.plugin.sh @@ -8,7 +8,7 @@ # Usage: gitstatus_start [OPTION]... # # -t FLOAT Fail the self-check on initialization if not getting a response from -# gitstatusd for this this many seconds. Defaults to 30. +# gitstatusd for this this many seconds. Defaults to 5. # # -s INT Report at most this many staged changes; negative value means infinity. # Defaults to 1. @@ -37,7 +37,7 @@ # changes for repositories with bash.showDirtyState = false. function gitstatus_start() { unset OPTIND - local opt timeout=30 max_dirty=-1 extra_flags + local opt timeout=5 max_dirty=-1 extra_flags local max_num_staged=1 max_num_unstaged=1 max_num_conflicted=1 max_num_untracked=1 local ignore_status_show_untracked_files while getopts "t:s:u:c:d:m:eUWD" opt; do @@ -117,7 +117,10 @@ function gitstatus_start() { { ( + trap '' INT + [[ "$GITSTATUS_DAEMON_LOG" == /dev/null ]] || set -x builtin cd / + ( local fd_in fd_out exec {fd_in}<"$req_fifo" {fd_out}>"$resp_fifo" || exit @@ -131,14 +134,15 @@ function gitstatus_start() { _gitstatus_bash_downloaded="$3" } - set -- -d "$gitstatus_plugin_dir" -s "$uname_s" -m "$uname_m" -- _gitstatus_set_daemon + set -- -d "$gitstatus_plugin_dir" -s "$uname_s" -m "$uname_m" \ + -p "printf '.\036' >&$fd_out" -- _gitstatus_set_daemon [[ "${GITSTATUS_AUTO_INSTALL:-1}" -ne 0 ]] || set -- -n "$@" source "$gitstatus_plugin_dir"/install || return [[ -n "$_gitstatus_bash_daemon" ]] || return [[ -n "$_gitstatus_bash_version" ]] || return [[ "$_gitstatus_bash_downloaded" == [01] ]] || return - local sig=(INT QUIT TERM EXIT ILL PIPE) + local sig=(QUIT TERM EXIT ILL PIPE) if [[ -x "$_gitstatus_bash_daemon" ]]; then "$_gitstatus_bash_daemon" \ @@ -174,9 +178,9 @@ function gitstatus_start() { wait "$pid" trap - ${sig[@]} echo -nE $'bye\x1f0\x1e' >&"$fd_out" - ) & - ) & disown - } 0/dev/null + ) & disown + ) & disown + } 0$GITSTATUS_DAEMON_LOG exec {_GITSTATUS_REQ_FD}>"$req_fifo" {_GITSTATUS_RESP_FD}<"$resp_fifo" || return command rm "$req_fifo" "$resp_fifo" || return @@ -186,8 +190,32 @@ function gitstatus_start() { local reply echo -nE $'hello\x1f\x1e' >&$_GITSTATUS_REQ_FD || return - IFS='' read -rd $'\x1e' -u $_GITSTATUS_RESP_FD -t "$timeout" reply || return - [[ "$reply" == $'hello\x1f0' ]] || return + local dl= + while true; do + IFS='' read -rd $'\x1e' -u $_GITSTATUS_RESP_FD -t "$timeout" reply || return + [[ "$reply" == $'hello\x1f0' ]] && break + [[ "$reply" == . ]] || return + if [[ -z "$dl" ]]; then + dl=1 + if [[ -t 2 ]]; then + local spinner=('\b\033[33m-\033[0m' '\b\033[33m\\\033[0m' '\b\033[33m|\033[0m' '\b\033[33m/\033[0m') + >&2 printf '[\033[33mgitstatus\033[0m] fetching \033[32mgitstatusd\033[0m .. ' + else + local spinner=('.') + >&2 printf '[gitstatus] fetching gitstatusd ..' + fi + fi + >&2 printf "${spinner[0]}" + spinner=("${spinner[@]:1}" "${spinner[0]}") + done + + if [[ -n "$dl" ]]; then + if [[ -t 2 ]]; then + >&2 printf '\b[\033[32mok\033[0m]\n' + else + >&2 echo ' [ok]' + fi + fi _GITSTATUS_DIRTY_MAX_INDEX_SIZE=$max_dirty _GITSTATUS_CLIENT_PID="$BASHPID" diff --git a/gitstatus.plugin.zsh b/gitstatus.plugin.zsh index d1d74469..0ee9f136 100644 --- a/gitstatus.plugin.zsh +++ b/gitstatus.plugin.zsh @@ -383,6 +383,11 @@ function _gitstatus_daemon"${1:-}"() { args+=(-t $((cpus > 16 ? 32 : cpus > 0 ? 2 * cpus : 16))) fi + mkfifo -- $file_prefix.fifo || return + print -rnu $pipe_fd -- ${(l:20:)pgid} || return + exec <$file_prefix.fifo || return + zf_rm -- $file_prefix.fifo || return + local _gitstatus_zsh_daemon _gitstatus_zsh_version _gitstatus_zsh_downloaded function _gitstatus_set_daemon$fsuf() { @@ -393,18 +398,14 @@ function _gitstatus_daemon"${1:-}"() { local gitstatus_plugin_dir_var=_gitstatus_plugin_dir$fsuf local gitstatus_plugin_dir=${(P)gitstatus_plugin_dir_var} - set -- -d $gitstatus_plugin_dir -s $uname_s -m $uname_m -- _gitstatus_set_daemon$fsuf + set -- -d $gitstatus_plugin_dir -s $uname_s -m $uname_m -p "printf . >&$pipe_fd" -- \ + _gitstatus_set_daemon$fsuf [[ ${GITSTATUS_AUTO_INSTALL:-1} == (|-|+)<1-> ]] || set -- -n "$@" source $gitstatus_plugin_dir/install || return [[ -n $_gitstatus_zsh_daemon ]] || return [[ -n $_gitstatus_zsh_version ]] || return [[ $_gitstatus_zsh_downloaded == [01] ]] || return - mkfifo -- $file_prefix.fifo || return - print -rnu $pipe_fd -- ${(l:20:)pgid} || return - exec <$file_prefix.fifo || return - zf_rm -- $file_prefix.fifo || return - if [[ -x $_gitstatus_zsh_daemon ]]; then $_gitstatus_zsh_daemon -G $_gitstatus_zsh_version "${(@)args}" >&$pipe_fd local -i ret=$? @@ -445,7 +446,7 @@ function _gitstatus_daemon"${1:-}"() { # Usage: gitstatus_start [OPTION]... NAME # # -t FLOAT Fail the self-check on initialization if not getting a response from gitstatusd for -# this this many seconds. Defaults to 30. +# this this many seconds. Defaults to 5. # # -s INT Report at most this many staged changes; negative value means infinity. # Defaults to 1. @@ -480,7 +481,7 @@ function gitstatus_start"${1:-}"() { local opt OPTARG local -i OPTIND - local -F timeout=30 + local -F timeout=5 local -i async=0 local -a args=() local -i dirty_max_index_size=-1 @@ -647,6 +648,57 @@ function gitstatus_start"${1:-}"() { print -nru $req_fd -- $'hello\x1f\x1e' || return local expected=$'hello\x1f0\x1e' actual + if (( $+functions[p10k] )) && [[ ! -t 1 && ! -t 0 ]]; then + local -F deadline='EPOCHREALTIME + 4' + else + local -F deadline='1' + fi + while true; do + [[ -t $resp_fd ]] + sysread -s 1 -t $timeout -i $resp_fd actual || return + [[ $actual == h ]] && break + [[ $actual == . ]] || return + (( EPOCHREALTIME < deadline )) && continue + if (( deadline > 0 )); then + deadline=0 + if (( stderr_fd )); then + unsetopt xtrace + exec 2>&$stderr_fd {stderr_fd}>&- + stderr_fd=0 + fi + if (( $+functions[p10k] )); then + p10k clear-instant-prompt || return + fi + if [[ $name == POWERLEVEL9K ]]; then + local label=powerlevel10k + else + local label=gitstatus + fi + if [[ -t 2 ]]; then + local spinner=($'\b%3F-%f' $'\b%3F\\%f' $'\b%3F|%f' $'\b%3F/%f') + print -Prnu2 -- "[%3F$label%f] fetching %2Fgitstatusd%f .. " + else + local spinner=('.') + print -rnu2 -- "[$label] fetching gitstatusd .." + fi + fi + print -Prnu2 -- $spinner[1] + spinner=($spinner[2,-1] $spinner[1]) + done + + if (( deadline == 0 )); then + if [[ -t 2 ]]; then + print -Pru2 -- $'\b[%2Fok%f]' + else + print -ru2 -- ' [ok]' + fi + if [[ $xtrace != /dev/null && -o no_xtrace ]]; then + exec {stderr_fd}>&2 || return + exec 2>>$xtrace || return + setopt xtrace + fi + fi + while (( $#actual < $#expected )); do [[ -t $resp_fd ]] sysread -s $(($#expected - $#actual)) -t $timeout -i $resp_fd 'actual[$#actual+1]' || return diff --git a/install b/install index 1ef27cbb..cc408354 100755 --- a/install +++ b/install @@ -12,14 +12,14 @@ _gitstatus_install_main() { local argv1=$1 shift - local no_check= no_install= uname_s= uname_m= gitstatus_dir= + local no_check= no_install= uname_s= uname_m= gitstatus_dir= dl_status= local opt= OPTARG= OPTIND=1 - while getopts ':s:m:d:fnh' opt "$@"; do + while getopts ':s:m:d:p:fnh' opt "$@"; do case "$opt" in h) command cat <<\END -Usage: install [-s KERNEL] [-m ARCH] [-d DIR] [-f|-n] [-- CMD [ARG]...] +Usage: install [-s KERNEL] [-m ARCH] [-d DIR] [-p CMD] [-f|-n] [-- CMD [ARG]...] If positional arguments are specified, call this on success: @@ -35,6 +35,7 @@ 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 @@ -65,6 +66,17 @@ END 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" @@ -204,30 +216,108 @@ END fi [ -d "$cache_dir" ] || mkdir -p -- "$cache_dir" || return - local url="https://github.com/romkatv/gitstatus/releases/download/$version/$file.tar.gz" - ( + 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 - local archive="$file".tmp.$$.tar.gz - local err + cleanup() { + local n + for n in "$@"; do + command rm -rf -- "$tmp"."$n".tar.gz "$tmp"."$n".status || return + done + } - if command -v curl >/dev/null 2>&1; then - err="$(command curl -fsSLo "$archive" -- "$url" 2>&1)" - elif command -v wget >/dev/null 2>&1; then - err="$(command wget -O "$archive" -- "$url" 2>&1)" - else - >&2 echo "[gitstatus] error: please install curl or wget" - exit 1 - fi + local sig='INT QUIT TERM ILL PIPE' - if [ $? != 0 ]; then - >&2 printf "%s\n" "$err" - >&2 echo "[gitstatus] error: failed to download gitstatusd: $url" + 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 @@ -239,12 +329,15 @@ END [ -e "$old" ] || break i="$((i+1))" done - command mv -f -- "$daemon" "$old" || exit + if ! command mv -f -- "$daemon" "$old"; then + cleanup 1 2 + exit 1 + fi fi - command tar -xzf "$archive" + command tar -xzf "$tmp"."$n".tar.gz local ret=$? - command rm -f -- "$archive" + cleanup 1 2 if [ -n "$old" ]; then if [ "$ret" = 0 ]; then command rm -f -- "$old" 2>/dev/null diff --git a/install.info b/install.info index 853d4056..96458f0d 100644 --- a/install.info +++ b/install.info @@ -1,4 +1,9 @@ +# ae988158e1044abb1626a15d6a27751cd80c13be +# # This file is used by ./install and indirectly by shell bindings. +# +# The first line is read by powerlevel10k instant prompt. It must +# be updated whenever the content of this file changes. # Official gitstatusd binaries. uname_s_glob="cygwin_nt-10.0"; uname_m_glob="i686"; file="gitstatusd-${uname_s}-${uname_m}"; version="v1.0.0";