mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-29 19:30:36 +02:00
This reverts commit 2d4da30fde
.
This Gnulib update was causing failures related to timezones in
stime.c. I tried to fix it by adopting the time_rz module from gnulib
but that then caused other failures. We can try again later.
555 lines
16 KiB
Text
Executable file
555 lines
16 KiB
Text
Executable file
eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
|
|
& eval 'exec perl -wS "$0" $argv:q'
|
|
if 0;
|
|
# Generate a release announcement message.
|
|
|
|
my $VERSION = '2012-06-08 06:53'; # 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) 2002-2014 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 Getopt::Long;
|
|
use Digest::MD5;
|
|
eval { require Digest::SHA; }
|
|
or eval 'use Digest::SHA1';
|
|
use POSIX qw(strftime);
|
|
|
|
(my $ME = $0) =~ s|.*/||;
|
|
|
|
my %valid_release_types = map {$_ => 1} qw (alpha beta stable);
|
|
my @archive_suffixes = ('tar.gz', 'tar.bz2', 'tar.lzma', 'tar.xz');
|
|
my $srcdir = '.';
|
|
|
|
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
|
|
{
|
|
my @types = sort keys %valid_release_types;
|
|
print $STREAM <<EOF;
|
|
Usage: $ME [OPTIONS]
|
|
Generate an announcement message. Run this from builddir.
|
|
|
|
OPTIONS:
|
|
|
|
These options must be specified:
|
|
|
|
--release-type=TYPE TYPE must be one of @types
|
|
--package-name=PACKAGE_NAME
|
|
--previous-version=VER
|
|
--current-version=VER
|
|
--gpg-key-id=ID The GnuPG ID of the key used to sign the tarballs
|
|
--url-directory=URL_DIR
|
|
|
|
The following are optional:
|
|
|
|
--news=NEWS_FILE include the NEWS section about this release
|
|
from this NEWS_FILE; accumulates.
|
|
--srcdir=DIR where to find the NEWS_FILEs (default: $srcdir)
|
|
--bootstrap-tools=TOOL_LIST a comma-separated list of tools, e.g.,
|
|
autoconf,automake,bison,gnulib
|
|
--gnulib-version=VERSION report VERSION as the gnulib version, where
|
|
VERSION is the result of running git describe
|
|
in the gnulib source directory.
|
|
required if gnulib is in TOOL_LIST.
|
|
--no-print-checksums do not emit MD5 or SHA1 checksums
|
|
--archive-suffix=SUF add SUF to the list of archive suffixes
|
|
--mail-headers=HEADERS a space-separated list of mail headers, e.g.,
|
|
To: x\@example.com Cc: y-announce\@example.com,...
|
|
|
|
--help display this help and exit
|
|
--version output version information and exit
|
|
|
|
EOF
|
|
}
|
|
exit $exit_code;
|
|
}
|
|
|
|
|
|
=item C<%size> = C<sizes (@file)>
|
|
|
|
Compute the sizes of the C<@file> and return them as a hash. Return
|
|
C<undef> if one of the computation failed.
|
|
|
|
=cut
|
|
|
|
sub sizes (@)
|
|
{
|
|
my (@file) = @_;
|
|
|
|
my $fail = 0;
|
|
my %res;
|
|
foreach my $f (@file)
|
|
{
|
|
my $cmd = "du -h $f";
|
|
my $t = `$cmd`;
|
|
# FIXME-someday: give a better diagnostic, a la $PROCESS_STATUS
|
|
$@
|
|
and (warn "command failed: '$cmd'\n"), $fail = 1;
|
|
chomp $t;
|
|
$t =~ s/^\s*([\d.]+[MkK]).*/${1}B/;
|
|
$res{$f} = $t;
|
|
}
|
|
return $fail ? undef : %res;
|
|
}
|
|
|
|
=item C<print_locations ($title, \@url, \%size, @file)
|
|
|
|
Print a section C<$title> dedicated to the list of <@file>, which
|
|
sizes are stored in C<%size>, and which are available from the C<@url>.
|
|
|
|
=cut
|
|
|
|
sub print_locations ($\@\%@)
|
|
{
|
|
my ($title, $url, $size, @file) = @_;
|
|
print "Here are the $title:\n";
|
|
foreach my $url (@{$url})
|
|
{
|
|
for my $file (@file)
|
|
{
|
|
print " $url/$file";
|
|
print " (", $$size{$file}, ")"
|
|
if exists $$size{$file};
|
|
print "\n";
|
|
}
|
|
}
|
|
print "\n";
|
|
}
|
|
|
|
=item C<print_checksums (@file)
|
|
|
|
Print the MD5 and SHA1 signature section for each C<@file>.
|
|
|
|
=cut
|
|
|
|
sub print_checksums (@)
|
|
{
|
|
my (@file) = @_;
|
|
|
|
print "Here are the MD5 and SHA1 checksums:\n";
|
|
print "\n";
|
|
|
|
foreach my $meth (qw (md5 sha1))
|
|
{
|
|
foreach my $f (@file)
|
|
{
|
|
open IN, '<', $f
|
|
or die "$ME: $f: cannot open for reading: $!\n";
|
|
binmode IN;
|
|
my $dig =
|
|
($meth eq 'md5'
|
|
? Digest::MD5->new->addfile(*IN)->hexdigest
|
|
: Digest::SHA1->new->addfile(*IN)->hexdigest);
|
|
close IN;
|
|
print "$dig $f\n";
|
|
}
|
|
}
|
|
print "\n";
|
|
}
|
|
|
|
=item C<print_news_deltas ($news_file, $prev_version, $curr_version)
|
|
|
|
Print the section of the NEWS file C<$news_file> addressing changes
|
|
between versions C<$prev_version> and C<$curr_version>.
|
|
|
|
=cut
|
|
|
|
sub print_news_deltas ($$$)
|
|
{
|
|
my ($news_file, $prev_version, $curr_version) = @_;
|
|
|
|
my $news_name = $news_file;
|
|
$news_name =~ s|^\Q$srcdir\E/||;
|
|
|
|
print "\n$news_name\n\n";
|
|
|
|
# Print all lines from $news_file, starting with the first one
|
|
# that mentions $curr_version up to but not including
|
|
# the first occurrence of $prev_version.
|
|
my $in_items;
|
|
|
|
my $re_prefix = qr/(?:\* )?(?:Noteworthy c|Major c|C)(?i:hanges)/;
|
|
|
|
my $found_news;
|
|
open NEWS, '<', $news_file
|
|
or die "$ME: $news_file: cannot open for reading: $!\n";
|
|
while (defined (my $line = <NEWS>))
|
|
{
|
|
if ( ! $in_items)
|
|
{
|
|
# Match lines like these:
|
|
# * Major changes in release 5.0.1:
|
|
# * Noteworthy changes in release 6.6 (2006-11-22) [stable]
|
|
$line =~ /^$re_prefix.*(?:[^\d.]|$)\Q$curr_version\E(?:[^\d.]|$)/o
|
|
or next;
|
|
$in_items = 1;
|
|
print $line;
|
|
}
|
|
else
|
|
{
|
|
# This regexp must not match version numbers in NEWS items.
|
|
# For example, they might well say "introduced in 4.5.5",
|
|
# and we don't want that to match.
|
|
$line =~ /^$re_prefix.*(?:[^\d.]|$)\Q$prev_version\E(?:[^\d.]|$)/o
|
|
and last;
|
|
print $line;
|
|
$line =~ /\S/
|
|
and $found_news = 1;
|
|
}
|
|
}
|
|
close NEWS;
|
|
|
|
$in_items
|
|
or die "$ME: $news_file: no matching lines for '$curr_version'\n";
|
|
$found_news
|
|
or die "$ME: $news_file: no news item found for '$curr_version'\n";
|
|
}
|
|
|
|
sub print_changelog_deltas ($$)
|
|
{
|
|
my ($package_name, $prev_version) = @_;
|
|
|
|
# Print new ChangeLog entries.
|
|
|
|
# First find all CVS-controlled ChangeLog files.
|
|
use File::Find;
|
|
my @changelog;
|
|
find ({wanted => sub {$_ eq 'ChangeLog' && -d 'CVS'
|
|
and push @changelog, $File::Find::name}},
|
|
'.');
|
|
|
|
# If there are no ChangeLog files, we're done.
|
|
@changelog
|
|
or return;
|
|
my %changelog = map {$_ => 1} @changelog;
|
|
|
|
# Reorder the list of files so that if there are ChangeLog
|
|
# files in the specified directories, they're listed first,
|
|
# in this order:
|
|
my @dir = qw ( . src lib m4 config doc );
|
|
|
|
# A typical @changelog array might look like this:
|
|
# ./ChangeLog
|
|
# ./po/ChangeLog
|
|
# ./m4/ChangeLog
|
|
# ./lib/ChangeLog
|
|
# ./doc/ChangeLog
|
|
# ./config/ChangeLog
|
|
my @reordered;
|
|
foreach my $d (@dir)
|
|
{
|
|
my $dot_slash = $d eq '.' ? $d : "./$d";
|
|
my $target = "$dot_slash/ChangeLog";
|
|
delete $changelog{$target}
|
|
and push @reordered, $target;
|
|
}
|
|
|
|
# Append any remaining ChangeLog files.
|
|
push @reordered, sort keys %changelog;
|
|
|
|
# Remove leading './'.
|
|
@reordered = map { s!^\./!!; $_ } @reordered;
|
|
|
|
print "\nChangeLog entries:\n\n";
|
|
# print join ("\n", @reordered), "\n";
|
|
|
|
$prev_version =~ s/\./_/g;
|
|
my $prev_cvs_tag = "\U$package_name\E-$prev_version";
|
|
|
|
my $cmd = "cvs -n diff -u -r$prev_cvs_tag -rHEAD @reordered";
|
|
open DIFF, '-|', $cmd
|
|
or die "$ME: cannot run '$cmd': $!\n";
|
|
# Print two types of lines, making minor changes:
|
|
# Lines starting with '+++ ', e.g.,
|
|
# +++ ChangeLog 22 Feb 2003 16:52:51 -0000 1.247
|
|
# and those starting with '+'.
|
|
# Don't print the others.
|
|
my $prev_printed_line_empty = 1;
|
|
while (defined (my $line = <DIFF>))
|
|
{
|
|
if ($line =~ /^\+\+\+ /)
|
|
{
|
|
my $separator = "*"x70 ."\n";
|
|
$line =~ s///;
|
|
$line =~ s/\s.*//;
|
|
$prev_printed_line_empty
|
|
or print "\n";
|
|
print $separator, $line, $separator;
|
|
}
|
|
elsif ($line =~ /^\+/)
|
|
{
|
|
$line =~ s///;
|
|
print $line;
|
|
$prev_printed_line_empty = ($line =~ /^$/);
|
|
}
|
|
}
|
|
close DIFF;
|
|
|
|
# The exit code should be 1.
|
|
# Allow in case there are no modified ChangeLog entries.
|
|
$? == 256 || $? == 128
|
|
or warn "warning: '$cmd' had unexpected exit code or signal ($?)\n";
|
|
}
|
|
|
|
sub get_tool_versions ($$)
|
|
{
|
|
my ($tool_list, $gnulib_version) = @_;
|
|
@$tool_list
|
|
or return ();
|
|
|
|
my $fail;
|
|
my @tool_version_pair;
|
|
foreach my $t (@$tool_list)
|
|
{
|
|
if ($t eq 'gnulib')
|
|
{
|
|
push @tool_version_pair, ucfirst $t . ' ' . $gnulib_version;
|
|
next;
|
|
}
|
|
# Assume that the last "word" on the first line of
|
|
# 'tool --version' output is the version string.
|
|
my ($first_line, undef) = split ("\n", `$t --version`);
|
|
if ($first_line =~ /.* (\d[\w.-]+)$/)
|
|
{
|
|
$t = ucfirst $t;
|
|
push @tool_version_pair, "$t $1";
|
|
}
|
|
else
|
|
{
|
|
defined $first_line
|
|
and $first_line = '';
|
|
warn "$t: unexpected --version output\n:$first_line";
|
|
$fail = 1;
|
|
}
|
|
}
|
|
|
|
$fail
|
|
and exit 1;
|
|
|
|
return @tool_version_pair;
|
|
}
|
|
|
|
{
|
|
# Neutralize the locale, so that, for instance, "du" does not
|
|
# issue "1,2" instead of "1.2", what confuses our regexps.
|
|
$ENV{LC_ALL} = "C";
|
|
|
|
my $mail_headers;
|
|
my $release_type;
|
|
my $package_name;
|
|
my $prev_version;
|
|
my $curr_version;
|
|
my $gpg_key_id;
|
|
my @url_dir_list;
|
|
my @news_file;
|
|
my $bootstrap_tools;
|
|
my $gnulib_version;
|
|
my $print_checksums_p = 1;
|
|
|
|
# Reformat the warnings before displaying them.
|
|
local $SIG{__WARN__} = sub
|
|
{
|
|
my ($msg) = @_;
|
|
# Warnings from GetOptions.
|
|
$msg =~ s/Option (\w)/option --$1/;
|
|
warn "$ME: $msg";
|
|
};
|
|
|
|
GetOptions
|
|
(
|
|
'mail-headers=s' => \$mail_headers,
|
|
'release-type=s' => \$release_type,
|
|
'package-name=s' => \$package_name,
|
|
'previous-version=s' => \$prev_version,
|
|
'current-version=s' => \$curr_version,
|
|
'gpg-key-id=s' => \$gpg_key_id,
|
|
'url-directory=s' => \@url_dir_list,
|
|
'news=s' => \@news_file,
|
|
'srcdir=s' => \$srcdir,
|
|
'bootstrap-tools=s' => \$bootstrap_tools,
|
|
'gnulib-version=s' => \$gnulib_version,
|
|
'print-checksums!' => \$print_checksums_p,
|
|
'archive-suffix=s' => \@archive_suffixes,
|
|
|
|
help => sub { usage 0 },
|
|
version => sub { print "$ME version $VERSION\n"; exit },
|
|
) or usage 1;
|
|
|
|
my $fail = 0;
|
|
# Ensure that each required option is specified.
|
|
$release_type
|
|
or (warn "release type not specified\n"), $fail = 1;
|
|
$package_name
|
|
or (warn "package name not specified\n"), $fail = 1;
|
|
$prev_version
|
|
or (warn "previous version string not specified\n"), $fail = 1;
|
|
$curr_version
|
|
or (warn "current version string not specified\n"), $fail = 1;
|
|
$gpg_key_id
|
|
or (warn "GnuPG key ID not specified\n"), $fail = 1;
|
|
@url_dir_list
|
|
or (warn "URL directory name(s) not specified\n"), $fail = 1;
|
|
|
|
my @tool_list = split ',', $bootstrap_tools;
|
|
|
|
grep (/^gnulib$/, @tool_list) ^ defined $gnulib_version
|
|
and (warn "when specifying gnulib as a tool, you must also specify\n"
|
|
. "--gnulib-version=V, where V is the result of running git describe\n"
|
|
. "in the gnulib source directory.\n"), $fail = 1;
|
|
|
|
exists $valid_release_types{$release_type}
|
|
or (warn "'$release_type': invalid release type\n"), $fail = 1;
|
|
|
|
@ARGV
|
|
and (warn "too many arguments:\n", join ("\n", @ARGV), "\n"),
|
|
$fail = 1;
|
|
$fail
|
|
and usage 1;
|
|
|
|
my $my_distdir = "$package_name-$curr_version";
|
|
|
|
my $xd = "$package_name-$prev_version-$curr_version.xdelta";
|
|
|
|
my @candidates = map { "$my_distdir.$_" } @archive_suffixes;
|
|
my @tarballs = grep {-f $_} @candidates;
|
|
|
|
@tarballs
|
|
or die "$ME: none of " . join(', ', @candidates) . " were found\n";
|
|
my @sizable = @tarballs;
|
|
-f $xd
|
|
and push @sizable, $xd;
|
|
my %size = sizes (@sizable);
|
|
%size
|
|
or exit 1;
|
|
|
|
my $headers = '';
|
|
if (defined $mail_headers)
|
|
{
|
|
($headers = $mail_headers) =~ s/\s+(\S+:)/\n$1/g;
|
|
$headers .= "\n";
|
|
}
|
|
|
|
# The markup is escaped as <\# so that when this script is sent by
|
|
# mail (or part of a diff), Gnus is not triggered.
|
|
print <<EOF;
|
|
|
|
${headers}Subject: $my_distdir released [$release_type]
|
|
|
|
<\#secure method=pgpmime mode=sign>
|
|
|
|
FIXME: put comments here
|
|
|
|
EOF
|
|
|
|
if (@url_dir_list == 1 && @tarballs == 1)
|
|
{
|
|
# When there's only one tarball and one URL, use a more concise form.
|
|
my $m = "$url_dir_list[0]/$tarballs[0]";
|
|
print "Here are the compressed sources and a GPG detached signature[*]:\n"
|
|
. " $m\n"
|
|
. " $m.sig\n\n";
|
|
}
|
|
else
|
|
{
|
|
print_locations ("compressed sources", @url_dir_list, %size, @tarballs);
|
|
-f $xd
|
|
and print_locations ("xdelta diffs (useful? if so, "
|
|
. "please tell bug-gnulib\@gnu.org)",
|
|
@url_dir_list, %size, $xd);
|
|
my @sig_files = map { "$_.sig" } @tarballs;
|
|
print_locations ("GPG detached signatures[*]", @url_dir_list, %size,
|
|
@sig_files);
|
|
}
|
|
|
|
if ($url_dir_list[0] =~ "gnu\.org")
|
|
{
|
|
print "Use a mirror for higher download bandwidth:\n";
|
|
if (@tarballs == 1 && $url_dir_list[0] =~ m!http://ftp\.gnu\.org/gnu/!)
|
|
{
|
|
(my $m = "$url_dir_list[0]/$tarballs[0]")
|
|
=~ s!http://ftp\.gnu\.org/gnu/!http://ftpmirror\.gnu\.org/!;
|
|
print " $m\n"
|
|
. " $m.sig\n\n";
|
|
|
|
}
|
|
else
|
|
{
|
|
print " http://www.gnu.org/order/ftp.html\n\n";
|
|
}
|
|
}
|
|
|
|
$print_checksums_p
|
|
and print_checksums (@sizable);
|
|
|
|
print <<EOF;
|
|
[*] Use a .sig file to verify that the corresponding file (without the
|
|
.sig suffix) is intact. First, be sure to download both the .sig file
|
|
and the corresponding tarball. Then, run a command like this:
|
|
|
|
gpg --verify $tarballs[0].sig
|
|
|
|
If that command fails because you don't have the required public key,
|
|
then run this command to import it:
|
|
|
|
gpg --keyserver keys.gnupg.net --recv-keys $gpg_key_id
|
|
|
|
and rerun the 'gpg --verify' command.
|
|
EOF
|
|
|
|
my @tool_versions = get_tool_versions (\@tool_list, $gnulib_version);
|
|
@tool_versions
|
|
and print "\nThis release was bootstrapped with the following tools:",
|
|
join ('', map {"\n $_"} @tool_versions), "\n";
|
|
|
|
print_news_deltas ($_, $prev_version, $curr_version)
|
|
foreach @news_file;
|
|
|
|
$release_type eq 'stable'
|
|
or print_changelog_deltas ($package_name, $prev_version);
|
|
|
|
exit 0;
|
|
}
|
|
|
|
### Setup "GNU" style for perl-mode and cperl-mode.
|
|
## Local Variables:
|
|
## mode: perl
|
|
## perl-indent-level: 2
|
|
## perl-continued-statement-offset: 2
|
|
## perl-continued-brace-offset: 0
|
|
## perl-brace-offset: 0
|
|
## perl-brace-imaginary-offset: 0
|
|
## perl-label-offset: -2
|
|
## perl-extra-newline-before-brace: t
|
|
## perl-merge-trailing-else: 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:
|