App-LintPrereqs

 view release on metacpan or  search on metacpan

lib/App/LintPrereqs.pm  view on Meta::CPAN

use Proc::ChildError qw(explain_child_error);
use Scalar::Util 'looks_like_number';
use Sort::Sub qw(prereq_ala_perlancar);
use Version::Util qw(version_gt version_ne);

our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2024-12-21'; # DATE
our $DIST = 'App-LintPrereqs'; # DIST
our $VERSION = '0.544'; # VERSION

our %SPEC;

our @EXPORT_OK = qw(lint_prereqs);

# create a merged list of prereqs from any phase
sub _create_prereqs_for_Any_phase {
    my $prereqs = shift;
    $prereqs->{Any}   = {};
    for my $phase (grep {$_ ne 'Any'} keys %$prereqs) {
        for my $mod (keys %{ $prereqs->{$phase} }) {
            my $v = $prereqs->{$phase}{$mod};
            if (exists $prereqs->{Any}{$mod}) {
                $prereqs->{Any}{$mod} = $v
                    if version_gt($v, $prereqs->{Any}{$mod});
            } else {
                $prereqs->{Any}{$mod} = $v;
            }
        }
    }
}

sub _scan_prereqs {
    my %args = @_;

    my $scanner = do {
        if ($args{scanner} eq 'lite') {
            require Perl::PrereqScanner::Lite;
            my $scanner = Perl::PrereqScanner::Lite->new;
            $scanner->add_extra_scanner('Moose');
            $scanner->add_extra_scanner('Version');
            $scanner;
        } elsif ($args{scanner} eq 'nqlite') {
            require Perl::PrereqScanner::NotQuiteLite;
            my $scanner = Perl::PrereqScanner::NotQuiteLite->new(
                parsers  => [qw/:installed -UniversalVersion/],
                suggests => 1,
            );
            $scanner;
        } else {
            require Perl::PrereqScanner;
            Perl::PrereqScanner->new;
        }
    };
    require File::Find;
    my %files; # key=phase, val=[file, ...]

    {
        $files{Runtime} = [];
        my @dirs = (grep {-d} (
            "lib", "bin", "script", "scripts",
            #"sample", "samples", "example", "examples" # decidedly not included
            #"share", # decidedly not included
            @{ $args{extra_runtime_dirs} // [] },
        ));
        last unless @dirs;
        find(
            sub {
                return unless -f;
                return if check_backup_filename(filename=>$_);
                push @{$files{Runtime}}, "$File::Find::dir/$_";
            },
            @dirs
        );
    }

    {
        my @dirs = (grep {-d} (
            "t", "xt",
            @{ $args{extra_test_dirs} // [] },
        ));
        last unless @dirs;
        find(
            sub {
                return unless -f;
                return if check_backup_filename(filename=>$_);
                return unless /\.(t|pl|pm)$/;
                push @{$files{Test}}, "$File::Find::dir/$_";
            },
            @dirs
        );
    }

    my %res; # key=phase, value=hash of {mod=>version , ...}
    for my $phase (keys %files) {
        $res{$phase} = {};
        for my $file (@{$files{$phase}}) {
            my $scanres = $scanner->scan_file($file);
            unless ($scanres) {
                log_trace("Scanned %s, got nothing", $file);
            }

            # if we use PP::NotQuiteLite, it returns PPN::Context which supports
            # a 'requires' method to return a CM:Requirements like the other
            # scanners
            my $reqs = $scanres->can("requires") ?
                $scanres->requires->as_string_hash : $scanres->as_string_hash;

            if ($scanres->can("suggests") && (my $sugs = $scanres->suggests)) {
                # currently it's not clear what makes PP:NotQuiteLite determine
                # something as a suggests requirement, so we include suggests as
                # a normal requires requirement.
                $sugs = $sugs->as_string_hash;
                for (keys %$sugs) {
                    $reqs->{$_} ||= $sugs->{$_};
                }
            }

            log_trace("Scanned %s, got: %s", $file, $reqs);
            for my $req (keys %$reqs) {
                my $v = $reqs->{$req};
                if (exists $res{$phase}{$req}) {
                    $res{$phase}{$req} = $v



( run in 0.927 second using v1.01-cache-2.11-cpan-39bf76dae61 )