File Coverage

blib/lib/Data/Resolver/FromTar.pm
Criterion Covered Total %
statement 99 102 97.0
branch 18 22 81.8
condition n/a
subroutine 19 19 100.0
pod 6 6 100.0
total 142 149 95.3


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             package Data::Resolver::FromTar;
3 3     3   293809 use v5.24;
  3         24  
4 3     3   19 use warnings;
  3         7  
  3         202  
5 3     3   16 use experimental 'signatures';
  3         25  
  3         24  
6              
7 3     3   581 use File::Spec::Unix ();
  3         7  
  3         82  
8 3     3   3115 use Archive::Tar ();
  3         362467  
  3         115  
9 3     3   28 use Archive::Tar::Constant ();
  3         8  
  3         805  
10              
11             sub __pass_if_type ($taf, $t) { $taf if defined($taf) && $taf->type == $t }
12              
13             sub __trim ($key) { $key =~ s{\A \./+ | /+ \z}{}rgmxs }
14              
15             sub __normalize_prefix ($key) {
16             $key =~ s{\A \./+ }{}mxs;
17             return '' unless length($key);
18             return $key =~ s{/*\z}{/}rmxs;
19             }
20              
21 3     3   475 use Moo;
  3         5750  
  3         27  
22 3     3   2765 no warnings 'experimental::signatures';
  3         7  
  3         134  
23 3     3   386 use namespace::clean;
  3         12222  
  3         28  
24              
25             extends 'Data::Resolver::Base';
26              
27             has root => (is => 'ro', required => 1);
28             has _lists => (is => 'lazy');
29             has prefix => (is => 'lazy', coerce => \&__normalize_prefix);
30             has _ta => (is => 'lazy');
31              
32 3     3   30 sub _build__lists ($self) {
  3         7  
  3         5  
33 3         6 my (@assets, %sub_resolvers);
34 3         59 my $prefix = $self->prefix;
35 3         29 my $lp = length($prefix);
36 3         54 for my $item ($self->_ta->list_files([qw< name type >])) {
37 18         486 my ($name, $type) = $item->@{qw< name type >};
38              
39 18         116 $name =~ s{\A \./+ | /+ \z}{}gmxs;
40 18 100       45 next if length($name) <= $lp;
41 14 100       34 next if substr($name, 0, $lp) ne $prefix;
42              
43 13         26 my $subname = substr($name, $lp);
44              
45 13 100       50 if ($subname =~ m{\A (.*?) /}mxs) {
    100          
    50          
46 7         18 $sub_resolvers{$1} = 1;
47             }
48             elsif ($type == Archive::Tar::Constant::DIR) {
49 3         11 $sub_resolvers{$subname} = 1;
50             }
51             elsif ($type == Archive::Tar::Constant::FILE) {
52 3         10 push @assets, $subname;
53             }
54             else {} # ignore this
55             }
56             return {
57 0         0 assets => [ sort { $a cmp $b } @assets ],
58 3         91 sub_resolvers => [ sort { $a cmp $b } keys %sub_resolvers ],
  0         0  
59             };
60             }
61              
62 2     2   32 sub _build_prefix ($self) { return '' }
  2         4  
  2         3  
  2         9  
63              
64 6     6   74 sub _build__ta ($self) {
  6         41  
  6         9  
65 6         47 my $tar = Archive::Tar->new;
66 6         114 $tar->read($self->root);
67 6         49765 return $tar;
68             }
69              
70 22     22   41 sub _child ($self, $key, $type) {
  22         52  
  22         41  
  22         41  
  22         36  
71 22         64 $key = __trim($key);
72 22         698 $key = $self->prefix . $key;
73 22         615 my $tar = $self->_ta;
74 22         166 for my $post ('', '/') {
75 33         7914 for my $pre ('', './') {
76 66         26305 my $full_key = join '', $pre, $key, $post;
77 66 100       238 next unless $tar->contains_file($full_key);
78 19         3103 my ($file) = $tar->get_files($full_key);
79 19 50       3029 return $file if $file->type == $type;
80 0         0 return;
81             }
82             }
83 3         2475 return;
84             }
85              
86 7     7 1 2818 sub get_asset ($self, $key) {
  7         14  
  7         17  
  7         13  
87 7 50       25 my $child = $self->_child($key, Archive::Tar::Constant::FILE)
88             or $self->not_found($key);
89 7         245 my (undef, undef, $basename) = File::Spec::Unix->splitpath($key);
90 7         43 return $self->asset($basename => raw => $child->get_content);
91             }
92              
93 4     4 1 972 sub get_sub_resolver ($self, $key) {
  4         9  
  4         11  
  4         8  
94 4 50       15 my $child = $self->_child($key, Archive::Tar::Constant::DIR)
95             or $self->not_found($key);
96 4         77 return $self->new(root => $self->root, prefix => $child->name);
97             }
98              
99 6     6 1 1289 sub has_asset ($self, $key) {
  6         13  
  6         11  
  6         10  
100 6 100       22 defined($self->_child($key, Archive::Tar::Constant::FILE)) ? 1 : 0;
101             }
102              
103 5     5 1 1902 sub has_sub_resolver ($self, $key) {
  5         11  
  5         10  
  5         8  
104 5 100       15 defined($self->_child($key, Archive::Tar::Constant::DIR)) ? 1 : 0;
105             }
106              
107 3     3 1 2955 sub list_asset_keys ($self) { return $self->_lists->{assets}->@* }
  3         6  
  3         12  
  3         93  
108              
109 2     2 1 1413 sub list_sub_resolver_keys ($s) { return $s->_lists->{sub_resolvers}->@* }
  2         4  
  2         4  
  2         55  
110              
111             1;