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   74 use strict;
  11         19  
  11         465  
4 11     11   64 use warnings;
  11         30  
  11         612  
5 11     11   58 use Cwd 'abs_path';
  11         17  
  11         742  
6 11     11   133 use File::Spec;
  11         79  
  11         12979  
7              
8             sub find_header_deps {
9 31     31 0 109 my $p = shift;
10 31 50       66 my $headers = [ grep {$_} map { abs_path($_) } @{$p->{headers} || []} ];
  31         115  
  31         329  
  31         159  
11 31 50       64 my $inc = [ grep {$_} map { abs_path($_) } @{$p->{inc} || []} ];
  0         0  
  0         0  
  31         124  
12 31         64 my $cache = {};
13 31 50       120 $headers = undef unless @$headers;
14            
15 31         53 my %ret;
16 31         55 foreach my $file (@{$p->{files}}) {
  31         98  
17 179 50       289 my $absfile = eval { abs_path($file) } or next;
  179         3710  
18 179 50       2854 next unless -f $absfile;
19 179 50       410 my $deps = _find_header_deps($absfile, $cache, $inc, $headers) or next;
20 179         780 $ret{$file} = [keys %$deps];
21             }
22            
23 31         268 return \%ret;
24             }
25              
26             sub _find_header_deps {
27 179     179   423 my ($file, $cache, $inc, $headers) = @_;
28 179 50       450 return $cache->{$file} if exists $cache->{$file};
29            
30 179         478 my $deps = $cache->{$file} = {};
31 179         359 my $content = readfile($file);
32 179         279 my $dir = $file;
33 179         2024 $dir =~ s#[^/\\]+$##;
34            
35 179         499 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         487 return $deps;
64             }
65              
66             sub find_xsi_deps {
67 77     77 0 123 my $files = shift;
68 77         120 my %ret;
69 77         211 foreach my $file (@$files) {
70 77 50       1938 my $absfile = abs_path($file) or next;
71 77 50       806 next unless -f $absfile;
72 77 50       246 my $deps = _find_xsi_deps($absfile) or next;
73 77         365 $ret{$file} = [keys %$deps];
74             }
75 77         369 return \%ret;
76             }
77              
78             sub _find_xsi_deps {
79 77     77   130 my $file = shift;
80            
81 77         197 my $content = readfile($file);
82 77         143 my $dir = $file;
83 77         725 $dir =~ s#[^/\\]+$##;
84              
85 77         144 my $deps = {};
86 77         259 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         256 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 445 my $file = shift;
104 256 50       8669 open my $fh, '<', $file or die "cannot open $file: $!";
105 256         1350 local $/ = undef;
106 256         5033 my $content = <$fh>;
107 256         2044 close $fh;
108 256         1413 return $content;
109             }
110              
111             1;