#!/usr/bin/env perl
#***********************************************************************
# This file is part of OpenMolcas.                                     *
#                                                                      *
# OpenMolcas is free software; you can redistribute it and/or modify   *
# it under the terms of the GNU Lesser General Public License, v. 2.1. *
# OpenMolcas is distributed in the hope that it will be useful, but it *
# is provided "as is" and without any express or implied warranties.   *
# For more details see the full text of the license in the file        *
# LICENSE or in <http://www.gnu.org/licenses/>.                        *
#                                                                      *
# Copyright (C) 2013, Steven Vancoillie                                *
#***********************************************************************
#
# git-devlog
#
# Program that logs all version tags, and for each tag
# shows the developers that have introduced a change as
# well as the result of the automatic verification. If
# the daily snapshot is a merge commit (more than one
# parent) then the developers are the authors of the
# parent commits (excluding previous tagged snapshots).
# If there is only 1 parent, the merge was a fast-forward
# and then the developer is the author of the commit
# pointed to by the tag.
#
# Used with Molcas to give a list of all daily snapshots
# (tagged with e.g. v7.9.17-07-13), and list the people
# and if they caused a rejection of the snaphot.
#
# Steven Vancoillie, July 2013

use File::Basename;

my $MOLCAS_DRIVER;
$MOLCAS_DRIVER = $ENV{"MOLCAS_DRIVER"} or $MOLCAS_DRIVER = "molcas";
my $DRIVER_base = basename($MOLCAS_DRIVER);

my $MOLCAS=$ENV{"MOLCAS"};
die "MOLCAS not set, set it or use command \"$DRIVER_base devlog\"\n" unless ($MOLCAS);

# if this is a git repo, sanity check if git exists,
# otherwise print a warning.
my $git_exists = 0;
foreach my $path (split /:/, $ENV{'PATH'}) {
    if ( -f "$path/git" && -x _ ) {
        $git_exists = 1;
        last;
    }
}
if ( not -e "$MOLCAS/.git" or not $git_exists) {
    print "Error: git not available or not a git repo\n";
    exit 1;
}

# check for option -v, which activates verbose mode
my $verbose;
while (my $opt = shift @ARGV) {
    if ($opt =~ /-v/) {
        $verbose = 1;
    }
}

print "building hash tables...\n";

my @tags = `git tag --list`;
my @snap = reverse sort grep /^v/, @tags;
my @fail = reverse sort grep /^F/, @tags;

my %tocom;
my %totag;
foreach (@snap) {
    chomp;
    chomp (my $commit = `git rev-parse $_^{commit}`);
    $tocom{$_} = $commit;
    $totag{$commit} = $_;
}

my %rejected;
foreach (@fail) {
    chomp;
    chomp (my $commit = `git rev-parse $_^{commit}`);
    $rejected{$commit}++;
}

print "analyzing developer logs...\n";

my %bad;
my %good;
foreach my $tag (@snap) {

    print "$tag\n" if $verbose;

    my $commit = $tocom{$tag};
    chomp (my $parents = `git log -n 1 --pretty=%P $commit`);
    my @parents = split / /, $parents;
    last unless @parents;
    # if not a merge (only 1 parent), then take the actual
    # commit as being relevant, otherwise loop over parents
    if (@parents == 1) {
        chomp (my $committer = lc `git log -n 1 --pretty=%ce $commit`);
        print "  - $committer" if $verbose;
        if ($rejected{$commit}) {
            print " (rejected)\n" if $verbose;
            $bad{$committer}++;
        } else {
            print "\n" if $verbose;
            $good{$committer}++;
        }
    } else {
        foreach (@parents) {
            next if $totag{$_};
            chomp (my $committer = lc `git log -n 1 --pretty=%ce $_`);
            print "  - $committer" if $verbose;
            if ($rejected{$_}) {
                print " (rejected)\n" if $verbose;
                $bad{$committer}++;
            } else {
                print "\n" if $verbose;
                $good{$committer}++;
            }
        }
    }
}

print "\n";
printf "%-32s %6s %6s\n", "developer e-mail", "fail", "pass";
printf "%-32s %6s %6s\n", "----------------", "----", "----";
foreach (sort keys %bad) {
    printf "%-32s %6d %6d\n", $_, $bad{$_}, $good{$_};
}

exit 0;
