Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / Path / Class / Dir.pm
1 package Path::Class::Dir;
2
3 $VERSION = '0.17';
4
5 use strict;
6 use Path::Class::File;
7 use Path::Class::Entity;
8 use Carp();
9 use base qw(Path::Class::Entity);
10
11 use IO::Dir ();
12 use File::Path ();
13
14 sub new {
15   my $self = shift->SUPER::new();
16
17   # If the only arg is undef, it's probably a mistake.  Without this
18   # special case here, we'd return the root directory, which is a
19   # lousy thing to do to someone when they made a mistake.  Return
20   # undef instead.
21   return if @_==1 && !defined($_[0]);
22
23   my $s = $self->_spec;
24   
25   my $first = (@_ == 0     ? $s->curdir :
26                $_[0] eq '' ? (shift, $s->rootdir) :
27                shift()
28               );
29   
30   ($self->{volume}, my $dirs) = $s->splitpath( $s->canonpath($first) , 1);
31   $self->{dirs} = [$s->splitdir($s->catdir($dirs, @_))];
32
33   return $self;
34 }
35
36 sub is_dir { 1 }
37
38 sub as_foreign {
39   my ($self, $type) = @_;
40
41   my $foreign = do {
42     local $self->{file_spec_class} = $self->_spec_class($type);
43     $self->SUPER::new;
44   };
45   
46   # Clone internal structure
47   $foreign->{volume} = $self->{volume};
48   my ($u, $fu) = ($self->_spec->updir, $foreign->_spec->updir);
49   $foreign->{dirs} = [ map {$_ eq $u ? $fu : $_} @{$self->{dirs}}];
50   return $foreign;
51 }
52
53 sub stringify {
54   my $self = shift;
55   my $s = $self->_spec;
56   return $s->catpath($self->{volume},
57                      $s->catdir(@{$self->{dirs}}),
58                      '');
59 }
60
61 sub volume { shift()->{volume} }
62
63 sub file {
64   local $Path::Class::Foreign = $_[0]->{file_spec_class} if $_[0]->{file_spec_class};
65   return Path::Class::File->new(@_);
66 }
67
68 sub dir_list {
69   my $self = shift;
70   my $d = $self->{dirs};
71   return @$d unless @_;
72   
73   my $offset = shift;
74   if ($offset < 0) { $offset = $#$d + $offset + 1 }
75   
76   return wantarray ? @$d[$offset .. $#$d] : $d->[$offset] unless @_;
77   
78   my $length = shift;
79   if ($length < 0) { $length = $#$d + $length + 1 - $offset }
80   return @$d[$offset .. $length + $offset - 1];
81 }
82
83 sub subdir {
84   my $self = shift;
85   return $self->new($self, @_);
86 }
87
88 sub parent {
89   my $self = shift;
90   my $dirs = $self->{dirs};
91   my ($curdir, $updir) = ($self->_spec->curdir, $self->_spec->updir);
92
93   if ($self->is_absolute) {
94     my $parent = $self->new($self);
95     pop @{$parent->{dirs}};
96     return $parent;
97
98   } elsif ($self eq $curdir) {
99     return $self->new($updir);
100
101   } elsif (!grep {$_ ne $updir} @$dirs) {  # All updirs
102     return $self->new($self, $updir); # Add one more
103
104   } elsif (@$dirs == 1) {
105     return $self->new($curdir);
106
107   } else {
108     my $parent = $self->new($self);
109     pop @{$parent->{dirs}};
110     return $parent;
111   }
112 }
113
114 sub relative {
115   # File::Spec->abs2rel before version 3.13 returned the empty string
116   # when the two paths were equal - work around it here.
117   my $self = shift;
118   my $rel = $self->_spec->abs2rel($self->stringify, @_);
119   return $self->new( length $rel ? $rel : $self->_spec->curdir );
120 }
121
122 sub open  { IO::Dir->new(@_) }
123 sub mkpath { File::Path::mkpath(shift()->stringify, @_) }
124 sub rmtree { File::Path::rmtree(shift()->stringify, @_) }
125
126 sub remove {
127   rmdir( shift() );
128 }
129
130 sub recurse {
131   my $self = shift;
132   my %opts = (preorder => 1, depthfirst => 0, @_);
133   
134   my $callback = $opts{callback}
135     or Carp::croak( "Must provide a 'callback' parameter to recurse()" );
136   
137   my @queue = ($self);
138   
139   my $visit_entry;
140   my $visit_dir = 
141     $opts{depthfirst} && $opts{preorder}
142     ? sub {
143       my $dir = shift;
144       $callback->($dir);
145       unshift @queue, $dir->children;
146     }
147     : $opts{preorder}
148     ? sub {
149       my $dir = shift;
150       $callback->($dir);
151       push @queue, $dir->children;
152     }
153     : sub {
154       my $dir = shift;
155       $visit_entry->($_) foreach $dir->children;
156       $callback->($dir);
157     };
158   
159   $visit_entry = sub {
160     my $entry = shift;
161     if ($entry->is_dir) { $visit_dir->($entry) } # Will call $callback
162     else { $callback->($entry) }
163   };
164   
165   while (@queue) {
166     $visit_entry->( shift @queue );
167   }
168 }
169
170 sub children {
171   my ($self, %opts) = @_;
172   
173   my $dh = $self->open or Carp::croak( "Can't open directory $self: $!" );
174   
175   my @out;
176   while (my $entry = $dh->read) {
177     # XXX What's the right cross-platform way to do this?
178     next if (!$opts{all} && ($entry eq '.' || $entry eq '..'));
179     push @out, $self->file($entry);
180     $out[-1] = $self->subdir($entry) if -d $out[-1];
181   }
182   return @out;
183 }
184
185 sub next {
186   my $self = shift;
187   unless ($self->{dh}) {
188     $self->{dh} = $self->open or Carp::croak( "Can't open directory $self: $!" );
189   }
190   
191   my $next = $self->{dh}->read;
192   unless (defined $next) {
193     delete $self->{dh};
194     return undef;
195   }
196   
197   # Figure out whether it's a file or directory
198   my $file = $self->file($next);
199   $file = $self->subdir($next) if -d $file;
200   return $file;
201 }
202
203 sub subsumes {
204   my ($self, $other) = @_;
205   die "No second entity given to subsumes()" unless $other;
206   
207   $other = $self->new($other) unless UNIVERSAL::isa($other, __PACKAGE__);
208   $other = $other->dir unless $other->is_dir;
209   
210   if ($self->is_absolute) {
211     $other = $other->absolute;
212   } elsif ($other->is_absolute) {
213     $self = $self->absolute;
214   }
215
216   $self = $self->cleanup;
217   $other = $other->cleanup;
218
219   if ($self->volume) {
220     return 0 unless $other->volume eq $self->volume;
221   }
222
223   # The root dir subsumes everything (but ignore the volume because
224   # we've already checked that)
225   return 1 if "@{$self->{dirs}}" eq "@{$self->new('')->{dirs}}";
226   
227   my $i = 0;
228   while ($i <= $#{ $self->{dirs} }) {
229     return 0 if $i > $#{ $other->{dirs} };
230     return 0 if $self->{dirs}[$i] ne $other->{dirs}[$i];
231     $i++;
232   }
233   return 1;
234 }
235
236 sub contains {
237   my ($self, $other) = @_;
238   return !!(-d $self and (-e $other or -l $other) and $self->subsumes($other));
239 }
240
241 1;
242 __END__
243
244 =head1 NAME
245
246 Path::Class::Dir - Objects representing directories
247
248 =head1 SYNOPSIS
249
250   use Path::Class qw(dir);  # Export a short constructor
251   
252   my $dir = dir('foo', 'bar');       # Path::Class::Dir object
253   my $dir = Path::Class::Dir->new('foo', 'bar');  # Same thing
254   
255   # Stringifies to 'foo/bar' on Unix, 'foo\bar' on Windows, etc.
256   print "dir: $dir\n";
257   
258   if ($dir->is_absolute) { ... }
259   if ($dir->is_relative) { ... }
260   
261   my $v = $dir->volume; # Could be 'C:' on Windows, empty string
262                         # on Unix, 'Macintosh HD:' on Mac OS
263   
264   $dir->cleanup; # Perform logical cleanup of pathname
265   $dir->resolve; # Perform physical cleanup of pathname
266   
267   my $file = $dir->file('file.txt'); # A file in this directory
268   my $subdir = $dir->subdir('george'); # A subdirectory
269   my $parent = $dir->parent; # The parent directory, 'foo'
270   
271   my $abs = $dir->absolute; # Transform to absolute path
272   my $rel = $abs->relative; # Transform to relative path
273   my $rel = $abs->relative('/foo'); # Relative to /foo
274   
275   print $dir->as_foreign('Mac');   # :foo:bar:
276   print $dir->as_foreign('Win32'); #  foo\bar
277
278   # Iterate with IO::Dir methods:
279   my $handle = $dir->open;
280   while (my $file = $handle->read) {
281     $file = $dir->file($file);  # Turn into Path::Class::File object
282     ...
283   }
284   
285   # Iterate with Path::Class methods:
286   while (my $file = $dir->next) {
287     # $file is a Path::Class::File or Path::Class::Dir object
288     ...
289   }
290
291
292 =head1 DESCRIPTION
293
294 The C<Path::Class::Dir> class contains functionality for manipulating
295 directory names in a cross-platform way.
296
297 =head1 METHODS
298
299 =over 4
300
301 =item $dir = Path::Class::Dir->new( <dir1>, <dir2>, ... )
302
303 =item $dir = dir( <dir1>, <dir2>, ... )
304
305 Creates a new C<Path::Class::Dir> object and returns it.  The
306 arguments specify names of directories which will be joined to create
307 a single directory object.  A volume may also be specified as the
308 first argument, or as part of the first argument.  You can use
309 platform-neutral syntax:
310
311   my $dir = dir( 'foo', 'bar', 'baz' );
312
313 or platform-native syntax:
314
315   my $dir = dir( 'foo/bar/baz' );
316
317 or a mixture of the two:
318
319   my $dir = dir( 'foo/bar', 'baz' );
320
321 All three of the above examples create relative paths.  To create an
322 absolute path, either use the platform native syntax for doing so:
323
324   my $dir = dir( '/var/tmp' );
325
326 or use an empty string as the first argument:
327
328   my $dir = dir( '', 'var', 'tmp' );
329
330 If the second form seems awkward, that's somewhat intentional - paths
331 like C</var/tmp> or C<\Windows> aren't cross-platform concepts in the
332 first place (many non-Unix platforms don't have a notion of a "root
333 directory"), so they probably shouldn't appear in your code if you're
334 trying to be cross-platform.  The first form is perfectly natural,
335 because paths like this may come from config files, user input, or
336 whatever.
337
338 As a special case, since it doesn't otherwise mean anything useful and
339 it's convenient to define this way, C<< Path::Class::Dir->new() >> (or
340 C<dir()>) refers to the current directory (C<< File::Spec->curdir >>).
341 To get the current directory as an absolute path, do C<<
342 dir()->absolute >>.
343
344 Finally, as another special case C<dir(undef)> will return undef,
345 since that's usually an accident on the part of the caller, and
346 returning the root directory would be a nasty surprise just asking for
347 trouble a few lines later.
348
349 =item $dir->stringify
350
351 This method is called internally when a C<Path::Class::Dir> object is
352 used in a string context, so the following are equivalent:
353
354   $string = $dir->stringify;
355   $string = "$dir";
356
357 =item $dir->volume
358
359 Returns the volume (e.g. C<C:> on Windows, C<Macintosh HD:> on Mac OS,
360 etc.) of the directory object, if any.  Otherwise, returns the empty
361 string.
362
363 =item $dir->is_dir
364
365 Returns a boolean value indicating whether this object represents a
366 directory.  Not surprisingly, C<Path::Class::File> objects always
367 return false, and C<Path::Class::Dir> objects always return true.
368
369 =item $dir->is_absolute
370
371 Returns true or false depending on whether the directory refers to an
372 absolute path specifier (like C</usr/local> or C<\Windows>).
373
374 =item $dir->is_relative
375
376 Returns true or false depending on whether the directory refers to a
377 relative path specifier (like C<lib/foo> or C<./dir>).
378
379 =item $dir->cleanup
380
381 Performs a logical cleanup of the file path.  For instance:
382
383   my $dir = dir('/foo//baz/./foo')->cleanup;
384   # $dir now represents '/foo/baz/foo';
385
386 =item $dir->resolve
387
388 Performs a physical cleanup of the file path.  For instance:
389
390   my $dir = dir('/foo//baz/../foo')->resolve;
391   # $dir now represents '/foo/foo', assuming no symlinks
392
393 This actually consults the filesystem to verify the validity of the
394 path.
395
396 =item $file = $dir->file( <dir1>, <dir2>, ..., <file> )
397
398 Returns a C<Path::Class::File> object representing an entry in C<$dir>
399 or one of its subdirectories.  Internally, this just calls C<<
400 Path::Class::File->new( @_ ) >>.
401
402 =item $subdir = $dir->subdir( <dir1>, <dir2>, ... )
403
404 Returns a new C<Path::Class::Dir> object representing a subdirectory
405 of C<$dir>.
406
407 =item $parent = $dir->parent
408
409 Returns the parent directory of C<$dir>.  Note that this is the
410 I<logical> parent, not necessarily the physical parent.  It really
411 means we just chop off entries from the end of the directory list
412 until we cain't chop no more.  If the directory is relative, we start
413 using the relative forms of parent directories.
414
415 The following code demonstrates the behavior on absolute and relative
416 directories:
417
418   $dir = dir('/foo/bar');
419   for (1..6) {
420     print "Absolute: $dir\n";
421     $dir = $dir->parent;
422   }
423   
424   $dir = dir('foo/bar');
425   for (1..6) {
426     print "Relative: $dir\n";
427     $dir = $dir->parent;
428   }
429   
430   ########### Output on Unix ################
431   Absolute: /foo/bar
432   Absolute: /foo
433   Absolute: /
434   Absolute: /
435   Absolute: /
436   Absolute: /
437   Relative: foo/bar
438   Relative: foo
439   Relative: .
440   Relative: ..
441   Relative: ../..
442   Relative: ../../..
443
444 =item @list = $dir->children
445
446 Returns a list of C<Path::Class::File> and/or C<Path::Class::Dir>
447 objects listed in this directory, or in scalar context the number of
448 such objects.  Obviously, it is necessary for C<$dir> to
449 exist and be readable in order to find its children.
450
451 Note that the children are returned as subdirectories of C<$dir>,
452 i.e. the children of F<foo> will be F<foo/bar> and F<foo/baz>, not
453 F<bar> and F<baz>.
454
455 Ordinarily C<children()> will not include the I<self> and I<parent>
456 entries C<.> and C<..> (or their equivalents on non-Unix systems),
457 because that's like I'm-my-own-grandpa business.  If you do want all
458 directory entries including these special ones, pass a true value for
459 the C<all> parameter:
460
461   @c = $dir->children(); # Just the children
462   @c = $dir->children(all => 1); # All entries
463
464 =item $abs = $dir->absolute
465
466 Returns a C<Path::Class::Dir> object representing C<$dir> as an
467 absolute path.  An optional argument, given as either a string or a
468 C<Path::Class::Dir> object, specifies the directory to use as the base
469 of relativity - otherwise the current working directory will be used.
470
471 =item $rel = $dir->relative
472
473 Returns a C<Path::Class::Dir> object representing C<$dir> as a
474 relative path.  An optional argument, given as either a string or a
475 C<Path::Class::Dir> object, specifies the directory to use as the base
476 of relativity - otherwise the current working directory will be used.
477
478 =item $boolean = $dir->subsumes($other)
479
480 Returns true if this directory spec subsumes the other spec, and false
481 otherwise.  Think of "subsumes" as "contains", but we only look at the
482 I<specs>, not whether C<$dir> actually contains C<$other> on the
483 filesystem.
484
485 The C<$other> argument may be a C<Path::Class::Dir> object, a
486 C<Path::Class::File> object, or a string.  In the latter case, we
487 assume it's a directory.
488
489   # Examples:
490   dir('foo/bar' )->subsumes(dir('foo/bar/baz'))  # True
491   dir('/foo/bar')->subsumes(dir('/foo/bar/baz')) # True
492   dir('foo/bar' )->subsumes(dir('bar/baz'))      # False
493   dir('/foo/bar')->subsumes(dir('foo/bar'))      # False
494
495
496 =item $boolean = $dir->contains($other)
497
498 Returns true if this directory actually contains C<$other> on the
499 filesystem.  C<$other> doesn't have to be a direct child of C<$dir>,
500 it just has to be subsumed.
501
502 =item $foreign = $dir->as_foreign($type)
503
504 Returns a C<Path::Class::Dir> object representing C<$dir> as it would
505 be specified on a system of type C<$type>.  Known types include
506 C<Unix>, C<Win32>, C<Mac>, C<VMS>, and C<OS2>, i.e. anything for which
507 there is a subclass of C<File::Spec>.
508
509 Any generated objects (subdirectories, files, parents, etc.) will also
510 retain this type.
511
512 =item $foreign = Path::Class::Dir->new_foreign($type, @args)
513
514 Returns a C<Path::Class::Dir> object representing C<$dir> as it would
515 be specified on a system of type C<$type>.  Known types include
516 C<Unix>, C<Win32>, C<Mac>, C<VMS>, and C<OS2>, i.e. anything for which
517 there is a subclass of C<File::Spec>.
518
519 The arguments in C<@args> are the same as they would be specified in
520 C<new()>.
521
522 =item @list = $dir->dir_list([OFFSET, [LENGTH]])
523
524 Returns the list of strings internally representing this directory
525 structure.  Each successive member of the list is understood to be an
526 entry in its predecessor's directory list.  By contract, C<<
527 Path::Class->new( $dir->dir_list ) >> should be equivalent to C<$dir>.
528
529 The semantics of this method are similar to Perl's C<splice> or
530 C<substr> functions; they return C<LENGTH> elements starting at
531 C<OFFSET>.  If C<LENGTH> is omitted, returns all the elements starting
532 at C<OFFSET> up to the end of the list.  If C<LENGTH> is negative,
533 returns the elements from C<OFFSET> onward except for C<-LENGTH>
534 elements at the end.  If C<OFFSET> is negative, it counts backward
535 C<OFFSET> elements from the end of the list.  If C<OFFSET> and
536 C<LENGTH> are both omitted, the entire list is returned.
537
538 In a scalar context, C<dir_list()> with no arguments returns the
539 number of entries in the directory list; C<dir_list(OFFSET)> returns
540 the single element at that offset; C<dir_list(OFFSET, LENGTH)> returns
541 the final element that would have been returned in a list context.
542
543 =item $fh = $dir->open()
544
545 Passes C<$dir> to C<< IO::Dir->open >> and returns the result as an
546 C<IO::Dir> object.  If the opening fails, C<undef> is returned and
547 C<$!> is set.
548
549 =item $dir->mkpath($verbose, $mode)
550
551 Passes all arguments, including C<$dir>, to C<< File::Path::mkpath()
552 >> and returns the result (a list of all directories created).
553
554 =item $dir->rmtree($verbose, $cautious)
555
556 Passes all arguments, including C<$dir>, to C<< File::Path::rmtree()
557 >> and returns the result (the number of files successfully deleted).
558
559 =item $dir->remove()
560
561 Removes the directory, which must be empty.  Returns a boolean value
562 indicating whether or not the directory was successfully removed.
563 This method is mainly provided for consistency with
564 C<Path::Class::File>'s C<remove()> method.
565
566 =item $dir_or_file = $dir->next()
567
568 A convenient way to iterate through directory contents.  The first
569 time C<next()> is called, it will C<open()> the directory and read the
570 first item from it, returning the result as a C<Path::Class::Dir> or
571 C<Path::Class::File> object (depending, of course, on its actual
572 type).  Each subsequent call to C<next()> will simply iterate over the
573 directory's contents, until there are no more items in the directory,
574 and then the undefined value is returned.  For example, to iterate
575 over all the regular files in a directory:
576
577   while (my $file = $dir->next) {
578     next unless -f $file;
579     my $fh = $file->open('r') or die "Can't read $file: $!";
580     ...
581   }
582
583 If an error occurs when opening the directory (for instance, it
584 doesn't exist or isn't readable), C<next()> will throw an exception
585 with the value of C<$!>.
586
587 =item $dir->recurse( callback => sub {...} )
588
589 Iterates through this directory and all of its children, and all of
590 its children's children, etc., calling the C<callback> subroutine for
591 each entry.  This is a lot like what the C<File::Find> module does,
592 and of course C<File::Find> will work fine on C<Path::Class> objects,
593 but the advantage of the C<recurse()> method is that it will also feed
594 your callback routine C<Path::Class> objects rather than just pathname
595 strings.
596
597 The C<recurse()> method requires a C<callback> parameter specifying
598 the subroutine to invoke for each entry.  It will be passed the
599 C<Path::Class> object as its first argument.
600
601 C<recurse()> also accepts two boolean parameters, C<depthfirst> and
602 C<preorder> that control the order of recursion.  The default is a
603 preorder, breadth-first search, i.e. C<< depthfirst => 0, preorder => 1 >>.
604 At the time of this writing, all combinations of these two parameters
605 are supported I<except> C<< depthfirst => 0, preorder => 0 >>.
606
607 =item $st = $file->stat()
608
609 Invokes C<< File::stat::stat() >> on this directory and returns a
610 C<File::stat> object representing the result.
611
612 =item $st = $file->lstat()
613
614 Same as C<stat()>, but if C<$file> is a symbolic link, C<lstat()>
615 stats the link instead of the directory the link points to.
616
617 =back
618
619 =head1 AUTHOR
620
621 Ken Williams, ken@mathforum.org
622
623 =head1 SEE ALSO
624
625 Path::Class, Path::Class::File, File::Spec
626
627 =cut