#!/usr/bin/perl -w # # Project Builder main application # # $Id$ # # Copyright B. Cornec 2007 # Provided under the GPL v2 # Syntax: pb [-p project] [...] use strict; use Switch; use Getopt::Std; use Data::Dumper; use English; use AppConfig qw(:argcount :expand); use File::Basename; use Time::localtime qw(localtime); use POSIX qw(strftime); use lib qw (lib etc); use vars qw (%defpkgdir %extpkgdir %version @filteredfiles); use common qw (env_init); use pb qw (defpkgdir extpkgdir version filteredfiles pb_init); use distro qw (distro_init); use cms; my %opts; # CLI Options my $action; # action to realize my $test = "FALSE"; my $option = ""; my @pkgs; my $pbtag; # Global TAG variable my $pbver; # Global VERSION variable my $pbrev; # GLOBAL REVISION variable my @date=(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst()); my $pbdate = strftime("%Y-%m-%d", @date); getopts('p:t',\%opts); # Handles project name if any if (defined $opts{'p'}) { $ENV{'PBPROJ'} = env_init($opts{'p'}); } else { $ENV{'PBPROJ'} = env_init(); } # Handles test option if (defined $opts{'t'}) { $test = "TRUE"; # Works only for SVN $option = "-r BASE"; } # Get Action $action = shift @ARGV; die "Syntax: pb [-p project] [...]" if (not defined $action); print "Project $ENV{'PBPROJ'}\n"; #print "Action: $action - ARGV:".Dumper(\@ARGV); # Act depending on action if ($action =~ /^cms2build$/) { print "Action: cms2build\n"; # Get packages list if (not defined $ARGV[0]) { @pkgs = keys %defpkgdir; } elsif ($ARGV[0] =~ /^all$/) { @pkgs = keys %defpkgdir; push(@pkgs, keys %extpkgdir); } else { @pkgs = @ARGV; } print "Packages:\n"; print Dumper(@pkgs); cms_init(); foreach my $p (@pkgs) { if (-f "$ENV{'PBROOT'}/$p/VERSION") { open(V,"$ENV{'PBROOT'}/$p/VERSION") || die "Unable to open $ENV{'PBROOT'}/$p/VERSION"; $pbver = ; chomp($pbver); close(V); } else { $pbver = $ENV{'PBVER'}; } if (-f "$ENV{'PBROOT'}/$p/TAG") { open(T,"$ENV{'PBROOT'}/$p/TAG") || die "Unable to open $ENV{'PBROOT'}/$p/TAG"; $pbtag = ; chomp($pbtag); close(T); } else { $pbtag = $ENV{'PBTAG'}; } $pbrev = $ENV{'PBREVISION'}; print "Management of $p $pbver-$pbtag (rev $pbrev)\n"; die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'}); # Clean up dest if necessary. The export will recreate it my $dest = "$ENV{'PBDESTDIR'}/$p-$pbver"; pbrm_rf($dest) if (-d $dest); # Export CMS tree for the concerned package to dest # And generate some additional files $OUTPUT_AUTOFLUSH=1; print "$ENV{'PBCMSEXP'} of $p..."; # computes in which dir we have to work my $dir = $defpkgdir{$p}; $dir = $extpkgdir{$p} if (not defined $dir); system("$ENV{'PBCMSEXP'} $option $ENV{'PBROOT'}/$dir $dest 1>/dev/null"); if ($? == -1) { print "failed to execute: $!\n"; } elsif ($? & 127) { printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; } else { print " Done under $dest\n"; } # Creates a REVISION file open(R,"> $dest/REVISION") || die "Unable to create $dest/REVISION"; print R "$pbrev\n"; close(R); # Extract cms log history and store it system("$ENV{'PBCMSLOG'} $option $ENV{'PBROOT'}/$dir > $dest/$ENV{'PBCMSLOGFILE'}"); print "$ENV{'PBCMSLOG'} of $p..."; if ($? == -1) { print "failed to execute: $!\n"; } elsif ($? & 127) { printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; } else { print " OK\n"; } open(D,"$ENV{'PBCONF'}/DISTROS") || die "Unable to find $ENV{'PBCONF'}/DISTROS\n"; while () { my $d = $_; my ($dir,$ver) = split(/_/,$d); chomp($ver); print "Generating build files for $dir ($ver)\n"; my ($ddir, $dver, $dfam, $dtype, $dsuf) = distro_init($dir,$ver); #print Dumper($ddir, $dver, $dfam, $dtype, $dsuf); #print "Filtering DDD => $pbdate, TTT => $pbtag, RRR => $pbtag$dsuf, VVV => $pbver\n"; # Filter build files from the less precise up to the most with overloading # Filter all files found, keeping the name, and generating in dest # Find all build files first relatively to PBROOT my %bfiles; #print "dir: $ENV{'PBCONF'}/$p\n"; if (-d "$ENV{'PBCONF'}/$p/$dtype") { opendir(BDIR,"$ENV{'PBCONF'}/$p/$dtype" || die "Unable to open dir $ENV{'PBCONF'}/$p/$dtype: $!"); foreach my $f (readdir(BDIR)) { next if ($f =~ /^\./); $bfiles{$f} = "$ENV{'PBCONF'}/$p/$dtype/$f"; $bfiles{$f} =~ s~$ENV{'PBROOT'}~~; } closedir(BDIR); } elsif (-d "$ENV{'PBCONF'}/$p/$dfam") { opendir(BDIR,"$ENV{'PBCONF'}/$p/$dfam" || die "Unable to open dir $ENV{'PBCONF'}/$p/$dfam: $!"); foreach my $f (readdir(BDIR)) { next if ($f =~ /^\./); $bfiles{$f} = "$ENV{'PBCONF'}/$p/$dfam/$f"; $bfiles{$f} =~ s~$ENV{'PBROOT'}~~; } closedir(BDIR); } elsif (-d "$ENV{'PBCONF'}/$p/$ddir") { opendir(BDIR,"$ENV{'PBCONF'}/$p/$ddir" || die "Unable to open dir $ENV{'PBCONF'}/$p/$ddir: $!"); foreach my $f (readdir(BDIR)) { next if ($f =~ /^\./); $bfiles{$f} = "$ENV{'PBCONF'}/$p/$ddir/$f"; $bfiles{$f} =~ s~$ENV{'PBROOT'}~~; } closedir(BDIR); } elsif (-d "$ENV{'PBCONF'}/$p/$ddir-$dver") { opendir(BDIR,"$ENV{'PBCONF'}/$p/$ddir-$dver" || die "Unable to open dir $ENV{'PBCONF'}/$p/$ddir-$dver: $!"); foreach my $f (readdir(BDIR)) { next if ($f =~ /^\./); $bfiles{$f} = "$ENV{'PBCONF'}/$p/$ddir-$dver/$f"; $bfiles{$f} =~ s~$ENV{'PBROOT'}~~; } closedir(BDIR); } else { print "No Build Files found for $ddir-$dver\n"; next; } print "bfiles: ".Dumper(\%bfiles)."\n"; # Get all filters to apply # They're cumulative from less specific to most specific # suffix is .pbf my @ffiles; my ($ffile0, $ffile1, $ffile2, $ffile3); if (-d "$ENV{'PBCONF'}/$p/pbfilter") { $ffile0 = "$ENV{'PBCONF'}/$p/pbfilter/$dtype.pbf" if (-f "$ENV{'PBCONF'}/$p/pbfilter/$dtype.pbf"); $ffile1 = "$ENV{'PBCONF'}/$p/pbfilter/$dfam.pbf" if (-f "$ENV{'PBCONF'}/$p/pbfilter/$dfam.pbf"); $ffile2 = "$ENV{'PBCONF'}/$p/pbfilter/$ddir.pbf" if (-f "$ENV{'PBCONF'}/$p/pbfilter/$ddir.pbf"); $ffile3 = "$ENV{'PBCONF'}/$p/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBCONF'}/$p/pbfilter/$ddir-$dver.pbf"); push @ffiles,$ffile0 if (defined $ffile0); push @ffiles,$ffile1 if (defined $ffile1); push @ffiles,$ffile2 if (defined $ffile2); push @ffiles,$ffile3 if (defined $ffile3); } my $config = AppConfig->new({ # Auto Create variables mentioned in Conf file CREATE => 1, DEBUG => 0, GLOBAL => { # Each conf item is a hash ARGCOUNT => AppConfig::ARGCOUNT_HASH } }); print "ffiles: ".Dumper(\@ffiles)."\n"; if (@ffiles) { $config->file(@ffiles); my $ptr = $config->get("filter"); print "f:".Dumper($ptr)."\n"; # Apply now all the filters on all the files concerned # All files are relative to PBROOT # destination dir depends on the type of file if (defined $ptr) { foreach my $f (values %bfiles) { filter_file($f,$ptr,"$dest/pbconf/$ddir-$dver/".basename($f)); } foreach my $f (@filteredfiles) { filter_file($f,$ptr,"$dest/$f"); } } } } close(D); } } else { print "'$action' is not available\n"; print "Available actions are:\n"; print " cms2build\n"; } sub filter_file { my $f=shift; my $ptr=shift; my %filter=%$ptr; my $destfile=shift; print "From $f to $destfile\n"; pbmkdir_p(dirname($destfile)) if (! -d dirname($destfile)); open(DEST,"> $destfile") || die "Unable to create $destfile"; open(FILE,"$ENV{'PBROOT'}/$f") || die "Unable to open $f: $!"; while () { my $line = $_; foreach my $s (keys %filter) { # Process single variables #print "debug: $filter{$s}\n"; my $tmp = $filter{$s}; next if (not defined $tmp); # Expand variables if any single one found if ($tmp =~ /\$/) { eval { $tmp =~ s/(\$\w+)/$1/eeg }; } $line =~ s|$s|$tmp|; } print DEST $line; } close(FILE); close(DEST); }