Patchwork D8948: rewriteutil: extract evolve code used to replace obsolete hashes in commits

login
register
mail settings
Submitter phabricator
Date Aug. 24, 2020, 11:08 p.m.
Message ID <differential-rev-PHID-DREV-bzzmnrwon4i35lgfnxgj-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47047/
State Superseded
Headers show

Comments

phabricator - Aug. 24, 2020, 11:08 p.m.
mharbison72 created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  The evolve command uses it, but there are core things like `phabsend` and
  `rebase` that would also benefit.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  mercurial/utils/rewriteutil.py

CHANGE DETAILS




To: mharbison72, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/mercurial/utils/rewriteutil.py b/mercurial/utils/rewriteutil.py
new file mode 100644
--- /dev/null
+++ b/mercurial/utils/rewriteutil.py
@@ -0,0 +1,56 @@ 
+# rewriteutil.py - utility code for rewriting changesets
+#
+# Copyright 2017 Octobus <contact@octobus.net>
+# Copyright 2020 Matt Harbison <mharbison72@gmail.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+import re
+
+from ..i18n import _
+from .. import (
+    node as nodemod,
+    obsutil,
+    scmutil,
+)
+
+sha1re = re.compile(br'\b[0-9a-f]{6,40}\b')
+
+
+def update_hash_refs(repo, commitmsg):
+    """Replace all obsolete commit hashes in the message with the current hash.
+
+    If the obsolete commit was split or is divergent, the hash is not replaced
+    as there's no way to know which successor to choose.
+    """
+    cache = {}
+    sha1s = re.findall(sha1re, commitmsg)
+    unfi = repo.unfiltered()
+    for sha1 in sha1s:
+        fullnode = scmutil.resolvehexnodeidprefix(unfi, sha1)
+        if fullnode is None:
+            continue
+        ctx = unfi[fullnode]
+        if not ctx.obsolete():
+            continue
+
+        successors = obsutil.successorssets(repo, ctx.node(), cache=cache)
+
+        # We can't make any assumptions about how to update the hash if the
+        # cset in question was split or diverged.
+        if len(successors) == 1 and len(successors[0]) == 1:
+            newsha1 = nodemod.hex(successors[0][0])
+            commitmsg = commitmsg.replace(sha1, newsha1[: len(sha1)])
+        else:
+            repo.ui.note(
+                _(
+                    b'The stale commit message reference to %s could '
+                    b'not be updated\n'
+                )
+                % sha1
+            )
+
+    return commitmsg