File Coverage

blib/lib/Config/Directory.pm
Criterion Covered Total %
statement 87 91 95.6
branch 50 60 83.3
condition 19 29 65.5
subroutine 10 10 100.0
pod 3 5 60.0
total 169 195 86.6


line stmt bran cond sub pod time code
1              
2             package Config::Directory;
3              
4 10     10   133160 use 5.000;
  10         38  
  10         367  
5 10     10   56 use strict;
  10         19  
  10         444  
6 10     10   53 use File::Basename;
  10         21  
  10         1190  
7 10     10   64 use File::Spec;
  10         14  
  10         249  
8              
9 10     10   52 use vars qw($VERSION);
  10         83  
  10         13109  
10              
11             $VERSION = '0.05';
12              
13             my $DIRLIST;
14             my $ARG;
15              
16             # Helper routine - read an individual file
17             sub readfile
18             {
19 37     37 0 63 my ($self, $dir_file, $arg) = @_;
20 37         57 my $content = '';
21              
22             # Open
23 37 50       1225 open FILE, "<$dir_file" or die "can't open file '$dir_file': $!";
24              
25             # Read only $arg->{lines} lines, if set
26 37 100 66     197 if ($arg->{lines} && $arg->{lines} =~ m/(\d+)/) {
27 6         30 for (1 .. $1) {
28 6         115 $content .= ;
29             }
30             }
31              
32             # Otherwise slurp entire file
33             else {
34 31         95 local $/ = undef;
35 31         699 $content = ;
36             }
37 37         420 close FILE;
38              
39 37         144 return $content;
40             }
41              
42             # Initialise hash
43             sub init
44             {
45 15     15 0 41 my ($self, $dir, $arg) = @_;
46 15 100       79 $dir = [ $dir ] if ref $dir ne 'ARRAY';
47 15         34 $DIRLIST = $dir;
48 15         29 $ARG = $arg;
49 15         39 my $env = $arg->{env};
50 15   100     108 my $maxsize = $arg->{maxsize} || 102_400;
51 15         30 my $ignore = $arg->{ignore};
52              
53             # Iterate over directories in reverse order
54 15         39 for my $d (reverse @$dir) {
55 18 50       431 if (! -d $d) {
56 0         0 warn "invalid directory '$d'";
57 0         0 next;
58             }
59            
60             # Read file list
61 18         42 my @files = ();
62 18 100       58 if ($arg->{glob}) {
63 2 100       8 if (ref $arg->{glob} eq 'ARRAY') {
64 1         1 for my $g (@{$arg->{glob}}) {
  1         3  
65 3         152 push @files, glob File::Spec->catfile($d, $g);
66             }
67             }
68             else {
69 1         273 @files = glob File::Spec->catfile($d, $arg->{glob});
70             }
71             }
72             else {
73 16 50       747 opendir DIR, $d or die "can't open directory '$d': $!";
74 16         516 @files = readdir DIR;
75             }
76              
77             # Iterate over files
78 18         54 for my $f (@files) {
79 87 100       1178 my $dir_file = $arg->{glob} ? $f : File::Spec->catfile($d, $f);
80 87 100       485 $f = basename($f) if $arg->{glob};
81              
82             # Ignore directories
83 87 100       1370 next if -d $dir_file;
84              
85             # Ignore if matches $ignore regex
86 54 100 100     223 next if defined $ignore && $f =~ m/$ignore/;
87              
88             # Ignore if size > $maxsize
89 51 100       823 next if -s $dir_file > $maxsize;
90              
91             # Ignore if not readable
92 50 50       841 next unless -r $dir_file;
93              
94             # Derived names
95 50 100       140 my $prefix_file = defined $arg->{prefix} ? $arg->{prefix} . "$f" : $f;
96 50         62 my $env_file = '';
97 50 100       188 if ($env) {
98 17 100       43 $env_file = $env eq '1' ? $prefix_file : "${env}$f";
99             }
100              
101             # Ignore if we have a later version
102 50 100       172 next if exists $self->{$prefix_file};
103              
104             # Warn on permissions problems
105 46 50       879 if (! -r $dir_file) {
106 0         0 warn "can't read file '$dir_file'";
107 0         0 next;
108             }
109              
110             # Zero-sized files clear any earlier entry
111 46 100       556 if (-z $dir_file) {
112 9         54 $self->{$prefix_file} = undef;
113 9 50 66     50 delete $ENV{$env_file} if $env_file and exists $ENV{$env_file};
114 9         23 next;
115             }
116              
117             # Read file
118 37         137 $self->{$prefix_file} = $self->readfile($dir_file, $arg);
119              
120             # Chomp value unless chomp => 0 arg given
121 37 100 100     200 chomp $self->{$prefix_file}
122             unless exists $arg->{'chomp'} && $arg->{'chomp'} == 0;
123              
124             # Trim value unless trim => 0 arg given
125 37 100 100     351 $self->{$prefix_file} =~ s/^\s*(.*?)\s*$/$1/m
126             unless exists $arg->{trim} && $arg->{trim} == 0;
127              
128             # Add to environment ('env_dir') if 'env' option and single line
129 37 100       210 if ($env) {
130 11         43 my ($first, $rest) = split /\n/, $self->{$prefix_file}, 2;
131 11 100       31 if (! $rest) {
132 8         69 $ENV{$env_file} = $self->{$prefix_file};
133 8         30 chomp $ENV{$env_file};
134             }
135             }
136             }
137 18 100       299 closedir DIR unless $arg->{glob};
138             }
139              
140             # Delete zero-sized files
141 15         77 for (keys %$self) {
142 46 100       142 delete $self->{$_} if ! defined $self->{$_};
143             }
144              
145 15         75 return $self;
146             }
147              
148             # Constructor
149             sub new
150             {
151 15     15 1 7269 my $self = bless {}, shift;
152 15         77 $self->init(@_);
153             }
154              
155             # Accessor
156             sub get
157             {
158 6     6 1 728 my ($self, $name) = @_;
159 6         89 $self->{$name};
160             }
161              
162             # Mutator
163             sub set
164             {
165 2     2 1 5 my ($self, $name, $value) = @_;
166              
167             # Find and check directory to write to
168 2         5 my $dir = $DIRLIST->[$#$DIRLIST];
169 2 50 33     56 die "final directory $dir is not writable" unless -d $dir && -w $dir;
170              
171             # Save to file
172 2         17 my $file = File::Spec->catfile($dir,$name);
173 2 50       158 open OUT, ">$file" or die "unable to open '$file' for write: $!";
174             {
175 2         5 local $\ = undef;
  2         8  
176 2         31 print OUT $value;
177 2 50 33     35 print OUT "\n"
      33        
      33        
178             unless substr($value,-1) eq "\n" || length($value) == 0 ||
179             (exists $ARG->{'chomp'} && $ARG->{'chomp'} == 0);
180             }
181 2 50       93 close OUT or die "unable to close '$file': $!";
182              
183             # Update $self
184 2         8 $self->{$name} = $value;
185             }
186              
187             1;
188              
189             __END__