File Coverage

blib/lib/Catmandu/Store/File/BagIt.pm
Criterion Covered Total %
statement 39 41 95.1
branch 10 10 100.0
condition 2 3 66.6
subroutine 11 12 91.6
pod 0 2 0.0
total 62 68 91.1


line stmt bran cond sub pod time code
1             package Catmandu::Store::File::BagIt;
2              
3             our $VERSION = '0.250';
4              
5 3     3   243261 use Catmandu::Sane;
  3         597072  
  3         26  
6 3     3   949 use Moo;
  3         7  
  3         15  
7 3     3   1076 use Carp;
  3         6  
  3         188  
8 3     3   1755 use Catmandu;
  3         341880  
  3         17  
9 3     3   767 use Catmandu::Util;
  3         8  
  3         124  
10 3     3   1821 use Catmandu::Store::File::BagIt::Index;
  3         12  
  3         117  
11 3     3   1497 use Catmandu::Store::File::BagIt::Bag;
  3         11  
  3         107  
12 3     3   24 use namespace::clean;
  3         4  
  3         14  
13              
14             with 'Catmandu::FileStore';
15             with 'Catmandu::Droppable';
16              
17             has root => (is => 'ro', required => '1');
18             has uuid => (is => 'ro', trigger => 1);
19             has keysize => (is => 'ro', default => 9, trigger => 1);
20              
21             sub _trigger_keysize {
22 6     6   19118 my $self = shift;
23              
24 6 100       138 croak "keysize needs to be a multiple of 3"
25             unless $self->keysize % 3 == 0;
26             }
27              
28             sub _trigger_uuid {
29 1     1   907 my $self = shift;
30              
31 1         7 $self->{keysize} = 36;
32             }
33              
34             sub path_string {
35 34     34 0 5098 my ($self, $key) = @_;
36              
37 34         78 my $keysize = $self->keysize;
38              
39 34         58 my $h = "[0-9A-F]"; # uc
40              
41             # If the key is a UUID then the matches need to be exact
42 34 100       392 if ($self->uuid) {
    100          
43 4 100       90 return undef unless $key =~ qr/\A${h}{8}-${h}{4}-${h}{4}-${h}{4}-${h}{12}\z/;
44             }
45             elsif ($key =~ qr/\A${h}+\z/) {
46 29 100 66     166 return undef unless length($key) && length($key) <= $keysize;
47 26         66 $key =~ s/^0+//;
48 26         137 $key = sprintf "%-${keysize}.${keysize}d", $key;
49             }
50             else {
51 1         5 return undef;
52             }
53              
54 28         249 my $path = $self->root . "/" . join("/", unpack('(A3)*', $key));
55              
56 28         109 $path;
57             }
58              
59             sub drop {
60 0     0 0   my ($self) = @_;
61              
62 0           $self->index->delete_all;
63             }
64              
65             1;
66              
67             __END__
68              
69             =pod
70              
71             =head1 NAME
72              
73             Catmandu::Store::File::BagIt - A Catmandu::FileStore to store files on disk in the BagIt format
74              
75             =head1 SYNOPSIS
76              
77             # From the command line
78              
79             # Export a list of all file containers
80             $ catmandu export File::BagIt --root t/data to YAML
81              
82             # Export a list of all files in container '1234'
83             $ catmandu export File::BagIt --root t/data --bag 1234 to YAML
84              
85             # Add a file to the container '1234'
86             $ catmandu stream /tmp/myfile.txt to File::BagIt --root t/data --bag 1234 --id myfile.txt
87              
88             # Download the file 'myfile.txt' from the container '1234'
89             $ catmandu stream File::BagIt --root t/data --bag 1234 --id myfile.txt to /tmp/output.txt
90              
91             # Delete the file 'myfile.txt' from the container '1234'
92             $ catmandu delete File::BagIt --root t/data --bag 1234 --id myfile.txt
93              
94             # From Perl
95             use Catmandu;
96              
97             my $store = Catmandu->store('File::BagIt' , root => 't/data');
98              
99             my $index = $store->index;
100              
101             # List all folder
102             $index->bag->each(sub {
103             my $container = shift;
104              
105             print "%s\n" , $container->{_id};
106             });
107              
108             # Add a new folder
109             $index->add({ _id => '1234' });
110              
111             # Get the folder
112             my $files = $index->files('1234');
113              
114             # Add a file to the folder
115             $files->upload(IO::File->new('<foobar.txt'), 'foobar.txt');
116              
117             # Retrieve a file
118             my $file = $files->get('foobar.txt');
119              
120             # Stream the contents of a file
121             $files->stream(IO::File->new('>foobar.txt'), $file);
122              
123             # Delete a file
124             $files->delete('foobar.txt');
125              
126             # Delete a folder
127             $index->delete('1234');
128              
129             =head1 DESCRIPTION
130              
131             L<Catmandu::Store::File::BagIt> is a L<Catmandu::FileStore> implementation to
132             store files in a directory structure. Each L<Catmandu::FileBag> is
133             a deeply nested directory based on the numeric identifier of the bag. E.g.
134              
135             $store->bag(1234)
136              
137             is stored as
138              
139             ${ROOT}/000/001/234
140              
141             In this directory all the L<Catmandu::FileBag> items are stored as
142             flat files.
143              
144             =head1 METHODS
145              
146             =head2 new(root => $path , [ keysize => NUM , uuid => 1])
147              
148             Create a new Catmandu::Store::File::BagIt with the following configuration
149             parameters:
150              
151             =over
152              
153             =item root
154              
155             The root directory where to store all the files. Required.
156              
157             =item keysize
158              
159             By default the directory structure is 3 levels deep. With the keysize option
160             a deeper nesting can be created. The keysize needs to be a multiple of 3.
161             All the container keys of a L<Catmandu::Store::File::BagIt> must be integers.
162              
163             =item uuid
164              
165             If the to a true value, then the Simple store will require UUID-s as keys
166              
167             =back
168              
169             =head1 LARGE FILE SUPPORT
170              
171             Streaming large files into a BagIt requires a large /tmp directory. The location
172             of the temp directory can be set with the TMPDIR environmental variable.
173              
174             =head1 INHERITED METHODS
175              
176             This Catmandu::FileStore implements:
177              
178             =over 3
179              
180             =item L<Catmandu::FileStore>
181              
182             =item L<Catmandu::Droppable>
183              
184             =back
185              
186             The index Catmandu::Bag in this Catmandu::Store implements:
187              
188             =over 3
189              
190             =item L<Catmandu::Bag>
191              
192             =item L<Catmandu::FileBag::Index>
193              
194             =item L<Catmandu::Droppable>
195              
196             =back
197              
198             The file Catmandu::Bag in this Catmandu::Store implements:
199              
200             =over 3
201              
202             =item L<Catmandu::Bag>
203              
204             =item L<Catmandu::FileBag>
205              
206             =item L<Catmandu::Droppable>
207              
208             =back
209              
210             =head1 SEE ALSO
211              
212             L<Catmandu::Store::File::BagIt::Index>,
213             L<Catmandu::Store::File::BagIt::Bag>,
214             L<Catmandu::Plugin::SideCar>,
215             L<Catmandu::FileStore>
216              
217             =cut