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