From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18535 invoked from network); 25 Nov 2005 12:18:10 -0000 X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00, FORGED_RCVD_HELO autolearn=ham version=3.1.0 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 25 Nov 2005 12:18:10 -0000 Received: (qmail 75090 invoked from network); 25 Nov 2005 12:18:04 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 25 Nov 2005 12:18:04 -0000 Received: (qmail 5855 invoked by alias); 25 Nov 2005 12:18:01 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 22031 Received: (qmail 5843 invoked from network); 25 Nov 2005 12:18:00 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 25 Nov 2005 12:18:00 -0000 Received: (qmail 74808 invoked from network); 25 Nov 2005 12:18:00 -0000 Received: from mxfep02.bredband.com (195.54.107.73) by a.mx.sunsite.dk with SMTP; 25 Nov 2005 12:17:57 -0000 Received: from puritan.petwork ([213.112.43.250] [213.112.43.250]) by mxfep02.bredband.com with ESMTP id <20051125121756.NSWI9142.mxfep02.bredband.com@puritan.petwork> for ; Fri, 25 Nov 2005 13:17:56 +0100 Received: by puritan.petwork (Postfix, from userid 1000) id CBED5ADFE5; Fri, 25 Nov 2005 13:17:57 +0100 (CET) Date: Fri, 25 Nov 2005 13:17:57 +0100 From: Nikolai Weibull To: Zsh hackers list Subject: Re: New 4.2 release Message-ID: <20051125121757.GB8868@puritan.petwork> Mail-Followup-To: Zsh hackers list References: <200511251058.jAPAwA2e006823@news01.csr.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="gBBFr7Ir9EOA20Yy" Content-Disposition: inline In-Reply-To: <200511251058.jAPAwA2e006823@news01.csr.com> User-Agent: Mutt/1.5.11 --gBBFr7Ir9EOA20Yy Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Peter Stephenson wrote: > As well as producing a test release for 4.3.1, I'd like to release > 4.2.6 early next week. Let me know if there's anything that you think > needs merging into 4.2, such as completion functions (or do it yourself). > > There aren't that many changes but some of them are significant. > I'm not aware of any new incompatibilities. I have a completion function for git. It has far too many TODOs, and is far too untested, but it is a good start. I'm getting really bored with it, so if anyone wants to provide suggestions or fixes, then be my guest. Git is still under heavy development, so things may still change at that end. Perhaps we should wait until 4.2.7 to include this. nikolai -- Nikolai Weibull: now available free of charge at http://bitwi.se/! Born in Chicago, IL USA; currently residing in Gothenburg, Sweden. main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);} --gBBFr7Ir9EOA20Yy Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename=_git Content-Transfer-Encoding: quoted-printable #compdef git git-apply git-checkout-index git-commit-tree git-hash-object g= it-index-pack git-init-db git-merge-index git-mktag git-pack-objects git-pr= une-packed git-read-tree git-unpack-objects git-update-index git-write-tree= git-cat-file git-diff-index git-diff-files git-diff-stages git-diff-tree g= it-fsck-objects git-ls-files git-ls-tree git-merge-base git-name-rev git-re= v-list git-show-index git-tar-tree git-unpack-file git-var git-verify-pack = git-clone-pack git-fetch-pack git-http-fetch git-local-fetch git-peek-remot= e git-receive-pack git-send-pack git-ssh-fetch git-ssh-upload git-update-se= rver-info git-upload-pack git-add git-am git-applymbox git-bisect git-branc= h git-checkout git-cherry-pick git-clone git-commit git-diff git-fetch git-= format-patch git-grep git-log git-ls-remote git-merge git-mv git-octopus gi= t-pull git-push git-rebase git-repack git-reset git-resolve git-revert git-= shortlog git-show-branch git-status git-verify-tag git-whatchanged git-appl= ypatch git-archimport git-convert-objects git-cvsimport git-lost-found git-= merge-one-file git-prune git-relink git-svnimport git-symbolic-ref git-tag = git-update-ref git-check-ref-format git-cherry git-count-objects git-daemon= git-get-tar-commit-id git-mailinfo git-mailsplit git-patch-id git-request-= pull git-send-email git-stripspace # Commands not completed: # git-sh-setup # git-shell # git-parse-remote=20 # git-rev-parse=20 # TODO: most commands need a valid git repository to run, so add a check fo= r it # so that we can make our handling a little bit cleaner (need to deal with # GIT_DIR=3D... stuff as pre-command modifier) # TODO: suggested zstyles: # # zstyle ':completion::*:git-{name-rev,add,rm}:*' ignore-line true typeset -g nul_arg=3D nul_arg=3D'-z[use NUL termination on output]' typeset -ga diff_args # TODO: -s and --diff-filter are undocumented diff_args=3D( '--diff-filter=3D-[filter to apply to diff]' '--find-copies-harder[try harder to find copies]' '--name-only[show only names of changed files]' '--name-status[show only names and status of changed files]' '--pickaxe-all[when -S finds a change, show all changes in that changeset= ]' '-B-[break complete rewrite changes into pairs of given size]: :_guard "[= [\:digit\:]]#" size' '-C-[detect copies as well as renames with given score]: :_guard "[[\:dig= it\:]]#" size' '-l-[number of rename/copy targets to run]: :_guard "[[\:digit\:]]#" numb= er' '-M-[detect renames with given score]: :_guard "[[\:digit\:]]#" size' '-O-[output patch in the order of glob-pattern lines in given file]:file:= _files' '-p[generate diff in patch format]' '-R[do a reverse diff]' '-S-[look for differences that contain the given string]:string' '-s[do not produce any output]' '-u[synonym for -p]' $nul_arg ) typeset -g pretty_arg=3D pretty_arg=3D'--pretty=3D-[pretty print commit messages]::pretty print:((ra= w\:"the raw commits" medium= \:"most parts of the messages" short\= :"few headers and only subject of messages" full\:= "all parts of the commit messages" onelin= e\:"commit-ids and subject of messages"))' typeset -g exec_arg=3D exec_arg=3D'--exec=3D-[specify path to git-upload-pack on remote side]:remo= te path' typeset -ga fetch_args fetch_args=3D( '-a[fetch all objects]' '-c[fetch commit objects]' '--recover[recover from a failed fetch]' '-t[fetch trees associated with commit objects]' '-v[show what is downloaded]' '-w[write out the given commit-id to the given file]:new file' ) typeset -ga merge_strategy merge_strategy=3D( '(-s --strategy)'{-s,--strategy=3D}'[use given merge strategy]:strategy:(= octopus recursive resolve stupid)') typeset -ga force_ref_arg force_ref_arg=3D('(-f --force)'{-f,--force}'[allow refs that are not ancest= ors to be updated]') typeset -ga tags_fetch_arg tags_fetch_arg=3D('(-t --tags)'{-t,--tags}'[fetch remote tags]') # TODO: either skip uninteresting commands or skip the description - the li= st # is just too long _git_commands () { local -a commands commands=3D( 'add:add paths to the index' 'am:apply patches from a mailbox (cooler than applymbox)' 'apply:apply patch on a git index file and a work tree' 'applymbox:apply patches from a mailbox' 'applypatch:apply one patch extracted from an e-mail' 'archimport:import an Arch repository into git' 'bisect:find the change that introduced a bug' 'branch:create and show branches' 'cat-file:provide content or type information for repository objects' 'check-ref-format:makes sure that a reference-name is well formed' 'checkout:checkout and switch to a branch' 'checkout-index:copy files from the index to the working directory' 'cherry:find commits not merged upstream' 'cherry-pick:cherry-pick the effect of an existing commit' 'clone:clones a repository into a new directory' 'clone-pack:clones a repository into the current repository (transport)' 'commit:record changes to the repository' 'commit-tree:creates a new commit object' 'convert-objects:converts old-style git repository' 'count-objects:count unpacked objects and display their disk consumptio= n' 'cvsimport:import a CVS "repository" into a git repository' 'daemon:starts a really simple server for git repositories' 'diff:show changes between commits, commit and working tree, etc.' 'diff-files:compares files in the working tree and the index' 'diff-index:compares content and mode of blobs between index and reposi= tory' 'diff-stages:compares two "merge states" in the index file' 'diff-tree:compares the content and mode of blobs found via two tree ob= jects' 'fetch:download objects and a head from another repository' 'fetch-pack:receive missing objects from another repository' 'format-patch:prepare patches for e-mail submission' 'fsck-objects:verifies the connectivity and validity of the objects in = the database' 'get-tar-commit-id:extract commit ID from an archive created using tar-= tree' 'grep:print lines matching a pattern' 'hash-object:computes the object ID from a file' 'http-fetch:downloads a remote git repository via HTTP' 'index-pack:build pack index file for an existing packed archive' 'init-db:creates an empty git object database' 'local-fetch:duplicates another git repository on a local system' 'log:shows commit logs' 'lost-found:recovers lost references that luckily have not yet been pru= ned' 'ls-files:information about files in the index/working directory' 'ls-remote:shows references in a remote or local repository' 'ls-tree:displays a tree object in human-readable form' 'mailinfo:extracts patch from a single e-mail message' 'mailsplit:splits an mbox file into a list of files' 'merge:grand unified merge driver' 'merge-base:finds a good common ancestor as possible for a merge' 'merge-index:runs a merge for files needing merging' 'merge-one-file:standard helper-program to use with merge-index' 'mktag:creates a tag object' 'mv:moves or renames a file, directory, or symlink' 'name-rev:find symbolic names for given revisions' 'octopus:merges more than two commits' 'pack-objects:creates a packed archive of objects' 'parse-remote:routines to help parsing $GIT_DIR/remotes/' 'patch-id:computes unique ID for a apatch' 'peek-remote:lists references on a remote repository using the upload-p= ack protocol' 'prune:prunes all unreachable objects from the object database' 'prune-packed:removes extra objects that are already in pack files' 'pull:fetch from and merge with a remote repository' 'push:update remote refs along with associated objects' 'read-tree:reads tree information into the directory index' 'rebase:rebases local commits to new upstream head' 'receive-pack:command invoked by send-pack to receive what is pushed to= it' 'relink:hardlinks acommon objects in local repositories' 'repack:packs unpacked objects in a repository' 'request-pull:generates a summary of pending changes' 'reset:resets current HEAD to the specified state' 'resolve:merges two commits' 'rev-list:lists commit object in reverse chronological order' 'rev-parse:picks out and massages parameters for other git commands' 'revert:reverts an existing commit' 'send-email:sends patch-e-mails out of "format-patch --mbox" output' 'send-pack:pushes to a remote repository, intelligently' 'shortlog:summarizes git log output' 'show-branch:shows branches and their commits' 'show-index:displays contents of a pack idx file' 'ssh-fetch:pulls from a remote repository over an SSH connection' 'ssh-upload:helper "server-side" program used by ssh-fetch' "status:shows the working-tree's status" 'stripspace:filters out empty lines' 'svnimport:imports a SVN repository into git' 'symbolic-ref:reads and modifies symbolic references' 'tag:creates a tag object signed with GPG' 'tar-tree:creates a tar archive of the files in the named tree' "unpack-file:creates a temporary file with a blob's contents" 'unpack-objects:unpacks objects out of a packed archive' 'update-index:modifies the index in some given way' 'update-ref:updates the object name stored in a reference safely' 'update-server-info:updates auxiliary information on a dumb server' 'upload-pack:command invoked by clone-pack and fetch-pack' 'var:displays a git logical variable' 'verify-pack:validates packed git archive files' 'verify-tag:checks the GPG signature of a tag' 'whatchanged:shows commit-logs and differences they introduce' 'write-tree:creates a tree from the current index') _describe -t commands 'git command' commands && ret=3D0 } # TODO: this needs to be cleaned up and fixed local curcontext=3D$curcontext ret=3D1 if [[ $words[1] =3D=3D git ]]; then if (( CURRENT =3D=3D 2 )); then _git_commands else shift words (( CURRENT-- )) curcontext=3D"${curcontext%:*:*}:git-$words[1]:" _call_function ret _git-$words[1] fi else _call_function ret _$words[1] fi _git-apply () { _arguments \ $nul_arg \ '*--apply[apply patches that would otherwise not be applied]' \ '*--check[check if patches are applicable]' \ '*--exclude=3D-[skip files matching specified pattern]:file pattern' \ '*--index[make sure that the patch is applicable to the index]' \ '*--index-info[output information about original version of a blob if a= vailable]' \ '*--no-merge[do not use merge behavior]' \ '*--numstat[same as --stat but in decimal notation and complete pathnam= es]' \ '*--stat[output diffstat for the input]' \ '*--summary[output summary of git-diff extended headers]' \ '*:file:_files' && ret=3D0 } _git-checkout-index () { _arguments -S \ '(-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]' \ '(-q --quiet)'{-q,--quiet}'[do not complain about existing files or mis= sing files]' \ '(-u --index)'{-u,--index}'[update stat information in index]' \ '--prefix=3D-[prefix to use when creating files]:directory:_directories= ' \ '*:file:_files' && ret=3D0 } _git-commit-tree () { if (( CURRENT =3D=3D 2 )); then __git_trees && ret=3D0 elif [[ $words[CURRENT-1] =3D=3D -p ]]; then local expl _description commits expl 'parent commit' __git_objects $expl && ret=3D0 else compadd - '-p' fi } _git-hash-object () { _arguments \ '-t[the type of object to create]:object type:((blob\:"a blob of data" commit\:"a tree with pa= rent commits" tag\:"a symbolic name f= or another object" tree\:"a recursive tree= of blobs"))' \ '-w[write the object to the object database]' \ ':file:_files' && ret=3D0 } _git-index-pack () { _arguments \ '-o[write generated pack index into specified file]' \ ':pack file:_files -g "*.pack"' && ret=3D0 } _git-init-db () { _arguments \ '--template=3D-[directory to use as a template for the object database]= :directory:_directories' && ret=3D0 } _git-merge-index () { if (( CURRENT > 2 )) && [[ $words[CURRENT-1] !=3D -[oq] ]]; then _arguments -S \ '(:)-a[run merge against all files in the index that need merging]' \ '*:index file:__git_files' && ret=3D0 else typeset -a arguments (( CURRENT =3D=3D 2 )) && arguments+=3D'-o[skip failed merges]' (( CURRENT =3D=3D 2 || CURRENT =3D=3D 3 )) && arguments+=3D'(-o)-q[do n= ot complain about failed merges]' (( 2 <=3D CURRENT && CURRENT <=3D 4 )) && arguments+=3D'*:merge program= :_files -g "*(*)"' _arguments -S $arguments && ret=3D0 fi } _git-mktag () { _message 'no arguments allowed; only accepts tags on standard input' } _git-pack-objects () { _arguments \ '--depth=3D-[maximum delta depth]' \ '--incremental[ignore objects that have already been packed]' \ '--non-empty[only create a package if it contains at least one object]'= \ '--local[similar to --incremental, but only ignore unpacked non-local o= bjects]' \ '--window=3D-[number of objects to use per delta compression]' \ '(:)--stdout[write the pack to standard output]' \ ':base-name:_files' && ret=3D0 } _git-prune-packed () { _arguments \ '-n[only list the objects that would be removed]' && ret=3D0 } _git-read-tree () { if (( CURRENT =3D=3D 2 )); then _arguments \ '--reset[perform a merge, not just a read, ignoring unmerged entries]= ' \ '--trivial[only perform trivial merges]' \ '-m[perform a merge, not just a read]' \ ':tree-ish:__git_tree_ishs' && ret=3D0 elif [[ $words[2] =3D=3D (-m|--reset) ]]; then _arguments \ '-i[update only the index; ignore changes in work tree]' \ '-u[update the work tree after successful merge]' \ '2:first tree-ish to be read/merged:__git_tree_ishs' \ '3:second tree-ish to be read/merged:__git_tree_ishs' \ '4:third tree-ish to be read/merged:__git_tree_ishs' && ret=3D0 else _message 'no more arguments' fi } _git-unpack-objects () { _arguments \ '-n[only list the objects that would be unpacked]' \ '-q[run quietly]' && ret=3D0 } _git-update-index () { local -a refreshables if (( $words[(I)--refresh] )); then refreshables=3D( '--ignore-missing[ignore missing files when refreshing the index]' '--unmerged[if unmerged changes exists, ignore them instead of exitin= g]' '-q[run quietly]') fi _arguments -S \ $refreshables \ '--add[add files not already in the index]' \ '--cacheinfo[insert information directly into the cache]: :_guard "[0-7= ]#" "octal file mode": :_guard "[[\:xdigit\:]]#" "object id":file:_files' \ '--chmod=3D-[set the execute permissions on the updated files]:permissi= on:((-x\:executable +x\:"not executable"))' \ '(--remove)--force-remove[remove files from both work tree and the inde= x]' \ '--index-info[read index information from stdin.]' \ '--info-only[only insert files object-IDs into index]' \ '--refresh[refresh the index]' \ '(--force-remove)--remove[remove files that are in the index but are mi= ssing from the work tree]' \ '--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]' \ '-z[paths are separated with NUL instead of LF for --stdin]' \ '*:file:_files' && ret=3D0 } _git-write-tree () { _arguments \ '--missing-ok[ignore objects in the index that are missing in the objec= t database]' && ret=3D0 } _git-cat-file () { if (( CURRENT =3D=3D 2 )); then _arguments \ '-t[show the type of the given object]' \ '-s[show the size of the given object]' \ '*: :_values "object type" blob commit tag tree' && ret=3D0 elif (( CURRENT =3D=3D 3 )); then __git_objects && ret=3D0 else _message 'no more arguments' fi } _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_files' && ret=3D0 } _git-diff-files () { _arguments \ $diff_args \ '-q[do not complain about nonexisting files]' \ '*:file:_files' && ret=3D0 } _git-diff-stages () { _arguments \ $diff_args \ ':stage 1:__git_stages' \ ':stage 2:__git_stages' \ '*:index file:__git_files' && ret=3D0 } _git-diff-tree () { local curcontext=3D$curcontext state line typeset -A opt_args _arguments -S \ $diff_args \ $pretty_arg \ '--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)]' \ '-v[show verbose headers]' \ ':tree-ish:__git_tree_ishs' \ '*::file:->files' && ret=3D0 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=3D0 else _alternative \ ': :__git_tree_ishs' \ ": :__git_tree_files $line[1]" && ret=3D0 fi ;; esac } _git-fsck-objects () { _arguments -S \ '--cache[consider objects recorded in the index as head nodes for reach= ability traces]' \ '(--standalone)--full[check all object directories]' \ '--root[show root nodes]' \ '(--full)--standalone[check only the current object directory]' \ '--strict[do strict checking]' \ '--tags[show tags]' \ '--unreachable[show objects that are unreferenced in the object databas= e]' \ '*:object:__git_objects' && ret=3D0 } _git-ls-files () { _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]' \ '-t[identify each files status]' \ '(-u --unmerged)'{-u,--unmerged}'[show unmerged files in the output]' \ '*'{-x,--exclude=3D-}'[skip files matching given pattern]:file pattern'= \ '*'{-X,--exclude-from=3D-}'[skip files matching patterns in given file]= :file:_files' \ '*--exclude-per-directory=3D-[skip directories matching patterns in giv= en file]:file:_files' \ '*:index file:__git_files' && ret=3D0 } _git-ls-tree () { local curcontext=3D$curcontext state line typeset -A opt_args _arguments \ $nul_arg \ '-d[do not show children of given tree]' \ '-r[recurse into subdirectories]' \ ':tree-ish:__git_tree_ishs' \ '*:tree file:->files' && ret=3D0 case $state in files) __git_tree_files $line[1] && ret=3D0 ;; esac } _git-merge-base () { _arguments \ '(-a --all)'{-a,--all}'[show all common ancestors]' \ ':commit 1:__git_commits' \ ':commit 2:__git_commits' && ret=3D0 } _git-name-rev () { _arguments -S \ '--tags[only use tags to name the commits]' \ '(--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=3D0 } # TODO: --no-merges undocumented _git-rev-list () { if (( $words[(I)--] && $words[(I)--] !=3D CURRENT )); then _arguments \ '*:index file:__git_files' && ret=3D0 else local show_breaks (( $words[(I)--merge-order] )) && show_breaks=3D'--show-breaks[show com= mit prefixes]' _arguments -S \ '--all[show all commits from refs]' \ '--bisect[show only the middlemost commit object]' \ '(--sparse)--dense[this is the inverse of --sparse, and is also the d= efault]' \ '(--pretty)--header[show commit headers]' \ '--objects[show object ids of objects referenced by the listed commit= s]' \ '--max-age[maximum age of commits to output]: :_guard "[[\:digit\:]]#= " number' \ '--max-count[maximum number of commits to output]: :_guard "[[\:digit= \:]]#" timestamp' \ '(--topo-order)--merge-order[decompose into minimal and maximal epoch= s]' \ '--min-age[minimum age of commits to output]: :_guard "[[\:digit\:]]#= " timestamp' \ '--parents[show parent commits]' \ '(--header)'$pretty_arg \ '(--dense)--sparse[when paths are given, output only commits that cha= nges any of them]' \ '(--merge-order)--topo-order[show commits in topological order]' \ $show_breaks \ '--unpacked[show only unpacked commits]' \ '*:commit id:__git_commits2' && ret=3D0 fi } _git-show-index () { _message 'no arguments allowed; accepts index file on standard input' } _git-tar-tree () { _arguments \ ':tree-ish:__git_tree_ishs' \ ':base-name:_files' && ret=3D0 } _git-unpack-file () { _arguments \ ':blob id:__git_blobs' && ret=3D0 } _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=3D0 } _git-verify-pack () { _arguments -S \ '-v[show objects contained in pack]' \ '*:index file:_files -g "*.idx"' && ret=3D0 } =20 __git-clone_or_fetch-pack () { _arguments \ $exec_arg \ ':remote repository:__git_remote_repository' \ '*:head:__git_heads' && ret=3D0 } _git-clone-pack () { __git-clone_or_fetch-pack } _git-fetch-pack () { __git-clone_or_fetch-pack } # TODO: __git_commits appropriate here? Probably not, as this should be a # remote commit, but perhaps good enough? __git-http_or_ssh-fetch () { _arguments \ $fetch_args \ ':commit id:__git_commits' \ ':URL:_urls' && ret=3D0 } _git-http-fetch () { __git-http_or_ssh-fetch } _git-local-fetch () { _arguments \ $fetch_args \ '-l[hard-link objects]' \ '-n[do not copy objects]' \ '-s[sym-link objects]' \ ':commit id:__git_commits' \ ':directory:_directories' && ret=3D0 } _git-peek-remote () { _arguments \ $exec_arg \ ':remote repository:__git_remote_repository' && ret=3D0 } _git-receive-pack () { _arguments \ ':directory:_directories' && ret=3D0 } _git-send-pack () { _arguments \ $exec_arg \ '--all[update all refs that exist locally]' \ '--force[update remote orphaned refs]' \ ':remote repository:__git_remote_repository' \ '*:remote refs' && ret=3D0 } # TODO: git-shell, but that's only invoked by other git commands. _git-ssh-fetch () { __git-http_or_ssh-fetch } _git-ssh-upload () { __git-http_or_ssh-fetch } _git-update-server-info () { _arguments \ '(-f --force)'{-f,--force}'[update the info files from scratch]' } _git-upload-pack () { _arguments \ ':directory:_directories' && ret=3D0 } _git-add () { _arguments \ '-n[do not actually add files; only show which ones would be added]' \ '-v[show files as they are added]' \ '*:file:_files -g "*(^e:__git_is_indexed:)"' && ret=3D0 } _git-am () { _arguments \ '--3way[use 3-way merge if patch does not apply cleanly]' \ '--dotest=3D-[use given directory as working area instead of .dotest]:d= irectory:_directories' \ '--interactive[apply patches interactively]' \ '--keep[do not modify Subject: header]' \ '--signoff[add Signed-off-by: line to the commit message]' \ '--skip[skip the current patch]' \ '--utf8[encode commit information in UTF-8]' \ '*:mbox file:_files' && ret=3D0 } _git-applymbox () { _arguments \ '-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 "= =2Edotest/0*"' \ ':mbox file:_files' \ '::signoff file:__git_signoff_file' && ret=3D0 } _git-bisect () { local bisect_cmds bisect_cmds=3D( 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 maste= r)" start:"reset bisection state and start a new bisection" visualize:"show the remaining revisions in gitk" ) if (( CURRENT =3D=3D 2 )); then _describe -t command "git-bisect commands" bisect_cmds && ret=3D0 else case $words[2] in (bad) _arguments \ '2:revision:__git_commits' && ret=3D0 ;; (good) _arguments \ '*:revision:__git_commits' && ret=3D0 ;; (replay) _arguments \ '2:file:_files' && ret=3D0 ;; (reset) _arguments \ '2:branch:__git_heads' && ret=3D0 ;; (*) _nothing ;; esac fi } _git-branch () { _arguments \ '(-D)-d[delete a branch, which must be fully merged]' \ '(-d)-D[delete a branch]' \ ':branch-name' \ ':base branch:__git_revisions' && ret=3D0 } _git-checkout () { _arguments \ '-f[force a complete re-read]' \ '-b[create a new branch based at given branch]:branch-name' \ ':branch:__git_revisions' \ '*:file:_files' && ret=3D0 } _git-cherry-pick () { _arguments \ '(-n --no-commit)'{-n,--no-commit}'[do not make the actually commit]' \ '(-r --replay)'{-r,--replay}'[use the original commit message intact]' \ ':commit:__git_revisions' && ret=3D0 } _git-clone () { local -a shared if (( $words[(I)(-l|--local)] )); then shared=3D('(-s --shared)'{-s,--shared}'[share the objects with the sour= ce repository]') fi _arguments \ '(-l --local)'{-l,--local}'[perform a local cloning of a repository]' \ $shared '(-q --quiet)'{-q,--quiet}'[operate quietly]' \ '-n[do not checkout HEAD after clone is complete]' \ '(-u --upload-pack)'{-u,--uploadpack}'[specify path to git-upload-pack = on remote side]:remote path' \ ':repository:__git_any_repositories' \ ':directory:_directories' && ret=3D0 } _git-commit () { _arguments -S \ '(-a --all)'{-a,--all}'[update all paths in the index file]' \ '(-s --signoff)'{-s,--signoff}'[add Signed-off-by line at the end of th= e commit message]' \ '(-v --verify -n --no-verify)'{-v,--verify}'[look for suspicious lines = the commit introduces]' \ '(-n --no-verify -v --verify)'{-n,--no-verify}'[do not look for suspici= ous lines the commit introduces]' \ '(-e --edit)'{-e,--edit}'[edit the commit message before committing]' \ '*:file:_files' \ - '(message)' \ '(-c -C --reedit-message --reuse-message)'{-c,--reedit-message=3D}'[u= se existing commit object and edit log message]:commit id:__git_commits' \ '(-c -C --reedit-message --reuse-message)'{-C,--reuse-message=3D}'[us= e existing commit object with same log message]:commit id:__git_commits' \ '(-F --file)'{-F,--file=3D}'[read commit message from given file]:fil= e:_files' \ '(-m --message)'{-m,--message=3D}'[use the given message as the commi= t message]:message' && ret=3D0 } # TODO: __git_files should be __git_tree_files (do like in git-diff-tree and # such) _git-diff () { _arguments \ $diff_args \ '::original revision:__git_revisions' \ '::new revision:__git_revisions' \ '*:index file:__git_files' && ret=3D0 } _git-fetch () { _arguments \ '(-a --append)'{-a,--append}'[append fetched refs instead of overwritin= g]' \ $force_ref_arg \ $tags_fetch_arg \ '(-u --update-head-ok)'{-u,--update-head-ok}'[allow updates of current = branch head]' \ ':repository:__git_any_repositories' \ '*:refspec:__git_ref_specs' && ret=3D0 } # TODO: should support R1..R2 syntax _git-format-patch () { _arguments \ '(-a --author)'{-a,--author}'[output From: header for your own commits = as well]' \ '(-d --date)'{-d,--date}'[output Date: header for your own commits as w= ell]' \ '(-h --help)'{-h,--help}'[display usage information]' \ '(-k --keep-subject)'{-k,--keep-subject}'[do not strip/add \[PATCH\] fr= om the first line of the commit message]' \ '(-m --mbox)'{-m,--mbox}'[use true mbox formatted output]' \ '(-n --numbered)'{-n,--numbered}'[name output in \[PATCH n/m\] format]'= \ '(-o --output-directory --stdout)'{-o,--output-directory}'[store result= ing files in given directory]:directory:_directories' \ '(-o --output-directory --mbox)--stdout[output the generated mbox on st= andard output (implies --mbox)]' \ ':their revision:__git_revisions' \ '::my revision:__git_revisions' && ret=3D0 } # TODO: something better _git-grep () { service=3Dgrep _grep ret=3D0 } # TODO: this isn't strictly right, but close enough _git-log () { _git-rev-list } # TODO: repository needs fixing _git-ls-remote () { _arguments \ '(-h --heads)'{-h,--heads}'[show only refs under refs/heads]' \ '(-t --tags)'{-t,--tags}'[show only refs under refs/tags]' \ ':repository:__git_any_repositories' \ '*: :__git_references' && ret=3D0 } _git-merge () { _arguments \ '(-n --no-summary)'{-n,--no-summary}'[do not show diffstat at end of me= rge]' \ $merge_strategy \ ':merge message' \ ':head:__git_revisions' \ '*:remote:__git_revisions' && ret=3D0 } _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]' \ '*:index file:__git_files' && ret=3D0 } _git-octupus () { _nothing } _git-pull () { _arguments \ $merge_strategy \ $force_ref_arg \ $tags_fetch_arg \ '(-a --append)'{-a,--append}'[append ref-names and object-names to .git= /FETCH_HEAD]' \ '--no-commit[do not commit the merge]' \ '(-n --no-summary)'{-n,--no-summary}'[do not show diffstate at end of m= erge]' \ '(-u,--update-head-ok)'{-u,--update-head-ok}'[allow updating of head to= current branch]' \ ':repository:__git_any_repositories' \ '*:refspec:__git_ref_specs' && ret=3D0 } _git-push () { _arguments \ $force_ref_arg \ '--all[fetch all refs]' \ ':repository:__git_any_repositories' \ '*:refspec:__git_ref_specs' && ret=3D0 } _git-rebase () { _arguments \ ':upstream branch:__git_revisions' \ '::working branch:__git_revisions' && ret=3D0 } _git-repack () { _arguments \ '-a[pack all objects into a single pack]' \ '-d[remove redundant packs after packing]' \ '-l[ignore unpacked non-local objects]' \ '-n[do not update server information]' && ret=3D0 } _git-reset () { _arguments \ '( --soft --hard)--mixed[like --soft but report what has not bee= n updated (default)]' \ '(--mixed --hard)--soft[do not touch the index file nor the work= ing tree]' \ '(--mixed --soft )--hard[match the working tree and index to the = given tree]' \ ':commit-ish:__git_revisions' && ret=3D0 } _git-resolve () { _arguments \ ':current commit:__git_revisions' \ ':merged commit:__git_revisions' \ ':commit message' } _git-revert () { _arguments \ '(-n --no-commit)'{-n,--no-commit}'[do not commit the reversion]' '(-r --replay)'{-r,--replay}'[use the original commit message intact]' \ ':commit:__git_revisions' && ret=3D0 } _git-shortlog () { _nothing } _git-show-branch () { _arguments \ '--all[show all refs under $GIT_DIR/refs]' \ '--heads[show all refs under $GIT_DIR/refs/heads]' \ '--independent[show only the reference that can not be reached from any= of the other]' \ '--list[do not display any commit ancestry]' \ '--merge-base[act like "git-merge-base -a" but with two heads]' \ '--more=3D-[go given number of commit beyond common ancestor (no ancest= ry if negative)]:number' \ '--no-name[do not show naming strings for each commit]' \ '--sha1-name[name commits with unique prefix of object names]' \ '--topo-order[show commits in topological order]' \ '--tags[show all refs under $GIT_DIR/refs/tags]' \ '*:reference:__git_revisions' && ret=3D0 } _git-status () { _nothing } _git-verify-tag () { _arguments \ ':tag:__git_tag_ids' && ret=3D0 } # TODO: this should be a combination of git-rev-list and git-diff-tree _git-whatchanged () { } _git-applypatch () { _arguments \ ':message file:_files' \ ':patch file:_files' \ ':info file:_files' \ '::signoff file:_files' && ret=3D0 } # TODO: archive/branch can use _arch_archives perhaps? _git-archimport () { _arguments \ '-h[display usage information]' \ '-v[produce verbose output]' \ '-T[create a tag for every commit]' \ '-t[use given directory as temporary directory]:directory:_directories'= \ ':archive/branch' \ '::archive/branch' } _git-convert-objects () { _arguments \ ':object:__git_objects' } # TODO: _cvs_root for -d would be nice _git-cvsimport () { _arguments \ '-C[specify the git repository to import into]:directory:_directories' \ '-d[specify the root of the CVS archive]:cvsroot' \ '-h[display usage information]' \ '-i[do not perform a checkout after importing]' \ '-k[remove keywords from source files in the CVS archive]' \ '-u[convert underscores in tag and branch names to dots]' \ '-M[attempt to detect merges based on the commit message with custom pa= ttern]:pattern' \ '-m[attempt to detect merges based on the commit message]' \ '-o[specify the branch into which you wish to import]:branch' \ '-p[specify additionaly options for cvsps]:cvsps-options' \ '-s[substitute the "/" character in branch names with given substitutio= n]:substitute' \ '-v[produce verbose output]' \ '-z[specify timestamp fuzz factor to cvsps]:fuzz-factor' \ ':cvsmodule' && ret=3D0 } # TODO: documentation is weird _git-lost-found () { _message "awaiting better documentation before proceeding..." } # TODO: something better _git-merge-one-file () { _message "you probably should not be issuing this command" } _git-prune () { _arguments -S \ '-n[do not remove anything; just report what would have been removed]' = && ret=3D0 } _git-relink () { _arguments \ '--safe[stop if two objects with the same hash exist but have different= sizes]' \ '*:directory:_directories' && ret=3D0 } # TODO: import stuff from _svn _git-svnimport () { _arguments \ '-b[specify the name of the SVN branches directory]:directory:_director= ies' \ '-C[specify the git repository to import into]:directory:_directories' \ '-D[use direct HTTP-requests if possible]:path' \ '-d[use direct HTTP-requests if possible for logs only]:path' \ '-h[display usage information]' \ '-i[do not perform a checkout after importing]' \ '-l[limit the number of SVN changesets to pull]: :_guard "[[\:digit\:]]= #" number' \ '-o[specify the branch into which you wish to import]:branch' \ '-M[attempt to detect merges based on the commit message with custom pa= ttern]:pattern' \ '-m[attempt to detect merges based on the commit message]' \ '-s[specify the change number to start importing from:start-revision' \ '-t[specify the name of the SVN trunk]:trunk:_directories' \ '-T[specify the name of the SVN tags directory]:directory:_directories'= \ '-v[produce verbose output]' \ ':svn-repositry-url:_urls' \ '::directory:_directories' && ret=3D0 } # TODO: how do we complete argument 1? # TODO: argument 2 should be __git_heads, but with full path _git-symbolic-ref () { _arguments \ ':symbolic reference' \ ':reference' && ret=3D0 } # TODO: first argument right? # TODO: document options once they are in man # key-id for -u could perhaps be completed from _gpg somehow _git-tag () { local message=3D if (( $words[(I)-[asu]] )); then message=3D'-m[specify tag message]' fi _arguments \ $message \ ':tag-name:__git_tags' \ '::head:__git_revisions' \ - '(creation)' \ '-a[annotate]' \ '-f[create a new tag even if one with the same name already exists]' \ '-s[annotate and sign]' \ '-u[annotate and sign with given key-id]:key-id' \ - '(deletion)' \ '-d[delete]:tag:__git_tags' && ret=3D0 } _git-update-ref () { _arguments \ ':symbolic reference:__git_revisions' \ ':new reference:__git_revisions' \ '::old reference:__git_revisions' && ret=3D0 } _git-check-ref-format () { _arguments \ ':reference:__git_revisions' && ret=3D0 } _git-cherry () { _arguments \ '-v[be verbose]' \ ':upstream:__git_revisions' \ '::head:__git_revisions' && ret=3D0 } _git-count-objects () { _nothing } # TODO: do better than _directory? The directory needs to be a git-reposit= ory, # so one could check for a required file in the given directory. _git-daemon () { _arguments -S \ '--export-all[allow pulling from all repositories without verification]= ' \ '(--port)--inetd[run server as an inetd service]' \ '--init-timeout=3D-[specify timeout between connection and request]' \ '--port=3D-[specify port to listen to]' \ '--syslog[log to syslog instead of stderr]' \ '--timeout=3D-[specify timeout for sub-requests]' \ '--verbose[log details about incoming connections and requested files]'= \ '*:repository:_directory' && ret=3D0 } _git-get-tar-commit-id () { _message 'no arguments allowed; accepts tar-file on standard input' } _git-mailinfo () { _arguments \ '-k[do not strip/add \[PATCH\] from the first line of the commit messag= e]' \ '-u[encode commit information in UTF-8]' \ ':message file:_files' \ ':patch file:_files' && ret=3D0 } _git-mailsplit () { _arguments \ '-d-[specify number of leading zeros]: :_guard "[[\:digit\:]]#" "precis= ion' \ ':mbox file/directory:_files' \ '::directory:_directories' && ret=3D0 } _git-patch-id () { _message 'no arguments allowed; accepts patch on standard input' } _git-request-pull () { _arguments \ ':start commit:__git_revisions' \ ':url:_urls' \ ':end commit:__git_revisions' } # TODO: do we want this? #_git-rev-parse () { #} _git-send-email () { _arguments \ '(--no-chain-reply-to)--chain-reply-to[each email will be sent as a rep= ly 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 se= ries]' \ '--from[specify the sender of the emails]' \ '--in-reply-to[specify the contents of the first In-Reply-To header]' \ '--smtp-server[specify the outgoing smtp server]:smtp server:_hosts' \ '--subject[specify the initial subject of the email thread]' \ '--to[specify the primary recipient of the emails]' ':file:_files' && ret=3D0 } _git-stripspace () { _message 'no arguments allowed; accepts input file on standard input' } # --- __git_guard () { typeset -A opts zparseopts -K -D -A opts M: J: V: 1 2 n F: X: [[ "$PREFIX$SUFFIX" !=3D $~1 ]] && return 1 if (( $+opts[-X] )); then _message -r $opts[-X] else _message -e $2 fi [[ -n "$PREFIX$SUFFIX" ]] } __git_objects () { __git_guard $* "[[:xdigit:]]#" "object" } __git_trees () { __git_guard $* "[[:xdigit:]]#" "tree" } __git_tree_ishs () { __git_guard $* "[[:xdigit:]]#" "tree-ish" } __git_blobs () { _git_guard $* "[[:xdigit:]]#" 'blob id' } __git_stages () { __git_guard $* "[[:digit:]]#" 'stage' } __git_files () { local expl files files=3D("${(@f)$(git-ls-files 2>/dev/null)}") if (( $? =3D=3D 0 )); then _wanted files expl 'index file' _multi_parts $@ - / files else _message 'not a git repository' fi } __git_tree_files () { local expl tree_files tree_files=3D(${"${(@f)$(git-ls-tree -r $@[-1] 2>/dev/null)}"#*$'\t'}) if (( $? =3D=3D 0 )); then _wanted files expl 'tree file' _multi_parts $@[1,-2] - / tree_files else _message 'not a git repository' fi } # TODO: deal with things that __git_heads and __git_tags has in common (i.e= =2E, # if both exists, they need to be completed to heads/x and tags/x. __git_commits () { _alternative \ 'heads::__git_heads' \ 'tags::__git_tags' } # TODO: deal with prefixes and suffixes listed in git-rev-parse __git_revisions () { __git_commits $* } __git_commits2 () { compset -P '\\\^' __git_commits } # FIXME: these should be imported from _ssh # TODO: this should take -/ to only get directories _remote_files () { # There should be coloring based on all the different ls -F classifiers. local expl rempat remfiles remdispf remdispd args suf ret=3D1 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=3D"${PREFIX%%[^./][^/]#}\*" else rempat=3D"${(q)PREFIX%%[^./][^/]#}\*" fi remfiles=3D(${(M)${(f)"$(_call_program files ssh $args -a -x ${IPREFIX%= :} ls -d1FL "$rempat" 2>/dev/null)"}%%[^/]#(|/)}) compset -P '*/' compset -S '/*' || suf=3D'remote file' # remdispf=3D(${remfiles:#*/}) remdispd=3D(${(M)remfiles:#*/}) _tags files while _tags; do while _next_label files expl ${suf:-remote directory}; do # [[ -n $suf ]] && compadd "$@" "$expl[@]" -d remdispf \ # ${(q)remdispf%[*=3D@|]} && ret=3D0=20 compadd ${suf:+-S/} "$@" "$expl[@]" -d remdispd \ ${(q)remdispd%/} && ret=3D0 done (( ret )) || return 0 done return ret else _message -e remote-files 'remote file' fi } __git_remote_repository () { local service service=3D _ssh if compset -P '*:'; then _remote_files else _alternative \ 'directories::_directories' \ 'hosts:host:_ssh_hosts -S:' fi } # should also be $GIT_DIR/remotes/origin __git_any_repositories () { _alternative \ 'files::_files' \ 'remote repositories::__git_remote_repository' } __git_ref_specs () { if compset -P '*:'; then __git_heads else compset -P '+' if compset -S ':*'; then __git_heads else __git_heads -S ':' fi fi } __git_signoff_file () { _alternative \ 'signoffs:signoff:(yes true me please)' \ 'files:signoff file:_files' } __git_tag_ids () { } __git_heads_or_tags () { local expl typeset -a refs opts typeset -A ours zparseopts -K -D -a opts S: M: J: V: 1 2 n F: X: P:=3Dours T:=3Dours (( $+ours[-P] )) || ours[-P]=3D./. refs=3D(${${"${(@f)$(git ls-remote --$ours[-T] $ours[-P] 2>/dev/null)}"#*= $'\t'}#refs/$ours[-T]/}) if (( $? =3D=3D 0 )); then _wanted $ours[-T] expl $ours[-T] compadd $opts - $refs else _message 'not a git repository' fi } __git_heads () { __git_heads_or_tags $* -T heads && ret=3D0 } __git_tags () { __git_heads_or_tags $* -T tags && ret=3D0 } # TODO: depending on what options are on the command-line already, complete # only tags or heads # TODO: perhaps caching is unnecessary. usually won=E2=80=99t 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 "."?)) __git_references () { # _alternative \ # 'heads::__git_heads' \ # 'tags::__git_tags' && ret=3D0 local expl # TODO: deal with GIT_DIR if [[ $_git_refs_cache_pwd !=3D $PWD ]]; then _git_refs_cache=3D(${${"${(@f)$(git ls-remote ./. 2>/dev/null)}"#*$'\t'= }#refs/(heads|tags)/}) _git_refs_cache_pwd=3D$PWD fi if (( $? =3D=3D 0 )); then _wanted references expl 'references' compadd - $_git_refs_cache else _message 'not a git repository' fi } __git_local_references () { local expl if [[ $_git_local_refs_cache_pwd !=3D $PWD ]]; then _git_local_refs_cache=3D(${${"${(@f)$(git ls-remote ./. 2>/dev/null)}"#= *$'\t'}#refs/}) _git_local_refs_cache_pwd=3D$PWD fi if (( $? =3D=3D 0 )); then _wanted references expl 'references' compadd - $_git_local_refs_cache else _message 'not a git repository' fi } # --- __git_is_indexed () { [[ -n $(git ls-files $REPLY) ]] } --gBBFr7Ir9EOA20Yy--