Skip Menu |

This queue is for tickets about the CPANPLUS CPAN distribution.

Report information
The Basics
Id: 53133
Status: resolved
Worked: 15 min
Priority: 0/
Queue: CPANPLUS

People
Owner: BINGOS [...] cpan.org
Requestors: mschwern [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in:
  • 0.90
  • 0.9001
Fixed in: (no value)



t/00_CPANPLUS-Internals-Utils.t t/00_CPANPLUS-Internals-Utils.t ............... 1/?
Show quoted text
#   Failed test '   Cwd() is 'foo''
#   at t/00_CPANPLUS-Internals-Utils.t line 39.
#                   '/var/local/cpan_shell/build/CPANPLUS-0.9001-w5B2Sn/t/foo'
#     doesn't match '(?i-xsm:\/private\/var\/local\/cpan_shell\/build\/CPANPLUS\-0\.9001\-w5B2Sn\/t\/foo)'
# Looks like you failed 1 test of 40.

That's this test:

    like( File::Spec->rel2abs(cwd()), qr/$abs_re/i,
                                        "   Cwd() is '$Dir'"); 

This failure occurs if the build directory is symlinked.  That's common on OS X where /etc /tmp and /var are actually symlinks.  File::Spec->rel2abs() and cwd() can return different values for a symlinked cwd because they use differing methods of determining the cwd.  The docs lie, File::Spec uses getcwd though older versions use cwd so you never can tell.

The result is that you can't just do a simple string compare.  That makes life difficult because the way to determine if they're the same is to compare inodes, but that's unreliable cross platform.  Best I can come up with is to walk the path and resolve any symlinks.  I did my best to make it cross platform, but I'd run it through thorough testing.
Subject: symlink_fix.diff
diff --git a/t/00_CPANPLUS-Internals-Utils.t b/t/00_CPANPLUS-Internals-Utils.t index 18011fd..8e372fe 100644 --- a/t/00_CPANPLUS-Internals-Utils.t +++ b/t/00_CPANPLUS-Internals-Utils.t @@ -18,6 +18,40 @@ use File::Basename; use CPANPLUS::Error; use CPANPLUS::Internals::Utils; +# File::Spec and Cwd might return different values for a +# symlinked directory, so we need to be careful. +sub paths_are_same { + my($have, $want, $name) = @_; + + $have = _resolve_symlinks($have); + $want = _resolve_symlinks($want); + + my $builder = Test::More->builder; + return $builder->like( $have, qr/\Q$want/i, $name ); +} + +# Resolve any symlinks in a path +sub _resolve_symlinks { + my $path = shift; + my($vol, $dirs, $file) = File::Spec->splitpath($path); + + my $resolved = File::Spec->catpath( $vol, "", "" ); + + for my $dir (File::Spec->splitdir($dirs)) { + # Resolve the next part of the path + my $next = File::Spec->catdir( $resolved, $dir ); + $next = eval { readlink $next } || $next; + + # If its absolute, use it. + # Otherwise tack it onto the end of the previous path. + $resolved = File::Spec->file_name_is_absolute($next) + ? $next + : File::Spec->catdir( $resolved, $next ); + } + + return File::Spec->catfile($resolved, $file); +} + my $Cwd = File::Spec->rel2abs(cwd()); my $Class = 'CPANPLUS::Internals::Utils'; my $Dir = 'foo'; @@ -35,13 +69,12 @@ rmdir $Dir if -d $Dir; ### test _chdir ### { ok( $Class->_chdir( dir => $Dir), "Chdir to '$Dir'" ); - my $abs_re = quotemeta File::Spec->rel2abs(File::Spec->catdir($Cwd,$Dir)); - like( File::Spec->rel2abs(cwd()), qr/$abs_re/i, + my $abs = File::Spec->rel2abs(File::Spec->catdir($Cwd,$Dir)); + paths_are_same( File::Spec->rel2abs(cwd()), $abs, " Cwd() is '$Dir'"); - my $cwd_re = quotemeta $Cwd; ok( $Class->_chdir( dir => $Cwd), "Chdir back to '$Cwd'" ); - like( File::Spec->rel2abs(cwd()), qr/$cwd_re/i, + paths_are_same( File::Spec->rel2abs(cwd()), $Cwd, " Cwd() is '$Cwd'" ); }
Thanks for this. I have applied it to the CPANPLUS svn repo and it has been backported into blead as well. Many thanks.