1
0
Fork 0
mirror of https://github.com/ohmyzsh/ohmyzsh.git synced 2024-11-26 07:40:07 +00:00

gitfast: synchronize with upstream

Up to version 1.8.2.1.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
This commit is contained in:
Felipe Contreras 2013-04-21 01:34:44 -05:00
parent 85426a57a2
commit 72a8c08cc8
3 changed files with 503 additions and 102 deletions

View file

@ -60,6 +60,15 @@ __gitcomp_nl ()
compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0 compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
} }
__gitcomp_file ()
{
emulate -L zsh
local IFS=$'\n'
compset -P '*[=:]'
compadd -Q -p "${2-}" -f -- ${=1} && _ret=0
}
_git () _git ()
{ {
local _ret=1 local _ret=1

View file

@ -13,6 +13,7 @@
# *) .git/remotes file names # *) .git/remotes file names
# *) git 'subcommands' # *) git 'subcommands'
# *) tree paths within 'ref:path/to/file' expressions # *) tree paths within 'ref:path/to/file' expressions
# *) file paths within current working directory and index
# *) common --long-options # *) common --long-options
# #
# To use these routines: # To use these routines:
@ -23,10 +24,6 @@
# 3) Consider changing your PS1 to also show the current branch, # 3) Consider changing your PS1 to also show the current branch,
# see git-prompt.sh for details. # see git-prompt.sh for details.
if [[ -n ${ZSH_VERSION-} ]]; then
autoload -U +X bashcompinit && bashcompinit
fi
case "$COMP_WORDBREAKS" in case "$COMP_WORDBREAKS" in
*:*) : great ;; *:*) : great ;;
*) COMP_WORDBREAKS="$COMP_WORDBREAKS:" *) COMP_WORDBREAKS="$COMP_WORDBREAKS:"
@ -169,7 +166,6 @@ __git_reassemble_comp_words_by_ref()
} }
if ! type _get_comp_words_by_ref >/dev/null 2>&1; then if ! type _get_comp_words_by_ref >/dev/null 2>&1; then
if [[ -z ${ZSH_VERSION:+set} ]]; then
_get_comp_words_by_ref () _get_comp_words_by_ref ()
{ {
local exclude cur_ words_ cword_ local exclude cur_ words_ cword_
@ -197,32 +193,6 @@ _get_comp_words_by_ref ()
shift shift
done done
} }
else
_get_comp_words_by_ref ()
{
while [ $# -gt 0 ]; do
case "$1" in
cur)
cur=${COMP_WORDS[COMP_CWORD]}
;;
prev)
prev=${COMP_WORDS[COMP_CWORD-1]}
;;
words)
words=("${COMP_WORDS[@]}")
;;
cword)
cword=$COMP_CWORD
;;
-n)
# assume COMP_WORDBREAKS is already set sanely
shift
;;
esac
shift
done
}
fi
fi fi
# Generates completion reply with compgen, appending a space to possible # Generates completion reply with compgen, appending a space to possible
@ -264,6 +234,124 @@ __gitcomp_nl ()
COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- "${3-$cur}")) COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- "${3-$cur}"))
} }
# Generates completion reply with compgen from newline-separated possible
# completion filenames.
# It accepts 1 to 3 arguments:
# 1: List of possible completion filenames, separated by a single newline.
# 2: A directory prefix to be added to each possible completion filename
# (optional).
# 3: Generate possible completion matches for this word (optional).
__gitcomp_file ()
{
local IFS=$'\n'
# XXX does not work when the directory prefix contains a tilde,
# since tilde expansion is not applied.
# This means that COMPREPLY will be empty and Bash default
# completion will be used.
COMPREPLY=($(compgen -P "${2-}" -W "$1" -- "${3-$cur}"))
# Tell Bash that compspec generates filenames.
compopt -o filenames 2>/dev/null
}
__git_index_file_list_filter_compat ()
{
local path
while read -r path; do
case "$path" in
?*/*) echo "${path%%/*}/" ;;
*) echo "$path" ;;
esac
done
}
__git_index_file_list_filter_bash ()
{
local path
while read -r path; do
case "$path" in
?*/*)
# XXX if we append a slash to directory names when using
# `compopt -o filenames`, Bash will append another slash.
# This is pretty stupid, and this the reason why we have to
# define a compatible version for this function.
echo "${path%%/*}" ;;
*)
echo "$path" ;;
esac
done
}
# Process path list returned by "ls-files" and "diff-index --name-only"
# commands, in order to list only file names relative to a specified
# directory, and append a slash to directory names.
__git_index_file_list_filter ()
{
# Default to Bash >= 4.x
__git_index_file_list_filter_bash
}
# Execute git ls-files, returning paths relative to the directory
# specified in the first argument, and using the options specified in
# the second argument.
__git_ls_files_helper ()
{
(
test -n "${CDPATH+set}" && unset CDPATH
# NOTE: $2 is not quoted in order to support multiple options
cd "$1" && git ls-files --exclude-standard $2
) 2>/dev/null
}
# Execute git diff-index, returning paths relative to the directory
# specified in the first argument, and using the tree object id
# specified in the second argument.
__git_diff_index_helper ()
{
(
test -n "${CDPATH+set}" && unset CDPATH
cd "$1" && git diff-index --name-only --relative "$2"
) 2>/dev/null
}
# __git_index_files accepts 1 or 2 arguments:
# 1: Options to pass to ls-files (required).
# Supported options are --cached, --modified, --deleted, --others,
# and --directory.
# 2: A directory path (optional).
# If provided, only files within the specified directory are listed.
# Sub directories are never recursed. Path must have a trailing
# slash.
__git_index_files ()
{
local dir="$(__gitdir)" root="${2-.}"
if [ -d "$dir" ]; then
__git_ls_files_helper "$root" "$1" | __git_index_file_list_filter |
sort | uniq
fi
}
# __git_diff_index_files accepts 1 or 2 arguments:
# 1) The id of a tree object.
# 2) A directory path (optional).
# If provided, only files within the specified directory are listed.
# Sub directories are never recursed. Path must have a trailing
# slash.
__git_diff_index_files ()
{
local dir="$(__gitdir)" root="${2-.}"
if [ -d "$dir" ]; then
__git_diff_index_helper "$root" "$1" | __git_index_file_list_filter |
sort | uniq
fi
}
__git_heads () __git_heads ()
{ {
local dir="$(__gitdir)" local dir="$(__gitdir)"
@ -321,7 +409,7 @@ __git_refs ()
if [[ "$ref" == "$cur"* ]]; then if [[ "$ref" == "$cur"* ]]; then
echo "$ref" echo "$ref"
fi fi
done | uniq -u done | sort | uniq -u
fi fi
return return
fi fi
@ -428,7 +516,7 @@ __git_complete_revlist_file ()
*) pfx="$ref:$pfx" ;; *) pfx="$ref:$pfx" ;;
esac esac
__gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \ __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \
| sed '/^100... blob /{ | sed '/^100... blob /{
s,^.* ,, s,^.* ,,
s,$, , s,$, ,
@ -461,6 +549,46 @@ __git_complete_revlist_file ()
} }
# __git_complete_index_file requires 1 argument: the options to pass to
# ls-file
__git_complete_index_file ()
{
local pfx cur_="$cur"
case "$cur_" in
?*/*)
pfx="${cur_%/*}"
cur_="${cur_##*/}"
pfx="${pfx}/"
__gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_"
;;
*)
__gitcomp_file "$(__git_index_files "$1")" "" "$cur_"
;;
esac
}
# __git_complete_diff_index_file requires 1 argument: the id of a tree
# object
__git_complete_diff_index_file ()
{
local pfx cur_="$cur"
case "$cur_" in
?*/*)
pfx="${cur_%/*}"
cur_="${cur_##*/}"
pfx="${pfx}/"
__gitcomp_file "$(__git_diff_index_files "$1" "$pfx")" "$pfx" "$cur_"
;;
*)
__gitcomp_file "$(__git_diff_index_files "$1")" "" "$cur_"
;;
esac
}
__git_complete_file () __git_complete_file ()
{ {
__git_complete_revlist_file __git_complete_revlist_file
@ -562,10 +690,19 @@ __git_complete_strategy ()
return 1 return 1
} }
__git_commands () {
if test -n "${GIT_TESTING_COMMAND_COMPLETION:-}"
then
printf "%s" "${GIT_TESTING_COMMAND_COMPLETION}"
else
git help -a|egrep '^ [a-zA-Z0-9]'
fi
}
__git_list_all_commands () __git_list_all_commands ()
{ {
local i IFS=" "$'\n' local i IFS=" "$'\n'
for i in $(git help -a|egrep '^ [a-zA-Z0-9]') for i in $(__git_commands)
do do
case $i in case $i in
*--*) : helper pattern;; *--*) : helper pattern;;
@ -585,7 +722,7 @@ __git_list_porcelain_commands ()
{ {
local i IFS=" "$'\n' local i IFS=" "$'\n'
__git_compute_all_commands __git_compute_all_commands
for i in "help" $__git_all_commands for i in $__git_all_commands
do do
case $i in case $i in
*--*) : helper pattern;; *--*) : helper pattern;;
@ -594,6 +731,7 @@ __git_list_porcelain_commands ()
archimport) : import;; archimport) : import;;
cat-file) : plumbing;; cat-file) : plumbing;;
check-attr) : plumbing;; check-attr) : plumbing;;
check-ignore) : plumbing;;
check-ref-format) : plumbing;; check-ref-format) : plumbing;;
checkout-index) : plumbing;; checkout-index) : plumbing;;
commit-tree) : plumbing;; commit-tree) : plumbing;;
@ -753,6 +891,43 @@ __git_has_doubledash ()
return 1 return 1
} }
# Try to count non option arguments passed on the command line for the
# specified git command.
# When options are used, it is necessary to use the special -- option to
# tell the implementation were non option arguments begin.
# XXX this can not be improved, since options can appear everywhere, as
# an example:
# git mv x -n y
#
# __git_count_arguments requires 1 argument: the git command executed.
__git_count_arguments ()
{
local word i c=0
# Skip "git" (first argument)
for ((i=1; i < ${#words[@]}; i++)); do
word="${words[i]}"
case "$word" in
--)
# Good; we can assume that the following are only non
# option arguments.
((c = 0))
;;
"$1")
# Skip the specified git command and discard git
# main options
((c = 0))
;;
?*)
((c++))
;;
esac
done
printf "%d" $c
}
__git_whitespacelist="nowarn warn error error-all fix" __git_whitespacelist="nowarn warn error error-all fix"
_git_am () _git_am ()
@ -801,8 +976,6 @@ _git_apply ()
_git_add () _git_add ()
{ {
__git_has_doubledash && return
case "$cur" in case "$cur" in
--*) --*)
__gitcomp " __gitcomp "
@ -811,7 +984,9 @@ _git_add ()
" "
return return
esac esac
COMPREPLY=()
# XXX should we check for --update and --all options ?
__git_complete_index_file "--others --modified"
} }
_git_archive () _git_archive ()
@ -961,15 +1136,15 @@ _git_cherry_pick ()
_git_clean () _git_clean ()
{ {
__git_has_doubledash && return
case "$cur" in case "$cur" in
--*) --*)
__gitcomp "--dry-run --quiet" __gitcomp "--dry-run --quiet"
return return
;; ;;
esac esac
COMPREPLY=()
# XXX should we check for -x option ?
__git_complete_index_file "--others"
} }
_git_clone () _git_clone ()
@ -989,6 +1164,8 @@ _git_clone ()
--upload-pack --upload-pack
--template= --template=
--depth --depth
--single-branch
--branch
" "
return return
;; ;;
@ -998,7 +1175,19 @@ _git_clone ()
_git_commit () _git_commit ()
{ {
__git_has_doubledash && return case "$prev" in
-c|-C)
__gitcomp_nl "$(__git_refs)" "" "${cur}"
return
;;
esac
case "$prev" in
-c|-C)
__gitcomp_nl "$(__git_refs)" "" "${cur}"
return
;;
esac
case "$cur" in case "$cur" in
--cleanup=*) --cleanup=*)
@ -1027,7 +1216,13 @@ _git_commit ()
" "
return return
esac esac
COMPREPLY=()
if git rev-parse --verify --quiet HEAD >/dev/null; then
__git_complete_diff_index_file "HEAD"
else
# This is the first commit
__git_complete_index_file "--cached"
fi
} }
_git_describe () _git_describe ()
@ -1043,6 +1238,8 @@ _git_describe ()
__gitcomp_nl "$(__git_refs)" __gitcomp_nl "$(__git_refs)"
} }
__git_diff_algorithms="myers minimal patience histogram"
__git_diff_common_options="--stat --numstat --shortstat --summary __git_diff_common_options="--stat --numstat --shortstat --summary
--patch-with-stat --name-only --name-status --color --patch-with-stat --name-only --name-status --color
--no-color --color-words --no-renames --check --no-color --color-words --no-renames --check
@ -1053,10 +1250,11 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
--no-ext-diff --no-ext-diff
--no-prefix --src-prefix= --dst-prefix= --no-prefix --src-prefix= --dst-prefix=
--inter-hunk-context= --inter-hunk-context=
--patience --patience --histogram --minimal
--raw --raw
--dirstat --dirstat= --dirstat-by-file --dirstat --dirstat= --dirstat-by-file
--dirstat-by-file= --cumulative --dirstat-by-file= --cumulative
--diff-algorithm=
" "
_git_diff () _git_diff ()
@ -1064,6 +1262,10 @@ _git_diff ()
__git_has_doubledash && return __git_has_doubledash && return
case "$cur" in case "$cur" in
--diff-algorithm=*)
__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
return
;;
--*) --*)
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
--base --ours --theirs --no-index --base --ours --theirs --no-index
@ -1116,6 +1318,14 @@ _git_fetch ()
__git_complete_remote_or_refspec __git_complete_remote_or_refspec
} }
__git_format_patch_options="
--stdout --attach --no-attach --thread --thread= --output-directory
--numbered --start-number --numbered-files --keep-subject --signoff
--signature --no-signature --in-reply-to= --cc= --full-index --binary
--not --all --cover-letter --no-prefix --src-prefix= --dst-prefix=
--inline --suffix= --ignore-if-in-upstream --subject-prefix=
"
_git_format_patch () _git_format_patch ()
{ {
case "$cur" in case "$cur" in
@ -1126,21 +1336,7 @@ _git_format_patch ()
return return
;; ;;
--*) --*)
__gitcomp " __gitcomp "$__git_format_patch_options"
--stdout --attach --no-attach --thread --thread=
--output-directory
--numbered --start-number
--numbered-files
--keep-subject
--signoff --signature --no-signature
--in-reply-to= --cc=
--full-index --binary
--not --all
--cover-letter
--no-prefix --src-prefix= --dst-prefix=
--inline --suffix= --ignore-if-in-upstream
--subject-prefix=
"
return return
;; ;;
esac esac
@ -1251,8 +1447,6 @@ _git_init ()
_git_ls_files () _git_ls_files ()
{ {
__git_has_doubledash && return
case "$cur" in case "$cur" in
--*) --*)
__gitcomp "--cached --deleted --modified --others --ignored __gitcomp "--cached --deleted --modified --others --ignored
@ -1265,7 +1459,10 @@ _git_ls_files ()
return return
;; ;;
esac esac
COMPREPLY=()
# XXX ignore options like --modified and always suggest all cached
# files.
__git_complete_index_file "--cached"
} }
_git_ls_remote () _git_ls_remote ()
@ -1397,7 +1594,14 @@ _git_mv ()
return return
;; ;;
esac esac
COMPREPLY=()
if [ $(__git_count_arguments "mv") -gt 0 ]; then
# We need to show both cached and untracked files (including
# empty directories) since this may not be the last argument.
__git_complete_index_file "--cached --others --directory"
else
__git_complete_index_file "--cached"
fi
} }
_git_name_rev () _git_name_rev ()
@ -1554,6 +1758,12 @@ _git_send_email ()
__gitcomp "ssl tls" "" "${cur##--smtp-encryption=}" __gitcomp "ssl tls" "" "${cur##--smtp-encryption=}"
return return
;; ;;
--thread=*)
__gitcomp "
deep shallow
" "" "${cur##--thread=}"
return
;;
--*) --*)
__gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to __gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to
--compose --confirm= --dry-run --envelope-sender --compose --confirm= --dry-run --envelope-sender
@ -1563,11 +1773,12 @@ _git_send_email ()
--signed-off-by-cc --smtp-pass --smtp-server --signed-off-by-cc --smtp-pass --smtp-server
--smtp-server-port --smtp-encryption= --smtp-user --smtp-server-port --smtp-encryption= --smtp-user
--subject --suppress-cc= --suppress-from --thread --to --subject --suppress-cc= --suppress-from --thread --to
--validate --no-validate" --validate --no-validate
$__git_format_patch_options"
return return
;; ;;
esac esac
COMPREPLY=() __git_complete_revlist
} }
_git_stage () _git_stage ()
@ -1581,7 +1792,7 @@ __git_config_get_set_variables ()
while [ $c -gt 1 ]; do while [ $c -gt 1 ]; do
word="${words[c]}" word="${words[c]}"
case "$word" in case "$word" in
--global|--system|--file=*) --system|--global|--local|--file=*)
config_file="$word" config_file="$word"
break break
;; ;;
@ -1687,7 +1898,7 @@ _git_config ()
case "$cur" in case "$cur" in
--*) --*)
__gitcomp " __gitcomp "
--global --system --file= --system --global --local --file=
--list --replace-all --list --replace-all
--get --get-all --get-regexp --get --get-all --get-regexp
--add --unset --unset-all --add --unset --unset-all
@ -1860,6 +2071,7 @@ _git_config ()
diff.suppressBlankEmpty diff.suppressBlankEmpty
diff.tool diff.tool
diff.wordRegex diff.wordRegex
diff.algorithm
difftool. difftool.
difftool.prompt difftool.prompt
fetch.recurseSubmodules fetch.recurseSubmodules
@ -2096,15 +2308,14 @@ _git_revert ()
_git_rm () _git_rm ()
{ {
__git_has_doubledash && return
case "$cur" in case "$cur" in
--*) --*)
__gitcomp "--cached --dry-run --ignore-unmatch --quiet" __gitcomp "--cached --dry-run --ignore-unmatch --quiet"
return return
;; ;;
esac esac
COMPREPLY=()
__git_complete_index_file "--cached"
} }
_git_shortlog () _git_shortlog ()
@ -2134,6 +2345,10 @@ _git_show ()
" "" "${cur#*=}" " "" "${cur#*=}"
return return
;; ;;
--diff-algorithm=*)
__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
return
;;
--*) --*)
__gitcomp "--pretty= --format= --abbrev-commit --oneline __gitcomp "--pretty= --format= --abbrev-commit --oneline
$__git_diff_common_options $__git_diff_common_options
@ -2429,20 +2644,88 @@ __gitk_main ()
__git_complete_revlist __git_complete_revlist
} }
if [[ -n ${ZSH_VERSION-} ]]; then
echo "WARNING: this script is deprecated, please see git-completion.zsh" 1>&2
autoload -U +X compinit && compinit
__gitcomp ()
{
emulate -L zsh
local cur_="${3-$cur}"
case "$cur_" in
--*=)
;;
*)
local c IFS=$' \t\n'
local -a array
for c in ${=1}; do
c="$c${4-}"
case $c in
--*=*|*.) ;;
*) c="$c " ;;
esac
array[$#array+1]="$c"
done
compset -P '*[=:]'
compadd -Q -S '' -p "${2-}" -a -- array && _ret=0
;;
esac
}
__gitcomp_nl ()
{
emulate -L zsh
local IFS=$'\n'
compset -P '*[=:]'
compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
}
__gitcomp_file ()
{
emulate -L zsh
local IFS=$'\n'
compset -P '*[=:]'
compadd -Q -p "${2-}" -f -- ${=1} && _ret=0
}
__git_zsh_helper ()
{
emulate -L ksh
local cur cword prev
cur=${words[CURRENT-1]}
prev=${words[CURRENT-2]}
let cword=CURRENT-1
__${service}_main
}
_git ()
{
emulate -L zsh
local _ret=1
__git_zsh_helper
let _ret && _default -S '' && _ret=0
return _ret
}
compdef _git git gitk
return
elif [[ -n ${BASH_VERSION-} ]]; then
if ((${BASH_VERSINFO[0]} < 4)); then
# compopt is not supported
__git_index_file_list_filter ()
{
__git_index_file_list_filter_compat
}
fi
fi
__git_func_wrap () __git_func_wrap ()
{ {
if [[ -n ${ZSH_VERSION-} ]]; then
emulate -L bash
setopt KSH_TYPESET
# workaround zsh's bug that leaves 'words' as a special
# variable in versions < 4.3.12
typeset -h words
# workaround zsh's bug that quotes spaces in the COMPREPLY
# array if IFS doesn't contain spaces.
typeset -h IFS
fi
local cur words cword prev local cur words cword prev
_get_comp_words_by_ref -n =: cur words cword prev _get_comp_words_by_ref -n =: cur words cword prev
$1 $1

View file

@ -10,9 +10,22 @@
# 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh). # 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).
# 2) Add the following line to your .bashrc/.zshrc: # 2) Add the following line to your .bashrc/.zshrc:
# source ~/.git-prompt.sh # source ~/.git-prompt.sh
# 3) Change your PS1 to also show the current branch: # 3a) Change your PS1 to call __git_ps1 as
# command-substitution:
# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' # Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
# ZSH: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ ' # ZSH: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
# the optional argument will be used as format string.
# 3b) Alternatively, if you are using bash, __git_ps1 can be
# used for PROMPT_COMMAND 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.
# 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.
# Optionally, you can supply a third argument with a printf
# format string to finetune the output of the branch status
# #
# The argument to __git_ps1 will be displayed only if you are currently # The argument to __git_ps1 will be displayed only if you are currently
# in a git repository. The %s token will be the name of the current # in a git repository. The %s token will be the name of the current
@ -30,7 +43,10 @@
# #
# If you would like to see if there're untracked files, then you can set # 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 # GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're untracked
# files, then a '%' will be shown next to the branch name. # 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, # If you would like to see the difference between HEAD and its upstream,
# set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates you are behind, ">" # set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates you are behind, ">"
@ -49,6 +65,19 @@
# find one, or @{upstream} otherwise. Once you have set # find one, or @{upstream} otherwise. Once you have set
# GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by # GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by
# setting the bash.showUpstream config variable. # setting the bash.showUpstream config variable.
#
# 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)
# 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".
# __gitdir accepts 0 or 1 arguments (i.e., location) # __gitdir accepts 0 or 1 arguments (i.e., location)
# returns location of .git repo # returns location of .git repo
@ -195,11 +224,43 @@ __git_ps1_show_upstream ()
# __git_ps1 accepts 0 or 1 arguments (i.e., format string) # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
# returns text to add to bash PS1 prompt (includes branch name) # 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 () __git_ps1 ()
{ {
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}"
;;
0|1) printf_format="${1:-$printf_format}"
;;
*) return
;;
esac
local g="$(__gitdir)" local g="$(__gitdir)"
if [ -n "$g" ]; then if [ -z "$g" ]; then
if [ $pcmode = yes ]; then
#In PC mode PS1 always needs to be set
PS1="$ps1pc_start$ps1pc_end"
fi
else
local r="" local r=""
local b="" local b=""
if [ -f "$g/rebase-merge/interactive" ]; then if [ -f "$g/rebase-merge/interactive" ]; then
@ -226,7 +287,7 @@ __git_ps1 ()
fi fi
b="$(git symbolic-ref HEAD 2>/dev/null)" || { b="$(git symbolic-ref HEAD 2>/dev/null)" || {
detached=yes
b="$( b="$(
case "${GIT_PS1_DESCRIBE_STYLE-}" in case "${GIT_PS1_DESCRIBE_STYLE-}" in
(contains) (contains)
@ -259,8 +320,9 @@ __git_ps1 ()
b="GIT_DIR!" b="GIT_DIR!"
fi fi
elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then [ "$(git config --bool bash.showDirtyState)" != "false" ]
then
git diff --no-ext-diff --quiet --exit-code || w="*" git diff --no-ext-diff --quiet --exit-code || w="*"
if git rev-parse --quiet --verify HEAD >/dev/null; then if git rev-parse --quiet --verify HEAD >/dev/null; then
git diff-index --cached --quiet HEAD -- || i="+" git diff-index --cached --quiet HEAD -- || i="+"
@ -268,16 +330,16 @@ __git_ps1 ()
i="#" i="#"
fi fi
fi fi
fi
if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$" git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
fi fi
if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
if [ -n "$(git ls-files --others --exclude-standard)" ]; then [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
[ -n "$(git ls-files --others --exclude-standard)" ]
then
u="%%" u="%%"
fi fi
fi
if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
__git_ps1_show_upstream __git_ps1_show_upstream
@ -285,6 +347,53 @@ __git_ps1 ()
fi fi
local f="$w$i$s$u" local f="$w$i$s$u"
printf -- "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p" if [ $pcmode = yes ]; then
local gitstring=
if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
local c_red='\e[31m'
local c_green='\e[32m'
local c_lblue='\e[1;34m'
local c_clear='\e[0m'
local bad_color=$c_red
local ok_color=$c_green
local branch_color="$c_clear"
local flags_color="$c_lblue"
local branchstring="$c${b##refs/heads/}"
if [ $detached = no ]; then
branch_color="$ok_color"
else
branch_color="$bad_color"
fi
# Setting gitstring directly with \[ and \] around colors
# is necessary to prevent wrapping issues!
gitstring="\[$branch_color\]$branchstring\[$c_clear\]"
if [ -n "$w$i$s$u$r$p" ]; then
gitstring="$gitstring "
fi
if [ "$w" = "*" ]; then
gitstring="$gitstring\[$bad_color\]$w"
fi
if [ -n "$i" ]; then
gitstring="$gitstring\[$ok_color\]$i"
fi
if [ -n "$s" ]; then
gitstring="$gitstring\[$flags_color\]$s"
fi
if [ -n "$u" ]; then
gitstring="$gitstring\[$bad_color\]$u"
fi
gitstring="$gitstring\[$c_clear\]$r$p"
else
gitstring="$c${b##refs/heads/}${f:+ $f}$r$p"
fi
gitstring=$(printf -- "$printf_format" "$gitstring")
PS1="$ps1pc_start$gitstring$ps1pc_end"
else
# NO color option unless in PROMPT_COMMAND mode
printf -- "$printf_format" "$c${b##refs/heads/}${f:+ $f}$r$p"
fi
fi fi
} }