changeset 1055:2d7398fffd0d

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.
author Dan Villiom Podlaski Christiansen <dan@cabo.dk>
date Fri, 09 Aug 2013 19:30:25 +0200
parents 131cb06dca76
children 0932bb4d8870
files hgsubversion/wrappers.py tests/test_externals.py tests/test_push_autoprops.py tests/test_push_command.py tests/test_push_dirs.py tests/test_push_eol.py tests/test_push_renames.py tests/test_single_dir_push.py
diffstat 8 files changed, 42 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
--- 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')
--- 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]
--- 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]
 
--- 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')
--- 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',
--- 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',