diff options
Diffstat (limited to '')
| -rwxr-xr-x | git-sonar | 114 |
1 files changed, 59 insertions, 55 deletions
@@ -83,6 +83,7 @@ FETCH_TIME="${GIT_SONAR_FETCH_TIME:-"300"}" ALERT_ICON="${GIT_SONAR_ALERT_ICON:-"${COLOR_YELLOW}⚡"}" STASH_ICON="${GIT_SONAR_STASH_ICON:-"${COLOR_YELLOW}≡"}" BRANCH_COLOR="${GIT_SONAR_BRANCH_COLOR:-"$COLOR_DEF"}" +STATUS_SEP="${GIT_SONAR_STATUS_SEPARATOR:-" "}" AHEAD_ICON="${GIT_SONAR_AHEAD_ICON:-"${COLOR_GREEN}↑"}" # "←" BEHIND_ICON="${GIT_SONAR_BEHIND_ICON:-"${COLOR_RED}↓"}" # "→" @@ -94,13 +95,10 @@ UNMERGED_COLOR="${GIT_SONAR_UNMERGED_COLOR:-"$COLOR_YELLOW"}" UNTRACKED_COLOR="${GIT_SONAR_UNTRACKED_COLOR:-"$COLOR_WHITE"}" PROMPT_COLOR="${GIT_SONAR_PROMPT_COLOR:-"$COLOR_GRAY"}" -PROMPT_FORMAT="${GIT_SONAR_PROMPT_FORMAT:-" ${PROMPT_COLOR}git:(${COLOR_DEF}%{alert}%{remote: }%{branch}%{ :local}${PROMPT_COLOR})${COLOR_DEF}%{ :stash}%{ :staged}%{ :unmerged}%{ :unstaged}%{ :untracked}"}" +PROMPT_FORMAT="${GIT_SONAR_PROMPT_FORMAT:-" ${PROMPT_COLOR}git:(${COLOR_DEF}%{alert}%{remote: }%{branch}%{ :local}${PROMPT_COLOR})${COLOR_DEF}%{ :stash}%{ :status}"}" -# Gather current git status and branch information. git porcelain status can -# be especially expensive to compute, so bypass it if the prompt disables status -# information. -[ -n "$opt_status" ] && git_status="$(git status --porcelain 2>/dev/null)" || git_status="" -upstream_name="$(git rev-parse --abbrev-ref --symbolic-full-name '@{upstream}' 2>/dev/null)" +# Gather information about the current git branch. +upstream_name="$(git rev-parse --abbrev-ref '@{upstream}' 2>/dev/null)" branch_name="$(git symbolic-ref --short HEAD 2>/dev/null)" commit_hash="$(git rev-parse --short HEAD 2>/dev/null)" @@ -116,18 +114,6 @@ determine_default_branch() { done } -line_count() { - # macos 'wc' produces odd formatting (extra spaces) - # The grep is present to deal with this, filter out cases where the count - # is zero, and provide a return value (true if count is non-zero). - wc -l 2>/dev/null | grep -oE '[1-9][0-9]*' -} - -status_count() { - # Use a sed transform to prevent unmerged paths from being miscounted - echo "$git_status" | sed -nE "s/^AA /AU /;s/^DD /DU /;/${1}/p" | line_count -} - print_commit_range() { if [ -n "$1" ] && [ -n "$2" ]; then ahead="$(git rev-list --count "${1}..${2}" 2>/dev/null)" || ahead="0" @@ -173,65 +159,86 @@ element_local() { element_stash() { if [ -n "$opt_stash" ]; then - if cnt="$(git stash list | line_count)"; then + cnt="$(git rev-list --walk-reflogs --ignore-missing --count refs/stash)" + if [ "$cnt" -ne 0 ]; then printf '%s%b%b' "$cnt" "$STASH_ICON" "$COLOR_DEF" fi fi } -element_staged() { +element_status() { if [ -n "$opt_status" ]; then + # git status is the most expensive subprocess we call, so place it here + # to bypass it if $opt_status is "false". The output is filtered + # through sed to prevent certain unmerged paths from being double + # counted as staged/unstaged ("AA"/"DD"). + git_status="$(\ + git status --porcelain 2>/dev/null \ + | sed 's/^AA /AU /;s/^DD /DU /' \ + )" + + gs="" + st_sep="$STATUS_SEP" + um_sep="$STATUS_SEP" + us_sep="$STATUS_SEP" + ut_sep="$STATUS_SEP" + + # See "man 1 git-status" sections "Short Format" and "Porcelain Format + # Version 1" for an explanation of these status indicators. + + # Staged for x in A M R C D T; do - if cnt="$(status_count "^${x}[^U] ")"; then - printf '%s%b%s%b' "$cnt" "$STAGED_COLOR" "$x" "$COLOR_DEF" + if cnt="$(echo "$git_status" | grep -cE "^${x}[^U] ")"; then + gs="$(printf '%b%b%s%b%s%b' \ + "$gs" "$st_sep" "$cnt" "$STAGED_COLOR" "$x" "$COLOR_DEF" \ + )" + st_sep="" fi done - fi -} -element_unstaged() { - if [ -n "$opt_status" ]; then - for x in M D T; do - if cnt="$(status_count "^[^U]${x} ")"; then - printf '%s%b%s%b' "$cnt" "$UNSTAGED_COLOR" "$x" "$COLOR_DEF" + # Unmerged, conflicted + for x in A U D; do + if cnt="$(echo "$git_status" | grep -cE "^(U${x}|${x}U) ")"; then + gs="$(printf '%b%b%s%b%s%b' \ + "$gs" "$um_sep" "$cnt" "$UNMERGED_COLOR" "$x" "$COLOR_DEF" \ + )" + um_sep="" fi done - fi -} -element_unmerged() { - if [ -n "$opt_status" ]; then - for x in A U D; do - if cnt="$(status_count "^(U${x}|${x}U) ")"; then - printf '%s%b%s%b' "$cnt" "$UNMERGED_COLOR" "$x" "$COLOR_DEF" + # Unstaged + for x in M D T; do # R C omitted + if cnt="$(echo "$git_status" | grep -cE "^[^U]${x} ")"; then + gs="$(printf '%b%b%s%b%s%b' \ + "$gs" "$us_sep" "$cnt" "$UNSTAGED_COLOR" "$x" "$COLOR_DEF" \ + )" + us_sep="" fi done - fi -} -element_untracked() { - if [ -n "$opt_status" ]; then - if cnt="$(status_count "^\?\? ")"; then - printf '%s%b?%b' "$cnt" "$UNTRACKED_COLOR" "$COLOR_DEF" + # Untracked + if cnt="$(echo "$git_status" | grep -cE "^\?\? ")"; then + gs="$(printf '%b%b%s%b?%b' \ + "$gs" "$ut_sep" "$cnt" "$UNTRACKED_COLOR" "$COLOR_DEF" \ + )" + ut_sep="" fi + + printf '%b' "${gs#"$STATUS_SEP"}" fi } # Main functions -IF_PRE="%\{([^%{}]{1,}:){0,1}" -IF_POST="(:[^%{}]{1,}){0,1}\}" SED_PRE="%{\(\([^%^{^}]*\)\:\)\{0,1\}" SED_POST="\(\:\([^%^{^}]*\)\)\{0,1\}}" prepare_element() { - if echo "$PROMPT_FORMAT" | grep -qE "${IF_PRE}${1}${IF_POST}"; then - result="$($2 | sed -e 's/\//\\\//g')" - if [ -n "$result" ]; then - printf '%b' "s/${SED_PRE}${1}${SED_POST}/\\\\2${result}\\\\4/" - else - printf '%b' "s/${SED_PRE}${1}${SED_POST}//" - fi + result="$($2 | sed 's/\//\\\//g')" + if [ -n "$result" ]; then + printf '%b' "s/${SED_PRE}${1}${SED_POST}/\\\\2${result}\\\\4/" + else + printf '%b' "s/${SED_PRE}${1}${SED_POST}//" fi } @@ -255,7 +262,4 @@ printf '%b' "$PROMPT_FORMAT" | sed \ -e "$(prepare_element remote element_remote)" \ -e "$(prepare_element local element_local)" \ -e "$(prepare_element stash element_stash)" \ - -e "$(prepare_element staged element_staged)" \ - -e "$(prepare_element unstaged element_unstaged)" \ - -e "$(prepare_element unmerged element_unmerged)" \ - -e "$(prepare_element untracked element_untracked)" + -e "$(prepare_element status element_status)" |
