File Coverage

blib/lib/CPAN/Access/AdHoc/Archive.pm
Criterion Covered Total %
statement 94 104 90.3
branch 24 34 70.5
condition n/a
subroutine 21 22 95.4
pod 12 12 100.0
total 151 172 87.7


line stmt bran cond sub pod time code
1             package CPAN::Access::AdHoc::Archive;
2              
3 6     6   44563 use 5.008;
  6         15  
  6         216  
4              
5 6     6   29 use strict;
  6         7  
  6         177  
6 6     6   22 use warnings;
  6         8  
  6         149  
7              
8 6     6   23 use Cwd ();
  6         6  
  6         119  
9 6         1341 use CPAN::Access::AdHoc::Util qw{
10             __attr __expand_distribution_path __guess_media_type :carp
11 6     6   1963 };
  6         11  
12 6     6   3931 use CPAN::Meta ();
  6         152388  
  6         154  
13 6     6   3693 use HTTP::Response ();
  6         130444  
  6         189  
14 6     6   2893 use Module::Pluggable::Object;
  6         35844  
  6         214  
15 6     6   1822 use URI::file;
  6         18222  
  6         5793  
16              
17             our $VERSION = '0.000_194';
18              
19             # Note that this can be called as a mutator, but the mutator
20             # functionality is private to the invocant's class.
21             sub archive {
22 163     163 1 214 my ( $self, @value ) = @_;
23 163         369 my $attr = $self->__attr();
24              
25 163 100       267 if ( @value ) {
26 26 50       81 caller eq ref $self
27             or __wail( 'Attribute archive is read-only' );
28 26         49 $attr->{archive} = $value[0];
29 26         67 return $self;
30             } else {
31 137         416 return $attr->{archive};
32             }
33             }
34              
35             sub base_directory {
36 1     1 1 492 __weep( 'The base_directory() method must be overridden' );
37             }
38              
39             sub extract {
40 1     1 1 590 __weep( 'The extract() method must be overridden' );
41             }
42              
43             sub get_item_content {
44 1     1 1 649 __weep( 'The get_item_content() method must be overridden' );
45             }
46              
47             sub get_item_mtime {
48 1     1 1 578 __weep( 'The get_item_mtime() method must be overridden' );
49             }
50              
51             {
52             my @archivers = Module::Pluggable::Object->new(
53             search_path => 'CPAN::Access::AdHoc::Archive',
54             inner => 0,
55             require => 1,
56             )->plugins();
57              
58             sub __handle_http_response {
59 27     27   43 my ( $class, $resp ) = @_;
60              
61 27         55 foreach my $archiver ( @archivers ) {
62 45         156 my $archive;
63 45 100       284 defined( $archive = $archiver->__handle_http_response( $resp ) )
64             and return $archive;
65             }
66              
67 1         34 return;
68             }
69             }
70              
71             sub item_present {
72 1     1 1 588 __weep( 'The item_present() method must be overridden' );
73             }
74              
75             sub list_contents {
76 1     1 1 579 __weep( 'The list_contents() method must be overridden' );
77             }
78              
79             sub metadata {
80 5     5 1 3286 my ( $self ) = @_;
81              
82 5         24 foreach my $spec (
83             [ load_json_string => 'META.json' ],
84             [ load_yaml_string => 'META.yml' ],
85             ) {
86 5         6 my ( $method, $file ) = @{ $spec };
  5         11  
87 5 50       22 $self->item_present( $file )
88             or next;
89 5         346 my $meta;
90             eval {
91 5         16 $meta = CPAN::Meta->$method(
92             $self->get_item_content( $file ) );
93 5 50       8 } or do {
94 0         0 __whinge( "CPAN::Meta->$method() failed: $@" );
95 0         0 next;
96             };
97 5         60814 return $meta;
98              
99             }
100              
101 0         0 return;
102              
103             }
104              
105             # Note that this can be called as a mutator, but the mutator
106             # functionality is private to the invocant's class.
107             sub mtime {
108 27     27 1 216 my ( $self, @value ) = @_;
109 27         85 my $attr = $self->__attr();
110              
111 27 100       74 if ( @value ) {
112 26 50       68 caller eq ref $self
113             or __wail( 'Attribute archive is read-only' );
114 26         44 $attr->{mtime} = $value[0];
115 26         52 return $self;
116             } else {
117 1         8 return $attr->{mtime};
118             }
119             }
120              
121             # Note that this can be called as a mutator, but the mutator
122             # functionality is private to the invocant's class.
123             sub path {
124 35     35 1 1598 my ( $self, @value ) = @_;
125 35         84 my $attr = $self->__attr();
126              
127 35 100       70 if ( @value ) {
128 26 50       74 caller eq ref $self
129             or __wail( 'Attribute path is read-only' );
130 26         49 $attr->{path} = $value[0];
131 26         49 return $self;
132             } else {
133 9         90 return $attr->{path};
134             }
135             }
136              
137             sub wrap_archive {
138 11     11 1 3868 my ( $class, @args ) = @_;
139 11 100       51 my $opt = 'HASH' eq ref $args[0] ? shift @args : {};
140 11         22 my ( $fn ) = @args;
141 11 50       296 -f $fn
142             or __wail( "File $fn not found" );
143 11         18 my $content;
144             {
145 11         15 local $/ = undef;
  11         48  
146 11 50       371 open my $fh, '<', $fn or __wail( "Unable to open $fn: $!" );
147 11         30 binmode $fh;
148 11         226 $content = <$fh>;
149 11         122 close $fh;
150             }
151 11         18 my $path;
152 11 100       49 if ( defined $opt->{directory} ) {
    100          
153 2 100       17 defined $opt->{author}
154             and __wail(
155             q{Specifying both 'author' and 'directory' is ambiguous} );
156 1         3 $path = $opt->{directory};
157 1         5 $path =~ s{ (?
158 1         17 $path .= ( File::Spec->splitpath( $fn ) )[2];
159             } elsif ( defined $opt->{author} ) {
160 4         26 my $author_path = __expand_distribution_path( $opt->{author} );
161 4         12 $author_path =~ s{ / \z }{}smx;
162 4         89 $path = join '/', 'authors/id', $author_path,
163             ( File::Spec->splitpath( $fn ) )[2];
164             } else {
165 5         429 my $uri = URI::file->new( Cwd::abs_path( $fn ) );
166 5         4730 $path = $uri->as_string();
167             $path =~ s{ \A .* / (?= authors/ | modules/ ) }{}smx
168 5 50       224 or do {
169 0         0 my @parts = File::Spec->splitpath( $uri->file() );
170 0         0 my @dir = File::Spec->splitdir( $parts[1] );
171 0 0       0 $dir[-1] eq ''
172             and pop @dir;
173 0         0 my $author_path = __expand_distribution_path( $dir[-1] );
174 0         0 $author_path =~ s{ / \z }{}smx;
175 0         0 $path = join '/', 'authors/id', $author_path, $parts[2];
176             };
177             }
178 10         86 my $resp = HTTP::Response->new( 200, 'OK', undef, $content );
179 10         500 __guess_media_type( $resp, $path );
180 10         50 return $class->__handle_http_response( $resp );
181             }
182              
183             sub write : method { ## no critic (ProhibitBuiltInHomonyms)
184 0     0 1   __weep( 'The write() method must be overridden' );
185             }
186              
187             1;
188              
189             __END__