<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[206967] trunk/Tools</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/206967">206967</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2016-10-09 09:34:53 -0700 (Sun, 09 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add support for canonicalizing contributors.json, and have check-webkit-style check the format.
https://bugs.webkit.org/show_bug.cgi?id=163177

Reviewed by Ryosuke Niwa.

Make it possible to round-trip contributors.json through CommitterList, so we can
support writing out contributors.json in canonical format. This requires saving
the case-preserved email and expertise in Contributor. CommitterList also needs
to be able to generate the &quot;exclusive&quot; lists, since it currently uses lists
that are the union of, say, committers and reviewers.

If contributors.json is malformed (invalid JSON), catch the Exception, report it
and exit rather than allowing the exception to propagate. With an invalid file,
an exception would be thrown before the JSON style checker reached this file, so
the error was not correctly reported.

Add style/checker/committer.py for checking that committers.json has the canonical format.

Add support to validate-committer-lists to dump out the canonical json (-d) or update
the file in-place (-c).

* Scripts/validate-committer-lists:
(CommitterListFromGit._print_three_column_row):
(CommitterListFromGit.possibly_expired_committers):
(CommitterListFromGit):
(CommitterListFromGit.print_possibly_expired_committers):
(main):
* Scripts/webkitpy/common/config/committers.py:
(Contributor.__init__):
(Contributor.__dict__):
(Committer.__init__):
(Reviewer.__init__):
(CommitterList.load_json):
(CommitterList):
(CommitterList._contributor_list_to_dict):
(CommitterList.as_json):
(CommitterList.reformat_in_place):
(CommitterList._exclusive_contributors):
(CommitterList._exclusive_committers):
(Contributor.matches_glob): Deleted.
(CommitterList.contributors): Deleted.
* Scripts/webkitpy/common/config/contributors.json:
* Scripts/webkitpy/style/checker.py:
(CheckerDispatcher._create_checker):
* Scripts/webkitpy/style/checkers/contributors.py: Added.
(ContributorsChecker):
(ContributorsChecker.__init__):
(ContributorsChecker.check):
(ContributorsChecker._unidiff_output):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsScriptsvalidatecommitterlists">trunk/Tools/Scripts/validate-committer-lists</a></li>
<li><a href="#trunkToolsScriptswebkitpycommonconfigcommitterspy">trunk/Tools/Scripts/webkitpy/common/config/committers.py</a></li>
<li><a href="#trunkToolsScriptswebkitpycommonconfigcontributorsjson">trunk/Tools/Scripts/webkitpy/common/config/contributors.json</a></li>
<li><a href="#trunkToolsScriptswebkitpystylecheckerpy">trunk/Tools/Scripts/webkitpy/style/checker.py</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkToolsScriptswebkitpystylecheckerscontributorspy">trunk/Tools/Scripts/webkitpy/style/checkers/contributors.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (206966 => 206967)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-10-09 07:34:08 UTC (rev 206966)
+++ trunk/Tools/ChangeLog        2016-10-09 16:34:53 UTC (rev 206967)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2016-10-08  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        Add support for canonicalizing contributors.json, and have check-webkit-style check the format.
+        https://bugs.webkit.org/show_bug.cgi?id=163177
+
+        Reviewed by Ryosuke Niwa.
+        
+        Make it possible to round-trip contributors.json through CommitterList, so we can
+        support writing out contributors.json in canonical format. This requires saving
+        the case-preserved email and expertise in Contributor. CommitterList also needs
+        to be able to generate the &quot;exclusive&quot; lists, since it currently uses lists
+        that are the union of, say, committers and reviewers.
+        
+        If contributors.json is malformed (invalid JSON), catch the Exception, report it
+        and exit rather than allowing the exception to propagate. With an invalid file,
+        an exception would be thrown before the JSON style checker reached this file, so
+        the error was not correctly reported.
+        
+        Add style/checker/committer.py for checking that committers.json has the canonical format.
+        
+        Add support to validate-committer-lists to dump out the canonical json (-d) or update
+        the file in-place (-c).
+
+        * Scripts/validate-committer-lists:
+        (CommitterListFromGit._print_three_column_row):
+        (CommitterListFromGit.possibly_expired_committers):
+        (CommitterListFromGit):
+        (CommitterListFromGit.print_possibly_expired_committers):
+        (main):
+        * Scripts/webkitpy/common/config/committers.py:
+        (Contributor.__init__):
+        (Contributor.__dict__):
+        (Committer.__init__):
+        (Reviewer.__init__):
+        (CommitterList.load_json):
+        (CommitterList):
+        (CommitterList._contributor_list_to_dict):
+        (CommitterList.as_json):
+        (CommitterList.reformat_in_place):
+        (CommitterList._exclusive_contributors):
+        (CommitterList._exclusive_committers):
+        (Contributor.matches_glob): Deleted.
+        (CommitterList.contributors): Deleted.
+        * Scripts/webkitpy/common/config/contributors.json:
+        * Scripts/webkitpy/style/checker.py:
+        (CheckerDispatcher._create_checker):
+        * Scripts/webkitpy/style/checkers/contributors.py: Added.
+        (ContributorsChecker):
+        (ContributorsChecker.__init__):
+        (ContributorsChecker.check):
+        (ContributorsChecker._unidiff_output):
+
</ins><span class="cx"> 2016-10-06  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Next step on moving to modern way to return DOM exceptions
</span></span></pre></div>
<a id="trunkToolsScriptsvalidatecommitterlists"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/validate-committer-lists (206966 => 206967)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/validate-committer-lists        2016-10-09 07:34:08 UTC (rev 206966)
+++ trunk/Tools/Scripts/validate-committer-lists        2016-10-09 16:34:53 UTC (rev 206967)
</span><span class="lines">@@ -215,19 +215,27 @@
</span><span class="cx">     def _print_three_column_row(widths, values):
</span><span class="cx">         print &quot;%s%s%s&quot; % (values[0].ljust(widths[0]), values[1].ljust(widths[1]), values[2])
</span><span class="cx"> 
</span><del>-    def print_possibly_expired_committers(self, committer_list):
</del><ins>+    def possibly_expired_committers(self, committer_list):
</ins><span class="cx">         authors_and_last_commits = self._last_commit_by_author().items()
</span><span class="cx">         authors_and_last_commits.sort(lambda a,b: cmp(a[1], b[1]), reverse=True)
</span><del>-        committer_cuttof = date.today() - timedelta(days=365)
</del><ins>+        committer_cutof = date.today() - timedelta(days=365)
+        retired_authors_and_last_commits = []
+        for (author, last_commit) in authors_and_last_commits:
+            last_commit_date = date.fromtimestamp(last_commit)
+            if committer_cutof &gt; last_commit_date:
+                retired_authors_and_last_commits.append((author, last_commit))
+        return retired_authors_and_last_commits
+
+    def print_possibly_expired_committers(self, committer_list):
+        retired_authors_and_last_commits = self.possibly_expired_committers(committer_list)
</ins><span class="cx">         column_widths = [13, 25]
</span><span class="cx">         print
</span><span class="cx">         print &quot;Committers who have not committed within one year:&quot;
</span><span class="cx">         self._print_three_column_row(column_widths, (&quot;Last Commit&quot;, &quot;Committer Email&quot;, &quot;Committer Record&quot;))
</span><del>-        for (author, last_commit) in authors_and_last_commits:
</del><ins>+        for (author, last_commit) in retired_authors_and_last_commits:
+            committer_record = committer_list.committer_by_email(author)
</ins><span class="cx">             last_commit_date = date.fromtimestamp(last_commit)
</span><del>-            if committer_cuttof &gt; last_commit_date:
-                committer_record = committer_list.committer_by_email(author)
-                self._print_three_column_row(column_widths, (str(last_commit_date), author, committer_record))
</del><ins>+            self._print_three_column_row(column_widths, (str(last_commit_date), author, committer_record))
</ins><span class="cx"> 
</span><span class="cx">     def print_committers_missing_from_committer_list(self, committer_list):
</span><span class="cx">         missing_from_contributors_json = []
</span><span class="lines">@@ -265,9 +273,22 @@
</span><span class="cx"> def main():
</span><span class="cx">     parser = OptionParser()
</span><span class="cx">     parser.add_option(&quot;-b&quot;, &quot;--check-bugzilla-emails&quot;, action=&quot;store_true&quot;, help=&quot;Check the bugzilla_email for each committer against bugs.webkit.org&quot;)
</span><ins>+    parser.add_option(&quot;-d&quot;, &quot;--dump&quot;, action=&quot;store_true&quot;, help=&quot;Dump the contributor list as JSON to stdout (suitable for saving to contributors.json)&quot;)
+    parser.add_option(&quot;-c&quot;, &quot;--canonicalize&quot;, action=&quot;store_true&quot;, help=&quot;Canonicalize contributors.json, rewriting it in-place&quot;)
+
</ins><span class="cx">     (options, args) = parser.parse_args()
</span><span class="cx"> 
</span><span class="cx">     committer_list = CommitterList()
</span><ins>+    if options.dump:
+        print committer_list.as_json()
+        return 0;
+
+    if options.canonicalize:
+        print &quot;Updating contributors.json in-place...&quot;
+        committer_list.reformat_in_place()
+        print &quot;Done&quot;
+        return 0;
+
</ins><span class="cx">     CommitterListFromMailingList().check_for_emails_missing_from_list(committer_list)
</span><span class="cx">  
</span><span class="cx">     if not Git.in_working_directory(&quot;.&quot;):
</span><span class="lines">@@ -277,6 +298,7 @@
</span><span class="cx">  - List of historical committers missing from contributors.json
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx">         return 1
</span><ins>+
</ins><span class="cx">     svn_committer_list = CommitterListFromGit()
</span><span class="cx">     svn_committer_list.print_possibly_expired_committers(committer_list)
</span><span class="cx">     svn_committer_list.print_committers_missing_from_committer_list(committer_list)
</span></span></pre></div>
<a id="trunkToolsScriptswebkitpycommonconfigcommitterspy"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/webkitpy/common/config/committers.py (206966 => 206967)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/webkitpy/common/config/committers.py        2016-10-09 07:34:08 UTC (rev 206966)
+++ trunk/Tools/Scripts/webkitpy/common/config/committers.py        2016-10-09 16:34:53 UTC (rev 206967)
</span><span class="lines">@@ -31,17 +31,14 @@
</span><span class="cx"> 
</span><span class="cx"> import fnmatch
</span><span class="cx"> import json
</span><ins>+import sys
</ins><span class="cx"> 
</span><span class="cx"> from webkitpy.common.editdistance import edit_distance
</span><span class="cx"> from webkitpy.common.memoized import memoized
</span><span class="cx"> from webkitpy.common.system.filesystem import FileSystem
</span><span class="cx"> 
</span><del>-
-# The list of contributors have been moved to contributors.json
-
-
</del><span class="cx"> class Contributor(object):
</span><del>-    def __init__(self, name, email_or_emails, irc_nickname_or_nicknames=None):
</del><ins>+    def __init__(self, name, email_or_emails, irc_nickname_or_nicknames=None, expertise=None):
</ins><span class="cx">         assert(name)
</span><span class="cx">         assert(email_or_emails)
</span><span class="cx">         self.full_name = name
</span><span class="lines">@@ -49,11 +46,13 @@
</span><span class="cx">             self.emails = [email_or_emails]
</span><span class="cx">         else:
</span><span class="cx">             self.emails = email_or_emails
</span><ins>+        self._case_preserved_emails = self.emails
</ins><span class="cx">         self.emails = map(lambda email: email.lower(), self.emails)  # Emails are case-insensitive.
</span><span class="cx">         if isinstance(irc_nickname_or_nicknames, str):
</span><span class="cx">             self.irc_nicknames = [irc_nickname_or_nicknames]
</span><span class="cx">         else:
</span><span class="cx">             self.irc_nicknames = irc_nickname_or_nicknames
</span><ins>+        self.expertise = expertise
</ins><span class="cx">         self.can_commit = False
</span><span class="cx">         self.can_review = False
</span><span class="cx"> 
</span><span class="lines">@@ -93,16 +92,26 @@
</span><span class="cx">                 return True
</span><span class="cx">         return False
</span><span class="cx"> 
</span><ins>+    def __dict__(self):
+        info = {&quot;emails&quot; : self._case_preserved_emails}
</ins><span class="cx"> 
</span><ins>+        if self.irc_nicknames:
+            info[&quot;nicks&quot;] = self.irc_nicknames
+
+        if self.expertise:
+            info[&quot;expertise&quot;] = self.expertise
+
+        return info
+
</ins><span class="cx"> class Committer(Contributor):
</span><del>-    def __init__(self, name, email_or_emails, irc_nickname=None):
-        Contributor.__init__(self, name, email_or_emails, irc_nickname)
</del><ins>+    def __init__(self, name, email_or_emails, irc_nickname=None, expertise=None):
+        Contributor.__init__(self, name, email_or_emails, irc_nickname, expertise)
</ins><span class="cx">         self.can_commit = True
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> class Reviewer(Committer):
</span><del>-    def __init__(self, name, email_or_emails, irc_nickname=None):
-        Committer.__init__(self, name, email_or_emails, irc_nickname)
</del><ins>+    def __init__(self, name, email_or_emails, irc_nickname=None, expertise=None):
+        Committer.__init__(self, name, email_or_emails, irc_nickname, expertise)
</ins><span class="cx">         self.can_review = True
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -132,17 +141,50 @@
</span><span class="cx">     def load_json():
</span><span class="cx">         filesystem = FileSystem()
</span><span class="cx">         json_path = filesystem.join(filesystem.dirname(filesystem.path_to_module('webkitpy.common.config')), 'contributors.json')
</span><del>-        contributors = json.loads(filesystem.read_text_file(json_path))
</del><ins>+        try:
+            contributors = json.loads(filesystem.read_text_file(json_path))
+        except ValueError, e:
+            sys.exit('contributors.json is malformed: ' + str(e))
</ins><span class="cx"> 
</span><span class="cx">         return {
</span><del>-            'Contributors': [Contributor(name, data.get('emails'), data.get('nicks')) for name, data in contributors['Contributors'].iteritems()],
-            'Committers': [Committer(name, data.get('emails'), data.get('nicks')) for name, data in contributors['Committers'].iteritems()],
-            'Reviewers': [Reviewer(name, data.get('emails'), data.get('nicks')) for name, data in contributors['Reviewers'].iteritems()],
</del><ins>+            'Contributors': [Contributor(name, data.get('emails'), data.get('nicks'), data.get('expertise')) for name, data in contributors['Contributors'].iteritems()],
+            'Committers':   [Committer(name, data.get('emails'), data.get('nicks'), data.get('expertise')) for name, data in contributors['Committers'].iteritems()],
+            'Reviewers':    [Reviewer(name, data.get('emails'), data.get('nicks'), data.get('expertise')) for name, data in contributors['Reviewers'].iteritems()],
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+    @staticmethod
+    def _contributor_list_to_dict(list):
+        committers_dict = {}
+        for contributor in sorted(list):
+            committers_dict[contributor.full_name] = contributor.__dict__()
+        return committers_dict
+
+    def as_json(self):
+        result = {
+            'Contributors': CommitterList._contributor_list_to_dict(self._exclusive_contributors()),
+            'Committers':   CommitterList._contributor_list_to_dict(self._exclusive_committers()),
+            'Reviewers':    CommitterList._contributor_list_to_dict(self._reviewers)
+        }
+        return json.dumps(result, sort_keys=True, indent=3, separators=(',', ' : '))
+
+    def reformat_in_place(self):
+        filesystem = FileSystem()
+        json_path = filesystem.join(filesystem.dirname(filesystem.path_to_module('webkitpy.common.config')), 'contributors.json')
+        filesystem.write_text_file(json_path, self.as_json())
+
+    # Contributors who are not in any other category.
+    def _exclusive_contributors(self):
+        return filter(lambda contributor: not (contributor.can_commit or contributor.can_review), self._contributors)
+
+    # Committers who are not reviewers.
+    def _exclusive_committers(self):
+        return filter(lambda contributor: contributor.can_commit and not contributor.can_review, self._committers)
+
+    # This is the superset of contributors + committers + reviewers
</ins><span class="cx">     def contributors(self):
</span><span class="cx">         return self._contributors
</span><span class="cx"> 
</span><ins>+    # This is the superset of committers + reviewers
</ins><span class="cx">     def committers(self):
</span><span class="cx">         return self._committers
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsScriptswebkitpycommonconfigcontributorsjson"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/webkitpy/common/config/contributors.json (206966 => 206967)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/webkitpy/common/config/contributors.json        2016-10-09 07:34:08 UTC (rev 206966)
+++ trunk/Tools/Scripts/webkitpy/common/config/contributors.json        2016-10-09 16:34:53 UTC (rev 206967)
</span><span class="lines">@@ -359,10 +359,10 @@
</span><span class="cx">             &quot;anilsson&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Babak Shafiei&quot;: {
-          &quot;emails&quot; : [
</del><ins>+      &quot;Babak Shafiei&quot; : {
+         &quot;emails&quot; : [
</ins><span class="cx">             &quot;bshafiei@apple.com&quot;
</span><del>-          ]
</del><ins>+         ]
</ins><span class="cx">       },
</span><span class="cx">       &quot;Balazs Kelemen&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="lines">@@ -376,13 +376,13 @@
</span><span class="cx">          ]
</span><span class="cx">       },
</span><span class="cx">       &quot;Basile Clement&quot; : {
</span><del>-        &quot;emails&quot; : [
</del><ins>+         &quot;emails&quot; : [
</ins><span class="cx">             &quot;basile_clement@apple.com&quot;,
</span><span class="cx">             &quot;cbasile06+webkit@gmail.com&quot;
</span><del>-        ],
-        &quot;nicks&quot; : [
</del><ins>+         ],
+         &quot;nicks&quot; : [
</ins><span class="cx">             &quot;elarnon&quot;
</span><del>-        ]
</del><ins>+         ]
</ins><span class="cx">       },
</span><span class="cx">       &quot;Bear Travis&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="lines">@@ -680,16 +680,6 @@
</span><span class="cx">             &quot;danakj&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;D\u00E1niel B\u00E1tyai&quot; : {
-         &quot;emails&quot; : [
-            &quot;dbatyai.u-szeged@partner.samsung.com&quot;,
-            &quot;dbatyai@inf.u-szeged.hu&quot;,
-            &quot;Batyai.Daniel@stud.u-szeged.hu&quot;
-         ],
-         &quot;nicks&quot; : [
-            &quot;dbatyai&quot;
-         ]
-      },
</del><span class="cx">       &quot;Daniel Cheng&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;dcheng@chromium.org&quot;
</span><span class="lines">@@ -896,6 +886,16 @@
</span><span class="cx">             &quot;atwilson&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;D\u00e1niel B\u00e1tyai&quot; : {
+         &quot;emails&quot; : [
+            &quot;dbatyai.u-szeged@partner.samsung.com&quot;,
+            &quot;dbatyai@inf.u-szeged.hu&quot;,
+            &quot;Batyai.Daniel@stud.u-szeged.hu&quot;
+         ],
+         &quot;nicks&quot; : [
+            &quot;dbatyai&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Eli Fidler&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;efidler@rim.com&quot;,
</span><span class="lines">@@ -914,7 +914,7 @@
</span><span class="cx">             &quot;epoger&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Enrique Oca\u00F1a Gonz\u00E1lez&quot; : {
</del><ins>+      &quot;Enrique Oca\u00f1a Gonz\u00e1lez&quot; : {
</ins><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;eocanha@igalia.com&quot;,
</span><span class="cx">             &quot;eocanha@gmail.com&quot;
</span><span class="lines">@@ -1016,7 +1016,7 @@
</span><span class="cx">             &quot;fmalita&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Frédéric Wang&quot; : {
</del><ins>+      &quot;Fr\u00e9d\u00e9ric Wang&quot; : {
</ins><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;fred.wang@free.fr&quot;,
</span><span class="cx">             &quot;fwang@igalia.com&quot;
</span><span class="lines">@@ -1271,6 +1271,18 @@
</span><span class="cx">             &quot;ike@apple.com&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;JF Bastien&quot; : {
+         &quot;emails&quot; : [
+            &quot;jfbastien@apple.com&quot;,
+            &quot;jfb@chromium.org&quot;
+         ],
+         &quot;expertise&quot; : &quot;JavaScript/ECMAScript&quot;,
+         &quot;nicks&quot; : [
+            &quot;jfb&quot;,
+            &quot;jfb_&quot;,
+            &quot;jfbastien&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Jacky Jiang&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;jkjiang@webkit.org&quot;,
</span><span class="lines">@@ -1283,22 +1295,22 @@
</span><span class="cx">             &quot;jkjiang&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Jaehun Lim&quot; : {
</del><ins>+      &quot;Jae Hyun Park&quot; : {
</ins><span class="cx">          &quot;emails&quot; : [
</span><del>-            &quot;ljaehun.lim@samsung.com&quot;
</del><ins>+            &quot;jaepark@webkit.org&quot;,
+            &quot;jae.park@company100.net&quot;
</ins><span class="cx">          ],
</span><del>-         &quot;expertise&quot; : &quot;The EFLWebKit port&quot;,
</del><span class="cx">          &quot;nicks&quot; : [
</span><del>-            &quot;jaehun&quot;
</del><ins>+            &quot;jaepark&quot;
</ins><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Jae Hyun Park&quot; : {
</del><ins>+      &quot;Jaehun Lim&quot; : {
</ins><span class="cx">          &quot;emails&quot; : [
</span><del>-            &quot;jaepark@webkit.org&quot;,
-            &quot;jae.park@company100.net&quot;
</del><ins>+            &quot;ljaehun.lim@samsung.com&quot;
</ins><span class="cx">          ],
</span><ins>+         &quot;expertise&quot; : &quot;The EFLWebKit port&quot;,
</ins><span class="cx">          &quot;nicks&quot; : [
</span><del>-            &quot;jaepark&quot;
</del><ins>+            &quot;jaehun&quot;
</ins><span class="cx">          ]
</span><span class="cx">       },
</span><span class="cx">       &quot;Jake Nielsen&quot; : {
</span><span class="lines">@@ -1472,18 +1484,6 @@
</span><span class="cx">             &quot;jeez_&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;JF Bastien&quot; : {
-         &quot;emails&quot; : [
-            &quot;jfbastien@apple.com&quot;,
-            &quot;jfb@chromium.org&quot;
-         ],
-         &quot;expertise&quot; : &quot;JavaScript/ECMAScript&quot;,
-         &quot;nicks&quot; : [
-             &quot;jfb&quot;,
-             &quot;jfb_&quot;,
-             &quot;jfbastien&quot;
-         ]
-      },
</del><span class="cx">       &quot;Jia Pu&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;jiapu.mail@gmail.com&quot;,
</span><span class="lines">@@ -1498,15 +1498,6 @@
</span><span class="cx">             &quot;Jiewen&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Jinyoung Hur&quot; : {
-         &quot;emails&quot; : [
-            &quot;hur.ims@navercorp.com&quot;
-         ],
-         &quot;expertise&quot; : &quot;The WinCairo Port, WebGL, Canvas, Accelerated Compositing&quot;,
-         &quot;nicks&quot; : [
-            &quot;jyhur&quot;
-         ]
-      },
</del><span class="cx">       &quot;Jinwoo Song&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;jinwoo7.song@samsung.com&quot;,
</span><span class="lines">@@ -1517,6 +1508,15 @@
</span><span class="cx">             &quot;jinwoo&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;Jinyoung Hur&quot; : {
+         &quot;emails&quot; : [
+            &quot;hur.ims@navercorp.com&quot;
+         ],
+         &quot;expertise&quot; : &quot;The WinCairo Port, WebGL, Canvas, Accelerated Compositing&quot;,
+         &quot;nicks&quot; : [
+            &quot;jyhur&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Joe Thomas&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;joethomas@motorola.com&quot;
</span><span class="lines">@@ -1696,6 +1696,15 @@
</span><span class="cx">             &quot;jschuh&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;Kalyan Kondapally&quot; : {
+         &quot;emails&quot; : [
+            &quot;kalyan.kondapally@intel.com&quot;,
+            &quot;kondapallykalyan@gmail.com&quot;
+         ],
+         &quot;nicks&quot; : [
+            &quot;kalyank&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Kangil Han&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;kangil.han@samsung.com&quot;,
</span><span class="lines">@@ -1715,15 +1724,6 @@
</span><span class="cx">             &quot;kareng&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Kalyan Kondapally&quot; : {
-         &quot;emails&quot; : [
-            &quot;kalyan.kondapally@intel.com&quot;,
-            &quot;kondapallykalyan@gmail.com&quot;
-         ],
-         &quot;nicks&quot; : [
-            &quot;kalyank&quot;
-         ]
-      },
</del><span class="cx">       &quot;Kaustubh Atrawalkar&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;kaustubh.ra@gmail.com&quot;,
</span><span class="lines">@@ -1733,11 +1733,6 @@
</span><span class="cx">             &quot;silverroots&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Keith Rollin&quot; : {
-         &quot;emails&quot; : [
-            &quot;krollin@apple.com&quot;
-         ]
-      },
</del><span class="cx">       &quot;Keishi Hattori&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;keishi@webkit.org&quot;
</span><span class="lines">@@ -1747,6 +1742,11 @@
</span><span class="cx">             &quot;keishi&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;Keith Rollin&quot; : {
+         &quot;emails&quot; : [
+            &quot;krollin@apple.com&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Kelly Norton&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;knorton@google.com&quot;,
</span><span class="lines">@@ -1889,15 +1889,6 @@
</span><span class="cx">             &quot;hyuki&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;L\u00E1szl\u00F3 Lang\u00F3&quot; : {
-         &quot;emails&quot; : [
-            &quot;llango.u-szeged@partner.samsung.com&quot;,
-            &quot;lango@inf.u-szeged.hu&quot;
-         ],
-         &quot;nicks&quot; : [
-            &quot;llango&quot;
-         ]
-      },
</del><span class="cx">       &quot;Laszlo Vidacs&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;lvidacs.u-szeged@partner.samsung.com&quot;,
</span><span class="lines">@@ -1980,6 +1971,15 @@
</span><span class="cx">             &quot;macpherson&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;L\u00e1szl\u00f3 Lang\u00f3&quot; : {
+         &quot;emails&quot; : [
+            &quot;llango.u-szeged@partner.samsung.com&quot;,
+            &quot;lango@inf.u-szeged.hu&quot;
+         ],
+         &quot;nicks&quot; : [
+            &quot;llango&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Mads Ager&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;ager@chromium.org&quot;
</span><span class="lines">@@ -2385,7 +2385,7 @@
</span><span class="cx">             &quot;galpeter@inf.u-szeged.hu&quot;,
</span><span class="cx">             &quot;pgal.u-szeged@partner.samsung.com&quot;
</span><span class="cx">          ],
</span><del>-         &quot;expertise&quot;: &quot;Python, CURL HTTP backend&quot;,
</del><ins>+         &quot;expertise&quot; : &quot;Python, CURL HTTP backend&quot;,
</ins><span class="cx">          &quot;nicks&quot; : [
</span><span class="cx">             &quot;elecro&quot;
</span><span class="cx">          ]
</span><span class="lines">@@ -2831,15 +2831,6 @@
</span><span class="cx">             &quot;tdanderson&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Thiago de Barros Lacerda&quot; : {
-         &quot;emails&quot; : [
-            &quot;thiago.lacerda@openbossa.org&quot;
-         ],
-         &quot;expertise&quot; : &quot;Nix port, WebRTC, MediaStream&quot;,
-         &quot;nicks&quot; : [
-            &quot;lacerda&quot;
-         ]
-      },
</del><span class="cx">       &quot;Thiago Marcos P. Santos&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;tmpsantos@gmail.com&quot;,
</span><span class="lines">@@ -2850,6 +2841,15 @@
</span><span class="cx">             &quot;tmpsantos&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;Thiago de Barros Lacerda&quot; : {
+         &quot;emails&quot; : [
+            &quot;thiago.lacerda@openbossa.org&quot;
+         ],
+         &quot;expertise&quot; : &quot;Nix port, WebRTC, MediaStream&quot;,
+         &quot;nicks&quot; : [
+            &quot;lacerda&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Thomas Sepez&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;tsepez@chromium.org&quot;
</span><span class="lines">@@ -3542,7 +3542,7 @@
</span><span class="cx">             &quot;plinss&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Philip J\u00E4genstedt&quot; : {
</del><ins>+      &quot;Philip J\u00e4genstedt&quot; : {
</ins><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;philipj@opera.com&quot;
</span><span class="cx">          ],
</span><span class="lines">@@ -3565,10 +3565,10 @@
</span><span class="cx">       },
</span><span class="cx">       &quot;Rebecca Hauck&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><del>-             &quot;rhauck@adobe.com&quot;
</del><ins>+            &quot;rhauck@adobe.com&quot;
</ins><span class="cx">          ],
</span><span class="cx">          &quot;nicks&quot; : [
</span><del>-             &quot;rhauck&quot;
</del><ins>+            &quot;rhauck&quot;
</ins><span class="cx">          ]
</span><span class="cx">       },
</span><span class="cx">       &quot;Ricky Mondello&quot; : {
</span><span class="lines">@@ -3635,11 +3635,6 @@
</span><span class="cx">             &quot;webcomponents-bugzilla@chromium.org&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;WebKitGTK+ Bugs&quot; : {
-         &quot;emails&quot; : [
-            &quot;bugs-noreply@webkitgtk.org&quot;
-         ]
-      },
</del><span class="cx">       &quot;WebKit Review Bot&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;webkit.review.bot@gmail.com&quot;
</span><span class="lines">@@ -3648,6 +3643,11 @@
</span><span class="cx">             &quot;sheriff-bot&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;WebKitGTK+ Bugs&quot; : {
+         &quot;emails&quot; : [
+            &quot;bugs-noreply@webkitgtk.org&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Wyatt Carss&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;wcarss@chromium.org&quot;,
</span><span class="lines">@@ -3864,6 +3864,15 @@
</span><span class="cx">             &quot;estes&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;Antoine Quint&quot; : {
+         &quot;emails&quot; : [
+            &quot;graouts@apple.com&quot;,
+            &quot;graouts@webkit.org&quot;
+         ],
+         &quot;nicks&quot; : [
+            &quot;graouts&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Antonio Gomes&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;tonikitoo@webkit.org&quot;,
</span><span class="lines">@@ -3876,15 +3885,6 @@
</span><span class="cx">             &quot;tonikitoo&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Antoine Quint&quot; : {
-         &quot;emails&quot; : [
-            &quot;graouts@apple.com&quot;,
-            &quot;graouts@webkit.org&quot;
-         ],
-         &quot;nicks&quot; : [
-            &quot;graouts&quot;
-         ]
-      },
</del><span class="cx">       &quot;Antti Koivisto&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;koivisto@iki.fi&quot;,
</span><span class="lines">@@ -4291,14 +4291,6 @@
</span><span class="cx">             &quot;ggaren&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Mark Lam&quot; : {
-         &quot;emails&quot; : [
-            &quot;mark.lam@apple.com&quot;
-         ],
-         &quot;nicks&quot; : [
-            &quot;mlam&quot;
-         ]
-      },
</del><span class="cx">       &quot;George Staikos&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;staikos@kde.org&quot;,
</span><span class="lines">@@ -4674,6 +4666,14 @@
</span><span class="cx">             &quot;mhahnenberg&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;Mark Lam&quot; : {
+         &quot;emails&quot; : [
+            &quot;mark.lam@apple.com&quot;
+         ],
+         &quot;nicks&quot; : [
+            &quot;mlam&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Mark Rowe&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;mrowe@bdash.net.nz&quot;,
</span><span class="lines">@@ -4899,6 +4899,15 @@
</span><span class="cx">             &quot;rniwa&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><ins>+      &quot;Saam Barati&quot; : {
+         &quot;emails&quot; : [
+            &quot;sbarati@apple.com&quot;,
+            &quot;saambarati1@gmail.com&quot;
+         ],
+         &quot;nicks&quot; : [
+            &quot;saamyjoon&quot;
+         ]
+      },
</ins><span class="cx">       &quot;Sam Weinig&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;sam@webkit.org&quot;,
</span><span class="lines">@@ -4909,15 +4918,6 @@
</span><span class="cx">             &quot;weinig&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Saam Barati&quot; : {
-         &quot;emails&quot; : [
-            &quot;sbarati@apple.com&quot;,
-            &quot;saambarati1@gmail.com&quot;
-         ],
-         &quot;nicks&quot; : [
-            &quot;saamyjoon&quot;
-         ]
-      },
</del><span class="cx">       &quot;Sergio Villar Senin&quot; : {
</span><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;svillar@igalia.com&quot;,
</span><span class="lines">@@ -5003,7 +5003,7 @@
</span><span class="cx">             &quot;sfalken&quot;
</span><span class="cx">          ]
</span><span class="cx">       },
</span><del>-      &quot;Sukolsak Sakshuwong&quot;: {
</del><ins>+      &quot;Sukolsak Sakshuwong&quot; : {
</ins><span class="cx">          &quot;emails&quot; : [
</span><span class="cx">             &quot;sukolsak@gmail.com&quot;,
</span><span class="cx">             &quot;ssakshuwong@apple.com&quot;
</span><span class="lines">@@ -5202,4 +5202,4 @@
</span><span class="cx">          ]
</span><span class="cx">       }
</span><span class="cx">    }
</span><del>-}
</del><ins>+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkToolsScriptswebkitpystylecheckerpy"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/webkitpy/style/checker.py (206966 => 206967)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/webkitpy/style/checker.py        2016-10-09 07:34:08 UTC (rev 206966)
+++ trunk/Tools/Scripts/webkitpy/style/checker.py        2016-10-09 16:34:53 UTC (rev 206967)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> 
</span><span class="cx"> from checkers.common import categories as CommonCategories
</span><span class="cx"> from checkers.common import CarriageReturnChecker
</span><ins>+from checkers.contributors import ContributorsChecker
</ins><span class="cx"> from checkers.changelog import ChangeLogChecker
</span><span class="cx"> from checkers.cpp import CppChecker
</span><span class="cx"> from checkers.cmake import CMakeChecker
</span><span class="lines">@@ -603,9 +604,12 @@
</span><span class="cx">                 checker = TextChecker(file_path, handle_style_error)
</span><span class="cx">         elif file_type == FileType.JSON:
</span><span class="cx">             basename = os.path.basename(file_path)
</span><del>-            if commit_queue and basename == 'contributors.json':
-                checker = JSONContributorsChecker(file_path, handle_style_error)
-            if basename == 'features.json':
</del><ins>+            if basename == 'contributors.json':
+                if commit_queue:
+                    checker = JSONContributorsChecker(file_path, handle_style_error)
+                else:
+                    checker = ContributorsChecker(file_path, handle_style_error)
+            elif basename == 'features.json':
</ins><span class="cx">                 checker = JSONFeaturesChecker(file_path, handle_style_error)
</span><span class="cx">             else:
</span><span class="cx">                 checker = JSONChecker(file_path, handle_style_error)
</span></span></pre></div>
<a id="trunkToolsScriptswebkitpystylecheckerscontributorspy"></a>
<div class="addfile"><h4>Added: trunk/Tools/Scripts/webkitpy/style/checkers/contributors.py (0 => 206967)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/webkitpy/style/checkers/contributors.py                                (rev 0)
+++ trunk/Tools/Scripts/webkitpy/style/checkers/contributors.py        2016-10-09 16:34:53 UTC (rev 206967)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+# Copyright (C) 2016 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+&quot;&quot;&quot;Checks WebKit style for the contributors.json file.&quot;&quot;&quot;
+
+import difflib
+import json
+import re
+from sets import Set
+from jsonchecker import JSONChecker
+from webkitpy.common.config.committers import CommitterList
+from webkitpy.common.system.filesystem import FileSystem
+
+
+class ContributorsChecker(JSONChecker):
+    &quot;&quot;&quot;Processes contributors.json lines&quot;&quot;&quot;
+
+    def __init__(self, file_path, handle_style_error):
+        super(ContributorsChecker, self).__init__(file_path, handle_style_error)
+        self._file_path = file_path
+
+    def check(self, lines):
+        super(ContributorsChecker, self).check(lines)
+        canonicalized = CommitterList().as_json()
+        actual = FileSystem().read_text_file(self._file_path)
+        diff = self._unidiff_output(actual, canonicalized)
+        if diff:
+            self._handle_style_error(0, 'json/syntax', 5, 'contributors.json differs from the canonical format. Use &quot;validate-committer-lists --canonicalize&quot; to reformat it.')
+            print diff
+
+    def _unidiff_output(self, expected, actual):
+        expected = expected.splitlines(1)
+        actual = actual.splitlines(1)
+        diff = difflib.unified_diff(expected, actual)
+        return ''.join(diff)
</ins></span></pre>
</div>
</div>

</body>
</html>