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   2306 use 5.006;
  2         7  
4 2     2   11 use strict;
  2         2  
  2         49  
5 2     2   9 use warnings;
  2         4  
  2         137  
6              
7             our $VERSION = '0.005';
8              
9             package App::ReportPrereqs;
10              
11 2     2   1876 use ExtUtils::MakeMaker ();
  2         238842  
  2         80  
12 2     2   20 use File::Basename qw(fileparse);
  2         5  
  2         160  
13 2     2   1581 use Getopt::Long qw(GetOptions);
  2         22508  
  2         15  
14 2     2   2310 use HTTP::Tiny 0.014 ();
  2         104784  
  2         86  
15 2     2   21 use List::Util qw(max);
  2         6  
  2         293  
16 2     2   1467 use Module::CPANfile ();
  2         31680  
  2         74  
17 2     2   1220 use Module::Path qw(module_path);
  2         1573  
  2         154  
18 2     2   16 use version 0.77 ();
  2         41  
  2         2040  
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   75807 my $with_develop = 0;
29 16         50 my @features;
30 16 100       84 return _usage() if !GetOptions( 'with-develop' => \$with_develop, 'with-feature=s@' => \@features );
31              
32 15         3423 my $cpanfile = 'cpanfile';
33 15         23 my $cpanfile_src = $cpanfile;
34              
35 15 100       49 if ( @ARGV == 1 ) {
    100          
36 2         3 $cpanfile_src = $ARGV[0];
37              
38 2         31 my $res = HTTP::Tiny->new->get($cpanfile_src);
39 2 100       375 if ( !$res->{success} ) {
40 1         4 print {*STDERR} $res->{content};
  1         28  
41 1         9 return 1;
42             }
43              
44 1         6 $cpanfile = \$res->{content};
45             }
46             elsif (@ARGV) {
47 1         4 return _usage();
48             }
49              
50 13         16 my $prereqs;
51 13 100       21 if ( !eval { $prereqs = Module::CPANfile->load($cpanfile)->prereqs_with(@features); 1; } ) {
  13         114  
  10         29211  
52 3         1323 my $error = $@;
53 3         5 print {*STDERR} "\n$error\n";
  3         131  
54 3         29 return 1;
55             }
56              
57 10         25 my @full_reports;
58             my @dep_errors;
59              
60             PHASE:
61 10         25 for my $phase (qw(configure build test runtime develop)) {
62 50 100 100     188 next PHASE if ( $phase eq 'develop' ) and ( !$with_develop );
63              
64             TYPE:
65 42         58 for my $type (qw(requires recommends suggests conflicts)) {
66 168         338 my $req_ref = $prereqs->requirements_for( $phase, $type )->as_string_hash;
67 168         10961 my @modules = grep { $_ ne 'perl' } keys %{$req_ref};
  74         144  
  168         293  
68 168 100       469 next TYPE if !@modules;
69              
70 30         83 my $title = "\u$phase \u$type";
71 30         57 my @reports = ( [qw(Module Want Have)] );
72              
73             MODULE:
74 30         91 for my $module ( sort @modules ) {
75 62         108 my $want = $req_ref->{$module};
76 62 50       159 if ( !defined $want ) {
    100          
77 0         0 $want = 'undef';
78             }
79             elsif ( $want eq '0' ) {
80 58         84 $want = 'any';
81             }
82              
83 62 100       98 my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required";
84              
85 62         148 my $mod_path = module_path($module);
86              
87 62 100       30026 if ( defined $mod_path ) {
88 31         235 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     9837 if ( ( !defined $have )
      66        
94             or ( $have !~ m{ ^ v? [0-9_\.\-]+ $ }xsm )
95 29         534 or ( !eval { version->parse($have) } ) )
96             {
97 2         4 $have = 'undef';
98             }
99              
100 31         165 push @reports, [ $module, $want, $have ];
101              
102 31 100       97 next MODULE if $type ne 'requires';
103              
104 22 100       37 if ( $have eq 'undef' ) {
105 2         6 push @dep_errors, "$module version unknown ($req_string)";
106 2         8 next MODULE;
107             }
108              
109 20 100       69 if ( !$prereqs->requirements_for( $phase, $type )->accepts_module( $module => $have ) ) {
110 1         94 push @dep_errors, "$module version '$have' is not in required range '$want'";
111 1         5 next MODULE;
112             }
113              
114 19         1915 next MODULE;
115             }
116              
117 31         162 push @reports, [ $module, $want, 'missing' ];
118              
119 31 100       76 next MODULE if $type ne 'requires';
120              
121 22         73 push @dep_errors, "$module is not installed ($req_string)";
122             }
123              
124 30         77 push @full_reports, "=== $title ===\n\n";
125              
126 30         59 my $ml = max( map { length $_->[0] } @reports );
  92         194  
127 30         44 my $wl = max( map { length $_->[1] } @reports );
  92         123  
128 30         40 my $hl = max( map { length $_->[2] } @reports );
  92         120  
129              
130 30         109 splice @reports, 1, 0, [ q{-} x $ml, q{-} x $wl, q{-} x $hl ];
131 30         46 push @full_reports, map { sprintf " %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2] } @reports;
  122         423  
132              
133 30         147 push @full_reports, "\n";
134             }
135             }
136              
137 10 50       22 if (@full_reports) {
138 10         395 print "Versions for all modules listed in $cpanfile_src:\n\n", @full_reports;
139             }
140              
141 10 100       49 if (@dep_errors) {
142 9         93 print "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n\n";
143 9         89 print "The following REQUIRED prerequisites were not satisfied:\n\n";
144              
145 9         29 for my $error (@dep_errors) {
146 25         232 print $error, "\n";
147             }
148             }
149              
150 10         218 return;
151             }
152              
153             sub _usage {
154 2     2   792 my $basename = fileparse($0);
155              
156 2         5 print {*STDERR} "usage: $basename [--with-{develop,feature=id}] [URL]\n";
  2         48  
157 2         28 return 2;
158             }
159              
160             1;
161              
162             __END__