Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added git completion

  • Loading branch information...
commit 5d1dc8bed3526ddf95cbb6b46803915512791897 1 parent 1632bb1
samyzee authored samyzee committed

Showing 2 changed files with 2,742 additions and 1 deletion. Show diff stats Hide diff stats

  1. +4 1 .bash_profile
  2. +2,738 0 .git-completion.sh
5 .bash_profile
@@ -6,4 +6,7 @@ for file in bash_prompt exports aliases functions extra; do
6 6 done
7 7
8 8 # Case-insensitive globbing (used in pathname expansion)
9   -shopt -s nocaseglob
  9 +shopt -s nocaseglob
  10 +
  11 +# Load the git completion script
  12 +source ~/.git-completion.sh
2,738 .git-completion.sh
... ... @@ -0,0 +1,2738 @@
  1 +#!bash
  2 +#
  3 +# bash/zsh completion support for core Git.
  4 +#
  5 +# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
  6 +# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
  7 +# Distributed under the GNU General Public License, version 2.0.
  8 +#
  9 +# The contained completion routines provide support for completing:
  10 +#
  11 +# *) local and remote branch names
  12 +# *) local and remote tag names
  13 +# *) .git/remotes file names
  14 +# *) git 'subcommands'
  15 +# *) tree paths within 'ref:path/to/file' expressions
  16 +# *) common --long-options
  17 +#
  18 +# To use these routines:
  19 +#
  20 +# 1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
  21 +# 2) Add the following line to your .bashrc/.zshrc:
  22 +# source ~/.git-completion.sh
  23 +#
  24 +# 3) Consider changing your PS1 to also show the current branch:
  25 +# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
  26 +# ZSH: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
  27 +#
  28 +# The argument to __git_ps1 will be displayed only if you
  29 +# are currently in a git repository. The %s token will be
  30 +# the name of the current branch.
  31 +#
  32 +# In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty
  33 +# value, unstaged (*) and staged (+) changes will be shown next
  34 +# to the branch name. You can configure this per-repository
  35 +# with the bash.showDirtyState variable, which defaults to true
  36 +# once GIT_PS1_SHOWDIRTYSTATE is enabled.
  37 +#
  38 +# You can also see if currently something is stashed, by setting
  39 +# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
  40 +# then a '$' will be shown next to the branch name.
  41 +#
  42 +# If you would like to see if there're untracked files, then you can
  43 +# set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
  44 +# untracked files, then a '%' will be shown next to the branch name.
  45 +#
  46 +# If you would like to see the difference between HEAD and its
  47 +# upstream, set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates
  48 +# you are behind, ">" indicates you are ahead, and "<>"
  49 +# indicates you have diverged. You can further control
  50 +# behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated
  51 +# list of values:
  52 +# verbose show number of commits ahead/behind (+/-) upstream
  53 +# legacy don't use the '--count' option available in recent
  54 +# versions of git-rev-list
  55 +# git always compare HEAD to @{upstream}
  56 +# svn always compare HEAD to your SVN upstream
  57 +# By default, __git_ps1 will compare HEAD to your SVN upstream
  58 +# if it can find one, or @{upstream} otherwise. Once you have
  59 +# set GIT_PS1_SHOWUPSTREAM, you can override it on a
  60 +# per-repository basis by setting the bash.showUpstream config
  61 +# variable.
  62 +#
  63 +#
  64 +# To submit patches:
  65 +#
  66 +# *) Read Documentation/SubmittingPatches
  67 +# *) Send all patches to the current maintainer:
  68 +#
  69 +# "Shawn O. Pearce" <spearce@spearce.org>
  70 +#
  71 +# *) Always CC the Git mailing list:
  72 +#
  73 +# git@vger.kernel.org
  74 +#
  75 +
  76 +if [[ -n ${ZSH_VERSION-} ]]; then
  77 + autoload -U +X bashcompinit && bashcompinit
  78 +fi
  79 +
  80 +case "$COMP_WORDBREAKS" in
  81 +*:*) : great ;;
  82 +*) COMP_WORDBREAKS="$COMP_WORDBREAKS:"
  83 +esac
  84 +
  85 +# __gitdir accepts 0 or 1 arguments (i.e., location)
  86 +# returns location of .git repo
  87 +__gitdir ()
  88 +{
  89 + if [ -z "${1-}" ]; then
  90 + if [ -n "${__git_dir-}" ]; then
  91 + echo "$__git_dir"
  92 + elif [ -d .git ]; then
  93 + echo .git
  94 + else
  95 + git rev-parse --git-dir 2>/dev/null
  96 + fi
  97 + elif [ -d "$1/.git" ]; then
  98 + echo "$1/.git"
  99 + else
  100 + echo "$1"
  101 + fi
  102 +}
  103 +
  104 +# stores the divergence from upstream in $p
  105 +# used by GIT_PS1_SHOWUPSTREAM
  106 +__git_ps1_show_upstream ()
  107 +{
  108 + local key value
  109 + local svn_remote=() svn_url_pattern count n
  110 + local upstream=git legacy="" verbose=""
  111 +
  112 + # get some config options from git-config
  113 + while read key value; do
  114 + case "$key" in
  115 + bash.showupstream)
  116 + GIT_PS1_SHOWUPSTREAM="$value"
  117 + if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
  118 + p=""
  119 + return
  120 + fi
  121 + ;;
  122 + svn-remote.*.url)
  123 + svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value"
  124 + svn_url_pattern+="\\|$value"
  125 + upstream=svn+git # default upstream is SVN if available, else git
  126 + ;;
  127 + esac
  128 + done < <(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')
  129 +
  130 + # parse configuration values
  131 + for option in ${GIT_PS1_SHOWUPSTREAM}; do
  132 + case "$option" in
  133 + git|svn) upstream="$option" ;;
  134 + verbose) verbose=1 ;;
  135 + legacy) legacy=1 ;;
  136 + esac
  137 + done
  138 +
  139 + # Find our upstream
  140 + case "$upstream" in
  141 + git) upstream="@{upstream}" ;;
  142 + svn*)
  143 + # get the upstream from the "git-svn-id: ..." in a commit message
  144 + # (git-svn uses essentially the same procedure internally)
  145 + local svn_upstream=($(git log --first-parent -1 \
  146 + --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
  147 + if [[ 0 -ne ${#svn_upstream[@]} ]]; then
  148 + svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
  149 + svn_upstream=${svn_upstream%@*}
  150 + local n_stop="${#svn_remote[@]}"
  151 + for ((n=1; n <= n_stop; ++n)); do
  152 + svn_upstream=${svn_upstream#${svn_remote[$n]}}
  153 + done
  154 +
  155 + if [[ -z "$svn_upstream" ]]; then
  156 + # default branch name for checkouts with no layout:
  157 + upstream=${GIT_SVN_ID:-git-svn}
  158 + else
  159 + upstream=${svn_upstream#/}
  160 + fi
  161 + elif [[ "svn+git" = "$upstream" ]]; then
  162 + upstream="@{upstream}"
  163 + fi
  164 + ;;
  165 + esac
  166 +
  167 + # Find how many commits we are ahead/behind our upstream
  168 + if [[ -z "$legacy" ]]; then
  169 + count="$(git rev-list --count --left-right \
  170 + "$upstream"...HEAD 2>/dev/null)"
  171 + else
  172 + # produce equivalent output to --count for older versions of git
  173 + local commits
  174 + if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
  175 + then
  176 + local commit behind=0 ahead=0
  177 + for commit in $commits
  178 + do
  179 + case "$commit" in
  180 + "<"*) let ++behind
  181 + ;;
  182 + *) let ++ahead
  183 + ;;
  184 + esac
  185 + done
  186 + count="$behind $ahead"
  187 + else
  188 + count=""
  189 + fi
  190 + fi
  191 +
  192 + # calculate the result
  193 + if [[ -z "$verbose" ]]; then
  194 + case "$count" in
  195 + "") # no upstream
  196 + p="" ;;
  197 + "0 0") # equal to upstream
  198 + p="=" ;;
  199 + "0 "*) # ahead of upstream
  200 + p=">" ;;
  201 + *" 0") # behind upstream
  202 + p="<" ;;
  203 + *) # diverged from upstream
  204 + p="<>" ;;
  205 + esac
  206 + else
  207 + case "$count" in
  208 + "") # no upstream
  209 + p="" ;;
  210 + "0 0") # equal to upstream
  211 + p=" u=" ;;
  212 + "0 "*) # ahead of upstream
  213 + p=" u+${count#0 }" ;;
  214 + *" 0") # behind upstream
  215 + p=" u-${count% 0}" ;;
  216 + *) # diverged from upstream
  217 + p=" u+${count#* }-${count% *}" ;;
  218 + esac
  219 + fi
  220 +
  221 +}
  222 +
  223 +
  224 +# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
  225 +# returns text to add to bash PS1 prompt (includes branch name)
  226 +__git_ps1 ()
  227 +{
  228 + local g="$(__gitdir)"
  229 + if [ -n "$g" ]; then
  230 + local r=""
  231 + local b=""
  232 + if [ -f "$g/rebase-merge/interactive" ]; then
  233 + r="|REBASE-i"
  234 + b="$(cat "$g/rebase-merge/head-name")"
  235 + elif [ -d "$g/rebase-merge" ]; then
  236 + r="|REBASE-m"
  237 + b="$(cat "$g/rebase-merge/head-name")"
  238 + else
  239 + if [ -d "$g/rebase-apply" ]; then
  240 + if [ -f "$g/rebase-apply/rebasing" ]; then
  241 + r="|REBASE"
  242 + elif [ -f "$g/rebase-apply/applying" ]; then
  243 + r="|AM"
  244 + else
  245 + r="|AM/REBASE"
  246 + fi
  247 + elif [ -f "$g/MERGE_HEAD" ]; then
  248 + r="|MERGING"
  249 + elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
  250 + r="|CHERRY-PICKING"
  251 + elif [ -f "$g/BISECT_LOG" ]; then
  252 + r="|BISECTING"
  253 + fi
  254 +
  255 + b="$(git symbolic-ref HEAD 2>/dev/null)" || {
  256 +
  257 + b="$(
  258 + case "${GIT_PS1_DESCRIBE_STYLE-}" in
  259 + (contains)
  260 + git describe --contains HEAD ;;
  261 + (branch)
  262 + git describe --contains --all HEAD ;;
  263 + (describe)
  264 + git describe HEAD ;;
  265 + (* | default)
  266 + git describe --tags --exact-match HEAD ;;
  267 + esac 2>/dev/null)" ||
  268 +
  269 + b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
  270 + b="unknown"
  271 + b="($b)"
  272 + }
  273 + fi
  274 +
  275 + local w=""
  276 + local i=""
  277 + local s=""
  278 + local u=""
  279 + local c=""
  280 + local p=""
  281 +
  282 + if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
  283 + if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
  284 + c="BARE:"
  285 + else
  286 + b="GIT_DIR!"
  287 + fi
  288 + elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
  289 + if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then
  290 + if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then
  291 + git diff --no-ext-diff --quiet --exit-code || w="*"
  292 + if git rev-parse --quiet --verify HEAD >/dev/null; then
  293 + git diff-index --cached --quiet HEAD -- || i="+"
  294 + else
  295 + i="#"
  296 + fi
  297 + fi
  298 + fi
  299 + if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
  300 + git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
  301 + fi
  302 +
  303 + if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then
  304 + if [ -n "$(git ls-files --others --exclude-standard)" ]; then
  305 + u="%"
  306 + fi
  307 + fi
  308 +
  309 + if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
  310 + __git_ps1_show_upstream
  311 + fi
  312 + fi
  313 +
  314 + local f="$w$i$s$u"
  315 + printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p"
  316 + fi
  317 +}
  318 +
  319 +# __gitcomp_1 requires 2 arguments
  320 +__gitcomp_1 ()
  321 +{
  322 + local c IFS=' '$'\t'$'\n'
  323 + for c in $1; do
  324 + case "$c$2" in
  325 + --*=*) printf %s$'\n' "$c$2" ;;
  326 + *.) printf %s$'\n' "$c$2" ;;
  327 + *) printf %s$'\n' "$c$2 " ;;
  328 + esac
  329 + done
  330 +}
  331 +
  332 +# The following function is based on code from:
  333 +#
  334 +# bash_completion - programmable completion functions for bash 3.2+
  335 +#
  336 +# Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
  337 +# © 2009-2010, Bash Completion Maintainers
  338 +# <bash-completion-devel@lists.alioth.debian.org>
  339 +#
  340 +# This program is free software; you can redistribute it and/or modify
  341 +# it under the terms of the GNU General Public License as published by
  342 +# the Free Software Foundation; either version 2, or (at your option)
  343 +# any later version.
  344 +#
  345 +# This program is distributed in the hope that it will be useful,
  346 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  347 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  348 +# GNU General Public License for more details.
  349 +#
  350 +# You should have received a copy of the GNU General Public License
  351 +# along with this program; if not, write to the Free Software Foundation,
  352 +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  353 +#
  354 +# The latest version of this software can be obtained here:
  355 +#
  356 +# http://bash-completion.alioth.debian.org/
  357 +#
  358 +# RELEASE: 2.x
  359 +
  360 +# This function can be used to access a tokenized list of words
  361 +# on the command line:
  362 +#
  363 +# __git_reassemble_comp_words_by_ref '=:'
  364 +# if test "${words_[cword_-1]}" = -w
  365 +# then
  366 +# ...
  367 +# fi
  368 +#
  369 +# The argument should be a collection of characters from the list of
  370 +# word completion separators (COMP_WORDBREAKS) to treat as ordinary
  371 +# characters.
  372 +#
  373 +# This is roughly equivalent to going back in time and setting
  374 +# COMP_WORDBREAKS to exclude those characters. The intent is to
  375 +# make option types like --date=<type> and <rev>:<path> easy to
  376 +# recognize by treating each shell word as a single token.
  377 +#
  378 +# It is best not to set COMP_WORDBREAKS directly because the value is
  379 +# shared with other completion scripts. By the time the completion
  380 +# function gets called, COMP_WORDS has already been populated so local
  381 +# changes to COMP_WORDBREAKS have no effect.
  382 +#
  383 +# Output: words_, cword_, cur_.
  384 +
  385 +__git_reassemble_comp_words_by_ref()
  386 +{
  387 + local exclude i j first
  388 + # Which word separators to exclude?
  389 + exclude="${1//[^$COMP_WORDBREAKS]}"
  390 + cword_=$COMP_CWORD
  391 + if [ -z "$exclude" ]; then
  392 + words_=("${COMP_WORDS[@]}")
  393 + return
  394 + fi
  395 + # List of word completion separators has shrunk;
  396 + # re-assemble words to complete.
  397 + for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
  398 + # Append each nonempty word consisting of just
  399 + # word separator characters to the current word.
  400 + first=t
  401 + while
  402 + [ $i -gt 0 ] &&
  403 + [ -n "${COMP_WORDS[$i]}" ] &&
  404 + # word consists of excluded word separators
  405 + [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
  406 + do
  407 + # Attach to the previous token,
  408 + # unless the previous token is the command name.
  409 + if [ $j -ge 2 ] && [ -n "$first" ]; then
  410 + ((j--))
  411 + fi
  412 + first=
  413 + words_[$j]=${words_[j]}${COMP_WORDS[i]}
  414 + if [ $i = $COMP_CWORD ]; then
  415 + cword_=$j
  416 + fi
  417 + if (($i < ${#COMP_WORDS[@]} - 1)); then
  418 + ((i++))
  419 + else
  420 + # Done.
  421 + return
  422 + fi
  423 + done
  424 + words_[$j]=${words_[j]}${COMP_WORDS[i]}
  425 + if [ $i = $COMP_CWORD ]; then
  426 + cword_=$j
  427 + fi
  428 + done
  429 +}
  430 +
  431 +if ! type _get_comp_words_by_ref >/dev/null 2>&1; then
  432 +if [[ -z ${ZSH_VERSION:+set} ]]; then
  433 +_get_comp_words_by_ref ()
  434 +{
  435 + local exclude cur_ words_ cword_
  436 + if [ "$1" = "-n" ]; then
  437 + exclude=$2
  438 + shift 2
  439 + fi
  440 + __git_reassemble_comp_words_by_ref "$exclude"
  441 + cur_=${words_[cword_]}
  442 + while [ $# -gt 0 ]; do
  443 + case "$1" in
  444 + cur)
  445 + cur=$cur_
  446 + ;;
  447 + prev)
  448 + prev=${words_[$cword_-1]}
  449 + ;;
  450 + words)
  451 + words=("${words_[@]}")
  452 + ;;
  453 + cword)
  454 + cword=$cword_
  455 + ;;
  456 + esac
  457 + shift
  458 + done
  459 +}
  460 +else
  461 +_get_comp_words_by_ref ()
  462 +{
  463 + while [ $# -gt 0 ]; do
  464 + case "$1" in
  465 + cur)
  466 + cur=${COMP_WORDS[COMP_CWORD]}
  467 + ;;
  468 + prev)
  469 + prev=${COMP_WORDS[COMP_CWORD-1]}
  470 + ;;
  471 + words)
  472 + words=("${COMP_WORDS[@]}")
  473 + ;;
  474 + cword)
  475 + cword=$COMP_CWORD
  476 + ;;
  477 + -n)
  478 + # assume COMP_WORDBREAKS is already set sanely
  479 + shift
  480 + ;;
  481 + esac
  482 + shift
  483 + done
  484 +}
  485 +fi
  486 +fi
  487 +
  488 +# __gitcomp accepts 1, 2, 3, or 4 arguments
  489 +# generates completion reply with compgen
  490 +__gitcomp ()
  491 +{
  492 + local cur_="$cur"
  493 +
  494 + if [ $# -gt 2 ]; then
  495 + cur_="$3"
  496 + fi
  497 + case "$cur_" in
  498 + --*=)
  499 + COMPREPLY=()
  500 + ;;
  501 + *)
  502 + local IFS=$'\n'
  503 + COMPREPLY=($(compgen -P "${2-}" \
  504 + -W "$(__gitcomp_1 "${1-}" "${4-}")" \
  505 + -- "$cur_"))
  506 + ;;
  507 + esac
  508 +}
  509 +
  510 +# __git_heads accepts 0 or 1 arguments (to pass to __gitdir)
  511 +__git_heads ()
  512 +{
  513 + local cmd i is_hash=y dir="$(__gitdir "${1-}")"
  514 + if [ -d "$dir" ]; then
  515 + git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
  516 + refs/heads
  517 + return
  518 + fi
  519 + for i in $(git ls-remote "${1-}" 2>/dev/null); do
  520 + case "$is_hash,$i" in
  521 + y,*) is_hash=n ;;
  522 + n,*^{}) is_hash=y ;;
  523 + n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
  524 + n,*) is_hash=y; echo "$i" ;;
  525 + esac
  526 + done
  527 +}
  528 +
  529 +# __git_tags accepts 0 or 1 arguments (to pass to __gitdir)
  530 +__git_tags ()
  531 +{
  532 + local cmd i is_hash=y dir="$(__gitdir "${1-}")"
  533 + if [ -d "$dir" ]; then
  534 + git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
  535 + refs/tags
  536 + return
  537 + fi
  538 + for i in $(git ls-remote "${1-}" 2>/dev/null); do
  539 + case "$is_hash,$i" in
  540 + y,*) is_hash=n ;;
  541 + n,*^{}) is_hash=y ;;
  542 + n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
  543 + n,*) is_hash=y; echo "$i" ;;
  544 + esac
  545 + done
  546 +}
  547 +
  548 +# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments
  549 +# presence of 2nd argument means use the guess heuristic employed
  550 +# by checkout for tracking branches
  551 +__git_refs ()
  552 +{
  553 + local i is_hash=y dir="$(__gitdir "${1-}")" track="${2-}"
  554 + local format refs
  555 + if [ -d "$dir" ]; then
  556 + case "$cur" in
  557 + refs|refs/*)
  558 + format="refname"
  559 + refs="${cur%/*}"
  560 + track=""
  561 + ;;
  562 + *)
  563 + for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
  564 + if [ -e "$dir/$i" ]; then echo $i; fi
  565 + done
  566 + format="refname:short"
  567 + refs="refs/tags refs/heads refs/remotes"
  568 + ;;
  569 + esac
  570 + git --git-dir="$dir" for-each-ref --format="%($format)" \
  571 + $refs
  572 + if [ -n "$track" ]; then
  573 + # employ the heuristic used by git checkout
  574 + # Try to find a remote branch that matches the completion word
  575 + # but only output if the branch name is unique
  576 + local ref entry
  577 + git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \
  578 + "refs/remotes/" | \
  579 + while read entry; do
  580 + eval "$entry"
  581 + ref="${ref#*/}"
  582 + if [[ "$ref" == "$cur"* ]]; then
  583 + echo "$ref"
  584 + fi
  585 + done | uniq -u
  586 + fi
  587 + return
  588 + fi
  589 + for i in $(git ls-remote "$dir" 2>/dev/null); do
  590 + case "$is_hash,$i" in
  591 + y,*) is_hash=n ;;
  592 + n,*^{}) is_hash=y ;;
  593 + n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
  594 + n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
  595 + n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;;
  596 + n,*) is_hash=y; echo "$i" ;;
  597 + esac
  598 + done
  599 +}
  600 +
  601 +# __git_refs2 requires 1 argument (to pass to __git_refs)
  602 +__git_refs2 ()
  603 +{
  604 + local i
  605 + for i in $(__git_refs "$1"); do
  606 + echo "$i:$i"
  607 + done
  608 +}
  609 +
  610 +# __git_refs_remotes requires 1 argument (to pass to ls-remote)
  611 +__git_refs_remotes ()
  612 +{
  613 + local cmd i is_hash=y
  614 + for i in $(git ls-remote "$1" 2>/dev/null); do
  615 + case "$is_hash,$i" in
  616 + n,refs/heads/*)
  617 + is_hash=y
  618 + echo "$i:refs/remotes/$1/${i#refs/heads/}"
  619 + ;;
  620 + y,*) is_hash=n ;;
  621 + n,*^{}) is_hash=y ;;
  622 + n,refs/tags/*) is_hash=y;;
  623 + n,*) is_hash=y; ;;
  624 + esac
  625 + done
  626 +}
  627 +
  628 +__git_remotes ()
  629 +{
  630 + local i ngoff IFS=$'\n' d="$(__gitdir)"
  631 + __git_shopt -q nullglob || ngoff=1
  632 + __git_shopt -s nullglob
  633 + for i in "$d/remotes"/*; do
  634 + echo ${i#$d/remotes/}
  635 + done
  636 + [ "$ngoff" ] && __git_shopt -u nullglob
  637 + for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do
  638 + i="${i#remote.}"
  639 + echo "${i/.url*/}"
  640 + done
  641 +}
  642 +
  643 +__git_list_merge_strategies ()
  644 +{
  645 + git merge -s help 2>&1 |
  646 + sed -n -e '/[Aa]vailable strategies are: /,/^$/{
  647 + s/\.$//
  648 + s/.*://
  649 + s/^[ ]*//
  650 + s/[ ]*$//
  651 + p
  652 + }'
  653 +}
  654 +
  655 +__git_merge_strategies=
  656 +# 'git merge -s help' (and thus detection of the merge strategy
  657 +# list) fails, unfortunately, if run outside of any git working
  658 +# tree. __git_merge_strategies is set to the empty string in
  659 +# that case, and the detection will be repeated the next time it
  660 +# is needed.
  661 +__git_compute_merge_strategies ()
  662 +{
  663 + : ${__git_merge_strategies:=$(__git_list_merge_strategies)}
  664 +}
  665 +
  666 +__git_complete_revlist_file ()
  667 +{
  668 + local pfx ls ref cur_="$cur"
  669 + case "$cur_" in
  670 + *..?*:*)
  671 + return
  672 + ;;
  673 + ?*:*)
  674 + ref="${cur_%%:*}"
  675 + cur_="${cur_#*:}"
  676 + case "$cur_" in
  677 + ?*/*)
  678 + pfx="${cur_%/*}"
  679 + cur_="${cur_##*/}"
  680 + ls="$ref:$pfx"
  681 + pfx="$pfx/"
  682 + ;;
  683 + *)
  684 + ls="$ref"
  685 + ;;
  686 + esac
  687 +
  688 + case "$COMP_WORDBREAKS" in
  689 + *:*) : great ;;
  690 + *) pfx="$ref:$pfx" ;;
  691 + esac
  692 +
  693 + local IFS=$'\n'
  694 + COMPREPLY=($(compgen -P "$pfx" \
  695 + -W "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \
  696 + | sed '/^100... blob /{
  697 + s,^.* ,,
  698 + s,$, ,
  699 + }
  700 + /^120000 blob /{
  701 + s,^.* ,,
  702 + s,$, ,
  703 + }
  704 + /^040000 tree /{
  705 + s,^.* ,,
  706 + s,$,/,
  707 + }
  708 + s/^.* //')" \
  709 + -- "$cur_"))
  710 + ;;
  711 + *...*)
  712 + pfx="${cur_%...*}..."
  713 + cur_="${cur_#*...}"
  714 + __gitcomp "$(__git_refs)" "$pfx" "$cur_"
  715 + ;;
  716 + *..*)
  717 + pfx="${cur_%..*}.."
  718 + cur_="${cur_#*..}"
  719 + __gitcomp "$(__git_refs)" "$pfx" "$cur_"
  720 + ;;
  721 + *)
  722 + __gitcomp "$(__git_refs)"
  723 + ;;
  724 + esac
  725 +}
  726 +
  727 +
  728 +__git_complete_file ()
  729 +{
  730 + __git_complete_revlist_file
  731 +}
  732 +
  733 +__git_complete_revlist ()
  734 +{
  735 + __git_complete_revlist_file
  736 +}
  737 +
  738 +__git_complete_remote_or_refspec ()
  739 +{
  740 + local cur_="$cur" cmd="${words[1]}"
  741 + local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
  742 + while [ $c -lt $cword ]; do
  743 + i="${words[c]}"
  744 + case "$i" in
  745 + --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
  746 + --all)
  747 + case "$cmd" in
  748 + push) no_complete_refspec=1 ;;
  749 + fetch)
  750 + COMPREPLY=()
  751 + return
  752 + ;;
  753 + *) ;;
  754 + esac
  755 + ;;
  756 + -*) ;;
  757 + *) remote="$i"; break ;;
  758 + esac
  759 + c=$((++c))
  760 + done
  761 + if [ -z "$remote" ]; then
  762 + __gitcomp "$(__git_remotes)"
  763 + return
  764 + fi
  765 + if [ $no_complete_refspec = 1 ]; then
  766 + COMPREPLY=()
  767 + return
  768 + fi
  769 + [ "$remote" = "." ] && remote=
  770 + case "$cur_" in
  771 + *:*)
  772 + case "$COMP_WORDBREAKS" in
  773 + *:*) : great ;;
  774 + *) pfx="${cur_%%:*}:" ;;
  775 + esac
  776 + cur_="${cur_#*:}"
  777 + lhs=0
  778 + ;;
  779 + +*)
  780 + pfx="+"
  781 + cur_="${cur_#+}"
  782 + ;;
  783 + esac
  784 + case "$cmd" in
  785 + fetch)
  786 + if [ $lhs = 1 ]; then
  787 + __gitcomp "$(__git_refs2 "$remote")" "$pfx" "$cur_"
  788 + else
  789 + __gitcomp "$(__git_refs)" "$pfx" "$cur_"
  790 + fi
  791 + ;;
  792 + pull)
  793 + if [ $lhs = 1 ]; then
  794 + __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur_"
  795 + else
  796 + __gitcomp "$(__git_refs)" "$pfx" "$cur_"
  797 + fi
  798 + ;;
  799 + push)
  800 + if [ $lhs = 1 ]; then
  801 + __gitcomp "$(__git_refs)" "$pfx" "$cur_"
  802 + else
  803 + __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur_"
  804 + fi
  805 + ;;
  806 + esac
  807 +}
  808 +
  809 +__git_complete_strategy ()
  810 +{
  811 + __git_compute_merge_strategies
  812 + case "$prev" in
  813 + -s|--strategy)
  814 + __gitcomp "$__git_merge_strategies"
  815 + return 0
  816 + esac
  817 + case "$cur" in
  818 + --strategy=*)
  819 + __gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
  820 + return 0
  821 + ;;
  822 + esac
  823 + return 1
  824 +}
  825 +
  826 +__git_list_all_commands ()
  827 +{
  828 + local i IFS=" "$'\n'
  829 + for i in $(git help -a|egrep '^ [a-zA-Z0-9]')
  830 + do
  831 + case $i in
  832 + *--*) : helper pattern;;
  833 + *) echo $i;;
  834 + esac
  835 + done
  836 +}
  837 +
  838 +__git_all_commands=
  839 +__git_compute_all_commands ()
  840 +{
  841 + : ${__git_all_commands:=$(__git_list_all_commands)}
  842 +}
  843 +
  844 +__git_list_porcelain_commands ()
  845 +{
  846 + local i IFS=" "$'\n'
  847 + __git_compute_all_commands
  848 + for i in "help" $__git_all_commands
  849 + do
  850 + case $i in
  851 + *--*) : helper pattern;;
  852 + applymbox) : ask gittus;;
  853 + applypatch) : ask gittus;;
  854 + archimport) : import;;
  855 + cat-file) : plumbing;;
  856 + check-attr) : plumbing;;
  857 + check-ref-format) : plumbing;;
  858 + checkout-index) : plumbing;;
  859 + commit-tree) : plumbing;;
  860 + count-objects) : infrequent;;
  861 + cvsexportcommit) : export;;
  862 + cvsimport) : import;;
  863 + cvsserver) : daemon;;
  864 + daemon) : daemon;;
  865 + diff-files) : plumbing;;
  866 + diff-index) : plumbing;;
  867 + diff-tree) : plumbing;;
  868 + fast-import) : import;;
  869 + fast-export) : export;;
  870 + fsck-objects) : plumbing;;
  871 + fetch-pack) : plumbing;;
  872 + fmt-merge-msg) : plumbing;;
  873 + for-each-ref) : plumbing;;
  874 + hash-object) : plumbing;;
  875 + http-*) : transport;;
  876 + index-pack) : plumbing;;
  877 + init-db) : deprecated;;
  878 + local-fetch) : plumbing;;
  879 + lost-found) : infrequent;;
  880 + ls-files) : plumbing;;
  881 + ls-remote) : plumbing;;
  882 + ls-tree) : plumbing;;
  883 + mailinfo) : plumbing;;
  884 + mailsplit) : plumbing;;
  885 + merge-*) : plumbing;;
  886 + mktree) : plumbing;;
  887 + mktag) : plumbing;;
  888 + pack-objects) : plumbing;;
  889 + pack-redundant) : plumbing;;
  890 + pack-refs) : plumbing;;
  891 + parse-remote) : plumbing;;
  892 + patch-id) : plumbing;;
  893 + peek-remote) : plumbing;;
  894 + prune) : plumbing;;
  895 + prune-packed) : plumbing;;
  896 + quiltimport) : import;;
  897 + read-tree) : plumbing;;
  898 + receive-pack) : plumbing;;
  899 + remote-*) : transport;;
  900 + repo-config) : deprecated;;
  901 + rerere) : plumbing;;
  902 + rev-list) : plumbing;;
  903 + rev-parse) : plumbing;;
  904 + runstatus) : plumbing;;
  905 + sh-setup) : internal;;
  906 + shell) : daemon;;
  907 + show-ref) : plumbing;;
  908 + send-pack) : plumbing;;
  909 + show-index) : plumbing;;
  910 + ssh-*) : transport;;
  911 + stripspace) : plumbing;;
  912 + symbolic-ref) : plumbing;;
  913 + tar-tree) : deprecated;;
  914 + unpack-file) : plumbing;;
  915 + unpack-objects) : plumbing;;
  916 + update-index) : plumbing;;
  917 + update-ref) : plumbing;;
  918 + update-server-info) : daemon;;
  919 + upload-archive) : plumbing;;
  920 + upload-pack) : plumbing;;
  921 + write-tree) : plumbing;;
  922 + var) : infrequent;;
  923 + verify-pack) : infrequent;;
  924 + verify-tag) : plumbing;;
  925 + *) echo $i;;
  926 + esac
  927 + done
  928 +}
  929 +
  930 +__git_porcelain_commands=
  931 +__git_compute_porcelain_commands ()
  932 +{
  933 + __git_compute_all_commands
  934 + : ${__git_porcelain_commands:=$(__git_list_porcelain_commands)}
  935 +}
  936 +
  937 +__git_pretty_aliases ()
  938 +{
  939 + local i IFS=$'\n'
  940 + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "pretty\..*" 2>/dev/null); do
  941 + case "$i" in
  942 + pretty.*)
  943 + i="${i#pretty.}"
  944 + echo "${i/ */}"
  945 + ;;
  946 + esac
  947 + done
  948 +}
  949 +
  950 +__git_aliases ()
  951 +{
  952 + local i IFS=$'\n'
  953 + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do
  954 + case "$i" in
  955 + alias.*)
  956 + i="${i#alias.}"
  957 + echo "${i/ */}"
  958 + ;;
  959 + esac
  960 + done
  961 +}
  962 +
  963 +# __git_aliased_command requires 1 argument
  964 +__git_aliased_command ()
  965 +{
  966 + local word cmdline=$(git --git-dir="$(__gitdir)" \
  967 + config --get "alias.$1")
  968 + for word in $cmdline; do
  969 + case "$word" in
  970 + \!gitk|gitk)
  971 + echo "gitk"
  972 + return
  973 + ;;
  974 + \!*) : shell command alias ;;
  975 + -*) : option ;;
  976 + *=*) : setting env ;;
  977 + git) : git itself ;;
  978 + *)
  979 + echo "$word"
  980 + return
  981 + esac
  982 + done
  983 +}
  984 +
  985 +# __git_find_on_cmdline requires 1 argument
  986 +__git_find_on_cmdline ()
  987 +{
  988 + local word subcommand c=1
  989 + while [ $c -lt $cword ]; do
  990 + word="${words[c]}"
  991 + for subcommand in $1; do
  992 + if [ "$subcommand" = "$word" ]; then
  993 + echo "$subcommand"
  994 + return
  995 + fi
  996 + done
  997 + c=$((++c))
  998 + done
  999 +}
  1000 +
  1001 +__git_has_doubledash ()
  1002 +{
  1003 + local c=1
  1004 + while [ $c -lt $cword ]; do
  1005 + if [ "--" = "${words[c]}" ]; then
  1006 + return 0
  1007 + fi
  1008 + c=$((++c))
  1009 + done
  1010 + return 1
  1011 +}
  1012 +
  1013 +__git_whitespacelist="nowarn warn error error-all fix"
  1014 +
  1015 +_git_am ()
  1016 +{
  1017 + local dir="$(__gitdir)"
  1018 + if [ -d "$dir"/rebase-apply ]; then
  1019 + __gitcomp "--skip --continue --resolved --abort"
  1020 + return
  1021 + fi
  1022 + case "$cur" in
  1023 + --whitespace=*)
  1024 + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
  1025 + return
  1026 + ;;
  1027 + --*)
  1028 + __gitcomp "
  1029 + --3way --committer-date-is-author-date --ignore-date
  1030 + --ignore-whitespace --ignore-space-change
  1031 + --interactive --keep --no-utf8 --signoff --utf8
  1032 + --whitespace= --scissors
  1033 + "
  1034 + return
  1035 + esac
  1036 + COMPREPLY=()
  1037 +}
  1038 +
  1039 +_git_apply ()
  1040 +{
  1041 + case "$cur" in
  1042 + --whitespace=*)
  1043 + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
  1044 + return
  1045 + ;;
  1046 + --*)
  1047 + __gitcomp "
  1048 + --stat --numstat --summary --check --index
  1049 + --cached --index-info --reverse --reject --unidiff-zero
  1050 + --apply --no-add --exclude=
  1051 + --ignore-whitespace --ignore-space-change
  1052 + --whitespace= --inaccurate-eof --verbose
  1053 + "
  1054 + return
  1055 + esac
  1056 + COMPREPLY=()
  1057 +}
  1058 +
  1059 +_git_add ()
  1060 +{
  1061 + __git_has_doubledash && return
  1062 +
  1063 + case "$cur" in
  1064 + --*)
  1065 + __gitcomp "
  1066 + --interactive --refresh --patch --update --dry-run
  1067 + --ignore-errors --intent-to-add
  1068 + "
  1069 + return
  1070 + esac
  1071 + COMPREPLY=()
  1072 +}
  1073 +
  1074 +_git_archive ()
  1075 +{
  1076 + case "$cur" in
  1077 + --format=*)
  1078 + __gitcomp "$(git archive --list)" "" "${cur##--format=}"
  1079 + return
  1080 + ;;
  1081 + --remote=*)
  1082 + __gitcomp "$(__git_remotes)" "" "${cur##--remote=}"
  1083 + return
  1084 + ;;
  1085 + --*)
  1086 + __gitcomp "
  1087 + --format= --list --verbose
  1088 + --prefix= --remote= --exec=
  1089 + "
  1090 + return
  1091 + ;;
  1092 + esac
  1093 + __git_complete_file
  1094 +}
  1095 +
  1096 +_git_bisect ()
  1097 +{
  1098 + __git_has_doubledash && return
  1099 +
  1100 + local subcommands="start bad good skip reset visualize replay log run"
  1101 + local subcommand="$(__git_find_on_cmdline "$subcommands")"
  1102 + if [ -z "$subcommand" ]; then
  1103 + if [ -f "$(__gitdir)"/BISECT_START ]; then
  1104 + __gitcomp "$subcommands"
  1105 + else
  1106 + __gitcomp "replay start"
  1107 + fi
  1108 + return
  1109 + fi
  1110 +
  1111 + case "$subcommand" in
  1112 + bad|good|reset|skip|start)
  1113 + __gitcomp "$(__git_refs)"
  1114 + ;;
  1115 + *)
  1116 + COMPREPLY=()
  1117 + ;;
  1118 + esac
  1119 +}
  1120 +
  1121 +_git_branch ()
  1122 +{
  1123 + local i c=1 only_local_ref="n" has_r="n"
  1124 +
  1125 + while [ $c -lt $cword ]; do
  1126 + i="${words[c]}"
  1127 + case "$i" in
  1128 + -d|-m) only_local_ref="y" ;;
  1129 + -r) has_r="y" ;;
  1130 + esac
  1131 + c=$((++c))
  1132 + done
  1133 +
  1134 + case "$cur" in
  1135 + --*)
  1136 + __gitcomp "
  1137 + --color --no-color --verbose --abbrev= --no-abbrev
  1138 + --track --no-track --contains --merged --no-merged
  1139 + --set-upstream
  1140 + "
  1141 + ;;
  1142 + *)
  1143 + if [ $only_local_ref = "y" -a $has_r = "n" ]; then
  1144 + __gitcomp "$(__git_heads)"
  1145 + else
  1146 + __gitcomp "$(__git_refs)"
  1147 + fi
  1148 + ;;
  1149 + esac
  1150 +}
  1151 +
  1152 +_git_bundle ()
  1153 +{
  1154 + local cmd="${words[2]}"
  1155 + case "$cword" in
  1156 + 2)
  1157 + __gitcomp "create list-heads verify unbundle"
  1158 + ;;
  1159 + 3)
  1160 + # looking for a file
  1161 + ;;
  1162 + *)
  1163 + case "$cmd" in
  1164 + create)
  1165 + __git_complete_revlist
  1166 + ;;
  1167 + esac
  1168 + ;;
  1169 + esac
  1170 +}
  1171 +
  1172 +_git_checkout ()
  1173 +{
  1174 + __git_has_doubledash && return
  1175 +
  1176 + case "$cur" in
  1177 + --conflict=*)
  1178 + __gitcomp "diff3 merge" "" "${cur##--conflict=}"
  1179 + ;;
  1180 + --*)
  1181 + __gitcomp "
  1182 + --quiet --ours --theirs --track --no-track --merge
  1183 + --conflict= --orphan --patch
  1184 + "
  1185 + ;;
  1186 + *)
  1187 + # check if --track, --no-track, or --no-guess was specified
  1188 + # if so, disable DWIM mode
  1189 + local flags="--track --no-track --no-guess" track=1
  1190 + if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
  1191 + track=''
  1192 + fi
  1193 + __gitcomp "$(__git_refs '' $track)"
  1194 + ;;
  1195 + esac
  1196 +}
  1197 +
  1198 +_git_cherry ()
  1199 +{
  1200 + __gitcomp "$(__git_refs)"
  1201 +}
  1202 +
  1203 +_git_cherry_pick ()
  1204 +{
  1205 + case "$cur" in
  1206 + --*)
  1207 + __gitcomp "--edit --no-commit"
  1208 + ;;
  1209 + *)
  1210 + __gitcomp "$(__git_refs)"
  1211 + ;;
  1212 + esac
  1213 +}
  1214 +
  1215 +_git_clean ()
  1216 +{
  1217 + __git_has_doubledash && return
  1218 +
  1219 + case "$cur" in
  1220 + --*)
  1221 + __gitcomp "--dry-run --quiet"
  1222 + return
  1223 + ;;
  1224 + esac
  1225 + COMPREPLY=()
  1226 +}
  1227 +
  1228 +_git_clone ()
  1229 +{
  1230 + case "$cur" in
  1231 + --*)
  1232 + __gitcomp "
  1233 + --local