App-perl-distrolint
view release on metacpan or search on metacpan
lib/App/perl/distrolint/CheckRole/EachFile.pm view on Meta::CPAN
# You may distribute under the terms of either the GNU General Public License
# or the Artistic License (the same terms as Perl itself)
#
# (C) Paul Evans, 2023-2026 -- leonerd@leonerd.org.uk
use v5.36;
use Object::Pad 0.800;
role App::perl::distrolint::CheckRole::EachFile 0.09;
use File::Find ();
use File::Basename qw( basename );
use List::Util 1.29 qw( any );
=head1 NAME
C<App::perl::distrolint::CheckRole::EachFile> - role for checks that iterate over files
=head1 DESCRIPTION
=for highlighter language=perl
This role provides a number of helper trampoline methods for implementing
check classes whose logic should iterate over various types of file found in
the distribution source.
=cut
=head1 METHODS
The following are trampoline methods. The first argument should either be a
code reference or a method name as a plain string. The remaining arguments
will be passed to the invoked code, along with the name of each selected file.
=cut
my @SKIP_TOP = qw(
blib
_build
);
my sub glob2regexp ( $s )
{
# Convert glob-like pattern into a regexp. Ish. It's not very good
$s =~ s{(\*\*)|(\*)|(\?)|(\.)|(.)}
{$1 ? ".+" : # ** becomes .+
$2 ? "[^/]+" : # * becomes [^/]+
$3 ? "." : # ? becomes .
$4 ? "\\." : # . becomes \.
quotemeta $5}ge;
return qr(^$s$);
}
method _run_foreach ( $opts, $method, @args )
{
my $ok = 1;
my @skip_patterns = split m/\s+/,
App::perl::distrolint::Config->check_config( $self, "skip", "" );
$_ = glob2regexp $_ for @skip_patterns;
File::Find::find({
no_chdir => 1,
preprocess => sub (@names) {
return sort { $a cmp $b } @names;
},
wanted => sub () {
my $path = $_;
return if $path eq ".";
$path =~ s{^\./}{};
my $basename = basename $path;
# skip hidden
$File::Find::prune = 1, return if $basename =~ m{^\..};
# skip toplevels
$File::Find::prune = 1, return if any { $_ eq $path } @SKIP_TOP;
-f $path or return;
return if $opts->{if_basename} and $basename !~ $opts->{if_basename};
$path =~ $_ and return for @skip_patterns;
$ok &= $self->$method( $path, @args );
},
}, "." );
return $ok;
}
=head2 run_for_each_file
$check->run_for_each_file( $method, @args );
Invokes the code once for every file found in the distribution.
=cut
method run_for_each_file ( $method, @args )
{
$self->_run_foreach( {}, $method, @args );
}
my %BASENAMES = (
perl => qr/\.PL$|\.pl$|\.pm$|\.t$/,
xs => qr/\.xs$/,
c => qr/\.c$|\.h$/,
);
my $SOURCE_BASENAMES = do {
my $re = join "|",
@BASENAMES{qw( perl xs c )},
qr/^typemap$/;
qr/$re/;
};
( run in 2.016 seconds using v1.01-cache-2.11-cpan-f4a522933cf )