#!perl
use
5.9.0;
use
Maintainers
qw(get_module_files reload_manifest %Modules)
;
our
$packagefile
=
'02packages.details.txt'
;
sub
usage () {
die
<<USAGE;
$0
$0 -t home1[:label] home2[:label] ...
Report which core modules are outdated.
To be run at the root of a perl source tree.
Options :
-h : help
-v : verbose (print all versions of all files, not only those which differ)
-f : force download of $packagefile from CPAN
(it's expected to be found in the current directory)
-t : display in tabular form CPAN vs one or more perl source trees
USAGE
}
sub
get_package_details () {
unlink
$packagefile
;
system
(
"wget $url && gunzip $packagefile.gz"
) == 0
or
die
"Failed to get package details\n"
;
}
getopts(
'fhvt'
);
our
$opt_h
and usage;
our
$opt_t
;
my
@sources
=
@ARGV
?
@ARGV
:
'.'
;
die
"Too many directories specified without -t option\n"
if
@sources
!= 1 and !
$opt_t
;
@sources
=
map
{
my
(
$dir
,
$label
) =
split
/:/;
$label
=
$dir
unless
defined
$label
;
[
$dir
,
$label
];
}
@sources
;
our
$opt_f
|| !-f
$packagefile
and get_package_details;
my
%cpanversions
;
open
my
$fh
,
'<'
,
$packagefile
or
die
$!;
while
(<
$fh
>) {
my
(
$p
,
$v
) =
split
' '
;
next
if
1../^\s*$/;
$cpanversions
{
$p
} =
$v
;
}
close
$fh
;
my
%results
;
foreach
my
$source
(
@sources
) {
my
(
$srcdir
,
$label
) =
@$source
;
my
$olddir
= getcwd();
chdir
$srcdir
or
die
"chdir $srcdir: $!\n"
;
reload_manifest;
for
my
$dist
(
sort
keys
%Modules
) {
next
unless
$Modules
{
$dist
}{CPAN};
for
my
$file
(get_module_files(
$dist
)) {
next
if
$file
!~ /(\.pm|_pm.PL)\z/
or
$file
=~ m{^t/} or
$file
=~ m{/t/};
my
$vcore
=
'!EXIST'
;
$vcore
= MM->parse_version(
$file
) //
'undef'
if
-f
$file
;
my
$module
=
$file
;
$module
=~ s/\_pm.PL\z//;
$module
=~ s/\.pm\z//;
$module
=~ s{^(lib|ext|dist|cpan)/}{}
and $1 =~ /(?:ext|dist|cpan)/
and (
$module
=~ s{^(\w+)-(\w+)/\2$}{$1/lib/$1/$2},
$module
=~ s{^(Encode)/(\w+)/\2$}{$1/lib/$1/$2},
$module
=~ s{^[^/]+/}{},
$module
=~ s{^lib/}{},
);
$module
=~ s{/}{::}g;
my
$vcpan
=
$cpanversions
{
$module
} //
'undef'
;
$results
{
$dist
}{
$file
}{
$label
} =
$vcore
;
$results
{
$dist
}{
$file
}{CPAN} =
$vcpan
;
}
}
chdir
$olddir
or
die
"chdir $olddir: $!\n"
;
}
my
@labels
= ((
map
$_
->[1],
@sources
),
'CPAN'
);
if
(
$opt_t
) {
my
%changed
;
my
@fields
;
for
my
$dist
(
sort
{
lc
$a
cmp
lc
$b
}
keys
%results
) {
for
my
$file
(
sort
keys
%{
$results
{
$dist
}}) {
my
@versions
= @{
$results
{
$dist
}{
$file
}}{
@labels
};
for
(0..
$#versions
) {
$fields
[
$_
] = max(
$fields
[
$_
],
length
$versions
[
$_
],
length
$labels
[
$_
],
length
'!EXIST'
);
}
if
(
our
$opt_v
or
grep
$_
ne
$versions
[0],
@versions
) {
$changed
{
$dist
} = 1;
}
}
}
printf
"%*s "
,
$fields
[
$_
],
$labels
[
$_
]
for
0..
$#labels
;
print
"\n"
;
printf
"%*s "
,
$fields
[
$_
],
'-'
x
length
$labels
[
$_
]
for
0..
$#labels
;
print
"\n"
;
my
$field_total
;
$field_total
+=
$_
+ 1
for
@fields
;
for
my
$dist
(
sort
{
lc
$a
cmp
lc
$b
}
keys
%results
) {
next
unless
$changed
{
$dist
};
print
" "
x
$field_total
,
" $dist\n"
;
for
my
$file
(
sort
keys
%{
$results
{
$dist
}}) {
my
@versions
= @{
$results
{
$dist
}{
$file
}}{
@labels
};
for
(0..
$#versions
) {
printf
"%*s "
,
$fields
[
$_
],
$versions
[
$_
]//
'!EXIST'
}
print
" $file\n"
;
}
}
}
else
{
for
my
$dist
(
sort
{
lc
$a
cmp
lc
$b
}
keys
%results
) {
my
$distname_printed
= 0;
for
my
$file
(
sort
keys
%{
$results
{
$dist
}}) {
my
(
$vcore
,
$vcpan
) = @{
$results
{
$dist
}{
$file
}}{
@labels
};
if
(
our
$opt_v
or
$vcore
ne
$vcpan
) {
print
"\n$dist ($Modules{$dist}{MAINTAINER}):\n"
unless
(
$distname_printed
++);
print
"\t$file: core=$vcore, cpan=$vcpan\n"
;
}
}
}
}