File Coverage

blib/lib/App/digestarchive.pm
Criterion Covered Total %
statement 93 94 98.9
branch 28 36 77.7
condition 7 11 63.6
subroutine 21 21 100.0
pod 1 8 12.5
total 150 170 88.2


line stmt bran cond sub pod time code
1             package App::digestarchive;
2              
3 6     6   24076 use strict;
  6         13  
  6         454  
4 6     6   90 use v5.8.0;
  6         18  
  6         300  
5 6     6   31 use warnings;
  6         11  
  6         265  
6 6     6   8583 use Archive::Tar;
  6         1285718  
  6         795  
7 6     6   76 use Compress::Zlib;
  6         13  
  6         2391  
8 6     6   43 use IO::Uncompress::Bunzip2 qw($Bunzip2Error);
  6         22  
  6         641  
9 6     6   6389 use Digest;
  6         3471  
  6         160  
10 6     6   28810 use Data::Dumper;
  6         109700  
  6         548  
11 6     6   7684 use Class::Accessor "antlers";
  6         18830  
  6         307  
12              
13             has digest_type => (is => "rw", type => "Str");
14             has archiver => (is => "rw", type => "Str");
15              
16             our $VERSION = '0.044';
17             our $DIGEST_TYPE = "MD5";
18             our $NONE_DIGEST_MESSAGE = "** can not get digest **";
19             our @ADD_ENTRY_METHODS = qw(digest link_or_real_name);
20              
21             sub new {
22              
23 5     5 1 645 my($class, %args) = @_;
24 5 50 33     96 bless {
25             digest_type => (exists $args{digest_type} && defined $args{digest_type}) ? $args{digest_type} : $DIGEST_TYPE,
26             # only Archive::Tar
27             archiver => Archive::Tar->new
28             }, $class;
29             }
30              
31              
32             sub read {
33              
34 13     13 0 8245 my($self, $file_or_fh_or_buffer) = @_;
35 13         62 my $buffer = $self->slurp($file_or_fh_or_buffer);
36 13         28 my $fh;
37              
38 13         53 my $magic = $self->get_magic($buffer);
39 13 100       106 if ($magic =~ Archive::Tar::GZIP_MAGIC_NUM) {
    100          
40 3 50       28 my $dest = Compress::Zlib::memGunzip($buffer) or die "Cannot uncompress: $gzerrno\n";
41 3         959 $fh = $self->scalar2fh($dest);
42             } elsif ($magic =~ Archive::Tar::BZIP_MAGIC_NUM) {
43 3 50       108 $fh = IO::Uncompress::Bunzip2->new(\$buffer) or die "Cannot open bunzip2: $Bunzip2Error\n";
44             } else {
45 7         34 $fh = $self->scalar2fh($buffer);
46             }
47 13         3342 $self->archiver->read($fh);
48             }
49              
50             sub all {
51              
52 3     3 0 5408 my($self, $filter_cb) = @_;
53 3         7 my @all;
54 3         14 while (my $f = $self->next) {
55              
56 15 100 66     68 if (defined $filter_cb && ref($filter_cb) && "CODE") {
      100        
57 5 100       17 if ($filter_cb->($f)) {
58 3         35 push @all, $f;
59             }
60             } else {
61 10         34 push @all, $f;
62             }
63             }
64 3         12 return \@all;
65             }
66              
67             sub next {
68              
69 19     19 0 1827 my $self = shift;
70 19         24 my $f = shift @{$self->archiver->_data};
  19         54  
71 19 100       259 return if !defined $f;
72              
73             {
74 6     6   4337 no strict "refs"; ## no critic
  6         17  
  6         224  
  16         31  
75 6     6   31 no warnings "redefine";
  6         11  
  6         9722  
76 16         27 my $pkg = ref $f;
77 16         36 foreach my $method (@ADD_ENTRY_METHODS) {
78 32         204 *{"$pkg\::$method"} = sub {
79 38     38   5512 my $self = shift;
80 38 100       112 if (scalar(@_) > 0) {
81 32         75 $self->{$method} = $_[0];
82             }
83 38         86 return $self->{$method};
84 32         110 };
85             }
86             }
87              
88             # set digest
89 16 100 66     53 $f->digest(($f->type == Archive::Tar::FILE or $f->type == Archive::Tar::HARDLINK) ? $self->digest($f->data) : $NONE_DIGEST_MESSAGE);
90             # set link_or_real_name
91 16 50       72 $f->link_or_real_name(($f->type == Archive::Tar::SYMLINK) ? sprintf "%s -> %s", $f->name, $f->linkname : $f->name);
92              
93 16         70 return $f;
94             }
95              
96              
97             sub digest {
98              
99 9     9 0 337 my($self, $data) = @_;
100 9 50       20 return if !defined $data;
101 9         31 return Digest->new($self->digest_type)->add($data)->hexdigest;
102             }
103              
104             sub scalar2fh {
105              
106 10     10 0 27 my($self, $buffer) = @_;
107 10 50   5   271 open my $fh, "<:scalar", \$buffer or die "change readable filehandle convert failed\n";
  5         61  
  5         9  
  5         53  
108 10         8929 return $fh;
109             }
110              
111             sub slurp {
112              
113 13     13 0 28 my($self, $file_or_fh_or_buffer) = @_;
114 13         29 my $fh;
115             my $buffer;
116 13 100       284 if (ref($file_or_fh_or_buffer) eq "GLOB") {
    100          
117 3         7 $fh = $file_or_fh_or_buffer;
118             } elsif (-f $file_or_fh_or_buffer) {
119 7 50       351 open $fh, "<", $file_or_fh_or_buffer or die "can not open file:$file_or_fh_or_buffer. $!";
120             }
121              
122 13 100       51 if (defined $fh) {
123 10         18 $buffer = do { local $/; <$fh> };
  10         44  
  10         651  
124 10         196 close $fh;
125             } else {
126 3         7 $buffer = $file_or_fh_or_buffer;
127             }
128 13         58 return $buffer;
129             }
130              
131              
132             sub get_magic {
133              
134 13     13 0 31 my($self, $data) = @_;
135 13 50       51 if (!defined $data) {
136 0         0 die "invalid data\n";
137             }
138 13         47 return substr $data, 0, 4;
139             }
140              
141              
142             1;
143             __END__