Commits

Dan Villiom Podlaski Christiansen committed 2d7398f

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.

  • Participants
  • Parent commits 131cb06

Comments (0)

Files changed (8)

File hgsubversion/wrappers.py

 import svnrepo
 import util
 
+try:
+    from mercurial import obsolete
+except ImportError:
+    obsolete = None
+
 pullfuns = {
     True: replay.convert_rev,
     False: stupidmod.convert_rev,
     ui = repo.ui
     old_encoding = util.swap_out_encoding()
 
+    hasobsolete = obsolete and obsolete._enabled
+
     temporary_commits = []
     try:
         # TODO: implement --rev/#rev support
             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)
             # 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
                         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()
         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.
                 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

File tests/test_externals.py

         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

File tests/test_push_autoprops.py

 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')

File tests/test_push_command.py

 
 
 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]

File tests/test_push_dirs.py

 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]
 

File tests/test_push_eol.py

 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')

File tests/test_push_renames.py

 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',

File tests/test_single_dir_push.py

 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',