File Coverage

lib/Module/LocalBuild.pm
Criterion Covered Total %
statement 12 83 14.4
branch 0 48 0.0
condition 0 15 0.0
subroutine 4 8 50.0
pod 1 1 100.0
total 17 155 10.9


line stmt bran cond sub pod time code
1             # See copyright, etc in below POD section.
2             ######################################################################
3              
4             package Module::LocalBuild;
5             # This package is used by a LOT of other packages. Keep it small.
6 1     1   24770 use Carp;
  1         3  
  1         84  
7 1     1   1025 use IO::Dir;
  1         27111  
  1         45  
8              
9 1     1   8 use strict;
  1         2  
  1         26  
10 1     1   5 use vars qw ($VERSION @Ignore_Files_Regexps);
  1         2  
  1         1107  
11              
12             $VERSION = '1.013';
13              
14             @Ignore_Files_Regexps = (qr!/CVS$!,
15             qr!.git$!,
16             qr!.svn$!,
17             qr!/here_perl$!,
18             qr!/blib$!,
19             qr!\.old$!,
20             qr!\.t$!, # Ignore all tests
21             qr!Makefile$!,
22             qr!Changes$!,
23             qr!pm_to_blib$!,
24             qr!/README$!,
25             );
26              
27             #######################################################################
28             # User interface
29              
30             sub need {
31 0     0 1   my $self = {dest_dir => undef,
32             locker_module => undef,
33             libs => [],
34             packages => [],
35             ignore_files => [@Ignore_Files_Regexps],
36             debug => $::Debug,
37             mlbuilder => "$^X mlbuilder",
38             deps => [],
39             @_};
40 0 0 0       $self->{dest_dir} or $#{$self->{packages}<0}
  0            
41             or croak "%Error: Module::LocalBuild::build called without dest_dir argument, stopped";
42              
43             # Make sure the dest area is included in lookups
44 0 0         if ($self->{dest_dir}) {
45 0           push @{$self->{libs}}, ("$self->{dest_dir}/blib/lib",
  0            
46             "$self->{dest_dir}/blib/arch");
47             }
48              
49             # Use libraries
50 0           foreach (@{$self->{libs}}) { _use_lib($_); }
  0            
  0            
51              
52             # Is the dest dir up to date?
53 0 0         if ($self->{dest_dir}) {
54 0           my $built_file = $self->{dest_dir}."/.built";
55              
56 0           my $rebuild = 0;
57 0 0         if ($::Perl_Path_Build_Skip) { # Historical avoidance of building
    0          
    0          
    0          
58             }
59             elsif (defined $ENV{MODULELOCALBUILD_CHECKED}) { # We've done it recently
60             }
61             elsif (-r $self->{dest_dir}."/.builtforce") { # User forced it, for example if a published area
62             }
63             elsif (! -r $built_file) { # Haven't built
64 0           $rebuild = 1;
65             } else {
66             # Have any files changed?
67 0   0       my $build_mtime = (stat($built_file))[9] || 0;
68             # Get true if any files newer than specified time
69 0           foreach my $dir (@{$self->{packages}}) {
  0            
70 0           my $action = 'build';
71 0 0         $rebuild=1 if _date_check_recurse($self, $dir, $build_mtime);
72             }
73 0           foreach my $dir (@{$self->{deps}}) {
  0            
74 0 0         $rebuild=1 if _date_check_recurse($self, $dir, $build_mtime);
75             }
76             }
77              
78             # Build the objects
79 0 0         if ($rebuild) {
80 0           _request_build($self);
81 0 0         if (! -r $built_file) {
82 0           die "%Error: Perl LocalBuild failed\n";
83             }
84             }
85              
86 0           $ENV{MODULELOCALBUILD_CHECKED} = (scalar(localtime));
87             }
88             }
89              
90             sub _request_build {
91 0     0     my $self = shift;
92 0           print STDERR "Building Perl Libraries...\n";
93 0           my @args;
94 0           foreach my $dir (@{$self->{packages}}) {
  0            
95 0           my $action = 'build'; # Later, check if $dir is a hash and check action
96 0 0         if ($action eq 'build') {
97 0           push @args, "--".$action, $dir;
98             } else {
99 0           croak "%Error: Invalid action $action for $dir, stopped";
100             }
101             }
102 0 0         my $cmd = ($self->{mlbuilder}
    0          
103             .($self->{debug}?" --debug":"")
104             ." --destdir ".$self->{dest_dir}
105             .(defined $self->{locker_module}
106             ? " --locker ".$self->{locker_module} : "")
107             .' '.join(' ',@args));
108 0 0         print "\t$cmd\n" if $self->{debug};
109 0           system $cmd; # No error checking, .built will do it for us
110             }
111              
112             #######################################################################
113             # Internals
114              
115             sub _use_lib {
116 0     0     my $lib = shift;
117             # Do a 'use lib' and also add to PERL5LIB
118             #print "_use_lib $lib\n";
119 0   0       my %p5lib_now = map {$_,$_} split (/:/, ($ENV{PERL5LIB}||""));
  0            
120 0 0         if (!$p5lib_now{$lib}) {
121             # Add to current lib list
122 0           import lib $lib; # Hack because don't want BEGIN block; in scripts 'use lib "..."' instead
123             # Add to PERL5LIB also. This enables scripts to call secondary
124             # scripts and still find our perltools, without requiring the
125             # secondary (and probably public) scripts to be changed
126 0 0         if ($ENV{PERL5LIB}) {
127 0           $ENV{PERL5LIB}=$lib.":".$ENV{PERL5LIB};
128             } else {
129 0           $ENV{PERL5LIB}=$lib;
130             }
131             }
132             }
133              
134             ########################################################################
135              
136             our $_Date_Check_Recurse_Newer;
137              
138             sub _date_check_recurse {
139 0     0     my $self = shift;
140 0           my $filename = shift;
141 0           my $build_mtime = shift;
142             # Return true if any file is newer than specified date
143             #print "_date_check_recurse $filename\n" if $self->{debug};
144              
145             # Exceptions
146 0           foreach my $re (@{$self->{ignore_files}}) {
  0            
147 0 0         return 0 if $filename =~ /$re/;
148             }
149              
150 0 0         if (-d $filename) {
151 0           my $rebuild;
152 0 0         my $dh = new IO::Dir($filename) or return 0;
153 0           while (defined (my $basefile = $dh->read)) {
154 0 0 0       next if (($basefile eq ".") || ($basefile eq ".."));
155 0           my $file = "$filename/$basefile";
156 0 0         $rebuild = 1 if _date_check_recurse($self, $file, $build_mtime);
157             }
158 0           $dh->close();
159 0           return $rebuild;
160             } else {
161 0   0       my $file_mtime = (stat($filename))[9] || 0;
162 0 0 0       if (($file_mtime > $build_mtime) && -f $filename) {
163 0           if (1 || $self->{debug}) { # So much will be printed out, we might as well.
164 0 0         if (!$_Date_Check_Recurse_Newer) {
165 0           print "Some Perl files have changed:\n";
166             }
167 0           $_Date_Check_Recurse_Newer++;
168 0           print "\t$filename is newer\n";
169             }
170 0           return 1;
171             }
172 0           return undef;
173             }
174             }
175              
176             #######################################################################
177             1;
178             __END__