File Coverage

blib/lib/Mac/Path/Util.pm
Criterion Covered Total %
statement 121 131 92.3
branch 36 48 75.0
condition 14 26 53.8
subroutine 29 31 93.5
pod 9 9 100.0
total 209 245 85.3


line stmt bran cond sub pod time code
1             # $Id: Util.pm 2666 2008-08-15 14:33:04Z comdog $
2             package Mac::Path::Util;
3 5     5   114832 use strict;
  5         13  
  5         196  
4              
5 5     5   26 use warnings;
  5         10  
  5         149  
6 5     5   22 no warnings;
  5         12  
  5         191  
7              
8 5     5   26 use base qw(Exporter);
  5         8  
  5         552  
9 5     5   27 use vars qw(@EXPORT_OK %EXPORT_TAGS $VERSION);
  5         8  
  5         350  
10              
11 5     5   26 use Cwd qw(getcwd);
  5         7  
  5         333  
12 5     5   24 use Exporter;
  5         8  
  5         404  
13              
14             @EXPORT_OK = qw(DARWIN MACOS);
15             %EXPORT_TAGS = (
16             'system' => [ qw(DARWIN MACOS) ],
17             );
18             $VERSION = '0.26';
19              
20             my $Startup;
21              
22             =head1 NAME
23              
24             Mac::Path::Util - convert between darwin and Mac paths
25              
26             =head1 SYNOPSIS
27              
28             use Mac::Path::Util;
29              
30             my $path = Mac::Path::Util->new( "/Users/foo/file.txt" );
31             my $mac_path = $path->mac_path;
32              
33             =head1 DESCRIPTION
34              
35             THIS IS ALPHA SOFTWARE. SOME THINGS ARE NOT FINISHED.
36              
37             Convert between darwin (unix) and Mac file paths.
38              
39             This is not as simple as changing the directory separator. The Mac path
40             has the volume name in it, whereas the darwin path leaves off the
41             startup volume name because it is mounted as /. Mac::Path::Util can
42             optionally use Mac::Carbon to determine the real startup volume name
43             (off by default) if you have installed Mac::Carbon. You can use
44             this module on other platforms too. Once the module has looked up the
45             volume name, it caches it. If you want to reset the cache, use the
46             clear_startup() method.
47              
48             Colons ( ":" ) in the darwin path become / in the Mac path, and forward
49             slashes in the Mac path become colons in the darwin path.
50              
51             Mac paths do not have a leading directory separator for absolute paths.
52              
53             Normally, Mac paths that end in a directory name have a trailing colon,
54             but this module cannot necessarily verify that since you may want to
55             convert paths.
56              
57             =head2 Methods
58              
59             =over 4
60              
61             =cut
62              
63 5     5   28 use constant DARWIN => 'darwin';
  5         17  
  5         425  
64 5     5   25 use constant MACOS => 'macos';
  5         8  
  5         383  
65              
66 5     5   44 use constant DONT_KNOW => "Don't know";
  5         10  
  5         224  
67 5     5   23 use constant BAD_PATH => "Bad Path";
  5         7  
  5         8383  
68              
69 5     5   35 use constant TRUE => 'true';
  5         11  
  5         248  
70 5     5   24 use constant FALSE => 'false';
  5         9  
  5         5956  
71              
72 5     5   44 use constant LOCAL => 'local';
  5         17  
  5         230  
73 5     5   38 use constant REMOTE => 'remote';
  5         10  
  5         228  
74              
75 5     5   29 use constant STARTUP => 'Startup';
  5         10  
  5         22498  
76              
77             =item new( PATH [, HASH ] )
78              
79             The optional anonymous hash can have these values:
80              
81             type DARWIN or MACOS (explicitly state which sort of path
82             with these symbolic constants)
83             startup the name of the startup volume (if not defined, tries to use
84             the startup volume on the local machine)
85              
86             =cut
87              
88             sub new
89             {
90 10     10 1 2689 my $class = shift;
91 10         19 my $path = shift;
92 10         16 my $args = shift;
93              
94 10 50 0     55 my $type = DONT_KNOW
      33        
95             unless ( $args->{type} && ( $args->{type} eq DARWIN
96             or $args->{type} eq MACOS ) );
97              
98 10   33     168 my $self = {
99             starting_path => $path,
100             type => $type,
101             path => $path,
102             use_carbon => ( $^O eq 'darwin' or $^O =~ /MacOS/ ),
103             };
104            
105 10         94 bless $self, $class;
106              
107 10   50     75 $self->{startup} = $args->{startup} || undef;
108              
109 10         36 $self->_identify;
110              
111 10 50       891 return if $self->{type} eq BAD_PATH;
112              
113             # we know that there is at least one colon in the path
114             # if the type is MACOS
115 10 100       30 if( $self->type eq MACOS )
    100          
116             {
117 1         4 $self->{mac_path} = $self->path;
118              
119             # absolute paths do not start with colons
120 1 50       2 if( index( $self->path, 0, 1 ) ne ":" )
121             {
122 1         3 my( $volume )= $self->path =~ m/^(.+?):/g;
123              
124 1         4 $self->{volume} = $volume;
125             }
126             else
127             {
128 0         0 $self->{volume} = $self->_get_startup;
129 0 0       0 $self->{startup} = $self->volume
130             if $self->_is_startup( $self->{volume} ) eq TRUE;
131             }
132             }
133             elsif( $self->type eq DARWIN )
134             {
135 4         12 $self->{darwin_path} = $self->path;
136              
137 4 50       10 if( index( $self->path, 0, 1 ) eq "/" )
138             {
139 0         0 $self->{volume} = $self->path =~ m|^/Volumes/(.*?)/?|g;
140             }
141              
142 4 50       10 unless( defined $self->volume )
143             {
144 4         8 $self->{volume} = $self->_get_startup;
145 4 50       13 $self->{startup} = $self->volume
146             if $self->_is_startup( $self->{volume} ) eq TRUE;
147             }
148            
149 4         12 $self->_darwin2mac;
150             }
151              
152              
153 10         36 return $self;
154             }
155              
156             =back
157              
158             =head2 Accessor methods
159              
160             =over 4
161              
162             =item type
163              
164             =item path
165              
166             =item volume
167              
168             =item startup
169              
170             =item mac_path
171              
172             =item darwin_path
173              
174             =back
175              
176             =cut
177              
178 27     27 1 2567 sub type { return $_[0]->{type} }
179 11     11 1 48 sub path { return $_[0]->{path} }
180 8     8 1 24 sub volume { return $_[0]->{volume} }
181 21     21 1 434 sub startup { return $_[0]->{startup} }
182 4     4 1 33 sub mac_path { return $_[0]->{mac_path} }
183 0     0 1 0 sub darwin_path { return $_[0]->{darwin_path} }
184              
185             =head2 Setter methods
186              
187             =over 4
188              
189             =item use_carbon( [ TRUE | FALSE ] )
190              
191             Mac::Path::Util will try to use Mac::Carbon to determine the real
192             startup volume name if you pass this method a true value and you
193             have Mac::Carbon installed. Otherwise it will use a default
194             startup volume name.
195              
196             =cut
197              
198             sub use_carbon
199             {
200 2     2 1 1249 my $self = shift;
201            
202 2 100       6 $self->{use_carbon} = $_[0] ? 1 : 0;
203            
204 2         6 $self->clear_startup
205             }
206              
207             sub _d2m_trans
208             {
209 8     8   14 my $name = shift;
210              
211 8         15 $name =~ tr|/:|:/|;
212              
213 8         35 return $name;
214             }
215              
216             sub _darwin2mac
217             {
218 8     8   1180 my $self = shift;
219              
220 8         23 my $name = $self->{starting_path};
221              
222 8         11 $self->{mac_path} = do {
223             # is this a relative url?
224 8 100       51 if( substr( $name, 0, 1 ) ne "/" )
    100          
    50          
225             {
226 3         6 my $path = ":" . _d2m_trans( $name );
227 3         9 $path;
228             }
229             # is this an absolute url with another Volume?
230             elsif( $name =~ m|^/Volumes/([^/]+)(/.*)| )
231             {
232 2         5 my $volume = $1;
233 2         5 my $path = $2;
234              
235 2         3 $path = _d2m_trans( $path );
236              
237 2         9 my $abs = $volume . $path;
238             }
239             # absolute path off of startup volume?
240             elsif( substr( $name, 0, 1 ) eq "/" )
241             {
242 3         9 my $volume = $self->_get_startup;
243              
244 3         11 my $path = _d2m_trans( $name );
245              
246 3         18 my $abs = $volume . $path;
247             }
248             };
249              
250 8         19 return $self->{mac_path};
251             }
252              
253             sub _mac2darwin
254             {
255 0     0   0 my $self = shift;
256 0         0 my $name = shift;
257              
258 0         0 $name =~ tr|/:|:/|;
259              
260 0         0 return $name;
261             }
262              
263             sub _identify
264             {
265 10     10   17 my $self = shift;
266              
267 10         13 my $colons = 0;
268 10         16 my $slashes = 0;
269              
270 10 100       35 if ( defined $self->{starting_path} ) {
271 8         18 $colons = $self->{starting_path} =~ tr/://;
272 8         18 $slashes = $self->{starting_path} =~ tr|/||;
273             }
274              
275 10 100 100     671 if( $colons == 0 and $slashes == 0 )
    100 100        
    100 66        
    50 33        
276             {
277 4         12 $self->{type} = DONT_KNOW;
278             }
279             elsif( $colons != 0 and $slashes == 0 )
280             {
281 1         4 $self->{type} = MACOS;
282             }
283             elsif( $colons == 0 and $slashes != 0 )
284             {
285 4         13 $self->{type} = DARWIN;
286             }
287             elsif( $colons != 0 and $slashes != 0 )
288             {
289 1         3 $self->{type} = DONT_KNOW;
290             }
291              
292             }
293              
294             =item clear_startup
295              
296             Clear the cached startup volume name. The next lookup will
297             reset the cache.
298              
299             =cut
300              
301             sub clear_startup
302             {
303 3     3 1 38 my $self = shift;
304              
305 3 50       12 delete $self->{startup} if ref $self;
306 3         6 $Startup = undef;
307             }
308              
309             sub _get_startup
310             {
311 13     13   2607 my $self = shift;
312            
313 13 100       37 return $self->startup if defined $self->startup;
314 11 100       41 return $Startup if defined $Startup;
315              
316 5         635 my $volume = do {
317 5 50 66     30 if( $self->{use_carbon} and eval { require MacPerl } )
  1         573  
318             {
319 0         0 (my $volume = scalar MacPerl::Volumes()) =~ s/^.+?:(.+)$/$1/;
320 0         0 $volume;
321             }
322             else
323             {
324 5         14 STARTUP;
325             }
326             };
327            
328             #print STDERR "I think the startup volume is [$volume]\n";
329              
330 5         20 $Startup = $self->{startup} = $volume;
331              
332 5         14 return $volume;
333             }
334              
335             sub _is_startup
336             {
337 6     6   1219 my $self = shift;
338 6         9 my $name = shift;
339              
340 6 100       14 $self->_get_startup unless defined $self->startup;
341            
342 6 100       38 $name eq $Startup ? TRUE : FALSE;
343             }
344              
345             =back
346              
347             =head1 SOURCE AVAILABILITY
348              
349             This source is part of a SourceForge project which always has the
350             latest sources in SVN, as well as all of the previous releases.
351              
352             http://sourceforge.net/projects/brian-d-foy/
353              
354             If, for some reason, I disappear from the world, one of the other
355             members of the project can shepherd this module appropriately.
356              
357             =head1 AUTHOR
358              
359             brian d foy, C<< >>
360              
361             =head1 COPYRIGHT AND LICENSE
362              
363             Copyright (c) 2002-2008 brian d foy. All rights reserved.
364              
365             This program is free software; you can redistribute it and/or modify
366             it under the same terms as Perl itself.
367              
368             =cut
369              
370             "See why 1984 won't be like 1984";