File Coverage

blib/lib/Catmandu/DirectoryIndex.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package Catmandu::DirectoryIndex;
2              
3 12     12   83346 use Catmandu::Sane;
  12         190568  
  12         109  
4              
5             our $VERSION = '1.16';
6              
7 12     12   3060 use Moo::Role;
  12         28  
  12         84  
8 12     12   4949 use Cwd;
  12         41  
  12         719  
9 12     12   75 use Catmandu::Util qw(check_string is_string);
  12         26  
  12         623  
10 12     12   78 use namespace::clean;
  12         23  
  12         79  
11              
12             with "Catmandu::Iterable";
13              
14             has base_dir => (
15             is => "ro",
16             isa => sub {check_string($_[0]);},
17             required => 1,
18             coerce => sub {
19             is_string($_[0]) ? Cwd::abs_path($_[0]) : $_[0];
20             }
21             );
22              
23             requires "get";
24             requires "add";
25             requires "delete";
26             requires "delete_all";
27              
28             1;
29              
30             __END__
31              
32             =pod
33              
34             =head1 NAME
35              
36             Catmandu::DirectoryIndex - A base role to store relations between id's and directories
37              
38             =head1 SYNOPSIS
39              
40             package MyDirectory;
41              
42             use Moo;
43             use File::Spec;
44             use File:Basename;
45             use Path::Tiny qw(path);
46              
47             with "Catmandu::DirectoryIndex";
48              
49             # translate id to directory
50             sub _to_path {
51             my ( $self, $id ) = @_;
52             File::Spec->catdir( $self->base_dir(), $id );
53             }
54              
55             sub get {
56             my ( $self, $id ) = @_;
57             my $path = $self->_to_path( $id );
58              
59             is_string( $path ) && -d $path ? { _id => $id, _path => $path } : undef;
60             }
61              
62             sub add {
63             my ( $self, $id ) = @_;
64             my $path = $self->_to_path( $id );
65              
66             path( $path )->mkpath unless -d $path;
67              
68             { _id => $id, _path => $path };
69             }
70              
71             sub delete {
72             my ( $self, $id ) = @_;
73             my $path = $self->_to_path( $id );
74              
75             if ( is_string( $path ) && -d $path ) {
76             path( $path )->remove_tree();
77             }
78             }
79              
80             sub delete_all {
81             path( $_[0]->base_dir )->remove_tree({ keep_root => 1 });
82             }
83              
84             # return a generator that returns list of records, that maps _id and _path
85             sub generator {
86             my $self = $_[0];
87             return sub {
88             state $records;
89              
90             if ( !defined( $records ) ) {
91             $records = [];
92              
93             opendir my $dh, $self->base_dir() or die($!);
94             while( my $entry = readdir( $dh ) ){
95             if ( -d $entry ) {
96             push @$records, {
97             _id => $entry,
98             _path => File::Spec->catfile( $self->base_dir, $entry )
99             };
100             }
101             }
102             closedir $dh;
103             }
104              
105             shift( @$records );
106             };
107             }
108              
109             package main;
110              
111             my $p = MyDirectory->new( base_dir => "/tmp" );
112              
113             Catmandu->store->bag->each(sub {
114             my $r = $_[0];
115             my $mapping = $p->get( $r->{_id} ) || $p->add( $r->{_id} );
116             say $id . " => " . $mapping->{path};
117             });
118              
119             =head1 CLASS METHODS AVAILABLE
120              
121             =head2 new( base_dir => $base_dir )
122              
123             =over
124              
125             =item base_dir
126              
127             The base directory where the files are stored. Required
128              
129             =back
130              
131             =head1 METHODS AVAILABLE
132              
133             =over
134              
135             =item base_dir
136              
137             =back
138              
139             =head1 METHODS TO IMPLEMENT
140              
141             Implementors must implement these methods
142              
143             =over
144              
145             =item add( $id ) : $mapping
146              
147             * Accepts $id as string
148              
149             * Translates $id to directory path
150              
151             * Creates directory if necessary
152              
153             * Returns HASH with keys C<_id> and C<_path>
154              
155             This method should throw an L<Catmandu::Error> when it detects an invalid id.
156              
157             It should either return the mapping or throw an error.
158              
159             =item get( $id ) : $mapping
160              
161             * Accepts $id as string
162              
163             * Translates $id to directory path
164              
165             * Returns HASH with keys C<_id> and C<_path>, if a path exists for $id
166              
167             This method should throw an L<Catmandu::Error> when it detects an invalid id.
168              
169             Difference with method "add":
170              
171             * no directory created
172              
173             * no mapping returned if no existing directory could be found
174              
175             =item delete ( $id )
176              
177             * Accepts id as string
178              
179             * Translates id to directory
180              
181             * Removes directory if it exists
182              
183             * Do other internal cleanup actions if any required
184              
185             This method should throw an L<Catmandu::Error> when at failure.
186              
187             =item delete_all()
188              
189             * Deletes files/directories in base_dir. Please keep the base_dir.
190              
191             * Do other internal cleanup actions if any required
192              
193             This method should throw an L<Catmandu::Error> when at failure.
194              
195             =item generator()
196              
197             Inherited requirement from L<Catmandu::Iterable>:
198              
199             * return function reference
200              
201             * every call to this function must return the next directory entry in the index
202             as a HASH with keys C<_id> and C<path>
203              
204             =back
205              
206             =head1 INHERITED METHODS
207              
208             This Catmandu::DirectoryIndex inherits:
209              
210             =over 3
211              
212             =item L<Catmandu::Iterable>
213              
214             So all functions from L<Catmandu::Iterable> are available to these objects.
215              
216             =back
217              
218             =head1 SEE ALSO
219              
220             L<Catmandu::Store::File::Simple> ,
221             L<Catmandu::DirectoryIndex::UUID> ,
222             L<Catmandu::DirectoryIndex::Number> ,
223             L<Catmandu::DirectoryIndex::Map>
224              
225             =cut