Skip Menu |

This queue is for tickets about the App-cpanoutdated CPAN distribution.

Report information
The Basics
Id: 72880
Status: open
Priority: 0/
Queue: App-cpanoutdated

People
Owner: Nobody in particular
Requestors: rr [...] yopmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: bad results from case-insensitive comparision
for some reason i'm now being told that i should update distributions modules which aren't even installed on my system. i think this is a result of a case-insensitive comparison somewhere. my filesystem is case-insensitive (HFS), but this wasn't an issue in the past, so not sure where the problem lies. $ perl -E 'say $^V' v5.14.2 $ cpan-outdated --verbose Attributes 0.14 2.60 P/PE/PERRAD/CORBA-IDL-2.60.tar.gz DB 1.03 19970614 D/DM/DMR/DProf-19970614.tar.gz INTEGER 1.00 1.93 S/SH/SHERZODR/Class-PObject-2.17.tar.gz
On Thu Dec 01 23:59:27 2011, http://rickroller.myopenid.com/ wrote: Show quoted text
> for some reason i'm now being told that i should update distributions > modules which aren't even installed on my system. i think this is a > result of a case-insensitive comparison somewhere. my filesystem is > case-insensitive (HFS), but this wasn't an issue in the past, so not > sure where the problem lies.
it looks like cpan-outdated is just testing for the file existence using -f. one solution would instead be to test the package name against the list of filenames returned from readdir for the directory. another would be to find all installed package files using File::Find and suck them into a hash, then test each package against the hash. the first solution would require the least amount of changes to your existing code. the second solution would probably speed up the entire program.
Subject: Re: [rt.cpan.org #72880] bad results from case-insensitive comparision
Date: Mon, 5 Dec 2011 15:31:06 +0900
To: bug-App-cpanoutdated [...] rt.cpan.org
From: Tokuhiro Matsuno <tokuhirom [...] gmail.com>
hmm... patches welcome. On Sun, Dec 4, 2011 at 7:02 PM, http://rickroller.myopenid.com/ via RT <bug-App-cpanoutdated@rt.cpan.org> wrote: Show quoted text
>       Queue: App-cpanoutdated >  Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=72880 > > > On Thu Dec 01 23:59:27 2011, http://rickroller.myopenid.com/ wrote:
>> for some reason i'm now being told that i should update distributions >> modules which aren't even installed on my system. i think this is a >> result of a case-insensitive comparison somewhere. my filesystem is >> case-insensitive (HFS), but this wasn't an issue in the past, so not >> sure where the problem lies.
> > it looks like cpan-outdated is just testing for the file existence using > -f. one solution would instead be to test the package name against the > list of filenames returned from readdir for the directory. > > another would be to find all installed package files using File::Find > and suck them into a hash, then test each package against the hash. > > the first solution would require the least amount of changes to your > existing code. the second solution would probably speed up the entire > program.
On Mon Dec 05 01:31:17 2011, tokuhirom@gmail.com wrote: Show quoted text
> hmm... patches welcome.
since you didn't weigh in on which approach you preferred, i've attached the easiest one. DB from DProf is still a different issue that might not to be special-cased.
Subject: case.patch
diff --git a/bin/cpan-outdated b/bin/cpan-outdated index f9954af..4abb8d8 100644 --- a/bin/cpan-outdated +++ b/bin/cpan-outdated @@ -70,6 +70,14 @@ sub main { my $path = "$dir/$file"; next SCAN_INC unless -f $path; + # Testing file existence isn't enough for for case-insensitive + # file systems. + my ($vol, $pkg_dir, $pkg_file) = File::Spec->splitpath($path); + opendir my $dh, $pkg_dir or die "$pkg_dir: $!"; + my $found = grep { $_ eq $pkg_file } readdir $dh; + closedir $dh; + next unless $found; + # ignore old distribution. # This is a heuristic approach. It is not a strict. # If you want a strict check, cpan-outdated looks 02packages.details.txt.gz twice.
On Mon Dec 05 01:31:17 2011, tokuhirom@gmail.com wrote: Show quoted text
> hmm... patches welcome.
here's the other approach. it's 20% faster for me, but the larger the @INC, the larger the savings.
Subject: suck.patch
diff --git a/bin/cpan-outdated b/bin/cpan-outdated index f9954af..a198a87 100644 --- a/bin/cpan-outdated +++ b/bin/cpan-outdated @@ -4,6 +4,7 @@ use warnings; use Getopt::Long; use Pod::Usage; use ExtUtils::MakeMaker; +use File::Find; use File::Temp; use File::Spec; use Config; @@ -57,6 +58,24 @@ sub main { while (my $line = <$fh>) { last if $line eq "\n"; } + + # Find the list of installed modules. + my %paths; + for my $dir (@libpath) { + next if $dir eq '.'; + my $len = length $dir; + find { + wanted => sub { + return unless substr $_, -3, 3, '' eq '.pm'; + return unless -f _; + substr $_, 0, 1 + $len, ''; + s{[\\/]}{::}g; + push @{ $paths{$_} }, $File::Find::name; + }, + no_chdir => 1 + }, $dir; + } + # body part my %seen; my %dist_latest_version; @@ -64,12 +83,10 @@ sub main { my ($pkg, $version, $dist) = split /\s+/, $line; next if $version eq 'undef'; next if $dist =~ m{/perl-[0-9._]+\.tar\.(gz|bz2)$}; - (my $file = $pkg) =~ s!::!/!g; - $file = "${file}.pm"; - SCAN_INC: for my $dir (@libpath) { - my $path = "$dir/$file"; - next SCAN_INC unless -f $path; + next unless exists $paths{$pkg}; + my @paths = @{ $paths{$pkg} }; + SCAN_INC: for my $path (@paths) { # ignore old distribution. # This is a heuristic approach. It is not a strict. # If you want a strict check, cpan-outdated looks 02packages.details.txt.gz twice. @@ -80,6 +97,7 @@ sub main { # This strategy works well for now. # ref https://github.com/tokuhirom/cpan-outdated/issues#issue/4 my $info = CPAN::DistnameInfo->new($dist); + next unless $info; if (my $latest = $dist_latest_version{$info->dist}) { # $info->version < $latest if (compare_version($info->version, $latest)) { @@ -90,7 +108,7 @@ sub main { $dist_latest_version{$info->dist} = $info->version; my $inst_version = parse_version($path); - $inst_version =~ s/\s+//; # workaround for Attribute::Params::Validate + $inst_version =~ s/\s+//; # workaround for Attribute::Params::Validate next if $inst_version eq 'undef'; if (compare_version($inst_version, $version)) { next if $seen{$dist}++;