1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-02 10:01:11 +02:00
zsh/Completion/Unix/Command/_git

4104 lines
149 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#compdef git git-add git-am git-annotate git-apply git-applymbox git-applypatch git-archimport git-archive git-bisect git-blame git-branch git-cat-file git-check-attr git-check-ref-format git-checkout git-checkout-index git-cherry git-cherry-pick git-clean git-clone git-clone-pack git-commit git-commit-tree git-convert-objects git-count-objects git-cvsexportcommit git-cvsimport git-cvsserver git-daemon git-describe git-diff git-diff-files git-diff-index git-diff-stages git-diff-tree git-fast-import git-fetch git-fetch-pack git-fmt-merge-msg git-for-each-ref git-format-patch git-fsck git-gc git-get-tar-commit-id git-grep git-hash-object git-http-fetch git-http-push git-imap-send git-index-pack git-init git-instaweb git-local-fetch git-log git-lost-found git-ls-files git-ls-remote git-ls-tree git-mailinfo git-mailsplit git-merge git-merge-base git-merge-file git-merge-index git-merge-one-file git-merge-tree git-mergetool git-mktag git-mktree git-mv git-name-rev git-octopus git-pack-objects git-pack-redundant git-pack-refs git-patch-id git-peek-remote git-prune git-prune-packed git-pull git-push git-quiltimport git-read-tree git-rebase git-receive-pack git-reflog git-relink git-remote git-repack gut-runstatus git-config git-request-pull git-rerere git-reset git-rev-list git-rev-parse git-revert git-rm git-send-email git-send-pack git-sh-setup git-shell git-shortlog git-show git-show-branch git-show-index git-show-ref git-ssh-fetch git-ssh-upload git-status git-stripspace git-svn git-svnimport git-symbolic-ref git-tag git-tar-tree git-unpack-file git-unpack-objects git-update-index git-update-ref git-update-server-info git-upload-archive git-upload-pack git-var git-verify-pack git-verify-tag git-whatchanged git-write-tree
# TODO: All if (( words[(I)-option] )) should be turned into
# if (( words[(I)-option] > 0 && words[(I)-option] < CURRENT )), as the user
# may go back and want to add an option before -option and in that case should
# be able to complete whatever may come before -option.
# TODO: suggested zstyles:
#
# zstyle ':completion::*:git-{name-rev,add,rm}:*' ignore-line true
_git() {
local nul_arg abbrev_arg find_copies_harder_arg diff_l_arg pretty_arg exec_arg
local author_conversion_file_arg long_author_conversion_file_arg verbose_arg
local help_arg template_arg shared_arg thin_arg author_conversion_file_arg_spec
local -a diff_args fetch_args merge_args force_ref_arg tags_fetch_arg
local -a upload_pack_arg common_fetch_args common_apply_args
local -a revision_arguments
nul_arg='-z[use NUL termination on output]'
abbrev_arg='--abbrev=-[set minimum SHA1 display-length]: :_guard "[[\:digit\:]]#" length'
find_copies_harder_arg='--find-copies-harder[try harder to find copies]'
diff_l_arg='-l-[limit number of rename/copy targets to run]: :_guard "[[\:digit\:]]#" number'
diff_args=(
'--diff-filter=-[select certain kinds of files for diff]: :_guard "[ACDMRTUXB*]#" kinds'
$find_copies_harder_arg
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--name-only[show only names of changed files]'
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--name-status[show only names and status of changed files]'
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)'{-u,-p}'[generate diff in patch format]'
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--stat=-[generate a diffstat instead of a patch]:: :__git_guard_diff-stat-width' \
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--patch-with-stat[generate patch and prepend its diffstat]' \
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--patch-with-raw[generate patch but also keep the default raw diff output]' \
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--raw[generate the default raw diff output]' \
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--numstat[generate a more machine-friendly diffstat]' \
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--shortstat[generate a summary diffstat]' \
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--summary[generate a condensed summary of extended header information]' \
'-B-[break complete rewrite changes into pairs of given size]: :_guard "[[\:digit\:]]#" size'
'-C-[detect copies as well as renames with given scope]: :_guard "[[\:digit\:]]#" size'
$diff_l_arg
'-M-[detect renames with given scope]: :_guard "[[\:digit\:]]#" size'
'-O-[output patch in the order of glob-pattern lines in given file]:file:_files'
'-R[do a reverse diff]'
'-S-[look for differences that contain the given string]:string'
'--pickaxe-all[when -S finds a change, show all changes in that changeset]'
'--pickaxe-regex[treat argument of -S as regular expression]'
'--full-index[show full object name of pre- and post-image blob]'
'(--full-index)--binary[in addition to --full-index, output binary diffs for git-apply]'
'( --no-color --color-words)--color[show colored diff]'
'(--color --color-words)--no-color[turn off colored diff]'
'(--color --no-color )--color-words[show colored-word diff]'
'--no-renames[turn off rename detection]'
'--check[warn if changes introduce trailing whitespace or space/tab indents]'
'(-a --text)'{-a,--text}'[treat all files as text]'
'(-b --ignore-space-change -w --ignore-all-space)'{-b,--ignore-space-change}'[ignore changes in amount of white space]'
'(-b --ignore-space-change -w --ignore-all-space)'{-w,--ignore-all-space}'[ignore white space when comparing lines]'
$abbrev_arg
$nul_arg
'--exit-code[report exit code 1 if differences, 0 otherwise]'
'(--exit-code)--quiet[disable all output]'
)
pretty_arg='--pretty=-[pretty print commit messages]::pretty print:((raw\:"the raw commits"
medium\:"most parts of the messages"
short\:"few headers and only subject of messages"
full\:"all parts of the commit messages"
oneline\:"commit-ids and subject of messages"))'
exec_arg='--exec=-[specify path to git-upload-pack on remote side]:remote path'
fetch_args=(
'-c[fetch commit objects]'
'-t[fetch trees associated with commit objects]'
'-a[fetch all objects]'
'-v[show what is downloaded]'
'-w[write commit-id into the filename under "$GIT_DIR/refs/<filename>"]:filename'
'--recover[recover from a failed fetch]'
)
# TODO: Add descriptions to strategies (stupid is undocumented).
merge_args=(
'(-n --no-summary)'{-n,--no-summary}'[do not show diffstat at the end of the merge]'
'--no-commit[perform the merge but do not autocommit]'
'--squash[merge, but do not make a commit]'
'*'{-s,--strategy=-}'[use given merge strategy]:merge strategy:__git_merge_strategies'
)
force_ref_arg=('(-f --force)'{-f,--force}'[allow refs that are not ancestors to be updated]')
tags_fetch_arg=(
'(--no-tags -t --tags)--no-tags[disable automatic tag following]'
'(--no-tags -t --tags)'{-t,--tags}'[fetch remote tags]'
)
author_conversion_file_arg_spec='[specify author-conversion file]:author-conversion file:_files'
author_conversion_file_arg='-A'$author_conversion_file_arg_spec
long_author_conversion_file_arg='--authors-file=-'$author_conversion_file_arg_spec
verbose_arg='-v[produce verbose output]'
help_arg='-h[display usage information]'
upload_pack_arg=('(-u --upload-pack)'{-u,--upload-pack=-}'[specify path to git-upload-pack on remote side]:remote path')
common_fetch_args=(
'(-a --append)'{-a,--append}'[append ref names and object names of fetched refs to "$GIT_DIR/FETCH_HEAD"]'
$upload_pack_arg
$force_ref_arg
$tags_fetch_arg
'(-k --keep)'{-k,--keep}'[keep downloaded pack]'
'(-u --update-head-ok)'{-u,--update-head-ok}'[allow updates of current branch head]'
'--depth=-[deepen the history of a shallow repository by the given number of commits]: :_guard "[[\:guard\:]]" "depth"'
)
common_apply_args=(
'--whitespace=-[detect a new or modified line that ends with trailing whitespaces]: :__git_apply_whitespace_strategies'
'-p-[remove N leading slashes from traditional diff paths]: :_guard "[[\:digit\:]]#" number'
'-C-[ensure at least N lines of context match before and after each change]: :_guard "[[\:digit\:]]#" number')
template_arg='--template=-[directory to use as a template for the object database]:directory:_directories'
shared_arg='--shared=-[share repository amongst several users]::permissions:__git_repository_permissions'
thin_arg='--thin[minimize number of objects to be sent]'
__git_zstyle_default () {
zstyle -t $1 $2
if (( $status == 2 )); then
zstyle $*
fi
}
# TODO: Either skip uninteresting commands or skip the description - the list
# is just too long.
# NOTE: I'm coming to the opinion that skipping the description is the right
# thing to do…, but not 100% sure yet.
(( $+functions[_git_commands] )) ||
_git_commands () {
local -a base_commands
base_commands=(
'add:add paths to the index'
'apply:apply patch on a git index file and a work tree'
'bisect:find the change that introduced a bug'
'branch:create and show branches'
'checkout:checkout and switch to a branch'
'cherry-pick:cherry-pick the effect of an existing commit'
'clone:clone a repository into a new directory'
'commit:record changes to the repository'
'diff:show changes between commits, commit and working tree, etc.'
'fetch:download objects and a head from another repository'
'gc:cleanup unnecessary files and optimize thee local repository'
'grep:print lines matching a pattern'
'init:create empty git object database'
'log:show commit logs'
'merge:grand unified merge driver'
'mv:move or rename file, directory, or symlink'
'prune:prune all unreachable objects from the object database'
'pull:fetch from and merge with a remote repository'
'push:update remote refs along with associated objects'
'rebase:rebase local commits to new upstream head'
'reset:reset current HEAD to the specified state'
'revert:revert existing commit'
'rm:remove files from the working tree and from the index'
'show-branch:show branches and their commits'
"status:show working-tree's status"
'tag:create tag object signed with GPG'
'verify-tag:check GPG signature of a tag')
local -a additional_commands
additional_commands=(
'am:apply patches from a mailbox (cooler than applymbox)'
'annotate:annotate file lines with commit info'
'applymbox:apply patches from a mailbox'
'applypatch:apply one patch extracted from an e-mail'
'archive:create an archive of files from a named tree'
'blame:blame file lines on commits'
'cat-file:provide content or type information for repository objects'
'check-attr:display gitattributes information'
'check-ref-format:makes sure that a reference-name is well formed'
'checkout-index:copy files from the index to the working directory'
'cherry:find commits not merged upstream'
'clean:remove untracked files from the working tree'
'clone-pack:clone a repository into the current repository (transport)'
'commit-tree:create a new commit object'
'count-objects:count unpacked objects and display their disk consumption'
'describe:show the most recent tag that is reachable from a commit'
'diff-files:compare files in the working tree and the index'
'diff-index:compare content and mode of blobs between index and repository'
'diff-stages:compare two "merge states" in the index file'
'diff-tree:compare the content and mode of blobs found via two tree objects'
'fetch-pack:receive missing objects from another repository'
'imap-send:dump mailbox from stdin into imap folder'
'index-pack:build pack index file for an existing packed archive'
'local-fetch:duplicate another git repository on a local system'
'ls-remote:show references in a remote or local repository'
'ls-tree:display tree object in human-readable form'
'mailinfo:extract patch from a single e-mail message'
'mailsplit:split mbox file into a list of files'
'merge-base:find as good a common ancestor as possible for a merge'
'merge-file:run a three-way file merge'
'merge-index:run merge for files needing merging'
'merge-tree:show three-way merge without touching index'
'mktag:create tag object'
'mktree:build tree-object from ls-tree formatted text'
'name-rev:find symbolic names for given revisions'
'octopus:merge more than two commits'
'pack-objects:create packed archive of objects'
'pack-redundant:find redundant pack files'
'pack-refs:pack heads and tags for efficient repository access'
'parse-remote:routines to help parsing $GIT_DIR/remotes/'
'peek-remote:list references on a remote repository using the upload-pack protocol'
'prune-packed:remove extra objects that are already in pack files'
'read-tree:read tree information into the directory index'
'reflog:manage reflog information'
'relink:hardlink common objects in local repositories'
'repack:pack unpacked objects in a repository'
'request-pull:generate summary of pending changes'
'rerere:reuse recorded resolve'
'rev-list:list commit object in reverse chronological order'
'shortlog:summarize git log output'
'show:show various types of objects'
'show-index:display contents of a pack idx file'
'show-ref:list references in a local repository'
'symbolic-ref:read and modify symbolic references'
'tar-tree:create tar archive of the files in the named tree'
"unpack-file:create temporary file with blob's contents"
'unpack-objects:unpack objects out of packed archive'
'update-ref:update object name stored in a reference safely'
'update-server-info:update auxiliary information on a dumb server'
'var:display git logical variable'
'verify-pack:validate packed git archive files'
'whatchanged:show commit-logs and differences they introduce'
'write-tree:create tree from the current index')
local -a useful_commands
useful_commands=(
'format-patch:prepare patches for e-mail submission'
'ls-files:information about files in the index/working directory'
'config:get and set options in "$GIT_DIR/config"'
'instaweb:instantly browse your working repository in gitweb'
'remote:manage set of tracked repositories'
'send-email:send patch-e-mails out of "format-patch" output'
'update-index:modify index in some given way')
local -a interoperability_commands
interoperability_commands=(
'archimport:import an Arch repository into git'
'cvsexportcommit:export a commit to a CVS checkout'
'cvsimport:import a CVS "repository" into a git repository'
'svnimport:import SVN repository into git'
'quiltimport:apply a quilt patchset'
'svn:bidirectional operation between a single Subversion branch and git')
local -a ancillary_commands
ancillary_commands=(
'config:get and set repository or global options'
'convert-objects:convert old-style git repository'
'for-each-ref:output information on each ref'
'get-tar-commit-id:extract commit ID from an archive created using tar-tree'
'hash-object:compute object ID from a file'
'patch-id:compute unique ID for a patch'
'fsck:verify the connectivity and validity of the objects in the database'
'lost-found:recover lost references that luckily have not yet been pruned'
'mergetool:run merge conflict resolution tools to resolve merge conflicts')
local -a internal_commands
internal_commands=(
'daemon:start a really simple server for git repositories'
'fast-import:import information into git directly'
'fmt-merge-msg:produce merge commit message'
'http-fetch:download remote git repository via HTTP'
'http-push:push missing objects using HTTP/DAV'
'merge-one-file:standard helper-program to use with merge-index'
'receive-pack:command invoked by send-pack to receive what is pushed to it'
'rev-parse:pick out and massage parameters for other git commands'
'runstatus:a helper for git-status and git-commit'
'send-pack:push to remote repository, intelligently'
'shell:restricted login shell for GIT-only SSH access'
'ssh-fetch:pull from remote repository over an SSH connection'
'ssh-upload:"server-side" helper program used by ssh-fetch'
'stripspace:filter out empty lines'
'upload-archive:send archive back to git-archive'
'upload-pack:command invoked by clone-pack and fetch-pack')
local wanted_commands
zstyle -s ':completion:${curcontext}:' commands wanted_commands || wanted_commands="all -internal"
local -aU unique_wanted_commands
unique_wanted_commands=($=wanted_commands)
integer index_of_all=$(( $unique_wanted_commands[(I)all] ))
if (( index_of_all > 0 )); then
unique_wanted_commands[index_of_all]=()
unique_wanted_commands+=(base additional useful interoperability ancillary internal)
fi
for (( i = 0; i < $#unique_wanted_commands; i++ )); do
if [[ $unique_wanted_commands[i] == (#bq)-(*) ]]; then
unique_wanted_commands[i]=()
unique_wanted_commands[(I)$match[1]]=()
fi
done
local -a commands
for wanted_command in $unique_wanted_commands; do
case $wanted_command in
(base)
commands+=($base_commands) ;;
(additional)
commands+=($additional_commands) ;;
(useful)
commands+=($useful_commands) ;;
(interoperability)
commands+=($interoperability_commands) ;;
(ancillary)
commands+=($ancillary_commands) ;;
(internal)
commands+=($internal_commands) ;;
esac
done
_describe -t commands 'git command' commands && ret=0
}
(( $+functions[__git_aliases] )) ||
__git_aliases () {
declare -a aliases
# TODO: See __git_config_gettable_name for discussion on how to actually get
# out the names, skipping the values.
# TODO: Should check if the terminal is unicode capable. If so, use and
# instead of '.
aliases=(${^${${(M)${(f)"$(_call_program aliases git config --list)"}:#alias.*}#alias.}/(#b)=(*)/:alias for \'$match[1]}\')
__git_command_successful || return 0
local expl
_describe -t aliases 'git alias' aliases
}
(( $+functions[__git_aliases_and_commands] )) ||
__git_aliases_and_commands () {
_alternative \
'aliases: :__git_aliases' \
'commands: :_git_commands'
}
# NOTE: -c is undocumented.
# TODO: Perhaps provide some sort of completion or guard for line range (-L).
# NOTE: --score-debug is undocumented.
# NOTE: --show-name is undocumented.
# NOTE: --show-number is undocumented.
(( $+functions[_git-annotate] )) ||
_git-annotate () {
_arguments -S \
'-b[show blank SHA-1 for boundary commits]' \
'--root[do not treat root commits as boundaries]' \
'--show-stats[include additional statistics at the end of blame output]' \
'-c[undocumented]' \
'-l[show long rev]' \
'-t[show raw timestamp]' \
'-S[use revs from revs-file]:revs-file:_files' \
'-M-[detect moving lines in the file as well]:: :_guard "[[\:digit\:]]" "number of characters"' \
'*-C-[detect copied lines from other files from same commit as well]:: :_guard "[[\:digit\:]]" "number of characters"' \
'-L[annotate only the given line range]:line range' \
'--contents[annotate against the given file if no rev is specified]:file:_files' \
'--incremental[show results incrementally for machine processing]' \
'--score-debug[uncodumented]' \
'(-f --show-name)'{-f,--show-name}'[undocumented]' \
'(-n --show-number)'{-n,--show-number}'[undocumented]' \
'(-p --porcelain)'{-p,--porcelain}'[show results designed for machine processing]' \
'(-h --help)'{-h,--help}'[show help message]' \
':file:__git_cached_files' \
'::revision:__git_revisions' && ret=0
}
(( $+functions[_git-apply] )) ||
_git-apply () {
_arguments \
$nul_arg \
'--allow-binary-replacement[allow binary files to be patched]' \
'--apply[apply patches that would otherwise not be applied]' \
'--cached[apply patches without touching the working tree]' \
'--check[check if patches are applicable (turns off "apply")]' \
'--exclude=-[skip files matching specified pattern]:pattern' \
'--inaccurate-eof[work around missing-new-line-at-EOF bugs]' \
'--index[make sure that the patch is applicable to the index]' \
'--index-info[output information about original version of a blob if available]' \
'--no-add[ignore additions made by the patch]' \
'--numstat[same as --stat but in decimal notation and complete pathnames (turns off "apply")]' \
'(-R --reverse)'{-R,--reverse}'[apply patches in reverse]' \
'--reject[apply as much as possible, and leave rejected hunks in .rej files]' \
'--stat[output diffstat for the input (turns off "apply")]' \
'--summary[output summary of git-diff extended headers (turns off "apply")]' \
'--unidiff-zero[disable unified-diff-context check]' \
'(-v --verbose)'{-v,--verbose}'[report progress to stderr]' \
$common_apply_args \
'*::patch:_files' && ret=0
}
# NOTE: Documentation mentions options that dont exist anymore, for example,
# --since, and shows -C twice!aa
(( $+functions[_git-blame] )) ||
_git-blame () {
_git-annotate
}
(( $+functions[_git-checkout-index] )) ||
_git-checkout-index () {
_arguments -S \
$nul_arg \
'(-a --all :)'{-a,--all}'[check out all files in the index]' \
'(-f --force)'{-f,--force}'[force overwrite of existing files]' \
'(-n --no-create)'{-n,--no-create}'[do not checkout new files]' \
'--stage=-[check out files from named stage]:stage:(1 2 3 all)' \
'--stdin[read list of paths from the standard input]' \
'--temp[write the content to temporary files]' \
'--prefix=-[prefix to use when creating files]:directory:_directories' \
'(-q --quiet)'{-q,--quiet}'[do not complain about existing files or missing files]' \
'(-u --index)'{-u,--index}'[update stat information in index]' \
'*::file:__git_cached_files' && ret=0
}
(( $+functions[_git-clean] )) ||
_git-clean () {
_arguments \
'-d[remove untracked directories]' \
'-n[just show what would be done]' \
'-q[be quiet, only report errors]' \
'(-X -x)-x[do use ignore rules]' \
'(-X -x)-X[remove only files ignored by git]' && ret=0
}
(( $+functions[_git-commit-tree] )) ||
_git-commit-tree () {
if (( CURRENT == 2 )); then
__git_trees && ret=0
elif [[ $words[CURRENT-1] == -p ]]; then
local expl
_description commits expl 'parent commit'
__git_objects $expl && ret=0
else
compadd - '-p'
fi
}
(( $+functions[_git-hash-object] )) ||
_git-hash-object () {
_arguments -S \
'(:)--stdin[read object from standard input]' \
'-t[the type of object to create]:object type:((blob\:"a blob of data"
commit\:"a tree with parent commits"
tag\:"a symbolic name for another object"
tree\:"a recursive tree of blobs"))' \
'-w[write the object to the object database]' \
'(--stdin):file:_files' && ret=0
}
(( $+functions[_git-index-pack] )) ||
_git-index-pack () {
local -a stdin_arguments
if (( words[(I)--stdin] )); then
stdin_arguments=(
'--fix-thin[record deltified objects, based on objects not included]'
'--keep=-[create .keep file]::reason:')
fi
_arguments \
'-v[report progress to stderr]' \
'-o[write generated pack index into specified file]:file:_files' \
'--stdin[read pack from stdin and instead write to specified file]' \
$stdin_arguments \
':pack file:_files -g "*.pack"' && ret=0
}
(( $+functions[_git-init] )) ||
_git-init () {
_arguments \
$shared_arg \
$template_arg && ret=0
}
(( $+functions[_git-merge-file] )) ||
_git-merge-file () {
integer n_labels=${#${(M)words[1,CURRENT-1]:#-L}}
local label_argument
if (( n_labels < 3 )) || [[ $words[CURRENT-1] == -L ]]; then
local -a ordinals
ordinals=(first second third)
label_argument="*-L[label to use for the $ordinals[n_labels+1] file]:label"
fi
_arguments \
$label_argument \
'(-p --stdout)'{-p,--stdout}'[send merged file to standard output instead of overwriting first file]' \
'(-q --quiet)'{-q,--quiet}'[do not warn about conflicts]' \
':current file:_files' \
':base file:_files' \
':other file:_files' && ret=0
}
(( $+functions[_git-merge-index] )) ||
_git-merge-index () {
if (( CURRENT > 2 )) && [[ $words[CURRENT-1] != -[oq] ]]; then
_arguments -S \
'(:)-a[run merge against all files in the index that need merging]' \
'*:index file:__git_cached_files' && ret=0
else
declare -a arguments
(( CURRENT == 2 )) && arguments+='-o[skip failed merges]'
(( CURRENT == 2 || CURRENT == 3 )) && arguments+='(-o)-q[do not complain about failed merges]'
(( 2 <= CURRENT && CURRENT <= 4 )) && arguments+='*:merge program:_files -g "*(*)"'
_arguments -S $arguments && ret=0
fi
}
# TODO: Shouldnt we add a __git_branches type completion?
(( $+functions[_git-merge-tree] )) ||
_git-merge-tree () {
_arguments \
':base-tree:__git_tree_ishs' \
':branch 1:__git_tree_ishs' \
':branch 2:__git_tree_ishs' && ret=0
}
(( $+functions[_git-mktag] )) ||
_git-mktag () {
_message 'no arguments allowed; only accepts tags on standard input'
}
(( $+functions[_git-mktree] )) ||
_git-mktree () {
_arguments \
'-z[read NUL-terminated ls-tree -z output]' && ret=0
}
(( $+functions[_git-pack-objects] )) ||
_git-pack-objects () {
_arguments \
'(--revs)--all[include all refs as well as revisions already specified]' \
'--all-progress[force progress output, even during write-out phase]' \
'--delta-base-offset[use delta-base-offset packing]' \
'--depth=-[maximum delta depth]: :_guard "[[\:digit\:]]#" number' \
'--incremental[ignore objects that have already been packed]' \
'--no-reuse-delta[do not reuse existing deltas, but compute them from scratch]' \
'--non-empty[only create a package if it contains at least one object]' \
'--local[similar to --incremental, but only ignore unpacked non-local objects]' \
'--progress[force progress output]' \
'--revs[read revision arguments from standard input]' \
'(:)--stdout[write the pack to standard output]' \
'-q[do not report progress]' \
'(--revs)--unpacked[limit objects to pack to those not already packed]' \
'--window=-[number of objects to use per delta compression]: :_guard "[[\:digit\:]]#" number' \
'(--stdout):base-name:_files' && ret=0
}
(( $+functions[_git-prune-packed] )) ||
_git-prune-packed () {
_arguments -S \
'-n[only list the objects that would be removed]' \
'-q[suppress progress output]' && ret=0
}
(( $+functions[_git-read-tree] )) ||
_git-read-tree () {
local aggressive_arg
if (( words[(I)-m] )); then
aggressive_arg='--aggressive[try harder to resolve merge conflicts]'
fi
local -a ui_args
if (( words[(I)(-m|--reset|--prefix)] )); then
ui_args=(
'( -i)-u[update the work tree after successful merge]'
'(-u )-i[update only the index; ignore changes in work tree]')
fi
local exclude_per_directory_arg
if (( words[(I)-u] )); then
exclude_per_directory_arg='--exclude-per-directory=-[specify .gitignore file]:.gitignore file:_files'
fi
_arguments -A '-*' \
'( --reset --prefix)-m[perform a merge, not just a read]' \
'(-m --prefix)--reset[perform a merge, not just a read, ignoring unmerged entries]' \
'(-m --reset 2 3)--prefix=-[read the contents of specified tree-ish under specified directory]:prefix:_directories -r ""' \
$aggressive_arg \
$ui_args \
$exclude_per_directory_arg \
'1:first tree-ish to be read/merged:__git_tree_ishs' \
'2:second tree-ish to be read/merged:__git_tree_ishs' \
'3:third tree-ish to be read/merged:__git_tree_ishs' && ret=0
}
# TODO: Complete value regex somehow?
(( $+functions[_git-config] )) ||
_git-config () {
local name_arg
if (( words[(I)--get-regexp] )); then
name_arg=':name regex'
elif (( words[(I)--get(-all|)] )); then
name_arg=':name:__git_config_gettable_name'
else
name_arg=':name:__git_config_name'
fi
_arguments -A '--*' \
'( --global)--system[use system-wide config file]' \
'(--system )--global[use user-global config file]' \
'( --bool)--int[setting is an integer]' \
'(--int )--bool[setting is a boolean]' \
$name_arg \
":value:__git_config_values $words[CURRENT-1]" \
'::value regex' \
- '(actions)' \
'(: -)--rename-section[rename the given section]:section:__git_config_section_names:new name' \
'(: -)--remove-section[remove the given section]:section:__git_config_section_names' \
'(3 -)--add[add new value without altering any existing ones]' \
'(2 -)--unset[remove the first matching value of the key]' \
'(2 -)--unset-all[remove all matching values of the key]' \
'(2 -)--get[get the first matching value of the key]' \
'(2 -)--get-all[get all matching values of the key]' \
'(2 -)--get-regexp[like "--get-all", but interpret "name" as a regular expression]' \
'(-)--replace-all[replace all values of the given key]' \
'(: --int --bool)'{-l,--list}'[list all variables set in config file]' && ret=0
}
# NOTE: --track is undocumented.
# TODO: --track, -t, --master, and -m should take remote branches, I guess.
# NOTE: --master is undocumented.
# NOTE: --fetch is undocumented.
(( $+functions[_git-remote] )) ||
_git-remote () {
local curcontext=$curcontext state line
declare -A opt_args
_arguments -C \
':command:->command' \
'*::options:->options' && ret=0
case $state in
(command)
declare -a commands
commands=(
'add:add a new remote'
'show:show information about a given remote'
'prune:delete all stale tracking branches for a given remote'
'update:fetch updates for a set of remotes')
_describe -t commands 'sub-command' commands && ret=0
;;
(options)
case $line[1] in
(add)
_arguments \
'*'{--track,-t}'[track given branch instead of default glob refspec]:branch:__git_branch_names' \
'(--master -m)'{--master,-m}"[set the remote's HEAD to point to given master branch]:branch:__git_branch_names" \
'(--fetch -f)'{--fetch,-f}'[run git-fetch on the new remote after it has been created]' \
':branch name:__git_remotes' \
':url:_urls' && ret=0
;;
(show|name|prune)
__git_remotes && ret=0
;;
(update)
__git_remote-groups && ret=0
;;
esac
;;
esac
}
(( $+functions[_git-unpack-objects] )) ||
_git-unpack-objects () {
_arguments \
'-n[only list the objects that would be unpacked]' \
'-q[run quietly]' \
'-r[try recovering objects from corrupt packs]' && ret=0
}
(( $+functions[_git-update-index] )) ||
_git-update-index () {
local nul_arg
if (( words[(I)--stdin] )); then
nul_arg='-z[paths are separated with NUL instead of LF for --stdin]'
fi
_arguments -S \
$refreshables \
'--add[add files not already in the index]' \
'( --force-remove)--remove[remove files that are in the index but are missing from the work tree]' \
'(--remove )--force-remove[remove files from both work tree and the index]' \
'(-q --unmerged --ignore-missing)--refresh[refresh the index]' \
'-q[run quietly]' \
'--unmerged[if unmerged changes exists, ignore them instead of exiting]' \
'--ignore-missing[ignore missing files when refreshing the index]' \
'*--cacheinfo[insert information directly into the cache]: :_guard "[0-7]#" "octal file mode": :_guard "[[\:xdigit\:]]#" "object id":file:_files' \
'(: -)--index-info[read index information from stdin.]' \
'--chmod=-[set the execute permissions on the updated files]:permission:((-x\:executable +x\:"not executable"))' \
'( --no-assume-unchanged)--assume-unchanged[set the "assume unchanged" bit for the given paths]' \
'(--assume-unchanged )--no-assume-unchanged[unset the "assume unchanged" bit for the given paths]' \
'(-)'{-g,--again}'[run git-update-index on differing index entries]' \
'(-)--unresolve[restore "unmerged" or "needs updating" state of files]' \
'--info-only[only insert files object-IDs into index]' \
'--replace[replace files already in the index if necessary]' \
'(: -)--stdin[read list of paths from standard input]' \
'--verbose[report what is being added and removed from the index]' \
$nul_arg \
'*::file:_files' && ret=0
}
(( $+functions[_git-write-tree] )) ||
_git-write-tree () {
_arguments \
'--missing-ok[ignore objects in the index that are missing in the object database]'
'--prefix=-[write tree representing given sub-directory]:sub-directory:_directories -r ""' && ret=0
}
(( $+functions[_git-cat-file] )) ||
_git-cat-file () {
_arguments \
'( -s -e -p 1)-t[show the type of the given object]' \
'(-t -e -p 1)-s[show the size of the given object]' \
'(-t -s -p 1)-e[exit with zero status if object exists]' \
'(-t -s -e 1)-p[pretty-print the given object]' \
'(-t -s -e -p ):object type:(blob commit tag tree)' \
'(-t -s -e -p ):object:__git_objects' && ret=0
}
(( $+functions[_git-describe] )) ||
_git-describe () {
_arguments \
$abbrev_arg \
'--all[use any ref found in "$GIT_DIR/refs/"]' \
'--tags[use any tag found in "$GIT_DIR/refs/tags/"]' \
$abbrev_arg \
'--candidates=-[consider up to given number of canditates]: :_guard "[[\:digit\:]]##" "number of canditates"' \
'--debug[display information about the searching strategy]' \
'*:committish:__git_committishs' && ret=0
}
# TODO: Use __git_modified_files instead?
(( $+functions[_git-diff-index] )) ||
_git-diff-index () {
_arguments -S \
$diff_args \
'--cached[do not consider the work tree at all]' \
'-m[flag non-checked-out files as up-to-date]' \
':tree-ish:__git_tree_ishs' \
'*::index file:__git_cached_files' && ret=0
}
# TODO: Use __git_modified_files instead?
(( $+functions[_git-diff-files] )) ||
_git-diff-files () {
_arguments \
$diff_args \
'(-0 -1 -2 -3 --base --ours --theirs -c --cc --no-index)-0[omit diff output for unmerged entries]' \
'(-0 -1 -2 -3 --base --ours --theirs -c --cc --no-index)'{-1,--base}'[diff against "base" version]' \
'(-0 -1 -2 -3 --base --ours --theirs -c --cc --no-index)'{-2,--ours}'[diff against "our branch" version]' \
'(-0 -1 -2 -3 --base --ours --theirs -c --cc --no-index)'{-3,--theirs}'[diff against "their branch" version]' \
'(-0 -1 -2 -3 --base --ours --theirs -c --cc --no-index)'{-c,--cc}'[compare "our branch", "their branch" and working tree files]' \
'(-0 -1 -2 -3 --base --ours --theirs -c --cc --no-index --exit-code *)--no-index[compare given files / directories]' \
'-q[remain silent even on nonexisting files]' \
'1:file:_files' \
'2:file:_files' \
'*::file:_files' && ret=0
}
# TODO: Use __git_modified_files instead?
(( $+functions[_git-diff-stages] )) ||
_git-diff-stages () {
_arguments \
$diff_args \
':stage 1:__git_stages' \
':stage 2:__git_stages' \
'*::index file:_files' && ret=0
}
# TODO: Use __git_modified_files instead?
(( $+functions[_git-diff-tree] )) ||
_git-diff-tree () {
local curcontext=$curcontext state line
declare -A opt_args
_arguments -C -S \
$diff_args \
$pretty_arg \
'--encoding=-[re-code commit log-message in given encoding]::log-message encoding:__git_encodings' \
'--no-commit-id[skip output of commit IDs]' \
'--root[show diff against the empty tree]' \
'--stdin[read commit and tree information from standard input]' \
'-m[show merge commits]' \
'-r[recurse into subdirectories]' \
'(-r)-t[show tree entry itself as well as subtrees (implies -r)]' \
'-s[do not show differences]' \
'-v[show commit message before the differences]' \
'(-c --cc)-c[show differences from each of the parents to the merge result]' \
'(-c --cc)--cc[how differences from each of the parents and omit differences from only one parent]' \
'--always[always show commit itself and the commit log message]' \
':tree-ish:__git_tree_ishs' \
'*::file:->files' && ret=0
case $state in
files)
if (( $#line > 2 )); then
# TODO: this is probably just stupid to do.
# What'd be nice would be
# common files:
# ...
# original tree:
# ...
# new tree:
# ...
_alternative \
"original tree:original tree:__git_tree_files $line[1]" \
"new tree:new tree:__git_tree_files $line[2]" && ret=0
else
_alternative \
': :__git_tree_ishs' \
": :__git_tree_files $line[1]" && ret=0
fi
;;
esac
}
# TODO: Better completion for --format: should complete %(field) stuff, that
# is, %(refname), %(objecttype), %(objectsize), %(objectname) with optional *
# in front.
# TODO: Documentation says that --count can be given * number of times, but
# sources beg to differ, allowing only one.
(( $+functions[_git-for-each-ref] )) ||
_git-for-each-ref () {
_arguments -S \
'--format=-[output format of ref information]:format' \
'(-s --shell -p --perl --python --tcl)'{-s,--shell}'[use string literals suitable for sh]' \
'(-s --shell -p --perl --python --tcl)'{-p,--perl}'[use string literals suitable for Perl]' \
'(-s --shell -p --perl --tcl)'--python'[use string literals suitable for Python]' \
'(-s --shell -p --perl --python )'--tcl'[use string literals suitable for Tcl]' \
'--count=-[maximum number of refs to iterate over]: :_guard "[[\:digit\:]]#" "maximum number of refs"' \
'--sort=-[key to sort refs by]:sort key:__git_ref_sort_keys' \
':: :_guard "([^-]?#|)" pattern' && ret=0
}
(( $+functions[_git-fmt-merge-msg] )) ||
_git-fmt-merge-msg () {
arguments \
'( --no-summary)--summary[add one-line descriptions from commits being merged]' \
'(--summary )--no-summary[do not add one-line descriptions from commits being merged]' \
'(-F --file)'{-F,--file}'[specify list of merged objects from file]:file:_files' && ret=0
}
(( $+functions[_git-fsck] )) ||
_git-fsck () {
_arguments \
'--cache[consider objects recorded in the index as head nodes for reachability traces]' \
'--full[check all object directories]' \
'--root[show root nodes]' \
'--strict[do strict checking]' \
'--tags[show tags]' \
'--unreachable[show objects that are unreferenced in the object database]' \
'*::object:__git_objects' && ret=0
}
(( $+functions[_git-ls-files] )) ||
_git-ls-files () {
local no_empty_directory_arg
if (( words[(I)--directory] )); then
no_empty_directory_arg='--no-empty-directory[do not list empty directories]'
fi
_arguments -S \
$nul_arg \
'(-c --cached)'{-c,--cached}'[show cached files in the output]' \
'(-d --deleted)'{-d,--deleted}'[show deleted files in the output]' \
'(-i --ignored)'{-i,--ignored}'[show ignored files in the output]' \
'(-k --killed)'{-k,--killed}'[show killed files in the output]' \
'(-m --modified)'{-m,--modified}'[show modified files in the output]' \
'(-o --others)'{-o,--others}'[show other files in the output]' \
'(-s --stage)'{-s,--stage}'[show stage files in the output]' \
'(-u --unmerged)'{-u,--unmerged}'[show unmerged files in the output]' \
'( -v)-t[identify each files status (HMRCK?)]' \
'(-t )-v[identify each files status (hmrck?)]' \
'*'{-x,--exclude=-}'[skip files matching given pattern]:file pattern' \
'*'{-X,--exclude-from=-}'[skip files matching patterns in given file]:file:_files' \
'*--exclude-per-directory=-[skip directories matching patterns in given file]:file:_files' \
'--directory[if a whole directory is classified as "other", show just its name]' \
$no_empty_directory_arg \
'--error-unmatch[if any <file> does not appear in the index, treat this as an error]' \
'--full-name[force paths to be output relative to the project top directory]' \
$abbrev_arg \
'*::index file:_files' && ret=0
}
(( $+functions[_git-ls-tree] )) ||
_git-ls-tree () {
local curcontext=$curcontext state line
declare -A opt_args
_arguments -C \
$nul_arg \
$abbrev_arg \
'(-t)-d[do not show children of given tree (implies -t)]' \
{--name-only,--name-status}'[list only filenames, one per line]' \
'-r[recurse into subdirectories]' \
'-t[show tree entries even when going to recurse them]' \
'--full-name[output full path-names]' \
':tree-ish:__git_tree_ishs' \
'*::tree file:->files' && ret=0
case $state in
files)
__git_tree_files $line[1] && ret=0
;;
esac
}
(( $+functions[_git-imap-send] )) ||
_git-imap-send () {
_message 'no arguments allowed; accepts mailbox file on standard input'
}
(( $+functions[_git-quiltimport] )) ||
_git-quiltimport () {
_arguments \
"--dry-run[check patches and warn if they can't be imported]" \
'--author[default author name and email address to use for patches]' \
'--patches[set directory containing patches]:patch directory:_directories' && ret=0
}
(( $+functions[_git-merge-base] )) ||
_git-merge-base () {
_arguments \
'(-a --all)'{-a,--all}'[show all common ancestors]' \
':commit 1:__git_commits' \
':commit 2:__git_commits' && ret=0
}
(( $+functions[_git-name-rev] )) ||
_git-name-rev () {
_arguments -S \
'--tags[only use tags to name the commits]' \
'--refs=-[only use refs matching given pattern]: :_guard "?#" "shell pattern"' \
'(--stdin :)--all[list all commits reachable from all refs]' \
'(--all :)--stdin[read from stdin and append revision-name]' \
'(--stdin --all)*:commit-ish:__git_revisions' && ret=0
}
(( $+functions[_git-pack-redundant] )) ||
_git-pack-redundant () {
_arguments \
'(:)--all[process all packs]' \
'--alt-odb[do not require objects to be present in local packs]' \
'--verbose[output some statistics to stderr]' \
'(--all)*::packs:_files -g "*.pack"' && ret=0
}
# TODO: --timestamp undocumented.
# TODO: __git_commits2 should be reworked/reworded.
(( $+functions[_git-rev-list] )) ||
_git-rev-list () {
if (( words[(I)--] && words[(I)--] != CURRENT )); then
_arguments \
'*:index file:__git_cached_files' && ret=0
else
__git_setup_revision_arguments
_arguments -S \
$revision_arguments \
'(--pretty)--header[show commit headers]' \
'--remote-empty[stop when a given path disappears from the tree]' \
'--timestamp[undocumented]' \
'( --bisect-vars)--bisect[show only the middlemost commit object]' \
'(--bisect )--bisect-vars[same as --bisect, outputing shell-evalable code]' \
'--stdin[read commit objects from standard input]' \
'*:commit id:__git_commits2' && ret=0
fi
}
(( $+functions[_git-show-ref] )) ||
_git-show-ref () {
_arguments -S \
- list \
'(-h --head)'{-h,--head}'[show the HEAD reference]' \
'--tags[show only "refs/tags"]' \
'--heads[show only "refs/heads"]' \
'(-d --dereference)'{-d,--dereference}'[dereference tags into object IDs as well]' \
'(-s --hash)'{-s+,--hash=-}'[only show the SHA-1 hash, not the reference name]:: :_guard "[[\:digit\:]]#" length' \
'--verify[enable stricter reference checking]' \
$abbrev_arg \
'(-q --quiet)'{-q,--quiet}'[do not print any results to stdout]' \
'*: :_guard "([^-]?#|)" pattern' \
- exclude \
'--exclude-existing=-[filter out existing refs from stdin]:: :_guard "([^-]?#|)" pattern' && ret=0
}
(( $+functions[_git-show] )) ||
_git-show () {
__git_setup_revision_arguments
_arguments -S \
$revision_arguments \
'*:object:__git_revisions' && ret=0
}
(( $+functions[_git-show-index] )) ||
_git-show-index () {
_message 'no arguments allowed; accepts index file on standard input'
}
(( $+functions[_git-tar-tree] )) ||
_git-tar-tree () {
_arguments \
'--remote=-[retrieve a tar archive from a remote repository]:__git_remote_repository' \
':tree-ish:__git_tree_ishs' \
':base:_files' && ret=0
}
(( $+functions[_git-unpack-file] )) ||
_git-unpack-file () {
_arguments \
':blob id:__git_blobs' && ret=0
}
(( $+functions[_git-var] )) ||
_git-var () {
_arguments \
'(:)-l[show logical variables]' \
'(-):variable:((GIT_AUTHOR_IDENT\:"name and email of the author" \
GIT_COMMITTER_IDENT\:"name and email of committer"))' && ret=0
}
(( $+functions[_git-verify-pack] )) ||
_git-verify-pack () {
_arguments -S \
'-v[show objects contained in pack]' \
'*:index file:_files -g "*.idx"' && ret=0
}
(( $+functions[_git-clone-pack] )) ||
_git-clone-pack () {
_arguments \
$exec_arg \
':repository:__git_any_repositories' \
'*:head:__git_heads' && ret=0
}
(( $+functions[_git-fetch-pack] )) ||
_git-fetch-pack () {
_arguments \
'--all[fetch all remote refs]' \
'(-q --quiet)'{-q,--quiet}'[make output less verbose]' \
'(-k --keep)'{-k,--keep}'[do not invoke git-unpack-objects on received data]' \
$thin_arg \
'(--upload-pack --exec)'{--upload-pack=-,--exec=-}'[specify path to git-upload-pack on remote side]:remote path' \
'--depth=-[limit fetching to ancestor-chains not longer than given number]: :_guard "[[\:digit\:]]#" "maximum ancestor-chain length"' \
'--no-progress[do not show progress]' \
$verbose_arg \
':repository:__git_any_repositories' \
'*:references:__git_references' && ret=0
}
(( $+functions[_git-fast-import] )) ||
_git-fast-import () {
_arguments \
'--date-format=-[specify the types of dates being passed]:((raw\:"native git format"
rfc2822\:"standard email format"
now\:"use current time and timezone"))' \
'--max-pack-size=-[maximum size of each packfile]: :_guard "[[\:digit\:]]#" "maximum pack size"' \
'--depth=-[maximum delta depth for blob and tree deltification]: :_guard "[[\:digit\:]]#" "maximum delta depth"' \
'--active-branches=-[maximum number of branches to maintain active at once]: :_guard "[[\:digit\:]]#" "maximum number of branches"' \
'--export-marks=-[dump the internal marks table to given file]:export file:_files' \
'--export-pack-edges=-[list packfiles and last commit on branches in them in given file]:export file:_files' \
'--force[force updating modified existing branches]' \
'--quiet[disable all non-fatal output]' \
'--stats[display statistics about object created]' && ret=0
}
(( $+functions[_git-http-fetch] )) ||
_git-http-fetch () {
_arguments \
$fetch_args \
'(1)--stdin[read commit ids and refs from standard input]' \
':commit id:__git_commits' \
':URL:_urls' && ret=0
}
(( $+functions[_git-http-push] )) ||
_git-http-push () {
_arguments \
'--all[verify that all objects in local ref history exist remotely]' \
'--complete[do not assume that the remote repository is complete]' \
'--force[allow refs that are not ancestors to be updated]' \
'--verbose[report the list of objects being walked locally and sent to the remote]' \
'( -D)-d[remove refs from remote repository]' \
'(-d )-D[forcefully remove refs from remote repository]' \
':URL:_urls' \
'*:remote refs:__git_remote_references' && ret=0
}
(( $+functions[_git-local-fetch] )) ||
_git-local-fetch () {
_arguments \
$fetch_args \
'-l[hard-link objects]' \
'-n[do not copy objects]' \
'-s[sym-link objects]' \
'(1)--stdin[read commit ids and refs from standard input]' \
':commit id:__git_commits' \
':directory:_directories' && ret=0
}
# TODO: --tags undocumented.
# TODO: --heads undocumented.
# TODO: --refs undocumented.
(( $+functions[_git-peek-remote] )) ||
_git-peek-remote () {
_arguments \
'--upload-pack=-[specify path to git-upload-pack on remote side]:remote path' \
$exec_arg \
'--tags[undocumented]' \
'--heads[undocumented]' \
'--refs[undocumented]' \
':repository:__git_repository' && ret=0
}
(( $+functions[_git-sh-setup] )) ||
_git-sh-setup () {
_message "you probably should not be issuing this command; it is an internal git helper"
}
# TODO: --dry-run undocumented.
# TODO: -n undocumented.
# TODO: --stale-fix undocumented.
# TODO: --verbose undocumented.
# TODO: -- undocumented.
(( $+functions[_git-reflog] )) ||
_git-reflog () {
__git_setup_revision_arguments
if (( CURRENT == 2 )); then
local curcontext=$curcontext state line
declare -A opt_args
_arguments -C \
$revision_arguments \
':subcommand:->subcommand' && ret=0
case $state in
(subcommand)
declare -a reflog_cmds
reflog_cmds=(
'expire:prune old reflog entries'
'show:show log of the current branch')
_describe -t subcommands 'subcommands' reflog_cmds && ret=0
;;
esac
else
case $words[2] in
(expire)
_arguments -S \
'(-n --dry-run)'{-n,--dry-run}'[undocumented]' \
'--expire=-[prune entries older than given time]:date' \
'--expire-unreachable=-[prune entries older than given time and unreachable]:date' \
'--stale-fix[undocumented]' \
'--all[prune all refs]' \
'--verbose' && ret=0
;;
(show|--*)
_arguments -S \
$revision_arguments \
':subcommand:' && ret=0
;;
esac
fi
}
(( $+functions[_git-receive-pack] )) ||
_git-receive-pack () {
_arguments \
':directory to sync into:_directories' && ret=0
}
(( $+functions[_git-shell] )) ||
_git-shell () {
local curcontext=$curcontext state line
declare -A opt_args
_arguments -C \
'-c[command to execute]:command:->commands' \
':argument to command:->arguments' && ret=0
case $state in
(commands)
declare -a commands
commands=(git-receive-pack git-upload-pack)
_describe -t commands command commands && ret=0
;;
(arguments)
case $line[1] in
(git-receive-pack)
local expl
_description directories expl 'directory to sync into'
_directories $expl
;;
(git-upload-pack)
local expl
_description directories expl 'directory to sync from'
_directories $expl
;;
esac
;;
esac
}
(( $+functions[_git-upload-archive] )) ||
_git-upload-archive () {
_arguments \
':directory to get tar archive from:_directories' && ret=0
}
(( $+functions[_git-send-pack] )) ||
_git-send-pack () {
_arguments \
'(--receive-pack --exec)'{--receive-pack=-,--exec=-}'[specify path to git-receive-pack on remote side]:remote path'
'--all[update all refs that exist locally]' \
'--force[update remote orphaned refs]' \
$verbose_arg \
$thin_arg \
':repository:__git_any_repositories' \
'*:remote refs:__git_remote_references' && ret=0
}
(( $+functions[_git-ssh-fetch] )) ||
_git-ssh-fetch () {
_arguments \
$fetch_args \
':commit id:__git_commits' \
':URL:_urls' && ret=0
}
(( $+functions[_git-ssh-upload] )) ||
_git-ssh-upload () {
_arguments \
$fetch_args \
':commit id:__git_commits' \
':URL:_urls' && ret=0
}
(( $+functions[_git-update-server-info] )) ||
_git-update-server-info () {
_arguments \
'(-f --force)'{-f,--force}'[update the info files from scratch]' && ret=0
}
(( $+functions[_git-upload-pack] )) ||
_git-upload-pack () {
_arguments \
'--strict[do not try <directory>/.git/ if <directory> is not a git directory' \
'--timeout=-[interrupt transfer after given number of seconds of inactivity]: :_guard "[[\:digit\:]]" "inactivity timeout"' \
':directory:_directories' && ret=0
}
(( $+functions[_git-add] )) ||
_git-add () {
local curcontext=$curcontext state line
declare -A opt_args
_arguments -C -S \
'-n[do not actually add files; only show which ones would be added]' \
'-v[show files as they are added]' \
'-f[allow adding otherwise ignored files]' \
'(-i --interactive : -)'{-i,--interactive}'[add contents interactively to the index]' \
'*:file:->files' && ret=0
case $state in
(files)
declare -a ignored_files_alternatives
if (( words[(I)-f] )); then
ignored_files_alternatives=(
'ignored-modified-files:ignored modified files:__git_modified_files --ignored'
'ignored-other-files:ignored other files:__git_other_files --ignored')
fi
_alternative \
'modified-files:modified files:__git_modified_files' \
'other-files:other files:__git_other_files' \
$ignored_files_alternatives && ret=0
;;
esac
}
__git_zstyle_default ':completion::complete:git-add:argument-rest:*' ignore-line yes
(( $+functions[_git-am] )) ||
_git-am () {
_arguments \
'--3way[use 3-way merge if patch does not apply cleanly]' \
'--binary[pass "--allow-binary-replacement" to "git-apply"]' \
'--dotest=-[use given directory as working area instead of .dotest]:directory:_directories' \
'--interactive[apply patches interactively]' \
'--keep[pass "-k" flag to "git-mailinfo"]' \
'--resolved[continue after resolving patch failure by hand]' \
'--signoff[add "Signed-off-by:" line to the commit message]' \
'--skip[skip the current patch]' \
'--utf8[pass "-u" flag to "git-mailinfo"]' \
'--no-utf8[do not pass "-u" flag to "git-mailinfo"]' \
$common_apply_args \
'*:mbox file:_files' && ret=0
}
(( $+functions[_git-archive] )) ||
_git-archive () {
local curcontext=$curcontext state line
declare -A opt_args
declare -a backend_args
if (( words[(I)--format=*] > 0 && words[(I)--format=*] < CURRENT )); then
case ${words[$words[(I)--format=*]]#--format=} in
(zip)
backend_args=(
'-0[do not deflate files]'
'-1[minimum compression]'
'-2[a little more compression]'
'-3[slightly more compression]'
'-4[a bit more compression]'
'-5[even more compression]'
'-6[slightly even more compression]'
'-7[getting there]'
'-8[close to maximum compression]'
'-9[maximum compression]')
;;
esac
fi
_arguments -C \
'--format=-[format of the resulting archive]:archive format:__git_archive_formats' \
'(- :)--list[list available archive formats]' \
'--prefix=-[prepend the given path prefix to to each filename]:path prefix:_directories -r ""' \
$backend_args \
'--remote=-[archive remote repository]:remote repository:__git_any_repositories' \
':tree-ish:__git_tree_ishs' \
'*:tree file:->files' && ret=0
case $state in
(files)
__git_tree_files $line[1] && ret=0
;;
esac
}
(( $+functions[_git-applymbox] )) ||
_git-applymbox () {
_arguments -A '-*' \
'-k[do not modify "Subject:" header]' \
'-m[apply patches with "git-apply" and fail if patch is unclean]' \
'-q[apply patches interactively]' \
'-u[encode commit information in UTF-8]' \
'(1)-c[restart command after fixing an unclean patch]:patch:_files -g ".dotest/0*"' \
':mbox file:_files' \
'::signoff file:__git_signoff_file' && ret=0
}
(( $+functions[_git-bisect] )) ||
_git-bisect () {
local bisect_cmds
bisect_cmds=(
bad:"mark current or given revision as bad"
good:"mark current or given revision as good"
log:"show the log of the current bisection"
next:"find next bisection to test and check it out"
replay:"replay a bisection log"
reset:"finish bisection search and return to the given branch (or master)"
start:"reset bisection state and start a new bisection"
visualize:"show the remaining revisions in gitk"
)
if (( CURRENT == 2 )); then
_describe -t command "git-bisect commands" bisect_cmds && ret=0
else
case $words[2] in
(bad)
_arguments \
'2:revision:__git_commits' && ret=0
;;
(good)
_arguments \
'*:revision:__git_commits' && ret=0
;;
(replay)
_arguments \
'2:file:_files' && ret=0
;;
(reset)
_arguments \
'2:branch:__git_heads' && ret=0
;;
(*)
_nothing
;;
esac
fi
}
# TODO: complete branch names?
(( $+functions[_git-branch] )) ||
_git-branch () {
local my_abbrev_arg
if (( words[(I)-v] > 0 && words[(I)-v] < CURRENT )); then
my_abbrev_arg=$abbrev_arg
fi
declare -a dependent_deletion_args
if (( words[(I)-d] || words[(I)-D] )); then
dependent_deletion_args=(
'-r[delete remote-tracking branches]'
'*:branch-name:__git_branch_names')
fi
declare -a dependent_modification_args
if (( words[(I)-m] || words[(I)-M] )); then
dependent_modification_args=(
':old or new branch-name:__git_branch_names'
'::new branch-name:__git_branch_names')
fi
# TODO: Im not happy with having to force a pattern with -A.
_arguments -S -A "-*" \
- list \
'( --no-color)--color[turn on branch coloring]' \
'(--color )--no-color[turn off branch coloring]' \
'( -a)-r[list only the remote-tracking branches]' \
'(-r )-a[list both remote-tracking branches and local branches]' \
'-v[show SHA1 and commit subject line for each head]' \
$my_abbrev_arg \
- create \
"-l[create the branch's reflog]" \
'-f[force the creation of a new branch]' \
':branch-name:__git_branch_names' \
'::start-point:__git_revisions' \
- modify \
'( -M)-m[rename a branch and the corresponding reflog]' \
'(-m )-M[rename a branch even if the new branch-name already exists]' \
$dependent_modification_args \
- delete \
'( -D)-d[delete a fully merged branch]' \
'(-d )-D[delete a branch]' \
$dependent_deletion_args && ret=0
}
__git_zstyle_default ':completion::complete:git-branch:delete-argument-rest:*' ignore-line yes
# TODO: __git_tree_ishs is just stupid. It should be giving us a list of tags
# and perhaps also allow all that just with ^{tree} and so on. Not quite sure
# how to do that, though.
(( $+functions[_git-checkout] )) ||
_git-checkout () {
local curcontext=$curcontext state line
declare -A opt_args
local new_branch_reflog_arg
if (( words[(I)-b] > 0 )); then
new_branch_reflog_arg="-l[create the new branch's reflog]"
fi
# TODO: This isnt quite correct in regards of the handling of the “--”
# option, as it should prevent us from seeing a branch, not stop matching
# options.
_arguments -C -S -A "-*" \
- switch-branch \
'-q[suppress feedback messages]' \
'-f[force a complete re-read]' \
'-b[create a new branch based at given branch]: :__git_guard_branch-name' \
$new_branch_reflog_arg \
'-m[3way merge current branch, working tree and new branch]' \
'::branch:__git_revisions' \
- update-files \
'::tree-ish:__git_tree_ishs' \
'::file:->files' && ret=0
case $state in
(files)
if [[ -n $line[1] ]]; then
__git_tree_files $line[1] && ret=0
else
__git_cached_files && ret=0
fi
;;
esac
}
(( $+functions[_git-cherry-pick] )) ||
_git-cherry-pick () {
_arguments \
'(-e --edit)'{-e,--edit}'[edit commit before committing the revert]' \
'(-n --no-commit)'{-n,--no-commit}'[do not make the actually commit]' \
'(-r --replay)'{-r,--replay}'[use original commit message intact]' \
'-x[append information about what commit was cherry-picked]' \
':commit:__git_revisions' && ret=0
}
(( $+functions[_git-clean] )) ||
_git-clean () {
_arguments -S \
'-d[also remove untracked directories]' \
'-n[do a dry run]' \
'-q[run quietly]' \
'(-X )-x[also remove ignored files]' \
'( -x)-X[remove only ignored files]' \
'*:file:_files' && ret=0
}
# TODO: The --no-checkout is undocumented.
(( $+functions[_git-clone] )) ||
_git-clone () {
local -a shared
if (( words[(I)(-l|--local)] )); then
shared=('(-s --shared)'{-s,--shared}'[share the objects with the source repository]')
fi
_arguments \
'--bare[make a bare GIT repository]' \
'(-l --local)'{-l,--local}'[perform a local cloning of a repository]' \
$shared \
'--reference[reference repository]:repository:_directories' \
'(-q --quiet)'{-q,--quiet}'[operate quietly]' \
'-n[do not checkout HEAD after clone is complete]' \
'(-o --origin)'{-o,--origin}'[use given name instead of "origin" as branch name]:name:__git_guard_branch-name' \
$upload_pack_arg \
$template_arg \
'--depth[create a shallow clone, given number of revisions deep]: :_guard "[[\:digit\:]]##" depth' \
':repository:__git_any_repositories' \
'*:directory:_directories' && ret=0
}
(( $+functions[_git-commit] )) ||
_git-commit () {
_arguments -S \
'(-a --all)'{-a,--all}'[update all paths in the index file]' \
'--author[override the author name used in the commit]:author name' \
'(-e --edit)'{-e,--edit}'[edit the commit message before committing]' \
'(-o --only -i --include)'{-i,--include}'[update the given files and commit the whole index]' \
'(-o --only -i --include)'{-o,--only}'[commit only the given files]' \
'(-n --no-verify)'{-n,--no-verify}'[do not look for suspicious lines the commit introduces]' \
'(-s --signoff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \
'(-q --quiet -v --verbose)'{-q,--quiet}'[suppress commit summary message]' \
'(-q --quiet -v --verbose)'{-v,--verbose}'[show unified diff of all file changes]' \
'(-u --untracked-files)'{-u,--untracked-files}'[show files in untracked directories]' \
'*:file:__git_modified_files' \
- '(message)' \
'--amend[amend the tip of the current branch]' \
{-c,--reedit-message=}'[use existing commit object and edit log message]:commit:__git_commits' \
{-C,--reuse-message=}'[use existing commit object with same log message]:commit:__git_commits' \
{-F,--file=}'[read commit message from given file]:file:_files' \
{-m,--message=}'[use the given message as the commit message]:message' && ret=0
}
__git_zstyle_default ':completion::complete:git-commit:argument-rest:*' ignore-line yes
# TODO: __git_files should be __git_tree_files (do like in git-diff-tree and
# such)
(( $+functions[_git-diff] )) ||
_git-diff () {
_arguments -S \
$diff_args \
'::original revision:__git_commits' \
'::new revision:__git_commits' \
'*::index file:__git_modified_files' && ret=0
}
(( $+functions[_git-fetch] )) ||
_git-fetch () {
_arguments \
$common_fetch_args \
':repository:__git_any_repositories' \
'*:refspec:__git_ref_specs' && ret=0
}
(( $+functions[_git-format-patch] )) ||
_git-format-patch () {
_arguments \
$diff_args \
'(-h --help)'{-h,--help}'[display usage information]' \
'(-k --keep-subject -n --numbered)'{-k,--keep-subject}'[do not strip/add \[PATCH\] from the first line of the commit message]' \
'(-k --keep-subject -n --numbered)'{-n,--numbered}'[name output in \[PATCH n/m\] format]' \
'--start-number=[start numbering patches at given number]: :_guard "[[\:digit\:]]" "patch number"' \
'(-o --output-directory --stdout)'{-o,--output-directory}'[store resulting files in given directory]:directory:_directories' \
'(-o --output-directory)--stdout[output the generated mbox on standard output (implies --mbox)]' \
'(-s --signoff)'{-s,--signoff}'[add "Signed-off-by:" line to the commit message]' \
'--attach=-[create attachments instead of inlining patches]::git version string' \
'--thread[make the second and subsequent mails refer to the first]' \
'--in-reply-to=[make the first mail a reply to the given message]:message id' \
'--ignore-if-in-upstream[do not include a patch that matches a commit in the given range]' \
'--suffix[use the given suffix for filenames]:filename suffix' \
':commit range:__git_commit_ranges' && ret=0
}
(( $+functions[_git-gc] )) ||
_git-gc () {
_arguments \
'--prune[remove unreferenced loose objects]' && ret=0
}
(( $+functions[_git-grep] )) ||
_git-grep () {
local -a pattern_operators
if (( words[(I)-e] == CURRENT - 2 )); then
pattern_operators=(
'--and[both patterns must match]'
'--or[either pattern must match]'
'--not[the following pattern must not match]')
fi
local curcontext=$curcontext state line
declare -A opt_args
_arguments -A '--*' \
'--cached[grep blobs registered in index file instead of working tree]' \
'(-a --text)'{-a,--text}'[process binary files as if they were text]' \
'(-i --ignore-case)'{-i,--ignore-case}'[ignore case when matching]' \
'(-w --word-regexp)'{-w,--word-regexp}'[match only whole words]' \
'(-v --invert-match)'{-v,--invert-match}'[select non-matching lines]' \
'( -H)-h[supress output of filenames]' \
'(-h )-H[show filenames]' \
'--full-name[output paths relative to the project top directory]' \
'(-E --extended-regexp -G --basic-regexp)'{-E,--extended-regexp}'[use POSIX extended regexes]' \
'(-E --extended-regexp -G --basic-regexp)'{-G,--basic-regexp}'[use POSIX basic regexes]' \
'-n[prefix the line number to matching lines]' \
'(-l --files-with-matches -L --files-without-match)'{-l,--files-with-match}'[show only names of matching files]' \
'(-l --files-with-matches -L --files-without-match)'{-L,--files-without-match}'[show only names of non-matching files]' \
'(-c --count)'{-c,--count}'[show number of matching lines in files]' \
'-A[show trailing context]: :_guard "[[\:digit\:]]#" lines' \
'-B[show leading context]: :_guard "[[\:digit\:]]#" lines' \
'-C[show context]: :_guard "[[\:digit\:]]#" lines' \
'(1)*-f[read patterns from given file]:pattern file:_files' \
'(1)*-e[use the given pattern for matching]:pattern' \
$pattern_operators \
'--all-match[all patterns must match]' \
':pattern:' \
'*::tree-or-file:->files' && ret=0
case $state in
(files)
integer first_tree last_tree start end
(( start = words[(I)(-f|-e)] > 0 ? 1 : 2 ))
(( end = $#line - 1 ))
for (( i = start; i <= end; i++ )); do
[[ line[i] == '--' ]] && break
git cat-file -e "${(Q)line[i]}^{tree}" 2>/dev/null || break
if (( first_tree == 0 )); then
(( first_tree = last_tree = i ))
else
(( last_tree = i ))
fi
done
if (( last_tree == 0 || last_tree == end )); then
if (( first_tree == 0 )); then
_alternative \
'tree:tree:__git_trees' \
"file:file:__git_cached_files" && ret=0
else
_alternative \
'tree:tree:__git_trees' \
"tree file:tree-files:__git_tree_files $line[first_tree,last_tree]" && ret=0
fi
else
if (( first_tree == 0 )); then
__git_cached_files
else
__git_tree_files $line[first_tree,last_tree]
fi
fi
;;
esac
}
(( $+functions[_git-log] )) ||
_git-log () {
__git_setup_revision_arguments
_arguments -S \
"$revision_arguments[@]" \
'*:tree-ish: _alternative c\:\:__git_committishs f\:\:_files' && ret=0
}
# TODO: repository needs fixing
(( $+functions[_git-ls-remote] )) ||
_git-ls-remote () {
_arguments \
'(-h --heads)'{-h,--heads}'[show only refs under refs/heads]' \
'(-t --tags)'{-t,--tags}'[show only refs under refs/tags]' \
$upload_pack_arg \
':repository:__git_any_repositories' \
'*: :__git_references' && ret=0
}
(( $+functions[_git-merge] )) ||
_git-merge () {
_arguments \
"$merge_args[@]" \
'-m:merge message' \
'*:remote:__git_commits' && ret=0
}
(( $+functions[_git-mv] )) ||
_git-mv () {
_arguments \
'-f[force renaming/moving even if targets exist]' \
'-k[skip move/renames that would lead to errors]' \
'-n[only show what would happen]' \
'*:source:__git_cached_files' \
':destination:_files' && ret=0
}
(( $+functions[_git-octupus] )) ||
_git-octupus () {
_nothing
}
(( $+functions[_git-pull] )) ||
_git-pull () {
_arguments \
"$merge_args[@]" \
$common_fetch_args \
':repository:__git_any_repositories' \
'*:refspec:__git_ref_specs' && ret=0
}
# NOTE: For --receive-pack we use _files to complete, even though this will
# only complete files on the local end, not the remote end. Still, it may be
# helpful to get some sort of completion going, perhaps modifying the path
# later on to match the remote end.
(( $+functions[_git-push] )) ||
_git-push () {
_arguments \
$force_ref_arg \
'--all[fetch all refs]' \
'--tags[all tags under "$GIT_DIR/refs/tags" are pushed]' \
'(--receive-pack --exec)'{--receive-pack=-,--exec=-}'[path to git-receive-pack on remote]:remote path:_files' \
'--repo=-[default repository to use]:repository:__git_any_repositories' \
'( --no-thin)--thin[try to minimize number of objects to be sent]' \
'(--thin )--no-thin[do not try to minimize number of objects to be sent]' \
$verbose_arg \
'::repository:__git_any_repositories' \
'*::refspec:__git_ref_specs' && ret=0
}
(( $+functions[_git-rebase] )) ||
_git-rebase () {
if [[ $words[2] == --(abort|continue|skip) ]]; then
_message 'no more options'
else
_arguments \
'--onto[start new branch with HEAD equal to "newbase"]:newbase' \
'--continue[continue after failure]' \
'--abort[abort current rebase]' \
'--skip[skip the current patch]' \
'--merge[use merging strategies to rebase]' \
'*'{-s,--strategy=-}'[use given merge strategy]:merge strategy:__git_merge_strategies' \
$verbose_arg \
'-C-[ensure that given lines of surrounding context match]: :_guard "[[\:digit\:]]##" "lines of context"' \
':upstream branch:__git_revisions' \
'::working branch:__git_revisions' && ret=0
fi
}
(( $+functions[_git-repack] )) ||
_git-repack () {
_arguments \
'-a[pack all objects into a single pack]' \
'-d[remove redundant packs after packing]' \
'-f[pass "--no-reuse-delta" option to "git pack-objects"]' \
'-l[pass "--local" option to "git pack-objects"]' \
'-n[do not update server information]' \
'-q[pass "-q" option to "git pack-objects"]' \
'--window=-[number of objects to consider when doing delta compression]' \
'--depth=-[maximum delta depth]' && ret=0
}
(( $+functions[_git-rerere] )) ||
_git-rerere () {
declare -a commands
commands=(
'clear:reset the metadata used by rerere'
'diff:output diffs for the current state of the resolution'
'status:like diff, but only output filesames'
'gc:prune old records of conflicted merges')
_describe -t commands 'command' commands
}
(( $+functions[_git-reset] )) ||
_git-reset () {
local commit_arg path_arg
if [[ $words[2] == --mixed ]]; then
commit_arg=':commit:__git_revisions'
path_arg="*:file:__git_tree_files $words[3]"
else
commit_arg='::commit:__git_revisions'
fi
_arguments -S -A '--*' \
'( --soft --hard)--mixed[like --soft but report what has not been updated (default)]' \
'(--mixed --hard)--soft[do not touch the index file nor the working tree]' \
'(--mixed --soft )--hard[match the working tree and index to the given tree]' \
$commit_arg \
$path_arg && ret=0
}
(( $+functions[_git-revert] )) ||
_git-revert () {
_arguments \
'(-e --edit --no-edit)'{-e,--edit}'[edit the commit before committing the revert]' \
'(-e --edit --no-edit)--no-edit[do not start the commit message editor]' \
'(-n --no-commit)'{-n,--no-commit}'[do not commit the reversion]' \
':commit:__git_commits' && ret=0
}
# TODO: should take all arguments found in setup_revisions() (probably more or
# less what git-rev-list takes).
(( $+functions[_git-shortlog] )) ||
_git-shortlog () {
__git_setup_revision_arguments
_arguments -S \
$revision_arguments \
'(: -)'{-h,--help}'[print a short usage message and exit]' \
'(-n --numbered)'{-n,--numbered}'[sort according to number of commits]' \
'(-s --summary)'{-s,--summary}'[suppress commit description]' \
'*::commitish:__git_committishs' && ret=0
}
# TODO: --date-order is undocumented.
# TODO: Better completion of --reflog.
(( $+functions[_git-show-branch] )) ||
_git-show-branch () {
_arguments -S \
'(--more --independent --merge-base)--list[synonym to "--more=-1"]' \
- branches \
'(-a --all)'{-a,--all}'[show both remote-tracking branches and local branches]' \
'(-r --remotes)'{-r,--remotes}'[show remote-tracking branches]' \
'( --list --independent --merge-base)--more=-[go given number of commit beyond common ancestor (no ancestry if negative)]:: :_guard "[[\:digit\:]]" limit' \
'(--more --list --merge-base)--independent[show only the reference that can not be reached from any of the other]' \
'(--more --list --independent )--merge-base[act like "git-merge-base -a" but with two heads]' \
'--current[include current branch to the list of revs]' \
'( --sha1-name)--no-name[do not show naming strings for each commit]' \
'(--no-name )--sha1-name[name commits with unique prefix of object names]' \
'--topo-order[show commits in topological order]' \
'--topics[show only commits that are NOT on the first branch given]' \
'--sparse[output merges that are reachable from multiple tips being shown]' \
'--date-order[undocumented]' \
'*:revision:__git_revisions' \
- reflogs \
'(-g --reflog)'{-g,--reflog=-}'[show reflog entries for given ref]::number of entries and base' \
':reference:__git_references' && ret=0
}
(( $+functions[_git-status] )) ||
_git-status () {
_git-commit
}
__git_zstyle_default ':completion::complete:git-status:argument-rest:*' ignore-line yes
(( $+functions[_git-verify-tag] )) ||
_git-verify-tag () {
_arguments \
':tag:__git_tags' && ret=0
}
# TODO: This should take those arguments that git-diff-tree can take, as well.
(( $+functions[_git-whatchanged] )) ||
_git-whatchanged () {
__git_setup_revision_arguments
_arguments -S \
$revision_arguments \
'1::commit id:__git_commits2' \
'*:managed file:__git_cached_files' && ret=0
}
(( $+functions[_git-applypatch] )) ||
_git-applypatch () {
_arguments \
':message file:_files' \
':patch file:_files' \
':info file:_files' \
'::signoff file:__git_signoff_file' && ret=0
}
# TODO: Need to combine the list of attributes defined in __git_attributes.
(( $+functions[_git-check-attr] )) ||
_git-check-attr () {
local -a attributes
attributes=(crlf ident filter diff merge)
local only_attributes=1
for (( i = 2; i < $#words; i++ )); do
if (( attributes[(I)$words[i]] == 0 )); then
only_attributes=0
break
fi
done
if (( !only_attributes || words[(I)--] )); then
__git_files && ret=0
else
_alternative \
'files:file:__git_files' \
'attributes:attribute:__git_attributes' && ret=0
fi
}
# TODO: archive/branch can use _arch_archives perhaps?
(( $+functions[_git-archimport] )) ||
_git-archimport () {
_arguments \
'-a[auto-register archives at http://mirrors.sourcecontrol.net]' \
'-D[attempt to import trees that have been merged from]: :_guard "[[\:digit\:]]#" depth' \
'-f[use the fast patchset import strategy]' \
$help_arg \
'-o[use old-style branch names]' \
'-T[create a tag for every commit]' \
'-t[use given directory as temporary directory]:directory:_directories' \
$verbose_arg \
':archive/branch' \
'::archive/branch'
}
(( $+functions[_git-convert-objects] )) ||
_git-convert-objects () {
_nothing
}
# TODO: Could use _cvs_root from _cvs for completing argument to -d.
# TODO: -h is undocumented.
(( $+functions[_git-cvsexportcommit] )) ||
_git-cvsexportcommit () {
_arguments \
'-c[commit automatically if the patch applied cleanly]' \
'-p[be pedantic (paranoid) when applying patches]' \
'-a[add authorship information]' \
'-d[set an alternative CVSROOT to use]:cvsroot' \
'-f[force the merge, even if the files are not up to date]' \
'-P[force the parent commit, even if it is not a direct parent]' \
'-m[prepend the commit message with the provided prefix]:message prefix' \
$verbose_arg \
$help_arg \
'::parent commit id:__git_commits' \
':commit id:__git_commits' && ret=0
}
# TODO: _cvs_root for -d would be nice
(( $+functions[_git-cvsimport] )) ||
_git-cvsimport () {
_arguments \
$author_conversion_file_arg \
'-C[specify the git repository to import into]:directory:_directories' \
'-d[specify the root of the CVS archive]:cvsroot' \
$help_arg \
'-i[do not perform a checkout after importing]' \
'-k[remove keywords from source files in the CVS archive]' \
'-m[attempt to detect merges based on the commit message]' \
'-M[attempt to detect merges based on the commit message with custom pattern]:pattern' \
'-o[specify the branch into which you wish to import]:branch:__git_branches' \
'-P[read cvsps output file]:file:_files' \
'-p[specify additionaly options for cvsps]:cvsps-options' \
'-s[substitute the "/" character in branch names with given substitution]:substitute' \
'-u[convert underscores in tag and branch names to dots]' \
'-S[skip paths matching given regex]:regex' \
'-a[import all commits, including recent ones]' \
'-L[limit the number of commits imported]: :_guard "[[\:digit\:]]" limit' \
$verbose_arg \
'-z[specify timestamp fuzz factor to cvsps]:fuzz-factor' \
':cvsmodule' && ret=0
}
(( $+functions[_git-cvsserver] )) ||
_git-cvsserver () {
_message "you probably should not be issuing this command; it is an internal git helper"
}
(( $+functions[_git-lost-found] )) ||
_git-lost-found () {
_nothing
}
(( $+functions[_git-pack-refs] )) ||
_git-pack-refs () {
_arguments \
'--all[pack all refs]' \
"( --no-prune)--prune[remove loose refs after packing them]" \
"(--prune )--no-prune[don't remove loose refs after packing them]" && ret=0
}
# TODO: something better
(( $+functions[_git-merge-one-file] )) ||
_git-merge-one-file () {
_message "you probably should not be issuing this command"
}
(( $+functions[_git-prune] )) ||
_git-prune () {
_arguments -S \
'-n[do not remove anything; just report what would have been removed]'
'*::heads:__git_heads' && ret=0
}
(( $+functions[_git-relink] )) ||
_git-relink () {
_arguments \
'--safe[stop if two objects with the same hash exist but have different sizes]' \
':directory:_directories' \
':directory:_directories' \
'*:directory:_directories' && ret=0
}
# TODO: import stuff from _svn
# TODO: Improve completion of -P argument.
(( $+functions[_git-svnimport] )) ||
_git-svnimport () {
_arguments \
$author_conversion_file_arg \
'-b[specify the name of the SVN branches directory]:directory:_directories' \
'-C[specify the git repository to import into]:directory:_directories' \
'-d[use direct HTTP-requests if possible for logs only]:path' \
'-D[use direct HTTP-requests if possible]:path' \
$help_arg \
'-i[do not perform a checkout after importing]' \
'-l[limit the number of SVN changesets to pull]: :_guard "[[\:digit\:]]#" number' \
'-m[attempt to detect merges based on the commit message]' \
'-M[attempt to detect merges based on the commit message with custom pattern]:pattern' \
'-o[specify the branch into which you wish to import]:branch' \
'-r[prepend "rX: " to commit messages, where X is the subversion revision]' \
'-s[specify the change number to start importing from:start-revision' \
'-T[specify the name of the SVN tags directory]:directory:_directories' \
'-t[specify the name of the SVN trunk]:trunk:_directories' \
'-I[import svn:ignore directory property to files with given name]:ignored file:_files' \
'-R[specify how often git repository should be repacked]: :_guard "[[\:digit\:]]#" "number of revisions"' \
'-P[import only given path of the SVN tree]::_directory' \
$verbose_arg \
':svn-repositry-url:_urls' \
'::directory:_directories' && ret=0
}
# TODO: how do we complete argument 1?
(( $+functions[_git-symbolic-ref] )) ||
_git-symbolic-ref () {
_arguments -A '-*' \
'-q[do not issue error if specified name is not a symbolic ref]' \
'-m[update reflog for specified name with specied reason]:reason for update' \
':symbolic reference' \
'::reference:__git_references' && ret=0
}
(( $+functions[_git-tag] )) ||
_git-tag () {
local message_args=
if (( words[(I)-[asu]] )); then
message_args=(
'( -F)-m[specify tag message]:message'
'(-m )-F[read tag message from given file]:message file:_files')
fi
_arguments -A '-*' \
- creation \
'( -s -u)-a[create an unsigned, annotated tag]' \
'(-a -u)-s[create an signed and annotated tag]' \
'(-a -s )-u[create a tag, annotated and signed with the given key]:secret key:__git_gpg_secret_keys' \
'( -v)-f[create a new tag even if one with the same name already exists]' \
'(-f )-v[verifies the gpg signutare of the given tag]' \
$message_args \
':tag name:__git_tags' \
'::head:__git_revisions' \
- deletion \
'-d[delete tags]:*:tag names:__git_tags' \
- listing \
'-l[list tags matching pattern]:pattern' && ret=0
}
__git_zstyle_default ':completion::complete:git-tag:deletion-option-d-rest:*' ignore-line yes
(( $+functions[_git-update-ref] )) ||
_git-update-ref () {
_arguments \
'-m[update reflog for specified name with specied reason]:reason for update' \
'(:)-d[delete given reference after verifying its value]:symbolic reference:__git_revisions:old reference:__git_revisions' \
':symbolic reference:__git_revisions' \
':new reference:__git_revisions' \
'::old reference:__git_revisions' && ret=0
}
(( $+functions[_git-check-ref-format] )) ||
_git-check-ref-format () {
_arguments \
':reference:__git_revisions' && ret=0
}
(( $+functions[_git-cherry] )) ||
_git-cherry () {
_arguments \
$verbose_arg \
':upstream:__git_revisions' \
'::head:__git_revisions' \
'::limit:__git_revisions' && ret=0
}
(( $+functions[_git-count-objects] )) ||
_git-count-objects () {
_arguments \
'-v[also report number of in-pack objects and objects that can be removed]' && ret=0
}
# TODO: do better than _directories? The directory needs to be a git-repository,
# so one could check for a required file in the given directory.
# TODO: --interpolated-path should complete %H, %CH, %IP, %P, and %D.
(( $+functions[_git-daemon] )) ||
_git-daemon () {
_arguments -S \
'--strict-paths[match paths exactly]' \
'--base-path=-[remap all the path requests as relative to the given path]:path:_directories' \
'--interpolated-path=-[dynamically construct alternate paths]:path:_directories' \
'--export-all[allow pulling from all repositories without verification]' \
'(--port --listen --user --group)--inetd[run server as an inetd service]' \
'(--inetd)--listen=-[listen on a specific IP address or hostname]:hostname:_hosts' \
'(--inetd)--port=-[specify port to listen to]:port:_ports' \
'--init-timeout=-[specify timeout between connection and request]: :_guard "[[\:digit\:]]#" timeout' \
'--timeout=-[specify timeout for sub-requests]: :_guard "[[\:digit\:]]#" timeout' \
'--syslog[log to syslog instead of stderr]' \
'--user-path=-[allow ~user notation to be used in requests]::path:_directories' \
'--verbose[log details about incoming connections and requested files]' \
'--reuseaddr[reuse addresses when already bound]' \
'(--syslog)--detach[detach from the shell]' \
'--pid-file=-[save the process id in given file]:pid file:_files' \
'--user=-[set uid of daemon]:user:_users' \
'--group=-[set gid of daemon]:group:_groups' \
'--enable=-[enable site-wide service]:service:__git_daemon_service' \
'--disable=-[disable site-wide service]:service:__git_daemon_service' \
'--allow-override[allow overriding site-wide service]:service:__git_daemon_service' \
'--forbid-override[forbid overriding site-wide service]:service:__git_daemon_service' \
'*:repository:_directories' && ret=0
}
(( $+functions[_git-get-tar-commit-id] )) ||
_git-get-tar-commit-id () {
_message 'no arguments allowed; accepts tar-file on standard input'
}
(( $+functions[_git-instaweb] )) ||
_git-instaweb () {
_arguments \
'(-l --local)'{-l,--local}'[bind the web server to 127.0.0.1]' \
'(-d --httpd)'{-d,--httpd=}'[HTTP-daemon command-line that will be executed]:command line' \
'(-m --module-path)'{-m,--module-path=}'[module path for the Apache HTTP-daemon]:module path:_directories' \
'(-p --port)'{-p,--port=}'[port to bind web server to]: :_guard "[[\:digit\:]]" port' \
'(-b --browser)'{-b,--browser=}'[web-browser command-line that will be executed]:command line' \
'--start[start the HTTP-daemon and exit]' \
'--stop[start the HTTP-daemon and exit]' \
'--restart[restart the HTTP-daemon and exit]' && ret=0
}
(( $+functions[_git-mailinfo] )) ||
_git-mailinfo () {
_arguments \
'-k[do not strip/add \[PATCH\] from the first line of the commit message]' \
'(-u --encoding)-u[encode commit information in UTF-8]' \
'(-u --encoding)--encoding[encode commit information in given encoding]:encoding:__git_encodings' \
':message file:_files' \
':patch file:_files' && ret=0
}
# TODO:
# /* Backwards compatibility: if no -o specified, accept
# <mbox> <dir> or just <dir> */
(( $+functions[_git-mailsplit] )) ||
_git-mailsplit () {
_arguments -S \
'-b[if file does not begin with "From " line, assume it is a single mail message]' \
'-d-[specify number of leading zeros]: :_guard "[[\:digit\:]]#" precision' \
'-f-[skip the first N numbers]: :_guard "[[\:digit\:]]#" number' \
'-o-[directory in which to place individual messages]:directory:_directories' \
'*::mbox file:_files' && ret=0
}
(( $+functions[_git-patch-id] )) ||
_git-patch-id () {
_message 'no arguments allowed; accepts patch on standard input'
}
(( $+functions[_git-request-pull] )) ||
_git-request-pull () {
_arguments \
':start commit:__git_commits' \
':url:_urls' \
'::end commit:__git_commits'
}
(( $+functions[_git-rev-parse] )) ||
_git-rev-parse () {
_arguments \
'(--revs-only --no-revs)--revs-only[do not output flags and parameters not meant for "git-rev-list"]' \
'(--revs-only --no-revs)--no-revs[do not output flags and parameters meant for "git-rev-list"]' \
'(--flags --no-flags)--flags[do not output non-flag parameters]' \
'(--flags --no-flags)--no-flags[do not output flag parameters]' \
'--default[use "arg" if there is no parameter given]:arg' \
'--verify[verify parameter to be usable]' \
'--sq[output single shell-quoted line]' \
'--not[toggle ^ prefix of object names]' \
'--symbolic[output in a format as true to input as possible]' \
'--all[show all refs found in $GIT_DIR/refs]' \
'--branches[show branch refs found in $GIT_DIR/refs/heads]' \
'--tags[show tag refs found in $GIT_DIR/refs/tags]' \
'--remotes[show tag refs found in $GIT_DIR/refs/remotes]' \
'--show-prefix[show path of current directory relative to top-leve directory]' \
'--show-cdup[show path of top-level directory relative to current directory]' \
'--git-dir[show "$GIT_DIR" if defined else show path to ".git" directory]' \
'--short=-[show only handful hexdigits prefix]:: :_guard "[[\:digit\:]]#" number' \
{--after=-,--since=-}'[show "--max-age=" parameter corresponding given date string]:datestring' \
{--berore=-,--until=-}'[show "--min-age=" parameter corresponding given date string]:datestring' \
'*:args' && ret=0
}
(( $+functions[_git-runstatus] )) ||
_git-runstatus () {
_arguments \
'--color[show colored status, highlighting modified files]' \
'--nocolor[turn of colored output]' \
'--amend[show status based on HEAD^1 instead of HEAD]' \
'--verbose[show unified diff of all file changes]' \
'--untracked[show files in untracked directories]' && ret=0
}
(( $+functions[_git-rm] )) ||
_git-rm () {
_arguments -S -A '-*' \
'-f[override the up-to-date check]' \
"-n[don't actually remove the files, just show if they exist in the index]" \
'-r[allow recursive removal when a leading directory-name is given]' \
'--cached[only remove files from the index]' \
'*:files:__git_cached_files' && ret=0
}
(( $+functions[_git-send-email] )) ||
_git-send-email () {
_arguments \
'--bcc=["Bcc:" value for each email]:email address:_email_addresses' \
'--cc=[starting "Cc:" value for each email]:email address:_email_addresses' \
'(--no-chain-reply-to)--chain-reply-to[each email will be sent as a reply to the previous one sent]' \
'(--chain-reply-to)--no-chain-reply-to[all emails after the first will be sent as replies to the first one]' \
'--compose[use $EDITOR to edit an introductory message for the patch series]' \
'--from=[specify the sender of the emails]:email address:_email_addresses' \
'--in-reply-to=[specify the contents of the first In-Reply-To header]:message-id' \
'--no-signed-off-by-cc[do not add emails foudn in "Signed-off-by:" lines to the "Cc:" list]' \
'--quiet[be less verbose]' \
'--smtp-server=[specify the outgoing smtp server]:smtp server:_hosts' \
'--subject=[specify the initial subject of the email thread]:subject' \
'--suppress-from[do not add the "From:" address to the "Cc:" list]' \
'--dry-run[do everything except actually send the emails]' \
'--envelope-sender[specify the envelope sender used to send the emails]:email address:_email_addresses' \
'--to=[specify the primary recipient of the emails]:email address:_email_addresses' \
'*:file:_files' && ret=0
}
# TODO: -h, -H, and --help are undocumented.
# TODO: -V and --version are undocumented.
# TODO: --minimize-connections is undocumented.
# TODO: --remote is undocumented.
# TODO: --log-window-size is undocumented.
# TODO: --config-dir is undocumented.
# TODO: --no-auth-cache is undocumented.
# TODO: -C and --copy-similarity are undocumented.
# TODO: --fetch-all and --all are undocumented.
# TODO: -v and --verbose are undocumented.
# TODO: -r and --revisions for show-ignore are undocumented.
# TODO: migrate is undocumented.
# TODO: --minimize for migrate is undocumented.
# TODO: -r, --color, --pager, and --non-recursive for log are undocumented.
# TODO: --local for rebase is undocumented.
# TODO: --message, -m, --file, -F, --revision, and -r for commit-diff are
# undocumented.
(( $+functions[_git-svn] )) ||
_git-svn () {
local curcontext=$curcontext state line
declare -A opt_args
_arguments -C \
'(- :)--version[display version information]' \
'(- :)--help[display help message]' \
':command:->command' \
'*::options:->options' && ret=0
case $state in
(command)
declare -a commands
commands=(
'init:initialize an empty git repository with additional svn data'
'fetch:fetch revisions from the SVN remote'
'clone:same as init, followed by fetch'
'rebase:fetch revs from SVN parent of HEAD and rebase current work on it'
'dcommit:commit diffs from given head onto SVN repository'
'log:output SVN log-messages'
"find-rev:output git commit corresponding to the given SVN revision's hash"
'set-tree:commit given commit or tree to SVN repository'
'show-ignore:output corresponding .gitignore file of svn:ignore'
'commit-diff:commit diff of two tree-ishs')
;;
(options)
declare -a arguments
if [[ $line[1] == (fetch|clone|dcommit|set-tree|rebase|migrate|init) ]]; then
arguments+=(
'--username=[username to use for SVN transport]:username:_users'
'--config-dir=[undocumented]:configuration directory:_directories'
'--no-auth-cache[undocumented]')
fi
if [[ $line[1] == (fetch|clone|dcommit|set-tree|rebase|log) ]]; then
arguments+=(
'( --authors-file)'$author_conversion_file_arg
'(-A )'$long_author_conversion_file_arg)
fi
# TODO: --repack-flags can be improved by actually completing the legal
# flags to git-repack.
if [[ $line[1] == (fetch|clone|dcommit|set-tree|rebase) ]]; then
arguments+=(
'(-q --quiet)'{-q,--quiet}'[make git-svn less verbose]'
'--repack=[repack files (for given number of revisions)]:: :_guard "[[\:digit\:]]#" "revision limit"'
'(--repack-flags --repack-args --repack-opts)'{--repack-flags=,--repack-args=,--repack-opts=}'[flags to pass to git-repack]:git-repack flags'
'( --no-follow-parent)--follow-parent[follow parent commit]'
'(--follow-parent )--no-follow-parent[do not follow parent commit]'
'--log-window-size=[undocumented]')
fi
if [[ $line[1] == (clone|init) ]]; then
arguments+=(
$shared_arg
$template_arg
'(-T --trunk)'{-T-,--trunk=}'[set trunk sub-directory]:trunk sub-directory:->subdirectory'
'(-t --tags)'{-t-,--tags=}'[set tags sub-directory]:tags sub-directory:->subdirectory'
'(-b --branches)'{-b-,--branches=}'[set branches sub-directory]:branches sub-directory:->subdirectory'
'--no-metadata[set svn-remote.X.noMetadata]'
'--use-svm-props[set svn-remote.X.useSvmProps]'
'--use-svnsync-props[set svn-remote.X.useSvnsyncProps]'
'--rewrite-root=[set svn-remote.X.rewriteRoot]:new root'
'--prefix=[prefix to use for names of remotes]:path prefix:_directories -r ""')
fi
if [[ $line[1] == (dcommit|set-tree|commit-diff) ]]; then
arguments+=(
'--rmdir[remove empty directories from SVN tree after commit]'
'(-e --edit)'{-e,--edit}'[edit commit message before committing]'
$find_copies_harder_arg
$diff_l_arg
'(-C --copy-similarity)'{-C-,--copy-similarity=}'[undocumented]:number')
fi
# FIXME: What arguments does clone actually take here?
if [[ $line[1] == (fetch|clone) ]]; then
arguments+=(
'(-r --revision)'{-r,--revision}'[only fetch given revision or revision range]:revision:->__git_svn_revisions'
'::svn remote:__git_svn-remotes')
fi
if [[ $line[1] == (dcommit|rebase) ]]; then
arguments+=(
'(-m --merge)'{-m,--merge}'[use merging strategies, if necessary]')
fi
if [[ $line[1] == (fetch|dcommit|rebase) ]]; then
arguments+=(
'(--fetch-all --all)'{--fetch-all,--all}'[undocumented]')
fi
if [[ $line[1] == (dcommit|rebase) ]]; then
arguments+=(
'*'{-s,--strategy=-}'[use given merge strategy]:merge strategy:__git_merge_strategies')
fi
if [[ $line[1] == (dcommit|log|rebase) ]]; then
arguments+=(
'(- --verbose)'{-v,--verbose}'[output extra information]')
fi
case $line[1] in
(clone)
arguments+=(
':url:_urls'
'::directory:_directories')
;;
(set-tree)
arguments+=('--stdin[read list of commits to commit from stdin]')
;;
(show-ignore)
arguments+=('-r --revision)'{-r,--revision)'[undocumented]:revision:->__git_svn_revisions'
(dcommit)
arguments+=(
'(-n --dry-run)'{-n,--dry-run}'[output git-commands that would show diffs that would be committed]')
;;
(migrate)
arguments+=(
'--minimize[undocumented]')
;;
(log)
__git_setup_revision_arguments
arguments+=(
$revision_arguments
'(-r --revision)'{-r-,--revision=}'[revisions to output log information for]: :__git_svn_revision_numbers'
'--limit=[like --max-count, but not counting merged/excluded commits]: :_guard "[[\:digit\:]]#" limit'
'--incremental[give output suitable for concatenation]'
'--show-commit[output git commit SHA-1, as well]'
'--oneline[similar to --pretty=oneline]'
'--color[undocumented]'
'--pager[undocumented]:pager:_files -g *(*)'
'--non-recursive[undocumented]')
;;
(rebase)
arguments+=(
'--local[undocumented]')
;;
(commit-diff)
arguments+=(
'(-m --message)'{-m-,--message=}'[undocumented]:message'
'(-F --file)'{-F-,--file=}'[undocumented]:file:_files'
'(-r --revision)'{-r-,--revision=}'[undocumented]:revision:__git_svn_revisions')
;;
esac
_arguments -C \
'(-h -H --help)'{-h,-H,--help}'[display usage information]' \
'(-V --version)'{-V,--version}'[display version information]' \
'--minimize-connections[undocumented]' \
'(-R --svn-remote --remote)'{-R,--svn-remote,--remote}'[svn remote to use]:svn remote:__git_svn-remotes'
'(-i --id)'{-i,--id}'[set GIT_SVN_ID]:GIT_SVN_ID'
$arguments && ret=0
case $state in
(subdirectory)
_alternative \
'sub-directories:sub-directory:_directories' \
'urls: :_urls' && ret=0
;;
esac
;;
esac
}
(( $+functions[_git-stripspace] )) ||
_git-stripspace () {
_message 'no arguments allowed; accepts input file on standard input'
}
(( $+functions[_git-mergetool] )) ||
_git-mergetool () {
local curcontext=$curcontext state line
typeset -A opt_args
_arguments -C \
'(-t --tool)'{-t,--tool=}':merge resolution tool:(kdiff3 tkdiff meld xxdiff emerge vimdiff gvimdiff opendiff)' \
'*:conflicted file:_files' && ret=0
}
# ---
(( $+functions[__git_guard] )) ||
__git_guard () {
declare -A opts
zparseopts -K -D -A opts M: J: V: 1 2 n F: X:
[[ "$PREFIX$SUFFIX" != $~1 ]] && return 1
if (( $+opts[-X] )); then
_message -r $opts[-X]
else
_message -e $2
fi
[[ -n "$PREFIX$SUFFIX" ]]
}
__git_guard_branch-name () {
if [[ -n "$PREFIX$SUFFIX" ]]; then
_call_program check-ref-format git check-ref-format "refs/heads/$PREFIX$SUFFIX" &>/dev/null
(( ${#pipestatus:#0} > 0 )) && return 1
fi
_message -e 'branch-name'
[[ -n "$PREFIX$SUFFIX" ]]
}
__git_guard_diff-stat-width () {
if [[ $PREFIX == *,* ]]; then
compset -P '*,'
_guard "[[:digit:]]#" "filename width"
else
compset -S ',*'
_guard "[[:digit:]]#" "width"
fi
}
(( $+functions[__git_command_successful] )) ||
__git_command_successful () {
if (( ${#pipestatus:#0} > 0 )); then
_message 'not a git repository'
return 1
fi
return 0
}
(( $+functions[__git_objects] )) ||
__git_objects () {
__git_guard $* "[[:xdigit:]]#" "object"
}
(( $+functions[__git_trees] )) ||
__git_trees () {
__git_guard $* "[[:xdigit:]]#" "tree"
}
(( $+functions[__git_tree_ishs] )) ||
__git_tree_ishs () {
__git_commits
}
(( $+functions[__git_blobs] )) ||
__git_blobs () {
_git_guard $* "[[:xdigit:]]#" 'blob id'
}
(( $+functions[__git_stages] )) ||
__git_stages () {
__git_guard $* "[[:digit:]]#" 'stage'
}
(( $+functions[__git_files] )) ||
__git_files () {
local expl files ls_opts opts gitdir
zparseopts -D -E -a opts -- -cached -deleted -modified -others -ignored -unmerged -killed
gitdir=$(_call_program gitdir git rev-parse --git-dir 2>/dev/null)
__git_command_successful || return
ls_opts=("--exclude-per-directory=.gitignore")
[[ -f "$gitdir/info/exclude" ]] && ls_opts+="--exclude-from=$gitdir/info/exclude"
files=(${(ps:\0:)"$(_call_program files git ls-files -z $ls_opts $opts 2>/dev/null)"})
__git_command_successful || return
_wanted files expl 'index file' _multi_parts $@ - / files
}
(( $+functions[__git_cached_files] )) ||
__git_cached_files () {
__git_files $* --cached
}
(( $+functions[__git_deleted_files] )) ||
__git_deleted_files () {
__git_files $* --deleted
}
(( $+functions[__git_killed_files] )) ||
__git_killed_files () {
__git_files $* --killed
}
(( $+functions[__git_modified_files] )) ||
__git_modified_files () {
__git_files $* --modified
}
(( $+functions[__git_other_files] )) ||
__git_other_files () {
__git_files $* --others
}
(( $+functions[__git_unmerged_files] )) ||
__git_unmerged_files () {
__git_files $* --unmerged
}
(( $+functions[__git_tree_files] )) ||
__git_tree_files () {
local multi_parts_opts
zparseopts -D -E -a multi_parts_opts M: J: V: 1 2 n F: X:
local tree
integer at_least_one_tree_added
local -a tree_files
(( at_least_one_tree_added = 0 ))
for tree in $*; do
tree_files+=(${(ps:\0:)"$(_call_program tree-files git ls-tree --name-only -z -r $tree 2>/dev/null)"})
__git_command_successful && (( at_least_one_tree_added = 1 ))
done
if (( !at_least_one_tree_added )); then
return
fi
local expl
# FIXME: Why doesnt -f to compadd work here?
_wanted files expl 'tree file' _multi_parts $multi_parts_opts - / tree_files
}
# TODO: deal with things that __git_heads and __git_tags has in common (i.e.,
# if both exists, they need to be completed to heads/x and tags/x.
(( $+functions[__git_commits] )) ||
__git_commits () {
_alternative \
'heads::__git_heads' \
'tags::__git_tags'
}
(( $+functions[__git_committishs] )) ||
__git_committishs () {
__git_commits
}
# TODO: deal with prefixes and suffixes listed in git-rev-parse
(( $+functions[__git_revisions] )) ||
__git_revisions () {
__git_commits $*
}
(( $+functions[__git_commits2] )) ||
__git_commits2 () {
compset -P '\\\^'
__git_commits
}
(( $+functions[__git_commit_ranges] )) ||
__git_commit_ranges () {
compset -P '*..'
__git_commits $*
}
# FIXME: these should be imported from _ssh
# TODO: this should take -/ to only get directories
_remote_files () {
# There should be coloring based on all the different ls -F classifiers.
local expl rempat remfiles remdispf remdispd args suf ret=1
if zstyle -T ":completion:${curcontext}:files" remote-access; then
zparseopts -D -E -a args p: 1 2 4 6 F:
if [[ -z $QIPREFIX ]]
then rempat="${PREFIX%%[^./][^/]#}\*"
else rempat="${(q)PREFIX%%[^./][^/]#}\*"
fi
remfiles=(${(M)${(f)"$(_call_program files ssh $args -a -x ${IPREFIX%:} ls -d1FL "$rempat" 2>/dev/null)"}%%[^/]#(|/)})
compset -P '*/'
compset -S '/*' || suf='remote file'
# remdispf=(${remfiles:#*/})
remdispd=(${(M)remfiles:#*/})
_tags files
while _tags; do
while _next_label files expl ${suf:-remote directory}; do
# [[ -n $suf ]] && compadd "$@" "$expl[@]" -d remdispf \
# ${(q)remdispf%[*=@|]} && ret=0
compadd ${suf:+-S/} "$@" "$expl[@]" -d remdispd \
${(q)remdispd%/} && ret=0
done
(( ret )) || return 0
done
return ret
else
_message -e remote-files 'remote file'
fi
}
(( $+functions[__git_remote_repository] )) ||
__git_remote_repository () {
local service
service= _ssh
if compset -P '*:'; then
_remote_files
else
_ssh_hosts -S:
fi
}
(( $+functions[__git_repository] )) ||
__git_repository () {
_alternative \
'directories::_directories' \
'remote repositories::__git_remote_repository'
}
# should also be $GIT_DIR/remotes/origin
(( $+functions[__git_any_repositories] )) ||
__git_any_repositories () {
_alternative \
'directories::_directories' \
'remotes::__git_remotes' \
'remote repositories::__git_remote_repository'
}
(( $+functions[__git_remotes] )) ||
__git_remotes () {
local expl gitdir remotes
gitdir=$(_call_program gitdir git rev-parse --git-dir 2>/dev/null)
__git_command_successful || return
# zparseopts -a opts X+:
#
# if (( !$opts[(I)-X] )); then
# descr=remote
# fi
remotes=(${${(f)"$(_call_program remotes git config --get-regexp '"^remote\..*\.url$"')"}//#(#b)remote.(*).url */$match[1]})
__git_command_successful || return
# TODO: Should combine the two instead of either or.
if (( $#remotes > 0 )); then
_wanted remotes expl remote compadd $* - $remotes
else
_wanted remotes expl remote _files $* - -W "($gitdir/remotes)" -g "$gitdir/remotes/*"
fi
}
(( $+functions[__git_ref_specs] )) ||
__git_ref_specs () {
if compset -P '*:'; then
__git_heads
else
compset -P '+'
if compset -S ':*'; then
__git_heads
else
__git_heads -S ':'
fi
fi
}
(( $+functions[__git_signoff_file] )) ||
__git_signoff_file () {
_alternative \
'signoffs:signoff:(yes true me please)' \
'files:signoff file:_files'
}
(( $+functions[__git_tag_ids] )) ||
__git_tag_ids () {
}
(( $+functions[__git_heads] )) ||
__git_heads () {
local expl
declare -a branch_names
branch_names=(${${(f)"$(_call_program heads git branch -a 2>/dev/null)"}#[* ] })
__git_command_successful || return
_wanted heads expl branch-name compadd $* - $branch_names
}
(( $+functions[__git_tags] )) ||
__git_tags () {
local expl
declare -a tag_names
tag_names=(${${(f)"$(_call_program tags git tag -l 2>/dev/null)"}#[* ] })
__git_command_successful || return
_wanted tags expl tag-name compadd $* - $tag_names
}
# TODO: depending on what options are on the command-line already, complete
# only tags or heads
# TODO: perhaps caching is unnecessary. usually wont contain that much data
# TODO: perhaps provide alternative here for both heads and tags (and use
# __git_heads and __git_tags)
# TODO: instead of "./.", we should be looking in the repository specified as
# an argument to the command (but default to "./." I suppose (why not "."?))
(( $+functions[__git_references] )) ||
__git_references () {
# _alternative \
# 'heads::__git_heads' \
# 'tags::__git_tags' && ret=0
local expl
# TODO: deal with GIT_DIR
if [[ $_git_refs_cache_pwd != $PWD ]]; then
_git_refs_cache=(${${${(f)"$(_call_program references git ls-remote ./. 2>/dev/null)"}#*$'\t'}#refs/(heads|tags)/})
__git_command_successful || return
_git_refs_cache_pwd=$PWD
fi
_wanted references expl 'references' compadd - $_git_refs_cache
}
(( $+functions[__git_local_references] )) ||
__git_local_references () {
local expl
if [[ $_git_local_refs_cache_pwd != $PWD ]]; then
_git_local_refs_cache=(${${${(f)"$(_call_program references git ls-remote ./. 2>/dev/null)"}#*$'\t'}#refs/})
__git_command_successful || return
_git_local_refs_cache_pwd=$PWD
fi
_wanted references expl 'references' compadd - $_git_local_refs_cache
}
(( $+functions[__git_remote_references] )) ||
__git_remote_references () {
__git_references
}
(( $+functions[__git_branch_names] )) ||
__git_branch_names () {
local expl
declare -a branch_names
branch_names=(${${(f)"$(_call_program branch-names git branch 2>/dev/null)"}#[* ] })
__git_command_successful || return
_wanted branch-names expl branch-name compadd $* - $branch_names
}
# TODO: Add merge.*.(name|driver|recursive) and diff.*.(command|funcname) (see
# gitattributes(5)).
(( $+functions[__git_config_name] )) ||
__git_config_name () {
local label=names
declare -a names
if [[ -prefix alias.* ]]; then
_message 'command-alias name'
elif [[ -prefix branch.*.* ]]; then
compset -P 'branch.*.'
names=(
'remote:what remote git-fetch should fetch'
'merge:default refspec to be marked for merging')
elif [[ -prefix branch.* ]]; then
compset -P 'branch.'
__git_branch_names -S '.' -r '.'
return
elif [[ -prefix remote.*.* ]]; then
compset -P 'remote.*.'
names=(
'url:URL of a remote repository'
'fetch:default set of refspecs for git-fetch'
'push:default set of refspecs for git-push'
'skipDefaultUpdate:whether to skip this remote when running git-remote'
'receivepack:default program to execute on remote when pushing'
'uploadpack:default program to execute on remote when fetching'
'tagopt:options for retrieving remote tags')
elif [[ -prefix remote.* ]]; then
compset -P 'remote.'
__git_remotes -S '.' -r '.'
return
elif [[ -prefix remotes.* ]]; then
compset -P 'remotes.'
__git_remote-groups
return
elif [[ -prefix gitcvs.* ]]; then
names=(
'enabled:whether the cvs pserver interface is enabled'
'logfile:name of log file for cvs pserver'
'allbinary:whether to treat all files from CVS as binary')
if [[ -prefix gitcvs.*.* ]]; then
compset -P 'gitcvs.*.'
label="gitcvs ${${words[CURRENT]#gitcvs.}%.*}-specific setting"
else
compset -P 'gitcvs.'
label='gitcvs setting'
names+=(
'dbname:name of database to use'
'dbdriver:name of DBI driver to use'
'dbuser:username to connect to database as'
'dbpass:password to use when connecting to database')
declare -a suffixed_names
suffixed_names=(
'ext:ext-connection-method-specific settings'
'pserver:pserver-connection-method-specific settings')
_describe -t suffixed-names 'gitcvs connection-specific setting' suffixed_names -M 'm:{a-zA-Z}={A-Za-z}' -M 'r:|.=* r:|=*' -S '.' -r '.' && ret=0
fi
elif [[ -prefix svn-remote.*.* ]]; then
compset -P 'svn.*.'
label="git-svn ${${words[CURRENT]#svn.}%.*}-specific setting"
names=(
'noMetadata:disable git-svn-id\: lines at end of commits (fetch, clone, dcommit, set-tree, rebase)'
'useSvmProps:whether to use remappings of URLs and UUIDs from mirrors (fetch, clone, dcommit, set-tree, rebase)'
'useSvnsyncProps:similar to useSvmProps, but for the svnsync command (fetch, clone, dcommit, set-tree, rebase)'
'rewriteRoot:alternate root URL to use')
elif [[ -prefix svn-remote.* ]]; then
compset -P 'svn-remote.'
__git_svn-remotes -M 'm:{a-zA-Z}={A-Za-z}' -M 'r:|.=* r:|=*' -S '.' -r '.' && ret=0
return
else
names=(
'core.fileMode:whether differences in the executable bit is relevant'
"core.autocrlf:what type of conversion of CRLF's git should do"
'core.symlinks:whether symlinks are treated as special files or not'
'core.gitProxy:command to execute to establish a connection to remote server'
'core.ignoreStat:whether modification times of files are ignored'
'core.preferSymlinkRefs:whether symbolic-reference files should be symlinks'
'core.bare:whether this repository has a working tree or not'
'core.logAllRefUpdates:whether to log updates of references'
'core.repositoryFormatVersion:internal variable determining the repository version'
'core.sharedRepository:what kind of sharing is done for this repository'
'core.warnAmbiguousRefs:whether to warn if a ref name is ambiguous'
'core.compression:level of compression to apply to packs'
'core.legacyheaders:whether to use the legacy object-header-format'
'core.packedGitWindowSize:size of mappings of pack files'
'core.packedGitLimit:maximum number of bytes to map from pack files'
'core.deltaBaseCacheLimit:maximum size of cache for base objects'
'apply.whitespace:default value for the --whitespace option to git-apply'
'color.branch:when to color output of git-branch'
'color.branch.current:color of the current branch'
'color.branch.local:color of a local branch'
'color.branch.remote:color of a remote branch'
'color.branch.plain:color of other branches'
'color.diff:when to color diff output'
'color.diff.plain:color of context text'
'color.diff.meta:color of metainformation'
'color.diff.frag:color of hunk headers'
'color.diff.old:color of removed lines'
'color.diff.new:color of added lines'
'color.diff.commit:color of commit headers'
'color.diff.whitespace:color of dubious whitespace'
'color.pager:whether the pager is fed colored output'
'color.status:when to color output of git-status'
'color.status.header:color of header text'
'color.status.added:color of added, but not yet committed, files'
'color.status.updated:color of updated, but not yet committed, files'
'color.status.changed:color of changed, but not yet added in the index, files'
'color.status.untracked:color of files not currently being tracked'
'diff.renameLimit:number of files to consider when detecting copy/renames'
'diff.renames:how hard to try to detect renames'
'fetch.unpackLimit:maximum number of objects to unpack when fetching'
'format.headers:additional email headers to include in email patches'
'format.suffix:default suffix for output files from git-format-patch'
'gc.packrefs:whether to allow git-gc to run git-pack-refs or not'
'gc.reflogexpire:default age for "git reflog expire"'
'gc.reflogexpireunreachable:default age for "git reflog expire" for unreachable'
'gc.rerereresolved:number of days to keep records of resolved merges'
'gc.rerereunresolved:number of days to keep records of unresolved merges'
'http.sslVerify:whether to verify the SSL certificate for HTTPS'
'http.sslCert:file containing SSL certificates for HTTPS'
'http.sslKey:file containing the SSL private key for HTTPS'
'http.sslCAInfo:file containing CA certificates to verify against for HTTPS'
'http.sslCAPath:path containing files with CA certificates to verify against for HTTPS'
'http.maxRequests:how many HTTP requests to launch in parallel'
'http.lowSpeedLimit:lower limit for HTTP transfer-speed'
'http.lowSpeedTime:duration for http.lowSpeedLimit'
'http.noEPSV:whether to disable the use of the EPSV ftp-command'
'i18n.commitEncoding:character encoding commit messages are stored in'
'i18n.logOutputEncoding:character encoding commit messages are output in'
'log.showroot:whether to show initial commit as a diff against an empty tree or not'
'merge.summary:whether to include summaries of merged commits'
'merge.tool:tool to use for merges (by git-mergetool)'
'merge.verbosity:amount of output shown by recursive merge strategy'
'pack.window:size of window used by git-pack-objects'
'pull.octopus:default merge strategy to use when pulling multiple branches'
'pull.twohead:default merge strategy to use when pulling a single branch'
'repack.usedeltabaseoffset:whether to allow git-repack to use delta-base offsets'
'show.difftree:default git-diff-tree options for git-show'
'showbranch.default:default set of branches for git-show-branch'
'tar.umask:umask to apply for git-tar-tree'
'user.email:email address used for commits'
'user.name:full name used for commits'
'user.signingkey:default GPG key to use when creating signed tags'
'whatchanged.difftree:default git-diff-tree arguments for git-whatchanged'
'receive.unpackLimit:maximum number of objects to unpack when pushing'
'receive.denyNonFastforwards:whether git-receive-pack denies ref updates which are not fast-forwards'
'transfer.unpackLimit:default value for fetch.unpackLimit and receive.unpackLimit'
'imap.Folder:IMAP folder to use with git-imap-send'
'imap.Tunnel:tunneling command to use for git-imap-send'
'imap.Host:host git-imap-send should connect to'
'imap.User:user git-imap-send should log in as'
'imap.Pass:password git-imap-send should use when logging in'
'imap.Port:port git-imap-send should connect on'
'instaweb.local:whether instaweb should bind to 127.0.0.1'
'instaweb.httpd:HTTP-daemon command-line to execute for instaweb'
'instaweb.port:port to bind HTTP daemon to for instaweb'
'instaweb.browser:web-browser command-line to execute for instaweb'
'instaweb.modulepath:module path for the Apache HTTP-daemon for instaweb'
'svn.noMetadata:disable git-svn-id\: lines at end of commits (fetch, clone, dcommit, set-tree, rebase)'
'svn.useSvmProps:whether to use remappings of URLs and UUIDs from mirrors (fetch, clone, dcommit, set-tree, rebase)'
'svn.useSvnsyncProps:similar to useSvmProps, but for the svnsync command (fetch, clone, dcommit, set-tree, rebase)'
'svn.followparent:whether to follow parent commit (fetch, clone, dcommit, set-tree, rebase)'
'svn.authorsfile:default authors file to use (fetch, clone, dcommit, set-tree, rebase)'
'svn.username:username to use for SVN transport (fetch, clone, dcommit, set-tree, rebase, init)'
'svn.configdir:configuration directory to use (fetch, clone, dcommit, set-tree, rebase, init)'
'svn.noauthcache:undocumented (fetch, clone, dcommit, set-tree, rebase, init)'
'svn.quiet:make git-svn less verbose (fetch, clone, dcommit, set-tree, rebase)'
'svn.repack:repack files (for given number of revisions) (fetch, clone, dcommit, set-tree, rebase)'
'svn.repackflags:flags to pass to git-repack (fetch, clone, dcommit, set-tree, rebase)'
'svn.logwindowsize:undocumented (fetch, clone, dcommit, set-tree, rebase)'
'svn.shared:share repository amongst several users (init, clone)'
'svn.template:directory to use as a template for the object database (init, clone)'
'svn.trunk:trunk sub-directory to use (init, clone)'
'svn.tags:tags sub-directory to use (init, clone)'
'svn.branches:branches sub-directory to use (init, clone)'
'svn.prefix:prefix to use for names on remotes (init, clone)'
'svn.rmdir:remove empty directories from SVN tree after commit (dcommit, set-tree, commit-diff)'
'svn.edit:edit commit message before committing (dcommit, set-tree, commit-diff)'
'svn.findcopiesharder:try harder to find copies (dcommit, set-tree, commit-diff)'
'svn.l:limit number of rename/copy targets to run (dcommit, set-tree, commit-diff)'
'svn.copysimilarity:undocumented (dcommit, set-tree, commit-diff)'
'svn.revision:only use given revision or revision range (fetch, clone, show-ignore, log, commit-diff)'
'svn.merge:use merging strategies, if necessary (dcommit, rebase)'
'svn.fetch-all:undocumented (fetch, dcommit, rebase)'
'svn.stdin:read list of commits to commit from stdin (set-tree)'
'svn.strategy:use given merge strategy (dcommit, rebase)'
'svn.verbose:output extra information (dcommit, log, rebase)'
'svn.dryrun:output git-commands that would show diffs that would be committed (dcommit)'
'svn.minimize:undocumented (migrate)'
'svn.limit:like --max-count, but not counting merged/excluded commits (log)'
'svn.incremental:give output suitable for concatenation (log)'
'svn.showcommit:output git commit SHA-1, as well (log)'
'svn.oneline:similar to --pretty=oneline (log)'
'svn.color:undocumented (log)'
'svn.pager:undocumented (log)'
'svn.nonrecursive:undocumented (log)'
'svn.local:undocumented (rebase)'
'svn.message:undocumented (commit-diff)'
'svn.file:(commit-diff) undocumented')
declare -a suffixed_names
suffixed_names=(
'alias:command aliases'
'branch:prefix for branch-specific variables'
'remote:prefix for remote-repository variables'
'remotes:prefix for remote-groups'
'gitcvs:prefix for git-cvsserver-specific variables'
'svn-remote:prefix for git-svn remote-repository variables')
_describe -t suffixed-names 'special name' suffixed_names -M 'm:{a-zA-Z}={A-Za-z}' -M 'r:|.=* r:|=*' -S '.' -r '.' && ret=0
fi
_describe -t names $label names -M 'm:{a-zA-Z}={A-Za-z}' -M 'r:|.=* r:|=*' && ret=0
}
(( $+functions[__git_config_gettable_name] )) ||
__git_config_gettable_name () {
local expl
declare -a names
# TODO: This is strictly not correct, as names can have equal signs in them
# as well. However, theres no good way to tell from the output of
# git-config, so thisll have to do until we write our own .git/config
# parser (which will never happen because its not worth the trouble).
names=(${${(f)"$(_call_program names git config --list)"}%%\=*})
__git_command_successful || return
_wanted names expl 'names' compadd $names
}
(( $+functions[__git_config_filtered_gettable_name] )) ||
__git_config_filtered_gettable_name () {
local expl
declare -a names
# TODO: See __git_config_gettable_name for discussion on how to actually get
# out the names, skipping the values.
names=(${${(M)${${(f)"$(_call_program $2 git config --list)"}%%\=*}:#$1.*}#$1.})
__git_command_successful || return
_wanted $2 expl $3 compadd $names
}
(( $+functions[__git_remote-groups] )) ||
__git_remote-groups () {
__git_config_filtered_gettable_name 'remotes' remote-groups 'remote-groups'
}
(( $+functions[__git_svn-remotes] )) ||
__git_svn-remotes () {
local expl
declare -a names
# TODO: See __git_config_gettable_name for discussion on how to actually get
# out the names, skipping the values.
names=(${${${(M)${${(f)"$(_call_program $2 git config --list)"}%%\=*}:#svn-remote.*}#svn-remote.}%%.*})
__git_command_successful || return
_wanted svn-remotes expl 'svn remote' compadd $names
}
# TODO: Itd be really cool if both the default and the current value could be
# shown for all values.
(( $+functions[__git_config_values] )) ||
__git_config_values () {
local compadd_opts
zparseopts -D -E -a compadd_opts M: J: V: 1 2 n F: X:
case $1 in
((#i)core.fileMode)
declare -a booleans
booleans=(
{true,yes}':track changes to executable bit of files'
{false,no}':ignore changes to executable bit of files')
_describe -t boolean 'boolean' booleans
;;
((#i)core.autocrlf)
declare -a modes
modes=(
{true,yes}':convert CRLF to LF when reading and LF to CRLF when writing'
{false,no}':leave CRLF at the end of lines in text files as is'
'input:convert CRLF to LF when reading')
_describe -t crlfmode 'crlf mode' modes
;;
((#i)core.symlinks)
declare -a booleans
booleans=(
{true,yes}':record symlink files as such'
{false,no}':check out symlinks as plain files that contain the link text')
_describe -t boolean 'boolean' booleans
;;
((#i)core.gitProxy)
_message 'proxy command'
;;
((#i)core.ignoreStat)
declare -a booleans
booleans=(
{true,yes}':working-copy files are unchanged until marked as changed'
{false,no}':use lstat() to determine if a file has changed')
_describe -t boolean 'boolean' booleans
;;
((#i)core.preferSymlinkRefs)
declare -a booleans
booleans=(
{true,yes}':use symbolic links for symbolic reference files'
{false,no}':use "symref" files for symbolic reference files')
_describe -t boolean 'boolean' booleans
;;
((#i)core.bare)
declare -a booleans
booleans=(
{true,yes}':the repository does not have a working directory'
{false,no}':the repository has a working directory')
_describe -t boolean 'boolean' booleans
;;
((#i)core.logAllRefUpdates)
declare -a booleans
booleans=(
{true,yes}':create ref files for branch heads'
{false,no}":don't automatically create ref files")
_describe -t boolean 'boolean' booleans
;;
((#i)core.repositoryFormatVersion)
_message 'repository format version string (internal)'
;;
((#i)core.sharedRepository)
__git_repository_permissions
;;
((#i)core.warnAmbiguousRefs)
declare -a booleans
booleans=(
{true,yes}':warn if a ref name matches multiple refs'
{false,no}':ignore ambiguous ref names')
_describe -t boolean 'boolean' booleans
;;
((#i)core.compression)
declare -a levels
levels=(
'-1:default level of compression'
'0:do not deflate files'
'1:minimum compression'
'2:a little more compression'
'3:slightly more compression'
'4:a bit more compression'
'5:even more compression'
'6:slightly even more compression'
'7:getting there'
'8:close to maximum compression'
'9:maximum compression')
_describe -t compression-level 'compression level' levels
;;
((#i)core.legacyheaders)
declare -a booleans
booleans=(
{true,yes}':use compatiblity format for loose objects'
{false,no}':use new, more efficient, format for loose objects')
_describe -t boolean 'boolean' booleans
;;
((#i)core.(packedGit(WindowSize|Limit)|deltaBaseCacheLimit))
_guard '[[:digit:]]#([kmg]|)' 'number of bytes'
;;
((#i)alias.*)
_message 'git sub-command with arguments'
;;
((#i)apply.whitespace)
__git_apply_whitespace_strategies
;;
((#i)branch.*.remote)
__git_remotes
;;
((#i)branch.*.merge)
__git_references
;;
((#i)color.(branch|diff|pager|status))
declare -a booleans
booleans=(
{always,true}':always output in color'
{never,false}':never output in color'
'auto:output in color if to a terminal')
_describe -t boolean 'boolean' booleans
;;
((#i)color.*.*)
compset -P '* '
case ($words[CURRENT]) in
(?*' '?*' '*)
if [[ $words[CURRENT] == *(bold|dim|ul|blink|reverse)* ]]; then
__git_colors
else
__git_color_attributes
fi
;;
(*)
local suffix q_flag
if [[ $words[CURRENT] == [\"\']* ]]; then
suffix=' '
q_flag=-q
else
suffix='\ '
fi
if [[ $words[CURRENT] == *(bold|dim|ul|blink|reverse)* ]]; then
__git_colors -S $suffix $q_flag
else
_alternative \
'colors:color:__git_colors -S $suffix $q_flag' \
'attributes:attribute:__git_color_attributes -S $suffix $q_flag'
fi
;;
esac
;;
((#i)diff.renameLimit)
_guard "[[:digit:]]#" number
;;
((#i)diff.renames)
declare -a settings
settings=(
{true,yes}':enable basic rename detection'
{false,no}":don't try to detect renames"
{copies,copy}':detect file renames and copies')
_describe -t values 'rename-detection setting' settings
;;
((#i)(fetch|receive|transfer).unpackLimit)
_guard "[[:digit:]]#" 'maximum number of objects to unpack'
;;
((#i)format.headers)
_message 'email header'
;;
((#i)format.suffix)
_message 'filename suffix'
;;
((#i)gc.packrefs)
declare -a values
values=(
{true,yes}':pack references when collecting garbage'
{false,no}':leave references alone when collecting garbage'
'notbare:pack references if the repository has a working directory')
_describe -t values 'value' values
;;
((#i)gc.(reflogexpire(unreachable|)|rerere(un|)resolved))
# TODO: It would be nice if the default value was shown under a separate
# description/tag.
__git_datetimes
;;
((#i)gitcvs.(*.|)enabled)
declare -a booleans
booleans=(
{true,yes}':enable the cvs server interface'
{false,no}":don't enable the cvs server interface")
_describe -t booleans 'boolean' booleans
;;
((#i)gitcvs.(*.|)logfile)
_files
;;
((#i)gitcvs.(*.|)allbinary)
declare -a booleans
booleans=(
{true,yes}':tell the client to treat all files as binary'
{false,no}':treat files normally')
_describe -t booleans 'boolean' booleans
;;
((#i)gitcvs.dbname)
# TODO: In the future, when computers are self-aware and this wont
# really matter anymore, one could inspect what gitcvs.dbdriver is set to
# and complete possible databases for that DBI driver.
_message -e 'database name'
;;
((#i)gitcvs.dbdriver)
declare -a drivers
# TODO: Would be nice to only include those that are installed, but I
# couldnt figure out a good way of doing that when I wrote this code.
drivers=(
'SQLite:use the SQLite database driver (default)'
'Pg:use the Pg database driver')
_describe -t dbi-drivers 'DBI driver' drivers
;;
((#i)gitcvs.dbuser)
local expl
_description users expl 'database user'
_users $expl
;;
((#i)gitcvs.dbpass)
_message -e 'database password'
;;
((#i)http.sslVerify)
declare -a booleans
booleans=(
{true,yes}':verify SSL certificates when fetching or pushing over HTTP'
{false,no}':skip verification of SSL certificates')
_describe -t booleans 'boolean' booleans
;;
((#i)http.sslCert)
local expl
_wanted files expl 'SSL certificate file' _files
;;
((#i)http.sslKey)
local expl
_wanted files expl 'SSL private-key file' _files
;;
((#i)http.sslCAInfo)
local expl
_wanted files expl 'certificates file' _files
;;
((#i)http.sslCAPath)
local expl
_wanted files expl 'CA certificates file' _files
;;
((#i)http.maxRequests)
_guard "[[:digit:]]#" 'maximum number of requests'
;;
((#i)http.lowSpeedLimit)
# TODO: Need a better description
_guard "[[:digit:]]#([kmg]|)" number
;;
((#i)http.lowSpeedTime)
_guard "[[:digit:]]#" seconds
;;
((#i)http.noEPSV)
declare -a booleans
booleans=(
{true,yes}":don't use EPSV mode over FTP (for stupid servers)"
{false,no}':use EPSV mode over FTP')
_describe -t booleans 'boolean' booleans
;;
((#i)i18n.(commitEncoding|logOutputEncoding))
__git_encodings
;;
((#i)log.showroot)
declare -a booleans
booleans=(
{true,yes}':show initial commit as a diff against an empty tree'
{false,no}':hide initial commit')
_describe -t booleans 'boolean' booleans
;;
((#i)merge.summary)
declare -a booleans
# TODO: Use (default) in more descriptions.
booleans=(
{true,yes}':include summaries in merge commit messages'
{false,no}":don't add summaries to merge commit messages (default)")
_describe -t booleans 'boolean' booleans
;;
((#i)merge.tool)
declare -a tools
tools=(kdiff3 tkdiff meld xxdiff emerge vimdiff)
_describe -t merge-tools 'merge tool' tools
;;
((#i)merge.verbosity)
declare -a levels
levels=(
'0:only final error message if conflicts were detected'
'1:conflicts'
'2:conflicts and file changes'
'5:debugging information')
_describe -t verbosity-levels 'verbosity level' levels
;;
((#i)pack.window)
_guard '[[:digit:]]#' 'window size'
;;
((#i)pull.(octopus|twohead))
__git_merge_strategies
;;
((#i)remote.*.url)
_urls
;;
((#i)remote.*.fetch)
: TODO
;;
((#i)remote.*.push)
: TODO
;;
((#i)remote.*.skipDefaultUpdate)
declare -a booleans
booleans=(
{true,yes}':skip this remote by default'
{false,no}':update this remote by default')
_describe -t booleans 'boolean' booleans
;;
((#i)remote.*.(receivepack|uploadpack))
# TODO: Perhaps actually use SSH here?
local expl
_wanted files expl "remote git-${${1##*.}%pack}-pack program" _files -g *(*)
;;
((#i)remote.*.tagopt)
declare -a opts
opts=(
"--no-tags:don't fetch tags automatically"
'"":fetch tags as usual')
_describe -t tag-options 'tag retrieval' opts
;;
((#i)remotes.*)
compset -P '* '
local suffix
if [[ $words[CURRENT] == [\"\']* ]]; then
suffix=' '
else
suffix='\ '
fi
# TODO: Should really only complete unique remotes, that is, not the same
# remote more than once in the list.
__git_remotes -S $suffix -q
;;
((#i)repack.usedeltabaseoffset)
declare -a booleans
booleas=(
{true,yes}':allow creation of delta-base-offset packs'
{false,no}":don't create delta-base-offset packs")
_describe -t booleans 'boolean' booleans
;;
((#i)show.difftree)
# TODO: This should complete the options available to these two commands.
_message 'default options to git-diff-tree and git-show'
;;
((#i)showbranch.default)
__git_branch_names
;;
((#i)tar.umask)
_alternative \
'number: :_guard "[0-7]#" "numeric mode"' \
"values:special value:((user:\"use user's current umask\"))"
;;
((#i)user.email)
_email_addresses
;;
((#i)user.name)
_users
;;
((#i)user.signingkey)
__git_gpg_secret_keys
;;
((#i)whatchanged.difftree)
# TODO: This should complete the options available to git-diff-tree.
_message 'default options to git-diff-tree when invoking git-whatchanged'
;;
((#i)receive.denyNonFastForwards)
declare -a booleans
booleans=(
{true,yes}":git-receive-pack will deny a ref update that isn't a fast forward"
{false,no}":allow a ref update that isn't a fast forward")
_describe -t booleans 'boolean' booleans
;;
((#i)imap.folder)
_mailboxes
;;
((#i)imap.tunnel)
_message -e commands 'imap tunneling command'
;;
((#i)imap.host)
_hosts
;;
((#i)imap.user)
# TODO: If imap.host is set, complete users on that system?
_users
;;
((#i)imap.pass)
_message -e passwords 'imap password'
;;
((#i)imap.port)
_ports
;;
((#i)instaweb.local)
declare -a booleans
booleans=(
{true,yes}':bind the HTTP daemon to 127.0.0.1'
{false,no}":don't bind the HTTP daemon to a specific address")
_describe -t booleans 'boolean' booleans
;;
((#i)instaweb.httpd)
_message -e command-lines 'HTTP-daemon command-line'
;;
((#i)instaweb.port)
_ports
;;
((#i)instaweb.browser)
_message -e command-lines 'web-browser command-line'
;;
((#i)instaweb.modulepath)
local expl
_description directories expl 'module path'
_directories $expl
;;
((#i)(svn.|svn-remote.*.)noMetaData)
declare -a booleans
booleans=(
{true,yes}':disable git-svn-id: lines at end of commits'
{false,no}':add git-svn-id: lines at end of commits')
_describe -t booleans 'boolean' booleans
;;
((#i)(svn.|svn-remote.*.)(useSvmProps|useSvnsyncProps))
declare -a booleans
booleans=(
{true,yes}':remap URLs and UUIDs for mirrors'
{false,no}":don't remap URLs and UUIDs for mirrors")
_describe -t booleans 'boolean' booleans
;;
((#i)svn.followparent)
__git_boolean_settings true 'follow parent commit'
;;
((#i)svn.authorsfile)
local expl
_description files expl 'authors-conversion file'
_files $expl
;;
((#i)svn.username)
_users
;;
((#i)svn.configdir)
_directories
;;
((#i)svn.noauthcache)
# TODO: Update description once this gets documented.
__git_boolean_settings false 'use auth cache'
;;
((#i)svn.quiet)
__git_boolean_settings false 'make git-svn less verbose' 'let git-svn produce verbose output'
;;
((#i)svn.repack)
_guard '[[:digit:]]#' 'revision limit'
;;
((#i)svn.repackflags)
# TODO: Should complete git-repack arguments
_message -e 'git-repack flags'
;;
((#i)svn.logwindowsize)
# TODO: Update description once this gets documented.
_guard '[[:digit:]]#' 'log-window size'
;;
((#i)svn.shared)
__git_repository_permissions
;;
((#i)svn.template)
# NOTE: This is of course ridiculous, as this can never be useful. Only
# here for completeness.
_directories
;;
((#i)svn.(trunk|tags|branches))
_alternative \
'sub-directories:sub-directory:_directories' \
'urls: :_urls' && ret=0
;;
((#i)svn.prefix)
_message -e 'prefix'
;;
((#i)svn.rmdir)
__git_boolean_settings false 'remove empty directories from SVN tree after commit' 'leave empty directories from SVN tree after commit'
;;
((#i)svn.edit)
__git_boolean_settings false 'edit commit message before committing' 'use commit message from SVN'
;;
((#i)svn.findcopiesharder)
__git_boolean_settings false 'try harder to find copies' 'use simple copy-finding algorithm'
;;
((#i)svn.l)
_guard "[[:digit:]]#" number
;;
((#i)svn.copysimilarity)
__git_boolean_settings false 'undocumented'
;;
((#i)svn.revision)
__git_svn_revisions
;;
((#i)svn.merge)
__git_boolean_settings false 'use merging strategies' "don't try to merge"
;;
((#i)svn.fetch-all)
__git_boolean_settings false 'undocumented'
;;
((#i)svn.stdin)
__git_boolean_settings false 'read list of commits to commit from stdin' "don't necessarily read list of commits to commit from stdin"
;;
((#i)svn.strategy)
__git_merge_strategies
;;
((#i)svn.verbose)
__git_boolean_settings false 'output extra information'
;;
((#i)svn.dryrun)
__git_boolean_settings false 'output git-commands that would show diffs that would be committed' 'actually run the git commands'
;;
((#i)svn.minimize)
__git_boolean_settings false 'undocumented'
;;
((#i)svn.limit)
_guard "[[:digit:]]#" limit
;;
((#i)svn.incremental)
__git_boolean_settings false 'give output suitable for concatenation'
;;
((#i)svn.showcommit)
__git_boolean_settings false 'output git commit SHA-1, as well' "don't output git commit SHA-1"
;;
((#i)svn.online)
__git_boolean_settings false 'produce output similar to --pretty=oneline'
;;
((#i)svn.color)
__git_boolean_settings false 'undocumented'
;;
((#i)svn.pager)
_message -e 'undocumented'
;;
((#i)svn.nonrecursive)
__git_boolean_settings false 'undocumented'
;;
((#i)svn.local)
__git_boolean_settings false 'undocumented'
;;
((#i)svn.message)
_message -e 'undocumented'
;;
((#i)svn.file)
_message -e 'undocumented'
;;
((#i)svn-remote.*.rewriteRoot)
_message -e 'new root'
;;
(*)
_message 'value'
;;
esac
}
# __git_boolean_settings [-t TAG] [-l LABEL] DEFAULT 'follow parent commit' ['follow HEAD commit']
#
# -t can be used to specify a tag to use (default: booleans).
# -l can be used to specify a label to use (default: 'boolean').
#
# The first argument is the default value, so that the description of the
# default value can be suffixed with " (default)". The second argument
# is the description for the true value. If a third argument is given,
# it is used as the description for the false value. If it is not given,
# the description will be the true value's description with the prefix
# "don't ".
(( $+functions[__git_boolean_settings] )) ||
__git_boolean_settings () {
local tag label garbage
zparseopts -D -E -a garba S: M: J: V: 1 2 n F: X: -t=tag -l=label
declare -A descriptions
descriptions=(true $2 false "don't $2")
if (( $# > 2 )); then
descriptions[false]=$3
fi
descriptions[$1]+=" (default)"
declare -a booleans
booleans=(
{true,yes}':'$descriptions[true]
{false,no}':'$descriptions[false])
_describe -t ${tag:-booleans} ${label:-boolean} booleans
}
# TODO: Use this function in other places.
(( $+functions[__git_colors] )) ||
__git_colors () {
declare -a colors
colors=(black red green yellow blue magenta cyan white)
_describe -t colors 'color' colors $*
}
# TODO: Use this function in other places.
(( $+functions[__git_color_attributes] )) ||
__git_color_attributes () {
declare -a attributes
attributes=(bold dim ul blink reverse)
_describe -t attributes 'attribute' attributes $*
}
(( $+functions[__git_config_section_names] )) ||
__git_config_section_names () {
# TODO: Come up with a good way of extracting this information.
_guard "?#" "section name"
}
(( $+functions[__git_archive_formats] )) ||
__git_archive_formats () {
local expl
declare -a formats
formats=(${${(f)"$(_call_program archive-formats git archive --list)"}})
__git_command_successful || return
_wanted archive-formats expl 'archive format' compadd $formats
}
(( $+functions[__git_gpg_secret_keys] )) ||
__git_gpg_secret_keys () {
local expl
_wanted secret-keys expl 'secret key' compadd \
${${(Mo)$(_call_program secret-keys gpg --list-secret-keys 2>/dev/null):%<*>}//(<|>)/}
}
(( $+functions[__git_merge_strategies] )) ||
__git_merge_strategies () {
declare -a merge_strategies_cache
merge_strategies_cache=(${${=${${(M)${(f)"$(<$(git --exec-path)/git-merge)"}:#all_strategies*}##all_strategies=\'}%%\'}:#recur})
local expl
_wanted merge-strategies expl 'merge strategy' compadd - $merge_strategies_cache
}
# TODO: Use this in more places.
(( $+functions[__git_datetimes] )) ||
__git_datetimes () {
_guard "*" 'time specification'
}
# TODO: Use this in more places.
# TODO: Use better algorithm, as shown in iconv completer (separate it to a new
# Type).
(( $+functions[__git_encodings] )) ||
__git_encodings () {
local expl
_wanted encodings expl 'encoding' compadd "$@" \
-M 'm:{a-zA-Z}={A-Za-z} r:|-=* r:|=*' \
${${${(f)"$(_call_program encodings iconv --list)"}## #}%//}
}
(( $+functions[__git_repository_permissions] )) ||
__git_repository_permissions () {
declare -a permissions
permissions=(
{group,true,yes}':files and objects are group-writable'
{all,world,everybody}':files and objects are readable by all users and group-shareable'
{umask,false}':use permissions reported by umask()')
_describe -t permissions 'permission' permissions
}
(( $+functions[__git_apply_whitespace_strategies] )) ||
__git_apply_whitespace_strategies () {
declare -a strategies
strategies=(
'nowarn:turn off the trailing-whitespace warning'
'warn:output trailing-whitespace warning, but apply patch'
'error:output trailing-whitespace warning and refuse to apply patch'
'error-all:same as "error", but output warnings for all files'
'strip:output trailing-whitespace warning and strip trailing whitespace')
_describe -t strategies 'trailing-whitespace resolution strategy' strategies
}
(( $+functions[__git_svn_revisions] )) ||
__git_svn_revisions () {
if [[ -prefix *: ]]; then
compset -P '*:'
_alternative \
'revision-numbers: :__git_svn_revision_numbers' \
'symbolic-revisions:symbolic revision:((HEAD\:"the topmost revision of the SVN repository"))'
else
_alternative \
'revision-numbers: :__git_svn_revision_numbers' \
'symbolic-revisions:symbolic revision:__git_svn_base_revisions'
fi
}
(( $+functions[__git_svn_revision_numbers] )) ||
__git_svn_revision_numbers () {
_guard "[[:digit:]]#" "revision number"
}
(( $+functions[__git_svn_base_revisions] )) ||
__git_svn_base_revisions () {
declare -a revisions
revisions=(
'BASE:the bottommost revision of the SVN repository')
# TODO: How do we deal with $*?
_describe -t symbolic-revisions 'symbolic revision' revisions -S ':' -r ': '
}
# TODO: numparent is undocumented.
(( $+functions[__git_ref_sort_keys] )) ||
__git_ref_sort_keys () {
compset -P '-'
local -a keys
keys=(
'refname:the name of the ref'
'objecttype:the type of the object'
'objectsize:the size of the object'
'objectname:the object name (SHA-1)'
'tree:the tree header-field'
'parent:the parent header-field'
'numparent:undocumented'
'object:the object header-field'
'type:the type header-field'
'tag:the tag header-field'
'author:the author header-field'
'authorname:the name component of the author header-field'
'authoremail:the email component of the author header-field'
'authordate:the date component of the author header-field'
'committername:the name component of the committer header-field'
'committeremail:the email component of the committer header-field'
'committerdate:the date component of the committer header-field'
'taggername:the name component of the tagger header-field'
'taggeremail:the email component of the tagger header-field'
'taggerdate:the date component of the tagger header-field'
'creatorname:the name component of the creator header-field'
'creatordate:the date component of the creator header-field'
'subject:the subject of the message'
'body:the body of the message'
'body:the contents of the message (subject and body)')
_describe -t sort-keys 'sort key' keys
}
(( $+functions[__git_daemon_service] )) ||
__git_daemon_service () {
local -a services
services=(
'upload-pack:serve git-fetch-pack and git-peek-remote clients'
'upload-archive:serve git-archive --remote clients')
_describe -t services 'service' services
}
(( $+functions[__git_attributes] )) ||
__git_attributes () {
local -a attributes
attributes=(
'crlf:line-ending convention'
'ident:ident substitution'
'filter:filters'
'diff:textual diff'
'merge:merging strategy')
_describe -t attributes 'attribute' attributes
}
# ---
# TODO: How do we do -/n/ here?
# --reflog undocumented
# -m undocumented
# -v undocumented
# --root undocumented
# --no-commit-id undocumented
# --always undocumented
# --abbrev undocumented
# --abbrev-commit undocumented
# --full-diff undocumented
# --full-history undocumented
# --all-match undocumented
# optional argument to --unpacked undocumented
(( $+functions[__git_setup_revision_arguments] )) ||
__git_setup_revision_arguments () {
revision_arguments=(
'(-n --max-count -)'{-n+,--max-count=-}'[maximum number of commits to output]: :_guard "[[\:digit\:]]#" number'
'--skip=-[skip given number of commits before output]: :_guard "[[\:digit\:]]#" number'
'( --since --after)--max-age=-[maximum age of commits to output]: :_guard "[[\:digit\:]]#" timestamp'
'(--max-age --since --after)'{--since=-,--after=-}'[show commits more recent than given date]:date'
'( --until --before)--min-age[minimum age of commits to output]: :_guard "[[\:digit\:]]#" timestamp'
'(--min-age --until --before)'{--until=-,--before=-}'[show commits older than given date]: :_guard "[[\:digit\:]]#" timestamp'
'--all[show all commits from refs]'
'--cherry-pick[omit any same-change commits]'
'--reflog[show all commits from reflogs]'
'(-g --walk-reflogs)'{-g,--walk-reflogs}'[walk reflog entries from most recent to oldest]'
'*--not[reverses meaning of ^ prefix for revisions that follow]'
'--default[use argument as default revision]:default revision:__git_revisions'
'--merge[after a failed merge, show refs that touch files having a conflict]'
'( --date-order)--topo-order[show commits in topological order]'
'(--topo-order )--date-order[show commits in date order]'
'--parents[show parent commits]'
'( --sparse)--dense[this is the inverse of --sparse, and is also the default]'
'(--dense )--sparse[when paths are given, output only commits that changes any of them]'
'--remove-empty[stop when a given path disappears from the tree]'
'--no-merges[do not print commits with more than one parent]'
'--boundary[output uninteresting commits at the boundary]'
'--left-right[mark which side of a symmetric diff a commit is reachable from]'
'( --objects-edge)--objects[show object ids of objects referenced by the listed commits]'
'(--objects )--objects-edge[show object ids of objects referenced by the listed and excluded commits]'
'( -t)-r[show recursive diffs]'
'(-r )-t[show the tree objects in the diff output]'
'-m[do not ignore merges]'
'( --cc --full-diff)-c[show merge diffs from parents simultaneously]'
'(-c --full-diff)--cc[show merge diffs from parents simultaneously without one-parent diffs]'
'(-c --cc )--full-diff[undocumented]'
'( --pretty --header)-v[show verbose header]'
'(-v --header)'$pretty_arg
'--root[show root diff]'
'--no-commit-id[do not show commit ids]'
'--always[always show header]'
$abbrev_arg
'--abbrev-commit[undocumented]'
'--full-history[undocumented]'
'--relative-date[show dates relative to the current time]'
"--date=-[format of date output]:date format:((relative\:'show dates relative to the current time'
local\:\"show timestamps in user's local timezone\"
default\:'show timestamp in the original timezone\""
'--author=-[limit commits to those by the given author]:author'
'--committer=-[limit commits to those by the given committer]:committer'
'--grep=-[limit commits to those with log messages matching the given pattern]:pattern'
'--all-match[undocumented]'
'--encoding=-[output log messages in given encoding]::encoding:__git_encodings'
$diff_args)
if (( words[(I)--objects(|-edge)] )); then
revision_arguments+=('--unpacked=-[print object IDs that are not in packs]::object')
fi
}
# ---
(( $+functions[__git_is_indexed] )) ||
__git_is_indexed () {
[[ -n $(git ls-files $REPLY) ]]
}
local curcontext=$curcontext ret=1
if [[ $words[1] == git ]]; then
local state line
declare -A opt_args
_arguments -C \
'(- :)--version[display version information]' \
'(- :)--help[display help message]' \
'--exec-path=-[path containing core git-programs]::directory:_directories' \
'(-p --paginate)'{-p,--paginate}'[pipe output into $PAGER]' \
'--git-dir=-[path to repository]:directory:_directories' \
'--bare[use $PWD as repository]' \
':command:->command' \
'*::options:->options' && ret=0
case $state in
(command)
__git_aliases_and_commands
;;
(options)
curcontext="${curcontext%:*:*}:git-$words[1]:"
_call_function ret _git-$words[1]
;;
esac
else
_call_function ret _$words[1]
fi
}
_git