-
-
Save itspriddle/158362 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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-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 | |
_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]' \ | |
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--dirstat[generate a dirstat by amount of changes]' \ | |
'(--name-only --name-status -u -p --stat --patch-with-stat --patch-with-raw --raw --numstat --shortstat --summary)--dirstat-by-file[generate a dirstat by number of files]' \ | |
'-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]' | |
'(-1 --base)'{-1,--base}'[diff against stage 1]' | |
'(-2 --ours)'{-2,--ours}'[diff against stage 2]' | |
'(-3 --theirs)'{-3,--theirs}'[diff against stage 3]' | |
$abbrev_arg | |
$nul_arg | |
'--exit-code[report exit code 1 if differences, 0 otherwise]' | |
'--unified=[generate diffs with n lines of context]:n' | |
'--inter-hunk-context=[combine hunks closer than n lines]:n' | |
'--patience[generate diffs with patience algorithm]' | |
'(--exit-code)--quiet[disable all output]' | |
'--relative=:path:_files -/' | |
) | |
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" | |
fuller\:"like full and includes dates" | |
email\:"use email headers like From and Subject" | |
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-stat)'{-n,--no-stat}'[do not show diffstat at the end of the merge]' | |
'--stat[show a diffstat at the end of the merge]' | |
'--no-commit[perform the merge but do not autocommit]' | |
'--squash[merge, but do not make a commit]' | |
'--log[fill in one-line descriptions of the commits being merged in the log message]' | |
'--no-log[do not list one-line descriptions of the commits being merged in the log message]' | |
'--no-ff[generate a merge commit even if the merge resolved as a fast-forward]' | |
'--ff[do not generate a merge commit if the merge resolved as a fast-forward]' | |
'*'{-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]' | |
'(-q --quiet)'{-q,--quiet}'[do not print any results to stdout]' | |
'(-v --verbose)'{-v,--verbose}'[output extra information]' | |
'--depth=[deepen the history of a shallow repository by the given number of commits]: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 the 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' | |
'stage:add file contents to the staging area' | |
'stash:stash away changes to the working tree' | |
'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' | |
'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' | |
'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]:number of characters' \ | |
'*-C-[detect copied lines from other files from same commit as well]: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")]' \ | |
'--include=-[include files matching specified pattern]:pattern' \ | |
'--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 don’t 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-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 \ | |
'(-q --quiet)'{-q,--quiet}'[do not print any results to stdout]' \ | |
'--bare[create a bare repository]' \ | |
$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: Shouldn’t 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]: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]: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 \ | |
'--trivial[restrict three-way merge to only happen if no file-level merging is required]' \ | |
'--index-output=[write index in the named file instead of $GIT_INDEX_FILE]:file:_files' \ | |
'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' | |
'rm:remove a remote from .git/config and all associated tracking branches' | |
'rename:rename a remote from .git/config and update all associated tracking branches') | |
_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) | |
_arguments \ | |
'-n[do not contact the remote for a list of branches]' \ | |
':remote:__git_remotes' && ret=0 | |
;; | |
(prune) | |
_arguments \ | |
'(--dry-run -n)'{-n,--dry-run}'[do not actually prune, only list what would be done]' \ | |
':remote:__git_remotes' && ret=0 | |
;; | |
(update) | |
__git_remote-groups && ret=0 | |
;; | |
(rm) | |
__git_remotes && ret=0 | |
;; | |
(rename) | |
__git_remotes && 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 | |
} | |
# shouldn't complete objects after --batch{,-check}... | |
(( $+functions[_git-cat-file] )) || | |
_git-cat-file () { | |
_arguments \ | |
'(-t -s -e -p --batch-check 1)--batch[print the SHA1, type, size, and contents of each object provided on stdin]' \ | |
'(-t -s -e -p --batch 1)--batch-check[print the SHA1, type, and size of each object provided on stdin]' \ | |
'( -s -e -p --batch-check --batch 1)-t[show the type of the given object]' \ | |
'(-t -e -p --batch-check --batch 1)-s[show the size of the given object]' \ | |
'(-t -s -p --batch-check --batch 1)-e[exit with zero status if object exists]' \ | |
'(-t -s -e --batch-check --batch 1)-p[pretty-print the given object]' \ | |
'(-t -s -e -p --batch-check --batch ):object type:(blob commit tag tree)' \ | |
'(-t -s -e -p --batch-check --batch ):object:__git_objects' && ret=0 | |
} | |
(( $+functions[_git-describe] )) || | |
_git-describe () { | |
_arguments \ | |
'--all[use any ref found in "$GIT_DIR/refs/"]' \ | |
'--tags[use any ref found in "$GIT_DIR/refs/tags"]' \ | |
'(--contains)--tags[use any tag found in "$GIT_DIR/refs/tags/"]' \ | |
$abbrev_arg \ | |
'--contains[find the tag after the commit instead of before]' \ | |
'--exact-match[only output exact matches, same as --candidates=0]' \ | |
'--always[show uniquely abbreviated commit object as fallback]' \ | |
'--long[always show full format, even for exact matches]' \ | |
'--match=[only consider tags matching glob pattern]:pattern' \ | |
'--candidates=-[consider up to given number of candidates]: :_guard "[[\:digit\:]]##" "number of candidates"' \ | |
'--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"' \ | |
'--always[show uniquely abbreviated commit object as fallback]' \ | |
'--no-undefined[die with non-zero return when a reference is undefined]' \ | |
'(--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. | |
(( $+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_commit_ranges2' && 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 () { | |
local curcontext=$curcontext state line | |
typeset -A opt_args | |
__git_setup_revision_arguments | |
_arguments -S \ | |
$revision_arguments \ | |
'-s[do not show differences]' \ | |
'*:object:__git_objects' && 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 --dry-run)'{-n,--dry-run}'[do not actually add files; only show which ones would be added]' \ | |
'(-v --verbose)'{-v,--verbose}'[show files as they are added]' \ | |
'(-f --force)'{-f,--force}'[allow adding otherwise ignored files]' \ | |
'(-i --interactive : -)'{-i,--interactive}'[add contents interactively to the index]' \ | |
'(-p --patch)'{-p,--patch}'[like -i but go directly into patch mode for specified files]' \ | |
'(-u --update -A --all)'{-u,--update}'[update only files git already knows about]' \ | |
'(-A --all -u --update)'{-A,--all}'[act as both add . and add -u]' \ | |
'(-N --intent-to-add)'{-N,--intent-to-add}'[record only that the path will be added later]' \ | |
'--refresh[do not add files, but refresh their stat() info in the index]' \ | |
'--ignore-errors[continue adding if an error occurs]' \ | |
'*: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-stage] )) || | |
_git-stage () { | |
_git-add | |
} | |
(( $+functions[_git-am] )) || | |
_git-am () { | |
_arguments \ | |
'--3way[use 3-way merge if patch does not apply cleanly]' \ | |
'--abort[restore the original branch and abort the patching operation]' \ | |
'--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' \ | |
'(- :)'{-l,--list}'[list available archive formats]' \ | |
'(-v --verbose)'{-v,--verbose}'[report progress to stderr]' \ | |
'--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' \ | |
'--exec=-[path to git-receive-pack on remote]:remote path:_files' \ | |
':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" | |
skip:"choose a nearby commit" | |
run:"run evaluation script" | |
) | |
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|skip) | |
_arguments \ | |
'*:revision:__git_commits' && ret=0 | |
;; | |
(replay) | |
_arguments \ | |
'2:file:_files' && ret=0 | |
;; | |
(reset) | |
_arguments \ | |
'2:branch:__git_heads' && ret=0 | |
;; | |
(run) | |
_arguments \ | |
'*::arguments: _normal' && ret=0 | |
;; | |
(start) | |
if (( words[(I)--] < CURRENT && words[(I)--] > 0 )); then | |
_arguments \ | |
'*:paths:_files' && ret=0 | |
else | |
_arguments \ | |
'2:bad revision:__git_commits' \ | |
'*:good revision:__git_commits' && ret=0 | |
fi | |
;; | |
(*) | |
_nothing | |
;; | |
esac | |
fi | |
} | |
# TODO: complete branch names? | |
(( $+functions[_git-branch] )) || | |
_git-branch () { | |
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: I’m 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]' \ | |
$abbrev_arg \ | |
'--no-abbrev[do not abbreviate sha1s]' \ | |
- create \ | |
'-l[create the branch'\''s reflog]' \ | |
'-f[force the creation of a new branch]' \ | |
'--track[set up configuration so pull merges from the start point]' \ | |
'--no-track[override the branch.autosetupmerge configuration variable]' \ | |
'--contains=[only list branches which contain the specified commit]:commit:__git_committishs' \ | |
'--merged[only list branches which are fully contained by HEAD]' \ | |
'--no-merged[do not list branches which are fully contained by HEAD]' \ | |
':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 | |
(( $+functions[__git_is_treeish] )) || | |
__git_is_treeish () { | |
local sha1 | |
sha1="$(git rev-parse $1 -- 2> /dev/null)" && | |
[[ "$(git cat-file -t "${sha1}^{tree}" 2> /dev/null)" == tree ]] | |
} | |
# 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 | |
if compset -N '--'; then | |
__git_cached_files | |
else | |
_arguments -C -S \ | |
'-q[suppress feedback messages]' \ | |
- switch-branch \ | |
'-f[force a complete re-read]' \ | |
'-b[create a new branch based at given branch]: :__git_guard_branch-name' \ | |
{-t,--track}'[set up configuration so pull merges from the start point]' \ | |
'--no-track[override the branch.autosetupmerge configuration variable]' \ | |
'-l[create the branch'\''s reflog]' \ | |
$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 | |
fi | |
#XXX TODO and all that: $line[1] only works if you didn't write any options. | |
#What's the variable that holds the tree-ish argument? Is it even reliably possible? | |
case $state in | |
(files) | |
if [[ -n $line[1] ]] && __git_is_treeish $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]' \ | |
'(-m --mainline)'{-m,--mainline}'[specify mainline when cherry-picking a merge commit]:parent number' \ | |
'-x[append information about what commit was cherry-picked]' \ | |
'(-s --signoff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \ | |
':commit:__git_revisions' && ret=0 | |
} | |
(( $+functions[_git-clean] )) || | |
_git-clean () { | |
_arguments -S -s \ | |
'-d[also remove untracked directories]' \ | |
'-n[do a dry run]' \ | |
'-f[required when clean.requireForce is true (default)]' \ | |
'-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 () { | |
_arguments -S \ | |
'--bare[make a bare GIT repository]' \ | |
'--mirror[clone refs into refs/* instead of refs/remotes/origin/*]' \ | |
'(-l --local)'{-l,--local}'[clone locally, hardlink refs and objects if possible]' \ | |
'(-s --shared)'{-s,--shared}'[share the objects with the source repository (warning: see man page)]' \ | |
'--reference[reference repository]:repository:_directories' \ | |
'(-q --quiet)'{-q,--quiet}'[operate quietly]' \ | |
'(-v --verbose)'{-v,--verbose}'[always display the progressbar]' \ | |
'(-n --no-checkout)'{-n,--no-checkout}'[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' \ | |
'--no-hardlinks[copy files instead of hardlinking when doing a local clone]' \ | |
$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 \ | |
'--allow-empty[allow recording an empty commit]' \ | |
'(-a --all)'{-a,--all}'[update all paths in the index file]' \ | |
'--author[override the author name used in the commit]:author name' \ | |
'--cleanup=-[specify how the commit message should be cleaned up]:mode:((verbatim\:"don'\''t change the commit message at all" | |
whitespace\:"remove leading and trailing whitespace lines" | |
strip\:"remove both whitespace and commentary lines" | |
default\:"act as '\''strip'\'' if the message is to be edited and as '\''whitespace'\'' otherwise"))' \ | |
'(-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_changed_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 \ | |
'(--cached --staged)'{--cached,--staged}'[show diff between index and named commit]' \ | |
'::commit range:__git_commit_ranges' \ | |
'::original revision:__git_objects' \ | |
'::new revision:__git_objects' \ | |
'*::index file:__git_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' \ | |
'--subject-prefix=[use the given prefix instead of \[PATCH\]]:prefix' \ | |
'--cc=[add a Cc: header, may be given multiple times]:email address' \ | |
'--cover-letter[generate a cover letter template]' \ | |
'--no-binary[do not output contents of changes in binary files, only note that they differ]' \ | |
':commit range:__git_commit_ranges' && ret=0 | |
} | |
(( $+functions[_git-gc] )) || | |
_git-gc () { | |
_arguments \ | |
'--aggressive[more aggressively optimize]' \ | |
'--auto[check whether housekeeping is required]' \ | |
'--quiet[suppress all progress reports]' && 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 --name-only)'{-l,--files-with-matches,--name-only}'[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]' \ | |
{-z,--null}'[output \0 after filenames]' \ | |
'(-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 () { | |
local curcontext=$curcontext state line | |
declare -A opt_args | |
__git_setup_revision_arguments | |
_arguments -S \ | |
$revision_arguments \ | |
'--source[show which ref each commit is reached from]' \ | |
'--decorate[print out ref names of any commits that are shown.]' \ | |
'*:file-or-branch:->files' && ret=0 | |
case $state in | |
(files) | |
_arguments -S \ | |
'::index file:__git_cached_files' \ | |
'*::branch:__git_commit_ranges2' && ret=0 | |
;; | |
esac | |
} | |
# 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-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[push all refs under refs/heads/]' \ | |
'--mirror[push all refs under refs/heads/ and refs/tags/ and delete non-existing refs]' \ | |
'--dry-run[do everything except actually send the updates]' \ | |
'--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:__git_revisions' \ | |
'--continue[continue after failure]' \ | |
'--abort[abort current rebase]' \ | |
'--skip[skip the current patch]' \ | |
'--whitespace=-[detect a new or modified line that ends with trailing whitespaces]: :__git_apply_whitespace_strategies' \ | |
'(-m --merge)'{-m,--merge}'[use merging strategies to rebase]' \ | |
'*'{-s,--strategy=-}'[use given merge strategy]:merge strategy:__git_merge_strategies' \ | |
$verbose_arg \ | |
'--no-verify[bypass the pre-rebase hook]' \ | |
'-C-[ensure that given lines of surrounding context match]: :_guard "[[\:digit\:]]##" "lines of context"' \ | |
'(-i --interactive)'{-i,--interactive}'[make a list of commits to be rebased and open in $EDITOR]' \ | |
'(-p --preserve-merges)'{-p,--preserve-merges}'[try to recreate merges instead of ignoring them]' \ | |
':upstream branch:__git_revisions' \ | |
'::working branch:__git_revisions' && ret=0 | |
fi | |
} | |
(( $+functions[_git-repack] )) || | |
_git-repack () { | |
_arguments -s -w \ | |
'(-A)-a[pack all objects into a single pack]' \ | |
'(-a)-A[pack all objects into a single pack, but unreachable objects become loose]' \ | |
'-d[remove redundant packs after packing]' \ | |
'-f[pass "--no-reuse-objects" 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"]' \ | |
'--max-pack-size=-[maximum size of each output packfile]:MiB' \ | |
'--window-memory=-[scale window size dynamically to not use more than N bytes of memory]:bytes' \ | |
'--window=-[number of objects to consider when doing delta compression]:N' \ | |
'--depth=-[maximum delta depth]:N' && 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]' \ | |
'--merge[bring local changes along to new commit]' \ | |
$commit_arg \ | |
$path_arg && ret=0 | |
} | |
(( $+functions[_git-revert] )) || | |
_git-revert () { | |
_arguments -s -w \ | |
'(-e --edit)'{-e,--edit}'[edit the commit before committing the revert]' \ | |
'--no-edit[do not edit the commit message]' \ | |
'-x[append commit name when cherry-picking]' \ | |
'(-m --mainline)'{-m+,--mainline=}'[pick which parent is mainline]:parent number' \ | |
'(-n --no-commit)'{-n,--no-commit}'[do not commit the reversion]' \ | |
'(-s --signoff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \ | |
':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_stashes] )) || | |
__git_stashes () { | |
local expl | |
declare -a st_list | |
st_list=(${${(f)"$(_call_program stashes git stash list 2>/dev/null)"}/: */}) | |
__git_command_successful || return | |
_wanted tags expl stash-list compadd $* - $st_list | |
} | |
(( $+functions[_git-stash] )) || | |
_git-stash () { | |
local expl | |
local -a stash_cmds | |
stash_cmds=( | |
apply:"restore the changes recorded in the stash" | |
branch:"branch off at the commit at which the stash was originally created" | |
clear:"remove all the stashed states" | |
drop:"remove a single stashed state from the stash list" | |
list:"list the stashes that you currently have" | |
pop:"remove and apply a single stashed state from the stash list" | |
save:"save your local modifications to a new stash" | |
show:"show the changes recorded in the stash as a diff" | |
) | |
if (( CURRENT == 2 )); then | |
_describe -t command "git-stash commands" stash_cmds && ret=0 | |
else | |
case $words[2] in | |
(apply) | |
_arguments \ | |
'--index[try to reinstate the index'\''s changes too]' \ | |
'*:stash:__git_stashes' && ret=0 | |
;; | |
(branch) | |
_arguments \ | |
'2:branch name:' \ | |
'*:stash:__git_stashes' && ret=0 | |
;; | |
(drop|pop|show) | |
_arguments \ | |
'*:stash:__git_stashes' && ret=0 | |
;; | |
(save) | |
_arguments \ | |
'--keep-index[all changes already added to the index are left intact]' \ | |
'*: :->end' && ret=0 | |
[[ $state == 'end' ]] && _message 'message' | |
;; | |
(*) | |
_nothing | |
;; | |
esac | |
fi | |
} | |
(( $+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_branch_names' \ | |
'-P[read cvsps output file]:file:_files' \ | |
'-p[specify additional options for cvsps]:cvsps-options' \ | |
'-r[the git remote to import into]:remote' \ | |
'-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]: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]' \ | |
'--expire:time:' \ | |
'*::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]' \ | |
'--contains=[only list tags which contain the specified commit]:commit:__git_committishs' \ | |
$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-level 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' \ | |
{--before=-,--until=-}'[show "--min-age=" parameter corresponding given date string]:datestring' \ | |
'*:objects:__git_objects' && 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]' \ | |
'--ignore-unmatch[exit with 0 status even if no files matched]' \ | |
'(-q --quiet)'{-q,--quiet}'[do not output files deleted]' \ | |
'*: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: --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: --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' | |
'branch:create a branch in the SVN repository' | |
'tag:create a tag in the SVN repository' | |
'log:output SVN log-messages' | |
'blame:show what revision and author last modified each line of a file:' | |
'find-rev:output git commit corresponding to the given SVN revision'\''s hash' | |
'set-tree:commit given commit or tree to SVN repository' | |
'create-ignore:recursively finds the svn:ignore property and creates .gitignore files' | |
'show-ignore:output corresponding toplevel .gitignore file of svn:ignore' | |
'commit-diff:commit diff of two tree-ishs' | |
'info:show information about a file or directory' | |
'proplist:list the SVN properties stored for a file or directory' | |
'propget:get a given SVN property for a file' | |
'show-externals:show the subversion externals') | |
_describe -t commands command commands && ret=0 | |
;; | |
(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' | |
'--stdlayout[shorthand for setting trunk,tags,branches as relative paths, the SVN default]' | |
'--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' | |
'--use-log-author[use author from the first From: or Signed-Off-By: line, when fetching into git]' | |
'--add-author-from[when committing to svn, append a From: line based on the git commit'\''s author string]' | |
'--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 | |
if [[ $line[1] == (fetch|clone|log|create-ignore|info|propget|proplist|show-externals) ]]; 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]' | |
'*'{-s,--strategy=-}'[use given merge strategy]:merge strategy:__git_merge_strategies') | |
fi | |
if [[ $line[1] == (fetch|dcommit|rebase) ]]; then | |
arguments+=( | |
'(--fetch-all --all)'{--fetch-all,--all}'[undocumented]') | |
fi | |
if [[ $line[1] == (dcommit|log|rebase) ]]; then | |
arguments+=( | |
'(-v --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]' | |
'--no-rebase[do not rebase or reset after committing]' | |
'--commit-url[commit to a different SVN url]:SVN URL:_url') | |
;; | |
(branch) | |
arguments+=( | |
'(-m --message)'{-m,--message}'[specify the commit message]:message' | |
'(-t --tag)'{-t,--tag}'[create a tag]') | |
;; | |
(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]') | |
;; | |
(blame) | |
arguments+=( | |
'--git-format[produce output in git-blame format, with SVN revision numbers instead of git commit hashes]') | |
;; | |
(rebase) | |
arguments+=( | |
'--local[do not fetch remotely, rebase against the last fetched commit from SVN]') | |
;; | |
(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 () { | |
compset -P '*:' | |
if [[ -n $IPREFIX ]]; then | |
__git_tree_files "$PREFIX" "${IPREFIX%:}" | |
else | |
_alternative \ | |
'revisions:revision:__git_revisions' \ | |
'files:file:__git_files' | |
fi | |
} | |
(( $+functions[__git_trees] )) || | |
__git_trees () { | |
__git_objects | |
} | |
(( $+functions[__git_tree_ishs] )) || | |
__git_tree_ishs () { | |
__git_commits | |
} | |
(( $+functions[__git_blobs] )) || | |
__git_blobs () { | |
__git_objects | |
} | |
(( $+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 | |
} | |
#this is for git-commit which can take files both git-added and not | |
(( $+functions[__git_changed_files] )) || | |
__git_changed_files () { | |
local -a files | |
files=(${(ps:\0:)"$(_call_program files git diff-index -z --name-only --no-color HEAD 2>/dev/null)"}) | |
__git_command_successful || return | |
_wanted files expl 'index file' _multi_parts $@ - / files | |
} | |
(( $+functions[__git_tree_files] )) || | |
__git_tree_files () { | |
local multi_parts_opts | |
local tree Path | |
integer at_least_one_tree_added | |
local -a tree_files | |
[[ "$1" == */ ]] && Path="$1" || Path="${1:h}/" | |
shift | |
(( at_least_one_tree_added = 0 )) | |
for tree in $*; do | |
tree_files+=(${(ps:\0:)"$(_call_program tree-files git ls-tree --name-only -z $tree $Path 2>/dev/null)"}) | |
__git_command_successful && (( at_least_one_tree_added = 1 )) | |
done | |
if (( !at_least_one_tree_added )); then | |
return | |
fi | |
local expl | |
_wanted files expl 'tree file' _multi_parts -f $@ -- / 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 $* | |
} | |
(( $+functions[__git_commit_ranges2] )) || | |
__git_commit_ranges2 () { | |
_alternative \ | |
'commits::__git_commits2' \ | |
'ranges::__git_commit_ranges' | |
} | |
# 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 | |
_alternative \ | |
'tags:tag:__git_tags' \ | |
'heads:head:__git_heads -qS :' | |
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 headrefs git for-each-ref --format='"%(refname)"' refs/heads refs/remotes 2>/dev/null)"}#refs/(heads|remotes)/}) | |
__git_command_successful || return | |
_wanted heads expl branch-name compadd $* - $branch_names HEAD | |
} | |
(( $+functions[__git_tags] )) || | |
__git_tags () { | |
local expl | |
declare -a tag_names | |
tag_names=(${${(f)"$(_call_program tagrefs git for-each-ref --format='"%(refname)"' refs/tags 2>/dev/null)"}#refs/tags/}) | |
__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 won’t 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 branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}) | |
__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.interactive:when to color in interactive mode' | |
'color.interactive.header:color of header' | |
'color.interactive.help:color of help' | |
'color.interactive.prompt:color of prompt' | |
'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' | |
'commit.template:template file for commit messages' | |
'color.ui:when to color if output is capable; most generic option, overriding by more specific ones' | |
'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, there’s no good way to tell from the output of | |
# git-config, so this’ll have to do until we write our own .git/config | |
# parser (which will never happen because it’s 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: It’d 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 won’t | |
# 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 | |
# couldn’t 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 () { | |
local expl | |
local -a merge_strategies | |
if ! merge_strategies=(${=${${(M)${(f)"$(_call_program strategies git merge -s '' 2>&1)"}:#[Aa]vailable (custom )#strategies are: *}#[Aa]vailable (custom )#strategies are: }%.}); then | |
merge_strategies=(${=${${(M)${(f)"$(<$(git --exec-path)/git-merge)"}:#all_strategies*}##all_strategies=\'}%%\'}) | |
fi | |
_wanted merge-strategies expl 'merge strategy' compadd -a merge_strategies "$@" | |
} | |
# 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]' | |
'--branches[show all commits from refs/heads]' | |
'--tags[show all commits from refs/tags]' | |
'--remotes[show all commits from refs/remotes]' | |
'--cherry-pick[omit any same-change commits]' | |
'--graph[draw a graphical representation of the commit history]' | |
'--reflog[show all commits from reflogs]' | |
'(-g --walk-reflogs --reverse)'{-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]' | |
'(-g --walk-reflogs)--reverse[show commits in reverse 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]' | |
'--first-parent[follow only the first parent from merge commits]' | |
'--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]' | |
'--simplify-merges[milder version of --full-history]' | |
'--full-history[undocumented]' | |
'--simplify-by-decoration[show only commits that are referenced by a ref]' | |
'--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" | |
iso\:"show timestamps in ISO 8601 format" | |
rfc\:"show timestamps in RFC 2822 format" | |
short\:"show only date but not time" | |
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 | |
# fun with $words[] and $CURRENT to enable completion for args | |
# to git aliases (eg. git co <TAB>) | |
local -A git_aliases | |
local -a git_aliases__ | |
git_aliases__=(${(f)${${${(f)"$(_call_program alias_expansion git config --get-regexp '\^alias\.')"}#alias.}/ /$'\n'}/(#e)/$'\n'}) | |
if (( ( ${#git_aliases__} % 2 ) == 0 )) ; then | |
git_aliases=(${git_aliases__}) | |
fi | |
unset git_aliases__ | |
if (( CURRENT >= 3 )) && [[ -n ${git_aliases[$words[2]]} ]] ; then | |
local -a tmpwords expalias | |
expalias=(${(z)git_aliases[$words[2]]}) | |
tmpwords=(${words[1]} ${expalias}) | |
if [[ -n "${words[3,-1]}" ]] ; then | |
tmpwords+=(${words[3,-1]}) | |
fi | |
[[ -n ${words[$CURRENT]} ]] || tmpwords+=('') | |
(( CURRENT += ${#expalias} - 1 )) | |
words=("${tmpwords[@]}") | |
unset tmpwords expalias | |
fi | |
if [[ $service == 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]' \ | |
'--no-pager[do not pipe git output into a pager]' \ | |
'--git-dir=-[path to repository]:directory:_directories' \ | |
'--work-tree=-[path to working tree]:directory:_directories' \ | |
'--bare[use $PWD as repository]' \ | |
'*::arg:->cmd_or_options' && return | |
case $state in | |
(cmd_or_options) | |
if (( CURRENT == 1 )); then | |
__git_aliases_and_commands | |
else | |
curcontext="${curcontext%:*:*}:git-$words[1]:" | |
_call_function ret _git-$words[1] | |
fi | |
;; | |
esac | |
else | |
_call_function ret _$service | |
fi | |
} | |
_git |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment