File Coverage

blib/lib/Config/Model/Backend/ShellVar.pm
Criterion Covered Total %
statement 56 59 94.9
branch 7 12 58.3
condition 1 2 50.0
subroutine 11 11 100.0
pod 3 3 100.0
total 78 87 89.6


line stmt bran cond sub pod time code
1             #
2             # This file is part of Config-Model
3             #
4             # This software is Copyright (c) 2005-2022 by Dominique Dumont.
5             #
6             # This is free software, licensed under:
7             #
8             # The GNU Lesser General Public License, Version 2.1, February 1999
9             #
10             package Config::Model::Backend::ShellVar 2.153; # TRIAL
11              
12 3     3   23 use Carp;
  3         10  
  3         234  
13 3     3   22 use Mouse;
  3         13  
  3         25  
14 3     3   1869 use Config::Model::Exception;
  3         10  
  3         106  
15 3     3   20 use File::Path;
  3         30  
  3         208  
16 3     3   20 use Log::Log4perl qw(get_logger :levels);
  3         18  
  3         51  
17 3     3   1922 use Config::Model::BackendTrackOrder;
  3         12  
  3         1962  
18              
19             extends 'Config::Model::Backend::Any';
20              
21             my $logger = get_logger("Backend::ShellVar");
22              
23             has tracker => (
24             is => 'ro',
25             isa => 'Config::Model::BackendTrackOrder',
26             lazy_build => 1,
27             handles => [qw/get_ordered_element_names/],
28             );
29              
30             sub _build_tracker {
31 8     8   28 my $self = shift;
32 8         145 return Config::Model::BackendTrackOrder->new(
33             backend_obj => $self,
34             node => $self->node,
35             ) ;
36             }
37              
38 8     8 1 24 sub annotation { return 1; }
39              
40             sub read {
41 8     8 1 25 my $self = shift;
42 8         72 my %args = @_;
43              
44             # args are:
45             # object => $obj, # Config::Model::Node object
46             # root => './my_test', # fake root directory, userd for tests
47             # config_dir => /etc/foo', # absolute path
48             # file => 'foo.conf', # file name
49             # file_path => './my_test/etc/foo/foo.conf'
50             # check => yes|no|skip
51              
52 8 50       42 return 0 unless $args{file_path}->exists; # no file to read
53 8   50     199 my $check = $args{check} || 'yes';
54              
55 8         41 my @lines = $args{file_path}->lines_utf8;
56              
57             # try to get global comments (comments before a blank line)
58 8         1845 $self->read_global_comments( \@lines, '#' );
59              
60 8         45 my @assoc = $self->associates_comments_with_data( \@lines, '#' );
61 8         34 foreach my $item (@assoc) {
62 26         76 my ( $data, $c ) = @$item;
63 26         200 my ($k,$v) = split /\s*=\s*/, $data, 2; # make reader quite tolerant
64 26         177 $v =~ s/^["']|["']$//g;
65 26 50       105 if ($logger->is_debug) {
66 0         0 my $msg = "Loading key '$k' value '$v'";
67 0 0       0 $msg .= " comment: '$c'" if $c;
68 0         0 $logger->debug($msg);
69             }
70 26         270 $self->tracker->register_element($k);
71 26         496 my $obj = $self->node->fetch_element($k);
72 26         111 $obj->store( value => $v, check => $check );
73 26 100       104 $obj->annotation($c) if $c;
74             }
75              
76 8         74 return 1;
77             }
78              
79             sub write {
80 7     7 1 21 my $self = shift;
81 7         41 my %args = @_;
82              
83             # args are:
84             # object => $obj, # Config::Model::Node object
85             # root => './my_test', # fake root directory, userd for tests
86             # config_dir => /etc/foo', # absolute path
87             # file => 'foo.conf', # file name
88             # file_path => './my_test/etc/foo/foo.conf'
89             # check => yes|no|skip
90              
91 7         22 my $node = $args{object};
92              
93 7         23 my @to_write;
94              
95             # Using Config::Model::ObjTreeScanner would be overkill
96 7         34 foreach my $elt ( $self->get_ordered_element_names ) {
97 49         200 my $obj = $node->fetch_element($elt);
98 49         190 my $v = $node->grab_value($elt);
99              
100 49 100       145 next unless defined $v;
101              
102 25         119 push @to_write, [ qq!$elt="$v"!, $obj->annotation ];
103             }
104              
105 7 50       48 if (@to_write) {
106 7         66 my $res = $self->write_global_comment( '#' );
107 7         49 foreach my $line_ref (@to_write) {
108 25         86 $res .= $self->write_data_and_comments( '#', @$line_ref );
109             }
110 7         52 $args{file_path}->spew_utf8($res);
111             }
112              
113 7         5311 return 1;
114             }
115              
116 3     3   52 no Mouse;
  3         9  
  3         39  
117             __PACKAGE__->meta->make_immutable;
118              
119             1;
120              
121             # ABSTRACT: Read and write config as a C<SHELLVAR> data structure
122              
123             __END__
124              
125             =pod
126              
127             =encoding UTF-8
128              
129             =head1 NAME
130              
131             Config::Model::Backend::ShellVar - Read and write config as a C<SHELLVAR> data structure
132              
133             =head1 VERSION
134              
135             version 2.153
136              
137             =head1 SYNOPSIS
138              
139             use Config::Model;
140              
141             my $model = Config::Model->new;
142             $model->create_config_class (
143             name => "MyClass",
144             element => [
145             [qw/foo bar/] => {qw/type leaf value_type string/}
146             ],
147              
148             rw_config => {
149             backend => 'ShellVar',
150             config_dir => '/tmp',
151             file => 'foo.conf',
152             auto_create => 1,
153             }
154             );
155              
156             my $inst = $model->instance(root_class_name => 'MyClass' );
157             my $root = $inst->config_root ;
158              
159             $root->load('foo=FOO1 bar=BAR1' );
160              
161             $inst->write_back ;
162              
163             File C<foo.conf> now contains:
164              
165             ## This file was written by Config::Model
166             ## You may modify the content of this file. Configuration
167             ## modifications will be preserved. Modifications in
168             ## comments may be mangled.
169             ##
170             foo="FOO1"
171              
172             bar="BAR1"
173              
174             =head1 DESCRIPTION
175              
176             This module is used directly by L<Config::Model> to read or write the
177             content of a configuration tree written with C<SHELLVAR> syntax in
178             C<Config::Model> configuration tree.
179              
180             Note that undefined values are skipped for list element. I.e. if a
181             list element contains C<('a',undef,'b')>, the data structure
182             contains C<'a','b'>.
183              
184             =head1 CONSTRUCTOR
185              
186             =head2 new
187              
188             Parameters: C<< ( node => $node_obj, name => 'shellvar' ) >>
189              
190             Inherited from L<Config::Model::Backend::Any>. The constructor is
191             called by L<Config::Model::BackendMgr>.
192              
193             =head2 read
194              
195             Of all parameters passed to this read call-back, only C<file_path> is
196             used.
197              
198             When a file is read, C<read> returns 1.
199              
200             =head2 write
201              
202             Of all parameters passed to this write call-back, only C<file_path> is
203             used.
204              
205             C<write> returns 1.
206              
207             =head1 AUTHOR
208              
209             Dominique Dumont, (ddumont at cpan dot org)
210              
211             =head1 SEE ALSO
212              
213             L<Config::Model>,
214             L<Config::Model::BackendMgr>,
215             L<Config::Model::Backend::Any>,
216              
217             =head1 AUTHOR
218              
219             Dominique Dumont
220              
221             =head1 COPYRIGHT AND LICENSE
222              
223             This software is Copyright (c) 2005-2022 by Dominique Dumont.
224              
225             This is free software, licensed under:
226              
227             The GNU Lesser General Public License, Version 2.1, February 1999
228              
229             =cut