File Coverage

blib/lib/Storage/Abstract/Driver/Memory.pm
Criterion Covered Total %
statement 56 58 96.5
branch 23 28 82.1
condition 2 3 66.6
subroutine 9 9 100.0
pod 2 2 100.0
total 92 100 92.0


line stmt bran cond sub pod time code
1             package Storage::Abstract::Driver::Memory;
2             $Storage::Abstract::Driver::Memory::VERSION = '0.008';
3 7     7   95 use v5.14;
  7         26  
4 7     7   37 use warnings;
  7         13  
  7         534  
5              
6 7     7   43 use Mooish::Base -standard;
  7         17  
  7         129  
7              
8 7     7   97845 use constant TYPE_FILE => 1;
  7         29  
  7         581  
9 7     7   38 use constant TYPE_DIR => 2;
  7         13  
  7         8474  
10              
11             extends 'Storage::Abstract::Driver';
12              
13             has field 'files' => (
14             isa => HashRef,
15             default => sub { {} },
16             );
17              
18             with 'Storage::Abstract::Role::Driver::Basic';
19              
20             sub _access_file
21             {
22 117     117   202 my ($self, $name, $new_value) = @_;
23 117         234 my @parts = $self->split_path($name);
24 117         176 my $has_new_value = @_ > 2;
25              
26 117         208 my $current = $self->files;
27             return {
28 117 100       234 type => TYPE_DIR,
29             files => $current,
30             } if !@parts;
31              
32 109         161 my $filename = pop @parts;
33 109         187 foreach my $part (@parts) {
34 57 100       112 if (!defined $current->{$part}) {
35 18 100       69 return undef unless $has_new_value;
36 9         33 $current->{$part} = {
37             type => TYPE_DIR,
38             files => {},
39             };
40             }
41              
42 48 50       121 if ($current->{$part}{type} != TYPE_DIR) {
43 0 0       0 return undef unless $has_new_value;
44              
45 0         0 Storage::Abstract::X::StorageError->raise(
46             "part $part of path $name already exists as a file"
47             );
48             }
49              
50 48         79 $current = $current->{$part}{files};
51             }
52              
53 100 100       171 if ($has_new_value) {
54 26 100       60 if (defined $new_value) {
55 21         56 $current->{$filename} = $new_value;
56             }
57             else {
58 5         12 delete $current->{$filename};
59             }
60             }
61              
62 100         229 return $current->{$filename};
63             }
64              
65             sub _list
66             {
67 31     31   80 my ($self, $prefix, $dir, %opts) = @_;
68 31         54 my @files = keys %{$dir};
  31         88  
69              
70 31 50       46 my @directories = grep { $dir->{$_} && $dir->{$_}{type} == TYPE_DIR } @files;
  82         228  
71              
72 53         178 my @results = grep { /$opts{filter_re}/ } $opts{directories}
73             ? @directories
74 31 50       61 : grep { $dir->{$_} && $dir->{$_}{type} == TYPE_FILE } @files
  57 100       121  
75             ;
76              
77 17         41 push @results, map { $self->_list($_, $dir->{$_}{files}, %opts) } @directories
78 31 100       64 if $opts{recursive};
79              
80 31         75 return map { $self->join_path($prefix, $_) } @results;
  57         121  
81             }
82              
83             sub store_impl
84             {
85             my ($self, $name, $handle) = @_;
86             my $files = $self->files;
87              
88             my $stored = $self->_access_file($name);
89              
90             Storage::Abstract::X::StorageError->raise(
91             'object already exists as a directory'
92             ) if $stored && $stored->{type} != TYPE_FILE;
93              
94             $stored = $self->_access_file(
95             $name, {
96             type => TYPE_FILE,
97             content => undef,
98             properties => $self->common_properties($handle),
99             }
100             );
101              
102             open my $fh, '>:raw', \$stored->{content}
103             or Storage::Abstract::X::StorageError->raise("Could not open storage: $!");
104              
105             tied(*$handle)->copy($fh);
106              
107             close $fh
108             or Storage::Abstract::X::StorageError->raise("Could not close handle: $!");
109             }
110              
111             sub is_stored_impl
112             {
113 40     40 1 92 my ($self, $name, %opts) = @_;
114 40 100       116 my $type = $opts{directory} ? TYPE_DIR : TYPE_FILE;
115              
116 40         161 my $stored = $self->_access_file($name);
117 40   66     548 return defined $stored && $stored->{type} == $type;
118             }
119              
120             sub retrieve_impl
121             {
122             my ($self, $name, $properties) = @_;
123             my $stored = $self->_access_file($name);
124              
125             if ($properties) {
126             %{$properties} = %{$stored->{properties}};
127             }
128              
129             return Storage::Abstract::Handle->adapt(\$stored->{content});
130             }
131              
132             sub dispose_impl
133             {
134             my ($self, $name, %opts) = @_;
135             my $type = $opts{directory} ? TYPE_DIR : TYPE_FILE;
136              
137             my $file = $self->_access_file($name);
138              
139             Storage::Abstract::X::StorageError->raise(
140             'object type mismatch - not a ' . ($opts{directory} ? 'directory' : 'file')
141             ) if $file->{type} != $type;
142              
143             Storage::Abstract::X::StorageError->raise(
144             'directory is not empty'
145             ) if $opts{directory} && keys %{$file->{files}} > 0;
146              
147             $self->_access_file($name, undef);
148             }
149              
150             sub list_impl
151             {
152 16     16 1 46 my ($self, $directory, %opts) = @_;
153              
154 16         33 my $stored_dir = $self->_access_file($directory);
155              
156 16 100       47 Storage::Abstract::X::NotFound->raise(
157             'directory does not exist'
158             ) unless $stored_dir;
159              
160             Storage::Abstract::X::StorageError->raise(
161             'object type mismatch - not a directory'
162 15 100       1455 ) unless $stored_dir->{type} == TYPE_DIR;
163              
164 14         35 $opts{filter_re} = quotemeta $opts{filter};
165 14         45 $opts{filter_re} =~ s{\\\*}{.*}g;
166 14         156 $opts{filter_re} = qr{^ $opts{filter_re} $}x;
167              
168             return [
169 42         65 map { $self->resolve_path($_) }
170 14         53 $self->_list($directory, $stored_dir->{files}, %opts)
171             ];
172             }
173              
174             1;
175              
176             __END__