-
Notifications
You must be signed in to change notification settings - Fork 25.6k
/
git-prompt.sh
672 lines (627 loc) · 20.8 KB
/
git-prompt.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
# bash/zsh git prompt support
#
# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
# Distributed under the GNU General Public License, version 2.0.
#
# This script allows you to see repository status in your prompt.
#
# To enable:
#
# 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).
# 2) Add the following line to your .bashrc/.zshrc/.profile:
# . ~/.git-prompt.sh # dot path/to/this-file
# 3a) Change your PS1 to call __git_ps1 as
# command-substitution:
# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
# ZSH: setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
# the optional argument will be used as format string.
# 3b) Alternatively, for a slightly faster prompt, __git_ps1 can
# be used for PROMPT_COMMAND in Bash or for precmd() in Zsh
# with two parameters, <pre> and <post>, which are strings
# you would put in $PS1 before and after the status string
# generated by the git-prompt machinery. e.g.
# Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
# will show username, at-sign, host, colon, cwd, then
# various status string, followed by dollar and SP, as
# your prompt.
# ZSH: precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
# will show username, pipe, then various status string,
# followed by colon, cwd, dollar and SP, as your prompt.
# Optionally, you can supply a third argument with a printf
# format string to finetune the output of the branch status
#
# See notes below about compatibility with other shells.
#
# The repository status will be displayed only if you are currently in a
# git repository. The %s token is the placeholder for the shown status.
#
# The prompt status always includes the current branch name.
#
# In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty value,
# unstaged (*) and staged (+) changes will be shown next to the branch
# name. You can configure this per-repository with the
# bash.showDirtyState variable, which defaults to true once
# GIT_PS1_SHOWDIRTYSTATE is enabled.
#
# You can also see if currently something is stashed, by setting
# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
# then a '$' will be shown next to the branch name.
#
# If you would like to see if there're untracked files, then you can set
# GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're untracked
# files, then a '%' will be shown next to the branch name. You can
# configure this per-repository with the bash.showUntrackedFiles
# variable, which defaults to true once GIT_PS1_SHOWUNTRACKEDFILES is
# enabled.
#
# If you would like to see the difference between HEAD and its upstream,
# set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates you are behind, ">"
# indicates you are ahead, "<>" indicates you have diverged and "="
# indicates that there is no difference. You can further control
# behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated list
# of values:
#
# verbose show number of commits ahead/behind (+/-) upstream
# name if verbose, then also show the upstream abbrev name
# legacy don't use the '--count' option available in recent
# versions of git-rev-list
# git always compare HEAD to @{upstream}
# svn always compare HEAD to your SVN upstream
#
# By default, __git_ps1 will compare HEAD to your SVN upstream if it can
# find one, or @{upstream} otherwise. Once you have set
# GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by
# setting the bash.showUpstream config variable.
#
# You can change the separator between the branch name and the above
# state symbols by setting GIT_PS1_STATESEPARATOR. The default separator
# is SP.
#
# When there is an in-progress operation such as a merge, rebase,
# revert, cherry-pick, or bisect, the prompt will include information
# related to the operation, often in the form "|<OPERATION-NAME>".
#
# When the repository has a sparse-checkout, a notification of the form
# "|SPARSE" will be included in the prompt. This can be shortened to a
# single '?' character by setting GIT_PS1_COMPRESSSPARSESTATE, or omitted
# by setting GIT_PS1_OMITSPARSESTATE.
#
# If you would like to see a notification on the prompt when there are
# unresolved conflicts, set GIT_PS1_SHOWCONFLICTSTATE to "yes". The
# prompt will include "|CONFLICT".
#
# If you would like to see more information about the identity of
# commits checked out as a detached HEAD, set GIT_PS1_DESCRIBE_STYLE
# to one of these values:
#
# contains relative to newer annotated tag (v1.6.3.2~35)
# branch relative to newer tag or branch (master~4)
# describe relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
# tag relative to any older tag (v1.6.3.1-13-gdd42c2f)
# default exactly matching tag
#
# If you would like a colored hint about the current dirty state, set
# GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
# the colored output of "git status -sb".
#
# If you would like __git_ps1 to do nothing in the case when the current
# directory is set up to be ignored by git, then set
# GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the
# repository level by setting bash.hideIfPwdIgnored to "false".
#
# Compatibility with other shells (beyond bash/zsh):
#
# We require posix-ish shell plus "local" support, which is most
# shells (even pdksh), but excluding ksh93 (because no "local").
#
# Prompt integration might differ between shells, but the gist is
# to load it once on shell init with '. path/to/git-prompt.sh',
# set GIT_PS1* vars once as needed, and either place $(__git_ps1..)
# inside PS1 once (0/1 args), or, before each prompt is displayed,
# call __git_ps1 (2/3 args) which sets PS1 with the status embedded.
#
# Many shells support the 1st method of command substitution,
# though some might need to first enable cmd substitution in PS1.
#
# When using colors, each escape sequence is wrapped between byte
# values 1 and 2 (control chars SOH, STX, respectively), which are
# invisible at the output, but for bash/readline they mark 0-width
# strings (SGR color sequences) when calculating the on-screen
# prompt width, to maintain correct input editing at the prompt.
#
# To replace or disable the 0-width markers, set GIT_PS1_COLOR_PRE
# and GIT_PS1_COLOR_POST to other markers, or empty (nul) to not
# use markers. For instance, some shells support '\[' and '\]' as
# start/end markers in PS1 - when invoking __git_ps1 with 3/4 args,
# but it may or may not work in command substitution mode. YMMV.
#
# If the shell doesn't support 0-width markers and editing behaves
# incorrectly when using colors in __git_ps1, then, other than
# disabling color, it might be solved using multi-line prompt,
# where the git status is not at the last line, e.g.:
# PS1='\n\w \u@\h$(__git_ps1 " (%s)")\n\$ '
# check whether printf supports -v
__git_printf_supports_v=
printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1
# like __git_SOH=$'\001' etc but works also in shells without $'...'
eval "$(printf '
__git_SOH="\001" __git_STX="\002" __git_ESC="\033"
__git_LF="\n" __git_CRLF="\r\n"
')"
# stores the divergence from upstream in $p
# used by GIT_PS1_SHOWUPSTREAM
__git_ps1_show_upstream ()
{
local key value
local svn_remotes="" svn_url_pattern="" count n
local upstream_type=git legacy="" verbose="" name=""
local LF="$__git_LF"
# get some config options from git-config
local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
while read -r key value; do
case "$key" in
bash.showupstream)
GIT_PS1_SHOWUPSTREAM="$value"
if [ -z "${GIT_PS1_SHOWUPSTREAM}" ]; then
p=""
return
fi
;;
svn-remote.*.url)
svn_remotes=${svn_remotes}${value}${LF} # URI\nURI\n...
svn_url_pattern="$svn_url_pattern\\|$value"
upstream_type=svn+git # default upstream type is SVN if available, else git
;;
esac
done <<-OUTPUT
$output
OUTPUT
# parse configuration values
local option
for option in ${GIT_PS1_SHOWUPSTREAM-}; do
case "$option" in
git|svn) upstream_type="$option" ;;
verbose) verbose=1 ;;
legacy) legacy=1 ;;
name) name=1 ;;
esac
done
# Find our upstream type
case "$upstream_type" in
git) upstream_type="@{upstream}" ;;
svn*)
# successful svn-upstream resolution:
# - get the list of configured svn-remotes ($svn_remotes set above)
# - get the last commit which seems from one of our svn-remotes
# - confirm that it is from one of the svn-remotes
# - use $GIT_SVN_ID if set, else "git-svn"
# get upstream from "git-svn-id: UPSTRM@N HASH" in a commit message
# (git-svn uses essentially the same procedure internally)
local svn_upstream="$(
git log --first-parent -1 \
--grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null
)"
if [ -n "$svn_upstream" ]; then
# extract the URI, assuming --grep matched the last line
svn_upstream=${svn_upstream##*$LF} # last line
svn_upstream=${svn_upstream#*: } # UPSTRM@N HASH
svn_upstream=${svn_upstream%@*} # UPSTRM
case ${LF}${svn_remotes} in
*"${LF}${svn_upstream}${LF}"*)
# grep indeed matched the last line - it's our remote
# default branch name for checkouts with no layout:
upstream_type=${GIT_SVN_ID:-git-svn}
;;
*)
# the commit message includes one of our remotes, but
# it's not at the last line. is $svn_upstream junk?
upstream_type=${svn_upstream#/}
;;
esac
elif [ "svn+git" = "$upstream_type" ]; then
upstream_type="@{upstream}"
fi
;;
esac
# Find how many commits we are ahead/behind our upstream
if [ -z "$legacy" ]; then
count="$(git rev-list --count --left-right \
"$upstream_type"...HEAD 2>/dev/null)"
else
# produce equivalent output to --count for older versions of git
local commits
if commits="$(git rev-list --left-right "$upstream_type"...HEAD 2>/dev/null)"
then
local commit behind=0 ahead=0
for commit in $commits
do
case "$commit" in
"<"*) behind=$((behind+1)) ;;
*) ahead=$((ahead+1)) ;;
esac
done
count="$behind $ahead"
else
count=""
fi
fi
# calculate the result
if [ -z "$verbose" ]; then
case "$count" in
"") # no upstream
p="" ;;
"0 0") # equal to upstream
p="=" ;;
"0 "*) # ahead of upstream
p=">" ;;
*" 0") # behind upstream
p="<" ;;
*) # diverged from upstream
p="<>" ;;
esac
else # verbose, set upstream instead of p
case "$count" in
"") # no upstream
upstream="" ;;
"0 0") # equal to upstream
upstream="|u=" ;;
"0 "*) # ahead of upstream
upstream="|u+${count#0 }" ;;
*" 0") # behind upstream
upstream="|u-${count% 0}" ;;
*) # diverged from upstream
upstream="|u+${count#* }-${count% *}" ;;
esac
if [ -n "$count" ] && [ -n "$name" ]; then
__git_ps1_upstream_name=$(git rev-parse \
--abbrev-ref "$upstream_type" 2>/dev/null)
if [ "$pcmode" = yes ] && [ "$ps1_expanded" = yes ]; then
upstream="$upstream \${__git_ps1_upstream_name}"
else
upstream="$upstream ${__git_ps1_upstream_name}"
# not needed anymore; keep user's
# environment clean
unset __git_ps1_upstream_name
fi
fi
fi
}
# Helper function that is meant to be called from __git_ps1. It
# injects color codes into the appropriate gitstring variables used
# to build a gitstring. Colored variables are responsible for clearing
# their own color.
__git_ps1_colorize_gitstring ()
{
if [ -n "${ZSH_VERSION-}" ]; then
local c_red='%F{red}'
local c_green='%F{green}'
local c_lblue='%F{blue}'
local c_clear='%f'
else
# \001 (SOH) and \002 (STX) are 0-width substring markers
# which bash/readline identify while calculating the prompt
# on-screen width - to exclude 0-screen-width esc sequences.
local c_pre="${GIT_PS1_COLOR_PRE-$__git_SOH}${__git_ESC}["
local c_post="m${GIT_PS1_COLOR_POST-$__git_STX}"
local c_red="${c_pre}31${c_post}"
local c_green="${c_pre}32${c_post}"
local c_lblue="${c_pre}1;34${c_post}"
local c_clear="${c_pre}0${c_post}"
fi
local bad_color="$c_red"
local ok_color="$c_green"
local flags_color="$c_lblue"
local branch_color=""
if [ "$detached" = no ]; then
branch_color="$ok_color"
else
branch_color="$bad_color"
fi
if [ -n "$c" ]; then
c="$branch_color$c$c_clear"
fi
b="$branch_color$b$c_clear"
if [ -n "$w" ]; then
w="$bad_color$w$c_clear"
fi
if [ -n "$i" ]; then
i="$ok_color$i$c_clear"
fi
if [ -n "$s" ]; then
s="$flags_color$s$c_clear"
fi
if [ -n "$u" ]; then
u="$bad_color$u$c_clear"
fi
}
# Helper function to read the first line of a file into a variable.
# __git_eread requires 2 arguments, the file path and the name of the
# variable, in that order.
__git_eread ()
{
test -r "$1" && IFS=$__git_CRLF read -r "$2" <"$1"
}
# see if a cherry-pick or revert is in progress, if the user has committed a
# conflict resolution with 'git commit' in the middle of a sequence of picks or
# reverts then CHERRY_PICK_HEAD/REVERT_HEAD will not exist so we have to read
# the todo file.
__git_sequencer_status ()
{
local todo
if test -f "$g/CHERRY_PICK_HEAD"
then
r="|CHERRY-PICKING"
return 0;
elif test -f "$g/REVERT_HEAD"
then
r="|REVERTING"
return 0;
elif __git_eread "$g/sequencer/todo" todo
then
case "$todo" in
p[\ \ ]|pick[\ \ ]*)
r="|CHERRY-PICKING"
return 0
;;
revert[\ \ ]*)
r="|REVERTING"
return 0
;;
esac
fi
return 1
}
# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
# when called from PS1 using command substitution
# in this mode it prints text to add to bash PS1 prompt (includes branch name)
#
# __git_ps1 requires 2 or 3 arguments when called from PROMPT_COMMAND (pc)
# in that case it _sets_ PS1. The arguments are parts of a PS1 string.
# when two arguments are given, the first is prepended and the second appended
# to the state string when assigned to PS1.
# The optional third parameter will be used as printf format string to further
# customize the output of the git-status string.
# In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
__git_ps1 ()
{
# preserve exit status
local exit="$?"
local pcmode=no
local detached=no
local ps1pc_start='\u@\h:\w '
local ps1pc_end='\$ '
local printf_format=' (%s)'
case "$#" in
2|3) pcmode=yes
ps1pc_start="$1"
ps1pc_end="$2"
printf_format="${3:-$printf_format}"
# set PS1 to a plain prompt so that we can
# simply return early if the prompt should not
# be decorated
PS1="$ps1pc_start$ps1pc_end"
;;
0|1) printf_format="${1:-$printf_format}"
;;
*) return "$exit"
;;
esac
# ps1_expanded: This variable is set to 'yes' if the shell
# subjects the value of PS1 to parameter expansion:
#
# * bash does unless the promptvars option is disabled
# * zsh does not unless the PROMPT_SUBST option is set
# * POSIX shells always do
#
# If the shell would expand the contents of PS1 when drawing
# the prompt, a raw ref name must not be included in PS1.
# This protects the user from arbitrary code execution via
# specially crafted ref names. For example, a ref named
# 'refs/heads/$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' might cause the
# shell to execute 'sudo rm -rf /' when the prompt is drawn.
#
# Instead, the ref name should be placed in a separate global
# variable (in the __git_ps1_* namespace to avoid colliding
# with the user's environment) and that variable should be
# referenced from PS1. For example:
#
# __git_ps1_foo=$(do_something_to_get_ref_name)
# PS1="...stuff...\${__git_ps1_foo}...stuff..."
#
# If the shell does not expand the contents of PS1, the raw
# ref name must be included in PS1.
#
# The value of this variable is only relevant when in pcmode.
#
# Assume that the shell follows the POSIX specification and
# expands PS1 unless determined otherwise. (This is more
# likely to be correct if the user has a non-bash, non-zsh
# shell and safer than the alternative if the assumption is
# incorrect.)
#
local ps1_expanded=yes
[ -z "${ZSH_VERSION-}" ] || eval '[[ -o PROMPT_SUBST ]]' || ps1_expanded=no
[ -z "${BASH_VERSION-}" ] || shopt -q promptvars || ps1_expanded=no
local repo_info rev_parse_exit_code
repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
--is-bare-repository --is-inside-work-tree --show-ref-format \
--short HEAD 2>/dev/null)"
rev_parse_exit_code="$?"
if [ -z "$repo_info" ]; then
return "$exit"
fi
local LF="$__git_LF"
local short_sha=""
if [ "$rev_parse_exit_code" = "0" ]; then
short_sha="${repo_info##*$LF}"
repo_info="${repo_info%$LF*}"
fi
local ref_format="${repo_info##*$LF}"
repo_info="${repo_info%$LF*}"
local inside_worktree="${repo_info##*$LF}"
repo_info="${repo_info%$LF*}"
local bare_repo="${repo_info##*$LF}"
repo_info="${repo_info%$LF*}"
local inside_gitdir="${repo_info##*$LF}"
local g="${repo_info%$LF*}"
if [ "true" = "$inside_worktree" ] &&
[ -n "${GIT_PS1_HIDE_IF_PWD_IGNORED-}" ] &&
[ "$(git config --bool bash.hideIfPwdIgnored)" != "false" ] &&
git check-ignore -q .
then
return "$exit"
fi
local sparse=""
if [ -z "${GIT_PS1_COMPRESSSPARSESTATE-}" ] &&
[ -z "${GIT_PS1_OMITSPARSESTATE-}" ] &&
[ "$(git config --bool core.sparseCheckout)" = "true" ]; then
sparse="|SPARSE"
fi
local r=""
local b=""
local step=""
local total=""
if [ -d "$g/rebase-merge" ]; then
__git_eread "$g/rebase-merge/head-name" b
__git_eread "$g/rebase-merge/msgnum" step
__git_eread "$g/rebase-merge/end" total
r="|REBASE"
else
if [ -d "$g/rebase-apply" ]; then
__git_eread "$g/rebase-apply/next" step
__git_eread "$g/rebase-apply/last" total
if [ -f "$g/rebase-apply/rebasing" ]; then
__git_eread "$g/rebase-apply/head-name" b
r="|REBASE"
elif [ -f "$g/rebase-apply/applying" ]; then
r="|AM"
else
r="|AM/REBASE"
fi
elif [ -f "$g/MERGE_HEAD" ]; then
r="|MERGING"
elif __git_sequencer_status; then
:
elif [ -f "$g/BISECT_LOG" ]; then
r="|BISECTING"
fi
if [ -n "$b" ]; then
:
elif [ -h "$g/HEAD" ]; then
# symlink symbolic ref
b="$(git symbolic-ref HEAD 2>/dev/null)"
else
local head=""
case "$ref_format" in
files)
if ! __git_eread "$g/HEAD" head; then
return "$exit"
fi
case $head in
"ref: "*)
head="${head#ref: }"
;;
*)
head=""
esac
;;
*)
head="$(git symbolic-ref HEAD 2>/dev/null)"
;;
esac
if test -z "$head"; then
detached=yes
b="$(
case "${GIT_PS1_DESCRIBE_STYLE-}" in
(contains)
git describe --contains HEAD ;;
(branch)
git describe --contains --all HEAD ;;
(tag)
git describe --tags HEAD ;;
(describe)
git describe HEAD ;;
(* | default)
git describe --tags --exact-match HEAD ;;
esac 2>/dev/null)" ||
b="$short_sha..."
b="($b)"
else
b="$head"
fi
fi
fi
if [ -n "$step" ] && [ -n "$total" ]; then
r="$r $step/$total"
fi
local conflict="" # state indicator for unresolved conflicts
if [ "${GIT_PS1_SHOWCONFLICTSTATE-}" = "yes" ] &&
[ "$(git ls-files --unmerged 2>/dev/null)" ]; then
conflict="|CONFLICT"
fi
local w=""
local i=""
local s=""
local u=""
local h=""
local c=""
local p="" # short version of upstream state indicator
local upstream="" # verbose version of upstream state indicator
if [ "true" = "$inside_gitdir" ]; then
if [ "true" = "$bare_repo" ]; then
c="BARE:"
else
b="GIT_DIR!"
fi
elif [ "true" = "$inside_worktree" ]; then
if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
[ "$(git config --bool bash.showDirtyState)" != "false" ]
then
git diff --no-ext-diff --quiet || w="*"
git diff --no-ext-diff --cached --quiet || i="+"
if [ -z "$short_sha" ] && [ -z "$i" ]; then
i="#"
fi
fi
if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
git rev-parse --verify --quiet refs/stash >/dev/null
then
s="$"
fi
if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
[ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
git ls-files --others --exclude-standard --directory --no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null
then
u="%${ZSH_VERSION+%}"
fi
if [ -n "${GIT_PS1_COMPRESSSPARSESTATE-}" ] &&
[ "$(git config --bool core.sparseCheckout)" = "true" ]; then
h="?"
fi
if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
__git_ps1_show_upstream
fi
fi
local z="${GIT_PS1_STATESEPARATOR- }"
b=${b##refs/heads/}
if [ "$pcmode" = yes ] && [ "$ps1_expanded" = yes ]; then
__git_ps1_branch_name=$b
b="\${__git_ps1_branch_name}"
fi
if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
__git_ps1_colorize_gitstring
fi
local f="$h$w$i$s$u$p"
local gitstring="$c$b${f:+$z$f}${sparse}$r${upstream}${conflict}"
if [ "$pcmode" = yes ]; then
if [ "${__git_printf_supports_v-}" != yes ]; then
gitstring=$(printf -- "$printf_format" "$gitstring")
else
printf -v gitstring -- "$printf_format" "$gitstring"
fi
PS1="$ps1pc_start$gitstring$ps1pc_end"
else
printf -- "$printf_format" "$gitstring"
fi
return "$exit"
}