[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

sequence "/@" in file path causes failure - Subversion bug?

From: Marian Petras <marian.petras_at_sun.com>
Date: Mon, 25 May 2009 19:41:16 +0200

Hello,

I am re-posting this question about a possible bug in Svn because I got
no response on the users' mailing list (for the original e-mail, see
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=1065&dsMessageId=2300569).

I cannot 'svn add' or 'svn commit' a file if the file's name starts with
an at sign (@) and the specified file path contains at least one
directory element.

For example, I would expect the following behavior:

     $ svn add 'dir/@File.txt'
     A dir/@File.txt

but I get

     $ svn add 'dir/@File.txt'
     svn: warning: 'dir_at_File.txt' not found

(Note the missing slash in the Svn output.)

Appending an extra at sign to the end of the path does not help:

     $ svn add 'dir/@File.txt@'
     svn: warning: 'dir/@File.txt@' not found

Now the slash was maintained but the trailing at sign was maintained,
too, which makes the path invalid.

This issue can be quite easily worked around by first changing to the
directory containing the file, invoking "svn add @File.txt" (i.e.
without any directory element in the file's path) and changing back to
the original directory:

     $ cd dir
     $ svn add '@File.txt'
     A @File.txt
     $ cd ..

The more serious problem is that 'svn commit' fails the same way:

     $ svn commit -m 'added file' 'dir/@File.txt'
     svn: Commit failed (details follow):
     svn: '/home/mp/wc/dir_at_File.txt' is not under version control

     $ svn commit -m 'added file' 'dir/@File.txt@'
     svn: Commit failed (details follow):
     svn: '/home/mp/wc/dir/@File.txt@' is not under version control

In some cases, this issue can be worked around by committing the whole
directory. But it is not an option if a subset of files in the given
directory is to be committed.

I attached a test script (for Unix-like systems). It creates two
subdirectories in the current directory ("working-copy", "test-repo")
and runs a test on them, displaying the executed commands on the console
as if invoked by the user.

Environment:

Operating system:

     Linux - Debian Lenny running on x86-64

Subversion info:

   Svn version 1.6.2 (r37639), compiled with:

      gcc (Debian 4.3.2-1.1) 4.3.2

      Configuration options:

           --with-berkeley-db=db.h:/usr/include:/usr/lib:db-4.6
           --with-gnome-keyring
           --enable-javahl
           --with-jdk=/usr/local/java/jdk1.5.0_18
           --with-junit=/usr/local/java/junit3.8.1/junit.jar

      uname -m = x86_64
      uname -r = 2.6.26-1-amd64
      uname -s = Linux
      uname -v = #1 SMP Fri Mar 13 17:46:45 UTC 2009

   No private modifications.

   Berkeley DB: 4.6

The problem is only with the command-line client. When JavaHL is used to
invoke the equivalent commands, everything works. This was discovered
during evaluation of a bug reported to the NetBeans project
(http://www.netbeans.org/issues/show_bug.cgi?id=165329). The Subversion
module of the NetBeans IDE prefers JavaHL but if it does not find one,
it falls back to using the command-line client.

I have also reproduced this behavior on the following systems:

     Linux (Debian Lenny, x86-64)
     Subversion version 1.5.1 (r32289)

     Linux (openSUSE, x86-64)
     Subversion version 1.6.0 (r36650)

     Windows XP 32-bit
     Subversion version 1.6.1 (r37116)

Marián Petráš
developer of the NetBeans IDE

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=2353599

#!/bin/sh

check_arg() {

        #
        # Checks whether the second argument contains an apostrophe character.
        # If so, displays an error message on the error output and interrupts the script.
        #

        if echo "$2" | fgrep -q \'; then
                echo "Argument to \"$1\" must not contain character \"'\" (apostrophe)." >&2
                exit 1
        fi
}

runcmd() {

        #
        # Runs the given command and and also displays what is being executed as if it was typed in the console.
        #

        local RUNCMD_PROMPT='$'

        local display_args_count=all
        case "$1" in
                -d[1-9])
                        # Only display the first given number of arguments, hide the rest of the command-line
                        display_args_count=`echo $1 | cut -c 3-`
                        shift
                        ;;
        esac
        check_arg "$0" "$1"
        if echo "$1" | fgrep -q ' '; then
                if ! test $display_args_count = 0; then
                        display_line="$RUNCMD_PROMPT '$1'"
                else
                        display_line=
                fi
                cmd_line="'$1'"
        else
                if ! test $display_args_count = 0; then
                        display_line="$RUNCMD_PROMPT $1"
                else
                        display_line=
                fi
                cmd_line="$1"
        fi
        shift
        if ! test '(' $display_args_count = all ')' -o '(' $display_args_count = 0 ')'; then
                display_args_count=`expr $display_args_count - 1`
        fi

        while ! test $# = 0; do
                check_arg "$0" "$1"
                if echo "$1" | fgrep -q ' '; then
                        if ! test $display_args_count = 0; then
                                display_line="$display_line '$1'"
                        fi
                        cmd_line="$cmd_line '$1'"
                else
                        if ! test $display_args_count = 0; then
                                display_line="$display_line $1"
                        fi
                        cmd_line="$cmd_line $1"
                fi

                shift
                if ! test '(' $display_args_count = all ')' -o '(' $display_args_count = 0 ')'; then
                        display_args_count=`expr $display_args_count - 1`
                fi
        done

        echo $display_line
        eval $cmd_line
}

trycmd() {

        #
        # Runs the given command trough 'runcmd' and checks whether execution of the command was successful.
        # The test for success is not done the common way, i.e. by checking the return code.
        # Instead, a command execution is considered successful if and only if the command has written
        # something on the standard output.
        #

        tmpfile="svn-cmd-output.txt"

        runcmd -d$# "$@" \| tee "$tmpfile"
        outputsize=`wc -c "$tmpfile" | awk '{ print $1 }'`
        rm "$tmpfile"

        echo "x$outputsize" | grep -q '^x[1-9][0-9]*$'
        return $?
}

echo
runcmd svnadmin create test-repo
runcmd mkdir working-copy
runcmd svn checkout file://`pwd | sed -e 's/ /%20/g'`/test-repo "`pwd`/working-copy"
runcmd cd working-copy
runcmd mkdir newdir
runcmd svn add newdir
runcmd svn commit -m "added dir \"newdir\""
runcmd echo 'Hello, world!' \> "newdir/\@NewFile.txt"
trycmd svn add "newdir/@NewFile.txt"
if ! test $? = 0; then
        trycmd svn add "newdir/@NewFile.txt@"
fi
if ! test $? = 0; then
        runcmd cd newdir
        runcmd svn add "@NewFile.txt"
        runcmd cd ..
fi
trycmd svn commit -m "added file \"newdir/@NewFile.txt\"" "newdir/@NewFile.txt"
if ! test $? = 0; then
        trycmd svn commit -m "added file \"newdir/@NewFile.txt\"" "newdir/@NewFile.txt@"
fi
runcmd cd ..
echo
Received on 2009-05-26 07:28:47 CEST

This is an archived mail posted to the Subversion Dev mailing list.