rebase: ensure rebase revision remains visible (issue4504) stable
authorPierre-Yves David <pierre-yves.david@fb.com>
Tue, 27 Jan 2015 12:33:56 +0000
branchstable
changeset 23970 8a544fb645bb
parent 23969 01e5b7323a48
child 23971 6becb9dbca25
child 23985 9a391d720cf9
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 was 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. To work around this issue, we ensure rebased revisions 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.
hgext/rebase.py
tests/test-rebase-obsolete.t
--- a/hgext/rebase.py	Wed Jan 28 02:28:39 2015 +0100
+++ b/hgext/rebase.py	Tue Jan 27 12:33:56 2015 +0000
@@ -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, 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)
+
--- a/tests/test-rebase-obsolete.t	Wed Jan 28 02:28:39 2015 +0100
+++ b/tests/test-rebase-obsolete.t	Tue Jan 27 12:33:56 2015 +0000
@@ -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
+