>From e5f00906cf7c8644500ad1eff39ad7f70be9d103 Mon Sep 17 00:00:00 2001 From: Dominik Vogt Date: Wed, 23 Jan 2008 13:02:49 +0100 Subject: [PATCH] ported completion of remote heads and tags from bash also handle --git-dir= option and GIT_DIR environment variable better completion of git-branch --- _git | 170 +++++++++++++++++++++++++++++++++++++++++++---------------------- 1 files changed, 112 insertions(+), 58 deletions(-) diff --git a/_git b/_git index 6f6e82d..6bc8a37 100644 --- a/_git +++ b/_git @@ -184,13 +184,30 @@ _git_command_options () { 'write-tree[creates a tree from the current index]' && ret=0 } -# TODO: this needs to be cleaned up and fixed local curcontext=$curcontext ret=1 -local first=1 +local gitdir="$GITDIR" +local curgitdir="" +local gitdir_arg="" if [[ $words[1] == git ]]; then while [[ $#words -ge 3 && $words[2] == -* ]]; do - compset -n 2 + if [[ $words[2] == --git-dir=* ]]; then + gitdir=${words[2]#--git-dir=} + compset -n 2 + elif [[ $words[2] == --git-dir && $#words -ge 4 ]]; then + gitdir=$words[3] + compset -n 2 + compset -n 2 + elif [[ "$words[2]" == --exec-path=* || "$words[2]" == --work-tree=* ]]; + then + compset -n 2 + elif [[ $words[2] == --exec-path || $words[2] == --work-tree && \ + $#words -ge 4 ]]; then + compset -n 2 + compset -n 2 + else + compset -n 2 + fi done if (( CURRENT == 2 )); then _git_command_options @@ -204,6 +221,27 @@ else _call_function ret _$words[1] fi +__gitdir () +{ + if [[ "$1" != "$gitdir_arg" || -z "$curgitdir" ]]; then + if [[ -z $gitdir ]]; then + if [[ -z "$1" ]]; then + if [[ -n "$gitdir" ]]; then + curgitdir="$gitdir" + elif [[ -d .git ]]; then + curgitdir=".git" + else + curgitdir=$(git-rev-parse --git-dir 2>/dev/null) + fi + elif [[ -d "$1/.git" ]]; then + curgitdir="$1/.git" + else + curgitdir="$1" + fi + fi + fi +} + _git-apply () { _arguments \ $nul_arg \ @@ -703,11 +741,46 @@ _git-bisect () { } _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=0 + local mode= + + # find out syntax mode + { (( $words[(I)-(d|D)] )) && mode=del } || + { (( $words[(I)-(m|M)] )) && mode=move } || + { (( $words[(I)-(a|r|f)] )) && mode=list_create } || + { (( CURRENT > 2 && CURRENT > $words[(i)^-*] )) && mode=list_create } + # remove options + while [[ CURRENT -gt 2 && -n $words[2] && $words[2] == -* ]]; do + compset -n 2 + done + case "$mode" in + list_create) + ;; + del) + if (( $words[(I)-r] )); then + _arguments '*:new branch:__git_remote_branch' && ret=0 + else + _arguments \ + '(-r)-r[delete remote tracking branches]' \ + '*:old branch:__git_local_branch' && ret=0 + fi + ;; + move) + _arguments \ + '1:old branch:__git_local_branch' \ + '2:new branch:' && ret=0 + ;; + *) + _arguments \ + - '(options)' \ + '-f[create branch forcefully]' \ + '-a[list all branches]' \ + '-r[list remote branches]' \ + '-d[delete a branch, which must be fully merged]' \ + '-D[delete a branch forcefully]' \ + '-m[move branch]:m:->move' \ + '-M[move branch forcefully]:M:->move' && ret=0 + ;; + esac } _git-checkout () { @@ -809,7 +882,7 @@ _git-ls-remote () { '(-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=0 + '*: :__git_all_references' && ret=0 } _git-merge () { @@ -1190,9 +1263,7 @@ __git_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. __git_commits () { - _alternative \ - 'heads::__git_heads' \ - 'tags::__git_tags' + __git_all_references } # TODO: deal with prefixes and suffixes listed in git-rev-parse @@ -1283,70 +1354,53 @@ __git_signoff_file () { __git_tag_ids () { } -__git_heads_or_tags () { +__git_references () { + local cmd i is_hash=y local expl - typeset -a refs opts - typeset -A ours - - zparseopts -K -D -a opts S: M: J: V: 1 2 n F: X: P:=ours T:=ours - - (( $+ours[-P] )) || ours[-P]=./. - - refs=(${${"${(@f)$(git ls-remote --$ours[-T] $ours[-P] 2>/dev/null)}"#*$'\t'}#refs/$ours[-T]/}) - if (( $? == 0 )); then - _wanted $ours[-T] expl $ours[-T] compadd $opts - $refs + local path1="$1" path2="$2" + + shift 2 + __gitdir + if [[ -d "$curgitdir" ]]; then + for i in $(git --git-dir="$curgitdir" \ + for-each-ref --format='%(refname)' \ + refs"$path1$path2" ); do + _wanted "$path2" expl "$path2" compadd $@ - "${i#refs$path1$path2/}" + done else _message 'not a git repository' fi } __git_heads () { - __git_heads_or_tags $* -T heads && ret=0 + __git_references / heads $@ && ret=0 } __git_tags () { - __git_heads_or_tags $* -T tags && ret=0 + __git_references / tags $@ && ret=0 } -# 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 "."?)) -__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)$(git ls-remote ./. 2>/dev/null)}"#*$'\t'}#refs/(heads|tags)/}) - _git_refs_cache_pwd=$PWD - fi +__git_remotes () { + __git_references /remotes "" $@ && ret=0 +} - if (( $? == 0 )); then - _wanted references expl 'references' compadd - $_git_refs_cache - else - _message 'not a git repository' - fi +__git_all_references () { + __git_heads && ret=0 + __git_tags && ret=0 + __git_remotes && ret=0 } __git_local_references () { - local expl + __git_heads && ret=0 + __git_tags && ret=0 +} - if [[ $_git_local_refs_cache_pwd != $PWD ]]; then - _git_local_refs_cache=(${${"${(@f)$(git ls-remote ./. 2>/dev/null)}"#*$'\t'}#refs/}) - _git_local_refs_cache_pwd=$PWD - fi +__git_local_branch () { + __git_heads && ret=0 +} - if (( $? == 0 )); then - _wanted references expl 'references' compadd - $_git_local_refs_cache - else - _message 'not a git repository' - fi +__git_remote_branch () { + __git_remotes && ret=0 } # --- -- 1.5.3.5.GIT