File Coverage

blib/lib/CPAN/FindDependencies/MakeMaker.pm
Criterion Covered Total %
statement 64 72 88.8
branch 10 18 55.5
condition n/a
subroutine 12 12 100.0
pod 1 1 100.0
total 87 103 84.4


line stmt bran cond sub pod time code
1             package CPAN::FindDependencies::MakeMaker;
2              
3 11     11   81 use strict;
  11         29  
  11         350  
4 11     11   64 use warnings;
  11         29  
  11         318  
5 11     11   66 use vars qw($VERSION @ISA @EXPORT_OK);
  11         32  
  11         633  
6              
7 11     11   127 use File::Temp qw(tempdir);
  11         31  
  11         753  
8 11     11   79 use Cwd qw(getcwd abs_path);
  11         202  
  11         644  
9 11     11   6149 use Capture::Tiny qw(capture);
  11         71634  
  11         712  
10 11     11   91 use Config;
  11         25  
  11         5702  
11              
12             require Exporter;
13             @ISA = qw(Exporter);
14             @EXPORT_OK = qw( getreqs_from_mm );
15              
16             $VERSION = '1.0';
17              
18             =head1 NAME
19              
20             CPAN::FindDependencies::MakeMaker - retrieve dependencies specified in Makefile.PL's
21              
22             =head1 SYNOPSIS
23              
24             Dependencies are also specified in Makefile.PL files used with the ExtUtils::MakeMaker module.
25              
26             =head1 FUNCTIONS
27              
28             =over
29              
30             =item getreqs_from_mm
31              
32             Expects the contents of a Makefile.PL as a string.
33              
34             Returns a hash reference of the form:
35              
36             {
37             Module::Name => 0.1,
38             ...
39             Last::Module => 9.0,
40             }
41              
42             =back
43              
44             =cut
45              
46             sub getreqs_from_mm {
47 5     5 1 23 my $MakefilePL = shift;
48 5         33 local $/ = undef;
49              
50 5         69 my $cwd = getcwd();
51 5         63 my $tempdir = tempdir(CLEANUP => 1);
52 5         2949 chdir($tempdir);
53              
54             # write Makefile.PL ...
55 5 50       377 open(my $MKFH, '>Makefile.PL') || die("Can't write Makefile.PL in $tempdir\n");
56 5         42 print $MKFH $MakefilePL;
57 5         189 close($MKFH);
58              
59 5 50       139 if ($^O eq 'MSWin32') {
60             # NB *not* for Cygwin, hence not Devel::CheckOS MicrosoftWindows
61 0         0 require Win32::Job;
62 0         0 my $job = Win32::Job->new;
63 0         0 $job->spawn($Config{perlpath}, "perl Makefile.PL", {stdin => 'NUL', 'stdout'=>'stdout.log','stderr'=>'stderr.log'});
64 0 0       0 unless ($job->run(10)) {
65 0         0 chdir($cwd);
66 0         0 return "Makefile.PL didn't finish in a reasonable time\n";
67             }
68             } else {
69             # execute, suppressing noise ...
70 5         18 eval { capture {
71 5 100   5   22800 if(my $pid = fork()) { # parent
72             local $SIG{ALRM} = sub {
73 1         1032 kill 9, $pid; # quit RIGHT FUCKING NOW
74 1         95 die("Makefile.PL didn't finish in a reasonable time\n");
75 3         595 };
76 3         79 alarm(10);
77 3         11817348 waitpid($pid, 0);
78 2         216 alarm(0);
79             } else {
80 2         0 exec($Config{perlpath}, 'Makefile.PL');
81             }
82 5         356 } };
83 3 100       7685 if($@) {
84 1         23 chdir($cwd);
85 1         57 return $@;
86             }
87             }
88              
89             # read Makefile
90 2 50       114 open($MKFH, 'Makefile') || warn "Can't read Makefile\n";
91 2         242 my $makefile_str = <$MKFH>;
92 2         36 close($MKFH);
93 2         52 chdir($cwd);
94              
95 2         60 return _parse_makefile( $makefile_str );
96             }
97              
98             sub _parse_makefile {
99 2     2   22 my $makefile_str = shift;
100 2 50       32 return "Unable to get Makefile" unless defined $makefile_str;
101 2         10 my %required_version_for;
102 2         1072 my @prereq_lines = grep { /^\s*#.*PREREQ/ } split /\n/, $makefile_str;
  1766         3238  
103 2         120 for my $line ( @prereq_lines ) {
104 2 50       114 if ( $line =~ /PREREQ_PM \s+ => \s+ \{ \s* (.*) \s* \} $/x ) {
  0         0  
105 11     11   104 no strict 'subs';
  11         26  
  11         959  
106 2         506 %required_version_for = eval "( $1 )";
107 2 50       34 return "Failed to eval $1: $@" if $@;
108 11     11   90 use strict 'subs';
  11         25  
  11         1173  
109             } else {
110 0         0 return "Unrecognized PREREQ line in Makefile.PL:\n$line";
111             }
112             }
113 2         92 return \%required_version_for;
114             }
115              
116             =head1 SECURITY
117              
118             This module assumes that its input is trustworthy and can be safely
119             executed. The only protection in place is that a vague attempt is made
120             to catch a Makefile.PL that just sits there doing nothing - either if it's
121             in a loop, or sitting at a prompt. But even that can be defeated by
122             an especially naughty person.
123              
124             =head1 BUGS/LIMITATIONS
125              
126             Makefile.PLs that have external dependencies/calls that can fatally die will
127             not be able to be successfully parsed and then scanned for dependencies, e.g.
128             libwww-perl.5808.
129              
130             =head1 SOURCE CODE REPOSITORY
131              
132             L<git://github.com/DrHyde/perl-modules-CPAN-FindDependencies.git>
133              
134             =head1 SEE ALSO
135              
136             L<CPAN::FindDepdendencies>
137              
138             L<CPAN>
139              
140             L<http://deps.cpantesters.org>
141              
142             =head1 AUTHOR, LICENCE and COPYRIGHT
143              
144             Copyright 2009 David Cantrell E<lt>F<david@cantrell.org.uk>E<gt> based largely
145             on code by Ian Tegebo (see L<http://rt.cpan.org/Public/Bug/Display.html?id=34814>)
146              
147             This software is free-as-in-speech software, and may be used,
148             distributed, and modified under the terms of either the GNU
149             General Public Licence version 2 or the Artistic Licence. It's
150             up to you which one you use. The full text of the licences can
151             be found in the files GPL2.txt and ARTISTIC.txt, respectively.
152              
153             =head1 CONSPIRACY
154              
155             This module is also free-as-in-mason software.
156              
157             =cut
158              
159             1;