# HG changeset patch # User Dan Villiom Podlaski Christiansen # Date 1376069425 -7200 # Node ID 2d7398fffd0dd30378b7a52d9e722699a3e15a3d # Parent 131cb06dca76605925bd2cc403726fcda2b26e87 push: obsolete rather than rebase & strip when enabled This requires a few changes to wrappers.push() to use obsolescence rather than strip and to make the rebase -- which is non-destructive with obsolete active -- to no longer keep the originals. Possible future work involves no longer relying on rebase for non-outgoing revisions, and simply leaving them in the troubled state. We test this feature by adding setting obsolete_mode_tests to True in classes that push changes. diff --git a/hgsubversion/wrappers.py b/hgsubversion/wrappers.py --- a/hgsubversion/wrappers.py +++ b/hgsubversion/wrappers.py @@ -21,6 +21,11 @@ import svnwrap import svnrepo import util +try: + from mercurial import obsolete +except ImportError: + obsolete = None + pullfuns = { True: replay.convert_rev, False: stupidmod.convert_rev, @@ -179,6 +184,8 @@ def push(repo, dest, force, revs): ui = repo.ui old_encoding = util.swap_out_encoding() + hasobsolete = obsolete and obsolete._enabled + temporary_commits = [] try: # TODO: implement --rev/#rev support @@ -248,7 +255,8 @@ def push(repo, dest, force, revs): tip_hash = hashes[tip_ctx.node()][0] try: ui.status('committing %s\n' % current_ctx) - pushmod.commit(ui, repo, current_ctx, meta, tip_hash, svn) + pushedrev = pushmod.commit(ui, repo, current_ctx, meta, + tip_hash, svn) except pushmod.NoFilesException: ui.warn("Could not push revision %s because it had no changes " "in svn.\n" % current_ctx) @@ -264,6 +272,13 @@ def push(repo, dest, force, revs): # 6. Move our tip to the latest pulled tip for c in tip_ctx.descendants(): if c.node() in hashes and c.branch() == svnbranch: + if meta.get_source_rev(ctx=c)[0] == pushedrev.revnum: + # This is corresponds to the changeset we just pushed + if hasobsolete: + ui.note('marking %s as obsoleted by %s\n' % + (original_ctx.hex(), c.hex())) + obsolete.createmarkers(repo, [(original_ctx, [c])]) + tip_ctx = c # Remember what files have been modified since the @@ -290,7 +305,8 @@ def push(repo, dest, force, revs): hgrebase.rebase(ui, repo, dest=node.hex(tip_ctx.node()), rev=[needs_rebase_set], - extrafn=extrafn, keep=True) + extrafn=extrafn, + keep=not hasobsolete) finally: os.chdir(saved_path) util.swap_out_encoding() @@ -302,8 +318,10 @@ def push(repo, dest, force, revs): finally: util.swap_out_encoding() - # strip the original changesets since the push was successful - util.strip(ui, repo, outgoing, "all") + if not hasobsolete: + # strip the original changesets since the push was + # successful and changeset obsolescence is unavailable + util.strip(ui, repo, outgoing, "all") finally: try: # It's always safe to delete the temporary commits. @@ -315,7 +333,12 @@ def push(repo, dest, force, revs): parent = repo[None].p1() if parent.node() in temporary_commits: hg.update(repo, parent.p1().node()) - util.strip(ui, repo, temporary_commits, backup=None) + if hasobsolete: + relations = ((repo[n], ()) for n in temporary_commits) + obsolete.createmarkers(repo, relations) + else: + util.strip(ui, repo, temporary_commits, backup=None) + finally: util.swap_out_encoding(old_encoding) return 1 # so we get a sane exit status, see hg's commands.push diff --git a/tests/test_externals.py b/tests/test_externals.py --- a/tests/test_externals.py +++ b/tests/test_externals.py @@ -277,6 +277,8 @@ d3/ext3 = [hgsubversion] d3:^/trunk/comm self.test_mergeexternals(True) class TestPushExternals(test_util.TestBase): + obsolete_mode_tests = True + def test_push_externals(self, stupid=False): repo = self._load_fixture_and_fetch('pushexternals.svndump') # Add a new reference on an existing and non-existing directory diff --git a/tests/test_push_autoprops.py b/tests/test_push_autoprops.py --- a/tests/test_push_autoprops.py +++ b/tests/test_push_autoprops.py @@ -8,6 +8,8 @@ import test_util from hgsubversion import svnwrap class PushAutoPropsTests(test_util.TestBase): + obsolete_mode_tests = True + def setUp(self): test_util.TestBase.setUp(self) repo, self.repo_path = self.load_and_fetch('emptyrepo.svndump') diff --git a/tests/test_push_command.py b/tests/test_push_command.py --- a/tests/test_push_command.py +++ b/tests/test_push_command.py @@ -23,6 +23,8 @@ import time class PushTests(test_util.TestBase): + obsolete_mode_tests = True + def setUp(self): test_util.TestBase.setUp(self) self.repo_path = self.load_and_fetch('simple_branch.svndump')[1] diff --git a/tests/test_push_dirs.py b/tests/test_push_dirs.py --- a/tests/test_push_dirs.py +++ b/tests/test_push_dirs.py @@ -3,6 +3,8 @@ import test_util import unittest class TestPushDirectories(test_util.TestBase): + obsolete_mode_tests = True + def test_push_dirs(self): repo_path = self.load_and_fetch('emptyrepo.svndump')[1] diff --git a/tests/test_push_eol.py b/tests/test_push_eol.py --- a/tests/test_push_eol.py +++ b/tests/test_push_eol.py @@ -3,6 +3,8 @@ import test_util import unittest class TestPushEol(test_util.TestBase): + obsolete_mode_tests = True + def setUp(self): test_util.TestBase.setUp(self) self._load_fixture_and_fetch('emptyrepo.svndump') diff --git a/tests/test_push_renames.py b/tests/test_push_renames.py --- a/tests/test_push_renames.py +++ b/tests/test_push_renames.py @@ -4,6 +4,8 @@ import sys import unittest class TestPushRenames(test_util.TestBase): + obsolete_mode_tests = True + def setUp(self): test_util.TestBase.setUp(self) self.repo_path = self.load_and_fetch('pushrenames.svndump', diff --git a/tests/test_single_dir_push.py b/tests/test_single_dir_push.py --- a/tests/test_single_dir_push.py +++ b/tests/test_single_dir_push.py @@ -11,6 +11,8 @@ from mercurial import node from mercurial import ui class TestSingleDirPush(test_util.TestBase): + obsolete_mode_tests = True + def test_push_single_dir(self): # Tests simple pushing from default branch to a single dir repo repo, repo_path = self.load_and_fetch('branch_from_tag.svndump',