changeset 521:839734dfb5c7

Handle tag subdirectory as tag in replay mode (issue119) Original version by Dirkjan Ochtman <dirkjan@ochtman.nl>
author Patrick Mezard <pmezard@gmail.com>
date Fri, 22 Jan 2010 18:01:19 -0600
parents 5a5b90a6d522
children 60bf433647e7
files hgsubversion/editor.py hgsubversion/svnmeta.py tests/fixtures/renametagdir.sh tests/fixtures/renametagdir.svndump tests/test_tags.py
diffstat 5 files changed, 274 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/hgsubversion/editor.py
+++ b/hgsubversion/editor.py
@@ -234,6 +234,9 @@ class HgEditor(delta.Editor):
                 self.current.emptybranches[branch] = False
         if br_path is None or not copyfrom_path:
             return path
+        if self.meta.get_path_tag(path):
+            del self.current.emptybranches[branch]
+            return path
         tag = self.meta.get_path_tag(copyfrom_path)
         if tag not in self.meta.tags:
             tag = None
--- a/hgsubversion/svnmeta.py
+++ b/hgsubversion/svnmeta.py
@@ -262,10 +262,13 @@ class SVNMeta(object):
             return (path, None, '')
         tag = self.get_path_tag(path)
         if tag:
-            matched = [t for t in self.tags.iterkeys() if tag.startswith(t+'/')]
+            # consider the new tags when dispatching entries
+            matched = []
+            for tags in (self.tags, self.addedtags):
+                matched += [t for t in tags if tag.startswith(t + '/')]
             if not matched:
                 return None, None, None
-            matched.sort(cmp=lambda x,y: cmp(len(x),len(y)), reverse=True)
+            matched.sort(key=len, reverse=True)
             brpath = tag[len(matched[0])+1:]
             svrpath = path[:-(len(brpath)+1)]
             ln = self.localname(svrpath)
new file mode 100755
--- /dev/null
+++ b/tests/fixtures/renametagdir.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# inspired by Python r62868
+
+mkdir temp
+cd temp
+svnadmin create repo
+svn co file://`pwd`/repo wc
+export REPO=file://`pwd`/repo
+cd wc
+mkdir branches trunk tags
+svn add *
+svn ci -m 'btt'
+
+echo a > trunk/a
+svn add trunk/a
+svn ci -m 'Add file.'
+svn up
+
+svn cp trunk branches/test
+svn ci -m 'Branch.'
+svn up
+
+cd ..
+svn cp -m 'First tag.' $REPO/branches/test@3 $REPO/tags/test-0.1
+svn cp -m 'Weird tag.' $REPO/branches/test@3 $REPO/tags/test-0.1/test
+
+cd ..
+svnadmin dump temp/repo > renametagdir.svndump
+echo
+echo 'Complete.'
+echo 'You probably want to clean up temp now.'
+echo 'Dump in renametagdir.svndump'
+exit 0
new file mode 100644
--- /dev/null
+++ b/tests/fixtures/renametagdir.svndump
@@ -0,0 +1,165 @@
+SVN-fs-dump-format-version: 2
+
+UUID: a0c6ec72-28b3-4974-bd95-6d36963afc51
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2010-01-16T19:26:17.747443Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 104
+Content-length: 104
+
+K 7
+svn:log
+V 3
+btt
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-01-16T19:26:18.096428Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tags
+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
+
+
+Revision-number: 2
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+Add file.
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-01-16T19:26:19.083966Z
+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: 3
+Prop-content-length: 108
+Content-length: 108
+
+K 7
+svn:log
+V 7
+Branch.
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-01-16T19:26:22.053451Z
+PROPS-END
+
+Node-path: branches/test
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk
+
+
+Revision-number: 4
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 10
+First tag.
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-01-16T19:26:24.099798Z
+PROPS-END
+
+Node-path: tags/test-0.1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 3
+Node-copyfrom-path: branches/test
+
+
+Revision-number: 5
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 10
+Weird tag.
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-01-16T19:26:24.191458Z
+PROPS-END
+
+Node-path: tags/test-0.1/test
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 3
+Node-copyfrom-path: branches/test
+
+
--- a/tests/test_tags.py
+++ b/tests/test_tags.py
@@ -1,4 +1,4 @@
-import os
+import os, sys, cStringIO, difflib
 import unittest
 
 from mercurial import commands
@@ -188,6 +188,73 @@ class TestTags(test_util.TestBase):
         commands.pull(repo.ui, repo)
         self.assertEqual(open(tm).read().splitlines()[0], '2')
 
+    def _debug_print_tags(self, repo, ctx, fp):
+        def formatnode(ctx):
+            crev = ctx.extra().get('convert_revision', 'unk/unk@unk')
+            path, rev = crev.rsplit('@', 1)
+            path = path.split('/', 1)[-1]
+            branch = ctx.branch() or 'default'
+            return 'hg=%s@%d:svn=%s@%s' % (branch, ctx.rev(), path, rev)
+
+        w = fp.write
+        if '.hgtags' not in ctx or not ctx['.hgtags'].data().strip():
+            return
+        desc = ctx.description().splitlines()[0].strip()
+        w('node: %s\n' % formatnode(ctx))
+        w('%s\n' % desc)
+        for line in ctx['.hgtags'].data().splitlines(False):
+            node, name = line.split(None, 1)
+            w('  %s: %s\n' % (name, formatnode(repo[node])))
+        w('\n')
+
+    def _test_tags(self, testpath, expected, stupid=False):
+        repo = self._load_fixture_and_fetch(testpath, stupid=stupid)
+        fp = cStringIO.StringIO()
+        for r in repo:
+            self._debug_print_tags(repo, repo[r], fp=fp)
+        output = fp.getvalue().strip()
+        expected = expected.strip()
+        if expected == output:
+            return
+        expected = expected.splitlines()
+        output = output.splitlines()
+        diff = difflib.unified_diff(expected, output, 'expected', 'output')
+        self.assert_(False, '\n' + '\n'.join(diff))
+
+    def test_tagging_into_tag(self, expected=None, stupid=False):
+        expected = """\
+node: hg=test@2:svn=branches/test@4
+First tag.
+  test-0.1: hg=test@1:svn=branches/test@3
+
+node: hg=test@3:svn=branches/test@5
+Weird tag.
+  test-0.1: hg=test@1:svn=branches/test@3
+  test-0.1/test: hg=test@1:svn=branches/test@3
+"""
+        self._test_tags('renametagdir.svndump', expected)
+
+    def test_tagging_into_tag_stupid(self):
+        # This test exposed existing flaws with tag handling in stupid mode.
+        # They will be resolved in the future.
+        expected = """\
+node: hg=test@2:svn=branches/test@4
+First tag.
+  test-0.1: hg=test@1:svn=branches/test@3
+
+node: hg=test@4:svn=branches/test@4
+Weird tag.
+  test-0.1: hg=test@1:svn=branches/test@3
+  test-0.1: hg=test@3:svn=tags/test-0.1@5
+
+node: hg=test@5:svn=branches/test@5
+Weird tag.
+  test-0.1: hg=test@1:svn=branches/test@3
+  test-0.1: hg=test@3:svn=tags/test-0.1@5
+  test-0.1/test: hg=test@1:svn=branches/test@3
+"""
+        self._test_tags('renametagdir.svndump', expected, True)
+    
 
 def suite():
     return unittest.TestLoader().loadTestsFromTestCase(TestTags)