File Coverage

blib/lib/Portable/FileSpec.pm
Criterion Covered Total %
statement 47 56 83.9
branch 14 36 38.8
condition 9 15 60.0
subroutine 8 9 88.8
pod 0 5 0.0
total 78 121 64.4


line stmt bran cond sub pod time code
1             package Portable::FileSpec;
2            
3             ### UGLY HACK: these functions where completely copied from File::Spec::Win32
4            
5 4     4   97 use 5.008;
  4         13  
  4         136  
6 4     4   20 use strict;
  4         5  
  4         108  
7 4     4   17 use warnings;
  4         6  
  4         4980  
8            
9             our $VERSION = '1.22';
10            
11             # Some regexes we use for path splitting
12             my $DRIVE_RX = '[a-zA-Z]:';
13             my $UNC_RX = '(?:\\\\\\\\|//)[^\\\\/]+[\\\\/][^\\\\/]+';
14             my $VOL_RX = "(?:$DRIVE_RX|$UNC_RX)";
15            
16             sub splitpath {
17 3     3 0 7 my ($path, $nofile) = @_;
18 3         8 my ($volume,$directory,$file) = ('','','');
19 3 50       9 if ( $nofile ) {
20 0         0 $path =~
21             m{^ ( $VOL_RX ? ) (.*) }sox;
22 0         0 $volume = $1;
23 0         0 $directory = $2;
24             }
25             else {
26 3         212 $path =~
27             m{^ ( $VOL_RX ? )
28             ( (?:.*[\\/](?:\.\.?\Z(?!\n))?)? )
29             (.*)
30             }sox;
31 3         17 $volume = $1;
32 3         8 $directory = $2;
33 3         9 $file = $3;
34             }
35            
36 3         12 return ($volume,$directory,$file);
37             }
38            
39             sub splitdir {
40 3     3 0 6 my ($directories) = @_ ;
41             #
42             # split() likes to forget about trailing null fields, so here we
43             # check to be sure that there will not be any before handling the
44             # simple case.
45             #
46 3 50       17 if ( $directories !~ m|[\\/]\Z(?!\n)| ) {
47 0         0 return split( m|[\\/]|, $directories );
48             }
49             else {
50             #
51             # since there was a trailing separator, add a file name to the end,
52             # then do the split, then replace it with ''.
53             #
54 3         144 my( @directories )= split( m|[\\/]|, "${directories}dummy" ) ;
55 3         9 $directories[ $#directories ]= '' ;
56 3         18 return @directories ;
57             }
58             }
59            
60             sub catpath {
61 24     24 0 38 my ($volume,$directory,$file) = @_;
62            
63             # If it's UNC, make sure the glue separator is there, reusing
64             # whatever separator is first in the $volume
65 24         24 my $v;
66 24 50 33     95 $volume .= $v
67             if ( (($v) = $volume =~ m@^([\\/])[\\/][^\\/]+[\\/][^\\/]+\Z(?!\n)@s) &&
68             $directory =~ m@^[^\\/]@s
69             ) ;
70            
71 24         28 $volume .= $directory ;
72            
73             # If the volume is not just A:, make sure the glue separator is
74             # there, reusing whatever separator is first in the $volume if possible.
75 24 100 66     177 if ( $volume !~ m@^[a-zA-Z]:\Z(?!\n)@s &&
      66        
76             $volume =~ m@[^\\/]\Z(?!\n)@ &&
77             $file =~ m@[^\\/]@
78             ) {
79 21         39 $volume =~ m@([\\/])@ ;
80 21 50       52 my $sep = $1 ? $1 : '\\' ;
81 21         30 $volume .= $sep ;
82             }
83            
84 24         36 $volume .= $file ;
85            
86 24         210 return $volume ;
87             }
88            
89             sub catdir {
90             # Legacy / compatibility support
91 24 50   24 0 58 return "" unless @_;
92 24 50       67 shift, return _canon_cat( "/", @_ ) if $_[0] eq "";
93            
94             # Compatibility with File::Spec <= 3.26:
95             # catdir('A:', 'foo') should return 'A:\foo'.
96 0 0       0 return _canon_cat( ($_[0].'\\'), @_[1..$#_] ) if $_[0] =~ m{^$DRIVE_RX\z}o;
97            
98 0         0 return _canon_cat( @_ );
99             }
100            
101             sub catfile {
102             # Legacy / compatibility support
103             #
104 0 0   0 0 0 shift, return _canon_cat( "/", @_ )
105             if $_[0] eq "";
106            
107             # Compatibility with File::Spec <= 3.26:
108             # catfile('A:', 'foo') should return 'A:\foo'.
109 0 0       0 return _canon_cat( ($_[0].'\\'), @_[1..$#_] )
110             if $_[0] =~ m{^$DRIVE_RX\z}o;
111            
112 0         0 return _canon_cat( @_ );
113             }
114            
115             sub _canon_cat {
116 24     24   54 my ($first, @rest) = @_;
117            
118 24 0       103 my $volume = $first =~ s{ \A ([A-Za-z]:) ([\\/]?) }{}x # drive letter
    0          
    50          
    50          
    50          
119             ? ucfirst( $1 ).( $2 ? "\\" : "" )
120             : $first =~ s{ \A (?:\\\\|//) ([^\\/]+)
121             (?: [\\/] ([^\\/]+) )?
122             [\\/]? }{}xs # UNC volume
123             ? "\\\\$1".( defined $2 ? "\\$2" : "" )."\\"
124             : $first =~ s{ \A [\\/] }{}x # root dir
125             ? "\\"
126             : "";
127 24         46 my $path = join "\\", $first, @rest;
128            
129 24         33 $path =~ tr#\\/#\\\\#s; # xx/yy --> xx\yy & xx\\yy --> xx\yy
130            
131             # xx/././yy --> xx/yy
132 24         79 $path =~ s{(?:
133             (?:\A|\\) # at begin or after a slash
134             \.
135             (?:\\\.)* # and more
136             (?:\\|\z) # at end or followed by slash
137             )+ # performance boost -- I do not know why
138             }{\\}gx;
139            
140             # XXX I do not know whether more dots are supported by the OS supporting
141             # this ... annotation (NetWare or symbian but not MSWin32).
142             # Then .... could easily become ../../.. etc:
143             # Replace \.\.\. by (\.\.\.+) and substitute with
144             # { $1 . ".." . "\\.." x (length($2)-2) }gex
145             # ... --> ../..
146 24         30 $path =~ s{ (\A|\\) # at begin or after a slash
147             \.\.\.
148             (?=\\|\z) # at end or followed by slash
149             }{$1..\\..}gx;
150             # xx\yy\..\zz --> xx\zz
151 24         54 while ( $path =~ s{(?:
152             (?:\A|\\) # at begin or after a slash
153             [^\\]+ # rip this 'yy' off
154             \\\.\.
155             (?
156             (?
157             (?:\\|\z) # at end or followed by slash
158             )+ # performance boost -- I do not know why
159             }{\\}sx ) {}
160            
161 24         58 $path =~ s#\A\\##; # \xx --> xx NOTE: this is *not* root
162 24         62 $path =~ s#\\\z##; # xx\ --> xx
163            
164 24 50       63 if ( $volume =~ m#\\\z# )
165             { # \.. --> \
166 24         30 $path =~ s{ \A # at begin
167             \.\.
168             (?:\\\.\.)* # and more
169             (?:\\|\z) # at end or followed by slash
170             }{}x;
171            
172 24 50 66     74 return $1 # \\HOST\SHARE\ --> \\HOST\SHARE
173             if $path eq ""
174             and $volume =~ m#\A(\\\\.*)\\\z#s;
175             }
176 24 50 66     151 return $path ne "" || $volume ? $volume.$path : ".";
177             }
178            
179            
180             1;