File Coverage

blib/lib/IO/Dir/Recursive.pm
Criterion Covered Total %
statement 59 63 93.6
branch 12 18 66.6
condition 12 17 70.5
subroutine 12 13 92.3
pod 1 1 100.0
total 96 112 85.7


line stmt bran cond sub pod time code
1             package IO::Dir::Recursive;
2              
3 1     1   34288 use strict;
  1         3  
  1         41  
4 1     1   6 use warnings;
  1         2  
  1         37  
5 1     1   1033 use Symbol;
  1         1037  
  1         136  
6 1     1   907 use IO::All;
  1         37384  
  1         10  
7 1     1   6131 use IO::Dir qw(DIR_UNLINK);
  1         40656  
  1         71  
8 1     1   11 use File::Spec;
  1         2  
  1         1018  
9              
10             our @ISA = qw(IO::Dir);
11              
12             our $VERSION = '0.03';
13              
14             =head1 NAME
15              
16             IO::Dir::Recursive - IO::Dir working recursive
17              
18             =head1 SYNOPSIS
19              
20             use IO::Dir::Recursive;
21            
22             my $dh = IO::Dir::Recursive->new('.');
23             print "$_\n" while $dh->read();
24              
25             tie my %dir, 'IO::Dir::Recursive', '.';
26            
27             print $dir{subdir1}->{subdir2}->{file}->slurp();
28              
29             =head1 DESCRIPTION
30              
31             IO::Dir::Recursive gives IO::Dir the ability to work recursive.
32              
33             =head1 EXPORT
34              
35             The following constans may be imported on request.
36              
37             =over 2
38              
39             =item * DIR_NOUPWARDS
40              
41             This constant can be passed as option to tie to strip out parent directories.
42              
43             =item * DIR_UNLINK
44              
45             This is inherited from IO::Dir. Deleting an element from the hash will delete
46             the corresponding file or subdirectory if this constant is passed as a tie
47             option.
48              
49             =cut
50              
51             our @EXPORT_OK = qw(DIR_NOUPWARDS);
52              
53             sub DIR_NOUPWARDS () { 2 }
54              
55             =head1 METHODS
56              
57             IO::Dir::Recursive inherits from IO::Dir and therefor inherits all its methods
58             with the following exceptions.
59              
60             =head2 read
61              
62             my $item = $dh->read();
63              
64             Reads the next item in $dh and returns the coresponding object for the item: an
65             IO::Dir::Recursive instance for directories, an IO::All instance for files or
66             undef if there are no other items left.
67              
68             =cut
69              
70             sub read {
71 0     0 1 0 my $dh = shift;
72 0         0 return $dh->_create_io_obj(scalar $dh->_read(@_));
73             }
74              
75             =head2 _read
76              
77             my $next = $dh->_read();
78              
79             Same as read() above, but returns a string describing the next item instead of
80             an object. Mainly for internal use, but maybe it's useful in some other places,
81             too.
82              
83             =cut
84              
85             sub _read {
86 20     20   21 my $dh = shift;
87 20         61 return $dh->SUPER::read();
88             }
89              
90             sub _create_io_obj {
91 8     8   12 my ($dh, $key) = @_;
92 8 50       21 return undef unless $key;
93 8 50       18 return $dh if $key eq '.';
94              
95 8         10 my $file = File::Spec->catdir(${*$dh}{io_dir_path}, $key);
  8         81  
96 8 50       20 return IO::Dir::Recursive->new(File::Spec->updir($file)) if $key eq '..';
97              
98 8 100       162 if (-d $file) {
99 5         7 tie my %subdir, 'IO::Dir::Recursive', $file, (${*$dh}{io_dir_unlink} | ${*$dh}{io_dir_noupwards});
  5         12  
  5         24  
100 5         33 return \%subdir;
101             }
102              
103 3         6 $file = File::Spec->catfile(${*$dh}{io_dir_path}, $key);
  3         34  
104 3 50       57 return IO::All->new($file) if -e $file;
105              
106 0         0 return undef;
107             }
108              
109             sub TIEHASH {
110 7     7   68 my ($class, $dir, $options) = @_;
111            
112 7 50       50 my $dh = $class->new($dir) or return undef;
113            
114 7   100     567 $options ||= 0;
115              
116 7         11 ${*$dh}{io_dir_unlink} = $options & DIR_UNLINK;
  7         16  
117 7         11 ${*$dh}{io_dir_noupwards} = $options & DIR_NOUPWARDS;
  7         17  
118 7         21 return $dh;
119             }
120              
121             sub FIRSTKEY {
122 4     4   35 my $dh = shift;
123 4         15 $dh->rewind();
124 4         42 my $key = $dh->_read(@_);
125 4 50       63 return undef unless defined $key;
126 4   66     5 while (${*$dh}{io_dir_noupwards} && defined $key && ($key eq '.' || $key eq '..')) {
  4   33     32  
      66        
127 0         0 $key = $dh->NEXTKEY(@_);
128             }
129 4         19 return $key;
130             }
131              
132             sub NEXTKEY {
133 12     12   315 my $dh = shift;
134 12         12 my $key;
135             {
136 12         15 $key = $dh->_read(@_);
  16         28  
137 16 100       147 return undef unless defined $key;
138 12 100 100     13 redo if ${*$dh}{io_dir_noupwards} && ($key eq '.' || $key eq '..');
  12   66     61  
139             }
140 8         27 return $key;
141             }
142              
143             sub FETCH {
144 8     8   8672 my ($dh, $key) = @_;
145 8         18 $dh->_create_io_obj($key);
146             }
147              
148             1;
149              
150             =head1 SEE ALSO
151              
152             L, L
153              
154             =head1 AUTHOR
155              
156             Florian Ragwitz, Eflora@cpan.orgE
157              
158             =head1 COPYRIGHT AND LICENSE
159              
160             Copyright (C) 2005 by Florian Ragwitz
161              
162             This library is free software; you can redistribute it and/or modify
163             it under the same terms as Perl itself, either Perl version 5.8.7 or,
164             at your option, any later version of Perl 5 you may have available.
165              
166              
167             =cut