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) )

Reply via email to