summaryrefslogtreecommitdiffstats
path: root/Tools/Scripts/webkitpy/common/config/committers.py
blob: 04ae256d2a78908ba3aaa70f137f933690df0985 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
# Copyright (c) 2011, Apple Inc. All rights reserved.
# Copyright (c) 2009, 2011, 2012 Google 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:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * 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.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
# OWNER OR 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.
#
# WebKit's Python module for committer and reviewer validation.

from webkitpy.common.editdistance import edit_distance

class Account(object):
    def __init__(self, name, email_or_emails, irc_nickname_or_nicknames=None):
        assert(name)
        assert(email_or_emails)
        self.full_name = name
        if isinstance(email_or_emails, str):
            self.emails = [email_or_emails]
        else:
            self.emails = email_or_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.can_commit = False
        self.can_review = False

    def bugzilla_email(self):
        # FIXME: We're assuming the first email is a valid bugzilla email,
        # which might not be right.
        return self.emails[0]

    def __str__(self):
        return '"%s" <%s>' % (self.full_name, self.emails[0])

    def contains_string(self, search_string):
        string = search_string.lower()
        if string in self.full_name.lower():
            return True
        if self.irc_nicknames:
            for nickname in self.irc_nicknames:
                if string in nickname.lower():
                    return True
        for email in self.emails:
            if string in email:
                return True
        return False


class Contributor(Account):
    def __init__(self, name, email_or_emails, irc_nickname=None):
        Account.__init__(self, name, email_or_emails, irc_nickname)
        self.is_contributor = True


class Committer(Contributor):
    def __init__(self, name, email_or_emails, irc_nickname=None):
        Contributor.__init__(self, name, email_or_emails, irc_nickname)
        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)
        self.can_review = True


# This is a list of email addresses that have bugzilla accounts but are not
# used for contributing (such as mailing lists).


watchers_who_are_not_contributors = [
    Account("Chromium Compositor Bugs", ["cc-bugs@google.com"], ""),
    Account("Chromium Media Reviews", ["feature-media-reviews@chromium.org"], ""),
    Account("David Levin", ["levin+threading@chromium.org"], ""),
    Account("David Levin", ["levin+watchlist@chromium.org"], ""),
    Account("Kent Tamura", ["tkent+wkapi@chromium.org"], ""),
]


# This is a list of people (or bots) who are neither committers nor reviewers, but get
# frequently CC'ed by others on Bugzilla bugs, so their names should be
# supported by autocomplete. No review needed to add to the list.


contributors_who_are_not_committers = [
    Contributor("Adam Kallai", "kadam@inf.u-szeged.hu", 'kadam'),
    Contributor("Aharon Lanin", "aharon@google.com"),
    Contributor("Alan Stearns", "stearns@adobe.com", 'astearns'),
    Contributor("Alec Flett", ["alecflett@chromium.org", "alecflett@google.com"], "alecf"),
    Contributor("Alexandre Elias", "aelias@chromium.org"),
    Contributor("Alexey Marinichev", ["amarinichev@chromium.org", "amarinichev@google.com"], "amarinichev"),
    Contributor("Allan Sandfeld Jensen", ["allan.jensen@nokia.com", "kde@carewolf.com", "sandfeld@kde.org"], "carewolf"),
    Contributor("Andras Piroska", "pandras@inf.u-szeged.hu", "andris88"),
    Contributor("Anne van Kesteren", "annevankesteren+webkit@gmail.com", "annevk"),
    Contributor("Annie Sullivan", "sullivan@chromium.org", "annie"),
    Contributor("Aryeh Gregor", "ayg@aryeh.name", "AryehGregor"),
    Contributor("Balazs Ankes", "bank@inf.u-szeged.hu", 'abalazs'),
    Contributor("Brian Salomon", "bsalomon@google.com"),
    Contributor("Commit Queue", "commit-queue@webkit.org"),
    Contributor("Daniel Sievers", "sievers@chromium.org"),
    Contributor("Dave Tharp", "dtharp@codeaurora.org", "dtharp"),
    Contributor("David Barr", "davidbarr@chromium.org", "barrbrain"),
    Contributor("David Dorwin", "ddorwin@chromium.org", "ddorwin"),
    Contributor("David Reveman", "reveman@chromium.org", "reveman"),
    Contributor("Douglas Davidson", "ddavidso@apple.com"),
    Contributor("Edward O'Connor", "eoconnor@apple.com", "hober"),
    Contributor("Eric Penner", "epenner@chromium.org", "epenner"),
    Contributor("Felician Marton", ["felician@inf.u-szeged.hu", "marton.felician.zoltan@stud.u-szeged.hu"], "Felician"),
    Contributor("Finnur Thorarinsson", ["finnur@chromium.org", "finnur.webkit@gmail.com"], "finnur"),
    Contributor("Grace Kloba", "klobag@chromium.org", "klobag"),
    Contributor("Greg Simon", "gregsimon@chromium.org", "gregsimon"),
    Contributor("Gregg Tavares", ["gman@google.com", "gman@chromium.org"], "gman"),
    Contributor("Hao Zheng", "zhenghao@chromium.org"),
    Contributor("Ian Hickson", "ian@hixie.ch", "hixie"),
    Contributor("Ian Vollick", "vollick@chromium.org", "vollick"),
    Contributor("Janos Badics", "jbadics@inf.u-szeged.hu", 'dicska'),
    Contributor("Jing Zhao", "jingzhao@chromium.org"),
    Contributor("John Bates", ["jbates@google.com", "jbates@chromium.org"], "jbates"),
    Contributor("John Bauman", ["jbauman@chromium.org", "jbauman@google.com"], "jbauman"),
    Contributor("John Grabowski", "jrg@chromium.org"),
    Contributor("John Mellor", "johnme@chromium.org"),
    Contributor("Kulanthaivel Palanichamy", "kulanthaivel@codeaurora.org", "kvel"),
    Contributor(u"Michael Br\u00fcning", "michael.bruning@nokia.com", "mibrunin"),
    Contributor("Min Qin", "qinmin@chromium.org"),
    Contributor("Nandor Huszka", "hnandor@inf.u-szeged.hu", "hnandor"),
    Contributor("Oliver Varga", ["voliver@inf.u-szeged.hu", "Varga.Oliver@stud.u-szeged.hu"], "TwistO"),
    Contributor("Peter Gal", "galpeter@inf.u-szeged.hu", "elecro"),
    Contributor("Peter Linss", "peter.linss@hp.com", "plinss"),
    Contributor("Radar WebKit Bug Importer", "webkit-bug-importer@group.apple.com"),
    Contributor("Roland Takacs", "rtakacs@inf.u-szeged.hu", "rtakacs"),
    Contributor("Szilard Ledan-Muntean", "szledan@inf.u-szeged.hu", "szledan"),
    Contributor("Tab Atkins", ["tabatkins@google.com", "jackalmage@gmail.com"], "tabatkins"),
    Contributor("Tamas Czene", ["tczene@inf.u-szeged.hu", "Czene.Tamas@stud.u-szeged.hu"], "tczene"),
    Contributor("Terry Anderson", "tdanderson@chromium.org", "tdanderson"),
    Contributor("Tien-Ren Chen", "trchen@chromium.org"),
    Contributor("Tom Hudson", "tomhudson@google.com"),
    Contributor("WebKit Review Bot", "webkit.review.bot@gmail.com", "sheriff-bot"),
    Contributor("Wyatt Carss", ["wcarss@chromium.org", "wcarss@google.com"], "wcarss"),
    Contributor("Zoltan Arvai", "zarvai@inf.u-szeged.hu", "azbest_hu"),
    Contributor("Zsolt Feher", "feherzs@inf.u-szeged.hu", "Smith"),
]


# This is intended as a canonical, machine-readable list of all non-reviewer
# committers for WebKit.  If your name is missing here and you are a committer,
# please add it.  No review needed.  All reviewers are committers, so this list
# is only of committers who are not reviewers.


committers_unable_to_review = [
    Committer("Aaron Boodman", "aa@chromium.org", "aboodman"),
    Committer("Adam Bergkvist", "adam.bergkvist@ericsson.com", "adambe"),
    Committer("Adam Klein", "adamk@chromium.org", "aklein"),
    Committer("Adam Langley", "agl@chromium.org", "agl"),
    Committer("Ademar de Souza Reis Jr", ["ademar.reis@gmail.com", "ademar@webkit.org"], "ademar"),
    Committer("Albert J. Wong", "ajwong@chromium.org"),
    Committer(u"Alexander F\u00e6r\u00f8y", ["ahf@0x90.dk", "alexander.faeroy@nokia.com"], "ahf"),
    Committer("Alexander Kellett", ["lypanov@mac.com", "a-lists001@lypanov.net", "lypanov@kde.org"], "lypanov"),
    Committer("Alexander Pavlov", "apavlov@chromium.org", "apavlov"),
    Committer("Alexandru Chiculita", "achicu@adobe.com", "achicu"),
    Committer("Alice Boxhall", "aboxhall@chromium.org", "aboxhall"),
    Committer("Alok Priyadarshi", "alokp@chromium.org", "alokp"),
    Committer("Ami Fischman", ["fischman@chromium.org", "fischman@google.com"], "fischman"),
    Committer("Amruth Raj", "amruthraj@motorola.com", "amruthraj"),
    Committer("Andre Boule", "aboule@apple.com"),
    Committer("Andrei Popescu", "andreip@google.com", "andreip"),
    Committer("Andrew Wellington", ["andrew@webkit.org", "proton@wiretapped.net"], "proton"),
    Committer("Andrew Scherkus", "scherkus@chromium.org", "scherkus"),
    Committer("Andrey Kosyakov", "caseq@chromium.org", "caseq"),
    Committer("Andras Becsi", ["abecsi@webkit.org", "andras.becsi@nokia.com"], "bbandix"),
    Committer("Andy Wingo", "wingo@igalia.com", "wingo"),
    Committer("Anna Cavender", "annacc@chromium.org", "annacc"),
    Committer("Anthony Ricaud", "rik@webkit.org", "rik"),
    Committer("Antoine Labour", "piman@chromium.org", "piman"),
    Committer("Anton D'Auria", "adauria@apple.com", "antonlefou"),
    Committer("Anton Muhin", "antonm@chromium.org", "antonm"),
    Committer("Arko Saha", "arko@motorola.com", "arkos"),
    Committer("Balazs Kelemen", "kbalazs@webkit.org", "kbalazs"),
    Committer("Ben Murdoch", "benm@google.com", "benm"),
    Committer("Ben Wells", "benwells@chromium.org", "benwells"),
    Committer("Benjamin C Meyer", ["ben@meyerhome.net", "ben@webkit.org", "bmeyer@rim.com"], "icefox"),
    Committer("Benjamin Kalman", ["kalman@chromium.org", "kalman@google.com"], "kalman"),
    Committer("Benjamin Otte", ["otte@gnome.org", "otte@webkit.org"], "otte"),
    Committer("Brett Wilson", "brettw@chromium.org", "brettx"),
    Committer("Caio Marcelo de Oliveira Filho", ["cmarcelo@webkit.org", "caio.oliveira@openbossa.org"], "cmarcelo"),
    Committer("Cameron McCormack", ["cam@mcc.id.au", "cam@webkit.org"], "heycam"),
    Committer("Carol Szabo", ["carol@webkit.org", "carol.szabo@nokia.com"], "cszabo1"),
    Committer("Cary Clark", ["caryclark@google.com", "caryclark@chromium.org"], "caryclark"),
    Committer("Charles Reis", "creis@chromium.org", "creis"),
    Committer("Charles Wei", ["charles.wei@torchmobile.com.cn"], "cswei"),
    Committer("Chris Evans", ["cevans@google.com", "cevans@chromium.org"]),
    Committer("Chris Guillory", ["ctguil@chromium.org", "chris.guillory@google.com"], "ctguil"),
    Committer("Chris Petersen", "cpetersen@apple.com", "cpetersen"),
    Committer("Christian Dywan", ["christian@twotoasts.de", "christian@webkit.org", "christian@lanedo.com"]),
    Committer("Collin Jackson", "collinj@webkit.org", "collinjackson"),
    Committer("Cris Neckar", "cdn@chromium.org", "cneckar"),
    Committer("Dan Winship", "danw@gnome.org", "danw"),
    Committer("Dana Jansens", "danakj@chromium.org", "danakj"),
    Committer("Daniel Cheng", "dcheng@chromium.org", "dcheng"),
    Committer("Dave Barton", "dbarton@mathscribe.com", "dbarton"),
    Committer("David Grogan", ["dgrogan@chromium.org", "dgrogan@google.com"], "dgrogan"),
    Committer("David Smith", ["catfish.man@gmail.com", "dsmith@webkit.org"], "catfishman"),
    Committer("Diego Gonzalez", ["diegohcg@webkit.org", "diego.gonzalez@openbossa.org"], "diegohcg"),
    Committer("Dmitry Lomov", ["dslomov@google.com", "dslomov@chromium.org"], "dslomov"),
    Committer("Dominic Cooney", ["dominicc@chromium.org", "dominicc@google.com"], "dominicc"),
    Committer("Dominic Mazzoni", ["dmazzoni@google.com", "dmazzoni@chromium.org"], "dmazzoni"),
    Committer("Drew Wilson", "atwilson@chromium.org", "atwilson"),
    Committer("Eli Fidler", ["eli@staikos.net", "efidler@rim.com"], "efidler"),
    Committer("Elliot Poger", "epoger@chromium.org", "epoger"),
    Committer("Emil A Eklund", "eae@chromium.org", "eae"),
    Committer("Erik Arvidsson", "arv@chromium.org", "arv"),
    Committer("Eric Roman", "eroman@chromium.org", "eroman"),
    Committer("Eric Uhrhane", "ericu@chromium.org", "ericu"),
    Committer("Evan Martin", "evan@chromium.org", "evmar"),
    Committer("Evan Stade", "estade@chromium.org", "estade"),
    Committer("Fady Samuel", "fsamuel@chromium.org", "fsamuel"),
    Committer("Feng Qian", "feng@chromium.org"),
    Committer("Florin Malita", ["fmalita@chromium.org", "fmalita@google.com"], "fmalita"),
    Committer("Fumitoshi Ukai", "ukai@chromium.org", "ukai"),
    Committer("Gabor Loki", "loki@webkit.org", "loki04"),
    Committer("Gabor Rapcsanyi", ["rgabor@webkit.org", "rgabor@inf.u-szeged.hu"], "rgabor"),
    Committer("Gavin Peters", ["gavinp@chromium.org", "gavinp@webkit.org", "gavinp@google.com"], "gavinp"),
    Committer("Girish Ramakrishnan", ["girish@forwardbias.in", "ramakrishnan.girish@gmail.com"], "girishr"),
    Committer("Graham Dennis", ["Graham.Dennis@gmail.com", "gdennis@webkit.org"]),
    Committer("Greg Bolsinga", "bolsinga@apple.com"),
    Committer("Grzegorz Czajkowski", "g.czajkowski@samsung.com", "grzegorz"),
    Committer("Gyuyoung Kim", ["gyuyoung.kim@samsung.com", "gyuyoung.kim@webkit.org"], "gyuyoung"),
    Committer("Hans Wennborg", "hans@chromium.org", "hwennborg"),
    Committer("Hayato Ito", "hayato@chromium.org", "hayato"),
    Committer("Hironori Bono", "hbono@chromium.org", "hbono"),
    Committer("Helder Correia", "helder@sencha.com", "helder"),
    Committer("Hin-Chung Lam", ["hclam@google.com", "hclam@chromium.org"]),
    Committer("Igor Trindade Oliveira", ["igor.oliveira@webkit.org", "igor.o@sisa.samsung.com"], "igoroliveira"),
    Committer("Ilya Sherman", "isherman@chromium.org", "isherman"),
    Committer("Ilya Tikhonovsky", "loislo@chromium.org", "loislo"),
    Committer("Ivan Krsti\u0107", "ike@apple.com"),
    Committer("Jakob Petsovits", ["jpetsovits@rim.com", "jpetso@gmx.at"], "jpetso"),
    Committer("Jakub Wieczorek", "jwieczorek@webkit.org", "fawek"),
    Committer("James Hawkins", ["jhawkins@chromium.org", "jhawkins@google.com"], "jhawkins"),
    Committer("James Kozianski", ["koz@chromium.org", "koz@google.com"], "koz"),
    Committer("James Simonsen", "simonjam@chromium.org", "simonjam"),
    Committer("Jarred Nicholls", ["jarred@webkit.org", "jarred@sencha.com"], "jarrednicholls"),
    Committer("Jay Civelli", "jcivelli@chromium.org", "jcivelli"),
    Committer("Jeff Miller", "jeffm@apple.com", "jeffm7"),
    Committer("Jeffrey Pfau", ["jeffrey@endrift.com", "jpfau@apple.com"], "jpfau"),
    Committer("Jenn Braithwaite", "jennb@chromium.org", "jennb"),
    Committer("Jens Alfke", ["snej@chromium.org", "jens@apple.com"]),
    Committer("Jer Noble", "jer.noble@apple.com", "jernoble"),
    Committer("Jeremy Moskovich", ["playmobil@google.com", "jeremy@chromium.org"], "jeremymos"),
    Committer("Jesus Sanchez-Palencia", ["jesus@webkit.org", "jesus.palencia@openbossa.org"], "jeez_"),
    Committer("Jia Pu", "jpu@apple.com"),
    Committer("Jochen Eisinger", "jochen@chromium.org", "jochen__"),
    Committer("John Abd-El-Malek", "jam@chromium.org", "jam"),
    Committer("John Gregg", ["johnnyg@google.com", "johnnyg@chromium.org"], "johnnyg"),
    Committer("John Knottenbelt", "jknotten@chromium.org", "jknotten"),
    Committer("Johnny Ding", ["jnd@chromium.org", "johnnyding.webkit@gmail.com"], "johnnyding"),
    Committer("Jon Lee", "jonlee@apple.com", "jonlee"),
    Committer("Joone Hur", "joone@webkit.org", "joone"),
    Committer("Joost de Valk", ["joost@webkit.org", "webkit-dev@joostdevalk.nl"], "Altha"),
    Committer("Joshua Bell", ["jsbell@chromium.org", "jsbell@google.com"], "jsbell"),
    Committer("Julie Parent", ["jparent@google.com", "jparent@chromium.org"], "jparent"),
    Committer("Jungshik Shin", "jshin@chromium.org"),
    Committer("Justin Schuh", "jschuh@chromium.org", "jschuh"),
    Committer("Kaustubh Atrawalkar", ["kaustubh@motorola.com"], "silverroots"),
    Committer("Keishi Hattori", "keishi@webkit.org", "keishi"),
    Committer("Kelly Norton", "knorton@google.com"),
    Committer("Ken Buchanan", "kenrb@chromium.org", "kenrb"),
    Committer("Kenichi Ishibashi", "bashi@chromium.org", "bashi"),
    Committer("Kenji Imasaki", "imasaki@chromium.org", "imasaki"),
    Committer("Kent Hansen", "kent.hansen@nokia.com", "khansen"),
    Committer(u"Kim Gr\u00f6nholm", "kim.1.gronholm@nokia.com"),
    Committer("Kimmo Kinnunen", ["kimmo.t.kinnunen@nokia.com", "kimmok@iki.fi", "ktkinnun@webkit.org"], "kimmok"),
    Committer("Kinuko Yasuda", "kinuko@chromium.org", "kinuko"),
    Committer("Kristof Kosztyo", "kkristof@inf.u-szeged.hu", "kkristof"),
    Committer("Krzysztof Kowalczyk", "kkowalczyk@gmail.com"),
    Committer("Kwang Yul Seo", ["kwangyul.seo@gmail.com", "skyul@company100.net", "kseo@webkit.org"], "kwangseo"),
    Committer("Leandro Gracia Gil", "leandrogracia@chromium.org", "leandrogracia"),
    Committer("Leandro Pereira", ["leandro@profusion.mobi", "leandro@webkit.org"], "acidx"),
    Committer("Leo Yang", ["leo.yang@torchmobile.com.cn", "leoyang@webkit.org", "leoyang.webkit@gmail.com", "leo.yang.c@gmail.com"], "leoyang"),
    Committer("Lucas De Marchi", ["demarchi@webkit.org", "lucas.demarchi@profusion.mobi"], "demarchi"),
    Committer("Lucas Forschler", ["lforschler@apple.com"], "lforschler"),
    Committer("Luke Macpherson", ["macpherson@chromium.org", "macpherson@google.com"], "macpherson"),
    Committer("Mads Ager", "ager@chromium.org"),
    Committer("Mahesh Kulkarni", ["mahesh.kulkarni@nokia.com", "maheshk@webkit.org"], "maheshk"),
    Committer("Marcus Voltis Bulach", "bulach@chromium.org"),
    Committer("Mario Sanchez Prada", ["msanchez@igalia.com", "mario@webkit.org"], "msanchez"),
    Committer("Mark Hahnenberg", "mhahnenberg@apple.com"),
    Committer("Mary Wu", ["mary.wu@torchmobile.com.cn", "wwendy2007@gmail.com"], "marywu"),
    Committer("Matt Delaney", "mdelaney@apple.com"),
    Committer("Matt Lilek", ["mlilek@apple.com", "webkit@mattlilek.com", "pewtermoose@webkit.org"], "pewtermoose"),
    Committer("Matt Perry", "mpcomplete@chromium.org"),
    Committer("Maxime Britto", ["maxime.britto@gmail.com", "britto@apple.com"]),
    Committer("Maxime Simon", ["simon.maxime@gmail.com", "maxime.simon@webkit.org"], "maxime.simon"),
    Committer("Michael Nordman", "michaeln@google.com", "michaeln"),
    Committer("Michelangelo De Simone", "michelangelo@webkit.org", "michelangelo"),
    Committer("Mihnea Ovidenie", "mihnea@adobe.com", "mihnea"),
    Committer("Mike Belshe", ["mbelshe@chromium.org", "mike@belshe.com"]),
    Committer("Mike Fenton", ["mifenton@rim.com", "mike.fenton@torchmobile.com"], "mfenton"),
    Committer("Mike Lawther", "mikelawther@chromium.org", "mikelawther"),
    Committer("Mike Reed", "reed@google.com", "reed"),
    Committer("Mike Thole", ["mthole@mikethole.com", "mthole@apple.com"]),
    Committer("Mikhail Naganov", "mnaganov@chromium.org"),
    Committer("Naoki Takano", ["honten@chromium.org", "takano.naoki@gmail.com"], "honten"),
    Committer("Nat Duca", ["nduca@chromium.org", "nduca@google.com"], "nduca"),
    Committer("Nayan Kumar K", ["nayankk@motorola.com", "nayankk@gmail.com"], "xc0ffee"),
    Committer("Nico Weber", ["thakis@chromium.org", "thakis@google.com"], "thakis"),
    Committer("Noel Gordon", ["noel.gordon@gmail.com", "noel@chromium.org", "noel@google.com"], "noel"),
    Committer("Pam Greene", "pam@chromium.org", "pamg"),
    Committer("Patrick Gansterer", ["paroga@paroga.com", "paroga@webkit.org"], "paroga"),
    Committer("Pavel Podivilov", "podivilov@chromium.org", "podivilov"),
    Committer("Peter Beverloo", ["peter@chromium.org", "beverloo@google.com"], "beverloo"),
    Committer("Peter Kasting", ["pkasting@google.com", "pkasting@chromium.org"], "pkasting"),
    Committer("Peter Varga", ["pvarga@webkit.org", "pvarga@inf.u-szeged.hu"], "stampho"),
    Committer("Philip Rogers", ["pdr@google.com", "pdr@chromium.org"], "pdr"),
    Committer("Pierre d'Herbemont", ["pdherbemont@free.fr", "pdherbemont@apple.com"], "pdherbemont"),
    Committer("Pierre-Olivier Latour", "pol@apple.com", "pol"),
    Committer("Pierre Rossi", "pierre.rossi@gmail.com", "elproxy"),
    Committer("Pratik Solanki", "psolanki@apple.com", "psolanki"),
    Committer("Qi Zhang", ["qi.2.zhang@nokia.com", "qi.zhang02180@gmail.com"], "qi"),
    Committer("Rafael Antognolli", "antognolli@profusion.mobi", "antognolli"),
    Committer("Rafael Brandao", "rafael.lobo@openbossa.org", "rafaelbrandao"),
    Committer("Rafael Weinstein", "rafaelw@chromium.org", "rafaelw"),
    Committer("Raphael Kubo da Costa", ["rakuco@webkit.org", "rakuco@FreeBSD.org"], "rakuco"),
    Committer("Ravi Kasibhatla", "ravi.kasibhatla@motorola.com", "kphanee"),
    Committer("Renata Hodovan", "reni@webkit.org", "reni"),
    Committer("Robert Hogan", ["robert@webkit.org", "robert@roberthogan.net", "lists@roberthogan.net"], "mwenge"),
    Committer("Roland Steiner", "rolandsteiner@chromium.org"),
    Committer("Ryuan Choi", "ryuan.choi@samsung.com", "ryuan"),
    Committer("Satish Sampath", "satish@chromium.org"),
    Committer("Scott Violet", "sky@chromium.org", "sky"),
    Committer("Sergio Villar Senin", ["svillar@igalia.com", "sergio@webkit.org"], "svillar"),
    Committer("Shawn Singh", "shawnsingh@chromium.org", "shawnsingh"),
    Committer("Shinya Kawanaka", "shinyak@chromium.org", "shinyak"),
    Committer("Siddharth Mathur", "siddharth.mathur@nokia.com", "simathur"),
    Committer("Stephen Chenney", "schenney@chromium.org", "schenney"),
    Committer("Steve Lacey", "sjl@chromium.org", "stevela"),
    Committer("Takashi Toyoshima", "toyoshim@chromium.org", "toyoshim"),
    Committer("Thomas Sepez", "tsepez@chromium.org", "tsepez"),
    Committer("Tim Horton", "timothy_horton@apple.com", "thorton"),
    Committer("Tom Zakrajsek", "tomz@codeaurora.org", "tomz"),
    Committer("Tommy Widenflycht", "tommyw@google.com", "tommyw"),
    Committer("Trey Matteson", "trey@usa.net", "trey"),
    Committer("Tristan O'Tierney", ["tristan@otierney.net", "tristan@apple.com"]),
    Committer("Vangelis Kokkevis", "vangelis@chromium.org", "vangelis"),
    Committer("Viatcheslav Ostapenko", "ostapenko.viatcheslav@nokia.com", "ostap"),
    Committer("Victor Wang", "victorw@chromium.org", "victorw"),
    Committer("Victoria Kirst", ["vrk@chromium.org", "vrk@google.com"], "vrk"),
    Committer("Vincent Scheib", "scheib@chromium.org", "scheib"),
    Committer("Vitaly Repeshko", "vitalyr@chromium.org"),
    Committer("William Siegrist", "wsiegrist@apple.com", "wms"),
    Committer("W. James MacLean", "wjmaclean@chromium.org", "seumas"),
    Committer("Xianzhu Wang", ["wangxianzhu@chromium.org", "phnixwxz@gmail.com", "wangxianzhu@google.com"], "wangxianzhu"),
    Committer("Xiaomei Ji", "xji@chromium.org", "xji"),
    Committer("Yael Aharon", "yael.aharon@nokia.com", "yael"),
    Committer("Yaar Schnitman", ["yaar@chromium.org", "yaar@google.com"]),
    Committer("Yi Shen", ["yi.4.shen@nokia.com", "shenyi2006@gmail.com"]),
    Committer("Yong Li", ["yong.li.webkit@gmail.com", "yong.li@torchmobile.com", "yoli@rim.com"], "yong"),
    Committer("Yongjun Zhang", ["yongjun.zhang@nokia.com", "yongjun_zhang@apple.com"]),
    Committer("Yoshifumi Inoue", "yosin@chromium.org", "yosin"),
    Committer("Yuqiang Xian", "yuqiang.xian@intel.com"),
    Committer("Yuta Kitamura", "yutak@chromium.org", "yutak"),
    Committer("Yuzo Fujishima", "yuzo@google.com", "yuzo"),
    Committer("Zalan Bujtas", ["zbujtas@gmail.com", "zalan.bujtas@nokia.com"], "zalan"),
    Committer("Zeno Albisser", ["zeno@webkit.org", "zeno.albisser@nokia.com"], "zalbisser"),
    Committer("Zhenyao Mo", "zmo@google.com", "zhenyao"),
    Committer("Zoltan Horvath", ["zoltan@webkit.org", "hzoltan@inf.u-szeged.hu", "horvath.zoltan.6@stud.u-szeged.hu"], "zoltan"),
    Committer(u"\u017dan Dober\u0161ek", "zandobersek@gmail.com", "zdobersek"),
]


# This is intended as a canonical, machine-readable list of all reviewers for
# WebKit.  If your name is missing here and you are a reviewer, please add it.
# No review needed.


reviewers_list = [
    Reviewer("Abhishek Arya", "inferno@chromium.org", "inferno-sec"),
    Reviewer("Ada Chan", "adachan@apple.com", "chanada"),
    Reviewer("Adam Barth", "abarth@webkit.org", "abarth"),
    Reviewer("Adam Roben", ["aroben@webkit.org", "aroben@apple.com"], "aroben"),
    Reviewer("Adam Treat", ["treat@kde.org", "treat@webkit.org", "atreat@rim.com"], "manyoso"),
    Reviewer("Adele Peterson", "adele@apple.com", "adele"),
    Reviewer("Adrienne Walker", ["enne@google.com", "enne@chromium.org"], "enne"),
    Reviewer("Alejandro G. Castro", ["alex@igalia.com", "alex@webkit.org"], "alexg__"),
    Reviewer("Alexey Proskuryakov", ["ap@webkit.org", "ap@apple.com"], "ap"),
    Reviewer("Alexis Menard", ["alexis.menard@openbossa.org", "menard@kde.org"], "darktears"),
    Reviewer("Alice Liu", "alice.liu@apple.com", "aliu"),
    Reviewer("Alp Toker", ["alp@nuanti.com", "alp@atoker.com", "alp@webkit.org"], "alp"),
    Reviewer("Anders Carlsson", ["andersca@apple.com", "acarlsson@apple.com"], "andersca"),
    Reviewer("Andreas Kling", ["kling@webkit.org", "awesomekling@apple.com", "andreas.kling@nokia.com"], "kling"),
    Reviewer("Andy Estes", "aestes@apple.com", "estes"),
    Reviewer("Antonio Gomes", ["tonikitoo@webkit.org", "agomes@rim.com"], "tonikitoo"),
    Reviewer("Antti Koivisto", ["koivisto@iki.fi", "antti@apple.com", "antti.j.koivisto@nokia.com"], "anttik"),
    Reviewer("Ariya Hidayat", ["ariya.hidayat@gmail.com", "ariya@sencha.com", "ariya@webkit.org"], "ariya"),
    Reviewer("Benjamin Poulain", ["benjamin@webkit.org", "benjamin.poulain@nokia.com", "ikipou@gmail.com"], "benjaminp"),
    Reviewer("Beth Dakin", "bdakin@apple.com", "dethbakin"),
    Reviewer("Brady Eidson", "beidson@apple.com", "bradee-oh"),
    Reviewer("Brent Fulgham", "bfulgham@webkit.org", "bfulgham"),
    Reviewer("Brian Weinstein", "bweinstein@apple.com", "bweinstein"),
    Reviewer("Cameron Zwarich", ["zwarich@apple.com", "cwzwarich@apple.com", "cwzwarich@webkit.org"]),
    Reviewer("Carlos Garcia Campos", ["cgarcia@igalia.com", "carlosgc@gnome.org", "carlosgc@webkit.org"], "KaL"),
    Reviewer("Chang Shu", ["cshu@webkit.org", "c.shu@sisa.samsung.com"], "cshu"),
    Reviewer("Chris Blumenberg", "cblu@apple.com", "cblu"),
    Reviewer("Chris Marrin", "cmarrin@apple.com", "cmarrin"),
    Reviewer("Chris Fleizach", "cfleizach@apple.com", "cfleizach"),
    Reviewer("Chris Jerdonek", "cjerdonek@webkit.org", "cjerdonek"),
    Reviewer("Chris Rogers", "crogers@google.com", "crogers"),
    Reviewer(u"Csaba Osztrogon\u00e1c", "ossy@webkit.org", "ossy"),
    Reviewer("Dan Bernstein", ["mitz@webkit.org", "mitz@apple.com"], "mitzpettel"),
    Reviewer("Daniel Bates", ["dbates@webkit.org", "dbates@rim.com"], "dydz"),
    Reviewer("Darin Adler", "darin@apple.com", "darin"),
    Reviewer("Darin Fisher", ["fishd@chromium.org", "darin@chromium.org"], "fishd"),
    Reviewer("David Harrison", "harrison@apple.com", "harrison"),
    Reviewer("David Hyatt", "hyatt@apple.com", ["dhyatt", "hyatt"]),
    Reviewer("David Kilzer", ["ddkilzer@webkit.org", "ddkilzer@apple.com"], "ddkilzer"),
    Reviewer("David Levin", "levin@chromium.org", "dave_levin"),
    Reviewer("Dean Jackson", "dino@apple.com", "dino"),
    Reviewer("Dimitri Glazkov", "dglazkov@chromium.org", "dglazkov"),
    Reviewer("Dirk Pranke", "dpranke@chromium.org", "dpranke"),
    Reviewer("Dirk Schulze", "krit@webkit.org", "krit"),
    Reviewer("Dmitry Titov", "dimich@chromium.org", "dimich"),
    Reviewer("Don Melton", "gramps@apple.com", "gramps"),
    Reviewer("Dumitru Daniliuc", "dumi@chromium.org", "dumi"),
    Reviewer("Enrica Casucci", "enrica@apple.com", "enrica"),
    Reviewer("Eric Carlson", "eric.carlson@apple.com", "eric_carlson"),
    Reviewer("Eric Seidel", "eric@webkit.org", "eseidel"),
    Reviewer("Filip Pizlo", "fpizlo@apple.com", "pizlo"),
    Reviewer("Gavin Barraclough", "barraclough@apple.com", "gbarra"),
    Reviewer("Geoffrey Garen", "ggaren@apple.com", "ggaren"),
    Reviewer("George Staikos", ["staikos@kde.org", "staikos@webkit.org"]),
    Reviewer("Gustavo Noronha Silva", ["gns@gnome.org", "kov@webkit.org", "gustavo.noronha@collabora.co.uk", "gustavo.noronha@collabora.com"], "kov"),
    Reviewer("Hajime Morita", ["morrita@google.com", "morrita@chromium.org"], "morrita"),
    Reviewer("Holger Freyther", ["zecke@selfish.org", "zecke@webkit.org"], "zecke"),
    Reviewer("James Robinson", ["jamesr@chromium.org", "jamesr@google.com"], "jamesr"),
    Reviewer("Jan Alonzo", ["jmalonzo@gmail.com", "jmalonzo@webkit.org"], "janm"),
    Reviewer("Jeremy Orlow", ["jorlow@webkit.org", "jorlow@chromium.org"], "jorlow"),
    Reviewer("Jessie Berlin", ["jberlin@webkit.org", "jberlin@apple.com"], "jessieberlin"),
    Reviewer("Jian Li", "jianli@chromium.org", "jianli"),
    Reviewer("Jocelyn Turcotte", "jocelyn.turcotte@nokia.com", "jturcotte"),
    Reviewer("John Sullivan", "sullivan@apple.com", "sullivan"),
    Reviewer("Jon Honeycutt", "jhoneycutt@apple.com", "jhoneycutt"),
    Reviewer("Joseph Pecoraro", ["joepeck@webkit.org", "pecoraro@apple.com"], "JoePeck"),
    Reviewer("Julien Chaffraix", ["jchaffraix@webkit.org", "julien.chaffraix@gmail.com", "jchaffraix@google.com", "jchaffraix@codeaurora.org"], "jchaffraix"),
    Reviewer("Justin Garcia", "justin.garcia@apple.com", "justing"),
    Reviewer("Ken Kocienda", "kocienda@apple.com"),
    Reviewer("Kenneth Rohde Christiansen", ["kenneth@webkit.org", "kenneth.christiansen@openbossa.org", "kenneth.christiansen@gmail.com"], ["kenne", "kenneth"]),
    Reviewer("Kenneth Russell", "kbr@google.com", "kbr_google"),
    Reviewer("Kent Tamura", ["tkent@chromium.org", "tkent@google.com"], "tkent"),
    Reviewer("Kentaro Hara", ["haraken@chromium.org"], "haraken"),
    Reviewer("Kevin Decker", "kdecker@apple.com", "superkevin"),
    Reviewer("Kevin McCullough", "kmccullough@apple.com", "maculloch"),
    Reviewer("Kevin Ollivier", ["kevino@theolliviers.com", "kevino@webkit.org"], "kollivier"),
    Reviewer("Lars Knoll", ["lars@trolltech.com", "lars@kde.org", "lars.knoll@nokia.com"], "lars"),
    Reviewer("Laszlo Gombos", "laszlo.1.gombos@nokia.com", "lgombos"),
    Reviewer("Levi Weintraub", ["leviw@chromium.org", "leviw@google.com", "lweintraub@apple.com"], "leviw"),
    Reviewer("Luiz Agostini", ["luiz@webkit.org", "luiz.agostini@openbossa.org"], "lca"),
    Reviewer("Maciej Stachowiak", "mjs@apple.com", "othermaciej"),
    Reviewer("Mark Rowe", "mrowe@apple.com", "bdash"),
    Reviewer("Martin Robinson", ["mrobinson@webkit.org", "mrobinson@igalia.com", "martin.james.robinson@gmail.com"], "mrobinson"),
    Reviewer("Michael Saboff", "msaboff@apple.com", "msaboff"),
    Reviewer("Mihai Parparita", "mihaip@chromium.org", "mihaip"),
    Reviewer("Nate Chapin", "japhet@chromium.org", ["japhet", "natechapin"]),
    Reviewer("Nikolas Zimmermann", ["zimmermann@kde.org", "zimmermann@physik.rwth-aachen.de", "zimmermann@webkit.org", "nzimmermann@rim.com"], "wildfox"),
    Reviewer("Noam Rosenthal", "noam.rosenthal@nokia.com", "noamr"),
    Reviewer("Ojan Vafai", "ojan@chromium.org", "ojan"),
    Reviewer("Oliver Hunt", "oliver@apple.com", "olliej"),
    Reviewer("Pavel Feldman", ["pfeldman@chromium.org", "pfeldman@google.com"], "pfeldman"),
    Reviewer("Philippe Normand", ["pnormand@igalia.com", "philn@webkit.org", "philn@igalia.com"], ["philn-tp", "pnormand"]),
    Reviewer("Richard Williamson", "rjw@apple.com", "rjw"),
    Reviewer("Rob Buis", ["rwlbuis@gmail.com", "rwlbuis@webkit.org", "rbuis@rim.com"], "rwlbuis"),
    Reviewer("Ryosuke Niwa", "rniwa@webkit.org", "rniwa"),
    Reviewer("Sam Weinig", ["sam@webkit.org", "weinig@apple.com"], "weinig"),
    Reviewer("Shinichiro Hamaji", "hamaji@chromium.org", "hamaji"),
    Reviewer("Simon Fraser", "simon.fraser@apple.com", "smfr"),
    Reviewer("Simon Hausmann", ["hausmann@webkit.org", "hausmann@kde.org", "simon.hausmann@nokia.com"], "tronical"),
    Reviewer("Stephanie Lewis", "slewis@apple.com", "sundiamonde"),
    Reviewer("Stephen White", "senorblanco@chromium.org", "senorblanco"),
    Reviewer("Steve Block", "steveblock@google.com", "steveblock"),
    Reviewer("Steve Falkenburg", "sfalken@apple.com", "sfalken"),
    Reviewer("Tim Omernick", "timo@apple.com"),
    Reviewer("Timothy Hatcher", ["timothy@apple.com", "timothy@hatcher.name"], "xenon"),
    Reviewer("Tony Chang", "tony@chromium.org", "tony^work"),
    Reviewer("Tony Gentilcore", "tonyg@chromium.org", "tonyg-cr"),
    Reviewer(u"Tor Arne Vestb\u00f8", ["vestbo@webkit.org", "tor.arne.vestbo@nokia.com"], "torarne"),
    Reviewer("Vicki Murley", "vicki@apple.com"),
    Reviewer("Vsevolod Vlasov", "vsevik@chromium.org", "vsevik"),
    Reviewer("Xan Lopez", ["xan.lopez@gmail.com", "xan@gnome.org", "xan@webkit.org", "xlopez@igalia.com"], "xan"),
    Reviewer("Yury Semikhatsky", "yurys@chromium.org", "yurys"),
    Reviewer("Zack Rusin", "zack@kde.org", "zackr"),
    Reviewer("Zoltan Herczeg", ["zherczeg@webkit.org", "zherczeg@inf.u-szeged.hu"], "zherczeg"),
]

class CommitterList(object):

    # Committers and reviewers are passed in to allow easy testing
    def __init__(self,
                 committers=committers_unable_to_review,
                 reviewers=reviewers_list,
                 contributors=contributors_who_are_not_committers,
                 watchers=watchers_who_are_not_contributors):
        self._accounts = watchers + contributors + committers + reviewers
        self._contributors = contributors + committers + reviewers
        self._committers = committers + reviewers
        self._reviewers = reviewers
        self._contributors_by_name = {}
        self._accounts_by_email = {}
        self._accounts_by_login = {}

    def accounts(self):
        return self._accounts

    def contributors(self):
        return self._contributors

    def committers(self):
        return self._committers

    def reviewers(self):
        return self._reviewers

    def _name_to_contributor_map(self):
        if not len(self._contributors_by_name):
            for contributor in self._contributors:
                assert(contributor.full_name)
                assert(contributor.full_name.lower() not in self._contributors_by_name)  # We should never have duplicate names.
                self._contributors_by_name[contributor.full_name.lower()] = contributor
        return self._contributors_by_name

    def _email_to_account_map(self):
        if not len(self._accounts_by_email):
            for account in self._accounts:
                for email in account.emails:
                    assert(email not in self._accounts_by_email)  # We should never have duplicate emails.
                    self._accounts_by_email[email] = account
        return self._accounts_by_email

    def _login_to_account_map(self):
        if not len(self._accounts_by_login):
            for account in self._accounts:
                if account.emails:
                    login = account.bugzilla_email()
                    assert(login not in self._accounts_by_login)  # We should never have duplicate emails.
                    self._accounts_by_login[login] = account
        return self._accounts_by_login

    def _contributor_only(self, record):
        if record and not record.is_contributor:
            return None
        return record

    def _committer_only(self, record):
        if record and not record.can_commit:
            return None
        return record

    def _reviewer_only(self, record):
        if record and not record.can_review:
            return None
        return record

    def committer_by_name(self, name):
        return self._committer_only(self.contributor_by_name(name))

    def contributor_by_irc_nickname(self, irc_nickname):
        for contributor in self.contributors():
            # FIXME: This should do case-insensitive comparison or assert that all IRC nicknames are in lowercase
            if contributor.irc_nicknames and irc_nickname in contributor.irc_nicknames:
                return contributor
        return None

    def contributors_by_search_string(self, string):
        return filter(lambda contributor: contributor.contains_string(string), self.contributors())

    def contributors_by_email_username(self, string):
        string = string + '@'
        result = []
        for contributor in self.contributors():
            for email in contributor.emails:
                if email.startswith(string):
                    result.append(contributor)
                    break
        return result

    def _contributor_name_shorthands(self, contributor):
        if ' ' not in contributor.full_name:
            return []
        split_fullname = contributor.full_name.split()
        first_name = split_fullname[0]
        last_name = split_fullname[-1]
        return first_name, last_name, first_name + last_name[0], first_name + ' ' + last_name[0]

    def _tokenize_contributor_name(self, contributor):
        full_name_in_lowercase = contributor.full_name.lower()
        tokens = [full_name_in_lowercase] + full_name_in_lowercase.split()
        if contributor.irc_nicknames:
            return tokens + [nickname.lower() for nickname in contributor.irc_nicknames if len(nickname) > 5]
        return tokens

    def contributors_by_fuzzy_match(self, string):
        string_in_lowercase = string.lower()

        # 1. Exact match for fullname, email and irc_nicknames
        account = self.contributor_by_name(string_in_lowercase) or self.account_by_email(string_in_lowercase) or self.contributor_by_irc_nickname(string_in_lowercase)
        if account:
            return [account], 0

        # 2. Exact match for email username (before @)
        accounts = self.contributors_by_email_username(string_in_lowercase)
        if accounts and len(accounts) == 1:
            return accounts, 0

        # 3. Exact match for first name, last name, and first name + initial combinations such as "Dan B" and "Tim H"
        accounts = [contributor for contributor in self.contributors() if string in self._contributor_name_shorthands(contributor)]
        if accounts and len(accounts) == 1:
            return accounts, 0

        # 4. Finally, fuzzy-match using edit-distance
        string = string_in_lowercase
        contributorWithMinDistance = []
        minDistance = len(string) / 2 - 1
        for contributor in self.contributors():
            tokens = self._tokenize_contributor_name(contributor)
            editdistances = [edit_distance(token, string) for token in tokens if abs(len(token) - len(string)) <= minDistance]
            if not editdistances:
                continue
            distance = min(editdistances)
            if distance == minDistance:
                contributorWithMinDistance.append(contributor)
            elif distance < minDistance:
                contributorWithMinDistance = [contributor]
                minDistance = distance
        if not len(contributorWithMinDistance):
            return [], len(string)
        return contributorWithMinDistance, minDistance

    def account_by_login(self, login):
        return self._login_to_account_map().get(login.lower()) if login else None

    def account_by_email(self, email):
        return self._email_to_account_map().get(email.lower()) if email else None

    def contributor_by_name(self, name):
        return self._name_to_contributor_map().get(name.lower()) if name else None

    def contributor_by_email(self, email):
        return self._contributor_only(self.account_by_email(email))

    def committer_by_email(self, email):
        return self._committer_only(self.account_by_email(email))

    def reviewer_by_email(self, email):
        return self._reviewer_only(self.account_by_email(email))