Hello!

I've found a bug when applying a patch in Git format to the working copy root.
Steps to reproduce:

#!/bin/sh

SVN=svn

#1. Create an empty SVN repository.

REPOSITORY_PATH="$PWD/svn.repo"

svnadmin create "$REPOSITORY_PATH"

# 2. Create a patch that sets some property on a root directory. E.g.

WC_PATH="/tmp/wc"
REPOSITORY_URL="file://$REPOSITORY_PATH"
PATCH_PATH=/tmp/patch
EXPECTED_PROPERTY_VALUE=value

$SVN co $REPOSITORY_URL $WC_PATH
svn propset svn:ignore $EXPECTED_PROPERTY_VALUE $WC_PATH

$SVN diff --git $WC_PATH > $PATCH_PATH

# 3. Create another clean working copy for that repository
# E.g. we can just clean an existing one:

$SVN revert $WC_PATH

# 4. Apply the patch

$SVN patch $PATCH_PATH $WC_PATH

# 5. Check the property of $WC_PATH

ACTUAL_PROPERTY_VALUE=`svn propget svn:ignore $WC_PATH`

echo "===="
if [ x"$EXPECTED_PROPERTY_VALUE" != x"$ACTUAL_PROPERTY_VALUE" ] ; then
  echo "Bug!"
  echo "Expected value: $EXPECTED_PROPERTY_VALUE"
  echo "Actual value: $ACTUAL_PROPERTY_VALUE"
else
  echo "Test passed!"
fi
echo "===="  


Note that the patch looks like

Index: /tmp/wc
===================================================================
diff --git a/ b/
--- a/  (revision 0)
+++ b/  (working copy)

Property changes on: 
___________________________________________________________________
Added: svn:ignore
## -0,0 +1 ##
+value


The problem happens in parse-diff.c in git_start() function when parsing

diff --git a/ b/

line in 2 places. The first one is:

 if (! *(new_path_marker + 3))
   {
     *new_state = state_start;
     return SVN_NO_ERROR;
   }

We get inside the check as there's no continuation after "b/" and SVN thinks 
the patch is invalid.

Another place is:

     /* No path after the marker. */
     if (! *new_path_start)
       break;

The logic is the same. When I comment out both check the code works correctly 
even though now there's an asymmetry between "old" and "new" path processing 
code.
[[[
   Fix "patch" command: allow empty path when patch is in Git format.

   * subversion/libsvn_diff/parse-diff.c
     (git_start): Remove empty path checks.
]]]
[[[
Index: subversion/libsvn_diff/parse-diff.c
===================================================================
--- subversion/libsvn_diff/parse-diff.c (revision 1835430)
+++ subversion/libsvn_diff/parse-diff.c (working copy)
@@ -1587,12 +1587,6 @@ git_start(enum parse_state *new_state, char *line,
       return SVN_NO_ERROR;
     }
 
-  if (! *(new_path_marker + 3))
-    {
-      *new_state = state_start;
-      return SVN_NO_ERROR;
-    }
-
   /* By now, we know that we have a line on the form '--git diff a/.+ b/.+'
    * We only need the filenames when we have deleted or added empty
    * files. In those cases the old_path and new_path is identical on the
@@ -1616,10 +1610,6 @@ git_start(enum parse_state *new_state, char *line,
       old_path_end = new_path_marker;
       new_path_start = new_path_marker + STRLEN_LITERAL(" b/");
 
-      /* No path after the marker. */
-      if (! *new_path_start)
-        break;
-
       len_old = old_path_end - old_path_start;
       len_new = new_path_end - new_path_start;

]]]
-- 
Dmitry Pavlenko,
TMate Software,
http://subgit.com/ - git-svn bridge

Reply via email to