autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] maint: remove ChangeLog from version control; now we generate it


From: Jim Meyering
Subject: [PATCH] maint: remove ChangeLog from version control; now we generate it
Date: Tue, 17 Jan 2012 11:45:50 +0100

Having to deal with a version-controlled ChangeLog is an
unnecessary hassle, these days...

Does anyone object?

----------------------------
Notes about the patch:

FTR, choosing a generically-named file like "ChangeLog" for use in
AC_CONFIG_SRCDIR is a bad idea.  That file is too commonly found in
other directories.  Now that ChangeLog is gone, I've replaced it with
the eponymous bin/autoconf.as.

For now at least, I've simply git-added the new file,
gitlog-to-changelog, from gnulib.  Eventually we should
start using gnulib-tool.

>From 13702a340debfef88a34ab753616df5ffcaf59b9 Mon Sep 17 00:00:00 2001
From: Jim Meyering <address@hidden>
Date: Tue, 17 Jan 2012 11:18:08 +0100
Subject: [PATCH] maint: remove ChangeLog from version control; now we
 generate it

Instead, generate it from git commit logs and insert it
into each distribution tarball.
* Makefile.am (EXTRA_DIST): Add ChangeLog.3.
(gen-ChangeLog): New rule.
(dist-hook): Depend on it.
(ChangeLog): New rule.
* build-aux/gitlog-to-changelog: New file, from gnulib.
* ChangeLog: Rename to ...
* ChangeLog.3: ...new file.
* configure.in (AC_CONFIG_SRCDIR): Use bin/autoconf.as, not ChangeLog.
---
 ChangeLog => ChangeLog.3      |    0
 Makefile.am                   |   18 ++-
 build-aux/gitlog-to-changelog |  377 +++++++++++++++++++++++++++++++++++++++++
 configure.ac                  |    2 +-
 4 files changed, 394 insertions(+), 3 deletions(-)
 rename ChangeLog => ChangeLog.3 (100%)
 create mode 100755 build-aux/gitlog-to-changelog

diff --git a/ChangeLog b/ChangeLog.3
similarity index 100%
rename from ChangeLog
rename to ChangeLog.3
diff --git a/Makefile.am b/Makefile.am
index 6799c8e..5897564 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,7 +22,7 @@ SUBDIRS = bin . lib doc tests man

 ACLOCAL_AMFLAGS = -I m4

-EXTRA_DIST = ChangeLog.0 ChangeLog.1 ChangeLog.2 \
+EXTRA_DIST = ChangeLog.0 ChangeLog.1 ChangeLog.2 ChangeLog.3 \
             BUGS COPYINGv3 COPYING.EXCEPTION \
             GNUmakefile maint.mk cfg.mk \
             build-aux/gendocs.sh \
@@ -69,9 +69,23 @@ $(top_srcdir)/.version:

 # Arrange so that .tarball-version appears only in distribution tarballs,
 # never in a checked-out repository.
-dist-hook:
+dist-hook: gen-ChangeLog
        echo $(VERSION) > $(distdir)/.tarball-version

+gen_start_date = 2012-01-16
+.PHONY: gen-ChangeLog
+gen-ChangeLog:
+       $(AM_V_GEN)if test -d .git; then                                \
+         $(top_srcdir)/build-aux/gitlog-to-changelog                   \
+           --since=$(gen_start_date) > $(distdir)/cl-t;                \
+         rm -f $(distdir)/ChangeLog;                                   \
+         mv $(distdir)/cl-t $(distdir)/ChangeLog;                      \
+       fi
+
+# If it doesn't exist, create it, to placate automake.
+ChangeLog:
+       touch $@
+
 # Arrange to remove the symlink to GNUmakefile in VPATH builds.
 # TODO remove this once automake vs. AC_CONFIG_LINKS issue is fixed.
 distclean-local:
diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog
new file mode 100755
index 0000000..0efedb0
--- /dev/null
+++ b/build-aux/gitlog-to-changelog
@@ -0,0 +1,377 @@
+eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
+  & eval 'exec perl -wS "$0" $argv:q'
+    if 0;
+# Convert git log output to ChangeLog format.
+
+my $VERSION = '2012-01-06 07:14'; # UTC
+# The definition above must lie within the first 8 lines in order
+# for the Emacs time-stamp write hook (at end) to update it.
+# If you change this file with Emacs, please let the write hook
+# do its job.  Otherwise, update this string manually.
+
+# Copyright (C) 2008-2012 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Written by Jim Meyering
+
+use strict;
+use warnings;
+use Getopt::Long;
+use POSIX qw(strftime);
+
+(my $ME = $0) =~ s|.*/||;
+
+# use File::Coda; # http://meyering.net/code/Coda/
+END {
+  defined fileno STDOUT or return;
+  close STDOUT and return;
+  warn "$ME: failed to close standard output: $!\n";
+  $? ||= 1;
+}
+
+sub usage ($)
+{
+  my ($exit_code) = @_;
+  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
+  if ($exit_code != 0)
+    {
+      print $STREAM "Try '$ME --help' for more information.\n";
+    }
+  else
+    {
+      print $STREAM <<EOF;
+Usage: $ME [OPTIONS] [ARGS]
+
+Convert git log output to ChangeLog format.  If present, any ARGS
+are passed to "git log".  To avoid ARGS being parsed as options to
+$ME, they may be preceded by '--'.
+
+OPTIONS:
+
+   --amend=FILE FILE maps from an SHA1 to perl code (i.e., s/old/new/) that
+                  makes a change to SHA1's commit log text or metadata.
+   --append-dot append a dot to the first line of each commit message if
+                  there is no other punctuation or blank at the end.
+   --since=DATE convert only the logs since DATE;
+                  the default is to convert all log entries.
+   --format=FMT set format string for commit subject and body;
+                  see 'man git-log' for the list of format metacharacters;
+                  the default is '%s%n%b%n'
+
+   --help       display this help and exit
+   --version    output version information and exit
+
+EXAMPLE:
+
+  $ME --since=2008-01-01 > ChangeLog
+  $ME -- -n 5 foo > last-5-commits-to-branch-foo
+
+SPECIAL SYNTAX:
+
+The following types of strings are interpreted specially when they appear
+at the beginning of a log message line.  They are not copied to the output.
+
+  Copyright-paperwork-exempt: Yes
+    Append the "(tiny change)" notation to the usual "date name email"
+    ChangeLog header to mark a change that does not require a copyright
+    assignment.
+  Co-authored-by: Joe User <address@hidden>
+    List the specified name and email address on a second
+    ChangeLog header, denoting a co-author.
+  Signed-off-by: Joe User <address@hidden>
+    These lines are simply elided.
+
+In a FILE specified via --amend, comment lines (starting with "#") are ignored.
+FILE must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1 (alone on
+a line) referring to a commit in the current project, and CODE refers to one
+or more consecutive lines of Perl code.  Pairs must be separated by one or
+more blank line.
+
+Here is sample input for use with --amend=FILE, from coreutils:
+
+3a169f4c5d9159283548178668d2fae6fced3030
+# fix typo in title:
+s/all tile types/all file types/
+
+1379ed974f1fa39b12e2ffab18b3f7a607082202
+# Due to a bug in vc-dwim, I mis-attributed a patch by Paul to myself.
+# Change the author to be Paul.  Note the escaped "@":
+s,Jim .*>,Paul Eggert <address@hidden>,
+
+EOF
+    }
+  exit $exit_code;
+}
+
+# If the string $S is a well-behaved file name, simply return it.
+# If it contains white space, quotes, etc., quote it, and return the new 
string.
+sub shell_quote($)
+{
+  my ($s) = @_;
+  if ($s =~ m![^\w+/.,-]!)
+    {
+      # Convert each single quote to '\''
+      $s =~ s/\'/\'\\\'\'/g;
+      # Then single quote the string.
+      $s = "'$s'";
+    }
+  return $s;
+}
+
+sub quoted_cmd(@)
+{
+  return join (' ', map {shell_quote $_} @_);
+}
+
+# Parse file F.
+# Comment lines (starting with "#") are ignored.
+# F must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1
+# (alone on a line) referring to a commit in the current project, and
+# CODE refers to one or more consecutive lines of Perl code.
+# Pairs must be separated by one or more blank line.
+sub parse_amend_file($)
+{
+  my ($f) = @_;
+
+  open F, '<', $f
+    or die "$ME: $f: failed to open for reading: $!\n";
+
+  my $fail;
+  my $h = {};
+  my $in_code = 0;
+  my $sha;
+  while (defined (my $line = <F>))
+    {
+      $line =~ /^\#/
+        and next;
+      chomp $line;
+      $line eq ''
+        and $in_code = 0, next;
+
+      if (!$in_code)
+        {
+          $line =~ /^([0-9a-fA-F]{40})$/
+            or (warn "$ME: $f:$.: invalid line; expected an SHA1\n"),
+              $fail = 1, next;
+          $sha = lc $1;
+          $in_code = 1;
+          exists $h->{$sha}
+            and (warn "$ME: $f:$.: duplicate SHA1\n"),
+              $fail = 1, next;
+        }
+      else
+        {
+          $h->{$sha} ||= '';
+          $h->{$sha} .= "$line\n";
+        }
+    }
+  close F;
+
+  $fail
+    and exit 1;
+
+  return $h;
+}
+
+{
+  my $since_date;
+  my $format_string = '%s%n%b%n';
+  my $amend_file;
+  my $append_dot = 0;
+  GetOptions
+    (
+     help => sub { usage 0 },
+     version => sub { print "$ME version $VERSION\n"; exit },
+     'since=s' => \$since_date,
+     'format=s' => \$format_string,
+     'amend=s' => \$amend_file,
+     'append-dot' => \$append_dot,
+    ) or usage 1;
+
+
+  defined $since_date
+    and unshift @ARGV, "--since=$since_date";
+
+  # This is a hash that maps an SHA1 to perl code (i.e., s/old/new/)
+  # that makes a correction in the log or attribution of that commit.
+  my $amend_code = defined $amend_file ? parse_amend_file $amend_file : {};
+
+  my @cmd = (qw (git log --log-size),
+             '--pretty=format:%H:%ct  %an  <%ae>%n%n'.$format_string, @ARGV);
+  open PIPE, '-|', @cmd
+    or die ("$ME: failed to run '". quoted_cmd (@cmd) ."': $!\n"
+            . "(Is your Git too old?  Version 1.5.1 or later is required.)\n");
+
+  my $prev_multi_paragraph;
+  my $prev_date_line = '';
+  my @prev_coauthors = ();
+  while (1)
+    {
+      defined (my $in = <PIPE>)
+        or last;
+      $in =~ /^log size (\d+)$/
+        or die "$ME:$.: Invalid line (expected log size):\n$in";
+      my $log_nbytes = $1;
+
+      my $log;
+      my $n_read = read PIPE, $log, $log_nbytes;
+      $n_read == $log_nbytes
+        or die "$ME:$.: unexpected EOF\n";
+
+      # Extract leading hash.
+      my ($sha, $rest) = split ':', $log, 2;
+      defined $sha
+        or die "$ME:$.: malformed log entry\n";
+      $sha =~ /^[0-9a-fA-F]{40}$/
+        or die "$ME:$.: invalid SHA1: $sha\n";
+
+      # If this commit's log requires any transformation, do it now.
+      my $code = $amend_code->{$sha};
+      if (defined $code)
+        {
+          eval 'use Safe';
+          my $s = new Safe;
+          # Put the unpreprocessed entry into "$_".
+          $_ = $rest;
+
+          # Let $code operate on it, safely.
+          my $r = $s->reval("$code")
+            or die "$ME:$.:$sha: failed to eval \"$code\":address@hidden";
+
+          # Note that we've used this entry.
+          delete $amend_code->{$sha};
+
+          # Update $rest upon success.
+          $rest = $_;
+        }
+
+      my @line = split "\n", $rest;
+      my $author_line = shift @line;
+      defined $author_line
+        or die "$ME:$.: unexpected EOF\n";
+      $author_line =~ /^(\d+)  (.*>)$/
+        or die "$ME:$.: Invalid line "
+          . "(expected date/author/email):\n$author_line\n";
+
+      # Format 'Copyright-paperwork-exempt: Yes' as a standard ChangeLog
+      # `(tiny change)' annotation.
+      my $tiny = (grep (/^Copyright-paperwork-exempt:\s+[Yy]es$/, @line)
+                  ? '  (tiny change)' : '');
+
+      my $date_line = sprintf "%s  %s$tiny\n",
+        strftime ("%F", localtime ($1)), $2;
+
+      my @coauthors = grep /^Co-authored-by:.*$/, @line;
+      # Omit meta-data lines we've already interpreted.
+      @line = grep !/^(?:Signed-off-by:[ ].*>$
+                       |Co-authored-by:[ ]
+                       |Copyright-paperwork-exempt:[ ]
+                       )/x, @line;
+
+      # Remove leading and trailing blank lines.
+      if (@line)
+        {
+          while ($line[0] =~ /^\s*$/) { shift @line; }
+          while ($line[$#line] =~ /^\s*$/) { pop @line; }
+        }
+
+      # Record whether there are two or more paragraphs.
+      my $multi_paragraph = grep /^\s*$/, @line;
+
+      # Format 'Co-authored-by: A U Thor <address@hidden>' lines in
+      # standard multi-author ChangeLog format.
+      for (@coauthors)
+        {
+          s/^Co-authored-by:\s*/\t    /;
+          s/\s*</  </;
+
+          /<address@hidden>/
+            or warn "$ME: warning: missing email address for "
+              . substr ($_, 5) . "\n";
+        }
+
+      # If this header would be different from the previous date/name/email/
+      # coauthors header, or if this or the previous entry consists of two
+      # or more paragraphs, then print the header.
+      if ($date_line ne $prev_date_line
+          or "@coauthors" ne "@prev_coauthors"
+          or $multi_paragraph
+          or $prev_multi_paragraph)
+        {
+          $prev_date_line eq ''
+            or print "\n";
+          print $date_line;
+          @coauthors
+            and print join ("\n", @coauthors), "\n";
+        }
+      $prev_date_line = $date_line;
+      @prev_coauthors = @coauthors;
+      $prev_multi_paragraph = $multi_paragraph;
+
+      # If there were any lines
+      if (@line == 0)
+        {
+          warn "$ME: warning: empty commit message:\n  $date_line\n";
+        }
+      else
+        {
+          if ($append_dot)
+            {
+              # If the first line of the message has enough room, then
+              if (length $line[0] < 72)
+                {
+                  # append a dot if there is no other punctuation or blank
+                  # at the end.
+                  $line[0] =~ /[[:punct:]\s]$/
+                    or $line[0] .= '.';
+                }
+            }
+
+          # Prefix each non-empty line with a TAB.
+          @line = map { length $_ ? "\t$_" : '' } @line;
+
+          print "\n", join ("\n", @line), "\n";
+        }
+
+      defined ($in = <PIPE>)
+        or last;
+      $in ne "\n"
+        and die "$ME:$.: unexpected line:\n$in";
+    }
+
+  close PIPE
+    or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
+  # FIXME-someday: include $PROCESS_STATUS in the diagnostic
+
+  # Complain about any unused entry in the --amend=F specified file.
+  my $fail = 0;
+  foreach my $sha (keys %$amend_code)
+    {
+      warn "$ME:$amend_file: unused entry: $sha\n";
+      $fail = 1;
+    }
+
+  exit $fail;
+}
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "my $VERSION = '"
+# time-stamp-format: "%:y-%02m-%02d %02H:%02M"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "'; # UTC"
+# End:
diff --git a/configure.ac b/configure.ac
index 92efb25..05a7f43 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@ AC_PREREQ([2.60])
 AC_INIT([GNU Autoconf],
        m4_esyscmd([build-aux/git-version-gen .tarball-version]),
        address@hidden)
-AC_CONFIG_SRCDIR([ChangeLog])
+AC_CONFIG_SRCDIR([bin/autoconf.as])

 AC_CONFIG_AUX_DIR([build-aux])

--
1.7.9.rc1.2.gccfe4



reply via email to

[Prev in Thread] Current Thread [Next in Thread]