File Coverage

blib/lib/PPM/Make/Config.pm
Criterion Covered Total %
statement 52 267 19.4
branch 6 124 4.8
condition 0 71 0.0
subroutine 14 23 60.8
pod 1 12 8.3
total 73 497 14.6


line stmt bran cond sub pod time code
1             package PPM::Make::Config;
2 5     5   29 use strict;
  5         18  
  5         172  
3 5     5   34 use warnings;
  5         10  
  5         141  
4 5     5   28 use base qw(Exporter);
  5         7  
  5         837  
5 5     5   45395 use File::HomeDir;
  5         53474  
  5         434  
6             require File::Spec;
7 5     5   52 use Config;
  5         12  
  5         213  
8 5     5   39249 use Config::IniFiles;
  5         425553  
  5         384  
9              
10             our ($ERROR);
11             our $VERSION = '0.9902';
12              
13             =head1 NAME
14              
15             PPM::Make::Config - Utility functions configuring PPM::Make
16              
17             =head1 SYNOPSIS
18              
19             use PPM::Make::Config qw(:all);
20              
21             =head1 DESCRIPTION
22              
23             This module contains a number of utility functions used by PPM::Make.
24              
25             =over 2
26              
27             =item WIN32
28              
29             Constant which is true if the platform matches C.
30              
31             =cut
32              
33 5     5   65 use constant WIN32 => $^O eq 'MSWin32';
  5         10  
  5         576  
34              
35 5     5   27 use constant ACTIVEPERL => eval { require ActivePerl::Config; 1 };
  5         9  
  5         11  
  5         4882  
  0         0  
36              
37             my @path_ext = ();
38             path_ext() if WIN32;
39              
40             sub has_cpan {
41 5     5 0 10 my $has_config = 0;
42 5         28 require File::Spec;
43 5         44 my $home = File::HomeDir->my_home;
44 5 50       290 if ($home) {
45             eval
46 5         10 {require File::Spec->catfile($home, '.cpan',
  5         4865  
47             'CPAN', 'MyConfig.pm');};
48 5 50       41 $has_config = 1 unless $@;
49             }
50 5 50       21 unless ($has_config) {
51 0         0 eval {local $^W = 0; require CPAN::HandleConfig;};
  0         0  
  0         0  
52 0         0 eval {local $^W = 0; require CPAN::Config;};
  0         0  
  0         0  
53 0         0 my $dir;
54 0         0 unless (WIN32) {
55 0         0 $dir = $INC{'CPAN/Config.pm'};
56             }
57 0 0 0     0 $has_config = 1 unless ($@ or ($dir and not -w $dir));
      0        
58             }
59 5 50       16128 require CPAN if $has_config;
60 5         2300046 return $has_config;
61             }
62              
63             =item HAS_CPAN
64              
65             Constant which is true if the C module is configured and
66             available.
67              
68             =cut
69              
70 5     5   29 use constant HAS_CPAN => has_cpan();
  5         9  
  5         119  
71              
72             sub has_ppm {
73 5     5 0 23 my $has_ppm = 0;
74 5         959 my $ppm = File::Spec->catfile($Config{bin}, 'ppm.bat');
75 5 50       1640 return unless -f $ppm;
76 0         0 my $version;
77              
78 0         0 VERSION: {
79 0 0       0 (eval {require PPM;}) and do {
  0         0  
80 0 0       0 unless ($@) {
81 0         0 $version = 2;
82 0         0 last VERSION;
83             }
84             };
85 0 0       0 (eval {require PPM::Config;}) and do {
  0         0  
86 0 0       0 unless ($@) {
87 0         0 $version = 3;
88 0         0 last VERSION;
89             }
90             };
91 0 0       0 (eval {require ActivePerl::PPM;}) and do {
  0         0  
92 0 0       0 unless ($@) {
93 0         0 $version = 4;
94 0         0 last VERSION;
95             }
96             };
97 0         0 $version = 'unknown';
98             }
99 0         0 return $version;
100             }
101              
102             =item HAS_PPM
103              
104             Constant which is true if the C module is available.
105             Will be set equal to the major version of ppm (2, 3 or 4), if found.
106              
107             =cut
108              
109 5     5   191 use constant HAS_PPM => has_ppm();
  5         17  
  5         50  
110              
111             sub has_mb {
112 5     5 0 22 my $has_mb = 0;
113 5         23 eval {require Module::Build;};
  5         14955  
114 5 50       726852 $has_mb = 1 unless $@;
115 5         13904 return $has_mb;
116             }
117              
118             =item HAS_MB
119              
120             Constant which is true if the C module is available.
121              
122             =cut
123              
124 5     5   124 use constant HAS_MB => has_mb();
  5         84  
  5         45  
125              
126             require Win32 if WIN32;
127              
128             our (@EXPORT_OK, %EXPORT_TAGS);
129             my @exports = qw(check_opts arch_and_os get_cfg_file read_cfg merge_opts
130             what_have_you fetch_nmake which $ERROR
131             WIN32 HAS_CPAN HAS_PPM HAS_MB ACTIVEPERL);
132             %EXPORT_TAGS = (all => [@exports]);
133             @EXPORT_OK = (@exports);
134              
135             sub check_opts {
136 0     0 0   my %opts = @_;
137 0           my %legal =
138 0           map {$_ => 1} qw(force ignore binary zip_archive remove program cpan
139             dist script exec os arch arch_sub add no_as vs upload
140             no_case no_cfg vsr vsp zipdist no_ppm4 no_html
141             reps no_upload skip cpan_meta no_remote_lookup);
142 0           foreach (keys %opts) {
143 0 0         next if $legal{$_};
144 0           warn "Unknown option '$_'\n";
145 0           return;
146             }
147              
148 0 0         if (defined $opts{add}) {
149 0 0         unless (ref($opts{add}) eq 'ARRAY') {
150 0           warn "Please supply an ARRAY reference to 'add'";
151 0           return;
152             }
153             }
154              
155 0 0 0       if (defined $opts{program} and my $progs = $opts{program}) {
156 0 0         unless (ref($progs) eq 'HASH') {
157 0           warn "Please supply a HASH reference to 'program'";
158 0           return;
159             }
160 0           my %ok = map {$_ => 1} qw(zip unzip tar gzip make);
  0            
161 0           foreach (keys %{$progs}) {
  0            
162 0 0         next if $ok{$_};
163 0           warn "Unknown program option '$_'\n";
164 0           return;
165             }
166             }
167            
168 0 0 0       if (defined $opts{upload} and my $upload = $opts{upload}) {
169 0 0         unless (ref($upload) eq 'HASH') {
170 0           warn "Please supply an HASH reference to 'upload'";
171 0           return;
172             }
173 0           my %ok = map {$_ => 1} qw(ppd ar host user passwd zip bundle);
  0            
174 0           foreach (keys %{$upload}) {
  0            
175 0 0         next if $ok{$_};
176 0           warn "Unknown upload option '$_'\n";
177 0           return;
178             }
179             }
180 0           return 1;
181             }
182              
183             sub arch_and_os {
184 0     0 0   my ($opt_arch, $opt_os, $opt_noas) = @_;
185              
186 0           my ($arch, $os);
187 0 0         if (defined $opt_arch) {
188 0 0         $arch = ($opt_arch eq "") ? undef : $opt_arch;
189             }
190             else {
191 0           $arch = $Config{archname};
192 0 0         unless ($opt_noas) {
193 0 0         if ($] >= 5.008) {
194 0           my $vstring = sprintf "%vd", $^V;
195 0           $vstring =~ s/\.\d+$//;
196 0           $arch .= "-$vstring";
197             }
198             }
199             }
200 0 0         if (defined $opt_os) {
201 0 0         $os = ($opt_os eq "") ? undef : $opt_os;
202             }
203             else {
204 0           $os = $Config{osname};
205             }
206 0           return ($arch, $os);
207             }
208              
209             sub get_cfg_file {
210 0 0 0 0 0   if (defined $ENV{PPM_CFG} and my $env = $ENV{PPM_CFG}) {
211 0 0         if (-e $env) {
212 0           return $env;
213             }
214             else {
215 0           warn qq{Cannot find '$env' from \$ENV{PPM_CFG}};
216 0           return;
217             }
218             }
219 0 0         if (my $home = File::HomeDir->my_home) {
220 0           my $candidate = File::Spec->catfile($home, '.ppmcfg');
221 0 0         return $candidate if (-e $candidate);
222             }
223 0           if (WIN32) {
224             my $candidate = '/.ppmcfg';
225             return $candidate if (-e $candidate);
226             }
227 0           return;
228             }
229              
230             sub read_cfg {
231 0     0 0   my ($file, $arch) = @_;
232 0           my $default = 'default';
233 0           my $cfg = Config::IniFiles->new(-file => $file, -default => $default);
234 0           my @p;
235 0 0         push @p, $cfg->Parameters($default) if ($cfg->SectionExists($default));
236 0 0         push @p, $cfg->Parameters($arch) if ($cfg->SectionExists($arch));
237 0 0         unless (@p > 1) {
238 0           warn "No default or section for $arch found";
239 0           return;
240             }
241              
242 0           my $on = qr!^(on|yes)$!;
243 0           my $off = qr!^(off|no)$!;
244 0           my %legal_progs = map {$_ => 1} qw(tar gzip make perl);
  0            
245 0           my %legal_upload = map {$_ => 1} qw(ppd ar host user passwd zip bundle);
  0            
246 0           my (%cfg, %programs, %upload);
247 0           foreach my $p (@p) {
248 0           my ($val, @vals);
249 0 0 0       if ($p eq 'add' or $p eq 'reps') {
250 0           @vals = $cfg->val($arch, $p);
251 0           $cfg{$p} = \@vals;
252 0           next;
253             }
254             else {
255 0           $val = $cfg->val($arch, $p);
256             }
257 0 0         $val = 1 if ($val =~ /$on/i);
258 0 0         if ($val =~ /$off/i) {
259 0           delete $cfg{$p};
260 0           next;
261             }
262 0 0         if ($legal_progs{$p}) {
    0          
263 0           $programs{$p} = $val;
264             }
265             elsif ($legal_upload{$p}) {
266 0           $upload{$p} = $val;
267             }
268             else {
269 0           $cfg{$p} = $val;
270             }
271             }
272 0 0         $cfg{program} = \%programs if %programs;
273 0 0         $cfg{upload} = \%upload if %upload;
274 0 0         return check_opts(%cfg) ? %cfg : undef;
275             }
276              
277             # merge two hashes, assuming the second one takes precedence
278             # over the first in the case of duplicate keys
279             sub merge_opts {
280 0     0 0   my ($h1, $h2) = @_;
281 0           my %opts = (%{$h1}, %{$h2});
  0            
  0            
282 0           foreach my $opt(qw(add reps)) {
283 0 0 0       if (defined $h1->{$opt} or defined $h2->{$opt}) {
284 0           my @a = ();
285 0 0         push @a, @{$h1->{$opt}} if $h1->{$opt};
  0            
286 0 0         push @a, @{$h2->{$opt}} if $h2->{$opt};
  0            
287 0           my %hash = map {$_ => 1} @a;
  0            
288 0           $opts{$opt} = [keys %hash];
289             }
290             }
291 0           for (qw(program upload)) {
292 0 0 0       next unless (defined $h1->{$_} or defined $h2->{$_});
293 0           my %h = ();
294 0 0         if (defined $h1->{$_}) {
295 0 0         if (defined $h2->{$_}) {
296 0           %h = (%{$h1->{$_}}, %{$h2->{$_}});
  0            
  0            
297             }
298             else {
299 0           %h = %{$h1->{$_}};
  0            
300             }
301             }
302             else {
303 0           %h = %{$h2->{$_}};
  0            
304             }
305 0           $opts{$_} = \%h;
306             }
307 0           return \%opts;
308             }
309              
310             sub what_have_you {
311 0     0 0   my ($progs, $arch, $os) = @_;
312 0           my %has;
313 0 0 0       if (defined $progs->{tar} and defined $progs->{gzip}) {
    0 0        
      0        
      0        
314 0           $has{tar} = $progs->{tar};
315 0           $has{gzip} = $progs->{gzip};
316             }
317             elsif ((not WIN32 and
318             (not $os or $os =~ /Win32/i or not $arch or $arch =~ /Win32/i))) {
319 0   0       $has{tar} =
320             $Config{tar} || which('tar') || $CPAN::Config->{tar};
321 0   0       $has{gzip} =
322             $Config{gzip} || which('gzip') || $CPAN::Config->{gzip};
323             }
324             else {
325 0           eval{require Archive::Tar; require Compress::Zlib};
  0            
  0            
326 0 0         if ($@) {
327 0   0       $has{tar} =
328             $Config{tar} || which('tar') || $CPAN::Config->{tar};
329 0   0       $has{gzip} =
330             $Config{gzip} || which('gzip') || $CPAN::Config->{gzip};
331             }
332             else {
333 0           my $atv = mod_version('Archive::Tar');
334 0           if (not WIN32 or (WIN32 and $atv >= 1.08)) {
335 0           $has{tar} = 'Archive::Tar';
336 0           $has{gzip} = 'Compress::Zlib';
337             }
338             else {
339             $has{tar} =
340             $Config{tar} || which('tar') || $CPAN::Config->{tar};
341             $has{gzip} =
342             $Config{gzip} || which('gzip') || $CPAN::Config->{gzip};
343             }
344             }
345             }
346              
347 0 0 0       if (defined $progs->{zip} and defined $progs->{unzip}) {
348 0           $has{zip} = $progs->{zip};
349 0           $has{unzip} = $progs->{unzip};
350             }
351             else {
352 0           eval{require Archive::Zip; };
  0            
353 0 0         if ($@) {
354 0   0       $has{zip} =
355             $Config{zip} || which('zip') || $CPAN::Config->{zip};
356 0   0       $has{unzip} =
357             $Config{unzip} || which('unzip') || $CPAN::Config->{unzip};
358             }
359             else {
360 0           my $zipv = mod_version('Archive::Zip');
361 0 0         if ($zipv >= 1.02) {
362 0           require Archive::Zip; import Archive::Zip qw(:ERROR_CODES);
  0            
363 0           $has{zip} = 'Archive::Zip';
364 0           $has{unzip} = 'Archive::Zip';
365             }
366             else {
367 0   0       $has{zip} =
368             $Config{zip} || which('zip') || $CPAN::Config->{zip};
369 0   0       $has{unzip} =
370             $Config{unzip} || which('unzip') || $CPAN::Config->{unzip};
371             }
372             }
373             }
374            
375 0           my $make = WIN32 ? 'nmake' : 'make';
376 0   0       $has{make} = $progs->{make} ||
377             $Config{make} || which($make) || $CPAN::Config->{make};
378              
379 0   0       $has{perl} =
380             $^X || which('perl');
381            
382 0           foreach (qw(tar gzip make perl)) {
383 0 0         unless ($has{$_}) {
384 0           $ERROR = "Cannot find a '$_' program";
385 0           return;
386             }
387 0           print "Using $has{$_} ....\n";
388             }
389              
390 0           return \%has;
391             }
392              
393             sub mod_version {
394 0     0 0   my $mod = shift;
395 0           eval "require $mod";
396 0 0         return if $@;
397 0           my $mv = eval "$mod->VERSION";
398 0 0         return 0 if $@;
399 0           $mv =~ s/_.*$//x;
400 0           $mv += 0;
401 0           return $mv;
402             }
403              
404             sub path_ext {
405 0 0   0 0   if ($ENV{PATHEXT}) {
406 0           push @path_ext, split ';', $ENV{PATHEXT};
407 0           for my $extention (@path_ext) {
408 0           $extention =~ s/^\.*(.+)$/$1/;
409             }
410             }
411             else {
412             #Win9X: doesn't have PATHEXT
413 0           push @path_ext, qw(com exe bat);
414             }
415             }
416              
417             =item which
418              
419             Find the full path to a program, if available.
420              
421             my $perl = which('perl');
422              
423             =cut
424              
425             sub which {
426 0     0 1   my $program = shift;
427 0 0         return undef unless $program;
428 0           my @results = ();
429 0           my $home = File::HomeDir->my_home;
430 0           for my $base (map { File::Spec->catfile($_, $program) } File::Spec->path()) {
  0            
431 0 0 0       if ($home and not WIN32) {
432             # only works on Unix, but that's normal:
433             # on Win32 the shell doesn't have special treatment of '~'
434 0           $base =~ s/~/$home/o;
435             }
436 0 0         return $base if -x $base;
437            
438 0           if (WIN32) {
439             for my $extention (@path_ext) {
440             return "$base.$extention" if -x "$base.$extention";
441             }
442             }
443             }
444             }
445              
446             1;
447              
448             __END__