VirtualBox

source: kBuild/vendor/sed/current/build-aux/announce-gen@ 3613

Last change on this file since 3613 was 3611, checked in by bird, 5 months ago

vendor/sed/current: GNU sed 4.9 (sed-4.9.tar.xz sha256:6e226b732e1cd739464ad6862bd1a1aba42d7982922da7a53519631d24975181)

  • Property svn:executable set to *
File size: 18.2 KB
Line 
1#!/bin/sh
2#! -*-perl-*-
3
4# Generate a release announcement message.
5
6# Copyright (C) 2002-2022 Free Software Foundation, Inc.
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program. If not, see <https://www.gnu.org/licenses/>.
20#
21# Written by Jim Meyering
22
23# This is a prologue that allows to run a perl script as an executable
24# on systems that are compliant to a POSIX version before POSIX:2017.
25# On such systems, the usual invocation of an executable through execlp()
26# or execvp() fails with ENOEXEC if it is a script that does not start
27# with a #! line. The script interpreter mentioned in the #! line has
28# to be /bin/sh, because on GuixSD systems that is the only program that
29# has a fixed file name. The second line is essential for perl and is
30# also useful for editing this file in Emacs. The next two lines below
31# are valid code in both sh and perl. When executed by sh, they re-execute
32# the script through the perl program found in $PATH. The '-x' option
33# is essential as well; without it, perl would re-execute the script
34# through /bin/sh. When executed by perl, the next two lines are a no-op.
35eval 'exec perl -wSx "$0" "$@"'
36 if 0;
37
38my $VERSION = '2022-07-10 01:47'; # UTC
39# The definition above must lie within the first 8 lines in order
40# for the Emacs time-stamp write hook (at end) to update it.
41# If you change this file with Emacs, please let the write hook
42# do its job. Otherwise, update this string manually.
43
44my $copyright_year = '2022';
45
46use strict;
47use Getopt::Long;
48use POSIX qw(strftime);
49
50(my $ME = $0) =~ s|.*/||;
51
52my %valid_release_types = map {$_ => 1} qw (alpha beta stable);
53my @archive_suffixes = qw (tar.gz tar.bz2 tar.lz tar.lzma tar.xz);
54my $srcdir = '.';
55
56sub usage ($)
57{
58 my ($exit_code) = @_;
59 my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
60 if ($exit_code != 0)
61 {
62 print $STREAM "Try '$ME --help' for more information.\n";
63 }
64 else
65 {
66 my @types = sort keys %valid_release_types;
67 print $STREAM <<EOF;
68Usage: $ME [OPTIONS]
69Generate an announcement message. Run this from builddir.
70
71OPTIONS:
72
73These options must be specified:
74
75 --release-type=TYPE TYPE must be one of @types
76 --package-name=PACKAGE_NAME
77 --previous-version=VER
78 --current-version=VER
79 --gpg-key-id=ID The GnuPG ID of the key used to sign the tarballs
80 --url-directory=URL_DIR
81
82The following are optional:
83
84 --news=NEWS_FILE include the NEWS section about this release
85 from this NEWS_FILE; accumulates.
86 --srcdir=DIR where to find the NEWS_FILEs (default: $srcdir)
87 --bootstrap-tools=TOOL_LIST a comma-separated list of tools, e.g.,
88 autoconf,automake,bison,gnulib
89 --gnulib-version=VERSION report VERSION as the gnulib version, where
90 VERSION is the result of running git describe
91 in the gnulib source directory.
92 required if gnulib is in TOOL_LIST.
93 --gpg-key-email=EMAIL The email address of the key used to
94 sign the tarballs
95 --gpg-keyring-url=URL URL pointing to keyring containing the key used
96 to sign the tarballs
97 --no-print-checksums do not emit SHA1 or SHA256 checksums
98 --archive-suffix=SUF add SUF to the list of archive suffixes
99 --mail-headers=HEADERS a space-separated list of mail headers, e.g.,
100 To: x\@example.com Cc: y-announce\@example.com,...
101
102 --help display this help and exit
103 --version output version information and exit
104
105EOF
106 }
107 exit $exit_code;
108}
109
110
111=item C<%size> = C<sizes (@file)>
112
113Compute the sizes of the C<@file> and return them as a hash. Return
114C<undef> if one of the computation failed.
115
116=cut
117
118sub sizes (@)
119{
120 my (@file) = @_;
121
122 my $fail = 0;
123 my %res;
124 foreach my $f (@file)
125 {
126 my $cmd = "du -h $f";
127 my $t = `$cmd`;
128 # FIXME-someday: give a better diagnostic, a la $PROCESS_STATUS
129 $@
130 and (warn "command failed: '$cmd'\n"), $fail = 1;
131 chomp $t;
132 $t =~ s/^\s*([\d.]+[MkK]).*/${1}B/;
133 $res{$f} = $t;
134 }
135 return $fail ? undef : %res;
136}
137
138=item C<print_locations ($title, \@url, \%size, @file)
139
140Print a section C<$title> dedicated to the list of <@file>, which
141sizes are stored in C<%size>, and which are available from the C<@url>.
142
143=cut
144
145sub print_locations ($\@\%@)
146{
147 my ($title, $url, $size, @file) = @_;
148 print "Here are the $title:\n";
149 foreach my $url (@{$url})
150 {
151 for my $file (@file)
152 {
153 print " $url/$file";
154 print " (", $$size{$file}, ")"
155 if exists $$size{$file};
156 print "\n";
157 }
158 }
159 print "\n";
160}
161
162=item C<print_checksums (@file)
163
164Print the SHA1 and SHA256 signature section for each C<@file>.
165
166=cut
167
168sub print_checksums (@)
169{
170 my (@file) = @_;
171
172 print "Here are the SHA1 and SHA256 checksums:\n";
173 print "\n";
174
175 use Digest::file qw(digest_file_hex digest_file_base64);
176
177 foreach my $f (@file)
178 {
179 print digest_file_hex($f, "SHA-1"), " $f\n";
180 print digest_file_base64($f, "SHA-256"), " $f\n";
181 }
182 print "\nThe SHA256 checksum is base64 encoded, instead of the\n";
183 print "hexadecimal encoding that most checksum tools default to.\n\n";
184}
185
186=item C<print_news_deltas ($news_file, $prev_version, $curr_version)
187
188Print the section of the NEWS file C<$news_file> addressing changes
189between versions C<$prev_version> and C<$curr_version>.
190
191=cut
192
193sub print_news_deltas ($$$)
194{
195 my ($news_file, $prev_version, $curr_version) = @_;
196
197 my $news_name = $news_file;
198 $news_name =~ s|^\Q$srcdir\E/||;
199
200 print "\n$news_name\n\n";
201
202 # Print all lines from $news_file, starting with the first one
203 # that mentions $curr_version up to but not including
204 # the first occurrence of $prev_version.
205 my $in_items;
206
207 my $re_prefix = qr/(?:\* )?(?:Noteworthy c|Major c|C)(?i:hanges)/;
208
209 my $found_news;
210 open NEWS, '<', $news_file
211 or die "$ME: $news_file: cannot open for reading: $!\n";
212 while (defined (my $line = <NEWS>))
213 {
214 if ( ! $in_items)
215 {
216 # Match lines like these:
217 # * Major changes in release 5.0.1:
218 # * Noteworthy changes in release 6.6 (2006-11-22) [stable]
219 $line =~ /^$re_prefix.*(?:[^\d.]|$)\Q$curr_version\E(?:[^\d.]|$)/o
220 or next;
221 $in_items = 1;
222 print $line;
223 }
224 else
225 {
226 # This regexp must not match version numbers in NEWS items.
227 # For example, they might well say "introduced in 4.5.5",
228 # and we don't want that to match.
229 $line =~ /^$re_prefix.*(?:[^\d.]|$)\Q$prev_version\E(?:[^\d.]|$)/o
230 and last;
231 print $line;
232 $line =~ /\S/
233 and $found_news = 1;
234 }
235 }
236 close NEWS;
237
238 $in_items
239 or die "$ME: $news_file: no matching lines for '$curr_version'\n";
240 $found_news
241 or die "$ME: $news_file: no news item found for '$curr_version'\n";
242}
243
244sub print_changelog_deltas ($$)
245{
246 my ($package_name, $prev_version) = @_;
247
248 # Print new ChangeLog entries.
249
250 # First find all CVS-controlled ChangeLog files.
251 use File::Find;
252 my @changelog;
253 find ({wanted => sub {$_ eq 'ChangeLog' && -d 'CVS'
254 and push @changelog, $File::Find::name}},
255 '.');
256
257 # If there are no ChangeLog files, we're done.
258 @changelog
259 or return;
260 my %changelog = map {$_ => 1} @changelog;
261
262 # Reorder the list of files so that if there are ChangeLog
263 # files in the specified directories, they're listed first,
264 # in this order:
265 my @dir = qw ( . src lib m4 config doc );
266
267 # A typical @changelog array might look like this:
268 # ./ChangeLog
269 # ./po/ChangeLog
270 # ./m4/ChangeLog
271 # ./lib/ChangeLog
272 # ./doc/ChangeLog
273 # ./config/ChangeLog
274 my @reordered;
275 foreach my $d (@dir)
276 {
277 my $dot_slash = $d eq '.' ? $d : "./$d";
278 my $target = "$dot_slash/ChangeLog";
279 delete $changelog{$target}
280 and push @reordered, $target;
281 }
282
283 # Append any remaining ChangeLog files.
284 push @reordered, sort keys %changelog;
285
286 # Remove leading './'.
287 @reordered = map { s!^\./!!; $_ } @reordered;
288
289 print "\nChangeLog entries:\n\n";
290 # print join ("\n", @reordered), "\n";
291
292 $prev_version =~ s/\./_/g;
293 my $prev_cvs_tag = "\U$package_name\E-$prev_version";
294
295 my $cmd = "cvs -n diff -u -r$prev_cvs_tag -rHEAD @reordered";
296 open DIFF, '-|', $cmd
297 or die "$ME: cannot run '$cmd': $!\n";
298 # Print two types of lines, making minor changes:
299 # Lines starting with '+++ ', e.g.,
300 # +++ ChangeLog 22 Feb 2003 16:52:51 -0000 1.247
301 # and those starting with '+'.
302 # Don't print the others.
303 my $prev_printed_line_empty = 1;
304 while (defined (my $line = <DIFF>))
305 {
306 if ($line =~ /^\+\+\+ /)
307 {
308 my $separator = "*"x70 ."\n";
309 $line =~ s///;
310 $line =~ s/\s.*//;
311 $prev_printed_line_empty
312 or print "\n";
313 print $separator, $line, $separator;
314 }
315 elsif ($line =~ /^\+/)
316 {
317 $line =~ s///;
318 print $line;
319 $prev_printed_line_empty = ($line =~ /^$/);
320 }
321 }
322 close DIFF;
323
324 # The exit code should be 1.
325 # Allow in case there are no modified ChangeLog entries.
326 $? == 256 || $? == 128
327 or warn "warning: '$cmd' had unexpected exit code or signal ($?)\n";
328}
329
330sub get_tool_versions ($$)
331{
332 my ($tool_list, $gnulib_version) = @_;
333 @$tool_list
334 or return ();
335
336 my $fail;
337 my @tool_version_pair;
338 foreach my $t (@$tool_list)
339 {
340 if ($t eq 'gnulib')
341 {
342 push @tool_version_pair, ucfirst $t . ' ' . $gnulib_version;
343 next;
344 }
345 # Assume that the last "word" on the first line of
346 # 'tool --version' output is the version string.
347 my ($first_line, undef) = split ("\n", `$t --version`);
348 if ($first_line =~ /.* (\d[\w.-]+)$/)
349 {
350 $t = ucfirst $t;
351 push @tool_version_pair, "$t $1";
352 }
353 else
354 {
355 defined $first_line
356 and $first_line = '';
357 warn "$t: unexpected --version output\n:$first_line";
358 $fail = 1;
359 }
360 }
361
362 $fail
363 and exit 1;
364
365 return @tool_version_pair;
366}
367
368{
369 # Use the C locale so that, for instance, "du" does not
370 # print "1,2" instead of "1.2", which would confuse our regexps.
371 $ENV{LC_ALL} = "C";
372
373 my $mail_headers;
374 my $release_type;
375 my $package_name;
376 my $prev_version;
377 my $curr_version;
378 my $gpg_key_id;
379 my @url_dir_list;
380 my @news_file;
381 my $bootstrap_tools;
382 my $gnulib_version;
383 my $print_checksums_p = 1;
384 my $gpg_key_email;
385 my $gpg_keyring_url;
386
387 # Reformat the warnings before displaying them.
388 local $SIG{__WARN__} = sub
389 {
390 my ($msg) = @_;
391 # Warnings from GetOptions.
392 $msg =~ s/Option (\w)/option --$1/;
393 warn "$ME: $msg";
394 };
395
396 GetOptions
397 (
398 'mail-headers=s' => \$mail_headers,
399 'release-type=s' => \$release_type,
400 'package-name=s' => \$package_name,
401 'previous-version=s' => \$prev_version,
402 'current-version=s' => \$curr_version,
403 'gpg-key-id=s' => \$gpg_key_id,
404 'gpg-key-email=s' => \$gpg_key_email,
405 'gpg-keyring-url=s' => \$gpg_keyring_url,
406 'url-directory=s' => \@url_dir_list,
407 'news=s' => \@news_file,
408 'srcdir=s' => \$srcdir,
409 'bootstrap-tools=s' => \$bootstrap_tools,
410 'gnulib-version=s' => \$gnulib_version,
411 'print-checksums!' => \$print_checksums_p,
412 'archive-suffix=s' => \@archive_suffixes,
413
414 help => sub { usage 0 },
415 version =>
416 sub
417 {
418 print "$ME version $VERSION\n";
419 print "Copyright (C) $copyright_year Free Software Foundation, Inc.\n";
420 print "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n"
421 . "This is free software: you are free to change and redistribute it.\n"
422 . "There is NO WARRANTY, to the extent permitted by law.\n";
423 print "\n";
424 my $author = "Jim Meyering";
425 print "Written by $author.\n";
426 exit
427 },
428 ) or usage 1;
429
430 my $fail = 0;
431 # Ensure that each required option is specified.
432 $release_type
433 or (warn "release type not specified\n"), $fail = 1;
434 $package_name
435 or (warn "package name not specified\n"), $fail = 1;
436 $prev_version
437 or (warn "previous version string not specified\n"), $fail = 1;
438 $curr_version
439 or (warn "current version string not specified\n"), $fail = 1;
440 $gpg_key_id
441 or (warn "GnuPG key ID not specified\n"), $fail = 1;
442 @url_dir_list
443 or (warn "URL directory name(s) not specified\n"), $fail = 1;
444
445 my @tool_list = split ',', $bootstrap_tools
446 if $bootstrap_tools;
447
448 grep (/^gnulib$/, @tool_list) && ! defined $gnulib_version
449 and (warn "when specifying gnulib as a tool, you must also specify\n"
450 . "--gnulib-version=V, where V is the result of running git describe\n"
451 . "in the gnulib source directory.\n"), $fail = 1;
452
453 ! grep (/^gnulib$/, @tool_list) && defined $gnulib_version
454 and (warn "with --gnulib-version=V you must use --bootstrap-tools=...\n"
455 . "including gnulib in that list"), $fail = 1;
456
457 !$release_type || exists $valid_release_types{$release_type}
458 or (warn "'$release_type': invalid release type\n"), $fail = 1;
459
460 @ARGV
461 and (warn "too many arguments:\n", join ("\n", @ARGV), "\n"),
462 $fail = 1;
463 $fail
464 and usage 1;
465
466 my $my_distdir = "$package_name-$curr_version";
467
468 my $xd = "$package_name-$prev_version-$curr_version.xdelta";
469
470 my @candidates = map { "$my_distdir.$_" } @archive_suffixes;
471 my @tarballs = grep {-f $_} @candidates;
472
473 @tarballs
474 or die "$ME: none of " . join(', ', @candidates) . " were found\n";
475 my @sizable = @tarballs;
476 -f $xd
477 and push @sizable, $xd;
478 my %size = sizes (@sizable);
479 %size
480 or exit 1;
481
482 my $headers = '';
483 if (defined $mail_headers)
484 {
485 ($headers = $mail_headers) =~ s/\s+(\S+:)/\n$1/g;
486 $headers .= "\n";
487 }
488
489 # The markup is escaped as <\# so that when this script is sent by
490 # mail (or part of a diff), Gnus is not triggered.
491 print <<EOF;
492
493${headers}Subject: $my_distdir released [$release_type]
494
495<\#secure method=pgpmime mode=sign>
496
497FIXME: put comments here
498
499EOF
500
501 if (@url_dir_list == 1 && @tarballs == 1)
502 {
503 # When there's only one tarball and one URL, use a more concise form.
504 my $m = "$url_dir_list[0]/$tarballs[0]";
505 print "Here are the compressed sources and a GPG detached signature:\n"
506 . " $m\n"
507 . " $m.sig\n\n";
508 }
509 else
510 {
511 print_locations ("compressed sources", @url_dir_list, %size, @tarballs);
512 -f $xd
513 and print_locations ("xdelta diffs (useful? if so, "
514 . "please tell bug-gnulib\@gnu.org)",
515 @url_dir_list, %size, $xd);
516 my @sig_files = map { "$_.sig" } @tarballs;
517 print_locations ("GPG detached signatures", @url_dir_list, %size,
518 @sig_files);
519 }
520
521 if ($url_dir_list[0] =~ "gnu\.org")
522 {
523 print "Use a mirror for higher download bandwidth:\n";
524 if (@tarballs == 1 && $url_dir_list[0] =~ m!https://ftp\.gnu\.org/gnu/!)
525 {
526 (my $m = "$url_dir_list[0]/$tarballs[0]")
527 =~ s!https://ftp\.gnu\.org/gnu/!https://ftpmirror\.gnu\.org/!;
528 print " $m\n"
529 . " $m.sig\n\n";
530
531 }
532 else
533 {
534 print " https://www.gnu.org/order/ftp.html\n\n";
535 }
536 }
537
538 $print_checksums_p
539 and print_checksums (@sizable);
540
541 print <<EOF;
542Use a .sig file to verify that the corresponding file (without the
543.sig suffix) is intact. First, be sure to download both the .sig file
544and the corresponding tarball. Then, run a command like this:
545
546 gpg --verify $tarballs[0].sig
547
548EOF
549 my $gpg_fingerprint = `LC_ALL=C gpg --fingerprint $gpg_key_id | grep -v ^sub`;
550 if ($gpg_fingerprint =~ /^pub/)
551 {
552 chop $gpg_fingerprint;
553 $gpg_fingerprint =~ s/ \[expires:.*//mg;
554 $gpg_fingerprint =~ s/^uid \[ultimate\]/uid /mg;
555 $gpg_fingerprint =~ s/^/ /mg;
556 print<<EOF
557The signature should match the fingerprint of the following key:
558
559$gpg_fingerprint
560EOF
561 }
562 print <<EOF;
563If that command fails because you don't have the required public key,
564or that public key has expired, try the following commands to retrieve
565or refresh it, and then rerun the 'gpg --verify' command.
566EOF
567 if ($gpg_key_email) {
568 print <<EOF;
569
570 gpg --locate-external-key $gpg_key_email
571EOF
572 }
573 print <<EOF;
574
575 gpg --recv-keys $gpg_key_id
576EOF
577 if ($gpg_keyring_url) {
578 print <<EOF;
579
580 wget -q -O- '$gpg_keyring_url' | gpg --import -
581EOF
582 }
583 print <<EOF;
584
585As a last resort to find the key, you can try the official GNU
586keyring:
587
588 wget -q https://ftp.gnu.org/gnu/gnu-keyring.gpg
589 gpg --keyring gnu-keyring.gpg --verify $tarballs[0].sig
590
591EOF
592
593 my @tool_versions = get_tool_versions (\@tool_list, $gnulib_version);
594 @tool_versions
595 and print "\nThis release was bootstrapped with the following tools:",
596 join ('', map {"\n $_"} @tool_versions), "\n";
597
598 print_news_deltas ($_, $prev_version, $curr_version)
599 foreach @news_file;
600
601 $release_type eq 'stable'
602 or print_changelog_deltas ($package_name, $prev_version);
603
604 exit 0;
605}
606
607### Setup "GNU" style for perl-mode and cperl-mode.
608## Local Variables:
609## mode: perl
610## perl-indent-level: 2
611## perl-continued-statement-offset: 2
612## perl-continued-brace-offset: 0
613## perl-brace-offset: 0
614## perl-brace-imaginary-offset: 0
615## perl-label-offset: -2
616## perl-extra-newline-before-brace: t
617## perl-merge-trailing-else: nil
618## eval: (add-hook 'before-save-hook 'time-stamp)
619## time-stamp-line-limit: 50
620## time-stamp-start: "my $VERSION = '"
621## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
622## time-stamp-time-zone: "UTC0"
623## time-stamp-end: "'; # UTC"
624## End:
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette