File Coverage

blib/lib/Test/Against/Commit.pm
Criterion Covered Total %
statement 106 302 35.1
branch 23 142 16.2
condition 0 26 0.0
subroutine 27 39 69.2
pod 19 21 90.4
total 175 530 33.0


line stmt bran cond sub pod time code
1             package Test::Against::Commit;
2 2     2   384891 use strict;
  2         5  
  2         80  
3 2     2   29 use 5.14.0;
  2         8  
4             our $VERSION = '0.17';
5             # core modules
6 2     2   1848 use Archive::Tar;
  2         276523  
  2         196  
7 2     2   22 use Carp;
  2         5  
  2         131  
8 2     2   17 use Cwd;
  2         7  
  2         126  
9 2     2   12 use File::Path ( qw| make_path | );
  2         5  
  2         118  
10 2     2   13 use File::Spec;
  2         5  
  2         58  
11 2     2   11 use File::Temp ( qw| tempfile | );
  2         8  
  2         98  
12             # non-core modules
13 2     2   1785 use CPAN::cpanminus::reporter::RetainReports;
  2         835488  
  2         131  
14 2     2   20 use Data::Dump ( qw| dd pp | );
  2         6  
  2         148  
15 2     2   12 use JSON;
  2         4  
  2         13  
16 2     2   2610 use Path::Tiny;
  2         38416  
  2         234  
17 2     2   2822 use Text::CSV_XS;
  2         41579  
  2         7090  
18              
19             =head1 NAME
20              
21             Test::Against::Commit - Test CPAN modules against Perl dev releases, branches or individual commits
22              
23             =head1 SYNOPSIS
24              
25             my $self = Test::Against::Commit->new( {
26             application_dir => '/path/to/application',
27             project => 'business_project',
28             install => ,
29             } );
30              
31             $self->prepare_testing_directories();
32              
33             my $this_cpanm = $self->fetch_cpanm( { verbose => 1 } );
34              
35             my $modules_ref = $self->process_modules( {
36             module_file => '/path/to/cpan-river-file.txt',
37             title => 'cpan-river-1000',
38             verbose => 1,
39             } );
40              
41             =head1 DESCRIPTION
42              
43             =head2 Who Should Use This Library?
44              
45             This library should be used by anyone who wishes to assess the impact of
46             day-to-day changes in the Perl 5 core distribution on the installability of
47             libraries found on the Comprehensive Perl Archive Network (CPAN). This
48             library supersedes the existing CPAN library
49             L.
50              
51             =head2 The Problem Addressed by This Library
52              
53             In the development of Perl as a language we face a problem typically referred
54             to as B (or B for short). Perl 5 undergoes an annual
55             development cycle characterized by:
56              
57             =over 4
58              
59             =item *
60              
61             Commits on a near daily basis to a L
62             repository|https://github.com/Perl/perl5>.
63              
64             =item *
65              
66             Monthly development releases (tarballs) whose version numbers follow the
67             convention of C<5.43.0>, C<5.43.1>, etc., where the middle digits are always
68             odd numbers.
69              
70             =item *
71              
72             Annual production releases and subsequent maintenance releases whose version
73             numbers have even-numbered middle digits, I, C<5.44.0>, C<5.44.1>, etc.
74              
75             =back
76              
77             A monthly development release is essentially a roll-up of a month's worth of
78             commits to the master repository branch known as B (pronounced
79             I<"bleed">). Changes in the Perl 5 code base have the potential to adversely
80             impact the installability of existing CPAN libraries. Hence, various
81             individuals have, over the years, developed ways of testing those libraries
82             against blead and reporting problems to those people actively involved in the
83             ongoing development of the Perl 5 core distribution. The latter are typically
84             referred to as "core developers" or as the "Perl 5 Porters."
85              
86             This library is intended as a contribution to those efforts by enabling the
87             Perl 5 Porters to assess the impact of changes in the Perl 5 core distribution
88             CPAN libraries well in advance of production and maintenance releases.
89              
90             =head2 The Approach Test-Against-Commit Takes
91              
92             Unlike other efforts, F does I depend on test reports
93             sent to L. Hence, it should be
94             unaffected by any technical problems which that site may face. As a
95             consequence, however, a user of this library must be willing to maintain more
96             of her own local infrastructure than a typical CPANtester would maintain.
97              
98             While this library could, in principle, be used to test the entirety of CPAN,
99             it is probably better suited for testing selected subsets of CPAN libraries
100             which the user deems important to her individual or organizational needs.
101              
102             Unlike its ancestor F, this library is designed to test CPAN
103             libraries against either Perl 5 monthly development releases or against
104             individual commits to any branch of any GH repository holding the Perl 5 core
105             distribution. I
106             build a F executable and how to run the core distribution's test suite.
107             This library leaves the configuration, build and installation of a F
108             executable to the user.> The scope of this library's activity begins at the
109             point that a F has been installed on disk, continues through
110             installation of libraries needed for testing CPAN libraries against that
111             executable to analysis of the results of that testing and presentation of
112             those results in a usable form.
113              
114             While this library is currently focused on Perl 5 libraries publicly available
115             on CPAN, it could in principle be extended to test an organization's private
116             libraries as well. This functionality, however, has not yet been implemented
117             or tested.
118              
119             =head2 Terminology
120              
121             Here are some terms which we use in a specific way in this library:
122              
123             =over 4
124              
125             =item * B
126              
127             A directory to which the user has write-privileges and which holds the input
128             and output for one or more I. I C.
129              
130             =item * B
131              
132             A short-hand description of the focus of a particular investigation using
133             Test-Against-Commit. I C could describe an investigation of
134             the impact of fatalization of certain uses of the Perl C function on
135             CPAN libraries.
136              
137             =item * B
138              
139             A subdirectory of the I which holds the input and
140             output data for one I. I C.
141              
142             =item * B
143              
144             An installation of one F executable, the libraries that get installed
145             with the core distribution, CPAN libraries whose installability we tested
146             against that F and data gathered to analyze that installability and
147             answer questions for the business purpose of the I.
148              
149             An installation will be built either from a particular checkout, tag or branch
150             from a F repository of the Perl 5 source code (C<23ae7f95ea>, C,
151             C) or from a Perl 5 development, production or maintenance release in
152             tarball form (C).
153              
154             A I will consist of at least one installation but will probably hold
155             two or three installations: the first will be used to determine a baseline
156             state, the second will be used to assess the impact of a proposed change in
157             the Perl 5 core distribution on installability of CPAN libraries.
158              
159             =item * B
160              
161             A subdirectory of the I holding one installation. I
162              
163             /path-to-application/ # <-- application directory
164             /path-to-application/goto-fatal/ # <-- project directory
165             /path-to-application/goto-fatal/23ae7f95ea/ # <-- installation directory
166             /path-to-application/goto-fatal/v5.43.3/ # <-- another installation directory
167              
168             Each installation directory will have exactly two subdirectories: C
169             and C. (See next two items.)
170              
171             =item * B
172              
173             A subdirectory of an I which in turn initially holds
174             two subdirectories, C and C.
175              
176             The C directory holds the F, F, F and other
177             executable when a particular F is built for the project. The C
178             directory holds all modules installed either initially with the executable or
179             subsequently, including those whose functionality we are assessing as part of
180             the project's business purpose. Test-Against-Commit methods will create other
181             subdirectories next to C and C, some of which are hidden, as part
182             of the testing progress.
183              
184             /path-to-application/goto-fatal/23ae7f95ea/ # <-- installation directory
185             /path-to-application/goto-fatal/23ae7f95ea/testing/ # <-- testing directory
186             /path-to-application/goto-fatal/23ae7f95ea/testing/bin/ # <-- bin directory
187             /path-to-application/goto-fatal/23ae7f95ea/testing/lib/ # <-- lib directory
188              
189             The data in the I can be thought of as the project's
190             I data.
191              
192             =item * B
193              
194             A subdirectory of an I which holds the data created by
195             running a program using Test::Against::Commit methods. This directory will in turn
196             hold two subdirectories: C and C.
197              
198             /path-to-application/goto-fatal/23ae7f95ea/ # <-- installation directory
199             /path-to-application/goto-fatal/23ae7f95ea/testing/ # <-- testing directory
200             ...
201             /path-to-application/goto-fatal/23ae7f95ea/results/ # <-- results directory
202             /path-to-application/goto-fatal/23ae7f95ea/results/analysis/
203             /path-to-application/goto-fatal/23ae7f95ea/results/storage/
204              
205             The data in the I can be thought of as the project's
206             I data.
207              
208             =item * B
209              
210             A I is an instance of (i) testing a set of one or more CPAN libraries
211             against a given I and (ii) the recording of data from that
212             instance of testing.
213              
214             =item * B
215              
216             The way one calls F when building Perl 5 from source, :
217              
218             sh ./Configure -des -Dusedevel
219              
220             or:
221              
222             sh ./Configure -des -Dusedevel \
223             -Duseithreads \
224             -Doptimize="-O2 -pipe -fstack-protector -fno-strict-aliasing"
225              
226             Once you begin to use Test-Against-Commit for a particular I, you
227             should use the same configuration for each I over the life of
228             that project. For instance, you should not configure without threads in one
229             run but with threads in the next. Nor should you switch from regular to
230             debugging builds between I. Otherwise, the results may reflect changes
231             in that configuration rather than changes in Perl 5 core distribution code or
232             changes in the targeted CPAN libraries.
233              
234             =back
235              
236             =head2 What Is the Result Produced by This Library?
237              
238             Our objective is to be able to compare output data recorded in one I for
239             a given I with data recorded in a different I for a different
240             (presumably subsequent) installation within the same I. To return to
241             the example of the I project, let's assume we have two different
242             installations, the first of which sets our baseline (which CPAN libraries
243             currently C and which currently C) and a second which determines
244             the impact of applying a pull request.
245              
246             /path-to-application/goto-fatal/ # <-- project directory
247             /path-to-application/goto-fatal/23ae7f95ea/ # <-- first installation directory
248             /path-to-application/goto-fatal/v5.43.3/ # <-- second installation directory
249              
250             We will end up comparing data stored in these installations' respective
251             C subdirectories.
252              
253             /path-to-application/goto-fatal/23ae7f95ea/results/analysis/
254             /path-to-application/goto-fatal/v5.43.3/results/analysis/
255              
256             =head2 What Preparations Are Needed to Use This Library?
257              
258             =over 4
259              
260             =item * Platform
261              
262             The user should select a machine/platform which is likely to be reasonably
263             stable over one Perl 5 annual development cycle. We presume that the
264             platform's system administrator will be updating system libraries for security
265             and other reasons over time. But it would be a hassle to run this software on
266             a machine scheduled for a complete major version update of its operating
267             system.
268              
269             =item * Perl 5 Configuration
270              
271             The user must decide on a Perl 5 configuration for a given I and then
272             must refrain from changing configurations over the course of the project's
273             existence. See item under L above.
274              
275             =item * F Executable Installation Location
276              
277             As noted above, this library leaves to the user the choice of a I
278             the Perl source code> and the decision of I an individual
279             F executable. It also leaves to the user, with one caveat, the decision
280             of I to install that executable on disk. That caveat is that the
281             I should reside in a directory named F which in turn
282             sits underneath a directory which we'll refer to as the I
283             directory>. The user will have to manually create the I
284             directory>, the I, the I and the
285             I and then use the I as the value for
286             the I<-Dprefix> option in the invocation of F.
287              
288             In terms of the directory structure discussed above, that the user would
289             create a directory structure something like this:
290              
291             $ cd ~/tmp
292             $ export TESTINGDIR=`pwd`/all-tad-projects/goto-fatal/23ae7f95ea/testing
293             $ echo $TESTINGDIR
294             .../tmp/all-tad-projects/goto-fatal/23ae7f95ea/testing
295             $ mkdir -p $TESTINGDIR
296             $ ls -l $TESTINGDIR
297             total 0
298              
299             $ cd
300              
301             The user would then invoke F in a way something like this:
302              
303             $ sh ./Configure -des -Dusedevel -Dprefix=$TESTINGDIR \
304             -Uversiononly -Dman1dir=none -Dman3dir=none
305             $ make install
306              
307             The user could then confirm installation with this:
308              
309             $ $TESTINGDIR/bin/perl -v | head -2 | tail -1
310             This is perl 5, version 43, subversion 3 (v5.43.3 (v5.43.2-343-g5fdb3e501b)) built for x86_64-linux
311              
312             Note that at this point we have not yet created the I ...
313              
314             $ cd ~/tmp
315             $ ls -l ./all-tad-projects/goto-fatal/23ae7f95ea/results
316             ... No such file or directory
317              
318             ... but no worries; Test-Against-Commit methods will handle that.
319              
320             =item * Selection of CPAN Libraries for Testing
321              
322             B
323              
324             When you use this library, you are in effect saying: I
325             modules important enough to me that I don't want to see them begin to break in
326             the course of Perl's annual development cycle. (If they do break, then the
327             Perl 5 Porters and the modules' authors/maintainers must address how to handle
328             the breakage.) To keep track of the problem, I'm going to build F from
329             a starting point where those modules are working proprerly and assess their
330             installability at later points.>
331              
332             Hence, once you decide to track a certain CPAN library, you should continue to
333             include it in your list of modules to be tracked for the balance of that year's
334             development cycle. You can, it is true, B additional modules to your
335             list part way through the development cycle. You simply won't have the same
336             baseline data that you have for the modules you selected at the very
337             beginning.
338              
339             Here are some approaches that come to mind:
340              
341             =over 4
342              
343             =item * CPAN river
344              
345             The CPAN river is a concept developed by Neil Bowers and other participants in
346             the Perl Toolchain Gang and Perl QA Hackathons and Summits. The concept
347             starts from the premise that CPAN libraries upon which many other CPAN
348             libraries depend are more important than those upon which few other libraries
349             depend. That's a useful definition of importance even if it is far from strictly
350             true. Modules "way upstream" feed modules and real-world code "farther
351             downstream." Hence, if Perl 5's development branch changes in a way such that
352             "upstream" modules start to fail to configure, build, test and install
353             correctly, then we have a potentially serious problem.
354              
355             =item * Organizational dependencies
356              
357             Many organizations use technologies such as F and F to keep
358             track of their dependencies on CPAN libraries. The lists compiled by such
359             applications could very easily be translated into a list of modules tested
360             once a month against a Perl development release.
361              
362             =item * What repeatedly breaks
363              
364             Certain CPAN libraries get broken relatively frequently. While this can
365             happen because of sub-standard coding practices in those libraries, it more
366             often happens because these libraries, in order to do what they want to do,
367             reach down deep into the Perl 5 guts and use features of the Perl-to-C API.
368              
369             =back
370              
371             =back
372              
373             =head1 METHODS
374              
375             =head2 C
376              
377             =over 4
378              
379             =item * Purpose
380              
381             Test::Against::Commit constructor. Guarantees that the top-level directory for
382             the application (C) already exists, then creates two
383             directories thereunder: F and F.
384              
385             =item * Arguments
386              
387             my $self = Test::Against::Commit->new( {
388             application_dir => '/path/to/application',
389             project => 'goto-fatal'
390             install => '23ae7f95ea',
391             } );
392              
393             Takes a hash reference with the following elements:
394              
395             =over 4
396              
397             =item * C
398              
399             String holding path to the directory which will serve as the top level for all
400             projects using Test-Against-Commit technology.
401              
402             =item * C
403              
404             String holding a short name for your current business project.
405              
406             =item * C
407              
408             String holding a name for the specific I of F against which you
409             will be attempting to install CPAN modules. If you have built F from
410             a F checkout, this should be the F commit ID (SHA), F tag or
411             F branch name from which you are starting. If you are building F
412             from a release tarball, consider using a string such as C from
413             the tarball's basename.
414              
415             =back
416              
417             =item * Return Value
418              
419             Test::Against::Commit object.
420              
421             =item * Comment
422              
423             The constructor merely verifies the existence of certain directories on your
424             machine. It does not install a F executable. That is the user's
425             responsibility. The user will subsequently have to call the
426             C and perhaps C to be fully ready
427             to test.
428              
429             =back
430              
431             =cut
432              
433             sub new {
434 8     8 1 590209 my ($class, $args) = @_;
435              
436 8 100       622 croak "Argument to constructor must be hashref"
437             unless ref($args) eq 'HASH';
438             croak "Hash ref must contain 'application_dir' element"
439 6 100       241 unless $args->{application_dir};
440             croak "Hash ref must contain 'install' element"
441 5 100       239 unless $args->{install};
442             croak "Could not locate application directory $args->{application_dir}"
443 4 100       361 unless (-d $args->{application_dir});
444             croak "Must supply name for project"
445 3 100       181 unless length($args->{project});
446              
447 2         9 my %verified = ();
448 2         48 my $project_dir = File::Spec->catdir($args->{application_dir}, $args->{project});
449 2 100       86 unless (-d $project_dir) { make_path($project_dir, { mode => 0755 }); }
  1         237  
450 2         48 $verified{project_dir} = $project_dir;
451 2         32 my $install_dir = File::Spec->catdir($project_dir, $args->{install});
452 2 100       70 unless (-d $install_dir) { make_path($install_dir, { mode => 0755 }); }
  1         202  
453 2         20 $verified{install_dir} = $install_dir;
454              
455 2         19 for my $dir (qw| testing results |) {
456 4         47 my $fdir = File::Spec->catdir($install_dir, $dir);
457 4 100       109 unless (-d $fdir) { make_path($fdir, { mode => 0755 }); }
  2         462  
458 4         24 my $k = $dir . '_dir';
459 4         34 $verified{$k} = $fdir;
460             }
461              
462 2         6 my $data;
463 2         8 for my $k (keys %{$args}) {
  2         14  
464 6         22 $data->{$k} = $args->{$k};
465             }
466 2         15 for my $k (keys %verified) {
467 8         23 $data->{$k} = $verified{$k};
468             }
469              
470 2         20 return bless $data, $class;
471             }
472              
473             =head2 C
474              
475             =over 4
476              
477             =item * Purpose
478              
479             Methods which simply return the path to relevant directories (along with
480             I of their name):
481              
482             =over 4
483              
484             =item * application directory (I)
485              
486             The top-level directory for all code and data implemented by
487             Test-Against-Commit. It will typically hold 1 subdirectory for each business
488             project using Test-Against-Commit technology.
489              
490             =item * project directory (I)
491              
492             TK
493              
494             =item * install directory (I)
495              
496             TK
497              
498             =item * testing directory (I)
499              
500             A directory which holds one or more subdirectories, each of which contains an
501             installation of a perl executable. That installation will start off with
502             C and C subdirectories and C<./bin/perl -Ilib -v> will be called
503             to demonstrate the presence of a viable F.
504              
505             =item * results directory (I)
506              
507             The directory under which all data created by runs of programs using
508             Test::Against::Commit will be placed. This will include data in JSON and
509             pipe-separated-value (PSV) formats.
510              
511             =back
512              
513             =item * Arguments
514              
515             $application_dir = $self->get_application_dir();
516              
517             $project_dir = $self->get_project_dir();
518              
519             $install_dir = $self->get_install_dir();
520              
521             $testing_dir = $self->get_testing_dir();
522              
523             $results_dir = $self->get_results_dir();
524              
525             =item * Return Value
526              
527             String holding a path to the named directory.
528              
529             =item * Comment
530              
531             These methods become available once a F executable has been installed
532             and C has been run.
533              
534             =back
535              
536             =cut
537              
538             sub get_application_dir {
539 2     2 1 2229 my $self = shift;
540 2         13 return $self->{application_dir};
541             }
542              
543             sub get_project_dir {
544 2     2 1 2300 my $self = shift;
545 2         17 return $self->{project_dir};
546             }
547              
548             sub get_install_dir {
549 2     2 1 928 my $self = shift;
550 2         13 return $self->{install_dir};
551             }
552              
553             sub get_testing_dir {
554 2     2 1 983 my $self = shift;
555 2         11 return $self->{testing_dir};
556             }
557              
558             sub get_results_dir {
559 2     2 1 914 my $self = shift;
560 2         10 return $self->{results_dir};
561             }
562              
563             =head2 C
564              
565             =over 4
566              
567             =item * Purpose
568              
569             Each F installed underneath C needs a unique name. If we
570             build this F from a F checkout, this should be one of the commit ID
571             (SHA), tag or branch name of the checkout.
572              
573             =item * Arguments
574              
575             my $install = $self->get_install();
576              
577             =item * Return Value
578              
579             String holding a F commit ID, tag or branch name.
580              
581             =item * Comment
582              
583             Since C is one of the key-value pairs we are handing to C, this
584             method essentially just gives us back what we already told it. However, we
585             will use it internally later to derive the path to the installed F
586             against which we are trying to install modules.
587              
588             TK: What about when we're building from a tarball?
589              
590             =back
591              
592             =cut
593              
594             sub get_install {
595 2     2 1 889 my $self = shift;
596 2         29 return $self->{install};
597             }
598              
599             =head2 C
600              
601             =over 4
602              
603             =item * Purpose
604              
605             Determines whether the F executable has been installed -- I
606             the user's responsibility to install it> -- and whether this application has
607             the correct directory structure.
608              
609             =item * Arguments
610              
611             $self->prepare_testing_directory()
612              
613             =item * Return Value
614              
615             Returns the Test::Against::Commit object, which now holds additional data.
616              
617             =item * Comment
618              
619             TK
620              
621             =back
622              
623             =cut
624              
625             sub prepare_testing_directory {
626 1     1 1 9 my $self = shift;
627              
628 1         4 for my $dir (qw| bin lib|) {
629 1         17 my $subdir = File::Spec->catdir($self->{testing_dir}, $dir);
630 1 50       75 if (-d $subdir) {
631 0         0 my $this = $dir . '_dir';
632 0         0 $self->{$this} = $subdir;
633             }
634             else {
635 1         324 croak "Could not locate $subdir; have you built and installed a perl executable?";
636             }
637             }
638 0         0 my $lib_dir = $self->get_lib_dir();
639 0         0 my $this_perl = File::Spec->catfile($self->get_bin_dir, 'perl');
640 0         0 my $invoke = "$this_perl -I$lib_dir";
641 0 0       0 my $rv = system(qq{$invoke -v | head -n 2 | tail -n 1})
642             and croak "Could not run perl executable at $this_perl";
643 0         0 $self->{this_perl} = $this_perl;
644              
645 0         0 my $this_cpan = File::Spec->catfile($self->get_bin_dir, 'cpan');
646 0         0 $invoke = "$this_cpan -v";
647 0 0       0 $rv = system(qq{$invoke})
648             and croak "Could not run cpan executable at $this_cpan";
649 0         0 $self->{this_cpan} = $this_cpan;
650              
651 0         0 return $self;
652             }
653              
654             =head2 C
655              
656             =over 4
657              
658             =item * Purpose
659              
660             Once C has been run, two additional methods
661             become available to help the code determine where it is.
662              
663             =over 4
664              
665             =item * bin directory (I)
666              
667             The directory underneath an individual C directory holding installed
668             executables such as F, F and F.
669              
670             =item * lib directory (I)
671              
672             The directory underneath an individual C directory holding the
673             libraries supporting the installed executables found in the C.
674              
675             =back
676              
677             =item * Arguments
678              
679             $bin_dir = $self->get_bin_dir();
680              
681             $lib_dir = $self->get_lib_dir();
682              
683             =item * Return Value
684              
685             String holding a path to the named directory.
686              
687             =item * Comment
688              
689             If the F executable has not yet been installed, these methods will
690             throw exceptions.
691              
692             =back
693              
694             =cut
695              
696             sub get_bin_dir {
697 4     4 1 943 my $self = shift;
698 4 50       56 if (! defined $self->{bin_dir}) {
699 4         611 croak "bin directory has not yet been defined; have you installed perl?";
700             }
701             else {
702 0         0 return $self->{bin_dir};
703             }
704             }
705              
706             sub get_lib_dir {
707 2     2 1 1715 my $self = shift;
708 2 50       16 if (! defined $self->{lib_dir}) {
709 2         254 croak "lib directory has not yet been defined; have you installed perl?";
710             }
711             else {
712 0         0 return $self->{lib_dir};
713             }
714             }
715              
716             =head2 C
717              
718             =over 4
719              
720             =item * Purpose
721              
722             Identify the location of the F executable file being tested.
723              
724             =item * Arguments
725              
726             $this_perl = $self->get_this_perl()
727              
728             =item * Return Value
729              
730             String holding the path to the F executable being tested.
731              
732             =item * Comment
733              
734             Will throw an exception if such a F executable has not yet been installed.
735              
736             =back
737              
738             =cut
739              
740             sub get_this_perl {
741 2     2 1 1693 my $self = shift;
742 2 50       14 if ($self->{this_perl}) {
743 0         0 return $self->{this_perl};
744             }
745             else {
746 2         10 local $@;
747 2         9 my $this_perl;
748 2         7 eval {
749 2         9 $this_perl = File::Spec->catfile($self->get_bin_dir, 'perl');
750             };
751 2 50       17 if ($@) {
    0          
752 2         193 croak $@;
753             }
754             elsif (-e $this_perl) {
755 0         0 $self->{this_perl} = $this_perl;
756 0         0 return $self->{this_perl};
757             }
758             else {
759 0         0 croak "No executable perl found at: $this_perl";
760             }
761             }
762             }
763              
764             =head2 C
765              
766             =over 4
767              
768             =item * Purpose
769              
770             Identify the location of the F executable file.
771              
772             =item * Arguments
773              
774             $this_cpan = $self->get_this_cpan()
775              
776             =item * Return Value
777              
778             String holding the path to the F executable being tested.
779              
780             =item * Comment
781              
782             Will throw an exception if such a F executable has not yet been installed. We will use F to subsequently install F.
783              
784             =back
785              
786             =cut
787              
788             sub get_this_cpan {
789 0     0 1 0 my $self = shift;
790 0 0       0 if ($self->{this_cpan}) {
791 0         0 return $self->{this_cpan};
792             }
793             else {
794 0         0 local $@;
795 0         0 my $this_cpan;
796 0         0 eval {
797 0         0 $this_cpan = File::Spec->catfile($self->get_bin_dir, 'cpan');
798             };
799 0 0       0 if ($@) {
    0          
800 0         0 croak $@;
801             }
802             elsif (-e $this_cpan) {
803 0         0 $self->{this_cpan} = $this_cpan;
804 0         0 return $self->{this_cpan};
805             }
806             else {
807 0         0 croak "No executable cpan found at: $this_cpan";
808             }
809             }
810             }
811              
812             =head2 C
813              
814             =over 4
815              
816             =item * Purpose
817              
818             Determine whether F has been installed. If it has not, install
819             F and the F executable against the installed F.
820              
821             =item * Arguments
822              
823             my $rv = $self->fetch_cpanm();
824              
825             None. All information is already inside the object. No C output.
826              
827             =item * Return Value
828              
829             Returns the Test::Against::Commit object, which now holds additional data.
830              
831             =item * Comment
832              
833             The F executable's location can subsequently be accessed by calling
834             C<$self->get_this_cpanm()>. The method also guarantees the existence of a
835             F<.cpanm> directory underneath the install directory, I side-by-side
836             with C and C. This directory can subsequently be accessed by
837             calling C<$self->get_cpanm_dir()>.
838              
839             =back
840              
841             =cut
842              
843             sub fetch_cpanm {
844 0     0 1 0 my $self = shift;
845              
846 0         0 my $cpanm_dir = File::Spec->catdir($self->get_testing_dir(), '.cpanm');
847 0 0       0 unless (-d $cpanm_dir) { make_path($cpanm_dir, { mode => 0755 }); }
  0         0  
848 0 0       0 croak "Could not locate $cpanm_dir" unless (-d $cpanm_dir);
849 0         0 $self->{cpanm_dir} = $cpanm_dir;
850              
851 0         0 my $bin_dir = $self->get_bin_dir();
852 0         0 my $this_cpan = File::Spec->catfile($bin_dir, 'cpan');
853 0         0 $self->{this_cpan} = $this_cpan;
854 0 0       0 system(qq| $this_cpan -v 1>/dev/null |) and croak "Unable to call 'cpan -v'";
855 0 0       0 system(qq| $this_cpan App::cpanminus 1>/dev/null |)
856             and croak "Unable to use cpan to install App::cpanminus";
857 0         0 my $this_cpanm = File::Spec->catfile($bin_dir, 'cpanm');
858 0 0       0 system(qq| $this_cpanm -V 1>/dev/null |) and croak "Unable to call 'cpanm -V'";
859 0         0 $self->{this_cpanm} = $this_cpanm;
860              
861 0         0 return $self;
862             }
863              
864             sub get_this_cpanm {
865 2     2 1 1660 my $self = shift;
866 2 50       16 if (! defined $self->{this_cpanm}) {
867 2         267 croak "location of cpanm has not yet been defined; run fetch_cpanm()";
868             }
869             else {
870 0         0 return $self->{this_cpanm};
871             }
872             }
873              
874             sub get_cpanm_dir {
875 2     2 1 1663 my $self = shift;
876 2 50       14 if (! defined $self->{cpanm_dir}) {
877 2         268 croak "cpanm directory has not yet been defined; run fetch_cpanm()";
878             }
879             else {
880 0           return $self->{cpanm_dir};
881             }
882             }
883              
884             =head2 C
885              
886             =over 4
887              
888             =item * Purpose
889              
890             Use F to install selected Perl modules against the F built for
891             testing purposes.
892              
893             =item * Arguments
894              
895             Two mutually exclusive interfaces:
896              
897             =over 4
898              
899             =item * Modules provided in a list
900              
901             my $modules_ref = $self->process_modules( {
902             module_list => [ 'DateTime', 'AnyEvent' ],
903             title => 'two-important-libraries',
904             verbose => 1,
905             } );
906              
907             =item * Modules listed in a file
908              
909             my $modules_ref = $self->process_modules( {
910             module_file => '/path/to/cpan-river-file.txt',
911             title => 'cpan-river-1000',
912             verbose => 1,
913             } );
914              
915             =back
916              
917             Each interface takes a hash reference with the following elements:
918              
919             =over 4
920              
921             =item * C B C
922              
923             Mutually exclusive; you may use one or the other but not both.
924              
925             The value of C must be an array reference holding a list of
926             modules for which you wish to assess the impact of changes in the Perl 5 core
927             distribution.
928              
929             The value of C must be an absolute path to a file which holds a
930             list of modules, one module per line. Lines in such a file that start with a
931             'C<#>' (hash-mark or sharp) be treated as a comment and no module listed on
932             that line will be processed.
933              
934             In either case the module names are spelled in C format --
935             I, double-colons -- rather than in C format
936             (hyphens).
937              
938             =item * C </td> </tr> <tr> <td class="h" > <a name="939">939</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="940">940</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> String which will be used to compose the name of project-specific output </td> </tr> <tr> <td class="h" > <a name="941">941</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> files. Required. </td> </tr> <tr> <td class="h" > <a name="942">942</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="943">943</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<verbose> </td> </tr> <tr> <td class="h" > <a name="944">944</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="945">945</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Extra information provided on STDOUT. Optional; defaults to being off; </td> </tr> <tr> <td class="h" > <a name="946">946</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> provide a Perl-true value to turn it on. Scope is limited to this method. </td> </tr> <tr> <td class="h" > <a name="947">947</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="948">948</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<dryrun> </td> </tr> <tr> <td class="h" > <a name="949">949</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="950">950</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Optional; defaults to being off. Program runs only as far as determining </td> </tr> <tr> <td class="h" > <a name="951">951</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> modules which the user will attempt to load, prints number of modules being </td> </tr> <tr> <td class="h" > <a name="952">952</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> attempted, then C<process_modules()> returns an undefined value (which would </td> </tr> <tr> <td class="h" > <a name="953">953</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> prevent subsequent methods from running correctly). </td> </tr> <tr> <td class="h" > <a name="954">954</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="955">955</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="956">956</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="957">957</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Return Value </td> </tr> <tr> <td class="h" > <a name="958">958</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="959">959</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Default: Single array reference holding a list of all modules that </td> </tr> <tr> <td class="h" > <a name="960">960</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> C<process_modules()> at least attempted to process. </td> </tr> <tr> <td class="h" > <a name="961">961</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="962">962</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> With true-value for C<dryrun>: Undefined value. </td> </tr> <tr> <td class="h" > <a name="963">963</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="964">964</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Comment </td> </tr> <tr> <td class="h" > <a name="965">965</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="966">966</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The method creates or confirms the existence of several directories underneath the </td> </tr> <tr> <td class="h" > <a name="967">967</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> I<results_dir> directory discussed above. These are illustrated as follows: </td> </tr> <tr> <td class="h" > <a name="968">968</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="969">969</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> /path-to-application/ # <-- application directory </td> </tr> <tr> <td class="h" > <a name="970">970</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> /path-to-application/goto-fatal/ # <-- project directory </td> </tr> <tr> <td class="h" > <a name="971">971</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> /path-to-application/goto-fatal/23ae7f95ea/ # <-- installation directory </td> </tr> <tr> <td class="h" > <a name="972">972</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> /path-to-application/goto-fatal/23ae7f95ea/testing/ # <-- testing directory </td> </tr> <tr> <td class="h" > <a name="973">973</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> /path-to-application/goto-fatal/23ae7f95ea/results/ # <-- results directory </td> </tr> <tr> <td class="h" > <a name="974">974</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> /path-to-application/goto-fatal/23ae7f95ea/results/analysis/ # <-- analysis directory </td> </tr> <tr> <td class="h" > <a name="975">975</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> /path-to-application/goto-fatal/23ae7f95ea/results/storage/ # <-- storage directory </td> </tr> <tr> <td class="h" > <a name="976">976</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="977">977</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="978">978</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="979">979</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =cut </td> </tr> <tr> <td class="h" > <a name="980">980</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="981">981</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub process_modules { </td> </tr> <tr> <td class="h" > <a name="982">982</a> </td> <td class="c0" > <a href="#983"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#982-1"> 0 </a> </td> <td class="c3" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#982-1"> 1 </a> </td> <td >   </td> <td class="s"> my ($self, $args) = @_; </td> </tr> <tr> <td class="h" > <a name="983">983</a> </td> <td class="c0" > <a href="#986"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#983-1"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#983-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "process_modules: Must supply hash ref as argument" </td> </tr> <tr> <td class="h" > <a name="984">984</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unless ( ( defined $args ) and ( ref($args) eq 'HASH' ) ); </td> </tr> <tr> <td class="h" > <a name="985">985</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="986">986</a> </td> <td class="c0" > <a href="#987"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#986-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $verbose = delete $args->{verbose} || ''; </td> </tr> <tr> <td class="h" > <a name="987">987</a> </td> <td class="c0" > <a href="#988"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#987-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $dryrun = delete $args->{dryrun} || ''; </td> </tr> <tr> <td class="h" > <a name="988">988</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my %eligible_args = map { $_ => 1 } ( qw| </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#991"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="989">989</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> module_file module_list title </td> </tr> <tr> <td class="h" > <a name="990">990</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> | ); </td> </tr> <tr> <td class="h" > <a name="991">991</a> </td> <td class="c0" > <a href="#993"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> for my $k (keys %$args) { </td> </tr> <tr> <td class="h" > <a name="992">992</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "process_modules: '$k' is not a valid element" </td> </tr> <tr> <td class="h" > <a name="993">993</a> </td> <td class="c0" > <a href="#996"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#993-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unless $eligible_args{$k}; </td> </tr> <tr> <td class="h" > <a name="994">994</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="995">995</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="996">996</a> </td> <td class="c0" > <a href="#997"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#996-1"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#996-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unless (defined $args->{title} and length $args->{title}) { </td> </tr> <tr> <td class="h" > <a name="997">997</a> </td> <td class="c0" > <a href="#999"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "Must supply value for 'title' element"; </td> </tr> <tr> <td class="h" > <a name="998">998</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="999">999</a> </td> <td class="c0" > <a href="#1001"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->{title} = $args->{title}; </td> </tr> <tr> <td class="h" > <a name="1000">1000</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1001">1001</a> </td> <td class="c0" > <a href="#1002"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1001-1"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#1001-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if (exists $args->{module_file} and exists $args->{module_list}) { </td> </tr> <tr> <td class="h" > <a name="1002">1002</a> </td> <td class="c0" > <a href="#1004"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "process_modules: Supply either a file for 'module_file' or an array ref for 'module_list' but not both"; </td> </tr> <tr> <td class="h" > <a name="1003">1003</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1004">1004</a> </td> <td class="c0" > <a href="#1005"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1004-1"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#1004-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if (! (exists $args->{module_file} or exists $args->{module_list}) ) { </td> </tr> <tr> <td class="h" > <a name="1005">1005</a> </td> <td class="c0" > <a href="#1007"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "process_modules: Must supply one of 'module_file' or 'module_list'"; </td> </tr> <tr> <td class="h" > <a name="1006">1006</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1007">1007</a> </td> <td class="c0" > <a href="#1009"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1007-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($args->{module_file}) { </td> </tr> <tr> <td class="h" > <a name="1008">1008</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "process_modules: Could not locate '$args->{module_file}'" </td> </tr> <tr> <td class="h" > <a name="1009">1009</a> </td> <td class="c0" > <a href="#1011"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1009-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unless (-f $args->{module_file}); </td> </tr> <tr> <td class="h" > <a name="1010">1010</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1011">1011</a> </td> <td class="c0" > <a href="#1013"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1011-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($args->{module_list}) { </td> </tr> <tr> <td class="h" > <a name="1012">1012</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "process_modules: Must supply array ref for 'module_list'" </td> </tr> <tr> <td class="h" > <a name="1013">1013</a> </td> <td class="c0" > <a href="#1016"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1013-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unless ref($args->{module_list}) eq 'ARRAY'; </td> </tr> <tr> <td class="h" > <a name="1014">1014</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1015">1015</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1016">1016</a> </td> <td class="c0" > <a href="#1018"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->setup_results_directories(); </td> </tr> <tr> <td class="h" > <a name="1017">1017</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1018">1018</a> </td> <td class="c0" > <a href="#1019"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1018-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say "cpanm_dir: ", $self->get_cpanm_dir() if $verbose; </td> </tr> <tr> <td class="h" > <a name="1019">1019</a> </td> <td class="c0" > <a href="#1021"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> local $ENV{PERL_CPANM_HOME} = $self->get_cpanm_dir(); </td> </tr> <tr> <td class="h" > <a name="1020">1020</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1021">1021</a> </td> <td class="c0" > <a href="#1022"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my @modules = (); </td> </tr> <tr> <td class="h" > <a name="1022">1022</a> </td> <td class="c0" > <a href="#1023"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1022-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($args->{module_list}) { </td> </tr> <tr> <td class="h" > <a name="1023">1023</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> @modules = @{$args->{module_list}}; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1027"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1024">1024</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1025">1025</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> else { </td> </tr> <tr> <td class="h" > <a name="1026">1026</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> open my $IN, '<', $args->{module_file} </td> </tr> <tr> <td class="h" > <a name="1027">1027</a> </td> <td class="c0" > <a href="#1028"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1027-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> or croak "Could not open $args->{module_file} for reading"; </td> </tr> <tr> <td class="h" > <a name="1028">1028</a> </td> <td class="c0" > <a href="#1029"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> while (my $m = <$IN>) { </td> </tr> <tr> <td class="h" > <a name="1029">1029</a> </td> <td class="c0" > <a href="#1030"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> chomp $m; </td> </tr> <tr> <td class="h" > <a name="1030">1030</a> </td> <td class="c0" > <a href="#1031"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1030-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> next if $m =~ m/^#/; # Skip lines that are commented out </td> </tr> <tr> <td class="h" > <a name="1031">1031</a> </td> <td class="c0" > <a href="#1033"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> push @modules, $m; </td> </tr> <tr> <td class="h" > <a name="1032">1032</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1033">1033</a> </td> <td class="c0" > <a href="#1035"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1033-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> close $IN or croak "Could not close $args->{module_file} after reading"; </td> </tr> <tr> <td class="h" > <a name="1034">1034</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1035">1035</a> </td> <td class="c0" > <a href="#1036"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1035-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($dryrun) { </td> </tr> <tr> <td class="h" > <a name="1036">1036</a> </td> <td class="c0" > <a href="#1037"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say "Planning to process ", scalar(@modules), " modules"; </td> </tr> <tr> <td class="h" > <a name="1037">1037</a> </td> <td class="c0" > <a href="#1038"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1037-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($verbose) { </td> </tr> <tr> <td class="h" > <a name="1038">1038</a> </td> <td class="c0" > <a href="#1040"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> dd(\@modules); </td> </tr> <tr> <td class="h" > <a name="1039">1039</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1040">1040</a> </td> <td class="c0" > <a href="#1043"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return; </td> </tr> <tr> <td class="h" > <a name="1041">1041</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1042">1042</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1043">1043</a> </td> <td class="c0" > <a href="#1045"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $libdir = $self->get_lib_dir(); </td> </tr> <tr> <td class="h" > <a name="1044">1044</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1045">1045</a> </td> <td class="c0" > <a href="#1048"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> for my $m (@modules) { </td> </tr> <tr> <td class="h" > <a name="1046">1046</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1047">1047</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Formulate the system call </td> </tr> <tr> <td class="h" > <a name="1048">1048</a> </td> <td class="c0" > <a href="#1056"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my @cmd = ( </td> </tr> <tr> <td class="h" > <a name="1049">1049</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->get_this_perl(), </td> </tr> <tr> <td class="h" > <a name="1050">1050</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> "-I$libdir", </td> </tr> <tr> <td class="h" > <a name="1051">1051</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->get_this_cpanm(), </td> </tr> <tr> <td class="h" > <a name="1052">1052</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $m, </td> </tr> <tr> <td class="h" > <a name="1053">1053</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ); </td> </tr> <tr> <td class="h" > <a name="1054">1054</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Execute the system call </td> </tr> <tr> <td class="h" > <a name="1055">1055</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="1056">1056</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> local $@; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1057"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1057">1057</a> </td> <td class="c0" > <a href="#1058"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $rv; </td> </tr> <tr> <td class="h" > <a name="1058">1058</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> eval { $rv = system(@cmd); }; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1059"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1059">1059</a> </td> <td class="c0" > <a href="#1060"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1059-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say "<$@>" if $@; </td> </tr> <tr> <td class="h" > <a name="1060">1060</a> </td> <td class="c0" > <a href="#1063"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1060-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say $self->get_this_cpanm(), " exited with ", $rv >> 8 </td> </tr> <tr> <td class="h" > <a name="1061">1061</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($verbose); </td> </tr> <tr> <td class="h" > <a name="1062">1062</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1063">1063</a> </td> <td class="c0" > <a href="#1065"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $this_buildlog_link = </td> </tr> <tr> <td class="h" > <a name="1064">1064</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> File::Spec->catfile($self->get_cpanm_dir(), 'build.log'); </td> </tr> <tr> <td class="h" > <a name="1065">1065</a> </td> <td class="c0" > <a href="#1066"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1065-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "$this_buildlog_link is not a symlink" unless (-l $this_buildlog_link); </td> </tr> <tr> <td class="h" > <a name="1066">1066</a> </td> <td class="c0" > <a href="#1067"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $this_buildlog = readlink($this_buildlog_link); </td> </tr> <tr> <td class="h" > <a name="1067">1067</a> </td> <td class="c0" > <a href="#1069"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1067-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "$this_buildlog not found" unless (-f $this_buildlog); </td> </tr> <tr> <td class="h" > <a name="1068">1068</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1069">1069</a> </td> <td class="c0" > <a href="#1075"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->process_one_report($this_buildlog); </td> </tr> <tr> <td class="h" > <a name="1070">1070</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1071">1071</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1072">1072</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # End of loop. </td> </tr> <tr> <td class="h" > <a name="1073">1073</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # This should lead to 100s of .json files in the analysis_dir. </td> </tr> <tr> <td class="h" > <a name="1074">1074</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1075">1075</a> </td> <td class="c0" > <a href="#1079"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return [ @modules ]; </td> </tr> <tr> <td class="h" > <a name="1076">1076</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1077">1077</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1078">1078</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub setup_results_directories { </td> </tr> <tr> <td class="h" > <a name="1079">1079</a> </td> <td class="c0" > <a href="#1080"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1079-1"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1079-1"> 0 </a> </td> <td >   </td> <td class="s"> my $self = shift; </td> </tr> <tr> <td class="h" > <a name="1080">1080</a> </td> <td class="c0" > <a href="#1081"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $results_dir = $self->get_results_dir(); </td> </tr> <tr> <td class="h" > <a name="1081">1081</a> </td> <td class="c0" > <a href="#1082"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $analysis_dir = File::Spec->catdir($results_dir, 'analysis'); </td> </tr> <tr> <td class="h" > <a name="1082">1082</a> </td> <td class="c0" > <a href="#1083"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $storage_dir = File::Spec->catdir($results_dir, 'storage'); </td> </tr> <tr> <td class="h" > <a name="1083">1083</a> </td> <td class="c0" > <a href="#1085"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my @created = make_path( $analysis_dir, $storage_dir, </td> </tr> <tr> <td class="h" > <a name="1084">1084</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { mode => 0755 }); </td> </tr> <tr> <td class="h" > <a name="1085">1085</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1085-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> for my $dir (@created) { croak "$dir not found" unless -d $dir; } </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1086"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1086">1086</a> </td> <td class="c0" > <a href="#1087"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->{analysis_dir} = $analysis_dir; </td> </tr> <tr> <td class="h" > <a name="1087">1087</a> </td> <td class="c0" > <a href="#1088"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->{storage_dir} = $storage_dir; </td> </tr> <tr> <td class="h" > <a name="1088">1088</a> </td> <td class="c0" > <a href="#1092"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return scalar(@created); </td> </tr> <tr> <td class="h" > <a name="1089">1089</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1090">1090</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1091">1091</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub process_one_report { </td> </tr> <tr> <td class="h" > <a name="1092">1092</a> </td> <td class="c0" > <a href="#1093"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1092-1"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1092-1"> 0 </a> </td> <td >   </td> <td class="s"> my ($self, $this_buildlog) = @_; </td> </tr> <tr> <td class="h" > <a name="1093">1093</a> </td> <td class="c0" > <a href="#1099"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $reporter = CPAN::cpanminus::reporter::RetainReports->new( </td> </tr> <tr> <td class="h" > <a name="1094">1094</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> force => 1, # ignore mtime check on build.log </td> </tr> <tr> <td class="h" > <a name="1095">1095</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> build_logfile => $this_buildlog, </td> </tr> <tr> <td class="h" > <a name="1096">1096</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> build_dir => $self->get_cpanm_dir(), </td> </tr> <tr> <td class="h" > <a name="1097">1097</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'ignore-versions' => 1, </td> </tr> <tr> <td class="h" > <a name="1098">1098</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ); </td> </tr> <tr> <td class="h" > <a name="1099">1099</a> </td> <td class="c0" > <a href="#1102"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1099-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "Unable to create new reporter for $this_buildlog" </td> </tr> <tr> <td class="h" > <a name="1100">1100</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unless defined $reporter; </td> </tr> <tr> <td class="h" > <a name="1101">1101</a> </td> <td class="c3" > 2 </td> <td >   </td> <td >   </td> <td class="c3" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1101-1"> 2 </a> </td> <td >   </td> <td > 21 </td> <td class="s"> no warnings 'redefine'; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c3" > 2 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 4 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c3" > 2 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 3950 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1102">1102</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1102-1"> 0 </a> </td> <td >   </td> <td >   </td> <td class="s"> local *CPAN::cpanminus::reporter::RetainReports::_check_cpantesters_config_data = sub { 1 }; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1103"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1103">1103</a> </td> <td class="c0" > <a href="#1104"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $reporter->set_report_dir($self->get_analysis_dir()); </td> </tr> <tr> <td class="h" > <a name="1104">1104</a> </td> <td class="c0" > <a href="#1105"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $reporter->run; </td> </tr> <tr> <td class="h" > <a name="1105">1105</a> </td> <td class="c0" > <a href="#1150"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return 1; </td> </tr> <tr> <td class="h" > <a name="1106">1106</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1107">1107</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1108">1108</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 C<get_analysis_dir() get_storage_dir()> </td> </tr> <tr> <td class="h" > <a name="1109">1109</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1110">1110</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="1111">1111</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1112">1112</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Purpose </td> </tr> <tr> <td class="h" > <a name="1113">1113</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1114">1114</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Once C<process_modules()> has been run, two additional methods become available to </td> </tr> <tr> <td class="h" > <a name="1115">1115</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> help code determine where output data are located. </td> </tr> <tr> <td class="h" > <a name="1116">1116</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1117">1117</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="1118">1118</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1119">1119</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * analysis directory (I<analysis_dir>) </td> </tr> <tr> <td class="h" > <a name="1120">1120</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1121">1121</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The directory underneath the I<results directory> holding files representing </td> </tr> <tr> <td class="h" > <a name="1122">1122</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> the parsed content of the build log of the most recent run. These files are </td> </tr> <tr> <td class="h" > <a name="1123">1123</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> in C<.json> format. </td> </tr> <tr> <td class="h" > <a name="1124">1124</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1125">1125</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * storage directory (I<storage_dir>) </td> </tr> <tr> <td class="h" > <a name="1126">1126</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1127">1127</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The directory underneath the I<results directory> holding final output results. </td> </tr> <tr> <td class="h" > <a name="1128">1128</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1129">1129</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="1130">1130</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1131">1131</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Arguments </td> </tr> <tr> <td class="h" > <a name="1132">1132</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1133">1133</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $storage_dir = $self->get_storage_dir(); </td> </tr> <tr> <td class="h" > <a name="1134">1134</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1135">1135</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Return Value </td> </tr> <tr> <td class="h" > <a name="1136">1136</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1137">1137</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> String holding a path to the named directory. </td> </tr> <tr> <td class="h" > <a name="1138">1138</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1139">1139</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Comment </td> </tr> <tr> <td class="h" > <a name="1140">1140</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1141">1141</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> These directories are only confirmed to exist once internal method </td> </tr> <tr> <td class="h" > <a name="1142">1142</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> C<setup_results_directories()> has been executed. (That method is called </td> </tr> <tr> <td class="h" > <a name="1143">1143</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> within C<process_modules()>.) Otherwise, these methods will throw exceptions. </td> </tr> <tr> <td class="h" > <a name="1144">1144</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1145">1145</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="1146">1146</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1147">1147</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =cut </td> </tr> <tr> <td class="h" > <a name="1148">1148</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1149">1149</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub get_analysis_dir { </td> </tr> <tr> <td class="h" > <a name="1150">1150</a> </td> <td class="c0" > <a href="#1151"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1150-1"> 0 </a> </td> <td class="c3" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1150-1"> 1 </a> </td> <td >   </td> <td class="s"> my $self = shift; </td> </tr> <tr> <td class="h" > <a name="1151">1151</a> </td> <td class="c0" > <a href="#1152"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1151-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if (! defined $self->{analysis_dir}) { </td> </tr> <tr> <td class="h" > <a name="1152">1152</a> </td> <td class="c0" > <a href="#1155"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "analysis directory has not yet been defined"; </td> </tr> <tr> <td class="h" > <a name="1153">1153</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1154">1154</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> else { </td> </tr> <tr> <td class="h" > <a name="1155">1155</a> </td> <td class="c0" > <a href="#1160"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $self->{analysis_dir}; </td> </tr> <tr> <td class="h" > <a name="1156">1156</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1157">1157</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1158">1158</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1159">1159</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub get_storage_dir { </td> </tr> <tr> <td class="h" > <a name="1160">1160</a> </td> <td class="c0" > <a href="#1161"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1160-1"> 0 </a> </td> <td class="c3" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1160-1"> 1 </a> </td> <td >   </td> <td class="s"> my $self = shift; </td> </tr> <tr> <td class="h" > <a name="1161">1161</a> </td> <td class="c0" > <a href="#1162"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1161-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if (! defined $self->{storage_dir}) { </td> </tr> <tr> <td class="h" > <a name="1162">1162</a> </td> <td class="c0" > <a href="#1165"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "storage directory has not yet been defined"; </td> </tr> <tr> <td class="h" > <a name="1163">1163</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1164">1164</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> else { </td> </tr> <tr> <td class="h" > <a name="1165">1165</a> </td> <td class="c0" > <a href="#1214"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $self->{storage_dir}; </td> </tr> <tr> <td class="h" > <a name="1166">1166</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1167">1167</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1168">1168</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1169">1169</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 C<analyze_json_logs()> </td> </tr> <tr> <td class="h" > <a name="1170">1170</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1171">1171</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="1172">1172</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1173">1173</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Purpose </td> </tr> <tr> <td class="h" > <a name="1174">1174</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1175">1175</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Create a character-delimited-values file summarizing the results of a given </td> </tr> <tr> <td class="h" > <a name="1176">1176</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> run. The delimiter defaults to a pipe (C<|>), thereby creating a </td> </tr> <tr> <td class="h" > <a name="1177">1177</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> pipe-separated values file (C<.psv>), but you may select a comma (C<,>), </td> </tr> <tr> <td class="h" > <a name="1178">1178</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> generating a comma-separated-values file (C<.csv>) as well. </td> </tr> <tr> <td class="h" > <a name="1179">1179</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1180">1180</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Arguments </td> </tr> <tr> <td class="h" > <a name="1181">1181</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1182">1182</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $fcdvfile = $self->analyze_json_logs( { verbose => 1, sep_char => '|' } ); </td> </tr> <tr> <td class="h" > <a name="1183">1183</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1184">1184</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Hash reference with these elements: </td> </tr> <tr> <td class="h" > <a name="1185">1185</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1186">1186</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="1187">1187</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1188">1188</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<verbose> </td> </tr> <tr> <td class="h" > <a name="1189">1189</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1190">1190</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Extra information provided on STDOUT. Optional; defaults to being off; </td> </tr> <tr> <td class="h" > <a name="1191">1191</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> provide a Perl-true value to turn it on. Scope is limited to this method. </td> </tr> <tr> <td class="h" > <a name="1192">1192</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1193">1193</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<sep_char> </td> </tr> <tr> <td class="h" > <a name="1194">1194</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1195">1195</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Delimiter character. Optional; defaults to pipe (C<|>), but comma (C<,>) may </td> </tr> <tr> <td class="h" > <a name="1196">1196</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> also be chosen. </td> </tr> <tr> <td class="h" > <a name="1197">1197</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1198">1198</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="1199">1199</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1200">1200</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Return Value </td> </tr> <tr> <td class="h" > <a name="1201">1201</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1202">1202</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> String holding absolute path to the C<.psv> or C<.csv> file created. </td> </tr> <tr> <td class="h" > <a name="1203">1203</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1204">1204</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Comment </td> </tr> <tr> <td class="h" > <a name="1205">1205</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1206">1206</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> As a precaution, the function creates a tarball to archive the F<.log.json> </td> </tr> <tr> <td class="h" > <a name="1207">1207</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> files for a given run. </td> </tr> <tr> <td class="h" > <a name="1208">1208</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1209">1209</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="1210">1210</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1211">1211</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =cut </td> </tr> <tr> <td class="h" > <a name="1212">1212</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1213">1213</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub analyze_json_logs { </td> </tr> <tr> <td class="h" > <a name="1214">1214</a> </td> <td class="c0" > <a href="#1221"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1214-1"> 0 </a> </td> <td class="c3" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1214-1"> 1 </a> </td> <td >   </td> <td class="s"> my ($self, $args) = @_; </td> </tr> <tr> <td class="h" > <a name="1215">1215</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # TODO: If we don't have an $args supplied at all, that's okay provided we </td> </tr> <tr> <td class="h" > <a name="1216">1216</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # can ensure that we will have a default sep_char set </td> </tr> <tr> <td class="h" > <a name="1217">1217</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this method with hash ref but lacking 'verbose' </td> </tr> <tr> <td class="h" > <a name="1218">1218</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this method with hash ref but lacking 'sep_char' </td> </tr> <tr> <td class="h" > <a name="1219">1219</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this method with hash ref but both KVPs </td> </tr> <tr> <td class="h" > <a name="1220">1220</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this method with no arg </td> </tr> <tr> <td class="h" > <a name="1221">1221</a> </td> <td class="c0" > <a href="#1223"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1221-1"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#1221-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "analyze_json_logs: Must supply hash ref as argument" </td> </tr> <tr> <td class="h" > <a name="1222">1222</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unless ( ( defined $args ) and ( ref($args) eq 'HASH' ) ); </td> </tr> <tr> <td class="h" > <a name="1223">1223</a> </td> <td class="c0" > <a href="#1224"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#1223-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $verbose = delete $args->{verbose} || ''; </td> </tr> <tr> <td class="h" > <a name="1224">1224</a> </td> <td class="c0" > <a href="#1225"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#1224-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $sep_char = delete $args->{sep_char} || '|'; </td> </tr> <tr> <td class="h" > <a name="1225">1225</a> </td> <td class="c0" > <a href="#1229"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1225-1"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--condition.html#1225-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "analyze_json_logs: Currently only pipe ('|') and comma (',') are supported as delimiter characters" </td> </tr> <tr> <td class="h" > <a name="1226">1226</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unless ($sep_char eq '|' or $sep_char eq ','); </td> </tr> <tr> <td class="h" > <a name="1227">1227</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1228">1228</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Locate our log.json files </td> </tr> <tr> <td class="h" > <a name="1229">1229</a> </td> <td class="c0" > <a href="#1231"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $json_log_files = $self->_list_log_files(); </td> </tr> <tr> <td class="h" > <a name="1230">1230</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test without verbose </td> </tr> <tr> <td class="h" > <a name="1231">1231</a> </td> <td class="c0" > <a href="#1234"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1231-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> dd($json_log_files) if $verbose; </td> </tr> <tr> <td class="h" > <a name="1232">1232</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1233">1233</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # As a precaution, we archive those log.json files. </td> </tr> <tr> <td class="h" > <a name="1234">1234</a> </td> <td class="c0" > <a href="#1242"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->_archive_log_files( { </td> </tr> <tr> <td class="h" > <a name="1235">1235</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> json_log_files => $json_log_files, </td> </tr> <tr> <td class="h" > <a name="1236">1236</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # $verbose: ensure that it is initialized, if only to '' </td> </tr> <tr> <td class="h" > <a name="1237">1237</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> verbose => $verbose, </td> </tr> <tr> <td class="h" > <a name="1238">1238</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } ); </td> </tr> <tr> <td class="h" > <a name="1239">1239</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1240">1240</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Having archived our log.json files, we now proceed to read them and to </td> </tr> <tr> <td class="h" > <a name="1241">1241</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # write a pipe- (or comma-) separated-values file summarizing the run. </td> </tr> <tr> <td class="h" > <a name="1242">1242</a> </td> <td class="c0" > <a href="#1243"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my %data = (); </td> </tr> <tr> <td class="h" > <a name="1243">1243</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> for my $log (@{$json_log_files}) { </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1244"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1244">1244</a> </td> <td class="c0" > <a href="#1245"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $flog = File::Spec->catfile($self->{results_dir}, $log); </td> </tr> <tr> <td class="h" > <a name="1245">1245</a> </td> <td class="c0" > <a href="#1246"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my %this = (); </td> </tr> <tr> <td class="h" > <a name="1246">1246</a> </td> <td class="c0" > <a href="#1247"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $f = Path::Tiny::path($flog); </td> </tr> <tr> <td class="h" > <a name="1247">1247</a> </td> <td class="c0" > <a href="#1249"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $decoded; </td> </tr> <tr> <td class="h" > <a name="1248">1248</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="1249">1249</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> local $@; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1250"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1250">1250</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> eval { $decoded = decode_json($f->slurp_utf8); }; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1251"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1251">1251</a> </td> <td class="c0" > <a href="#1252"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1251-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($@) { </td> </tr> <tr> <td class="h" > <a name="1252">1252</a> </td> <td class="c0" > <a href="#1253"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> warn "JSON decoding problem in $flog: <$@>"; </td> </tr> <tr> <td class="h" > <a name="1253">1253</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> eval { $decoded = JSON->new->decode($f->slurp_utf8); }; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1256"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1254">1254</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1255">1255</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1256">1256</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> map { $this{$_} = $decoded->{$_} } ( qw| author distname grade | ); </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1257"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1257">1257</a> </td> <td class="c0" > <a href="#1261"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $data{$decoded->{dist}} = \%this; </td> </tr> <tr> <td class="h" > <a name="1258">1258</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1259">1259</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1260">1260</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Now we create a CSV file (really ... a PSV) </td> </tr> <tr> <td class="h" > <a name="1261">1261</a> </td> <td class="c0" > <a href="#1269"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $fcdvfile = $self->_create_csv_file( { </td> </tr> <tr> <td class="h" > <a name="1262">1262</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # $verbose: ensure that it is initialized, if only to '' </td> </tr> <tr> <td class="h" > <a name="1263">1263</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sep_char => $sep_char, </td> </tr> <tr> <td class="h" > <a name="1264">1264</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> data => \%data, </td> </tr> <tr> <td class="h" > <a name="1265">1265</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # $verbose: ensure that it is initialized, if only to '' </td> </tr> <tr> <td class="h" > <a name="1266">1266</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> verbose => $verbose, </td> </tr> <tr> <td class="h" > <a name="1267">1267</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } ); </td> </tr> <tr> <td class="h" > <a name="1268">1268</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1269">1269</a> </td> <td class="c0" > <a href="#1273"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $fcdvfile; </td> </tr> <tr> <td class="h" > <a name="1270">1270</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1271">1271</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1272">1272</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _list_log_files { </td> </tr> <tr> <td class="h" > <a name="1273">1273</a> </td> <td class="c0" > <a href="#1274"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1273-1"> 0 </a> </td> <td >   </td> <td >   </td> <td class="s"> my $self = shift; </td> </tr> <tr> <td class="h" > <a name="1274">1274</a> </td> <td class="c0" > <a href="#1275"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $analysis_dir = $self->{analysis_dir}; </td> </tr> <tr> <td class="h" > <a name="1275">1275</a> </td> <td class="c0" > <a href="#1276"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1275-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> opendir my $DIRH, $analysis_dir or croak "Unable to open $analysis_dir for reading"; </td> </tr> <tr> <td class="h" > <a name="1276">1276</a> </td> <td class="c0" > <a href="#1277"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my @json_log_files = sort map { File::Spec->catfile('analysis', $_) } </td> </tr> <tr> <td class="h" > <a name="1277">1277</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> grep { m/\.log\.json$/ } readdir $DIRH; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1278"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1278">1278</a> </td> <td class="c0" > <a href="#1279"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1278-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> closedir $DIRH or croak "Unable to close $analysis_dir after reading"; </td> </tr> <tr> <td class="h" > <a name="1279">1279</a> </td> <td class="c0" > <a href="#1283"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return \@json_log_files; </td> </tr> <tr> <td class="h" > <a name="1280">1280</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1281">1281</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1282">1282</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _archive_log_files { </td> </tr> <tr> <td class="h" > <a name="1283">1283</a> </td> <td class="c0" > <a href="#1288"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1283-1"> 0 </a> </td> <td >   </td> <td >   </td> <td class="s"> my ($self, $args) = @_; </td> </tr> <tr> <td class="h" > <a name="1284">1284</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # TODO: Is this file name self-documenting enough? Need datestamp? </td> </tr> <tr> <td class="h" > <a name="1285">1285</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $output = join('.' => ( </td> </tr> <tr> <td class="h" > <a name="1286">1286</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->{title}, </td> </tr> <tr> <td class="h" > <a name="1287">1287</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->{install}, </td> </tr> <tr> <td class="h" > <a name="1288">1288</a> </td> <td class="c0" > <a href="#1293"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'log', </td> </tr> <tr> <td class="h" > <a name="1289">1289</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'json', </td> </tr> <tr> <td class="h" > <a name="1290">1290</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'tar', </td> </tr> <tr> <td class="h" > <a name="1291">1291</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'gz' </td> </tr> <tr> <td class="h" > <a name="1292">1292</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) ); </td> </tr> <tr> <td class="h" > <a name="1293">1293</a> </td> <td class="c0" > <a href="#1295"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $foutput = File::Spec->catfile($self->{storage_dir}, $output); </td> </tr> <tr> <td class="h" > <a name="1294">1294</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this without $args->{verbose} </td> </tr> <tr> <td class="h" > <a name="1295">1295</a> </td> <td class="c0" > <a href="#1296"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1295-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say "Output will be: $foutput" if $args->{verbose}; </td> </tr> <tr> <td class="h" > <a name="1296">1296</a> </td> <td class="c0" > <a href="#1297"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $versioned_results_dir = $self->{results_dir}; </td> </tr> <tr> <td class="h" > <a name="1297">1297</a> </td> <td class="c0" > <a href="#1298"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $previous_cwd = cwd(); </td> </tr> <tr> <td class="h" > <a name="1298">1298</a> </td> <td class="c0" > <a href="#1300"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1298-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> chdir $self->{results_dir} or croak "Unable to chdir to $self->{results_dir}"; </td> </tr> <tr> <td class="h" > <a name="1299">1299</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this without $args->{verbose} </td> </tr> <tr> <td class="h" > <a name="1300">1300</a> </td> <td class="c0" > <a href="#1301"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1300-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say "Now in $self->{results_dir}" if $args->{verbose}; </td> </tr> <tr> <td class="h" > <a name="1301">1301</a> </td> <td class="c0" > <a href="#1302"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $tar = Archive::Tar->new; </td> </tr> <tr> <td class="h" > <a name="1302">1302</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $tar->add_files(@{$args->{json_log_files}}); </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1303"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1303">1303</a> </td> <td class="c0" > <a href="#1304"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $tar->write($foutput, COMPRESS_GZIP); </td> </tr> <tr> <td class="h" > <a name="1304">1304</a> </td> <td class="c0" > <a href="#1306"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1304-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "$foutput not created" unless (-f $foutput); </td> </tr> <tr> <td class="h" > <a name="1305">1305</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this without $args->{verbose} </td> </tr> <tr> <td class="h" > <a name="1306">1306</a> </td> <td class="c0" > <a href="#1307"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1306-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say "Created archive $foutput" if $args->{verbose}; </td> </tr> <tr> <td class="h" > <a name="1307">1307</a> </td> <td class="c0" > <a href="#1308"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1307-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> chdir $previous_cwd or croak "Unable to change back to $previous_cwd"; </td> </tr> <tr> <td class="h" > <a name="1308">1308</a> </td> <td class="c0" > <a href="#1312"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return 1; </td> </tr> <tr> <td class="h" > <a name="1309">1309</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1310">1310</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1311">1311</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _create_csv_file { </td> </tr> <tr> <td class="h" > <a name="1312">1312</a> </td> <td class="c0" > <a href="#1317"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--subroutine.html#1312-1"> 0 </a> </td> <td >   </td> <td >   </td> <td class="s"> my ($self, $args) = @_; </td> </tr> <tr> <td class="h" > <a name="1313">1313</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1314">1314</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $cdvfile = join('.' => ( </td> </tr> <tr> <td class="h" > <a name="1315">1315</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->{title}, </td> </tr> <tr> <td class="h" > <a name="1316">1316</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $self->{install}, </td> </tr> <tr> <td class="h" > <a name="1317">1317</a> </td> <td class="c0" > <a href="#1319"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1317-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (($args->{sep_char} eq ',') ? 'csv' : 'psv'), </td> </tr> <tr> <td class="h" > <a name="1318">1318</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) ); </td> </tr> <tr> <td class="h" > <a name="1319">1319</a> </td> <td class="c0" > <a href="#1321"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $fcdvfile = File::Spec->catfile($self->{storage_dir}, $cdvfile); </td> </tr> <tr> <td class="h" > <a name="1320">1320</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this without $args->{verbose} </td> </tr> <tr> <td class="h" > <a name="1321">1321</a> </td> <td class="c0" > <a href="#1323"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1321-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say "Output will be: $fcdvfile" if $args->{verbose}; </td> </tr> <tr> <td class="h" > <a name="1322">1322</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1323">1323</a> </td> <td class="c0" > <a href="#1324"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my @fields = ( qw| author distname grade | ); </td> </tr> <tr> <td class="h" > <a name="1324">1324</a> </td> <td class="c0" > <a href="#1325"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $install = $self->{install}; </td> </tr> <tr> <td class="h" > <a name="1325">1325</a> </td> <td class="c0" > <a href="#1333"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $columns = [ </td> </tr> <tr> <td class="h" > <a name="1326">1326</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'dist', </td> </tr> <tr> <td class="h" > <a name="1327">1327</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> @fields, </td> </tr> <tr> <td class="h" > <a name="1328">1328</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ]; </td> </tr> <tr> <td class="h" > <a name="1329">1329</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $psv = Text::CSV_XS->new({ </td> </tr> <tr> <td class="h" > <a name="1330">1330</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> binary => 1, </td> </tr> <tr> <td class="h" > <a name="1331">1331</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> auto_diag => 1, </td> </tr> <tr> <td class="h" > <a name="1332">1332</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sep_char => $args->{sep_char}, </td> </tr> <tr> <td class="h" > <a name="1333">1333</a> </td> <td class="c0" > <a href="#1335"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> eol => $/, </td> </tr> <tr> <td class="h" > <a name="1334">1334</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }); </td> </tr> <tr> <td class="h" > <a name="1335">1335</a> </td> <td class="c0" > <a href="#1337"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1335-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> open my $OUT, ">:encoding(utf8)", $fcdvfile </td> </tr> <tr> <td class="h" > <a name="1336">1336</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> or croak "Unable to open $fcdvfile for writing"; </td> </tr> <tr> <td class="h" > <a name="1337">1337</a> </td> <td class="c0" > <a href="#1338"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1337-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $psv->print($OUT, $columns), "\n" or $psv->error_diag; </td> </tr> <tr> <td class="h" > <a name="1338">1338</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> for my $dist (sort keys %{$args->{data}}) { </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1341"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1339">1339</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $psv->print($OUT, [ </td> </tr> <tr> <td class="h" > <a name="1340">1340</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $dist, </td> </tr> <tr> <td class="h" > <a name="1341">1341</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1341-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> @{$args->{data}->{$dist}}{@fields}, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#1344"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1342">1342</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ]) or $psv->error_diag; </td> </tr> <tr> <td class="h" > <a name="1343">1343</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1344">1344</a> </td> <td class="c0" > <a href="#1345"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1344-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> close $OUT or croak "Unable to close $fcdvfile after writing"; </td> </tr> <tr> <td class="h" > <a name="1345">1345</a> </td> <td class="c0" > <a href="#1350"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1345-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> croak "$fcdvfile not created" unless (-f $fcdvfile); </td> </tr> <tr> <td class="h" > <a name="1346">1346</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Test this without $args->{verbose} </td> </tr> <tr> <td class="h" > <a name="1347">1347</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> say "Examine ", </td> </tr> <tr> <td class="h" > <a name="1348">1348</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (($args->{sep_char} eq ',') ? 'comma' : 'pipe'), </td> </tr> <tr> <td class="h" > <a name="1349">1349</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> "-separated values in $fcdvfile" </td> </tr> <tr> <td class="h" > <a name="1350">1350</a> </td> <td class="c0" > <a href="#1351"> 0 </a> </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#1350-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if $args->{verbose}; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td >   </td> <td class="c0" > <a href="blib-lib-Test-Against-Commit-pm--branch.html#-2"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1351">1351</a> </td> <td class="c0" > 0 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $fcdvfile; </td> </tr> <tr> <td class="h" > <a name="1352">1352</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1353">1353</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1354">1354</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 1; </td> </tr> <tr> <td class="h" > <a name="1355">1355</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1356">1356</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 LIMITATIONS </td> </tr> <tr> <td class="h" > <a name="1357">1357</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1358">1358</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This library has a fair number of direct and indirect dependencies on other </td> </tr> <tr> <td class="h" > <a name="1359">1359</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> CPAN libraries. Consequently, the library may experience problems if there </td> </tr> <tr> <td class="h" > <a name="1360">1360</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> are major changes in those libraries. In particular, the code is indirectly </td> </tr> <tr> <td class="h" > <a name="1361">1361</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> dependent upon F<App::cpanminus::reporter>, which in turn is dependent upon </td> </tr> <tr> <td class="h" > <a name="1362">1362</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> F<cpanm>. (Nonetheless, this software could never have been written without </td> </tr> <tr> <td class="h" > <a name="1363">1363</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> those two libraries by Breno G. de Oliveira and Tatsuhiko Miyagawa, </td> </tr> <tr> <td class="h" > <a name="1364">1364</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> respectively.) </td> </tr> <tr> <td class="h" > <a name="1365">1365</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1366">1366</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This library has been developed in a Unix programming environment and is </td> </tr> <tr> <td class="h" > <a name="1367">1367</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> unlikely to work in its current form on Windows, Cygwin or VMS. </td> </tr> <tr> <td class="h" > <a name="1368">1368</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1369">1369</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 AUTHOR </td> </tr> <tr> <td class="h" > <a name="1370">1370</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1371">1371</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> James E Keenan </td> </tr> <tr> <td class="h" > <a name="1372">1372</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> CPAN ID: JKEENAN </td> </tr> <tr> <td class="h" > <a name="1373">1373</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> jkeenan@cpan.org </td> </tr> <tr> <td class="h" > <a name="1374">1374</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> http://thenceforward.net/perl </td> </tr> <tr> <td class="h" > <a name="1375">1375</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1376">1376</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 SUPPORT </td> </tr> <tr> <td class="h" > <a name="1377">1377</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1378">1378</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Please report any bugs in our GitHub Issues queue at </td> </tr> <tr> <td class="h" > <a name="1379">1379</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<https://github.com/jkeenan/perl5-test-cpan-against-commit/issues>. </td> </tr> <tr> <td class="h" > <a name="1380">1380</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1381">1381</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 COPYRIGHT </td> </tr> <tr> <td class="h" > <a name="1382">1382</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1383">1383</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This program is free software; you can redistribute </td> </tr> <tr> <td class="h" > <a name="1384">1384</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> it and/or modify it under the same terms as Perl itself. </td> </tr> <tr> <td class="h" > <a name="1385">1385</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1386">1386</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The full text of the license can be found in the </td> </tr> <tr> <td class="h" > <a name="1387">1387</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> LICENSE file included with this module. </td> </tr> <tr> <td class="h" > <a name="1388">1388</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1389">1389</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Copyright James E Keenan 2017-2025. All rights reserved. </td> </tr> <tr> <td class="h" > <a name="1390">1390</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1391">1391</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 ACKNOWLEDGEMENTS </td> </tr> <tr> <td class="h" > <a name="1392">1392</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1393">1393</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This library's ancestor, Test-Against-Dev, emerged in the wake of the author's </td> </tr> <tr> <td class="h" > <a name="1394">1394</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> participation in the Perl 5 Core Hackathon held in Amsterdam, Netherlands, in </td> </tr> <tr> <td class="h" > <a name="1395">1395</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> October 2017. The author thanks the lead organizers of that event, Sawyer X </td> </tr> <tr> <td class="h" > <a name="1396">1396</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> and Todd Rinaldo, for the invitation to the hackathon. The event could not </td> </tr> <tr> <td class="h" > <a name="1397">1397</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> have happened without the generous contributions from the following companies: </td> </tr> <tr> <td class="h" > <a name="1398">1398</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1399">1399</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="1400">1400</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1401">1401</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * L<Booking.com|https://www.booking.com> </td> </tr> <tr> <td class="h" > <a name="1402">1402</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1403">1403</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * L<cPanel|https://cpanel.com> </td> </tr> <tr> <td class="h" > <a name="1404">1404</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1405">1405</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * L<Craigslist|https://www.craigslist.org/about/craigslist_is_hiring> </td> </tr> <tr> <td class="h" > <a name="1406">1406</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1407">1407</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * L<Bluehost|https://www.bluehost.com/> </td> </tr> <tr> <td class="h" > <a name="1408">1408</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1409">1409</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * L<Assurant|https://www.assurantmortgagesolutions.com/> </td> </tr> <tr> <td class="h" > <a name="1410">1410</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1411">1411</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * L<Grant Street Group|https://grantstreet.com/> </td> </tr> <tr> <td class="h" > <a name="1412">1412</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1413">1413</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="1414">1414</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1415">1415</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 Additional Contributors </td> </tr> <tr> <td class="h" > <a name="1416">1416</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1417">1417</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="1418">1418</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1419">1419</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * Mohammad S Anwar </td> </tr> <tr> <td class="h" > <a name="1420">1420</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1421">1421</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="1422">1422</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1423">1423</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 SEE ALSO </td> </tr> <tr> <td class="h" > <a name="1424">1424</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1425">1425</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> perl(1). CPAN::cpanminus::reporter::RetainReports(3). </td> </tr> <tr> <td class="h" > <a name="1426">1426</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> App::cpanminus::reporter(3). cpanm(3). </td> </tr> <tr> <td class="h" > <a name="1427">1427</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1428">1428</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<2017 Perl 5 Core Hackathon Discussion on Testing|https://github.com/p5h/2017/wiki/What-Do-We-Want-and-Need-from-Smoke-Testing%3F>. </td> </tr> <tr> <td class="h" > <a name="1429">1429</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1430">1430</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<perl.cpan.testers.discuss Thread on Testing|https://www.nntp.perl.org/group/perl.cpan.testers.discuss/2017/10/msg4172.html>. </td> </tr> <tr> <td class="h" > <a name="1431">1431</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1432">1432</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =cut </td> </tr> <tr> <td class="h" > <a name="1433">1433</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> </table> </body> </html>