diff options
Diffstat (limited to 'gitstatus')
-rw-r--r-- | gitstatus/README.md | 1 | ||||
-rwxr-xr-x | gitstatus/bin/gitstatusd-android-aarch64 | bin | 1064360 -> 1076696 bytes | |||
-rwxr-xr-x | gitstatus/bin/gitstatusd-cygwin_nt-10.0-x86_64 | bin | 2147840 -> 2167296 bytes | |||
-rwxr-xr-x | gitstatus/bin/gitstatusd-darwin-x86_64 | bin | 2073216 -> 2095092 bytes | |||
-rwxr-xr-x | gitstatus/bin/gitstatusd-freebsd-amd64 | bin | 3252072 -> 3268488 bytes | |||
-rwxr-xr-x | gitstatus/bin/gitstatusd-linux-aarch64 | bin | 2261776 -> 2286400 bytes | |||
-rwxr-xr-x | gitstatus/bin/gitstatusd-linux-armv7l | bin | 1865248 -> 1877556 bytes | |||
-rwxr-xr-x | gitstatus/bin/gitstatusd-linux-x86_64 | bin | 2315464 -> 2340104 bytes | |||
-rwxr-xr-x | gitstatus/bin/gitstatusd-linux-x86_64-static | bin | 2045144 -> 2065632 bytes | |||
-rw-r--r-- | gitstatus/gitstatus.plugin.zsh | 397 | ||||
-rwxr-xr-x | gitstatus/pull-upstream.zsh | 10 |
11 files changed, 233 insertions, 175 deletions
diff --git a/gitstatus/README.md b/gitstatus/README.md index 2196d30f..bfe8c3e3 100644 --- a/gitstatus/README.md +++ b/gitstatus/README.md @@ -1,2 +1 @@ This is a bundled copy of [gitstatus](https://github.com/romkatv/gitstatus) ZSH plugin. - diff --git a/gitstatus/bin/gitstatusd-android-aarch64 b/gitstatus/bin/gitstatusd-android-aarch64 Binary files differindex 3da517d3..e9b22e72 100755 --- a/gitstatus/bin/gitstatusd-android-aarch64 +++ b/gitstatus/bin/gitstatusd-android-aarch64 diff --git a/gitstatus/bin/gitstatusd-cygwin_nt-10.0-x86_64 b/gitstatus/bin/gitstatusd-cygwin_nt-10.0-x86_64 Binary files differindex 51a1f0a0..a1baa948 100755 --- a/gitstatus/bin/gitstatusd-cygwin_nt-10.0-x86_64 +++ b/gitstatus/bin/gitstatusd-cygwin_nt-10.0-x86_64 diff --git a/gitstatus/bin/gitstatusd-darwin-x86_64 b/gitstatus/bin/gitstatusd-darwin-x86_64 Binary files differindex 31eb9db3..fb4e4a02 100755 --- a/gitstatus/bin/gitstatusd-darwin-x86_64 +++ b/gitstatus/bin/gitstatusd-darwin-x86_64 diff --git a/gitstatus/bin/gitstatusd-freebsd-amd64 b/gitstatus/bin/gitstatusd-freebsd-amd64 Binary files differindex 20d77a41..de7e0f24 100755 --- a/gitstatus/bin/gitstatusd-freebsd-amd64 +++ b/gitstatus/bin/gitstatusd-freebsd-amd64 diff --git a/gitstatus/bin/gitstatusd-linux-aarch64 b/gitstatus/bin/gitstatusd-linux-aarch64 Binary files differindex ebae869a..b99ecfee 100755 --- a/gitstatus/bin/gitstatusd-linux-aarch64 +++ b/gitstatus/bin/gitstatusd-linux-aarch64 diff --git a/gitstatus/bin/gitstatusd-linux-armv7l b/gitstatus/bin/gitstatusd-linux-armv7l Binary files differindex 89b59a74..3d301aa9 100755 --- a/gitstatus/bin/gitstatusd-linux-armv7l +++ b/gitstatus/bin/gitstatusd-linux-armv7l diff --git a/gitstatus/bin/gitstatusd-linux-x86_64 b/gitstatus/bin/gitstatusd-linux-x86_64 Binary files differindex 802f71ac..36691cf4 100755 --- a/gitstatus/bin/gitstatusd-linux-x86_64 +++ b/gitstatus/bin/gitstatusd-linux-x86_64 diff --git a/gitstatus/bin/gitstatusd-linux-x86_64-static b/gitstatus/bin/gitstatusd-linux-x86_64-static Binary files differindex 8eee5b55..b561edd9 100755 --- a/gitstatus/bin/gitstatusd-linux-x86_64-static +++ b/gitstatus/bin/gitstatusd-linux-x86_64-static diff --git a/gitstatus/gitstatus.plugin.zsh b/gitstatus/gitstatus.plugin.zsh index 6750aa4a..6e603ae3 100644 --- a/gitstatus/gitstatus.plugin.zsh +++ b/gitstatus/gitstatus.plugin.zsh @@ -19,51 +19,56 @@ # # Example: Start gitstatusd, send it a request, wait for response and print it. # -# source gitstatus.plugin.zsh +# source ~/gitstatus/gitstatus.plugin.zsh # gitstatus_start MY # gitstatus_query -d $PWD MY -# set | egrep '^VCS_STATUS' +# typeset -m 'VCS_STATUS_*' # # Output: # # VCS_STATUS_ACTION='' -# VCS_STATUS_COMMIT=6e86ec135bf77875e222463cbac8ef72a7e8d823 +# VCS_STATUS_COMMIT=c000eddcff0fb38df2d0137efe24d9d2d900f209 # VCS_STATUS_COMMITS_AHEAD=0 # VCS_STATUS_COMMITS_BEHIND=0 -# VCS_STATUS_INDEX_SIZE=42 -# VCS_STATUS_NUM_STAGED=0 -# VCS_STATUS_NUM_UNSTAGED=2 -# VCS_STATUS_NUM_UNTRACKED=3 +# VCS_STATUS_HAS_CONFLICTED=0 # VCS_STATUS_HAS_STAGED=0 # VCS_STATUS_HAS_UNSTAGED=1 # VCS_STATUS_HAS_UNTRACKED=1 +# VCS_STATUS_INDEX_SIZE=33 # VCS_STATUS_LOCAL_BRANCH=master +# VCS_STATUS_NUM_CONFLICTED=0 +# VCS_STATUS_NUM_STAGED=0 +# VCS_STATUS_NUM_UNSTAGED=1 +# VCS_STATUS_NUM_UNSTAGED_DELETED=0 +# VCS_STATUS_NUM_UNTRACKED=1 # VCS_STATUS_REMOTE_BRANCH=master # VCS_STATUS_REMOTE_NAME=origin # VCS_STATUS_REMOTE_URL=git@github.com:romkatv/powerlevel10k.git # VCS_STATUS_RESULT=ok-sync # VCS_STATUS_STASHES=0 # VCS_STATUS_TAG='' -# VCS_STATUS_WORKDIR=/home/romka/.oh-my-zsh/custom/themes/powerlevel10k +# VCS_STATUS_WORKDIR=/home/romka/powerlevel10k [[ -o 'interactive' ]] || 'return' -# Temporarily disable aliases. -if [[ -o 'aliases' ]]; then - 'builtin' 'unsetopt' 'aliases' - local _gitstatus_restore_aliases=1 -else - local _gitstatus_restore_aliases=0 -fi +# Temporarily change options. +'builtin' 'local' '-a' '_gitstatus_opts' +[[ ! -o 'aliases' ]] || _gitstatus_opts+=('aliases') +[[ ! -o 'sh_glob' ]] || _gitstatus_opts+=('sh_glob') +[[ ! -o 'no_brace_expand' ]] || _gitstatus_opts+=('no_brace_expand') +'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' autoload -Uz add-zsh-hook zmodload zsh/datetime zsh/system +typeset -g _gitstatus_plugin_dir=${${(%):-%x}:A:h} + # Retrives status of a git repo from a directory under its working tree. # ## Usage: gitstatus_query [OPTION]... NAME # -# -d STR Directory to query. Defaults to ${${GIT_DIR:-$PWD}:a}. Must be absolute. +# -d STR Directory to query. Must be absolute. Defaults to $GIT_DIR or the current +# directory if GIT_DIR is not set. # -c STR Callback function to call once the results are available. Called only after # gitstatus_query returns 0 with VCS_STATUS_RESULT=tout. # -t FLOAT Timeout in seconds. Will block for at most this long. If no results are @@ -71,7 +76,7 @@ zmodload zsh/datetime zsh/system # VCS_STATUS_RESULT=tout and return 0. # -p Don't compute anything that requires reading Git index. If this option is used, # the following parameters will be 0: VCS_STATUS_INDEX_SIZE, -# VCS_STATUS_{NUM,HAS}_{STAGED,UNSTAGED,UNTRACKED}. +# VCS_STATUS_{NUM,HAS}_{STAGED,UNSTAGED,UNTRACKED,CONFLICTED}. # # On success sets VCS_STATUS_RESULT to one of the following values: # @@ -86,33 +91,37 @@ zmodload zsh/datetime zsh/system # # If VCS_STATUS_RESULT is ok-sync or ok-async, additional variables are set: # -# VCS_STATUS_WORKDIR Git repo working directory. Not empty. -# VCS_STATUS_COMMIT Commit hash that HEAD is pointing to. Either 40 hex digits or empty -# if there is no HEAD (empty repo). -# VCS_STATUS_LOCAL_BRANCH Local branch name or empty if not on a branch. -# VCS_STATUS_REMOTE_NAME The remote name, e.g. "upstream" or "origin". -# VCS_STATUS_REMOTE_BRANCH Upstream branch name. Can be empty. -# VCS_STATUS_REMOTE_URL Remote URL. Can be empty. -# VCS_STATUS_ACTION Repository state, A.K.A. action. Can be empty. -# VCS_STATUS_INDEX_SIZE The number of files in the index. -# VCS_STATUS_NUM_STAGED The number of staged changes. -# VCS_STATUS_NUM_CONFLICTED The number of unstaged changes. -# VCS_STATUS_NUM_UNSTAGED The number of unstaged changes. -# VCS_STATUS_NUM_UNTRACKED The number of untracked files. -# VCS_STATUS_HAS_STAGED 1 if there are staged changes, 0 otherwise. -# VCS_STATUS_HAS_CONFLICTED 1 if there are conflicted changes, 0 otherwise. -# VCS_STATUS_HAS_UNSTAGED 1 if there are unstaged changes, 0 if there aren't, -1 if unknown. -# VCS_STATUS_HAS_UNTRACKED 1 if there are untracked files, 0 if there aren't, -1 if unknown. -# VCS_STATUS_COMMITS_AHEAD Number of commits the current branch is ahead of upstream. -# Non-negative integer. -# VCS_STATUS_COMMITS_BEHIND Number of commits the current branch is behind upstream. Non-negative -# integer. -# VCS_STATUS_STASHES Number of stashes. Non-negative integer. -# VCS_STATUS_TAG The last tag (in lexicographical order) that points to the same -# commit as HEAD. +# VCS_STATUS_WORKDIR Git repo working directory. Not empty. +# VCS_STATUS_COMMIT Commit hash that HEAD is pointing to. Either 40 hex digits or +# empty if there is no HEAD (empty repo). +# VCS_STATUS_LOCAL_BRANCH Local branch name or empty if not on a branch. +# VCS_STATUS_REMOTE_NAME The remote name, e.g. "upstream" or "origin". +# VCS_STATUS_REMOTE_BRANCH Upstream branch name. Can be empty. +# VCS_STATUS_REMOTE_URL Remote URL. Can be empty. +# VCS_STATUS_ACTION Repository state, A.K.A. action. Can be empty. +# VCS_STATUS_INDEX_SIZE The number of files in the index. +# VCS_STATUS_NUM_STAGED The number of staged changes. +# VCS_STATUS_NUM_CONFLICTED The number of conflicted changes. +# VCS_STATUS_NUM_UNSTAGED The number of unstaged changes. +# VCS_STATUS_NUM_UNTRACKED The number of untracked files. +# VCS_STATUS_HAS_STAGED 1 if there are staged changes, 0 otherwise. +# VCS_STATUS_HAS_CONFLICTED 1 if there are conflicted changes, 0 otherwise. +# VCS_STATUS_HAS_UNSTAGED 1 if there are unstaged changes, 0 if there aren't, -1 if +# unknown. +# VCS_STATUS_NUM_UNSTAGED_DELETED The number of unstaged deleted files. Note that renamed files +# are reported as deleted plus added. +# VCS_STATUS_HAS_UNTRACKED 1 if there are untracked files, 0 if there aren't, -1 if +# unknown. +# VCS_STATUS_COMMITS_AHEAD Number of commits the current branch is ahead of upstream. +# Non-negative integer. +# VCS_STATUS_COMMITS_BEHIND Number of commits the current branch is behind upstream. +# Non-negative integer. +# VCS_STATUS_STASHES Number of stashes. Non-negative integer. +# VCS_STATUS_TAG The last tag (in lexicographical order) that points to the same +# commit as HEAD. # -# The point of reporting -1 as unstaged and untracked is to allow the command to skip scanning -# files in large repos. See -m flag of gitstatus_start. +# The point of reporting -1 via VCS_STATUS_HAS_* is to allow the command to skip scanning files in +# large repos. See -m flag of gitstatus_start. # # gitstatus_query returns an error if gitstatus_start hasn't been called in the same shell or # the call had failed. @@ -126,8 +135,8 @@ function gitstatus_query() { setopt err_return no_unset local opt - local dir=${${GIT_DIR:-$PWD}:a} - local callback='' + local dir=${GIT_DIR:-} + local callback local -F timeout=-1 local no_diff=0 while true; do @@ -144,12 +153,15 @@ function gitstatus_query() { (( OPTIND == ARGC )) || { echo "usage: gitstatus_query [OPTION]... NAME" >&2; return 1 } local name=${*[$OPTIND]} - [[ -n ${(P)${:-GITSTATUS_DAEMON_PID_${name}}:-} ]] + local daemon_pid_var=GITSTATUS_DAEMON_PID_${name} + (( ${(P)daemon_pid_var:-0} > 0 )) # Verify that gitstatus_query is running in the same process that ran gitstatus_start. local client_pid_var=_GITSTATUS_CLIENT_PID_${name} [[ ${(P)client_pid_var} == $$ ]] + [[ $dir == /* ]] || dir=${(%):-%/}/$dir + local req_fd_var=_GITSTATUS_REQ_FD_${name} local -i req_fd=${(P)req_fd_var} local -r req_id="$EPOCHREALTIME" @@ -203,6 +215,7 @@ function _gitstatus_process_response() { typeset -gi VCS_STATUS_COMMITS_BEHIND="${resp[16]}" typeset -gi VCS_STATUS_STASHES="${resp[17]}" typeset -g VCS_STATUS_TAG="${resp[18]}" + typeset -gi VCS_STATUS_NUM_UNSTAGED_DELETED="${resp[19]:-0}" typeset -gi VCS_STATUS_HAS_STAGED=$((VCS_STATUS_NUM_STAGED > 0)) (( dirty_max_index_size >= 0 && VCS_STATUS_INDEX_SIZE > dirty_max_index_size )) && { typeset -gi VCS_STATUS_HAS_UNSTAGED=-1 @@ -235,6 +248,7 @@ function _gitstatus_process_response() { unset VCS_STATUS_COMMITS_BEHIND unset VCS_STATUS_STASHES unset VCS_STATUS_TAG + unset VCS_STATUS_NUM_UNSTAGED_DELETED } (( ! ours )) && (( #header )) && emulate -L zsh && "${header[@]}" || true @@ -261,6 +275,8 @@ function _gitstatus_process_response() { # # -m INT If a repo has more files in its index than this, override -u and -d (but not -s) # with zeros. Negative value means infinity. Defaults to -1. +# +# -e Count files within untracked directories like `git status --untracked-files`. function gitstatus_start() { emulate -L zsh setopt err_return no_unset no_bg_nice @@ -272,15 +288,20 @@ function gitstatus_start() { local -i max_num_conflicted=1 local -i max_num_untracked=1 local -i dirty_max_index_size=-1 + local -i async + local recurse_untracked_dirs while true; do - getopts "t:s:u:d:m:" opt || break + getopts "t:s:u:c:d:m:ea" opt || break case $opt in + a) async=1;; t) timeout=$OPTARG;; s) max_num_staged=$OPTARG;; u) max_num_unstaged=$OPTARG;; c) max_num_conflicted=$OPTARG;; d) max_num_untracked=$OPTARG;; m) dirty_max_index_size=$OPTARG;; + e) recurse_untracked_dirs='--recurse-untracked-dirs';; + +e) recurse_untracked_dirs=;; ?) return 1;; esac done @@ -289,139 +310,170 @@ function gitstatus_start() { (( OPTIND == ARGC )) || { echo "usage: gitstatus_start [OPTION]... NAME" >&2; return 1 } local name=${*[$OPTIND]} - [[ -z ${(P)${:-GITSTATUS_DAEMON_PID_${name}}:-} ]] || return 0 - - local dir && dir=${${(%):-%x}:A:h} - local xtrace_file lock_file req_fifo resp_fifo log_file - local -i stderr_fd=-1 lock_fd=-1 req_fd=-1 resp_fd=-1 daemon_pid=-1 - - function gitstatus_start_impl() { - local log_level=${GITSTATUS_LOG_LEVEL:-} + local lock_file req_fifo resp_fifo log_level + local log_file=/dev/null xtrace_file=/dev/null + local -i stderr_fd lock_fd req_fd resp_fd daemon_pid + local daemon_pid_var=GITSTATUS_DAEMON_PID_${name} + (( $+parameters[$daemon_pid_var] )) && { + (( ! async )) || return 0 + daemon_pid=${(P)daemon_pid_var} + (( daemon_pid == -1 )) || return 0 + local resp_fd_var=_GITSTATUS_RESP_FD_${name} + local log_file_var=GITSTATUS_DAEMON_LOG_${name} + local xtrace_file_var=GITSTATUS_XTRACE_${name} + resp_fd=${(P)resp_fd_var} + log_file=${(P)log_file_var} + xtrace_file=${(P)xtrace_file_var} + } || { + log_level=${GITSTATUS_LOG_LEVEL:-} [[ -n $log_level || ${GITSTATUS_ENABLE_LOGGING:-0} != 1 ]] || log_level=INFO - [[ -z $log_level ]] || { - xtrace_file=$(mktemp "${TMPDIR:-/tmp}"/gitstatus.$$.xtrace.XXXXXXXXXX) - typeset -g GITSTATUS_XTRACE_${name}=$xtrace_file - exec {stderr_fd}>&2 2>$xtrace_file - setopt xtrace + log_file=${TMPDIR:-/tmp}/gitstatus.$$.daemon-log.$EPOCHREALTIME.$RANDOM + xtrace_file=${TMPDIR:-/tmp}/gitstatus.$$.xtrace.$EPOCHREALTIME.$RANDOM } - - local os && os=$(uname -s) && [[ -n $os ]] - [[ $os != Linux || $(uname -o) != Android ]] || os=Android - local arch && arch=$(uname -m) && [[ -n $arch ]] - - local daemon=${GITSTATUS_DAEMON:-$dir/bin/gitstatusd-${os:l}-${arch:l}} - [[ -f $daemon ]] - - lock_file=$(mktemp "${TMPDIR:-/tmp}"/gitstatus.$$.lock.XXXXXXXXXX) - zsystem flock -f lock_fd $lock_file - - req_fifo=$(mktemp -u "${TMPDIR:-/tmp}"/gitstatus.$$.pipe.req.XXXXXXXXXX) - mkfifo $req_fifo - - resp_fifo=$(mktemp -u "${TMPDIR:-/tmp}"/gitstatus.$$.pipe.resp.XXXXXXXXXX) - mkfifo $resp_fifo - - [[ -n $log_level ]] && - log_file=$(mktemp "${TMPDIR:-/tmp}"/gitstatus.$$.daemon-log.XXXXXXXXXX) || - log_file=/dev/null typeset -g GITSTATUS_DAEMON_LOG_${name}=$log_file + typeset -g GITSTATUS_XTRACE_${name}=$xtrace_file + } - local -i threads=${GITSTATUS_NUM_THREADS:-0} - (( threads > 0)) || { - threads=8 - case $os in - FreeBSD) (( ! $+commands[sysctl] )) || threads=$(( 2 * $(sysctl -n hw.ncpu) ));; - *) (( ! $+commands[getconf] )) || threads=$(( 2 * $(getconf _NPROCESSORS_ONLN) ));; - esac - (( threads <= 32 )) || threads=32 + function gitstatus_start_impl() { + [[ $xtrace_file == /dev/null ]] || { + exec {stderr_fd}>&2 2>>$xtrace_file + setopt xtrace } - local -a daemon_args=( - --lock-fd=3 - --parent-pid=${(q)$} - --num-threads=${(q)threads} - --max-num-staged=${(q)max_num_staged} - --max-num-unstaged=${(q)max_num_unstaged} - --max-num-conflicted=${(q)max_num_conflicted} - --max-num-untracked=${(q)max_num_untracked} - --dirty-max-index-size=${(q)dirty_max_index_size} - ${${log_level:#INFO}:+--log-level=$log_level}) - - local cmd=" - echo \$\$ - ${(q)daemon} $daemon_args - if [[ \$? != (0|10) && \$? -le 128 && - -z ${(q)GITSTATUS_DAEMON:-} && - -f ${(q)daemon}-static ]]; then - ${(q)daemon}-static $daemon_args - fi - echo -nE $'bye\x1f0\x1e'" - local setsid=${commands[setsid]:-/usr/local/opt/util-linux/bin/setsid} - [[ -f $setsid ]] && setsid=${(q)setsid} || setsid= - cmd="$setsid zsh -dfxc ${(q)cmd} &!" - # We use `zsh -c` instead of plain {} or () to work around bugs in zplug. It hangs on startup. - # Double fork is to daemonize. Some macOS users had issues when gitstatusd was a child process - # of the interactive zsh. For example, https://github.com/romkatv/powerlevel10k/issues/123 - # and https://github.com/romkatv/powerlevel10k/issues/97. Note that on macOS setsid has to - # be installed manually by running `brew install util-linux`. Unfortunately, none of these - # helped to resolve https://github.com/romkatv/powerlevel10k/issues/123. - zsh -dfmxc $cmd <$req_fifo >$resp_fifo 2>$log_file 3<$lock_file &! - - sysopen -w -o cloexec,sync -u req_fd $req_fifo - sysopen -r -o cloexec -u resp_fd $resp_fifo - - read -u $resp_fd daemon_pid - - rm -f $req_fifo $resp_fifo $lock_file - - function _gitstatus_process_response_${name}() { - _gitstatus_process_response ${${(%)${:-%N}}#_gitstatus_process_response_} 0 '' + (( daemon_pid == -1 )) || { + local daemon=${GITSTATUS_DAEMON:-} os + [[ -n $daemon ]] || { + os="$(uname -s)" && [[ -n $os ]] + [[ $os != Linux || "$(uname -o)" != Android ]] || os=Android + local arch && arch="$(uname -m)" && [[ -n $arch ]] + daemon=$_gitstatus_plugin_dir/bin/gitstatusd-${os:l}-${arch:l} + } + [[ -x $daemon ]] + + lock_file=${TMPDIR:-/tmp}/gitstatus.$$.lock.$EPOCHREALTIME.$RANDOM + echo -n >$lock_file + zsystem flock -f lock_fd $lock_file + + req_fifo=${TMPDIR:-/tmp}/gitstatus.$$.req.$EPOCHREALTIME.$RANDOM + resp_fifo=${TMPDIR:-/tmp}/gitstatus.$$.resp.$EPOCHREALTIME.$RANDOM + mkfifo $req_fifo $resp_fifo + + local -i threads=${GITSTATUS_NUM_THREADS:-0} + (( threads > 0)) || { + threads=8 + [[ -n $os ]] || { os="$(uname -s)" && [[ -n $os ]] } + case $os in + FreeBSD) (( ! $+commands[sysctl] )) || threads=$(( 2 * $(sysctl -n hw.ncpu) ));; + *) (( ! $+commands[getconf] )) || threads=$(( 2 * $(getconf _NPROCESSORS_ONLN) ));; + esac + (( threads <= 32 )) || threads=32 + } + + local -a daemon_args=( + --lock-fd=3 + --parent-pid=${(q)$} + --num-threads=${(q)threads} + --max-num-staged=${(q)max_num_staged} + --max-num-unstaged=${(q)max_num_unstaged} + --max-num-conflicted=${(q)max_num_conflicted} + --max-num-untracked=${(q)max_num_untracked} + --dirty-max-index-size=${(q)dirty_max_index_size} + --log-level=${(q)log_level:-INFO} + $recurse_untracked_dirs) + + local cmd=" + echo \$\$ + ${(q)daemon} $daemon_args + if [[ \$? != (0|10) && \$? -le 128 && -f ${(q)daemon}-static ]]; then + ${(q)daemon}-static $daemon_args + fi + echo -nE $'bye\x1f0\x1e'" + local setsid=${commands[setsid]:-/usr/local/opt/util-linux/bin/setsid} + [[ -x $setsid ]] && setsid=${(q)setsid} || setsid= + cmd="cd /; read; $setsid zsh -dfxc ${(q)cmd} &!; rm -f ${(q)req_fifo} ${(q)resp_fifo} ${(q)lock_file}" + # We use `zsh -c` instead of plain {} or () to work around bugs in zplug (it hangs on + # startup). Double fork is to daemonize, and so is `setsid`. Note that on macOS `setsid` has + # to be installed manually by running `brew install util-linux`. + zsh -dfmxc $cmd <$req_fifo >$resp_fifo 2>$log_file 3<$lock_file &! + + sysopen -w -o cloexec,sync -u req_fd $req_fifo + sysopen -r -o cloexec -u resp_fd $resp_fifo + echo -nE $'0\nhello\x1f\x1e' >&$req_fd } - zle -F $resp_fd _gitstatus_process_response_${name} - - local reply IFS='' - echo -nE $'hello\x1f\x1e' >&$req_fd - read -r -d $'\x1e' -u $resp_fd -t $timeout reply - [[ $reply == $'hello\x1f0' ]] - - function _gitstatus_cleanup_${ZSH_SUBSHELL}_${daemon_pid}() { - emulate -L zsh - setopt err_return no_unset - local fname=${(%):-%N} - local prefix=_gitstatus_cleanup_${ZSH_SUBSHELL}_ - [[ $fname == ${prefix}* ]] || return 0 - local -i daemon_pid=${fname#$prefix} - kill -- -$daemon_pid &>/dev/null || true + + (( async )) && { + daemon_pid=-1 + } || { + read -u $resp_fd daemon_pid + + function _gitstatus_process_response_${name}() { + local name=${${(%):-%N}#_gitstatus_process_response_} + (( ARGC == 1 )) && { + _gitstatus_process_response $name 0 '' + true + } || { + gitstatus_stop $name + } + } + zle -F $resp_fd _gitstatus_process_response_${name} + + local reply IFS='' + read -r -d $'\x1e' -u $resp_fd -t $timeout reply + [[ $reply == $'hello\x1f0' ]] + + function _gitstatus_cleanup_$$_${ZSH_SUBSHELL}_${daemon_pid}() { + emulate -L zsh + setopt err_return no_unset + local fname=${(%):-%N} + local prefix=_gitstatus_cleanup_$$_${ZSH_SUBSHELL}_ + [[ $fname == ${prefix}* ]] || return 0 + local -i daemon_pid=${fname#$prefix} + kill -- -$daemon_pid &>/dev/null || true + } + add-zsh-hook zshexit _gitstatus_cleanup_$$_${ZSH_SUBSHELL}_${daemon_pid} } - add-zsh-hook zshexit _gitstatus_cleanup_${ZSH_SUBSHELL}_${daemon_pid} - [[ $stderr_fd == -1 ]] || { + (( ! stderr_fd )) || { unsetopt xtrace exec 2>&$stderr_fd {stderr_fd}>&- - stderr_fd=-1 + stderr_fd=0 } } gitstatus_start_impl && { typeset -gi GITSTATUS_DAEMON_PID_${name}=$daemon_pid - typeset -gi _GITSTATUS_REQ_FD_${name}=$req_fd - typeset -gi _GITSTATUS_RESP_FD_${name}=$resp_fd - typeset -gi _GITSTATUS_LOCK_FD_${name}=$lock_fd - typeset -gi _GITSTATUS_CLIENT_PID_${name}=$$ - typeset -gi _GITSTATUS_DIRTY_MAX_INDEX_SIZE_${name}=$dirty_max_index_size + (( ! req_fd )) || { + typeset -gi _GITSTATUS_REQ_FD_${name}=$req_fd + typeset -gi _GITSTATUS_RESP_FD_${name}=$resp_fd + typeset -gi _GITSTATUS_LOCK_FD_${name}=$lock_fd + typeset -gi _GITSTATUS_CLIENT_PID_${name}=$$ + typeset -gi _GITSTATUS_DIRTY_MAX_INDEX_SIZE_${name}=$dirty_max_index_size + } unset -f gitstatus_start_impl } || { unsetopt err_return - add-zsh-hook -d zshexit _gitstatus_cleanup_${ZSH_SUBSHELL}_${daemon_pid} - [[ $daemon_pid -gt 0 ]] && kill -- -$daemon_pid &>/dev/null - [[ $stderr_fd -ge 0 ]] && { exec 2>&$stderr_fd {stderr_fd}>&- } - [[ $lock_fd -ge 0 ]] && zsystem flock -u $lock_fd - [[ $req_fd -ge 0 ]] && exec {req_fd}>&- - [[ $resp_fd -ge 0 ]] && { zle -F $resp_fd; exec {resp_fd}>&- } + add-zsh-hook -d zshexit _gitstatus_cleanup_$$_${ZSH_SUBSHELL}_${daemon_pid} + (( $+functions[_gitstatus_process_response_${name}] )) && { + zle -F $resp_fd + unfunction _gitstatus_process_response_${name} + } + (( resp_fd )) && exec {resp_fd}>&- + (( req_fd )) && exec {req_fd}>&- + (( lock_fd )) && zsystem flock -u $lock_fd + (( stderr_fd )) && { exec 2>&$stderr_fd {stderr_fd}>&- } + (( daemon_pid > 0 )) && kill -- -$daemon_pid &>/dev/null + rm -f $lock_file $req_fifo $resp_fifo unset -f gitstatus_start_impl + unset GITSTATUS_DAEMON_PID_${name} + unset _GITSTATUS_REQ_FD_${name} + unset _GITSTATUS_RESP_FD_${name} + unset _GITSTATUS_LOCK_FD_${name} + unset _GITSTATUS_CLIENT_PID_${name} + unset _GITSTATUS_DIRTY_MAX_INDEX_SIZE_${name} + >&2 print -P '[%F{red}ERROR%f]: gitstatus failed to initialize.' >&2 echo -E '' >&2 echo -E ' Your git prompt may disappear or become slow.' @@ -439,7 +491,7 @@ function gitstatus_start() { >&2 awk '{print " " $0}' <$log_file >&2 print -nP '%f' fi - if [[ -n ${GITSTATUS_LOG_LEVEL:-} || ${GITSTATUS_ENABLE_LOGGING:-0} == 1 ]]; then + if [[ ${GITSTATUS_LOG_LEVEL:-} == DEBUG ]]; then >&2 echo -E '' >&2 echo -E ' Your system information:' >&2 print -P '%F{yellow}' @@ -476,20 +528,28 @@ function gitstatus_stop() { local lock_fd_var=_GITSTATUS_LOCK_FD_${name} local daemon_pid_var=GITSTATUS_DAEMON_PID_${name} local client_pid_var=_GITSTATUS_CLIENT_PID_${name} + local dirty_size_var=_GITSTATUS_DIRTY_MAX_INDEX_SIZE_${name} + + [[ ${(P)daemon_pid_var:-} != -1 ]] || gitstatus_start -t 0 "$name" 2>/dev/null local req_fd=${(P)req_fd_var:-} local resp_fd=${(P)resp_fd_var:-} local lock_fd=${(P)lock_fd_var:-} - local daemon_pid=${(P)daemon_pid_var:-} + local daemon_pid=${(P)daemon_pid_var:-0} + + local cleanup_func=_gitstatus_cleanup_$$_${ZSH_SUBSHELL}_${daemon_pid} - local cleanup_func=_gitstatus_cleanup_${ZSH_SUBSHELL}_${daemon_pid} + (( $+functions[_gitstatus_process_response_${name}] )) && { + zle -F $resp_fd + unfunction _gitstatus_process_response_${name} + } - [[ -n $daemon_pid ]] && kill -- -$daemon_pid &>/dev/null - [[ -n $req_fd ]] && exec {req_fd}>&- - [[ -n $resp_fd ]] && { zle -F $resp_fd; exec {resp_fd}>&- } - [[ -n $lock_fd ]] && zsystem flock -u $lock_fd + (( resp_fd )) && exec {resp_fd}>&- + (( req_fd )) && exec {req_fd}>&- + (( lock_fd )) && zsystem flock -u $lock_fd + (( daemon_pid > 0 )) && kill -- -$daemon_pid &>/dev/null - unset $req_fd_var $resp_fd_var $lock_fd_var $daemon_pid_var $client_pid_var + unset $req_fd_var $resp_fd_var $lock_fd_var $daemon_pid_var $client_pid_var $dirty_size_var if (( $+functions[$cleanup_func] )); then add-zsh-hook -d zshexit $cleanup_func @@ -506,8 +566,9 @@ function gitstatus_stop() { function gitstatus_check() { emulate -L zsh (( ARGC == 1 )) || { echo "usage: gitstatus_check NAME" >&2; return 1 } - [[ -n ${(P)${:-GITSTATUS_DAEMON_PID_${1}}} ]] + local daemon_pid_var=GITSTATUS_DAEMON_PID_${1} + (( ${(P)daemon_pid_var:-0} > 0 )) } -(( ! _gitstatus_restore_aliases )) || setopt aliases -'builtin' 'unset' '_gitstatus_restore_aliases' +(( ${#_gitstatus_opts} )) && setopt ${_gitstatus_opts[@]} +'builtin' 'unset' '_gitstatus_opts' diff --git a/gitstatus/pull-upstream.zsh b/gitstatus/pull-upstream.zsh index 2cb758a5..0ec22438 100755 --- a/gitstatus/pull-upstream.zsh +++ b/gitstatus/pull-upstream.zsh @@ -9,10 +9,10 @@ setopt err_exit no_unset pipe_fail extended_glob xtrace readonly GITSTATUS_DIR GITSTATUS_URL readonly -a IGNORE=(pull-upstream.zsh README.md) -function pull() { - local repo && repo=$(mktemp -d ${TMPDIR:-/tmp}/gitstatus-pull-upstream.XXXXXXXXXX) +() { + local repo && repo="$(mktemp -d ${TMPDIR:-/tmp}/gitstatus-pull-upstream.XXXXXXXXXX)" trap "rm -rf ${(q)repo}" EXIT - git clone $GITSTATUS_URL $repo + git clone --depth 1 $GITSTATUS_URL $repo local dst for dst in $GITSTATUS_DIR/**/*(.,@); do @@ -22,9 +22,7 @@ function pull() { [[ -f $src ]] && { mkdir -p ${dst:h} && cp -f $src $dst || return } || { - rm $dst + rm -f $dst } done } - -pull |