#!/usr/bin/perl # Copyright (C) 2017, 2019 Chris Lamb 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