File Coverage

lib/Badger/Filesystem/Path.pm
Criterion Covered Total %
statement 99 132 75.0
branch 42 58 72.4
condition 23 61 37.7
subroutine 28 38 73.6
pod 31 31 100.0
total 223 320 69.6


line stmt bran cond sub pod time code
1             #========================================================================
2             #
3             # Badger::Filesystem::Path
4             #
5             # DESCRIPTION
6             # OO representation of a path in a filesystem, serving as a base class
7             # for file and directories.
8             #
9             # AUTHOR
10             # Andy Wardley
11             #
12             #========================================================================
13              
14             package Badger::Filesystem::Path;
15              
16 70     70   412 use File::Spec;
  70         118  
  70         4744  
17             use Badger::Class
18 70         1052 version => 0.01,
19             debug => 0,
20             base => 'Badger::Filesystem::Base Badger::Exporter',
21             import => 'class',
22             constants => 'HASH ARRAY TRUE',
23             get_methods => 'path name volume directory',
24             utils => 'blessed',
25             as_text => 'path',
26             is_true => 1,
27             constant => {
28             type => 'Path',
29             STAT_PATH => 17, # offset in extended stat fields
30             },
31             exports => {
32             tags => { fields => '@STAT_FIELDS' },
33             },
34             messages => {
35             no_exist => '%s does not exist: %s',
36             bad_stat => '%s cannot be scanned: %s',
37             bad_look => 'No path specified to look %s',
38             missing => 'No %s specified',
39 70     70   398 };
  70         174  
40              
41 70     70   35890 use Badger::Timestamp;
  70         188  
  70         819  
42 70     70   1003 use Badger::Filesystem;
  70         137  
  70         768  
43 70     70   31110 use Badger::Filesystem::Directory;
  70         147  
  70         800  
44              
45              
46             our $FILESYSTEM = 'Badger::Filesystem';
47             our $TIMESTAMP = 'Badger::Timestamp';
48             our $MATCH_EXT = qr/\.([^\.]+)$/; # TODO: is this filesystem-specific?
49             our @VDN_FIELDS = @Badger::Filesystem::Base::VDN_FIELDS;
50             our @STAT_FIELDS = qw( device inode mode links user group device_type
51             size atime mtime ctime block_size blocks
52             readable writeable executable owner );
53             our $STAT_FIELD = {
54             # In here we'll store the map from stat field name to number
55             # device => 0,
56             # inode => 1,
57             # ...etc...
58             };
59              
60             our $TS_FIELD = {
61             # On the left we have the timestamp methods we want to generate as
62             # wrappers around the stat fields listed on the right.
63             created => 'ctime',
64             accessed => 'atime',
65             modified => 'mtime',
66             };
67              
68             # generate methods to access stat fields: mode(), atime(), ctime(), etc.
69             my $n = 0;
70              
71             class->methods(
72             map {
73             my $m = $n++; # new lexical variable for closure
74             $STAT_FIELD->{ $_ } = $m; # fill in $STAT_FIELD entry
75 56     56   283 $_ => sub { $_[0]->stats->[$m] } # generate subroutine
76             }
77             @STAT_FIELDS
78             );
79              
80             # generate accessed(), created() and modified() methods which return
81             # Badger::Timestamp objects for the atime, ctime and mtime stat values
82              
83             class->methods(
84             map {
85             my $method = $_; # new lexical variable for closure
86             my $stat = $TS_FIELD->{ $_ };
87             my $statno = $STAT_FIELD->{ $stat };
88             $method => sub {
89 3   33 3   22 return $_[0]->{ $method }
90             ||= $TIMESTAMP->new( $_[0]->stats->[$statno] )
91             }
92             }
93             keys %$TS_FIELD
94             );
95              
96              
97             # define some aliases
98             *is_dir = \&is_directory;
99             *dir = \&directory;
100             *vol = \&volume; # goes up to 11
101             *ext = \&extension;
102             *base_name = \&basename;
103             *up = \&parent;
104             *meta = \&metadata;
105             *canonical = \&absolute;
106             *perms = \&permissions;
107              
108              
109             sub new {
110 566   66 566 1 713 my $class = shift; $class = ref $class || $class;
  566         1244  
111 566         594 my $args;
112              
113 566 100       830 if (@_ == 1) {
114 559 50 66     976 $args = ref $_[0] eq HASH ? shift
    100          
115             : ref $_[0] eq ARRAY || ! ref $_[0] ? { path => shift }
116             : return $class->error_msg( unexpected => arguments => $_[0] => 'hash ref' )
117             }
118             else {
119 7         15 $args = { @_ };
120             }
121              
122             # allow short aliases for various configuration options, including
123             # those of directory/file subclasses to make life easy for them.
124 566 50 0     911 $args->{ filesystem } ||= $args->{ fs } if $args->{ fs };
125 566 100 33     860 $args->{ directory } ||= $args->{ dir } if $args->{ dir };
126 566 50 0     774 $args->{ volume } ||= $args->{ vol } if $args->{ vol };
127 566         819 my $self = bless { }, $class;
128              
129             # maintain a reference to the filesystem that created us, if available,
130             # but don't bother if we didn't get one - we can use the default
131 566 100       2957 $self->{ filesystem } = $args->{ filesystem } if $args->{ filesystem };
132 566         1232 $self->init($args);
133             }
134              
135             sub init {
136 33     33 1 52 my ($self, $config) = @_;
137 33   50     65 my $path = $config->{ path } || return $self->error_msg( missing => 'path' );
138 33         46 my $fs = $self->filesystem;
139 33         91 $path = $self->{ path } = $fs->join_directory($path);
140 33         184 return $self;
141             }
142              
143             sub is_absolute {
144 29     29 1 53 my $self = shift;
145             $self->{ absolute } = $self->filesystem->is_absolute($self->{ path })
146 29 100       110 unless defined $self->{ absolute };
147 29         178 return $self->{ absolute };
148             }
149              
150             sub is_relative {
151 2 100   2 1 12 shift->is_absolute ? 0 : 1;
152             }
153              
154             sub is_file {
155 0     0 1 0 my $self = shift;
156 0   0     0 my $defn = $self->filesystem->definitive_read($self->{ path }) || return;
157 0         0 return -f $defn;
158             }
159              
160             sub is_directory {
161 0     0 1 0 my $self = shift;
162 0   0     0 my $defn = $self->filesystem->definitive_read($self->{ path }) || return;
163 0         0 return -d $defn;
164             }
165              
166             sub absolute {
167 21     21 1 63 my $self = shift;
168             return $self->is_absolute
169             ? $self->{ path }
170 21 100       73 : $self->filesystem->absolute($self->{ path });
171             }
172              
173             sub relative {
174 78     78 1 116 my $self = shift;
175 78         153 my $fs = $self->filesystem;
176 78         218 my $path = $fs->join_directory(@_);
177             # If the path isn't already absolute then we merge it onto our
178             # directory or path if directory is undefined. By calling the
179             # base() method, we allow the file subclass to return its
180             # parent directory so that things Just Work[tm]
181             # $self->debug("relative path: $path is_absolute?\n");
182 78 100       201 return $fs->is_absolute($path)
183             ? $path
184             : $fs->collapse_directory( $fs->join_directory($self->base, $path) );
185             }
186              
187             sub definitive {
188 4     4 1 17 my $self = shift;
189             # use the definitive path from the last stat or fetch anew
190             return
191             ($self->{ stats } && $self->{ stats }->[STAT_PATH])
192 4   33     46 || $self->filesystem->definitive($self->{ path });
193             }
194              
195             sub collapse {
196 0     0 1 0 my $self = shift;
197 0         0 my $fs = $self->filesystem;
198 0         0 $self->{ directory } = $fs->collapse_directory( $self->{ directory } );
199 0         0 $self->{ path } = $fs->join_path( @$self{ @VDN_FIELDS } );
200 0         0 return $self;
201             }
202              
203             sub above {
204 0     0 1 0 my $self = shift;
205 0         0 my $this = quotemeta $self->collapse->path;
206 0   0     0 my $that = shift || return $self->error_msg( bad_look => 'above' );
207 0 0 0     0 $that = $self->new("$that") unless blessed $that && $that->isa(__PACKAGE__);
208 0         0 $that = $that->collapse->path;
209 0 0       0 $self->debug("does $that match /^$this/ ??\n") if $DEBUG;
210 0         0 $that =~ /^$this/;
211             }
212              
213             sub below {
214 0     0 1 0 my $self = shift;
215 0   0     0 my $that = shift || return $self->error_msg( bad_look => 'above' );
216 0 0 0     0 $that = $self->new("$that") unless blessed $that && $that->isa(__PACKAGE__);
217 0         0 $that->above($self);
218             }
219              
220             sub base {
221 3     3 1 5 my $self = shift;
222 3   33     13 return $self->{ directory } || $self->{ path };
223             }
224              
225             sub parent {
226 85     85 1 107 my $self = shift;
227 85   100     148 my $skip = shift || 0;
228             my $parent = $self->{ parent }
229             ||= $self->filesystem->directory(
230 85   66     186 $self->{ directory } ||= $self->path_up
      66        
231             );
232              
233             return
234             # don't return parents above the root
235 85 100       346 $self->{ path } eq $parent->{ path } ? $self
    100          
236             # delegate to parent if there are generations to skip
237             : $skip ? $parent->parent($skip - 1)
238             # otherwise we've found the parent we're looking for
239             : $parent;
240             }
241              
242             sub path_up {
243 20     20 1 22 my $self = shift;
244 20         25 my $fs = $self->filesystem;
245 20         39 my $path = $fs->split_directory($self->{ path });
246              
247 20 50       35 $self->debug("split path [$path] into [", join(', ', @$path), "]\n")
248             if $DEBUG;
249              
250 20 100       33 if (@$path > 1) {
    50          
251             # multiple items in path can be relative or absolute - we're not
252             # fussed. e.g. /foo/bar ==> /foo or foo/bar ==> foo
253 17         20 pop(@$path);
254             }
255             elsif (@$path == 1) {
256             # if there's a single item in a path then it's either a single
257             # relative path item (e.g. 'foo' ==> ['foo']), in which case we
258             # return the current working directory, or it's an empty item
259             # indicating the root directory (e.g. '/' => ['']) in which case we
260             # do nothing, because you can't go up from the root directory.
261 3 50       8 if (length $path->[0]) {
262 3         55 return $fs->cwd;
263             }
264 0         0 $self->not_implemented("going up from relative paths");
265             }
266             else {
267 0         0 $self->error("Invalid path (no elements)\n");
268             }
269              
270 17         31 return $fs->join_directory($path);
271             }
272              
273             sub exists {
274 0     0 1 0 shift->stat;
275             }
276              
277             sub must_exist {
278 69     69 1 105 my $self = shift;
279              
280 69 100       138 unless ($self->exists) {
281 4 50 33     29 if (@_ && $_[0]) {
282 4         9 my $flag = shift;
283             # true flag indicates we should attempt to create it
284 4         18 $self->create(@_); # pass any other args, like dir file permission
285             }
286             else {
287 0         0 return $self->error_msg( no_exist => $self->type, $self->{ path } );
288             }
289             }
290 69         192 return $self;
291             }
292              
293             sub create {
294 0     0 1 0 shift->not_implemented;
295             }
296              
297             sub stat {
298 38     38 1 63 my $self = shift->must_exist;
299             my $stats = $self->filesystem->stat_path($self->{ path })
300 38   50     72 || return $self->decline_msg( not_found => file => $self->{ path } );
301              
302             # the definitive path can be tagged on the end
303             # $self->{ definitive } = $stats->[STAT_PATH]
304             # if defined $stats->[STAT_PATH];
305              
306             return wantarray
307 38 50       125 ? @$stats
308             : $stats;
309             }
310              
311             sub stats {
312 59   66 59 1 138 my $stats = $_[0]->{ stats } ||= $_[0]->stat;
313             return wantarray
314 59 50       227 ? @$stats
315             : $stats;
316             }
317              
318             sub restat {
319 0     0 1 0 my $self = shift;
320 0         0 delete $self->{ stats };
321 0         0 delete @$self{ keys %$TS_FIELD }; # timestamps for created, modified, etc.
322 0         0 return $self->stats;
323             }
324              
325             sub permissions {
326 1     1 1 3 shift->mode & 0777;
327             }
328              
329             sub chmod {
330 1     1 1 2 my $self = shift;
331 1         3 $self->filesystem->chmod_path($self->{ path }, @_);
332 1         4 return $self;
333             }
334              
335             sub basename {
336 3     3 1 6 my $self = shift;
337 3         10 my $name = $self->name;
338 3 100       11 $name = $self->{ path } unless defined $name;
339 3         38 $name =~ s/$MATCH_EXT//g;
340 3         13 return $name;
341             }
342              
343             sub extension {
344 2     2 1 4 my $self = shift;
345 2 50       24 return $self->{ path } =~ $MATCH_EXT
346             ? $1
347             : '';
348             }
349              
350             sub filesystem {
351 1150     1150 1 1177 my $self = shift;
352 1150 100       1785 return $self->class->any_var('FILESYSTEM')->prototype
353             unless ref $self;
354             $self->{ filesystem }
355 1149   66     3346 ||= $self->class->any_var('FILESYSTEM')->prototype;
356             }
357              
358             sub visit {
359 14     14 1 39 my $self = shift;
360 14         21 my $visitor = $self->filesystem->visitor(@_);
361 14         30 $visitor->visit($self);
362 14         38 return $visitor;
363             }
364              
365             sub collect {
366 2     2 1 6 shift->visit(@_)->collect;
367             }
368              
369             sub enter {
370             # enter() is a custom accept() method for the entry point of a visitor
371 0     0 1 0 shift->accept;
372             }
373              
374             sub accept {
375 0     0 1 0 $_[1]->visit_path($_[0]);
376             }
377              
378             sub metadata {
379 3     3 1 10 my $self = shift;
380 3   100     10 my $meta = $self->{ metadata } ||= { };
381 3 100       12 if (@_ == 1) {
    100          
382 1         5 return $meta->{ $_[0] };
383             }
384             elsif (@_ > 1) {
385 1         4 while (@_) {
386 1         2 my $key = shift;
387 1         4 $meta->{ $key } = shift;
388             }
389             }
390 2         9 return $meta;
391             }
392              
393             1;
394              
395             =encoding utf8
396              
397             =head1 NAME
398              
399             Badger::Filesystem::Path - generic fileystem path object
400              
401             =head1 SYNOPSIS
402              
403             # using Badger::Filesytem constructor subroutine
404             use Badger::Filesystem 'Path';
405              
406             # use native OS-specific paths:
407             $path = Path('/path/to/something');
408              
409             # or generic OS-independant paths
410             $path = Path('path', 'to', 'something');
411              
412             # manual object construction
413             use Badger::Filesystem::Path;
414              
415             # positional arguments
416             $path = Badger::Filesystem::Path->new('/path/to/something');
417             $path = Badger::Filesystem::Path->new(['path', 'to', 'something']);
418              
419             # named parameters
420             $path = Badger::Filesystem::Path->new(
421             path => '/path/to/something'
422             );
423             $path = Badger::Filesystem::Path->new(
424             path => ['path', 'to', 'something']
425             );
426              
427             # path inspection methods
428             $path->path; # current path
429             $path->base; # parent directory or path itself
430             $path->parent; # directory object for base
431             $path->extension # filename .XXX extension
432             $path->basename # filename without .XXX extension
433             $path->is_absolute; # path is absolute
434             $path->is_relative; # path is relative
435             $path->exists; # returns true/false
436             $path->must_exist; # throws error if not
437             @stats = $path->stat; # returns list
438             $stats = $path->stat; # returns list ref
439              
440             # path translation methods
441             $path->relative; # relative to cwd
442             $path->relative($base); # relative to $base
443             $path->absolute; # relative to filesystem root
444             $path->definitive; # physical file location
445             $path->collapse; # resolve '.' and '..' in $path
446              
447             # path comparison methods
448             $path->above($another_path); # $path is ancestor of $another_path
449             $path->below($another_path); # $path is descendant of $another_path
450              
451             =head1 INTRODUCTION
452              
453             This is the documentation for the C module.
454             It defines a base class object for the L and
455             L objects which inherit (and in some cases
456             redefine) the methods described below.
457              
458             In other words, you should read this documentation first if you're working
459             with L or L objects.
460              
461             =head1 DESCRIPTION
462              
463             The C module defines a base class object for
464             representing paths in a real or virtual file system.
465              
466             You can create a generic path object (e.g. to represent a path that doesn't
467             relate to a specific file or directory in a file system), using the C
468             constructor method in L.
469              
470             use Badger::Filesystem 'Path';
471              
472             my $path = Path('/path/to/something');
473              
474             However in most cases you'll want to create a file or directory subclass
475             object. The easiest way to do that is like this:
476              
477             use Badger::Filesystem 'File Path';
478              
479             my $file = File('/path/to/file');
480             my $dir = Dir('/path/to/dir');
481              
482             If you're concerned about portability to other operating systems and/or
483             file systems, then you can specify paths as a list or reference to a list
484             of component names.
485              
486             my $file = File('path', 'to', 'file');
487             my $dir = Dir(['path', 'to', 'dir']);
488              
489             =head1 METHODS
490              
491             =head2 new($path)
492              
493             Constructor method to create a new C object.
494             The path can be specified as a single positional argument, either as a
495             text string or reference to list of path components.
496              
497             # single text string
498             $path = Badger::Filesystem::Path->new('/path/to/something');
499              
500             # reference to list
501             $path = Badger::Filesystem::Path->new(['path', 'to', 'something']);
502              
503             It can also be specified as a C named parameter.
504              
505             # named parameter list
506             $path = Badger::Filesystem::Path->new(
507             path => '/path/to/something'
508             );
509              
510             # reference to hash of named parameter(s)
511             $path = Badger::Filesystem::Path->new({
512             path => '/path/to/something'
513             });
514              
515             The constructor method also recognises the C named parameter which
516             can contain a reference to the L object or class that
517             created it. In most cases you can rely on the L to create
518             path objects for you, using either the L
519             method, or the L subroutine.
520              
521             use Badger::Filesystem 'FS Path';
522              
523             # FS is alias for 'Badger::Filesystem'
524             # Path() is constructor subrooutine
525             my $path;
526              
527             # using the path() method
528             $path = FS->path('/path/to/something');
529             $path = FS->path('path', 'to', 'something');
530             $path = FS->path(['path', 'to', 'something']);
531              
532             # using the Path() subroutine
533             $path = Path('/path/to/something');
534             $path = Path('path', 'to', 'something');
535             $path = Path(['path', 'to', 'something']);
536              
537             The examples that follow will use the C constructor subroutine.
538              
539             =head2 init(\%config)
540              
541             Default initialisation method which subclasses (e.g.
542             L and L) can
543             redefine.
544              
545             =head2 path()
546              
547             This method returns the path as a text string. It is called automatically
548             whenever the path object is stringified.
549              
550             =head2 is_absolute()
551              
552             Returns true if the path is absolute, false if not.
553              
554             =head2 is_relative()
555              
556             Returns true if the path is relative, false if not.
557              
558             =head2 absolute($base)
559              
560             Returns an absolute representation of the path, relative to the C<$base>
561             path passed as an argument, or the current working directory if C<$base>
562             is not specified.
563              
564             # assume cwd is /foo/bar,
565             my $path = Path('/baz/bam');
566              
567             print $path->absolute; # /foo/bar/baz/bam
568             print $path->absolute('/wiz'); # /wiz/baz/bam
569              
570             =head2 relative($base)
571              
572             Returns a relative representation of the path, relative to the C<$base>
573             path passed as an argument, or the current working directory if C<$base>
574             is not specified.
575              
576             # assume cwd is /foo/bar,
577             my $path = Path('/foo/bar/baz/bam');
578              
579             print $path->relative; # /baz/bam
580             print $path->relative('/foo'); # /bar/baz/bam
581              
582             =head2 definitive()
583              
584             Returns the definitive representation of the path which in most cases will
585             be the same as the L path.
586              
587             However, if you're using a L,
588             then the I path I include the virtual root directory,
589             whereas a the I path will I.
590              
591             my $vfs = Badger::Filesystem::Virtual->new( root => '/my/vfs' );
592             my $path = $vfs->file('/foo/bar');
593             print $path->absolute; # /foo/bar
594             print $path->definitive; # /my/vfs/foo/bar
595              
596             =head2 canonical()
597              
598             This method returns the canonical representation of the path. In most cases
599             this is the same as the absolute path (in fact the base class aliases the
600             C method directly to the L method).
601              
602             print Path('foo')->canonical; # /your/current/path/foo
603             print Path('/foo/bar')->canonical; # /foo/bar
604             print Path('/foo/bar/')->canonical; # /foo/bar
605             print Path('/foo/bar.txt')->canonical; # /foo/bar.txt
606              
607             Note that the C base class will I any
608             trailing slashes (or whatever the appropriate directory separator is for your
609             filesystem) from the end of an absolute path.
610              
611             In the case of directories, implemented by the
612             L subclass, a trailing slash (or relevant
613             separator for your filesystem) will be added.
614              
615             print Dir('/foo/bar')->canonical; # /foo/bar/
616              
617             This is done by delegation to the
618             L method in
619             L.
620              
621             =head2 collapse()
622              
623             Reduces the path to its simplest form by resolving and removing any C<.>
624             (current directory) and C<..> (parent directory) components (or whatever the
625             corresponding tokens are for the current and parent directories of your
626             filesystem).
627              
628             my $path = Path('/foo/bar/../baz')->collapse;
629             print $path; # /foo/baz
630              
631             See the L method in
632             L for further information.
633              
634             =head2 above($child)
635              
636             Returns true if the path is "above" the C<$child> path passed as an argument.
637             Formally, we say that the path is an I of C<$child> meaning that it
638             is the parent directory, or grand-parent, or great-grand-parent, and so on.
639              
640             my $parent = Path('/foo/bar');
641             my $child = Path('/foo/bar/baz');
642             $parent->above($child); # true
643              
644             This is implemented as a simple prefix match. That is, the parent path must
645             appear at the start of the child path. Consequently, this method will not
646             account for symbolic links or other similar filesystem features, and it may
647             not work properly on systems that don't follow this convention (although there
648             are none that I'm aware of).
649              
650             =head2 below($parent)
651              
652             Returns true if the path is "below" the C<$parent> path passed as an argument.
653             Formally, we say that the path is a I of C<$parent> meaning that it
654             is an immediate sub-directory, or sub-sub-directory, and so on.
655              
656             my $parent = Path('/foo/bar');
657             my $child = Path('/foo/bar/baz');
658             $child->below($parent); # true
659              
660             Like L, this is implemented using a simple prefix match.
661              
662             =head2 base()
663              
664             Returns the base directory of a path. For L and
665             L objects, this method will return the complete
666             path.
667              
668             print Path('/foo/bar')->base; # /foo/bar
669             print Directory('/foo/bar')->base; # /foo/bar
670              
671             However the L module returns the parent directory in
672             which the file is located.
673              
674             print File('/foo/bar')->base; # /foo
675              
676             =head2 parent($skip_generations) / up($skip_generations)
677              
678             Returns a L object representing the parent
679             directory for a path.
680              
681             Path->('/foo/bar')->parent; # path object for /foo
682              
683             A numerical argument can be provided to indicate the number of generation
684             you want to skip. A value of C<0> is the same as providing no argument - it
685             returns the parent. A value of C<1> skips the parent and returns the
686             grand-parent, and so on.
687              
688             Path->('/foo/bar/baz/bam')->parent(2); # path object for /foo
689              
690             The root directory will be returned if you try to skip too many generations.
691              
692             Path->('/foo/bar/baz/bam')->parent(20); # path object for /
693              
694             =head2 path_up()
695              
696             This returns a text string representing the parent of a path. If the path
697             contains multiple items (e.g. '/foo/bar' or 'foo/bar') then the last item
698             will be removed (e.g. resulting in '/foo' or 'foo' respectively). If an
699             absolute path contains one item or none (e.g. '/foo' or '/') then the
700             root directory ('/') will be returned. A relative path with only one item
701             (e.g. 'foo') is assumed to be relative to the current working directory
702             which will be returned (e.g. '/path/to/current/dir').
703              
704             =head2 exists()
705              
706             Returns true if the path exists in the filesystem (e.g. as a file, directory,
707             or some other entry), or false if not.
708              
709             if ($path->exists) {
710             print "$path already exists\n";
711             }
712             else {
713             print "Creating $path\n";
714             # ...etc...
715             }
716              
717             =head2 must_exist($create)
718              
719             Checks that the path exists (by calling L) and throws an error
720             if it doesn't.
721              
722             $path->must_exist; # no need to check return value
723              
724             The C<$create> flag can be set to have it attempt to L itself if it
725             doesn't already exist. However, this only makes sense for file and directory
726             subclasses and not base class paths.
727              
728             $dir->must_exist(1); # create if it doesn't
729              
730             =head2 create()
731              
732             In the base class this will method will throw an error. You can't physically
733             create an abstract path unless you know what kind of concrete entity (e.g.
734             file or directory) it maps onto. In other words, the L method will
735             only work for the L and
736             L subclasses.
737              
738             $path->create; # FAIL
739             $dir->create; # OK
740             $file->create; # OK
741              
742             =head2 chmod($perms)
743              
744             This method changes the file permissions on a file or directory.
745              
746             $file->chmod(0775);
747              
748             =head2 stat()
749              
750             Performs a filesystem C on the path and returns a list (in list
751             context), or a reference to a list (in scalar context) containing the 13
752             information elements.
753              
754             @list = $path->stat; # list context
755             $list = $path->stat; # scalar context
756              
757             A summary of the fields is shown below. See C for complete
758             details. Each of the individual fields can also be accessed via their own
759             methods, also listed in the table.
760              
761             Field Method Description
762             ------------------------------------------------------------------------
763             0 device() device number of filesystem
764             1 inoode() inode number
765             2 mode() file mode (type and permissions)
766             3 links() number of (hard) links to the file
767             4 user() numeric user ID of file’s owner
768             5 group() numeric group ID of file’s owner
769             6 device_type() the device identifier (special files only)
770             7 size() total size of file, in bytes
771             8 atime() last access time in seconds since the epoch
772             9 mtime() last modify time in seconds since the epoch
773             10 ctime() inode change time in seconds since the epoch (*)
774             11 block_size() preferred block size for file system I/O
775             12 blocks() actual number of blocks allocated
776              
777             In addition to those that are returned by Perl's inbuilt C function,
778             this method returns four additional flags.
779              
780             13 readable() file is readable by current process
781             14 writeable() file is writeable by current process
782             15 executable() file is executable by current process
783             16 owner() file is owned by current process
784              
785             =head2 stats()
786              
787             A wrapper around the L method which caches the results to avoid
788             making repeated filesystem calls.
789              
790             @list = $path->stats; # list context
791             $list = $path->stats; # scalar context
792              
793             Note that the L, L and L methods also
794             cache the L objects they create to represent the
795             access, creation and modification times respectively.
796              
797             =head2 restat()
798              
799             Clears any cached values stored by the L, L,
800             L and L methods and calls L to reload
801             (and re-cache) the data from a L call.
802              
803             =head2 device()
804              
805             Returns the device number for the file. See L.
806              
807             =head2 inode()
808              
809             Returns the inode number for the file. See L.
810              
811             =head2 mode()
812              
813             Returns the file mode for the file. Note that this contains both the
814             file type and permissions. See L.
815              
816             =head2 permissions() / perms()
817              
818             Returns the file permissions. This is equivalent to
819             C<< $file->mode & 0777 >>.
820              
821             =head2 links()
822              
823             Returns the number of hard links to the file. See L.
824              
825             =head2 user()
826              
827             Returns the numeric user ID of the file's owner. See L.
828              
829             =head2 group()
830              
831             Returns the numeric group ID of the file's group. See L.
832              
833             =head2 device_type()
834              
835             Returns the device identifier (for special files only). See L.
836              
837             =head2 size()
838              
839             Returns the total size of the file in bytes. See L.
840              
841             =head2 atime()
842              
843             Returns the time (in seconds since the epoch) that the file was last accessed.
844             See L.
845              
846             =head2 accessed()
847              
848             Returns a L object for the L value. This object
849             will auto-stringify to produce an ISO-8601 formatted date. You can also
850             call various methods to access different parts of the time and/or date.
851              
852             print $file->accessed; # 2009/04/20 16:25:00
853             print $file->accessed->date; # 2009/04/20
854             print $file->accessed->year; # 2009
855              
856             =head2 mtime()
857              
858             Returns the time (in seconds since the epoch) that the file was last modified.
859             See L.
860              
861             =head2 modified()
862              
863             Returns a L object for the L value.
864              
865             print $file->modified; # 2009/04/20 16:25:00
866             print $file->modified->time; # 16:25:0
867             print $file->modified->hour; # 16
868              
869             =head2 ctime()
870              
871             Returns the time (in seconds since the epoch) that the file was created. See
872             L.
873              
874             =head2 created()
875              
876             Returns a L object for the L value.
877              
878             print $file->created; # 2009/04/20 16:25:00
879             print $file->created->date; # 2009/04/20
880             print $file->created->time; # 16:25:00
881              
882             =head2 block_size()
883              
884             Returns the preferred block size for file system I/O on the file. See
885             L.
886              
887             =head2 blocks()
888              
889             Returns the actual number of blocks allocated to the file. See L.
890              
891             =head2 readable()
892              
893             Returns a true value if the file is readable by the current user (i.e. the
894             owner of the current process), false if not. See L.
895              
896             =head2 writeable()
897              
898             Returns a true value if the file is writeable by the current user (i.e. the
899             owner of the current process), false if not. See L.
900              
901             =head2 executable()
902              
903             Returns a true value if the file is executable by the current user (i.e. the
904             owner of the current process), false if not. See L.
905              
906             =head2 owner()
907              
908             Returns a true value if the file is owned by the current user (i.e. the
909             owner of the current process), false if not. See L.
910              
911             =head2 filesystem()
912              
913             Returns a reference to a L object, or the name of the
914             filesystem class (e.g. L or a subclass) that created
915             the path object. If this is undefined then the default value defined in
916             the L<$FILESYSTEM> class variable is returned. Unless you've changed it,
917             or re-defined it in a subclass, this value will be C.
918              
919             The end result is that you can use the C method to access a
920             L object or class through which you can perform other
921             filesystem related operations. This is used internally by a number of
922             method.
923              
924             # access filesystem via existing path
925             $path->filesystem->dir('/a/new/directory/object');
926              
927             # same as
928             Badger::Filesystem->dir('/a/new/directory/object');
929              
930             =head2 visit($visitor)
931              
932             Entry point for a filesystem visitor to visit a filesystem path. A
933             reference to a L object (or subclass) should
934             be passed as the first argument.
935              
936             use Badger::Filesystem::Visitor;
937              
938             my $visitor = Badger::Filesystem::Visitor->new( recurse => 1 );
939             $path->visit($visitor);
940              
941             Alternately, a list or reference to a hash array of named parameters may be
942             provided. These will be used to instantiate a new
943             L object (via the L
944             L method) which will then be
945             applied to the path. If no arguments are passed then a visitor is created
946             with a default configuration.
947              
948             # either list of named params
949             $path->visit( recurse => 1 );
950              
951             # or reference to hash array
952             $path->visit({ recurse => 1});
953              
954             The method then calls the visitor
955             L passing C<$self> as an argument
956             to begin the visit.
957              
958             =head2 accept($visitor)
959              
960             This method is called to dispatch a visitor to the correct method for a
961             filesystem object. In the L base class, it calls the
962             visitor L method,
963             passing the C<$self> object reference as an argument. Subclasses redefine this
964             method to call other visitor methods.
965              
966             =head2 enter($visitor)
967              
968             This is a special case of the L method which subclasses (e.g.
969             L) use to differentiate between the
970             initial entry point of a visitor and subsequent visits to directories
971             contained therein. In the base class it simply delegates to the L
972             method.
973              
974             =head2 collect(\%params)
975              
976             This is a short-cut to call the L method and then the
977             L method on the
978             L object returned.
979              
980             # short form
981             my @items = $path->collect( files => 1, dirs => 0 );
982              
983             # long form
984             my @items = $path->visit( files => 1, dirs => 0 )->collect;
985              
986             =head2 metadata() / meta()
987              
988             This method allows you to associate metadata with a path. The method
989             accepts multiple arguments to set metadata:
990              
991             $path->metadata( title => 'An Example', author => 'Arthur Dent' );
992              
993             It also accepts a single argument to fetch a metadata item:
994              
995             print $path->metadata('author'); # Arthur Dent
996              
997             You can also call it without arguments. The method returns a reference
998             to a hash array of metadata items.
999              
1000             my $meta = $path->metadata;
1001             print $meta->{ author }; # Arthur Dent
1002              
1003             =head1 STUB METHODS
1004              
1005             The following methods serve little or no purpose in the
1006             C base class. They are redefined by the
1007             C and C modules
1008             to do the right thing.
1009              
1010             =head2 is_file()
1011              
1012             This method always returns false in the C base
1013             class. The C subclass redefines this to return
1014             true. NOTE: this may be changed to examine the filesystem and return true
1015             if the path references a file.
1016              
1017             =head2 is_directory() / is_dir()
1018              
1019             This method always returns false in the C base
1020             class. The C subclass redefines this to return
1021             true. NOTE: this may be changed to examine the filesystem and return true
1022             if the path references a file.
1023              
1024             =head2 volume() / vol()
1025              
1026             Returns any volume defined as part of the path. This method does nothing in
1027             the C base class.
1028              
1029             =head2 directory() / dir()
1030              
1031             Returns the directory portion of a path. This method does nothing in the
1032             C base class.
1033              
1034             =head2 name()
1035              
1036             Returns the file name portion of a path. This method does nothing in the
1037             C base class.
1038              
1039             =head2 extension() / ext()
1040              
1041             Returns any file extension portion following the final C<.> in the path.
1042             This works in the C base class by looking at the
1043             full path.
1044              
1045             print Path('/foo/bar.txt')->extension; # txt
1046              
1047             =head2 basename() / base_name()
1048              
1049             Returns the filename I the file extension following the final
1050             C<.> in the path. This works (for some definition of "works") in the
1051             C base class by looking at the path L,
1052             if defined, or the full C if not. Note that this will produce
1053             unexpected results in some cases due to the fact that the base class
1054             does not define a value for L. e.g.
1055              
1056             print Path('/foo/bar.txt')->basename; # /foo/bar
1057              
1058             However, in most cases you would be using this through a
1059             L subclass which will product the correct
1060             results.
1061              
1062             print File('/foo/bar.txt')->basename; # bar
1063              
1064             =head1 AUTHOR
1065              
1066             Andy Wardley L
1067              
1068             =head1 COPYRIGHT
1069              
1070             Copyright (C) 2005-2009 Andy Wardley. All rights reserved.
1071              
1072             =head1 ACKNOWLEDGEMENTS
1073              
1074             The C modules are built around a number of existing
1075             Perl modules, including L, L, L, L,
1076             L and draw heavily on ideas in L.
1077              
1078             Please see the L
1079             in L for further information.
1080              
1081             =head1 SEE ALSO
1082              
1083             L,
1084             L,
1085             L,
1086             L.
1087              
1088             =cut
1089              
1090             # Local Variables:
1091             # mode: Perl
1092             # perl-indent-level: 4
1093             # indent-tabs-mode: nil
1094             # End:
1095             #
1096             # vim: expandtab shiftwidth=4:
1097             # TextMate: should support split pane editing