Patchwork D3818: scmutil: make cleanupnodes optionally also fix the phase

login
register
mail settings
Submitter phabricator
Date June 21, 2018, 12:45 p.m.
Message ID <afd01b751ab3173121e6cece790bcb35@localhost.localdomain>
Download mbox | patch
Permalink /patch/32361/
State Not Applicable
Headers show

Comments

phabricator - June 21, 2018, 12:45 p.m.
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG32fba6fe893d: scmutil: make cleanupnodes optionally also fix the phase (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3818?vs=9240&id=9247

REVISION DETAIL
  https://phab.mercurial-scm.org/D3818

AFFECTED FILES
  contrib/phabricator.py
  hgext/fix.py
  hgext/uncommit.py
  mercurial/cmdutil.py
  mercurial/scmutil.py

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: quark, mharbison72, yuja, mercurial-devel

Patch

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -779,7 +779,8 @@ 
     def __contains__(self, node):
         return self._revcontains(self._torev(node))
 
-def cleanupnodes(repo, replacements, operation, moves=None, metadata=None):
+def cleanupnodes(repo, replacements, operation, moves=None, metadata=None,
+                 fixphase=False, targetphase=None):
     """do common cleanups when old nodes are replaced by new nodes
 
     That includes writing obsmarkers or stripping nodes, and moving bookmarks.
@@ -795,6 +796,7 @@ 
     metadata is dictionary containing metadata to be stored in obsmarker if
     obsolescence is enabled.
     """
+    assert fixphase or targetphase is None
     if not replacements and not moves:
         return
 
@@ -825,11 +827,38 @@ 
             newnode = newnodes[0]
         moves[oldnode] = newnode
 
+    allnewnodes = [n for ns in replacements.values() for n in ns]
+    toretract = {}
+    toadvance = {}
+    if fixphase:
+        precursors = {}
+        for oldnode, newnodes in replacements.items():
+            for newnode in newnodes:
+                precursors.setdefault(newnode, []).append(oldnode)
+
+        allnewnodes.sort(key=lambda n: unfi[n].rev())
+        newphases = {}
+        def phase(ctx):
+            return newphases.get(ctx.node(), ctx.phase())
+        for newnode in allnewnodes:
+            ctx = unfi[newnode]
+            if targetphase is None:
+                oldphase = max(unfi[oldnode].phase()
+                               for oldnode in precursors[newnode])
+                parentphase = max(phase(p) for p in ctx.parents())
+                newphase = max(oldphase, parentphase)
+            else:
+                newphase = targetphase
+            newphases[newnode] = newphase
+            if newphase > ctx.phase():
+                toretract.setdefault(newphase, []).append(newnode)
+            elif newphase < ctx.phase():
+                toadvance.setdefault(newphase, []).append(newnode)
+
     with repo.transaction('cleanup') as tr:
         # Move bookmarks
         bmarks = repo._bookmarks
         bmarkchanges = []
-        allnewnodes = [n for ns in replacements.values() for n in ns]
         for oldnode, newnode in moves.items():
             oldbmarks = repo.nodebookmarks(oldnode)
             if not oldbmarks:
@@ -850,6 +879,11 @@ 
         if bmarkchanges:
             bmarks.applychanges(repo, tr, bmarkchanges)
 
+        for phase, nodes in toretract.items():
+            phases.retractboundary(repo, tr, phase, nodes)
+        for phase, nodes in toadvance.items():
+            phases.advanceboundary(repo, tr, phase, nodes)
+
         # Obsolete or strip nodes
         if obsolete.isenabled(repo, obsolete.createmarkersopt):
             # If a node is already obsoleted, and we want to obsolete it
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -35,6 +35,7 @@ 
     obsolete,
     patch,
     pathutil,
+    phases,
     pycompat,
     revlog,
     rewriteutil,
@@ -784,16 +785,12 @@ 
                                 extra=extra,
                                 branch=label)
 
-            commitphase = ctx.phase()
-            overrides = {('phases', 'new-commit'): commitphase}
-            with repo.ui.configoverride(overrides, 'branch-change'):
-                newnode = repo.commitctx(mc)
-
+            newnode = repo.commitctx(mc)
             replacements[ctx.node()] = (newnode,)
             ui.debug('new node id is %s\n' % hex(newnode))
 
         # create obsmarkers and move bookmarks
-        scmutil.cleanupnodes(repo, replacements, 'branch-change')
+        scmutil.cleanupnodes(repo, replacements, 'branch-change', fixphase=True)
 
         # move the working copy too
         wctx = repo[None]
@@ -2536,21 +2533,19 @@ 
             # This not what we expect from amend.
             return old.node()
 
+        commitphase = None
         if opts.get('secret'):
-            commitphase = 'secret'
-        else:
-            commitphase = old.phase()
-        overrides = {('phases', 'new-commit'): commitphase}
-        with ui.configoverride(overrides, 'amend'):
-            newid = repo.commitctx(new)
+            commitphase = phases.secret
+        newid = repo.commitctx(new)
 
         # Reroute the working copy parent to the new changeset
         repo.setparents(newid, nullid)
         mapping = {old.node(): (newid,)}
         obsmetadata = None
         if opts.get('note'):
             obsmetadata = {'note': opts['note']}
-        scmutil.cleanupnodes(repo, mapping, 'amend', metadata=obsmetadata)
+        scmutil.cleanupnodes(repo, mapping, 'amend', metadata=obsmetadata,
+                             fixphase=True, targetphase=commitphase)
 
         # Fixing the dirstate because localrepo.commitctx does not update
         # it. This is rather convenient because we did not need to update
diff --git a/hgext/uncommit.py b/hgext/uncommit.py
--- a/hgext/uncommit.py
+++ b/hgext/uncommit.py
@@ -91,12 +91,7 @@ 
                          user=ctx.user(),
                          date=ctx.date(),
                          extra=ctx.extra())
-    # phase handling
-    commitphase = ctx.phase()
-    overrides = {('phases', 'new-commit'): commitphase}
-    with repo.ui.configoverride(overrides, 'uncommit'):
-        newid = repo.commitctx(new)
-    return newid
+    return repo.commitctx(new)
 
 def _fixdirstate(repo, oldctx, newctx, status):
     """ fix the dirstate after switching the working directory from oldctx to
@@ -183,7 +178,7 @@ 
                 # Fully removed the old commit
                 mapping[old.node()] = ()
 
-            scmutil.cleanupnodes(repo, mapping, 'uncommit')
+            scmutil.cleanupnodes(repo, mapping, 'uncommit', fixphase=True)
 
             with repo.dirstate.parentchange():
                 repo.dirstate.setparents(newid, node.nullid)
@@ -242,12 +237,7 @@ 
                                 user=predctx.user(),
                                 date=predctx.date(),
                                 extra=extras)
-        # phase handling
-        commitphase = curctx.phase()
-        overrides = {('phases', 'new-commit'): commitphase}
-        with repo.ui.configoverride(overrides, 'uncommit'):
-            newprednode = repo.commitctx(newctx)
-
+        newprednode = repo.commitctx(newctx)
         newpredctx = repo[newprednode]
         dirstate = repo.dirstate
 
@@ -257,4 +247,4 @@ 
             _fixdirstate(repo, curctx, newpredctx, s)
 
         mapping = {curctx.node(): (newprednode,)}
-        scmutil.cleanupnodes(repo, mapping, 'unamend')
+        scmutil.cleanupnodes(repo, mapping, 'unamend', fixphase=True)
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -158,7 +158,7 @@ 
                 del filedata[rev]
 
         replacements = {prec: [succ] for prec, succ in replacements.iteritems()}
-        scmutil.cleanupnodes(repo, replacements, 'fix')
+        scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
 
 def getworkqueue(ui, repo, pats, opts, revstofix, basectxs):
     """"Constructs the list of files to be fixed at specific revisions
@@ -484,25 +484,23 @@ 
             isexec=fctx.isexec(),
             copied=copied)
 
-    overrides = {('phases', 'new-commit'): ctx.phase()}
-    with ui.configoverride(overrides, source='fix'):
-        memctx = context.memctx(
-            repo,
-            parents=(newp1node, newp2node),
-            text=ctx.description(),
-            files=set(ctx.files()) | set(filedata.keys()),
-            filectxfn=filectxfn,
-            user=ctx.user(),
-            date=ctx.date(),
-            extra=ctx.extra(),
-            branch=ctx.branch(),
-            editor=None)
-        sucnode = memctx.commit()
-        prenode = ctx.node()
-        if prenode == sucnode:
-            ui.debug('node %s already existed\n' % (ctx.hex()))
-        else:
-            replacements[ctx.node()] = sucnode
+    memctx = context.memctx(
+        repo,
+        parents=(newp1node, newp2node),
+        text=ctx.description(),
+        files=set(ctx.files()) | set(filedata.keys()),
+        filectxfn=filectxfn,
+        user=ctx.user(),
+        date=ctx.date(),
+        extra=ctx.extra(),
+        branch=ctx.branch(),
+        editor=None)
+    sucnode = memctx.commit()
+    prenode = ctx.node()
+    if prenode == sucnode:
+        ui.debug('node %s already existed\n' % (ctx.hex()))
+    else:
+        replacements[ctx.node()] = sucnode
 
 def getfixers(ui):
     """Returns a map of configured fixer tools indexed by their names
diff --git a/contrib/phabricator.py b/contrib/phabricator.py
--- a/contrib/phabricator.py
+++ b/contrib/phabricator.py
@@ -580,9 +580,7 @@ 
                         repo, old, parents=parents, text=newdesc,
                         user=old.user(), date=old.date(), extra=old.extra())
 
-                    overrides = {(b'phases', b'new-commit'): old.phase()}
-                    with ui.configoverride(overrides, b'phabsend'):
-                        newnode = new.commit()
+                    newnode = new.commit()
 
                     mapping[old.node()] = [newnode]
                     # Update diff property
@@ -592,7 +590,7 @@ 
                 if tagname in repo.tags():
                     tags.tag(repo, tagname, nullid, message=None, user=None,
                              date=None, local=True)
-            scmutil.cleanupnodes(repo, mapping, b'phabsend')
+            scmutil.cleanupnodes(repo, mapping, b'phabsend', fixphase=True)
             if wnode in mapping:
                 unfi.setparents(mapping[wnode][0])