changeset 582:44c56a7727c4

editor: fix issamefile() and copy detection in replay mode Known failures: - comprehensive/test_verify on replace_branch_with_branch: replaced files content is incorrect - comprehensive/test_stupid_pull on replace_branch_with_branch: very stupid mode does not handle replacements correctly.
author Patrick Mezard <pmezard@gmail.com>
date Tue, 02 Mar 2010 17:06:06 +0100
parents 90efea2c19df
children a016b253910b
files hgsubversion/editor.py hgsubversion/util.py tests/fixtures/replace_branch_with_branch.sh tests/fixtures/replace_branch_with_branch.svndump tests/test_fetch_branches.py
diffstat 5 files changed, 309 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/hgsubversion/editor.py
+++ b/hgsubversion/editor.py
@@ -216,13 +216,13 @@ class HgEditor(delta.Editor):
             fctx = ctx.filectx(from_file)
             flags = fctx.flags()
             self.current.set(path, fctx.data(), 'x' in flags, 'l' in flags)
-        if from_branch == branch:
-            parentid = self.meta.get_parent_revision(self.current.rev.revnum,
-                                                     branch)
-            if parentid != revlog.nullid:
-                parentctx = self.repo.changectx(parentid)
-                if util.issamefile(parentctx, ctx, from_file):
-                    self.current.copies[path] = from_file
+            if from_branch == branch:
+                parentid = self.meta.get_parent_revision(
+                    self.current.rev.revnum, branch)
+                if parentid != revlog.nullid:
+                    parentctx = self.repo.changectx(parentid)
+                    if util.issamefile(parentctx, ctx, from_file):
+                        self.current.copies[path] = from_file
 
     @ieditor
     def add_directory(self, path, parent_baton, copyfrom_path,
--- a/hgsubversion/util.py
+++ b/hgsubversion/util.py
@@ -145,7 +145,9 @@ def swap_out_encoding(new_encoding="UTF-
 
 
 def issamefile(parentctx, childctx, f):
-    """Assuming f exists and is the same in childctx and parentctx, return True."""
+    """Return True if f exists and is the same in childctx and parentctx"""
+    if f not in parentctx or f not in childctx:
+        return False
     if parentctx == childctx:
         return True
     if parentctx.rev() > childctx.rev():
new file mode 100755
--- /dev/null
+++ b/tests/fixtures/replace_branch_with_branch.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+RSVN="`pwd`/rsvn.py"
+export PATH=/bin:/usr/bin
+mkdir temp
+cd temp
+
+svnadmin create repo
+svn co file://`pwd`/repo wc
+
+cd wc
+mkdir trunk branches
+cd trunk
+echo a > a
+cd ..
+svn add *
+svn ci -m 'initial'
+
+svn up
+svn cp trunk branches/branch1
+svn ci -m 'branch1'
+svn up
+echo b > branches/branch1/b
+echo d > branches/branch1/d
+svn add branches/branch1/b branches/branch1/d
+svn ci -m 'add b to branch1'
+svn cp trunk branches/branch2
+svn ci -m 'branch2'
+svn up
+echo c > branches/branch2/c
+svn add branches/branch2/c
+svn ci -m 'add c to branch2'
+svn up
+
+# Clobber branch1 with branch2
+cd ..
+cat > clobber.rsvn <<EOF
+rdelete branches/branch1
+rcopy branches/branch2 branches/branch1
+rcopy branches/branch1/d branches/branch1/a
+EOF
+
+python $RSVN --message=blah --username=evil `pwd`/repo < clobber.rsvn
+
+svnadmin dump repo > ../replace_branch_with_branch.svndump
new file mode 100644
--- /dev/null
+++ b/tests/fixtures/replace_branch_with_branch.svndump
@@ -0,0 +1,234 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 9ccfc2a0-ffd9-470e-a000-ccb1f0fe21e5
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2010-02-24T20:15:47.286918Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 108
+Content-length: 108
+
+K 7
+svn:log
+V 7
+initial
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-02-24T20:15:48.124168Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3
+Text-content-sha1: 3f786850e387550fdab836ed7e6dc881de23001b
+Content-length: 12
+
+PROPS-END
+a
+
+
+Revision-number: 2
+Prop-content-length: 108
+Content-length: 108
+
+K 7
+svn:log
+V 7
+branch1
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-02-24T20:15:51.070312Z
+PROPS-END
+
+Node-path: branches/branch1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 3
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 16
+add b to branch1
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-02-24T20:15:53.123732Z
+PROPS-END
+
+Node-path: branches/branch1/b
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 3b5d5c3712955042212316173ccf37be
+Text-content-sha1: 89e6c98d92887913cadf06b2adb97f26cde4849b
+Content-length: 12
+
+PROPS-END
+b
+
+
+Node-path: branches/branch1/d
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: e29311f6f1bf1af907f9ef9f44b8328b
+Text-content-sha1: e983f374794de9c64e3d1c1de1d490c0756eeeff
+Content-length: 12
+
+PROPS-END
+d
+
+
+Revision-number: 4
+Prop-content-length: 108
+Content-length: 108
+
+K 7
+svn:log
+V 7
+branch2
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-02-24T20:15:55.095809Z
+PROPS-END
+
+Node-path: branches/branch2
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk
+
+
+Revision-number: 5
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 16
+add c to branch2
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-02-24T20:15:57.098439Z
+PROPS-END
+
+Node-path: branches/branch2/c
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 2cd6ee2c70b0bde53fbe6cac3c8b8bb1
+Text-content-sha1: 2b66fd261ee5c6cfc8de7fa466bab600bcfe4f69
+Content-length: 12
+
+PROPS-END
+c
+
+
+Revision-number: 6
+Prop-content-length: 102
+Content-length: 102
+
+K 7
+svn:log
+V 4
+blah
+K 10
+svn:author
+V 4
+evil
+K 8
+svn:date
+V 27
+2010-02-24T20:15:59.687871Z
+PROPS-END
+
+Node-path: branches/branch1
+Node-kind: dir
+Node-action: delete
+
+Node-path: branches/branch1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 5
+Node-copyfrom-path: branches/branch2
+
+
+
+
+Node-path: branches/branch1/a
+Node-kind: file
+Node-action: delete
+
+Node-path: branches/branch1/a
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 5
+Node-copyfrom-path: branches/branch1/d
+Text-copy-source-md5: e29311f6f1bf1af907f9ef9f44b8328b
+Text-copy-source-sha1: e983f374794de9c64e3d1c1de1d490c0756eeeff
+
+
+
+
--- a/tests/test_fetch_branches.py
+++ b/tests/test_fetch_branches.py
@@ -131,6 +131,26 @@ class TestFetchBranches(test_util.TestBa
         self.assertEqual(node.hex(repo['tip'].node()),
                          '4108a81a82c7925d5551091165dc54c41b06a8a8')
 
+    def test_replace_branch_with_branch(self, stupid=False):
+        repo = self._load_fixture_and_fetch('replace_branch_with_branch.svndump',
+                                            stupid)
+        self.assertEqual(7, len(repo))
+        # tip is former topological branch1 being closed
+        ctx = repo['tip']
+        self.assertEqual('1', ctx.extra().get('close', '0'))
+        self.assertEqual('branch1', ctx.branch())
+        # r5 is where the replacement takes place
+        ctx = repo[5]
+        self.assertEqual(set(['a', 'c']), set(ctx))
+        self.assertEqual('0', ctx.extra().get('close', '0'))
+        self.assertEqual('branch1', ctx.branch())
+        self.assertEqual('c\n', ctx['c'].data())
+        # a replacement does not work yet
+        #self.assertEqual('d\n', ctx['a'].data())
+
+    def test_replace_branch_with_branch_stupid(self, stupid=False):
+        self.test_replace_branch_with_branch(True)
+
 def suite():
     all = [unittest.TestLoader().loadTestsFromTestCase(TestFetchBranches),
           ]