File Coverage

blib/lib/Storage/Abstract/Driver/Directory.pm
Criterion Covered Total %
statement 65 66 98.4
branch 12 14 85.7
condition n/a
subroutine 15 15 100.0
pod 3 4 75.0
total 95 99 95.9


line stmt bran cond sub pod time code
1             package Storage::Abstract::Driver::Directory;
2             $Storage::Abstract::Driver::Directory::VERSION = '0.008';
3 3     3   50 use v5.14;
  3         14  
4 3     3   21 use warnings;
  3         6  
  3         262  
5              
6 3     3   20 use Mooish::Base -standard;
  3         7  
  3         45  
7              
8 3     3   50872 use File::Spec;
  3         10  
  3         144  
9 3     3   36 use File::Path qw(make_path);
  3         8  
  3         322  
10 3     3   20 use File::Basename qw(dirname);
  3         6  
  3         271  
11              
12             # need this in BEGIN block because we use constants from this package
13 3     3   23 BEGIN { extends 'Storage::Abstract::Driver' }
14              
15             # This driver deals with OS filesystem directly, so these must be
16             # system-specific. Unix paths from Storage::Abstract::Driver must be converted
17             # to paths on this OS
18 3     3   519 use constant UPDIR_STR => File::Spec->updir;
  3         6  
  3         330  
19 3     3   20 use constant CURDIR_STR => File::Spec->curdir;
  3         8  
  3         256  
20 3     3   18 use constant DIRSEP_STR => File::Spec->catfile('', '');
  3         7  
  3         4176  
21              
22             has param 'directory' => (
23             isa => SimpleStr,
24             );
25              
26             has param 'create_directory' => (
27             isa => Bool,
28             default => !!0,
29             );
30              
31             with 'Storage::Abstract::Role::Driver::Basic';
32              
33             sub BUILD
34             {
35 4     4 0 10739 my ($self) = @_;
36              
37 4         26 my $directory = $self->directory;
38 4 50       28 if ($self->create_directory) {
39 0         0 make_path($directory);
40             }
41              
42 4 50       346 die "directory $directory does not exist"
43             unless -d $directory;
44             }
45              
46             sub _list
47             {
48 29     29   109 my ($self, $dir, %opts) = @_;
49 29         2693 my @files = File::Spec->no_upwards(glob File::Spec->catfile($dir, '*'));
50              
51 29         119 my @directories = grep { -d } @files;
  78         736  
52              
53 49         372 my @results = grep { /$opts{filter_re}/ } $opts{directories}
54             ? @directories
55 29 100       97 : grep { !-d } @files
  53         433  
56             ;
57              
58 17         62 push @results, map { $self->_list($_, %opts) } @directories
59 29 100       97 if $opts{recursive};
60              
61 29         160 return @results;
62             }
63              
64             sub resolve_path
65             {
66 51     51 1 169 my ($self, $name, %opts) = @_;
67              
68 51         183 my $resolved = $self->SUPER::resolve_path($name, %opts);
69 50         76 if (Storage::Abstract::Driver::DIRSEP_STR ne DIRSEP_STR) {
70             Storage::Abstract::X::PathError->raise("System-specific dirsep in file path $name")
71             if $resolved =~ quotemeta DIRSEP_STR;
72             }
73              
74 50         103 my @parts = split Storage::Abstract::Driver::DIRSEP_STR, $resolved;
75              
76 50         66 if (Storage::Abstract::Driver::UPDIR_STR ne UPDIR_STR || Storage::Abstract::Driver::CURDIR_STR ne CURDIR_STR) {
77             Storage::Abstract::X::PathError->raise("System-specific updir or curdir in file path $name")
78             unless @parts == File::Spec->no_upwards(@parts);
79             }
80              
81 50         1002 return File::Spec->catfile($self->directory, @parts);
82             }
83              
84             sub store_impl
85             {
86             my ($self, $name, $handle) = @_;
87              
88             my $directory = dirname($name);
89             make_path($directory) unless -e $directory;
90              
91             open my $fh, '>:raw', $name
92             or Storage::Abstract::X::StorageError->raise($!);
93              
94             tied(*$handle)->copy($fh);
95              
96             close $fh
97             or Storage::Abstract::X::StorageError->raise($!);
98             }
99              
100             sub is_stored_impl
101             {
102 27     27 1 71 my ($self, $name, %opts) = @_;
103              
104 27 100       126 if ($opts{directory}) {
105 7         237 return -d $name;
106             }
107             else {
108 20         944 return -f $name;
109             }
110             }
111              
112             sub retrieve_impl
113             {
114             my ($self, $name, $properties) = @_;
115              
116             if ($properties) {
117             my @stat = stat $name;
118             %{$properties} = (
119             size => $stat[7],
120             mtime => $stat[9],
121             );
122             }
123              
124             return Storage::Abstract::Handle->adapt($name);
125             }
126              
127             sub dispose_impl
128             {
129             my ($self, $name, %opts) = @_;
130              
131             if ($opts{directory}) {
132             rmdir $name
133             or Storage::Abstract::X::StorageError->raise($!);
134             }
135             else {
136             unlink $name
137             or Storage::Abstract::X::StorageError->raise($!);
138             }
139             }
140              
141             sub list_impl
142             {
143 14     14 1 49 my ($self, $directory, %opts) = @_;
144              
145 14 100       399 Storage::Abstract::X::NotFound->raise(
146             'directory does not exist'
147             ) unless -e $directory;
148              
149 13 100       128 Storage::Abstract::X::StorageError->raise(
150             'object type mismatch - not a directory'
151             ) unless -d $directory;
152              
153 12         48 my $dirsep = quotemeta $self->DIRSEP_STR;
154 12         38 $opts{filter_re} = quotemeta $opts{filter};
155 12         102 $opts{filter_re} =~ s{\\\*}{[^$dirsep]*}g;
156 12         268 $opts{filter_re} = qr{(?<=$dirsep) $opts{filter_re} $}x;
157              
158 12         86 my @all_files = $self->_list($directory, %opts);
159              
160 12         70 my $basedir = $self->directory;
161 12         28 foreach my $file (@all_files) {
162 38         1895 $file = File::Spec->abs2rel($file, $basedir);
163 38         140 my @parts = File::Spec->splitdir($file);
164 38         149 $file = $self->SUPER::resolve_path($self->join_path(@parts));
165             }
166              
167 12         161 return \@all_files;
168             }
169              
170             1;
171              
172             __END__