# -*- perl -*- Lintian::Processable::Changelog -- access to collected changelog data
#
# Copyright © 1998 Richard Braakman
# Copyright © 2019-2020 Felix Lechner
#
# 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 2 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 .
package Lintian::Processable::Changelog;
use v5.20;
use warnings;
use utf8;
use File::Copy qw(copy);
use List::SomeUtils qw(first_value);
use Path::Tiny;
use Unicode::UTF8 qw(valid_utf8 decode_utf8 encode_utf8);
use Lintian::IPC::Run3 qw(safe_qx);
use Moo::Role;
use namespace::clean;
=head1 NAME
Lintian::Processable::Changelog - access to collected changelog data
=head1 SYNOPSIS
use Lintian::Processable;
=head1 DESCRIPTION
Lintian::Processable::Changelog provides an interface to changelog data.
=head1 INSTANCE METHODS
=over 4
=item changelog_path
=cut
has changelog_path => (
is => 'rw',
lazy => 1,
default => sub {
my ($self) = @_;
if ($self->type eq 'source') {
my $file = $self->patched->resolve_path('debian/changelog');
return
unless $file && $file->is_open_ok;
return $file->unpacked_path;
}
# pick the first existing file
my @changelogfiles = (
'changelog.Debian.gz','changelog.Debian',
'changelog.debian.gz','changelog.debian',
'changelog.gz','changelog',
);
my $packagepath = 'usr/share/doc/' . $self->name;
my @candidatepaths = grep { defined }
map { $self->installed->lookup("$packagepath/$_") } @changelogfiles;
my $packagechangelogpath
= first_value { $_->is_file || length $_->link } @candidatepaths;
return
unless defined $packagechangelogpath;
# stop for dangling symbolic link
my $resolved = $packagechangelogpath->resolve_path;
return
unless defined $resolved;
my $changelogpath;
if ($packagechangelogpath->basename =~ /\.gz$/) {
my $contents
= decode_utf8(safe_qx('gunzip', '-c', $resolved->unpacked_path));
$changelogpath
= path($self->basedir)->child('changelog')->stringify;
path($changelogpath)->spew_utf8($contents);
} else {
$changelogpath = $resolved->unpacked_path;
}
if ($packagechangelogpath->basename !~ m/changelog\.debian/i) {
# Either this is a native package OR a non-native package where the
# debian changelog is missing. checks/changelog is not too happy
# with the latter case, so check looks like a Debian changelog.
my @lines = path($changelogpath)->lines;
my $ok = 0;
for my $line (@lines) {
next if $line =~ /^\s*+$/;
# look for something like
# lintian (2.5.3) UNRELEASED; urgency=low
if ($line
=~ /^\S+\s*\([^\)]+\)\s*(?:UNRELEASED|(?:[^ \t;]+\s*)+)\;/)
{
$ok = 1;
}
last;
}
# Remove it if it not the Debian changelog.
unless ($ok) {
unlink $changelogpath
or die encode_utf8("Cannot unlink $changelogpath");
undef $changelogpath;
}
}
return
unless defined $changelogpath;
return $changelogpath;
});
=item changelog
For binary:
Returns the changelog of the binary package as a Parse::DebianChangelog
object, or an empty object if the changelog doesn't exist. The changelog-file
collection script must have been run to create the changelog file, which
this method expects to find in F.
For source:
Returns the changelog of the source package as a Parse::DebianChangelog
object, or an empty object if the changelog cannot be resolved safely.
=cut
has changelog => (
is => 'rw',
lazy => 1,
default => sub {
my ($self) = @_;
my $changelog = Lintian::Inspect::Changelog->new;
my $dch = $self->changelog_path;
return $changelog
unless $dch;
my $bytes = path($dch)->slurp;
return $changelog
unless valid_utf8($bytes);
$changelog->parse(decode_utf8($bytes));
return $changelog;
});
1;
=back
=head1 AUTHOR
Originally written by Felix Lechner for
Lintian.
=head1 SEE ALSO
lintian(1)
=cut
# Local Variables:
# indent-tabs-mode: nil
# cperl-indent-level: 4
# End:
# vim: syntax=perl sw=4 sts=4 sr et