# HG changeset patch # User Patrick Mezard # Date 1264204879 21600 # Node ID 839734dfb5c7862f89fdfb0acb32e5bf87351d0d # Parent 5a5b90a6d522abb81e223e60ac622e4a41891779 Handle tag subdirectory as tag in replay mode (issue119) Original version by Dirkjan Ochtman diff --git a/hgsubversion/editor.py b/hgsubversion/editor.py --- 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 diff --git a/hgsubversion/svnmeta.py b/hgsubversion/svnmeta.py --- 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) diff --git a/tests/fixtures/renametagdir.sh b/tests/fixtures/renametagdir.sh 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 diff --git a/tests/fixtures/renametagdir.svndump b/tests/fixtures/renametagdir.svndump 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 + + diff --git a/tests/test_tags.py b/tests/test_tags.py --- 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)