summaryrefslogtreecommitdiffstats
path: root/private/generate-tag-summary
diff options
context:
space:
mode:
Diffstat (limited to 'private/generate-tag-summary')
-rwxr-xr-xprivate/generate-tag-summary151
1 files changed, 151 insertions, 0 deletions
diff --git a/private/generate-tag-summary b/private/generate-tag-summary
new file mode 100755
index 0000000..d8c59b5
--- /dev/null
+++ b/private/generate-tag-summary
@@ -0,0 +1,151 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2017, 2019 Chris Lamb <lamby@debian.org>
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Cwd qw(realpath);
+use File::Basename qw(dirname);
+use Unicode::UTF8 qw(decode_utf8 encode_utf8);
+
+# neither Path::This nor lib::relative are in Debian
+use constant THISFILE => realpath __FILE__;
+use constant THISDIR => dirname realpath __FILE__;
+
+# use Lintian modules that belong to this program
+use lib THISDIR . '/../lib';
+
+use Const::Fast;
+use Getopt::Long;
+use IPC::Run3;
+
+use Lintian::IPC::Run3 qw(safe_qx);
+
+const my $PLUS => q{+};
+const my $WAIT_STATUS_SHIFT => 8;
+
+my (%added, %removed, %opt);
+
+my %opthash = ('in-place|i' => \$opt{'in-place'},);
+
+# init commandline parser
+Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev',
+ 'permute');
+
+# process commandline options
+Getopt::Long::GetOptions(%opthash)
+ or die encode_utf8("error parsing options\n");
+
+my ($commit_range) = @ARGV;
+if (not $commit_range) {
+ my $bytes = safe_qx(qw(git describe --abbrev=0));
+ my $status = $? >> $WAIT_STATUS_SHIFT;
+
+ die encode_utf8("git describe failed with code $status\n")
+ if $status;
+
+ my $describe = $bytes;
+ chomp($describe);
+
+ if (not $describe) {
+ die encode_utf8("git describe did not return anything.\n");
+ }
+ $commit_range = "${describe}..HEAD";
+ print encode_utf8("Assuming commit range to be: ${commit_range}\n");
+}
+
+my $output;
+my @command =(qw{git diff}, $commit_range, qw{-- tags/*/*.tag});
+run3(\@command, \undef, \$output);
+
+my @lines = split(/\n/, $output);
+while (defined(my $line = shift @lines)) {
+
+ next
+ unless $line =~ m{ \A ([\+-]) Tag: \s*+ ([^ ]++) \s*+ \Z}xsm;
+
+ my ($change, $tag) = ($1, $2);
+ if ($change eq $PLUS) {
+ $added{$tag} = 1;
+ } else {
+ $removed{$tag} = 1;
+ }
+}
+
+for my $tag (keys(%added)) {
+ if (exists($removed{$tag})) {
+ # Added and removed? More likely, the tag was moved between
+ # two files.
+ delete($added{$tag});
+ delete($removed{$tag});
+ }
+}
+
+if (not %added and not %removed) {
+ print {*STDERR} encode_utf8("No tags were added or removed\n");
+}
+
+if ($opt{'in-place'}) {
+ my $matched = 0;
+
+ my $infile = 'debian/changelog';
+ open(my $in_fd, '<:encoding(UTF-8)', $infile)
+ or die encode_utf8("Cannot open $infile");
+
+ my $outfile = 'debian/changelog.tmp';
+ open(my $out_fd, '>', $outfile)
+ or die encode_utf8("Cannot open $outfile");
+
+ while (my $line = <$in_fd>) {
+ chomp $line;
+ if ($line =~ m/^ \* WIP\b/) {
+ emit_tag_summary($out_fd);
+ $matched++;
+ } else {
+ print {$out_fd} encode_utf8($line . "\n");
+ }
+ }
+ close($out_fd);
+ close($in_fd);
+ if ($matched != 1) {
+ die encode_utf8(
+ "changelog did not match WIP placeholder exactly once\n");
+ }
+
+ rename($outfile, $infile)
+ or die encode_utf8("Cannot rename $outfile to $infile");
+
+ print encode_utf8("Updated $infile\n");
+
+} else {
+ emit_tag_summary(\*STDOUT);
+}
+
+sub emit_tag_summary {
+ my ($fd) = @_;
+
+ if (%added or %removed) {
+ print {$fd} encode_utf8(" * Summary of tag changes:\n");
+ }
+ if (%added) {
+ print {$fd} encode_utf8(" + Added:\n");
+ for my $tag (sort(keys(%added))) {
+ print {$fd} encode_utf8(" - $tag\n");
+ }
+ }
+ if (%removed) {
+ print {$fd} encode_utf8(" + Removed:\n");
+ for my $tag (sort(keys(%removed))) {
+ print {$fd} encode_utf8(" - $tag\n");
+ }
+ }
+ return;
+}
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et