File Coverage

blib/lib/Catmandu/Fix/include.pm
Criterion Covered Total %
statement 62 66 93.9
branch 10 18 55.5
condition n/a
subroutine 13 13 100.0
pod 0 1 0.0
total 85 98 86.7


line stmt bran cond sub pod time code
1              
2             use Catmandu::Sane;
3 1     1   87328  
  1         3  
  1         7  
4             our $VERSION = '1.2018';
5              
6             use Moo;
7 1     1   6 use Catmandu;
  1         2  
  1         4  
8 1     1   754 use Catmandu::Fix;
  1         3  
  1         5  
9 1     1   189 use File::Spec;
  1         2  
  1         17  
10 1     1   4 use Cwd qw(realpath);
  1         2  
  1         19  
11 1     1   3 use namespace::clean;
  1         40  
  1         43  
12 1     1   6 use Catmandu::Fix::Has;
  1         1  
  1         5  
13 1     1   673  
  1         3  
  1         5  
14             with 'Catmandu::Fix::Inlineable';
15              
16             has path => (fix_arg => 1);
17             has _files => (is => 'lazy');
18             has _fixer => (is => 'lazy');
19              
20             my ($self) = @_;
21             my $path = $self->path;
22 4     4   57  
23 4         12 if ($path =~ /\*/) { # path is glob pattern
24             return $self->_find_glob($path);
25 4 100       14 }
26 1         5  
27             [$self->_find_file($path)];
28             }
29 3         8  
30             my ($self, $path) = @_;
31             my $roots = Catmandu->roots;
32             my $file;
33 3     3   8  
34 3         15 if (File::Spec->file_name_is_absolute($path)) {
35 3         6 $file = $path;
36             }
37 3 50       26 else {
38 0         0 for my $root (@$roots) {
39             my $f = File::Spec->catfile($root, $path);
40             if (-r $f) {
41 3         8 $file = $f;
42 3         31 last;
43 3 50       68 }
44 3         8 }
45 3         6  
46             }
47              
48             Catmandu::Error->throw(
49             "unable to find $path in " . join(',', @$roots) . ")")
50             unless defined $file;
51 3 50       10  
52             realpath($file);
53             }
54              
55 3         120 my ($self, $path) = @_;
56             my $roots = Catmandu->roots;
57              
58             if (File::Spec->file_name_is_absolute($path)) {
59 1     1   3 return [sort map {realpath($_)} grep {-r $_} glob $path];
60 1         6 }
61              
62 1 50       9 my %seen;
63 0         0 my $files = [];
  0         0  
  0         0  
64              
65             for my $root (@$roots) {
66 1         3 my $glob = File::Spec->catfile($root, $path);
67 1         1 for my $file (glob $glob) {
68             my $rel_path = File::Spec->abs2rel($file, $root);
69 1         3 next if $seen{$rel_path};
70 1         12 if (-r $file) {
71 1         184 push @$files, realpath($file);
72 3         159 $seen{$rel_path} = 1;
73 3 50       17 }
74 3 50       54 }
75 3         118 }
76 3         14  
77             [sort @$files];
78             }
79              
80             my ($self) = @_;
81 1         10 my $files = $self->_files;
82             return unless @$files;
83             Catmandu::Fix->new(fixes => $files);
84             }
85 4     4   32  
86 4         58 my ($self, $data) = @_;
87 4 50       14 my $fixer = $self->_fixer;
88 4         80 return $data unless $fixer;
89             $fixer->fix($data);
90             }
91              
92 4     4 0 41 1;
93 4         68  
94 4 50       1610  
95 4         18 =pod
96              
97             =head1 NAME
98              
99             Catmandu::Fix::include - include fixes from another file
100              
101             =head1 SYNOPSIS
102              
103             include('/path/to/myfixes.txt')
104             include('fixes/*.fix')
105              
106             =head1 NOTES
107              
108             =over 4
109              
110             =item path is relative to a Catmandu load path
111              
112             #1. a catmandu load path is a directory where a catmandu configuration file can be found
113             #2. as there are multiple load paths, it will loop through all the path, and include the first file it can find
114             #3. in catmandu, the default_load_path is either
115             # 3.1. the directory of the running script
116             # 3.2. the parent directory of the running script if the directory is 'bin'
117              
118             #use default load_path
119             #called from script "/opt/catmandu-project/fix.pl"
120             #default_load_path: /opt/catmandu-project
121             #file must be located at "/opt/catmandu-project/fixes/myfixes.txt"
122             Catmandu->fixer("include('fixes/myfixes.txt')");
123              
124             #use default load_path
125             #called from script "/opt/catmandu-project/bin/fix.pl"
126             #default_load_path: /opt/catmandu-project (notice the absence of 'bin')
127             #file must be located at "/opt/catmandu-project/fixes/myfixes.txt"
128             Catmandu->fixer("include('fixes/myfixes.txt')");
129              
130             #load fixes, located at /opt/catmandu-project/fixes/myfixes.txt
131             Catmandu->load("/opt/catmandu-project");
132             Catmandu->fixer("include('fixes/myfixes.txt')");
133              
134             #look for 'fixes/myfixes.txt' in /opt/catmandu-project2, and if that fails in /opt/catmandu-project-1
135             Catmandu->load("/opt/catmandu-project2","/opt/catmandu-project-1");
136             Catmandu->fixer("include('fixes/myfixes.txt')");
137              
138             #if "/opt/catmandu-project/fixes/myfixes2.txt" does not exists, the fix will fail
139             Catmandu->load("/opt/catmandu-project");
140             Catmandu->fixer("include('fixes/myfixes2.txt)");
141              
142              
143             =item circular references are not detected
144              
145             =item if the 'include' is enclosed within an if-statement, the fixes are inserted in the control structure, but only executed if the if-statement evaluates to 'true'.
146              
147             #the fixes in the file 'add_address_fields.txt' are only executed when field 'name' has content,
148             #but, the fixes are included in the control structure.
149             if all_match('name','.+')
150             include('add_address_fields.txt')
151             end
152              
153             =back
154              
155             =head1 SEE ALSO
156              
157             L<Catmandu::Fix>
158              
159             =cut