summaryrefslogtreecommitdiff
path: root/contrib/completion/git-completion.bash
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/completion/git-completion.bash')
-rwxr-xr-xcontrib/completion/git-completion.bash294
1 files changed, 217 insertions, 77 deletions
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 1a762e88e7..67569901e7 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,24 @@
# set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
# untracked files, then a '%' will be shown next to the branch name.
#
+# 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, and "<>"
+# indicates you have diverged. 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
+# 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.
+#
+#
# To submit patches:
#
# *) Read Documentation/SubmittingPatches
@@ -78,14 +96,133 @@ __gitdir ()
fi
}
+# stores the divergence from upstream in $p
+# used by GIT_PS1_SHOWUPSTREAM
+__git_ps1_show_upstream ()
+{
+ local key value
+ local svn_remote=() svn_url_pattern count n
+ local upstream=git legacy="" verbose=""
+
+ # get some config options from git-config
+ while read 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_remote[ $((${#svn_remote[@]} + 1)) ]="$value"
+ svn_url_pattern+="\\|$value"
+ upstream=svn+git # default upstream is SVN if available, else git
+ ;;
+ esac
+ done < <(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')
+
+ # parse configuration values
+ for option in ${GIT_PS1_SHOWUPSTREAM}; do
+ case "$option" in
+ git|svn) upstream="$option" ;;
+ verbose) verbose=1 ;;
+ legacy) legacy=1 ;;
+ esac
+ done
+
+ # Find our upstream
+ case "$upstream" in
+ git) upstream="@{upstream}" ;;
+ svn*)
+ # get the upstream from the "git-svn-id: ..." 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}\)" 2>/dev/null))
+ if [[ 0 -ne ${#svn_upstream[@]} ]]; then
+ svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
+ svn_upstream=${svn_upstream%@*}
+ for ((n=1; "$n" <= "${#svn_remote[@]}"; ++n)); do
+ svn_upstream=${svn_upstream#${svn_remote[$n]}}
+ done
+
+ if [[ -z "$svn_upstream" ]]; then
+ # default branch name for checkouts with no layout:
+ upstream=${GIT_SVN_ID:-git-svn}
+ else
+ upstream=${svn_upstream#/}
+ fi
+ elif [[ "svn+git" = "$upstream" ]]; then
+ upstream="@{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"...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"...HEAD 2>/dev/null)"
+ then
+ local commit behind=0 ahead=0
+ for commit in $commits
+ do
+ case "$commit" in
+ "<"*) let ++behind
+ ;;
+ *) let ++ahead
+ ;;
+ 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
+ case "$count" in
+ "") # no upstream
+ p="" ;;
+ "0 0") # equal to upstream
+ p=" u=" ;;
+ "0 "*) # ahead of upstream
+ p=" u+${count#0 }" ;;
+ *" 0") # behind upstream
+ p=" u-${count% 0}" ;;
+ *) # diverged from upstream
+ p=" u+${count#* }-${count% *}" ;;
+ esac
+ fi
+
+}
+
+
# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
# returns text to add to bash PS1 prompt (includes branch name)
__git_ps1 ()
{
local g="$(__gitdir)"
if [ -n "$g" ]; then
- local r
- local b
+ local r=""
+ local b=""
if [ -f "$g/rebase-merge/interactive" ]; then
r="|REBASE-i"
b="$(cat "$g/rebase-merge/head-name")"
@@ -127,11 +264,12 @@ __git_ps1 ()
}
fi
- local w
- local i
- local s
- local u
- local c
+ local w=""
+ local i=""
+ local s=""
+ local u=""
+ local c=""
+ local p=""
if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
@@ -159,13 +297,14 @@ __git_ps1 ()
u="%"
fi
fi
- fi
- if [ -n "${1-}" ]; then
- printf "$1" "$c${b##refs/heads/}$w$i$s$u$r"
- else
- printf " (%s)" "$c${b##refs/heads/}$w$i$s$u$r"
+ if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+ __git_ps1_show_upstream
+ fi
fi
+
+ local f="$w$i$s$u"
+ printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p"
fi
}
@@ -253,7 +392,9 @@ __git_refs ()
refs="${cur%/*}"
;;
*)
- if [ -e "$dir/HEAD" ]; then echo HEAD; fi
+ for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
+ if [ -e "$dir/$i" ]; then echo $i; fi
+ done
format="refname:short"
refs="refs/tags refs/heads refs/remotes"
;;
@@ -628,10 +769,19 @@ __git_aliased_command ()
local word cmdline=$(git --git-dir="$(__gitdir)" \
config --get "alias.$1")
for word in $cmdline; do
- if [ "${word##-*}" ]; then
- echo $word
+ case "$word" in
+ \!gitk|gitk)
+ echo "gitk"
return
- fi
+ ;;
+ \!*) : shell command alias ;;
+ -*) : option ;;
+ *=*) : setting env ;;
+ git) : git itself ;;
+ *)
+ echo "$word"
+ return
+ esac
done
}
@@ -670,7 +820,7 @@ _git_am ()
{
local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
if [ -d "$dir"/rebase-apply ]; then
- __gitcomp "--skip --resolved --abort"
+ __gitcomp "--skip --continue --resolved --abort"
return
fi
case "$cur" in
@@ -789,6 +939,7 @@ _git_branch ()
__gitcomp "
--color --no-color --verbose --abbrev= --no-abbrev
--track --no-track --contains --merged --no-merged
+ --set-upstream
"
;;
*)
@@ -833,7 +984,7 @@ _git_checkout ()
--*)
__gitcomp "
--quiet --ours --theirs --track --no-track --merge
- --conflict= --patch
+ --conflict= --orphan --patch
"
;;
*)
@@ -1043,7 +1194,7 @@ _git_format_patch ()
--numbered --start-number
--numbered-files
--keep-subject
- --signoff
+ --signoff --signature --no-signature
--in-reply-to= --cc=
--full-index --binary
--not --all
@@ -1085,6 +1236,11 @@ _git_gc ()
COMPREPLY=()
}
+_git_gitk ()
+{
+ _gitk
+}
+
_git_grep ()
{
__git_has_doubledash && return
@@ -1310,6 +1466,24 @@ _git_name_rev ()
__gitcomp "--tags --all --stdin"
}
+_git_notes ()
+{
+ local subcommands="edit show"
+ if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
+ __gitcomp "$subcommands"
+ return
+ fi
+
+ case "${COMP_WORDS[COMP_CWORD-1]}" in
+ -m|-F)
+ COMPREPLY=()
+ ;;
+ *)
+ __gitcomp "$(__git_refs)"
+ ;;
+ esac
+}
+
_git_pull ()
{
__git_complete_strategy && return
@@ -1371,6 +1545,7 @@ _git_rebase ()
--preserve-merges --stat --no-stat
--committer-date-is-author-date --ignore-date
--ignore-whitespace --whitespace=
+ --autosquash
"
return
@@ -1418,6 +1593,11 @@ _git_send_email ()
COMPREPLY=()
}
+_git_stage ()
+{
+ _git_add
+}
+
__git_config_get_set_variables ()
{
local prevword word config_file= c=$COMP_CWORD
@@ -1688,6 +1868,7 @@ _git_config ()
format.headers
format.numbered
format.pretty
+ format.signature
format.signoff
format.subjectprefix
format.suffix
@@ -2021,7 +2202,7 @@ _git_svn ()
init fetch clone rebase dcommit log find-rev
set-tree commit-diff info create-ignore propget
proplist show-ignore show-externals branch tag blame
- migrate
+ migrate mkdirs reset gc
"
local subcommand="$(__git_find_on_cmdline "$subcommands")"
if [ -z "$subcommand" ]; then
@@ -2068,7 +2249,7 @@ _git_svn ()
__gitcomp "--stdin $cmt_opts $fc_opts"
;;
create-ignore,--*|propget,--*|proplist,--*|show-ignore,--*|\
- show-externals,--*)
+ show-externals,--*|mkdirs,--*)
__gitcomp "--revision="
;;
log,--*)
@@ -2105,6 +2286,9 @@ _git_svn ()
--no-auth-cache --username=
"
;;
+ reset,--*)
+ __gitcomp "--revision= --parent"
+ ;;
*)
COMPREPLY=()
;;
@@ -2146,6 +2330,11 @@ _git_tag ()
esac
}
+_git_whatchanged ()
+{
+ _git_log
+}
+
_git ()
{
local i c=1 command __git_dir
@@ -2182,63 +2371,14 @@ _git ()
return
fi
+ local completion_func="_git_${command//-/_}"
+ declare -F $completion_func >/dev/null && $completion_func && return
+
local expansion=$(__git_aliased_command "$command")
- [ "$expansion" ] && command="$expansion"
-
- case "$command" in
- am) _git_am ;;
- add) _git_add ;;
- apply) _git_apply ;;
- archive) _git_archive ;;
- bisect) _git_bisect ;;
- bundle) _git_bundle ;;
- branch) _git_branch ;;
- checkout) _git_checkout ;;
- cherry) _git_cherry ;;
- cherry-pick) _git_cherry_pick ;;
- clean) _git_clean ;;
- clone) _git_clone ;;
- commit) _git_commit ;;
- config) _git_config ;;
- describe) _git_describe ;;
- diff) _git_diff ;;
- difftool) _git_difftool ;;
- fetch) _git_fetch ;;
- format-patch) _git_format_patch ;;
- fsck) _git_fsck ;;
- gc) _git_gc ;;
- grep) _git_grep ;;
- help) _git_help ;;
- init) _git_init ;;
- log) _git_log ;;
- ls-files) _git_ls_files ;;
- ls-remote) _git_ls_remote ;;
- ls-tree) _git_ls_tree ;;
- merge) _git_merge;;
- mergetool) _git_mergetool;;
- merge-base) _git_merge_base ;;
- mv) _git_mv ;;
- name-rev) _git_name_rev ;;
- pull) _git_pull ;;
- push) _git_push ;;
- rebase) _git_rebase ;;
- remote) _git_remote ;;
- replace) _git_replace ;;
- reset) _git_reset ;;
- revert) _git_revert ;;
- rm) _git_rm ;;
- send-email) _git_send_email ;;
- shortlog) _git_shortlog ;;
- show) _git_show ;;
- show-branch) _git_show_branch ;;
- stash) _git_stash ;;
- stage) _git_add ;;
- submodule) _git_submodule ;;
- svn) _git_svn ;;
- tag) _git_tag ;;
- whatchanged) _git_log ;;
- *) COMPREPLY=() ;;
- esac
+ if [ -n "$expansion" ]; then
+ completion_func="_git_${expansion//-/_}"
+ declare -F $completion_func >/dev/null && $completion_func
+ fi
}
_gitk ()