line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Prereq::Meta; |
2
|
|
|
|
|
|
|
|
3
|
6
|
|
|
6
|
|
293655
|
use 5.010; # because Module::Extract::Use has this. |
|
6
|
|
|
|
|
55
|
|
4
|
|
|
|
|
|
|
|
5
|
6
|
|
|
6
|
|
28
|
use strict; |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
127
|
|
6
|
6
|
|
|
6
|
|
29
|
use warnings; |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
162
|
|
7
|
|
|
|
|
|
|
|
8
|
6
|
|
|
6
|
|
30
|
use Carp; |
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
351
|
|
9
|
6
|
|
|
6
|
|
2492
|
use CPAN::Meta; |
|
6
|
|
|
|
|
134237
|
|
|
6
|
|
|
|
|
238
|
|
10
|
6
|
|
|
6
|
|
59
|
use Exporter qw{ import }; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
246
|
|
11
|
6
|
|
|
6
|
|
3618
|
use ExtUtils::Manifest (); |
|
6
|
|
|
|
|
55731
|
|
|
6
|
|
|
|
|
192
|
|
12
|
6
|
|
|
6
|
|
61
|
use File::Find (); |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
81
|
|
13
|
6
|
|
|
6
|
|
29
|
use File::Glob (); |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
81
|
|
14
|
6
|
|
|
6
|
|
24
|
use File::Spec; |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
92
|
|
15
|
6
|
|
|
6
|
|
3282
|
use Module::Extract::Use; |
|
6
|
|
|
|
|
10476
|
|
|
6
|
|
|
|
|
212
|
|
16
|
6
|
|
|
6
|
|
15491
|
use Module::CoreList; |
|
6
|
|
|
|
|
557548
|
|
|
6
|
|
|
|
|
613
|
|
17
|
6
|
|
|
6
|
|
9358
|
use Module::Metadata; |
|
6
|
|
|
|
|
32052
|
|
|
6
|
|
|
|
|
268
|
|
18
|
6
|
|
|
6
|
|
64
|
use Scalar::Util (); |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
126
|
|
19
|
6
|
|
|
6
|
|
30
|
use Test::More 0.88; |
|
6
|
|
|
|
|
198
|
|
|
6
|
|
|
|
|
66
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
our $VERSION = '0.002'; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our @EXPORT_OK = qw{ all_prereq_ok file_prereq_ok prereq_ok }; |
24
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
25
|
|
|
|
|
|
|
all => \@EXPORT_OK, |
26
|
|
|
|
|
|
|
); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Hash lifted verbatim from File::Spec 3.78 published 2018-08-29 |
29
|
|
|
|
|
|
|
use constant DEFAULT_PATH_TYPE => { |
30
|
|
|
|
|
|
|
MSWin32 => 'Win32', |
31
|
|
|
|
|
|
|
os2 => 'OS2', |
32
|
|
|
|
|
|
|
VMS => 'VMS', |
33
|
|
|
|
|
|
|
NetWare => 'Win32', # Yes, File::Spec::Win32 works on NetWare. |
34
|
|
|
|
|
|
|
symbian => 'Win32', # Yes, File::Spec::Win32 works on symbian. |
35
|
|
|
|
|
|
|
dos => 'OS2', # Yes, File::Spec::OS2 works on DJGPP. |
36
|
|
|
|
|
|
|
cygwin => 'Cygwin', |
37
|
|
|
|
|
|
|
amigaos => 'AmigaOS', |
38
|
6
|
|
50
|
6
|
|
2133
|
}->{$^O} || 'Unix'; |
|
6
|
|
|
|
|
29
|
|
|
6
|
|
|
|
|
748
|
|
39
|
|
|
|
|
|
|
|
40
|
6
|
|
|
6
|
|
40
|
use constant REF_ARRAY => ref []; |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
10762
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub new { |
43
|
16
|
|
|
16
|
1
|
19677
|
my ( $class, %arg ) = @_; |
44
|
|
|
|
|
|
|
|
45
|
16
|
|
50
|
|
|
151
|
$arg{file_error} //= 'Failed to analyze %f: %e'; |
46
|
16
|
|
100
|
|
|
83
|
$arg{name} //= 'Prereq test: %f uses %m'; |
47
|
|
|
|
|
|
|
# NOTE that {path_type} is unsupported, and may change or be |
48
|
|
|
|
|
|
|
# retracted without warning. I thought I needed it to support |
49
|
|
|
|
|
|
|
# argument {prune}, which is itself experimental. |
50
|
16
|
|
50
|
|
|
110
|
$arg{path_type} //= DEFAULT_PATH_TYPE; |
51
|
16
|
|
50
|
|
|
115
|
$arg{per_file_note} //= '%f'; |
52
|
16
|
|
100
|
|
|
84
|
$arg{perl_version} //= 'none'; |
53
|
16
|
|
50
|
|
|
96
|
$arg{skip_name} //= 'Prereq test: %f does not use any modules'; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
state $default = { |
56
|
|
|
|
|
|
|
accept => [], |
57
|
|
|
|
|
|
|
meta_file => [ qw{ |
58
|
|
|
|
|
|
|
MYMETA.json MYMETA.yml META.json META.yml } ], |
59
|
|
|
|
|
|
|
prune => [], |
60
|
|
|
|
|
|
|
uses => [], |
61
|
|
|
|
|
|
|
verbose => ( |
62
|
16
|
50
|
|
|
|
57
|
scalar grep { -d } qw{ .bzr .cdv .git .hg .svn CVS } ) ? 1 : 0, |
|
30
|
|
|
|
|
339
|
|
63
|
|
|
|
|
|
|
}; |
64
|
16
|
|
|
|
|
40
|
foreach my $name ( keys %{ $default } ) { |
|
16
|
|
|
|
|
79
|
|
65
|
80
|
|
100
|
|
|
406
|
$arg{$name} //= $default->{$name}; |
66
|
|
|
|
|
|
|
my $code = __PACKAGE__->can( "__validate_$name" ) || |
67
|
|
|
|
|
|
|
__PACKAGE__->can( '__validate_' . ref $default->{$name} ) || |
68
|
80
|
|
100
|
16
|
|
941
|
sub {}; |
69
|
80
|
|
|
|
|
257
|
$code->( $name, \%arg ); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
16
|
|
|
|
|
54
|
my $core_modules; |
73
|
|
|
|
|
|
|
{ |
74
|
|
|
|
|
|
|
# %Module::CoreList::version is public, so I figured the easiest |
75
|
|
|
|
|
|
|
# implementation of the 'special' Perl versions was to just hack |
76
|
|
|
|
|
|
|
# them into it. |
77
|
16
|
|
|
|
|
33
|
local $Module::CoreList::version{none} = {}; |
|
16
|
|
|
|
|
90
|
|
78
|
|
|
|
|
|
|
local $Module::CoreList::version{this} = |
79
|
16
|
|
|
|
|
88
|
$Module::CoreList::version{$]}; |
80
|
|
|
|
|
|
|
$core_modules = $Module::CoreList::version{$arg{perl_version}} |
81
|
16
|
50
|
|
|
|
170
|
or croak( "Unknown 'perl_version' $arg{perl_version}" ); |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# The below is pretty much verbatim from the CPAN::Meta synopsis |
85
|
|
|
|
|
|
|
|
86
|
16
|
|
|
|
|
51
|
my $meta_data = $arg{_meta_file}; |
87
|
|
|
|
|
|
|
|
88
|
16
|
|
|
|
|
31
|
my %requires; |
89
|
|
|
|
|
|
|
|
90
|
16
|
|
|
|
|
88
|
my $prereqs = $meta_data->effective_prereqs(); |
91
|
16
|
|
|
|
|
14518
|
foreach my $phase ( qw{ configure build test runtime } ) { |
92
|
64
|
|
|
|
|
281
|
my $reqs = $prereqs->requirements_for( $phase, 'requires' ); |
93
|
64
|
|
|
|
|
2218
|
foreach my $module ( $reqs->required_modules() ) { |
94
|
169
|
|
|
|
|
458
|
$requires{$module} = {}; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# The above is pretty much verbatim from the CPAN::Meta synopsis |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# NOTE that if we actually need the Perl version, we need to nab it |
101
|
|
|
|
|
|
|
# before here. |
102
|
16
|
|
|
|
|
45
|
delete $requires{perl}; |
103
|
|
|
|
|
|
|
|
104
|
16
|
|
|
|
|
71
|
my $provides = _provides(); |
105
|
|
|
|
|
|
|
|
106
|
2159
|
|
|
|
|
3887
|
my %has = map { $_ => 1 } |
107
|
16
|
|
|
|
|
77
|
@{ $arg{accept} }, |
108
|
16
|
|
|
|
|
665
|
keys %{ $core_modules }, |
109
|
16
|
|
|
|
|
99
|
keys %{ $provides }, |
|
16
|
|
|
|
|
151
|
|
110
|
|
|
|
|
|
|
keys %requires, |
111
|
|
|
|
|
|
|
; |
112
|
|
|
|
|
|
|
|
113
|
16
|
|
|
|
|
187
|
$arg{uses} = { map { $_ => 1 } @{ $arg{uses} } }; |
|
2
|
|
|
|
|
9
|
|
|
16
|
|
|
|
|
84
|
|
114
|
|
|
|
|
|
|
|
115
|
16
|
100
|
|
|
|
97
|
if ( $arg{verbose} ) { |
116
|
2
|
|
|
|
|
4
|
my @dup; |
117
|
2
|
100
|
|
|
|
17
|
@dup = grep { $requires{$_} } @{ $arg{accept} } |
|
1
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
7
|
|
118
|
|
|
|
|
|
|
and diag "The following @{[ |
119
|
1
|
50
|
|
|
|
14
|
@dup == 1 ? 'module appears' : 'modules appear' |
120
|
|
|
|
|
|
|
]} in both the prerequisites and\nthe 'accept' argument: ", |
121
|
|
|
|
|
|
|
join ', ', sort @dup; |
122
|
2
|
100
|
|
|
|
379
|
@dup = grep { $arg{uses}{$_} } @{ $arg{accept} } |
|
1
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
8
|
|
123
|
|
|
|
|
|
|
and diag "The following @{[ |
124
|
1
|
50
|
|
|
|
11
|
@dup == 1 ? 'module appears' : 'modules appear' |
125
|
|
|
|
|
|
|
]} in both the 'accept' argument and\nthe 'uses' argument: ", |
126
|
|
|
|
|
|
|
join ', ', sort @dup; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
16
|
|
|
|
|
291
|
delete $arg{accept}; |
130
|
16
|
|
|
|
|
109
|
delete $arg{_meta_file}; |
131
|
16
|
|
|
|
|
52
|
delete $arg{path_type}; |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
my $self = bless { |
134
|
|
|
|
|
|
|
# accept => $arg{accept}, |
135
|
|
|
|
|
|
|
# core_modules => $core_modules, |
136
|
|
|
|
|
|
|
file_error => delete $arg{file_error}, |
137
|
|
|
|
|
|
|
has => \%has, |
138
|
|
|
|
|
|
|
meta_file => delete $arg{meta_file}, |
139
|
|
|
|
|
|
|
meta_data => $meta_data, |
140
|
|
|
|
|
|
|
name => delete $arg{name}, |
141
|
|
|
|
|
|
|
per_file_note => delete $arg{per_file_note}, |
142
|
|
|
|
|
|
|
perl_version => delete $arg{perl_version}, |
143
|
|
|
|
|
|
|
prune => delete $arg{prune}, |
144
|
|
|
|
|
|
|
# provides => $provides, |
145
|
|
|
|
|
|
|
skip_name => delete $arg{skip_name}, |
146
|
|
|
|
|
|
|
uses => delete $arg{uses}, |
147
|
|
|
|
|
|
|
verbose => delete $arg{verbose}, |
148
|
|
|
|
|
|
|
_both_tools => ( -e 'Makefile.PL' && -e 'Build.PL' ), |
149
|
|
|
|
|
|
|
_normalize_path => delete $arg{_normalize_path}, |
150
|
16
|
|
33
|
|
|
1088
|
_requires => \%requires, |
|
|
|
33
|
|
|
|
|
151
|
|
|
|
|
|
|
}, ref $class || $class; |
152
|
|
|
|
|
|
|
|
153
|
16
|
100
|
|
|
|
106
|
if ( my $num = keys %arg ) { |
154
|
1
|
50
|
|
|
|
11
|
croak "Unknown argument@{[ $num > 1 ? 's' : '' ]} ", join ', ', |
155
|
1
|
|
|
|
|
3
|
map { "'$_'" } sort keys %arg; |
|
1
|
|
|
|
|
184
|
|
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
15
|
|
|
|
|
562
|
return $self; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub all_prereq_ok { |
162
|
10
|
|
|
10
|
1
|
119
|
my ( $self, @file ) = _unpack_args( @_ ); |
163
|
|
|
|
|
|
|
|
164
|
10
|
100
|
|
|
|
42
|
unless( @file ) { |
165
|
|
|
|
|
|
|
@file = ( |
166
|
8
|
|
|
|
|
355
|
( grep { -d } qw{ blib/arch blib/lib blib/script t } ), |
167
|
2
|
|
|
|
|
20
|
( map { File::Spec->abs2rel( $_ ) } |
|
4
|
|
|
|
|
326
|
|
168
|
|
|
|
|
|
|
File::Glob::bsd_glob( '*.PL' ) ), |
169
|
|
|
|
|
|
|
); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
10
|
|
|
|
|
35
|
my $need_skip = 1; |
173
|
10
|
|
|
|
|
19
|
my $ok = 1; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
File::Find::find( |
176
|
|
|
|
|
|
|
{ |
177
|
|
|
|
|
|
|
wanted => sub { |
178
|
63
|
100
|
|
63
|
|
301
|
if ( $self->{_normalize_path} ) { |
179
|
1
|
|
|
|
|
17
|
$self->{_normalize_path}->(); |
180
|
1
|
50
|
|
|
|
6
|
if ( $self->{prune}{$_} ) { |
181
|
1
|
|
|
|
|
3
|
$File::Find::prune = 1; |
182
|
1
|
|
|
|
|
13
|
return; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
} |
185
|
62
|
100
|
|
|
|
196
|
_is_perl( $_ ) |
186
|
|
|
|
|
|
|
or return; |
187
|
|
|
|
|
|
|
# The following is because File::Find tends to give us |
188
|
|
|
|
|
|
|
# './fubar' if 'fubar' is in the current directory. |
189
|
29
|
|
|
|
|
3137
|
$_ = File::Spec->abs2rel( $_ ); |
190
|
29
|
|
|
|
|
97
|
$need_skip = 0; |
191
|
29
|
100
|
|
|
|
117
|
$self->file_prereq_ok( $_ ) |
192
|
|
|
|
|
|
|
or $ok = 0; |
193
|
29
|
|
|
|
|
964
|
return; |
194
|
|
|
|
|
|
|
}, |
195
|
|
|
|
|
|
|
no_chdir => 1, |
196
|
23
|
|
|
23
|
|
927
|
preprocess => sub { return( sort @_ ) }, |
197
|
|
|
|
|
|
|
}, |
198
|
10
|
|
|
|
|
1333
|
@file, |
199
|
|
|
|
|
|
|
); |
200
|
|
|
|
|
|
|
|
201
|
10
|
100
|
|
|
|
154
|
if ( $need_skip ) { |
202
|
1
|
|
|
|
|
15
|
state $TEST = Test::More->builder(); |
203
|
1
|
|
|
|
|
25
|
local $Test::Builder::Level = _nest_depth(); |
204
|
|
|
|
|
|
|
# $TEST->skip( "$file does not use any modules" ); |
205
|
1
|
|
|
|
|
7
|
$TEST->skip( 'No Perl files found' ); |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
10
|
|
|
|
|
806
|
return $ok; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub all_prereqs_used { |
212
|
3
|
|
|
3
|
1
|
378
|
my ( $self ) = @_; |
213
|
|
|
|
|
|
|
|
214
|
3
|
|
|
|
|
20
|
state $TEST = Test::More->builder(); |
215
|
3
|
|
|
|
|
33
|
local $Test::Builder::Level = _nest_depth(); |
216
|
|
|
|
|
|
|
|
217
|
3
|
|
|
|
|
14
|
$TEST->note( '' ); |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
my @unused = sort |
220
|
19
|
|
100
|
|
|
69
|
grep { ! $self->{uses}{$_} && ! $self->{_requires}{$_}{file} } |
221
|
3
|
|
|
|
|
743
|
keys %{ $self->{_requires} }; |
|
3
|
|
|
|
|
17
|
|
222
|
3
|
100
|
|
|
|
17
|
my $rslt = $TEST->ok( ! @unused, 'All required modules are used' ) |
223
|
|
|
|
|
|
|
or $TEST->diag( "The following @{[ |
224
|
1
|
50
|
|
|
|
1009
|
@unused == 1 ? 'prerequisite is' : 'prerequisites are' |
225
|
|
|
|
|
|
|
]} unused: ", join ', ', @unused ); |
226
|
|
|
|
|
|
|
|
227
|
3
|
100
|
66
|
|
|
787
|
if ( $self->{verbose} and |
228
|
1
|
50
|
|
|
|
10
|
my @dup = grep { $self->{_requires}{$_}{file} && $self->{uses}{$_} } |
229
|
1
|
|
|
|
|
4
|
keys %{ $self->{_requires} } |
230
|
|
|
|
|
|
|
) { |
231
|
1
|
|
|
|
|
3
|
$TEST->diag( "The following @{[ |
232
|
1
|
50
|
|
|
|
10
|
@dup == 1 ? 'module appears' : 'modules appear' |
233
|
|
|
|
|
|
|
]} in both 'use' statements and\nthe 'uses' argument: ", |
234
|
|
|
|
|
|
|
join ', ', sort @dup ); |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
3
|
|
|
|
|
290
|
return $rslt; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub file_prereq_ok { |
241
|
35
|
|
|
35
|
1
|
153
|
my ( $self, $file, @arg ) = _unpack_args( @_ ); |
242
|
|
|
|
|
|
|
@arg |
243
|
35
|
50
|
|
|
|
121
|
and confess( |
244
|
|
|
|
|
|
|
'Usage: $tpm->file_prereq_ok( $file ) or file_prereq_ok( $file )' ); |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# Because this gets us a pre-built object I use $Test::Builder::Level |
247
|
|
|
|
|
|
|
# (localized) to get tests reported relative to the correct file and |
248
|
|
|
|
|
|
|
# line, rather than setting the 'level' attribute. |
249
|
35
|
|
|
|
|
114
|
state $TEST = Test::More->builder(); |
250
|
35
|
|
|
|
|
191
|
local $Test::Builder::Level = _nest_depth(); |
251
|
|
|
|
|
|
|
|
252
|
35
|
50
|
|
|
|
122
|
if ( $self->{per_file_note} ne '' ) { |
253
|
|
|
|
|
|
|
# We are not interested in the actual test number, but we need |
254
|
|
|
|
|
|
|
# to know how many digits it is so that the note can be indented |
255
|
|
|
|
|
|
|
# properly. |
256
|
35
|
|
|
|
|
258
|
$TEST->note( '' ); |
257
|
|
|
|
|
|
|
$TEST->note( |
258
|
|
|
|
|
|
|
' ' x ( 4 + length( $TEST->current_test() + 1 ) ), |
259
|
|
|
|
|
|
|
_format( |
260
|
|
|
|
|
|
|
$self->{per_file_note}, |
261
|
|
|
|
|
|
|
{ |
262
|
35
|
|
|
|
|
12453
|
e => '', |
263
|
|
|
|
|
|
|
f => $file, |
264
|
|
|
|
|
|
|
m => '', |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
), |
267
|
|
|
|
|
|
|
); |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
35
|
|
|
|
|
8522
|
my $need_skip = 1; |
271
|
35
|
|
|
|
|
66
|
my $ok = 1; |
272
|
35
|
|
|
|
|
82
|
my %module_found; |
273
|
|
|
|
|
|
|
|
274
|
35
|
|
|
|
|
95
|
state $extor = Module::Extract::Use->new(); |
275
|
|
|
|
|
|
|
|
276
|
35
|
|
|
|
|
232
|
my $modules = $extor->get_modules_with_details( $file ); |
277
|
35
|
100
|
|
|
|
2897800
|
if ( my $err = $extor->error() ) { |
278
|
|
|
|
|
|
|
$TEST->ok( 0, |
279
|
|
|
|
|
|
|
_format( |
280
|
|
|
|
|
|
|
$self->{file_error}, |
281
|
|
|
|
|
|
|
{ |
282
|
1
|
|
|
|
|
11
|
e => $err, |
283
|
|
|
|
|
|
|
f => $file, |
284
|
|
|
|
|
|
|
m => '', |
285
|
|
|
|
|
|
|
}, |
286
|
|
|
|
|
|
|
) |
287
|
|
|
|
|
|
|
); |
288
|
1
|
|
|
|
|
1181
|
return 0; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
34
|
|
|
|
|
268
|
foreach my $usage ( |
292
|
215
|
|
|
|
|
392
|
sort { $a->{module} cmp $b->{module} } |
293
|
34
|
|
|
|
|
214
|
@{ $modules } |
294
|
|
|
|
|
|
|
) { |
295
|
137
|
|
|
|
|
28176
|
my $module = $usage->{module}; |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# The following is needed because Module::Extract::Use tries too |
298
|
|
|
|
|
|
|
# hard to find return() statements embedded in other statements. |
299
|
137
|
100
|
|
|
|
834
|
$module =~ m/ \A [\w:]+ \z /smx |
300
|
|
|
|
|
|
|
or next; |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# The following is needed because Module::Extract::Use returns |
303
|
|
|
|
|
|
|
# duplicate 'require' statements because it finds them both in |
304
|
|
|
|
|
|
|
# the scan for PPI::Statement::Include objects and in the scan |
305
|
|
|
|
|
|
|
# for PPI::Token::Word 'require' objects. |
306
|
136
|
100
|
|
|
|
507
|
$module_found{$module}++ |
307
|
|
|
|
|
|
|
and next; |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
$self->{_requires}{$module} |
310
|
134
|
100
|
100
|
|
|
413
|
and push @{ $self->{_requires}{$module}{file} ||= [] }, $file; |
|
107
|
|
|
|
|
505
|
|
311
|
|
|
|
|
|
|
|
312
|
134
|
|
|
|
|
251
|
state $toolchain = { |
313
|
|
|
|
|
|
|
'Makefile.PL' => { |
314
|
|
|
|
|
|
|
'ExtUtils::MakeMaker' => 1, |
315
|
|
|
|
|
|
|
'inc::Module::Install' => 1, |
316
|
|
|
|
|
|
|
}, |
317
|
|
|
|
|
|
|
'Build.PL' => { |
318
|
|
|
|
|
|
|
'Module::Build' => 1, |
319
|
|
|
|
|
|
|
'Module::Build::Tiny' => 1, |
320
|
|
|
|
|
|
|
}, |
321
|
|
|
|
|
|
|
}; |
322
|
|
|
|
|
|
|
|
323
|
134
|
|
|
|
|
177
|
$need_skip = 0; |
324
|
|
|
|
|
|
|
$TEST->ok( |
325
|
|
|
|
|
|
|
$self->{has}{$module} || |
326
|
|
|
|
|
|
|
$self->{_both_tools} && $toolchain->{$file}{$module} || |
327
|
|
|
|
|
|
|
0, |
328
|
|
|
|
|
|
|
_format( |
329
|
|
|
|
|
|
|
$self->{name}, |
330
|
|
|
|
|
|
|
{ |
331
|
134
|
100
|
100
|
|
|
856
|
e => '', |
332
|
|
|
|
|
|
|
f => $file, |
333
|
|
|
|
|
|
|
m => $module, |
334
|
|
|
|
|
|
|
}, |
335
|
|
|
|
|
|
|
), |
336
|
|
|
|
|
|
|
) or $ok = 0; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
34
|
100
|
|
|
|
9742
|
if ( $need_skip ) { |
341
|
4
|
|
|
|
|
24
|
local $Test::Builder::Level = _nest_depth(); |
342
|
|
|
|
|
|
|
# $TEST->skip( "$file does not use any modules" ); |
343
|
|
|
|
|
|
|
$TEST->skip( _format( |
344
|
|
|
|
|
|
|
$self->{skip_name}, |
345
|
|
|
|
|
|
|
{ |
346
|
4
|
|
|
|
|
33
|
e => '', |
347
|
|
|
|
|
|
|
f => $file, |
348
|
|
|
|
|
|
|
m => '', |
349
|
|
|
|
|
|
|
}, |
350
|
|
|
|
|
|
|
), |
351
|
|
|
|
|
|
|
); |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
34
|
|
|
|
|
2349
|
return $ok; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
sub _format { |
358
|
174
|
|
|
174
|
|
4503
|
my ( $tplt, $sub ) = @_; |
359
|
174
|
|
33
|
|
|
890
|
$tplt =~ s| % ( . ) | $sub->{$1} // $1 |smxge; |
|
307
|
|
|
|
|
1255
|
|
360
|
174
|
|
|
|
|
743
|
return $tplt; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub prereq_ok { |
364
|
1
|
|
|
1
|
1
|
76
|
my ( $perl_version, $name, $accept ) = @_; |
365
|
1
|
|
33
|
|
|
11
|
my $self = __PACKAGE__->new( |
366
|
|
|
|
|
|
|
accept => $accept, |
367
|
|
|
|
|
|
|
name => $name, |
368
|
|
|
|
|
|
|
perl_version => $perl_version // $], |
369
|
|
|
|
|
|
|
); |
370
|
1
|
|
|
|
|
6
|
return $self->all_prereq_ok(); |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
sub _is_perl { |
374
|
62
|
|
|
62
|
|
128
|
my ( $file ) = @_; |
375
|
62
|
100
|
|
|
|
6932
|
-T $file |
376
|
|
|
|
|
|
|
or return 0; |
377
|
39
|
100
|
|
|
|
428
|
$file =~ m/ [.] (?: (?i: pl ) | pm | t ) \z /smx |
378
|
|
|
|
|
|
|
and return 1; |
379
|
10
|
50
|
|
|
|
282
|
open my $fh, '<', $file |
380
|
|
|
|
|
|
|
or return 0; |
381
|
10
|
|
|
|
|
106
|
local $_ = <$fh>; |
382
|
10
|
|
|
|
|
106
|
close $fh; |
383
|
|
|
|
|
|
|
defined |
384
|
10
|
50
|
|
|
|
29
|
or return 0; |
385
|
10
|
|
|
|
|
245
|
return m/ \A [#]! .* perl /smx; |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
{ |
389
|
|
|
|
|
|
|
my %ignore; |
390
|
|
|
|
|
|
|
BEGIN { |
391
|
6
|
|
|
6
|
|
44
|
%ignore = map { $_ => 1 } __PACKAGE__, qw{ DB File::Find }; |
|
18
|
|
|
|
|
4724
|
|
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
sub _nest_depth { |
395
|
43
|
|
|
43
|
|
79
|
my $nest = 0; |
396
|
43
|
|
50
|
|
|
470
|
$nest++ while $ignore{ caller( $nest ) || '' }; |
397
|
43
|
|
|
|
|
106
|
return $nest; |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# All the __normalize_path_* subroutines operate on $_. They take no |
402
|
|
|
|
|
|
|
# arguments and return nothing relevant. The names are File::Spec:: |
403
|
|
|
|
|
|
|
# OS-specific class names, and the intent is that anything supported by |
404
|
|
|
|
|
|
|
# File::Spec should appear here. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
1
|
|
|
sub __normalize_path_AmigaOS {} # Assumed based on File::Spec::AmigaOS |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
1
|
|
|
sub __normalize_path_Cygwin {} # I believe. |
409
|
|
|
|
|
|
|
|
410
|
1
|
|
|
1
|
|
418
|
sub __normalize_path_OS2 { s| \\ |/|smxg; } ## no critic (RequireFinalReturn) |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
3
|
|
|
sub __normalize_path_Unix {} |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
sub __normalize_path_VMS { |
415
|
1
|
|
|
1
|
|
604
|
croak( 'Can not normalize VMS paths' ); |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
1
|
|
|
1
|
|
528
|
sub __normalize_path_Win32 { s| \\ |/|smxg; } ## no critic (RequireFinalReturn) |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# We don't use Module::Metadata->provides(), because it filters out |
421
|
|
|
|
|
|
|
# private packages. While we're at it, we just process every .pm we find. |
422
|
|
|
|
|
|
|
sub _provides { |
423
|
16
|
|
|
16
|
|
34
|
my %provides; |
424
|
16
|
|
|
|
|
101
|
my $manifest = ExtUtils::Manifest::maniread(); |
425
|
16
|
|
|
|
|
9594
|
foreach my $file ( keys %{ $manifest } ) { |
|
16
|
|
|
|
|
151
|
|
426
|
608
|
100
|
|
|
|
1491
|
$file =~ m/ [.] pm \z /smx |
427
|
|
|
|
|
|
|
or next; |
428
|
64
|
50
|
|
|
|
544
|
my $info = Module::Metadata->new_from_file( $file ) |
429
|
|
|
|
|
|
|
or next; |
430
|
64
|
|
|
|
|
256163
|
foreach my $module ( $info->packages_inside() ) { |
431
|
64
|
|
|
|
|
480
|
state $ignore = { map { $_ => 1 } qw{ main DB } }; |
|
10
|
|
|
|
|
39
|
|
432
|
64
|
100
|
|
|
|
303
|
$ignore->{$module} |
433
|
|
|
|
|
|
|
and next; |
434
|
48
|
|
|
|
|
440
|
$provides{$module} = 1; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
} |
437
|
16
|
|
|
|
|
537
|
return \%provides; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
sub _unpack_args { |
441
|
45
|
|
|
45
|
|
139
|
my @arg = @_; |
442
|
45
|
100
|
66
|
|
|
536
|
my $self = ( ref( $arg[0] ) && ref( $arg[0] )->isa( __PACKAGE__ ) ) ? |
443
|
|
|
|
|
|
|
shift @arg : |
444
|
|
|
|
|
|
|
__PACKAGE__->new(); |
445
|
45
|
|
|
|
|
170
|
return ( $self, @arg ); |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub __validate_meta_file { |
449
|
16
|
|
|
16
|
|
51
|
my ( $name, $arg ) = @_; |
450
|
16
|
100
|
66
|
|
|
114
|
if ( Scalar::Util::blessed( $arg->{$name} ) && |
451
|
|
|
|
|
|
|
$arg->{$name}->isa( 'CPAN::Meta' ) |
452
|
|
|
|
|
|
|
) { |
453
|
1
|
|
|
|
|
6
|
$arg->{"_$name"} = $arg->{$name}; |
454
|
1
|
|
|
|
|
4
|
return; |
455
|
|
|
|
|
|
|
} |
456
|
15
|
|
|
|
|
52
|
__validate_ARRAY( $name, $arg ); |
457
|
15
|
50
|
|
|
|
26
|
@{ $arg->{$name} } |
|
15
|
|
|
|
|
61
|
|
458
|
|
|
|
|
|
|
or croak( "'$name' must specify at least one file" ); |
459
|
15
|
|
|
|
|
31
|
foreach my $fn ( @{ $arg->{$name} } ) { |
|
15
|
|
|
|
|
49
|
|
460
|
16
|
100
|
|
|
|
464
|
-r $fn |
461
|
|
|
|
|
|
|
or next; |
462
|
15
|
|
|
|
|
60
|
$arg->{$name} = $fn; |
463
|
15
|
|
|
|
|
180
|
$arg->{"_$name"} = CPAN::Meta->load_file( $fn ); |
464
|
15
|
|
|
|
|
355599
|
return; |
465
|
|
|
|
|
|
|
} |
466
|
0
|
0
|
|
|
|
0
|
1 == @{ $arg } |
|
0
|
|
|
|
|
0
|
|
467
|
|
|
|
|
|
|
and croak( "$arg->{$name}[0] not readable" ); |
468
|
0
|
|
|
|
|
0
|
local $" = ', '; |
469
|
0
|
|
|
|
|
0
|
croak( "None of @{ $arg->{$name} } readable" ); |
|
0
|
|
|
|
|
0
|
|
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
sub __validate_prune { |
473
|
16
|
|
|
16
|
|
54
|
my ( $name, $arg ) = @_; |
474
|
16
|
|
|
|
|
80
|
__validate_ARRAY( $name, $arg ); |
475
|
16
|
|
|
|
|
28
|
my %rslt; |
476
|
16
|
|
|
|
|
34
|
foreach ( @{ $arg->{$name} } ) { |
|
16
|
|
|
|
|
59
|
|
477
|
1
|
|
33
|
|
|
14
|
$arg->{_normalize_path} ||= __PACKAGE__->can( |
|
|
|
33
|
|
|
|
|
478
|
|
|
|
|
|
|
"__normalize_path_$arg->{path_type}" ) |
479
|
|
|
|
|
|
|
|| croak( "Invalid path type '$arg->{path_type}'" ); |
480
|
1
|
|
|
|
|
5
|
$arg->{_normalize_path}->(); |
481
|
1
|
|
|
|
|
3
|
$rslt{$_} = 1; |
482
|
|
|
|
|
|
|
} |
483
|
16
|
|
100
|
|
|
102
|
$arg->{_normalize_path} ||= undef; |
484
|
16
|
|
|
|
|
40
|
$arg->{$name} = \%rslt; |
485
|
16
|
|
|
|
|
45
|
return; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
sub __validate_ARRAY { |
489
|
63
|
|
|
63
|
|
160
|
my ( $name, $arg ) = @_; |
490
|
|
|
|
|
|
|
ref $arg->{$name} |
491
|
63
|
100
|
|
|
|
188
|
or $arg->{$name} = [ $arg->{$name} ]; |
492
|
63
|
50
|
|
|
|
183
|
REF_ARRAY eq ref $arg->{$name} |
493
|
|
|
|
|
|
|
or croak( "'$name' must be a SCALAR or an ARRAY reference" ); |
494
|
63
|
|
|
|
|
123
|
return; |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
1; |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
__END__ |