File Coverage

blib/lib/Catmandu/Store/File/BagIt/Index.pm
Criterion Covered Total %
statement 52 56 92.8
branch 7 10 70.0
condition n/a
subroutine 12 14 85.7
pod 0 3 0.0
total 71 83 85.5


line stmt bran cond sub pod time code
1             package Catmandu::Store::File::BagIt::Index;
2              
3             our $VERSION = '0.250';
4              
5 3     3   21 use Catmandu::Sane;
  3         8  
  3         26  
6 3     3   687 use Moo;
  3         7  
  3         16  
7 3     3   1117 use Path::Tiny;
  3         8  
  3         166  
8 3     3   26 use Carp;
  3         8  
  3         245  
9 3     3   22 use POSIX qw(ceil);
  3         22  
  3         32  
10 3     3   7008 use Path::Iterator::Rule;
  3         28462  
  3         137  
11 3     3   26 use File::Spec;
  3         6  
  3         68  
12 3     3   16 use namespace::clean;
  3         6  
  3         21  
13              
14 3     3   1179 use Data::Dumper;
  3         7  
  3         3635  
15              
16             with 'Catmandu::Bag';
17             with 'Catmandu::FileBag::Index';
18             with 'Catmandu::Droppable';
19              
20             sub generator {
21 2     2 0 3673 my ($self) = @_;
22              
23 2         12 my $root = $self->store->root;
24 2         9 my $keysize = $self->store->keysize;
25 2         23 my @root_split = File::Spec->splitdir($root);
26              
27 2         20 my $mindepth = ceil($keysize / 3);
28              
29 2 50       47 unless (-d $root) {
30 0         0 $self->log->error("no root $root found");
31 0     0   0 return sub {undef};
  0         0  
32             }
33              
34 2         57 $self->log->debug("creating generator for root: $root");
35              
36 2         2175 my $rule = Path::Iterator::Rule->new;
37 2         25 $rule->min_depth($mindepth);
38 2         102 $rule->max_depth($mindepth);
39 2         69 $rule->directory;
40              
41             return sub {
42 5     5   38 state $iter = $rule->iter($root, {depthfirst => 1});
43              
44 5         325 my $path = $iter->();
45              
46 5 100       2610 return undef unless defined($path);
47              
48             # Strip of the root part and translate the path to an identifier
49 3         23 my @split_path = File::Spec->splitdir($path);
50 3         12 my $id = join("", splice(@split_path, int(@root_split)));
51              
52 3 50       40 unless ($self->store->uuid) {
53 3         19 $id =~ s/^0+//;
54             }
55              
56 3         79 $self->get($id);
57 2         56 };
58             }
59              
60             sub exists {
61 11     11 0 3642 my ($self, $id) = @_;
62              
63 11 50       34 croak "Need an id" unless defined $id;
64              
65 11         235 $self->log->debug("Checking exists $id");
66              
67 11         2442 my $path = $self->store->path_string($id);
68              
69 11 100       297 defined($path) && -d $path;
70             }
71              
72             sub add {
73             my ($self, $data) = @_;
74              
75             croak "Need an id" unless defined $data && exists $data->{_id};
76              
77             my $id = $data->{_id};
78              
79             if (exists $data->{_stream}) {
80             croak "Can't add a file to the index";
81             }
82              
83             my $path = $self->store->path_string($id);
84              
85             unless (defined $path) {
86             my $err
87             = "Failed to create path from $id need a number of max "
88             . $self->store->keysize
89             . " digits";
90             $self->log->error($err);
91             Catmandu::BadArg->throw($err);
92             }
93              
94             $self->log->debug("Generating path $path for key $id");
95              
96             # Throws an exception when the path can't be created
97             path($path)->mkpath;
98              
99             my $new_data = $self->get($id);
100              
101             $data->{$_} = $new_data->{$_} for keys %$new_data;
102              
103             1;
104             }
105              
106             sub get {
107             my ($self, $id) = @_;
108              
109             croak "Need an id" unless defined $id;
110              
111             my $path = $self->store->path_string($id);
112              
113             unless ($path) {
114             $self->log->error(
115             "Failed to create path from $id need a number of max "
116             . $self->store->keysize
117             . " digits");
118             return undef;
119             }
120              
121             $self->log->debug("Loading path $path for id $id");
122              
123             return undef unless -d $path;
124              
125             my @stat = stat $path;
126              
127             return +{_id => $id,};
128             }
129              
130             sub delete {
131             my ($self, $id) = @_;
132              
133             croak "Need a key" unless defined $id;
134              
135             my $path = $self->store->path_string($id);
136              
137             unless ($path) {
138             $self->log->error("Failed to create path from $id");
139             return undef;
140             }
141              
142             $self->log->debug("Destoying path $path for key $id");
143              
144             return undef unless -d $path;
145              
146             # Throws an exception when the path can't be created
147             path($path)->remove_tree;
148              
149             1;
150             }
151              
152             sub delete_all {
153             my ($self) = @_;
154              
155             $self->each(
156             sub {
157             my $key = shift->{_id};
158             $self->delete($key);
159             }
160             );
161             }
162              
163             sub drop {
164 0     0 0   $_[0]->delete_all;
165             }
166              
167             sub commit {
168             return 1;
169             }
170              
171             1;
172              
173             __END__
174              
175             =pod
176              
177             =head1 NAME
178              
179             Catmandu::Store::File::BagIt::Index - Index of all "Folders" in a Catmandu::Store::File::BagIt
180              
181             =head1 SYNOPSIS
182              
183             use Catmandu;
184              
185             my $store = Catmandu->store('File::BagIt' , root => 't/data');
186              
187             my $index = $store->index;
188              
189             # List all containers
190             $index->each(sub {
191             my $container = shift;
192              
193             print "%s\n" , $container->{_id};
194             });
195              
196             # Add a new folder
197             $index->add({_id => '1234'});
198              
199             # Delete a folder
200             $index->delete(1234);
201              
202             # Get a folder
203             my $folder = $index->get(1234);
204              
205             # Get the files in an folder
206             my $files = $index->files(1234);
207              
208             $files->each(sub {
209             my $file = shift;
210              
211             my $name = $file->_id;
212             my $size = $file->size;
213             my $content_type = $file->content_type;
214             my $created = $file->created;
215             my $modified = $file->modified;
216              
217             $file->stream(IO::File->new(">/tmp/$name"), file);
218             });
219              
220             # Add a file
221             $files->upload(IO::File->new("<data.dat"),"data.dat");
222              
223             # Retrieve a file
224             my $file = $files->get("data.dat");
225              
226             # Stream a file to an IO::Handle
227             $files->stream(IO::File->new(">data.dat"),$file);
228              
229             # Delete a file
230             $files->delete("data.dat");
231              
232             # Delete a folders
233             $index->delete("1234");
234              
235             =head1 INHERITED METHODS
236              
237             This Catmandu::Bag implements:
238              
239             =over 3
240              
241             =item L<Catmandu::Bag>
242              
243             =item L<Catmandu::FileBag::Index>
244              
245             =item L<Catmandu::Droppable>
246              
247             =back
248              
249             =cut