about summary refs log tree commit diff
path: root/Completion/Unix/Command/_subversion
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Unix/Command/_subversion')
-rw-r--r--Completion/Unix/Command/_subversion104
1 files changed, 66 insertions, 38 deletions
diff --git a/Completion/Unix/Command/_subversion b/Completion/Unix/Command/_subversion
index 26eef500f..ccaf310fa 100644
--- a/Completion/Unix/Command/_subversion
+++ b/Completion/Unix/Command/_subversion
@@ -68,7 +68,6 @@ _svn () {
     ;;
     args)
       local cmd args usage idx
-      typeset -gHA _cache_svn_status _cache_svn_mtime
 
       cmd="${${(k)_svn_cmds[(R)*:$words[1]:*]}:-${(k)_svn_cmds[(i):$words[1]:]}}"
       if (( $#cmd )); then
@@ -123,7 +122,7 @@ _svn () {
         case $cmd in;
           (add)
             args+=(
-              '*:file:_files -g "*(e:_svn_uncontrolled:)"'
+              '*:file: _svn_modified "addable"'
             )
           ;;
           (auth)
@@ -140,18 +139,18 @@ _svn () {
           ;;
           (commit)
             args=(
-	      ${args/(#b)(*--file*):arg:/$match[1]:file:_files}
-              '*:file:_files -g "*(e:_svn_status:)"'
+	      ${args/(#b)(*--file*):arg:/${match[1]}:file:_files}
+              '*:file: _svn_modified "committable"'
             )
           ;;
           (delete)
             args+=(
-              '*:file:_files -g ".svn(/e:_svn_deletedfiles:)"'
+              '*:file:_files -g "*(e:_svn_controlled:)"'
             )
           ;;
           (diff)
             args+=(
-	      '*: : _alternative "files:file:_files -g \*\(e:_svn_status:\)" "urls:URL:_svn_urls"'
+	      '*: : _alternative "files:file: _svn_modified revertable" "urls:URL:_svn_urls"'
 	    )
           ;;
           (help)
@@ -190,7 +189,7 @@ _svn () {
 	    args=(
 	    ':propname:(svn:ignore svn:keywords svn:executable svn:eol-style svn:mime-type svn:externals svn:needs-lock svn:global-ignores svn:auto-props)'
 	    ':propval:->propset_propval'
-	    ${args/(#b)(*--file*):arg:/$match[1]:file:_files}
+	    ${args/(#b)(*--file*):arg:/${match[1]}:file:_files}
 	    '*:path or url: _alternative "files:file:_files" "urls:URL:_svn_urls"'
 	    )
 	  ;;
@@ -201,7 +200,7 @@ _svn () {
           ;;
           (revert)
             args+=(
-              '*:file:_files -g "(.svn|*)(/e:_svn_deletedfiles:,e:_svn_status:)"'
+              '*:file: _svn_modified "revertable"'
             )
           ;;
           (x-unshelve)
@@ -319,6 +318,9 @@ _svnadmin () {
           # Test cases:
           #   svnadmin freeze . rsync --<TAB> offers --file
           #   svnadmin freeze -- . rsync -<TAB> offers rsync's options
+          #   svnadmin freeze . -- rsync -<TAB> should do the same (but currently doesn't)
+          #
+          # TODO: Fix the third case.
           #
           # Note: the NORMARG calculations here include one positional argument
           # (the '.') before the command.
@@ -351,50 +353,76 @@ _svn_controlled() {
   # because 1.6 has been deprecated for 8 years and EOL for 6 years, we opt to DTRT
   # for >=1.7.  Therefore:
 
-  # TODO: Reimplement this function and _svn_uncontrolled for svn>=1.7.
+  # TODO: Reimplement this function for svn>=1.7.
   # (Use 'svn st' or 'svn info', not 'svn ls')
   return 0
 }
 
 
-(( $+functions[_svn_uncontrolled] )) ||
-_svn_uncontrolled() {
-  # TODO: See comments in _svn_controlled
-  return 0
-}
-
 (( $+functions[_svn_conflicts] )) ||
 _svn_conflicts() {
-  () { (( $# > 0 )) } $REPLY.(mine|r<->)(NY1)
+  # ### These strings are actually translatable
+  #
+  # The asterisks are to support an optional extension; see
+  # "preserved-conflict-file-exts" in ~/.subversion/config.
+  () { (( $# > 0 )) } $REPLY.(mine|r<->|working*|merge-left*|merge-right*)(NY1)
 }
 
-(( $+functions[_svn_deletedfiles] )) ||
-_svn_deletedfiles() {
-  # Typical usage would be _files -g '.svn(/e:_svn_deletedfiles:)'
-  local cont controlled
-  reply=( )
-  [[ $REPLY = (*/|).svn ]] || return
-  controlled=( $REPLY/text-base/*.svn-base(N:r:t) )
-  for cont in ${controlled}; do
-    [[ -e $REPLY:h/$cont ]] || reply+=( ${REPLY%.svn}$cont )
-  done
-}
+(( $+functions[_svn_modified] )) ||
+_svn_modified() {
+  setopt localoptions extendedglob
 
-(( $+functions[_svn_status] )) ||
-_svn_status() {
-  local dir=$REPLY:h
-  local pat="${1:-([ADMR~]|?M)}"
+  local depth dir expl maybe_quiet partial_word space=' '
 
-  zmodload -F zsh/stat b:zstat 2>/dev/null
-  local key="$(zstat +device $dir):$(zstat +inode $dir)"
-  local mtime="$(zstat +mtime $dir/.svn/entries)"
+  local svn_context=$1
 
-  if (( ! $+_cache_svn_status[$key] || _cache_svn_mtime[$key] != mtime )); then
-    _cache_svn_status[$key]="$(_call_program files svn status -N $dir)"
-    _cache_svn_mtime[$key]="$mtime"
+  local partial_word=${(Q)words[CURRENT]}
+  if [[ -z $partial_word ]]; then
+    dir="./"
+  elif [[ -d $partial_word ]]; then
+    dir=$partial_word
+  else
+    dir=${partial_word:h}
   fi
 
-  (( ${(M)#${(f)_cache_svn_status[$key]}:#(#s)${~pat}*$REPLY} ))
+  if zstyle -T ":completion:${curcontext}:${curtag}" verbose; then
+    depth=infinity
+  else
+    depth=immediates
+  fi
+
+  if [[ $svn_context = addable ]]; then
+    maybe_quiet=""
+  else
+    maybe_quiet="-q"
+  fi
+
+  local -a status_lines
+  # Run 'status'
+  status_lines=( ${(f)"$(_call_program modified-files "svn status $maybe_quiet --depth=${(q)depth} -- ${(q)dir}")"} )
+  # Filter to only the right set of statuses
+  case $svn_context in
+    (committable)
+      status_lines=( ${(M)status_lines:#(#s)([ADMR]?|?M)${space}???${space}${space}*} )
+      ;;
+    (revertable)
+      status_lines=( ${(M)status_lines:#(#s)([ACDMR~!]?|?[CM])${space}????${space}*} )
+      ;;
+    (addable)
+      # The 'D' is just in case there's an unversioned file of the same name as the deleted file
+      status_lines=( ${(M)status_lines:#(#s)[?ID]${space}${space}???${space}${space}*} )
+      ;;
+  esac
+  # Strip the 7 status-letter columns and the column of spaces
+  status_lines=( ${status_lines#????????} )
+  # Strip one leading space.  This is in case `svn status` ever adds another
+  # column.  If that hasn't happened and you're reading this comment because
+  # the following line broke your use of filenames that start with a literal
+  # space, well, nice to meet you!  I didn't know you existed.
+  status_lines=( ${status_lines#${space}} )
+
+  _wanted svn-modified expl 'modified files in svn' \
+    compadd - "${status_lines[@]}"
 }
 
 (( $+functions[_svn_remote_paths] )) ||