File Coverage

blib/lib/Storage/Abstract/Driver.pm
Criterion Covered Total %
statement 72 88 81.8
branch 14 16 87.5
condition 17 17 100.0
subroutine 19 26 73.0
pod 7 17 41.1
total 129 164 78.6


line stmt bran cond sub pod time code
1             package Storage::Abstract::Driver;
2             $Storage::Abstract::Driver::VERSION = '0.008';
3 11     11   7528 use v5.14;
  11         41  
4 11     11   58 use warnings;
  11         33  
  11         783  
5              
6 11     11   57 use Mooish::Base -standard;
  11         22  
  11         87  
7              
8 11     11   158038 use Scalar::Util qw(blessed);
  11         24  
  11         868  
9 11     11   7098 use Storage::Abstract::Handle;
  11         38  
  11         478  
10 11     11   84 use Storage::Abstract::X;
  11         42  
  11         348  
11              
12             # Not using File::Spec here, because paths must be unix-like regardless of
13             # local OS
14 11     11   64 use constant UPDIR_STR => '..';
  11         60  
  11         914  
15 11     11   69 use constant CURDIR_STR => '.';
  11         50  
  11         598  
16 11     11   59 use constant DIRSEP_STR => '/';
  11         22  
  11         11828  
17              
18             has param 'readonly' => (
19             isa => Bool,
20             writer => 1,
21             lazy => 1,
22             clearer => -hidden,
23             );
24              
25             # HELPERS
26              
27             # this is intentionally not portable - only drivers working on an actual
28             # filesystem should port this unix-like path to its own representation
29             sub resolve_path
30             {
31 264     264 1 672 my ($self, $name, %opts) = @_;
32              
33 264         593 my @path = $self->split_path($name);
34             Storage::Abstract::X::PathError->raise("path $name is empty")
35 264 100 100     656 unless @path || $opts{allow_empty};
36              
37 263         346 my $i = 0;
38 263         307 my $last_ok = 1;
39 263         558 while ($i < @path) {
40 476 100 100     1606 if ($path[$i] eq UPDIR_STR) {
    100          
41 12 100       80 Storage::Abstract::X::PathError->raise("path $name is trying to leave root")
42             if $i == 0;
43              
44 6         15 splice @path, $i - 1, 2;
45 6         11 $last_ok = 0;
46 6         11 $i -= 1;
47             }
48             elsif ($path[$i] eq '' || $path[$i] eq CURDIR_STR) {
49 77         118 splice @path, $i, 1;
50 77         165 $last_ok = 0;
51             }
52             else {
53 387         462 $i += 1;
54 387         672 $last_ok = 1;
55             }
56             }
57              
58             Storage::Abstract::X::PathError->raise("path $name has no filename")
59 257 100 100     537 unless $last_ok || $opts{allow_directory};
60              
61 254         532 return $self->join_path(@path);
62             }
63              
64             sub split_path
65             {
66 387     387 0 672 my ($self, $name) = @_;
67 387         1047 return split DIRSEP_STR, $name, -1;
68             }
69              
70             sub join_path
71             {
72 349     349 0 787 my ($self, @parts) = @_;
73 349         2250 return join DIRSEP_STR, @parts;
74             }
75              
76             sub common_properties
77             {
78 21     21 1 36 my ($self, $handle) = @_;
79              
80             return {
81 21         83 size => tied(*$handle)->size,
82             mtime => time,
83             };
84             }
85              
86             sub refresh
87       2 0   {
88             # Nothing to clear here
89             }
90              
91             # TO BE IMPLEMENTED IN SUBCLASSES
92              
93             sub store_impl
94             {
95 0     0 1 0 my ($self, $name, $handle) = @_;
96              
97 0         0 ...;
98             }
99              
100             sub is_stored_impl
101             {
102 0     0 1 0 my ($self, $name, %opts) = @_;
103              
104 0         0 ...;
105             }
106              
107             sub retrieve_impl
108             {
109 0     0 1 0 my ($self, $name, $properties) = @_;
110              
111 0         0 ...;
112             }
113              
114             sub dispose_impl
115             {
116 0     0 1 0 my ($self, $name, %opts) = @_;
117              
118 0         0 ...;
119             }
120              
121             sub list_impl
122             {
123 0     0 1 0 my ($self, $directory, %opts) = @_;
124              
125 0         0 ...;
126             }
127              
128             sub prune_impl
129             {
130 0     0 0 0 my ($self) = @_;
131              
132 0         0 ...;
133             }
134              
135             # PUBLIC INTERFACE
136              
137             sub store
138             {
139 36     36 0 28594 my ($self, $name, $handle) = @_;
140 36         77 local $Storage::Abstract::X::path_context = $name;
141              
142 36 100       524 Storage::Abstract::X::Readonly->raise('storage is readonly')
143             if $self->readonly;
144              
145 35         607 $self->store_impl($self->resolve_path($name), $handle);
146 32         244 return;
147             }
148              
149             sub is_stored
150             {
151 76     76 0 38717 my ($self, $name, %opts) = @_;
152 76         226 local $Storage::Abstract::X::path_context = $name;
153              
154 76         343 return $self->is_stored_impl($self->resolve_path($name, allow_directory => $opts{directory}), %opts);
155             }
156              
157             sub retrieve
158             {
159 18     18 0 10060 my ($self, $name, $properties) = @_;
160 18         45 local $Storage::Abstract::X::path_context = $name;
161              
162 18         57 return $self->retrieve_impl($self->resolve_path($name), $properties);
163             }
164              
165             sub dispose
166             {
167 16     16 0 16450 my ($self, $name, %opts) = @_;
168 16         51 local $Storage::Abstract::X::path_context = $name;
169              
170 16 100       220 Storage::Abstract::X::Readonly->raise('storage is readonly')
171             if $self->readonly;
172              
173 15         142 $self->dispose_impl($self->resolve_path($name, allow_directory => $opts{directory}), %opts);
174 10         34 return;
175             }
176              
177             sub list
178             {
179 33     33 0 46886 my ($self, $directory, %opts) = @_;
180 33         63 local $Storage::Abstract::X::path_context = $directory;
181              
182 33   100     175 $directory = $self->resolve_path(
183             $directory // '',
184             allow_directory => !!1,
185             allow_empty => !!1,
186             );
187 33   100     134 $opts{recursive} //= !!0;
188 33   100     158 $opts{filter} //= '*';
189 33   100     111 $opts{directories} //= !!0;
190              
191 33         135 return $self->list_impl($directory, %opts);
192             }
193              
194             sub prune
195             {
196 0     0 0   my ($self) = @_;
197              
198 0 0         Storage::Abstract::X::Readonly->raise('storage is readonly')
199             if $self->readonly;
200              
201 0           $self->prune_impl();
202 0           return;
203             }
204              
205             1;
206              
207             __END__