line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Perl5::Dist::Backcompat; |
2
|
1
|
|
|
1
|
|
106512
|
use 5.14.0; |
|
1
|
|
|
|
|
5
|
|
3
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
60
|
|
4
|
|
|
|
|
|
|
our $VERSION = '0.04'; |
5
|
1
|
|
|
1
|
|
2921
|
use Archive::Tar; |
|
1
|
|
|
|
|
133332
|
|
|
1
|
|
|
|
|
108
|
|
6
|
1
|
|
|
1
|
|
13
|
use Carp qw( carp croak ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
59
|
|
7
|
1
|
|
|
1
|
|
6
|
use Cwd qw( cwd ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
46
|
|
8
|
1
|
|
|
1
|
|
695
|
use File::Copy qw( copy move ); |
|
1
|
|
|
|
|
6220
|
|
|
1
|
|
|
|
|
113
|
|
9
|
1
|
|
|
1
|
|
10
|
use File::Find qw( find ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
77
|
|
10
|
1
|
|
|
1
|
|
8
|
use File::Spec; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
24
|
|
11
|
1
|
|
|
1
|
|
1824
|
use File::Temp qw( tempdir ); |
|
1
|
|
|
|
|
13144
|
|
|
1
|
|
|
|
|
75
|
|
12
|
|
|
|
|
|
|
# From CPAN |
13
|
1
|
|
|
1
|
|
1343
|
use CPAN::DistnameInfo; |
|
1
|
|
|
|
|
1077
|
|
|
1
|
|
|
|
|
48
|
|
14
|
1
|
|
|
1
|
|
550
|
use Data::Dump qw( dd pp ); |
|
1
|
|
|
|
|
5915
|
|
|
1
|
|
|
|
|
125
|
|
15
|
1
|
|
|
1
|
|
751
|
use File::Copy::Recursive::Reduced qw( dircopy ); |
|
1
|
|
|
|
|
2110
|
|
|
1
|
|
|
|
|
5079
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Perl5::Dist::Backcompat - Analyze F distributions for CPAN release viability |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
my $params = { |
24
|
|
|
|
|
|
|
perl_workdir => '/path/to/git/checkout/of/perl', |
25
|
|
|
|
|
|
|
verbose => 1, |
26
|
|
|
|
|
|
|
}; |
27
|
|
|
|
|
|
|
my $self = Perl5::Dist::Backcompat->new( $params ); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head1 DESCRIPTION |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
This module serves as the backend for the program F which |
32
|
|
|
|
|
|
|
is also part of the F distribution. This document's |
33
|
|
|
|
|
|
|
focus is on documenting the methods used publicly in that program as well as |
34
|
|
|
|
|
|
|
internal methods and subroutines called by those public methods. For |
35
|
|
|
|
|
|
|
discussion on the problem which this distribution tries to solve, and how well |
36
|
|
|
|
|
|
|
it currently does that or not, please (i) read the plain-text F in the |
37
|
|
|
|
|
|
|
CPAN distribution or the F in the L
|
38
|
|
|
|
|
|
|
repository|https://github.com/jkeenan/p5-dist-backcompat>; and (ii) read the |
39
|
|
|
|
|
|
|
front-end program's documentation via F. |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head1 PREREQUISITES |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
F 5.14.0 or newer, with the following modules installed from CPAN: |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=over 4 |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=item * F |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=item * F |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=item * F |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=back |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 PUBLIC METHODS |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head2 C |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=over 4 |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=item * Purpose |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
Perl5::Dist::Backcompat constructor. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=item * Arguments |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
my $self = Perl5::Dist::Backcompat->new( $params ); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
Single hash reference. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=item * Return Value |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Perl5::Dist::Backcompat object. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=back |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=cut |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub new { |
80
|
0
|
|
|
0
|
1
|
|
my ($class, $params) = @_; |
81
|
0
|
0
|
0
|
|
|
|
if (defined $params and ref($params) ne 'HASH') { |
82
|
0
|
|
|
|
|
|
croak "Argument supplied to constructor must be hashref"; |
83
|
|
|
|
|
|
|
} |
84
|
0
|
|
|
|
|
|
my %valid_params = map {$_ => 1} qw( |
|
0
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
verbose |
86
|
|
|
|
|
|
|
host |
87
|
|
|
|
|
|
|
path_to_perls |
88
|
|
|
|
|
|
|
perl_workdir |
89
|
|
|
|
|
|
|
tarball_dir |
90
|
|
|
|
|
|
|
); |
91
|
0
|
|
|
|
|
|
my @invalid_params = (); |
92
|
0
|
|
|
|
|
|
for my $p (keys %$params) { |
93
|
0
|
0
|
|
|
|
|
push @invalid_params, $p unless $valid_params{$p}; |
94
|
|
|
|
|
|
|
} |
95
|
0
|
0
|
|
|
|
|
if (@invalid_params) { |
96
|
0
|
|
|
|
|
|
my $msg = "Constructor parameter(s) @invalid_params not valid"; |
97
|
0
|
|
|
|
|
|
croak $msg; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
croak "Must supply value for 'perl_workdir'" |
100
|
0
|
0
|
|
|
|
|
unless $params->{perl_workdir}; |
101
|
|
|
|
|
|
|
|
102
|
0
|
|
|
|
|
|
my $data = {}; |
103
|
0
|
|
|
|
|
|
for my $p (keys %valid_params) { |
104
|
0
|
0
|
|
|
|
|
$data->{$p} = (defined $params->{$p}) ? $params->{$p} : ''; |
105
|
|
|
|
|
|
|
} |
106
|
0
|
|
0
|
|
|
|
$data->{host} ||= 'dromedary.p5h.org'; |
107
|
0
|
|
0
|
|
|
|
$data->{path_to_perls} ||= '/media/Tux/perls-t/bin'; |
108
|
0
|
|
0
|
|
|
|
$data->{tarball_dir} ||= "$ENV{P5P_DIR}/dist-backcompat/tarballs"; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
croak "Could not locate directory $data->{path_to_perls} for perl executables" |
111
|
0
|
0
|
|
|
|
|
unless -d $data->{path_to_perls}; |
112
|
|
|
|
|
|
|
croak "Could not locate directory $data->{tarball_dir} for downloaded tarballs" |
113
|
0
|
0
|
|
|
|
|
unless -d $data->{tarball_dir}; |
114
|
|
|
|
|
|
|
|
115
|
0
|
|
|
|
|
|
return bless $data, $class; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=head2 C |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=over 4 |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=item * Purpose |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
Guarantee that we can find the F executables we'll be using; the F |
125
|
|
|
|
|
|
|
checkout of the core distribution; metadata files and loading of data |
126
|
|
|
|
|
|
|
therefrom. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=item * Arguments |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
$self->init(); |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
None; all data needed is found within the object. |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=item * Return Value |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Returns the object itself. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=back |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=cut |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub init { |
143
|
|
|
|
|
|
|
# From here on, we assume we're starting from the home directory of |
144
|
|
|
|
|
|
|
# someone with an account on Dromedary. |
145
|
|
|
|
|
|
|
|
146
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
147
|
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
my $currdir = cwd(); |
149
|
|
|
|
|
|
|
chdir $self->{perl_workdir} |
150
|
0
|
0
|
|
|
|
|
or croak "Unable to change to $self->{perl_workdir}"; |
151
|
|
|
|
|
|
|
|
152
|
0
|
|
|
|
|
|
my $describe = `git describe`; |
153
|
0
|
|
|
|
|
|
chomp($describe); |
154
|
0
|
0
|
|
|
|
|
croak "Unable to get value for 'git describe'" |
155
|
|
|
|
|
|
|
unless $describe; |
156
|
0
|
|
|
|
|
|
$self->{describe} = $describe; |
157
|
0
|
0
|
|
|
|
|
chdir $currdir or croak "Unable to change back to starting directory"; |
158
|
|
|
|
|
|
|
|
159
|
0
|
|
|
|
|
|
my $manifest = File::Spec->catfile($self->{perl_workdir}, 'MANIFEST'); |
160
|
0
|
0
|
|
|
|
|
croak "Could not locate $manifest" unless -f $manifest; |
161
|
0
|
|
|
|
|
|
$self->{manifest} = $manifest; |
162
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
|
my $maint_file = File::Spec->catfile($self->{perl_workdir}, 'Porting', 'Maintainers.pl'); |
164
|
0
|
|
|
|
|
|
require $maint_file; # to get %Modules in package Maintainers |
165
|
0
|
|
|
|
|
|
$self->{maint_file} = $maint_file; |
166
|
|
|
|
|
|
|
|
167
|
0
|
|
|
|
|
|
my $manilib_file = File::Spec->catfile($self->{perl_workdir}, 'Porting', 'manifest_lib.pl'); |
168
|
0
|
|
|
|
|
|
require $manilib_file; # to get function sort_manifest() |
169
|
0
|
|
|
|
|
|
$self->{manilib_file} = $manilib_file; |
170
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
|
my %distmodules = (); |
172
|
0
|
|
|
|
|
|
for my $m (keys %Maintainers::Modules) { |
173
|
0
|
0
|
|
|
|
|
if ($Maintainers::Modules{$m}{FILES} =~ m{dist/}) { |
174
|
0
|
|
|
|
|
|
$distmodules{$m} = $Maintainers::Modules{$m}; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# Sanity checks; all modules under dist/ should be blead-upstream and have P5P |
179
|
|
|
|
|
|
|
# as maintainer. |
180
|
0
|
|
|
|
|
|
_sanity_check(\%distmodules, $self->{describe}, $self->{verbose}); |
181
|
0
|
|
|
|
|
|
$self->{distmodules} = \%distmodules; |
182
|
|
|
|
|
|
|
|
183
|
0
|
|
|
|
|
|
my $metadata_file = File::Spec->catfile( |
184
|
|
|
|
|
|
|
'.', 'etc', 'dist-backcompat-distro-metadata.txt'); |
185
|
0
|
0
|
|
|
|
|
croak "Could not locate $metadata_file" unless -f $metadata_file; |
186
|
0
|
|
|
|
|
|
$self->{metadata_file} = $metadata_file; |
187
|
|
|
|
|
|
|
|
188
|
0
|
|
|
|
|
|
my %distro_metadata = (); |
189
|
|
|
|
|
|
|
|
190
|
0
|
0
|
|
|
|
|
open my $IN, '<', $metadata_file or croak "Unable to open $metadata_file for reading"; |
191
|
0
|
|
|
|
|
|
while (my $l = <$IN>) { |
192
|
0
|
|
|
|
|
|
chomp $l; |
193
|
0
|
0
|
|
|
|
|
next if $l =~ m{^(\#|\s*$)}; |
194
|
0
|
|
|
|
|
|
my @rowdata = split /\|/, $l; |
195
|
|
|
|
|
|
|
# Refine this later |
196
|
0
|
|
0
|
|
|
|
$distro_metadata{$rowdata[0]} = { |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
197
|
|
|
|
|
|
|
minimum_perl_version => $rowdata[1] // '', |
198
|
|
|
|
|
|
|
needs_threaded_perl => $rowdata[2] // '', |
199
|
|
|
|
|
|
|
needs_ppport_h => $rowdata[3] // '', |
200
|
|
|
|
|
|
|
needs_threads_h => $rowdata[4] // '', |
201
|
|
|
|
|
|
|
needs_shared_h => $rowdata[5] // '', |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
}; |
204
|
|
|
|
|
|
|
} |
205
|
0
|
0
|
|
|
|
|
close $IN or die "Unable to close $metadata_file after reading: $!"; |
206
|
|
|
|
|
|
|
|
207
|
0
|
|
|
|
|
|
my $this = $self->identify_cpan_tarballs_with_makefile_pl(); |
208
|
0
|
|
|
|
|
|
for my $d (keys %{$this}) { |
|
0
|
|
|
|
|
|
|
209
|
0
|
|
|
|
|
|
$distro_metadata{$d}{tarball} = $this->{$d}->{tarball}; |
210
|
0
|
|
|
|
|
|
$distro_metadata{$d}{distvname} = $this->{$d}->{distvname}; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
0
|
|
|
|
|
|
$self->{distro_metadata} = \%distro_metadata; |
214
|
|
|
|
|
|
|
|
215
|
0
|
|
|
|
|
|
my $older_perls_file = File::Spec->catfile( |
216
|
|
|
|
|
|
|
'.', 'etc', 'dist-backcompat-older-perls.txt'); |
217
|
0
|
0
|
|
|
|
|
croak "Could not locate $older_perls_file" unless -f $older_perls_file; |
218
|
0
|
|
|
|
|
|
$self->{older_perls_file} = $older_perls_file; |
219
|
|
|
|
|
|
|
|
220
|
0
|
|
|
|
|
|
return $self; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=head2 C |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=over 4 |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=item * Purpose |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
Categorize each F distro in one of 4 categories based on the status and |
230
|
|
|
|
|
|
|
appropriateness of its F (if any). |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=item * Arguments |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
$self->categorize_distros(); |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
None; all data needed is already within the object. |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=item * Return Value |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Returns the object. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item * Comment |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Since our objective is to determine the CPAN release viability of code found |
245
|
|
|
|
|
|
|
within F distros in core, we need various ways to categorize those |
246
|
|
|
|
|
|
|
distros. This method will make a categorization based on the status of the |
247
|
|
|
|
|
|
|
distros's F. The categories will be mutually exclusive. By order |
248
|
|
|
|
|
|
|
of processing the categories will be: |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=item * |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
B As based on an examination of C<%Maintainers::Modules> in |
253
|
|
|
|
|
|
|
F, at least one distro has no current CPAN release. |
254
|
|
|
|
|
|
|
Such modules will be categorized as C. |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=item * |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
B Certain F distros have a CPAN release which contains a F. |
259
|
|
|
|
|
|
|
Such distros I also have a F in core; that F |
260
|
|
|
|
|
|
|
may or may not be functionally identical to that on CPAN. In either case, we |
261
|
|
|
|
|
|
|
shall make an assumption that the F found in the most recent CPAN |
262
|
|
|
|
|
|
|
release is the version to be preferred for the purpose of this program. Such |
263
|
|
|
|
|
|
|
distros will be categorized as C. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
B The following 3 categories should be considered I because, |
266
|
|
|
|
|
|
|
as the code in this methods is currently structured, all current F |
267
|
|
|
|
|
|
|
distros are categorized as either C or C. These categories |
268
|
|
|
|
|
|
|
may be removed in a future release. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=over 4 |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=item * |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
B Certain F distros have a F in core. Assuming that such a |
275
|
|
|
|
|
|
|
distro has not already been categorized as C, we will use that version |
276
|
|
|
|
|
|
|
in this program. Such distros will be categorized as C. |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=item * |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
B If a F distro has no F either on CPAN or in core but, at |
281
|
|
|
|
|
|
|
the end of F in the Perl 5 build process does have a F |
282
|
|
|
|
|
|
|
generated by that process, we will categorize such a distro as C. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=item * |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
B The remaining F distros have a F neither on CPAN nor in |
287
|
|
|
|
|
|
|
core. For purpose of compilation in core they I have a F |
288
|
|
|
|
|
|
|
generated by core's F process, but this file, if created, does |
289
|
|
|
|
|
|
|
not appear to be retained on disk at the end of F. Such a distro might |
290
|
|
|
|
|
|
|
lack a F in its CPAN release because the CPAN releasor uses |
291
|
|
|
|
|
|
|
technology such as F to produce such a release and such |
292
|
|
|
|
|
|
|
technology does not require a F to be included in the CPAN |
293
|
|
|
|
|
|
|
tarball. At the present time we will categorize such distros as C and |
294
|
|
|
|
|
|
|
these will be skipped by subsequent methods. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=back |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=back |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=cut |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub categorize_distros { |
303
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
304
|
0
|
|
|
|
|
|
my %makefile_pl_status = (); |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
# First, identify those dist/ distros which, on the basis of data in |
307
|
|
|
|
|
|
|
# Porting/Maintainers.PL, do not currently have CPAN releases. |
308
|
|
|
|
|
|
|
|
309
|
0
|
|
|
|
|
|
for my $m (keys %{$self->{distmodules}}) { |
|
0
|
|
|
|
|
|
|
310
|
0
|
0
|
|
|
|
|
if (! exists $self->{distmodules}->{$m}{DISTRIBUTION}) { |
311
|
0
|
|
|
|
|
|
my ($distname) = $self->{distmodules}->{$m}{FILES} =~ m{^dist/(.*)/?$}; |
312
|
0
|
|
|
|
|
|
$makefile_pl_status{$distname} = 'unreleased'; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# Second, identify those dist/ distros which have their own hard-coded |
317
|
|
|
|
|
|
|
# Makefile.PLs in their CPAN releases. We'll call these 'cpan'. (We've |
318
|
|
|
|
|
|
|
# already done some of the work for this in |
319
|
|
|
|
|
|
|
# $self->identify_cpan_tarballs_with_makefile_pl() called from within |
320
|
|
|
|
|
|
|
# init(). The location of a distro's tarball is given by: |
321
|
|
|
|
|
|
|
# $self->{distro_metadata}->{$d}->{tarball}.) |
322
|
|
|
|
|
|
|
|
323
|
0
|
|
|
|
|
|
for my $d (keys %{$self->{distro_metadata}}) { |
|
0
|
|
|
|
|
|
|
324
|
0
|
0
|
|
|
|
|
if (! $makefile_pl_status{$d}) { |
325
|
0
|
|
|
|
|
|
my $tb = $self->{distro_metadata}->{$d}->{tarball}; |
326
|
0
|
|
|
|
|
|
my ($tar, $hasmpl); |
327
|
0
|
|
|
|
|
|
$tar = Archive::Tar->new($tb); |
328
|
0
|
0
|
|
|
|
|
croak "Unable to create Archive::Tar object for $d" unless defined $tar; |
329
|
0
|
|
|
|
|
|
$self->{distro_metadata}->{$d}->{tar} = $tar; |
330
|
|
|
|
|
|
|
$hasmpl = $self->{distro_metadata}->{$d}->{tar}->contains_file( |
331
|
0
|
|
|
|
|
|
File::Spec->catfile($self->{distro_metadata}->{$d}->{distvname},'Makefile.PL') |
332
|
|
|
|
|
|
|
); |
333
|
0
|
0
|
|
|
|
|
if ($hasmpl) { |
334
|
0
|
|
|
|
|
|
$makefile_pl_status{$d} = 'cpan'; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
else { |
337
|
0
|
0
|
|
|
|
|
carp "$d Makefile.PL doubtful" unless $hasmpl; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
# Third, identify those dist/ distros which have their own hard-coded |
343
|
|
|
|
|
|
|
# Makefile.PLs in the core distribution. We'll call these 'native'. |
344
|
|
|
|
|
|
|
|
345
|
0
|
|
|
|
|
|
my @sorted = read_manifest($self->{manifest}); |
346
|
|
|
|
|
|
|
|
347
|
0
|
|
|
|
|
|
for my $f (@sorted) { |
348
|
0
|
0
|
|
|
|
|
next unless $f =~ m{^dist/}; |
349
|
0
|
|
|
|
|
|
my $path = (split /\t+/, $f)[0]; |
350
|
0
|
0
|
|
|
|
|
if ($path =~ m{/(.*?)/Makefile\.PL$}) { |
351
|
0
|
|
|
|
|
|
my $distro = $1; |
352
|
|
|
|
|
|
|
$makefile_pl_status{$distro} = 'native' |
353
|
0
|
0
|
|
|
|
|
unless $makefile_pl_status{$distro}; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# Fourth, identify those dist/ distros whose Makefile.PL is generated during |
358
|
|
|
|
|
|
|
# Perl's own 'make' process. |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
my $get_generated_makefiles = sub { |
361
|
0
|
|
|
0
|
|
|
my $pattern = qr{dist/(.*?)/Makefile\.PL$}; |
362
|
0
|
0
|
|
|
|
|
if ( $File::Find::name =~ m{$pattern} ) { |
363
|
0
|
|
|
|
|
|
my $distro = $1; |
364
|
0
|
0
|
|
|
|
|
if (! $makefile_pl_status{$distro}) { |
365
|
0
|
|
|
|
|
|
$makefile_pl_status{$distro} = 'generated'; |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
} |
368
|
0
|
|
|
|
|
|
}; |
369
|
|
|
|
|
|
|
find( |
370
|
0
|
|
|
|
|
|
\&{$get_generated_makefiles}, |
371
|
0
|
|
|
|
|
|
File::Spec->catdir($self->{perl_workdir}, 'dist' ) |
372
|
|
|
|
|
|
|
); |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# Fifth, identify those dist/ distros whose Makefile.PLs are not yet |
375
|
|
|
|
|
|
|
# accounted for. |
376
|
|
|
|
|
|
|
|
377
|
0
|
|
|
|
|
|
for my $d (sort keys %{$self->{distmodules}}) { |
|
0
|
|
|
|
|
|
|
378
|
0
|
0
|
|
|
|
|
next unless exists $self->{distmodules}->{$d}{FILES}; |
379
|
0
|
|
|
|
|
|
my ($distname) = $self->{distmodules}->{$d}{FILES} =~ m{^dist/([^/]+)/?$}; |
380
|
0
|
0
|
|
|
|
|
if (! exists $makefile_pl_status{$distname}) { |
381
|
0
|
|
|
|
|
|
$makefile_pl_status{$distname} = 'tbd'; |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
0
|
|
|
|
|
|
$self->{makefile_pl_status} = \%makefile_pl_status; |
386
|
0
|
|
|
|
|
|
return $self; |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
=head2 C |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=over 4 |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=item * Purpose |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
Display a chart listing F distros in one column and the status of their |
396
|
|
|
|
|
|
|
respective Fs in the second column. |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=item * Arguments |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
$self->show_makefile_pl_status(); |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
None; this method simply displays data already present in the object. |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=item * Return Value |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
Returns a true value when complete. |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=item * Comment |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
Does nothing unless a true value for C was passed to C. |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=back |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
=cut |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
sub show_makefile_pl_status { |
417
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
418
|
0
|
|
|
|
|
|
my %counts; |
419
|
0
|
|
|
|
|
|
for my $module (sort keys %{$self->{makefile_pl_status}}) { |
|
0
|
|
|
|
|
|
|
420
|
0
|
|
|
|
|
|
$counts{$self->{makefile_pl_status}->{$module}}++; |
421
|
|
|
|
|
|
|
} |
422
|
0
|
0
|
|
|
|
|
if ($self->{verbose}) { |
423
|
0
|
|
|
|
|
|
for my $k (sort keys %counts) { |
424
|
0
|
|
|
|
|
|
printf " %-18s%4s\n" => ($k, $counts{$k}); |
425
|
|
|
|
|
|
|
} |
426
|
0
|
|
|
|
|
|
say ''; |
427
|
0
|
|
|
|
|
|
printf "%-24s%-12s\n" => ('Distribution', 'Status'); |
428
|
0
|
|
|
|
|
|
printf "%-24s%-12s\n" => ('------------', '------'); |
429
|
0
|
|
|
|
|
|
for my $module (sort keys %{$self->{makefile_pl_status}}) { |
|
0
|
|
|
|
|
|
|
430
|
0
|
|
|
|
|
|
printf "%-24s%-12s\n" => ($module, $self->{makefile_pl_status}->{$module}); |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
} |
433
|
0
|
|
|
|
|
|
return 1; |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
=head2 C |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=over 4 |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=item * Purpose |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
Assemble the list of F distros which the program will actually test |
443
|
|
|
|
|
|
|
against older Fs. |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=item * Arguments |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
my @distros_for_testing = $self->get_distros_for_testing( [ @distros_requested ] ); |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
Single arrayref, optional (though recommended). If no arrayref is provided, |
450
|
|
|
|
|
|
|
then the program will test I F distros I those whose |
451
|
|
|
|
|
|
|
"Makefile.PL status" is C. |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
=item * Return Value |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
List holding distros to be tested. (This is provided for readability of the |
456
|
|
|
|
|
|
|
code, but the list will be stored within the object and subsequently |
457
|
|
|
|
|
|
|
referenced therefrom. |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
=item * Comment |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
In a production program, the list of distros selected for testing may be |
462
|
|
|
|
|
|
|
provided on the command-line and processed by C |
463
|
|
|
|
|
|
|
within that program. But it's only at this point that we need to add such a |
464
|
|
|
|
|
|
|
list to the object. |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
=back |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
=cut |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
sub get_distros_for_testing { |
471
|
0
|
|
|
0
|
1
|
|
my ($self, $distros) = @_; |
472
|
0
|
0
|
|
|
|
|
if (defined $distros) { |
473
|
0
|
0
|
|
|
|
|
croak "Argument passed to get_distros_for_testing() must be arrayref" |
474
|
|
|
|
|
|
|
unless ref($distros) eq 'ARRAY'; |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
else { |
477
|
0
|
|
|
|
|
|
$distros = []; |
478
|
|
|
|
|
|
|
} |
479
|
0
|
|
|
|
|
|
my @distros_for_testing = (scalar @{$distros}) |
480
|
0
|
|
|
|
|
|
? @{$distros} |
481
|
0
|
|
|
|
|
|
: sort grep { $self->{makefile_pl_status}->{$_} ne 'unreleased' } |
482
|
0
|
0
|
|
|
|
|
keys %{$self->{makefile_pl_status}}; |
|
0
|
|
|
|
|
|
|
483
|
0
|
0
|
|
|
|
|
if ($self->{verbose}) { |
484
|
0
|
|
|
|
|
|
say "\nWill test ", scalar @distros_for_testing, |
485
|
|
|
|
|
|
|
" distros which have been presumably released to CPAN:"; |
486
|
0
|
|
|
|
|
|
say " $_" for @distros_for_testing; |
487
|
|
|
|
|
|
|
} |
488
|
0
|
|
|
|
|
|
$self->{distros_for_testing} = [ @distros_for_testing ]; |
489
|
0
|
|
|
|
|
|
return @distros_for_testing; |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=head2 C |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=over 4 |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=item * Purpose |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
Validate the paths and executability of the older perl versions against which |
499
|
|
|
|
|
|
|
we're going to test F distros. |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
=item * Arguments |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
my @perls = $self->validate_older_perls(); |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
None; all necessary information is found within the object. |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
=item * Return Value |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
List holding older F executables against which distros will be tested. |
510
|
|
|
|
|
|
|
(This is provided for readability of the code, but the list will be stored |
511
|
|
|
|
|
|
|
within the object and subsequently referenced therefrom. |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=back |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=cut |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
sub validate_older_perls { |
518
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
519
|
0
|
|
|
|
|
|
my @perllist = (); |
520
|
|
|
|
|
|
|
open my $IN1, '<', $self->{older_perls_file} |
521
|
0
|
0
|
|
|
|
|
or croak "Unable to open $self->{older_perls_file} for reading"; |
522
|
0
|
|
|
|
|
|
while (my $l = <$IN1>) { |
523
|
0
|
|
|
|
|
|
chomp $l; |
524
|
0
|
0
|
|
|
|
|
next if $l =~ m{^(\#|\s*$)}; |
525
|
0
|
|
|
|
|
|
push @perllist, $l; |
526
|
|
|
|
|
|
|
} |
527
|
0
|
0
|
|
|
|
|
close $IN1 |
528
|
|
|
|
|
|
|
or croak "Unable to close $self->{older_perls_file} after reading"; |
529
|
|
|
|
|
|
|
|
530
|
0
|
|
|
|
|
|
my @perls = (); |
531
|
|
|
|
|
|
|
|
532
|
0
|
|
|
|
|
|
for my $p (@perllist) { |
533
|
0
|
0
|
|
|
|
|
say "Locating $p executable ..." if $self->{verbose}; |
534
|
0
|
|
|
|
|
|
my $rv; |
535
|
0
|
|
|
|
|
|
my $path_to_perl = File::Spec->catfile($self->{path_to_perls}, $p); |
536
|
0
|
0
|
|
|
|
|
warn "Could not locate $path_to_perl" unless -e $path_to_perl; |
537
|
0
|
|
|
|
|
|
$rv = system(qq| $path_to_perl -v 1>/dev/null 2>&1 |); |
538
|
0
|
0
|
|
|
|
|
warn "Could not execute perl -v with $path_to_perl" if $rv; |
539
|
|
|
|
|
|
|
|
540
|
0
|
|
|
|
|
|
my ($major, $minor, $patch) = $p =~ m{^perl(5)\.(\d+)\.(\d+)$}; |
541
|
0
|
|
|
|
|
|
my $canon = sprintf "%s.%03d%03d" => ($major, $minor, $patch); |
542
|
|
|
|
|
|
|
|
543
|
0
|
|
|
|
|
|
push @perls, { |
544
|
|
|
|
|
|
|
version => $p, |
545
|
|
|
|
|
|
|
path => $path_to_perl, |
546
|
|
|
|
|
|
|
canon => $canon, |
547
|
|
|
|
|
|
|
}; |
548
|
|
|
|
|
|
|
} |
549
|
0
|
|
|
|
|
|
$self->{perls} = [ @perls ]; |
550
|
0
|
|
|
|
|
|
return @perls; |
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=head2 C |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
=over 4 |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
=item * Purpose |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
Test a given F distro against each of the older Fs against which |
560
|
|
|
|
|
|
|
it is eligible to be tested. |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
=item * Arguments |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
$self->test_distros_against_older_perls('/path/to/debugging/directory'); |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
String holding absolute path to an already created directory to which files |
567
|
|
|
|
|
|
|
can be written for later study and debugging. That directory I be |
568
|
|
|
|
|
|
|
created by C, but it should I be created with C<( |
569
|
|
|
|
|
|
|
CLEANUP => 1)>; the user should manually remove this directory after analysis |
570
|
|
|
|
|
|
|
is complete. |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
=item * Return Value |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
Returns the object itself. |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
=item * Comment |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
The method will loop over the selected distros, calling |
579
|
|
|
|
|
|
|
C against each. |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
=back |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
=cut |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
sub test_distros_against_older_perls { |
586
|
0
|
|
|
0
|
1
|
|
my ($self, $results_dir) = @_; |
587
|
|
|
|
|
|
|
# $results_dir will be explicitly user-created to hold the results of |
588
|
|
|
|
|
|
|
# testing. |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
# A program using Perl5::Dist::Backcompat won't need it until now. So even |
591
|
|
|
|
|
|
|
# if we feed that directory to the program via GetOptions, it doesn't need |
592
|
|
|
|
|
|
|
# to go into the constructor. It may be a tempdir but should almost |
593
|
|
|
|
|
|
|
# certainly NOT be set to get automatically cleaned up at program |
594
|
|
|
|
|
|
|
# conclusion (otherwise, where would you look for the results?). |
595
|
|
|
|
|
|
|
|
596
|
0
|
0
|
|
|
|
|
croak "Unable to locate $results_dir" unless -d $results_dir; |
597
|
0
|
|
|
|
|
|
$self->{results_dir} = $results_dir; |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
# Calculations WILL, however, be done in a true tempdir. We'll create |
600
|
|
|
|
|
|
|
# subdirs and files underneath that tempdir. We'll cd to that tempdir but |
601
|
|
|
|
|
|
|
# come back to where we started before this method exits. |
602
|
|
|
|
|
|
|
# $self->{temp_top_dir} will be the conceptual equivalent of the top-level |
603
|
|
|
|
|
|
|
# directory in the Perl 5 distribution. Hence, underneath it we'll create |
604
|
|
|
|
|
|
|
# the equivalents of the F, F, etc., and |
605
|
|
|
|
|
|
|
# F directories. |
606
|
0
|
|
|
|
|
|
$self->{currdir} = cwd(); |
607
|
0
|
|
|
|
|
|
$self->{temp_top_dir} = tempdir( CLEANUP => 1 ); |
608
|
0
|
|
|
|
|
|
my %results = (); |
609
|
|
|
|
|
|
|
|
610
|
0
|
0
|
|
|
|
|
chdir $self->{temp_top_dir} or croak "Unable to change to tempdir $self->{temp_top_dir}"; |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
# Create a 't/' directory underneath the temp_top_dir |
613
|
0
|
|
|
|
|
|
my $temp_t_dir = File::Spec->catdir($self->{temp_top_dir}, 't'); |
614
|
0
|
0
|
|
|
|
|
mkdir $temp_t_dir or croak "Unable to mkdir $temp_t_dir"; |
615
|
0
|
|
|
|
|
|
$self->{temp_t_dir} = $temp_t_dir; |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
# Several of the F distros need F for their tests; copy |
618
|
|
|
|
|
|
|
# it into position once only. |
619
|
0
|
|
|
|
|
|
my $testpl = File::Spec->catfile($self->{perl_workdir}, 't', 'test.pl'); |
620
|
0
|
0
|
|
|
|
|
croak "Could not locate $testpl" unless -f $testpl; |
621
|
0
|
0
|
|
|
|
|
copy $testpl => $self->{temp_t_dir} or croak "Unable to copy $testpl"; |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
# Create a 'dist/' directory underneath the temp_top_dir |
624
|
0
|
|
|
|
|
|
my $temp_dist_dir = File::Spec->catdir($self->{temp_top_dir}, 'dist'); |
625
|
0
|
0
|
|
|
|
|
mkdir $temp_dist_dir or croak "Unable to mkdir $temp_dist_dir"; |
626
|
0
|
|
|
|
|
|
$self->{temp_dist_dir} = $temp_dist_dir; |
627
|
|
|
|
|
|
|
|
628
|
0
|
|
|
|
|
|
for my $d (@{$self->{distros_for_testing}}) { |
|
0
|
|
|
|
|
|
|
629
|
0
|
|
|
|
|
|
my $this_result = $self->test_one_distro_against_older_perls($d); |
630
|
0
|
|
|
|
|
|
$results{$d} = $this_result; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
chdir $self->{currdir} |
634
|
0
|
0
|
|
|
|
|
or croak "Unable to change back to starting directory $self->{currdir}"; |
635
|
|
|
|
|
|
|
|
636
|
0
|
|
|
|
|
|
$self->{results} = { %results }; |
637
|
0
|
|
|
|
|
|
return $self; |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
# temp_top_dir should go out of scope here (though its path and those of |
640
|
|
|
|
|
|
|
# temp_t_dir and temp_dist_dir will still be in the object) |
641
|
|
|
|
|
|
|
} |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
=head2 C |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=over 4 |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
=item * Purpose |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
Print on F: |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
=over 4 |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
=item 1 |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
A list of the F files created for each |
656
|
|
|
|
|
|
|
tested distro (each file containing a summary of the results for that distro |
657
|
|
|
|
|
|
|
against each designated F executable. Example: |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
Summaries |
660
|
|
|
|
|
|
|
--------- |
661
|
|
|
|
|
|
|
Attribute-Handlers /tmp/29LsgNfjVb/Attribute-Handlers.summary.txt |
662
|
|
|
|
|
|
|
Carp /tmp/29LsgNfjVb/Carp.summary.txt |
663
|
|
|
|
|
|
|
Data-Dumper /tmp/29LsgNfjVb/Data-Dumper.summary.txt |
664
|
|
|
|
|
|
|
... |
665
|
|
|
|
|
|
|
threads /tmp/29LsgNfjVb/threads.summary.txt |
666
|
|
|
|
|
|
|
threads-shared /tmp/29LsgNfjVb/threads-shared.summary.txt |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
=item 2 |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
A concatenation of all those files. |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
=back |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
=item * Arguments |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
To simply list the summary files: |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
$self->print_distro_summaries(); |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
To list the summary files and concatenate their content: |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
$self->print_distro_summaries( {cat_summaries => 1} ); |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
=item * Return Value |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
Returns true value upon success. |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
=item * Comment |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
You'll probably want to redirect or F F to a file for further |
691
|
|
|
|
|
|
|
study. |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
=back |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
=cut |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
sub print_distro_summaries { |
698
|
0
|
|
|
0
|
1
|
|
my ($self, $args) = @_; |
699
|
0
|
0
|
|
|
|
|
if (! defined $args) { $args = {}; } |
|
0
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
else { |
701
|
0
|
0
|
|
|
|
|
croak "Argument to print_distro_summaries must be hashref" |
702
|
|
|
|
|
|
|
unless ref($args) eq 'HASH'; |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
|
705
|
0
|
|
|
|
|
|
say "\nSummaries"; |
706
|
0
|
|
|
|
|
|
say '-' x 9; |
707
|
0
|
|
|
|
|
|
for my $d (sort keys %{$self->{results}}) { |
|
0
|
|
|
|
|
|
|
708
|
0
|
|
|
|
|
|
$self->print_distro_summary($d); |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
0
|
0
|
|
|
|
|
if ($args->{cat_summaries}) { |
712
|
0
|
|
|
|
|
|
say "\nOverall (at $self->{describe}):"; |
713
|
0
|
|
|
|
|
|
for my $d (sort keys %{$self->{results}}) { |
|
0
|
|
|
|
|
|
|
714
|
0
|
|
|
|
|
|
say "\n$d"; |
715
|
0
|
|
|
|
|
|
dd $self->{results}->{$d}; |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
} |
718
|
0
|
|
|
|
|
|
return 1; |
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
=head2 C |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
=over 4 |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
=item * Purpose |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
Provide an overall summary of PASSes and FAILs in the distro/perl-version matrix. |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
=item * Arguments |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
None, all data needed is stored within object. |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
=item * Return Value |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
Array ref with 4 elements: overall attempts, overall passes, overall failures, |
736
|
|
|
|
|
|
|
overall skipped. |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
=item * Comment |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
An entry in the distro/perl-version matrix is skipped if there is a failure |
741
|
|
|
|
|
|
|
running F, which causes the C, C and C |
742
|
|
|
|
|
|
|
values to be all undefined. |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
=back |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
=cut |
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
sub tally_results { |
749
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
750
|
0
|
|
|
|
|
|
my $overall_attempts = 0; |
751
|
0
|
|
|
|
|
|
my $overall_successes = 0; |
752
|
0
|
|
|
|
|
|
my $overall_skipped = 0; |
753
|
0
|
|
|
|
|
|
for my $d (keys %{$self->{results}}) { |
|
0
|
|
|
|
|
|
|
754
|
0
|
|
|
|
|
|
for my $p (keys %{$self->{results}->{$d}}) { |
|
0
|
|
|
|
|
|
|
755
|
0
|
|
|
|
|
|
$overall_attempts++; |
756
|
0
|
|
|
|
|
|
my %thisrun = %{$self->{results}->{$d}->{$p}}; |
|
0
|
|
|
|
|
|
|
757
|
0
|
0
|
0
|
|
|
|
if ( |
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
758
|
|
|
|
|
|
|
! defined $thisrun{configure} and |
759
|
|
|
|
|
|
|
! defined $thisrun{make} and |
760
|
|
|
|
|
|
|
! defined $thisrun{test} |
761
|
|
|
|
|
|
|
) { |
762
|
0
|
|
|
|
|
|
$overall_skipped++; |
763
|
|
|
|
|
|
|
} |
764
|
|
|
|
|
|
|
elsif ( |
765
|
|
|
|
|
|
|
$thisrun{configure} and |
766
|
|
|
|
|
|
|
$thisrun{make} and |
767
|
|
|
|
|
|
|
$thisrun{test} |
768
|
|
|
|
|
|
|
) { |
769
|
0
|
|
|
|
|
|
$overall_successes++; |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
} |
772
|
|
|
|
|
|
|
} |
773
|
0
|
|
|
|
|
|
my $overall_failures = $overall_attempts - ($overall_successes + $overall_skipped); |
774
|
0
|
|
|
|
|
|
return [$overall_attempts, $overall_successes, $overall_failures, $overall_skipped]; |
775
|
|
|
|
|
|
|
} |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
=head1 INTERNAL METHODS |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
The following methods use the Perl5::Dist::Backcompat object but are called |
780
|
|
|
|
|
|
|
from within the public methods. Other than this library's author, you |
781
|
|
|
|
|
|
|
shouldn't need to explicitly call these methods (or the internal subroutines |
782
|
|
|
|
|
|
|
documented below) in a production program. The documentation here is mainly |
783
|
|
|
|
|
|
|
for people working on this distribution itself. |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
=cut |
786
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
=head2 C |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
=over 4 |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
=item * Purpose |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
Test one selected F distribution against the list of older Fs. |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
=item * Arguments |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
Single string holding the name of the distro in C format. |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
=item * Return Value |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
Hash reference with one element for each F executable selected: |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
{ |
804
|
|
|
|
|
|
|
"5.006002" => { a => "perl5.6.2", configure => 1, make => 0, test => undef }, |
805
|
|
|
|
|
|
|
"5.008009" => { a => "perl5.8.9", configure => 1, make => 0, test => undef }, |
806
|
|
|
|
|
|
|
"5.010001" => { a => "perl5.10.1", configure => 1, make => 0, test => undef }, |
807
|
|
|
|
|
|
|
... |
808
|
|
|
|
|
|
|
"5.034000" => { a => "perl5.34.0", configure => 1, make => 1, test => 1 }, |
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
The value of each element is a hashref with elements keyed as follows: |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
=over 4 |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
=item * C |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
Perl version in the spelling used in the default value for C. |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
=item * C |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
The result of calling F: C<1> for success; C<0> for failure; |
822
|
|
|
|
|
|
|
C for not attempted. |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
=item * C |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
The result of calling F: same meaning as above. |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
=item * C |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
The result of calling F: same meaning as above. |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
=back |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
=back |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
=cut |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
sub test_one_distro_against_older_perls { |
839
|
0
|
|
|
0
|
1
|
|
my ($self, $d) = @_; |
840
|
0
|
0
|
|
|
|
|
say "Testing $d ..." if $self->{verbose}; |
841
|
0
|
|
|
|
|
|
my $this_result = {}; |
842
|
|
|
|
|
|
|
|
843
|
0
|
|
|
|
|
|
my $source_dir = File::Spec->catdir($self->{perl_workdir}, 'dist', $d); |
844
|
0
|
|
|
|
|
|
my $this_tempdir = File::Spec->catdir($self->{temp_dist_dir}, $d); |
845
|
0
|
0
|
|
|
|
|
mkdir $this_tempdir or croak "Unable to mkdir $this_tempdir"; |
846
|
0
|
0
|
|
|
|
|
dircopy($source_dir, $this_tempdir) |
847
|
|
|
|
|
|
|
or croak "Unable to copy $source_dir to $this_tempdir"; |
848
|
|
|
|
|
|
|
|
849
|
0
|
0
|
|
|
|
|
chdir $this_tempdir or croak "Unable to chdir to tempdir for dist/$d"; |
850
|
0
|
0
|
|
|
|
|
say " Now in $this_tempdir ..." if $self->{verbose}; |
851
|
|
|
|
|
|
|
|
852
|
0
|
|
|
|
|
|
THIS_PERL: for my $p (@{$self->{perls}}) { |
|
0
|
|
|
|
|
|
|
853
|
0
|
|
|
|
|
|
$this_result->{$p->{canon}}{a} = $p->{version}; |
854
|
|
|
|
|
|
|
# Skip this perl version if (a) distro has a specified |
855
|
|
|
|
|
|
|
# 'minimum_perl_version' and (b) that minimum version is greater than |
856
|
|
|
|
|
|
|
# the current perl we're running. |
857
|
0
|
0
|
0
|
|
|
|
if ( |
858
|
|
|
|
|
|
|
( |
859
|
|
|
|
|
|
|
$self->{distro_metadata}->{$d}{minimum_perl_version} |
860
|
|
|
|
|
|
|
and |
861
|
|
|
|
|
|
|
$self->{distro_metadata}->{$d}{minimum_perl_version} >= $p->{canon} |
862
|
|
|
|
|
|
|
) |
863
|
|
|
|
|
|
|
# Since we're currently using threaded perls for this |
864
|
|
|
|
|
|
|
# process, the following condition is not pertinent. But we'll |
865
|
|
|
|
|
|
|
# retain it here commented out for possible future use. |
866
|
|
|
|
|
|
|
# |
867
|
|
|
|
|
|
|
# or |
868
|
|
|
|
|
|
|
# ( |
869
|
|
|
|
|
|
|
# $self->{distro_metadata}->{$d}{needs_threaded_perl} |
870
|
|
|
|
|
|
|
# ) |
871
|
|
|
|
|
|
|
) { |
872
|
0
|
|
|
|
|
|
$this_result->{$p->{canon}}{configure} = undef; |
873
|
0
|
|
|
|
|
|
$this_result->{$p->{canon}}{make} = undef; |
874
|
0
|
|
|
|
|
|
$this_result->{$p->{canon}}{test} = undef; |
875
|
0
|
|
|
|
|
|
next THIS_PERL; |
876
|
|
|
|
|
|
|
} |
877
|
0
|
|
|
|
|
|
my $f = join '.' => ($d, $p->{version}, 'txt'); |
878
|
0
|
|
|
|
|
|
my $debugfile = File::Spec->catfile($self->{results_dir}, $f); |
879
|
0
|
0
|
|
|
|
|
if ($self->{verbose}) { |
880
|
0
|
|
|
|
|
|
say "Testing $d with $p->{canon} ($p->{version}); see $debugfile"; |
881
|
|
|
|
|
|
|
} |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
# Here, assuming the distro ($d) is classified as 'cpan', we should |
884
|
|
|
|
|
|
|
# extract the Makefile.PL from the tar and swap that into the |
885
|
|
|
|
|
|
|
# following 'perl Makefile.PL' command. |
886
|
|
|
|
|
|
|
|
887
|
0
|
|
|
|
|
|
my ($rv, $cmd); |
888
|
0
|
|
|
|
|
|
my $this_makefile_pl = 'Makefile.PL'; |
889
|
0
|
0
|
|
|
|
|
if ($self->{makefile_pl_status}->{$d} eq 'cpan') { |
890
|
|
|
|
|
|
|
# We currently expect this branch to prevail 40 times |
891
|
0
|
0
|
|
|
|
|
if (-f $this_makefile_pl) { |
892
|
0
|
|
|
|
|
|
move $this_makefile_pl => "$this_makefile_pl.noncpan"; |
893
|
|
|
|
|
|
|
} |
894
|
0
|
|
|
|
|
|
my $source = File::Spec->catfile($self->{distro_metadata}->{$d}->{distvname},'Makefile.PL'); |
895
|
0
|
|
|
|
|
|
my $destination = File::Spec->catfile('.', $this_makefile_pl); |
896
|
|
|
|
|
|
|
my $extract = $self->{distro_metadata}->{$d}->{tar}->extract_file( |
897
|
0
|
|
|
|
|
|
$source, |
898
|
|
|
|
|
|
|
$destination, |
899
|
|
|
|
|
|
|
); |
900
|
0
|
0
|
|
|
|
|
croak "Unable to extract Makefile.PL from tarball" unless $extract; |
901
|
0
|
0
|
|
|
|
|
croak "Unable to locate extracted Makefile.PL" unless -f $destination; |
902
|
|
|
|
|
|
|
} |
903
|
0
|
0
|
|
|
|
|
croak "Could not locate $this_makefile_pl for configuring" unless -f $this_makefile_pl; |
904
|
|
|
|
|
|
|
|
905
|
0
|
0
|
|
|
|
|
if ($self->{distro_metadata}->{$d}->{needs_ppport_h}) { |
906
|
0
|
|
|
|
|
|
my $source = File::Spec->catfile($self->{distro_metadata}->{$d}->{distvname},'ppport.h'); |
907
|
0
|
|
|
|
|
|
my $destination = File::Spec->catfile('.', 'ppport.h'); |
908
|
|
|
|
|
|
|
my $extract = $self->{distro_metadata}->{$d}->{tar}->extract_file( |
909
|
0
|
|
|
|
|
|
$source, |
910
|
|
|
|
|
|
|
$destination, |
911
|
|
|
|
|
|
|
); |
912
|
0
|
0
|
|
|
|
|
croak "Unable to extract ppport.h from tarball" unless $extract; |
913
|
0
|
0
|
|
|
|
|
croak "Unable to locate extracted ppport.h" unless -f $destination; |
914
|
|
|
|
|
|
|
} |
915
|
|
|
|
|
|
|
|
916
|
0
|
0
|
|
|
|
|
if ($self->{distro_metadata}->{$d}->{needs_threads_h}) { |
917
|
0
|
|
|
|
|
|
my $source = File::Spec->catfile($self->{distro_metadata}->{$d}->{distvname},'threads.h'); |
918
|
0
|
|
|
|
|
|
my $destination = File::Spec->catfile('.', 'threads.h'); |
919
|
|
|
|
|
|
|
my $extract = $self->{distro_metadata}->{$d}->{tar}->extract_file( |
920
|
0
|
|
|
|
|
|
$source, |
921
|
|
|
|
|
|
|
$destination, |
922
|
|
|
|
|
|
|
); |
923
|
0
|
0
|
|
|
|
|
croak "Unable to extract threads.h from tarball" unless $extract; |
924
|
0
|
0
|
|
|
|
|
croak "Unable to locate extracted threads.h" unless -f $destination; |
925
|
|
|
|
|
|
|
} |
926
|
|
|
|
|
|
|
|
927
|
0
|
0
|
|
|
|
|
if ($self->{distro_metadata}->{$d}->{needs_shared_h}) { |
928
|
0
|
|
|
|
|
|
my $source = File::Spec->catfile($self->{distro_metadata}->{$d}->{distvname},'shared.h'); |
929
|
0
|
|
|
|
|
|
my $destination = File::Spec->catfile('.', 'shared.h'); |
930
|
|
|
|
|
|
|
my $extract = $self->{distro_metadata}->{$d}->{tar}->extract_file( |
931
|
0
|
|
|
|
|
|
$source, |
932
|
|
|
|
|
|
|
$destination, |
933
|
|
|
|
|
|
|
); |
934
|
0
|
0
|
|
|
|
|
croak "Unable to extract shared.h from tarball" unless $extract; |
935
|
0
|
0
|
|
|
|
|
croak "Unable to locate extracted shared.h" unless -f $destination; |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
|
938
|
0
|
|
|
|
|
|
$cmd = qq| $p->{path} $this_makefile_pl > $debugfile 2>&1 |; |
939
|
0
|
0
|
|
|
|
|
$rv = system($cmd) and say STDERR " FAIL: $d: $p->{canon}: Makefile.PL"; |
940
|
0
|
0
|
|
|
|
|
$this_result->{$p->{canon}}{configure} = $rv ? 0 : 1; undef $rv; |
|
0
|
|
|
|
|
|
|
941
|
0
|
0
|
|
|
|
|
unless ($this_result->{$p->{canon}}{configure}) { |
942
|
0
|
|
|
|
|
|
undef $this_result->{$p->{canon}}{make}; |
943
|
0
|
|
|
|
|
|
undef $this_result->{$p->{canon}}{test}; |
944
|
0
|
|
|
|
|
|
next THIS_PERL; |
945
|
|
|
|
|
|
|
} |
946
|
|
|
|
|
|
|
|
947
|
0
|
0
|
|
|
|
|
$rv = system(qq| make >> $debugfile 2>&1 |) |
948
|
|
|
|
|
|
|
and say STDERR " FAIL: $d: $p->{canon}: make"; |
949
|
0
|
0
|
|
|
|
|
$this_result->{$p->{canon}}{make} = $rv ? 0 : 1; undef $rv; |
|
0
|
|
|
|
|
|
|
950
|
0
|
0
|
|
|
|
|
unless ($this_result->{$p->{canon}}{make}) { |
951
|
0
|
|
|
|
|
|
undef $this_result->{$p->{canon}}{test}; |
952
|
0
|
|
|
|
|
|
next THIS_PERL; |
953
|
|
|
|
|
|
|
} |
954
|
|
|
|
|
|
|
|
955
|
0
|
0
|
|
|
|
|
$rv = system(qq| make test >> $debugfile 2>&1 |) |
956
|
|
|
|
|
|
|
and say STDERR " FAIL: $d: $p->{canon}: make test"; |
957
|
0
|
0
|
|
|
|
|
$this_result->{$p->{canon}}{test} = $rv ? 0 : 1; undef $rv; |
|
0
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
|
959
|
0
|
0
|
|
|
|
|
system(qq| make clean 2>&1 1>/dev/null |) |
960
|
|
|
|
|
|
|
and carp "Unable to 'make clean' for $d"; |
961
|
|
|
|
|
|
|
} |
962
|
|
|
|
|
|
|
chdir $self->{temp_top_dir} |
963
|
0
|
0
|
|
|
|
|
or croak "Unable to change to tempdir $self->{temp_top_dir}"; |
964
|
0
|
|
|
|
|
|
return $this_result; |
965
|
|
|
|
|
|
|
} |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
=head2 C |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
=over 4 |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
=item * Purpose |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
Create a file holding a summary of the results for running one distro against |
974
|
|
|
|
|
|
|
each of the selected Fs. |
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
=item * Arguments |
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
$self->print_distro_summary('Some-Distro'); |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
String holding name of distro. |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
=item * Return Value |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
Returns true value on success. |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
=item * Comment |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
File created will be named like F. |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
File's content will look like this: |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
Attribute-Handlers v5.35.7-48-g34e3587 |
993
|
|
|
|
|
|
|
{ |
994
|
|
|
|
|
|
|
"5.006002" => { a => "perl5.6.2", configure => 1, make => 0, test => undef }, |
995
|
|
|
|
|
|
|
"5.008009" => { a => "perl5.8.9", configure => 1, make => 0, test => undef }, |
996
|
|
|
|
|
|
|
"5.010001" => { a => "perl5.10.1", configure => 1, make => 0, test => undef }, |
997
|
|
|
|
|
|
|
... |
998
|
|
|
|
|
|
|
"5.034000" => { a => "perl5.34.0", configure => 1, make => 1, test => 1 }, |
999
|
|
|
|
|
|
|
} |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
=back |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
=cut |
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
sub print_distro_summary { |
1006
|
0
|
|
|
0
|
1
|
|
my ($self, $d) = @_; |
1007
|
0
|
|
|
|
|
|
my $output = File::Spec->catfile($self->{results_dir}, "$d.summary.txt"); |
1008
|
0
|
0
|
|
|
|
|
open my $OUT, '>', $output or die "Unable to open $output for writing: $!"; |
1009
|
0
|
|
|
|
|
|
say $OUT sprintf "%-52s%20s" => ($d, $self->{describe}); |
1010
|
0
|
|
|
|
|
|
my $oldfh = select($OUT); |
1011
|
0
|
|
|
|
|
|
dd $self->{results}->{$d}; |
1012
|
0
|
0
|
|
|
|
|
close $OUT or die "Unable to close $output after writing: $!"; |
1013
|
0
|
|
|
|
|
|
select $oldfh; |
1014
|
|
|
|
|
|
|
say sprintf "%-24s%-48s" => ($d, $output) |
1015
|
0
|
0
|
|
|
|
|
if $self->{verbose}; |
1016
|
|
|
|
|
|
|
} |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
# Check tarballs we have on disk to see whether they contain a |
1019
|
|
|
|
|
|
|
# Makefile.PL. |
1020
|
|
|
|
|
|
|
# $ pwd |
1021
|
|
|
|
|
|
|
# /home/jkeenan/learn/perl/p5p/dist-backcompat/tarballs/authors/id |
1022
|
|
|
|
|
|
|
# $ ls . | head -n 5 |
1023
|
|
|
|
|
|
|
# Attribute-Handlers-0.99.tar.gz |
1024
|
|
|
|
|
|
|
# autouse-1.11.tar.gz |
1025
|
|
|
|
|
|
|
# base-2.23.tar.gz |
1026
|
|
|
|
|
|
|
# Carp-1.50.tar.gz |
1027
|
|
|
|
|
|
|
# constant-1.33.tar.gz |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
sub identify_cpan_tarballs_with_makefile_pl { |
1030
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
1031
|
0
|
|
|
|
|
|
my $id_dir = File::Spec->catdir($self->{tarball_dir}, 'authors', 'id'); |
1032
|
0
|
0
|
|
|
|
|
opendir my $DIR, $id_dir |
1033
|
|
|
|
|
|
|
or croak "Unable to open directory $id_dir for reading"; |
1034
|
0
|
|
|
|
|
|
my @available = map { File::Spec->catfile('authors', 'id', $_) } |
1035
|
0
|
|
|
|
|
|
grep { m/\.tar\.gz$/ } readdir $DIR; |
|
0
|
|
|
|
|
|
|
1036
|
0
|
0
|
|
|
|
|
closedir $DIR or croak "Unable to close directory $id_dir after reading"; |
1037
|
0
|
|
|
|
|
|
my %this = (); |
1038
|
0
|
|
|
|
|
|
for my $tb (@available) { |
1039
|
0
|
|
|
|
|
|
my $d = CPAN::DistnameInfo->new($tb); |
1040
|
0
|
|
|
|
|
|
my $dist = $d->dist; |
1041
|
0
|
|
|
|
|
|
my $distvname = $d->distvname; |
1042
|
0
|
|
|
|
|
|
$this{$dist}{tarball} = File::Spec->catfile($self->{tarball_dir}, $tb); |
1043
|
0
|
|
|
|
|
|
$this{$dist}{distvname} = $distvname; |
1044
|
|
|
|
|
|
|
} |
1045
|
0
|
|
|
|
|
|
return \%this; |
1046
|
|
|
|
|
|
|
} |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
=head1 INTERNAL SUBROUTINES |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
=head2 C |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
=over 4 |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
=item * Purpose |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
Assure us that our environment is adequate to the task. |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
=item * Arguments |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
sanity_check(\%distmodules, $verbose); |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
List of two scalars: (i) reference to the hash which is storing list of |
1063
|
|
|
|
|
|
|
F distros; (ii) verbosity selection. |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
=item * Return Value |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
Implicitly returns true on success, but does not otherwise return any |
1068
|
|
|
|
|
|
|
meaningful value. |
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
=item * Comment |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
If verbosity is selected, displays the current git commit and other useful |
1073
|
|
|
|
|
|
|
information on F. |
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
=back |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
=cut |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
sub _sanity_check { |
1080
|
0
|
|
|
0
|
|
|
my ($distmodules, $describe, $verbose) = @_; |
1081
|
0
|
|
|
|
|
|
for my $m (keys %{$distmodules}) { |
|
0
|
|
|
|
|
|
|
1082
|
0
|
0
|
|
|
|
|
if ($distmodules->{$m}{UPSTREAM} ne 'blead') { |
1083
|
0
|
|
|
|
|
|
warn "Distro $m has UPSTREAM other than 'blead'"; |
1084
|
|
|
|
|
|
|
} |
1085
|
0
|
0
|
|
|
|
|
if ($distmodules->{$m}{MAINTAINER} ne 'P5P') { |
1086
|
0
|
|
|
|
|
|
warn "Distro $m has MAINTAINER other than 'P5P'"; |
1087
|
|
|
|
|
|
|
} |
1088
|
|
|
|
|
|
|
} |
1089
|
|
|
|
|
|
|
|
1090
|
0
|
0
|
|
|
|
|
if ($verbose) { |
1091
|
0
|
|
|
|
|
|
say "p5-dist-backcompat"; |
1092
|
0
|
|
|
|
|
|
my $ldescribe = length $describe; |
1093
|
|
|
|
|
|
|
my $message = q|Found | . |
1094
|
0
|
|
|
|
|
|
(scalar keys %{$distmodules}) . |
|
0
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
q| 'dist/' entries in %Maintainers::Modules|; |
1096
|
0
|
|
|
|
|
|
my $lmessage = length $message; |
1097
|
0
|
|
|
|
|
|
my $ldiff = $lmessage - $ldescribe; |
1098
|
0
|
|
|
|
|
|
say sprintf "%-${ldiff}s%s" => ('Results at commit:', $describe); |
1099
|
0
|
|
|
|
|
|
say "\n$message"; |
1100
|
|
|
|
|
|
|
} |
1101
|
0
|
|
|
|
|
|
return 1; |
1102
|
|
|
|
|
|
|
} |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
=head2 C |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
=over 4 |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
=item * Purpose |
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
Get a sorted list of all files in F (without their descriptions). |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
=item * Arguments |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
read_manifest('/path/to/MANIFEST'); |
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
One scalar: the path to F in a git checkout of the Perl 5 core distribution. |
1117
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
=item * Return Value |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
List (sorted) of all files in F. |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
=item * Comment |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
Depends on C from F. |
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
(This is so elementary and useful that it should probably be in F!) |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
=back |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
=cut |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
sub read_manifest { |
1133
|
0
|
|
|
0
|
1
|
|
my $manifest = shift; |
1134
|
0
|
0
|
|
|
|
|
open(my $IN, '<', $manifest) or die("Can't read '$manifest': $!"); |
1135
|
0
|
|
|
|
|
|
my @manifest = <$IN>; |
1136
|
0
|
0
|
|
|
|
|
close($IN) or die($!); |
1137
|
0
|
|
|
|
|
|
chomp(@manifest); |
1138
|
|
|
|
|
|
|
|
1139
|
0
|
|
|
|
|
|
my %seen= ( '' => 1 ); # filter out blank lines |
1140
|
0
|
|
|
|
|
|
return grep { !$seen{$_}++ } sort_manifest(@manifest); |
|
0
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
} |
1142
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
1; |
1144
|
|
|
|
|
|
|
|