From 735e2d504e4c71e1d4f4538044c09e30d4d7ff47 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Sat, 7 Oct 2023 20:29:01 +0100 Subject: [PATCH] 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. --- .bashrc | 54 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/.bashrc b/.bashrc index 37e6551..529a631 100644 --- a/.bashrc +++ b/.bashrc @@ -3,28 +3,35 @@ __prompt_git_status() { # Generate a git branch/status prompt. # Based on git-prompt.sh by Shawn O. Pearce . + # Arguments: + # $1 The printf format string for the prompt. Must include %s. # Environment variables: - # 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_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_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_UPSTREAM=1 - Show status of this repository compaired to upstream: + # GIT_PROMPT_SHOW_TYPE=1 Show type of repository (Bare, Shallow). + # 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_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_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: # ?? - No upstream set. # == - Working tree is equal to upstream. # <> - Divergent from upstream. # >> or >x - Working tree is ahead of upstream (x = commits ahead when used with next option). # << or 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. (( $# != 1 )) && return "$RET" # Get some repository information. # 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) ) ERR="$?" @@ -33,11 +40,11 @@ __prompt_git_status() { # Generate the prompt. 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!" elif [[ "${GIT_REPO_INFO[5]}" == "true" ]]; then - # If in the working directory, generate the prompt. - # Add status markers. + # In the working directory, generate the prompt. + # Add type markers. [[ -n "$GIT_PROMPT_SHOW_TYPE" ]] && { if [[ "${GIT_REPO_INFO[2]}" == "true" ]]; then GIT_PROMPT+="B:" @@ -46,11 +53,15 @@ __prompt_git_status() { fi } - # Add the branch. - GIT_PROMPT+="$(git describe --contains --all HEAD)" + # 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)" + else + GIT_PROMPT+="!NO COMMITS!" + fi - # Add a marker if directory is ignored, there's untracked files or a stash. - if [[ -n "$GIT_PROMPT_SHOW_IGNORED" ]] && git check-ignore -q "${PWD#"${GIT_REPO_INFO[0]}/"}"; then + # 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 "${PWD#"${GIT_REPO_INFO[0]}/"}" >/dev/null 2>&1 ; then GIT_PROMPT+=" !" elif [[ -n "$GIT_PROMPT_SHOW_UNSTAGED" ]] && git ls-files --modified --exclude-standard --directory --error-unmatch -- ':/*' >/dev/null 2>&1; then GIT_PROMPT+=" *" @@ -62,8 +73,15 @@ __prompt_git_status() { GIT_PROMPT+=" $" fi - # Get upstream status. + # Add upstream status. [[ -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:]' ' ')" case "$COUNT" in "")