From 0a0020e449554b303740f9731839517e2b5abec4 Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown Date: Thu, 18 Jun 2020 00:31:31 +0100 Subject: feat(gerrithook): implement a crap gerrit mercurial extension Change-Id: Iae1fc9fb5efe046fe70b229e7b5cedc3c8f15749 --- users/lukegb/hgext/gerrithook.py | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 users/lukegb/hgext/gerrithook.py (limited to 'users/lukegb') 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') -- cgit 1.4.1