source: ProjectBuilder/devel/pb/lib/ProjectBuilder/Base.pm@ 108

Last change on this file since 108 was 108, checked in by Bruno Cornec, 17 years ago

Lots of changes to prepare the dev of the VMs support.
No more global variables
Support $ENV{'HOME'} in pbrc for pbrc keyword (allows portability across accounts and share of .pbrc)
Fixes on pb_cms_export for SVN in order to be called externally
pn_env_init retunrs now a lot of params in a list
pb_get_pkg needs params and is simplified by consequence
pbinit is called with a simple system. pb_system has isues with cascading stdout/stderr redirections
pb_send2ssh now supports sending to VM + launch of a pbscript if it exists and it should bring back packages from VM in the future and it now supports more parameters.

  • Property svn:executable set to *
File size: 12.9 KB
Line 
1#!/usr/bin/perl -w
2#
3# Base subroutines for the Project-Builder project
4#
5# $Id$
6#
7
8use strict;
9use lib qw (lib);
10use File::Basename;
11use File::Path;
12use File::Temp qw /tempdir/;
13use AppConfig qw(ARGCOUNT_HASH);
14use Data::Dumper;
15
16$ENV{'PBETC'} = "$ENV{'HOME'}/.pbrc";
17
18sub pb_env_init {
19
20my $proj=shift;
21my $ver;
22my $tag;
23
24# For the moment not dynamic
25my $debug = 0; # Debug level
26my $LOG = *STDOUT; # Where to log
27
28#
29# Check project name
30# Could be with env var PBPROJ
31# or option -p
32# if not define take the first in conf file
33#
34if ((defined $ENV{'PBPROJ'}) &&
35 (not (defined $proj))) {
36 $proj = $ENV{'PBPROJ'};
37}
38
39#
40# We get the pbrc file for that project
41# and use its content
42#
43my ($pbrc) = pb_conf_read("$ENV{'PBETC'}","pbrc");
44print "DEBUG pbrc: ".Dumper($pbrc)."\n" if ($debug >= 1);
45
46my %pbrc = %$pbrc;
47if (not defined $proj) {
48 # Take the first as the default project
49 $proj = (keys %pbrc)[0];
50 print $LOG "Using $proj as default project as none has been specified\n" if (($debug >= 0) and (defined $proj));
51}
52die "No project defined - use env var PBPROJ or -p proj" if (not (defined $proj));
53
54#
55# Set delivery directory
56#
57my $topdir=dirname($pbrc{$proj});
58# Expand potential env variable in it
59eval { $topdir =~ s/(\$ENV.+\})/$1/eeg };
60chdir $topdir || die "Unable to change directory to $topdir";
61$pbrc{$proj} = $topdir."/pbrc";
62$ENV{'PBDESTDIR'}=$topdir."/delivery";
63
64#
65# Use project configuration file if needed
66#
67if (not defined $ENV{'PBROOT'}) {
68 if (-f $pbrc{$proj}) {
69 my ($pbroot) = pb_conf_read($pbrc{$proj},"pbroot");
70 my %pbroot = %$pbroot;
71 # All lines should point to the same pbroot so take the first
72 $ENV{'PBROOT'} = (values %$pbroot)[0] if (defined $pbroot);
73 print $LOG "Using $ENV{'PBROOT'} as default pbroot from $pbrc{$proj}\n" if (($debug >= 0) and (defined $ENV{'PBROOT'}));
74 }
75 die "No pbroot defined - use env var PBROOT or -r pbroot " if (not defined $ENV{'PBROOT'});
76}
77
78#
79# Check pb conf compliance
80#
81$ENV{'PBCONF'} = "$ENV{'PBROOT'}/pbconf";
82die "Project $proj not Project-Builder compliant. Please populate $ENV{'PBCONF'}" if ( not -d "$ENV{'PBCONF'}");
83
84my %version = ();
85my %defpkgdir = ();
86my %extpkgdir = ();
87my %filteredfiles = ();
88
89if (-f "$ENV{'PBCONF'}/$proj.pb") {
90 # List of pkg to build by default (mandatory)
91 # List of additional pkg to build when all is called (optional)
92 # Valid version names (optional)
93 # List of files to filter (optional)
94 my ($defpkgdir, $extpkgdir, $version, $filteredfiles, $pkgv, $pkgt) = pb_conf_read("$ENV{'PBCONF'}/$proj.pb","defpkgdir","extpkgdir","version","filteredfiles","projver","projtag");
95 print "DEBUG: defpkgdir: ".Dumper($defpkgdir)."\n" if ($debug >= 1);
96 print "DEBUG: extpkgdir: ".Dumper($extpkgdir)."\n" if ($debug >= 1);
97 print "DEBUG: version: ".Dumper($version)."\n" if ($debug >= 1);
98 print "DEBUG: filteredfiles: ".Dumper($filteredfiles)."\n" if ($debug >= 1);
99 die "Unable to find defpkgdir in $ENV{'PBCONF'}/$proj.pb" if (not defined $defpkgdir);
100 # Global
101 %defpkgdir = %$defpkgdir;
102 # Global
103 %extpkgdir = %$defpkgdir if (defined $defpkgdir);
104 %version = %$version if (defined $version);
105 # Global
106 %filteredfiles = %$filteredfiles if (defined $filteredfiles);
107 #
108 # Get global Version/Tag
109 #
110
111 if (not defined $ENV{'PBVER'}) {
112 if ((defined $pkgv) && (defined $pkgv->{$proj})) {
113 $ENV{'PBVER'}=$pkgv->{$proj};
114 } else {
115 die "No projver found in $ENV{'PBCONF'}/$proj.pb";
116 }
117 }
118 die "Invalid version name $ENV{'PBVER'} in $ENV{'PBCONF'}/$proj.pb" if (($ENV{'PBVER'} !~ /[0-9.]+/) && (not exists $version{$ENV{'PBVER'}}));
119
120 if (not defined $ENV{'PBTAG'}) {
121 if ((defined $pkgt) && (defined $pkgt->{$proj})) {
122 $ENV{'PBTAG'}=$pkgt->{$proj};
123 } else {
124 die "No projtag found in $ENV{'PBCONF'}/$proj.pb";
125 }
126 }
127 die "Invalid tag name $ENV{'PBTAG'} in $ENV{'PBCONF'}/$proj.pb" if ($ENV{'PBTAG'} !~ /[0-9.]+/);
128} else {
129 die "Unable to open $ENV{'PBCONF'}/$proj.pb";
130}
131
132#
133# Set temp directory
134#
135if (not defined $ENV{'TMPDIR'}) {
136 $ENV{'TMPDIR'}="/tmp";
137}
138$ENV{'PBTMP'} = tempdir( "pb.XXXXXXXXXX", DIR => $ENV{'TMPDIR'}, CLEANUP => 1 );
139
140#
141# Removes all directory existing below the delivery dir
142# as they are temp dir only
143# Files stay and have to be cleaned up manually
144#
145if (-d $ENV{'PBDESTDIR'}) {
146 opendir(DIR,$ENV{'PBDESTDIR'}) || die "Unable to open directory $ENV{'PBDESTDIR'}: $!";
147 foreach my $d (readdir(DIR)) {
148 next if ($d =~ /^\./);
149 next if (-f "$ENV{'PBDESTDIR'}/$d");
150 pb_rm_rf("$ENV{'PBDESTDIR'}/$d") if (-d "$ENV{'PBDESTDIR'}/$d");
151 }
152 closedir(DIR);
153}
154if (! -d "$ENV{'PBDESTDIR'}") {
155 pb_mkdir_p($ENV{'PBDESTDIR'}) || die "Unable to recursively create $ENV{'PBDESTDIR'}";
156}
157
158#
159# Set build directory
160#
161$ENV{'PBBUILDDIR'}=$topdir."/build";
162if (! -d "$ENV{'PBBUILDDIR'}") {
163 pb_mkdir_p($ENV{'PBBUILDDIR'}) || die "Unable to recursively create $ENV{'PBBUILDDIR'}";
164}
165
166umask 0022;
167return($proj,$debug,$LOG,\%pbrc, \%filteredfiles, \%defpkgdir, \%extpkgdir);
168}
169
170# Internal mkdir -p function
171sub pb_mkdir_p {
172my @dir = @_;
173my $ret = mkpath(@dir, 0, 0755);
174return($ret);
175}
176
177# Internal rm -rf function
178sub pb_rm_rf {
179my @dir = @_;
180my $ret = rmtree(@dir, 0, 0);
181return($ret);
182}
183
184# Internal system function
185sub pb_system {
186
187my $cmd=shift;
188my $cmt=shift || $cmd;
189
190print "$cmt... ";
191system("$cmd 2>&1 > $ENV{'PBTMP'}/system.log");
192if ($? == -1) {
193 print "failed to execute ($cmd) : $!\n";
194 pb_display_file("$ENV{'PBTMP'}/system.log");
195} elsif ($? & 127) {
196 printf "child ($cmd) died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without';
197 pb_display_file("$ENV{'PBTMP'}/system.log");
198} elsif ($? == 0) {
199 print "OK\n";
200} else {
201 printf "child ($cmd) exited with value %d\n", $? >> 8;
202 pb_display_file("$ENV{'PBTMP'}/system.log");
203}
204}
205
206sub pb_display_file {
207
208my $file=shift;
209
210open(FILE,"$file") || die "Unable to open $file";
211while (<FILE>) {
212 print $_;
213}
214close(FILE);
215}
216
217# Function which returns a pointer on a hash
218# corresponding to a declaration (arg2) in the main conf file
219# and test the returned vaue as they need to exist in that case
220sub pb_conf_get {
221
222my @param = @_;
223
224my @ptr = pb_conf_read("$ENV{'PBETC'}", @param);
225
226foreach my $i (0..$#param) {
227 die "No $param[$i] defined for $ENV{'PBPROJ'}" if (not defined $ptr[$i]);
228 my $p = $ptr[$i];
229 $p->{$ENV{'PBPROJ'}} = $p->{'default'} if (not defined $p->{$ENV{'PBPROJ'}});
230 die "No $param[$i] defined for $ENV{'PBPROJ'}" if (not defined $p->{$ENV{'PBPROJ'}});
231}
232#print "DEBUG: param: ".Dumper(@ptr)."\n" if ($debug >= 1);
233return(@ptr);
234}
235
236# Function which returns a pointer on a hash
237# corresponding to a declaration (arg2) in a conf file (arg1)
238sub pb_conf_read {
239
240my $conffile = shift;
241my @param = @_;
242my $trace;
243my @ptr;
244
245my $debug = 0;
246
247if ($debug > 0) {
248 $trace = 1;
249} else {
250 $trace = 0;
251}
252
253
254my $config = AppConfig->new({
255 # Auto Create variables mentioned in Conf file
256 CREATE => 1,
257 DEBUG => $trace,
258 GLOBAL => {
259 # Each conf item is a hash
260 ARGCOUNT => ARGCOUNT_HASH,
261 },
262 });
263$config->file($conffile);
264for my $param (@param) {
265 push @ptr,$config->get($param);
266}
267print "DEBUG: params: ".Dumper(@param)." ".Dumper(@ptr)."\n" if ($debug >= 1);
268return(@ptr);
269}
270
271# Setup environment for CMS system
272sub pb_cms_init {
273
274my $proj = shift || undef;
275my $ret;
276
277my ($cms) = pb_conf_get("cms");
278# This one is optional
279my ($cvsroot) = pb_conf_read($ENV{'PBETC'},"cvsroot");
280
281if ($cms->{$proj} eq "svn") {
282 $ENV{'PBREVISION'}=`(cd "$ENV{'PBROOT'}" ; svnversion .)`;
283 chomp($ENV{'PBREVISION'});
284 $ENV{'PBCMSLOG'}="svn log";
285 $ENV{'PBCMSLOGFILE'}="svn.log";
286} elsif ($cms->{$proj} eq "cvs") {
287 # Way too slow
288 #$ENV{'PBREVISION'}=`(cd "$ENV{'PBROOT'}" ; cvs rannotate -f . 2>&1 | awk '{print \$1}' | grep -E '^[0-9]' | cut -d. -f2 |sort -nu | tail -1)`;
289 #chomp($ENV{'PBREVISION'});
290 $ENV{'PBREVISION'}="CVS";
291 $ENV{'PBCMSLOG'}="cvs log";
292 $ENV{'PBCMSLOGFILE'}="cvs.log";
293 #
294 # Export content if needed
295 #
296 $ENV{'CVSROOT'} = $cvsroot->{$proj} if (defined $cvsroot->{$proj});
297} else {
298 die "cms $cms->{$proj} unknown";
299}
300return($cms);
301}
302
303sub pb_cms_export {
304my $cms = shift;
305my $pbdate = shift || undef;
306my $source = shift;
307my $destdir = shift;
308my $tmp;
309
310if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
311 if (-d $source) {
312 $tmp = $destdir;
313 } else {
314 $tmp = $destdir."/".basename($source);
315 }
316 pb_system("svn export $source $tmp","Exporting $source from SVN");
317} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
318 my $dir=dirname($destdir);
319 my $base=basename($destdir);
320 # Doesn't work if called from outside with a full path name to a file/dir to export
321 $tmp=basename($source);
322 # CVS needs a relative path !
323 pb_system("cd $dir ; cvs export -D $pbdate -d $base $tmp","Exporting $source from CVS");
324} else {
325 die "cms $cms->{$ENV{'PBPROJ'}} unknown";
326}
327}
328
329sub pb_cms_log {
330my $cms = shift;
331my $pkgdir = shift;
332my $destfile = shift;
333
334if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
335 pb_system("svn log $pkgdir > $destfile","Extracting log info from SVN");
336} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
337 my $tmp=basename($pkgdir);
338 # CVS needs a relative path !
339 pb_system("cvs log $tmp > $destfile","Extracting log info from CVS");
340} else {
341 die "cms $cms->{$ENV{'PBPROJ'}} unknown";
342}
343}
344
345
346
347# Get all filters to apply
348# They're cumulative from less specific to most specific
349# suffix is .pbf
350
351sub pb_get_filters {
352
353# For the moment not dynamic
354my $debug = 0; # Debug level
355my $LOG = *STDOUT; # Where to log
356
357my @ffiles;
358my ($ffile0, $ffile1, $ffile2, $ffile3);
359my $pbpkg = shift || die "No package specified";
360my $dtype = shift || die "No dtype specified";
361my $dfam = shift || die "No dfam specified";
362my $ddir = shift || die "No ddir specified";
363my $dver = shift || die "No dver specified";
364my $ptr; # returned value pointer on the hash of filters
365my %ptr;
366
367if (-d "$ENV{'PBCONF'}/$pbpkg/pbfilter") {
368 $ffile0 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dtype.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dtype.pbf");
369 $ffile1 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dfam.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dfam.pbf");
370 $ffile2 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir.pbf");
371 $ffile3 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir-$dver.pbf");
372
373 push @ffiles,$ffile0 if (defined $ffile0);
374 push @ffiles,$ffile1 if (defined $ffile1);
375 push @ffiles,$ffile2 if (defined $ffile2);
376 push @ffiles,$ffile3 if (defined $ffile3);
377}
378if (@ffiles) {
379 print $LOG "DEBUG ffiles: ".Dumper(\@ffiles)."\n" if ($debug >= 1);
380
381 my $config = AppConfig->new({
382 # Auto Create variables mentioned in Conf file
383 CREATE => 1,
384 DEBUG => 0,
385 GLOBAL => {
386 # Each conf item is a hash
387 ARGCOUNT => AppConfig::ARGCOUNT_HASH
388 }
389 });
390
391 $config->file(@ffiles);
392 $ptr = $config->get("filter");
393 print $LOG "DEBUG f:".Dumper($ptr)."\n" if ($debug >= 1);
394} else {
395 $ptr = { };
396}
397%ptr = %$ptr;
398return(\%ptr);
399}
400
401# Function which applies filter on files (only for pb)
402sub pb_filter_file_pb {
403
404my $f=shift;
405my $ptr=shift;
406my %filter=%$ptr;
407my $destfile=shift;
408my $dtype=shift;
409my $pbsuf=shift;
410my $pbpkg=shift;
411my $pbver=shift;
412my $pbtag=shift;
413my $pbrev=shift;
414my $pbdate=shift;
415my $defpkgdir = shift;
416my $extpkgdir = shift;
417
418# For the moment not dynamic
419my $debug = 0; # Debug level
420my $LOG = *STDOUT; # Where to log
421
422print $LOG "DEBUG: From $f to $destfile\n" if ($debug >= 1);
423pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
424open(DEST,"> $destfile") || die "Unable to create $destfile";
425open(FILE,"$f") || die "Unable to open $f: $!";
426while (<FILE>) {
427 my $line = $_;
428 foreach my $s (keys %filter) {
429 # Process single variables
430 print $LOG "DEBUG filter{$s}: $filter{$s}\n" if ($debug >= 1);
431 my $tmp = $filter{$s};
432 next if (not defined $tmp);
433 # Expand variables if any single one found
434 print $LOG "DEBUG tmp: $tmp\n" if ($debug >= 1);
435 if ($tmp =~ /\$/) {
436 eval { $tmp =~ s/(\$\w+)/$1/eeg };
437 # special case for ChangeLog only for pb
438 } elsif (($tmp =~ /^yes$/) && ($s =~ /^PBLOG$/) && ($line =~ /^PBLOG$/)) {
439 $tmp = "";
440 my $p = $defpkgdir->{$pbpkg};
441 $p = $extpkgdir->{$pbpkg} if (not defined $p);
442 pb_changelog($dtype, $pbpkg, $pbtag, $pbsuf, $p, \*DEST);
443 }
444 $line =~ s|$s|$tmp|;
445 }
446 print DEST $line;
447}
448close(FILE);
449close(DEST);
450}
451
452# Function which applies filter on files (external call)
453sub pb_filter_file {
454
455my $f=shift;
456my $ptr=shift;
457my %filter=%$ptr;
458my $destfile=shift;
459my $pbsuf=shift;
460my $pbpkg=shift;
461my $pbver=shift;
462my $pbtag=shift;
463my $pbrev=shift;
464my $pbdate=shift;
465
466# For the moment not dynamic
467my $debug = 0; # Debug level
468my $LOG = *STDOUT; # Where to log
469
470print $LOG "DEBUG: From $f to $destfile\n" if ($debug >= 1);
471pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
472open(DEST,"> $destfile") || die "Unable to create $destfile";
473open(FILE,"$f") || die "Unable to open $f: $!";
474while (<FILE>) {
475 my $line = $_;
476 foreach my $s (keys %filter) {
477 # Process single variables
478 print $LOG "DEBUG filter{$s}: $filter{$s}\n" if ($debug > 1);
479 my $tmp = $filter{$s};
480 next if (not defined $tmp);
481 # Expand variables if any single one found
482 if ($tmp =~ /\$/) {
483 eval { $tmp =~ s/(\$\w+)/$1/eeg };
484 }
485 $line =~ s|$s|$tmp|;
486 }
487 print DEST $line;
488}
489close(FILE);
490close(DEST);
491}
492
493
4941;
Note: See TracBrowser for help on using the repository browser.