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.02';
4              
5 2     2   1998639 use 5.010;
  2         6  
6 2     2   488 use utf8;
  2         9  
  2         11  
7              
8 2     2   402 use namespace::autoclean;
  2         13648  
  2         15  
9              
10 2     2   1054 use MooseX::App::Role;
  2         610120  
  2         6  
11              
12 2     2   60944 use Config::Any;
  2         7621  
  2         59  
13 2     2   1076 use File::HomeDir;
  2         9614  
  2         135  
14 2     2   15 use Cwd;
  2         3  
  2         126  
15 2     2   957 use MooseX::Types::Path::Tiny qw/Path Paths AbsPaths AbsFile/;
  2         294514  
  2         17  
16 2     2   5636 use Path::Tiny;
  2         3  
  2         118  
17 2     2   38 use Try::Tiny;
  2         3  
  2         1932  
18              
19             option 'no_configs' => (
20             is => 'rw',
21             isa => 'Bool',
22             default => 0,
23             documentation => '--no_configs tells HPC::Runner not to load any configs',
24             );
25              
26             option 'config' => (
27             isa => 'Str',
28             is => 'rw',
29             required => 0,
30             documentation => 'Override the search paths and supply your own config.',
31             isa => AbsFile,
32             coerce => 1,
33             predicate => 'has_config',
34             );
35              
36             option 'config_base' => (
37             is => 'rw',
38             isa => 'Str',
39             default => '.config',
40             documentation => 'Basename of config files',
41             );
42              
43             option 'search' => (
44             traits => ['Bool'],
45             is => 'rw',
46             isa => 'Bool',
47             default => 1,
48             handles => {
49             'no_search' => 'unset',
50             },
51             documentation =>
52             'Search for config files in ~/.config.(ext) and in your current working directory.'
53             );
54              
55             option 'search_path' => (
56             traits => ['Array'],
57             is => 'rw',
58             isa => 'ArrayRef[Str]',
59             default => sub { [ File::HomeDir->my_home, getcwd() ] },
60             handles => {
61             all_search_path => 'elements',
62             append_search_path => 'push',
63             prepend_search_path => 'unshift',
64             map_search_path => 'map',
65             has_search_path => 'count',
66             },
67             documentation => '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             after '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 1 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         4 $self->search_configs;
126             }
127             }
128              
129             sub search_configs {
130 1     1 0 1 my $self = shift;
131 1         1 my $extension = shift;
132              
133 1         10 foreach my $extension ( Config::Any->extensions ) {
134 10         7850 foreach my $dir ( $self->all_search_path ) {
135 10         10 my $dir = $dir . '/';
136              
137             #We will check with and without extensions
138 10         8 my $check_file;
139 10         267 $check_file = File::Spec->catfile( $dir . $self->config_base );
140 10 50       121 $self->append_config_files($check_file) if -f $check_file;
141              
142 10         271 $check_file =
143             File::Spec->catfile(
144             $dir . $self->config_base . '.' . $extension );
145 10 100       186 $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 2 my $self = shift;
155              
156 1         2 my $command_name = $self->{_original_class_name};
157 1         33 my $cfg =
158             Config::Any->load_files( { files => $self->config_files, use_ext => 1 } );
159              
160 1         3055 $self->_config_data($cfg);
161              
162 1         4 $self->apply_configs;
163             }
164              
165             sub apply_configs {
166 1     1 0 2 my $self = shift;
167              
168 1         2 my $command_name = $self->{_original_class_name};
169 1         39 for ( my $x = 0 ; $x < $self->count_config_files ; $x++ ) {
170 1         27 my $c = $self->_config_data->[$x]->{ $self->config_files->[$x] };
171 1         4 my @keys = keys %{$c};
  1         5  
172              
173 1 50       38 if ( !$self->has_filter_keys ) {
174 1         3 my @filter_keys = grep { $_ ne 'global' } @keys;
  2         4  
175 1         29 $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         35 map { $self->apply_attributes( $c, $_ ) } $self->all_filter_keys;
  1         4  
182             }
183              
184             }
185              
186             sub apply_attributes {
187 2     2 0 2 my $self = shift;
188 2         2 my $conf = shift;
189 2         3 my $attr = shift;
190              
191 2 50       5 return unless ref($conf) eq 'HASH';
192 2 50       4 return unless ref( $conf->{$attr} ) eq 'HASH';
193              
194 2         2 while ( my ( $key, $value ) = each %{ $conf->{$attr} } ) {
  4         65  
195              
196 2 100       53 if ( $self->can($key) ) {
197             try {
198 1     1   85 $self->$key($value);
199             }
200             catch {
201 0     0   0 warn 'You tried to assign ' . $key . ' to ' . $value . "\n";
202             #TODO Add logging
203 1         10 };
204             }
205             }
206             }
207              
208             1;
209              
210             __END__
211              
212             =encoding utf-8
213              
214             =head1 NAME
215              
216             HPC::Runner::Command::Utils::ManyConfigs - Load many layered configs
217              
218             =head1 SYNOPSIS
219              
220             use Moose;
221             with 'HPC::Runner::Command::Utils::ManyConfigs';
222              
223             #Specify search_paths with --search_path
224             #Specify config base with --config_base
225              
226              
227             =head1 DESCRIPTION
228              
229             HPC::Runner::Command::Utils::ManyConfigs are just some helper utilities to make it easier to layer config files
230              
231             It is in the HPC::Runner::Command namespace, but it is meant to be portable for any MooseX::App.
232              
233             =head1 AUTHOR
234              
235             Jillian Rowe E<lt>jillian.e.rowe@gmail.comE<gt>
236              
237             =head1 COPYRIGHT
238              
239             Copyright 2017- Jillian Rowe
240              
241             =head1 LICENSE
242              
243             This library is free software; you can redistribute it and/or modify
244             it under the same terms as Perl itself.
245              
246             =head1 SEE ALSO
247              
248             =cut