#!/usr/bin/env perl
#
# SPDX-License-Identifier: GPL-2.0-only

package gerrit_stats;

# To install any needed modules install the cpanm app, and use it to install the required modules:
#  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 );
use File::Find;
use File::Path;
use Getopt::Long;
use Getopt::Std;
use JSON::Util;
use Net::OpenSSH;
use Data::Dumper qw(Dumper);
use DateTime;
use Devel::Size qw(size total_size);

my $old_version;
my $new_version;
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;
my $print_commit_list = 1;

#disable print buffering
$OUTPUT_AUTOFLUSH = 1;
binmode STDOUT, ":utf8";

Main();

#-------------------------------------------------------------------------------
# Main
#-------------------------------------------------------------------------------
sub Main {
    check_arguments();

    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();
    }

    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`;
    get_commits(@commits);
    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, Commenters\n";

    # Loop through all commits
    for my $commit_id (@commits) {
        $commit_id =~ s/^\s+|\s+$//g;

        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 $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 ) {
            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
            $owner = $commit_info->{'owner'}{'name'};
            if ( !$owner ) {
                $owner = $commit_info->{'owner'}{'username'};
            }
            if ( !$owner ) {
                $owner = "-";
            }
            if ( $owner && exists( $aliases{$owner} ) ) {
                $owner = $aliases{$owner};
            }
            $owner =~ s/"/'/g;
            $owner =~ s/,/./g;

            $author = $commit_info->{'currentPatchSet'}{'author'}{'name'};
            if ( $author && exists( $aliases{$author} ) ) {
                $author = $aliases{$author};
            }
            if ( !$author ) {
                $author = $commit_info->{'currentPatchSet'}{'author'}{'username'};
            }
            $author =~ s/"/'/g;
            $author =~ s/,/./g;
            $author_email   = $commit_info->{'currentPatchSet'}{'author'}{'email'};
            $inserted_lines = $commit_info->{'currentPatchSet'}{'sizeInsertions'};
            $deleted_lines  = $commit_info->{'currentPatchSet'}{'sizeDeletions'};
            $subject        = $commit_info->{'subject'};
            $subject =~ s/"/'/g;

            #get the patch's submitter
            my $approvals = $commit_info->{'currentPatchSet'}{'approvals'};
            for my $approval (@$approvals) {
                if ( $approval->{'type'} eq "SUBM" ) {
                    $submit_epoch = $approval->{'grantedOn'};
                    $submitter    = $approval->{'by'}{'name'};
                    if ( exists( $aliases{$submitter} ) ) {
                        $submitter = $aliases{$submitter};
                    }
                }
            }

            # 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};
                    }
                }
                $commenter =~ s/"/'/g;
                $commenter =~ s/,/./g;
                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 ) {
                    $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" ) ) {
                        $submit_epoch = $approval->{'grantedOn'};
                        $submitter    = $approval->{'by'}{'name'};
                        if ( $submitter && exists( $aliases{$submitter} ) ) {
                            $submitter = $aliases{$submitter};
                        }
                    }
                    $submitter =~ s/"/'/g;
                    $submitter =~ s/,/./g;

                    if ( $approval->{'type'} eq "Code-Review" ) {
                        my $patch_reviewer = $approval->{'by'}{'name'};
                        if ($patch_reviewer) {
                            if ( exists $patch_reviewers{$patch_reviewer} ) {
                                $patch_reviewers{$patch_reviewer}++;
                            } else {
                                $patch_reviewers{$patch_reviewer} = 1;
                            }
                        }
                    }
                }
            }

        } else {

            # 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 );
            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/ ) {
                $inserted_lines = $1;
            }
            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</ ) {
                    my $patch_reviewer = $1;
                    if ( exists( $aliases{$patch_reviewer} ) ) {
                        $patch_reviewer = $aliases{$patch_reviewer};
                    }
                    if ($patch_reviewer) {
                        if ( exists $patch_reviewers{$patch_reviewer} ) {
                            $patch_reviewers{$patch_reviewer}++;
                        } else {
                            $patch_reviewers{$patch_reviewer} = 1;
                        }
                    }
                }
            }

        }

        # 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 ) {
            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 ( $submitter && exists $submitters{$submitter} && exists $submitters{$submitter}{count} ) {
            $submitters{$submitter}{count}++;
        } else {
            $submitters{$submitter}{count} = 1;
            $number_of_submitters++;
            $submitters{$submitter}{"self"} = 0;
            $submitters{$submitter}{others} = 0;
            $submitters{$submitter}{name}   = $submitter;
        }

        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 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 ( exists( $aliases{$reviewer} ) ) {
                $reviewer = $aliases{$reviewer};
            }

            if ( $reviewerlist eq "" ) {
                $reviewerlist = $reviewer;
            } else {
                $reviewerlist .= ", $reviewer";
            }

            if ( $reviewer && exists $reviewers{$reviewer} ) {
                $reviewers{$reviewer}++;
            } else {
                $reviewers{$reviewer} = 1;
            }
        }
        if ( !$reviewerlist ) {
            $reviewerlist = "-";
        }

        if ($print_commit_list) {
            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} ) {
            $owners{$owner}++;
        } else {
            $owners{$owner} = 1;
        }

        if ( $author && exists $authors{$author}{"num"} ) {
            $authors{$author}{"num"}++;
            $author_added{$author}   += $inserted_lines;
            $author_removed{$author} += $deleted_lines;
            $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;
        }
        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 ) {
        $Days += 1;
    }

    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";
    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 ) ) {
        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 "%-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{$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 "%-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";
    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;
}

#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
sub check_versions {
    `git cat-file -e $old_version^{commit} 2>/dev/null`;
    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} ) {
        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+)(\/\w+)*/ ) {
        $URL_WITH_USER = $1;
    } else {
        print "Error: Could not get a ssh url with a username from gitconfig.\n";
        print "       use the -u option to set a url.\n";
        exit 1;
    }
}

#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
sub get_commits {
    my @commits     = @_;
    my $submit_time = "";
    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;

    print "Using URL: ssh://$URL_WITH_USER\n";

    if ( !-d $infodir ) {
        mkpath($infodir);
    }

    for my $commit_id (@commits) {
        $commit_id =~ s/^\s+|\s+$//g;
        $submit_time = "";
        my $gerrit_review;

        # Look for last coreboot commit
        if ( $commit_id eq "7309709742" ) {
            last;
        }

        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" ) ) {
            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" ) ) {
                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";
                close $HANDLE;
                next;
            }
            my $approvals = $commit_info->{'currentPatchSet'}{'approvals'};

            for my $approval (@$approvals) {
                if ( $approval->{'type'} eq "SUBM" ) {
                    $submit_time = $approval->{'grantedOn'};
                }
            }
            my $dt = "";
            if ($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";
                print $HANDLE "No submit time";
                close $HANDLE;

                next;
            }

            open( my $HANDLE, ">", "$infodir/$commit_id" ) or die "Error: could not open file '$infodir/$commit_id'\n";
            print $HANDLE $info[0];
            close $HANDLE;

            $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" ) ) {
            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";
            close $HANDLE;
        }
    }
    print "\n";
}

#-------------------------------------------------------------------------------
# check_arguments parse the command line arguments
#-------------------------------------------------------------------------------
sub check_arguments {
    my $show_usage = 0;
    GetOptions(
        '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 ) {
        $URL_WITH_USER =~ s|ssh://||;
    }
    if (@ARGV) {
        ( $old_version, $new_version ) = @ARGV;
    } else {
        usage();
    }
}

#-------------------------------------------------------------------------------
# usage - Print the arguments for the user
#-------------------------------------------------------------------------------
sub usage {
    print "gerrit_stats <options> [Old version] [New version]\n";
    print "Old version should be a tag (4.1), a branch (origin/4.1), or a commit id\n";
    print "New version can be 'HEAD' a branch (origin/main) a tag (4.2), or a commit id\n";
    print " Options:\n";
    print "    u | url [url]           url with username.\n";
    print "Example: \"$0 -u Gaumless\@review.coreboot.org:29418 origin/4.1 4.2\"\n";
    exit(0);
}

1;