File Coverage

blib/lib/App/mymeta_requires.pm
Criterion Covered Total %
statement 67 91 73.6
branch 19 32 59.3
condition 0 2 0.0
subroutine 15 16 93.7
pod 0 6 0.0
total 101 147 68.7


line stmt bran cond sub pod time code
1 2     2   81806 use 5.008001;
  2         5  
2 2     2   6 use strict;
  2         2  
  2         30  
3 2     2   5 use warnings;
  2         2  
  2         79  
4              
5             package App::mymeta_requires;
6             # ABSTRACT: Extract module requirements from MYMETA files
7              
8             our $VERSION = '0.006';
9              
10             # Dependencies
11 2     2   755 use Class::Load qw/try_load_class/;
  2         24280  
  2         86  
12 2     2   843 use CPAN::Meta;
  2         39202  
  2         48  
13 2     2   9 use List::Util qw/max/;
  2         2  
  2         143  
14 2     2   989 use Getopt::Lucid ':all';
  2         29377  
  2         204  
15 2     2   10 use CPAN::Meta::Requirements;
  2         2  
  2         39  
16              
17 2     2   830 use Class::Tiny qw/opt/;
  2         4068  
  2         11  
18              
19             my $opt_spec = [
20             Param("file|f"),
21             Switch("verbose|v"),
22             Switch("report"),
23             Switch("help|h"),
24             Switch("runtime|r")->default(1),
25             Switch("configure|c")->default(1),
26             Switch("build|b")->default(1),
27             Switch("test|t")->default(1),
28             Switch("develop|d")->default(0),
29             Switch("recommends")->default(1),
30             Switch("suggests")->default(1),
31             ];
32              
33             sub BUILD {
34 11     11 0 30637 my $self = shift;
35 11         60 $self->{opt} = Getopt::Lucid->getopt($opt_spec);
36             }
37              
38             sub run {
39 11     11 0 18240 my $self = shift;
40 11 50       32 $self = $self->new unless ref $self;
41              
42 11 50       259 if ( $self->opt->get_help ) {
43 0         0 require File::Basename;
44 0         0 require Pod::Usage;
45 0         0 my $file = File::Basename::basename($0);
46 0         0 Pod::Usage::pod2usage();
47             }
48              
49 11 50       473 my $mymeta = $self->load_mymeta
50             or die "Could not load a MYMETA file\n";
51 11         34 my $prereqs = $self->merge_prereqs( $mymeta->effective_prereqs );
52 11 50       304 if ( $self->opt->get_report ) {
53 0         0 print for $self->prereq_report( $prereqs );
54             }
55             else {
56 11         344 my @missing = $self->find_missing( $prereqs );
57 11         545 print for sort @missing;
58             }
59 11         177 return 0;
60             }
61              
62             sub load_mymeta {
63 11     11 0 15 my $self = shift;
64 11 100       187 my @candidates = $self->opt->get_file
65             ? ($self->opt->get_file)
66             : qw/MYMETA.json MYMETA.yml META.json META.yml/;
67 11         553 for my $f ( @candidates ) {
68 23 100       198 next unless -r $f;
69 11 50       16 my $mymeta = eval { CPAN::Meta->load_file($f) }
  11         59  
70             or $self->_log("Error loading '$f': $@\n");
71 11 50       150346 if ( $mymeta ) {
72 11         41 $self->_log("Got MYMETA from '$f'\n");
73 11         430 return $mymeta;
74             }
75             }
76 0         0 return;
77             }
78              
79             sub merge_prereqs {
80 11     11 0 29089 my ($self, $prereqs) = @_;
81 11         29 my $merged = CPAN::Meta::Requirements->new;
82 11         84 for my $phase (qw(configure runtime build test develop)) {
83 55         1561 my $get_p = "get_$phase";
84 55 100       923 next unless $self->opt->$get_p;
85             # Always get 'requires'
86 46         1545 $merged->add_requirements( $prereqs->requirements_for( $phase, 'requires' ) );
87             # Maybe get other types
88 46         3607 for my $extra( qw/recommends suggests/ ) {
89 92         1781 my $get_x = "get_$extra";
90 92 100       1523 next unless $self->opt->$get_x;
91 76         2361 $merged->add_requirements( $prereqs->requirements_for( $phase, $extra ) );
92             }
93             }
94 11         356 return $merged;
95             }
96              
97             sub find_missing {
98 11     11 0 13 my ($self, $prereqs) = @_;
99 11         11 my @missing;
100 11         23 for my $mod ( $prereqs->required_modules ) {
101 75 50       805 next if $mod eq 'perl';
102 75 100       127 if ( try_load_class($mod) ) {
103 16 50       65468 push @missing, "$mod\n" unless $prereqs->accepts_module($mod, $mod->VERSION);
104             }
105             else {
106 59         14264 push @missing, "$mod\n";
107             }
108             }
109 11         152 return @missing;
110             }
111              
112             sub prereq_report {
113 0     0 0 0 my ( $self, $prereqs ) = @_;
114 0         0 my @report;
115 0         0 for my $mod ( sort $prereqs->required_modules ) {
116 0 0       0 next if $mod eq 'perl';
117 0         0 my $req = $prereqs->requirements_for_module($mod);
118 0 0       0 if ( try_load_class($mod) ) {
119 0   0     0 my $version = $mod->VERSION || "";
120 0         0 push @report, [ $mod, $version, $req ];
121             }
122             else {
123 0         0 push @report, [ $mod, "", $req ];
124             }
125             }
126 0         0 my $max_mod_len = max( map { length $_->[0] } @report );
  0         0  
127 0         0 my $max_ver_len = max( map { length $_->[1] } @report );
  0         0  
128 0         0 my $max_req_len = max( map { length $_->[2] } @report );
  0         0  
129              
130 0         0 unshift @report, [ "Module", "Have", "Want" ],
131             [ "-" x $max_mod_len, "-" x $max_ver_len, "-" x $max_req_len ];
132              
133             return map {
134 0         0 sprintf( "%-*s %-*s %-*s\n",
  0         0  
135             $max_mod_len, $_->[0], $max_ver_len, $_->[1], $max_req_len, $_->[2] )
136             } @report;
137             }
138              
139             sub _log {
140 11     11   11 my $self = shift;
141 11 50       233 warn "$_[0]\n" if $self->opt->get_verbose;
142             }
143              
144             1;
145              
146              
147             # vim: ts=2 sts=2 sw=2 et:
148              
149             __END__