[PATCH STABLE] rebase: ensure rebase revision remains visible (issue4504)

Pierre-Yves David pierre-yves.david at fb.com
Wed Jan 28 20:51:43 UTC 2015


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1422362036 0
#      Tue Jan 27 12:33:56 2015 +0000
# Branch stable
# Node ID bd1b422a66565d3c8edcd8245cf0e857d2a1903e
# Parent  f1c127df7c4f645db6538a56d9a1c416505796cc
rebase: ensure rebase revision remains visible (issue4504)

Before this changeset rebase was getting very confused if any revision in the
rebase set became hidden. This wans fairly easy to achieve if a rebased revision
was made visible by the working copy location. The rebase process would update
somewhere else and the revision would become hidden.

This work around this issue we ensure rebased revision remain visible for the
whole process.

This is a simple change suitable for stable. More subtle usage of unfiltered
repository in rebase may solve this issue more cleanly.

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -16,7 +16,7 @@
 
 from mercurial import hg, util, repair, merge, cmdutil, commands, bookmarks
 from mercurial import extensions, patch, scmutil, phases, obsolete, error
-from mercurial import copies
+from mercurial import copies, repoview
 from mercurial.commands import templateopts
 from mercurial.node import nullrev, nullid, hex, short
 from mercurial.lock import release
@@ -778,6 +778,7 @@
 
 def clearstatus(repo):
     'Remove the status files'
+    _clearrebasesetvisibiliy(repo)
     util.unlinkpath(repo.join("rebasestate"), ignoremissing=True)
 
 def restorestatus(repo):
@@ -831,6 +832,7 @@
         repo.ui.debug('computed skipped revs: %s\n' %
                       (' '.join(str(r) for r in sorted(skipped)) or None))
         repo.ui.debug('rebase status resumed\n')
+        _setrebasesetvisibility(repo, set(state.keys())
         return (originalwd, target, state, skipped,
                 collapse, keep, keepbranches, external, activebookmark)
     except IOError, err:
@@ -892,6 +894,7 @@
     dest: context
     rebaseset: set of rev
     '''
+    _setrebasesetvisibility(repo, rebaseset)
 
     # This check isn't strictly necessary, since mq detects commits over an
     # applied patch. But it prevents messing up the working directory when
@@ -1044,6 +1047,31 @@
             raise util.Abort(_('--tool can only be used with --rebase'))
         orig(ui, repo, *args, **opts)
 
+def _setrebasesetvisibility(repo, revs):
+    """store the currently rebased set on the repo object
+
+    This is used by another function to prevent rebased revision to because
+    hidden (see issue4505)"""
+    repo = repo.unfiltered()
+    revs = set(revs)
+    repo._rebaseset = revs
+    # invalidate cache if visibility changes
+    hiddens = repo.filteredrevcache.get('visible', set())
+    if revs & hiddens:
+        repo.invalidatevolatilesets()
+
+def _clearrebasesetvisibiliy(repo):
+    """remove rebaseset data from the repo"""
+    repo = repo.unfiltered()
+    if '_rebaseset' in vars(repo):
+        del repo._rebaseset
+
+def _rebasedvisible(orig, repo):
+    """ensure rebased revs stay visible (see issue4505)"""
+    blockers = orig(repo)
+    blockers.update(getattr(repo, '_rebaseset', ()))
+    return blockers
+
 def summaryhook(ui, repo):
     if not os.path.exists(repo.join('rebasestate')):
         return
@@ -1062,7 +1090,7 @@
               (len(state) - numrebased)))
 
 def uisetup(ui):
-    'Replace pull with a decorator to provide --rebase option'
+    #Replace pull with a decorator to provide --rebase option
     entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
     entry[1].append(('', 'rebase', None,
                      _("rebase working directory to branch head")))
@@ -1072,3 +1100,6 @@
     cmdutil.unfinishedstates.append(
         ['rebasestate', False, False, _('rebase in progress'),
          _("use 'hg rebase --continue' or 'hg rebase --abort'")])
+    # ensure rebased rev are not hidden
+    extensions.wrapfunction(repoview, '_getdynamicblockers', _rebasedvisible)
+
diff --git a/tests/test-rebase-obsolete.t b/tests/test-rebase-obsolete.t
--- a/tests/test-rebase-obsolete.t
+++ b/tests/test-rebase-obsolete.t
@@ -498,3 +498,45 @@
   |/
   o  0:cd010b8cd998 A
   
+
+Test hidden changesets in the rebase set (issue4504)
+
+  $ hg up --hidden 9
+  3 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo J > J
+  $ hg add J
+  $ hg commit -m J
+  $ hg debugobsolete `hg log --rev . -T '{node}'`
+
+  $ hg rebase --rev .~1::. --dest 'max(desc(D))' --traceback
+  rebasing 9:4bde274eefcf "I"
+  rebasing 13:06edfc82198f "J" (tip)
+  $ hg log -G
+  @  15:5ae8a643467b J
+  |
+  o  14:9ad579b4a5de I
+  |
+  | o  12:acd174b7ab39 I
+  | |
+  | o  11:6c11a6218c97 H
+  | |
+  o |  10:b5313c85b22e D
+  |/
+  | o    8:53a6a128b2b7 M
+  | |\
+  | | x  7:02de42196ebe H
+  | | |
+  o---+  6:eea13746799a G
+  | | |
+  | | o  5:24b6387c8c8c F
+  | | |
+  o---+  4:9520eea781bc E
+   / /
+  x |  3:32af7686d403 D
+  | |
+  o |  2:5fddd98957c8 C
+  | |
+  o |  1:42ccdea3bb16 B
+  |/
+  o  0:cd010b8cd998 A
+  


More information about the Mercurial-devel mailing list