CPAN-Visitor
view release on metacpan or search on metacpan
lib/CPAN/Visitor.pm view on Meta::CPAN
}
if ( ! $extract_ok ) {
warn "Couldn't extract '$job->{distpath}'\n" if $Archive::Extract::WARN;
return;
}
# most distributions unpack a single directory that we must enter
# but some behave poorly and unpack to the current directory
my @children = Path::Class::dir()->children;
if ( @children == 1 && -d $children[0] ) {
return Path::Class::dir($job->{tempdir}, $children[0])->absolute->stringify;
}
else {
return Path::Class::dir($job->{tempdir})->absolute->stringify;
}
}
sub _enter {
my $job = shift;
my $curdir = Path::Class::dir()->absolute;
my $target_dir = $job->{result}{extract} or return;
if ( -d $target_dir ) {
unless ( -x $target_dir ) {
warn "Directory '$target_dir' missing +x; trying to fix it\n"
unless $job->{quiet};
chmod 0755, $target_dir;
}
chdir $target_dir;
}
else {
warn "Can't chdir to directory '$target_dir'\n"
unless $job->{quiet};
return;
}
return $curdir;
}
sub _visit { 1 } # do nothing
# chdir out and clean up
sub _leave {
my $job = shift;
chdir $job->{result}{enter};
return 1;
}
sub _finish { 1 } # no special finish action
#--------------------------------------------------------------------------#
# iteration methods
#--------------------------------------------------------------------------#
# iterate()
#
# Arguments:
#
# jobs -- if greater than 1, distributions are processed in parallel
# via Parallel::ForkManager
#
# iterate() takes several optional callbacks which are run in the following
# order. Callbacks get a single hashref argument as described above under
# default actions.
#
# check -- whether the distribution should be processed; goes to next file
# if false; default is always true
#
# start -- used for any setup, logging, etc; default does nothing
#
# extract -- extracts a distribution into a temp directory or otherwise
# prepares for visiting; skips to finish action if it returns
# a false value; default returns the path to the extracted
# directory
#
# enter -- skips to the finish action if it returns false; default takes
# the result of extract, chdir's into it, and returns the
# original directory
#
# visit -- examine the distribution or otherwise do stuff; the default
# does nothing;
#
# leave -- default returns to the original directory (the result of enter)
#
# finish -- any teardown processing, logging, etc.
sub iterate {
my ($self, %params) = validated_hash( \@_,
jobs => { isa => 'Int', default => 0 },
check => { isa => 'CodeRef', default => \&_check },
start => { isa => 'CodeRef', default => \&_start },
extract => { isa => 'CodeRef', default => \&_extract },
enter => { isa => 'CodeRef', default => \&_enter },
visit => { isa => 'CodeRef', default => \&_visit },
leave => { isa => 'CodeRef', default => \&_leave },
finish => { isa => 'CodeRef', default => \&_finish },
);
my $pm = Parallel::ForkManager->new( $params{jobs} > 1 ? $params{jobs} : 0 );
for my $distfile ( @{ $self->files } ) {
$pm->start and next;
$self->_iterate($distfile, \%params);
$pm->finish;
}
$pm->wait_all_children;
return 1;
}
sub _iterate {
my ($self, $distfile, $params) = @_;
my $curdir = Path::Class::dir()->absolute;
# $job outside eval so that later chdir to original directory
# happens before $job is destroyed and any tempdirs deleted
my $job;
eval {
$job = {
distfile => $distfile,
distpath => $self->_fullpath($distfile),
tempdir => File::Temp->newdir(),
stash => $self->stash,
quiet => $self->quiet,
lib/CPAN/Visitor.pm view on Meta::CPAN
=item *
C<leave> â code reference callback
=item *
C<finish> â code reference callback
=back
See L</ACTION CALLBACKS> for more. Generally, you only need to provide the
C<visit> callback, which is called from inside the unpacked distribution
directory.
The C<iterate> method always returns true.
=for Pod::Coverage BUILD
=head1 ACTION CALLBACKS
Each selected distribution is processed with a series of callback
functions. These are each passed a hash-ref with information about
the particular distribution being processed.
sub _my_visit {
my $job = shift;
# do stuff
}
The job hash-ref is initialized with the following fields:
=over 4
=item *
C<distfile> â the unique, short CPAN distfile name, e.g. DAGOLDEN/CPAN-Visitor-0.001.tar.gz
=item *
C<distpath> â the absolute path the distribution archive, e.g. /my/cpan/authors/id/D/DA/DAGOLDEN/CPAN-Visitor-0.001.tar.gz
=item *
C<tempdir> â a File::Temp directory object for extraction or other things
=item *
C<stash> â the 'stash' hashref from the Visitor object
=item *
C<quiet> â the 'quiet' flag from the Visitor object
=item *
C<result> â an empty hashref to start; the return values from each action are added and may be referenced by subsequent actions
=back
The C<result> field is used to accumulate the return values from action
callbacks. For example, the return value from the default 'extract' action is
the unpacked distribution directory:
$job->{result}{extract} # distribution directory path
You do not need to store the results yourself â the C<iterate> method
takes care of it for you.
Callbacks occur in the following order. Some callbacks skip further
processing if the return value is false.
=over 4
=item *
C<check> â determines whether the distribution should be processed; goes to next file if false; default is always true
=item *
C<start> â used for any setup, logging, etc; default does nothing
=item *
C<extract> â operate on the tarball to prepare for visiting; skips to finish action if it returns a false value; the default extracts a distribution into a temp directory and returns the path to the extracted directory; if the C<stash> has a true v...
=item *
C<enter> â skips to the finish action if it returns false; default takes the result of extract, chdir's into it, and returns the original directory; if the extract result is missing the +x permissions, this will attempt to add it before calling chd...
=item *
C<visit> â examine the distribution or otherwise do stuff; the default does nothing;
=item *
C<leave> â default returns to the original directory (the result of enter)
=item *
C<finish> â any teardown processing, logging, etc.
=back
These allow complete customization of the iteration process. For example,
one could do something like this:
=over 4
=item *
replace the default C<extract> callback with one that returns an arrayref of distribution files without actually unpacking it into a physical directory
=item *
replace the default C<enter> callback with one that does nothing but return a true value; replace the default C<leave> callback likewise
=item *
have the C<visit> callback get the C<< $job->{result}{extract} >> listing and examine it for the presence of certain files
=back
This could potentially speed up iteration if only the file names within
the distribution are of interest and not the contents of the actual files.
=head1 SEE ALSO
=over 4
( run in 2.410 seconds using v1.01-cache-2.11-cpan-cdf2f3d4e48 )