Git.pm: Implement Git::exec_path()
[gitweb.git] / git-fmt-merge-msg.perl
index 778388e254e8ecc07494c168aec503e3bc511fb3..be2a48cf65949ba16b354e476dd39f5c334f1b25 100755 (executable)
@@ -6,6 +6,9 @@
 # by grouping branches and tags together to form a single line.
 
 use strict;
+use Git;
+
+my $repo = Git->repository();
 
 my @src;
 my %src;
@@ -27,10 +30,38 @@ sub andjoin {
        return ($m);
 }
 
+sub repoconfig {
+       my ($val) = $repo->command_oneline('repo-config', '--get', 'merge.summary');
+       return $val;
+}
+
+sub current_branch {
+       my ($bra) = $repo->command_oneline('symbolic-ref', 'HEAD');
+       $bra =~ s|^refs/heads/||;
+       if ($bra ne 'master') {
+               $bra = " into $bra";
+       } else {
+               $bra = "";
+       }
+       return $bra;
+}
+
+sub shortlog {
+       my ($tip) = @_;
+       my @result;
+       foreach ($repo->command('log', '--no-merges', '--topo-order', '--pretty=oneline', $tip, '^HEAD')) {
+               s/^[0-9a-f]{40}\s+//;
+               push @result, $_;
+       }
+       return @result;
+}
+
+my @origin = ();
 while (<>) {
-       my ($bname, $tname, $gname, $src);
+       my ($bname, $tname, $gname, $src, $sha1, $origin);
        chomp;
-       s/^[0-9a-f]*    //;
+       s/^([0-9a-f]*)  //;
+       $sha1 = $1;
        next if (/^not-for-merge/);
        s/^     //;
        if (s/ of (.*)$//) {
@@ -45,6 +76,7 @@ sub andjoin {
                $src{$src} = {
                        BRANCH => [],
                        TAG => [],
+                       R_BRANCH => [],
                        GENERIC => [],
                        # &1 == has HEAD.
                        # &2 == has others.
@@ -52,19 +84,35 @@ sub andjoin {
                };
        }
        if (/^branch (.*)$/) {
+               $origin = $1;
                push @{$src{$src}{BRANCH}}, $1;
                $src{$src}{HEAD_STATUS} |= 2;
        }
        elsif (/^tag (.*)$/) {
+               $origin = $_;
                push @{$src{$src}{TAG}}, $1;
                $src{$src}{HEAD_STATUS} |= 2;
        }
+       elsif (/^remote branch (.*)$/) {
+               $origin = $1;
+               push @{$src{$src}{R_BRANCH}}, $1;
+               $src{$src}{HEAD_STATUS} |= 2;
+       }
        elsif (/^HEAD$/) {
+               $origin = $src;
                $src{$src}{HEAD_STATUS} |= 1;
        }
        else {
                push @{$src{$src}{GENERIC}}, $_;
                $src{$src}{HEAD_STATUS} |= 2;
+               $origin = $src;
+       }
+       if ($src eq '.' || $src eq $origin) {
+               $origin =~ s/^'(.*)'$/$1/;
+               push @origin, [$sha1, "$origin"];
+       }
+       else {
+               push @origin, [$sha1, "$origin of $src"];
        }
 }
 
@@ -82,6 +130,8 @@ sub andjoin {
        }
        push @this, andjoin("branch ", "branches ",
                           $src{$src}{BRANCH});
+       push @this, andjoin("remote branch ", "remote branches ",
+                          $src{$src}{R_BRANCH});
        push @this, andjoin("tag ", "tags ",
                           $src{$src}{TAG});
        push @this, andjoin("commit ", "commits ",
@@ -92,4 +142,33 @@ sub andjoin {
        }
        push @msg, $this;
 }
-print "Merge ", join("; ", @msg), "\n";
+
+my $into = current_branch();
+
+print "Merge ", join("; ", @msg), $into, "\n";
+
+if (!repoconfig) {
+       exit(0);
+}
+
+# We limit the merge message to the latst 20 or so per each branch.
+my $limit = 20;
+
+for (@origin) {
+       my ($sha1, $name) = @$_;
+       my @log = shortlog($sha1);
+       if ($limit + 1 <= @log) {
+               print "\n* $name: (" . scalar(@log) . " commits)\n";
+       }
+       else {
+               print "\n* $name:\n";
+       }
+       my $cnt = 0;
+       for my $log (@log) {
+               if ($limit < ++$cnt) {
+                       print "  ...\n";
+                       last;
+               }
+               print "  $log\n";
+       }
+}