# HG changeset patch # User Dirkjan Ochtman # Date 1243603724 -7200 # Node ID 9327e93256450c6991904654fc4b028bf51f8b35 # Parent af9fc01299b46f656ac5d6f43b4cf0f6f5d67a4d Use tbdelta to push added tags into .hgtags. diff --git a/hgsubversion/hg_delta_editor.py b/hgsubversion/hg_delta_editor.py --- a/hgsubversion/hg_delta_editor.py +++ b/hgsubversion/hg_delta_editor.py @@ -566,8 +566,9 @@ class HgChangeReceiver(delta.Editor): and branch not in added_branches): parent = {branch: (None, 0, revision.revnum)} added_branches.update(parent) + rmtags = dict((t, self.tags[t][0]) for t in tags_to_delete) return { - 'tags': (added_tags, tags_to_delete), + 'tags': (added_tags, rmtags), 'branches': (added_branches, self.branches_to_delete), } @@ -616,6 +617,52 @@ class HgChangeReceiver(delta.Editor): check = lambda x: x[0][1] == branch and x[0][0] < rev.revnum return sorted(filter(check, self.revmap.iteritems()), reverse=True) + def committags(self, delta, rev, endbranches): + + date = self.fixdate(rev.date) + # determine additions/deletions per branch + branches = {} + for tag, source in delta[0].iteritems(): + b, r = source + branches.setdefault(b, []).append(('add', tag, r)) + for tag, branch in delta[1].iteritems(): + branches.setdefault(branch, []).append(('rm', tag, None)) + + for b, tags in branches.iteritems(): + + # modify parent's .hgtags source + parent = self.repo[{None: 'default'}.get(b, b)] + if '.hgtags' not in parent: + src = '' + else: + src = parent['.hgtags'].data() + for op, tag, r in sorted(tags, reverse=True): + if op == 'add': + tagged = node.hex(self.revmap[r, b]) + elif op == 'rm': + tagged = node.hex(node.nullid) + src += '%s %s\n' % (tagged, tag) + + # add new changeset containing updated .hgtags + def fctxfun(repo, memctx, path): + return context.memfilectx(path='.hgtags', data=src, + islink=False, isexec=False, + copied=None) + extra = util.build_extra(rev.revnum, b, self.uuid, self.subdir) + ctx = context.memctx(self.repo, + (parent.node(), node.nullid), + rev.message or ' ', + ['.hgtags'], + fctxfun, + self.authors[rev.author], + date, + extra) + new = self.repo.commitctx(ctx) + if (rev.revnum, b) not in self.revmap: + self.add_to_revmap(rev.revnum, b, new) + if b in endbranches: + endbranches[b] = new + def commit_current_delta(self, tbdelta): if hasattr(self, '_exception_info'): #pragma: no cover traceback.print_exception(*self._exception_info) @@ -740,7 +787,11 @@ class HgChangeReceiver(delta.Editor): if (rev.revnum, branch) not in self.revmap: self.add_to_revmap(rev.revnum, branch, new_hash) - # 3. close any branches that need it + # 3. handle tags + if tbdelta['tags'][0] or tbdelta['tags'][1]: + self.committags(tbdelta['tags'], rev, closebranches) + + # 4. close any branches that need it for branch in tbdelta['branches'][1]: # self.get_parent_revision(rev.revnum, branch) ha = closebranches.get(branch) @@ -752,9 +803,10 @@ class HgChangeReceiver(delta.Editor): self.clear_current_info() def delbranch(self, branch, node, rev): - def del_all_files(*args): - raise IOError - files = self.repo[node].manifest().keys() + pctx = self.repo[node] + def filectxfun(repo, memctx, path): + return pctx[path] + files = pctx.manifest().keys() extra = {'close': 1} if self.usebranchnames: extra['branch'] = branch or 'default' @@ -762,7 +814,7 @@ class HgChangeReceiver(delta.Editor): (node, revlog.nullid), rev.message or util.default_commit_msg, files, - del_all_files, + filectxfun, self.authors[rev.author], self.fixdate(rev.date), extra) diff --git a/hgsubversion/stupid.py b/hgsubversion/stupid.py --- a/hgsubversion/stupid.py +++ b/hgsubversion/stupid.py @@ -549,6 +549,9 @@ def convert_rev(ui, hg_editor, svn, r, t if closed is not None: deleted_branches[branch] = closed + if tbdelta['tags'][0] or tbdelta['tags'][1]: + hg_editor.committags(tbdelta['tags'], r, deleted_branches) + for b, parent in deleted_branches.iteritems(): if parent == node.nullid: continue diff --git a/hgsubversion/svnrepo.py b/hgsubversion/svnrepo.py --- a/hgsubversion/svnrepo.py +++ b/hgsubversion/svnrepo.py @@ -74,15 +74,6 @@ def generate_repo_class(ui, repo): raise hgutil.Abort('cannot display incoming changes from ' 'Subversion repositories, yet') - @localsvn - def tags(self): - tags = superclass.tags(self) - hg_editor = hg_delta_editor.HgChangeReceiver(repo=self) - for tag, source in hg_editor.tags.iteritems(): - target = hg_editor.get_parent_revision(source[1]+1, source[0]) - tags['tag/%s' % tag] = target - return tags - repo.__class__ = svnlocalrepo class svnremoterepo(mercurial.repo.repository): diff --git a/tests/test_tags.py b/tests/test_tags.py --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -13,21 +13,12 @@ class TestTags(test_util.TestBase): return test_util.load_fixture_and_fetch(fixture_name, self.repo_path, self.wc_path, stupid=stupid) - def _test_tag_revision_info(self, repo): - print repo.tags() - self.assertEqual(node.hex(repo[0].node()), - '434ed487136c1b47c1e8f952edb4dc5a8e6328df') - self.assertEqual(node.hex(repo['tip'].node()), - 'c95251e0dd04697deee99b79cc407d7db76e6a5f') - self.assertEqual(repo['tip'], repo[1]) - def test_tags(self, stupid=False): repo = self._load_fixture_and_fetch('basic_tag_tests.svndump', stupid=stupid) - self._test_tag_revision_info(repo) - repo = self.repo - self.assertEqual(repo['tip'].node(), repo['tag/tag_r3'].node()) - self.assertEqual(repo['tip'].node(), repo['tag/copied_tag'].node()) + self.assertEqual(sorted(repo.tags()), ['copied_tag', 'tag_r3', 'tip']) + self.assertEqual(repo['tag_r3'], repo['copied_tag']) + self.assertEqual(repo['tag_r3'].rev(), 1) def test_tags_stupid(self): self.test_tags(stupid=True) @@ -35,10 +26,8 @@ class TestTags(test_util.TestBase): def test_remove_tag(self, stupid=False): repo = self._load_fixture_and_fetch('remove_tag_test.svndump', stupid=stupid) - self._test_tag_revision_info(repo) - repo = self.repo - self.assertEqual(repo['tip'].node(), repo['tag/tag_r3'].node()) - self.assert_('tag/copied_tag' not in repo.tags()) + self.assertEqual(repo['tag_r3'].rev(), 1) + self.assert_('copied_tag' not in repo.tags()) def test_remove_tag_stupid(self): self.test_remove_tag(stupid=True) @@ -46,11 +35,8 @@ class TestTags(test_util.TestBase): def test_rename_tag(self, stupid=False): repo = self._load_fixture_and_fetch('rename_tag_test.svndump', stupid=stupid) - self._test_tag_revision_info(repo) - repo = self.repo - self.assertEqual(repo['tip'].node(), repo['tag/tag_r3'].node()) - self.assertEqual(repo['tip'].node(), repo['tag/other_tag_r3'].node()) - self.assert_('tag/copied_tag' not in repo.tags()) + self.assertEqual(repo['tag_r3'], repo['other_tag_r3']) + self.assert_('copied_tag' not in repo.tags()) def test_rename_tag_stupid(self): self.test_rename_tag(stupid=True) @@ -58,11 +44,9 @@ class TestTags(test_util.TestBase): def test_branch_from_tag(self, stupid=False): repo = self._load_fixture_and_fetch('branch_from_tag.svndump', stupid=stupid) - repo = self.repo - self.assertEqual(repo['tip'].node(), repo['branch_from_tag'].node()) - self.assertEqual(repo[1].node(), repo['tag/tag_r3'].node()) - self.assertEqual(repo['branch_from_tag'].parents()[0].node(), - repo['tag/copied_tag'].node()) + self.assert_('branch_from_tag' in repo.branchtags()) + self.assertEqual(repo[1], repo['tag_r3']) + self.assertEqual(repo['branch_from_tag'].parents()[0], repo['copied_tag']) def test_branch_from_tag_stupid(self): self.test_branch_from_tag(stupid=True) @@ -70,15 +54,9 @@ class TestTags(test_util.TestBase): def test_tag_by_renaming_branch(self, stupid=False): repo = self._load_fixture_and_fetch('tag_by_rename_branch.svndump', stupid=stupid) - repo = self.repo - branches = set() - for h in repo.heads(): - ctx = repo[h] - if 'close' not in ctx.extra(): - branches.add(ctx.branch()) - + branches = set(repo[h] for h in repo.heads(closed=False)) self.assert_('dummy' not in branches) - self.assertEqual(repo['tag/dummy'], repo['tip'].parents()[0]) + self.assertEqual(repo['dummy'], repo['tip'].parents()[0].parents()[0]) extra = repo['tip'].extra().copy() extra.pop('convert_revision', None) self.assertEqual(extra, {'branch': 'dummy', 'close': '1'})