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   53120 use 5.008;
  6         18  
  6         214  
4              
5 6     6   29 use strict;
  6         10  
  6         172  
6 6     6   27 use warnings;
  6         11  
  6         144  
7              
8 6     6   30 use Cwd ();
  6         7  
  6         137  
9 6         1410 use CPAN::Access::AdHoc::Util qw{
10             __attr __expand_distribution_path __guess_media_type :carp
11 6     6   2687 };
  6         16  
12 6     6   29223 use CPAN::Meta ();
  6         244429  
  6         162  
13 6     6   6663 use HTTP::Response ();
  6         192350  
  6         188  
14 6     6   5445 use Module::Pluggable::Object;
  6         51756  
  6         221  
15 6     6   3399 use URI::file;
  6         27926  
  6         7272  
16              
17             our $VERSION = '0.000_18';
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 290 my ( $self, @value ) = @_;
23 163         521 my $attr = $self->__attr();
24              
25 163 100       564 if ( @value ) {
26 26 50       92 caller eq ref $self
27             or __wail( 'Attribute archive is read-only' );
28 26         78 $attr->{archive} = $value[0];
29 26         97 return $self;
30             } else {
31 137         791 return $attr->{archive};
32             }
33             }
34              
35             sub base_directory {
36 1     1 1 526 __weep( 'The base_directory() method must be overridden' );
37             }
38              
39             sub extract {
40 1     1 1 551 __weep( 'The extract() method must be overridden' );
41             }
42              
43             sub get_item_content {
44 1     1 1 532 __weep( 'The get_item_content() method must be overridden' );
45             }
46              
47             sub get_item_mtime {
48 1     1 1 503 __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   54 my ( $class, $resp ) = @_;
60              
61 27         70 foreach my $archiver ( @archivers ) {
62 45         231 my $archive;
63 45 100       411 defined( $archive = $archiver->__handle_http_response( $resp ) )
64             and return $archive;
65             }
66              
67 1         42 return;
68             }
69             }
70              
71             sub item_present {
72 1     1 1 563 __weep( 'The item_present() method must be overridden' );
73             }
74              
75             sub list_contents {
76 1     1 1 483 __weep( 'The list_contents() method must be overridden' );
77             }
78              
79             sub metadata {
80 5     5 1 13430 my ( $self ) = @_;
81              
82 5         30 foreach my $spec (
83             [ load_json_string => 'META.json' ],
84             [ load_yaml_string => 'META.yml' ],
85             ) {
86 5         10 my ( $method, $file ) = @{ $spec };
  5         12  
87 5 50       30 $self->item_present( $file )
88             or next;
89 5         613 my $meta;
90             eval {
91 5         21 $meta = CPAN::Meta->$method(
92             $self->get_item_content( $file ) );
93 5 50       13 } or do {
94 0         0 __whinge( "CPAN::Meta->$method() failed: $@" );
95 0         0 next;
96             };
97 5         88015 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 240 my ( $self, @value ) = @_;
109 27         115 my $attr = $self->__attr();
110              
111 27 100       103 if ( @value ) {
112 26 50       102 caller eq ref $self
113             or __wail( 'Attribute archive is read-only' );
114 26         86 $attr->{mtime} = $value[0];
115 26         74 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 3720 my ( $self, @value ) = @_;
125 35         107 my $attr = $self->__attr();
126              
127 35 100       92 if ( @value ) {
128 26 50       94 caller eq ref $self
129             or __wail( 'Attribute path is read-only' );
130 26         66 $attr->{path} = $value[0];
131 26         79 return $self;
132             } else {
133 9         110 return $attr->{path};
134             }
135             }
136              
137             sub wrap_archive {
138 11     11 1 5091 my ( $class, @args ) = @_;
139 11 100       57 my $opt = 'HASH' eq ref $args[0] ? shift @args : {};
140 11         34 my ( $fn ) = @args;
141 11 50       384 -f $fn
142             or __wail( "File $fn not found" );
143 11         21 my $content;
144             {
145 11         24 local $/ = undef;
  11         53  
146 11 50       506 open my $fh, '<', $fn or __wail( "Unable to open $fn: $!" );
147 11         37 binmode $fh;
148 11         330 $content = <$fh>;
149 11         160 close $fh;
150             }
151 11         29 my $path;
152 11 100       61 if ( defined $opt->{directory} ) {
    100          
153 2 100       14 defined $opt->{author}
154             and __wail(
155             q{Specifying both 'author' and 'directory' is ambiguous} );
156 1         3 $path = $opt->{directory};
157 1         7 $path =~ s{ (?
158 1         22 $path .= ( File::Spec->splitpath( $fn ) )[2];
159             } elsif ( defined $opt->{author} ) {
160 4         30 my $author_path = __expand_distribution_path( $opt->{author} );
161 4         17 $author_path =~ s{ / \z }{}smx;
162 4         84 $path = join '/', 'authors/id', $author_path,
163             ( File::Spec->splitpath( $fn ) )[2];
164             } else {
165 5         1129 my $uri = URI::file->new( Cwd::abs_path( $fn ) );
166 5         6457 $path = $uri->as_string();
167             $path =~ s{ \A .* / (?= authors/ | modules/ ) }{}smx
168 5 50       323 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         125 my $resp = HTTP::Response->new( 200, 'OK', undef, $content );
179 10         729 __guess_media_type( $resp, $path );
180 10         74 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__