tvl-depot/users/lukegb/hgext/gerrithook.py

64 lines
2 KiB
Python
Raw Normal View History

"""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')