mozhghooks/prevent_webidl_changes.py
author Ehsan Akhgari <ehsan@mozilla.com>
Thu, 10 Jul 2014 16:09:13 -0400
changeset 201 a7ff9c6c9e69f5bd82d400d2bf293ce15ea98ab4
parent 197 ae1d24339570ee7600e96b18e4672f04bf76c45a
permissions -rwxr-xr-x
Bug 1032531 - Change the webidl hook to allow commits authored by a DOM reviewer; r=ted

#!/usr/bin/python
# Copyright (C) 2012 Mozilla Foundation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
"""
This hook is to prevent changes to .webidl files in pushes without proper DOM peer review.
"""

import re
from mercurial.node import short
from mercurial import util

backoutMessage = [re.compile(x) for x in [
    r'^(back(ing|ed)?\s+out|backout)',
    r'^(revert(ed|ing)?)'
]]

def isBackout(message):
    for r in backoutMessage:
        if r.search(message):
            return True
    return False

def hook(ui, repo, hooktype, node, **kwargs):
    DOM_peers = [
        'jst',              # Johnny Stenback
        'peterv',           # Peter Van der Beken
        'bz', 'bzbarsky',   # Boris Zbarsky
        'sicking', 'jonas', # Jonas Sicking
        'smaug',            # Olli Pettay
        'bent',             # Ben Turner
        'mounir',           # Mounir Lamouri
        'khuey',            # Kyle Huey
        'jlebar',           # Justin Lebar
        'hsivonen',         # Henri Sivonen
        'mrbkap',           # Blake Kaplan
        'bholley',          # Bobby Holley
    ]
    DOM_authors = [
        'jst@mozilla.com',         # Johnny Stenback
        'peterv@propagandism.org', # Peter Van der Beken
        'bzbarsky@mit.edu',        # Boris Zbarsky
        'jonas@sicking.cc',        # Jonas Sicking
        'olli.pettay@helsinki.fi', # Olli Pettay
        'bent.mozilla@gmail.com',  # Ben Turner
        'mounir@lamouri.fr',       # Mounir Lamouri
        'khuey@kylehuey.com',      # Kyle Huey
        'justin.lebar@gmail.com',  # Justin Lebar
        'hsivonen@hsivonen.fi',    # Henri Sivonen
        'mrbkap@gmail.com',        # Blake Kaplan
    ]
    error = ""
    webidlReviewed = False
    changesets = list(repo.changelog.revs(repo[node].rev()))
    if 'a=release' in repo.changectx(changesets[-1]).description().lower():
        # Accept the entire push for code uplifts.
        return 0
    # Loop through each changeset being added to the repository
    for i in reversed(changesets):
        c = repo.changectx(i)

        if len(c.parents()) > 1:
            # Skip merge changesets
            continue

        # Loop through each file for the current changeset
        for file in c.files():
            # Only Check WebIDL Files
            if file.endswith('.webidl'):
                message = c.description().lower()
                email = util.email(c.user())
                def search():
                  matches = re.findall('\Ws?r\s*=\s*(\w+(?:,\w+)*)', message)
                  for match in matches:
                      for reviewer in match.split(','):
                          if reviewer in DOM_peers:
                              return True
                  # We allow DOM peers to commit changes to WebIDL files without any review
                  # requirements assuming that they have looked at the changes they're committing.
                  for peer in DOM_authors:
                      if peer == email:
                          return True
                  return False
                webidlReviewed = search()
                if not webidlReviewed and not isBackout(message):
                        error += "WebIDL file %s altered in changeset %s without DOM peer review\n" % (file, short(c.node()))
    # Check if an error occured in any of the files that were changed
    if error != "":
        print "\n\n************************** ERROR ****************************"
        ui.warn("\n" + error + "\n")
        print "\n\rChanges to WebIDL files in this repo require review from a DOM peer in the form of r=...\n\rThis is to ensure that we behave responsibly with exposing new Web APIs. We appreciate your understanding..\n\r"
        print "*************************************************************\n\n"
        # Reject the changesets
        return 1
    else:
        if webidlReviewed:
            print "You've received proper review from a DOM peer on your WebIDL change(s) in your push, thanks for paying enough attention."
    # Accept the changesets
    return 0