Skip to content

Commit 6935020

Browse files
committed
Merge branch 'sg/bash-prompt'
* sg/bash-prompt: bash prompt: mention that PROMPT_COMMAND mode is faster bash prompt: avoid command substitution when finalizing gitstring bash prompt: avoid command substitution when checking for untracked files bash prompt: use bash builtins to check stash state bash prompt: use bash builtins to check for unborn branch for dirty state bash prompt: combine 'git rev-parse' for detached head bash prompt: combine 'git rev-parse' executions in the main code path bash prompt: use bash builtins to find out current branch bash prompt: use bash builtins to find out rebase state bash prompt: run 'git rev-parse --git-dir' directly instead of __gitdir() bash prompt: return early from __git_ps1() when not in a git repository bash prompt: print unique detached HEAD abbreviated object name bash prompt: add a test for symbolic link symbolic refs completion, bash prompt: move __gitdir() tests to completion test suite bash prompt: use 'write_script' helper in interactive rebase test bash prompt: fix redirection coding style in tests
2 parents 0d07e98 + a694258 commit 6935020

File tree

4 files changed

+367
-333
lines changed

4 files changed

+367
-333
lines changed

contrib/completion/git-completion.bash

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ esac
3333
# returns location of .git repo
3434
__gitdir ()
3535
{
36-
# Note: this function is duplicated in git-prompt.sh
37-
# When updating it, make sure you update the other one to match.
3836
if [ -z "${1-}" ]; then
3937
if [ -n "${__git_dir-}" ]; then
4038
echo "$__git_dir"

contrib/completion/git-prompt.sh

Lines changed: 127 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
1616
# ZSH: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
1717
# the optional argument will be used as format string.
18-
# 3b) Alternatively, if you are using bash, __git_ps1 can be
19-
# used for PROMPT_COMMAND with two parameters, <pre> and
20-
# <post>, which are strings you would put in $PS1 before
21-
# and after the status string generated by the git-prompt
22-
# machinery. e.g.
18+
# 3b) Alternatively, for a slighly faster prompt, if you are
19+
# using bash, __git_ps1 can be used for PROMPT_COMMAND
20+
# with two parameters, <pre> and <post>, which are strings
21+
# you would put in $PS1 before and after the status string
22+
# generated by the git-prompt machinery. e.g.
2323
# Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
2424
# ZSH: precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
2525
# will show username, at-sign, host, colon, cwd, then
@@ -80,30 +80,6 @@
8080
# GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
8181
# the colored output of "git status -sb".
8282

83-
# __gitdir accepts 0 or 1 arguments (i.e., location)
84-
# returns location of .git repo
85-
__gitdir ()
86-
{
87-
# Note: this function is duplicated in git-completion.bash
88-
# When updating it, make sure you update the other one to match.
89-
if [ -z "${1-}" ]; then
90-
if [ -n "${__git_dir-}" ]; then
91-
echo "$__git_dir"
92-
elif [ -n "${GIT_DIR-}" ]; then
93-
test -d "${GIT_DIR-}" || return 1
94-
echo "$GIT_DIR"
95-
elif [ -d .git ]; then
96-
echo .git
97-
else
98-
git rev-parse --git-dir 2>/dev/null
99-
fi
100-
elif [ -d "$1/.git" ]; then
101-
echo "$1/.git"
102-
else
103-
echo "$1"
104-
fi
105-
}
106-
10783
# stores the divergence from upstream in $p
10884
# used by GIT_PS1_SHOWUPSTREAM
10985
__git_ps1_show_upstream ()
@@ -335,50 +311,83 @@ __git_ps1 ()
335311
;;
336312
esac
337313

338-
local g="$(__gitdir)"
339-
if [ -z "$g" ]; then
314+
local repo_info rev_parse_exit_code
315+
repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
316+
--is-bare-repository --is-inside-work-tree \
317+
--short HEAD 2>/dev/null)"
318+
rev_parse_exit_code="$?"
319+
320+
if [ -z "$repo_info" ]; then
340321
if [ $pcmode = yes ]; then
341322
#In PC mode PS1 always needs to be set
342323
PS1="$ps1pc_start$ps1pc_end"
343324
fi
325+
return
326+
fi
327+
328+
local short_sha
329+
if [ "$rev_parse_exit_code" = "0" ]; then
330+
short_sha="${repo_info##*$'\n'}"
331+
repo_info="${repo_info%$'\n'*}"
332+
fi
333+
local inside_worktree="${repo_info##*$'\n'}"
334+
repo_info="${repo_info%$'\n'*}"
335+
local bare_repo="${repo_info##*$'\n'}"
336+
repo_info="${repo_info%$'\n'*}"
337+
local inside_gitdir="${repo_info##*$'\n'}"
338+
local g="${repo_info%$'\n'*}"
339+
340+
local r=""
341+
local b=""
342+
local step=""
343+
local total=""
344+
if [ -d "$g/rebase-merge" ]; then
345+
read b 2>/dev/null <"$g/rebase-merge/head-name"
346+
read step 2>/dev/null <"$g/rebase-merge/msgnum"
347+
read total 2>/dev/null <"$g/rebase-merge/end"
348+
if [ -f "$g/rebase-merge/interactive" ]; then
349+
r="|REBASE-i"
350+
else
351+
r="|REBASE-m"
352+
fi
344353
else
345-
local r=""
346-
local b=""
347-
local step=""
348-
local total=""
349-
if [ -d "$g/rebase-merge" ]; then
350-
b="$(cat "$g/rebase-merge/head-name" 2>/dev/null)"
351-
step=$(cat "$g/rebase-merge/msgnum" 2>/dev/null)
352-
total=$(cat "$g/rebase-merge/end" 2>/dev/null)
353-
if [ -f "$g/rebase-merge/interactive" ]; then
354-
r="|REBASE-i"
354+
if [ -d "$g/rebase-apply" ]; then
355+
read step 2>/dev/null <"$g/rebase-apply/next"
356+
read total 2>/dev/null <"$g/rebase-apply/last"
357+
if [ -f "$g/rebase-apply/rebasing" ]; then
358+
read b 2>/dev/null <"$g/rebase-apply/head-name"
359+
r="|REBASE"
360+
elif [ -f "$g/rebase-apply/applying" ]; then
361+
r="|AM"
355362
else
356-
r="|REBASE-m"
363+
r="|AM/REBASE"
357364
fi
365+
elif [ -f "$g/MERGE_HEAD" ]; then
366+
r="|MERGING"
367+
elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
368+
r="|CHERRY-PICKING"
369+
elif [ -f "$g/REVERT_HEAD" ]; then
370+
r="|REVERTING"
371+
elif [ -f "$g/BISECT_LOG" ]; then
372+
r="|BISECTING"
373+
fi
374+
375+
if [ -n "$b" ]; then
376+
:
377+
elif [ -h "$g/HEAD" ]; then
378+
# symlink symbolic ref
379+
b="$(git symbolic-ref HEAD 2>/dev/null)"
358380
else
359-
if [ -d "$g/rebase-apply" ]; then
360-
step=$(cat "$g/rebase-apply/next" 2>/dev/null)
361-
total=$(cat "$g/rebase-apply/last" 2>/dev/null)
362-
if [ -f "$g/rebase-apply/rebasing" ]; then
363-
b="$(cat "$g/rebase-apply/head-name" 2>/dev/null)"
364-
r="|REBASE"
365-
elif [ -f "$g/rebase-apply/applying" ]; then
366-
r="|AM"
367-
else
368-
r="|AM/REBASE"
381+
local head=""
382+
if ! read head 2>/dev/null <"$g/HEAD"; then
383+
if [ $pcmode = yes ]; then
384+
PS1="$ps1pc_start$ps1pc_end"
369385
fi
370-
elif [ -f "$g/MERGE_HEAD" ]; then
371-
r="|MERGING"
372-
elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
373-
r="|CHERRY-PICKING"
374-
elif [ -f "$g/REVERT_HEAD" ]; then
375-
r="|REVERTING"
376-
elif [ -f "$g/BISECT_LOG" ]; then
377-
r="|BISECTING"
386+
return
378387
fi
379-
380-
test -n "$b" ||
381-
b="$(git symbolic-ref HEAD 2>/dev/null)" || {
388+
# is it a symbolic ref?
389+
b="${head#ref: }"
390+
if [ "$head" = "$b" ]; then
382391
detached=yes
383392
b="$(
384393
case "${GIT_PS1_DESCRIBE_STYLE-}" in
@@ -392,70 +401,74 @@ __git_ps1 ()
392401
git describe --tags --exact-match HEAD ;;
393402
esac 2>/dev/null)" ||
394403

395-
b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
396-
b="unknown"
404+
b="$short_sha..."
397405
b="($b)"
398-
}
406+
fi
399407
fi
408+
fi
400409

401-
if [ -n "$step" ] && [ -n "$total" ]; then
402-
r="$r $step/$total"
403-
fi
410+
if [ -n "$step" ] && [ -n "$total" ]; then
411+
r="$r $step/$total"
412+
fi
404413

405-
local w=""
406-
local i=""
407-
local s=""
408-
local u=""
409-
local c=""
410-
local p=""
414+
local w=""
415+
local i=""
416+
local s=""
417+
local u=""
418+
local c=""
419+
local p=""
411420

412-
if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
413-
if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
414-
c="BARE:"
421+
if [ "true" = "$inside_gitdir" ]; then
422+
if [ "true" = "$bare_repo" ]; then
423+
c="BARE:"
424+
else
425+
b="GIT_DIR!"
426+
fi
427+
elif [ "true" = "$inside_worktree" ]; then
428+
if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
429+
[ "$(git config --bool bash.showDirtyState)" != "false" ]
430+
then
431+
git diff --no-ext-diff --quiet --exit-code || w="*"
432+
if [ -n "$short_sha" ]; then
433+
git diff-index --cached --quiet HEAD -- || i="+"
415434
else
416-
b="GIT_DIR!"
417-
fi
418-
elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
419-
if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
420-
[ "$(git config --bool bash.showDirtyState)" != "false" ]
421-
then
422-
git diff --no-ext-diff --quiet --exit-code || w="*"
423-
if git rev-parse --quiet --verify HEAD >/dev/null; then
424-
git diff-index --cached --quiet HEAD -- || i="+"
425-
else
426-
i="#"
427-
fi
428-
fi
429-
if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
430-
git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
435+
i="#"
431436
fi
437+
fi
438+
if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
439+
[ -r "$g/refs/stash" ]; then
440+
s="$"
441+
fi
432442

433-
if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
434-
[ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
435-
[ -n "$(git ls-files --others --exclude-standard)" ]
436-
then
437-
u="%${ZSH_VERSION+%}"
438-
fi
443+
if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
444+
[ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
445+
git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null
446+
then
447+
u="%${ZSH_VERSION+%}"
448+
fi
439449

440-
if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
441-
__git_ps1_show_upstream
442-
fi
450+
if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
451+
__git_ps1_show_upstream
443452
fi
453+
fi
444454

445-
local z="${GIT_PS1_STATESEPARATOR-" "}"
446-
local f="$w$i$s$u"
447-
if [ $pcmode = yes ]; then
448-
local gitstring=
449-
if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
450-
__git_ps1_colorize_gitstring
451-
else
452-
gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
453-
fi
455+
local z="${GIT_PS1_STATESEPARATOR-" "}"
456+
local f="$w$i$s$u"
457+
if [ $pcmode = yes ]; then
458+
local gitstring=
459+
if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
460+
__git_ps1_colorize_gitstring
461+
else
462+
gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
463+
fi
464+
if [[ -n ${ZSH_VERSION-} ]]; then
454465
gitstring=$(printf -- "$printf_format" "$gitstring")
455-
PS1="$ps1pc_start$gitstring$ps1pc_end"
456466
else
457-
# NO color option unless in PROMPT_COMMAND mode
458-
printf -- "$printf_format" "$c${b##refs/heads/}${f:+$z$f}$r$p"
467+
printf -v gitstring -- "$printf_format" "$gitstring"
459468
fi
469+
PS1="$ps1pc_start$gitstring$ps1pc_end"
470+
else
471+
# NO color option unless in PROMPT_COMMAND mode
472+
printf -- "$printf_format" "$c${b##refs/heads/}${f:+$z$f}$r$p"
460473
fi
461474
}

0 commit comments

Comments
 (0)