util/release: Update gerrit_stats script to latest version

This updates a number of things:
- Move the cache directory under the .local directory
- Reformat & clean up with perltidy.  Add the perltidy command line.
- Add username and email aliases to clean up duplicates and unknown
  email addresses.
- Use full length commit IDs
- Collect patch commenters
- Check variables before using them as key values
- Ignore patch submit time, just collect the date
- Get stats about large patches
- Format the output better

Example output:
Statistics from commit c35f2819348501579a32e870e21f5f1b062d26e8 to commit f8fbf0917c722378454b07c2e8ec1a3f87b324ae
Patch, Date, Owner, Author, Submitter, Inserted lines, Deleted lines, Subject, Reviewers, Commenters
"f8fbf0917c722378454b07c2e8ec1a3f87b324ae", 2022/12/10, Frank Chu, Frank Chu, Martin Roth, 22, 1, "mb/google/brya/var/marasov: Change FSP board type to Type3", "Frank Chu, Eric Lai" , "-"
"5778e06771627a5541ca2b137e783f47257f05ec", 2022/12/10, Dinesh Gehlot, Dinesh Gehlot, Subrata Banik, 30, 1, "soc/intel/meteorlake: Drop casts around `soc_read_pmc_base()`", "Kapil Porwal, Elyes Haouas" , "Subrata Banik"
"ed8bdefcdf6c19258febb9931d1e8eb12b958bcc", 2022/12/10, Jamie Ryu, Jamie Ryu, Felix Held, 76, 3, "mb/intel/mtlrvp: Add MTL-P RVP board ids", "Usha P,
Sridhar Siricilla, Eric Lai, Subrata Banik" , "Eric Lai, Subrata Banik, Harsha B R, Angel Pons"

- Total Commits: 985
- Average Commits per day: 17.85
- Total lines added: 61475
- Average lines added per commit: 62.41
- Number of patches adding more than 100 lines: 49
- Average lines added per small commit: 37.82
- Total lines removed: 758022
- Average lines removed per commit: 769.57
- Total difference between added and removed: -696547

=== Authors - Number of commits ===
Author                         ,Ptchs ,Revws , Cmnts , Sbmts , Email                                                , Prcnt, Last commit         ,
Earliest_commit
Elyes Haouas                   ,  126 ,   90 ,    28 ,     0 , ehaouas@noos.fr                                      ,12.79%, 2022/12/10 , 2022/10/17
Arthur Heymans                 ,  107 ,   99 ,    28 ,    40 , arthur@aheymans.xyz                                  ,10.86%, 2022/12/10 , 2022/10/17

=== Authors - Lines added ===
Martin Roth                   ,      10103, 16.434%
Kyösti Mälkki                 ,       6044, 9.832%
Arthur Heymans                ,       3314, 5.391%

=== Authors - Lines removed ===
Arthur Heymans                ,    -741944, 97.879%
Felix Held                    ,      -3031,  0.400%
Kyösti Mälkki                 ,      -1680,  0.222%

=== Reviewers - Number of patches reviewed ===
Angel Pons                    ,    272, 27.614%
Eric Lai                      ,    201, 20.406%
Felix Held                    ,    106, 10.761%

=== Submitters - Number of patches submitted ===
Name                          ,      #,  total%,    Own,    own%,  Other,  other%
Felix Held                    ,    482, 48.934%,     56,  11.62%,    426,  88.38%
Martin Roth                   ,    179, 18.173%,     42,  23.46%,    137,  76.54%
Subrata Banik                 ,     54,  5.482%,     31,  57.41%,     23,  42.59%

Signed-off-by: Martin Roth <gaumless@gmail.com>
Change-Id: Ie1694116ab36ca4db25d13935adadca10e50068f
Reviewed-on: https://review.coreboot.org/c/coreboot/+/70572
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Felix Singer <felixsinger@posteo.net>
diff --git a/util/release/gerrit_stats.pl b/util/release/gerrit_stats.pl
index 9468157..789cb05 100755
--- a/util/release/gerrit_stats.pl
+++ b/util/release/gerrit_stats.pl
@@ -8,6 +8,8 @@
 #  sudo cpan App::cpanminus
 #  sudo /usr/local/bin/cpanm JSON::Util Net::OpenSSH DateTime Devel::Size
 
+# perltidy -l=200 -bt=2 -ce
+
 use strict;
 use warnings;
 use English qw( -no_match_vars );
@@ -23,7 +25,7 @@
 
 my $old_version;
 my $new_version;
-my $infodir="$ENV{'HOME'}/.commit_info/" . `git config -l | grep remote.origin.url | sed 's|.*@||' | sed 's|:.*||'`;
+my $infodir = "$ENV{'HOME'}/.local/commit_info/" . `git config -l | grep remote.origin.url | sed 's|.*@||' | sed 's|:.*||'`;
 chomp($infodir);
 my $URL_WITH_USER;
 my $SKIP_GERRIT_CHECK;
@@ -41,106 +43,275 @@
 sub Main {
     check_arguments();
 
-    my %submitters = ();
-    my %authors = ();
-    my %owners = ();
-    my %reviewers = ();
-    my %author_added = ();
-    my %author_removed = ();
-    my $total_added = 0;
-    my $total_removed = 0;
-    my $number_of_commits = 0;
-    my $number_of_submitters = 0;
-    my $submit_epoch = "";
-    my $first_submit_epoch = "";
-    if (!$URL_WITH_USER) {
-        get_user()
+    my %submitters                = ();
+    my %authors                   = ();
+    my %owners                    = ();
+    my %reviewers                 = ();
+    my %commenters                = ();
+    my %author_added              = ();
+    my %author_removed            = ();
+    my $total_added               = 0;
+    my $total_removed             = 0;
+    my $number_of_commits         = 0;
+    my $number_of_submitters      = 0;
+    my $submit_epoch              = "";
+    my $first_submit_epoch        = "";
+    my $patches_over_100_lines    = 0;
+    my $total_lines_large_patches = 0;
+    my %email_addresses           = (
+        'Kacper Stojek' => 'kacper.stojek@3mdeb.com',
+        'Damien Zammit' => 'damien@zamaudio.com',
+        'Pavel Sayekat' => 'pavelsayekat@gmail.com',
+        'Lance Zhao'    => 'lance.zhao@gmail.com',
+    );
+
+    my %aliases = (
+        ' Felix Singer'                        => 'Felix Singer',
+        'Abhay kumar'                          => 'Abhay Kumar',
+        'AlexandruX Gagniuc'                   => 'Alexandru Gagniuc',
+        'Anish K. Patel'                       => 'Anish K Patel',
+        'Bao Zheng'                            => 'Zheng Bao',
+        'Bernhard M. Wiedemann'                => 'Bernhard M. Wiedermann',
+        'Björn Busse'                         => 'Bjarn Busse',
+        'BryantOu'                             => 'Bryant Ou',
+        'Chen Wisley'                          => 'Wisley Chen',
+        'Cheng-Yi Chiang'                      => 'Jimmy Cheng-Yi Chiang',
+        'Chris Ching (using chromium account)' => 'Chris Ching,',
+        'ChromeOS Developer'                   => 'Dave Parker',
+        'Cristi M'                             => 'Cristian Magherusan-Stanciu',
+        'Cristian M?gheru?an-Stanciu'          => 'Cristian Magherusan-Stanciu',
+        'Cristian MÄgheruÈan-Stanciu'          => 'Cristian Magherusan-Stanciu',
+        'Cristian MÄgheruÈan-Stanciu'          => 'Cristian Magherusan-Stanciu',
+        'DAWEI CHIEN'                          => 'Dawei Chien',
+        'efdesign98'                           => 'Frank Vibrans',
+        'Eugene D. Myers'                      => 'Eugene Myers',
+        'Frank Vibrans III'                    => 'Frank Vibrans',
+        'frank vibrans'                        => 'Frank Vibrans',
+        'Frank.Vibrans'                        => 'Frank Vibrans',
+        'FrankChu'                             => 'Frank Chu',
+        'garmin chang'                         => 'Garmin Chang',
+        'Garmin.Chang'                         => 'Garmin Chang',
+        'hannahwilliams2'                      => 'Hannah Williams',
+        'HAOUAS Elyes'                         => 'Elyes Haouas',
+        'Harshapriya N'                        => 'Harsha Priya',
+        'Hsuan-ting Chen'                      => 'Hsuan Ting Chen',
+        'Iru Cai (vimacs)'                     => 'Iru Cai',
+        'Jérémy Compostella'                   => 'Jeremy Compostella',
+        'Jérémy Compostella'                   => 'Jeremy Compostella',
+        'JG Poxu'                              => 'Po Xu',
+        'JonathonHall-Purism'                  => 'Jonathon Hall',
+        'Karthikeyan Ramasubramanian'          => 'Karthik Ramasubramanian',
+        'Kerry She'                            => 'Kerry Sheh',
+        'kewei.xu'                             => 'kewei xu',
+        'Kumar, Gomathi'                       => 'Gomathi Kumar',
+        'Kyösti Mälkki'                      => 'Kyösti Mälkki',
+        'Kyösti Mälkki'                        => 'Kyösti Mälkki',
+        'Marcello Sylvester Bauer'             => 'Marcello Sylvester Bauer',
+        'Martin L Roth'                        => 'Martin Roth',
+        'Martin Roth - Personal'               => 'Martin Roth',
+        'Matt Ziegelbaum'                      => 'Matthew Ziegelbaum',
+        'mengqi.zhang'                         => 'Mengqi Zhang',
+        'mrnuke'                               => 'Alexandru Gagniuc',
+        'Nina-CM Wu'                           => 'Nina Wu',
+        'ot_zhenguo.li'                        => 'Zhenguo Li',
+        'Patrick Georgi patrick.georgi'        => 'Patrick Georgi',
+        'Patrick Georgi patrick'               => 'Patrick Georgi',
+        'Pavlushka'                            => 'Pavel Sayekat',
+        'Ravi Kumar Bokka'                     => 'Ravi Kumar',
+        'Ravi kumar'                           => 'Ravi Kumar',
+        'Ravi Sarawadi'                        => 'Ravishankar Sarawadi',
+        'ravindr1'                             => 'Ravindra',
+        'Ravindra N'                           => 'Ravindra',
+        'Ricardo Ribalda Delgado'              => 'Ricardo Ribalda',
+        'ron minnich'                          => 'Ron Minnich',
+        'Ronald G. Minnich'                    => 'Ron Minnich',
+        'samrab'                               => 'Sudheer Amrabadi',
+        'SANTHOSH JANARDHANA HASSAN'           => 'Santhosh Janardhana Hassan',
+        'semihalf-czapiga-jakub'               => 'Jakub Czapiga',
+        'Seunghwan Kim'                        => 'SH Kim',
+        'Sooi, Li Cheng'                       => 'Li Cheng Sooi',
+        'Stefan Reinauerstepan'                => 'Stefan Reinauer',
+        'stepan'                               => 'Stefan Reinauer',
+        'Swift Geek (Sebastian Grzywna)'       => 'Sebastian "Swift Geek" Grzywna',
+        'Sylvain "ythier" Hitier'              => 'Sylvain Hitier',
+        'Thomas Gstädtner'                    => 'Thomas Gstaedtner',
+        'UwePoeche'                            => 'Uwe Poeche',
+        'UwePoeche'                            => 'Uwe Poeche',
+        'Varshit Pandya'                       => 'Varshit B Pandya',
+        'Wayne3 Wang'                          => 'Wayne Wang',
+        'Wayne3_Wang'                          => 'Wayne Wang',
+        'Xi Chen'                              => 'Xixi Chen',
+        'Yu-Hsuan Hsu'                         => 'Yu-hsuan Hsu',
+        'zbao'                                 => 'Zheng Bao',
+        'Zheng Bao zheng.bao'                  => 'Zheng Bao',
+        'zhiyong tao'                          => 'Zhiyong Tao',
+        'Дмитрий Понаморев'                    => 'Dmitry Ponamorev',
+    );
+
+    if ( !$URL_WITH_USER ) {
+        get_user();
     }
 
-     # make sure the versions exist
+    print "Saving data to $infodir\n";
+
+    # Make sure the versions exist
     check_versions();
 
-    #fetch patches if needed.  Get ids of first and last commits
-    my @commits = `git log --pretty=%h "$old_version..$new_version" 2>/dev/null`;
+    # Fetch patches if needed.  Get ids of first and last commits
+    my @commits = `git log --pretty=%H "$old_version..$new_version" 2>/dev/null`;
     get_commits(@commits);
-    my $last_commit_id = $commits[0];
-    my $first_commit_id = $commits[@commits - 1];
+    my $last_commit_id  = $commits[0];
+    my $first_commit_id = $commits[ @commits - 1 ];
     chomp $last_commit_id;
     chomp $first_commit_id;
 
     print "Statistics from commit $first_commit_id to commit $last_commit_id\n";
-    print "Patch, Date, Owner, Author, Submitter, Inserted lines, Deleted lines, Subject, Reviewers\n";
+    print "Patch, Date, Owner, Author, Submitter, Inserted lines, Deleted lines, Subject, Reviewers, Commenters\n";
 
-    #loop through all commits
+    # Loop through all commits
     for my $commit_id (@commits) {
         $commit_id =~ s/^\s+|\s+$//g;
 
-        my $submitter = "";
-        my %patch_reviewers = ();
+        my $submitter        = "";
+        my %patch_reviewers  = ();
+        my %patch_commenters = ();
         my $info;
         my $owner;
         my $author;
         my $author_email;
         my $inserted_lines = 0;
-        my $deleted_lines = 0;
+        my $deleted_lines  = 0;
         my $subject;
 
         $number_of_commits++;
         print "\"$commit_id\", ";
 
-        #read the data file for the current commit
-        if (-f  "$infodir/$commit_id" && -s "$infodir/$commit_id" > 20) {
+        # Read the data file for the current commit
+        if ( -f "$infodir/$commit_id" && -s "$infodir/$commit_id" > 20 ) {
             open( my $HANDLE, "<", "$infodir/$commit_id" ) or die "Error: could not open file '$infodir/$commit_id'\n";
             $info = <$HANDLE>;
             close $HANDLE;
 
             my $commit_info = JSON::Util->decode($info);
 
-            #get the easy data
+            # Get the easy data
             $owner = $commit_info->{'owner'}{'name'};
-            if (! $owner) {
+            if ( !$owner ) {
                 $owner = $commit_info->{'owner'}{'username'};
             }
-            if (! $owner) {
-                $owner = "";
+            if ( !$owner ) {
+                $owner = "-";
             }
-            $author = $commit_info->{'currentPatchSet'}{'author'}{'name'};
-            $author_email = $commit_info->{'currentPatchSet'}{'author'}{'email'};
-            if (! $author) {
-                $author = $commit_info->{'currentPatchSet'}{'author'}{'username'};
+            if ( $owner && exists( $aliases{$owner} ) ) {
+                $owner = $aliases{$owner};
             }
 
+            $author = $commit_info->{'currentPatchSet'}{'author'}{'name'};
+            if ( $author && exists( $aliases{$author} ) ) {
+                $author = $aliases{$author};
+            }
+            if ( !$author ) {
+                $author = $commit_info->{'currentPatchSet'}{'author'}{'username'};
+            }
+            $author_email   = $commit_info->{'currentPatchSet'}{'author'}{'email'};
             $inserted_lines = $commit_info->{'currentPatchSet'}{'sizeInsertions'};
-            $deleted_lines = $commit_info->{'currentPatchSet'}{'sizeDeletions'};
-            $subject = $commit_info->{'subject'};
+            $deleted_lines  = $commit_info->{'currentPatchSet'}{'sizeDeletions'};
+            $subject        = $commit_info->{'subject'};
 
             #get the patch's submitter
             my $approvals = $commit_info->{'currentPatchSet'}{'approvals'};
             for my $approval (@$approvals) {
-                if ($approval->{'type'} eq "SUBM") {
+                if ( $approval->{'type'} eq "SUBM" ) {
                     $submit_epoch = $approval->{'grantedOn'};
-                    $submitter = $approval->{'by'}{'name'};
+                    $submitter    = $approval->{'by'}{'name'};
+                    if ( exists( $aliases{$submitter} ) ) {
+                        $submitter = $aliases{$submitter};
+                    }
                 }
             }
 
-            #get all the reviewers for all patch revisions
+            # Get all the commenters for all patch revisions
+            my $comments = $commit_info->{'comments'};
+            for my $comment (@$comments) {
+                my $commenter;
+                if ( $comment->{'reviewer'}{'username'} ) {
+                    if ( $comment->{'reviewer'}{'username'} eq "jenkins" ) {
+                        next;
+                    }
+                    if ( $comment->{'reviewer'}{'username'} eq "hardwaretestrobot" ) {
+                        next;
+                    }
+                    if ( $comment->{'reviewer'}{'username'} eq "raptor-automated-test" ) {
+                        next;
+                    }
+                }
+
+                if ( $comment->{'reviewer'}{'name'} ) {
+                    if ( $comment->{'reviewer'}{'name'} eq "Gerrit Code Review" ) {
+                        next;
+                    }
+                }
+                if ( $comment->{'message'} ) {
+                    if ( $comment->{'message'} =~ "successfully cherry-picked" ) {
+                        next;
+                    }
+                    if ( $comment->{'message'} =~ ": Code-Review" ) {
+                        next;
+                    }
+                    if ( $comment->{'message'} =~ "Uploaded patch set" ) {
+                        next;
+                    }
+                }
+
+                if ( !$commenter ) {
+                    $commenter = $comment->{'reviewer'}{'name'};
+                    if ( $commenter && exists( $aliases{$commenter} ) ) {
+                        $commenter = $aliases{$commenter};
+                    }
+                }
+                if ( !$commenter ) {
+                    $commenter = $comment->{'reviewer'}{'username'};
+                    if ( $commenter && exists( $aliases{$commenter} ) ) {
+                        $commenter = $aliases{$commenter};
+                    }
+                }
+                if ( $commenter && $author && $commenter eq $author ) {
+                    next;
+                }
+                if ($commenter) {
+                    if ( $commenter && exists $patch_commenters{$commenter} ) {
+                        $patch_commenters{$commenter}++;
+                    } else {
+                        $patch_commenters{$commenter} = 1;
+                    }
+                }
+            }
+
+            # Get all the reviewers for all patch revisions
             my $patchsets = $commit_info->{'patchSets'};
             for my $patch (@$patchsets) {
-                if (! $author) {
+                if ( !$author ) {
                     $author = $patch->{'author'}{'name'};
+                    if ( $author && exists( $aliases{$author} ) ) {
+                        $author = $aliases{$author};
+                    }
                 }
+
                 my $approvals = $patch->{'approvals'};
                 for my $approval (@$approvals) {
 
-                    if ( (! $submitter) && ($approval->{'type'} eq "SUBM")) {
+                    if ( ( !$submitter ) && ( $approval->{'type'} eq "SUBM" ) ) {
                         $submit_epoch = $approval->{'grantedOn'};
-                        $submitter = $approval->{'by'}{'name'};
+                        $submitter    = $approval->{'by'}{'name'};
+                        if ( $submitter && exists( $aliases{$submitter} ) ) {
+                            $submitter = $aliases{$submitter};
+                        }
                     }
 
-                    if ($approval->{'type'} eq "Code-Review") {
+                    if ( $approval->{'type'} eq "Code-Review" ) {
                         my $patch_reviewer = $approval->{'by'}{'name'};
                         if ($patch_reviewer) {
-                            if (exists $patch_reviewers{$patch_reviewer}) {
+                            if ( exists $patch_reviewers{$patch_reviewer} ) {
                                 $patch_reviewers{$patch_reviewer}++;
                             } else {
                                 $patch_reviewers{$patch_reviewer} = 1;
@@ -151,24 +322,36 @@
             }
 
         } else {
-            # get the info from git
+
+            # Get the info from git
             my $logline = `git log --pretty="%ct@@@%s@@@%an@@@%aE@@@%cn" $commit_id^..$commit_id --`;
             $logline =~ m/^(.*)@@@(.*)@@@(.*)@@@(.*)@@@(.*)\n/;
-            ($submit_epoch, $subject, $author, $author_email, $submitter) = ($1, $2, $3, $4, $5);
+            ( $submit_epoch, $subject, $author, $author_email, $submitter ) = ( $1, $2, $3, $4, $5 );
+            if ( exists( $aliases{$author} ) ) {
+                $author = $aliases{$author};
+            }
             $owner = $author;
+
+            if ( $submitter && exists( $aliases{$submitter} ) ) {
+                $submitter = $aliases{$submitter};
+            }
+
             $logline = `git log --pretty= --shortstat $commit_id^..$commit_id --`;
-            if ($logline =~ m/\s+(\d+)\s+insertion/) {
+            if ( $logline =~ m/\s+(\d+)\s+insertion/ ) {
                 $inserted_lines = $1;
             }
-            if ($logline =~ m/\s+(\d+)\s+deletion/) {
+            if ( $logline =~ m/\s+(\d+)\s+deletion/ ) {
                 $deleted_lines = $1 * -1;
             }
             my @loglines = `git log $commit_id^..$commit_id -- | grep '\\sReviewed-by:'`;
-            for my $line (@loglines){
-                if ($line =~ m/.*:\s+(.*)\s</) {
+            for my $line (@loglines) {
+                if ( $line =~ m/.*:\s+(.*)\s</ ) {
                     my $patch_reviewer = $1;
+                    if ( exists( $aliases{$patch_reviewer} ) ) {
+                        $patch_reviewer = $aliases{$patch_reviewer};
+                    }
                     if ($patch_reviewer) {
-                        if (exists $patch_reviewers{$patch_reviewer}) {
+                        if ( exists $patch_reviewers{$patch_reviewer} ) {
                             $patch_reviewers{$patch_reviewer}++;
                         } else {
                             $patch_reviewers{$patch_reviewer} = 1;
@@ -181,155 +364,230 @@
 
         # Not entirely certain why this is needed, but for a number of patches have been submitted
         # the submit time in gerrit is set to April 9, 2015.
-        if ($submit_epoch == 1428586219){
+        if ( $submit_epoch == 1428586219 ) {
             my $logline = `git log --pretty="%ct" $commit_id^..$commit_id --`;
             $logline =~ m/^(.*)\n/;
             $submit_epoch = $1;
         }
 
-        #add the count and owner to the submitter hash
-        if (exists $submitters{$submitter}) {
-            $submitters{$submitter}++;
+        # Add the count and owner to the submitter hash
+        if ( $submitter && exists $submitters{$submitter} && exists $submitters{$submitter}{count} ) {
+            $submitters{$submitter}{count}++;
         } else {
-            $submitters{$submitter} = 1;
+            $submitters{$submitter}{count} = 1;
             $number_of_submitters++;
+            $submitters{$submitter}{"self"} = 0;
+            $submitters{$submitter}{others} = 0;
+            $submitters{$submitter}{name}   = $submitter;
         }
 
-        #create a readable date
-        my $dt = DateTime->from_epoch(epoch => $submit_epoch);
-        $dt->set_time_zone( 'Europe/Paris' );
-        my $submit_time = $dt->strftime('%Y/%m/%d %H:%M:%S');
-        if (!$first_submit_epoch) {
+        if ( $submitter eq $author ) {
+            $submitters{$submitter}{"self"}++;
+        } else {
+            $submitters{$submitter}{others}++;
+        }
+
+        # Create a readable date
+        my $dt = DateTime->from_epoch( epoch => $submit_epoch );
+        $dt->set_time_zone('Europe/Paris');
+        my $submit_time = $dt->strftime('%Y/%m/%d');
+        if ( !$first_submit_epoch ) {
             $first_submit_epoch = $submit_epoch;
         }
 
-        #create the list of reviewers to print
+        # Create the list of commenters to print
+        my $commenterlist = "";
+        foreach my $commenter ( keys %patch_commenters ) {
+            if ( $commenter && exists( $aliases{$commenter} ) ) {
+                $commenter = $aliases{$commenter};
+            }
+
+            if ( $commenterlist eq "" ) {
+                $commenterlist = $commenter;
+            } else {
+                $commenterlist .= ", $commenter";
+            }
+
+            if ( $commenter && exists $commenters{$commenter} ) {
+                $commenters{$commenter}++;
+            } else {
+                $commenters{$commenter} = 1;
+            }
+        }
+        if ( !$commenterlist ) {
+            $commenterlist = "-";
+        }
+
+        # Create the list of reviewers to print
         my $reviewerlist = "";
-        foreach my $reviewer (keys %patch_reviewers) {
-            if ($reviewerlist eq "") {
+        foreach my $reviewer ( keys %patch_reviewers ) {
+            if ( exists( $aliases{$reviewer} ) ) {
+                $reviewer = $aliases{$reviewer};
+            }
+
+            if ( $reviewerlist eq "" ) {
                 $reviewerlist = $reviewer;
             } else {
                 $reviewerlist .= ", $reviewer";
             }
 
-            if (exists $reviewers{$reviewer}) {
+            if ( $reviewer && exists $reviewers{$reviewer} ) {
                 $reviewers{$reviewer}++;
             } else {
                 $reviewers{$reviewer} = 1;
             }
         }
-        if (! $reviewerlist) {
-            $reviewerlist = "-"
+        if ( !$reviewerlist ) {
+            $reviewerlist = "-";
         }
 
         if ($print_commit_list) {
-            print "$submit_time, $owner, $author, $submitter, $inserted_lines, $deleted_lines, \"$subject\", \"$reviewerlist\"\n";
+            print "$submit_time, $owner, $author, $submitter, $inserted_lines, $deleted_lines, \"$subject\", \"$reviewerlist\" , \"$commenterlist\"\n";
         } else {
             print "$number_of_commits\n";
         }
         $total_added += $inserted_lines;
+        if ( $inserted_lines - $deleted_lines > 100 ) {
+            $patches_over_100_lines++;
+            $total_lines_large_patches += $inserted_lines;
+        }
         $total_removed += $deleted_lines;
-        if (exists $owners{$owner}) {
+        if ( exists $owners{$owner} ) {
             $owners{$owner}++;
         } else {
             $owners{$owner} = 1;
         }
 
-        if (exists $authors{$author}{"num"}) {
+        if ( $author && exists $authors{$author}{"num"} ) {
             $authors{$author}{"num"}++;
-            $author_added{$author} += $inserted_lines;
+            $author_added{$author}   += $inserted_lines;
             $author_removed{$author} += $deleted_lines;
-            $authors{$author}{"earliest_commit"}=$submit_time;
+            $authors{$author}{"earliest_commit"} = $submit_time;
         } else {
-            $authors{$author}{"num"} = 1;
-            $authors{$author}{"latest_commit"}=$submit_time;
-            $authors{$author}{"earliest_commit"}=$submit_time;
-            $author_added{$author} = $inserted_lines;
-            $author_removed{$author} = $deleted_lines;
+            $authors{$author}{"num"}             = 1;
+            $authors{$author}{"latest_commit"}   = $submit_time;
+            $authors{$author}{"earliest_commit"} = $submit_time;
+            $author_added{$author}               = $inserted_lines;
+            $author_removed{$author}             = $deleted_lines;
         }
-        if (! exists $authors{$author}{email} && $author_email) {
-            $authors{$author}{email} = "$author_email";
+        if ( $author && ( !exists $authors{$author}{email} || $authors{$author}{email} eq "-" ) ) {
+            if ($author_email) {
+                $authors{$author}{email} = "$author_email";
+            } elsif ( exists $email_addresses{$author} ) {
+                $authors{$author}{email} = $email_addresses{$author};
+            }
         }
     }
-    my $Days = ($first_submit_epoch - $submit_epoch) / 86400;
-    if (($first_submit_epoch - $submit_epoch) % 86400) {
+    my $Days = ( $first_submit_epoch - $submit_epoch ) / 86400;
+    if ( ( $first_submit_epoch - $submit_epoch ) % 86400 ) {
         $Days += 1;
     }
 
-    print "- Total Commits: $number_of_commits\n";
+    print "\n- Total Commits: $number_of_commits\n";
     printf "- Average Commits per day: %.2f\n", $number_of_commits / $Days;
     print "- Total lines added: $total_added\n";
+    printf "- Average lines added per commit: %.2f\n", $total_added / $number_of_commits;
+    print "- Number of patches adding more than 100 lines: $patches_over_100_lines\n";
+    printf "- Average lines added per small commit: %.2f\n", ( $total_added - $total_lines_large_patches ) / ( $number_of_commits - $patches_over_100_lines );
+
     print "- Total lines removed: $total_removed\n";
-    print "- Total difference: " . ($total_added + $total_removed) . "\n\n";
+    printf "- Average lines removed per commit: %.2f\n", $total_removed / $number_of_commits;
+    print "- Total difference between added and removed: " . ( $total_added - $total_removed ) . "\n\n";
 
     print "=== Authors - Number of commits ===\n";
+    printf "%-30s ,%5s ,%5s ,%6s ,%6s , %-52s ,%6s, %-19s , %s\n", "Author", "Ptchs", "Revws", "Cmnts", "Sbmts", "Email", "Prcnt", "Last commit", "Earliest_commit";
+
     my $number_of_authors = 0;
-    foreach my $author (sort { $authors{$b}{num} <=> $authors{$a}{num} } (keys %authors) ) {
-	if (! exists $authors{$author}{"email"}) {
-		$authors{$author}{"email"} = "-";
-	}
-        printf "%-25s %5d %-40s (%2.2f%%) {%s / %s}\n",$author, $authors{$author}{"num"}, $authors{$author}{"email"}, $authors{$author}{"num"} / $number_of_commits * 100, $authors{$author}{"latest_commit"}, $authors{$author}{"earliest_commit"};
+    foreach my $author ( sort { $authors{$b}{num} <=> $authors{$a}{num} } ( keys %authors ) ) {
+        my $submissions = 0;
+        if ( $author && exists $submitters{$author} ) {
+            $submissions = $submitters{$author}{count};
+        }
+        my $review_count = 0;
+        if ( $author && exists $reviewers{$author} ) {
+            $review_count = $reviewers{$author};
+        }
+
+        my $comment_count = 0;
+        if ( $author && exists $commenters{$author} ) {
+            $comment_count = $commenters{$author};
+        }
+
+        if ( $author && !exists $authors{$author}{"email"} ) {
+            $authors{$author}{"email"} = "-";
+        }
+
+        printf "%-30s ,%5d ,%5d ,%6d ,%6d , %-52s ,%5.2f%%, %s , %s\n", $author, $authors{$author}{"num"}, $review_count,
+          $comment_count, $submissions, $authors{$author}{"email"}, $authors{$author}{"num"} / $number_of_commits * 100,
+          $authors{$author}{"latest_commit"}, $authors{$author}{"earliest_commit"};
         $number_of_authors++;
     }
     print "Total Authors: $number_of_authors\n\n";
 
     print "=== Authors - Lines added ===\n";
-    foreach my $author (sort { $author_added{$b} <=> $author_added{$a} } (keys %author_added) ) {
-        if ($author_added{$author}) {
-            printf "%-25s %5d (%2.3f%%)\n",$author, $author_added{$author}, $author_added{$author} / $total_added * 100;
+    foreach my $author ( sort { $author_added{$b} <=> $author_added{$a} } ( keys %author_added ) ) {
+        if ( $author_added{$author} ) {
+            printf "%-30s, %10d, %2.3f%%\n", $author, $author_added{$author}, $author_added{$author} / $total_added * 100;
         }
     }
     print "\n";
 
     print "=== Authors - Lines removed ===\n";
-    foreach my $author (sort { $author_removed{$a} <=> $author_removed{$b} } (keys %author_removed) ) {
-        if ($author_removed{$author}) {
-            printf "%-25s %5d (%2.3f%%)\n",$author,$author_removed{$author} * -1, $author_removed{$author} / $total_removed * 100;
+    foreach my $author ( sort { $author_removed{$b} <=> $author_removed{$a} } ( keys %author_removed ) ) {
+        if ( $author_removed{$author} ) {
+            printf "%-30s, %10d, %6.3f%%\n", $author, $author_removed{$author} * -1, $author_removed{$author} / $total_removed * 100;
         }
     }
     print "\n";
 
     print "=== Reviewers - Number of patches reviewed ===\n";
     my $number_of_reviewers = 0;
-    foreach my $reviewer (sort { $reviewers{$b} <=> $reviewers{$a} } (keys %reviewers) ) {
-        printf "%-25s %5d (%2.3f%%)\n",$reviewer, $reviewers{$reviewer}, $reviewers{$reviewer} / $number_of_commits * 100;
+    foreach my $reviewer ( sort { $reviewers{$b} <=> $reviewers{$a} } ( keys %reviewers ) ) {
+        printf "%-30s, %6d, %6.3f%%\n", $reviewer, $reviewers{$reviewer}, $reviewers{$reviewer} / $number_of_commits * 100;
         $number_of_reviewers++;
     }
     print "Total Reviewers: $number_of_reviewers\n\n";
 
     print "=== Submitters - Number of patches submitted ===\n";
-    foreach my $submitter (sort { $submitters{$b} <=> $submitters{$a} } (keys %submitters) ) {
-        printf "%-25s %5d (%2.3f%%)\n",$submitter, $submitters{$submitter}, $submitters{$submitter} / $number_of_commits * 100;
+    printf "%-30s, %6s, %7s, %6s, %7s, %6s, %7s\n", "Name", "#", "total%", "Own", "own%", "Other", "other%";
+    foreach my $submitter ( sort { $submitters{$b}{count} <=> $submitters{$a}{count} } ( keys %submitters ) ) {
+        printf "%-30s, % 6d, %6.3f%%, %6d, %6.2f%%, %6d, %6.2f%%\n",
+          $submitter,
+          $submitters{$submitter}{count},
+          $submitters{$submitter}{count} / $number_of_commits * 100,
+          $submitters{$submitter}{"self"},
+          $submitters{$submitter}{"self"} / $submitters{$submitter}{count} * 100,
+          $submitters{$submitter}{others}, $submitters{$submitter}{others} / $submitters{$submitter}{count} * 100;
     }
     print "Total Submitters: $number_of_submitters\n\n";
 
     print "Commits, Ave, Added, Removed, Diff, Authors, Reviewers, Submitters\n";
-    printf "$number_of_commits, %.2f, $total_added, $total_removed, " . ($total_added + $total_removed) . ", $number_of_authors, $number_of_reviewers, $number_of_submitters\n", $number_of_commits / $Days;
+    printf "$number_of_commits, %.2f, $total_added, $total_removed, " . ( $total_added + $total_removed ) . ", $number_of_authors, $number_of_reviewers, $number_of_submitters\n",
+      $number_of_commits / $Days;
 }
 
 #-------------------------------------------------------------------------------
 #-------------------------------------------------------------------------------
 sub check_versions {
     `git cat-file -e $old_version^{commit} 2>/dev/null`;
-    if (${^CHILD_ERROR_NATIVE}){
+    if ( ${^CHILD_ERROR_NATIVE} ) {
         print "Error: Old version ($old_version) does not exist.\n";
         exit 1;
     }
 
     `git cat-file -e $new_version^{commit} 2>/dev/null`;
-    if (${^CHILD_ERROR_NATIVE}){
+    if ( ${^CHILD_ERROR_NATIVE} ) {
         print "Error: New version ($new_version) does not exist.\n";
         exit 1;
     }
 }
 
 #-------------------------------------------------------------------------------
-#-------------------------------------------------------------------------------
 sub get_user {
-    my $url=`git config -l | grep remote.origin.url`;
 
-    if ($url =~ /.*url=ssh:\/\/(\w+@[a-zA-Z][a-zA-Z0-9\.]+:\d+)/)
-    {
+    my $url = `git config -l | grep remote.origin.url`;
+
+    if ( $url =~ /.*url=ssh:\/\/(\w+@[a-zA-Z][a-zA-Z0-9\.]+:\d+)(\/\w+)*/ ) {
         $URL_WITH_USER = $1;
     } else {
         print "Error: Could not get a ssh url with a username from gitconfig.\n";
@@ -341,44 +599,44 @@
 #-------------------------------------------------------------------------------
 #-------------------------------------------------------------------------------
 sub get_commits {
-    my @commits = @_;
+    my @commits     = @_;
     my $submit_time = "";
-    if (defined $SKIP_GERRIT_CHECK) {
+    if ( defined $SKIP_GERRIT_CHECK && $SKIP_GERRIT_CHECK ) {
         return;
     }
-    my $ssh = Net::OpenSSH->new("$URL_WITH_USER", );
-    $ssh->error and die "Couldn't establish SSH connection to $URL_WITH_USER:". $ssh->error;
+    my $ssh = Net::OpenSSH->new( "$URL_WITH_USER", );
+    $ssh->error and die "Couldn't establish SSH connection to $URL_WITH_USER:" . $ssh->error;
 
     print "Using URL: ssh://$URL_WITH_USER\n";
 
-    if (! -d $infodir) {
-        mkpath($infodir)
+    if ( !-d $infodir ) {
+        mkpath($infodir);
     }
 
     for my $commit_id (@commits) {
         $commit_id =~ s/^\s+|\s+$//g;
         $submit_time = "";
-            my $gerrit_review;
+        my $gerrit_review;
 
-        # Quit if we've reeached the last coreboot commit supporting these queries
-        if ($commit_id =~ /^7309709/) {
+        # Look for last coreboot commit
+        if ( $commit_id eq "7309709742" ) {
             last;
         }
 
-        if (-f "$infodir/$commit_id") {
+        if ( -f "$infodir/$commit_id" ) {
             $gerrit_review = 1;
         } else {
             $gerrit_review = `git log $commit_id^..$commit_id | grep '\\sReviewed-on:\\s'`;
         }
 
-        if ($gerrit_review && $commit_id && (! -f "$infodir/$commit_id") ) {
+        if ( $gerrit_review && $commit_id && ( !-f "$infodir/$commit_id" ) ) {
             print "Downloading $commit_id";
             my @info = $ssh->capture("gerrit query --format=JSON --comments --files --current-patch-set --all-approvals --submit-records --dependencies commit:$commit_id");
             $ssh->error and die "remote ls command failed: " . $ssh->error;
 
-            my $commit_info = JSON::Util->decode($info[0]);
-            my $rowcount = $commit_info->{'rowCount'};
-            if (defined $rowcount && ($rowcount eq "0")) {
+            my $commit_info = JSON::Util->decode( $info[0] );
+            my $rowcount    = $commit_info->{'rowCount'};
+            if ( defined $rowcount && ( $rowcount eq "0" ) ) {
                 print " - no gerrit commit for that id.\n";
                 open( my $HANDLE, ">", "$infodir/$commit_id" ) or die "Error: could not open file '$infodir/$commit_id'\n";
                 print $HANDLE "No gerrit commit";
@@ -388,13 +646,13 @@
             my $approvals = $commit_info->{'currentPatchSet'}{'approvals'};
 
             for my $approval (@$approvals) {
-                if ($approval->{'type'} eq "SUBM") {
-                    $submit_time = $approval->{'grantedOn'}
+                if ( $approval->{'type'} eq "SUBM" ) {
+                    $submit_time = $approval->{'grantedOn'};
                 }
             }
-            my $dt="";
+            my $dt = "";
             if ($submit_time) {
-                $dt = DateTime->from_epoch(epoch => $submit_time);
+                $dt = DateTime->from_epoch( epoch => $submit_time );
             } else {
                 print " - no submit time for that id.\n";
                 open( my $HANDLE, ">", "$infodir/$commit_id" ) or die "Error: could not open file '$infodir/$commit_id'\n";
@@ -408,9 +666,9 @@
             print $HANDLE $info[0];
             close $HANDLE;
 
-            $dt->set_time_zone( 'Europe/Paris' );
+            $dt->set_time_zone('Europe/Paris');
             print " - submit time: " . $dt->strftime('%Y/%m/%d %H:%M:%S') . "\n";
-        } elsif ($commit_id && (! -f "$infodir/$commit_id")) {
+        } elsif ( $commit_id && ( !-f "$infodir/$commit_id" ) ) {
             print "No gerrit commit for $commit_id\n";
             open( my $HANDLE, ">", "$infodir/$commit_id" ) or die "Error: could not open file '$infodir/$commit_id'\n";
             print $HANDLE "No gerrit commit";
@@ -426,16 +684,17 @@
 sub check_arguments {
     my $show_usage = 0;
     GetOptions(
-        'help|?'         => sub { usage() },
-        'url|u=s'        => \$URL_WITH_USER,
-        'skip|s'         => \$SKIP_GERRIT_CHECK,
+        'help|?'  => sub { usage() },
+        'url|u=s' => \$URL_WITH_USER,
+        'skip|s'  => \$SKIP_GERRIT_CHECK,
     );
+
     # strip ssh:// from url if passed in.
-    if (defined $URL_WITH_USER) {
+    if ( defined $URL_WITH_USER ) {
         $URL_WITH_USER =~ s|ssh://||;
     }
     if (@ARGV) {
-        ($old_version, $new_version) = @ARGV;
+        ( $old_version, $new_version ) = @ARGV;
     } else {
         usage();
     }