diff --git a/functions/_tide_item_git.fish b/functions/_tide_item_git.fish index 56e1e315..a95e65ea 100644 --- a/functions/_tide_item_git.fish +++ b/functions/_tide_item_git.fish @@ -1,16 +1,6 @@ function _tide_item_git - if git branch --show-current 2>/dev/null | string shorten -"$tide_git_truncation_strategy"m$tide_git_truncation_length | read -l location - git rev-parse --git-dir --is-inside-git-dir | read -fL gdir in_gdir - set location $_tide_location_color$location - else if test $pipestatus[1] != 0 - return - else if git tag --points-at HEAD | string shorten -"$tide_git_truncation_strategy"m$tide_git_truncation_length | read location - git rev-parse --git-dir --is-inside-git-dir | read -fL gdir in_gdir - set location '#'$_tide_location_color$location - else - git rev-parse --git-dir --is-inside-git-dir --short HEAD | read -fL gdir in_gdir location - set location @$_tide_location_color$location - end + git rev-parse --git-dir --is-inside-git-dir 2>/dev/null | read -fL gdir in_gdir + or return # Operation if test -d $gdir/rebase-merge @@ -44,16 +34,40 @@ function _tide_item_git # Git status/stash + Upstream behind/ahead test $in_gdir = true && set -l _set_dir_opt -C $gdir/.. - # Suppress errors in case we are in a bare repo or there is no upstream - set -l stat (git $_set_dir_opt --no-optional-locks status --porcelain 2>/dev/null) - string match -qr '(0|(?.*))\n(0|(?.*))\n(0|(?.*)) -(0|(?.*))\n(0|(?.*))(\n(0|(?.*))\t(0|(?.*)))?' \ - "$(git $_set_dir_opt stash list 2>/dev/null | count - string match -r ^UU $stat | count - string match -r ^[ADMR] $stat | count - string match -r ^.[ADMR] $stat | count - string match -r '^\?\?' $stat | count - git rev-list --count --left-right @{upstream}...HEAD 2>/dev/null)" + set -l stat (git $_set_dir_opt --no-optional-locks status --porcelain --branch 2>/dev/null) + + set -l location + set -l ahead (string match -r '(?<=ahead )\d+' $stat[1]) + set -l behind (string match -r '(?<=behind )\d+' $stat[1]) + + set -l conflicted (count (string match -r '^UU' $stat[2..])) + set -l staged (count (string match -r '^[ADMR]' $stat[2..])) + set -l dirty (count (string match -r '^.[ADMR]' $stat[2..])) + set -l untracked (count (string match -r '^\?\?' $stat[2..])) + + # Get location + set -l branch (string split '...' $stat[1])[1] + set branch (string replace -r '^## (?:No commits yet on )?' '' $branch) + + if test -n "$branch" -a "$branch" != "HEAD (no branch)" + set location (echo -ns $branch | string shorten -"$tide_git_truncation_strategy"m$tide_git_truncation_length) + set location $_tide_location_color$location + else if git branch --show-current 2>/dev/null | string shorten -"$tide_git_truncation_strategy"m$tide_git_truncation_length | read -f location + set location $_tide_location_color$location + else if git tag --points-at HEAD 2>/dev/null | string shorten -"$tide_git_truncation_strategy"m$tide_git_truncation_length | read location + set location '#'$_tide_location_color$location + else + git rev-parse --short HEAD 2>/dev/null | read -f location + set location @$_tide_location_color$location + end + + set -l stash (git $_set_dir_opt stash list 2>/dev/null | count) + + test "$stash" = 0 && set -e stash + test "$conflicted" = 0 && set -e conflicted + test "$staged" = 0 && set -e staged + test "$dirty" = 0 && set -e dirty + test "$untracked" = 0 && set -e untracked if test -n "$operation$conflicted" set -g tide_git_bg_color $tide_git_bg_color_urgent diff --git a/tests/_tide_item_git.test.fish b/tests/_tide_item_git.test.fish index d3d7f605..7c4cf4d9 100644 --- a/tests/_tide_item_git.test.fish +++ b/tests/_tide_item_git.test.fish @@ -99,7 +99,7 @@ _git_item # CHECK: 10charhere ?1 cd $dir/massive-status-repo _git init _git branch -m main -mock git "--no-optional-locks status --porcelain" "string repeat -n100000 'D some-file-name'\n" +mock git "--no-optional-locks status --porcelain --branch" "echo '## main'; string repeat -n100000 'D some-file-name'\n" _git_item # CHECK: main +100000 # ------ cleanup ------