Various updates to __prompt_git_status in .bashrc. See full log.

* Update various comments, include expected arguments and example prompt.
* Use IFS to split GIT_REPO_INFO on \n rather than spaces.
* If the repository has no commits yet, display "!NO COMMITS!" as the branch.
* Use the GIT_REPO_INFO for top-directory instead of another call out to git.
* Use pwd -P to force actual paths not following symlinks.
* Pull upstream status if GIT_PROMPT_AUTO_PREFETCH is set, the current
  directory is the git repo top-dir and maintenance tasks for this repo have
  been enabled.  This allows reporting whether the branch is behind the
  remote by any number.
This commit is contained in:
Darren 'Tadgy' Austin 2023-10-07 20:29:01 +01:00
commit 735e2d504e

52
.bashrc
View file

@ -3,28 +3,35 @@
__prompt_git_status() { __prompt_git_status() {
# Generate a git branch/status prompt. # Generate a git branch/status prompt.
# Based on git-prompt.sh by Shawn O. Pearce <spearce@spearce.org>. # Based on git-prompt.sh by Shawn O. Pearce <spearce@spearce.org>.
# Arguments:
# $1 The printf format string for the prompt. Must include %s.
# Environment variables: # Environment variables:
# GIT_PROMPT_SHOW_TYPE=1 - Show type of repository (Bare, Shallow). # GIT_PROMPT_SHOW_TYPE=1 Show type of repository (Bare, Shallow).
# GIT_PROMPT_SHOW_IGNORED=1 - Show a ! if the directory is ignored. # GIT_PROMPT_SHOW_IGNORED=1 Show a ! if the current directory is ignored.
# GIT_PROMPT_SHOW_UNSTAGED=1 - Show a * if there are unstaged changes (superceeded by above). # GIT_PROMPT_SHOW_UNSTAGED=1 Show a * if there are unstaged changes (superceeded by above).
# GIT_PROMPT_SHOW_UNCOMMITTED=1 - Show a & if there are staged but uncommitted changes (superceeded by above). # GIT_PROMPT_SHOW_UNCOMMITTED=1 Show a & if there are staged but uncommitted changes (superceeded by above).
# GIT_PROMPT_SHOW_UNTRACKED=1 - Show a ? if there are untracked files in the working directory (superceeded by above). # GIT_PROMPT_SHOW_UNTRACKED=1 Show a ? if there are untracked files in the working directory (superceeded by above).
# GIT_PROMPT_SHOW_STASH=1 - Show a $ if there is a stash in this repository (superceeded by above). # GIT_PROMPT_SHOW_STASH=1 Show a $ if there is a stash in this repository (superceeded by above).
# GIT_PROMPT_SHOW_UPSTREAM=1 - Show status of this repository compaired to upstream: # GIT_PROMPT_SHOW_UPSTREAM=1 Show status of this repository compaired to upstream:
# ?? - No upstream set. # ?? - No upstream set.
# == - Working tree is equal to upstream. # == - Working tree is equal to upstream.
# <> - Divergent from upstream. # <> - Divergent from upstream.
# >> or >x - Working tree is ahead of upstream (x = commits ahead when used with next option). # >> or >x - Working tree is ahead of upstream (x = commits ahead when used with next option).
# << or <x - Working tree is behind upstream (x = commits behind when used with next option). # << or <x - Working tree is behind upstream (x = commits behind when used with next option).
# GIT_PROMPT_SHOW_UPSTREAM_EXTENDED=1 - In addition to upstream status, show the number of commits difference (inplies above). # GIT_PROMPT_SHOW_UPSTREAM_EXTENDED=1 In addition to upstream status, show the number of commits difference (inplies above).
local COUNT GIT_PROMPT GIT_REPO_INFO RET="$?" # GIT_PROMPT_AUTO_PREFETCH=1 Automatically 'prefetch' upstream refs for comparisons (requires GIT_PROMPT_SHOW_UPSTREAM above).
# Displays: The printf formatted git prompt based upon $1 and the environment vaiables above, for example:
# S:branch_name * >5
# Returns: Exit code of the command line before entering this function.
# shellcheck disable=SC2155
local COUNT GIT_PROMPT GIT_REPO_INFO PWD=$(pwd -P) RET="$?"
# Bail out if there's no format argument given. # Bail out if there's no format argument given.
(( $# != 1 )) && return "$RET" (( $# != 1 )) && return "$RET"
# Get some repository information. # Get some repository information.
# shellcheck disable=SC2207 # shellcheck disable=SC2207
GIT_REPO_INFO=( $(git rev-parse --show-toplevel --git-dir --is-bare-repository --is-shallow-repository --is-inside-git-dir --is-inside-work-tree \ IFS=$'\n' GIT_REPO_INFO=( $(git rev-parse --show-toplevel --git-dir --is-bare-repository --is-shallow-repository --is-inside-git-dir --is-inside-work-tree \
--glob=prefetch 2>/dev/null) ) --glob=prefetch 2>/dev/null) )
ERR="$?" ERR="$?"
@ -33,11 +40,11 @@ __prompt_git_status() {
# Generate the prompt. # Generate the prompt.
if [[ "${GIT_REPO_INFO[4]}" == "true" ]]; then if [[ "${GIT_REPO_INFO[4]}" == "true" ]]; then
# If in the git directory, use a special branch marker. # In the git directory, use a special branch marker.
GIT_PROMPT+="!GIT_DIR!" GIT_PROMPT+="!GIT_DIR!"
elif [[ "${GIT_REPO_INFO[5]}" == "true" ]]; then elif [[ "${GIT_REPO_INFO[5]}" == "true" ]]; then
# If in the working directory, generate the prompt. # In the working directory, generate the prompt.
# Add status markers. # Add type markers.
[[ -n "$GIT_PROMPT_SHOW_TYPE" ]] && { [[ -n "$GIT_PROMPT_SHOW_TYPE" ]] && {
if [[ "${GIT_REPO_INFO[2]}" == "true" ]]; then if [[ "${GIT_REPO_INFO[2]}" == "true" ]]; then
GIT_PROMPT+="B:" GIT_PROMPT+="B:"
@ -46,11 +53,15 @@ __prompt_git_status() {
fi fi
} }
# Add the branch. # Add the branch if there have been commits.
if [[ -e "${GIT_REPO_INFO[1]}/refs/heads/master" ]]; then
GIT_PROMPT+="$(git describe --contains --all HEAD)" GIT_PROMPT+="$(git describe --contains --all HEAD)"
else
GIT_PROMPT+="!NO COMMITS!"
fi
# Add a marker if directory is ignored, there's untracked files or a stash. # Add a marker if directory is ignored, there's unstaged files, uncommitted changes, untracked files or a stash.
if [[ -n "$GIT_PROMPT_SHOW_IGNORED" ]] && git check-ignore -q "${PWD#"${GIT_REPO_INFO[0]}/"}"; then if [[ -n "$GIT_PROMPT_SHOW_IGNORED" ]] && git check-ignore "${PWD#"${GIT_REPO_INFO[0]}/"}" >/dev/null 2>&1 ; then
GIT_PROMPT+=" !" GIT_PROMPT+=" !"
elif [[ -n "$GIT_PROMPT_SHOW_UNSTAGED" ]] && git ls-files --modified --exclude-standard --directory --error-unmatch -- ':/*' >/dev/null 2>&1; then elif [[ -n "$GIT_PROMPT_SHOW_UNSTAGED" ]] && git ls-files --modified --exclude-standard --directory --error-unmatch -- ':/*' >/dev/null 2>&1; then
GIT_PROMPT+=" *" GIT_PROMPT+=" *"
@ -62,8 +73,15 @@ __prompt_git_status() {
GIT_PROMPT+=" $" GIT_PROMPT+=" $"
fi fi
# Get upstream status. # Add upstream status.
[[ -n "$GIT_PROMPT_SHOW_UPSTREAM" ]] || [[ -n "$GIT_PROMPT_SHOW_UPSTREAM_EXTENDED" ]] && { [[ -n "$GIT_PROMPT_SHOW_UPSTREAM" ]] || [[ -n "$GIT_PROMPT_SHOW_UPSTREAM_EXTENDED" ]] && {
# Whether to run prefetch tasks.
[[ -n "$GIT_PROMPT_AUTO_PREFETCH" ]] && {
# Only prefetch remotes if in the top-level working directory and if the repository is configured for maintenance work.
[[ "$PWD" == "${GIT_REPO_INFO[0]}" ]] && git config --global --get --fixed-value maintenance.repo "$PWD" >/dev/null 2>&1 && {
git maintenance run --task=prefetch 2>/dev/null || printf "\\033[1;31m%s\\033[39m\\n" "Git maintenance 'prefetch' task failed." >&2
}
}
COUNT="$(git rev-list --count --left-right "${GIT_REPO_INFO[6]:-@{upstream\}}...HEAD" 2>/dev/null | tr '[:blank:]' ' ')" COUNT="$(git rev-list --count --left-right "${GIT_REPO_INFO[6]:-@{upstream\}}...HEAD" 2>/dev/null | tr '[:blank:]' ' ')"
case "$COUNT" in case "$COUNT" in
"") "")