File Coverage

blib/lib/Zoidberg/Utils.pm
Criterion Covered Total %
statement 62 79 78.4
branch 17 42 40.4
condition 3 6 50.0
subroutine 12 13 92.3
pod 2 5 40.0
total 96 145 66.2


line stmt bran cond sub pod time code
1              
2             package Zoidberg::Utils;
3              
4             our $VERSION = '0.981';
5              
6 38     38   25377 use strict;
  38         66  
  38         787  
7 38     38   14667 use vars '$AUTOLOAD';
  38         79  
  38         878  
8 22     22   17638 use Zoidberg::Utils::Error;
  22         38  
  22         131  
9             use Exporter::Tidy
10 22         225 default => [qw/:output :error/],
11             output => [qw/output message debug/],
12             error => [qw/error bug todo complain/],
13             fs => [qw/path list_dir/],
14             other => [qw/
15             setting read_data_file read_file merge_hash
16             complain typed_output output_is_captured
17             list_path unique_file regex_glob
18             getopt help usage version path2hashref
19 22     22   2835 /] ;
  22         29  
20              
21             our $ERROR_CALLER = 1;
22              
23             our %loadable = (
24             fs => ['Zoidberg::Utils::FileSystem', qw/path list_dir list_path unique_file regex_glob/ ],
25             output => ['Zoidberg::Utils::Output', qw/output message debug complain typed_output output_is_captured/ ],
26             getopt => ['Zoidberg::Utils::GetOpt', qw/getopt help usage version path2hashref/ ],
27             );
28              
29             sub AUTOLOAD {
30 53     53   1772 $AUTOLOAD =~ s/.*:://;
31 53 50       247 return if $AUTOLOAD eq 'DESTROY';
32              
33 53         108 my ($class, @subs);
34 53         252 for my $key (keys %loadable) {
35 76 100       138 next unless grep {$AUTOLOAD eq $_} @{$loadable{$key}};
  477         936  
  76         210  
36 53         94 ($class, @subs) = @{delete $loadable{$key}};
  53         365  
37 53     21   5022 eval "use $class \@subs";
  21         25171  
  21         64  
  21         178  
38 53 50       10538 die if $@;
39 53         196 last;
40             }
41              
42 53 50       232 die "Could not load '$AUTOLOAD'" unless $class;
43 22     22   6645 no strict 'refs';
  22         162  
  22         18857  
44 53         111 goto &{$AUTOLOAD};
  53         361  
45             }
46              
47             ## Various methods ##
48              
49             sub setting {
50             # FIXME support for Fish argument and namespace
51 1     1 0 2 my $key = shift;
52 1 50       8 return undef unless exists $Zoidberg::CURRENT->{settings}{$key};
53 1         8 my $ref = $Zoidberg::CURRENT->{settings}{$key};
54 1 50 33     34 return (wantarray && ref($ref) eq 'ARRAY') ? (@$ref) : $ref;
55             }
56              
57             sub read_data_file {
58 1     1 1 1553 my $file = shift;
59 1 50       12 error 'read_data_file() is not intended for fully specified files, try read_file()'
60             if $file =~ m!^/!;
61 1         9 for my $dir (setting('data_dirs')) {
62 2         16 for ("$dir/data/$file", map "$dir/data/$file.$_", qw/pl pd yaml/) {
63 6 100       100 next unless -f $_;
64 1 50       3440 error "Can not read file: $_" unless -r $_;
65 1         8 return read_file($_);
66             }
67             }
68 0         0 error "Could not find 'data/$file' in (" .join(', ', setting('data_dirs')).')';
69             }
70              
71             sub read_file {
72 65     65 1 134 my $file = shift;
73 65 50       1799 error "no such file: $file\n" unless -f $file;
74              
75 65         85 my $ref;
76 65 50       1058 if ($file =~ /^\w+$/) { todo 'executable data file' }
  0 50       0  
    0          
    0          
77             elsif ($file =~ /\.(pl)$/i) {
78 65         557518 eval q{package Main; $ref = do $file; die $@ if $@ };
79             }
80 0         0 elsif ($file =~ /\.(pd)$/i) { $ref = pd_read($file) }
81             elsif ($file =~ /\.(yaml)$/i) {
82 0 0       0 eval 'require YAML' or error $@;
83 0         0 $ref = YAML::LoadFile($file);
84             }
85 0         0 else { error qq/Unkown file type: "$file"\n/ }
86              
87 65 50       309 error "In file $file\: $@" if $@;
88 65 50       301 error "File $file did not return a defined value" unless defined $ref;
89 65         422 return $ref;
90             }
91              
92             sub pd_read {
93 0     0 0 0 my $FILE = shift;
94              
95 0         0 print STDERR "Deprecated config file: $FILE - should be a .pl instead of .pd\n";
96              
97 0 0       0 open FILE, '<', $FILE or return undef;
98 0         0 my $CONTENT = join '', ();
99 0         0 close FILE;
100 0         0 my $VAR1;
101 0         0 eval $CONTENT;
102 0 0       0 complain("Failed to eval the contents of $FILE ($@)") if $@;
103 0         0 return $VAR1;
104             }
105              
106             sub merge_hash {
107 96     96 0 210 my $ref = {};
108 96         163 local $ERROR_CALLER = 2;
109 96         358 $ref = _merge($ref, $_) for @_;
110 96         739 return $ref;
111             }
112              
113             sub _merge { # Removed use of Storable::dclone - can throw nasty bugs
114 192     192   585 my ($ref, $ding) = @_;
115 192         290 while (my ($k, $v) = each %{$ding}) {
  624         2038  
116 432 50 66     1322 if (defined $$ref{$k} and ref($v) eq 'HASH') {
117 0 0       0 error 'incompatible types for key: '.$k.' in merging hashes'
118             unless ref($$ref{$k}) eq 'HASH';
119 0         0 $$ref{$k} = _merge($$ref{$k}, $v); #recurs
120             }
121 432         986 else { $ref->{$k} = $v; }
122             }
123 192         613 return $ref;
124             }
125              
126             1;
127              
128             __END__