#!/usr/bin/perl -w
use strict;
use File::Basename;
use File::Spec;
-d '.git' or die "$0: Not a Git repository";
my $root = dirname($0);
my $application = "$root/application";
my $last = `(cd $root; git ls-files "whats" | tail -1)`;
@ARGV = ("$root/$last");
my $date;
my $output_file;
{
my($sec,$min,$h,$mday,$month,$year) = localtime(time);
$year += 1900;
$month++;
$date = sprintf("%04d-%02d-%02d", $year, $month, $mday);
my $dir = sprintf("$root/whats/cooking/%04d/%02d", $year, $month);
system "mkdir -p $dir";
$output_file = sprintf("$dir/%02d.txt", $mday);
$output_file = File::Spec->rel2abs($output_file);
open STDOUT, ">", $output_file or
die "$0: Failed to open $output_file for writing: $!\n";
}
my $title = "What's cooking in erlang/otp ($date)";
my $from = `git config imap.user`;
my $header_date = gmtime(time);
chomp $from;
print "From - $header_date\n";
print "From: $from\n"
if $from ne '';
print "Date: $header_date\n";
print "To: erlang patches <erlang-patches\@erlang.org>\n";
print "Subject: $title\n";
print "X-dev-at: ", `git rev-parse master`;
my %cooking;
my %stalled;
my $current;
my $prev_dev = '`git describe master`';
if (@ARGV) {
my $state = 'header';
while (<>) {
$prev_dev = $1 if /^X-dev-at: ([\da-f]{40})/;
next if /^-------/;
$state = 'intro' if $state eq 'header' && /^\s*$/;
if (m/^\[([^\]]*)\]/) {
my $group = $1;
if ($group =~ /^Graduated/) {
$state = 'skip';
} elsif ($group =~ /^Stalled/) {
$state = 'stalled';
} else {
$state = 'cooking';
}
$current = '';
next;
}
print if $state eq 'intro';
if ($state eq 'cooking') {
if (/^[*] (\S+)/) {
$current = $1;
$cooking{$current} = "";
next;
}
next if /^ [+-]/;
next unless $current;
$cooking{$current} .= $_
unless /^\s*$/ && $cooking{$current} eq '';
}
if ($state eq 'stalled') {
if (/^[*] (\S+)/) {
$current = $1;
$stalled{$current} = "";
next;
}
next if /^ [+-]/;
next unless $current;
$stalled{$current} .= $_
unless /^\s*$/ && $stalled{$current} eq '';
}
}
}
my @old_in_dev = `git branch --merged $prev_dev`;
chomp @old_in_dev;
map { s/^\s*// } @old_in_dev;
@old_in_dev = grep { m@^[^/]{2,4}/[^/]*@ } @old_in_dev;
my %old_in_dev = map { $_ => 1 } @old_in_dev;
my @in_dev = `git branch --merged master`;
chomp @in_dev;
map { s/^\s*// } @in_dev;
@in_dev = grep { m@^[^/]{2,4}/[^/]*@ && !exists $old_in_dev{$_} } @in_dev;
my %in_dev = map { $_ => 1 } @in_dev;
my @in_pu = `git branch --merged pu`;
chomp @in_pu;
map { s/^\s*// } @in_pu;
@in_pu = grep { m@^[^/]{2,4}/[^/]*@ } @in_pu;
@in_pu = grep { !exists $in_dev{$_} && !exists $old_in_dev{$_} } @in_pu;
my %in_pu = map { $_ => 1 } @in_pu;
my @dropped = `git for-each-ref --format='%(refname)' refs/heads/??*/*`;
chomp @dropped;
map { s@^refs/heads/@@ } @dropped;
@dropped = grep { m@^[^/]{2,4}/[^/]*@ } @dropped;
@dropped = grep { !exists $in_dev{$_} &&
!exists $old_in_dev{$_} &&
!exists $in_pu{$_} } @dropped;
my %child;
foreach (`git rev-list --no-merges --children $prev_dev..pu`) {
chomp;
my($ref,$child) = split ' ';
$child{$ref} = $child;
}
if (@in_dev) {
header("[Graduated]");
foreach (@in_dev) {
describe_graduated($_);
}
}
header("[New topics]");
foreach (@in_pu) {
describe('-', $_, '') unless defined $cooking{$_} or
defined $stalled{$_}
}
header("[Stalled]");
foreach (@in_pu) {
my $text = $stalled{$_};
describe('-', $_, $text) if defined $text;
}
header("[Cooking]");
foreach (@in_pu) {
my $text = $cooking{$_};
describe('-', $_, $text) if defined $text;
}
if (@dropped) {
header("[Dropped]");
foreach (@dropped) {
describe('.', $_, '');
}
}
close STDOUT;
system qq(cd $root; git add $output_file >/dev/null; git commit -m "Add $title" >/dev/null);
sub header {
print '-' x 60, "\n";
print $_[0], "\n\n";
}
sub describe {
my($marker,$topic,$text) = @_;
print_commits($topic, "master..$topic", $marker);
$text =~ s/\n*$//g;
print "\n$text\n" if $text ne '';
print "\n";
}
sub describe_graduated {
my($topic) = @_;
my $id = `git rev-parse $topic`;
chomp $id;
print_commits($topic, "$child{$id}^1..$id", '+');
print "\n";
}
sub print_commits {
my($topic,$range,$marker) = @_;
my(@revs) = `git rev-list $range`;
my $commits = @revs == 1 ? "1 commit" : scalar(@revs) . " commits";
my $max = 12;
my $diff_range = $range;
$diff_range =~ s/[.][.]/.../;
my $apps = `$application $diff_range`;
chomp $apps;
system qq[git show -s --date=short --format="* $topic ($apps) (%ad) $commits" $topic];
system qq[git --no-pager log -n $max --format=" $marker %s (%h)" $range];
print ".\n.\n\.\n" if @revs > $max;
}