Post by Gerlando FalautoHi everyone,
I strongly felt the urge to have some way of bash-completing URLS
from the command line when doing checkouts, listing, cat (for
README/REVNOTES files) and so on...
I looked up the "tools/client-side/bash_completion" script only to
realize it works for local (file:///) but not remote URLs.
So I came up with the attached patch, which works for me (tested
with bash 4.1.2, svn 1.6.11)
The idea was (apart from adding sub-dir completion with a gross "svn
ls" command) to (manually) list known repositories within a
http://srv1/proj1
svn://srv2/proj2
The reason behind this is that data cached in
~/.subversion/auth/svn.simple does not contain the full project URL
(only the server name) and I could not find a way to get that
information anywhere else.
I known it would've made more sense to ask for advice *BEFORE*
touching the code, but still... :-)
Thanks in advance for your feedback!
Gerlando
P.S. I'm not subscribed to the list, so please Cc: me, thanks!
diff --git a/svn-completion.bash b/svn-completion.bash
index 12285f4..c2684b3 100644
--- a/svn-completion.bash
+++ b/svn-completion.bash
@@ -35,6 +35,12 @@
shopt -s extglob
+function _debug()
+{
+ true
+}
+
# Tree helper functions which only use bash, to ease readability.
# look for value associated to key from stdin in K/V hash file format
@@ -112,6 +118,53 @@ function _svn_lls()
done
}
+# _svn_remotels currUrl proto
+# e.g. currUrl = //server/project/dirprefix
+# list svn files/dirs (using svn ls) from a given path
+# NOTE: this function outputs full URLs (except the protocol part), like
+# //srv/proj/branches/ //srv/proj/tags/ //srv/proj/trunk/
+function _svn_remotels()
+{
+ local currUrl=$1
+ local proto=$2
+
+ local fullUrl=$2$1
+ _debug "Trying to complete $opt"
+
+ # HACK: fullUrl is something like http://srv/proj/ or http://srv/proj/ta
+ # so we add an X and get the dirname from there in order to see where we
+ # should run "svn ls" against (that is, http://srv/proj)
+ local urlDir=$(dirname "${fullUrl}X")/
+
+ # now get the prefix part of the file (e.g. "ta" for "target.def")
+ # (this is used for local filtering)
+ local filepref=${fullUrl#${urlDir}}
+
+ # This output prefix "//srv/proj/" will be re-added to the individual ls entries
+ # so to get something like a "full path" listing (except leading "protocol:")
+ local outurlDir=${urlDir#${proto}}
+
+ _debug "prefix to be matched is $filepref"
+
+ local files=()
+ local f=
+ svn ls --non-interactive $urlDir </dev/null 2>/dev/null | while IFS= read -r f
+ do
+ _debug -n "... $f:"
+ # if the filename matches the provided string, add it to the list
+ if [[ -z "$filepref" || $f == $filepref* ]]
+ then
+ _debug YES
+ echo "$outurlDir$f"
+ else
+ _debug NO
+ fi
+ done
+
+ return 0
+}
+
# This completion guides the command/option order along the one suggested
# by "svn help", although other syntaxes are allowed.
#
@@ -395,9 +448,22 @@ _svn()
fi
# URL completion
$SVN_BASH_COMPL_EXT == *urls* ]]
then
+ # 1) http
+ # 3) //full/path/to
+ # So we need to reconstruct this
+ #FIXME this should be made more robust
+
+ local currUrl=${COMP_WORDS[i-1]} #//srv-
+ local partUrl=${COMP_WORDS[i-3]}${COMP_WORDS[i-2]}${COMP_WORDS[i-1]}
+
+ _debug partUrl=${partUrl} cur = ${cur}
+
# see about COMP_WORDBREAKS workaround in prop completion
if [[ $cur == file:* ]]
then
@@ -405,27 +471,50 @@ _svn()
local where=${cur/file:/}
COMPREPLY=( $(compgen -d -S '/' -X '*/.*' -- $where ) )
return
- elif [[ $cur == *:* ]]
+ elif [[ $partUrl == *://*/* ]]
then
+ local IFS=$'\n'
+ # Get the list of remote files (as full paths)
+ local results="$(_svn_remotels ${currUrl} ${prefixUrl} )"
+ COMPREPLY=( $(compgen -W "${results}" ))
+ # - nospace: DO NOT add a new space even if it's the only completion
+ # - filenames: remove common leading paths
+ compopt -o nospace -o filenames
+ return 0
+ elif [[ $partUrl == *:* ]]
+ then
+ _debug trying to get known urls
# get known urls
local urls= file=
- for file in ~/.subversion/auth/svn.simple/* ; do
- if [ -r $file ] ; then
- local url=$(_svn_read_hashfile svn:realmstring < $file)
- url=${url/*</}
- url=${url/>*/}
- urls="$urls $url"
- fi
+# for file in ~/.subversion/auth/svn.simple/* ; do
+# if [ -r $file ] ; then
+# local url=$(_svn_read_hashfile svn:realmstring < $file)
+# url=${url/*</}
+# url=${url/>*/}
+# urls="$urls $url"
+# fi
+# done
+ for url in $(< ~/.svn_repos)
+ do
+ urls="$urls $url"
done
-
+ _debug "...known urls are: ${urls}"
# only suggest/show possible suffixes
- local prefix=${cur%:*} suffix=${cur#*:} c= choices=
+ local prefix=${partUrl%:*} suffix=${partUrl#*:} c= choices=
+
for c in $urls ; do
+ _debug "evaluating ${c} prefix=${prefix} suffix=${suffix}"
[[ $c == $prefix:* ]] && choices="$choices ${c#*:}"
done
+ _debug "choices is now ${choices}"
- COMPREPLY=( $(compgen -W "$choices" -- $suffix ) )
- return
+ COMPREPLY=( $(compgen -W "$choices" -- $cur ) )
+ # - nospace: DO NOT add a new space even if it's the only completion
+ compopt -o nospace
+ return 0
else
# show schemas
COMPREPLY=( $(compgen -W "$urlSchemas" -- $cur) )