aboutsummaryrefslogblamecommitdiffstats
path: root/cook
blob: c57f3ffa97e9837df864e5b9980ab06a78f0bf87 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                            
                                      


                                                        
 















                                                                      






                                  

                                                          
                                           

            
            
            
                                       









                                                          

                                             


                                   
                          














                                                           












                                                           








                                                       
                                          









                                                                           








                                                                        

          
                                                               













                                







                                                        




                             







                                              










                                                                                            
                                  
                                                     

                                     






                                    
                                                     



                   
                                   


                                                                       




                                                                                          
                                                                             

                                       
#!/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;
}