File Coverage

blib/lib/HPC/Runner/Command/Utils/ManyConfigs.pm
Criterion Covered Total %
statement 71 74 95.9
branch 11 18 61.1
condition n/a
subroutine 17 18 94.4
pod 0 6 0.0
total 99 116 85.3


line stmt bran cond sub pod time code
1             package HPC::Runner::Command::Utils::ManyConfigs;
2              
3             our $VERSION = '0.03';
4              
5 2     2   1773406 use 5.010;
  2         6  
6 2     2   489 use utf8;
  2         10  
  2         9  
7              
8 2     2   406 use namespace::autoclean;
  2         12908  
  2         10  
9 2     2   866 use MooseX::App::Role;
  2         631024  
  2         8  
10              
11 2     2   60804 use Config::Any;
  2         7549  
  2         62  
12 2     2   933 use File::HomeDir;
  2         7972  
  2         119  
13 2     2   9 use Cwd;
  2         4  
  2         98  
14 2     2   781 use MooseX::Types::Path::Tiny qw/Path Paths AbsPaths AbsFile/;
  2         240734  
  2         14  
15 2     2   4504 use Path::Tiny;
  2         4  
  2         112  
16 2     2   30 use Try::Tiny;
  2         2  
  2         1633  
17              
18             option 'no_configs' => (
19             is => 'rw',
20             isa => 'Bool',
21             default => 0,
22             documentation => '--no_configs tells HPC::Runner not to load any configs',
23             );
24              
25             option 'config' => (
26             isa => 'Str',
27             is => 'rw',
28             required => 0,
29             documentation => 'Override the search paths and supply your own config.',
30             isa => AbsFile,
31             coerce => 1,
32             predicate => 'has_config',
33             );
34              
35             option 'config_base' => (
36             is => 'rw',
37             isa => 'Str',
38             default => '.config',
39             documentation => 'Basename of config files',
40             );
41              
42             option 'search' => (
43             traits => ['Bool'],
44             is => 'rw',
45             isa => 'Bool',
46             default => 1,
47             handles => {
48             'no_search' => 'unset',
49             },
50             documentation =>
51             'Search for config files in ~/.config.(ext) and in your current working directory.'
52             );
53              
54             option 'search_path' => (
55             traits => ['Array'],
56             is => 'rw',
57             isa => 'ArrayRef[Str]',
58             default => sub { [ File::HomeDir->my_home, getcwd() ] },
59             handles => {
60             all_search_path => 'elements',
61             append_search_path => 'push',
62             prepend_search_path => 'unshift',
63             map_search_path => 'map',
64             has_search_path => 'count',
65             },
66             documentation =>
67             'Enable a search path for configs. Default is the home dir and your cwd.'
68             );
69              
70             has 'filter_keys' => (
71             is => 'rw',
72             traits => ['Array'],
73             is => 'rw',
74             isa => 'ArrayRef[Str]',
75             default => sub { [] },
76             handles => {
77             all_filter_keys => 'elements',
78             append_filter_keys => 'push',
79             prepend_filter_keys => 'unshift',
80             map_filter_keys => 'map',
81             has_filter_keys => 'count',
82             },
83             );
84              
85             has 'config_files' => (
86             traits => ['Array'],
87             is => 'rw',
88             isa => AbsPaths,
89             coerce => 1,
90             default => sub { [] },
91             handles => {
92             all_config_files => 'elements',
93             append_config_files => 'push',
94             prepend_config_files => 'unshift',
95             map_config_files => 'map',
96             has_config_files => 'count',
97             count_config_files => 'count',
98             },
99             );
100              
101             has '_config_data' => (
102             is => 'rw',
103             isa => 'ArrayRef',
104             predicate => 'has_config_data',
105             default => sub { [] },
106             );
107              
108       1 0   sub BUILD { }
109              
110             before 'BUILD' => sub {
111             my $self = shift;
112              
113             return if $self->no_configs;
114             $self->decide_search_configs;
115             };
116              
117             sub decide_search_configs {
118 1     1 0 3 my $self = shift;
119              
120 1 50       30 if ( $self->has_config ) {
    50          
121 0         0 $self->append_config_files( $self->config );
122 0         0 $self->load_configs;
123             }
124             elsif ( $self->search ) {
125 1         5 $self->search_configs;
126             }
127             }
128              
129             sub search_configs {
130 1     1 0 1 my $self = shift;
131 1         2 my $extension = shift;
132              
133 1         10 foreach my $extension ( Config::Any->extensions ) {
134 10         7780 foreach my $dir ( $self->all_search_path ) {
135 10         10 my $dir = $dir . '/';
136              
137             #We will check with and without extensions
138 10         7 my $check_file;
139 10         268 $check_file = File::Spec->catfile( $dir . $self->config_base );
140 10 50       140 $self->append_config_files($check_file) if -f $check_file;
141              
142 10         275 $check_file =
143             File::Spec->catfile(
144             $dir . $self->config_base . '.' . $extension );
145 10 100       194 $self->append_config_files($check_file) if -f $check_file;
146             }
147             }
148              
149 1         5 $self->load_configs;
150              
151             }
152              
153             sub load_configs {
154 1     1 0 1 my $self = shift;
155              
156 1         2 my $command_name = $self->{_original_class_name};
157 1         30 my $cfg =
158             Config::Any->load_files( { files => $self->config_files, use_ext => 1 } );
159              
160 1         2828 $self->_config_data($cfg);
161              
162 1         4 $self->apply_configs;
163             }
164              
165             sub apply_configs {
166 1     1 0 1 my $self = shift;
167              
168 1         2 my $command_name = $self->{_original_class_name};
169 1         37 for ( my $x = 0 ; $x < $self->count_config_files ; $x++ ) {
170 1         26 my $c = $self->_config_data->[$x]->{ $self->config_files->[$x] };
171 1         3 my @keys = keys %{$c};
  1         4  
172              
173 1 50       35 if ( !$self->has_filter_keys ) {
174 1         2 my @filter_keys = grep { $_ ne 'global' } @keys;
  2         4  
175 1         28 $self->filter_keys( \@filter_keys );
176             }
177              
178             #Global is always applied
179 1 50       6 $self->apply_attributes( $c, 'global' ) if exists $c->{global};
180              
181 1         36 map { $self->apply_attributes( $c, $_ ) } $self->all_filter_keys;
  1         2  
182             }
183              
184             }
185              
186             sub apply_attributes {
187 2     2 0 3 my $self = shift;
188 2         3 my $conf = shift;
189 2         2 my $attr = shift;
190              
191 2 50       5 return unless ref($conf) eq 'HASH';
192 2 50       5 return unless ref( $conf->{$attr} ) eq 'HASH';
193              
194 2         2 while ( my ( $key, $value ) = each %{ $conf->{$attr} } ) {
  4         68  
195              
196 2 100       15 if ( $self->can($key) ) {
197             try {
198 1     1   101 $self->$key($value);
199             }
200             catch {
201 0     0   0 warn 'You tried to assign ' . $key . ' to ' . $value . "\n";
202              
203             #TODO Add logging
204 1         46 };
205             }
206             }
207             }
208              
209             1;
210              
211             __END__
212              
213             =encoding utf-8
214              
215             =head1 NAME
216              
217             HPC::Runner::Command::Utils::ManyConfigs - Load many layered configs
218              
219             =head1 SYNOPSIS
220              
221             use Moose;
222             with 'HPC::Runner::Command::Utils::ManyConfigs';
223              
224             #Specify search_paths with --search_path
225             #Specify config base with --config_base
226              
227              
228             =head1 DESCRIPTION
229              
230             HPC::Runner::Command::Utils::ManyConfigs are just some helper utilities to make it easier to layer config files
231              
232             It is in the HPC::Runner::Command namespace, but it is meant to be portable for any MooseX::App.
233              
234             =head1 AUTHOR
235              
236             Jillian Rowe E<lt>jillian.e.rowe@gmail.comE<gt>
237              
238             =head1 COPYRIGHT
239              
240             Copyright 2017- Jillian Rowe
241              
242             =head1 LICENSE
243              
244             This library is free software; you can redistribute it and/or modify
245             it under the same terms as Perl itself.
246              
247             =head1 SEE ALSO
248              
249             =cut