File Coverage

blib/lib/XS/Install/Deps.pm
Criterion Covered Total %
statement 59 87 67.8
branch 11 40 27.5
condition 0 6 0.0
subroutine 9 10 90.0
pod 0 4 0.0
total 79 147 53.7


line stmt bran cond sub pod time code
1             package
2             XS::Install::Deps;
3 11     11   78 use strict;
  11         23  
  11         379  
4 11     11   62 use warnings;
  11         22  
  11         311  
5 11     11   56 use Cwd 'abs_path';
  11         18  
  11         515  
6 11     11   60 use File::Spec;
  11         21  
  11         10826  
7              
8             sub find_header_deps {
9 31     31 0 64 my $p = shift;
10 31 50       56 my $headers = [ grep {$_} map { abs_path($_) } @{$p->{headers} || []} ];
  31         115  
  31         403  
  31         111  
11 31 50       65 my $inc = [ grep {$_} map { abs_path($_) } @{$p->{inc} || []} ];
  0         0  
  0         0  
  31         116  
12 31         58 my $cache = {};
13 31 50       81 $headers = undef unless @$headers;
14            
15 31         50 my %ret;
16 31         60 foreach my $file (@{$p->{files}}) {
  31         94  
17 179 50       310 my $absfile = eval { abs_path($file) } or next;
  179         3893  
18 179 50       2345 next unless -f $absfile;
19 179 50       555 my $deps = _find_header_deps($absfile, $cache, $inc, $headers) or next;
20 179         729 $ret{$file} = [keys %$deps];
21             }
22            
23 31         213 return \%ret;
24             }
25              
26             sub _find_header_deps {
27 179     179   467 my ($file, $cache, $inc, $headers) = @_;
28 179 50       417 return $cache->{$file} if exists $cache->{$file};
29            
30 179         525 my $deps = $cache->{$file} = {};
31 179         384 my $content = readfile($file);
32 179         360 my $dir = $file;
33 179         1389 $dir =~ s#[^/\\]+$##;
34            
35 179         572 while ($content =~ /^\s*#\s*include\s*("|<)([^">]+)(?:"|>)/mg) {
36 0         0 my ($type, $dep) = ($1, $2);
37 0         0 my $absdep;
38 0 0       0 if ($type eq '"') { # try to find locally first
39 0         0 $absdep = getfile($dir.$dep);
40             }
41 0 0       0 unless ($absdep) { # try to find globally
42 0         0 foreach my $dir (@$inc) {
43 0         0 $absdep = getfile($dir.'/'.$dep);
44 0 0       0 last if $absdep;
45             }
46             }
47 0 0 0     0 if ($absdep and $headers) { # if supplied, ignore everything that is outside of specified dirs
48 0         0 my $found;
49 0         0 foreach my $dir (@$headers) {
50 0 0       0 next unless index($absdep, $dir) == 0;
51 0         0 $found = 1;
52 0         0 last;
53             }
54 0 0       0 $absdep = undef unless $found;
55             }
56 0 0       0 next unless $absdep;
57            
58 0         0 $deps->{File::Spec->abs2rel($absdep)}++;
59 0         0 my $subdeps = _find_header_deps($absdep, $cache, $inc, $headers);
60 0         0 $deps->{$_}++ for keys %$subdeps;
61             }
62            
63 179         486 return $deps;
64             }
65              
66             sub find_xsi_deps {
67 77     77 0 143 my $files = shift;
68 77         114 my %ret;
69 77         175 foreach my $file (@$files) {
70 77 50       1957 my $absfile = abs_path($file) or next;
71 77 50       1083 next unless -f $absfile;
72 77 50       302 my $deps = _find_xsi_deps($absfile) or next;
73 77         390 $ret{$file} = [keys %$deps];
74             }
75 77         355 return \%ret;
76             }
77              
78             sub _find_xsi_deps {
79 77     77   135 my $file = shift;
80            
81 77         183 my $content = readfile($file);
82 77         162 my $dir = $file;
83 77         647 $dir =~ s#[^/\\]+$##;
84              
85 77         172 my $deps = {};
86 77         234 while ($content =~ /^\s*INCLUDE\s*:\s*(.+)/mg) {
87 0 0       0 my $xsi = getfile($dir.$1) or next;
88 0         0 $deps->{File::Spec->abs2rel($xsi)}++;
89 0         0 my $subdeps = _find_xsi_deps($xsi);
90 0         0 $deps->{$_}++ for keys %$subdeps;
91             }
92            
93 77         263 return $deps;
94             }
95              
96             sub getfile {
97 0     0 0 0 my $f = abs_path($_[0]);
98 0 0 0     0 return undef unless $f and -f $f;
99 0         0 return $f;
100             }
101              
102             sub readfile {
103 256     256 0 386 my $file = shift;
104 256 50       8587 open my $fh, '<', $file or die "cannot open $file: $!";
105 256         1486 local $/ = undef;
106 256         4048 my $content = <$fh>;
107 256         2282 close $fh;
108 256         1852 return $content;
109             }
110              
111             1;