File Coverage

blib/lib/Bio/Root/Build.pm
Criterion Covered Total %
statement 19 193 9.8
branch 1 68 1.4
condition 0 19 0.0
subroutine 7 22 31.8
pod 15 15 100.0
total 42 317 13.2


line stmt bran cond sub pod time code
1             package Bio::Root::Build;
2 35     35   762149 use Bio::Root::Version;
  35         93  
  35         320  
3 35     35   1039 use strict;
  35         73  
  35         689  
4 35     35   145 use warnings;
  35         59  
  35         2143  
5              
6             =head1 SYNOPSIS
7              
8             ...TO BE ADDED
9              
10             =head1 DESCRIPTION
11              
12             This is a subclass of Module::Build so we can override certain methods and do
13             fancy stuff
14              
15             It was first written against Module::Build::Base v0.2805. Many of the methods
16             here are copy/pasted from there in their entirety just to change one or two
17             minor things, since for the most part Module::Build::Base code is hard to
18             cleanly override.
19              
20             B: per bug 3196, the majority of the code in this module has been revised
21             or commented out to bring it in line with the Module::Build API. In particular,
22             'requires/recommends' tags in the Build.PL file were not of the same format as
23             those for Module::Build, and so caused serious issues with newer versions
24             (including giving incorrect meta data). Other problematic methods involving
25             automatic installation of prereq modules via CPAN were also removed as they do
26             not work with more modern perl tools such as perlbrew and cpanm.
27              
28             =head1 AUTHOR Sendu Bala
29              
30             =cut
31              
32 0         0 BEGIN {
33             # we really need Module::Build to be installed
34 35 50   35   7859 eval "use base 'Module::Build'; 1" or die "This package requires Module::Build v0.42 or greater to install itself.\n$@";
  35     35   222  
  35         77  
  35         3758  
35              
36             # ensure we'll be able to reload this module later by adding its path to inc
37 35     35   160 use Cwd;
  35         84  
  35         2909  
38 35     35   906 use lib Cwd::cwd();
  35         1046  
  35         64399  
39             }
40              
41             our @extra_types = qw(options excludes_os feature_requires test); # test must always be last in the list!
42             our $checking_types = "requires|conflicts|".join("|", @extra_types);
43              
44             our $VERSION = $Bio::Root::Version::VERSION;
45              
46             =head2 find_pm_files
47              
48             Our modules are in Bio, not lib
49             =cut
50              
51             sub find_pm_files {
52 0     0 1   my $self = shift;
53 0           foreach my $pm (@{$self->rscan_dir('Bio', qr/\.pm$/)}) {
  0            
54 0           $self->{properties}{pm_files}->{$pm} = File::Spec->catfile('lib', $pm);
55             }
56              
57 0           $self->_find_file_by_type('pm', 'lib');
58             }
59              
60             =head2 choose_scripts
61              
62             Ask what scripts to install (this method is unique to bioperl)
63             =cut
64              
65             sub choose_scripts {
66 0     0 1   my $self = shift;
67 0           my $accept = shift;
68              
69             # we can offer interactive installation by groups only if we have subdirs
70             # in scripts and no .PLS files there
71 0 0         opendir(my $scripts_dir, 'scripts') or die "Can't open directory 'scripts': $!\n";
72 0           my $int_ok = 0;
73 0           my @group_dirs;
74              
75             # only retain top-level script directories (the 'categories')
76 0           while (my $thing = readdir($scripts_dir)) {
77 0 0         next if $thing =~ /^\./;
78 0           $thing = File::Spec->catfile('scripts', $thing);
79 0 0         if (-d $thing) {
80 0           $int_ok = 1;
81 0           push(@group_dirs, $thing);
82             }
83             }
84 0           closedir($scripts_dir);
85 0 0         my $question = $int_ok ? "Install [a]ll BioPerl scripts, [n]one, ".
86             "or choose groups [i]nteractively?" : "Install [a]ll BioPerl scripts ".
87             "or [n]one?";
88              
89 0 0         my $prompt = $accept ? 'a' : $self->prompt($question, 'a');
90              
91 0 0         if ($prompt =~ /^[aA]/) {
    0          
92 0           $self->log_info(" - will install all scripts\n");
93 0           $self->notes(chosen_scripts => 'all');
94             }
95             elsif ($prompt =~ /^[iI]/) {
96 0           $self->log_info(" - will install interactively:\n");
97              
98 0           my @chosen_scripts;
99 0           foreach my $group_dir (@group_dirs) {
100 0           my $group = File::Basename::basename($group_dir);
101 0           print " * group '$group' has:\n";
102              
103 0           my @script_files = @{$self->rscan_dir($group_dir, qr/\.PLS$|\.pl$/)};
  0            
104 0           foreach my $script_file (@script_files) {
105 0           my $script = File::Basename::basename($script_file);
106 0           print " $script\n";
107             }
108              
109 0           my $result = $self->prompt(" Install scripts for group '$group'? [y]es [n]o [q]uit", 'n');
110 0 0         die if $result =~ /^[qQ]/;
111 0 0         if ($result =~ /^[yY]/) {
112 0           $self->log_info(" + will install group '$group'\n");
113 0           push(@chosen_scripts, @script_files);
114             }
115             else {
116 0           $self->log_info(" - will not install group '$group'\n");
117             }
118             }
119              
120 0 0         my $chosen_scripts = @chosen_scripts ? join("|", @chosen_scripts) : 'none';
121              
122 0           $self->notes(chosen_scripts => $chosen_scripts);
123             }
124             else {
125 0           $self->log_info(" - won't install any scripts\n");
126 0           $self->notes(chosen_scripts => 'none');
127             }
128              
129 0           print "\n";
130             }
131              
132             =head2 script_files
133              
134             Our version of script_files doesn't take args but just installs those scripts
135             requested by the user after choose_scripts() is called. If it wasn't called,
136             installs all scripts in scripts directory
137             =cut
138              
139             sub script_files {
140 0     0 1   my $self = shift;
141              
142 0 0         unless (-d 'scripts') {
143 0           return {};
144             }
145              
146 0           my $chosen_scripts = $self->notes('chosen_scripts');
147 0 0         if ($chosen_scripts) {
148 0 0         return if $chosen_scripts eq 'none';
149 0 0         return { map {$_, 1} split(/\|/, $chosen_scripts) } unless $chosen_scripts eq 'all';
  0            
150             }
151              
152 0           return $_ = { map {$_,1} @{$self->rscan_dir('scripts', qr/\.PLS$|\.pl$/)} };
  0            
  0            
153             }
154              
155             =head2 prompt
156              
157             Overridden simply to not print the default answer if chosen by hitting return
158             =cut
159              
160             sub prompt {
161 0     0 1   my $self = shift;
162 0 0         my $mess = shift or die "prompt() called without a prompt message";
163              
164 0           my $def;
165 0 0 0       if ( $self->_is_unattended && !@_ ) {
166 0           die <
167             ERROR: This build seems to be unattended, but there is no default value
168             for this question. Aborting.
169             EOF
170             }
171 0 0         $def = shift if @_;
172 0 0         ($def, my $dispdef) = defined $def ? ($def, "[$def] ") : ('', ' ');
173              
174 0           local $|=1;
175 0           print "$mess $dispdef";
176              
177 0           my $ans = $self->_readline();
178              
179 0 0 0       if ( !defined($ans) # Ctrl-D or unattended
180             or !length($ans) ) { # User hit return
181             #print "$def\n"; didn't like this!
182 0           $ans = $def;
183             }
184              
185 0           return $ans;
186             }
187              
188             =head2 ACTION_manifest
189              
190             We always generate a new MANIFEST instead of allowing existing files to remain
191             MANIFEST.SKIP is left alone
192             =cut
193              
194             sub ACTION_manifest {
195 0     0 1   my ($self) = @_;
196 0 0 0       if ( -e 'MANIFEST' || -e 'MANIFEST.SKIP' ) {
197 0           $self->log_warn("MANIFEST files already exist, will overwrite them\n");
198 0           unlink('MANIFEST');
199             }
200 0           require ExtUtils::Manifest; # ExtUtils::Manifest is not warnings clean.
201 0           local ($^W, $ExtUtils::Manifest::Quiet) = (0,1);
202 0           ExtUtils::Manifest::mkmanifest();
203             }
204              
205             =head2 ACTION_install
206              
207             Extended to run scripts post-installation
208             =cut
209              
210             sub ACTION_install {
211 0     0 1   my ($self) = @_;
212 0           require ExtUtils::Install;
213 0           $self->depends_on('build');
214             ExtUtils::Install::install($self->install_map,
215             !$self->quiet,
216             0,
217 0   0       $self->{args}{uninst} || 0);
218             #$self->run_post_install_scripts;
219             }
220              
221             =head2 test_internet
222              
223             For use with auto_features, which should require LWP::UserAgent as one of
224             its reqs
225              
226             Note: as of 4-11-11, this is no longer called - if someone wants to run
227             network tests (off by default) w/o a network, then they are hanging themselves
228             by their own shoelaces.
229             =cut
230              
231             sub test_internet {
232 0     0 1   eval {require LWP::UserAgent;};
  0            
233 0 0         if ($@) {
234             # ideally this won't happen because auto_feature already specified
235             # LWP::UserAgent, so this sub wouldn't get called if LWP not installed
236 0           return "LWP::UserAgent not installed";
237             }
238 0           my $ua = LWP::UserAgent->new;
239 0           $ua->timeout(10);
240 0           $ua->env_proxy;
241 0           my $response = $ua->get('http://search.cpan.org/');
242 0 0         unless ($response->is_success) {
243 0           return "Could not connect to the internet (http://search.cpan.org/)";
244             }
245 0           return;
246             }
247              
248             =head2 ACTION_ppmdist
249              
250             Don't copy across man3 docs since they're of little use under Windows and
251             have bad filenames
252             =cut
253              
254             sub ACTION_ppmdist {
255 0     0 1   my $self = shift;
256 0           my @types = $self->install_types(1);
257 0           $self->SUPER::ACTION_ppmdist(@_);
258 0           $self->install_types(0);
259             }
260              
261             =head2 install_types
262              
263             When supplied a true value, pretends libdoc doesn't exist (preventing man3
264             installation for ppmdist). when supplied false, they exist again
265             =cut
266              
267             sub install_types {
268 0     0 1   my ($self, $no_libdoc) = @_;
269 0 0         $self->{no_libdoc} = $no_libdoc if defined $no_libdoc;
270 0           my @types = $self->SUPER::install_types;
271 0 0         if ($self->{no_libdoc}) {
272 0           my @altered_types;
273 0           foreach my $type (@types) {
274 0 0         push(@altered_types, $type) unless $type eq 'libdoc';
275             }
276 0           return @altered_types;
277             }
278 0           return @types;
279             }
280              
281             =head2 ACTION_dist
282              
283             We make all archive formats we want, not just .tar.gz
284             we also auto-run manifest action, since we always want to re-create
285             MANIFEST and MANIFEST.SKIP just-in-time
286             =cut
287              
288             sub ACTION_dist {
289 0     0 1   my ($self) = @_;
290              
291 0           $self->depends_on('manifest');
292 0           $self->depends_on('distdir');
293              
294 0           my $dist_dir = $self->dist_dir;
295              
296 0           $self->make_zip($dist_dir);
297 0           $self->make_tarball($dist_dir);
298 0           $self->delete_filetree($dist_dir);
299             }
300              
301             =head2 ACTION_clean
302              
303             Define custom clean/realclean actions to rearrange config file cleanup
304             =cut
305              
306             sub ACTION_clean {
307 0     0 1   my ($self) = @_;
308 0           $self->log_info("Cleaning up build files\n");
309 0           foreach my $item (map glob($_), $self->cleanup) {
310 0           $self->delete_filetree($item);
311             }
312 0           $self->log_info("Cleaning up configuration files\n");
313 0           $self->delete_filetree($self->config_dir);
314             }
315              
316             =head2 ACTION_realclean
317              
318             Define custom clean/realclean actions to rearrange config file cleanup
319             =cut
320              
321             sub ACTION_realclean {
322 0     0 1   my ($self) = @_;
323 0           $self->depends_on('clean');
324 0           for my $method (qw(mymetafile mymetafile2 build_script)) {
325 0 0         if ($self->can($method)) {
326 0           $self->delete_filetree($self->$method);
327 0           $self->log_info("Cleaning up $method data\n");
328             }
329             }
330             }
331              
332             =head2 make_zip
333              
334             Makes zip file for windows users and bzip2 files as well
335             =cut
336              
337             sub make_zip {
338 0     0 1   my ($self, $dir, $file) = @_;
339 0   0       $file ||= $dir;
340              
341 0           $self->log_info("Creating $file.zip\n");
342 0 0         my $zip_flags = $self->verbose ? '-r' : '-rq';
343 0           $self->do_system($self->split_like_shell("zip"), $zip_flags, "$file.zip", $dir);
344              
345 0           $self->log_info("Creating $file.bz2\n");
346 0           require Archive::Tar;
347             # Archive::Tar versions >= 1.09 use the following to enable a compatibility
348             # hack so that the resulting archive is compatible with older clients.
349 0           $Archive::Tar::DO_NOT_USE_PREFIX = 0;
350 0           my $files = $self->rscan_dir($dir);
351 0           Archive::Tar->create_archive("$file.tar", 0, @$files);
352 0           $self->do_system($self->split_like_shell("bzip2"), "-k", "$file.tar");
353             }
354              
355             =head2 prompt_for_network
356              
357             A method that can be called in a Build.PL script to ask the user if they want
358             internet tests.
359             Should only be called if you have tested for yourself that
360             $build->feature('Network Tests') is true
361             =cut
362              
363             sub prompt_for_network {
364 0     0 1   my ($self, $accept) = @_;
365              
366 0 0         my $proceed = $accept ? 0 : $self->y_n( "Do you want to run tests that require connection to servers across the internet\n"
367             . "(likely to cause some failures)? y/n", 'n');
368              
369 0 0         if ($proceed) {
370 0           $self->notes('network' => 1);
371 0           $self->log_info(" - will run internet-requiring tests\n");
372 0           my $use_email = $self->y_n("Do you want to run tests requiring a valid email address? y/n",'n');
373 0 0         if ($use_email) {
374 0           my $address = $self->prompt("Enter email address:");
375 0           $self->notes(email => $address);
376             }
377             }
378             else {
379 0           $self->notes(network => 0);
380 0           $self->log_info(" - will not run internet-requiring tests\n");
381             }
382             }
383              
384             =head2 print_build_script
385              
386             Override the build script warnings flag
387             =cut
388              
389             sub print_build_script {
390 0     0 1   my ($self, $fh) = @_;
391              
392 0           my $build_package = $self->build_class;
393              
394 0           my $closedata="";
395              
396 0           my $config_requires;
397 0 0         if ( -f $self->metafile ) {
398 0           my $meta = eval { $self->read_metafile( $self->metafile ) };
  0            
399 0   0       $config_requires = $meta && $meta->{configure_requires}{'Module::Build'};
400             }
401 0   0       $config_requires ||= 0;
402              
403 0           my %q = map {$_, $self->$_()} qw(config_dir base_dir);
  0            
404              
405 0 0         $q{base_dir} = Win32::GetShortPathName($q{base_dir}) if $self->is_windowsish;
406              
407 0           $q{magic_numfile} = $self->config_file('magicnum');
408              
409 0           my @myINC = $self->_added_to_INC;
410 0           @myINC = map { $_ = File::Spec->canonpath( $_ );
  0            
411 0           $_ =~ s/([\\\'])/\\$1/g;
412 0           $_;
413             } @myINC;
414             # Remove duplicates
415 0           @myINC = sort {$a cmp $b}
416 0           keys %{ { map { $_ => 1 } @myINC } };
  0            
  0            
417              
418 0           foreach my $key (keys %q) {
419 0           $q{$key} = File::Spec->canonpath( $q{$key} );
420 0           $q{$key} =~ s/([\\\'])/\\$1/g;
421             }
422              
423 0           my $quoted_INC = join ",\n", map " '$_'", @myINC;
424 0           my $shebang = $self->_startperl;
425 0           my $magic_number = $self->magic_number;
426              
427             # unique to bioperl, shut off overly verbose warnings on windows, bug 3215
428 0 0         my $w = $^O =~ /win/i ? '# no warnings (win)' : '$^W = 1; # Use warnings';
429              
430 0           print $fh <
431             $shebang
432              
433             use strict;
434             use Cwd;
435             use File::Basename;
436             use File::Spec;
437              
438             sub magic_number_matches {
439             return 0 unless -e '$q{magic_numfile}';
440             open my \$FH, '<', '$q{magic_numfile}' or return 0;
441             my \$filenum = <\$FH>;
442             close \$FH;
443             return \$filenum == $magic_number;
444             }
445              
446             my \$progname;
447             my \$orig_dir;
448             BEGIN {
449             $w
450             \$progname = basename(\$0);
451             \$orig_dir = Cwd::cwd();
452             my \$base_dir = '$q{base_dir}';
453             if (!magic_number_matches()) {
454             unless (chdir(\$base_dir)) {
455             die ("Could not chdir '\$base_dir', aborting\\n");
456             }
457             unless (magic_number_matches()) {
458             die ("Configuration seems to be out of date, please re-run 'perl Build.PL' again.\\n");
459             }
460             }
461             unshift \@INC,
462             (
463             $quoted_INC
464             );
465             }
466              
467             close(*DATA) unless eof(*DATA); # ensure no open handles to this script
468              
469             use $build_package;
470             Module::Build->VERSION(q{$config_requires});
471              
472             # Some platforms have problems setting \$^X in shebang contexts, fix it up here
473             \$^X = Module::Build->find_perl_interpreter;
474              
475             if (-e 'Build.PL' and not $build_package->up_to_date('Build.PL', \$progname)) {
476             warn "Warning: Build.PL has been altered. You may need to run 'perl Build.PL' again.\\n";
477             }
478              
479             # This should have just enough arguments to be able to bootstrap the rest.
480             my \$build =
481             $build_package->resume( properties => { config_dir => '$q{config_dir}',
482             orig_dir => \$orig_dir, },
483             );
484              
485             \$build->dispatch;
486             EOF
487             }
488              
489             1;