2 # Generate an announcement message.
9 (my $VERSION = '$Revision: 1.24 $ ') =~ tr/[0-9].//cd;
10 (my $ME = $0) =~ s|.*/||;
12 my %valid_release_types = map {$_ => 1} qw (alpha beta major);
16 # Nobody ever checks the status of print()s. That's okay, because
17 # if any do fail, we're guaranteed to get an indicator when we close()
20 # Close stdout now, and if there were no errors, return happy status.
21 # If stdout has already been closed by the script, though, do nothing.
27 # Errors closing stdout. Indicate that, and hope stderr is OK.
28 warn "$ME: closing standard output: $!\n";
30 # Don't be so arrogant as to assume that we're the first END handler
31 # defined, and thus the last one invoked. There may be others yet
32 # to come. $? will be passed on to them, and to the final _exit().
34 # If it isn't already an error, make it one (and if it _is_ an error,
35 # preserve the value: it might be important).
42 my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
45 print $STREAM "Try `$ME --help' for more information.\n";
49 my @types = sort keys %valid_release_types;
55 Generate an announcement message.
57 FIXME: describe the following
59 --release-type=TYPE TYPE must be one of @types
60 --package-name=PACKAGE_NAME
61 --previous-version=VER
63 --gpg-key-id=ID The GnuPG ID of the key used to sign the tarballs
64 --release-archive-directory=DIR
65 --url-directory=URL_DIR
66 --news=NEWS_FILE optional
68 --help display this help and exit
69 --version output version information and exit
77 =item C<%size> = C<sizes (@file)>
79 Compute the sizes of the C<@file> and return them as a hash. Return
80 C<undef> if one of the computation failed.
92 my $cmd = "du --human $f";
94 # FIXME-someday: give a better diagnostic, a la $PROCESS_STATUS
96 and (warn "$ME: command failed: `$cmd'\n"), $fail = 1;
98 $t =~ s/^([\d.]+[MkK]).*/${1}B/;
101 return $fail ? undef : %res;
104 =item C<print_locations ($title, \@url, \%size, @file)
106 Print a section C<$title> dedicated to the list of <@file>, which
107 sizes are stored in C<%size>, and which are available from the C<@url>.
111 sub print_locations ($\@\%@)
113 my ($title, $url, $size, @file) = @_;
114 print "Here are the $title:\n";
115 foreach my $url (@{$url})
120 print " (", $$size{$file}, ")"
121 if exists $$size{$file};
128 =item C<print_checksums (@file)
130 Print the MD5 and SHA1 signature section for each C<@file>.
134 sub print_checksums (@)
138 print "Here are the MD5 and SHA1 checksums:\n";
141 foreach my $meth (qw (md5 sha1))
143 foreach my $f (@file)
146 or die "$ME: $f: cannot open for reading: $!\n";
150 ? Digest::MD5->new->addfile(*IN)->hexdigest
151 : Digest::SHA1->new->addfile(*IN)->hexdigest);
160 =item C<print_news_deltas ($news_file, $prev_version, $curr_version)
162 Print the section of the NEWS file C<$news_file> addressing changes
163 between versions C<$prev_version> and C<$curr_version>.
167 sub print_news_deltas ($$$)
169 my ($news_file, $prev_version, $curr_version) = @_;
171 print "\n$news_file\n\n";
173 # Print all lines from $news_file, starting with the first one
174 # that mentions $curr_version up to but not including
175 # the first occurrence of $prev_version.
178 open NEWS, '<', $news_file
179 or die "$ME: $news_file: cannot open for reading: $!\n";
180 while (defined (my $line = <NEWS>))
184 # Match lines like this one:
185 # * Major changes in release 5.0.1:
186 # but not any other line that starts with a space, *, or -.
187 $line =~ /^(\* Major changes.*|[^ *-].*)\Q$curr_version\E/o
194 # Be careful that this regexp cannot match version numbers
195 # in NEWS items -- they might well say `introduced in 4.5.5',
196 # and we don't want that to match.
197 $line =~ /^(\* Major changes.*|[^ *-].*)\Q$prev_version\E/o
205 or die "$ME: $news_file: no matching lines for `$curr_version'\n";
208 sub print_changelog_deltas ($$)
210 my ($package_name, $prev_version) = @_;
212 # Print new ChangeLog entries.
214 # First find all CVS-controlled ChangeLog files.
217 find ({wanted => sub {$_ eq 'ChangeLog' && -d 'CVS'
218 and push @changelog, $File::Find::name}},
221 # If there are no ChangeLog files, we're done.
224 my %changelog = map {$_ => 1} @changelog;
226 # Reorder the list of files so that if there are ChangeLog
227 # files in the specified directories, they're listed first,
229 my @dir = qw ( . src lib m4 config doc );
231 # A typical @changelog array might look like this:
241 my $dot_slash = $d eq '.' ? $d : "./$d";
242 my $target = "$dot_slash/ChangeLog";
243 delete $changelog{$target}
244 and push @reordered, $target;
247 # Append any remaining ChangeLog files.
248 push @reordered, sort keys %changelog;
250 # Remove leading `./'.
251 @reordered = map { s!^\./!!; $_ } @reordered;
253 print "\nChangeLog entries:\n\n";
254 # print join ("\n", @reordered), "\n";
256 $prev_version =~ s/\./_/g;
257 my $prev_cvs_tag = "\U$package_name\E-$prev_version";
259 my $cmd = "cvs -n diff -u -r$prev_cvs_tag -rHEAD @reordered";
260 open DIFF, '-|', $cmd
261 or die "$ME: cannot run `$cmd': $!\n";
262 # Print two types of lines, making minor changes:
263 # Lines starting with `+++ ', e.g.,
264 # +++ ChangeLog 22 Feb 2003 16:52:51 -0000 1.247
265 # and those starting with `+'.
266 # Don't print the others.
267 my $prev_printed_line_empty = 1;
268 while (defined (my $line = <DIFF>))
270 if ($line =~ /^\+\+\+ /)
272 my $separator = "*"x70 ."\n";
275 $prev_printed_line_empty
277 print $separator, $line, $separator;
279 elsif ($line =~ /^\+/)
283 $prev_printed_line_empty = ($line =~ /^$/);
288 # The exit code should be 1.
289 # Allow in case there are no modified ChangeLog entries.
290 $? == 256 || $? == 128
291 or warn "$ME: warning: `cmd' had unexpected exit code or signal ($?)\n";
295 # Neutralize the locale, so that, for instance, "du" does not
296 # issue "1,2" instead of "1.2", what confuses our regexps.
303 my $release_archive_dir;
310 'release-type=s' => \$release_type,
311 'package-name=s' => \$package_name,
312 'previous-version=s' => \$prev_version,
313 'current-version=s' => \$curr_version,
314 'gpg-key-id=s' => \$gpg_key_id,
315 'release-archive-directory=s' => \$release_archive_dir,
316 'url-directory=s' => \@url_dir_list,
317 'news=s' => \@news_file,
319 help => sub { usage 0 },
320 version => sub { print "$ME version $VERSION\n"; exit },
324 # Ensure that sure each required option is specified.
326 or (warn "$ME: release type not specified\n"), $fail = 1;
328 or (warn "$ME: package name not specified\n"), $fail = 1;
330 or (warn "$ME: previous version string not specified\n"), $fail = 1;
332 or (warn "$ME: current version string not specified\n"), $fail = 1;
334 or (warn "$ME: release directory name not specified\n"), $fail = 1;
336 or (warn "$ME: URL directory name(s) not specified\n"), $fail = 1;
338 exists $valid_release_types{$release_type}
339 or (warn "$ME: `$release_type': invalid release type\n"), $fail = 1;
342 and (warn "$ME: too many arguments\n"), $fail = 1;
346 my $my_distdir = "$package_name-$curr_version";
347 my $tgz = "$my_distdir.tar.gz";
348 my $tbz = "$my_distdir.tar.bz2";
349 my $xd = "$package_name-$prev_version-$curr_version.xdelta";
351 my %size = sizes ($tgz, $tbz, $xd);
355 # The markup is escaped as <\# so that when this script is sent by
356 # mail (or part of a diff), Gnus is not triggered.
359 Subject: $my_distdir released
361 <\#secure method=pgpmime mode=sign>
363 FIXME: put comments here
367 print_locations ("compressed sources", @url_dir_list, %size,
369 print_locations ("xdelta-style diffs", @url_dir_list, %size,
371 print_locations ("GPG detached signatures[*]", @url_dir_list, %size,
372 "$tgz.sig", "$tbz.sig");
374 print_checksums ($tgz, $tbz, $xd);
378 [*] You can use either of the above signature files to verify that
379 the corresponding file (without the .sig suffix) is intact. First,
380 be sure to download both the .sig file and the corresponding tarball.
381 Then, run a command like this:
383 gpg --verify $tgz.sig
385 If that command fails because you don't have the required public key,
386 then run this command to import it:
388 gpg --keyserver wwwkeys.pgp.net --recv-keys $gpg_key_id
390 and rerun the \`gpg --verify' command.
393 print_news_deltas ($_, $prev_version, $curr_version)
396 $release_type eq 'major'
397 or print_changelog_deltas ($package_name, $prev_version);
404 ### Setup "GNU" style for perl-mode and cperl-mode.
406 ## perl-indent-level: 2
407 ## perl-continued-statement-offset: 2
408 ## perl-continued-brace-offset: 0
409 ## perl-brace-offset: 0
410 ## perl-brace-imaginary-offset: 0
411 ## perl-label-offset: -2
412 ## cperl-indent-level: 2
413 ## cperl-brace-offset: 0
414 ## cperl-continued-brace-offset: 0
415 ## cperl-label-offset: -2
416 ## cperl-extra-newline-before-brace: t
417 ## cperl-merge-trailing-else: nil
418 ## cperl-continued-statement-offset: 2