Revision history for Perl distribution PathTools.
+3.21 Wed Oct 4 21:13:21 CDT 2006
+
+ - Added a bunch of X<> tags to the File::Spec docs to help
+ podindex. [Gabor Szabo]
+
+ - On Win32, abs2rel('C:\one\two\t\foo', 't\bar') should return
+ '..\foo' when the cwd is 'C:\one\two', but it wasn't noticing that
+ the two relevant volumes were the same so it would return the full
+ path 'C:\one\two\t\foo'. This is fixed. [Spotted by Alexandr
+ Ciornii]
+
+ - On Win32, rel2abs() now always adds a volume (drive letter) if the
+ given path doesn't have a volume (drive letter or UNC volume).
+ Previously it could return a value that didn't have a volume if the
+ input was a semi-absolute path like /foo/bar instead of a
+ fully-absolute path like C:/foo/bar .
+
3.19 Tue Jul 11 22:40:26 CDT 2006
- When abs2rel() is called with two relative paths
use Exporter;
use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
-$VERSION = '3.19';
+$VERSION = '3.21';
@ISA = qw/ Exporter /;
@EXPORT = qw(cwd getcwd fastcwd fastgetcwd);
use strict;
use vars qw(@ISA $VERSION);
-$VERSION = '3.19';
+$VERSION = '3.21';
$VERSION = eval $VERSION;
my %module = (MacOS => 'Mac',
=over 2
=item canonpath
+X<canonpath>
No physical check on the filesystem, but a logical cleanup of a
path.
actually traverse the filesystem cleaning up paths like this.
=item catdir
+X<catdir>
Concatenate two or more directory names to form a complete path ending
with a directory. But remove the trailing slash from the resulting
$path = File::Spec->catdir( @directories );
=item catfile
+X<catfile>
Concatenate one or more directory names and a filename to form a
complete path ending with a filename
$path = File::Spec->catfile( @directories, $filename );
=item curdir
+X<curdir>
Returns a string representation of the current directory.
$curdir = File::Spec->curdir();
=item devnull
+X<devnull>
Returns a string representation of the null device.
$devnull = File::Spec->devnull();
=item rootdir
+X<rootdir>
Returns a string representation of the root directory.
$rootdir = File::Spec->rootdir();
=item tmpdir
+X<tmpdir>
Returns a string representation of the first writable directory from a
list of possible temporary directories. Returns the current directory
$tmpdir = File::Spec->tmpdir();
=item updir
+X<updir>
Returns a string representation of the parent directory.
(see L<File::Spec::VMS/file_name_is_absolute>).
=item path
+X<path>
Takes no argument. Returns the environment variable C<PATH> (or the local
platform's equivalent) as a list.
@PATH = File::Spec->path();
=item join
+X<join, path>
join is the same as catfile.
=item splitpath
+X<splitpath> X<split, path>
Splits a path in to volume, directory, and filename portions. On systems
with no concept of volume, returns '' for volume.
(usually identical to) the original path.
=item splitdir
+X<splitdir> X<split, dir>
The opposite of L</catdir()>.
$full_path = File::Spec->catpath( $volume, $directory, $file );
=item abs2rel
+X<abs2rel> X<absolute, path> X<relative, path>
Takes a destination path and an optional base path returns a relative path
from the base path to the destination path:
Based on code written by Shigio Yamaguchi.
=item rel2abs()
+X<rel2abs> X<absolute, path> X<relative, path>
Converts a relative path to an absolute path.
for ($path, $base) { $_ = $self->canonpath($_) }
- my ($path_volume) = $self->splitpath($path, 1);
- my ($base_volume) = $self->splitpath($base, 1);
-
- # Can't relativize across volumes
- return $path unless $path_volume eq $base_volume;
-
if (grep $self->file_name_is_absolute($_), $path, $base) {
for ($path, $base) { $_ = $self->rel2abs($_) }
}
for ($path, $base) { $_ = $self->catdir('/', $_) }
}
+ my ($path_volume) = $self->splitpath($path, 1);
+ my ($base_volume) = $self->splitpath($base, 1);
+
+ # Can't relativize across volumes
+ return $path unless $path_volume eq $base_volume;
+
my $path_directories = ($self->splitpath($path, 1))[1];
my $base_directories = ($self->splitpath($base, 1))[1];
@ISA = qw(File::Spec::Unix);
+# Some regexes we use for path splitting
+my $DRIVE_RX = '[a-zA-Z]:';
+my $UNC_RX = '(?:\\\\\\\\|//)[^\\\\/]+[\\\\/][^\\\\/]+';
+my $VOL_RX = "(?:$DRIVE_RX|$UNC_RX)";
+
+
=head1 NAME
File::Spec::Win32 - methods for Win32 file specs
sub file_name_is_absolute {
my ($self,$file) = @_;
- return scalar($file =~ m{^([a-z]:)?[\\/]}is);
+ return $file =~ m{^$VOL_RX}os ? 2 :
+ $file =~ m{^[\\/]}is ? 1 :
+ 0;
}
=item catfile
my ($volume,$directory,$file) = ('','','');
if ( $nofile ) {
$path =~
- m{^( (?:[a-zA-Z]:|(?:\\\\|//)[^\\/]+[\\/][^\\/]+)? )
- (.*)
- }xs;
+ m{^ ( $VOL_RX ? ) (.*) }sox;
$volume = $1;
$directory = $2;
}
else {
$path =~
- m{^ ( (?: [a-zA-Z]: |
- (?:\\\\|//)[^\\/]+[\\/][^\\/]+
- )?
- )
+ m{^ ( $VOL_RX ? )
( (?:.*[\\/](?:\.\.?\Z(?!\n))?)? )
(.*)
- }xs;
+ }sox;
$volume = $1;
$directory = $2;
$file = $3;
sub rel2abs {
my ($self,$path,$base ) = @_;
- if ( ! $self->file_name_is_absolute( $path ) ) {
-
- if ( !defined( $base ) || $base eq '' ) {
- require Cwd ;
- $base = Cwd::getdcwd( ($self->splitpath( $path ))[0] ) if defined &Cwd::getdcwd ;
- $base = $self->_cwd() unless defined $base ;
- }
- elsif ( ! $self->file_name_is_absolute( $base ) ) {
- $base = $self->rel2abs( $base ) ;
- }
- else {
- $base = $self->canonpath( $base ) ;
- }
-
- my ( $path_directories, $path_file ) =
- ($self->splitpath( $path, 1 ))[1,2] ;
-
- my ( $base_volume, $base_directories ) =
- $self->splitpath( $base, 1 ) ;
-
- $path = $self->catpath(
- $base_volume,
- $self->catdir( $base_directories, $path_directories ),
- $path_file
- ) ;
+ my $is_abs = $self->file_name_is_absolute($path);
+
+ # Check for volume (should probably document the '2' thing...)
+ return $self->canonpath( $path ) if $is_abs == 2;
+
+ if ($is_abs) {
+ # It's missing a volume, add one
+ my $vol = ($self->splitpath( $self->_cwd() ))[0];
+ return $self->canonpath( $vol . $path );
+ }
+
+ if ( !defined( $base ) || $base eq '' ) {
+ require Cwd ;
+ $base = Cwd::getdcwd( ($self->splitpath( $path ))[0] ) if defined &Cwd::getdcwd ;
+ $base = $self->_cwd() unless defined $base ;
}
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ my ( $path_directories, $path_file ) =
+ ($self->splitpath( $path, 1 ))[1,2] ;
+
+ my ( $base_volume, $base_directories ) =
+ $self->splitpath( $base, 1 ) ;
+
+ $path = $self->catpath(
+ $base_volume,
+ $self->catdir( $base_directories, $path_directories ),
+ $path_file
+ ) ;
return $self->canonpath( $path ) ;
}
[ "FakeWin32->abs2rel('C:/one/two/three')", 'three' ],
[ "FakeWin32->abs2rel('C:\\Windows\\System32', 'C:\\')", 'Windows\System32' ],
[ "FakeWin32->abs2rel('\\\\computer2\\share3\\foo.txt', '\\\\computer2\\share3')", 'foo.txt' ],
+[ "FakeWin32->abs2rel('C:\\one\\two\\t\\asd1\\', 't\\asd\\')", '..\\asd1' ],
[ "FakeWin32->rel2abs('temp','C:/')", 'C:\\temp' ],
[ "FakeWin32->rel2abs('temp','C:/a')", 'C:\\a\\temp' ],
[ "FakeWin32->rel2abs('temp','C:/a/')", 'C:\\a\\temp' ],
[ "FakeWin32->rel2abs('../','C:/')", 'C:\\' ],
[ "FakeWin32->rel2abs('../','C:/a')", 'C:\\' ],
+[ "FakeWin32->rel2abs('\\foo','C:/a')", 'C:\\foo' ],
[ "FakeWin32->rel2abs('temp','//prague_main/work/')", '\\\\prague_main\\work\\temp' ],
[ "FakeWin32->rel2abs('../temp','//prague_main/work/')", '\\\\prague_main\\work\\temp' ],
[ "FakeWin32->rel2abs('temp','//prague_main/work')", '\\\\prague_main\\work\\temp' ],