Merge branch 'master' of http://repo.or.cz/r/msysgit into devel
[msysgit/historical-msysgit.git] / lib / perl5 / 5.6.1 / File / Spec / Epoc.pm
blob36dc3b2c3fb4cb1af35b0ed68fa41b82b5313442
1 package File::Spec::Epoc;
3 use strict;
4 use Cwd;
5 use vars qw(@ISA);
6 require File::Spec::Unix;
7 @ISA = qw(File::Spec::Unix);
9 =head1 NAME
11 File::Spec::Epoc - methods for Epoc file specs
13 =head1 SYNOPSIS
15 require File::Spec::Epoc; # Done internally by File::Spec if needed
17 =head1 DESCRIPTION
19 See File::Spec::Unix for a documentation of the methods provided
20 there. This package overrides the implementation of these methods, not
21 the semantics.
23 This package is still work in progress ;-)
24 o.flebbe@gmx.de
27 =over
29 =item devnull
31 Returns a string representation of the null device.
33 =cut
35 sub devnull {
36 return "nul:";
39 =item tmpdir
41 Returns a string representation of a temporay directory:
43 =cut
45 my $tmpdir;
46 sub tmpdir {
47 return "C:/System/temp";
50 sub case_tolerant {
51 return 1;
54 sub file_name_is_absolute {
55 my ($self,$file) = @_;
56 return scalar($file =~ m{^([a-z?]:)?[\\/]}is);
59 =item path
61 Takes no argument, returns the environment variable PATH as an array. Since
62 there is no search path supported, it returns undef, sorry.
64 =cut
65 sub path {
66 return undef;
69 =item canonpath
71 No physical check on the filesystem, but a logical cleanup of a
72 path. On UNIX eliminated successive slashes and successive "/.".
74 =cut
76 sub canonpath {
77 my ($self,$path) = @_;
78 $path =~ s/^([a-z]:)/\u$1/s;
80 $path =~ s|/+|/|g unless($^O eq 'cygwin' or $^O eq 'msys'); # xx////xx -> xx/xx
81 $path =~ s|(/\.)+/|/|g; # xx/././xx -> xx/xx
82 $path =~ s|^(\./)+||s unless $path eq "./"; # ./xx -> xx
83 $path =~ s|^/(\.\./)+|/|s; # /../../xx -> xx
84 $path =~ s|/\z|| unless $path eq "/"; # xx/ -> xx
85 return $path;
88 =item splitpath
90 ($volume,$directories,$file) = File::Spec->splitpath( $path );
91 ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
93 Splits a path in to volume, directory, and filename portions. Assumes that
94 the last file is a path unless the path ends in '\\', '\\.', '\\..'
95 or $no_file is true. On Win32 this means that $no_file true makes this return
96 ( $volume, $path, undef ).
98 Separators accepted are \ and /.
100 The results can be passed to L</catpath> to get back a path equivalent to
101 (usually identical to) the original path.
103 =cut
105 sub splitpath {
106 my ($self,$path, $nofile) = @_;
107 my ($volume,$directory,$file) = ('','','');
108 if ( $nofile ) {
109 $path =~
110 m{^( (?:[a-zA-Z?]:|(?:\\\\|//)[^\\/]+[\\/][^\\/]+)? )
111 (.*)
112 }xs;
113 $volume = $1;
114 $directory = $2;
116 else {
117 $path =~
118 m{^ ( (?: [a-zA-Z?]: |
119 (?:\\\\|//)[^\\/]+[\\/][^\\/]+
122 ( (?:.*[\\\\/](?:\.\.?\z)?)? )
123 (.*)
124 }xs;
125 $volume = $1;
126 $directory = $2;
127 $file = $3;
130 return ($volume,$directory,$file);
134 =item splitdir
136 The opposite of L</catdir()>.
138 @dirs = File::Spec->splitdir( $directories );
140 $directories must be only the directory portion of the path on systems
141 that have the concept of a volume or that have path syntax that differentiates
142 files from directories.
144 Unlike just splitting the directories on the separator, leading empty and
145 trailing directory entries can be returned, because these are significant
146 on some OSs. So,
148 File::Spec->splitdir( "/a/b/c" );
150 Yields:
152 ( '', 'a', 'b', '', 'c', '' )
154 =cut
156 sub splitdir {
157 my ($self,$directories) = @_ ;
159 # split() likes to forget about trailing null fields, so here we
160 # check to be sure that there will not be any before handling the
161 # simple case.
163 if ( $directories !~ m|[\\/]\z| ) {
164 return split( m|[\\/]|, $directories );
166 else {
168 # since there was a trailing separator, add a file name to the end,
169 # then do the split, then replace it with ''.
171 my( @directories )= split( m|[\\/]|, "${directories}dummy" ) ;
172 $directories[ $#directories ]= '' ;
173 return @directories ;
178 =item catpath
180 Takes volume, directory and file portions and returns an entire path. Under
181 Unix, $volume is ignored, and this is just like catfile(). On other OSs,
182 the $volume become significant.
184 =cut
186 sub catpath {
187 my ($self,$volume,$directory,$file) = @_;
189 # If it's UNC, make sure the glue separator is there, reusing
190 # whatever separator is first in the $volume
191 $volume .= $1
192 if ( $volume =~ m@^([\\/])[\\/][^\\/]+[\\/][^\\/]+\z@s &&
193 $directory =~ m@^[^\\/]@s
196 $volume .= $directory ;
198 # If the volume is not just A:, make sure the glue separator is
199 # there, reusing whatever separator is first in the $volume if possible.
200 if ( $volume !~ m@^[a-zA-Z]:\z@s &&
201 $volume =~ m@[^\\/]\z@ &&
202 $file =~ m@[^\\/]@
204 $volume =~ m@([\\/])@ ;
205 my $sep = $1 ? $1 : '\\' ;
206 $volume .= $sep ;
209 $volume .= $file ;
211 return $volume ;
215 =item abs2rel
217 Takes a destination path and an optional base path returns a relative path
218 from the base path to the destination path:
220 $rel_path = File::Spec->abs2rel( $destination ) ;
221 $rel_path = File::Spec->abs2rel( $destination, $base ) ;
223 If $base is not present or '', then L</cwd()> is used. If $base is relative,
224 then it is converted to absolute form using L</rel2abs()>. This means that it
225 is taken to be relative to L<cwd()>.
227 On systems with the concept of a volume, this assumes that both paths
228 are on the $destination volume, and ignores the $base volume.
230 On systems that have a grammar that indicates filenames, this ignores the
231 $base filename as well. Otherwise all path components are assumed to be
232 directories.
234 If $path is relative, it is converted to absolute form using L</rel2abs()>.
235 This means that it is taken to be relative to L</cwd()>.
237 Based on code written by Shigio Yamaguchi.
239 No checks against the filesystem are made.
241 =cut
243 sub abs2rel {
244 my($self,$path,$base) = @_;
246 # Clean up $path
247 if ( ! $self->file_name_is_absolute( $path ) ) {
248 $path = $self->rel2abs( $path ) ;
250 else {
251 $path = $self->canonpath( $path ) ;
254 # Figure out the effective $base and clean it up.
255 if ( ! $self->file_name_is_absolute( $base ) ) {
256 $base = $self->rel2abs( $base ) ;
258 elsif ( !defined( $base ) || $base eq '' ) {
259 $base = cwd() ;
261 else {
262 $base = $self->canonpath( $base ) ;
265 # Split up paths
266 my ( $path_volume, $path_directories, $path_file ) =
267 $self->splitpath( $path, 1 ) ;
269 my ( undef, $base_directories, undef ) =
270 $self->splitpath( $base, 1 ) ;
272 # Now, remove all leading components that are the same
273 my @pathchunks = $self->splitdir( $path_directories );
274 my @basechunks = $self->splitdir( $base_directories );
276 while ( @pathchunks &&
277 @basechunks &&
278 lc( $pathchunks[0] ) eq lc( $basechunks[0] )
280 shift @pathchunks ;
281 shift @basechunks ;
284 # No need to catdir, we know these are well formed.
285 $path_directories = CORE::join( '\\', @pathchunks );
286 $base_directories = CORE::join( '\\', @basechunks );
288 # $base_directories now contains the directories the resulting relative
289 # path must ascend out of before it can descend to $path_directory. So,
290 # replace all names with $parentDir
292 #FA Need to replace between backslashes...
293 $base_directories =~ s|[^\\]+|..|g ;
295 # Glue the two together, using a separator if necessary, and preventing an
296 # empty result.
298 #FA Must check that new directories are not empty.
299 if ( $path_directories ne '' && $base_directories ne '' ) {
300 $path_directories = "$base_directories\\$path_directories" ;
301 } else {
302 $path_directories = "$base_directories$path_directories" ;
305 # It makes no sense to add a relative path to a UNC volume
306 $path_volume = '' unless $path_volume =~ m{^[A-Z]:}is ;
308 return $self->canonpath(
309 $self->catpath($path_volume, $path_directories, $path_file )
313 =item rel2abs
315 Converts a relative path to an absolute path.
317 $abs_path = File::Spec->rel2abs( $destination ) ;
318 $abs_path = File::Spec->rel2abs( $destination, $base ) ;
320 If $base is not present or '', then L<cwd()> is used. If $base is relative,
321 then it is converted to absolute form using L</rel2abs()>. This means that it
322 is taken to be relative to L</cwd()>.
324 Assumes that both paths are on the $base volume, and ignores the
325 $destination volume.
327 On systems that have a grammar that indicates filenames, this ignores the
328 $base filename as well. Otherwise all path components are assumed to be
329 directories.
331 If $path is absolute, it is cleaned up and returned using L</canonpath()>.
333 Based on code written by Shigio Yamaguchi.
335 No checks against the filesystem are made.
337 =cut
339 sub rel2abs($;$;) {
340 my ($self,$path,$base ) = @_;
342 if ( ! $self->file_name_is_absolute( $path ) ) {
344 if ( !defined( $base ) || $base eq '' ) {
345 $base = cwd() ;
347 elsif ( ! $self->file_name_is_absolute( $base ) ) {
348 $base = $self->rel2abs( $base ) ;
350 else {
351 $base = $self->canonpath( $base ) ;
354 my ( undef, $path_directories, $path_file ) =
355 $self->splitpath( $path, 1 ) ;
357 my ( $base_volume, $base_directories, undef ) =
358 $self->splitpath( $base, 1 ) ;
360 $path = $self->catpath(
361 $base_volume,
362 $self->catdir( $base_directories, $path_directories ),
363 $path_file
367 return $self->canonpath( $path ) ;
370 =back
372 =head1 SEE ALSO
374 L<File::Spec>
376 =cut