File Coverage

blib/lib/File/Copy/Recursive/Verify.pm
Criterion Covered Total %
statement 36 36 100.0
branch 2 2 100.0
condition n/a
subroutine 10 10 100.0
pod 2 2 100.0
total 50 50 100.0


line stmt bran cond sub pod time code
1             package File::Copy::Recursive::Verify;
2 2     2   28956 use strict;
  2         3  
  2         45  
3 2     2   6 use warnings;
  2         2  
  2         61  
4              
5             our $VERSION = '0.1.0';
6              
7 2     2   737 use Path::Tiny;
  2         7826  
  2         116  
8 2     2   809 use Try::Tiny::Retry ':all';
  2         4479  
  2         262  
9 2     2   841 use File::Copy::Verify qw(verify_copy);
  2         10369  
  2         123  
10              
11 2         11 use Class::Tiny qw(src_dir dst_dir),
12             {
13             tries => 10,
14             hash_algo => 'MD5',
15             src_hash => {},
16             dst_hash => {},
17 2     2   12 };
  2         3  
18              
19 2     2   1309 use parent 'Exporter';
  2         3  
  2         7  
20              
21             our @EXPORT_OK = qw(verify_rcopy rcopy);
22              
23             =encoding utf-8
24              
25             =head1 NAME
26              
27             File::Copy::Recursive::Verify - data-safe recursive copy
28              
29             =head1 SYNOPSIS
30              
31             use File::Copy::Recursive::Verify qw(verify_rcopy);
32              
33             verify_rcopy($dir_a, $dir_b);
34              
35             #OOP equivalent
36              
37             File::Copy::Recursive::Verify->new(
38             src_dir => $dir_a,
39             dst_dir => $dir_b,
40             )->copy();
41              
42             #some complex copy - I know SHA-256 hash of subdir/a.dat file
43             #tree $dir_a:
44             #.
45             #├── c.dat
46             #└── subdir
47             # ├── a.dat
48             # └── b.dat
49              
50             verify_rcopy($dir_a, $dir_b, {tries => 3, hash_algo => 'SHA-256', src_hash => {'subdir/a.dat' => '0'x64}});
51              
52             #OOP equivalent
53              
54             File::Copy::Recursive::Verify->new(
55             src_dir => $dir_a,
56             dst_dir => $dir_b,
57             tries => 3,
58             hash_algo => 'SHA-256',
59             src_hash => {'subdir/a.dat' => 0x64},
60             )->copy();
61              
62             =head1 DESCRIPTION
63              
64             Use L for recursive copy.
65              
66             =head1 FUNCTIONS
67              
68             =head2 verify_rcopy($src_dir, $dst_dir, $options)
69              
70             functional api
71              
72             Recusive copy of C to C.
73              
74             Retry mechanism is via L (Each file will try verify_copy 10 times with exponential backoff in default).
75              
76             As verification digest are use fastest I in default.
77              
78             C<$options> is HashRef of L.
79              
80             return I of copied files (key source, value destination)
81              
82             =cut
83              
84             sub verify_rcopy {
85 4     4 1 19584 my ($src_dir, $dst_dir, $options) = @_;
86              
87 4         43 return File::Copy::Recursive::Verify->new(
88             src_dir => $src_dir,
89             dst_dir => $dst_dir,
90             %$options
91             )->copy();
92             }
93              
94             =head2 rcopy
95              
96             alias of C
97              
98             =cut
99              
100             sub rcopy;
101             *rcopy = \&verify_rcopy;
102              
103             =head1 METHODS
104              
105             =head2 new(%attributes)
106              
107             =head3 %attributes
108              
109             =head4 src_dir
110              
111             source dir
112              
113             =head4 src_hash
114              
115             source I of path -> hash
116              
117             =head4 dst_dir
118              
119             destination dir
120              
121             =head4 dst_hash
122              
123             destination I of path -> hash
124              
125             =head4 hash_algo
126              
127             hash algorithm
128              
129             default I
130              
131             =head4 tries
132              
133             number of tries
134              
135             more about retry - L
136              
137             =head2 copy;
138              
139             start recursive copy
140              
141             return I of copied files (key source, value destination)
142              
143             =cut
144              
145             sub copy {
146 4     4 1 178 my ($self) = @_;
147              
148             return path($self->src_dir)->visit(
149             sub {
150 16     16   1798 my ($path, $copied) = @_;
151              
152 16 100       32 return if $path->is_dir();
153              
154 12         318 my $rel_src = $path->relative($self->src_dir);
155 12         1862 my $dst = path($self->dst_dir, $rel_src);
156 12         269 $dst->parent->mkpath();
157 12         1160 my $rel_dst = $dst->relative($self->dst_dir);
158              
159             retry {
160             File::Copy::Verify->new(
161             src => $path,
162             src_hash => $self->src_hash->{$rel_src->stringify()},
163             dst => $dst,
164 12         2697 dst_hash => $self->dst_hash->{$rel_dst->stringify()},
165             hash_algo => $self->hash_algo
166             )->copy();
167              
168 10         10887 $copied->{$path} = $dst;
169             }
170 12         285 delay_exp { $self->tries, 1e5 }
171             catch {
172 2         1630 die $_;
173 12         1596 };
174             },
175 4         82 { recurse => 1 }
176             );
177             }
178              
179             =head1 LICENSE
180              
181             Copyright (C) Avast Software.
182              
183             This library is free software; you can redistribute it and/or modify
184             it under the same terms as Perl itself.
185              
186             =head1 AUTHOR
187              
188             Jan Seidl Eseidl@avast.comE
189              
190             =cut
191              
192             1;