File Coverage

blib/lib/File/Find/Rule/Filesys/Virtual.pm
Criterion Covered Total %
statement 80 185 43.2
branch 13 20 65.0
condition 6 9 66.6
subroutine 13 14 92.8
pod 1 2 50.0
total 113 230 49.1


line stmt bran cond sub pod time code
1             package File::Find::Rule::Filesys::Virtual;
2 1     1   43636 use strict;
  1         3  
  1         39  
3 1     1   6 use warnings;
  1         3  
  1         170  
4 1     1   6 use File::Find::Rule 0.28;
  1         44  
  1         8  
5 1     1   49 use base qw( File::Find::Rule );
  1         1  
  1         158  
6             our $VERSION = 1.22;
7              
8             =head1 NAME
9              
10             File::Find::Rule::Filesys::Virtual - File::Find::Rule adapted to Filesys::Virtual
11              
12             =head1 SYNOPSIS
13              
14             use File::Find::Rule::Filesys::Virtual;
15             use Filesys::Virtual::Ninja;
16             my $vfs = Filesys::Virtual::Ninja->new;
17             my @virtual_ninja_foos = File::Find::Rule::Filesys::Virtual
18             ->virtual( $vfs )
19             ->name( "foo.*' )
20             ->in( '/' );
21              
22             =head1 DESCRIPTION
23              
24             This module allows you to use File::Find::Rule file finding semantics
25             to Filesys::Virtual derived filesystems.
26              
27             =cut
28              
29              
30 1     1   193 BEGIN { *_force_object = \&File::Find::Rule::_force_object }
31             sub virtual {
32 9     9 0 13152 my $self = _force_object shift;
33 9         60 $self->{_virtual} = shift;
34 9         130 return $self;
35             }
36              
37             our %X_tests;
38             *X_tests = \%File::Find::Rule::X_tests;
39             for my $test (keys %X_tests) {
40             $test =~ s/^-//;
41 0     0   0 my $sub = eval 'sub () {
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  2         8  
  2         75  
  2         35  
  2         18  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
42             my $self = _force_object shift;
43             push @{ $self->{rules} }, {
44             code => "\$File::Find::vfs->test(q{' . $test . '}, \$_)",
45             rule => "'.$X_tests{"-$test"}.'",
46             };
47             return $self;
48             } ';
49 1     1   6 no strict 'refs';
  1         1  
  1         243  
50             *{ $X_tests{"-$test"} } = $sub;
51             }
52              
53             {
54             our @stat_tests;
55             *stat_tests = \@File::Find::Rule::stat_tests;
56              
57             my $i = 0;
58             for my $test (@stat_tests) {
59             my $index = $i++; # to close over
60             my $sub = sub {
61 3     3   10 my $self = _force_object shift;
62              
63 3         21 my @tests = map { Number::Compare->parse_to_perl($_) } @_;
  3         21  
64              
65 3         18 push @{ $self->{rules} }, {
  3         120  
66             rule => $test,
67             args => \@_,
68             code => 'do { my $val = ($File::Find::vfs->stat($_))['.$index.'] || 0;'.
69 3         86 join ('||', map { "(\$val $_)" } @tests ).' }',
70             };
71 3         21 return $self;
72             };
73 1     1   5 no strict 'refs';
  1         2  
  1         813  
74             *$test = $sub;
75             }
76             }
77              
78             sub grep {
79 1     1 1 4 my $self = _force_object shift;
80 0 0       0 my @pattern = map {
81 1         6 ref $_
82             ? ref $_ eq 'ARRAY'
83 1 50       9 ? map { [ ( ref $_ ? $_ : qr/$_/ ) => 0 ] } @$_
    50          
84             : [ $_ => 1 ]
85             : [ qr/$_/ => 1 ]
86             } @_;
87              
88             $self->exec( sub {
89 7     7   148 my $vfs = $File::Find::vfs;
90 7 50       32 my $fh = $vfs->open_read($_) or return;
91 7         868 local ($_, $.);
92 7         605 while (<$fh>) {
93 40         51 for my $p (@pattern) {
94 40         49 my ($rule, $ret) = @$p;
95 40 50       266 if (ref $rule eq 'Regexp' ? /$rule/ : $rule->(@_)) {
    100          
96 2         10 $vfs->close_read($fh);
97 2         104 return $ret;
98             }
99             }
100             }
101 5         17 $vfs->close_read($fh);
102 5         229 return;
103 1         26 } );
104             }
105              
106              
107             sub _call_find {
108 7     7   6709 my $self = shift;
109 7         11 my %args = %{ shift() };
  7         25  
110 7         17 my $path = shift;
111 7         15 my $vfs = local $File::Find::vfs = $self->{_virtual};
112 7         28 my $cwd = $vfs->cwd;
113 7         100 __inner_find( $args{wanted}, $path, "" );
114 7         486 $vfs->chdir( $cwd );
115             }
116              
117             # fake the behaviour of File::Find. It burns!
118             sub __inner_find {
119 11     11   18 my $wanted = shift;
120 11         15 my $path = shift;
121 11         14 my $parent = shift;
122 11         13 my $vfs = $File::Find::vfs;
123              
124 11 100       37 unless ( $vfs->chdir( $path ) ) {
125             # Couldn't chdir into it, so we see if it's a file.
126             # Actually because there are many forms of "file" (plain,
127             # symlink, socket, block, character) we just check if it
128             # exists and that it's not a directory.
129 2 50 33     195 if ($vfs->test('e', $path) && !$vfs->test('d', $path)) {
130 2         524 my ($dir, $name) = $path =~ m{^(.*/)(.*)};
131 2         4 local $_ = $name;
132 2         4 local $File::Find::dir = $dir;
133 2         4 local $File::Find::name = $path;
134 2         3 local $File::Find::prune;
135 2         7 $vfs->chdir($dir);
136 2         385 $wanted->();
137             }
138 2         252 return; # I have no clue - bail
139             }
140 9 100       849 local $File::Find::dir = $parent ? "$parent/$path" : $path;
141 9         35 for my $name ($vfs->list) {
142 31         3935 local $_ = $name;
143 31         69 local $File::Find::name = "$File::Find::dir/$name";
144 31         32 local $File::Find::prune;
145             #print "_: $_\n";
146             #print "dir: $File::Find::dir\n";
147             #print "name: $File::Find::name\n";
148              
149 31         809 $wanted->();
150              
151 31 100 66     3464 if ($vfs->test("d", $name ) && !$File::Find::prune && $name !~ /^\..?$/) {
      100        
152 4         485 my $cwd = $vfs->cwd;
153 4         40 __inner_find( $wanted, $name, $File::Find::dir );
154 4         536 $vfs->chdir( $cwd );
155             }
156             }
157             }
158              
159              
160             1;
161              
162             __END__