File Coverage

blib/lib/PPM/Make/Config.pm
Criterion Covered Total %
statement 52 257 20.2
branch 6 120 5.0
condition 0 56 0.0
subroutine 14 23 60.8
pod 1 12 8.3
total 73 468 15.6


line stmt bran cond sub pod time code
1             package PPM::Make::Config;
2 5     5   16 use strict;
  5         12  
  5         103  
3 5     5   15 use warnings;
  5         6  
  5         98  
4 5     5   15 use base qw(Exporter);
  5         5  
  5         387  
5 5     5   2155 use File::HomeDir;
  5         21420  
  5         258  
6             require File::Spec;
7 5     5   25 use Config;
  5         6  
  5         145  
8 5     5   3138 use Config::IniFiles;
  5         119055  
  5         301  
9              
10             our ($ERROR);
11             our $VERSION = '0.9904';
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   37 use constant WIN32 => $^O eq 'MSWin32';
  5         6  
  5         442  
34              
35 5     5   18 use constant ACTIVEPERL => eval { require ActivePerl::Config; 1 };
  5         7  
  5         5  
  5         2051  
  0         0  
36              
37             my @path_ext = ();
38             path_ext() if WIN32;
39              
40             sub has_cpan {
41 5     5 0 5 my $has_config = 0;
42 5         13 require File::Spec;
43 5         27 my $home = File::HomeDir->my_home;
44 5 50       203 if ($home) {
45             eval
46 5         7 {require File::Spec->catfile($home, '.cpan',
  5         2127  
47             'CPAN', 'MyConfig.pm');};
48 5 50       22 $has_config = 1 unless $@;
49             }
50 5 50       13 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       3492 require CPAN if $has_config;
60 5         1072469 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   16 use constant HAS_CPAN => has_cpan();
  5         9  
  5         9  
71              
72             sub has_ppm {
73 5     5 0 11 my $has_ppm = 0;
74 5         220 my $ppm = File::Spec->catfile($Config{bin}, 'ppm.bat');
75 5 50       702 return unless -f $ppm;
76 0         0 my $version;
77              
78             VERSION: {
79 0 0       0 (eval {require PPM;}) and do {
  0         0  
  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   68 use constant HAS_PPM => has_ppm();
  5         11  
  5         18  
110              
111             sub has_mb {
112 5     5 0 12 my $has_mb = 0;
113 5         10 eval {require Module::Build;};
  5         3119  
114 5 50       249738 $has_mb = 1 unless $@;
115 5         8783 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   25 use constant HAS_MB => has_mb();
  5         13  
  5         19  
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 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             my %legal =
138 0           map {$_ => 1} qw(force ignore binary zip_archive remove program cpan
  0            
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}) {
314 0           $has{tar} = $progs->{tar};
315 0           $has{gzip} = $progs->{gzip};
316             }
317             elsif (not WIN32) {
318             $has{tar} =
319 0   0       $Config{tar} || which('tar') || $CPAN::Config->{tar};
320             $has{gzip} =
321 0   0       $Config{gzip} || which('gzip') || $CPAN::Config->{gzip};
322             }
323             else {
324             eval{require Archive::Tar; require Compress::Zlib};
325             if ($@) {
326             $has{tar} =
327             $Config{tar} || which('tar') || $CPAN::Config->{tar};
328             $has{gzip} =
329             $Config{gzip} || which('gzip') || $CPAN::Config->{gzip};
330             }
331             else {
332             my $atv = mod_version('Archive::Tar');
333             if (not WIN32 or (WIN32 and $atv >= 1.08)) {
334             $has{tar} = 'Archive::Tar';
335             $has{gzip} = 'Compress::Zlib';
336             }
337             else {
338             $has{tar} =
339             $Config{tar} || which('tar') || $CPAN::Config->{tar};
340             $has{gzip} =
341             $Config{gzip} || which('gzip') || $CPAN::Config->{gzip};
342             }
343             }
344             }
345              
346 0 0 0       if (defined $progs->{zip} and defined $progs->{unzip}) {
347 0           $has{zip} = $progs->{zip};
348 0           $has{unzip} = $progs->{unzip};
349             }
350             else {
351 0           eval{require Archive::Zip; };
  0            
352 0 0         if ($@) {
353             $has{zip} =
354 0   0       $Config{zip} || which('zip') || $CPAN::Config->{zip};
355             $has{unzip} =
356 0   0       $Config{unzip} || which('unzip') || $CPAN::Config->{unzip};
357             }
358             else {
359 0           my $zipv = mod_version('Archive::Zip');
360 0 0         if ($zipv >= 1.02) {
361 0           require Archive::Zip; import Archive::Zip qw(:ERROR_CODES);
  0            
362 0           $has{zip} = 'Archive::Zip';
363 0           $has{unzip} = 'Archive::Zip';
364             }
365             else {
366             $has{zip} =
367 0   0       $Config{zip} || which('zip') || $CPAN::Config->{zip};
368             $has{unzip} =
369 0   0       $Config{unzip} || which('unzip') || $CPAN::Config->{unzip};
370             }
371             }
372             }
373            
374 0           my $make = WIN32 ? 'nmake' : 'make';
375             $has{make} = $progs->{make} ||
376 0   0       $Config{make} || which($make) || $CPAN::Config->{make};
377              
378             $has{perl} =
379 0   0       $^X || which('perl');
380            
381 0           foreach (qw(tar gzip make perl)) {
382 0 0         unless ($has{$_}) {
383 0           $ERROR = "Cannot find a '$_' program";
384 0           return;
385             }
386 0           print "Using $has{$_} ....\n";
387             }
388              
389 0           return \%has;
390             }
391              
392             sub mod_version {
393 0     0 0   my $mod = shift;
394 0           eval "require $mod";
395 0 0         return if $@;
396 0           my $mv = eval "$mod->VERSION";
397 0 0         return 0 if $@;
398 0           $mv =~ s/_.*$//x;
399 0           $mv += 0;
400 0           return $mv;
401             }
402              
403             sub path_ext {
404 0 0   0 0   if ($ENV{PATHEXT}) {
405 0           push @path_ext, split ';', $ENV{PATHEXT};
406 0           for my $extention (@path_ext) {
407 0           $extention =~ s/^\.*(.+)$/$1/;
408             }
409             }
410             else {
411             #Win9X: doesn't have PATHEXT
412 0           push @path_ext, qw(com exe bat);
413             }
414             }
415              
416             =item which
417              
418             Find the full path to a program, if available.
419              
420             my $perl = which('perl');
421              
422             =cut
423              
424             sub which {
425 0     0 1   my $program = shift;
426 0 0         return undef unless $program;
427 0           my @results = ();
428 0           my $home = File::HomeDir->my_home;
429 0           for my $base (map { File::Spec->catfile($_, $program) } File::Spec->path()) {
  0            
430 0 0 0       if ($home and not WIN32) {
431             # only works on Unix, but that's normal:
432             # on Win32 the shell doesn't have special treatment of '~'
433 0           $base =~ s/~/$home/o;
434             }
435 0 0         return $base if -x $base;
436            
437 0           if (WIN32) {
438             for my $extention (@path_ext) {
439             return "$base.$extention" if -x "$base.$extention";
440             }
441             }
442             }
443             }
444              
445             1;
446              
447             __END__