source: ProjectBuilder/devel/pb-modules/lib/ProjectBuilder/Conf.pm@ 2250

Last change on this file since 2250 was 2250, checked in by Bruno Cornec, 7 years ago

Doc fixes mostly

File size: 12.8 KB
RevLine 
[405]1#!/usr/bin/perl -w
2#
3# ProjectBuilder Conf module
4# Conf files subroutines brought by the the Project-Builder project
5# which can be easily used by wahtever perl project
6#
[2032]7# Copyright B. Cornec 2007-2016
[1528]8# Eric Anderson's changes are (c) Copyright 2012 Hewlett Packard
9# Provided under the GPL v2
10#
[405]11# $Id$
12#
13
14package ProjectBuilder::Conf;
15
16use strict;
[1507]17use Carp 'confess';
[405]18use Data::Dumper;
19use ProjectBuilder::Base;
[1148]20use ProjectBuilder::Version;
[2241]21#use YAML;
[405]22
23# Inherit from the "Exporter" module which handles exporting functions.
24
[2241]25use vars qw($VERSION $REVISION @ISA @EXPORT);
[405]26use Exporter;
27
28# Export, by default, all the functions into the namespace of
29# any code which uses this module.
30
31our @ISA = qw(Exporter);
[2154]32our @EXPORT = qw(pb_conf_init pb_conf_add pb_conf_read pb_conf_read_if pb_conf_write pb_conf_get pb_conf_get_if pb_conf_get_all pb_conf_get_hash pb_conf_cache);
[2241]33($VERSION,$REVISION) = pb_version_init();
[405]34
[898]35# Global hash of conf files
36# Key is the conf file name
37# Value is its rank
38my %pbconffiles;
[409]39
[1495]40# Global hash of conf file content
41# Key is the config keyword
42# Value is a hash whose key depends on the nature of the config keyword as documented
43# and value is the confguration value
[898]44# We consider that values can not change during the life of pb
[1495]45my $h = ();
[898]46
[405]47=pod
48
49=head1 NAME
50
51ProjectBuilder::Conf, part of the project-builder.org - module dealing with configuration files
52
53=head1 DESCRIPTION
54
55This modules provides functions dealing with configuration files.
56
57=head1 SYNOPSIS
58
59 use ProjectBuilder::Conf;
60
61 #
62 # Read hash codes of values from a configuration file and return table of pointers
63 #
64 my ($k1, $k2) = pb_conf_read_if("$ENV{'HOME'}/.pbrc","key1","key2");
65 my ($k) = pb_conf_read("$ENV{'HOME'}/.pbrc","key");
66
67=head1 USAGE
68
[2152]69The configuration files are loaded in a specific order from most generic to the most specific
70to allow for overwrite to work:
71
[2250]72For recent versions of pb (>= 0.15):
731. /usr/share/pb/pb.yml - the read-only system conf file provided by install
742. /etc/pb/pb.yml - the same global conf file given to the sysadmin in order to make system wide modifications
753. /path/to/project.yml - Configuration file for the project we're building for
764. /vm|vepath/to/.pbrc.yml - configuration file for VM, VE or RM specific parameters. Cumulative should be orthogonal
775. $HOME/.pbrc.yml - user's configuration file
78
79For versions of pb up to 0.14:
[2241]801. /usr/share/pb/pb.conf - the read-only system conf file provided by install
812. /etc/pb/pb.conf - the same global conf file given to the sysadmin in order to make system wide modifications
[2152]823. /path/to/project.pb - Configuration file for the project we're building for
834. /(vm|ve|rm)path/to/.pbrc - configuration file for VM, VE or RM specific parameters. Cumulative should be orthogonal
845. $HOME/.pbrc - user's configuration file
85
[2250]86The format of the configuration file is as follows:
87
88For recent versions of pb (>= 0.15):
89YAML format is now used - The version of the configuration files is
90
91Supposing the file is called "$ENV{'HOME'}/.pbrc.yml", containing the following:
92
93 $ cat $HOME/.pbrc.yml
94 ---
95 pbver:
96 - pb: 3
97 - default: 1
98 pblist:
99 - pb: 12,25
100
101calling it like this:
102
103 my ($k1, $k2) = pb_conf_read_if("$ENV{'HOME'}/.pbrc.yml","pbver","pblist");
104
105will allow to get the mapping:
106
107 $k1->{'pb'} contains 3
108 $k1->{'default'} contains 1
109 $k2->{'pb'} contains 12,25
110
111For versions of pb up to 0.14:
112An own format was used - The version of the configuration files is 0
113
114key tag = value1,value2,...
115
116Supposing the file is called "$ENV{'HOME'}/.pbrc", containing the following:
117
118 $ cat $HOME/.pbrc
119 pbver pb = 3
120 pbver default = 1
121 pblist pb = 12,25
122
123calling it like this:
124
125 my ($k1, $k2) = pb_conf_read_if("$ENV{'HOME'}/.pbrc","pbver","pblist");
126
127will allow to get the mapping:
128
129 $k1->{'pb'} contains 3
130 $k1->{'default'} contains 1
131 $k2->{'pb'} contains 12,25
132
133Valid chars for keys and tags are letters, numbers, '-' and '_'.
134
[405]135=over 4
136
[505]137=item B<pb_conf_init>
138
[898]139This function setup the environment PBPROJ for project-builder function usage from other projects.
[505]140The first parameter is the project name.
[898]141It sets up environment variables (PBPROJ)
[505]142
143=cut
144
145sub pb_conf_init {
146
[1907]147my $proj=shift;
[505]148
[1495]149pb_log(1,"Entering pb_conf_init\n");
[1584]150#
151# Check project name
152# Could be with env var PBPROJ
153# or option -p
154# if not defined take the first in conf file
155#
156if ((defined $ENV{'PBPROJ'}) &&
157 (not defined $proj)) {
158 pb_log(2,"PBPROJ env var setup ($ENV{'PBPROJ'}) so using it\n");
159 $proj = $ENV{'PBPROJ'};
160}
161
[505]162if (defined $proj) {
163 $ENV{'PBPROJ'} = $proj;
164} else {
165 $ENV{'PBPROJ'} = "default";
166}
[1495]167pb_log(1,"PBPROJ = $ENV{'PBPROJ'}\n");
[505]168}
169
170
[1495]171=item B<pb_conf_cache>
[505]172
[2250]173This function caches the configuration file content passed as first parameter into the hash passed in second parameter
[1495]174It returns the modified hash
175Can be used in correlation with the %h hash to store permanently values or not if temporarily.
176
177=cut
178
179sub pb_conf_cache {
180
181my $cf = shift;
182my $lh = shift;
183
[2249]184my $ldfunc;
185
[2077]186# Read the content of the config file and cache it in the %h hash then available for queries
[2241]187if ($confver < 0.15) {
[2176]188 open(CONF,$cf) || confess "Unable to open $cf";
189 # This is the original conf file format for versions up to 0.14
190 while(<CONF>) {
191 next if (/^#/);
192 if (/^\s*([A-z0-9-_.]+)\s+([[A-z0-9-_.\?\[\]\*\+\\]+)\s*=\s*(.*)$/) {
193 pb_log(3,"DEBUG: 1:$1 2:$2 3:$3\n");
194 $lh->{$1}->{$2}=$3;
195 }
[1495]196 }
[2176]197 close(CONF);
198} else {
[2249]199 eval {
200 require YAML;
201 YAML->import();
202 };
203 if ($@) {
204 eval {
205 # No YAML found using a more std but less complete one. Old perl only
206 require Module::Build::YAML;
207 Module::Build::YAML->import();
208 };
209 if ($@) {
210 die "Unable to handle YAML configuration files without a YAML.pm module\n";
211 } else {
212 $ldfunc = \&Module::Build::YAML::LoadFile;
213 }
214 } else {
215 $ldfunc = \&YAML::LoadFile;
216 }
217
218 $lh = $ldfunc->($cf);
[1495]219}
220return($lh);
221}
222
[409]223=item B<pb_conf_add>
224
[1495]225This function adds the configuration file to the list last, and cache their content in the %h hash
[409]226
227=cut
228
229sub pb_conf_add {
230
[415]231pb_log(2,"DEBUG: pb_conf_add with ".Dumper(@_)."\n");
[1495]232my $lh;
[898]233
234foreach my $cf (@_) {
[1495]235 if (! -r $cf) {
236 pb_log(0,"WARNING: pb_conf_add can not read $cf\n");
237 next;
238 }
[898]239 # Skip already used conf files
[1495]240 return($lh) if (defined $pbconffiles{$cf});
241
[2154]242 # The new conf file overload values already managed
[898]243 my $num = keys %pbconffiles;
[1495]244 pb_log(2,"DEBUG: pb_conf_cache of $cf at position $num\n");
[898]245 $pbconffiles{$cf} = $num;
[1495]246
247 # Read the content of the config file
248 $lh = pb_conf_cache($cf,$lh);
249 # and cache it in the %h hash for further queries but after the previous
250 # as we load conf files in reverse order (most precise first)
251 pb_conf_add_last_in_hash($lh)
[409]252}
[898]253}
[409]254
[1495]255
[405]256=item B<pb_conf_read_if>
257
258This function returns a table of pointers on hashes
259corresponding to the keys in a configuration file passed in parameter.
260If that file doesn't exist, it returns undef.
261
[1495]262The file read is forgotten after its usage. If you want permanent caching of the data, use pb_conf_add then pb_conf_get
263
[405]264=cut
265
266sub pb_conf_read_if {
267
268my $conffile = shift;
269my @param = @_;
270
271open(CONF,$conffile) || return((undef));
272close(CONF);
273return(pb_conf_read($conffile,@param));
274}
275
276=item B<pb_conf_read>
277
278This function is similar to B<pb_conf_read_if> except that it dies when the file in parameter doesn't exist.
279
280=cut
281
282sub pb_conf_read {
283
284my $conffile = shift;
285my @param = @_;
286my @ptr;
[1495]287my $lh;
[405]288
[1495]289$lh = pb_conf_cache($conffile,$lh);
290
291foreach my $param (@param) {
292 push @ptr,$lh->{$param};
[405]293}
[1495]294return(@ptr);
295}
[405]296
[1904]297=item B<pb_conf_write>
[1495]298
[1904]299This function writes in the file passed ias first parameter the hash of values passed as second parameter
[1495]300
[1904]301=cut
302
303sub pb_conf_write {
304
305my $conffile = shift;
[1905]306my $h = shift;
[2249]307my $dpfunc;
[1904]308
[1905]309confess "No configuration file defined to write into !" if (not defined $conffile);
310confess "No hash defined to read from !" if (not defined $h);
311open(CONF,"> $conffile") || confess "Unable to write into $conffile";
[1904]312
[2241]313if ($confver < 0.15) {
[2176]314 # This is the original conf file format for versions up to 0.14
315 foreach my $p (sort keys %$h) {
316 my $j = $h->{$p};
317 foreach my $k (sort keys %$j) {
318 print CONF "$p $k = $j->{$k}\n";
319 }
[1904]320 }
[2176]321} else {
322 # This is the new YAML format
[2249]323 eval {
324 require YAML;
325 YAML->import();
326 };
327 if ($@) {
328 eval {
329 # No YAML found using a more std but less complete one. Old perl only
330 require Module::Build::YAML;
331 Module::Build::YAML->import();
332 };
333 if ($@) {
334 die "Unable to handle YAML configuration files without a YAML.pm module\n";
335 } else {
336 $dpfunc = \&Module::Build::YAML::Dump;
337 }
338 } else {
339 $dpfunc = \&YAML::Dump;
340 }
341
342 print CONF $dpfunc->($h);
[1904]343}
344close(CONF);
345}
346
347
348
[1495]349=item B<pb_conf_get_in_hash_if>
350
[1594]351This function returns a table, corresponding to a set of values queried in the hash passed in parameter or undef if it doesn't exist.
352It takes a table of keys as an input parameter.
[1495]353
354=cut
355
356sub pb_conf_get_in_hash_if {
357
358my $lh = shift || return(());
359my @params = @_;
360my @ptr = ();
361
362pb_log(2,"DEBUG: pb_conf_get_in_hash_if on params ".join(' ',@params)."\n");
363foreach my $k (@params) {
364 push @ptr,$lh->{$k};
[405]365}
[1495]366
367pb_log(2,"DEBUG: pb_conf_get_in_hash_if returns\n".Dumper(@ptr));
[405]368return(@ptr);
369}
370
[1495]371
372
[409]373=item B<pb_conf_get_if>
[405]374
[1495]375This function returns a table, corresponding to a set of values queried in the %h hash or undef if it doen't exist. It takes a table of keys as an input parameter.
[405]376
[409]377=cut
378
379sub pb_conf_get_if {
380
[2154]381my @param = @_;
382my @return = pb_conf_get_in_hash_if($h,@_);
383my $proj = undef;
384
385if (not defined $ENV{'PBPROJ'}) {
386 $proj = "unknown";
387} else {
388 $proj = $ENV{'PBPROJ'};
[405]389}
[409]390
[2154]391foreach my $i (0..$#param) {
392 if (not defined $return[$i]->{$proj}) {
393 $return[$i]->{$proj} = $return[$i]->{'default'} if (defined $return[$i]->{'default'});
394 }
395}
396return(@return);
397}
398
[1495]399=item B<pb_conf_add_last_in_hash>
[405]400
[1495]401This function merges the values passed in the hash parameter into the %h hash, but only if itdoesn't already contain a value, or if the value is more precise (real value instead of default)
[405]402
[1495]403It is used internally by pb_conf_add and is not exported.
[409]404
405=cut
406
[1495]407sub pb_conf_add_last_in_hash {
[409]408
[1907]409my $ptr = shift;
[409]410
[1495]411return if (not defined $ptr);
412# TODO: test $ptr is a hash pointer
[405]413
[1509]414# When called without correct initialization, try to work anyway with default as project
415pb_conf_init("default") if (not defined $ENV{'PBPROJ'});
416
[1495]417my @params = (sort keys %$ptr);
[405]418
[1495]419# Everything is returned via @h
420# @h contains the values overloading what @ptr may contain.
[2154]421my @h = pb_conf_get_in_hash_if($h,@params);
[1495]422my @ptr = pb_conf_get_in_hash_if($ptr,@params);
[409]423
[405]424my $p1;
425my $p2;
426
[1495]427pb_log(2,"DEBUG: pb_conf_add_last_in_hash params: ".Dumper(@params)."\n");
[2154]428pb_log(2,"DEBUG: pb_conf_add_last_in_hash current hash: ".Dumper(@h)."\n");
429pb_log(2,"DEBUG: pb_conf_add_last_in_hash new inputs: ".Dumper(@ptr)."\n");
[405]430
[1495]431foreach my $i (0..$#params) {
432 $p1 = $h[$i];
433 $p2 = $ptr[$i];
[2154]434 # Always try to take the param from h in priority
[1495]435 # in order to mask what could be defined already in ptr
[405]436 if (not defined $p2) {
[415]437 # exit if no p1 either
[1509]438 next if (not defined $p1);
[405]439 } else {
[409]440 # Ref found in p2
[405]441 if (not defined $p1) {
[409]442 # No ref in p1 so use p2's value
[405]443 $p1 = $p2;
444 } else {
445 # Both are defined - handling the overloading
[2154]446 # Now copy back into p1 all p2 content
447 # as p1 content always has priority over p2
[405]448 if (not defined $p1->{$ENV{'PBPROJ'}}) {
449 if (defined $p2->{$ENV{'PBPROJ'}}) {
[1594]450 $p1->{$ENV{'PBPROJ'}} = $p2->{$ENV{'PBPROJ'}};
[405]451 }
452 }
453 # Now copy back into p1 all p2 content which doesn't exist in p1
[2154]454 # # p1 content always has priority over p2
[405]455 foreach my $k (keys %$p2) {
456 $p1->{$k} = $p2->{$k} if (not defined $p1->{$k});
457 }
458 }
459 }
[1495]460 $h->{$params[$i]} = $p1;
[405]461}
[1495]462pb_log(2,"DEBUG: pb_conf_add_last_in_hash output: ".Dumper($h)."\n");
[405]463}
464
[409]465=item B<pb_conf_get>
[405]466
[409]467This function is the same B<pb_conf_get_if>, except that it tests each returned value as they need to exist in that case.
468
469=cut
470
471sub pb_conf_get {
472
473my @param = @_;
474my @return = pb_conf_get_if(@param);
[932]475my $proj = undef;
[409]476
[932]477if (not defined $ENV{'PBPROJ'}) {
478 $proj = "unknown";
479} else {
480 $proj = $ENV{'PBPROJ'};
481}
[409]482
[1538]483confess "No params found for $proj" if (not @return);
[932]484
[409]485foreach my $i (0..$#param) {
[1507]486 confess "No $param[$i] defined for $proj" if (not defined $return[$i]);
[409]487}
488return(@return);
489}
490
[1495]491
[1694]492=item B<pb_conf_get_all>
493
[2077]494This function returns an array with all configuration parameters
[1694]495
496=cut
497
498sub pb_conf_get_all {
499
500return(sort keys %$h);
501}
502
[2077]503
504=item B<pb_conf_get_hash>
505
506This function returns a pointer to the hash with all configuration parameters
507
508=cut
509
510sub pb_conf_get_hash {
511
512return($h);
513}
514
[405]515=back
516
517=head1 WEB SITES
518
519The main Web site of the project is available at L<http://www.project-builder.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
520
521=head1 USER MAILING LIST
522
523None exists for the moment.
524
525=head1 AUTHORS
526
527The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
528
529=head1 COPYRIGHT
530
531Project-Builder.org is distributed under the GPL v2.0 license
532described in the file C<COPYING> included with the distribution.
533
534=cut
535
536
5371;
Note: See TracBrowser for help on using the repository browser.