line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Config::Source;
|
2
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
98827
|
use 5.14.0;
|
|
5
|
|
|
|
|
20
|
|
|
5
|
|
|
|
|
510
|
|
4
|
5
|
|
|
5
|
|
27
|
use strict;
|
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
181
|
|
5
|
|
|
|
|
|
|
|
6
|
5
|
|
|
5
|
|
27
|
use warnings FATAL => 'all';
|
|
5
|
|
|
|
|
35
|
|
|
5
|
|
|
|
|
243
|
|
7
|
|
|
|
|
|
|
|
8
|
5
|
|
|
5
|
|
26
|
use List::Util 1.35 qw( any none );
|
|
5
|
|
|
|
|
135
|
|
|
5
|
|
|
|
|
639
|
|
9
|
|
|
|
|
|
|
|
10
|
5
|
|
|
5
|
|
33
|
use Carp qw( croak );
|
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
7748
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 NAME
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Config::Source - manage a configuration from multiple sources
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 VERSION
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Version 0.08
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=cut
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
our $VERSION = '0.08';
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
use Config::Source;
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $config = Config::Source->new;
|
29
|
|
|
|
|
|
|
$config->add_source( get_default_config() );
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# override values from the default keys with
|
32
|
|
|
|
|
|
|
$config->add_source( File::Spec->catfile( $HOME, '.application', 'config' ) );
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# and now with
|
35
|
|
|
|
|
|
|
$config->add_source( '/etc/application.config' );
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
my $value = $config->get( 'user.key' );
|
38
|
|
|
|
|
|
|
$config->set( 'user.key' => $value );
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
$config->save_file( File::Spec->catfile( $HOME, '.application', 'config' ) );
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub get_default_config {
|
43
|
|
|
|
|
|
|
return {
|
44
|
|
|
|
|
|
|
'app.name' => '...',
|
45
|
|
|
|
|
|
|
'app.version' => 1,
|
46
|
|
|
|
|
|
|
'user.key' => 'test',
|
47
|
|
|
|
|
|
|
'user.array' => [ 200, 300 ],
|
48
|
|
|
|
|
|
|
'user.deeper.struct' => { a => 'b', c => [ 'd', 'e' ] },
|
49
|
|
|
|
|
|
|
};
|
50
|
|
|
|
|
|
|
}
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
This module allows defining and loading multiple sources to generate a configuration.
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Sometimes you want a configuration initially provided by your application, but partially or
|
57
|
|
|
|
|
|
|
fully redefined at multiple locations. You can have a default configuration
|
58
|
|
|
|
|
|
|
distributed with your program and under your control as developer.
|
59
|
|
|
|
|
|
|
On the first startup you want to generate a user configuration file to
|
60
|
|
|
|
|
|
|
store individual relevant data. And for the administration, you want to provide a
|
61
|
|
|
|
|
|
|
central configuration file indented to specify shared resources. You may also
|
62
|
|
|
|
|
|
|
want a file which is only loaded on debug sessions.
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
This module uses Perl data structures for representing your configuration. It can also assure,
|
65
|
|
|
|
|
|
|
that you only work with a true copy of the data.
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head1 CONFIGURATION FILE
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
Your configuration file must simply return an hash with the last
|
70
|
|
|
|
|
|
|
evaluated statement. Additionally, you can use all the perl code you want.
|
71
|
|
|
|
|
|
|
But this code is discarded if you save your config back.
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
This module proposes a flat hash for storing your configuration. It treats
|
74
|
|
|
|
|
|
|
everything behind the first level of keys as a value.
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
instead of writing:
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
{
|
79
|
|
|
|
|
|
|
'log' => {
|
80
|
|
|
|
|
|
|
'file' => 'path',
|
81
|
|
|
|
|
|
|
'level' => 'DEBUG',
|
82
|
|
|
|
|
|
|
},
|
83
|
|
|
|
|
|
|
}
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
you should write:
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
{
|
88
|
|
|
|
|
|
|
'log.file' => 'path,
|
89
|
|
|
|
|
|
|
'log.level' => 'DEBUG',
|
90
|
|
|
|
|
|
|
}
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
Of course, you can use any separator in the string you want.
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
If you want get a more hierarchical access, take a look at
|
95
|
|
|
|
|
|
|
Config::Source::Hierarchical (not implemented, currently only a throught).
|
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=head1 METHODS
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=head2 new( parameter => value, ... )
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
All the following parameter are optional.
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=over 4
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=item C
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
If true, then every time you try to C a ref-data, a clone will performed,
|
108
|
|
|
|
|
|
|
before returning it. Default is false.
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=item C
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
If true, then every time you try to C a ref-data, a clone will performed,
|
113
|
|
|
|
|
|
|
before assign it to the key. Default is true.
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=back
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=cut
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub new {
|
120
|
6
|
|
|
6
|
1
|
1406
|
my ( $class, %p ) = @_;
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# be sure, a clone module is set
|
123
|
6
|
100
|
|
|
|
69
|
$class->import if not $class->can( 'clone' );
|
124
|
|
|
|
|
|
|
|
125
|
6
|
|
|
|
|
19
|
my $this = bless {}, $class;
|
126
|
|
|
|
|
|
|
|
127
|
6
|
|
50
|
|
|
62
|
$this->{clone_get} = $p{clone_get} // 0;
|
128
|
6
|
|
50
|
|
|
44
|
$this->{clone_set} = $p{clone_set} // 1;
|
129
|
|
|
|
|
|
|
|
130
|
6
|
|
|
|
|
24
|
return $this;
|
131
|
|
|
|
|
|
|
}
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head2 add_source( source, parameter => value, ... )
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Loads the given source. This can either be a filepath, a hashref or a scalarref.
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
The following parameter are supportet:
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=over 4
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item C
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
If you want to exclude some keys from loading from the given source, you can pass
|
144
|
|
|
|
|
|
|
a arrayref with these keys or regexes.
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
$config->add_source( $source, discard => [ 'key.to.remove', qr/^match/ ] );
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item C
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
Discard all keys, which are not currently loaded by the configuration. Default is false
|
151
|
|
|
|
|
|
|
for the first source you want to load and true for each subsequent one. Keys matched
|
152
|
|
|
|
|
|
|
by C will always be discarded.
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item C
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Takes a reference to a list of keys or regular expressions for merging. Keys matched
|
157
|
|
|
|
|
|
|
by C will always be discarded.
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
I
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=back
|
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=cut
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub add_source {
|
166
|
10
|
|
|
10
|
1
|
1887
|
my ( $this, $source, %p ) = @_;
|
167
|
|
|
|
|
|
|
|
168
|
10
|
|
100
|
|
|
44
|
$p{discard_additional_keys} //= 1;
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# load the source into a hashref
|
171
|
10
|
|
|
|
|
30
|
my $hash = $this->_load_source( $source );
|
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# delete keys from discard
|
174
|
10
|
100
|
|
|
|
32
|
if ( $p{discard} ) {
|
175
|
1
|
|
|
|
|
4
|
for my $key ( keys %$hash ) {
|
176
|
5
|
100
|
|
9
|
|
12
|
delete $hash->{ $key } if any { $key =~ $_ } @{ $p{discard} };
|
|
9
|
|
|
|
|
73
|
|
|
5
|
|
|
|
|
20
|
|
177
|
|
|
|
|
|
|
}
|
178
|
|
|
|
|
|
|
}
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# always alias
|
181
|
|
|
|
|
|
|
# if currently no config
|
182
|
10
|
100
|
|
|
|
29
|
if ( not defined $this->{_} ) {
|
183
|
6
|
|
|
|
|
11
|
$this->{_} = $hash;
|
184
|
6
|
|
|
|
|
22
|
return $this;
|
185
|
|
|
|
|
|
|
}
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
# delete additional key
|
188
|
|
|
|
|
|
|
# if they should discarded
|
189
|
|
|
|
|
|
|
# and always override the keys
|
190
|
4
|
100
|
|
|
|
11
|
if ( $p{discard_additional_keys} ) {
|
191
|
2
|
|
|
|
|
8
|
while ( my ( $key, $value ) = each %$hash ) {
|
192
|
7
|
100
|
|
|
|
28
|
$this->{_}{ $key } = $value
|
193
|
|
|
|
|
|
|
if exists $this->{_}{ $key };
|
194
|
|
|
|
|
|
|
}
|
195
|
|
|
|
|
|
|
}
|
196
|
|
|
|
|
|
|
else {
|
197
|
2
|
|
|
|
|
7
|
while ( my ( $key, $value ) = each %$hash ) {
|
198
|
7
|
|
|
|
|
21
|
$this->{_}{ $key } = $value;
|
199
|
|
|
|
|
|
|
}
|
200
|
|
|
|
|
|
|
}
|
201
|
|
|
|
|
|
|
|
202
|
4
|
|
|
|
|
16
|
return $this;
|
203
|
|
|
|
|
|
|
}
|
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=head2 get( key )
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
Returns the value for the given key.
|
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Dies if the key is not found.
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=cut
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub get {
|
214
|
10
|
|
|
10
|
1
|
757
|
my ( $this, $key ) = @_;
|
215
|
|
|
|
|
|
|
|
216
|
10
|
50
|
66
|
|
|
46
|
if ( ref $this->{_}{ $key } and $this->{clone_get} ) {
|
217
|
0
|
|
|
|
|
0
|
return clone( $this->{_}{ $key } );
|
218
|
|
|
|
|
|
|
}
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
return
|
221
|
10
|
50
|
|
|
|
78
|
exists( $this->{_}{ $key } )
|
222
|
|
|
|
|
|
|
? $this->{_}{ $key }
|
223
|
|
|
|
|
|
|
: croak "config key: $key does not exist"
|
224
|
|
|
|
|
|
|
;
|
225
|
|
|
|
|
|
|
}
|
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head2 set( key => value )
|
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
Set the key to the given value.
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Dies if the key not exists.
|
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Before setting deep data structures a copy with clone is performed by default.
|
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=cut
|
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub set {
|
238
|
5
|
|
|
5
|
1
|
49
|
my ( $this, $key, $value ) = @_;
|
239
|
|
|
|
|
|
|
|
240
|
5
|
50
|
|
|
|
12
|
if ( $this->exists( $key ) ) {
|
241
|
5
|
100
|
66
|
|
|
20
|
if ( ref $value and $this->{clone_set} ) {
|
242
|
1
|
|
|
|
|
64
|
$this->{_}{ $key } = clone( $value );
|
243
|
|
|
|
|
|
|
} else {
|
244
|
4
|
|
|
|
|
7
|
$this->{_}{ $key } = $value;
|
245
|
|
|
|
|
|
|
}
|
246
|
|
|
|
|
|
|
} else {
|
247
|
0
|
|
|
|
|
0
|
croak "key does not exist: $key";
|
248
|
|
|
|
|
|
|
}
|
249
|
|
|
|
|
|
|
|
250
|
5
|
|
|
|
|
13
|
1;
|
251
|
|
|
|
|
|
|
}
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=head2 exists( key )
|
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
Return true, if the key exists. False otherwise.
|
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=cut
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub exists {
|
261
|
12
|
|
|
12
|
1
|
31
|
my ( $this, $key ) = @_;
|
262
|
|
|
|
|
|
|
|
263
|
12
|
100
|
|
|
|
54
|
return 1 if exists $this->{_}{ $key };
|
264
|
4
|
|
|
|
|
18
|
return 0;
|
265
|
|
|
|
|
|
|
}
|
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=head2 keys( regex )
|
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
Returns all matching keys in sorted order, so you can
|
270
|
|
|
|
|
|
|
easily iterate over it.
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
If Regex is omitted, all keys are returned.
|
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=cut
|
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub keys {
|
277
|
1
|
|
|
1
|
1
|
2
|
my ( $this, $regex ) = @_;
|
278
|
|
|
|
|
|
|
|
279
|
1
|
50
|
|
|
|
4
|
return sort keys %{ $this->{_} } if not defined $regex;
|
|
0
|
|
|
|
|
0
|
|
280
|
1
|
|
|
|
|
1
|
return sort grep { /$regex/ } keys %{ $this->{_} };
|
|
7
|
|
|
|
|
28
|
|
|
1
|
|
|
|
|
4
|
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=head2 reset( key, source )
|
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
Resets the given key to the value in the given configs.
|
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
Dies, if the key is not found either in the current config, or the source.
|
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=cut
|
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
sub reset {
|
292
|
3
|
|
|
3
|
1
|
69
|
my ( $this, $key, $source ) = @_;
|
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# SMELL: hm... can we optimize this?
|
295
|
|
|
|
|
|
|
# there possible a double clone!
|
296
|
3
|
|
|
|
|
7
|
my $hash = $this->_load_source( $source );
|
297
|
|
|
|
|
|
|
|
298
|
3
|
50
|
|
|
|
10
|
croak "key does not exist in source: $key"
|
299
|
|
|
|
|
|
|
if not exists $hash->{ $key };
|
300
|
|
|
|
|
|
|
|
301
|
3
|
|
|
|
|
8
|
$this->set( $key, $hash->{ $key } );
|
302
|
|
|
|
|
|
|
|
303
|
3
|
|
|
|
|
17
|
1;
|
304
|
|
|
|
|
|
|
}
|
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head2 getall( parameter => value )
|
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Returns a cloned copy from the configuration hash. This is a hashref.
|
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
You can restrict the given keys with the following parameters:
|
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=over 4
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=item C
|
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
Arrayref with keys or regular expressions. Only the matched keys from the configuration will saved.
|
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=item C
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
Arrayref with keys or regular expressions. All matched keys will excluded from saving.
|
321
|
|
|
|
|
|
|
Keys matched by include and exclude will excluded.
|
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=back
|
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=cut
|
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub getall {
|
328
|
9
|
|
|
9
|
1
|
28
|
my ( $this, %p ) = @_;
|
329
|
|
|
|
|
|
|
|
330
|
9
|
|
|
|
|
335
|
my $hash = clone( $this->{_} );
|
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# i use alway a tmp hash - because key should not
|
333
|
|
|
|
|
|
|
# deleted in a loop around the hash
|
334
|
9
|
100
|
|
|
|
27
|
if ( $p{include} ) {
|
335
|
|
|
|
|
|
|
|
336
|
2
|
|
|
|
|
3
|
my $tmp_hash;
|
337
|
|
|
|
|
|
|
|
338
|
2
|
|
|
|
|
8
|
while ( my ( $key, $value ) = each %$hash ) {
|
339
|
12
|
100
|
|
17
|
|
24
|
if ( any { $key =~ $_ } @{ $p{include} } ) {
|
|
17
|
|
|
|
|
111
|
|
|
12
|
|
|
|
|
36
|
|
340
|
6
|
|
|
|
|
27
|
$tmp_hash->{ $key } = $value;
|
341
|
|
|
|
|
|
|
}
|
342
|
|
|
|
|
|
|
}
|
343
|
|
|
|
|
|
|
|
344
|
2
|
|
|
|
|
3
|
$hash = $tmp_hash;
|
345
|
|
|
|
|
|
|
}
|
346
|
|
|
|
|
|
|
|
347
|
9
|
100
|
|
|
|
26
|
if ( $p{exclude} ) {
|
348
|
|
|
|
|
|
|
|
349
|
2
|
|
|
|
|
17
|
my $tmp_hash;
|
350
|
|
|
|
|
|
|
|
351
|
2
|
|
|
|
|
9
|
while( my ( $key, $value ) = each %$hash ) {
|
352
|
11
|
100
|
|
21
|
|
27
|
if ( none { $key =~ $_ } @{ $p{exclude} } ) {
|
|
21
|
|
|
|
|
163
|
|
|
11
|
|
|
|
|
24
|
|
353
|
2
|
|
|
|
|
10
|
$tmp_hash->{ $key } = $value;
|
354
|
|
|
|
|
|
|
}
|
355
|
|
|
|
|
|
|
}
|
356
|
|
|
|
|
|
|
|
357
|
2
|
|
|
|
|
4
|
$hash = $tmp_hash;
|
358
|
|
|
|
|
|
|
}
|
359
|
|
|
|
|
|
|
|
360
|
9
|
|
|
|
|
50
|
return $hash;
|
361
|
|
|
|
|
|
|
}
|
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
=head2 save_file( file, paramter => value, ... )
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
Saves the configuration to the given file.
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
Dies if no file spezified.
|
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
You can restrict the saved keys with the same parameters specified in C.
|
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=cut
|
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
sub save_file {
|
374
|
1
|
|
|
1
|
1
|
20
|
my ( $this, $file, %p ) = @_;
|
375
|
|
|
|
|
|
|
|
376
|
1
|
50
|
|
|
|
3
|
croak 'No user file spezified' if not $file;
|
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
# a little bit optimised ;) - but fragile base class!
|
379
|
1
|
50
|
33
|
|
|
7
|
my $hash = ( $p{include} or $p{exclude} )
|
380
|
|
|
|
|
|
|
? $this->getall( %p )
|
381
|
|
|
|
|
|
|
: $this->{_}
|
382
|
|
|
|
|
|
|
;
|
383
|
|
|
|
|
|
|
|
384
|
1
|
|
|
|
|
2800
|
require Data::Dumper;
|
385
|
|
|
|
|
|
|
|
386
|
1
|
|
|
|
|
14828
|
my $dumper = Data::Dumper->new( [ $hash ] );
|
387
|
1
|
|
|
|
|
51
|
$dumper->Useperl( 1 );
|
388
|
1
|
|
|
|
|
19
|
$dumper->Terse( 1 );
|
389
|
1
|
|
|
|
|
10
|
$dumper->Sortkeys( 1 );
|
390
|
|
|
|
|
|
|
|
391
|
1
|
50
|
|
|
|
183
|
open my $fh, '>', $file or croak $!;
|
392
|
1
|
|
|
|
|
7
|
print $fh $dumper->Dump;
|
393
|
1
|
|
|
|
|
1441
|
close $fh;
|
394
|
|
|
|
|
|
|
|
395
|
1
|
|
|
|
|
22
|
1;
|
396
|
|
|
|
|
|
|
}
|
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=head1 INTERNAL METHODS
|
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=head2 _load_source
|
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=cut
|
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
sub _load_source {
|
405
|
13
|
|
|
13
|
|
20
|
my ( $this, $source ) = @_;
|
406
|
|
|
|
|
|
|
|
407
|
13
|
100
|
|
|
|
45
|
if ( ref $source eq 'HASH' ) {
|
|
|
50
|
|
|
|
|
|
408
|
6
|
|
|
|
|
575
|
return clone( $source );
|
409
|
|
|
|
|
|
|
}
|
410
|
|
|
|
|
|
|
elsif ( ref $source eq 'SCALAR' ) {
|
411
|
0
|
|
|
|
|
0
|
return eval $$source;
|
412
|
0
|
0
|
|
|
|
0
|
croak "error parsing scalar source: $@" if $@;
|
413
|
|
|
|
|
|
|
}
|
414
|
|
|
|
|
|
|
else {
|
415
|
7
|
50
|
|
|
|
316
|
open my $fh, '<', $source or croak "error opening $source: $!";
|
416
|
7
|
|
|
|
|
10
|
my $hash = eval do { local $/; <$fh> };
|
|
7
|
|
|
|
|
21
|
|
|
7
|
|
|
|
|
594
|
|
417
|
7
|
50
|
|
|
|
26
|
croak "error parsing $source: $@" if $@;
|
418
|
|
|
|
|
|
|
|
419
|
7
|
|
|
|
|
99
|
return $hash;
|
420
|
|
|
|
|
|
|
}
|
421
|
|
|
|
|
|
|
}
|
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=head1 ACCESSORS
|
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
=over 4
|
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
=item C
|
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
=item C
|
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=back
|
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=cut
|
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
# Code partly inspired from Object::Tiny and Object Tiny::RW
|
436
|
0
|
0
|
|
0
|
1
|
0
|
sub clone_get { if ( @_ > 1 ) { $_[0]->{clone_get} = $_[1] } ; return $_[0]->{clone_get} }
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
437
|
0
|
0
|
|
0
|
1
|
0
|
sub clone_set { if ( @_ > 1 ) { $_[0]->{clone_set} = $_[1] } ; return $_[0]->{clone_set} }
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=head1 CLONING
|
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
You can change the cloning implementation with a package parameter:
|
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
use Data::Clone;
|
444
|
|
|
|
|
|
|
use Config::Source clone => \&Data::Clone::clone;
|
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
Or change it at any time with the class method C. The default
|
447
|
|
|
|
|
|
|
implementation is Storables dclone.
|
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=cut
|
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
sub import {
|
452
|
5
|
|
|
5
|
|
33
|
my ( $class, %p ) = @_;
|
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
my $sub = ref $p{clone} eq 'CODE'
|
455
|
|
|
|
|
|
|
? $p{clone}
|
456
|
5
|
50
|
|
|
|
22
|
: do { require Storable; \&Storable::dclone }
|
|
5
|
|
|
|
|
5436
|
|
|
5
|
|
|
|
|
19103
|
|
457
|
|
|
|
|
|
|
;
|
458
|
|
|
|
|
|
|
|
459
|
5
|
|
|
5
|
|
40
|
no strict 'refs';
|
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
455
|
|
460
|
5
|
|
|
|
|
12
|
*{__PACKAGE__ . '::clone'} = $sub;
|
|
5
|
|
|
|
|
3821
|
|
461
|
|
|
|
|
|
|
}
|
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=head1 OTHER FILE FORMATS
|
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
Most of the config modules out there can return a simple hash
|
466
|
|
|
|
|
|
|
of the configuration. The following example shows how
|
467
|
|
|
|
|
|
|
to read a default configuration and a user configuration
|
468
|
|
|
|
|
|
|
with Config::General, as well as the saving of the
|
469
|
|
|
|
|
|
|
configuration file back.
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
use Config::General;
|
472
|
|
|
|
|
|
|
use Config::Source;
|
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
my %default = Config::General->new( 'default_location' )->getall;
|
475
|
|
|
|
|
|
|
my %user = Config::General->new( 'user_location' ) ->getall;
|
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
my $config = Config::Source->new
|
478
|
|
|
|
|
|
|
->add_source( \%default )
|
479
|
|
|
|
|
|
|
->add_source( \%user );
|
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
# ...
|
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
my $hash = $config->getall;
|
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
Config::General->new->save_file( 'user_location', $hash );
|
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
Be sure the passed values are unblessed hash references. And know the limitations
|
488
|
|
|
|
|
|
|
of the other modules.
|
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Maybe i add the option to direct load these file formats in a future release.
|
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=head1 AUTHOR
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
Tarek Unger, C<< >>
|
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=head1 BUGS
|
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through
|
499
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll
|
500
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes.
|
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
=head1 SUPPORT
|
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command.
|
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
perldoc Config::Source
|
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
You can also look for information at:
|
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=over 20
|
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker (report bugs here)
|
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
L
|
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation
|
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
L
|
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=item * CPAN Ratings
|
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
L
|
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
=item * Search CPAN
|
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
L
|
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
=item * Repository
|
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
L
|
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
=back
|
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS
|
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT
|
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
Copyright 2013-2014 Tarek Unger.
|
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
547
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published
|
548
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License.
|
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
See L for more information.
|
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=cut
|
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
1; # End of Config::Source
|