#!/usr/bin/perl

use strict;
use warnings;
use Git::Repository;
use Date::Parse;
use Date::Format;


my $oldrev = shift || usage();
my $newrev = shift || usage();

my $r = Git::Repository->new();

my @old = _parselines($r->run('log', "$newrev..$oldrev"));
my @new = _parselines($r->run('log', "$oldrev..$newrev"));
my %oldnames = map { $_->{title} => 1 } @old;
my %newnames = map { $_->{title} => 1 } @new;

my (@adds, @removes);

foreach my $item (reverse @old) {
  next if $newnames{$item->{title}};
  push @removes, _fmt($item)
}

foreach my $item (reverse @new) {
  next if $oldnames{$item->{title}};
  push @adds, _fmt($item);
}

print <<EOF;
OldRev: $oldrev
NewRev: $newrev

EOF

if (@removes) {
  print "Removes the following commits:\n";
  print join("\n", @removes);
  print "\n\n";
}

if (@adds) {
  print "Adds the following commits:\n";
  print join("\n", @adds);
  print "\n\n";
}

sub usage {
  die <<EOF;
Usage: $0 <oldref> <newref>
EOF
}

sub _parselines {
  my @lines = @_;
  my @items;
  my $item;
  foreach my $line (@lines) {
    if ($line =~ m/^commit (.*)/) {
      my $commit = $1;
      push @items, $item if $item;
      $item = { commit => $commit };
    }
    if ($line =~ m/Author:\s*(.*)/) {
        $item->{author} = $1;
    }
    if ($line =~ m/Date:\s*(.*)/) {
        $item->{date} = $1;
    }
    if (not $item->{title} and $line =~ m/^    (\S.*)/) {
        $item->{title} = $1;
    }
  }
  push @items, $item if $item;
  return @items;
}

sub _fmt {
   my $item = shift;
   my $a = _author($item->{author});
   my $d = _date($item->{date});
   my $c = substr($item->{commit}, 0, 8);
   return "  $c $d $a: $item->{title}";
}

sub _author {
  my $author = shift;
  return $author unless $author =~ m/\<(.*?)\@/;
  return $1;
}

sub _date {
  my $date = shift;
  my $time = str2time($date);
  return time2str("%Y-%m-%d", $time);
}
