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