File Coverage

blib/lib/WWW/AUR/Package.pm
Criterion Covered Total %
statement 139 146 95.2
branch 20 34 58.8
condition 2 2 100.0
subroutine 31 32 96.8
pod 5 7 71.4
total 197 221 89.1


line stmt bran cond sub pod time code
1             package WWW::AUR::Package;
2              
3 7     7   26864 use warnings 'FATAL' => 'all';
  7         7  
  7         245  
4 7     7   22 use strict;
  7         8  
  7         139  
5              
6 7     7   26 use File::Basename qw(basename);
  7         6  
  7         701  
7 7     7   24 use File::Path qw(make_path);
  7         7  
  7         281  
8 7     7   24 use File::Spec qw();
  7         6  
  7         77  
9 7     7   19 use Carp qw();
  7         6  
  7         71  
10              
11 7     7   2444 use WWW::AUR::Package::File qw();
  7         12  
  7         147  
12 7     7   30 use WWW::AUR::URI qw( pkgbuild_uri pkgfile_uri pkg_uri );
  7         5  
  7         317  
13 7     7   26 use WWW::AUR::RPC qw();
  7         5  
  7         96  
14 7     7   19 use WWW::AUR qw( _path_params _useragent );
  7         5  
  7         1134  
15              
16             ##############################################################################
17             # CONSTANTS
18             #-----------------------------------------------------------------------------
19              
20             #---CONSTRUCTOR---
21             sub new
22             {
23 8762     8762 0 8821 my $class = shift;
24 8762 50       11456 Carp::croak( "You must at least supply a name as argument" ) if @_ == 0;
25              
26 8762         6971 my $name = shift;
27 8762         10635 my %params = @_;
28              
29 8762         5140 my $info;
30 8762 100       9247 if ( $params{info} ) {
31 8655         6311 $info = $params{info};
32             } else {
33             # this might croak on error
34 107         176 $info = eval { WWW::AUR::RPC::info( $name ) };
  107         291  
35 107 100       525 Carp::croak( "Failed to find package: $name" ) unless ( $info );
36             }
37 8761         25004 $info->{git_clone_ro} = sprintf('https://%s/%s.git', $WWW::AUR::HOST, $name);
38 8761         13427 $info->{git_clone_rw} = sprintf('ssh+git://aur@%s/%s.git', $WWW::AUR::HOST, $name);
39              
40 8761         11953 my $self = bless { _path_params( @_ ),
41             pkgfile => "$name.src.tar.gz",
42             info => $info,
43             }, $class;
44              
45 8761         30722 return $self;
46             }
47              
48             sub _def_info_accessor
49             {
50 84     84   61 my ($field) = @_;
51              
52 7     7   29 no strict 'refs';
  7         9  
  7         3242  
53 84         254 *{ "WWW::AUR::Package::$field" } = sub {
54 5206     5206   18613 my ($self) = @_;
55 5206   100     11567 return $self->{info}{$field} || q{};
56 84         138 };
57             }
58              
59             for ( qw{ id name version desc category url urlpath
60             license votes outdated ctime mtime } ) {
61             _def_info_accessor( $_ );
62             }
63              
64             sub maintainer_name
65             {
66 1     1 1 1 my ($self) = @_;
67 1         3 return $self->{'info'}{'maintainer'}; # might be undef for orphan
68             }
69              
70             #---PUBLIC METHOD---
71             # Returns a copy of the package info as a hash...
72             sub info
73             {
74 0     0 1 0 my ($self) = @_;
75 0         0 return %{ $self->{info} };
  0         0  
76             }
77              
78             #---PRIVATE METHOD---
79             sub _download_url
80             {
81 8     8   10 my ($self) = @_;
82              
83 8         287 return pkgfile_uri( $self->name );
84             }
85              
86             #---OBJECT METHOD---
87             sub download_size
88             {
89 1     1 0 3 my ($self) = @_;
90 1         188 Carp::cluck("Subroutine download_size does not work due to nginx not returning content-length");
91 1         112 return 0;
92             # TODO: Fix or remove this
93 0         0 my $ua = _useragent();
94 0         0 my $resp = $ua->head( $self->_download_url() );
95 0 0       0 return undef unless $resp->is_success;
96 0         0 return $resp->header( 'content-length' );
97             }
98              
99             #---OBJECT METHOD---
100             sub download
101             {
102 4     4 1 1035 my ($self, $usercb) = @_;
103              
104 4         14 my $pkgurl = $self->_download_url();
105             my $pkgpath = File::Spec->catfile( $self->{dlpath},
106 4         63 $self->{pkgfile} );
107              
108 4         577 make_path( $self->{dlpath} );
109              
110 4 50       415 open my $pkgfile, '>', $pkgpath or die "Failed to open $pkgpath:\n$!";
111 4         14 binmode $pkgfile;
112              
113             my $store_chunk = sub {
114 4     4   580620 my $chunk = shift;
115 4         37 print $pkgfile $chunk;
116 4         18 };
117              
118 4 100       12 if ( $usercb ) {
119 1         6 my $total = $self->download_size();
120 1         1 my $dled = 0;
121              
122 1         1 my $store = $store_chunk;
123             $store_chunk = sub {
124 1     1   205269 my $chunk = shift;
125 1         3 $dled += length $chunk;
126 1         6 $usercb->( $dled, $total );
127 1         7 $store->( $chunk );
128 1         5 };
129             }
130              
131 4         20 my $ua = _useragent();
132 4         722 my $resp = $ua->get( $self->_download_url(),
133             ':content_cb' => $store_chunk );
134 4 50       7374 close $pkgfile or die "close: $!";
135 4 50       18 Carp::croak( 'Failed to download package file:' . $resp->status_line )
136             unless $resp->is_success;
137              
138 4         64 $self->{pkgfile_obj} = WWW::AUR::Package::File->new
139             ( $pkgpath, _path_params( %$self ));
140              
141 4         123 return $pkgpath;
142             }
143              
144             #---PUBLIC METHOD---
145             # Purpose: Returns an object representing the package maintainer.
146             sub maintainer
147             {
148 1     1 1 273 my $self = shift;
149 1         3 my $mname = $self->maintainer_name();
150 1 50       4 return undef unless defined $mname;
151              
152             # Propogate parameters to our new Maintainer object...
153 1 50       3 Carp::croak 'Only a hash of path parameters are allowed as argument'
154             unless @_ % 2 == 0;
155              
156 1         9 require WWW::AUR::Maintainer;
157              
158             # Propogate parameters to our new Maintainer object...
159             # Path parameters given as arguments override the path params the
160             # package object was given...
161 1         5 my %params = ( _path_params( %$self ), _path_params( @_ ) );
162 1         9 my $mobj = WWW::AUR::Maintainer->new( $mname, %params );
163 1         7 return $mobj;
164             }
165              
166             sub _def_file_wrapper
167             {
168 42     42   35 my ($name) = @_;
169              
170 7     7   30 no warnings 'redefine';
  7         11  
  7         231  
171 7     7   22 no strict 'refs';
  7         26  
  7         795  
172 42         25 my $file_method = *{ $WWW::AUR::Package::File::{$name} }{ 'CODE' };
  42         82  
173 42         105 *{ $name } = sub {
174 3     3   352 my $self = shift;
175 3 50       22 return undef unless $self->{'pkgfile_obj'};
176 3         6 my $ret = eval { $file_method->( $self->{'pkgfile_obj'}, @_ ) };
  3         13  
177 3 50       12 die if $@;
178 3         24 return $ret;
179 42         99 };
180             }
181              
182             _def_file_wrapper( $_ ) for qw{ extract src_pkg_path
183             src_dir_path make_src_path build
184             bin_pkg_path };
185              
186             # Wrap the Package::File methods to call download first if we have to...
187             sub _def_dl_wrapper
188             {
189 14     14   16 my ($name) = @_;
190              
191 7     7   25 no warnings 'redefine';
  7         8  
  7         168  
192 7     7   22 no strict 'refs';
  7         7  
  7         1507  
193              
194 14         11 my $oldcode = *{ $name }{ 'CODE' };
  14         23  
195 14         30 *{ $name } = sub {
196 2     2   271 my $self = shift;
197 2 50       9 unless ( $self->{'pkgfile_obj'} ) { $self->download(); }
  2         8  
198 2         10 return $oldcode->( $self, @_ );
199 14         29 };
200             }
201              
202             _def_dl_wrapper( $_ ) for qw/ extract build /;
203              
204             #---PRIVATE METHOD---
205             # Purpose: Download the package's PKGBUILD without saving it to a file.
206             sub _download_pkgbuild
207             {
208 1     1   2 my ($self) = @_;
209              
210 1         2 my $name = $self->name;
211 1         5 my $pkgbuild_uri = pkgbuild_uri( $name );
212              
213 1         2 my $ua = _useragent();
214 1         158 my $resp = $ua->get( $pkgbuild_uri );
215              
216 1 50       165805 Carp::croak "Failed to download ${name}'s PKGBUILD: "
217             . $resp->status_line() unless $resp->is_success();
218              
219 1         13 return $resp->content();
220             }
221              
222             sub pkgbuild
223             {
224 2     2 1 6 my ($self) = @_;
225              
226             return $self->{pkgfile_obj}->pkgbuild
227 2 100       13 if $self->{pkgfile_obj};
228              
229             return $self->{pkgbuild_obj}
230 1 50       2 if $self->{pkgbuild_obj};
231              
232 1         3 my $pbtext = $self->_download_pkgbuild;
233              
234 1         43 $self->{pkgbuild_txt} = $pbtext;
235 1         2 $self->{pkgbuild_obj} = eval { WWW::AUR::PKGBUILD->new( $pbtext ) };
  1         9  
236 1 50       3 Carp::confess if $@; # stack trace
237              
238 1         3 return $self->{pkgbuild_obj};
239             }
240              
241             1;