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   79 use strict;
  11         24  
  11         387  
4 11     11   61 use warnings;
  11         25  
  11         337  
5 11     11   60 use Cwd 'abs_path';
  11         32  
  11         565  
6 11     11   79 use File::Spec;
  11         23  
  11         11142  
7              
8             sub find_header_deps {
9 31     31 0 64 my $p = shift;
10 31 50       64 my $headers = [ grep {$_} map { abs_path($_) } @{$p->{headers} || []} ];
  31         134  
  31         399  
  31         147  
11 31 50       69 my $inc = [ grep {$_} map { abs_path($_) } @{$p->{inc} || []} ];
  0         0  
  0         0  
  31         134  
12 31         71 my $cache = {};
13 31 50       86 $headers = undef unless @$headers;
14            
15 31         53 my %ret;
16 31         67 foreach my $file (@{$p->{files}}) {
  31         90  
17 179 50       310 my $absfile = eval { abs_path($file) } or next;
  179         3928  
18 179 50       2256 next unless -f $absfile;
19 179 50       640 my $deps = _find_header_deps($absfile, $cache, $inc, $headers) or next;
20 179         789 $ret{$file} = [keys %$deps];
21             }
22            
23 31         234 return \%ret;
24             }
25              
26             sub _find_header_deps {
27 179     179   449 my ($file, $cache, $inc, $headers) = @_;
28 179 50       495 return $cache->{$file} if exists $cache->{$file};
29            
30 179         573 my $deps = $cache->{$file} = {};
31 179         359 my $content = readfile($file);
32 179         434 my $dir = $file;
33 179         1432 $dir =~ s#[^/\\]+$##;
34            
35 179         621 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         536 return $deps;
64             }
65              
66             sub find_xsi_deps {
67 77     77 0 151 my $files = shift;
68 77         117 my %ret;
69 77         169 foreach my $file (@$files) {
70 77 50       1868 my $absfile = abs_path($file) or next;
71 77 50       1037 next unless -f $absfile;
72 77 50       273 my $deps = _find_xsi_deps($absfile) or next;
73 77         511 $ret{$file} = [keys %$deps];
74             }
75 77         358 return \%ret;
76             }
77              
78             sub _find_xsi_deps {
79 77     77   137 my $file = shift;
80            
81 77         1107 my $content = readfile($file);
82 77         214 my $dir = $file;
83 77         672 $dir =~ s#[^/\\]+$##;
84              
85 77         184 my $deps = {};
86 77         262 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         231 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 432 my $file = shift;
104 256 50       8923 open my $fh, '<', $file or die "cannot open $file: $!";
105 256         1776 local $/ = undef;
106 256         4473 my $content = <$fh>;
107 256         2630 close $fh;
108 256         1796 return $content;
109             }
110              
111             1;