Blame build-aux/gitlog-to-changelog

Packit Service fdd496
eval '(exit $?0)' && eval 'exec perl -wS "$0" "$@"'
Packit Service fdd496
  & eval 'exec perl -wS "$0" $argv:q'
Packit Service fdd496
    if 0;
Packit Service fdd496
# Convert git log output to ChangeLog format.
Packit Service fdd496
Packit Service fdd496
my $VERSION = '2016-03-22 21:49'; # UTC
Packit Service fdd496
# The definition above must lie within the first 8 lines in order
Packit Service fdd496
# for the Emacs time-stamp write hook (at end) to update it.
Packit Service fdd496
# If you change this file with Emacs, please let the write hook
Packit Service fdd496
# do its job.  Otherwise, update this string manually.
Packit Service fdd496
Packit Service fdd496
# Copyright (C) 2008-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
# This program is free software: you can redistribute it and/or modify
Packit Service fdd496
# it under the terms of the GNU General Public License as published by
Packit Service fdd496
# the Free Software Foundation, either version 3 of the License, or
Packit Service fdd496
# (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
# This program is distributed in the hope that it will be useful,
Packit Service fdd496
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
# GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
# You should have received a copy of the GNU General Public License
Packit Service fdd496
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service fdd496
Packit Service fdd496
# Written by Jim Meyering
Packit Service fdd496
Packit Service fdd496
use strict;
Packit Service fdd496
use warnings;
Packit Service fdd496
use Getopt::Long;
Packit Service fdd496
use POSIX qw(strftime);
Packit Service fdd496
Packit Service fdd496
(my $ME = $0) =~ s|.*/||;
Packit Service fdd496
Packit Service fdd496
# use File::Coda; # http://meyering.net/code/Coda/
Packit Service fdd496
END {
Packit Service fdd496
  defined fileno STDOUT or return;
Packit Service fdd496
  close STDOUT and return;
Packit Service fdd496
  warn "$ME: failed to close standard output: $!\n";
Packit Service fdd496
  $? ||= 1;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
sub usage ($)
Packit Service fdd496
{
Packit Service fdd496
  my ($exit_code) = @_;
Packit Service fdd496
  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
Packit Service fdd496
  if ($exit_code != 0)
Packit Service fdd496
    {
Packit Service fdd496
      print $STREAM "Try '$ME --help' for more information.\n";
Packit Service fdd496
    }
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
      print $STREAM <
Packit Service fdd496
Usage: $ME [OPTIONS] [ARGS]
Packit Service fdd496
Packit Service fdd496
Convert git log output to ChangeLog format.  If present, any ARGS
Packit Service fdd496
are passed to "git log".  To avoid ARGS being parsed as options to
Packit Service fdd496
$ME, they may be preceded by '--'.
Packit Service fdd496
Packit Service fdd496
OPTIONS:
Packit Service fdd496
Packit Service fdd496
   --amend=FILE FILE maps from an SHA1 to perl code (i.e., s/old/new/) that
Packit Service fdd496
                  makes a change to SHA1's commit log text or metadata.
Packit Service fdd496
   --append-dot append a dot to the first line of each commit message if
Packit Service fdd496
                  there is no other punctuation or blank at the end.
Packit Service fdd496
   --no-cluster never cluster commit messages under the same date/author
Packit Service fdd496
                  header; the default is to cluster adjacent commit messages
Packit Service fdd496
                  if their headers are the same and neither commit message
Packit Service fdd496
                  contains multiple paragraphs.
Packit Service fdd496
   --srcdir=DIR the root of the source tree, from which the .git/
Packit Service fdd496
                  directory can be derived.
Packit Service fdd496
   --since=DATE convert only the logs since DATE;
Packit Service fdd496
                  the default is to convert all log entries.
Packit Service fdd496
   --until=DATE convert only the logs older than DATE.
Packit Service fdd496
   --ignore-matching=PAT ignore commit messages whose first lines match PAT.
Packit Service fdd496
   --ignore-line=PAT ignore lines of commit messages that match PAT.
Packit Service fdd496
   --format=FMT set format string for commit subject and body;
Packit Service fdd496
                  see 'man git-log' for the list of format metacharacters;
Packit Service fdd496
                  the default is '%s%n%b%n'
Packit Service fdd496
   --strip-tab  remove one additional leading TAB from commit message lines.
Packit Service fdd496
   --strip-cherry-pick  remove data inserted by "git cherry-pick";
Packit Service fdd496
                  this includes the "cherry picked from commit ..." line,
Packit Service fdd496
                  and the possible final "Conflicts:" paragraph.
Packit Service fdd496
   --help       display this help and exit
Packit Service fdd496
   --version    output version information and exit
Packit Service fdd496
Packit Service fdd496
EXAMPLE:
Packit Service fdd496
Packit Service fdd496
  $ME --since=2008-01-01 > ChangeLog
Packit Service fdd496
  $ME -- -n 5 foo > last-5-commits-to-branch-foo
Packit Service fdd496
Packit Service fdd496
SPECIAL SYNTAX:
Packit Service fdd496
Packit Service fdd496
The following types of strings are interpreted specially when they appear
Packit Service fdd496
at the beginning of a log message line.  They are not copied to the output.
Packit Service fdd496
Packit Service fdd496
  Copyright-paperwork-exempt: Yes
Packit Service fdd496
    Append the "(tiny change)" notation to the usual "date name email"
Packit Service fdd496
    ChangeLog header to mark a change that does not require a copyright
Packit Service fdd496
    assignment.
Packit Service fdd496
  Co-authored-by: Joe User <user\@example.com>
Packit Service fdd496
    List the specified name and email address on a second
Packit Service fdd496
    ChangeLog header, denoting a co-author.
Packit Service fdd496
  Signed-off-by: Joe User <user\@example.com>
Packit Service fdd496
    These lines are simply elided.
Packit Service fdd496
Packit Service fdd496
In a FILE specified via --amend, comment lines (starting with "#") are ignored.
Packit Service fdd496
FILE must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1 (alone on
Packit Service fdd496
a line) referring to a commit in the current project, and CODE refers to one
Packit Service fdd496
or more consecutive lines of Perl code.  Pairs must be separated by one or
Packit Service fdd496
more blank line.
Packit Service fdd496
Packit Service fdd496
Here is sample input for use with --amend=FILE, from coreutils:
Packit Service fdd496
Packit Service fdd496
3a169f4c5d9159283548178668d2fae6fced3030
Packit Service fdd496
# fix typo in title:
Packit Service fdd496
s/all tile types/all file types/
Packit Service fdd496
Packit Service fdd496
1379ed974f1fa39b12e2ffab18b3f7a607082202
Packit Service fdd496
# Due to a bug in vc-dwim, I mis-attributed a patch by Paul to myself.
Packit Service fdd496
# Change the author to be Paul.  Note the escaped "@":
Packit Service fdd496
s,Jim .*>,Paul Eggert <eggert\\\@cs.ucla.edu>,
Packit Service fdd496
Packit Service fdd496
EOF
Packit Service fdd496
    }
Packit Service fdd496
  exit $exit_code;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# If the string $S is a well-behaved file name, simply return it.
Packit Service fdd496
# If it contains white space, quotes, etc., quote it, and return the new string.
Packit Service fdd496
sub shell_quote($)
Packit Service fdd496
{
Packit Service fdd496
  my ($s) = @_;
Packit Service fdd496
  if ($s =~ m![^\w+/.,-]!)
Packit Service fdd496
    {
Packit Service fdd496
      # Convert each single quote to '\''
Packit Service fdd496
      $s =~ s/\'/\'\\\'\'/g;
Packit Service fdd496
      # Then single quote the string.
Packit Service fdd496
      $s = "'$s'";
Packit Service fdd496
    }
Packit Service fdd496
  return $s;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
sub quoted_cmd(@)
Packit Service fdd496
{
Packit Service fdd496
  return join (' ', map {shell_quote $_} @_);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Parse file F.
Packit Service fdd496
# Comment lines (starting with "#") are ignored.
Packit Service fdd496
# F must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1
Packit Service fdd496
# (alone on a line) referring to a commit in the current project, and
Packit Service fdd496
# CODE refers to one or more consecutive lines of Perl code.
Packit Service fdd496
# Pairs must be separated by one or more blank line.
Packit Service fdd496
sub parse_amend_file($)
Packit Service fdd496
{
Packit Service fdd496
  my ($f) = @_;
Packit Service fdd496
Packit Service fdd496
  open F, '<', $f
Packit Service fdd496
    or die "$ME: $f: failed to open for reading: $!\n";
Packit Service fdd496
Packit Service fdd496
  my $fail;
Packit Service fdd496
  my $h = {};
Packit Service fdd496
  my $in_code = 0;
Packit Service fdd496
  my $sha;
Packit Service fdd496
  while (defined (my $line = <F>))
Packit Service fdd496
    {
Packit Service fdd496
      $line =~ /^\#/
Packit Service fdd496
        and next;
Packit Service fdd496
      chomp $line;
Packit Service fdd496
      $line eq ''
Packit Service fdd496
        and $in_code = 0, next;
Packit Service fdd496
Packit Service fdd496
      if (!$in_code)
Packit Service fdd496
        {
Packit Service fdd496
          $line =~ /^([0-9a-fA-F]{40})$/
Packit Service fdd496
            or (warn "$ME: $f:$.: invalid line; expected an SHA1\n"),
Packit Service fdd496
              $fail = 1, next;
Packit Service fdd496
          $sha = lc $1;
Packit Service fdd496
          $in_code = 1;
Packit Service fdd496
          exists $h->{$sha}
Packit Service fdd496
            and (warn "$ME: $f:$.: duplicate SHA1\n"),
Packit Service fdd496
              $fail = 1, next;
Packit Service fdd496
        }
Packit Service fdd496
      else
Packit Service fdd496
        {
Packit Service fdd496
          $h->{$sha} ||= '';
Packit Service fdd496
          $h->{$sha} .= "$line\n";
Packit Service fdd496
        }
Packit Service fdd496
    }
Packit Service fdd496
  close F;
Packit Service fdd496
Packit Service fdd496
  $fail
Packit Service fdd496
    and exit 1;
Packit Service fdd496
Packit Service fdd496
  return $h;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# git_dir_option $SRCDIR
Packit Service fdd496
#
Packit Service fdd496
# From $SRCDIR, the --git-dir option to pass to git (none if $SRCDIR
Packit Service fdd496
# is undef).  Return as a list (0 or 1 element).
Packit Service fdd496
sub git_dir_option($)
Packit Service fdd496
{
Packit Service fdd496
  my ($srcdir) = @_;
Packit Service fdd496
  my @res = ();
Packit Service fdd496
  if (defined $srcdir)
Packit Service fdd496
    {
Packit Service fdd496
      my $qdir = shell_quote $srcdir;
Packit Service fdd496
      my $cmd = "cd $qdir && git rev-parse --show-toplevel";
Packit Service fdd496
      my $qcmd = shell_quote $cmd;
Packit Service fdd496
      my $git_dir = qx($cmd);
Packit Service fdd496
      defined $git_dir
Packit Service fdd496
        or die "$ME: cannot run $qcmd: $!\n";
Packit Service fdd496
      $? == 0
Packit Service fdd496
        or die "$ME: $qcmd had unexpected exit code or signal ($?)\n";
Packit Service fdd496
      chomp $git_dir;
Packit Service fdd496
      push @res, "--git-dir=$git_dir/.git";
Packit Service fdd496
    }
Packit Service fdd496
  @res;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
{
Packit Service fdd496
  my $since_date;
Packit Service fdd496
  my $until_date;
Packit Service fdd496
  my $format_string = '%s%n%b%n';
Packit Service fdd496
  my $amend_file;
Packit Service fdd496
  my $append_dot = 0;
Packit Service fdd496
  my $cluster = 1;
Packit Service fdd496
  my $ignore_matching;
Packit Service fdd496
  my $ignore_line;
Packit Service fdd496
  my $strip_tab = 0;
Packit Service fdd496
  my $strip_cherry_pick = 0;
Packit Service fdd496
  my $srcdir;
Packit Service fdd496
  GetOptions
Packit Service fdd496
    (
Packit Service fdd496
     help => sub { usage 0 },
Packit Service fdd496
     version => sub { print "$ME version $VERSION\n"; exit },
Packit Service fdd496
     'since=s' => \$since_date,
Packit Service fdd496
     'until=s' => \$until_date,
Packit Service fdd496
     'format=s' => \$format_string,
Packit Service fdd496
     'amend=s' => \$amend_file,
Packit Service fdd496
     'append-dot' => \$append_dot,
Packit Service fdd496
     'cluster!' => \$cluster,
Packit Service fdd496
     'ignore-matching=s' => \$ignore_matching,
Packit Service fdd496
     'ignore-line=s' => \$ignore_line,
Packit Service fdd496
     'strip-tab' => \$strip_tab,
Packit Service fdd496
     'strip-cherry-pick' => \$strip_cherry_pick,
Packit Service fdd496
     'srcdir=s' => \$srcdir,
Packit Service fdd496
    ) or usage 1;
Packit Service fdd496
Packit Service fdd496
  defined $since_date
Packit Service fdd496
    and unshift @ARGV, "--since=$since_date";
Packit Service fdd496
  defined $until_date
Packit Service fdd496
    and unshift @ARGV, "--until=$until_date";
Packit Service fdd496
Packit Service fdd496
  # This is a hash that maps an SHA1 to perl code (i.e., s/old/new/)
Packit Service fdd496
  # that makes a correction in the log or attribution of that commit.
Packit Service fdd496
  my $amend_code = defined $amend_file ? parse_amend_file $amend_file : {};
Packit Service fdd496
Packit Service fdd496
  my @cmd = ('git',
Packit Service fdd496
             git_dir_option $srcdir,
Packit Service fdd496
             qw(log --log-size),
Packit Service fdd496
             '--pretty=format:%H:%ct  %an  <%ae>%n%n'.$format_string, @ARGV);
Packit Service fdd496
  open PIPE, '-|', @cmd
Packit Service fdd496
    or die ("$ME: failed to run '". quoted_cmd (@cmd) ."': $!\n"
Packit Service fdd496
            . "(Is your Git too old?  Version 1.5.1 or later is required.)\n");
Packit Service fdd496
Packit Service fdd496
  my $prev_multi_paragraph;
Packit Service fdd496
  my $prev_date_line = '';
Packit Service fdd496
  my @prev_coauthors = ();
Packit Service fdd496
  my @skipshas = ();
Packit Service fdd496
  while (1)
Packit Service fdd496
    {
Packit Service fdd496
      defined (my $in = <PIPE>)
Packit Service fdd496
        or last;
Packit Service fdd496
      $in =~ /^log size (\d+)$/
Packit Service fdd496
        or die "$ME:$.: Invalid line (expected log size):\n$in";
Packit Service fdd496
      my $log_nbytes = $1;
Packit Service fdd496
Packit Service fdd496
      my $log;
Packit Service fdd496
      my $n_read = read PIPE, $log, $log_nbytes;
Packit Service fdd496
      $n_read == $log_nbytes
Packit Service fdd496
        or die "$ME:$.: unexpected EOF\n";
Packit Service fdd496
Packit Service fdd496
      # Extract leading hash.
Packit Service fdd496
      my ($sha, $rest) = split ':', $log, 2;
Packit Service fdd496
      defined $sha
Packit Service fdd496
        or die "$ME:$.: malformed log entry\n";
Packit Service fdd496
      $sha =~ /^[0-9a-fA-F]{40}$/
Packit Service fdd496
        or die "$ME:$.: invalid SHA1: $sha\n";
Packit Service fdd496
Packit Service fdd496
      my $skipflag = 0;
Packit Service fdd496
      if (@skipshas)
Packit Service fdd496
        {
Packit Service fdd496
          foreach(@skipshas)
Packit Service fdd496
            {
Packit Service fdd496
              if ($sha =~ /^$_/)
Packit Service fdd496
                {
Packit Service fdd496
                  $skipflag = $_;
Packit Service fdd496
                  last;
Packit Service fdd496
                }
Packit Service fdd496
            }
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      # If this commit's log requires any transformation, do it now.
Packit Service fdd496
      my $code = $amend_code->{$sha};
Packit Service fdd496
      if (defined $code)
Packit Service fdd496
        {
Packit Service fdd496
          eval 'use Safe';
Packit Service fdd496
          my $s = new Safe;
Packit Service fdd496
          # Put the unpreprocessed entry into "$_".
Packit Service fdd496
          $_ = $rest;
Packit Service fdd496
Packit Service fdd496
          # Let $code operate on it, safely.
Packit Service fdd496
          my $r = $s->reval("$code")
Packit Service fdd496
            or die "$ME:$.:$sha: failed to eval \"$code\":\n$@\n";
Packit Service fdd496
Packit Service fdd496
          # Note that we've used this entry.
Packit Service fdd496
          delete $amend_code->{$sha};
Packit Service fdd496
Packit Service fdd496
          # Update $rest upon success.
Packit Service fdd496
          $rest = $_;
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      # Remove lines inserted by "git cherry-pick".
Packit Service fdd496
      if ($strip_cherry_pick)
Packit Service fdd496
        {
Packit Service fdd496
          $rest =~ s/^\s*Conflicts:\n.*//sm;
Packit Service fdd496
          $rest =~ s/^\s*\(cherry picked from commit [\da-f]+\)\n//m;
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      my @line = split /[ \t]*\n/, $rest;
Packit Service fdd496
      my $author_line = shift @line;
Packit Service fdd496
      defined $author_line
Packit Service fdd496
        or die "$ME:$.: unexpected EOF\n";
Packit Service fdd496
      $author_line =~ /^(\d+)  (.*>)$/
Packit Service fdd496
        or die "$ME:$.: Invalid line "
Packit Service fdd496
          . "(expected date/author/email):\n$author_line\n";
Packit Service fdd496
Packit Service fdd496
      # Format 'Copyright-paperwork-exempt: Yes' as a standard ChangeLog
Packit Service fdd496
      # `(tiny change)' annotation.
Packit Service fdd496
      my $tiny = (grep (/^(?:Copyright-paperwork-exempt|Tiny-change):\s+[Yy]es$/, @line)
Packit Service fdd496
                  ? '  (tiny change)' : '');
Packit Service fdd496
Packit Service fdd496
      my $date_line = sprintf "%s  %s$tiny\n",
Packit Service fdd496
        strftime ("%Y-%m-%d", localtime ($1)), $2;
Packit Service fdd496
Packit Service fdd496
      my @coauthors = grep /^Co-authored-by:.*$/, @line;
Packit Service fdd496
      # Omit meta-data lines we've already interpreted.
Packit Service fdd496
      @line = grep !/^(?:Signed-off-by:[ ].*>$
Packit Service fdd496
                       |Co-authored-by:[ ]
Packit Service fdd496
                       |Copyright-paperwork-exempt:[ ]
Packit Service fdd496
                       |Tiny-change:[ ]
Packit Service fdd496
                       )/x, @line;
Packit Service fdd496
Packit Service fdd496
      # Remove leading and trailing blank lines.
Packit Service fdd496
      if (@line)
Packit Service fdd496
        {
Packit Service fdd496
          while ($line[0] =~ /^\s*$/) { shift @line; }
Packit Service fdd496
          while ($line[$#line] =~ /^\s*$/) { pop @line; }
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      # Handle Emacs gitmerge.el "skipped" commits.
Packit Service fdd496
      # Yes, this should be controlled by an option.  So sue me.
Packit Service fdd496
      if ( grep /^(; )?Merge from /, @line )
Packit Service fdd496
      {
Packit Service fdd496
          my $found = 0;
Packit Service fdd496
          foreach (@line)
Packit Service fdd496
          {
Packit Service fdd496
              if (grep /^The following commit.*skipped:$/, $_)
Packit Service fdd496
              {
Packit Service fdd496
                  $found = 1;
Packit Service fdd496
                  ## Reset at each merge to reduce chance of false matches.
Packit Service fdd496
                  @skipshas = ();
Packit Service fdd496
                  next;
Packit Service fdd496
              }
Packit Service fdd496
              if ($found && $_ =~ /^([0-9a-fA-F]{7,}) [^ ]/)
Packit Service fdd496
              {
Packit Service fdd496
                  push ( @skipshas, $1 );
Packit Service fdd496
              }
Packit Service fdd496
          }
Packit Service fdd496
      }
Packit Service fdd496
Packit Service fdd496
      # Ignore commits that match the --ignore-matching pattern, if specified.
Packit Service fdd496
      if (defined $ignore_matching && @line && $line[0] =~ /$ignore_matching/)
Packit Service fdd496
        {
Packit Service fdd496
          $skipflag = 1;
Packit Service fdd496
        }
Packit Service fdd496
      elsif ($skipflag)
Packit Service fdd496
        {
Packit Service fdd496
          ## Perhaps only warn if a pattern matches more than once?
Packit Service fdd496
          warn "$ME: warning: skipping $sha due to $skipflag\n";
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      if (! $skipflag)
Packit Service fdd496
        {
Packit Service fdd496
          if (defined $ignore_line && @line)
Packit Service fdd496
            {
Packit Service fdd496
              @line = grep ! /$ignore_line/, @line;
Packit Service fdd496
              while ($line[$#line] =~ /^\s*$/) { pop @line; }
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          # Record whether there are two or more paragraphs.
Packit Service fdd496
          my $multi_paragraph = grep /^\s*$/, @line;
Packit Service fdd496
Packit Service fdd496
          # Format 'Co-authored-by: A U Thor <email@example.com>' lines in
Packit Service fdd496
          # standard multi-author ChangeLog format.
Packit Service fdd496
          for (@coauthors)
Packit Service fdd496
            {
Packit Service fdd496
              s/^Co-authored-by:\s*/\t    /;
Packit Service fdd496
              s/\s*</  </;
Packit Service fdd496
Packit Service fdd496
              /<.*?@.*\..*>/
Packit Service fdd496
                or warn "$ME: warning: missing email address for "
Packit Service fdd496
                  . substr ($_, 5) . "\n";
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          # If clustering of commit messages has been disabled, if this header
Packit Service fdd496
          # would be different from the previous date/name/etc. header,
Packit Service fdd496
          # or if this or the previous entry consists of two or more paragraphs,
Packit Service fdd496
          # then print the header.
Packit Service fdd496
          if ( ! $cluster
Packit Service fdd496
              || $date_line ne $prev_date_line
Packit Service fdd496
              || "@coauthors" ne "@prev_coauthors"
Packit Service fdd496
              || $multi_paragraph
Packit Service fdd496
              || $prev_multi_paragraph)
Packit Service fdd496
            {
Packit Service fdd496
              $prev_date_line eq ''
Packit Service fdd496
                or print "\n";
Packit Service fdd496
              print $date_line;
Packit Service fdd496
              @coauthors
Packit Service fdd496
                and print join ("\n", @coauthors), "\n";
Packit Service fdd496
            }
Packit Service fdd496
          $prev_date_line = $date_line;
Packit Service fdd496
          @prev_coauthors = @coauthors;
Packit Service fdd496
          $prev_multi_paragraph = $multi_paragraph;
Packit Service fdd496
Packit Service fdd496
          # If there were any lines
Packit Service fdd496
          if (@line == 0)
Packit Service fdd496
            {
Packit Service fdd496
              warn "$ME: warning: empty commit message:\n  $date_line\n";
Packit Service fdd496
            }
Packit Service fdd496
          else
Packit Service fdd496
            {
Packit Service fdd496
              if ($append_dot)
Packit Service fdd496
                {
Packit Service fdd496
                  # If the first line of the message has enough room, then
Packit Service fdd496
                  if (length $line[0] < 72)
Packit Service fdd496
                    {
Packit Service fdd496
                      # append a dot if there is no other punctuation or blank
Packit Service fdd496
                      # at the end.
Packit Service fdd496
                      $line[0] =~ /[[:punct:]\s]$/
Packit Service fdd496
                        or $line[0] .= '.';
Packit Service fdd496
                    }
Packit Service fdd496
                }
Packit Service fdd496
Packit Service fdd496
              # Remove one additional leading TAB from each line.
Packit Service fdd496
              $strip_tab
Packit Service fdd496
                and map { s/^\t// } @line;
Packit Service fdd496
Packit Service fdd496
              # Prefix each non-empty line with a TAB.
Packit Service fdd496
              @line = map { length $_ ? "\t$_" : '' } @line;
Packit Service fdd496
Packit Service fdd496
              print "\n", join ("\n", @line), "\n";
Packit Service fdd496
            }
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      defined ($in = <PIPE>)
Packit Service fdd496
        or last;
Packit Service fdd496
      $in ne "\n"
Packit Service fdd496
        and die "$ME:$.: unexpected line:\n$in";
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
  close PIPE
Packit Service fdd496
    or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
Packit Service fdd496
  # FIXME-someday: include $PROCESS_STATUS in the diagnostic
Packit Service fdd496
Packit Service fdd496
  # Complain about any unused entry in the --amend=F specified file.
Packit Service fdd496
  my $fail = 0;
Packit Service fdd496
  foreach my $sha (keys %$amend_code)
Packit Service fdd496
    {
Packit Service fdd496
      warn "$ME:$amend_file: unused entry: $sha\n";
Packit Service fdd496
      $fail = 1;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
  exit $fail;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Local Variables:
Packit Service fdd496
# mode: perl
Packit Service fdd496
# indent-tabs-mode: nil
Packit Service fdd496
# eval: (add-hook 'write-file-hooks 'time-stamp)
Packit Service fdd496
# time-stamp-start: "my $VERSION = '"
Packit Service fdd496
# time-stamp-format: "%:y-%02m-%02d %02H:%02M"
Packit Service fdd496
# time-stamp-time-zone: "UTC0"
Packit Service fdd496
# time-stamp-end: "'; # UTC"
Packit Service fdd496
# End: