diff --git a/AUTHORS b/AUTHORS index bda3bb73c..617acadc7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,103 +13,96 @@ # contents of this file. # -Aaron Bieber (qbit) +Jakob Borg (calmh) +Audrius Butkevicius (AudriusButkevicius) +Simon Frei (imsodin) +Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com> +Alexander Graf (alex2108) +Alexandre Viau (aviau) +Anderson Mesquita (andersonvom) +André Colomb (acolomb) +Antony Male (canton7) +Ben Schulz (uok) +bt90 +Caleb Callaway (cqcallaw) +Daniel Harte (norgeous) +Emil Lundberg +Eric P +Evgeny Kuznetsov +greatroar <61184462+greatroar@users.noreply.github.com> +Lars K.W. Gohlke (lkwg82) +Lode Hoste (Zillode) +Michael Ploujnikov (plouj) +Ross Smith II (rasa) +Stefan Tatschner (rumpelsepp) +Wulf Weich (wweich) Adam Piggott (ProactiveServices) Adel Qalieh (adelq) -Alan Pope -Alberto Donato Aleksey Vasenev Alessandro G. (alessandro.g89) Alex Ionescu Alex Lindeman <139387+aelindeman@users.noreply.github.com> Alex Xu -Alexander Graf (alex2108) Alexander Seiler Alexandre Alves -Alexandre Viau (aviau) Aman Gupta -Anatoli Babenia -Anderson Mesquita (andersonvom) Andreas Sommer andresvia -Andrew Dunham (andrew-d) -Andrew Meyer Andrew Rabert (nvllsvm) <6550543+nvllsvm@users.noreply.github.com> Andrey D (scienmind) -André Colomb (acolomb) andyleap Anjan Momi Anthony Goeckner Antoine Lamielle (0x010C) -Antony Male (canton7) Anur Aranjedeath Arkadiusz Tymiński Aroun Arthur Axel fREW Schmidt (frioux) Artur Zubilewicz -Audrius Butkevicius (AudriusButkevicius) Aurélien Rainone <476650+arl@users.noreply.github.com> BAHADIR YILMAZ Bart De Vries (mogwa1) Beat Reichenbach <44111292+beatreichenbach@users.noreply.github.com> -Ben Curthoys (bencurthoys) -Ben Schulz (uok) Ben Shepherd (benshep) Ben Sidhom (bsidhom) Benedikt Heine (bebehei) -Benedikt Morbach -Benjamin Nater <17193640+bn4t@users.noreply.github.com> Benno Fünfstück Benny Ng (tpng) boomsquared <54829195+boomsquared@users.noreply.github.com> Boqin Qin Boris Rybalkin -Brandon Philips (philips) Brendan Long (brendanlong) -Brian R. Becker (brbecker) -bt90 -Caleb Callaway (cqcallaw) -Carsten Hagemann (carstenhag) Catfriend1 <16361913+Catfriend1@users.noreply.github.com> Cathryne Linenweaver (Cathryne) Cedric Staniewski (xduugu) -chenrui Chih-Hsuan Yen <1937689+yan12125@users.noreply.github.com> Choongkyu Chris Howie (cdhowie) Chris Joel (cdata) -Chris Tonkinson Christian Kujau Christian Prescott chucic cjc7373 Colin Kennedy (moshen) Cromefire_ <26320625+cromefire@users.noreply.github.com> -cui fliter Cyprien Devillez d-volution <49024624+d-volution@users.noreply.github.com> -Dale Visser Dan Daniel Barczyk <46358936+DanielBarczyk@users.noreply.github.com> Daniel Bergmann (brgmnn) -Daniel Harte (norgeous) Daniel Martí (mvdan) Daniel Padrta <64928366+danpadcz@users.noreply.github.com> Darshil Chanpura (dtchanpura) dashangcun <907225865@qq.com> David Rimmer (dinosore) -deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com> DeflateAwning <11021263+DeflateAwning@users.noreply.github.com> Denis A. (dva) Dennis Wilson (snnd) -dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> -dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> derekriemer DerRockWolf <50499906+DerRockWolf@users.noreply.github.com> desbma Devon G. Redekopp -diemade digital Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com> Dmitry Saveliev (dsaveliev) @@ -119,14 +112,11 @@ Dominik Heidler (asdil12) Elias Jarlebring (jarlebring) Elliot Huffman Emil Hessman (ceh) -Emil Lundberg Eng Zer Jun entity0xfe <109791748+entity0xfe@users.noreply.github.com> Eric Lesiuta -Eric P Erik Meitner (WSGCSysadmin) Evan Spensley <94762716+0evan@users.noreply.github.com> -Evgeny Kuznetsov Federico Castagnini (facastagnini) Felix <53702818+f-eliks@users.noreply.github.com> Felix Ableitner (Nutomic) @@ -140,7 +130,6 @@ ghjklw Gilli Sigurdsson (gillisig) Gleb Sinyavskiy Graham Miln (grahammiln) -greatroar <61184462+greatroar@users.noreply.github.com> Greg guangwu gudvinr @@ -155,50 +144,35 @@ Hugo Locurcio Iain Barnett Ian Johnson (anonymouse64) ignacy123 -Ikko Ashimine -Ilya Brin <464157+ilyabrin@users.noreply.github.com> Iskander Sharipov (Alex) Jaakko Hannikainen (jgke) -Jacek Szafarkiewicz (hadogenes) Jack Croft Jacob Jake Peterson (acogdev) -Jakob Borg (calmh) James O'Beirne James Patterson (jpjp) -janost Jaroslav Lichtblau Jaroslav Malec (dzarda) -jaseg Jaspitta -Jauder Ho Jaya Chithra (jayachithra) Jaya Kumar Jeffery To jelle van der Waa Jens Diemer (jedie) -Jerry Jacobs (xor-gate) -Jesse Lucas Jochen Voss (seehuhn) -Johan Andersson Johan Vromans (sciurius) John Rinehart (fuzzybear3965) Jonas Thelemann Jonathan -Jonathan Cross -Jonta <359397+Jonta@users.noreply.github.com> Jose Manuel Delicado (jmdaweb) jtagcat Julian Lehrhuber Jörg Thalheim Jędrzej Kula -K.B.Dharun Krishna -Kalle Laine Kapil Sareen Karol Różycki (krozycki) Kebin Liu Keith Harrison -Keith Turner Kelong Cong (kc1212) Ken'ichi Kamada (kamadak) Kevin Allen (ironmig) @@ -207,30 +181,23 @@ Kevin White, Jr. (kwhite17) klemens Kurt Fitzner (Kudalufi) kylosus <33132401+kylosus@users.noreply.github.com> -Lars K.W. Gohlke (lkwg82) Lars Lehtonen -Laurent Arnoud Laurent Etiemble (letiemble) Leo Arias (elopio) Liu Siyuan (liusy182) -Lode Hoste (Zillode) Lord Landon Agahnim (LordLandon) LSmithx2 <42276854+lsmithx2@users.noreply.github.com> -luchenhan <168071714+luchenhan@users.noreply.github.com> Lukas Lihotzki Luke Hamburg <1992842+luckman212@users.noreply.github.com> luzpaz Majed Abdulaziz (majedev) Marc Laporte (marclaporte) -Marc Pujol (kilburn) Marcin Dziadus (marcindziadus) -marco-m Marcus B Spencer Marcus Legendre Mario Majila Mark Pulford (mpx) Martchus -Martin Polehla Mateusz Naściszewski (mateon1) Mateusz Ż mathias4833 <67101597+mathias4833@users.noreply.github.com> @@ -241,15 +208,10 @@ Matteo Ruina Maurizio Tomasi Max Max Schulze (kralo) -maxice8 <30738253+maxice8@users.noreply.github.com> MaximAL -Maxime Thirouin Maximilian -mclang <1721600+mclang@users.noreply.github.com> Michael Jephcote (Rewt0r) -Michael Ploujnikov (plouj) Michael Rienstra -Michael Tilli (pyfisch) MichaIng Migelo Mike Boone @@ -258,7 +220,6 @@ MikolajTwarog <43782609+MikolajTwarog@users.noreply.github.com> Mingxuan Lin mv1005 <49659413+mv1005@users.noreply.github.com> Nate Morrison (nrm21) -Naveen <172697+naveensrinivasan@users.noreply.github.com> nf Nicholas Rishel (PrototypeNM1) Nick Busey @@ -273,7 +234,6 @@ NoLooseEnds Oliver Freyermuth orangekame3 otbutz -Otiel overkill <22098433+0verk1ll@users.noreply.github.com> Oyebanji Jacob Mayowa Pablo @@ -281,7 +241,6 @@ Pascal Jungblut (pascalj) Paul Brit Paul Donald Pawel Palenica (qepasa) -Paweł Rozlach perewa Peter Badida Peter Dave Hello @@ -291,19 +250,15 @@ Phani Rithvij Phil Davis Philippe Schommers (filoozoom) Phill Luby (pluby) -Pier Paolo Ramon Piotr Bejda (piobpl) polyfloyd -Pramodh KP (pramodhkp) <1507241+pramodhkp@users.noreply.github.com> Quentin Hibon Rahmi Pruitt red_led -Richard Hartmann Robert Carosi (nov1n) Roberto Santalla Robin Schoonover Roman Zaynetdinov (zaynetro) -Ross Smith II (rasa) rubenbe Ruslan Yevdokymov <38809160+ruslanye@users.noreply.github.com> Ryan Qian @@ -315,18 +270,14 @@ Sergey Mishin (ralder) Sertonix <83883937+Sertonix@users.noreply.github.com> Severin von Wnuck-Lipinski Shaarad Dalvi <60266155+shaaraddalvi@users.noreply.github.com> -Simon Frei (imsodin) Simon Mwepu Simon Pickup Sly_tom_cat Sonu Kumar Saw <31889738+dev-saw99@users.noreply.github.com> Stefan Kuntz (Stefan-Code) -Stefan Tatschner (rumpelsepp) Steven Eckhoff Suhas Gundimeda (snugghash) Sven Bachmann -Syncthing Automation -Syncthing Release Automation Sébastien WENSKE Taylor Khan (nelsonkhan) Terrance @@ -335,14 +286,11 @@ Thomas <9749173+uhthomas@users.noreply.github.com> Thomas Hipp Tim Abell (timabell) Tim Howes (timhowes) -Tim Nordenfur Tobias Frölich <40638719+tobifroe@users.noreply.github.com> Tobias Klauser Tobias Nygren (tnn2) Tobias Tom (tobiastom) Tom Jakubowski -Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com> -Tommy Thorn Tommy van der Vorst Tully Robinson (tojrobinson) Tyler Brazier (tylerbrazier) @@ -360,10 +308,9 @@ WangXi Will Rouesnel William A. Kennington III (wkennington) wouter bolsterlee -Wulf Weich (wweich) xarx00 Xavier O. (damajor) -xjtdy888 (xjtdy888) +xjtdy888 (xjtdy888) Yannic A. (eipiminus1) 佛跳墙 落心 diff --git a/gui/default/syncthing/core/aboutModalView.html b/gui/default/syncthing/core/aboutModalView.html index d040801fa..3d2240c4f 100644 --- a/gui/default/syncthing/core/aboutModalView.html +++ b/gui/default/syncthing/core/aboutModalView.html @@ -30,7 +30,7 @@

The Syncthing Authors

-Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Emil Lundberg, Eric P, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ross Smith II, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, bt90, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Ionescu, Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Anatoli Babenia, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, DerRockWolf, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, Gusted, Han Boetes, HansK-p, Harrison Jones, Hazem Krimi, Heiko Zuerker, Hireworks, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, K.B.Dharun Krishna, Kalle Laine, Kapil Sareen, Karol Różycki, Kebin Liu, Keith Harrison, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Luke Hamburg, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus B Spencer, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Martin Polehla, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, Maximilian, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Paul Donald, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ruslan Yevdokymov, Ryan Qian, Sacheendra Talluri, Scott Klupfel, Sertonix, Severin von Wnuck-Lipinski, Shaarad Dalvi, Simon Mwepu, Simon Pickup, Sly_tom_cat, Sonu Kumar Saw, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Sébastien WENSKE, Taylor Khan, Terrance, TheCreeper, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tim Nordenfur, Tobias Frölich, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tommy van der Vorst, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, Vladimir Rusinov, WangXi, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, cjc7373, cui fliter, d-volution, dashangcun, derekriemer, desbma, diemade, digital, domain, entity0xfe, georgespatton, ghjklw, guangwu, gudvinr, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, kylosus, luchenhan, luzpaz, marco-m, mathias4833, maxice8, mclang, mv1005, nf, orangekame3, otbutz, overkill, perewa, polyfloyd, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心 +Jakob Borg, Audrius Butkevicius, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, bt90, Caleb Callaway, Daniel Harte, Emil Lundberg, Eric P, Evgeny Kuznetsov, greatroar, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Ross Smith II, Stefan Tatschner, Wulf Weich, Adam Piggott, Adel Qalieh, Aleksey Vasenev, Alessandro G., Alex Ionescu, Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Andreas Sommer, andresvia, Andrew Rabert, Andrey D, andyleap, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benno Fünfstück, Benny Ng, boomsquared, Boqin Qin, Boris Rybalkin, Brendan Long, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Christian Kujau, Christian Prescott, chucic, cjc7373, Colin Kennedy, Cromefire_, Cyprien Devillez, d-volution, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, dashangcun, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, derekriemer, DerRockWolf, desbma, Devon G. Redekopp, digital, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, domain, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, entity0xfe, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, georgespatton, ghjklw, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, guangwu, gudvinr, Gusted, Han Boetes, HansK-p, Harrison Jones, Hazem Krimi, Heiko Zuerker, Hireworks, Hugo Locurcio, Iain Barnett, Ian Johnson, ignacy123, Iskander Sharipov, Jaakko Hannikainen, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jaya Chithra, Jaya Kumar, Jeffery To, jelle van der Waa, Jens Diemer, Jochen Voss, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jose Manuel Delicado, jtagcat, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, Kapil Sareen, Karol Różycki, Kebin Liu, Keith Harrison, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., klemens, Kurt Fitzner, kylosus, Lars Lehtonen, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, LSmithx2, Lukas Lihotzki, Luke Hamburg, luzpaz, Majed Abdulaziz, Marc Laporte, Marcin Dziadus, Marcus B Spencer, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Mateusz Naściszewski, Mateusz Ż, mathias4833, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maximilian, Michael Jephcote, Michael Rienstra, MichaIng, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, mv1005, Nate Morrison, nf, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, orangekame3, otbutz, overkill, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Paul Donald, Pawel Palenica, perewa, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Philippe Schommers, Phill Luby, Piotr Bejda, polyfloyd, Quentin Hibon, Rahmi Pruitt, red_led, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, rubenbe, Ruslan Yevdokymov, Ryan Qian, Ryan Sullivan, Sacheendra Talluri, Scott Klupfel, sec65, Sergey Mishin, Sertonix, Severin von Wnuck-Lipinski, Shaarad Dalvi, Simon Mwepu, Simon Pickup, Sly_tom_cat, Sonu Kumar Saw, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Sébastien WENSKE, Taylor Khan, Terrance, TheCreeper, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tobias Frölich, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy van der Vorst, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, vapatel2, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, villekalliomaki, Vladimir Rusinov, wangguoliang, WangXi, Will Rouesnel, William A. Kennington III, wouter bolsterlee, xarx00, Xavier O., xjtdy888, Yannic A., 佛跳墙, 落心
diff --git a/script/authors.go b/script/authors.go index 73fc8e5e2..febe22606 100644 --- a/script/authors.go +++ b/script/authors.go @@ -14,14 +14,14 @@ package main import ( "bytes" + "cmp" "fmt" - "io" "log" "math" "os" "os/exec" "regexp" - "sort" + "slices" "strings" ) @@ -64,59 +64,33 @@ type author struct { func main() { // Read authors from the AUTHORS file - authors := getAuthors() - - // Grab the set of thus known email addresses - listed := make(stringSet) - names := make(map[string]int) - for i, a := range authors { - names[a.name] = i - for _, e := range a.emails { - listed.add(e) - } - } + authorSet := getAuthors() // Grab the set of all known authors based on the git log, and add any // missing ones to the authors list. - all := allAuthors() - for email, name := range all { - if listed.has(email) { - continue - } + addAuthors(authorSet) - if _, ok := names[name]; ok && name != "" { - // We found a match on name - authors[names[name]].emails = append(authors[names[name]].emails, email) - listed.add(email) - continue - } + authors := authorSet.filteredAuthors() - authors = append(authors, author{ - name: name, - emails: []string{email}, - }) - names[name] = len(authors) - 1 - listed.add(email) - } + // Write authors to the about dialog - // Write author names in GUI about modal - - getContributions(authors) - sort.Sort(byContributions(authors)) + slices.SortFunc(authors, func(a, b author) int { + return cmp.Or( + -cmp.Compare(a.log10commits, b.log10commits), + cmp.Compare(strings.ToLower(a.name), strings.ToLower(b.name))) + }) var lines []string for _, author := range authors { - if authorBotsRe.MatchString(author.name) { - // Only humans are eligible, pending future legislation to the - // contrary. - continue - } lines = append(lines, author.name) } replacement := strings.Join(lines, ", ") authorsRe := regexp.MustCompile(`(?s)id="contributor-list">.*?`) - bs := readAll(htmlFile) + bs, err := os.ReadFile(htmlFile) + if err != nil { + log.Fatal(err) + } bs = authorsRe.ReplaceAll(bs, []byte("id=\"contributor-list\">\n"+replacement+"\n ")) if err := os.WriteFile(htmlFile, bs, 0o644); err != nil { @@ -125,8 +99,6 @@ func main() { // Write AUTHORS file - sort.Sort(byName(authors)) - out, err := os.Create("AUTHORS") if err != nil { log.Fatal(err) @@ -141,16 +113,22 @@ func main() { for _, email := range author.emails { fmt.Fprintf(out, " <%s>", email) } - fmt.Fprintf(out, "\n") + fmt.Fprint(out, "\n") } out.Close() } -func getAuthors() []author { - bs := readAll("AUTHORS") - lines := strings.Split(string(bs), "\n") - var authors []author +func getAuthors() *authorSet { + bs, err := os.ReadFile("AUTHORS") + if err != nil { + log.Fatal(err) + } + lines := strings.Split(string(bs), "\n") + authors := &authorSet{ + emails: make(map[string]int), + commits: make(map[string]stringSet), + } for _, line := range lines { if len(line) == 0 || line[0] == '#' { continue @@ -159,7 +137,9 @@ func getAuthors() []author { fields := strings.Fields(line) var author author for _, field := range fields { - if m := nicknameRe.FindStringSubmatch(field); len(m) > 1 { + if field == "#" { + break + } else if m := nicknameRe.FindStringSubmatch(field); len(m) > 1 { author.nickname = m[1] } else if m := emailRe.FindStringSubmatch(field); len(m) > 1 { author.emails = append(author.emails, m[1]) @@ -172,53 +152,11 @@ func getAuthors() []author { } } - authors = append(authors, author) + authors.add(author) } return authors } -func readAll(path string) []byte { - fd, err := os.Open(path) - if err != nil { - log.Fatal(err) - } - defer fd.Close() - - bs, err := io.ReadAll(fd) - if err != nil { - log.Fatal(err) - } - - return bs -} - -// Add number of commits per author to the author list. -func getContributions(authors []author) { - buf := new(bytes.Buffer) - cmd := exec.Command("git", "log", "--pretty=format:%ae") - cmd.Stdout = buf - err := cmd.Run() - if err != nil { - log.Fatal(err) - } - -next: - for _, line := range strings.Split(buf.String(), "\n") { - for i := range authors { - for _, email := range authors[i].emails { - if email == line { - authors[i].commits++ - continue next - } - } - } - } - - for i := range authors { - authors[i].log10commits = int(math.Log10(float64(authors[i].commits + 1))) - } -} - // list of commits that we don't include in our author file; because they // are legacy things that don't affect code, are committed with incorrect // address, or for other reasons. @@ -230,102 +168,95 @@ var excludeCommits = stringSetFromStrings([]string{ "9bdcadf6345aba3a939e9e58d85b89dbe9d44bc9", "b933e9666abdfcd22919dd458c930d944e1e1b7f", "b84d960a81c1282a79e2b9477558de4f1af6faae", + "4dfb9d7c83ed172f12ae19408517961f4a49beeb", }) // allAuthors returns the set of authors in the git commit log, except those // in excluded commits. -func allAuthors() map[string]string { - // Format is hash, email, name, newline, body. The body is indented with - // one space, to differentiate from the hash lines. - args := append([]string{"log", "--format=%H %ae %an%n%w(,1,1)%b"}) - cmd := exec.Command("git", args...) - bs, err := cmd.Output() +func addAuthors(authors *authorSet) { + // All existing source-tracked files + bs, err := exec.Command("git", "ls-tree", "-r", "HEAD", "--name-only").CombinedOutput() if err != nil { - log.Fatal("git:", err) + fmt.Println(string(bs)) + log.Fatal("git ls-tree:", err) } + files := strings.Split(string(bs), "\n") + files = slices.DeleteFunc(files, func(s string) bool { + return !(strings.HasPrefix(s, "assets/") || + strings.HasPrefix(s, "cmd/") || + strings.HasPrefix(s, "etc/") || + strings.HasPrefix(s, "gui/") || + strings.HasPrefix(s, "internal/") || + strings.HasPrefix(s, "lib/") || + strings.HasPrefix(s, "proto/") || + strings.HasPrefix(s, "script/") || + strings.HasPrefix(s, "test/") || + strings.HasPrefix(s, "Dockerfile") || + s == "build.go") + }) coAuthoredPrefix := "Co-authored-by: " - names := make(map[string]string) - skipCommit := false - for _, line := range bytes.Split(bs, []byte{'\n'}) { - if len(line) == 0 { - continue + for _, file := range files { + // All commits affecting those files, following any renames to their + // origin. Format is hash, email, name, newline, body. The body is + // indented with one space, to differentiate from the hash lines. + args := []string{"log", "--format=%H %ae %an%n%w(,1,1)%b", "--follow", "--", file} + bs, err = exec.Command("git", args...).CombinedOutput() + if err != nil { + fmt.Println(string(bs)) + log.Fatal("git log:", err) } - switch line[0] { - case ' ': - // Look for Co-authored-by: lines in the commit body. - if skipCommit { + skipCommit := false + var hash, email, name string + for _, line := range bytes.Split(bs, []byte{'\n'}) { + if len(line) == 0 { continue } - line = line[1:] - if bytes.HasPrefix(line, []byte(coAuthoredPrefix)) { - // Co-authored-by: Name Name - line = line[len(coAuthoredPrefix):] - if name, email, ok := strings.Cut(string(line), "<"); ok { - name = strings.TrimSpace(name) - email = strings.Trim(strings.TrimSpace(email), "<>") - if email == "@" { - // GitHub special for users who hide their email. - continue - } - if names[email] == "" { - names[email] = name + switch line[0] { + case ' ': + // Look for Co-authored-by: lines in the commit body. + if skipCommit { + continue + } + + line = line[1:] + if bytes.HasPrefix(line, []byte(coAuthoredPrefix)) { + // Co-authored-by: Name Name + line = line[len(coAuthoredPrefix):] + if name, email, ok := strings.Cut(string(line), "<"); ok { + name = strings.TrimSpace(name) + email = strings.Trim(strings.TrimSpace(email), "<>") + if email == "@" { + // GitHub special for users who hide their email. + continue + } + authors.setName(email, name) + authors.addCommit(email, hash) } } - } - default: // hash email name - fields := strings.SplitN(string(line), " ", 3) - if len(fields) != 3 { - continue - } - hash, email, name := fields[0], fields[1], fields[2] + default: // hash email name + fields := strings.SplitN(string(line), " ", 3) + if len(fields) != 3 { + continue + } + hash, email, name = fields[0], fields[1], fields[2] - if excludeCommits.has(hash) { - skipCommit = true - continue - } - skipCommit = false + if excludeCommits.has(hash) { + skipCommit = true + continue + } + skipCommit = false - if names[email] == "" { - names[email] = name + authors.setName(email, name) + authors.addCommit(email, hash) } } } - - return names } -type byContributions []author - -func (l byContributions) Len() int { return len(l) } - -// Sort first by log10(commits), then by name. This means that we first get -// an alphabetic list of people with >= 1000 commits, then a list of people -// with >= 100 commits, and so on. -func (l byContributions) Less(a, b int) bool { - if l[a].log10commits != l[b].log10commits { - return l[a].log10commits > l[b].log10commits - } - return l[a].name < l[b].name -} - -func (l byContributions) Swap(a, b int) { l[a], l[b] = l[b], l[a] } - -type byName []author - -func (l byName) Len() int { return len(l) } - -func (l byName) Less(a, b int) bool { - aname := strings.ToLower(l[a].name) - bname := strings.ToLower(l[b].name) - return aname < bname -} - -func (l byName) Swap(a, b int) { l[a], l[b] = l[b], l[a] } - // A simple string set type type stringSet map[string]struct{} @@ -347,12 +278,68 @@ func (s stringSet) has(e string) bool { return ok } -func (s stringSet) except(other stringSet) stringSet { - diff := make(stringSet) - for e := range s { - if !other.has(e) { - diff.add(e) +// A set of authors + +type authorSet struct { + authors []author + emails map[string]int // email to author index + commits map[string]stringSet // email to commit hashes +} + +func (a *authorSet) add(author author) { + for _, e := range author.emails { + if idx, ok := a.emails[e]; ok { + emails := append(author.emails, a.authors[idx].emails...) + slices.Sort(emails) + emails = slices.Compact(emails) + a.authors[idx].name = author.name + a.authors[idx].emails = emails + + for _, e := range emails { + a.emails[e] = idx + } + return } } - return diff + + for _, e := range author.emails { + a.emails[e] = len(a.authors) + } + a.authors = append(a.authors, author) +} + +func (a *authorSet) setName(email, name string) { + idx, ok := a.emails[email] + if !ok { + a.emails[email] = len(a.authors) + a.authors = append(a.authors, author{name: name, emails: []string{email}}) + } else if a.authors[idx].name == "" { + a.authors[idx].name = name + } +} + +func (a *authorSet) addCommit(email, hash string) { + ss, ok := a.commits[email] + if !ok { + ss = make(stringSet) + a.commits[email] = ss + } + ss.add(hash) +} + +func (a *authorSet) filteredAuthors() []author { + authors := make([]author, len(a.authors)) + copy(authors, a.authors) + for i, author := range authors { + for _, e := range author.emails { + authors[i].commits += len(a.commits[e]) + } + } + authors = slices.DeleteFunc(authors, func(a author) bool { + return a.commits == 0 || authorBotsRe.MatchString(a.name) + }) + for i := range authors { + authors[i].log10commits = int(math.Log10(float64(authors[i].commits))) + } + return authors }