mirror of https://gitee.com/openkylin/lintian.git
223 lines
6.3 KiB
Perl
Executable File
223 lines
6.3 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
use v5.20;
|
|
use warnings;
|
|
use utf8;
|
|
|
|
# Generate a list of packages that are provided by the Perl core packages
|
|
# and also packaged separately at a (hopefully) newer version.
|
|
# The list will have the package name and the upstream version of the
|
|
# corresponding module integrated in the currently installed Perl version.
|
|
|
|
# Copyright (C) 2008 Niko Tyni
|
|
#
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
|
|
use Const::Fast;
|
|
use List::SomeUtils qw(none);
|
|
use Unicode::UTF8 qw(encode_utf8);
|
|
|
|
# from /usr/share/doc/libapt-pkg-perl/examples/apt-cache
|
|
use AptPkg::Config '$_config';
|
|
use AptPkg::System '$_system';
|
|
use AptPkg::Cache;
|
|
|
|
const my $EMPTY => q{};
|
|
const my $LAST_ITEM => -1;
|
|
|
|
(my $self = $0) =~ s{.*/}{};
|
|
|
|
# initialise the global config object with the default values and
|
|
# setup the $_system object
|
|
$_config->init;
|
|
$_system = $_config->system;
|
|
|
|
# suppress cache building messages
|
|
$_config->{quiet} = 2;
|
|
|
|
# set up the cache
|
|
my $cache = AptPkg::Cache->new;
|
|
# end from /usr/share/doc/libapt-pkg-perl/examples/apt-cache
|
|
|
|
# special cases when libfoo-bar-perl => Foo::Bar doesn't work
|
|
my %module_name = (
|
|
'libio-compress-perl' => 'IO::Compress::Gzip',
|
|
'libio-compress-zlib-perl' => 'IO::Compress::Gzip',
|
|
);
|
|
|
|
# special cases for where the code gets the prefix wrong
|
|
my %manual_split
|
|
= ('libautodie-perl' => qr/\A (\d++\.) (\d{2}) (\d{2})? \Z/xsmo,);
|
|
|
|
use Module::CoreList;
|
|
my $versioning = $_system->versioning;
|
|
|
|
my $perl_version = $];
|
|
|
|
# Map 5.022002 into 5.22
|
|
$perl_version =~ s/^(5)\.0*([1-9][0-9])\d+/$1.$2/;
|
|
|
|
# we look at packages provided by these
|
|
my @core_packages = (qw(perl-base perl), "perl-modules-$perl_version");
|
|
|
|
# check we have a cache of Debian sid packages available
|
|
warn encode_utf8(
|
|
join(q{ },
|
|
'Warning: this list should only be updated on a system',
|
|
'with an up to date APT cache of the Debian unstable distribution')
|
|
)
|
|
if (
|
|
none {
|
|
defined $_->{Origin}
|
|
&& defined $_->{Archive}
|
|
&& $_->{Origin} eq 'Debian'
|
|
&& $_->{Archive} eq 'unstable';
|
|
}@{$cache->files}
|
|
);
|
|
|
|
print encode_utf8(<<"EOF");
|
|
# virtual packages provided by the Perl core packages that also have a
|
|
# separate binary package available
|
|
#
|
|
# the listed version is the one included in the Perl core
|
|
#
|
|
# regenerate by running
|
|
# debian/rules refresh-perl-provides
|
|
# in the lintian source tree
|
|
#
|
|
# last updated for PERL_VERSION=$]
|
|
EOF
|
|
|
|
for my $pkg (@core_packages) {
|
|
my $cached_versions = $cache->{$pkg}
|
|
or
|
|
die encode_utf8("no such binary package found in the APT cache: $pkg");
|
|
my $latest = bin_latest($cached_versions);
|
|
|
|
for my $provides (@{$latest->{ProvidesList}}) {
|
|
my $name = $provides->{Name};
|
|
# skip virtual-only packages
|
|
next if (!$cache->{$name}{VersionList});
|
|
my $cpan_version = find_core_version($name);
|
|
|
|
next if !$cpan_version;
|
|
|
|
# the number of digits is a pain
|
|
# we use the current version in the Debian archive to determine
|
|
# how many we need
|
|
# the epoch is easier, we just copy it
|
|
|
|
my ($epoch, $digits) = epoch_and_digits($name);
|
|
my $debian_version
|
|
= cpan_version_to_deb($name, $cpan_version, $epoch, $digits);
|
|
|
|
next if !$debian_version;
|
|
|
|
print encode_utf8("$name $debian_version\n");
|
|
}
|
|
}
|
|
|
|
# look up the CPAN version of a package in the core
|
|
sub find_core_version {
|
|
my $module = shift;
|
|
my $ret;
|
|
|
|
return undef
|
|
if $module =~ /^perl(5|api)/;
|
|
|
|
if (exists $module_name{$module}) {
|
|
$module = $module_name{$module};
|
|
} else {
|
|
# mangle the package name into the module name
|
|
$module =~ s/^lib//;
|
|
$module =~ s/-perl$//;
|
|
$module =~ s/-/::/g;
|
|
}
|
|
|
|
for (Module::CoreList->find_modules(qr/^\Q$module\E$/i, 0+$])) {
|
|
$ret = $Module::CoreList::version{0+$]}{$_};
|
|
last;
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
sub cpan_version_to_deb {
|
|
my ($pkg, $cpan_version, $epoch, $digits) = @_;
|
|
$epoch ||= $EMPTY;
|
|
|
|
# cpan_version
|
|
# digits
|
|
# result
|
|
# 1.15_02, 2 => 1.15.02
|
|
# 1.15_02, 4 => 1.1502
|
|
# 1.15_02, 0 => 1.15.02
|
|
#
|
|
# 1.15_021, 2 => 1.15.021
|
|
# 1.15_021, 4 => 1.1500.021
|
|
# 1.15_021, 0 => 1.15.021
|
|
#
|
|
# 1.15, 1 => 1.15
|
|
# 1.15, 2 => 1.15
|
|
# 1.15, 4 => 1.1500
|
|
# 1.15, 0 => 1.15
|
|
|
|
# split 1.15_02 to (1, 15, 02)
|
|
my $regex = qr/^(\d+\.)(\d+)(?:_(\d+))?$/;
|
|
$regex = $manual_split{$pkg} if exists $manual_split{$pkg};
|
|
my ($major, $prefix, $suffix) = ($cpan_version =~ $regex);
|
|
die encode_utf8("no match with $cpan_version?") if !$major;
|
|
|
|
$suffix ||= $EMPTY;
|
|
if (length($suffix) + length($prefix) == $digits) {
|
|
$prefix .= $suffix;
|
|
$suffix = $EMPTY;
|
|
}
|
|
if (length($suffix) + length($prefix) < $digits) {
|
|
$prefix .= '0' while length($prefix) < $digits;
|
|
}
|
|
$suffix = ".$suffix" if $suffix ne $EMPTY;
|
|
return $epoch.$major.$prefix.$suffix;
|
|
}
|
|
|
|
# Given a Debian binary package name, look up its latest version
|
|
# and return its epoch (including the colon) if available, and
|
|
# the number of digits in its decimal part
|
|
sub epoch_and_digits {
|
|
my $p = shift;
|
|
return (0, 0) if !exists $cache->{$p};
|
|
return (0, 0) if !exists $cache->{$p}{VersionList}; # virtual package
|
|
my $latest = bin_latest($cache->{$p});
|
|
my $v = $latest->{VerStr};
|
|
$v =~ s/\+dfsg//;
|
|
my ($epoch, $major, $prefix, $suffix, $revision)
|
|
= ($v =~ /^(?:(\d+:))?((?:\d+\.))+(\d+)(?:_(\d+))?(-[^-]+)$/);
|
|
return ($epoch, length $prefix);
|
|
}
|
|
|
|
sub bin_latest {
|
|
my $p = shift;
|
|
return (sort bin_byversion @{$p->{VersionList}})[$LAST_ITEM];
|
|
}
|
|
|
|
sub bin_byversion {
|
|
return $versioning->compare($a->{VerStr}, $b->{VerStr});
|
|
}
|
|
|
|
# Local Variables:
|
|
# indent-tabs-mode: nil
|
|
# cperl-indent-level: 4
|
|
# End:
|
|
# vim: syntax=perl sw=4 sts=4 sr et
|