File Coverage

blib/lib/CPAN/Index/API/File/PackagesDetails.pm
Criterion Covered Total %
statement 54 60 90.0
branch 7 12 58.3
condition 2 3 66.6
subroutine 14 16 87.5
pod 3 5 60.0
total 80 96 83.3


line stmt bran cond sub pod time code
1             package CPAN::Index::API::File::PackagesDetails;
2             {
3             $CPAN::Index::API::File::PackagesDetails::VERSION = '0.007';
4             }
5              
6             # ABSTRACT: Interface to 02packages.details.txt
7              
8 1     1   235100 use strict;
  1         2  
  1         43  
9 1     1   6 use warnings;
  1         1  
  1         35  
10              
11 1     1   3502 use URI;
  1         5597  
  1         36  
12 1     1   1038 use URI::file;
  1         7097  
  1         46  
13 1     1   1159 use Path::Class qw(file dir);
  1         30320  
  1         107  
14 1     1   13 use Carp qw(croak);
  1         3  
  1         55  
15 1     1   7 use List::Util qw(first);
  1         2  
  1         123  
16 1     1   1043 use namespace::autoclean;
  1         27623  
  1         9  
17 1     1   2463 use Moose;
  1         521217  
  1         11  
18              
19             with qw(
20             CPAN::Index::API::Role::Writable
21             CPAN::Index::API::Role::Readable
22             CPAN::Index::API::Role::Clonable
23             CPAN::Index::API::Role::HavingFilename
24             CPAN::Index::API::Role::HavingGeneratedBy
25             );
26              
27             has uri => (
28             is => 'ro',
29             isa => 'Str',
30             required => 1,
31             lazy_build => 1,
32             );
33              
34             has repo_uri => (
35             is => 'ro',
36             isa => 'Str',
37             );
38              
39             has description => (
40             is => 'ro',
41             isa => 'Str',
42             required => 1,
43             default => 'Package names found in directory $CPAN/authors/id/',
44             );
45              
46             has columns => (
47             is => 'ro',
48             isa => 'Str',
49             required => 1,
50             default => 'package name, version, path',
51             );
52              
53             has intended_for => (
54             is => 'ro',
55             isa => 'Str',
56             required => 1,
57             default => 'Automated fetch routines, namespace documentation.',
58             );
59              
60             has packages => (
61             is => 'bare',
62             isa => 'ArrayRef[HashRef]',
63             default => sub { [] },
64             traits => ['Array'],
65             handles => {
66             package_count => 'count',
67             packages => 'elements',
68             add_package => 'push',
69             },
70             );
71              
72             sub BUILDARGS {
73 5     5 1 29 my ( $class, %args ) = @_;
74              
75 5 50 66     29 if ( $args{uri} or $args{repo_uri} )
    0          
76             {
77 5         173 return \%args;
78             }
79             elsif ($args{repo_path})
80             {
81 0         0 $args{repo_uri} = URI::file->new(
82             dir($args{repo_path})->absolute,
83             )->as_string;
84              
85 0         0 return \%args;
86             }
87             else
88             {
89 0         0 croak "Either 'uri', 'repo_uri' or 'repo_path' is required";
90             }
91             }
92              
93             sub _build_uri {
94 3     3   6 my $self = shift;
95 3         118 my $uri = URI->new($self->repo_uri);
96 6         199 $uri->path_segments(
97 3         4153 grep { $_ ne '' } $uri->path_segments,
98             file($self->default_location)->dir->dir_list,
99             file($self->default_location)->basename,
100             );
101 3         200 return $uri->as_string;
102             }
103              
104             sub package
105             {
106 0     0 0 0 my ($self, $name) = @_;
107 0     0   0 return first { $_->{name} eq $name } $self->packages;
  0         0  
108             }
109              
110             sub sorted_packages
111             {
112 3     3 0 19 my $self = shift;
113 3         141 return sort { $a->{name} cmp $b->{name} } $self->packages;
  10         27  
114             }
115              
116             sub parse {
117 2     2 1 4 my ( $self, $content ) = @_;
118              
119 2         16 my %map = (
120             'File' => 'file',
121             'URL' => 'uri',
122             'Description' => 'description',
123             'Columns' => 'columns',
124             'Intended-For' => 'intended_for',
125             'Written-By' => 'generated_by',
126             'Line-Count' => 'line_count',
127             'Last-Updated' => 'last_generated',
128             );
129              
130 2         12 my @lines = split "\n", $content;
131 2         4 my ( %args, @packages );
132              
133 2         6 while ( my $line = shift @lines ) {
134 16 50       40 last if $line =~ /^\s*$/;
135 16 50       69 next unless my ( $key, $value ) = $line =~ /^([^:]+):\s*(.*)/;
136 16         48 $args{$map{$key}} = $value;
137             }
138              
139 2         5 foreach my $line ( @lines ) {
140 4         12 my ( $name, $version, $distribution ) = split ' ', $line;
141              
142             # normalize missing version
143 4 100       13 undef $version if $version eq 'undef';
144              
145 4         12 my $package = {
146             name => $name,
147             version => $version,
148             distribution => $distribution,
149             };
150 4         10 push @packages, $package;
151             }
152              
153 2 100       8 $args{packages} = \@packages if @packages;
154              
155 2         23 return %args;
156             }
157              
158 11     11 1 490 sub default_location { 'modules/02packages.details.txt.gz' }
159              
160             __PACKAGE__->meta->make_immutable;
161              
162              
163              
164              
165             =pod
166              
167             =head1 NAME
168              
169             CPAN::Index::API::File::PackagesDetails - Interface to 02packages.details.txt
170              
171             =head1 VERSION
172              
173             version 0.007
174              
175             =head1 SYNOPSIS
176              
177             my $pckdetails = CPAN::Index::File::PackagesDetails->parse_from_repo_uri(
178             'http://cpan.perl.org'
179             );
180              
181             foreach my $package ($pckdetails->packages) {
182             ... # do something
183             }
184              
185             =head1 DESCRIPTION
186              
187             This is a class to read and write 03modlist.data
188              
189             =head1 METHODS
190              
191             =head2 packages
192              
193             List of hashrefs representing packages indexed in the file. Each hashref
194             has the following structure:
195              
196             =over
197              
198             =item name
199              
200             Package name, e.g. C<Foo::Bar>.
201              
202             =item version
203              
204             Package version, e.g. C<0.001>.
205              
206             =item distribuiton
207              
208             Distribution the package belongs to, e.g. C<Foo-Bar-0.001>.
209              
210             =back
211              
212             =head2 package_count
213              
214             Number of packages indexed in the file.
215              
216             =head2 filename
217              
218             Name of this file - defaults to C<02packages.details.txt.gz>;
219              
220             =head2 description
221              
222             Short description of the file.
223              
224             =head2 intended_for
225              
226             Target consumers of the file.
227              
228             =head2 uri
229              
230             Absolute URI pointing to the file location.
231              
232             =head2 parse
233              
234             Parses the file and reurns its representation as a data structure.
235              
236             =head2 default_location
237              
238             Default file location - C<modules/02packages.details.txt.gz>.
239              
240             =head1 METHODS FROM ROLES
241              
242             =over
243              
244             =item <CPAN::Index::API::Role::Readable/read_from_string>
245              
246             =item <CPAN::Index::API::Role::Readable/read_from_file>
247              
248             =item <CPAN::Index::API::Role::Readable/read_from_tarball>
249              
250             =item <CPAN::Index::API::Role::Readable/read_from_repo_path>
251              
252             =item <CPAN::Index::API::Role::Readable/read_from_repo_uri>
253              
254             =item L<CPAN::Index::API::Role::Writable/tarball_is_default>
255              
256             =item L<CPAN::Index::API::Role::Writable/repo_path>
257              
258             =item L<CPAN::Index::API::Role::Writable/template>
259              
260             =item L<CPAN::Index::API::Role::Writable/content>
261              
262             =item L<CPAN::Index::API::Role::Writable/write_to_file>
263              
264             =item L<CPAN::Index::API::Role::Writable/write_to_tarball>
265              
266             =item L<CPAN::Index::API::Role::Clonable/clone>
267              
268             =item L<CPAN::Index::API::Role::HavingFilename/filename>
269              
270             =item L<CPAN::Index::API::Role::HavingGeneratedBy/generated_by>
271              
272             =item L<CPAN::Index::API::Role::HavingGeneratedBy/last_generated>
273              
274             =back
275              
276             =head1 AUTHOR
277              
278             Peter Shangov <pshangov@yahoo.com>
279              
280             =head1 COPYRIGHT AND LICENSE
281              
282             This software is copyright (c) 2012 by Venda, Inc..
283              
284             This is free software; you can redistribute it and/or modify it under
285             the same terms as the Perl 5 programming language system itself.
286              
287             =cut
288              
289              
290             __DATA__
291             File: [% $self->filename %]
292             URL: [% $self->uri %]
293             Description: [% $self->description %]
294             Columns: [% $self->columns %]
295             Intended-For: [% $self->intended_for %]
296             Written-By: [% $self->generated_by %]
297             Line-Count: [% $self->package_count %]
298             Last-Updated: [% $self->last_generated %]
299             [%
300             if ($self->package_count)
301             {
302             $OUT .= "\n";
303             foreach my $package ($self->sorted_packages) {
304             $OUT .= sprintf "%-34s %5s %s\n",
305             $package->{name},
306             defined $package->{version} ? $package->{version} : 'undef',
307             $package->{distribution};
308             }
309             }
310             else
311             {
312             $OUT .= ''; # keeps Text::Template happy
313             }
314             %]