diff options
| author | Tuowen Zhao <ztuowen@gmail.com> | 2019-09-11 18:19:51 -0600 | 
|---|---|---|
| committer | Tuowen Zhao <ztuowen@gmail.com> | 2019-09-11 18:19:51 -0600 | 
| commit | d676c1553254309beca5bb9a8edb43fbe09a7169 (patch) | |
| tree | d0bb04b6487e6fedbb2b2370a894fccd19d4c567 /plugins/gitfast | |
| parent | fb141c2257f648cd29b64cbd3f2ca9123f6e427f (diff) | |
| parent | ddd359dd668f448856438304bedfe952d1749efd (diff) | |
| download | zsh-d676c1553254309beca5bb9a8edb43fbe09a7169.tar.gz zsh-d676c1553254309beca5bb9a8edb43fbe09a7169.tar.bz2 zsh-d676c1553254309beca5bb9a8edb43fbe09a7169.zip | |
Merge remote-tracking branch 'orig/master'
Diffstat (limited to 'plugins/gitfast')
| -rw-r--r-- | plugins/gitfast/README.md | 129 | ||||
| -rw-r--r-- | plugins/gitfast/_git | 30 | ||||
| -rw-r--r-- | plugins/gitfast/git-completion.bash | 2057 | ||||
| -rw-r--r-- | plugins/gitfast/git-prompt.sh | 28 | ||||
| -rw-r--r-- | plugins/gitfast/gitfast.plugin.zsh | 4 | ||||
| -rwxr-xr-x | plugins/gitfast/update | 9 | ||||
| -rw-r--r-- | plugins/gitfast/updates.patch | 56 | 
7 files changed, 1324 insertions, 989 deletions
| diff --git a/plugins/gitfast/README.md b/plugins/gitfast/README.md index c3073709e..84e35d77c 100644 --- a/plugins/gitfast/README.md +++ b/plugins/gitfast/README.md @@ -10,129 +10,6 @@ plugins=(... gitfast)  ## Aliases -| Alias                | Command                                                                                                                                | -| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| g                    | `git`                                                                                                                                  | -| ga                   | `git add`                                                                                                                              | -| gaa                  | `git add --all`                                                                                                                        | -| gapa                 | `git add --patch`                                                                                                                      | -| gau                  | `git add --update`                                                                                                                     | -| gb                   | `git branch`                                                                                                                           | -| gba                  | `git branch -a`                                                                                                                        | -| gbd                  | `git branch -d`                                                                                                                        | -| gbda                 | `git branch --no-color --merged | command grep -vE "^(\*|\s*(master|develop|dev)\s*$)" | command xargs -n 1 git branch -d`             | -| gbl                  | `git blame -b -w`                                                                                                                      | -| gbnm                 | `git branch --no-merged`                                                                                                               | -| gbr                  | `git branch --remote`                                                                                                                  | -| gbs                  | `git bisect`                                                                                                                           | -| gbsb                 | `git bisect bad`                                                                                                                       | -| gbsg                 | `git bisect good`                                                                                                                      | -| gbsr                 | `git bisect reset`                                                                                                                     | -| gbss                 | `git bisect start`                                                                                                                     | -| gc                   | `git commit -v`                                                                                                                        | -| gc!                  | `git commit -v --amend`                                                                                                                | -| gca                  | `git commit -v -a`                                                                                                                     | -| gca!                 | `git commit -v -a --amend`                                                                                                             | -| gcam                 | `git commit -a -m`                                                                                                                     | -| gcan!                | `git commit -v -a --no-edit --amend`                                                                                                   | -| gcans!               | `git commit -v -a -s --no-edit --amend`                                                                                                | -| gcb                  | `git checkout -b`                                                                                                                      | -| gcd                  | `git checkout develop`                                                                                                                 | -| gcf                  | `git config --list`                                                                                                                    | -| gcl                  | `git clone --recursive`                                                                                                                | -| gclean               | `git clean -fd`                                                                                                                        | -| gcm                  | `git checkout master`                                                                                                                  | -| gcmsg                | `git commit -m`                                                                                                                        | -| gcn!                 | `git commit -v --no-edit --amend`                                                                                                      | -| gco                  | `git checkout`                                                                                                                         | -| gcount               | `git shortlog -sn`                                                                                                                     | -| gcp                  | `git cherry-pick`                                                                                                                      | -| gcpa                 | `git cherry-pick --abort`                                                                                                              | -| gcpc                 | `git cherry-pick --continue`                                                                                                           | -| gcs                  | `git commit -S`                                                                                                                        | -| gcsm                 | `git commit -s -m`                                                                                                                     | -| gd                   | `git diff`                                                                                                                             | -| gdca                 | `git diff --cached`                                                                                                                    | -| gdct                 | `` git describe --tags `git rev-list --tags --max-count=1` ``                                                                          | -| gdt                  | `git diff-tree --no-commit-id --name-only -r`                                                                                          | -| gdw                  | `git diff --word-diff`                                                                                                                 | -| gf                   | `git fetch`                                                                                                                            | -| gfa                  | `git fetch --all --prune`                                                                                                              | -| gfo                  | `git fetch origin`                                                                                                                     | -| gg                   | `git gui citool`                                                                                                                       | -| gga                  | `git gui citool --amend`                                                                                                               | -| ggpull               | `git pull origin $(git_current_branch)`                                                                                                | -| ggpur                | `ggu`                                                                                                                                  | -| ggpush               | `git push origin $(git_current_branch)`                                                                                                | -| ggsup                | `git branch --set-upstream-to=origin/$(git_current_branch)`                                                                            | -| ghh                  | `git help`                                                                                                                             | -| gignore              | `git update-index --assume-unchanged`                                                                                                  | -| gignored             | `git ls-files -v | grep "^[[:lower:]]"`                                                                                                | -| git-svn-dcommit-push | `git svn dcommit && git push github master:svntrunk`                                                                                   | -| gk                   | `\gitk --all --branches`                                                                                                               | -| gke                  | `\gitk --all $(git log -g --pretty=%h)`                                                                                                | -| gl                   | `git pull`                                                                                                                             | -| glg                  | `git log --stat`                                                                                                                       | -| glgg                 | `git log --graph`                                                                                                                      | -| glgga                | `git log --graph --decorate --all`                                                                                                     | -| glgm                 | `git log --graph --max-count=10`                                                                                                       | -| glgp                 | `git log --stat -p`                                                                                                                    | -| glo                  | `git log --oneline --decorate`                                                                                                         | -| glog                 | `git log --oneline --decorate --graph`                                                                                                 | -| gloga                | `git log --oneline --decorate --graph --all`                                                                                           | -| glol                 | `git log --graph --pretty='\''%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'\'' --abbrev-commit`       | -| glola                | `git log --graph --pretty='\''%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'\'' --abbrev-commit --all` | -| glp                  | `_git_log_prettily`                                                                                                                    | -| glum                 | `git pull upstream master`                                                                                                             | -| gm                   | `git merge`                                                                                                                            | -| gmom                 | `git merge origin/master`                                                                                                              | -| gmt                  | `git mergetool --no-prompt`                                                                                                            | -| gmtvim               | `git mergetool --no-prompt --tool=vimdiff`                                                                                             | -| gmum                 | `git merge upstream/master`                                                                                                            | -| gp                   | `git push`                                                                                                                             | -| gpd                  | `git push --dry-run`                                                                                                                   | -| gpoat                | `git push origin --all && git push origin --tags`                                                                                      | -| gpristine            | `git reset --hard && git clean -dfx`                                                                                                   | -| gpsup                | `git push --set-upstream origin $(git_current_branch)`                                                                                 | -| gpu                  | `git push upstream`                                                                                                                    | -| gpv                  | `git push -v`                                                                                                                          | -| gr                   | `git remote`                                                                                                                           | -| gra                  | `git remote add`                                                                                                                       | -| grb                  | `git rebase`                                                                                                                           | -| grba                 | `git rebase --abort`                                                                                                                   | -| grbc                 | `git rebase --continue`                                                                                                                | -| grbi                 | `git rebase -i`                                                                                                                        | -| grbm                 | `git rebase master`                                                                                                                    | -| grbs                 | `git rebase --skip`                                                                                                                    | -| grh                  | `git reset HEAD`                                                                                                                       | -| grhh                 | `git reset HEAD --hard`                                                                                                                | -| grmv                 | `git remote rename`                                                                                                                    | -| grrm                 | `git remote remove`                                                                                                                    | -| grset                | `git remote set-url`                                                                                                                   | -| grt                  | `cd $(git rev-parse --show-toplevel || echo ".")`                                                                                      | -| gru                  | `git reset --`                                                                                                                         | -| grup                 | `git remote update`                                                                                                                    | -| grv                  | `git remote -v`                                                                                                                        | -| gsb                  | `git status -sb`                                                                                                                       | -| gsd                  | `git svn dcommit`                                                                                                                      | -| gsi                  | `git submodule init`                                                                                                                   | -| gsps                 | `git show --pretty=short --show-signature`                                                                                             | -| gsr                  | `git svn rebase`                                                                                                                       | -| gss                  | `git status -s`                                                                                                                        | -| gst                  | `git status`                                                                                                                           | -| gsta                 | `git stash save`                                                                                                                       | -| gstaa                | `git stash apply`                                                                                                                      | -| gstc                 | `git stash clear`                                                                                                                      | -| gstd                 | `git stash drop`                                                                                                                       | -| gstl                 | `git stash list`                                                                                                                       | -| gstp                 | `git stash pop`                                                                                                                        | -| gsts                 | `git stash show --text`                                                                                                                | -| gsu                  | `git submodule update`                                                                                                                 | -| gts                  | `git tag -s`                                                                                                                           | -| gtv                  | `git tag | sort -V`                                                                                                                    | -| gunignore            | `git update-index --no-assume-unchanged`                                                                                               | -| gunwip               | `git log -n 1 | grep -q -c "\-\-wip\-\-" && git reset HEAD~1`                                                                          | -| gup                  | `git pull --rebase`                                                                                                                    | -| gupv                 | `git pull --rebase -v`                                                                                                                 | -| gwch                 | `git whatchanged -p --abbrev-commit --pretty=medium`                                                                                   | -| gwip                 | `git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify -m "--wip-- [skip ci]"`                             | +An earlier version of the plugin also loaded the git plugin. If you want to keep those +aliases enable the [git plugin](https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins/git) +as well. diff --git a/plugins/gitfast/_git b/plugins/gitfast/_git index 6d1b4ecc7..886bf95d1 100644 --- a/plugins/gitfast/_git +++ b/plugins/gitfast/_git @@ -9,7 +9,7 @@  #  # If your script is somewhere else, you can configure it on your ~/.zshrc:  # -#  zstyle ':completion:*:*:git:*' script ~/.git-completion.sh +#  zstyle ':completion:*:*:git:*' script ~/.git-completion.zsh  #  # The recommended way to install this script is to copy to '~/.zsh/_git', and  # then add the following to your ~/.zshrc file: @@ -30,7 +30,7 @@ if [ -z "$script" ]; then  	local -a locations  	local e  	locations=( -		"$(dirname ${funcsourcetrace[1]%:*})/git-completion.bash" +		$(dirname ${funcsourcetrace[1]%:*})/git-completion.bash  		'/etc/bash_completion.d/git' # fedora, old debian  		'/usr/share/bash-completion/completions/git' # arch, ubuntu, new debian  		'/usr/share/bash-completion/git' # gentoo @@ -39,7 +39,7 @@ if [ -z "$script" ]; then  		test -f $e && script="$e" && break  	done  fi -ZSH_VERSION='' . "$script" +GIT_SOURCING_ZSH_COMPLETION=y . "$script"  __gitcomp ()  { @@ -67,6 +67,15 @@ __gitcomp ()  	esac  } +__gitcomp_direct () +{ +	emulate -L zsh + +	local IFS=$'\n' +	compset -P '*[=:]' +	compadd -Q -- ${=1} && _ret=0 +} +  __gitcomp_nl ()  {  	emulate -L zsh @@ -84,13 +93,22 @@ __gitcomp_nl_append ()  	compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0  } +__gitcomp_file_direct () +{ +	emulate -L zsh + +	local IFS=$'\n' +	compset -P '*[=:]' +	compadd -f -- ${=1} && _ret=0 +} +  __gitcomp_file ()  {  	emulate -L zsh  	local IFS=$'\n'  	compset -P '*[=:]' -	compadd -Q -p "${2-}" -f -- ${=1} && _ret=0 +	compadd -p "${2-}" -f -- ${=1} && _ret=0  }  __git_zsh_bash_func () @@ -214,10 +232,8 @@ _git ()  	if (( $+functions[__${service}_zsh_main] )); then  		__${service}_zsh_main -	elif (( $+functions[__${service}_main] )); then +	else  		emulate ksh -c __${service}_main -	elif (( $+functions[_${service}] )); then -		emulate ksh -c _${service}  	fi  	let _ret && _default && _ret=0 diff --git a/plugins/gitfast/git-completion.bash b/plugins/gitfast/git-completion.bash index 8ce6b5c5f..e087c4bf0 100644 --- a/plugins/gitfast/git-completion.bash +++ b/plugins/gitfast/git-completion.bash @@ -28,27 +28,58 @@  # completion style.  For example '!f() { : git commit ; ... }; f' will  # tell the completion to use commit completion.  This also works with aliases  # of form "!sh -c '...'".  For example, "!sh -c ': git commit ; ... '". +# +# Compatible with bash 3.2.57. +# +# You can set the following environment variables to influence the behavior of +# the completion routines: +# +#   GIT_COMPLETION_CHECKOUT_NO_GUESS +# +#     When set to "1", do not include "DWIM" suggestions in git-checkout +#     and git-switch completion (e.g., completing "foo" when "origin/foo" +#     exists).  case "$COMP_WORDBREAKS" in  *:*) : great ;;  *)   COMP_WORDBREAKS="$COMP_WORDBREAKS:"  esac +# Discovers the path to the git repository taking any '--git-dir=<path>' and +# '-C <path>' options into account and stores it in the $__git_repo_path +# variable. +__git_find_repo_path () +{ +	if [ -n "$__git_repo_path" ]; then +		# we already know where it is +		return +	fi + +	if [ -n "${__git_C_args-}" ]; then +		__git_repo_path="$(git "${__git_C_args[@]}" \ +			${__git_dir:+--git-dir="$__git_dir"} \ +			rev-parse --absolute-git-dir 2>/dev/null)" +	elif [ -n "${__git_dir-}" ]; then +		test -d "$__git_dir" && +		__git_repo_path="$__git_dir" +	elif [ -n "${GIT_DIR-}" ]; then +		test -d "${GIT_DIR-}" && +		__git_repo_path="$GIT_DIR" +	elif [ -d .git ]; then +		__git_repo_path=.git +	else +		__git_repo_path="$(git rev-parse --git-dir 2>/dev/null)" +	fi +} + +# Deprecated: use __git_find_repo_path() and $__git_repo_path instead  # __gitdir accepts 0 or 1 arguments (i.e., location)  # returns location of .git repo  __gitdir ()  {  	if [ -z "${1-}" ]; then -		if [ -n "${__git_dir-}" ]; then -			echo "$__git_dir" -		elif [ -n "${GIT_DIR-}" ]; then -			test -d "${GIT_DIR-}" || return 1 -			echo "$GIT_DIR" -		elif [ -d .git ]; then -			echo .git -		else -			git rev-parse --git-dir 2>/dev/null -		fi +		__git_find_repo_path || return 1 +		echo "$__git_repo_path"  	elif [ -d "$1/.git" ]; then  		echo "$1/.git"  	else @@ -56,6 +87,78 @@ __gitdir ()  	fi  } +# Runs git with all the options given as argument, respecting any +# '--git-dir=<path>' and '-C <path>' options present on the command line +__git () +{ +	git ${__git_C_args:+"${__git_C_args[@]}"} \ +		${__git_dir:+--git-dir="$__git_dir"} "$@" 2>/dev/null +} + +# Removes backslash escaping, single quotes and double quotes from a word, +# stores the result in the variable $dequoted_word. +# 1: The word to dequote. +__git_dequote () +{ +	local rest="$1" len ch + +	dequoted_word="" + +	while test -n "$rest"; do +		len=${#dequoted_word} +		dequoted_word="$dequoted_word${rest%%[\\\'\"]*}" +		rest="${rest:$((${#dequoted_word}-$len))}" + +		case "${rest:0:1}" in +		\\) +			ch="${rest:1:1}" +			case "$ch" in +			$'\n') +				;; +			*) +				dequoted_word="$dequoted_word$ch" +				;; +			esac +			rest="${rest:2}" +			;; +		\') +			rest="${rest:1}" +			len=${#dequoted_word} +			dequoted_word="$dequoted_word${rest%%\'*}" +			rest="${rest:$((${#dequoted_word}-$len+1))}" +			;; +		\") +			rest="${rest:1}" +			while test -n "$rest" ; do +				len=${#dequoted_word} +				dequoted_word="$dequoted_word${rest%%[\\\"]*}" +				rest="${rest:$((${#dequoted_word}-$len))}" +				case "${rest:0:1}" in +				\\) +					ch="${rest:1:1}" +					case "$ch" in +					\"|\\|\$|\`) +						dequoted_word="$dequoted_word$ch" +						;; +					$'\n') +						;; +					*) +						dequoted_word="$dequoted_word\\$ch" +						;; +					esac +					rest="${rest:2}" +					;; +				\") +					rest="${rest:1}" +					break +					;; +				esac +			done +			;; +		esac +	done +} +  # The following function is based on code from:  #  #   bash_completion - programmable completion functions for bash 3.2+ @@ -75,8 +178,7 @@ __gitdir ()  #   GNU General Public License for more details.  #  #   You should have received a copy of the GNU General Public License -#   along with this program; if not, write to the Free Software Foundation, -#   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#   along with this program; if not, see <http://www.gnu.org/licenses/>.  #  #   The latest version of this software can be obtained here:  # @@ -185,6 +287,20 @@ _get_comp_words_by_ref ()  }  fi +# Fills the COMPREPLY array with prefiltered words without any additional +# processing. +# Callers must take care of providing only words that match the current word +# to be completed and adding any prefix and/or suffix (trailing space!), if +# necessary. +# 1: List of newline-separated matching completion words, complete with +#    prefix and suffix. +__gitcomp_direct () +{ +	local IFS=$'\n' + +	COMPREPLY=($1) +} +  __gitcompappend ()  {  	local x i=${#COMPREPLY[@]} @@ -215,9 +331,32 @@ __gitcomp ()  	case "$cur_" in  	--*=)  		;; +	--no-*) +		local c i=0 IFS=$' \t\n' +		for c in $1; do +			if [[ $c == "--" ]]; then +				continue +			fi +			c="$c${4-}" +			if [[ $c == "$cur_"* ]]; then +				case $c in +				--*=*|*.) ;; +				*) c="$c " ;; +				esac +				COMPREPLY[i++]="${2-}$c" +			fi +		done +		;;  	*)  		local c i=0 IFS=$' \t\n'  		for c in $1; do +			if [[ $c == "--" ]]; then +				c="--no-...${4-}" +				if [[ $c == "$cur_"* ]]; then +					COMPREPLY[i++]="${2-}$c " +				fi +				break +			fi  			c="$c${4-}"  			if [[ $c == "$cur_"* ]]; then  				case $c in @@ -231,6 +370,48 @@ __gitcomp ()  	esac  } +# Clear the variables caching builtins' options when (re-)sourcing +# the completion script. +if [[ -n ${ZSH_VERSION-} ]]; then +	unset $(set |sed -ne 's/^\(__gitcomp_builtin_[a-zA-Z0-9_][a-zA-Z0-9_]*\)=.*/\1/p') 2>/dev/null +else +	unset $(compgen -v __gitcomp_builtin_) +fi + +# This function is equivalent to +# +#    __gitcomp "$(git xxx --git-completion-helper) ..." +# +# except that the output is cached. Accept 1-3 arguments: +# 1: the git command to execute, this is also the cache key +# 2: extra options to be added on top (e.g. negative forms) +# 3: options to be excluded +__gitcomp_builtin () +{ +	# spaces must be replaced with underscore for multi-word +	# commands, e.g. "git remote add" becomes remote_add. +	local cmd="$1" +	local incl="$2" +	local excl="$3" + +	local var=__gitcomp_builtin_"${cmd/-/_}" +	local options +	eval "options=\$$var" + +	if [ -z "$options" ]; then +		# leading and trailing spaces are significant to make +		# option removal work correctly. +		options=" $incl $(__git ${cmd/_/ } --git-completion-helper) " || return + +		for i in $excl; do +			options="${options/ $i / }" +		done +		eval "$var=\"$options\"" +	fi + +	__gitcomp "$options" +} +  # Variation of __gitcomp_nl () that appends to the existing list of  # completion candidates, COMPREPLY.  __gitcomp_nl_append () @@ -254,6 +435,24 @@ __gitcomp_nl ()  	__gitcomp_nl_append "$@"  } +# Fills the COMPREPLY array with prefiltered paths without any additional +# processing. +# Callers must take care of providing only paths that match the current path +# to be completed and adding any prefix path components, if necessary. +# 1: List of newline-separated matching paths, complete with all prefix +#    path components. +__gitcomp_file_direct () +{ +	local IFS=$'\n' + +	COMPREPLY=($1) + +	# use a hack to enable file mode in bash < 4 +	compopt -o filenames +o nospace 2>/dev/null || +	compgen -f /non-existing-dir/ >/dev/null || +	true +} +  # Generates completion reply with compgen from newline-separated possible  # completion filenames.  # It accepts 1 to 3 arguments: @@ -273,7 +472,8 @@ __gitcomp_file ()  	# use a hack to enable file mode in bash < 4  	compopt -o filenames +o nospace 2>/dev/null || -	compgen -f /non-existing-dir/ > /dev/null +	compgen -f /non-existing-dir/ >/dev/null || +	true  }  # Execute 'git ls-files', unless the --committable option is specified, in @@ -283,11 +483,13 @@ __gitcomp_file ()  __git_ls_files_helper ()  {  	if [ "$2" == "--committable" ]; then -		git -C "$1" diff-index --name-only --relative HEAD +		__git -C "$1" -c core.quotePath=false diff-index \ +			--name-only --relative HEAD -- "${3//\\/\\\\}*"  	else  		# NOTE: $2 is not quoted in order to support multiple options -		git -C "$1" ls-files --exclude-standard $2 -	fi 2>/dev/null +		__git -C "$1" -c core.quotePath=false ls-files \ +			--exclude-standard $2 -- "${3//\\/\\\\}*" +	fi  } @@ -297,101 +499,283 @@ __git_ls_files_helper ()  #    If provided, only files within the specified directory are listed.  #    Sub directories are never recursed.  Path must have a trailing  #    slash. +# 3: List only paths matching this path component (optional).  __git_index_files ()  { -	local dir="$(__gitdir)" root="${2-.}" file +	local root="$2" match="$3" -	if [ -d "$dir" ]; then -		__git_ls_files_helper "$root" "$1" | -		while read -r file; do -			case "$file" in -			?*/*) echo "${file%%/*}" ;; -			*) echo "$file" ;; -			esac -		done | sort | uniq -	fi +	__git_ls_files_helper "$root" "$1" "$match" | +	awk -F / -v pfx="${2//\\/\\\\}" '{ +		paths[$1] = 1 +	} +	END { +		for (p in paths) { +			if (substr(p, 1, 1) != "\"") { +				# No special characters, easy! +				print pfx p +				continue +			} + +			# The path is quoted. +			p = dequote(p) +			if (p == "") +				continue + +			# Even when a directory name itself does not contain +			# any special characters, it will still be quoted if +			# any of its (stripped) trailing path components do. +			# Because of this we may have seen the same direcory +			# both quoted and unquoted. +			if (p in paths) +				# We have seen the same directory unquoted, +				# skip it. +				continue +			else +				print pfx p +		} +	} +	function dequote(p,    bs_idx, out, esc, esc_idx, dec) { +		# Skip opening double quote. +		p = substr(p, 2) + +		# Interpret backslash escape sequences. +		while ((bs_idx = index(p, "\\")) != 0) { +			out = out substr(p, 1, bs_idx - 1) +			esc = substr(p, bs_idx + 1, 1) +			p = substr(p, bs_idx + 2) + +			if ((esc_idx = index("abtvfr\"\\", esc)) != 0) { +				# C-style one-character escape sequence. +				out = out substr("\a\b\t\v\f\r\"\\", +						 esc_idx, 1) +			} else if (esc == "n") { +				# Uh-oh, a newline character. +				# We cant reliably put a pathname +				# containing a newline into COMPREPLY, +				# and the newline would create a mess. +				# Skip this path. +				return "" +			} else { +				# Must be a \nnn octal value, then. +				dec = esc             * 64 + \ +				      substr(p, 1, 1) * 8  + \ +				      substr(p, 2, 1) +				out = out sprintf("%c", dec) +				p = substr(p, 3) +			} +		} +		# Drop closing double quote, if there is one. +		# (There isnt any if this is a directory, as it was +		# already stripped with the trailing path components.) +		if (substr(p, length(p), 1) == "\"") +			out = out substr(p, 1, length(p) - 1) +		else +			out = out p + +		return out +	}'  } +# __git_complete_index_file requires 1 argument: +# 1: the options to pass to ls-file +# +# The exception is --committable, which finds the files appropriate commit. +__git_complete_index_file () +{ +	local dequoted_word pfx="" cur_ + +	__git_dequote "$cur" + +	case "$dequoted_word" in +	?*/*) +		pfx="${dequoted_word%/*}/" +		cur_="${dequoted_word##*/}" +		;; +	*) +		cur_="$dequoted_word" +	esac + +	__gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")" +} + +# Lists branches from the local repository. +# 1: A prefix to be added to each listed branch (optional). +# 2: List only branches matching this word (optional; list all branches if +#    unset or empty). +# 3: A suffix to be appended to each listed branch (optional).  __git_heads ()  { -	local dir="$(__gitdir)" -	if [ -d "$dir" ]; then -		git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ -			refs/heads -		return -	fi +	local pfx="${1-}" cur_="${2-}" sfx="${3-}" + +	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ +			"refs/heads/$cur_*" "refs/heads/$cur_*/**"  } +# Lists tags from the local repository. +# Accepts the same positional parameters as __git_heads() above.  __git_tags ()  { -	local dir="$(__gitdir)" -	if [ -d "$dir" ]; then -		git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ -			refs/tags -		return -	fi +	local pfx="${1-}" cur_="${2-}" sfx="${3-}" + +	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ +			"refs/tags/$cur_*" "refs/tags/$cur_*/**"  } -# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments -# presence of 2nd argument means use the guess heuristic employed -# by checkout for tracking branches +# Lists refs from the local (by default) or from a remote repository. +# It accepts 0, 1 or 2 arguments: +# 1: The remote to list refs from (optional; ignored, if set but empty). +#    Can be the name of a configured remote, a path, or a URL. +# 2: In addition to local refs, list unique branches from refs/remotes/ for +#    'git checkout's tracking DWIMery (optional; ignored, if set but empty). +# 3: A prefix to be added to each listed ref (optional). +# 4: List only refs matching this word (optional; list all refs if unset or +#    empty). +# 5: A suffix to be appended to each listed ref (optional; ignored, if set +#    but empty). +# +# Use __git_complete_refs() instead.  __git_refs ()  { -	local i hash dir="$(__gitdir "${1-}")" track="${2-}" +	local i hash dir track="${2-}" +	local list_refs_from=path remote="${1-}"  	local format refs -	if [ -d "$dir" ]; then -		case "$cur" in +	local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}" +	local match="${4-}" +	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers + +	__git_find_repo_path +	dir="$__git_repo_path" + +	if [ -z "$remote" ]; then +		if [ -z "$dir" ]; then +			return +		fi +	else +		if __git_is_configured_remote "$remote"; then +			# configured remote takes precedence over a +			# local directory with the same name +			list_refs_from=remote +		elif [ -d "$remote/.git" ]; then +			dir="$remote/.git" +		elif [ -d "$remote" ]; then +			dir="$remote" +		else +			list_refs_from=url +		fi +	fi + +	if [ "$list_refs_from" = path ]; then +		if [[ "$cur_" == ^* ]]; then +			pfx="$pfx^" +			fer_pfx="$fer_pfx^" +			cur_=${cur_#^} +			match=${match#^} +		fi +		case "$cur_" in  		refs|refs/*)  			format="refname" -			refs="${cur%/*}" +			refs=("$match*" "$match*/**")  			track=""  			;;  		*) -			for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do -				if [ -e "$dir/$i" ]; then echo $i; fi +			for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD REBASE_HEAD; do +				case "$i" in +				$match*) +					if [ -e "$dir/$i" ]; then +						echo "$pfx$i$sfx" +					fi +					;; +				esac  			done -			format="refname:short" -			refs="refs/tags refs/heads refs/remotes" +			format="refname:strip=2" +			refs=("refs/tags/$match*" "refs/tags/$match*/**" +				"refs/heads/$match*" "refs/heads/$match*/**" +				"refs/remotes/$match*" "refs/remotes/$match*/**")  			;;  		esac -		git --git-dir="$dir" for-each-ref --format="%($format)" \ -			$refs +		__git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \ +			"${refs[@]}"  		if [ -n "$track" ]; then  			# employ the heuristic used by git checkout  			# Try to find a remote branch that matches the completion word  			# but only output if the branch name is unique -			local ref entry -			git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \ -				"refs/remotes/" | \ -			while read -r entry; do -				eval "$entry" -				ref="${ref#*/}" -				if [[ "$ref" == "$cur"* ]]; then -					echo "$ref" -				fi -			done | sort | uniq -u +			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ +				--sort="refname:strip=3" \ +				"refs/remotes/*/$match*" "refs/remotes/*/$match*/**" | \ +			uniq -u  		fi  		return  	fi -	case "$cur" in +	case "$cur_" in  	refs|refs/*) -		git ls-remote "$dir" "$cur*" 2>/dev/null | \ +		__git ls-remote "$remote" "$match*" | \  		while read -r hash i; do  			case "$i" in  			*^{}) ;; -			*) echo "$i" ;; +			*) echo "$pfx$i$sfx" ;;  			esac  		done  		;;  	*) -		echo "HEAD" -		git for-each-ref --format="%(refname:short)" -- \ -			"refs/remotes/$dir/" 2>/dev/null | sed -e "s#^$dir/##" +		if [ "$list_refs_from" = remote ]; then +			case "HEAD" in +			$match*)	echo "${pfx}HEAD$sfx" ;; +			esac +			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ +				"refs/remotes/$remote/$match*" \ +				"refs/remotes/$remote/$match*/**" +		else +			local query_symref +			case "HEAD" in +			$match*)	query_symref="HEAD" ;; +			esac +			__git ls-remote "$remote" $query_symref \ +				"refs/tags/$match*" "refs/heads/$match*" \ +				"refs/remotes/$match*" | +			while read -r hash i; do +				case "$i" in +				*^{})	;; +				refs/*)	echo "$pfx${i#refs/*/}$sfx" ;; +				*)	echo "$pfx$i$sfx" ;;  # symbolic refs +				esac +			done +		fi  		;;  	esac  } +# Completes refs, short and long, local and remote, symbolic and pseudo. +# +# Usage: __git_complete_refs [<option>]... +# --remote=<remote>: The remote to list refs from, can be the name of a +#                    configured remote, a path, or a URL. +# --track: List unique remote branches for 'git checkout's tracking DWIMery. +# --pfx=<prefix>: A prefix to be added to each ref. +# --cur=<word>: The current ref to be completed.  Defaults to the current +#               word to be completed. +# --sfx=<suffix>: A suffix to be appended to each ref instead of the default +#                 space. +__git_complete_refs () +{ +	local remote track pfx cur_="$cur" sfx=" " + +	while test $# != 0; do +		case "$1" in +		--remote=*)	remote="${1##--remote=}" ;; +		--track)	track="yes" ;; +		--pfx=*)	pfx="${1##--pfx=}" ;; +		--cur=*)	cur_="${1##--cur=}" ;; +		--sfx=*)	sfx="${1##--sfx=}" ;; +		*)		return 1 ;; +		esac +		shift +	done + +	__gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")" +} +  # __git_refs2 requires 1 argument (to pass to __git_refs) +# Deprecated: use __git_complete_fetch_refspecs() instead.  __git_refs2 ()  {  	local i @@ -400,11 +784,29 @@ __git_refs2 ()  	done  } +# Completes refspecs for fetching from a remote repository. +# 1: The remote repository. +# 2: A prefix to be added to each listed refspec (optional). +# 3: The ref to be completed as a refspec instead of the current word to be +#    completed (optional) +# 4: A suffix to be appended to each listed refspec instead of the default +#    space (optional). +__git_complete_fetch_refspecs () +{ +	local i remote="$1" pfx="${2-}" cur_="${3-$cur}" sfx="${4- }" + +	__gitcomp_direct "$( +		for i in $(__git_refs "$remote" "" "" "$cur_") ; do +			echo "$pfx$i:$i$sfx" +		done +		)" +} +  # __git_refs_remotes requires 1 argument (to pass to ls-remote)  __git_refs_remotes ()  {  	local i hash -	git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \ +	__git ls-remote "$1" 'refs/heads/*' | \  	while read -r hash i; do  		echo "$i:refs/remotes/$1/${i#refs/heads/}"  	done @@ -412,14 +814,26 @@ __git_refs_remotes ()  __git_remotes ()  { -	local d="$(__gitdir)" -	test -d "$d/remotes" && ls -1 "$d/remotes" -	git --git-dir="$d" remote +	__git_find_repo_path +	test -d "$__git_repo_path/remotes" && ls -1 "$__git_repo_path/remotes" +	__git remote +} + +# Returns true if $1 matches the name of a configured remote, false otherwise. +__git_is_configured_remote () +{ +	local remote +	for remote in $(__git_remotes); do +		if [ "$remote" = "$1" ]; then +			return 0 +		fi +	done +	return 1  }  __git_list_merge_strategies ()  { -	git merge -s help 2>&1 | +	LANG=C LC_ALL=C git merge -s help 2>&1 |  	sed -n -e '/[Aa]vailable strategies are: /,/^$/{  		s/\.$//  		s/.*:// @@ -441,9 +855,14 @@ __git_compute_merge_strategies ()  	__git_merge_strategies=$(__git_list_merge_strategies)  } +__git_merge_strategy_options="ours theirs subtree subtree= patience +	histogram diff-algorithm= ignore-space-change ignore-all-space +	ignore-space-at-eol renormalize no-renormalize no-renames +	find-renames find-renames= rename-threshold=" +  __git_complete_revlist_file ()  { -	local pfx ls ref cur_="$cur" +	local dequoted_word pfx ls ref cur_="$cur"  	case "$cur_" in  	*..?*:*)  		return @@ -451,14 +870,18 @@ __git_complete_revlist_file ()  	?*:*)  		ref="${cur_%%:*}"  		cur_="${cur_#*:}" -		case "$cur_" in + +		__git_dequote "$cur_" + +		case "$dequoted_word" in  		?*/*) -			pfx="${cur_%/*}" -			cur_="${cur_##*/}" +			pfx="${dequoted_word%/*}" +			cur_="${dequoted_word##*/}"  			ls="$ref:$pfx"  			pfx="$pfx/"  			;;  		*) +			cur_="$dequoted_word"  			ls="$ref"  			;;  		esac @@ -468,56 +891,25 @@ __git_complete_revlist_file ()  		*)   pfx="$ref:$pfx" ;;  		esac -		__gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \ -				| sed '/^100... blob /{ -				           s,^.*	,, -				           s,$, , -				       } -				       /^120000 blob /{ -				           s,^.*	,, -				           s,$, , -				       } -				       /^040000 tree /{ -				           s,^.*	,, -				           s,$,/, -				       } -				       s/^.*	//')" \ -			"$pfx" "$cur_" "" +		__gitcomp_file "$(__git ls-tree "$ls" \ +				| sed 's/^.*	// +				       s/$//')" \ +			"$pfx" "$cur_"  		;;  	*...*)  		pfx="${cur_%...*}..."  		cur_="${cur_#*...}" -		__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" +		__git_complete_refs --pfx="$pfx" --cur="$cur_"  		;;  	*..*)  		pfx="${cur_%..*}.."  		cur_="${cur_#*..}" -		__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" +		__git_complete_refs --pfx="$pfx" --cur="$cur_"  		;;  	*) -		__gitcomp_nl "$(__git_refs)" -		;; -	esac -} - - -# __git_complete_index_file requires 1 argument: -# 1: the options to pass to ls-file -# -# The exception is --committable, which finds the files appropriate commit. -__git_complete_index_file () -{ -	local pfx="" cur_="$cur" - -	case "$cur_" in -	?*/*) -		pfx="${cur_%/*}" -		cur_="${cur_##*/}" -		pfx="${pfx}/" +		__git_complete_refs  		;;  	esac - -	__gitcomp_file "$(__git_index_files "$1" ${pfx:+"$pfx"})" "$pfx" "$cur_"  }  __git_complete_file () @@ -541,6 +933,7 @@ __git_complete_remote_or_refspec ()  		i="${words[c]}"  		case "$i" in  		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;; +		-d|--delete) [ "$cmd" = "push" ] && lhs=0 ;;  		--all)  			case "$cmd" in  			push) no_complete_refspec=1 ;; @@ -550,6 +943,7 @@ __git_complete_remote_or_refspec ()  			*) ;;  			esac  			;; +		--multiple) no_complete_refspec=1; break ;;  		-*) ;;  		*) remote="$i"; break ;;  		esac @@ -580,23 +974,23 @@ __git_complete_remote_or_refspec ()  	case "$cmd" in  	fetch)  		if [ $lhs = 1 ]; then -			__gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_" +			__git_complete_fetch_refspecs "$remote" "$pfx" "$cur_"  		else -			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" +			__git_complete_refs --pfx="$pfx" --cur="$cur_"  		fi  		;;  	pull|remote)  		if [ $lhs = 1 ]; then -			__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" +			__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"  		else -			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" +			__git_complete_refs --pfx="$pfx" --cur="$cur_"  		fi  		;;  	push)  		if [ $lhs = 1 ]; then -			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" +			__git_complete_refs --pfx="$pfx" --cur="$cur_"  		else -			__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" +			__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"  		fi  		;;  	esac @@ -609,136 +1003,30 @@ __git_complete_strategy ()  	-s|--strategy)  		__gitcomp "$__git_merge_strategies"  		return 0 +		;; +	-X) +		__gitcomp "$__git_merge_strategy_options" +		return 0 +		;;  	esac  	case "$cur" in  	--strategy=*)  		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"  		return 0  		;; +	--strategy-option=*) +		__gitcomp "$__git_merge_strategy_options" "" "${cur##--strategy-option=}" +		return 0 +		;;  	esac  	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 () -{ -	local i IFS=" "$'\n' -	for i in $(__git_commands) -	do -		case $i in -		*--*)             : helper pattern;; -		*) echo $i;; -		esac -	done -} -  __git_all_commands=  __git_compute_all_commands ()  {  	test -n "$__git_all_commands" || -	__git_all_commands=$(__git_list_all_commands) -} - -__git_list_porcelain_commands () -{ -	local i IFS=" "$'\n' -	__git_compute_all_commands -	for i in $__git_all_commands -	do -		case $i in -		*--*)             : helper pattern;; -		applymbox)        : ask gittus;; -		applypatch)       : ask gittus;; -		archimport)       : import;; -		cat-file)         : plumbing;; -		check-attr)       : plumbing;; -		check-ignore)     : plumbing;; -		check-mailmap)    : plumbing;; -		check-ref-format) : plumbing;; -		checkout-index)   : plumbing;; -		column)           : internal helper;; -		commit-tree)      : plumbing;; -		count-objects)    : infrequent;; -		credential)       : credentials;; -		credential-*)     : credentials helper;; -		cvsexportcommit)  : export;; -		cvsimport)        : import;; -		cvsserver)        : daemon;; -		daemon)           : daemon;; -		diff-files)       : plumbing;; -		diff-index)       : plumbing;; -		diff-tree)        : plumbing;; -		fast-import)      : import;; -		fast-export)      : export;; -		fsck-objects)     : plumbing;; -		fetch-pack)       : plumbing;; -		fmt-merge-msg)    : plumbing;; -		for-each-ref)     : plumbing;; -		hash-object)      : plumbing;; -		http-*)           : transport;; -		index-pack)       : plumbing;; -		init-db)          : deprecated;; -		local-fetch)      : plumbing;; -		ls-files)         : plumbing;; -		ls-remote)        : plumbing;; -		ls-tree)          : plumbing;; -		mailinfo)         : plumbing;; -		mailsplit)        : plumbing;; -		merge-*)          : plumbing;; -		mktree)           : plumbing;; -		mktag)            : plumbing;; -		pack-objects)     : plumbing;; -		pack-redundant)   : plumbing;; -		pack-refs)        : plumbing;; -		parse-remote)     : plumbing;; -		patch-id)         : plumbing;; -		prune)            : plumbing;; -		prune-packed)     : plumbing;; -		quiltimport)      : import;; -		read-tree)        : plumbing;; -		receive-pack)     : plumbing;; -		remote-*)         : transport;; -		rerere)           : plumbing;; -		rev-list)         : plumbing;; -		rev-parse)        : plumbing;; -		runstatus)        : plumbing;; -		sh-setup)         : internal;; -		shell)            : daemon;; -		show-ref)         : plumbing;; -		send-pack)        : plumbing;; -		show-index)       : plumbing;; -		ssh-*)            : transport;; -		stripspace)       : plumbing;; -		symbolic-ref)     : plumbing;; -		unpack-file)      : plumbing;; -		unpack-objects)   : plumbing;; -		update-index)     : plumbing;; -		update-ref)       : plumbing;; -		update-server-info) : daemon;; -		upload-archive)   : plumbing;; -		upload-pack)      : plumbing;; -		write-tree)       : plumbing;; -		var)              : infrequent;; -		verify-pack)      : infrequent;; -		verify-tag)       : plumbing;; -		*) echo $i;; -		esac -	done -} - -__git_porcelain_commands= -__git_compute_porcelain_commands () -{ -	test -n "$__git_porcelain_commands" || -	__git_porcelain_commands=$(__git_list_porcelain_commands) +	__git_all_commands=$(__git --list-cmds=main,others,alias,nohelpers)  }  # Lists all set config variables starting with the given section prefix, @@ -746,7 +1034,7 @@ __git_compute_porcelain_commands ()  __git_get_config_variables ()  {  	local section="$1" i IFS=$'\n' -	for i in $(git --git-dir="$(__gitdir)" config --name-only --get-regexp "^$section\..*" 2>/dev/null); do +	for i in $(__git config --name-only --get-regexp "^$section\..*"); do  		echo "${i#$section.}"  	done  } @@ -756,16 +1044,10 @@ __git_pretty_aliases ()  	__git_get_config_variables "pretty"  } -__git_aliases () -{ -	__git_get_config_variables "alias" -} -  # __git_aliased_command requires 1 argument  __git_aliased_command ()  { -	local word cmdline=$(git --git-dir="$(__gitdir)" \ -		config --get "alias.$1") +	local word cmdline=$(__git config --get "alias.$1")  	for word in $cmdline; do  		case "$word" in  		\!gitk|gitk) @@ -803,6 +1085,50 @@ __git_find_on_cmdline ()  	done  } +# Echo the value of an option set on the command line or config +# +# $1: short option name +# $2: long option name including = +# $3: list of possible values +# $4: config string (optional) +# +# example: +# result="$(__git_get_option_value "-d" "--do-something=" \ +#     "yes no" "core.doSomething")" +# +# result is then either empty (no option set) or "yes" or "no" +# +# __git_get_option_value requires 3 arguments +__git_get_option_value () +{ +	local c short_opt long_opt val +	local result= values config_key word + +	short_opt="$1" +	long_opt="$2" +	values="$3" +	config_key="$4" + +	((c = $cword - 1)) +	while [ $c -ge 0 ]; do +		word="${words[c]}" +		for val in $values; do +			if [ "$short_opt$val" = "$word" ] || +			   [ "$long_opt$val"  = "$word" ]; then +				result="$val" +				break 2 +			fi +		done +		((c--)) +	done + +	if [ -n "$config_key" ] && [ -z "$result" ]; then +		result="$(__git config "$config_key")" +	fi + +	echo "$result" +} +  __git_has_doubledash ()  {  	local c=1 @@ -853,12 +1179,14 @@ __git_count_arguments ()  }  __git_whitespacelist="nowarn warn error error-all fix" +__git_patchformat="mbox stgit stgit-series hg mboxrd" +__git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"  _git_am ()  { -	local dir="$(__gitdir)" -	if [ -d "$dir"/rebase-apply ]; then -		__gitcomp "--skip --continue --resolved --abort" +	__git_find_repo_path +	if [ -d "$__git_repo_path"/rebase-apply ]; then +		__gitcomp "$__git_am_inprogress_options"  		return  	fi  	case "$cur" in @@ -866,13 +1194,13 @@ _git_am ()  		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"  		return  		;; +	--patch-format=*) +		__gitcomp "$__git_patchformat" "" "${cur##--patch-format=}" +		return +		;;  	--*) -		__gitcomp " -			--3way --committer-date-is-author-date --ignore-date -			--ignore-whitespace --ignore-space-change -			--interactive --keep --no-utf8 --signoff --utf8 -			--whitespace= --scissors -			" +		__gitcomp_builtin am "" \ +			"$__git_am_inprogress_options"  		return  	esac  } @@ -885,13 +1213,7 @@ _git_apply ()  		return  		;;  	--*) -		__gitcomp " -			--stat --numstat --summary --check --index -			--cached --index-info --reverse --reject --unidiff-zero -			--apply --no-add --exclude= -			--ignore-whitespace --ignore-space-change -			--whitespace= --inaccurate-eof --verbose -			" +		__gitcomp_builtin apply  		return  	esac  } @@ -899,16 +1221,21 @@ _git_apply ()  _git_add ()  {  	case "$cur" in +	--chmod=*) +		__gitcomp "+x -x" "" "${cur##--chmod=}" +		return +		;;  	--*) -		__gitcomp " -			--interactive --refresh --patch --update --dry-run -			--ignore-errors --intent-to-add -			" +		__gitcomp_builtin add  		return  	esac -	# XXX should we check for --update and --all options ? -	__git_complete_index_file "--others --modified --directory --no-empty-directory" +	local complete_opt="--others --modified --directory --no-empty-directory" +	if test -n "$(__git_find_on_cmdline "-u --update")" +	then +		complete_opt="--modified" +	fi +	__git_complete_index_file "$complete_opt"  }  _git_archive () @@ -925,7 +1252,7 @@ _git_archive ()  	--*)  		__gitcomp "  			--format= --list --verbose -			--prefix= --remote= --exec= +			--prefix= --remote= --exec= --output  			"  		return  		;; @@ -940,7 +1267,8 @@ _git_bisect ()  	local subcommands="start bad good skip reset visualize replay log run"  	local subcommand="$(__git_find_on_cmdline "$subcommands")"  	if [ -z "$subcommand" ]; then -		if [ -f "$(__gitdir)"/BISECT_START ]; then +		__git_find_repo_path +		if [ -f "$__git_repo_path"/BISECT_START ]; then  			__gitcomp "$subcommands"  		else  			__gitcomp "replay start" @@ -950,13 +1278,15 @@ _git_bisect ()  	case "$subcommand" in  	bad|good|reset|skip|start) -		__gitcomp_nl "$(__git_refs)" +		__git_complete_refs  		;;  	*)  		;;  	esac  } +__git_ref_fieldlist="refname objecttype objectsize objectname upstream push HEAD symref" +  _git_branch ()  {  	local i c=1 only_local_ref="n" has_r="n" @@ -964,29 +1294,24 @@ _git_branch ()  	while [ $c -lt $cword ]; do  		i="${words[c]}"  		case "$i" in -		-d|-m)	only_local_ref="y" ;; -		-r)	has_r="y" ;; +		-d|--delete|-m|--move)	only_local_ref="y" ;; +		-r|--remotes)		has_r="y" ;;  		esac  		((c++))  	done  	case "$cur" in  	--set-upstream-to=*) -		__gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}" +		__git_complete_refs --cur="${cur##--set-upstream-to=}"  		;;  	--*) -		__gitcomp " -			--color --no-color --verbose --abbrev= --no-abbrev -			--track --no-track --contains --merged --no-merged -			--set-upstream-to= --edit-description --list -			--unset-upstream -			" +		__gitcomp_builtin branch  		;;  	*)  		if [ $only_local_ref = "y" -a $has_r = "n" ]; then -			__gitcomp_nl "$(__git_heads)" +			__gitcomp_direct "$(__git_heads "" "$cur" " ")"  		else -			__gitcomp_nl "$(__git_refs)" +			__git_complete_refs  		fi  		;;  	esac @@ -1021,41 +1346,40 @@ _git_checkout ()  		__gitcomp "diff3 merge" "" "${cur##--conflict=}"  		;;  	--*) -		__gitcomp " -			--quiet --ours --theirs --track --no-track --merge -			--conflict= --orphan --patch -			" +		__gitcomp_builtin checkout  		;;  	*)  		# check if --track, --no-track, or --no-guess was specified  		# if so, disable DWIM mode -		local flags="--track --no-track --no-guess" track=1 -		if [ -n "$(__git_find_on_cmdline "$flags")" ]; then -			track='' +		local flags="--track --no-track --no-guess" track_opt="--track" +		if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] || +		   [ -n "$(__git_find_on_cmdline "$flags")" ]; then +			track_opt=''  		fi -		__gitcomp_nl "$(__git_refs '' $track)" +		__git_complete_refs $track_opt  		;;  	esac  } -_git_cherry () -{ -	__gitcomp_nl "$(__git_refs)" -} +__git_cherry_pick_inprogress_options="--continue --quit --abort"  _git_cherry_pick ()  { -	local dir="$(__gitdir)" -	if [ -f "$dir"/CHERRY_PICK_HEAD ]; then -		__gitcomp "--continue --quit --abort" +	__git_find_repo_path +	if [ -f "$__git_repo_path"/CHERRY_PICK_HEAD ]; then +		__gitcomp "$__git_cherry_pick_inprogress_options"  		return  	fi + +	__git_complete_strategy && return +  	case "$cur" in  	--*) -		__gitcomp "--edit --no-commit --signoff --strategy= --mainline" +		__gitcomp_builtin cherry-pick "" \ +			"$__git_cherry_pick_inprogress_options"  		;;  	*) -		__gitcomp_nl "$(__git_refs)" +		__git_complete_refs  		;;  	esac  } @@ -1064,7 +1388,7 @@ _git_clean ()  {  	case "$cur" in  	--*) -		__gitcomp "--dry-run --quiet" +		__gitcomp_builtin clean  		return  		;;  	esac @@ -1077,32 +1401,19 @@ _git_clone ()  {  	case "$cur" in  	--*) -		__gitcomp " -			--local -			--no-hardlinks -			--shared -			--reference -			--quiet -			--no-checkout -			--bare -			--mirror -			--origin -			--upload-pack -			--template= -			--depth -			--single-branch -			--branch -			" +		__gitcomp_builtin clone  		return  		;;  	esac  } +__git_untracked_file_modes="all no normal" +  _git_commit ()  {  	case "$prev" in  	-c|-C) -		__gitcomp_nl "$(__git_refs)" "" "${cur}" +		__git_complete_refs  		return  		;;  	esac @@ -1115,27 +1426,19 @@ _git_commit ()  		;;  	--reuse-message=*|--reedit-message=*|\  	--fixup=*|--squash=*) -		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}" +		__git_complete_refs --cur="${cur#*=}"  		return  		;;  	--untracked-files=*) -		__gitcomp "all no normal" "" "${cur##--untracked-files=}" +		__gitcomp "$__git_untracked_file_modes" "" "${cur##--untracked-files=}"  		return  		;;  	--*) -		__gitcomp " -			--all --author= --signoff --verify --no-verify -			--edit --no-edit -			--amend --include --only --interactive -			--dry-run --reuse-message= --reedit-message= -			--reset-author --file= --message= --template= -			--cleanup= --untracked-files --untracked-files= -			--verbose --quiet --fixup= --squash= -			" +		__gitcomp_builtin commit  		return  	esac -	if git rev-parse --verify --quiet HEAD >/dev/null; then +	if __git rev-parse --verify --quiet HEAD >/dev/null; then  		__git_complete_index_file "--committable"  	else  		# This is the first commit @@ -1147,22 +1450,21 @@ _git_describe ()  {  	case "$cur" in  	--*) -		__gitcomp " -			--all --tags --contains --abbrev= --candidates= -			--exact-match --debug --long --match --always -			" +		__gitcomp_builtin describe  		return  	esac -	__gitcomp_nl "$(__git_refs)" +	__git_complete_refs  }  __git_diff_algorithms="myers minimal patience histogram" +__git_diff_submodule_formats="diff log short" +  __git_diff_common_options="--stat --numstat --shortstat --summary  			--patch-with-stat --name-only --name-status --color  			--no-color --color-words --no-renames --check  			--full-index --binary --abbrev --diff-filter= -			--find-copies-harder +			--find-copies-harder --ignore-cr-at-eol  			--text --ignore-space-at-eol --ignore-space-change  			--ignore-all-space --ignore-blank-lines --exit-code  			--quiet --ext-diff --no-ext-diff @@ -1173,6 +1475,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary  			--dirstat --dirstat= --dirstat-by-file  			--dirstat-by-file= --cumulative  			--diff-algorithm= +			--submodule --submodule= --ignore-submodules  "  _git_diff () @@ -1184,6 +1487,10 @@ _git_diff ()  		__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"  		return  		;; +	--submodule=*) +		__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}" +		return +		;;  	--*)  		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex  			--base --ours --theirs --no-index @@ -1196,7 +1503,8 @@ _git_diff ()  }  __git_mergetools_common="diffuse diffmerge ecmerge emerge kdiff3 meld opendiff -			tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc codecompare +			tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc +			codecompare smerge  "  _git_difftool () @@ -1209,11 +1517,11 @@ _git_difftool ()  		return  		;;  	--*) -		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex -			--base --ours --theirs -			--no-renames --diff-filter= --find-copies-harder -			--relative --ignore-submodules -			--tool=" +		__gitcomp_builtin difftool "$__git_diff_common_options +					--base --cached --ours --theirs +					--pickaxe-all --pickaxe-regex +					--relative --staged +					"  		return  		;;  	esac @@ -1222,11 +1530,6 @@ _git_difftool ()  __git_fetch_recurse_submodules="yes on-demand no" -__git_fetch_options=" -	--quiet --verbose --append --upload-pack --force --keep --depth= -	--tags --no-tags --all --prune --dry-run --recurse-submodules= -" -  _git_fetch ()  {  	case "$cur" in @@ -1234,21 +1537,21 @@ _git_fetch ()  		__gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}"  		return  		;; +	--filter=*) +		__gitcomp "blob:none blob:limit= sparse:oid=" "" "${cur##--filter=}" +		return +		;;  	--*) -		__gitcomp "$__git_fetch_options" +		__gitcomp_builtin fetch  		return  		;;  	esac  	__git_complete_remote_or_refspec  } -__git_format_patch_options=" -	--stdout --attach --no-attach --thread --thread= --no-thread -	--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= -	--output-directory --reroll-count --to= --quiet --notes +__git_format_patch_extra_options=" +	--full-index --not --all --no-prefix --src-prefix= +	--dst-prefix= --notes  "  _git_format_patch () @@ -1261,7 +1564,7 @@ _git_format_patch ()  		return  		;;  	--*) -		__gitcomp "$__git_format_patch_options" +		__gitcomp_builtin format-patch "$__git_format_patch_extra_options"  		return  		;;  	esac @@ -1272,20 +1575,7 @@ _git_fsck ()  {  	case "$cur" in  	--*) -		__gitcomp " -			--tags --root --unreachable --cache --no-reflogs --full -			--strict --verbose --lost-found -			" -		return -		;; -	esac -} - -_git_gc () -{ -	case "$cur" in -	--*) -		__gitcomp "--prune --aggressive" +		__gitcomp_builtin fsck  		return  		;;  	esac @@ -1296,8 +1586,43 @@ _git_gitk ()  	_gitk  } -__git_match_ctag() { -	awk "/^${1//\//\\/}/ { print \$1 }" "$2" +# Lists matching symbol names from a tag (as in ctags) file. +# 1: List symbol names matching this word. +# 2: The tag file to list symbol names from. +# 3: A prefix to be added to each listed symbol name (optional). +# 4: A suffix to be appended to each listed symbol name (optional). +__git_match_ctag () { +	awk -v pfx="${3-}" -v sfx="${4-}" " +		/^${1//\//\\/}/ { print pfx \$1 sfx } +		" "$2" +} + +# Complete symbol names from a tag file. +# Usage: __git_complete_symbol [<option>]... +# --tags=<file>: The tag file to list symbol names from instead of the +#                default "tags". +# --pfx=<prefix>: A prefix to be added to each symbol name. +# --cur=<word>: The current symbol name to be completed.  Defaults to +#               the current word to be completed. +# --sfx=<suffix>: A suffix to be appended to each symbol name instead +#                 of the default space. +__git_complete_symbol () { +	local tags=tags pfx="" cur_="${cur-}" sfx=" " + +	while test $# != 0; do +		case "$1" in +		--tags=*)	tags="${1##--tags=}" ;; +		--pfx=*)	pfx="${1##--pfx=}" ;; +		--cur=*)	cur_="${1##--cur=}" ;; +		--sfx=*)	sfx="${1##--sfx=}" ;; +		*)		return 1 ;; +		esac +		shift +	done + +	if test -r "$tags"; then +		__gitcomp_direct "$(__git_match_ctag "$cur_" "$tags" "$pfx" "$sfx")" +	fi  }  _git_grep () @@ -1306,50 +1631,34 @@ _git_grep ()  	case "$cur" in  	--*) -		__gitcomp " -			--cached -			--text --ignore-case --word-regexp --invert-match -			--full-name --line-number -			--extended-regexp --basic-regexp --fixed-strings -			--perl-regexp -			--threads -			--files-with-matches --name-only -			--files-without-match -			--max-depth -			--count -			--and --or --not --all-match -			" +		__gitcomp_builtin grep  		return  		;;  	esac  	case "$cword,$prev" in  	2,*|*,-*) -		if test -r tags; then -			__gitcomp_nl "$(__git_match_ctag "$cur" tags)" -			return -		fi +		__git_complete_symbol && return  		;;  	esac -	__gitcomp_nl "$(__git_refs)" +	__git_complete_refs  }  _git_help ()  {  	case "$cur" in  	--*) -		__gitcomp "--all --info --man --web" +		__gitcomp_builtin help  		return  		;;  	esac -	__git_compute_all_commands -	__gitcomp "$__git_all_commands $(__git_aliases) -		attributes cli core-tutorial cvs-migration -		diffcore gitk glossary hooks ignore modules -		namespaces repository-layout tutorial tutorial-2 -		workflows -		" +	if test -n "$GIT_TESTING_ALL_COMMAND_LIST" +	then +		__gitcomp "$GIT_TESTING_ALL_COMMAND_LIST $(__git --list-cmds=alias,list-guide) gitk" +	else +		__gitcomp "$(__git --list-cmds=main,nohelpers,alias,list-guide) gitk" +	fi  }  _git_init () @@ -1362,7 +1671,7 @@ _git_init ()  		return  		;;  	--*) -		__gitcomp "--quiet --bare --template= --shared --shared=" +		__gitcomp_builtin init  		return  		;;  	esac @@ -1372,13 +1681,7 @@ _git_ls_files ()  {  	case "$cur" in  	--*) -		__gitcomp "--cached --deleted --modified --others --ignored -			--stage --directory --no-empty-directory --unmerged -			--killed --exclude= --exclude-from= -			--exclude-per-directory= --exclude-standard -			--error-unmatch --with-tree= --full-name -			--abbrev --ignored --exclude-per-directory -			" +		__gitcomp_builtin ls-files  		return  		;;  	esac @@ -1390,11 +1693,24 @@ _git_ls_files ()  _git_ls_remote ()  { +	case "$cur" in +	--*) +		__gitcomp_builtin ls-remote +		return +		;; +	esac  	__gitcomp_nl "$(__git_remotes)"  }  _git_ls_tree ()  { +	case "$cur" in +	--*) +		__gitcomp_builtin ls-tree +		return +		;; +	esac +  	__git_complete_file  } @@ -1421,18 +1737,31 @@ __git_log_shortlog_options="  	--all-match --invert-grep  " -__git_log_pretty_formats="oneline short medium full fuller email raw format:" -__git_log_date_formats="relative iso8601 rfc2822 short local default raw" +__git_log_pretty_formats="oneline short medium full fuller email raw format: mboxrd" +__git_log_date_formats="relative iso8601 iso8601-strict rfc2822 short local default raw unix format:"  _git_log ()  {  	__git_has_doubledash && return +	__git_find_repo_path -	local g="$(git rev-parse --git-dir 2>/dev/null)"  	local merge="" -	if [ -f "$g/MERGE_HEAD" ]; then +	if [ -f "$__git_repo_path/MERGE_HEAD" ]; then  		merge="--merge"  	fi +	case "$prev,$cur" in +	-L,:*:*) +		return	# fall back to Bash filename completion +		;; +	-L,:*) +		__git_complete_symbol --cur="${cur#:}" --sfx=":" +		return +		;; +	-G,*|-S,*) +		__git_complete_symbol +		return +		;; +	esac  	case "$cur" in  	--pretty=*|--format=*)  		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) @@ -1447,6 +1776,14 @@ _git_log ()  		__gitcomp "full short no" "" "${cur##--decorate=}"  		return  		;; +	--diff-algorithm=*) +		__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" +		return +		;; +	--submodule=*) +		__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}" +		return +		;;  	--*)  		__gitcomp "  			$__git_log_common_options @@ -1458,6 +1795,7 @@ _git_log ()  			--relative-date --date=  			--pretty= --format= --oneline  			--show-signature +			--cherry-mark  			--cherry-pick  			--graph  			--decorate --decorate= @@ -1469,29 +1807,35 @@ _git_log ()  			"  		return  		;; +	-L:*:*) +		return	# fall back to Bash filename completion +		;; +	-L:*) +		__git_complete_symbol --cur="${cur#-L:}" --sfx=":" +		return +		;; +	-G*) +		__git_complete_symbol --pfx="-G" --cur="${cur#-G}" +		return +		;; +	-S*) +		__git_complete_symbol --pfx="-S" --cur="${cur#-S}" +		return +		;;  	esac  	__git_complete_revlist  } -# Common merge options shared by git-merge(1) and git-pull(1). -__git_merge_options=" -	--no-commit --no-stat --log --no-log --squash --strategy -	--commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit -	--verify-signatures --no-verify-signatures --gpg-sign -	--quiet --verbose --progress --no-progress -" -  _git_merge ()  {  	__git_complete_strategy && return  	case "$cur" in  	--*) -		__gitcomp "$__git_merge_options -			--rerere-autoupdate --no-rerere-autoupdate --abort" +		__gitcomp_builtin merge  		return  	esac -	__gitcomp_nl "$(__git_refs)" +	__git_complete_refs  }  _git_mergetool () @@ -1502,7 +1846,7 @@ _git_mergetool ()  		return  		;;  	--*) -		__gitcomp "--tool=" +		__gitcomp "--tool= --prompt --no-prompt --gui --no-gui"  		return  		;;  	esac @@ -1512,18 +1856,18 @@ _git_merge_base ()  {  	case "$cur" in  	--*) -		__gitcomp "--octopus --independent --is-ancestor --fork-point" +		__gitcomp_builtin merge-base  		return  		;;  	esac -	__gitcomp_nl "$(__git_refs)" +	__git_complete_refs  }  _git_mv ()  {  	case "$cur" in  	--*) -		__gitcomp "--dry-run" +		__gitcomp_builtin mv  		return  		;;  	esac @@ -1537,52 +1881,40 @@ _git_mv ()  	fi  } -_git_name_rev () -{ -	__gitcomp "--tags --all --stdin" -} -  _git_notes ()  { -	local subcommands='add append copy edit list prune remove show' +	local subcommands='add append copy edit get-ref list merge prune remove show'  	local subcommand="$(__git_find_on_cmdline "$subcommands")"  	case "$subcommand,$cur" in  	,--*) -		__gitcomp '--ref' +		__gitcomp_builtin notes  		;;  	,*)  		case "$prev" in  		--ref) -			__gitcomp_nl "$(__git_refs)" +			__git_complete_refs  			;;  		*)  			__gitcomp "$subcommands --ref"  			;;  		esac  		;; -	add,--reuse-message=*|append,--reuse-message=*|\ -	add,--reedit-message=*|append,--reedit-message=*) -		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}" -		;; -	add,--*|append,--*) -		__gitcomp '--file= --message= --reedit-message= -				--reuse-message=' +	*,--reuse-message=*|*,--reedit-message=*) +		__git_complete_refs --cur="${cur#*=}"  		;; -	copy,--*) -		__gitcomp '--stdin' +	*,--*) +		__gitcomp_builtin notes_$subcommand  		;; -	prune,--*) -		__gitcomp '--dry-run --verbose' -		;; -	prune,*) +	prune,*|get-ref,*) +		# this command does not take a ref, do not complete it  		;;  	*)  		case "$prev" in  		-m|-F)  			;;  		*) -			__gitcomp_nl "$(__git_refs)" +			__git_complete_refs  			;;  		esac  		;; @@ -1599,18 +1931,15 @@ _git_pull ()  		return  		;;  	--*) -		__gitcomp " -			--rebase --no-rebase -			$__git_merge_options -			$__git_fetch_options -		" +		__gitcomp_builtin pull +  		return  		;;  	esac  	__git_complete_remote_or_refspec  } -__git_push_recurse_submodules="check on-demand" +__git_push_recurse_submodules="check on-demand only"  __git_complete_force_with_lease ()  { @@ -1620,10 +1949,10 @@ __git_complete_force_with_lease ()  	--*=)  		;;  	*:*) -		__gitcomp_nl "$(__git_refs)" "" "${cur_#*:}" +		__git_complete_refs --cur="${cur_#*:}"  		;;  	*) -		__gitcomp_nl "$(__git_refs)" "" "$cur_" +		__git_complete_refs --cur="$cur_"  		;;  	esac  } @@ -1654,26 +1983,36 @@ _git_push ()  		return  		;;  	--*) +		__gitcomp_builtin push +		return +		;; +	esac +	__git_complete_remote_or_refspec +} + +_git_range_diff () +{ +	case "$cur" in +	--*)  		__gitcomp " -			--all --mirror --tags --dry-run --force --verbose -			--quiet --prune --delete --follow-tags -			--receive-pack= --repo= --set-upstream -			--force-with-lease --force-with-lease= --recurse-submodules= +			--creation-factor= --no-dual-color +			$__git_diff_common_options  		"  		return  		;;  	esac -	__git_complete_remote_or_refspec +	__git_complete_revlist  }  _git_rebase ()  { -	local dir="$(__gitdir)" -	if [ -f "$dir"/rebase-merge/interactive ]; then -		__gitcomp "--continue --skip --abort --edit-todo" +	__git_find_repo_path +	if [ -f "$__git_repo_path"/rebase-merge/interactive ]; then +		__gitcomp "--continue --skip --abort --quit --edit-todo --show-current-patch"  		return -	elif [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then -		__gitcomp "--continue --skip --abort" +	elif [ -d "$__git_repo_path"/rebase-apply ] || \ +	     [ -d "$__git_repo_path"/rebase-merge ]; then +		__gitcomp "--continue --skip --abort --quit --show-current-patch"  		return  	fi  	__git_complete_strategy && return @@ -1685,7 +2024,7 @@ _git_rebase ()  	--*)  		__gitcomp "  			--onto --merge --strategy --interactive -			--preserve-merges --stat --no-stat +			--rebase-merges --preserve-merges --stat --no-stat  			--committer-date-is-author-date --ignore-date  			--ignore-whitespace --whitespace=  			--autosquash --no-autosquash @@ -1693,12 +2032,13 @@ _git_rebase ()  			--autostash --no-autostash  			--verify --no-verify  			--keep-empty --root --force-rebase --no-ff +			--rerere-autoupdate  			--exec  			"  		return  	esac -	__gitcomp_nl "$(__git_refs)" +	__git_complete_refs  }  _git_reflog () @@ -1709,7 +2049,7 @@ _git_reflog ()  	if [ -z "$subcommand" ]; then  		__gitcomp "$subcommands"  	else -		__gitcomp_nl "$(__git_refs)" +		__git_complete_refs  	fi  } @@ -1720,9 +2060,7 @@ _git_send_email ()  {  	case "$prev" in  	--to|--cc|--bcc|--from) -		__gitcomp " -		$(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null) -		" +		__gitcomp "$(__git send-email --dump-aliases)"  		return  		;;  	esac @@ -1752,22 +2090,20 @@ _git_send_email ()  		return  		;;  	--to=*|--cc=*|--bcc=*|--from=*) -		__gitcomp " -		$(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null) -		" "" "${cur#--*=}" +		__gitcomp "$(__git send-email --dump-aliases)" "" "${cur#--*=}"  		return  		;;  	--*) -		__gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to +		__gitcomp_builtin send-email "--annotate --bcc --cc --cc-cmd --chain-reply-to  			--compose --confirm= --dry-run --envelope-sender  			--from --identity  			--in-reply-to --no-chain-reply-to --no-signed-off-by-cc -			--no-suppress-from --no-thread --quiet +			--no-suppress-from --no-thread --quiet --reply-to  			--signed-off-by-cc --smtp-pass --smtp-server  			--smtp-server-port --smtp-encryption= --smtp-user  			--subject --suppress-cc= --suppress-from --thread --to  			--validate --no-validate -			$__git_format_patch_options" +			$__git_format_patch_extra_options"  		return  		;;  	esac @@ -1779,6 +2115,90 @@ _git_stage ()  	_git_add  } +_git_status () +{ +	local complete_opt +	local untracked_state + +	case "$cur" in +	--ignore-submodules=*) +		__gitcomp "none untracked dirty all" "" "${cur##--ignore-submodules=}" +		return +		;; +	--untracked-files=*) +		__gitcomp "$__git_untracked_file_modes" "" "${cur##--untracked-files=}" +		return +		;; +	--column=*) +		__gitcomp " +			always never auto column row plain dense nodense +			" "" "${cur##--column=}" +		return +		;; +	--*) +		__gitcomp_builtin status +		return +		;; +	esac + +	untracked_state="$(__git_get_option_value "-u" "--untracked-files=" \ +		"$__git_untracked_file_modes" "status.showUntrackedFiles")" + +	case "$untracked_state" in +	no) +		# --ignored option does not matter +		complete_opt= +		;; +	all|normal|*) +		complete_opt="--cached --directory --no-empty-directory --others" + +		if [ -n "$(__git_find_on_cmdline "--ignored")" ]; then +			complete_opt="$complete_opt --ignored --exclude=*" +		fi +		;; +	esac + +	__git_complete_index_file "$complete_opt" +} + +_git_switch () +{ +	case "$cur" in +	--conflict=*) +		__gitcomp "diff3 merge" "" "${cur##--conflict=}" +		;; +	--*) +		__gitcomp_builtin switch +		;; +	*) +		# check if --track, --no-track, or --no-guess was specified +		# if so, disable DWIM mode +		local track_opt="--track" only_local_ref=n +		if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] || +		   [ -n "$(__git_find_on_cmdline "--track --no-track --no-guess")" ]; then +			track_opt='' +		fi +		# explicit --guess enables DWIM mode regardless of +		# $GIT_COMPLETION_CHECKOUT_NO_GUESS +		if [ -n "$(__git_find_on_cmdline "--guess")" ]; then +			track_opt='--track' +		fi +		if [ -z "$(__git_find_on_cmdline "-d --detach")" ]; then +			only_local_ref=y +		else +			# --guess --detach is invalid combination, no +			# dwim will be done when --detach is specified +			track_opt= +		fi +		if [ $only_local_ref = y -a -z "$track_opt" ]; then +			__gitcomp_direct "$(__git_heads "" "$cur" " ")" +		else +			__git_complete_refs $track_opt +		fi +		;; +	esac +} +  __git_config_get_set_variables ()  {  	local prevword word config_file= c=$cword @@ -1798,22 +2218,37 @@ __git_config_get_set_variables ()  		c=$((--c))  	done -	git --git-dir="$(__gitdir)" config $config_file --name-only --list 2>/dev/null +	__git config $config_file --name-only --list +} + +__git_config_vars= +__git_compute_config_vars () +{ +	test -n "$__git_config_vars" || +	__git_config_vars="$(git help --config-for-completion | sort | uniq)"  }  _git_config ()  { -	case "$prev" in +	local varname + +	if [ "${BASH_VERSINFO[0]:-0}" -ge 4 ]; then +		varname="${prev,,}" +	else +		varname="$(echo "$prev" |tr A-Z a-z)" +	fi + +	case "$varname" in  	branch.*.remote|branch.*.pushremote)  		__gitcomp_nl "$(__git_remotes)"  		return  		;;  	branch.*.merge) -		__gitcomp_nl "$(__git_refs)" +		__git_complete_refs  		return  		;;  	branch.*.rebase) -		__gitcomp "false true preserve interactive" +		__gitcomp "false true merges preserve interactive"  		return  		;;  	remote.pushdefault) @@ -1833,9 +2268,8 @@ _git_config ()  	remote.*.push)  		local remote="${prev#remote.}"  		remote="${remote%.push}" -		__gitcomp_nl "$(git --git-dir="$(__gitdir)" \ -			for-each-ref --format='%(refname):%(refname)' \ -			refs/heads)" +		__gitcomp_nl "$(__git for-each-ref \ +			--format='%(refname):%(refname)' refs/heads)"  		return  		;;  	pull.twohead|pull.octopus) @@ -1860,7 +2294,7 @@ _git_config ()  		return  		;;  	diff.submodule) -		__gitcomp "log short" +		__gitcomp "$__git_diff_submodule_formats"  		return  		;;  	help.format) @@ -1871,7 +2305,7 @@ _git_config ()  		__gitcomp "$__git_log_date_formats"  		return  		;; -	sendemail.aliasesfiletype) +	sendemail.aliasfiletype)  		__gitcomp "mutt mailrc pine elm gnus"  		return  		;; @@ -1897,32 +2331,25 @@ _git_config ()  	esac  	case "$cur" in  	--*) -		__gitcomp " -			--system --global --local --file= -			--list --replace-all -			--get --get-all --get-regexp -			--add --unset --unset-all -			--remove-section --rename-section -			--name-only -			" +		__gitcomp_builtin config  		return  		;;  	branch.*.*)  		local pfx="${cur%.*}." cur_="${cur##*.}" -		__gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_" +		__gitcomp "remote pushRemote merge mergeOptions rebase" "$pfx" "$cur_"  		return  		;;  	branch.*)  		local pfx="${cur%.*}." cur_="${cur#*.}" -		__gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "." -		__gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_" +		__gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")" +		__gitcomp_nl_append $'autoSetupMerge\nautoSetupRebase\n' "$pfx" "$cur_"  		return  		;;  	guitool.*.*)  		local pfx="${cur%.*}." cur_="${cur##*.}"  		__gitcomp " -			argprompt cmd confirm needsfile noconsole norescan -			prompt revprompt revunmerged title +			argPrompt cmd confirm needsFile noConsole noRescan +			prompt revPrompt revUnmerged title  			" "$pfx" "$cur_"  		return  		;; @@ -1951,14 +2378,14 @@ _git_config ()  		local pfx="${cur%.*}." cur_="${cur##*.}"  		__gitcomp "  			url proxy fetch push mirror skipDefaultUpdate -			receivepack uploadpack tagopt pushurl +			receivepack uploadpack tagOpt pushurl  			" "$pfx" "$cur_"  		return  		;;  	remote.*)  		local pfx="${cur%.*}." cur_="${cur#*.}"  		__gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "." -		__gitcomp_nl_append "pushdefault" "$pfx" "$cur_" +		__gitcomp_nl_append "pushDefault" "$pfx" "$cur_"  		return  		;;  	url.*.*) @@ -1966,324 +2393,95 @@ _git_config ()  		__gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_"  		return  		;; +	*.*) +		__git_compute_config_vars +		__gitcomp "$__git_config_vars" +		;; +	*) +		__git_compute_config_vars +		__gitcomp "$(echo "$__git_config_vars" | sed 's/\.[^ ]*/./g')"  	esac -	__gitcomp " -		add.ignoreErrors -		advice.commitBeforeMerge -		advice.detachedHead -		advice.implicitIdentity -		advice.pushNonFastForward -		advice.resolveConflict -		advice.statusHints -		alias. -		am.keepcr -		apply.ignorewhitespace -		apply.whitespace -		branch.autosetupmerge -		branch.autosetuprebase -		browser. -		clean.requireForce -		color.branch -		color.branch.current -		color.branch.local -		color.branch.plain -		color.branch.remote -		color.decorate.HEAD -		color.decorate.branch -		color.decorate.remoteBranch -		color.decorate.stash -		color.decorate.tag -		color.diff -		color.diff.commit -		color.diff.frag -		color.diff.func -		color.diff.meta -		color.diff.new -		color.diff.old -		color.diff.plain -		color.diff.whitespace -		color.grep -		color.grep.context -		color.grep.filename -		color.grep.function -		color.grep.linenumber -		color.grep.match -		color.grep.selected -		color.grep.separator -		color.interactive -		color.interactive.error -		color.interactive.header -		color.interactive.help -		color.interactive.prompt -		color.pager -		color.showbranch -		color.status -		color.status.added -		color.status.changed -		color.status.header -		color.status.nobranch -		color.status.unmerged -		color.status.untracked -		color.status.updated -		color.ui -		commit.status -		commit.template -		core.abbrev -		core.askpass -		core.attributesfile -		core.autocrlf -		core.bare -		core.bigFileThreshold -		core.compression -		core.createObject -		core.deltaBaseCacheLimit -		core.editor -		core.eol -		core.excludesfile -		core.fileMode -		core.fsyncobjectfiles -		core.gitProxy -		core.ignoreStat -		core.ignorecase -		core.logAllRefUpdates -		core.loosecompression -		core.notesRef -		core.packedGitLimit -		core.packedGitWindowSize -		core.pager -		core.preferSymlinkRefs -		core.preloadindex -		core.quotepath -		core.repositoryFormatVersion -		core.safecrlf -		core.sharedRepository -		core.sparseCheckout -		core.symlinks -		core.trustctime -		core.untrackedCache -		core.warnAmbiguousRefs -		core.whitespace -		core.worktree -		diff.autorefreshindex -		diff.external -		diff.ignoreSubmodules -		diff.mnemonicprefix -		diff.noprefix -		diff.renameLimit -		diff.renames -		diff.statGraphWidth -		diff.submodule -		diff.suppressBlankEmpty -		diff.tool -		diff.wordRegex -		diff.algorithm -		difftool. -		difftool.prompt -		fetch.recurseSubmodules -		fetch.unpackLimit -		format.attach -		format.cc -		format.coverLetter -		format.headers -		format.numbered -		format.pretty -		format.signature -		format.signoff -		format.subjectprefix -		format.suffix -		format.thread -		format.to -		gc. -		gc.aggressiveWindow -		gc.auto -		gc.autopacklimit -		gc.packrefs -		gc.pruneexpire -		gc.reflogexpire -		gc.reflogexpireunreachable -		gc.rerereresolved -		gc.rerereunresolved -		gitcvs.allbinary -		gitcvs.commitmsgannotation -		gitcvs.dbTableNamePrefix -		gitcvs.dbdriver -		gitcvs.dbname -		gitcvs.dbpass -		gitcvs.dbuser -		gitcvs.enabled -		gitcvs.logfile -		gitcvs.usecrlfattr -		guitool. -		gui.blamehistoryctx -		gui.commitmsgwidth -		gui.copyblamethreshold -		gui.diffcontext -		gui.encoding -		gui.fastcopyblame -		gui.matchtrackingbranch -		gui.newbranchtemplate -		gui.pruneduringfetch -		gui.spellingdictionary -		gui.trustmtime -		help.autocorrect -		help.browser -		help.format -		http.lowSpeedLimit -		http.lowSpeedTime -		http.maxRequests -		http.minSessions -		http.noEPSV -		http.postBuffer -		http.proxy -		http.sslCipherList -		http.sslVersion -		http.sslCAInfo -		http.sslCAPath -		http.sslCert -		http.sslCertPasswordProtected -		http.sslKey -		http.sslVerify -		http.useragent -		i18n.commitEncoding -		i18n.logOutputEncoding -		imap.authMethod -		imap.folder -		imap.host -		imap.pass -		imap.port -		imap.preformattedHTML -		imap.sslverify -		imap.tunnel -		imap.user -		init.templatedir -		instaweb.browser -		instaweb.httpd -		instaweb.local -		instaweb.modulepath -		instaweb.port -		interactive.singlekey -		log.date -		log.decorate -		log.showroot -		mailmap.file -		man. -		man.viewer -		merge. -		merge.conflictstyle -		merge.log -		merge.renameLimit -		merge.renormalize -		merge.stat -		merge.tool -		merge.verbosity -		mergetool. -		mergetool.keepBackup -		mergetool.keepTemporaries -		mergetool.prompt -		notes.displayRef -		notes.rewrite. -		notes.rewrite.amend -		notes.rewrite.rebase -		notes.rewriteMode -		notes.rewriteRef -		pack.compression -		pack.deltaCacheLimit -		pack.deltaCacheSize -		pack.depth -		pack.indexVersion -		pack.packSizeLimit -		pack.threads -		pack.window -		pack.windowMemory -		pager. -		pretty. -		pull.octopus -		pull.twohead -		push.default -		push.followTags -		rebase.autosquash -		rebase.stat -		receive.autogc -		receive.denyCurrentBranch -		receive.denyDeleteCurrent -		receive.denyDeletes -		receive.denyNonFastForwards -		receive.fsckObjects -		receive.unpackLimit -		receive.updateserverinfo -		remote.pushdefault -		remotes. -		repack.usedeltabaseoffset -		rerere.autoupdate -		rerere.enabled -		sendemail. -		sendemail.aliasesfile -		sendemail.aliasfiletype -		sendemail.bcc -		sendemail.cc -		sendemail.cccmd -		sendemail.chainreplyto -		sendemail.confirm -		sendemail.envelopesender -		sendemail.from -		sendemail.identity -		sendemail.multiedit -		sendemail.signedoffbycc -		sendemail.smtpdomain -		sendemail.smtpencryption -		sendemail.smtppass -		sendemail.smtpserver -		sendemail.smtpserveroption -		sendemail.smtpserverport -		sendemail.smtpuser -		sendemail.suppresscc -		sendemail.suppressfrom -		sendemail.thread -		sendemail.to -		sendemail.validate -		showbranch.default -		status.relativePaths -		status.showUntrackedFiles -		status.submodulesummary -		submodule. -		tar.umask -		transfer.unpackLimit -		url. -		user.email -		user.name -		user.signingkey -		web.browser -		branch. remote. -	"  }  _git_remote ()  { -	local subcommands="add rename remove set-head set-branches set-url show prune update" +	local subcommands=" +		add rename remove set-head set-branches +		get-url set-url show prune update +		"  	local subcommand="$(__git_find_on_cmdline "$subcommands")"  	if [ -z "$subcommand" ]; then -		__gitcomp "$subcommands" +		case "$cur" in +		--*) +			__gitcomp_builtin remote +			;; +		*) +			__gitcomp "$subcommands" +			;; +		esac  		return  	fi -	case "$subcommand" in -	rename|remove|set-url|show|prune) -		__gitcomp_nl "$(__git_remotes)" +	case "$subcommand,$cur" in +	add,--*) +		__gitcomp_builtin remote_add +		;; +	add,*) +		;; +	set-head,--*) +		__gitcomp_builtin remote_set-head  		;; -	set-head|set-branches) +	set-branches,--*) +		__gitcomp_builtin remote_set-branches +		;; +	set-head,*|set-branches,*)  		__git_complete_remote_or_refspec  		;; -	update) -		__gitcomp "$(__git_get_config_variables "remotes")" +	update,--*) +		__gitcomp_builtin remote_update +		;; +	update,*) +		__gitcomp "$(__git_remotes) $(__git_get_config_variables "remotes")" +		;; +	set-url,--*) +		__gitcomp_builtin remote_set-url +		;; +	get-url,--*) +		__gitcomp_builtin remote_get-url +		;; +	prune,--*) +		__gitcomp_builtin remote_prune  		;;  	*) +		__gitcomp_nl "$(__git_remotes)"  		;;  	esac  }  _git_replace ()  { -	__gitcomp_nl "$(__git_refs)" +	case "$cur" in +	--format=*) +		__gitcomp "short medium long" "" "${cur##--format=}" +		return +		;; +	--*) +		__gitcomp_builtin replace +		return +		;; +	esac +	__git_complete_refs +} + +_git_rerere () +{ +	local subcommands="clear forget diff remaining status gc" +	local subcommand="$(__git_find_on_cmdline "$subcommands")" +	if test -z "$subcommand" +	then +		__gitcomp "$subcommands" +		return +	fi  }  _git_reset () @@ -2292,34 +2490,53 @@ _git_reset ()  	case "$cur" in  	--*) -		__gitcomp "--merge --mixed --hard --soft --patch" +		__gitcomp_builtin reset  		return  		;;  	esac -	__gitcomp_nl "$(__git_refs)" +	__git_complete_refs  } +_git_restore () +{ +	case "$cur" in +	--conflict=*) +		__gitcomp "diff3 merge" "" "${cur##--conflict=}" +		;; +	--source=*) +		__git_complete_refs --cur="${cur##--source=}" +		;; +	--*) +		__gitcomp_builtin restore +		;; +	esac +} + +__git_revert_inprogress_options="--continue --quit --abort" +  _git_revert ()  { -	local dir="$(__gitdir)" -	if [ -f "$dir"/REVERT_HEAD ]; then -		__gitcomp "--continue --quit --abort" +	__git_find_repo_path +	if [ -f "$__git_repo_path"/REVERT_HEAD ]; then +		__gitcomp "$__git_revert_inprogress_options"  		return  	fi +	__git_complete_strategy && return  	case "$cur" in  	--*) -		__gitcomp "--edit --mainline --no-edit --no-commit --signoff" +		__gitcomp_builtin revert "" \ +			"$__git_revert_inprogress_options"  		return  		;;  	esac -	__gitcomp_nl "$(__git_refs)" +	__git_complete_refs  }  _git_rm ()  {  	case "$cur" in  	--*) -		__gitcomp "--cached --dry-run --ignore-unmatch --quiet" +		__gitcomp_builtin rm  		return  		;;  	esac @@ -2336,7 +2553,7 @@ _git_shortlog ()  		__gitcomp "  			$__git_log_common_options  			$__git_log_shortlog_options -			--numbered --summary +			--numbered --summary --email  			"  		return  		;; @@ -2358,6 +2575,10 @@ _git_show ()  		__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"  		return  		;; +	--submodule=*) +		__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}" +		return +		;;  	--*)  		__gitcomp "--pretty= --format= --abbrev-commit --oneline  			--show-signature @@ -2373,12 +2594,7 @@ _git_show_branch ()  {  	case "$cur" in  	--*) -		__gitcomp " -			--all --remotes --topo-order --date-order --current --more= -			--list --independent --merge-base --no-name -			--color --no-color -			--sha1-name --sparse --topics --reflog -			" +		__gitcomp_builtin show-branch  		return  		;;  	esac @@ -2388,13 +2604,21 @@ _git_show_branch ()  _git_stash ()  {  	local save_opts='--all --keep-index --no-keep-index --quiet --patch --include-untracked' -	local subcommands='save list show apply clear drop pop create branch' -	local subcommand="$(__git_find_on_cmdline "$subcommands")" +	local subcommands='push list show apply clear drop pop create branch' +	local subcommand="$(__git_find_on_cmdline "$subcommands save")" +	if [ -n "$(__git_find_on_cmdline "-p")" ]; then +		subcommand="push" +	fi  	if [ -z "$subcommand" ]; then  		case "$cur" in  		--*)  			__gitcomp "$save_opts"  			;; +		sa*) +			if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then +				__gitcomp "save" +			fi +			;;  		*)  			if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then  				__gitcomp "$subcommands" @@ -2403,6 +2627,9 @@ _git_stash ()  		esac  	else  		case "$subcommand,$cur" in +		push,--*) +			__gitcomp "$save_opts --message" +			;;  		save,--*)  			__gitcomp "$save_opts"  			;; @@ -2412,18 +2639,21 @@ _git_stash ()  		drop,--*)  			__gitcomp "--quiet"  			;; +		list,--*) +			__gitcomp "--name-status --oneline --patch-with-stat" +			;;  		show,--*|branch,--*)  			;;  		branch,*)  			if [ $cword -eq 3 ]; then -				__gitcomp_nl "$(__git_refs)"; +				__git_complete_refs  			else -				__gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ +				__gitcomp_nl "$(__git stash list \  						| sed -n -e 's/:.*//p')"  			fi  			;;  		show,*|apply,*|drop,*|pop,*) -			__gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ +			__gitcomp_nl "$(__git stash list \  					| sed -n -e 's/:.*//p')"  			;;  		*) @@ -2436,11 +2666,12 @@ _git_submodule ()  {  	__git_has_doubledash && return -	local subcommands="add status init deinit update summary foreach sync" -	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then +	local subcommands="add status init deinit update set-branch summary foreach sync absorbgitdirs" +	local subcommand="$(__git_find_on_cmdline "$subcommands")" +	if [ -z "$subcommand" ]; then  		case "$cur" in  		--*) -			__gitcomp "--quiet --cached" +			__gitcomp "--quiet"  			;;  		*)  			__gitcomp "$subcommands" @@ -2448,6 +2679,36 @@ _git_submodule ()  		esac  		return  	fi + +	case "$subcommand,$cur" in +	add,--*) +		__gitcomp "--branch --force --name --reference --depth" +		;; +	status,--*) +		__gitcomp "--cached --recursive" +		;; +	deinit,--*) +		__gitcomp "--force --all" +		;; +	update,--*) +		__gitcomp " +			--init --remote --no-fetch +			--recommend-shallow --no-recommend-shallow +			--force --rebase --merge --reference --depth --recursive --jobs +		" +		;; +	set-branch,--*) +		__gitcomp "--default --branch" +		;; +	summary,--*) +		__gitcomp "--cached --files --summary-limit" +		;; +	foreach,--*|sync,--*) +		__gitcomp "--recursive" +		;; +	*) +		;; +	esac  }  _git_svn () @@ -2468,14 +2729,14 @@ _git_svn ()  			--no-metadata --use-svm-props --use-svnsync-props  			--log-window-size= --no-checkout --quiet  			--repack-flags --use-log-author --localtime +			--add-author-from  			--ignore-paths= --include-paths= $remote_opts  			"  		local init_opts="  			--template= --shared= --trunk= --tags=  			--branches= --stdlayout --minimize-url  			--no-metadata --use-svm-props --use-svnsync-props -			--rewrite-root= --prefix= --use-log-author -			--add-author-from $remote_opts +			--rewrite-root= --prefix= $remote_opts  			"  		local cmt_opts="  			--edit --rmdir --find-copies-harder --copy-similarity= @@ -2554,8 +2815,8 @@ _git_tag ()  	while [ $c -lt $cword ]; do  		i="${words[c]}"  		case "$i" in -		-d|-v) -			__gitcomp_nl "$(__git_tags)" +		-d|--delete|-v|--verify) +			__gitcomp_direct "$(__git_tags "" "$cur" " ")"  			return  			;;  		-f) @@ -2570,21 +2831,17 @@ _git_tag ()  		;;  	-*|tag)  		if [ $f = 1 ]; then -			__gitcomp_nl "$(__git_tags)" +			__gitcomp_direct "$(__git_tags "" "$cur" " ")"  		fi  		;;  	*) -		__gitcomp_nl "$(__git_refs)" +		__git_complete_refs  		;;  	esac  	case "$cur" in  	--*) -		__gitcomp " -			--list --delete --verify --annotate --message --file -			--sign --cleanup --local-user --force --column --sort -			--contains --points-at -			" +		__gitcomp_builtin tag  		;;  	esac  } @@ -2594,9 +2851,85 @@ _git_whatchanged ()  	_git_log  } +_git_worktree () +{ +	local subcommands="add list lock move prune remove unlock" +	local subcommand="$(__git_find_on_cmdline "$subcommands")" +	if [ -z "$subcommand" ]; then +		__gitcomp "$subcommands" +	else +		case "$subcommand,$cur" in +		add,--*) +			__gitcomp_builtin worktree_add +			;; +		list,--*) +			__gitcomp_builtin worktree_list +			;; +		lock,--*) +			__gitcomp_builtin worktree_lock +			;; +		prune,--*) +			__gitcomp_builtin worktree_prune +			;; +		remove,--*) +			__gitcomp "--force" +			;; +		*) +			;; +		esac +	fi +} + +__git_complete_common () { +	local command="$1" + +	case "$cur" in +	--*) +		__gitcomp_builtin "$command" +		;; +	esac +} + +__git_cmds_with_parseopt_helper= +__git_support_parseopt_helper () { +	test -n "$__git_cmds_with_parseopt_helper" || +		__git_cmds_with_parseopt_helper="$(__git --list-cmds=parseopt)" + +	case " $__git_cmds_with_parseopt_helper " in +	*" $1 "*) +		return 0 +		;; +	*) +		return 1 +		;; +	esac +} + +__git_complete_command () { +	local command="$1" +	local completion_func="_git_${command//-/_}" +	if ! declare -f $completion_func >/dev/null 2>/dev/null && +		declare -f _completion_loader >/dev/null 2>/dev/null +	then +		_completion_loader "git-$command" +	fi +	if declare -f $completion_func >/dev/null 2>/dev/null +	then +		$completion_func +		return 0 +	elif __git_support_parseopt_helper "$command" +	then +		__git_complete_common "$command" +		return 0 +	else +		return 1 +	fi +} +  __git_main ()  { -	local i c=1 command __git_dir +	local i c=1 command __git_dir __git_repo_path +	local __git_C_args C_args_count=0  	while [ $c -lt $cword ]; do  		i="${words[c]}" @@ -2606,6 +2939,10 @@ __git_main ()  		--bare)      __git_dir="." ;;  		--help) command="help"; break ;;  		-c|--work-tree|--namespace) ((c++)) ;; +		-C)	__git_C_args[C_args_count++]=-C +			((c++)) +			__git_C_args[C_args_count++]="${words[c]}" +			;;  		-*) ;;  		*) command="$i"; break ;;  		esac @@ -2613,6 +2950,17 @@ __git_main ()  	done  	if [ -z "$command" ]; then +		case "$prev" in +		--git-dir|-C|--work-tree) +			# these need a path argument, let's fall back to +			# Bash filename completion +			return +			;; +		-c|--namespace) +			# we don't support completing these options' arguments +			return +			;; +		esac  		case "$cur" in  		--*)   __gitcomp "  			--paginate @@ -2631,20 +2979,24 @@ __git_main ()  			--help  			"  			;; -		*)     __git_compute_porcelain_commands -		       __gitcomp "$__git_porcelain_commands $(__git_aliases)" ;; +		*) +			if test -n "$GIT_TESTING_PORCELAIN_COMMAND_LIST" +			then +				__gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST" +			else +				__gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)" +			fi +			;;  		esac  		return  	fi -	local completion_func="_git_${command//-/_}" -	declare -f $completion_func >/dev/null && $completion_func && return +	__git_complete_command "$command" && return  	local expansion=$(__git_aliased_command "$command")  	if [ -n "$expansion" ]; then  		words[1]=$expansion -		completion_func="_git_${expansion//-/_}" -		declare -f $completion_func >/dev/null && $completion_func +		__git_complete_command "$expansion"  	fi  } @@ -2652,9 +3004,11 @@ __gitk_main ()  {  	__git_has_doubledash && return -	local g="$(__gitdir)" +	local __git_repo_path +	__git_find_repo_path +  	local merge="" -	if [ -f "$g/MERGE_HEAD" ]; then +	if [ -f "$__git_repo_path/MERGE_HEAD" ]; then  		merge="--merge"  	fi  	case "$cur" in @@ -2670,7 +3024,10 @@ __gitk_main ()  	__git_complete_revlist  } -if [[ -n ${ZSH_VERSION-} ]]; then +if [[ -n ${ZSH_VERSION-} ]] && +   # Don't define these functions when sourced from 'git-completion.zsh', +   # it has its own implementations. +   [[ -z ${GIT_SOURCING_ZSH_COMPLETION-} ]]; then  	echo "WARNING: this script is deprecated, please see git-completion.zsh" 1>&2  	autoload -U +X compinit && compinit @@ -2701,6 +3058,15 @@ if [[ -n ${ZSH_VERSION-} ]]; then  		esac  	} +	__gitcomp_direct () +	{ +		emulate -L zsh + +		local IFS=$'\n' +		compset -P '*[=:]' +		compadd -Q -- ${=1} && _ret=0 +	} +  	__gitcomp_nl ()  	{  		emulate -L zsh @@ -2710,13 +3076,22 @@ if [[ -n ${ZSH_VERSION-} ]]; then  		compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0  	} +	__gitcomp_file_direct () +	{ +		emulate -L zsh + +		local IFS=$'\n' +		compset -P '*[=:]' +		compadd -f -- ${=1} && _ret=0 +	} +  	__gitcomp_file ()  	{  		emulate -L zsh  		local IFS=$'\n'  		compset -P '*[=:]' -		compadd -Q -p "${2-}" -f -- ${=1} && _ret=0 +		compadd -p "${2-}" -f -- ${=1} && _ret=0  	}  	_git () @@ -2771,6 +3146,6 @@ __git_complete gitk __gitk_main  # when the user has tab-completed the executable name and consequently  # included the '.exe' suffix.  # -if [[ "$OSTYPE" = cygwin* ]]; then +if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then  __git_complete git.exe __git_main  fi diff --git a/plugins/gitfast/git-prompt.sh b/plugins/gitfast/git-prompt.sh index 0da14eee9..f7009b063 100644 --- a/plugins/gitfast/git-prompt.sh +++ b/plugins/gitfast/git-prompt.sh @@ -82,6 +82,7 @@  #     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 @@ -218,7 +219,7 @@ __git_ps1_show_upstream ()  		if [[ -n "$count" && -n "$name" ]]; then  			__git_ps1_upstream_name=$(git rev-parse \  				--abbrev-ref "$upstream" 2>/dev/null) -			if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then +			if [ "$pcmode" = yes ] && [ "$ps1_expanded" = yes ]; then  				p="$p \${__git_ps1_upstream_name}"  			else  				p="$p ${__git_ps1_upstream_name}" @@ -236,7 +237,7 @@ __git_ps1_show_upstream ()  # to build a gitstring.  __git_ps1_colorize_gitstring ()  { -	if [[ -n ${ZSH_VERSION-} ]]; then +	if [[ -n "${ZSH_VERSION-}" ]]; then  		local c_red='%F{red}'  		local c_green='%F{green}'  		local c_lblue='%F{blue}' @@ -254,7 +255,7 @@ __git_ps1_colorize_gitstring ()  	local flags_color="$c_lblue"  	local branch_color="" -	if [ $detached = no ]; then +	if [ "$detached" = no ]; then  		branch_color="$ok_color"  	else  		branch_color="$bad_color" @@ -277,11 +278,12 @@ __git_ps1_colorize_gitstring ()  	r="$c_clear$r"  } +# 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 ()  { -	local f="$1" -	shift -	test -r "$f" && read "$@" <"$f" +	test -r "$1" && IFS=$'\r\n' read "$2" <"$1"  }  # __git_ps1 accepts 0 or 1 arguments (i.e., format string) @@ -355,8 +357,8 @@ __git_ps1 ()  	# incorrect.)  	#  	local ps1_expanded=yes -	[ -z "$ZSH_VERSION" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no -	[ -z "$BASH_VERSION" ] || shopt -q promptvars || ps1_expanded=no +	[ -z "${ZSH_VERSION-}" ] || [[ -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 \ @@ -368,7 +370,7 @@ __git_ps1 ()  		return $exit  	fi -	local short_sha +	local short_sha=""  	if [ "$rev_parse_exit_code" = "0" ]; then  		short_sha="${repo_info##*$'\n'}"  		repo_info="${repo_info%$'\n'*}" @@ -443,6 +445,8 @@ __git_ps1 ()  					git describe --contains HEAD ;;  				(branch)  					git describe --contains --all HEAD ;; +				(tag) +					git describe --tags HEAD ;;  				(describe)  					git describe HEAD ;;  				(* | default) @@ -504,13 +508,13 @@ __git_ps1 ()  	# NO color option unless in PROMPT_COMMAND mode or it's Zsh  	if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then -		if [ $pcmode = yes ] || [ -n "${ZSH_VERSION-}" ]; then +		if [ "$pcmode" = yes ] || [ -n "${ZSH_VERSION-}" ]; then  			__git_ps1_colorize_gitstring  		fi  	fi  	b=${b##refs/heads/} -	if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then +	if [ "$pcmode" = yes ] && [ "$ps1_expanded" = yes ]; then  		__git_ps1_branch_name=$b  		b="\${__git_ps1_branch_name}"  	fi @@ -518,7 +522,7 @@ __git_ps1 ()  	local f="$w$i$s$u"  	local gitstring="$c$b${f:+$z$f}$r$p" -	if [ $pcmode = yes ]; then +	if [ "$pcmode" = yes ]; then  		if [ "${__git_printf_supports_v-}" != yes ]; then  			gitstring=$(printf -- "$printf_format" "$gitstring")  		else diff --git a/plugins/gitfast/gitfast.plugin.zsh b/plugins/gitfast/gitfast.plugin.zsh index dba1b1315..7b6b67e92 100644 --- a/plugins/gitfast/gitfast.plugin.zsh +++ b/plugins/gitfast/gitfast.plugin.zsh @@ -1,6 +1,4 @@ -dir=$(dirname $0) -source $dir/../git/git.plugin.zsh -source $dir/git-prompt.sh +source "${0:A:h}/git-prompt.sh"  function git_prompt_info() {    dirty="$(parse_git_dirty)" diff --git a/plugins/gitfast/update b/plugins/gitfast/update new file mode 100755 index 000000000..05054245f --- /dev/null +++ b/plugins/gitfast/update @@ -0,0 +1,9 @@ +#!/bin/sh + +url="https://git.kernel.org/pub/scm/git/git.git/plain/contrib/completion" +version="2.16.0" + +curl -s -o _git "${url}/git-completion.zsh?h=v${version}" && +curl -s -o git-completion.bash "${url}/git-completion.bash?h=v${version}" && +curl -s -o git-prompt.sh "${url}/git-prompt.sh?h=v${version}" && +git apply updates.patch diff --git a/plugins/gitfast/updates.patch b/plugins/gitfast/updates.patch new file mode 100644 index 000000000..28a31f859 --- /dev/null +++ b/plugins/gitfast/updates.patch @@ -0,0 +1,56 @@ +diff --git b/plugins/gitfast/_git a/plugins/gitfast/_git +index e2554130..a2e3bef5 100644 +--- b/plugins/gitfast/_git ++++ a/plugins/gitfast/_git +@@ -30,7 +30,7 @@ if [ -z "$script" ]; then + 	local -a locations + 	local e + 	locations=( +-		$(dirname ${funcsourcetrace[1]%:*})/git-completion.bash ++		"$(dirname ${funcsourcetrace[1]%:*})/git-completion.bash" + 		'/etc/bash_completion.d/git' # fedora, old debian + 		'/usr/share/bash-completion/completions/git' # arch, ubuntu, new debian + 		'/usr/share/bash-completion/git' # gentoo +@@ -214,8 +214,10 @@ _git () +  + 	if (( $+functions[__${service}_zsh_main] )); then + 		__${service}_zsh_main +-	else ++	elif (( $+functions[__${service}_main] )); then + 		emulate ksh -c __${service}_main ++	elif (( $+functions[_${service}] )); then ++		emulate ksh -c _${service} + 	fi +  + 	let _ret && _default && _ret=0 +diff --git b/plugins/gitfast/git-completion.bash a/plugins/gitfast/git-completion.bash +index 9c8f7380..14012cab 100644 +--- b/plugins/gitfast/git-completion.bash ++++ a/plugins/gitfast/git-completion.bash +@@ -2915,6 +2915,6 @@ __git_complete gitk __gitk_main + # when the user has tab-completed the executable name and consequently + # included the '.exe' suffix. + # +-if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then ++if [[ "$OSTYPE" = cygwin* ]]; then + __git_complete git.exe __git_main + fi +diff --git b/plugins/gitfast/git-prompt.sh a/plugins/gitfast/git-prompt.sh +index 97eacd78..c1de34eb 100644 +--- b/plugins/gitfast/git-prompt.sh ++++ a/plugins/gitfast/git-prompt.sh +@@ -502,9 +502,11 @@ __git_ps1 () +  + 	local z="${GIT_PS1_STATESEPARATOR-" "}" +  +-	# NO color option unless in PROMPT_COMMAND mode +-	if [ $pcmode = yes ] && [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then +-		__git_ps1_colorize_gitstring ++	# NO color option unless in PROMPT_COMMAND mode or it's Zsh ++	if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then ++		if [ $pcmode = yes ] || [ -n "${ZSH_VERSION-}" ]; then ++			__git_ps1_colorize_gitstring ++		fi + 	fi +  + 	b=${b##refs/heads/} | 
