about summary refs log tree commit diff
path: root/users/lukegb/hgext
diff options
context:
space:
mode:
authorLuke Granger-Brown <hg@lukegb.com>2020-06-17T23·31+0100
committerLuke Granger-Brown <hg@lukegb.com>2020-06-17T23·31+0100
commit0a0020e449554b303740f9731839517e2b5abec4 (patch)
treec76a15b5e3472797450704c3d8eca05ce597c3af /users/lukegb/hgext
parent7f7f45ea883c93fcb7021e4a44a8081721534566 (diff)
feat(gerrithook): implement a crap gerrit mercurial extension r/1013
Change-Id: Iae1fc9fb5efe046fe70b229e7b5cedc3c8f15749
Diffstat (limited to 'users/lukegb/hgext')
-rw-r--r--users/lukegb/hgext/gerrithook.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/users/lukegb/hgext/gerrithook.py b/users/lukegb/hgext/gerrithook.py
new file mode 100644
index 000000000000..8b24f7bd71ad
--- /dev/null
+++ b/users/lukegb/hgext/gerrithook.py
@@ -0,0 +1,63 @@
+"""Bizarre hacks to make Gerrit better."""
+
+import collections
+import re
+import random
+import mercurial
+
+_ = mercurial.i18n._
+
+cmdtable = {}
+command = mercurial.registrar.command(cmdtable)
+
+testedwith = '5.3.1'
+
+_changeid_regex = re.compile(b'^Change-Id: (I.*)$', re.M)
+
+def random_hash():
+    """Returns a random SHA1-like hex string."""
+    return b"%040x" % random.getrandbits(160)
+
+def reposetup(ui, repo):
+
+    class GerritRepo(repo.__class__):
+        def commitctx(self, ctx, *args, **kwargs):
+            match = _changeid_regex.search(ctx._text)
+            if not match:
+                ctx._text = ctx._text.rstrip(b'\n')
+                ctx._text += b'\n\nChange-Id: I' + random_hash()
+            return super().commitctx(ctx, *args, **kwargs)
+
+    repo.__class__ = GerritRepo
+
+
+@command(b'gerrit-obsolete', [], _(b'[options]'))
+def gerritobsolete(ui, repo, **opts):
+    """Mark draft commits as obsolete by public commits based on Gerrit Change-Id tag."""
+    if repo.obsstore.readonly:
+        ui.error(b'obsstore is readonly')
+        return
+    changesets = collections.defaultdict(set)
+    drafts = set()
+    for draft in repo.set('draft() - obsolete()'):
+        match = _changeid_regex.search(draft.description())
+        if not match:
+            continue
+        changesets[match.groups()[0]].add(draft)
+        drafts.add(draft)
+    if not drafts:
+        return
+    publicparent = next(repo.set(
+        b'ancestor((public() and bookmark("master")), %s)' % (
+            b', '.join(x.hex() for x in drafts))))
+    megare = b're:(?ms)^Change-Id: (%s)$' % (b'|'.join(changesets.keys()),)
+    markers = []
+    for public in repo.set('(%s..(public() and master)) and desc(%s)', publicparent, megare):
+        match = _changeid_regex.search(public.description())
+        if not match:
+            continue
+        drafts = changesets[match.groups()[0]]
+        if not drafts:
+            continue
+        markers.append((tuple(drafts), (public,)))
+    mercurial.obsolete.createmarkers(repo, markers, operation=b'gerrit-obsolete')