source: ProjectBuilder/devel/pb/bin/pb@ 68

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

Remove use of PBTOPDIR useless
delivery dir is cleaned of dir in it only now.
One level less generated during delivery (easier)

  • Property svn:executable set to *
File size: 13.9 KB
RevLine 
[5]1#!/usr/bin/perl -w
2#
3# Project Builder main application
4#
5# $Id$
6#
7# Copyright B. Cornec 2007
8# Provided under the GPL v2
9
[22]10# Syntax: see at end
[9]11
[18]12use strict 'vars';
[5]13use Getopt::Std;
[9]14use Data::Dumper;
15use English;
[16]16use AppConfig qw(:argcount :expand);
17use File::Basename;
[26]18use File::Copy;
[13]19use Time::localtime qw(localtime);
20use POSIX qw(strftime);
[5]21
[53]22use vars qw (%defpkgdir %extpkgdir %version %confparam %filteredfiles %pbroot $debug $LOG $projectbuilderver $projectbuilderrev);
[21]23$debug = 0; # Debug level
[22]24$LOG = *STDOUT; # Where to log
[17]25use lib qw (lib);
[50]26use ProjectBuilder::common qw (env_init);
27use ProjectBuilder::distro qw (distro_init);
28use ProjectBuilder::cms;
29use ProjectBuilder::changelog qw (changelog);
[53]30use ProjectBuilder::Version qw (version_init);
[5]31
32my %opts; # CLI Options
[9]33my $action; # action to realize
34my $test = "FALSE";
35my $option = "";
36my @pkgs;
[16]37my $pbtag; # Global TAG variable
38my $pbver; # Global VERSION variable
[53]39my $pbrev; # Global REVISION variable
[16]40my @date=(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst());
41my $pbdate = strftime("%Y-%m-%d", @date);
[5]42
[67]43getopts('hl:p:qr:tv',\%opts);
[5]44
[53]45version_init();
[21]46if (defined $opts{'h'}) {
47 syntax();
48 exit(0);
49}
50if (defined $opts{'v'}) {
51 $debug++;
52}
53if (defined $opts{'q'}) {
54 $debug=-1;
55}
[22]56if (defined $opts{'l'}) {
57 open(LOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
58 $LOG = *LOG;
59 $debug = 0 if ($debug == -1);
60 }
[9]61# Handles test option
62if (defined $opts{'t'}) {
63 $test = "TRUE";
64 # Works only for SVN
65 $option = "-r BASE";
66}
[5]67
[9]68# Get Action
69$action = shift @ARGV;
[21]70die syntax() if (not defined $action);
[6]71
[67]72# Handle root of the project if defined
73if (defined $opts{'r'}) {
74 $ENV{'PBROOT'} = $opts{'r'};
75}
[59]76# Handles project name if any
77if (defined $opts{'p'}) {
78 $ENV{'PBPROJ'} = env_init($opts{'p'});
79} else {
80 $ENV{'PBPROJ'} = env_init();
81}
82
[22]83print $LOG "Project $ENV{'PBPROJ'}\n" if ($debug >= 0);
84print $LOG "Action: $action\n" if ($debug >= 0);
[9]85
86# Act depending on action
87if ($action =~ /^cms2build$/) {
[22]88 my $ptr = get_pkg();
89 @pkgs = @$ptr;
[9]90 cms_init();
91
[27]92 foreach my $pbpkg (@pkgs) {
93 if (-f "$ENV{'PBROOT'}/$pbpkg/VERSION") {
94 open(V,"$ENV{'PBROOT'}/$pbpkg/VERSION") || die "Unable to open $ENV{'PBROOT'}/$pbpkg/VERSION";
[16]95 $pbver = <V>;
96 chomp($pbver);
[9]97 close(V);
98 } else {
[16]99 $pbver = $ENV{'PBVER'};
[9]100 }
101
[27]102 if (-f "$ENV{'PBROOT'}/$pbpkg/TAG") {
103 open(T,"$ENV{'PBROOT'}/$pbpkg/TAG") || die "Unable to open $ENV{'PBROOT'}/$pbpkg/TAG";
[16]104 $pbtag = <T>;
105 chomp($pbtag);
[9]106 close(T);
107 } else {
[16]108 $pbtag = $ENV{'PBTAG'};
[9]109 }
[16]110 $pbrev = $ENV{'PBREVISION'};
[22]111 print $LOG "\n" if ($debug >= 0);
[27]112 print $LOG "Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n" if ($debug >= 0);
[9]113 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
[16]114 # Clean up dest if necessary. The export will recreate it
[27]115 my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
[9]116 pbrm_rf($dest) if (-d $dest);
117
118 # Export CMS tree for the concerned package to dest
119 # And generate some additional files
120 $OUTPUT_AUTOFLUSH=1;
[29]121
[9]122 # computes in which dir we have to work
[27]123 my $dir = $defpkgdir{$pbpkg};
124 $dir = $extpkgdir{$pbpkg} if (not defined $dir);
[30]125 pbsystem("$ENV{'PBCMSEXP'} $option $ENV{'PBROOT'}/$dir $dest 1>/dev/null", "Exporting $ENV{'PBROOT'}/$dir");
[9]126
127 # Creates a REVISION file
128 open(R,"> $dest/REVISION") || die "Unable to create $dest/REVISION";
[16]129 print R "$pbrev\n";
[9]130 close(R);
131
132 # Extract cms log history and store it
[30]133 pbsystem("$ENV{'PBCMSLOG'} $option $ENV{'PBROOT'}/$dir > $dest/$ENV{'PBCMSLOGFILE'}", "Extracting log info");
[29]134
[21]135 my %build;
[11]136 open(D,"$ENV{'PBCONF'}/DISTROS") || die "Unable to find $ENV{'PBCONF'}/DISTROS\n";
137 while (<D>) {
138 my $d = $_;
[55]139 my ($ndir,$ver) = split(/_/,$d);
[11]140 chomp($ver);
[55]141 my ($ddir, $dver, $dfam, $dtype, $dsuf) = distro_init($ndir,$ver);
[22]142 print $LOG "DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $dsuf)."\n" if ($debug >= 1);
143 print $LOG "DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n" if ($debug >= 1);
[13]144
[16]145 # Filter build files from the less precise up to the most with overloading
[13]146 # Filter all files found, keeping the name, and generating in dest
[16]147
148 # Find all build files first relatively to PBROOT
149 my %bfiles;
[27]150 print $LOG "DEBUG dir: $ENV{'PBCONF'}/$pbpkg\n" if ($debug >= 1);
[21]151 $build{"$ddir-$dver"} = "yes";
[27]152 if (-d "$ENV{'PBCONF'}/$pbpkg/$dtype") {
153 opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$dtype") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$dtype: $!";
[16]154 foreach my $f (readdir(BDIR)) {
155 next if ($f =~ /^\./);
[27]156 $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$dtype/$f";
[16]157 $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
158 }
[13]159 closedir(BDIR);
[27]160 } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$dfam") {
161 opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$dfam") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$dfam: $!";
[16]162 foreach my $f (readdir(BDIR)) {
163 next if ($f =~ /^\./);
[27]164 $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$dfam/$f";
[16]165 $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
166 }
167 closedir(BDIR);
[27]168 } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$ddir") {
169 opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$ddir") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$ddir: $!";
[16]170 foreach my $f (readdir(BDIR)) {
171 next if ($f =~ /^\./);
[27]172 $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$ddir/$f";
[16]173 $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
174 }
[13]175 closedir(BDIR);
[27]176 } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$ddir-$dver") {
177 opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$ddir-$dver") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$ddir-$dver: $!";
[16]178 foreach my $f (readdir(BDIR)) {
179 next if ($f =~ /^\./);
[27]180 $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$ddir-$dver/$f";
[16]181 $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
182 }
[13]183 closedir(BDIR);
184 } else {
[21]185 $build{"$ddir-$dver"} = "no";
[13]186 next;
187 }
[22]188 print $LOG "DEBUG bfiles: ".Dumper(\%bfiles)."\n" if ($debug >= 1);
[13]189
[15]190 # Get all filters to apply
191 # They're cumulative from less specific to most specific
192 # suffix is .pbf
[16]193 my @ffiles;
194 my ($ffile0, $ffile1, $ffile2, $ffile3);
[27]195 if (-d "$ENV{'PBCONF'}/$pbpkg/pbfilter") {
196 $ffile0 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dtype.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dtype.pbf");
197 $ffile1 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dfam.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dfam.pbf");
198 $ffile2 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir.pbf");
199 $ffile3 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir-$dver.pbf");
[16]200 push @ffiles,$ffile0 if (defined $ffile0);
201 push @ffiles,$ffile1 if (defined $ffile1);
202 push @ffiles,$ffile2 if (defined $ffile2);
203 push @ffiles,$ffile3 if (defined $ffile3);
204 }
205 my $config = AppConfig->new({
206 # Auto Create variables mentioned in Conf file
207 CREATE => 1,
208 DEBUG => 0,
209 GLOBAL => {
210 # Each conf item is a hash
211 ARGCOUNT => AppConfig::ARGCOUNT_HASH
212 }
213 });
[19]214 my $ptr;
[16]215 if (@ffiles) {
[22]216 print $LOG "DEBUG ffiles: ".Dumper(\@ffiles)."\n" if ($debug >= 1);
[16]217 $config->file(@ffiles);
[19]218 $ptr = $config->get("filter");
[22]219 print $LOG "DEBUG f:".Dumper($ptr)."\n" if ($debug >= 1);
[19]220 } else {
221 $ptr = { };
222 }
[15]223
[19]224 # Apply now all the filters on all the files concerned
225 # destination dir depends on the type of file
226 if (defined $ptr) {
227 foreach my $f (values %bfiles) {
[57]228 filter_file("$ENV{'PBROOT'}/$f",$ptr,"$dest/pbconf/$ddir-$dver/".basename($f),$pbpkg,$dtype,$dsuf);
[16]229 }
[61]230 if (defined $filteredfiles{$dir}) {
231 foreach my $f (split(/,/,$filteredfiles{$dir})) {
232 filter_file("$ENV{'PBROOT'}/$dir/$f",$ptr,"$dest/$f",$pbpkg,$dtype,$dsuf);
233 }
[19]234 }
[15]235 }
[18]236 }
[21]237 if ($debug >= 0) {
238 my @found;
239 my @notfound;
240 foreach my $b (keys %build) {
241 push @found,$b if ($build{$b} =~ /yes/);
242 push @notfound,$b if ($build{$b} =~ /no/);
243 }
[22]244 print $LOG "Build files generated for ".join(',',@found)."\n";
245 print $LOG "No Build files found for ".join(',',@notfound)."\n";
[21]246 }
[18]247 close(D);
248 # Prepare the dest directory for archive
[60]249 if (-x "$ENV{'PBCONF'}/$pbpkg/pbinit") {
[29]250 pbsystem("cd $dest ; $ENV{'PBCONF'}/$pbpkg/pbinit","Executing init script $ENV{'PBCONF'}/$pbpkg/pbinit");
[11]251 }
[29]252
[18]253 # Archive dest dir
[22]254 chdir "$ENV{'PBDESTDIR'}";
[25]255 # Possibility to look at PBSRC to guess more the filename
[68]256 pbsystem("tar cfpz $pbpkg-$pbver.tar.gz $pbpkg-$pbver","Creating $pbpkg tar files compressed");
[31]257 print $LOG "Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n" if ($debug >= 0);
258 # Keep track of what is generated for build2pkg default
[68]259 open(LAST,"> $ENV{'PBDESTDIR'}/LAST") || die "Unable to create $ENV{'PBDESTDIR'}/LAST";
[31]260 print LAST "$pbver-$pbtag\n";
261 close(LAST);
[9]262 }
[22]263} elsif ($action =~ /^build2pkg$/) {
264 # Check whether we have a specific version to build
265 my $vertag = shift @ARGV;
266 if (not defined $vertag) {
[68]267 open(LAST,"$ENV{'PBDESTDIR'}/LAST") || die "Unable to open $ENV{'PBDESTDIR'}/LAST\nYou may want to precise as parameter version-tag";
[22]268 $vertag = <LAST>;
269 chomp($vertag);
270 close(LAST);
271 }
272 ($pbver,$pbtag) = split(/-/,$vertag);
273
274 # Get list of packages to build
275 my $ptr = get_pkg();
276 @pkgs = @$ptr;
277
278 # Get the running distro to build on
[23]279 my ($ddir, $dver, $dfam, $dtype, $dsuf) = distro_init();
[25]280 print $LOG "DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $dsuf))."\n" if ($debug >= 1);
[22]281
[25]282 chdir "$ENV{'PBBUILDDIR'}";
[27]283 foreach my $pbpkg (@pkgs) {
284 my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
[67]285 print $LOG "Source file: $src\n" if ($debug >= 0);
[25]286
287 if ($dtype eq "rpm") {
288 # rpm has its own standard build directory
[28]289 my $tmp=`rpmquery --eval '%{_topdir}' 2> /dev/null`;
290 chomp($tmp);
291 $ENV{'PBBUILDDIR'}=$tmp;
292 print $LOG "Working under $ENV{'PBBUILDDIR'}\n" if ($debug >= 0);
[25]293 foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
[28]294 if (! -d "$ENV{'PBBUILDDIR'}/$d") {
295 pbmkdir_p("$ENV{'PBBUILDDIR'}/$d") || die "Please ensure that you can write into $ENV{'PBBUILDDIR'} to create $d\nSolution: setup _topdir in your ~/.rpmmacros or\nchown the $ENV{'PBBUILDDIR'} directory to your uid";
296 }
[25]297 }
298
299 # We need to first extract the spec file
[28]300 symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
301 my @specfile;
302 @specfile = extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$ENV{'PBBUILDDIR'}/SPECS");
[25]303
[28]304 print $LOG "specfile: ".Dumper(\@specfile)."\n" if ($debug >= 1);
[25]305 # set LANGUAGE to check for correct log messages
306 $ENV{'LANGUAGE'}="C";
[28]307 #system("ls -R $ENV{'PBBUILDDIR'}") if ($debug >= 1);
308 foreach my $f (@specfile) {
309 if ($f =~ /\.spec$/) {
[30]310 pbsystem("rpmbuild -ba $f","Building package with $f");
[28]311 last;
312 }
313 }
[25]314 } elsif ($dtype eq "tgz") {
315 pbmkdir_p("$ENV{'PBBUILDDIR'}/install") if (! -d "$ENV{'PBBUILDDIR'}/install");
316 } elsif ($dtype eq "ebuild") {
317 pbmkdir_p("$ENV{'PBBUILDDIR'}/portage") if (! -d "$ENV{'PBBUILDDIR'}/portage");
318 } else {
319 }
[22]320 }
[9]321} else {
[22]322 print $LOG "'$action' is not available\n";
[21]323 syntax();
[9]324}
[16]325
[17]326# Function which applies filter on files
[16]327sub filter_file {
328
329my $f=shift;
330my $ptr=shift;
331my %filter=%$ptr;
332my $destfile=shift;
[27]333my $pbpkg=shift;
[17]334my $dtype=shift;
335my $dsuf=shift;
[16]336
[22]337print $LOG "DEBUG: From $f to $destfile\n" if ($debug >= 1);
[16]338pbmkdir_p(dirname($destfile)) if (! -d dirname($destfile));
339open(DEST,"> $destfile") || die "Unable to create $destfile";
[57]340open(FILE,"$f") || die "Unable to open $f: $!";
[16]341while (<FILE>) {
342 my $line = $_;
343 foreach my $s (keys %filter) {
344 # Process single variables
[22]345 print $LOG "DEBUG filter{$s}: $filter{$s}\n" if ($debug > 1);
[16]346 my $tmp = $filter{$s};
347 next if (not defined $tmp);
348 # Expand variables if any single one found
349 if ($tmp =~ /\$/) {
350 eval { $tmp =~ s/(\$\w+)/$1/eeg };
[17]351 # special case for ChangeLog
[20]352 } elsif (($tmp =~ /^yes$/) && ($s =~ /^PBLOG$/) && ($line =~ /^PBLOG$/)) {
[27]353 my $p = $defpkgdir{$pbpkg};
354 $p = $extpkgdir{$pbpkg} if (not defined $p);
355 changelog($dtype, $pbpkg, $pbtag, $dsuf, $p, \*DEST);
[20]356 $tmp = "";
[16]357 }
358 $line =~ s|$s|$tmp|;
359 }
360 print DEST $line;
[17]361}
[16]362close(FILE);
363close(DEST);
364}
[21]365
[22]366sub get_pkg {
367
368my @pkgs;
369
370# Get packages list
371if (not defined $ARGV[0]) {
372 @pkgs = keys %defpkgdir;
373} elsif ($ARGV[0] =~ /^all$/) {
374 @pkgs = keys %defpkgdir;
375 if (defined %extpkgdir) {
376 my $k = keys %extpkgdir;
377 if (defined $k) {
378 push(@pkgs, keys %extpkgdir);
379 }
380 }
381} else {
382 @pkgs = @ARGV;
383}
384print $LOG "Packages: ".join(',',@pkgs)."\n" if ($debug >= 0);
385return(\@pkgs);
386}
387
[25]388sub extract_build_files {
389
390my $src=shift;
391my $dir=shift;
[26]392my $ddir=shift;
[28]393my @files;
[25]394
[46]395pbsystem("tar xfpz $src $dir >/dev/null","Extracting build files");
[25]396opendir(DIR,"$dir") || die "Unable to open directory $dir";
397foreach my $f (readdir(DIR)) {
398 next if ($f =~ /^\./);
[26]399 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
[28]400 print $LOG "mv $dir/$f $ddir\n" if ($debug >= 1);
401 push @files,"$ddir/$f";
[25]402}
403closedir(DIR);
[26]404# Not enough but still a first cleanup
[25]405pbrm_rf("$dir");
[28]406return(@files);
[25]407}
408
[21]409sub syntax {
410
[53]411 print "pb (aka project-builder) Version $projectbuilderver-$projectbuilderrev\n";
412 print "\n";
[21]413 print "Syntax: pb [-vhqt][-p project] <action> [<params>...]\n";
414 print "\n";
415 print "-h : This help file\n";
416 print "-q : Quiet mode\n";
417 print "-t : Test mode (not done yet)\n";
418 print "-v : Verbose mode\n";
419 print "\n";
420 print "-p project : Name of the project you're working on\n";
421 print " (or use the env variable PBPROJ) \n";
422 print "\n";
423 print "<action> can be:\n";
424 print "\n";
425 print "\tcms2build: Create a tar file of the project under your CMS\n";
426 print "\t CMS supported are SVN and CVS\n";
[22]427 print "\t parameters are packages to build\n";
428 print "\t if not using default list\n";
[21]429 print "\n";
430 print "\tbuild2pkg: Create packages for your running distribution \n";
[22]431 print "\t first parameter is version-tag to build\n";
432 print "\t if not using default version-tag\n";
433 print "\t following parameters are packages to build\n";
434 print "\t if not using default list\n";
[21]435 print "\n";
436 print "\n";
437}
Note: See TracBrowser for help on using the repository browser.