changeset 35319:228916ca12b5

rebase: add concludememorynode(), and call it when rebasing in-memory Differential Revision: https://phab.mercurial-scm.org/D1248
author Phil Cohen <phillco@fb.com>
date Thu, 07 Dec 2017 22:35:43 -0800
parents 2bac2d836ce0
children d901a88891fe
files hgext/rebase.py mercurial/context.py
diffstat 2 files changed, 75 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/rebase.py	Thu Dec 07 16:07:06 2017 -0800
+++ b/hgext/rebase.py	Thu Dec 07 22:35:43 2017 -0800
@@ -495,11 +495,21 @@
                     merging = p2 != nullrev
                     editform = cmdutil.mergeeditform(merging, 'rebase')
                     editor = cmdutil.getcommiteditor(editform=editform, **opts)
-                    newnode = concludenode(repo, rev, p1, p2,
-                                           extrafn=_makeextrafn(self.extrafns),
-                                           editor=editor,
-                                           keepbranches=self.keepbranchesf,
-                                           date=self.date)
+                    if self.wctx.isinmemory():
+                        newnode = concludememorynode(repo, rev, p1, p2,
+                            wctx=self.wctx,
+                            extrafn=_makeextrafn(self.extrafns),
+                            editor=editor,
+                            keepbranches=self.keepbranchesf,
+                            date=self.date)
+                        mergemod.mergestate.clean(repo)
+                    else:
+                        newnode = concludenode(repo, rev, p1, p2,
+                            extrafn=_makeextrafn(self.extrafns),
+                            editor=editor,
+                            keepbranches=self.keepbranchesf,
+                            date=self.date)
+
                     if newnode is None:
                         # If it ended up being a no-op commit, then the normal
                         # merge state clean-up path doesn't happen, so do it
@@ -552,13 +562,22 @@
             dsguard = None
             if ui.configbool('rebase', 'singletransaction'):
                 dsguard = dirstateguard.dirstateguard(repo, 'rebase')
-            with util.acceptintervention(dsguard):
-                newnode = concludenode(repo, revtoreuse, p1, self.external,
-                                       commitmsg=commitmsg,
-                                       extrafn=_makeextrafn(self.extrafns),
-                                       editor=editor,
-                                       keepbranches=self.keepbranchesf,
-                                       date=self.date)
+            if self.inmemory:
+                newnode = concludememorynode(repo, revtoreuse, p1,
+                    self.external,
+                    commitmsg=commitmsg,
+                    extrafn=_makeextrafn(self.extrafns),
+                    editor=editor,
+                    keepbranches=self.keepbranchesf,
+                    date=self.date, wctx=self.wctx)
+            else:
+                with util.acceptintervention(dsguard):
+                    newnode = concludenode(repo, revtoreuse, p1, self.external,
+                        commitmsg=commitmsg,
+                        extrafn=_makeextrafn(self.extrafns),
+                        editor=editor,
+                        keepbranches=self.keepbranchesf,
+                        date=self.date)
             if newnode is not None:
                 newrev = repo[newnode].rev()
                 for oldrev in self.state.iterkeys():
@@ -964,6 +983,44 @@
                      (max(destancestors),
                       ', '.join(str(p) for p in sorted(parents))))
 
+def concludememorynode(repo, rev, p1, p2, wctx=None,
+                       commitmsg=None, editor=None, extrafn=None,
+                       keepbranches=False, date=None):
+    '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev
+    but also store useful information in extra.
+    Return node of committed revision.'''
+    ctx = repo[rev]
+    if commitmsg is None:
+        commitmsg = ctx.description()
+    keepbranch = keepbranches and repo[p1].branch() != ctx.branch()
+    extra = {'rebase_source': ctx.hex()}
+    if extrafn:
+        extrafn(ctx, extra)
+
+    destphase = max(ctx.phase(), phases.draft)
+    overrides = {('phases', 'new-commit'): destphase}
+    with repo.ui.configoverride(overrides, 'rebase'):
+        if keepbranch:
+            repo.ui.setconfig('ui', 'allowemptycommit', True)
+        # Replicates the empty check in ``repo.commit``.
+        if wctx.isempty() and not repo.ui.configbool('ui', 'allowemptycommit'):
+            return None
+
+        if date is None:
+            date = ctx.date()
+
+        # By convention, ``extra['branch']`` (set by extrafn) clobbers
+        # ``branch`` (used when passing ``--keepbranches``).
+        branch = repo[p1].branch()
+        if 'branch' in extra:
+            branch = extra['branch']
+
+        memctx = wctx.tomemctx(commitmsg, parents=(p1, p2), date=date,
+            extra=extra, user=ctx.user(), branch=branch, editor=editor)
+        commitres = repo.commitctx(memctx)
+        wctx.clean() # Might be reused
+        return commitres
+
 def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None,
                  keepbranches=False, date=None):
     '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev
--- a/mercurial/context.py	Thu Dec 07 16:07:06 2017 -0800
+++ b/mercurial/context.py	Thu Dec 07 22:35:43 2017 -0800
@@ -2102,6 +2102,12 @@
     def isdirty(self, path):
         return path in self._cache
 
+    def isempty(self):
+        # We need to discard any keys that are actually clean before the empty
+        # commit check.
+        self._compact()
+        return len(self._cache) == 0
+
     def clean(self):
         self._cache = {}