#!/usr/bin/env perl

use warnings;
use strict;
use open ':encoding(UTF-8)';
use Encode;
use Text::Wrap;

#
# We'd like to minimize the number of dependencies, otherwise we'd probably use
# the Text::Unidecode module instead.
#
sub asciify {
	my $text = shift;
	my %charmap = (
		ord "\N{LATIN CAPITAL LETTER A WITH DIAERESIS}" => 'Ae',
		ord "\N{LATIN CAPITAL LETTER O WITH DIAERESIS}" => 'Oe',
		ord "\N{LATIN CAPITAL LETTER U WITH DIAERESIS}" => 'Ue',
		ord "\N{LATIN SMALL LETTER A WITH DIAERESIS}"   => 'ae',
		ord "\N{LATIN SMALL LETTER O WITH DIAERESIS}"   => 'oe',
		ord "\N{LATIN SMALL LETTER U WITH DIAERESIS}"   => 'ue',
		ord "\N{LATIN SMALL LETTER SHARP S}"            => 'ss'
	);

	return encode('ascii', $text, sub {
		my $char = shift;

		foreach my $key (keys %charmap) {
			return $charmap{$key} if $key == $char;
		}
		return sprintf('<U+%04X>', $char);
	});
}

# The lines will have a length of no more than $columns - 1.
$Text::Wrap::columns = 81;

if (system('git rev-parse --git-dir >/dev/null 2>&1') != 0) {
	print "Not a Git repository, so I won't update the ChangeLog.\n";
	exit 0;
}

my $regex =
    '^commit [0-9a-f]+\n' .
    '^Author: (?<name>.+) <(?<email>.*)>\n' .
    '^Date:   (?<date>\d{4}-\d{2}-\d{2})\n' .
    '^\n' .
    '(?<message>(^    .*\n)+)' .
    '^\n' .
    '(?<files>(^.+\n)+)';

my $git_log = qx'git log -M -C --stat --name-only --date=short';
die "Cannot get `git log' output\n" if $? != 0;

my ($prev_date, $prev_name, $prev_email);

while ($git_log =~ /$regex/gm) {
	my %commit = %+;

	if (not defined $prev_date
	    or $commit{date} ne $prev_date
	    or $commit{name} ne $prev_name
	    or $commit{email} ne $prev_email) {
		print $commit{date}, '  ';
		print asciify($commit{name}), '  ';
		print '<', $commit{email}, '>', "\n\n";
	}
	$prev_date = $commit{date};
	$prev_name = $commit{name};
	$prev_email = $commit{email};

	my @files = split(/\n/, $commit{files});
	my @message = map { s/^ {4}//r } split(/\n/, asciify($commit{message}));
	my $first_line = shift(@message) =~ s/^$files[-1]: //r;
	my $intro = sprintf('* %s: %s', join(', ', @files), $first_line);

	print fill("\t", "\t", $intro), "\n";
	foreach my $line (@message) {
		print "\t$line" if length($line) > 0;
		print "\n";
	}
	print "\n";
}
