Modified: trunk/Tools/Scripts/validate-committer-lists (206966 => 206967)
--- 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)
@@ -215,19 +215,27 @@
def _print_three_column_row(widths, values):
print "%s%s%s" % (values[0].ljust(widths[0]), values[1].ljust(widths[1]), values[2])
- def print_possibly_expired_committers(self, committer_list):
+ def possibly_expired_committers(self, committer_list):
authors_and_last_commits = self._last_commit_by_author().items()
authors_and_last_commits.sort(lambda a,b: cmp(a[1], b[1]), reverse=True)
- committer_cuttof = date.today() - timedelta(days=365)
+ 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 > 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)
column_widths = [13, 25]
print
print "Committers who have not committed within one year:"
self._print_three_column_row(column_widths, ("Last Commit", "Committer Email", "Committer Record"))
- for (author, last_commit) in authors_and_last_commits:
+ for (author, last_commit) in retired_authors_and_last_commits:
+ committer_record = committer_list.committer_by_email(author)
last_commit_date = date.fromtimestamp(last_commit)
- if committer_cuttof > 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))
+ self._print_three_column_row(column_widths, (str(last_commit_date), author, committer_record))
def print_committers_missing_from_committer_list(self, committer_list):
missing_from_contributors_json = []
@@ -265,9 +273,22 @@
def main():
parser = OptionParser()
parser.add_option("-b", "--check-bugzilla-emails", action="" help="Check the bugzilla_email for each committer against bugs.webkit.org")
+ parser.add_option("-d", "--dump", action="" help="Dump the contributor list as JSON to stdout (suitable for saving to contributors.json)")
+ parser.add_option("-c", "--canonicalize", action="" help="Canonicalize contributors.json, rewriting it in-place")
+
(options, args) = parser.parse_args()
committer_list = CommitterList()
+ if options.dump:
+ print committer_list.as_json()
+ return 0;
+
+ if options.canonicalize:
+ print "Updating contributors.json in-place..."
+ committer_list.reformat_in_place()
+ print "Done"
+ return 0;
+
CommitterListFromMailingList().check_for_emails_missing_from_list(committer_list)
if not Git.in_working_directory("."):
@@ -277,6 +298,7 @@
- List of historical committers missing from contributors.json
"""
return 1
+
svn_committer_list = CommitterListFromGit()
svn_committer_list.print_possibly_expired_committers(committer_list)
svn_committer_list.print_committers_missing_from_committer_list(committer_list)
Modified: trunk/Tools/Scripts/webkitpy/common/config/committers.py (206966 => 206967)
--- 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)
@@ -31,17 +31,14 @@
import fnmatch
import json
+import sys
from webkitpy.common.editdistance import edit_distance
from webkitpy.common.memoized import memoized
from webkitpy.common.system.filesystem import FileSystem
-
-# The list of contributors have been moved to contributors.json
-
-
class Contributor(object):
- def __init__(self, name, email_or_emails, irc_nickname_or_nicknames=None):
+ def __init__(self, name, email_or_emails, irc_nickname_or_nicknames=None, expertise=None):
assert(name)
assert(email_or_emails)
self.full_name = name
@@ -49,11 +46,13 @@
self.emails = [email_or_emails]
else:
self.emails = email_or_emails
+ self._case_preserved_emails = self.emails
self.emails = map(lambda email: email.lower(), self.emails) # Emails are case-insensitive.
if isinstance(irc_nickname_or_nicknames, str):
self.irc_nicknames = [irc_nickname_or_nicknames]
else:
self.irc_nicknames = irc_nickname_or_nicknames
+ self.expertise = expertise
self.can_commit = False
self.can_review = False
@@ -93,16 +92,26 @@
return True
return False
+ def __dict__(self):
+ info = {"emails" : self._case_preserved_emails}
+ if self.irc_nicknames:
+ info["nicks"] = self.irc_nicknames
+
+ if self.expertise:
+ info["expertise"] = self.expertise
+
+ return info
+
class Committer(Contributor):
- def __init__(self, name, email_or_emails, irc_nickname=None):
- Contributor.__init__(self, name, email_or_emails, irc_nickname)
+ def __init__(self, name, email_or_emails, irc_nickname=None, expertise=None):
+ Contributor.__init__(self, name, email_or_emails, irc_nickname, expertise)
self.can_commit = True
class Reviewer(Committer):
- def __init__(self, name, email_or_emails, irc_nickname=None):
- Committer.__init__(self, name, email_or_emails, irc_nickname)
+ def __init__(self, name, email_or_emails, irc_nickname=None, expertise=None):
+ Committer.__init__(self, name, email_or_emails, irc_nickname, expertise)
self.can_review = True
@@ -132,17 +141,50 @@
def load_json():
filesystem = FileSystem()
json_path = filesystem.join(filesystem.dirname(filesystem.path_to_module('webkitpy.common.config')), 'contributors.json')
- contributors = json.loads(filesystem.read_text_file(json_path))
+ try:
+ contributors = json.loads(filesystem.read_text_file(json_path))
+ except ValueError, e:
+ sys.exit('contributors.json is malformed: ' + str(e))
return {
- '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()],
+ '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()],
}
+ @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
def contributors(self):
return self._contributors
+ # This is the superset of committers + reviewers
def committers(self):
return self._committers
Modified: trunk/Tools/Scripts/webkitpy/common/config/contributors.json (206966 => 206967)
--- 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)
@@ -359,10 +359,10 @@
"anilsson"
]
},
- "Babak Shafiei": {
- "emails" : [
+ "Babak Shafiei" : {
+ "emails" : [
"bshaf...@apple.com"
- ]
+ ]
},
"Balazs Kelemen" : {
"emails" : [
@@ -376,13 +376,13 @@
]
},
"Basile Clement" : {
- "emails" : [
+ "emails" : [
"basile_clem...@apple.com",
"cbasile06+web...@gmail.com"
- ],
- "nicks" : [
+ ],
+ "nicks" : [
"elarnon"
- ]
+ ]
},
"Bear Travis" : {
"emails" : [
@@ -680,16 +680,6 @@
"danakj"
]
},
- "D\u00E1niel B\u00E1tyai" : {
- "emails" : [
- "dbatyai.u-sze...@partner.samsung.com",
- "dbat...@inf.u-szeged.hu",
- "batyai.dan...@stud.u-szeged.hu"
- ],
- "nicks" : [
- "dbatyai"
- ]
- },
"Daniel Cheng" : {
"emails" : [
"dch...@chromium.org"
@@ -896,6 +886,16 @@
"atwilson"
]
},
+ "D\u00e1niel B\u00e1tyai" : {
+ "emails" : [
+ "dbatyai.u-sze...@partner.samsung.com",
+ "dbat...@inf.u-szeged.hu",
+ "batyai.dan...@stud.u-szeged.hu"
+ ],
+ "nicks" : [
+ "dbatyai"
+ ]
+ },
"Eli Fidler" : {
"emails" : [
"efid...@rim.com",
@@ -914,7 +914,7 @@
"epoger"
]
},
- "Enrique Oca\u00F1a Gonz\u00E1lez" : {
+ "Enrique Oca\u00f1a Gonz\u00e1lez" : {
"emails" : [
"eoca...@igalia.com",
"eoca...@gmail.com"
@@ -1016,7 +1016,7 @@
"fmalita"
]
},
- "Frédéric Wang" : {
+ "Fr\u00e9d\u00e9ric Wang" : {
"emails" : [
"fred.w...@free.fr",
"fw...@igalia.com"
@@ -1271,6 +1271,18 @@
"i...@apple.com"
]
},
+ "JF Bastien" : {
+ "emails" : [
+ "jfbast...@apple.com",
+ "j...@chromium.org"
+ ],
+ "expertise" : "_javascript_/ECMAScript",
+ "nicks" : [
+ "jfb",
+ "jfb_",
+ "jfbastien"
+ ]
+ },
"Jacky Jiang" : {
"emails" : [
"jkji...@webkit.org",
@@ -1283,22 +1295,22 @@
"jkjiang"
]
},
- "Jaehun Lim" : {
+ "Jae Hyun Park" : {
"emails" : [
- "ljaehun....@samsung.com"
+ "jaep...@webkit.org",
+ "jae.p...@company100.net"
],
- "expertise" : "The EFLWebKit port",
"nicks" : [
- "jaehun"
+ "jaepark"
]
},
- "Jae Hyun Park" : {
+ "Jaehun Lim" : {
"emails" : [
- "jaep...@webkit.org",
- "jae.p...@company100.net"
+ "ljaehun....@samsung.com"
],
+ "expertise" : "The EFLWebKit port",
"nicks" : [
- "jaepark"
+ "jaehun"
]
},
"Jake Nielsen" : {
@@ -1472,18 +1484,6 @@
"jeez_"
]
},
- "JF Bastien" : {
- "emails" : [
- "jfbast...@apple.com",
- "j...@chromium.org"
- ],
- "expertise" : "_javascript_/ECMAScript",
- "nicks" : [
- "jfb",
- "jfb_",
- "jfbastien"
- ]
- },
"Jia Pu" : {
"emails" : [
"jiapu.m...@gmail.com",
@@ -1498,15 +1498,6 @@
"Jiewen"
]
},
- "Jinyoung Hur" : {
- "emails" : [
- "hur....@navercorp.com"
- ],
- "expertise" : "The WinCairo Port, WebGL, Canvas, Accelerated Compositing",
- "nicks" : [
- "jyhur"
- ]
- },
"Jinwoo Song" : {
"emails" : [
"jinwoo7.s...@samsung.com",
@@ -1517,6 +1508,15 @@
"jinwoo"
]
},
+ "Jinyoung Hur" : {
+ "emails" : [
+ "hur....@navercorp.com"
+ ],
+ "expertise" : "The WinCairo Port, WebGL, Canvas, Accelerated Compositing",
+ "nicks" : [
+ "jyhur"
+ ]
+ },
"Joe Thomas" : {
"emails" : [
"joetho...@motorola.com"
@@ -1696,6 +1696,15 @@
"jschuh"
]
},
+ "Kalyan Kondapally" : {
+ "emails" : [
+ "kalyan.kondapa...@intel.com",
+ "kondapallykal...@gmail.com"
+ ],
+ "nicks" : [
+ "kalyank"
+ ]
+ },
"Kangil Han" : {
"emails" : [
"kangil....@samsung.com",
@@ -1715,15 +1724,6 @@
"kareng"
]
},
- "Kalyan Kondapally" : {
- "emails" : [
- "kalyan.kondapa...@intel.com",
- "kondapallykal...@gmail.com"
- ],
- "nicks" : [
- "kalyank"
- ]
- },
"Kaustubh Atrawalkar" : {
"emails" : [
"kaustubh...@gmail.com",
@@ -1733,11 +1733,6 @@
"silverroots"
]
},
- "Keith Rollin" : {
- "emails" : [
- "krol...@apple.com"
- ]
- },
"Keishi Hattori" : {
"emails" : [
"kei...@webkit.org"
@@ -1747,6 +1742,11 @@
"keishi"
]
},
+ "Keith Rollin" : {
+ "emails" : [
+ "krol...@apple.com"
+ ]
+ },
"Kelly Norton" : {
"emails" : [
"knor...@google.com",
@@ -1889,15 +1889,6 @@
"hyuki"
]
},
- "L\u00E1szl\u00F3 Lang\u00F3" : {
- "emails" : [
- "llango.u-sze...@partner.samsung.com",
- "la...@inf.u-szeged.hu"
- ],
- "nicks" : [
- "llango"
- ]
- },
"Laszlo Vidacs" : {
"emails" : [
"lvidacs.u-sze...@partner.samsung.com",
@@ -1980,6 +1971,15 @@
"macpherson"
]
},
+ "L\u00e1szl\u00f3 Lang\u00f3" : {
+ "emails" : [
+ "llango.u-sze...@partner.samsung.com",
+ "la...@inf.u-szeged.hu"
+ ],
+ "nicks" : [
+ "llango"
+ ]
+ },
"Mads Ager" : {
"emails" : [
"a...@chromium.org"
@@ -2385,7 +2385,7 @@
"galpe...@inf.u-szeged.hu",
"pgal.u-sze...@partner.samsung.com"
],
- "expertise": "Python, CURL HTTP backend",
+ "expertise" : "Python, CURL HTTP backend",
"nicks" : [
"elecro"
]
@@ -2831,15 +2831,6 @@
"tdanderson"
]
},
- "Thiago de Barros Lacerda" : {
- "emails" : [
- "thiago.lace...@openbossa.org"
- ],
- "expertise" : "Nix port, WebRTC, MediaStream",
- "nicks" : [
- "lacerda"
- ]
- },
"Thiago Marcos P. Santos" : {
"emails" : [
"tmpsan...@gmail.com",
@@ -2850,6 +2841,15 @@
"tmpsantos"
]
},
+ "Thiago de Barros Lacerda" : {
+ "emails" : [
+ "thiago.lace...@openbossa.org"
+ ],
+ "expertise" : "Nix port, WebRTC, MediaStream",
+ "nicks" : [
+ "lacerda"
+ ]
+ },
"Thomas Sepez" : {
"emails" : [
"tse...@chromium.org"
@@ -3542,7 +3542,7 @@
"plinss"
]
},
- "Philip J\u00E4genstedt" : {
+ "Philip J\u00e4genstedt" : {
"emails" : [
"phil...@opera.com"
],
@@ -3565,10 +3565,10 @@
},
"Rebecca Hauck" : {
"emails" : [
- "rha...@adobe.com"
+ "rha...@adobe.com"
],
"nicks" : [
- "rhauck"
+ "rhauck"
]
},
"Ricky Mondello" : {
@@ -3635,11 +3635,6 @@
"webcomponents-bugzi...@chromium.org"
]
},
- "WebKitGTK+ Bugs" : {
- "emails" : [
- "bugs-nore...@webkitgtk.org"
- ]
- },
"WebKit Review Bot" : {
"emails" : [
"webkit.review....@gmail.com"
@@ -3648,6 +3643,11 @@
"sheriff-bot"
]
},
+ "WebKitGTK+ Bugs" : {
+ "emails" : [
+ "bugs-nore...@webkitgtk.org"
+ ]
+ },
"Wyatt Carss" : {
"emails" : [
"wca...@chromium.org",
@@ -3864,6 +3864,15 @@
"estes"
]
},
+ "Antoine Quint" : {
+ "emails" : [
+ "grao...@apple.com",
+ "grao...@webkit.org"
+ ],
+ "nicks" : [
+ "graouts"
+ ]
+ },
"Antonio Gomes" : {
"emails" : [
"toniki...@webkit.org",
@@ -3876,15 +3885,6 @@
"tonikitoo"
]
},
- "Antoine Quint" : {
- "emails" : [
- "grao...@apple.com",
- "grao...@webkit.org"
- ],
- "nicks" : [
- "graouts"
- ]
- },
"Antti Koivisto" : {
"emails" : [
"koivi...@iki.fi",
@@ -4291,14 +4291,6 @@
"ggaren"
]
},
- "Mark Lam" : {
- "emails" : [
- "mark....@apple.com"
- ],
- "nicks" : [
- "mlam"
- ]
- },
"George Staikos" : {
"emails" : [
"stai...@kde.org",
@@ -4674,6 +4666,14 @@
"mhahnenberg"
]
},
+ "Mark Lam" : {
+ "emails" : [
+ "mark....@apple.com"
+ ],
+ "nicks" : [
+ "mlam"
+ ]
+ },
"Mark Rowe" : {
"emails" : [
"mr...@bdash.net.nz",
@@ -4899,6 +4899,15 @@
"rniwa"
]
},
+ "Saam Barati" : {
+ "emails" : [
+ "sbar...@apple.com",
+ "saambara...@gmail.com"
+ ],
+ "nicks" : [
+ "saamyjoon"
+ ]
+ },
"Sam Weinig" : {
"emails" : [
"s...@webkit.org",
@@ -4909,15 +4918,6 @@
"weinig"
]
},
- "Saam Barati" : {
- "emails" : [
- "sbar...@apple.com",
- "saambara...@gmail.com"
- ],
- "nicks" : [
- "saamyjoon"
- ]
- },
"Sergio Villar Senin" : {
"emails" : [
"svil...@igalia.com",
@@ -5003,7 +5003,7 @@
"sfalken"
]
},
- "Sukolsak Sakshuwong": {
+ "Sukolsak Sakshuwong" : {
"emails" : [
"sukol...@gmail.com",
"ssakshuw...@apple.com"
@@ -5202,4 +5202,4 @@
]
}
}
-}
+}
\ No newline at end of file
Added: trunk/Tools/Scripts/webkitpy/style/checkers/contributors.py (0 => 206967)
--- 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)
@@ -0,0 +1,54 @@
+# 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.
+
+"""Checks WebKit style for the contributors.json file."""
+
+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):
+ """Processes contributors.json lines"""
+
+ 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 "validate-committer-lists --canonicalize" 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)