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