Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: third_party/WebKit/Tools/Scripts/validate-committer-lists

Issue 1455883005: Remove WebKit's validate-committer-lists script. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
3 # Copyright (c) 2009, Google Inc. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #
31 # Checks Python's known list of committers against lists.webkit.org and SVN hist ory.
32
33
34 import os
35 import subprocess
36 import re
37 import urllib2
38 from datetime import date, datetime, timedelta
39 from optparse import OptionParser
40
41 from webkitpy.common.config.committers import CommitterList
42 from webkitpy.common.system.deprecated_logging import log, error
Nico 2015/11/19 05:47:31 (none of these modules exist any more, so if I try
43 from webkitpy.common.checkout.scm import Git
44 from webkitpy.common.net.bugzilla import Bugzilla
45
46 # WebKit includes a built copy of BeautifulSoup in Scripts/webkitpy
47 # so this import should always succeed.
48 from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup
49
50
51 def print_list_if_non_empty(title, list_to_print):
52 if not list_to_print:
53 return
54 print # Newline before the list
55 print title
56 for item in list_to_print:
57 print item
58
59
60 class CommitterListFromMailingList(object):
61 committers_list_url = "http://lists.webkit.org/mailman/roster.cgi/webkit-com mitters"
62 reviewers_list_url = "http://lists.webkit.org/mailman/roster.cgi/webkit-revi ewers"
63
64 def _fetch_emails_from_page(self, url):
65 page = urllib2.urlopen(url)
66 soup = BeautifulSoup(page)
67
68 emails = []
69 # Grab the cells in the first column (which happens to be the bug ids).
70 for email_item in soup('li'):
71 email_link = email_item.find("a")
72 email = email_link.string.replace(" at ", "@") # The email is obfusc ated using " at " instead of "@".
73 emails.append(email)
74 return emails
75
76 @staticmethod
77 def _commiters_not_found_in_email_list(committers, emails):
78 missing_from_mailing_list = []
79 for committer in committers:
80 for email in committer.emails:
81 if email in emails:
82 break
83 else:
84 missing_from_mailing_list.append(committer)
85 return missing_from_mailing_list
86
87 @staticmethod
88 def _emails_not_found_in_committer_list(committers, emails):
89 email_to_committer_map = {}
90 for committer in committers:
91 for email in committer.emails:
92 email_to_committer_map[email] = committer
93
94 return filter(lambda email: not email_to_committer_map.get(email), email s)
95
96 def check_for_emails_missing_from_list(self, committer_list):
97 committer_emails = self._fetch_emails_from_page(self.committers_list_url )
98 list_name = "webkit-committers@lists.webkit.org"
99
100 missing_from_mailing_list = self._commiters_not_found_in_email_list(comm itter_list.committers(), committer_emails)
101 print_list_if_non_empty("Committers missing from %s:" % list_name, missi ng_from_mailing_list)
102
103 users_missing_from_committers = self._emails_not_found_in_committer_list (committer_list.committers(), committer_emails)
104 print_list_if_non_empty("Subcribers to %s missing from committer.py:" % list_name, users_missing_from_committers)
105
106
107 reviewer_emails = self._fetch_emails_from_page(self.reviewers_list_url)
108 list_name = "webkit-reviewers@lists.webkit.org"
109
110 missing_from_mailing_list = self._commiters_not_found_in_email_list(comm itter_list.reviewers(), reviewer_emails)
111 print_list_if_non_empty("Reviewers missing from %s:" % list_name, missin g_from_mailing_list)
112
113 missing_from_reviewers = self._emails_not_found_in_committer_list(commit ter_list.reviewers(), reviewer_emails)
114 print_list_if_non_empty("Subcribers to %s missing from reviewers in comm itter.py:" % list_name, missing_from_reviewers)
115
116 missing_from_committers = self._emails_not_found_in_committer_list(commi tter_list.committers(), reviewer_emails)
117 print_list_if_non_empty("Subcribers to %s completely missing from commit ters.py" % list_name, missing_from_committers)
118
119
120 class CommitterListFromGit(object):
121 login_to_email_address = {
122 'aliceli1' : 'alice.liu@apple.com',
123 'bdash' : 'mrowe@apple.com',
124 'bdibello' : 'bdibello@apple.com', # Bruce DiBello, only 4 commits: r100 23, r9548, r9538, r9535
125 'cblu' : 'cblu@apple.com',
126 'cpeterse' : 'cpetersen@apple.com',
127 'eseidel' : 'eric@webkit.org',
128 'gdennis' : 'gdennis@webkit.org',
129 'goldsmit' : 'goldsmit@apple.com', # Debbie Goldsmith, only one commit r 8839
130 'gramps' : 'gramps@apple.com',
131 'honeycutt' : 'jhoneycutt@apple.com',
132 'jdevalk' : 'joost@webkit.org',
133 'jens' : 'jens@apple.com',
134 'justing' : 'justin.garcia@apple.com',
135 'kali' : 'kali@apple.com', # Christy Warren, did BIDI work, 5 commits: r 8815, r8802, r8801, r8791, r8773, r8603
136 'kjk' : 'kkowalczyk@gmail.com',
137 'kmccullo' : 'kmccullough@apple.com',
138 'kocienda' : 'kocienda@apple.com',
139 'lamadio' : 'lamadio@apple.com', # Lou Amadio, only 2 commits: r17949 an d r17783
140 'lars' : 'lars@kde.org',
141 'lweintraub' : 'lweintraub@apple.com',
142 'lypanov' : 'lypanov@kde.org',
143 'mhay' : 'mhay@apple.com', # Mike Hay, 3 commits: r3813, r2552, r2548
144 'ouch' : 'ouch@apple.com', # John Louch
145 'pyeh' : 'patti@apple.com', # Patti Yeh, did VoiceOver work in WebKit
146 'rjw' : 'rjw@apple.com',
147 'seangies' : 'seangies@apple.com', # Sean Gies?, only 5 commits: r16600, r16592, r16511, r16489, r16484
148 'sheridan' : 'sheridan@apple.com', # Shelly Sheridan
149 'thatcher' : 'timothy@apple.com',
150 'tomernic' : 'timo@apple.com',
151 'trey' : 'trey@usa.net',
152 'tristan' : 'tristan@apple.com',
153 'vicki' : 'vicki@apple.com',
154 'voas' : 'voas@apple.com', # Ed Voas, did some Carbon work in WebKit
155 'zack' : 'zack@kde.org',
156 'zimmermann' : 'zimmermann@webkit.org',
157 }
158
159 def __init__(self):
160 self._last_commit_time_by_author_cache = {}
161
162 def _fetch_authors_and_last_commit_time_from_git_log(self):
163 last_commit_dates = {}
164 git_log_args = ['git', 'log', '--reverse', '--pretty=format:%ae %at']
165 process = subprocess.Popen(git_log_args, stdout=subprocess.PIPE)
166
167 # eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc 1257090899
168 line_regexp = re.compile("^(?P<author>.+)@\S+ (?P<timestamp>\d+)$")
169 while True:
170 output_line = process.stdout.readline()
171 if output_line == '' and process.poll() != None:
172 return last_commit_dates
173
174 match_result = line_regexp.match(output_line)
175 if not match_result:
176 error("Failed to match line: %s" % output_line)
177 last_commit_dates[match_result.group('author')] = float(match_result .group('timestamp'))
178
179 def _fill_in_emails_for_old_logins(self):
180 authors_missing_email = filter(lambda author: author.find('@') == -1, se lf._last_commit_time_by_author_cache)
181 authors_with_email = filter(lambda author: author.find('@') != -1, self. _last_commit_time_by_author_cache)
182 prefixes_of_authors_with_email = map(lambda author: author.split('@')[0] , authors_with_email)
183
184 for author in authors_missing_email:
185 # First check to see if we have a manual mapping from login to email .
186 author_email = self.login_to_email_address.get(author)
187
188 # Most old logins like 'darin' are now just 'darin@apple.com', so ch eck for a prefix match if a manual mapping was not found.
189 if not author_email and author in prefixes_of_authors_with_email:
190 author_email_index = prefixes_of_authors_with_email.index(author )
191 author_email = authors_with_email[author_email_index]
192
193 if not author_email:
194 # No known email mapping, likely not an active committer. We co uld log here.
195 continue
196
197 # log("%s -> %s" % (author, author_email)) # For sanity checking.
198 no_email_commit_time = self._last_commit_time_by_author_cache.get(au thor)
199 email_commit_time = self._last_commit_time_by_author_cache.get(autho r_email)
200 # We compare the timestamps for extra sanity even though we could as sume commits before email address were used for login are always going to be old er.
201 if not email_commit_time or email_commit_time < no_email_commit_time :
202 self._last_commit_time_by_author_cache[author_email] = no_email_ commit_time
203 del self._last_commit_time_by_author_cache[author]
204
205 def _last_commit_by_author(self):
206 if not self._last_commit_time_by_author_cache:
207 self._last_commit_time_by_author_cache = self._fetch_authors_and_las t_commit_time_from_git_log()
208 self._fill_in_emails_for_old_logins()
209 del self._last_commit_time_by_author_cache['(no author)'] # The init ial svn import isn't very useful.
210 return self._last_commit_time_by_author_cache
211
212 @staticmethod
213 def _print_three_column_row(widths, values):
214 print "%s%s%s" % (values[0].ljust(widths[0]), values[1].ljust(widths[1]) , values[2])
215
216 def print_possibly_expired_committers(self, committer_list):
217 authors_and_last_commits = self._last_commit_by_author().items()
218 authors_and_last_commits.sort(lambda a,b: cmp(a[1], b[1]), reverse=True)
219 committer_cuttof = date.today() - timedelta(days=365)
220 column_widths = [13, 25]
221 print
222 print "Committers who have not committed within one year:"
223 self._print_three_column_row(column_widths, ("Last Commit", "Committer E mail", "Committer Record"))
224 for (author, last_commit) in authors_and_last_commits:
225 last_commit_date = date.fromtimestamp(last_commit)
226 if committer_cuttof > last_commit_date:
227 committer_record = committer_list.committer_by_email(author)
228 self._print_three_column_row(column_widths, (str(last_commit_dat e), author, committer_record))
229
230 def print_committers_missing_from_committer_list(self, committer_list):
231 missing_from_committers_py = []
232 last_commit_time_by_author = self._last_commit_by_author()
233 for author in last_commit_time_by_author:
234 if not committer_list.committer_by_email(author):
235 missing_from_committers_py.append(author)
236
237 never_committed = []
238 for committer in committer_list.committers():
239 for email in committer.emails:
240 if last_commit_time_by_author.get(email):
241 break
242 else:
243 never_committed.append(committer)
244
245 print_list_if_non_empty("Historical committers missing from committer.py :", missing_from_committers_py)
246 print_list_if_non_empty("Committers in committer.py who have never commi tted:", never_committed)
247
248
249 class CommitterListBugzillaChecker(object):
250 def __init__(self):
251 self._bugzilla = Bugzilla()
252
253 def _has_invalid_bugzilla_email(self, committer):
254 return not self._bugzilla.queries.fetch_logins_matching_substring(commit ter.bugzilla_email())
255
256 def print_committers_with_invalid_bugzilla_emails(self, committer_list):
257 print # Print a newline before we start hitting bugzilla (it logs about logging in).
258 print "Checking committer emails against bugzilla (this will take a long time)"
259 committers_with_invalid_bugzilla_email = filter(self._has_invalid_bugzil la_email, committer_list.committers())
260 print_list_if_non_empty("Committers with invalid bugzilla email:", commi tters_with_invalid_bugzilla_email)
261
262
263 def main():
264 parser = OptionParser()
265 parser.add_option("-b", "--check-bugzilla-emails", action="store_true", help ="Check the bugzilla_email for each committer against bugs.webkit.org")
266 (options, args) = parser.parse_args()
267
268 committer_list = CommitterList()
269 CommitterListFromMailingList().check_for_emails_missing_from_list(committer_ list)
270
271 if not Git.in_working_directory("."):
272 print """\n\nWARNING: validate-committer-lists requires a git checkout.
273 The following checks are disabled:
274 - List of committers ordered by last commit
275 - List of historical committers missing from committers.py
276 """
277 return 1
278 svn_committer_list = CommitterListFromGit()
279 svn_committer_list.print_possibly_expired_committers(committer_list)
280 svn_committer_list.print_committers_missing_from_committer_list(committer_li st)
281
282 if options.check_bugzilla_emails:
283 CommitterListBugzillaChecker().print_committers_with_invalid_bugzilla_em ails(committer_list)
284
285
286 if __name__ == "__main__":
287 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698