Skip Menu |

This queue is for tickets about the PathTools CPAN distribution.

Report information
The Basics
Id: 13606
Status: new
Priority: 0/
Queue: PathTools

People
Owner: Nobody in particular
Requestors:
Cc:
AdminCc:

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



Subject: Win32->canonpath("\\..\\..\\"). canonpath("/../..")
The following patch fixes File::Spec::Win32->canonpath("\\..\\..\\") to be \. It is currently the empty string. This also fixes File::Spec::Win32->catdir("", "..", "..", "") which is the way catdir represents "\\..\\..\\". Basically, I made Win32->canonpath() use the same /../../xx -> /xx technique as the Unix code. This also fixes Unix->canonpath("/../..") which returned /.. It now returns /. Win32->canonpath("\\..\\..") similarly fixed. While I was at it, I fixed one of the Unix->canonpath comments (/../../xx -> /xx not xx). And more visiually described what the ... transforms are doing in Win32.
--- PathTools-3.09/lib/File/Spec/Unix.pm 2005-06-15 16:43:54.000000000 -0700 +++ PathTools-3.09.new/lib/File/Spec/Unix.pm 2005-07-08 16:04:31.000000000 -0700 @@ -59,8 +59,8 @@ $path =~ s|/+|/|g; # xx////xx -> xx/xx $path =~ s@(/\.)+(/|\Z(?!\n))@/@g; # xx/././xx -> xx/xx $path =~ s|^(\./)+||s unless $path eq "./"; # ./xx -> xx - $path =~ s|^/(\.\./)+|/|s; # /../../xx -> xx - $path =~ s|/\Z(?!\n)|| unless $path eq "/"; # xx/ -> xx + $path =~ s|^/(\.\./?)+|/|s; # /../../xx -> /xx + $path =~ s|/\Z(?!\n)|| unless $path eq "/"; # xx/ -> xx return "$node$path"; } --- PathTools-3.09/lib/File/Spec/Win32.pm 2005-06-15 16:43:54.000000000 -0700 +++ PathTools-3.09.new/lib/File/Spec/Win32.pm 2005-07-08 16:05:27.000000000 -0700 @@ -133,16 +133,17 @@ $path =~ s|([^\\])\\+|$1\\|g; # xx\\\\xx -> xx\xx $path =~ s|(\\\.)+\\|\\|g; # xx\.\.\xx -> xx\xx $path =~ s|^(\.\\)+||s unless $path eq ".\\"; # .\xx -> xx + # xx1/xx2/xx3/../../xx -> xx1/xx + $path =~ s|\\\.\.\.\\|\\\.\.\\\.\.\\|g; # \...\ -> \..\..\ + $path =~ s|^\.\.\.\\|\.\.\\\.\.\\|g; # ...\ -> ..\..\ + + $path =~ s|^\\(\.\.\\?)+|\\|s; # \..\xx -> \xx $path =~ s|\\\Z(?!\n)|| unless $path =~ m{^([A-Z]:)?\\\Z(?!\n)}s; # xx\ -> xx - # xx1/xx2/xx3/../../xx -> xx1/xx - $path =~ s|\\\.\.\.\\|\\\.\.\\\.\.\\|g; # \...\ is 2 levels up - $path =~ s|^\.\.\.\\|\.\.\\\.\.\\|g; # ...\ is 2 levels up + return $path if $path =~ m|^\.\.|; # skip relative paths return $path unless $path =~ /\.\./; # too few .'s to cleanup return $path if $path =~ /\.\.\.\./; # too many .'s to cleanup - $path =~ s{^\\\.\.$}{\\}; # \.. -> \ - 1 while $path =~ s{^\\\.\.}{}; # \..\xx -> \xx my ($vol,$dirs,$file) = $self->splitpath($path); my @dirs = $self->splitdir($dirs); --- PathTools-3.09/t/Spec.t 2005-06-15 16:43:54.000000000 -0700 +++ PathTools-3.09.new/t/Spec.t 2005-07-08 16:10:41.000000000 -0700 @@ -86,7 +86,8 @@ [ "Unix->catdir()", '' ], [ "Unix->catdir('/')", '/' ], -[ "Unix->catdir('','d1','d2','d3','')", '/d1/d2/d3' ], +[ "Unix->catdir('', '..', '..', '')", '/' ], +[ "Unix->catdir('', '..', '..')", '/' ], [ "Unix->catdir('d1','d2','d3','')", 'd1/d2/d3' ], [ "Unix->catdir('','d1','d2','d3')", '/d1/d2/d3' ], [ "Unix->catdir('d1','d2','d3')", 'd1/d2/d3' ], @@ -97,6 +98,8 @@ [ "Unix->canonpath('/./')", '/' ], [ "Unix->canonpath('/a/./')", '/a' ], [ "Unix->canonpath('/a/.')", '/a' ], +[ "Unix->canonpath('/../../')", '/' ], +[ "Unix->canonpath('/../..')", '/' ], [ "Unix->abs2rel('/t1/t2/t3','/t1/t2/t3')", '' ], [ "Unix->abs2rel('/t1/t2/t4','/t1/t2/t3')", '../t4' ], @@ -177,6 +180,8 @@ [ "Win32->catdir('/', '..\\')", '\\' ], [ "Win32->catdir('\\', '../')", '\\' ], [ "Win32->catdir('\\', '..\\')", '\\' ], +[ "Win32->catdir('', '..', '..', '')", '\\' ], +[ "Win32->catdir('', '..', '..')", '\\' ], [ "Win32->catdir('//d1','d2')", '\\\\d1\\d2' ], [ "Win32->catdir('\\d1\\','d2')", '\\d1\\d2' ], [ "Win32->catdir('\\d1','d2')", '\\d1\\d2' ], @@ -226,6 +231,8 @@ [ "Win32->canonpath('\\..\\')", '\\' ], [ "Win32->canonpath('/../')", '\\' ], [ "Win32->canonpath('/..\\')", '\\' ], +[ "Win32->canonpath('\\..\\..\\')", '\\' ], +[ "Win32->canonpath('\\..\\..')", '\\' ], [ "Win32->can('_cwd')", '/CODE/' ], # FakeWin32 subclass (see below) just sets CWD to C:\one\two and getdcwd('D') to D:\alpha\beta