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

[PATCH] can't "svn patch" working copy root if the patch is in --git format

From: Dmitry Pavlenko <pavlenko_at_tmatesoft.com>
Date: Mon, 09 Jul 2018 17:10:26 +0200

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
Received on 2018-07-09 17:59:42 CEST

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