Created
October 7, 2021 03:57
-
-
Save Milly/f2e57dab3852e0750dd21f186d0f5dd9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
zstyle ':vcs_info:git+set-message:*' hooks git_compute_vars | |
function __git_eread() { | |
[[ -r "$1" ]] && IFS=$'\r\n' read "$2" <"$1" | |
} | |
function __git_config_hash() { | |
local _reg="$1" | |
local _out="$(git config -z --get-regexp "$_reg" 2>/dev/null|tr '\0\n' '\n ')" | |
local _k _v | |
while read -r _k _v; do config[${_k}]=$_v; done <<< "$_out" | |
} | |
function +vi-git_compute_vars() { | |
[[ $1 == 0 ]] || return 0 | |
local repo_info="$(git rev-parse \ | |
--absolute-git-dir \ | |
--is-inside-git-dir \ | |
--is-inside-work-tree \ | |
--is-bare-repository \ | |
--short HEAD \ | |
2>/dev/null)" || return | |
: ${(A)repo_info::="${(@f)repo_info}"} | |
local git_dir=${repo_info[1]} | |
local inside_gitdir=${repo_info[2]} | |
local inside_worktree=${repo_info[3]} | |
local bare_repo=${repo_info[4]} | |
local short_sha=${repo_info[5]} | |
local dir_state= | |
local unstaged= | |
local staged= | |
local stashed= | |
local untracked= | |
local upstream= | |
local upstream_name= | |
if [[ $inside_gitdir == 'true' ]]; then | |
if [[ $bare_repo == 'true' ]]; then | |
dir_state="%F{red}BARE%f:" | |
else | |
dir_state="%F{red}GIT_DIR%f!" | |
fi | |
elif [[ $inside_worktree == true ]]; then | |
git diff --no-ext-diff --quiet || unstaged='*' | |
git diff --no-ext-diff --cached --quiet || staged='+' | |
[[ -z $short_sha && -z $staged ]] && staged='#' | |
git rev-parse --verify --quiet refs/stash >/dev/null && stashed='$' | |
git ls-files --others --exclude-standard --directory \ | |
--no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null \ | |
&& untracked='%' | |
local count=($(git rev-list --count --left-right '@{upstream}...HEAD' 2>/dev/null)) | |
if [[ ${#count} == 0 ]]; then # no upstream | |
: | |
elif [[ ${count[1]} == 0 ]]; then # equal or ahead | |
[[ ${count[2]} == 0 ]] && upstream='=' || upstream="+${count[2]}" | |
elif [[ ${count[2]} == 0 ]]; then # behind | |
upstream="-${count[1]}" | |
else # diverged | |
upstream="+${count[2]}-${count[1]}" | |
fi | |
[[ -n $upstream ]] \ | |
&& upstream_name="$(git rev-parse --abbrev-ref '@{upstream}' 2>/dev/null)" | |
fi | |
local action= | |
local branch= | |
local step= | |
local total= | |
local detached=no | |
if [[ -d "$git_dir/rebase-merge" ]]; then | |
__git_eread "$git_dir/rebase-merge/head-name" branch | |
__git_eread "$git_dir/rebase-merge/msgnum" step | |
__git_eread "$git_dir/rebase-merge/end" total | |
if [[ -f "$git_dir/rebase-merge/interactive" ]]; then | |
action="REBASE-i" | |
else | |
action="REBASE-m" | |
fi | |
else | |
if [[ -d "$git_dir/rebase-apply" ]]; then | |
__git_eread "$git_dir/rebase-apply/next" step | |
__git_eread "$git_dir/rebase-apply/last" total | |
if [[ -f "$git_dir/rebase-apply/rebasing" ]]; then | |
__git_eread "$git_dir/rebase-apply/head-name" branch | |
action="REBASE" | |
elif [[ -f "$git_dir/rebase-apply/applying" ]]; then | |
action="AM" | |
else | |
action="AM/REBASE" | |
fi | |
elif [[ -f "$git_dir/MERGE_HEAD" ]]; then | |
action="MERGING" | |
elif [[ -f "$git_dir/CHERRY_PICK_HEAD" ]]; then | |
action="CHERRY-PICKING" | |
elif [[ -f "$git_dir/REVERT_HEAD" ]]; then | |
action="REVERTING" | |
elif [[ -f "$git_dir/BISECT_LOG" ]]; then | |
action="BISECTING" | |
fi | |
if [[ -n "$branch" ]]; then | |
: | |
elif [[ -h "$git_dir/HEAD" ]]; then | |
# symlink symbolic ref | |
branch="$(git symbolic-ref HEAD 2>/dev/null)" | |
else | |
local head= | |
__git_eread "$git_dir/HEAD" head || return | |
# is it a symbolic ref? | |
branch="${head#ref: }" | |
if [[ "$head" = "$branch" ]]; then | |
detached=yes | |
branch="$(git describe --tags --exact-match HEAD 2>/dev/null)" || | |
branch="$short_sha..." | |
branch="($branch)" | |
fi | |
fi | |
fi | |
branch="%F{magenta}${branch#refs/heads/}%f" | |
[[ -n "$action" ]] && action="|%F{red}$action%f" | |
[[ -n "$step" && -n "$total" ]] && action="$action $step/$total" | |
local state= | |
if [[ -z "$unstaged$staged$untracked" ]]; then | |
state="%F{green}OK%f" | |
else | |
[[ -n "$unstaged" ]] && state="$state${state:+,}%B%F{red}Changed%b%f" | |
[[ -n "$staged" ]] && state="$state${state:+,}%B%F{green}Staged%b%f" | |
[[ -n "$untracked" ]] && state="$state${state:+,}%F{yellow}Untrack%f" | |
fi | |
[[ -n "$stashed" ]] && state="$state${state:+,}%F{cyan}Stash%f" | |
state="$state" | |
local sub_module= | |
[[ "$git_dir" == */.git/modules/* ]] \ | |
&& sub_module="%F{white}${git_dir#*/.git/modules/}%f:" | |
local -A config | |
__git_config_hash '^user\.(name|email)$' | |
local user="%F{yellow}${config[user.name]}" | |
[[ -n ${config[user.email]} ]] && user="$user %F{cyan}<${config[user.email]}>" | |
user="$user%f" | |
hook_com[message]="%f(git)-[${dir_state}${sub_module}${branch}${upstream}](${state}${action}):$user%f" | |
ret=1 # show $hook[message] as is | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment