source: devel/pb/bin/pb @ 95

Last change on this file since 95 was 95, checked in by Bruno Cornec, 13 years ago

No more reading files under pkgdir but in project.pb for potential dedicated VERSION and TAG

  • Property svn:executable set to *
File size: 15.8 KB
Line 
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
10# Syntax: see at end
11
12use strict 'vars';
13use Getopt::Std;
14use Data::Dumper;
15use English;
16use AppConfig qw(:argcount :expand);
17use File::Basename;
18use File::Copy;
19use Time::localtime qw(localtime);
20use POSIX qw(strftime);
21
22# Global variables
23use vars qw (%defpkgdir %extpkgdir %filteredfiles %pbrc $debug $LOG);
24
25$debug = 0;                 # Debug level
26$LOG = *STDOUT;             # Where to log
27use lib qw (lib);
28use ProjectBuilder::Distribution qw (pb_distro_init);
29use ProjectBuilder::Changelog qw (pb_changelog);
30use ProjectBuilder::Version qw (pb_version_init);
31use ProjectBuilder::Base qw (pb_conf_read pb_conf_get pb_cms_init pb_mkdir_p pb_system pb_rm_rf pb_get_filters pb_filter_file pb_filter_file_pb);
32
33my %opts;                   # CLI Options
34my $action;                 # action to realize
35my $test = "FALSE";
36my $option = "";
37my @pkgs;
38my $pbtag;                  # Global Tag variable
39my $pbver;                  # Global Version variable
40my %pbver;                  # per package
41my %pbtag;                  # per package
42my $pbrev;                  # Global REVISION variable
43my @date=(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst());
44my $pbdate = strftime("%Y-%m-%d", @date);
45
46getopts('hl:m:p:qr:tv',\%opts);
47
48my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
49if (defined $opts{'h'}) {
50    pb_syntax();
51    exit(0);
52}
53if (defined $opts{'v'}) {
54    $debug++;
55}
56if (defined $opts{'q'}) {
57    $debug=-1;
58}
59if (defined $opts{'l'}) {
60    open(LOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
61    $LOG = *LOG;
62    $debug = 0  if ($debug == -1);
63    }
64# Handles test option
65if (defined $opts{'t'}) {
66    $test = "TRUE";
67    # Works only for SVN
68    $option = "-r BASE";
69}
70
71# Get Action
72$action = shift @ARGV;
73die pb_syntax() if (not defined $action);
74
75# Handle root of the project if defined
76if (defined $opts{'r'}) {
77    $ENV{'PBROOT'} = $opts{'r'};
78}
79# Handle virtual machines if any
80if (defined $opts{'m'}) {
81    $ENV{'PBVM'} = $opts{'m'};
82}
83# Handles project name if any
84if (defined $opts{'p'}) {
85    $ENV{'PBPROJ'} = pb_env_init($opts{'p'});
86} else {
87    $ENV{'PBPROJ'} = pb_env_init();
88}
89
90print $LOG "Project $ENV{'PBPROJ'}\n" if ($debug >= 0);
91print $LOG "Action: $action\n" if ($debug >= 0);
92
93# Keep those project values to store them at the end each time
94my $pbprojtag = $ENV{'PBTAG'};
95my $pbprojver = $ENV{'PBVER'};
96
97# Act depending on action
98if ($action =~ /^cms2build$/) {
99    pb_cms2build();
100} elsif ($action =~ /^build2pkg$/) {
101    pb_build2pkg();
102} elsif ($action =~ /^cms2pkg$/) {
103    pb_cms2build();
104    pb_build2pkg();
105} elsif ($action =~ /^build2ssh$/) {
106    pb_build2ssh();
107} elsif ($action =~ /^pkg2ssh$/) {
108    pb_pkg2ssh();
109} elsif ($action =~ /^build2vm$/) {
110    pb_build2vm();
111} elsif ($action =~ /^cms2vm$/) {
112    pb_cms2build();
113    pb_build2vm();
114} else {
115    print $LOG "'$action' is not available\n";
116    pb_syntax();
117}
118
119sub pb_cms2build {
120
121    my $ptr = pb_get_pkg();
122    @pkgs = @$ptr;
123    pb_cms_init($ENV{'PBPROJ'});
124
125    my ($pkgv, $pkgt) = pb_conf_read("$ENV{'PBCONF'}/$ENV{'PBPROJ'}.pb","pkgversion","pkgtag");
126    foreach my $pbpkg (@pkgs) {
127        if (defined $pkgv->$pbpkg) {
128            $pbver = $pkgv->$pbpkg;
129        } else {
130            $pbver = $ENV{'PBVER'};
131        }
132        if (defined $pkgt->$pbpkg) {
133            $pbtag = $pkgt->$pbpkg;
134        } else {
135            $pbtag = $ENV{'PBTAG'};
136        }
137
138        $pbrev = $ENV{'PBREVISION'};
139        print $LOG "\n" if ($debug >= 0);
140        print $LOG "Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n" if ($debug >= 0);
141        die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
142        # Clean up dest if necessary. The export will recreate it
143        my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
144        pb_rm_rf($dest) if (-d $dest);
145
146        # Export CMS tree for the concerned package to dest
147        # And generate some additional files
148        $OUTPUT_AUTOFLUSH=1;
149
150        # computes in which dir we have to work
151        my $dir = $defpkgdir{$pbpkg};
152        $dir = $extpkgdir{$pbpkg} if (not defined $dir);
153        pb_system("$ENV{'PBCMSEXP'} $option $ENV{'PBROOT'}/$dir $dest 1>/dev/null", "Exporting $ENV{'PBROOT'}/$dir");
154
155        # Creates a REVISION file
156        open(R,"> $dest/REVISION") || die "Unable to create $dest/REVISION";
157        print R "$pbrev\n";
158        close(R);
159
160        # Extract cms log history and store it
161        pb_system("$ENV{'PBCMSLOG'} $option $ENV{'PBROOT'}/$dir > $dest/$ENV{'PBCMSLOGFILE'}", "Extracting log info");
162
163        my %build;
164
165        my ($ptr) = pb_conf_get("vmlist");
166        foreach my $d (split(/,/,$ptr->{$ENV{'PBPROJ'}})) {
167            my ($name,$ver) = split(/_/,$d);
168            chomp($ver);
169            my ($ddir, $dver, $dfam, $dtype, $dsuf) = pb_distro_init($name,$ver);
170            print $LOG "DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $dsuf)."\n" if ($debug >= 1);
171            print $LOG "DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n" if ($debug >= 1);
172
173            # Filter build files from the less precise up to the most with overloading
174            # Filter all files found, keeping the name, and generating in dest
175
176            # Find all build files first relatively to PBROOT
177            my %bfiles;
178            print $LOG "DEBUG dir: $ENV{'PBCONF'}/$pbpkg\n" if ($debug >= 1);
179            $build{"$ddir-$dver"} = "yes";
180            if (-d "$ENV{'PBCONF'}/$pbpkg/$dtype") {
181                opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$dtype") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$dtype: $!";
182                foreach my $f (readdir(BDIR)) {
183                    next if ($f =~ /^\./);
184                    $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$dtype/$f";
185                    $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
186                }
187                closedir(BDIR);
188            } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$dfam") {
189                opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$dfam") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$dfam: $!";
190                foreach my $f (readdir(BDIR)) {
191                    next if ($f =~ /^\./);
192                    $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$dfam/$f";
193                    $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
194                }
195                closedir(BDIR);
196            } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$ddir") {
197                opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$ddir") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$ddir: $!";
198                foreach my $f (readdir(BDIR)) {
199                    next if ($f =~ /^\./);
200                    $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$ddir/$f";
201                    $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
202                }
203                closedir(BDIR);
204            } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$ddir-$dver") {
205                opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$ddir-$dver") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$ddir-$dver: $!";
206                foreach my $f (readdir(BDIR)) {
207                    next if ($f =~ /^\./);
208                    $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$ddir-$dver/$f";
209                    $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
210                }
211                closedir(BDIR);
212            } else {
213                $build{"$ddir-$dver"} = "no";
214                next;
215            }
216            print $LOG "DEBUG bfiles: ".Dumper(\%bfiles)."\n" if ($debug >= 1);
217
218            # Get all filters to apply
219            my $ptr = pb_get_filters($pbpkg, $dtype, $dfam, $ddir, $dver);
220
221            # Apply now all the filters on all the files concerned
222            # destination dir depends on the type of file
223            if (defined $ptr) {
224                foreach my $f (values %bfiles) {
225                    pb_filter_file_pb("$ENV{'PBROOT'}/$f",$ptr,"$dest/pbconf/$ddir-$dver/".basename($f),$dtype,$dsuf,$pbpkg,$pbver,$pbtag,$pbrev,$pbdate);
226                }
227                if (defined $filteredfiles{$pbpkg}) {
228                    foreach my $f (split(/,/,$filteredfiles{$pbpkg})) {
229                        pb_filter_file("$ENV{'PBROOT'}/$dir/$f",$ptr,"$dest/$f",$pbpkg,$pbver,$pbtag,$pbrev,$pbdate);
230                    }
231                }
232            }
233        }
234        if ($debug >= 0) {
235            my @found;
236            my @notfound;
237            foreach my $b (keys %build) {
238                push @found,$b if ($build{$b} =~ /yes/);
239                push @notfound,$b if ($build{$b} =~ /no/);
240            }
241            print $LOG "Build files generated for ".join(',',@found)."\n";
242            print $LOG "No Build files found for ".join(',',@notfound)."\n";
243        }
244        # Prepare the dest directory for archive
245        if (-x "$ENV{'PBCONF'}/$pbpkg/pbinit") {
246            pb_system("cd $dest ; $ENV{'PBCONF'}/$pbpkg/pbinit","Executing init script $ENV{'PBCONF'}/$pbpkg/pbinit");
247        }
248
249        # Archive dest dir
250        chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
251        # Possibility to look at PBSRC to guess more the filename
252        pb_system("tar cfz $pbpkg-$pbver.tar.gz $pbpkg-$pbver","Creating $pbpkg tar files compressed");
253        print $LOG "Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n" if ($debug >= 0);
254
255        # Keep track of what is generated for default
256        open(LAST,"> $pbrc{$ENV{'PBPROJ'}}") || die "Unable to create $pbrc{$ENV{'PBPROJ'}}";
257        print LAST "pbroot $pbprojver-$pbprojtag = $ENV{'PBROOT'}\n";
258        close(LAST);
259
260        # Keep track of per package version
261        if (! -f "$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") {
262            open(PKG,">$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb";
263            print PKG "# Empty\n";
264            close(PKG);
265        }
266        my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
267        $pkg = { } if (not defined $pkg);
268        if ((not defined $pkg->{$pbpkg}) || ($pkg->{$pbpkg} ne "$pbver-$pbtag")) {
269            $pkg->{$pbpkg} = "$pbver-$pbtag";
270        }
271
272        print $LOG "DEBUG pkg: ".Dumper($pkg)."\n" if ($debug >= 1);
273        open(PKG,"> $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb";
274        foreach my $p (keys %$pkg) {
275            print PKG "pbpkg $p = $pkg->{$p}\n";
276        }
277        close(PKG);
278    }
279}
280
281sub pb_build2pkg {
282
283    # Get list of packages to build
284    my $ptr = pb_get_pkg();
285    @pkgs = @$ptr;
286
287    # Get the running distro to build on
288    my ($ddir, $dver, $dfam, $dtype, $dsuf) = pb_distro_init();
289    print $LOG "DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $dsuf))."\n" if ($debug >= 1);
290
291    # Get content saved in cms2build
292    my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
293    $pkg = { } if (not defined $pkg);
294
295    chdir "$ENV{'PBBUILDDIR'}";
296    foreach my $pbpkg (@pkgs) {
297        my $vertag = $pkg->{$pbpkg};
298        # get the version of the current package - maybe different
299        ($pbver,$pbtag) = split(/-/,$vertag);
300
301        my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
302        print $LOG "Source file: $src\n" if ($debug >= 0);
303
304        if ($dtype eq "rpm") {
305            # rpm has its own standard build directory
306            my $tmp=`rpmquery --eval '%{_topdir}' 2> /dev/null`;
307            chomp($tmp);
308            $ENV{'PBBUILDDIR'}=$tmp;
309            print $LOG "Working under $ENV{'PBBUILDDIR'}\n" if ($debug >= 0);
310            foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
311                if (! -d "$ENV{'PBBUILDDIR'}/$d") {
312                pb_mkdir_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";
313                }
314            }
315
316            # We need to first extract the spec file
317            symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
318            my @specfile;
319            @specfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$ENV{'PBBUILDDIR'}/SPECS");
320
321            print $LOG "specfile: ".Dumper(\@specfile)."\n" if ($debug >= 1);
322            # set LANGUAGE to check for correct log messages
323            $ENV{'LANGUAGE'}="C";
324            #system("ls -R $ENV{'PBBUILDDIR'}") if ($debug >= 1);
325            foreach my $f (@specfile) {
326                if ($f =~ /\.spec$/) {
327                    pb_system("rpmbuild -ba $f","Building package with $f");
328                    last;
329                }
330            }
331        } elsif ($dtype eq "tgz") {
332            pb_mkdir_p("$ENV{'PBBUILDDIR'}/install") if (! -d "$ENV{'PBBUILDDIR'}/install");
333        } elsif ($dtype eq "ebuild") {
334            pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage") if (! -d "$ENV{'PBBUILDDIR'}/portage");
335        } else {
336        }
337    }
338}
339
340sub pb_build2ssh {
341    pb_send2ssh("Sources");
342}
343
344sub pb_pkg2ssh {
345    pb_send2ssh("Packages");
346}
347
348sub pb_send2ssh {
349
350    my $cmt = shift;
351
352    my @src;
353
354    # Get list of packages to build
355    my $ptr = pb_get_pkg();
356    @pkgs = @$ptr;
357
358    # Get the running distro to build on
359    my ($ddir, $dver, $dfam, $dtype, $dsuf) = pb_distro_init();
360    print $LOG "DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $dsuf))."\n" if ($debug >= 1);
361
362    # Get content saved in cms2build
363    my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
364    $pkg = { } if (not defined $pkg);
365
366    chdir "$ENV{'PBBUILDDIR'}";
367    my $src;
368    foreach my $pbpkg (@pkgs) {
369        my $vertag = $pkg->{$pbpkg};
370        # get the version of the current package - maybe different
371        ($pbver,$pbtag) = split(/-/,$vertag);
372
373        if ($cmt eq "Sources") {
374            $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
375        } elsif ($cmt eq "Packages") {
376            if ($dtype eq "rpm") {
377                $src="$ENV{'PBBUILDDIR'}/RPMS/*/$pbpkg$pbver-$pbtag$dsuf.*.rpm $ENV{'PBBUILDDIR'}/SRPMS/$pbpkg$pbver-$pbtag$dsuf.src.rpm"
378            } elsif ($dtype eq "deb") {
379                my $tmp = "$ENV{'PBBUILDDIR'}/$pbpkg";
380                $src="$tmp"."_*.deb $tmp"."_*.dsc $tmp"."_*.tar.gz"
381            } elsif ($dtype eq "ebuild") {
382                $src="$ENV{'PBBUILDDIR'}/portage/*/$pbpkg/$pbpkg$pbver.ebuild"
383            } elsif ($dtype eq "slackware") {
384                $src="$ENV{'PBBUILDDIR'}/build-$pbpkg/$pbpkg$pbver-*-$pbtag.tgz"
385            } else {
386                die "Unknown dtype format $dtype";
387            }
388        }
389        print $LOG "$cmt: $src\n" if ($debug >= 0);
390        push @src, $src;
391    }
392    my ($pt) = pb_conf_get("sshhost", "sshlogin", "sshdir");
393    my ($sshhost,$sshlogin,$sshdir) = @$pt;
394    my $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
395    my $dir;
396    if ($cmt eq "Sources") {
397        $dir = "$sshdir->{$ENV{'PBPROJ'}}/src";
398    } elsif ($cmt eq "Packages") {
399        $dir = "$sshdir->{$ENV{'PBPROJ'}}/$ddir/$dver";
400    } else {
401        return;
402    }
403    $src = join(' ',@src);
404    pb_system("ssh -q $mac \"mkdir -p $dir ; cd $dir ; rm -f $src\"","Preparing $dir on $mac");
405    pb_system("scp -p $src $mac:$dir","$cmt delivery in $dir on $mac");
406}
407
408sub pb_get_pkg {
409
410my @pkgs;
411
412# Get packages list
413if (not defined $ARGV[0]) {
414    @pkgs = keys %defpkgdir;
415} elsif ($ARGV[0] =~ /^all$/) {
416    @pkgs = keys %defpkgdir;
417    if (defined %extpkgdir) {
418        my $k = keys %extpkgdir;
419        if (defined $k) {
420            push(@pkgs, keys %extpkgdir);
421        }
422    }
423} else {
424    @pkgs = @ARGV;
425}
426print $LOG "Packages: ".join(',',@pkgs)."\n" if ($debug >= 0);
427return(\@pkgs);
428}
429
430sub pb_get_vm {
431
432my @vm;
433
434# Get VM list
435if (not defined $ENV{'PBVM'}) {
436    @vm = keys %defpkgdir;
437} elsif ($ENV{'PBVM'} =~ /^all$/) {
438    @vm = keys %defpkgdir;
439    if (defined %extpkgdir) {
440        my $k = keys %extpkgdir;
441        if (defined $k) {
442            push(@vm, keys %extpkgdir);
443        }
444    }
445} else {
446    @vm = $ENV{'PBVM'};
447}
448print $LOG "VMs: ".join(',',@vm)."\n" if ($debug >= 0);
449return(\@vm);
450}
451
452sub pb_extract_build_files {
453
454my $src=shift;
455my $dir=shift;
456my $ddir=shift;
457my @files;
458
459pb_system("tar xfpz $src $dir >/dev/null","Extracting build files");
460opendir(DIR,"$dir") || die "Unable to open directory $dir";
461foreach my $f (readdir(DIR)) {
462    next if ($f =~ /^\./);
463    move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
464    print $LOG "mv $dir/$f $ddir\n" if ($debug >= 1);
465    push @files,"$ddir/$f";
466}
467closedir(DIR);
468# Not enough but still a first cleanup
469pb_rm_rf("$dir");
470return(@files);
471}
472
473sub pb_syntax {
474
475    print "pb (aka project-builder) Version $projectbuilderver-$projectbuilderrev\n";
476    print "\n";
477    print "Syntax: pb [-vhqt][-r pbroot][-p project][-m \"mach-1...\"] <action> [<pkg1>...]\n";
478    print "\n";
479    print "-h : This help file\n";
480    print "-q : Quiet mode\n";
481    print "-t : Test mode (not done yet)\n";
482    print "-v : Verbose mode\n";
483    print "\n";
484    print "-m machine : Name of the virtual Machines you want\n";
485    print "             to build on (space separated)        \n";
486    print "             (or use the env variable PBVM)       \n";
487    print "\n";
488    print "-p project : Name of the project you're working on\n";
489    print "             (or use the env variable PBPROJ)     \n";
490    print "\n";
491    print "-r pbroot  : Path Name of project under the CMS \n";
492    print "             (or use the env variable PBROOT)   \n";
493    print "\n";
494    print "<action> can be:\n";
495    print "\n";
496    print "\tcms2build: Create a tar file of the project under your CMS\n";
497    print "\t           CMS supported are SVN and CVS\n";
498    print "\t           parameters are packages to build\n";
499    print "\t           if not using default list\n";
500    print "\n";
501    print "\tbuild2pkg: Create packages for your running distribution  \n";
502    print "\t           first parameter is version-tag to build\n";
503    print "\t           if not using default version-tag\n";
504    print "\t           following parameters are packages to build\n";
505    print "\t           if not using default list\n";
506    print "\n";
507    print "\tcms2pkg:   cms2build + build2pkg\n";
508    print "\n";
509}
Note: See TracBrowser for help on using the repository browser.