hghooks/mozhghooks/check/prevent_sync_ipc_changes.py (66 lines of code) (raw):

# 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 from mercurial.utils import stringutil from mercurial.node import short from mozautomation.commitparser import ( parse_requal_reviewers, is_backout, ) from mozhg.util import repo_owner from ..checks import PreTxnChangegroupCheck, print_banner IPC_PEERS = [ { "name": b"Andrew McCreight", "nick": [b"mccr8"], "email": [b"continuation@gmail.com"], }, {"name": b"Jed Davis", "nick": [b"jld"], "email": [b"jld@mozilla.com"]}, {"name": b"Nika Layzell", "nick": [b"nika"], "email": [b"nika@thelayzells.com"]}, {"name": b"David Parks", "nick": [b"handyman"], "email": [b"daparks@mozilla.com"]}, ] MISSING_REVIEW = b""" Changeset %s alters sync-messages.ini without IPC peer review. Please, request review from either: """ for p in IPC_PEERS: MISSING_REVIEW += b" - %s (:%s)\n" % (p["name"], p["nick"][0]) class SyncIPCCheck(PreTxnChangegroupCheck): """Changes to ipc/ipdl/sync-messages.ini requires IPC peer review.""" @property def name(self): return b"ipcsync_check" def relevant(self): return ( self.repo_metadata[b"firefox_releasing"] and repo_owner(self.repo) != b"scm_allow_direct_push" ) def pre(self, node): # Accept the entire push for code uplifts self.is_uplift = b"a=release" in self.repo[b"tip"].description().lower() def check(self, ctx): if self.is_uplift: return True # Ignore merge changesets if len(ctx.parents()) > 1: return True # Ignore backouts if is_backout(ctx.description()): return True # Ignore changes that don't touch sync-messages.ini ipc_files = [f for f in ctx.files() if f == b"ipc/ipdl/sync-messages.ini"] if not ipc_files: return True # Allow patches authored by peers if self._is_peer_email(stringutil.email(ctx.user())): return True # Allow if reviewed by any peer requal = list(parse_requal_reviewers(ctx.description())) if any(self._is_peer_nick(nick) for nick in requal): return True # Reject print_banner(self.ui, b"error", MISSING_REVIEW % short(ctx.node())) return False def post_check(self): return True @staticmethod def _is_peer_email(email): email = email.lower() for peer in IPC_PEERS: if email in peer["email"]: return True return False @staticmethod def _is_peer_nick(nick): nick = nick.lower() for peer in IPC_PEERS: if nick in peer["nick"]: return True return False