#!/usr/bin/env perl
use warnings;
use strict;
use Text::Wrap qw(wrap fill $columns $huge);
use Getopt::Long;
use POSIX qw(strftime);
my $days_back = 10365; # Go back a year by default.
my $send_help = 0; # Display help and exit.
my $tag_pattern = "^\\d";
GetOptions(
"age=s" => \$days_back,
"help" => \$send_help,
"tags=s" => \$tag_pattern,
) or $send_help = 1;
# Find the trunk for the current repository if one isn't specified.
die(
"$0 usage:\n",
" [--age DAYS] limit report to DAYS in the past (default: 365)\n",
" [--tags REGEXP] report on tags matching REGEXP (default: ^v\\d+_)\n",
) if $send_help;
my $earliest_date = strftime(
"%FT %T +0000", gmtime(time() - $days_back * 86400)
);
$Text::Wrap::huge = "wrap";
$Text::Wrap::columns = 74;
chomp(my @tags = `git tag`);
{
my $i = @tags;
while ($i--) {
unless ($tags[$i] =~ /$tag_pattern/o) {
splice @tags, $i, 1;
next;
}
my $commit = `git show $tags[$i] --pretty='tformat:(((((%ci)))))' | grep '(((((' | head -1`;
die $commit unless $commit =~ /\(\(\(\(\((.+?)\)\)\)\)\)/;
$tags[$i] = {
'time' => $1,
'tag' => $tags[$i],
};
}
}
push @tags, { 'time' => '9999-99-99 99:99:99 +0000', 'tag' => 'HEAD' };
@tags = sort { $a->{'time'} cmp $b->{'time'} } @tags;
{
my $i = @tags;
while ($i--) {
last if $tags[$i]{time} lt $earliest_date;
my @commit;
open my $commit, "-|", "git log $tags[$i-1]{tag}..$tags[$i]{tag} ." or die $!;
local $/ = "\n\n";
while (<$commit>) {
if (/^\S/) {
s/^/ /mg;
push @commit, $_;
next;
}
# Trim off identical leading whitespace.
my ($whitespace) = /^(\s*)/;
if (length $whitespace) {
s/^$whitespace//mg;
}
# Re-flow the paragraph if it isn't indented from the norm.
# This should preserve indented quoted text, wiki-style.
unless (/^\s/) {
push @commit, fill(" ", " ", $_), "\n\n";
}
else {
push @commit, $_;
}
}
# Don't display the tag if there's nothing under it.
next unless @commit;
my $tag_line = "$tags[$i]{time} $tags[$i]{tag}";
print(
("=" x length($tag_line)), "\n",
$tag_line, "\n",
("=" x length($tag_line)), "\n",
"\n",
);
print @commit;
}
}
print(
"==============\n",
"End of Excerpt\n",
"==============\n",
);