File Coverage

lib/CPAN/Mini/Visit/Filtered.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package CPAN::Mini::Visit::Filtered;
2              
3             our $VERSION = '0.01_06';
4              
5 2     2   2850 use MooseX::Declare;
  0            
  0            
6             use Moose::Util::TypeConstraints;
7              
8             =head1 NAME
9              
10             CPAN::Mini::Visit::Filtered - visit unpacked distributions in a filtered CPAN::Mini mirror
11              
12             =head1 SYNOPSIS
13              
14             my $visitor = CPAN::Mini::Visit::Filtered->new(
15             action => sub {
16             # XXX put something here
17             },
18             filter => sub { /briang/i },
19             );
20              
21             $visitor->visit_distributions;
22              
23             =head1 DESCRIPTION XXX
24              
25             =head1 RATIONALE XXX
26              
27             =cut
28              
29             class CPAN::Mini::Visit::Filtered {
30             use MooseX::StrictConstructor;
31              
32             use Archive::Extract qw();
33             use Carp qw();
34             use CPAN::DistnameInfo qw();
35             use Cwd qw();
36             use File::Find::Rule qw();
37             use File::Spec qw();
38             use File::Temp qw();
39             # CPAN::Mini
40              
41             =head1 CONSTRUCTOR
42              
43             new() returns a new CPAN::Mini::Visit::Filtered object. Parameters to new() should be
44             supplied as key=>value pairs. The following attributes are recognised.
45              
46             =head1 ATTRIBUTES
47              
48             Attributes of the CPAN::Mini::Visit::Filtered class are all read-only: they can be set only
49             when constructing an object. They all have getters, however, that can
50             be used at any time, though its doubtful that you'll need to.
51              
52             CPAN::Mini::Visit::Filtered objects have the following attributes:
53              
54             =head2 action
55              
56             Once the archive has been unpacked, the coderef stored in action will
57             be called. The subroutine will be passed a CPAN::DistnameInfo object.
58              
59             This parameter is mandatory.
60              
61             =cut
62              
63             has qw(action is ro isa CodeRef required 1);
64              
65             =head2 archive_types
66              
67             This is a regular expression that matches valid archives. The default
68             value matches C<< *.tar.gz >>, C<< *.tgz >>, C<< *.tar.bz2 >> and
69             C<< *.zip >>.
70              
71             =cut
72              
73             has qw(archive_types is ro),
74             default => sub { qr{\.(?:tar\.bz2|tar\.gz|tgz|zip)$} };
75              
76             =head2 cpan_base
77              
78             This is the base directory where the CPAN::Mini mirror is stored.
79              
80             This paramater is mandatory
81              
82             =cut
83              
84             has qw(cpan_base is ro isa Str required 1),
85             # default => sub {
86             # require CPAN::Mini;
87              
88             # my $config_file = CPAN::Mini->config_file({});
89             # Carp::croak("CPAN::Mini config file not located: $!")
90             # unless defined $config_file and -e $config_file;
91             # my %config = CPAN::Mini->read_config({quiet=>1});
92             # Carp::croak("You haven't defined 'cpan_base' and no 'local' option was found in $config_file")
93             # unless defined $config{local};
94             # return $config{local}
95             # },
96             trigger => sub {
97             my $self = shift;
98             my $base = $self->cpan_base;
99              
100             Carp::croak("Attribute (cpan_base) does not exist: '$base'")
101             unless -e $base;
102             Carp::croak("Attribute (cpan_base) is not a directory: '$base'")
103             unless -d _;
104             };
105              
106             =head2 filter
107              
108             This coderef is called before any archive is unpacked. The intention
109             is that this callback is used to filter out distributions you have no
110             interest in.
111              
112             The subroutine will be passed a CPAN::DistnameInfo object and $_ will
113             be set to the full path and filename of the file as stored in the
114             CPAN::Mini mirror. The function should return a true value if you wish
115             this archive to be processed further.
116              
117             By default all archives will be included. (With the possible exception
118             of Acme::*. See L<include_acme>.)
119              
120             =cut
121              
122             has qw(filter is ro isa CodeRef),
123             default => sub { sub {1} };
124              
125             =head2 include_acme
126              
127             Set this parameter to a true value if you wish to process the modules
128             from the Acme::* namespace. Traditionally, these modules are all
129             "jokes", and you may not wish to process them
130              
131             By default, the Acme distributions will not be included.
132              
133             =cut
134              
135             has qw(include_acme is ro isa Bool default 0);
136              
137             =head2 unpack_dir
138              
139             The directory where the distributions will be unpacked.
140              
141             By default, a temporary directory (as determined by
142             File::Temp::tempdir) will be allocated for you, and will be deleted
143             when no longer required.
144              
145             =cut
146              
147             has qw(unpack_dir is ro isa Str),
148             default => File::Temp::tempdir(
149             File::Spec->catfile(File::Spec->tmpdir, "cmvf-$$-XXXXXXXX"),
150             CLEANUP => 1
151             );
152              
153             # private
154              
155             # cache for CPAN::DI object
156             has qw(_distinfo is rw isa CPAN::DistnameInfo writer _set_distinfo);
157             has qw(_initial_dir is ro isa Str), default => Cwd::getcwd;
158              
159             =head1 METHODS
160              
161             =head2 distinfo
162              
163             =cut
164              
165             method distinfo(Str $archive) {
166             return $self->_distinfo
167             if defined $self->_distinfo
168             && $self->_distinfo->pathname eq $archive;
169              
170             return $self->_set_distinfo(CPAN::DistnameInfo->new($archive));
171             }
172              
173             =head2 find_archives
174              
175             =cut
176              
177             method find_archives() {
178             my $include_acme = $self->include_acme
179             ? sub { 1 }
180             : sub { $_[0]->dist !~ /^acme-/i };
181             my $filter = $self->filter;
182              
183             return grep {
184             my $info = $self->distinfo($_);
185             $include_acme->($info) && $filter->($info)
186             } File::Find::Rule->file
187             ->name($self->archive_types)
188             ->in( File::Spec->catdir($self->cpan_base, qw{authors id}) );
189             }
190              
191             =head2 visit_distributions
192              
193             =cut
194              
195             method visit_distributions() {
196             my $dest = $self->unpack_dir;
197              
198             for my $archive ($self->find_archives) {
199             my $ae = Archive::Extract->new(archive => $archive);
200             my $ok = $ae->extract( to => $dest ); # XXX and if it fails???
201              
202             my $info = $self->distinfo($archive);
203              
204             chdir $self->unpack_dir or die $!; # XXX
205             chdir $info->distvname or die $!;
206             chdir $self->_initial_dir or die $!;
207              
208             $self->action->($info);
209             }
210             }
211             };
212              
213             1;
214              
215             __END__
216              
217             # XXX Oh noes. They're all blank
218              
219             =head1 SEE ALSO
220              
221             =head1 AUTHOR
222              
223             =head1 BUGS
224              
225             =head1 COPYRIGHT & LICENSE
226              
227             =cut