File Coverage

bin/report-prereqs
Criterion Covered Total %
statement 111 112 99.1
branch 34 36 94.4
condition 7 9 77.7
subroutine 13 13 100.0
pod n/a
total 165 170 97.0


line stmt bran cond sub pod time code
1             #!perl
2              
3 2     2   1974 use 5.006;
  2         7  
4 2     2   9 use strict;
  2         4  
  2         45  
5 2     2   8 use warnings;
  2         3  
  2         125  
6              
7             our $VERSION = '0.006';
8              
9             package App::ReportPrereqs;
10              
11 2     2   1798 use ExtUtils::MakeMaker ();
  2         229304  
  2         77  
12 2     2   19 use File::Basename qw(fileparse);
  2         4  
  2         119  
13 2     2   1552 use Getopt::Long qw(GetOptions);
  2         22136  
  2         11  
14 2     2   2006 use HTTP::Tiny 0.014 ();
  2         100433  
  2         80  
15 2     2   18 use List::Util qw(max);
  2         3  
  2         212  
16 2     2   1198 use Module::CPANfile ();
  2         29963  
  2         63  
17 2     2   1035 use Module::Path qw(module_path);
  2         1342  
  2         130  
18 2     2   14 use version 0.77 ();
  2         41  
  2         1842  
19              
20             if ( !caller ) {
21             my $rc = _main();
22             exit 0 if !defined $rc;
23             exit 2 if $rc == 2;
24             exit 1;
25             }
26              
27             sub _main {
28 16     16   72875 my $with_develop = 0;
29 16         48 my @features;
30 16 100       77 return _usage() if !GetOptions( 'with-develop' => \$with_develop, 'with-feature=s@' => \@features );
31              
32 15         3261 my $cpanfile = 'cpanfile';
33 15         24 my $cpanfile_src = $cpanfile;
34              
35 15 100       41 if ( @ARGV == 1 ) {
    100          
36 2         4 $cpanfile_src = $ARGV[0];
37              
38 2         41 my $res = HTTP::Tiny->new->get($cpanfile_src);
39 2 100       310 if ( !$res->{success} ) {
40 1         3 print {*STDERR} $res->{content};
  1         64  
41 1         12 return 1;
42             }
43              
44 1         3 $cpanfile = \$res->{content};
45             }
46             elsif (@ARGV) {
47 1         8 return _usage();
48             }
49              
50 13         18 my $prereqs;
51 13 100       15 if ( !eval { $prereqs = Module::CPANfile->load($cpanfile)->prereqs_with(@features); 1; } ) {
  13         99  
  10         28623  
52 3         1232 my $error = $@;
53 3         5 print {*STDERR} "\n$error\n";
  3         102  
54 3         29 return 1;
55             }
56              
57 10         25 my @full_reports;
58             my @dep_errors;
59              
60             PHASE:
61 10         21 for my $phase (qw(configure build test runtime develop)) {
62 50 100 100     139 next PHASE if ( $phase eq 'develop' ) and ( !$with_develop );
63              
64             TYPE:
65 42         57 for my $type (qw(requires recommends suggests conflicts)) {
66 168         331 my $req_ref = $prereqs->requirements_for( $phase, $type )->as_string_hash;
67 168         10469 my @modules = grep { $_ ne 'perl' } keys %{$req_ref};
  74         132  
  168         286  
68 168 100       425 next TYPE if !@modules;
69              
70 30         92 my $title = "\u$phase \u$type";
71 30         59 my @reports = ( [qw(Module Want Have)] );
72              
73             MODULE:
74 30         82 for my $module ( sort @modules ) {
75 62         87 my $want = $req_ref->{$module};
76 62 50       158 if ( !defined $want ) {
    100          
77 0         0 $want = 'undef';
78             }
79             elsif ( $want eq '0' ) {
80 58         68 $want = 'any';
81             }
82              
83 62 100       105 my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required";
84              
85 62         158 my $mod_path = module_path($module);
86              
87 62 100       30679 if ( defined $mod_path ) {
88 31         210 my $have = MM->parse_version($mod_path); ## no critic (Modules::RequireExplicitInclusion)
89              
90             # This validation was added in EUMM 7.47_01 in ExtUtils::MM_Unix
91             # We use the same validation to make the file testable - otherwise the
92             # result depends on the version of EUMM used.
93 31 100 66     9731 if ( ( !defined $have )
      66        
94             or ( $have !~ m{ ^ v? [0-9_\.\-]+ $ }xsm )
95 29         490 or ( !eval { version->parse($have) } ) )
96             {
97 2         4 $have = 'undef';
98             }
99              
100 31         162 push @reports, [ $module, $want, $have ];
101              
102 31 100       87 next MODULE if $type ne 'requires';
103              
104 22 100       37 if ( $have eq 'undef' ) {
105 2         7 push @dep_errors, "$module version unknown ($req_string)";
106 2         6 next MODULE;
107             }
108              
109 20 100       70 if ( !$prereqs->requirements_for( $phase, $type )->accepts_module( $module => $have ) ) {
110 1         90 push @dep_errors, "$module version '$have' is not in required range '$want'";
111 1         4 next MODULE;
112             }
113              
114 19         1864 next MODULE;
115             }
116              
117 31         115 push @reports, [ $module, $want, 'missing' ];
118              
119 31 100       72 next MODULE if $type ne 'requires';
120              
121 22         75 push @dep_errors, "$module is not installed ($req_string)";
122             }
123              
124 30         76 push @full_reports, "=== $title ===\n\n";
125              
126 30         50 my $ml = max( map { length $_->[0] } @reports );
  92         207  
127 30         49 my $wl = max( map { length $_->[1] } @reports );
  92         121  
128 30         37 my $hl = max( map { length $_->[2] } @reports );
  92         119  
129              
130 30         102 splice @reports, 1, 0, [ q{-} x $ml, q{-} x $wl, q{-} x $hl ];
131 30         49 push @full_reports, map { sprintf " %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2] } @reports;
  122         401  
132              
133 30         144 push @full_reports, "\n";
134             }
135             }
136              
137 10 50       25 if (@full_reports) {
138 10         348 print "Versions for all modules listed in $cpanfile_src:\n\n", @full_reports;
139             }
140              
141 10 100       54 if (@dep_errors) {
142 9         96 print "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n\n";
143 9         84 print "The following REQUIRED prerequisites were not satisfied:\n\n";
144              
145 9         26 for my $error (@dep_errors) {
146 25         236 print $error, "\n";
147             }
148             }
149              
150 10         209 return;
151             }
152              
153             sub _usage {
154 2     2   789 my $basename = fileparse($0);
155              
156 2         6 print {*STDERR} "usage: $basename [--with-{develop,feature=id}] [URL]\n";
  2         51  
157 2         27 return 2;
158             }
159              
160             1;
161              
162             __END__