http://subversion.apache.org/patches
Please send this to dev@! (and follow the other suggestions too please -- e.g., submit against trunk@HEAD) Gerlando Falauto wrote on Fri, Jul 27, 2012 at 11:31:51 +0200: > Hi 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 > ~/.svn_repos file, one per line: > > 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() > +{ > + # echo "$@" >> /tmp/svn-completion.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 > +# proto = http: > +# 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 > - if [[ $cmd == @(co|checkout|ls|list) && $stat = 'arg' && \ > + if [[ $cmd == @(co|checkout|ls|list|cat) && $stat = 'arg' && \ > $SVN_BASH_COMPL_EXT == *urls* ]] > then > + # whenever a colon (:) is present, bash will split it into > three different parts: > + # 1) http > + # 2) : > + # 3) //full/path/to > + # So we need to reconstruct this > + #FIXME this should be made more robust > + > + local prefixUrl=${COMP_WORDS[i-3]}${COMP_WORDS[i-2]} #http: > + 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}" )) > + _debug "...completion results are: ${COMPREPLY[@]}" > + # Set output options: > + # - 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 ) ) > + # Set output options: > + # - 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) )