source: devel/pb/bin/pb @ 1117

Revision 1117, 104.1 KB checked in by bruno, 2 years ago (diff)

r4058@localhost: bruno | 2010-11-26 11:42:34 +0100

  • New Web site management with 4 targtes instead of only 2 (sbx2webssh, ...)
  • Property svn:executable set to *
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';
13
14# The modules mentioned here are required by pb when used both
15# locally or inside a VE/VM
16# Additional required modules only used locally are called with a require
17# in their respective section
18use Getopt::Long qw(:config auto_abbrev no_ignore_case);
19use Data::Dumper;
20use English;
21use File::Basename;
22use File::Copy;
23use File::stat;
24use File::Temp qw(tempdir);
25use File::Find;
26use Time::localtime qw(localtime);
27use POSIX qw(strftime);
28use lib qw (lib);
29use ProjectBuilder::Version;
30use ProjectBuilder::Base;
31use ProjectBuilder::Display;
32use ProjectBuilder::Conf;
33use ProjectBuilder::Distribution;
34use ProjectBuilder::CMS;
35use ProjectBuilder::Env;
36use ProjectBuilder::Filter;
37use ProjectBuilder::Changelog;
38
39# Global variables
40my %opts;                                       # CLI Options
41my $action;                                     # action to realize
42my $test = "FALSE";                     # Not used
43my $pbforce = 0;                        # Force VE/VM rebuild
44my $pbsnap = 0;                         # Do not use snapshot mode for VM/VE by default
45my $option = "";                        # Not used
46my @pkgs;                                       # list of packages
47my $pbtag;                                      # Global Tag variable
48my $pbver;                                      # Global Version variable
49my $pbscript;                           # Name of the script
50my %pbver;                                      # per package
51my %pbtag;                                      # per package
52my $pbrev;                                      # Global REVISION variable
53my $pbaccount;                          # Login to use to connect to the VM
54my $pbport;                                     # Port to use to connect to the VM
55my $newver;                                     # New version to create
56my $iso = undef;                        # ISO image for the VM to create
57
58my @date = pb_get_date();
59my $pbdate = strftime("%Y-%m-%d", @date);
60
61=pod
62
63=head1 NAME
64
65pb, aka project-builder.org - builds packages for your projects
66
67=head1 DESCRIPTION
68
69pb helps you build various packages directly from your project sources.
70Those sources could be handled by a CMS (Configuration Management System)
71such as Subversion, CVS, Git, Mercurial... or being a simple reference to a compressed tar file.
72It's based on a set of configuration files, a set of provided macros to help
73you keeping build files as generic as possible. For example, a single .spec
74file should be required to generate for all rpm based distributions, even
75if you could also have multiple .spec files if required.
76
77=head1 SYNOPSIS
78
79pb [-vhSq][-r pbroot][-p project][[-s script -a account -P port][-m mach-1[,...]]][-i iso] <action> [<pkg1> ...]
80
81pb [--verbose][--help][--man][--quiet][--snapshot][--revision pbroot][--project project][[--script script --account account --port port][--machine mach-1[,...]]][--iso iso] <action> [<pkg1> ...]
82
83=head1 OPTIONS
84
85=over 4
86
87=item B<-v|--verbose>
88
89Print a brief help message and exits.
90
91=item B<-q|--quiet>
92
93Do not print any output.
94
95=item B<-h|--help>
96
97Print a brief help message and exits.
98
99=item B<-S|--snapshot>
100
101Use the snapshot mode of VMs or VEs
102
103=item B<--man>
104
105Prints the manual page and exits.
106
107=item B<-m|--machine machine1[,machine2,...]>
108
109Name of the Virtual Machines (VM) or Virtual Environments (VE) you want to build on (coma separated).
110All if none precised (or use the env variable PBV).
111
112=item B<-s|--script script>
113
114Name of the script you want to execute on the related VMs or VEs.
115
116=item B<-i|--iso iso_image>
117
118Name of the ISO image of the distribution you want to install on the related VMs.
119
120=item B<-a|--account account>
121
122Name of the account to use to connect on the related VMs.
123
124=item B<-P|--port port_number>
125
126Port number to use to connect on the related VMs.\n";
127
128=item B<-p|--project project_name>
129
130Name of the project you're working on (or use the env variable PBPROJ)
131
132=item B<-r|--revision revision>
133
134Path Name of the project revision under the CMS (or use the env variable PBROOT)
135
136=item B<-V|--version new_version>
137
138New version of the project to create based on the current one.
139
140=back
141
142=head1 ARGUMENTS
143
144<action> can be:
145
146=over 4
147
148=item B<sbx2build>
149
150Create tar files for the project under your CMS.
151Current state of the exported content is taken.
152CMS supported are SVN, SVK, CVS, Git and Mercurial
153parameters are packages to build
154if not using default list
155
156=item B<cms2build>
157
158Create tar files for the project under your CMS.
159Current state of the CMS is taken.
160CMS supported are SVN, SVK, CVS, Git and Mercurial
161parameters are packages to build
162if not using default list
163
164=item B<build2pkg>
165
166Create packages for your running distribution
167
168=item B<cms2pkg>
169
170cms2build + build2pkg
171
172=item B<sbx2pkg>
173
174sbx2build + build2pkg
175
176=item B<build2ssh>
177
178Send the tar files to a SSH host
179
180=item B<sbx2ssh>
181
182sbx2build + build2ssh
183
184=item B<cms2ssh>
185
186cms2build + build2ssh
187
188=item B<pkg2ssh>
189
190Send the packages built to a SSH host
191
192=item B<build2vm>
193
194Create packages in VMs, launching them if needed
195and send those packages to a SSH host once built
196VM type supported are QEMU
197
198=item B<build2ve>
199
200Create packages in VEs, creating it if needed
201and send those packages to a SSH host once built
202
203=item B<sbx2vm>
204
205sbx2build + build2vm
206
207=item B<sbx2ve>
208
209sbx2build + build2ve
210
211=item B<cms2vm>
212
213cms2build + build2vm
214
215=item B<cms2ve>
216
217cms2build + build2ve
218
219=item B<launchvm>
220
221Launch one virtual machine
222
223=item B<launchve>
224
225Launch one virtual environment
226
227=item B<script2vm>
228
229Launch one virtual machine if needed
230and executes a script on it
231
232=item B<script2ve>
233
234Execute a script in a virtual environment
235
236=item B<newvm>
237
238Create a new virtual machine
239
240=item B<newve>
241
242Create a new virtual environment
243
244=item B<setupvm>
245
246Setup a virtual machine for pb usage
247
248=item B<setupve>
249
250Setup a virtual environment for pb usage
251
252=item B<snapvm>
253
254Snapshot a virtual machine for pb usage
255
256=item B<snapve>
257
258Snapshot a virtual environment for pb usage
259
260=item B<updatevm>
261
262Update the distribution in the virtual machine
263
264=item B<updateve>
265
266Update the distribution in the virtual environment
267
268=item B<test2pkg>
269
270Test a package locally
271
272=item B<test2vm>
273
274Test a package in a virtual machine
275
276=item B<test2ve>
277
278Test a package in a virtual environment
279
280=item B<newver>
281
282Create a new version of the project derived
283from the current one
284
285=item B<newproj>
286
287Create a new project and a template set of
288configuration files under pbconf
289
290=item B<announce>
291
292Announce the availability of the project through various means
293
294=item B<sbx2webssh>
295
296Create tar files for the website under your CMS.
297Current state of the exported content is taken.
298Deliver the content to the target server using ssh from the exported dir.
299
300=item B<cms2webssh>
301
302Create tar files for the website from your CMS.
303Deliver the content to the target server using ssh from the DVCS.
304
305=item B<sbx2webpkg>
306
307Create tar files for the website under your CMS.
308Current state of the exported content is taken.
309
310=item B<cms2webpkg>
311
312Create tar files for the website under your CMS.
313
314=item B<clean>
315
316Purge the build and delivery directories related to the current project
317
318=back
319
320<pkgs> can be a list of packages, the keyword 'all' or nothing, in which case the default list of packages is taken (corresponding to the defpkgdir list of arguments in the configuration file).
321
322=head1 WEB SITES
323
324The 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/>.
325
326=head1 USER MAILING LIST
327
328None exists for the moment.
329
330=head1 CONFIGURATION FILES
331
332Each pb user may have a configuration in F<$HOME/.pbrc>. The values in this file may overwrite any other configuration file value.
333
334Here is an example of such a configuration file:
335
336 #
337 # Define for each project the URL of its pbconf repository
338 # No default option allowed here as they need to be all different
339 #
340 # URL of the pbconf content
341 # This is the format of a classical URL with the extension of additional schema such as
342 # svn+ssh, cvs+ssh, ...
343 #
344 pbconfurl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe/pbconf
345
346 # This is normaly defined in the project's configuration file
347 # Url of the project
348 #
349 pburl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe
350 
351 # All these URLs needs to be defined here as the are the entry point
352 # for how to build packages for the project
353 #
354 pbconfurl pb = svn+ssh://svn.project-builder.org/mondo/svn/pb/pbconf
355 pbconfurl mondorescue = svn+ssh://svn.project-builder.org/mondo/svn/project-builder/mondorescue/pbconf
356 pbconfurl collectl = svn+ssh://bruno@svn.mondorescue.org/mondo/svn/project-builder/collectl/pbconf
357 pbconfurl netperf = svn+ssh://svn.mondorescue.org/mondo/svn/project-builder/netperf/pbconf
358 
359 # Under that dir will take place everything related to pb
360 # If you want to use VMs/chroot/..., then use $ENV{'HOME'} to make it portable
361 # to your VMs/chroot/...
362 # if not defined then /var/cache
363 pbdefdir default = $ENV{'HOME'}/project-builder
364 pbdefdir pb = $ENV{'HOME'}
365 pbdefdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
366 pbdefdir mondorescue = $ENV{'HOME'}/mondo/svn
367 
368 # pbconfdir points to the directory where the CMS content of the pbconfurl is checked out
369 # If not defined, pbconfdir is under pbdefdir/pbproj/pbconf
370 pbconfdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs/pbconf
371 pbconfdir mondorescue = $ENV{'HOME'}/mondo/svn/pbconf
372 
373 # pbdir points to the directory where the CMS content of the pburl is checked out
374 # If not defined, pbdir is under pbdefdir/pbproj
375 # Only defined if we have access to the dev of the project
376 pbdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
377 pbdir mondorescue = $ENV{'HOME'}/mondo/svn
378 
379 # -daemonize doesn't work with qemu 0.8.2
380 vmopt default = -m 384
381
382=head1 AUTHORS
383
384The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
385
386=head1 COPYRIGHT
387
388Project-Builder.org is distributed under the GPL v2.0 license
389described in the file C<COPYING> included with the distribution.
390
391=cut
392
393# ---------------------------------------------------------------------------
394
395my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
396my $appname = "pb";
397
398# Initialize the syntax string
399
400pb_syntax_init("$appname (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n");
401
402GetOptions("help|?|h" => \$opts{'h'}, 
403                "man" => \$opts{'man'},
404                "verbose|v+" => \$opts{'v'},
405                "snapshot|S" => \$opts{'S'},
406                "quiet|q" => \$opts{'q'},
407                "log-files|l=s" => \$opts{'l'},
408                "force|f" => \$opts{'f'},
409                "account|a=s" => \$opts{'a'},
410                "revision|r=s" => \$opts{'r'},
411                "script|s=s" => \$opts{'s'},
412                "machines|mock|m=s" => \$opts{'m'},
413                "port|P=i" => \$opts{'P'},
414                "project|p=s" => \$opts{'p'},
415                "iso|i=s" => \$opts{'i'},
416                "version|V=s" => \$opts{'V'},
417) || pb_syntax(-1,0);
418
419if (defined $opts{'h'}) {
420        pb_syntax(0,1);
421}
422if (defined $opts{'man'}) {
423        pb_syntax(0,2);
424}
425if (defined $opts{'v'}) {
426        $pbdebug = $opts{'v'};
427}
428if (defined $opts{'f'}) {
429        $pbforce=1;
430}
431if (defined $opts{'q'}) {
432        $pbdebug=-1;
433}
434if (defined $opts{'S'}) {
435        $pbsnap=1;
436}
437if (defined $opts{'l'}) {
438        open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
439        $pbLOG = \*pbLOG;
440        $pbdebug = 0  if ($pbdebug == -1);
441        }
442pb_log_init($pbdebug, $pbLOG);
443pb_display_init("text","");
444
445# Handle root of the project if defined
446if (defined $opts{'r'}) {
447        $ENV{'PBROOTDIR'} = $opts{'r'};
448}
449# Handle virtual machines if any
450if (defined $opts{'m'}) {
451        $ENV{'PBV'} = $opts{'m'};
452}
453if (defined $opts{'s'}) {
454        $pbscript = $opts{'s'};
455}
456if (defined $opts{'a'}) {
457        $pbaccount = $opts{'a'};
458        die "option -a requires a -s script option" if (not defined $pbscript);
459}
460if (defined $opts{'P'}) {
461        $pbport = $opts{'P'};
462}
463if (defined $opts{'V'}) {
464        $newver = $opts{'V'};
465}
466if (defined $opts{'i'}) {
467        $iso = $opts{'i'};
468}
469
470# Get Action
471$action = shift @ARGV;
472die pb_syntax(-1,1) if (not defined $action);
473
474my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
475my $pbinit = undef;
476$pbinit = 1 if ($action =~ /^newproj$/);
477
478# Handles project name if any
479# And get global params
480($filteredfiles, $supfiles, $defpkgdir, $extpkgdir) = pb_env_init($opts{'p'},$pbinit,$action);
481
482#
483# Check for command requirements
484#
485my ($req,$opt) = pb_conf_get_if("oscmd","oscmdopt");
486my ($req2,$opt2) = (undef,undef);
487$req2 = $req->{$appname} if (defined $req);
488$opt2 = $opt->{$appname} if (defined $opt);
489pb_check_requirements($req2,$opt2);
490
491pb_log(0,"Project: $ENV{'PBPROJ'}\n");
492pb_log(0,"Action: $action\n");
493
494# Act depending on action
495if ($action =~ /^cms2build$/) {
496        pb_cms2build("CMS");
497} elsif ($action =~ /^sbx2build$/) {
498        pb_cms2build("SandBox");
499} elsif ($action =~ /^build2pkg$/) {
500        pb_build2pkg();
501} elsif ($action =~ /^cms2pkg$/) {
502        pb_cms2build("CMS");
503        pb_build2pkg();
504} elsif ($action =~ /^sbx2pkg$/) {
505        pb_cms2build("SandBox");
506        pb_build2pkg();
507} elsif ($action =~ /^build2ssh$/) {
508        pb_build2ssh();
509} elsif ($action =~ /^cms2ssh$/) {
510        pb_cms2build("CMS");
511        pb_build2ssh();
512} elsif ($action =~ /^sbx2ssh$/) {
513        pb_cms2build("SandBox");
514        pb_build2ssh();
515} elsif ($action =~ /^pkg2ssh$/) {
516        pb_pkg2ssh();
517} elsif ($action =~ /^build2ve$/) {
518        pb_build2v("ve","build");
519} elsif ($action =~ /^build2vm$/) {
520        pb_build2v("vm","build");
521} elsif ($action =~ /^cms2ve$/) {
522        pb_cms2build("CMS");
523        pb_build2v("ve","build");
524} elsif ($action =~ /^sbx2ve$/) {
525        pb_cms2build("SandBox");
526        pb_build2v("ve","build");
527} elsif ($action =~ /^cms2vm$/) {
528        pb_cms2build("CMS");
529        pb_build2v("vm","build");
530} elsif ($action =~ /^sbx2vm$/) {
531        pb_cms2build("SandBox");
532        pb_build2v("vm","build");
533} elsif ($action =~ /^launchvm$/) {
534        pb_launchv("vm",$ENV{'PBV'},0);
535} elsif ($action =~ /^launchve$/) {
536        pb_launchv("ve",$ENV{'PBV'},0);
537} elsif ($action =~ /^script2vm$/) {
538        pb_script2v($pbscript,"vm");
539} elsif ($action =~ /^script2ve$/) {
540        pb_script2v($pbscript,"ve");
541} elsif ($action =~ /^newver$/) {
542        pb_newver();
543} elsif ($action =~ /^newve$/) {
544        pb_launchv("ve",$ENV{'PBV'},1);
545} elsif ($action =~ /^newvm$/) {
546        pb_launchv("vm",$ENV{'PBV'},1);
547        pb_log(0, "Please ensure that sshd is running in your VM by default\n");
548        pb_log(0, "and that it allows remote root login (PermitRootLogin yes in /etc/ssh/sshd_config)\n");
549        pb_log(0, "Also ensure that network is up, firewalling correctly configured\n");
550        pb_log(0, "and perl, sudo, ntpdate and scp/ssh installed\n");
551        pb_log(0, "You should then be able to login with ssh -p VMPORT root\@localhost (if VM started with pb)\n");
552} elsif ($action =~ /^setupve$/) {
553        pb_setup2v("ve");
554} elsif ($action =~ /^setupvm$/) {
555        pb_setup2v("vm");
556} elsif ($action =~ /^updateve$/) {
557        pb_update2v("ve");
558} elsif ($action =~ /^updatevm$/) {
559        pb_update2v("vm");
560} elsif ($action =~ /^snapve$/) {
561        pb_snap2v("ve");
562} elsif ($action =~ /^snapvm$/) {
563        pb_snap2v("vm");
564} elsif ($action =~ /^test2pkg$/) {
565        pb_test2pkg();
566} elsif ($action =~ /^test2ve$/) {
567        pb_build2v("ve","test");
568} elsif ($action =~ /^test2vm$/) {
569        pb_build2v("vm","test");
570} elsif ($action =~ /^newproj$/) {
571        # Nothing to do - already done in pb_env_init
572} elsif ($action =~ /^clean$/) {
573        pb_clean();
574} elsif ($action =~ /^announce$/) {
575        # For announce only. Require avoids the systematic load of these modules
576        require DBI;
577        require DBD::SQLite;
578        require Mail::SendMail;
579
580        pb_announce();
581} elsif ($action =~ /^sbx2webpkg$/) {
582        require DBI;
583        require DBD::SQLite;
584
585        pb_cms2build("SandBox","Web");
586} elsif ($action =~ /^sbx2webssh$/) {
587        require DBI;
588        require DBD::SQLite;
589
590        pb_cms2build("SandBox","Web");
591        pb_send2target("Web");
592} elsif ($action =~ /^cms2webpkg$/) {
593        require DBI;
594        require DBD::SQLite;
595
596        pb_cms2build("CMS","Web");
597} elsif ($action =~ /^cms2webssh$/) {
598        require DBI;
599        require DBD::SQLite;
600
601        pb_cms2build("CMS","Web");
602        pb_send2target("Web");
603} else {
604        pb_log(0,"\'$action\' is not available\n");
605        pb_syntax(-2,1);
606}
607
608sub pb_cms2build {
609
610        my $param = shift || undef;
611        my $web = shift || undef;
612
613        my $pkg;
614        my @pkgs;
615        my $webdir;
616
617        my %pkgs;
618        my %pb;                         # Structure to store conf info
619
620        die "pb_cms2build requires a parameter: SandBox or CMS" if (not defined $param);
621
622        # If Website, then pkg is only the website
623        if (defined $web) {
624                ($webdir) = pb_conf_get("webdir");
625                pb_log(2,"webdir: ".Dumper($webdir)."\n");
626                $pkgs[0] = $webdir->{$ENV{'PBPROJ'}};
627                $extpkgdir = $webdir;
628                pb_log(0,"Package: $pkgs[0]\n");
629        } else {
630                $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
631                @pkgs = @$pkg;
632        }
633
634        my ($scheme, $uri) = pb_cms_init($pbinit,$param);
635
636        # We need 2 lines here
637        my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
638        my @pt = pb_conf_get_if("vmlist","velist");
639
640        # declare packager and repo for filtering
641        # TODO: Is pbrepo needed so early in the process ?
642        my ($tmp1, $tmp2) = pb_conf_get("pbpackager","pbrepo");
643        $ENV{'PBPACKAGER'} = $tmp1->{$ENV{'PBPROJ'}};
644        $ENV{'PBREPO'} = $tmp2->{$ENV{'PBPROJ'}};
645
646        foreach my $pbpkg (@pkgs) {
647                $ENV{'PBPKG'} = $pbpkg;
648
649                if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
650                        $pbver = $pkgv->{$pbpkg};
651                } else {
652                        $pbver = $ENV{'PBPROJVER'};
653                }
654                # If it's a test version, then tag == 0.date
655                if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
656                        $pbtag = "0.".strftime("%Y%m%d%H%M%S", @date);
657                        $ENV{'PBPROJTAG'} = $pbtag;
658                } elsif ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
659                        $pbtag = $pkgt->{$pbpkg};
660                } else {
661                        $pbtag = $ENV{'PBPROJTAG'};
662                }
663
664                $pbrev = $ENV{'PBREVISION'};
665                pb_log(0,"\n");
666                pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
667                die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
668
669                # Clean up dest if necessary. The export will recreate it
670                my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
671                pb_rm_rf($dest) if (-d $dest);
672
673                # Export CMS tree for the concerned package to dest
674                # And generate some additional files
675                $OUTPUT_AUTOFLUSH=1;
676
677                # computes in which dir we have to work
678                my $dir = $defpkgdir->{$pbpkg};
679                $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
680                $dir = $webdir->{$ENV{'PBPROJ'}} if (defined $web);
681                die "Variable \$dir not defined. Please report to dev team with log of a verbose run and this info ".Dumper($webdir) if (not defined $dir);
682                pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
683
684                # Exporting content from CMS
685                my $sourcedir = undef;
686                my $sourceuri = $uri;
687                if ($param eq "SandBox") {
688                        # Point to the local instance
689                        $sourcedir = "$ENV{'PBDIR'}/$dir";
690                } else {
691                        # Get it from a subdir of the URI with same version as localy but different root
692                        $sourceuri = "$ENV{'PBDIR'}/$dir";
693                        $sourceuri =~ s|^$ENV{'PBPROJDIR'}/|$uri|;
694                }
695                my $preserve = pb_cms_export($sourceuri,$sourcedir,$dest);
696
697                # Generated fake content for test versions to speed up stuff
698                my $chglog;
699
700                # Get project info on authors and log file
701                $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
702                $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
703                $chglog = undef if (! -f $chglog);
704
705                my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
706                $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
707                $authors = "/dev/null" if (! -f $authors);
708
709                # Extract cms log history and store it
710                if ((defined $chglog) && (! -f "$dest/NEWS")) {
711                        pb_log(2,"Generating NEWS file from $chglog\n");
712                        copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
713                }
714                pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors,$testver);
715
716                my %build;
717                # We want to at least build for the underlying distro
718                my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init();
719                my $tmpl = "$ddir-$dver-$arch,";
720                my %patches;
721
722                # Get list of distributions for which we need to generate build files
723                if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
724                        $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
725                }
726                if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
727                        # The 2 lists needs to be grouped with a ',' separating them
728                        if ($tmpl ne "") {
729                                $tmpl .= ",";
730                        }
731                        $tmpl .= $pt[1]->{$ENV{'PBPROJ'}} 
732                }
733       
734                # Setup %pb structure to allow filtering later on, on files using that structure
735                $pb{'tag'} = $pbtag;
736                $pb{'rev'} = $pbrev;
737                $pb{'ver'} = $pbver;
738                $pb{'pkg'} = $pbpkg;
739                $pb{'realpkg'} = $pbpkg;
740                $pb{'date'} = $pbdate;
741                $pb{'defpkgdir'} = $defpkgdir;
742                $pb{'extpkgdir'} = $extpkgdir;
743                $pb{'chglog'} = $chglog;
744                $pb{'packager'} = $ENV{'PBPACKAGER'};
745                $pb{'proj'} = $ENV{'PBPROJ'};
746                $pb{'repo'} = $ENV{'PBREPO'};
747                $pb{'patches'} = \%patches;
748                pb_log(2,"DEBUG: pb: ".Dumper(%pb)."\n");
749       
750                # Do not do that for website
751                if (not defined $web) {
752                        pb_log(0,"Build files are being generated for ...\n");
753                        my %virt;
754                        # De-duplicate similar VM and VE
755                        foreach my $d (split(/,/,$tmpl)) {
756                                # skip ill-formatted vms (name-ver-arch)
757                                next if ($d !~ /-/);
758                                $virt{$d} = $d;
759                        }
760
761                        foreach my $d (keys %virt) {
762                                my ($name,$ver,$arch) = split(/-/,$d);
763                                pb_log(0,"Bad format for $d") if ((not defined $name) || (not defined $ver) || (not defined $arch)) ;
764                                chomp($arch);
765                                my ($ddir, $dver, $dfam);
766                                ($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'os'}, $pb{'suf'}, $pb{'upd'}, $pb{'arch'}) = pb_distro_init($name,$ver,$arch);
767                                pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'suf'})."\n");
768                                pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
769       
770                                # We need to compute the real name of the package
771                                my $pbrealpkg = pb_cms_get_real_pkg($pbpkg,$pb{'dtype'});
772                                $pb{'realpkg'} = $pbrealpkg;
773                                pb_log(1,"Virtual package $pbpkg has a real package name of $pbrealpkg on $ddir-$dver\n") if ($pbrealpkg ne $pbpkg);
774       
775                                # Filter build files from the less precise up to the most with overloading
776                                # Filter all files found, keeping the name, and generating in dest
777       
778                                # Find all build files first relatively to PBROOTDIR
779                                # Find also all specific files referenced in the .pb conf file
780                                my %bfiles = ();
781                                my %pkgfiles = ();
782                                $build{"$ddir-$dver-$arch"} = "yes";
783       
784                                if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}") {
785                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
786                                } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
787                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
788                                } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
789                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
790                                } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
791                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
792                                } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch") {
793                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
794                                } else {
795                                        $build{"$ddir-$dver-$arch"} = "no";
796                                        next;
797                                }
798                                pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
799       
800                                # Get all filters to apply
801                                my $ptr = pb_get_filters($pbpkg, $pb{'dtype'}, $dfam, $ddir, $dver);
802       
803                                # Prepare local patches for this distro - They are always applied first - May be a problem one day
804                                foreach my $p (sort(<$ENV{'PBROOTDIR'}/$pbpkg/pbpatch/*>)) {
805                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.all$/));
806                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.all$/);
807                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$pb{'dtype'}$/));
808                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$pb{'dtype'}$/);
809                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$dfam$/));
810                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$dfam$/);
811                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir$/));
812                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir$/);
813                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver$/));
814                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver$/);
815                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver-$arch$/));
816                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver-$arch$/);
817                                }
818       
819                                # Prepare also remote patches to be included - Applied after the local ones
820                                foreach my $p ("all","$pb{'dtype'}","$dfam","$ddir","$ddir-$dver","$ddir-$dver-$arch") {
821                                        my $f = "$ENV{'PBROOTDIR'}/$pbpkg/pbextpatch.$p";
822                                        next if (not -f $f);
823                                        if (not open(PATCH,$f)) {
824                                                pb_display("Unable to open existing external patch file content $f\n");
825                                                next;
826                                        }
827                                        while (<PATCH>) {
828                                                chomp();
829                                                $patches{"$ddir-$dver-$arch"} .= "," if (defined $patches{"$ddir-$dver-$arch"});
830                                                $patches{"$ddir-$dver-$arch"} .= "$_";
831                                        }
832                                        close(PATCH);
833                                }
834                                pb_log(2,"DEBUG: pb->patches: ".Dumper($pb{'patches'})."\n");
835       
836                                # Apply now all the filters on all the files concerned
837                                # destination dir depends on the type of file
838                                if (defined $ptr) {
839                                        # For patch support
840                                        $pb{'tuple'} = "$ddir-$dver-$arch";
841                                        foreach my $f (values %bfiles,values %pkgfiles) {
842                                                pb_filter_file("$ENV{'PBROOTDIR'}/$f",$ptr,"$dest/pbconf/$ddir-$dver-$arch/".basename($f),\%pb);
843                                        }
844                                }
845                        }
846                        my @found;
847                        my @notfound;
848                        foreach my $b (keys %build) {
849                                push @found,$b if ($build{$b} =~ /yes/);
850                                push @notfound,$b if ($build{$b} =~ /no/);
851                        }
852                        pb_log(0," ... ".join(',',sort(@found))."\n");
853                        pb_log(0,"No Build files found for ".join(',',sort(@notfound))."\n") if (@notfound);
854                        pb_log(2,"DEBUG: patches: ".Dumper(%patches)."\n");
855                }
856
857                # Get the generic filter (all.pbf) and
858                # apply those to the non-build files including those
859                # generated by pbinit if applicable
860
861                # Get only all.pbf filter
862                my $ptr = pb_get_filters($pbpkg);
863
864                my $liste ="";
865                if (defined $filteredfiles->{$pbpkg}) {
866                        foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
867                                pb_filter_file_inplace($ptr,"$dest/$f",\%pb);
868                                $liste = "$f $liste";
869                        }
870                }
871                pb_log(2,"Files ".$liste."have been filtered\n");
872
873                # Do not do that for website
874                if (not defined $web) {
875                        my %tmp;
876                        my $warnflag = 0;
877                        # Filter potential patches (local + remote)
878                        pb_log(0,"Delivering and compressing patches ");
879                        foreach my $v (keys %patches) {
880                                pb_mkdir_p("$dest/pbconf/$v/pbpatch");
881                                foreach my $pf (split(/,/,$patches{$v})) {
882                                        my $pp = basename($pf);
883                                        if ($param eq "SandBox") {
884                                                $warnflag = 1;
885                                        }
886                                        pb_cms_export($pf,undef,"$dest/pbconf/$v/pbpatch");
887                                        pb_filter_file_inplace($ptr,"$dest/pbconf/$v/pbpatch/$pp",\%pb);
888                                        pb_system("gzip -9f $dest/pbconf/$v/pbpatch/$pp","","quiet");
889                                        $tmp{$pf} = "";
890                                }
891                        }
892                        foreach my $v (keys %tmp) {
893                                pb_log(0,"$v ");
894                        }
895                        pb_log(0,"\n");
896                        pb_log(0,"WARNING: Patches are always taken from repository not local export\n") if ($warnflag == 1);
897                } else {
898                        # Instead call News generation
899                        pb_web_news2html($dest);
900                        # And create an empty pbconf
901                        pb_mkdir_p("$dest/pbconf");
902                        # And prepare the pbscript to execute remotely
903                        open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
904                        print SCRIPT "#!/bin/bash\n";
905                        print SCRIPT "#set -x\n";
906                        print SCRIPT "echo ... Extracting Website content\n";
907                        print SCRIPT "find . -type f | grep -Ev '^./$pbpkg-$pbver.tar.gz|^./pbscript' | xargs rm -f non-existent\n";
908                        print SCRIPT "find * -type d -depth | xargs rmdir 2> /dev/null \n";
909                        print SCRIPT "tar xfz $pbpkg-$pbver.tar.gz\n";
910                        print SCRIPT "mv $pbpkg-$pbver/* .\n";
911                        print SCRIPT "rm -f $pbpkg-$pbver.tar.gz\n";
912                        print SCRIPT "rmdir $pbpkg-$pbver\n";
913                        close(SCRIPT);
914                }
915
916                # Prepare the dest directory for archive
917                if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
918                        pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",\%pb);
919                        chmod 0755,"$ENV{'PBTMP'}/pbinit";
920                        pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit","verbose");
921                }
922
923                # Do we have additional script to run to prepare the environement for the project ?
924                # Then include it in the pbconf delivery
925                foreach my $pbvf (<$ENV{'PBROOTDIR'}/pbv*.pre>,<$ENV{'PBROOTDIR'}/pbv*.post>, <$ENV{'PBROOTDIR'}/pbtest*>) {
926                        if (-x "$pbvf") {
927                                my $target = "$ENV{'PBDESTDIR'}/".basename($pbvf);
928                                pb_filter_file("$pbvf",$ptr,$target,\%pb);
929                                chmod 0755,"$target";
930                        }
931                }
932
933                # Archive dest dir
934                chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
935                if (defined $preserve) {
936                        # In that case we want to preserve the original tar file for checksum purposes
937                        # The one created is btw equivalent in that case to this one
938                        # Maybe check basename of both to be sure they are the same ?
939                        pb_log(0,"Preserving original tar file ");
940                        move("$preserve","$pbpkg-$pbver.tar.gz");
941                } else {
942                        # Possibility to look at PBSRC to guess more the filename
943                        pb_system("tar cfz $pbpkg-$pbver.tar.gz --exclude=$pbpkg-$pbver/pbconf $pbpkg-$pbver","Creating $pbpkg tar files compressed");
944                }
945                pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
946                pb_system("tar cfz $pbpkg-$pbver.pbconf.tar.gz $pbpkg-$pbver/pbconf","Creating pbconf tar files compressed");
947                pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz\n");
948
949                # Keep track of version-tag per pkg
950                $pkgs{$pbpkg} = "$pbver-$pbtag";
951
952                # Final cleanup
953                pb_rm_rf($dest) if (-d $dest);
954        }
955
956        # Keep track of per package version
957        pb_log(2,"DEBUG pkgs: ".Dumper(%pkgs)."\n");
958        open(PKG,"> $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb";
959        foreach my $pbpkg (keys %pkgs) {
960                print PKG "pbpkg $pbpkg = $pkgs{$pbpkg}\n";
961        }
962        close(PKG);
963
964        # Keep track of what is generated by default
965        # We need to store the dir and info on version-tag
966        # Base our content on the existing .pb file
967        copy("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb","$ENV{'PBDESTDIR'}/pbrc");
968        open(LAST,">> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
969        print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
970        print LAST "projver $ENV{'PBPROJ'} = $ENV{'PBPROJVER'}\n";
971        print LAST "projtag $ENV{'PBPROJ'} = $ENV{'PBPROJTAG'}\n";
972        print LAST "pbpackager $ENV{'PBPROJ'} = $ENV{'PBPACKAGER'}\n";
973        close(LAST);
974}
975
976sub pb_test2pkg {
977        # Get the running distro to test on
978        my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init();
979        pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $arch))."\n");
980
981        # Get list of packages to test
982        # Get content saved in cms2build
983        my $ptr = pb_get_pkg();
984        @pkgs = @$ptr;
985
986        # Additional potential repo
987        pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
988        foreach my $pbpkg (@pkgs) {
989                # We need to install the package to test, and deps brought with it
990                pb_distro_installdeps(undef,$dtype,$pbins,$pbpkg);
991                pb_system("$ENV{'PBDESTDIR'}/pbtest","Launching test for $pbpkg","verbose");
992        }
993}
994
995sub pb_build2pkg {
996
997        # Get the running distro to build on
998        my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init();
999        pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $arch))."\n");
1000
1001        # Get list of packages to build
1002        my $ptr = pb_get_pkg();
1003        @pkgs = @$ptr;
1004
1005        # Get content saved in cms2build
1006        my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1007        $pkg = { } if (not defined $pkg);
1008
1009        chdir "$ENV{'PBBUILDDIR'}";
1010        my $made = ""; # pkgs made during build
1011        foreach my $pbpkg (@pkgs) {
1012                my $vertag = $pkg->{$pbpkg};
1013                # get the version of the current package - maybe different
1014                ($pbver,$pbtag) = split(/-/,$vertag);
1015
1016                my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
1017                my $src2="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
1018                pb_log(2,"Source file: $src\n");
1019                pb_log(2,"Pbconf file: $src2\n");
1020
1021                pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
1022                if ($dtype eq "rpm") {
1023                        foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
1024                                if (! -d "$ENV{'PBBUILDDIR'}/$d") {
1025                                pb_mkdir_p("$ENV{'PBBUILDDIR'}/$d") || die "Please ensure that you can write into $ENV{'PBBUILDDIR'} to create $d\nchown the $ENV{'PBBUILDDIR'} directory to your uid";
1026                                }
1027                        }
1028
1029                        # Remove in case a previous link/file was there
1030                        unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
1031                        symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
1032                        # We need to first extract the spec file
1033                        my @specfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$ENV{'PBBUILDDIR'}/SPECS","spec");
1034
1035                        # We need to handle potential patches to upstream sources
1036                        pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/pbpatch/","$ENV{'PBBUILDDIR'}/SOURCES","patch");
1037
1038                        pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
1039                        # set LANGUAGE to check for correct log messages
1040                        $ENV{'LANGUAGE'}="C";
1041                        # Older Redhat use _target_platform in %configure incorrectly
1042                        my $specialdef = "";
1043                        if (($ddir eq "redhat") || (($ddir eq "rhel") && ($dver eq "2.1"))) {
1044                                $specialdef = "--define \'_target_platform \"\"\'";
1045                        }
1046
1047                        # If needed we may add repository to the build env
1048                        pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
1049                        foreach my $f (@specfile) {
1050                                if ($f =~ /\.spec$/) {
1051                                        pb_distro_installdeps($f,$dtype,$pbins);
1052                                        pb_system("rpmbuild $specialdef --define \"packager $ENV{'PBPACKAGER'}\" --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}","verbose");
1053                                        last;
1054                                }
1055                        }
1056                        # Get the name of the generated packages
1057                        open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to open $ENV{'PBTMP'}/system.log";
1058                        while (<LOG>) {
1059                                chomp($_);
1060                                next if ($_ !~ /^Wrote:/);
1061                                s|.*/([S]*RPMS.*)|$1|;
1062                                $made .=" $_";
1063                        }
1064                        close(LOG);
1065
1066                } elsif ($dtype eq "deb") {
1067                        chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1068                        pb_system("tar xfz $src","Extracting sources");
1069                        pb_system("tar xfz $src2","Extracting pbconf");
1070
1071                        chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1072                        pb_rm_rf("debian");
1073                        symlink "pbconf/$ddir-$dver-$arch","debian" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
1074                        chmod 0755,"debian/rules";
1075
1076                        pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
1077                        pb_distro_installdeps("debian/control",$dtype,$pbins);
1078                        pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package","verbose");
1079                        # Get the name of the generated packages
1080                        open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to open $ENV{'PBTMP'}/system.log";
1081                        while (<LOG>) {
1082                                chomp();
1083                                my $tmp = $_;
1084                                next if ($tmp !~ /^dpkg-deb.*:/);
1085                                $tmp =~ s|.*../(.*)_(.*).deb.*|$1|;
1086                                $made="$made $tmp.dsc $tmp.tar.gz $tmp"."_*.deb $tmp"."_*.changes";
1087                        }
1088                        close(LOG);
1089                } elsif ($dtype eq "ebuild") {
1090                        my @ebuildfile;
1091                        # For gentoo we need to take pb as subsystem name
1092                        # We put every apps here under sys-apps. hope it's correct
1093                        # We use pb's home dir in order to have a single OVERLAY line
1094                        my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
1095                        pb_mkdir_p($tmpd) if (! -d "$tmpd");
1096                        pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
1097
1098                        # We need to first extract the ebuild file
1099                        @ebuildfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$tmpd","ebuild");
1100
1101                        # Prepare the build env for gentoo
1102                        my $found = 0;
1103                        my $pbbd = $ENV{'HOME'};
1104                        $pbbd =~ s|/|\\/|g;
1105                        if (-r "/etc/make.conf") {
1106                                open(MAKE,"/etc/make.conf");
1107                                while (<MAKE>) {
1108                                        $found = 1 if (/$pbbd\/portage/);
1109                                }
1110                                close(MAKE);
1111                        }
1112                        if ($found == 0) {
1113                                pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
1114                        }
1115                        #$found = 0;
1116                        #if (-r "/etc/portage/package.keywords") {
1117                        #open(KEYW,"/etc/portage/package.keywords");
1118                        #while (<KEYW>) {
1119                        #$found = 1 if (/portage\/pb/);
1120                        #}
1121                        #close(KEYW);
1122                        #}
1123                        #if ($found == 0) {
1124                        #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
1125                        #}
1126
1127                        # Build
1128                        foreach my $f (@ebuildfile) {
1129                                if ($f =~ /\.ebuild$/) {
1130                                        pb_distro_installdeps($f,$dtype,$pbins);
1131                                        move($f,"$tmpd/$pbpkg-$pbver.ebuild");
1132                                        pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package","verbose");
1133                                        # Now move it where pb expects it
1134                                        pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
1135                                        move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver-r$pbtag.ebuild");
1136                                }
1137                        }
1138
1139                        $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver-r$pbtag.ebuild";
1140                } elsif ($dtype eq "tgz") {
1141                        # Slackware family
1142                        $made="$made $pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
1143
1144                        chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1145                        pb_system("tar xfz $src","Extracting sources");
1146                        pb_system("tar xfz $src2","Extracting pbconf");
1147                        chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1148                        symlink "pbconf/$ddir-$dver-$arch","install" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
1149                        if (-x "install/pbslack") {
1150                                pb_distro_installdeps("./install/pbslack",$dtype,$pbins);
1151                                pb_system("./install/pbslack","Building software");
1152                                pb_system("sudo /sbin/makepkg -p -l y -c y $pbpkg","Packaging $pbpkg","verbose");
1153                        }
1154                } elsif ($dtype eq "pkg") {
1155                        # Solaris
1156                        $made="$made $pbpkg-$pbver-$pbtag.pkg.gz";
1157                        my $pkgdestdir="$ENV{'PBBUILDDIR'}/install";
1158
1159                        chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1160                        # Will host resulting packages
1161                        pb_mkdir_p("$dtype");
1162                        pb_mkdir_p("$pkgdestdir/delivery");
1163                        pb_system("tar xfz $src","Extracting sources under $ENV{'PBBUILDDIR'}");
1164                        pb_system("tar xfz $src2","Extracting pbconf under $ENV{'PBBUILDDIR'}");
1165                        chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1166                        if (-f "pbconf/$ddir-$dver-$arch/pbbuild") {
1167                                chmod 0755,"pbconf/$ddir-$dver-$arch/pbbuild";
1168                                # pkginfo file is mandatory
1169                                die "Unable to find pkginfo file in pbconf/$ddir-$dver-$arch" if (! -f "pbconf/$ddir-$dver-$arch/pkginfo");
1170                                # Build
1171                                pb_system("pbconf/$ddir-$dver-$arch/pbbuild $pkgdestdir/delivery","Building software and installing under $pkgdestdir/delivery");
1172                                # Copy complementary files
1173                                if (-f "pbconf/$ddir-$dver-$arch/prototype") {
1174                                        copy("pbconf/$ddir-$dver-$arch/prototype", $pkgdestdir) 
1175                                } else {
1176                                        # No prototype provided, calculating it
1177                                        open(PROTO,"> $pkgdestdir/prototype") || die "Unable to create prototype file";
1178                                        print PROTO "i pkginfo\n";
1179                                        print PROTO "i depend\n" if (-f "pbconf/$ddir-$dver-$arch/depend");
1180                                        $ENV{'PBSOLDESTDIR'} = "$pkgdestdir/delivery";
1181                                        find(\&create_solaris_prototype, "$pkgdestdir/delivery");
1182                                }
1183                                copy("pbconf/$ddir-$dver-$arch/depend", $pkgdestdir) if (-f "pbconf/$ddir-$dver-$arch/depend");
1184                                copy("pbconf/$ddir-$dver-$arch/pkginfo", $pkgdestdir);
1185                                pb_system("cd $pkgdestdir/delivery ; pkgmk -o -f ../prototype -r $pkgdestdir/delivery -d $ENV{'PBBUILDDIR'}/$dtype","Packaging $pbpkg","verbose");
1186                                pb_system("cd $ENV{'PBBUILDDIR'}/$dtype ;  echo \"\" | pkgtrans -o -n -s $ENV{'PBBUILDDIR'}/$dtype $ENV{'PBBUILDDIR'}/$pbpkg-$pbver-$pbtag.pkg all","Transforming $pbpkg","verbose");
1187                                pb_system("cd $ENV{'PBBUILDDIR'} ;  gzip -9f $pbpkg-$pbver-$pbtag.pkg","Compressing $pbpkg-$pbver-$pbtag.pkg","verbose");
1188                        } else {
1189                                pb_log(0,"No pbconf/$ddir-$dver-$arch/pbbuild file found for $pbpkg-$pbver in \n");
1190                        }
1191                        chdir ".." || die "Unable to chdir to parent dir";
1192                        pb_system("rm -rf $pbpkg-$pbver $ENV{'PBBUILDDIR'}/$dtype $pkgdestdir", "Cleanup");
1193                } else {
1194                        die "Unknown dtype format $dtype";
1195                }
1196        }
1197        # Find the appropriate check cmd/opts
1198        my ($oschkcmd,$oschkopt) = pb_conf_get_if("oschkcmd","oschkopt");
1199        my $chkcmd .= pb_distro_get_param($ddir,$dver,$arch,$oschkcmd,$dtype,$dfam,$dos);
1200        my $chkopt .= pb_distro_get_param($ddir,$dver,$arch,$oschkopt,$dtype,$dfam,$dos);
1201
1202        # Packages check if needed
1203        if ($dtype eq "rpm") {
1204                if (-x $chkcmd) {
1205                        pb_system("$chkcmd $chkopt $made","Checking validity of rpms with $chkcmd","verbose");
1206                }
1207                my $rpms ="";
1208                my $srpms ="";
1209                foreach my $f (split(/ /,$made)) {
1210                        $rpms .= "$ENV{'PBBUILDDIR'}/$f " if ($f =~ /^RPMS\//);
1211                        $srpms .= "$ENV{'PBBUILDDIR'}/$f " if ($f =~ /^SRPMS\//);
1212                }
1213                pb_log(0,"SRPM packages generated: $srpms\n");
1214                pb_log(0,"RPM packages generated: $rpms\n");
1215        } elsif ($dtype eq "deb") {
1216                my $made2 = "";
1217                foreach my $f (split(/ /,$made)) {
1218                        $made2 .= "../$f " if ($f =~ /\.changes$/);
1219                }
1220                if (-x $chkcmd) {
1221                        pb_system("$chkcmd $chkopt $made2","Checking validity of debs with $chkcmd","verbose");
1222                } else {
1223                        pb_log(0,"deb packages generated: $made2\n");
1224                }
1225        } else {
1226                pb_log(0,"No check done for $dtype yet\n");
1227                pb_log(0,"Packages generated: $made\n");
1228        }
1229
1230        # Keep track of what is generated so that we can get them back from VMs
1231        open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1232        print KEEP "$made\n";
1233        close(KEEP);
1234}
1235
1236sub create_solaris_prototype {
1237
1238        my $uidgid = "bin bin";
1239        my $pkgdestdir = $ENV{'PBSOLDESTDIR'};
1240
1241        return if ($_ =~ /^$pkgdestdir$/);
1242        if (-d $_) {
1243                my $n = $File::Find::name;
1244                $n =~ s~$pkgdestdir/~~;
1245                print PROTO "d none $n 0755 $uidgid\n";
1246        } elsif (-x $_) {
1247                my $n = $File::Find::name;
1248                $n =~ s~$pkgdestdir/~~;
1249                print PROTO "f none $n 0755 $uidgid\n";
1250        } elsif (-f $_) {
1251                my $n = $File::Find::name;
1252                $n =~ s~$pkgdestdir/~~;
1253                print PROTO "f none $n 0644 $uidgid\n";
1254        }
1255}
1256
1257sub pb_build2ssh {
1258        pb_send2target("Sources");
1259}
1260
1261sub pb_pkg2ssh {
1262        pb_send2target("Packages");
1263}
1264
1265# By default deliver to the the public site hosting the
1266# ftp structure (or whatever) or a VM/VE
1267sub pb_send2target {
1268
1269        my $cmt = shift;
1270        my $v = shift || undef;
1271        my $vmexist = shift || 0;                       # 0 is FALSE
1272        my $vmpid = shift || 0;                         # 0 is FALSE
1273        my $snapme = shift || 0;                        # 0 is FALSE
1274
1275        pb_log(2,"DEBUG: pb_send2target($cmt,".Dumper($v).",$vmexist,$vmpid)\n");
1276        my $host = "sshhost";
1277        my $login = "sshlogin";
1278        my $dir = "sshdir";
1279        my $port = "sshport";
1280        my $conf = "sshconf";
1281        my $tmout = undef;
1282        my $path = undef;
1283        if ($cmt =~ /^VM/) {
1284                $login = "vmlogin";
1285                $dir = "pbdefdir";
1286                # Specific VM
1287                $tmout = "vmtmout";
1288                $path = "vmpath";
1289                $host = "vmhost";
1290                $port = "vmport";
1291        } elsif ($cmt =~ /^VE/) {
1292                $login = "velogin";
1293                $dir = "pbdefdir";
1294                # Specific VE
1295                $path = "vepath";
1296                $conf = "rbsconf";
1297        } elsif ($cmt eq "Web") {
1298                $host = "websshhost";
1299                $login = "websshlogin";
1300                $dir = "websshdir";
1301                $port = "websshport";
1302        }
1303        my $cmd = "";
1304        my $src = "";
1305        my ($odir,$over,$oarch) = (undef, undef, undef);
1306        my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch);
1307
1308        if ($cmt ne "Announce") {
1309                # Get list of packages to build
1310                my $ptr = pb_get_pkg();
1311                @pkgs = @$ptr;
1312
1313                # Get the running distro to consider
1314                if (defined $v) {
1315                        ($odir,$over,$oarch) = split(/-/,$v);
1316                }
1317                ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch) = pb_distro_init($odir,$over,$oarch);
1318                pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $darch))."\n");
1319
1320                # Get list of packages to build
1321                # Get content saved in cms2build
1322                my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1323                $pkg = { } if (not defined $pkg);
1324
1325                chdir "$ENV{'PBBUILDDIR'}";
1326                foreach my $pbpkg (@pkgs) {
1327                        my $vertag = $pkg->{$pbpkg};
1328                        # get the version of the current package - maybe different
1329                        ($pbver,$pbtag) = split(/-/,$vertag);
1330
1331                        if (($cmt eq "Sources") || ($cmt =~ /V[EM]build/)) {
1332                                $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
1333                                if ($cmd eq "") {
1334                                        $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1335                                } else {
1336                                        $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1337                                }
1338                        } elsif ($cmt eq "Web") {
1339                                $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz"
1340                        }
1341                }
1342                # Adds conf file for availability of conf elements
1343                pb_conf_add("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb");
1344        }
1345
1346        if ($cmt =~ /V[EM]build/) {
1347                $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript";
1348        } elsif (($cmt =~ /V[EM]Script/) || ($cmt eq "Web")) {
1349                $src="$src $ENV{'PBDESTDIR'}/pbscript";
1350        } elsif ($cmt =~ /V[EM]test/) {
1351                $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript $ENV{'PBDESTDIR'}/pbtest";
1352        } elsif ($cmt eq "Announce") {
1353                $src="$src $ENV{'PBTMP'}/pbscript";
1354        } elsif ($cmt eq "Packages") {
1355                # Get package list from file made during build2pkg
1356                open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1357                $src = <KEEP>;
1358                chomp($src);
1359                close(KEEP);
1360                $src="$src $ENV{'PBBUILDDIR'}/pbscript";
1361        }
1362        # Remove potential leading spaces (cause problem with basename)
1363        $src =~ s/^ *//;
1364        my $basesrc = "";
1365        foreach my $i (split(/ +/,$src)) {
1366                $basesrc .= " ".basename($i);
1367        }
1368
1369        pb_log(0,"Sources handled ($cmt): $src\n");
1370        pb_log(2,"values: ".Dumper(($host,$login,$dir,$port,$tmout,$path,$conf))."\n");
1371        my ($sshhost,$sshlogin,$sshdir,$sshport) = pb_conf_get($host,$login,$dir,$port);
1372        # Not mandatory...
1373        my ($rbsconf,$testver,$delivery) = pb_conf_get_if($conf,"testver","delivery");
1374        $delivery->{$ENV{'PBPROJ'}} = "" if (not defined $delivery->{$ENV{'PBPROJ'}});
1375        my ($vtmout,$vepath);
1376        # ...Except those in virtual context
1377        if ($cmt =~ /^VE/) {
1378                ($vepath) = pb_conf_get($path);
1379        }
1380        if ($cmt =~ /^VM/) {
1381                ($vtmout) = pb_conf_get($tmout);
1382        }
1383        pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vepath,$rbsconf))."\n");
1384
1385        my $mac;
1386        if ($cmt !~ /^VE/) {
1387                $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
1388                # Overwrite account value if passed as parameter
1389                $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
1390                pb_log(2, "DEBUG: pbaccount: $pbaccount => mac: $mac\n") if (defined $pbaccount);
1391        } else {
1392                # VE
1393                # Overwrite account value if passed as parameter (typically for setup2ve)
1394                $mac = $sshlogin->{$ENV{'PBPROJ'}};
1395                $mac = $pbaccount if (defined $pbaccount);
1396        }
1397
1398        my $tdir;
1399        my $bdir;
1400        if (($cmt eq "Sources") || ($cmt =~ /V[EM]Script/)) {
1401                $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}/src";
1402        } elsif (($cmt =~ /V[EM]build/)  || ($cmt =~ /V[EM]test/)) {
1403                $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
1404                $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
1405                # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
1406                $bdir =~ s|\$ENV.+\}/||;
1407        } elsif ($cmt eq "Announce") {
1408                $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}";
1409        } elsif ($cmt eq "Web") {
1410                $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}";
1411        } elsif ($cmt eq "Packages") {
1412                $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch";
1413
1414                my $repodir = $tdir;
1415                $repodir =~ s|^$sshdir->{$ENV{'PBPROJ'}}/||;
1416
1417                my ($pbrepo) = pb_conf_get("pbrepo");
1418
1419                # Repository management
1420                open(PBS,"> $ENV{'PBBUILDDIR'}/pbscript") || die "Unable to create $ENV{'PBBUILDDIR'}/pbscript";
1421                if ($dtype eq "rpm") {
1422                        # Also make a pbscript to generate yum/urpmi bases
1423                        print PBS << "EOF";
1424#!/bin/bash
1425# Prepare a script to ease yum setup
1426cat > $ENV{'PBPROJ'}.repo << EOT
1427[$ENV{'PBPROJ'}]
1428name=$ddir $dver $darch - $ENV{'PBPROJ'} Vanilla Packages
1429baseurl=$pbrepo->{$ENV{'PBPROJ'}}/$repodir
1430enabled=1
1431gpgcheck=0
1432EOT
1433chmod 644 $ENV{'PBPROJ'}.repo
1434
1435# Clean up old repo content
1436rm -rf headers/ repodata/
1437# Create yum repo
1438if [ -x /usr/bin/yum-arch ]; then
1439        yum-arch .
1440fi
1441# Create repodata
1442createrepo .
1443EOF
1444                        if ($dfam eq "md") {
1445                                # For Mandriva add urpmi management
1446                                print PBS << "EOF";
1447# Prepare a script to ease urpmi setup
1448cat > $ENV{'PBPROJ'}.addmedia << EOT
1449urpmi.addmedia $ENV{'PBPROJ'} $pbrepo->{$ENV{'PBPROJ'}}/$repodir with media_info/hdlist.cz
1450EOT
1451chmod 755 $ENV{'PBPROJ'}.addmedia
1452
1453# Clean up old repo content
1454rm -f hdlist.cz synthesis.hdlist.cz
1455# Create urpmi repo
1456genhdlist2 --clean .
1457if [ \$\? -ne 0 ]; then
1458        genhdlist .
1459fi
1460EOF
1461                        }
1462                        if ($ddir eq "fedora") {
1463                                # Extract the spec file to please Fedora maintainers :-(
1464                                print PBS << "EOF";
1465for p in $basesrc; do
1466        echo \$p | grep -q 'src.rpm'
1467        if [ \$\? -eq 0 ]; then
1468                rpm2cpio \$p | cpio -ivdum --quiet '*.spec'
1469        fi
1470done
1471EOF
1472                        }
1473                        if ($dfam eq "novell") {
1474                                # Add ymp scripts for one-click install on SuSE
1475                                print PBS << "EOF";
1476# Prepare a script to ease SuSE one-click install
1477# Cf: http://de.opensuse.org/1-Klick-Installation/ISV
1478#
1479cat > $ENV{'PBPROJ'}.ymp << EOT
1480<?xml version="1.0" encoding="utf-8"?>
1481<!-- vim: set sw=2 ts=2 ai et: -->
1482<metapackage xmlns:os="http://opensuse.org/Standards/One_Click_Install" xmlns="http://opensuse.org/Standards/One_Click_Install">
1483        <group><!-- The group of software, typically one for project-builder.org -->
1484                <name>$ENV{'PBPROJ'} Bundle</name> <!-- Name of the software group -->
1485                <summary>Software bundle for the $ENV{'PBPROJ'} project</summary> <!--This message is shown to the user and should describe the whole bundle -->
1486                <description>This is the summary of the $ENV{'PBPROJ'} Project
1487                     
1488                        Details are available on a per package basis below
1489
1490                </description><!--This is also shown to the user -->
1491                <remainSubscribed>false</remainSubscribed> <!-- Don't know what it mean -->
1492                <repositories><!-- List of needed repositories -->
1493                        <repository>
1494                                <name>$ENV{'PBPROJ'} Repository</name> <!-- Name of the repository  -->
1495                                <summary>This repository contains the $ENV{'PBPROJ'} project packages.</summary> <!-- Summary of the repository -->
1496                                <description>This repository contains the $ENV{'PBPROJ'} project packages.</description><!-- This description is shown to the user -->
1497                                <url>$pbrepo->{$ENV{'PBPROJ'}}/$repodir</url><!--URL of repository, which is added -->
1498                        </repository>
1499                </repositories>
1500                <software><!-- A List of packages, which should be added through the one-click-installation -->
1501EOT
1502for p in $basesrc; do
1503        sum=`rpm -q --qf '%{SUMMARY}' \$p`
1504        name=`rpm -q --qf '%{NAME}' \$p`
1505        desc=`rpm -q --qf '%{description}' \$p`
1506        cat >> $ENV{'PBPROJ'}.ymp << EOT
1507                        <item>
1508                                <name>\$name</name><!-- Name of the package, is shown to the user and used to identify the package at the repository -->
1509                                <summary>\$sum</summary> <!-- Summary of the package -->
1510                                <description>\$desc</description> <!-- Description, is shown to the user -->
1511                        </item>
1512EOT
1513done
1514cat >> $ENV{'PBPROJ'}.ymp << EOT
1515                </software>
1516        </group>
1517</metapackage>
1518EOT
1519chmod 644 $ENV{'PBPROJ'}.ymp
1520EOF
1521                        }
1522                } elsif ($dtype eq "deb") {
1523                        # Also make a pbscript to generate apt bases
1524                        # Cf: http://www.debian.org/doc/manuals/repository-howto/repository-howto.fr.html
1525                        my $rpd = dirname("$pbrepo->{$ENV{'PBPROJ'}}/$repodir");
1526                        print PBS << "EOF";
1527#!/bin/bash
1528# Prepare a script to ease apt setup
1529cat > $ENV{'PBPROJ'}.sources.list << EOT
1530deb $rpd $dver contrib
1531deb-src $rpd $dver contrib
1532EOT
1533chmod 644 $ENV{'PBPROJ'}.sources.list
1534
1535# Up two levels to deal with the dist dir cross versions
1536cd ../..
1537mkdir -p dists/$dver/contrib/binary-$darch dists/$dver/contrib/source
1538
1539# Prepare a script to create apt info file
1540TMPD=`mktemp -d /tmp/pb.XXXXXXXXXX` || exit 1
1541mkdir -p \$TMPD
1542cat > \$TMPD/Release << EOT
1543Archive: unstable
1544Component: contrib
1545Origin: $ENV{'PBPROJ'}
1546Label: $ENV{'PBPROJ'} dev repository $pbrepo->{$ENV{'PBPROJ'}}
1547EOT
1548
1549echo "Creating Packages metadata ($darch)"
1550dpkg-scanpackages -a$darch $dver/$darch /dev/null | gzip -c9 > dists/$dver/contrib/binary-$darch/Packages.gz
1551dpkg-scanpackages -a$darch $dver/$darch /dev/null | bzip2 -c9 > dists/$dver/contrib/binary-$darch/Packages.bz2
1552echo "Creating Contents metadata ($darch)"
1553apt-ftparchive contents $dver | gzip -c9 > dists/$dver/contrib/Contents-$darch.gz
1554echo "Creating Release metadata ($darch)"
1555cat \$TMPD/Release > dists/$dver/contrib/binary-$darch/Release
1556echo "Architecture: $darch" >> dists/$dver/contrib/binary-$darch/Release
1557echo "Creating Source metadata"
1558dpkg-scansources $dver/$darch /dev/null | gzip -c9 > dists/$dver/contrib/source/Sources.gz
1559cat \$TMPD/Release > dists/$dver/contrib/source/Release
1560echo "Architecture: Source" >> dists/$dver/contrib/source/Release
1561echo "Creating Release metadata"
1562apt-ftparchive release dists/$dver > dists/$dver/Release
1563rm -rf \$TMPD
1564EOF
1565                } elsif ($dtype eq "ebuild") {
1566                        # make a pbscript to generate links to latest version
1567                        print PBS << "EOF";
1568#!/bin/bash
1569# Prepare a script to create correct links
1570for p in $src; do
1571        echo \$p | grep -q '.ebuild'
1572        if [ \$\? -eq 0 ]; then
1573                j=`basename \$p`
1574                pp=`echo \$j | cut -d'-' -f1`
1575                ln -sf \$j \$pp.ebuild
1576        fi
1577done
1578EOF
1579                }
1580                close(PBS);
1581                chmod 0755,"$ENV{'PBBUILDDIR'}/pbscript";
1582        } else {
1583                return;
1584        }
1585
1586        # Useless for VE
1587        my $nport;
1588        if ($cmt !~ /^VE/) {
1589                $nport = $sshport->{$ENV{'PBPROJ'}};
1590                $nport = "$pbport" if (defined $pbport);
1591        }
1592
1593        # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
1594        $tdir =~ s|\$ENV.+\}/||;
1595
1596        my $tm = undef;
1597        if ($cmt =~ /^VM/) {
1598                $tm = $vtmout->{$ENV{'PBPROJ'}};
1599        }
1600
1601        # ssh communication if not VE
1602        # should use a hash instead...
1603        my ($shcmd,$cpcmd,$cptarget,$cp2target);
1604        if ($cmt !~ /^VE/) {
1605                my $keyfile = pb_ssh_get(0);
1606                $shcmd = "ssh -i $keyfile -q -o UserKnownHostsFile=/dev/null -p $nport $mac";
1607                $cpcmd = "scp -i $keyfile -p -o UserKnownHostsFile=/dev/null -P $nport";
1608                $cptarget = "$mac:$tdir";
1609                if ($cmt =~ /^VMbuild/) {
1610                        $cp2target = "$mac:$bdir";
1611                }
1612        } else {
1613                my $tp = $vepath->{$ENV{'PBPROJ'}};
1614                ($odir,$over,$oarch) = split(/-/,$v);
1615                my $tpdir = "$tp/$odir/$over/$oarch";
1616                my ($ptr) = pb_conf_get("vetype");
1617                my $vetype = $ptr->{$ENV{'PBPROJ'}};
1618                if ($vetype eq "chroot") {
1619                        $shcmd = "sudo chroot $tpdir /bin/su - $mac -c ";
1620                } elsif ($vetype eq "schroot") {
1621                        $shcmd = "schroot $tp -u $mac -- ";
1622                }
1623                $cpcmd = "sudo cp -r ";
1624                # We need to get the home dir of the target account to deliver in the right place
1625                open(PASS,"$tpdir/etc/passwd") || die "Unable to open $tpdir/etc/passwd";
1626                my $homedir = "";
1627                while (<PASS>) {
1628                        my ($c1,$c2,$c3,$c4,$c5,$c6,$c7) = split(/:/);
1629                        $homedir = $c6 if ($c1 =~ /^$mac$/);
1630                        pb_log(3,"Homedir: $homedir - account: $c6\n");
1631                }
1632                close(PASS);
1633                $cptarget = "$tpdir/$homedir/$tdir";
1634                if ($cmt eq "VEbuild") {
1635                        $cp2target = "$tpdir/$homedir/$bdir";
1636                }
1637                pb_log(2,"On VE using $cptarget as target dir to copy to\n");
1638        }
1639
1640        my $logres = "";
1641        # Do not touch when just announcing
1642        if ($cmt ne "Announce") {
1643                pb_system("$shcmd \"mkdir -p $tdir ; cd $tdir ; echo \'for i in $basesrc; do if [ -f \$i ]; then rm -f \$i; fi; done\ ; $cmd' | bash\"","Preparing $tdir on $cptarget");
1644        } else {
1645                $logres = "> ";
1646        }
1647        pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
1648
1649        # For VE we need to change the owner manually
1650        if ($cmt =~ /^VE/) {
1651                pb_system("$shcmd \"sudo chown -R $mac $tdir\"","Adapt owner in $tdir to $mac");
1652        }
1653
1654        pb_system("$shcmd \"echo \'cd $tdir ; if [ -x pbscript ]; then ./pbscript; fi ; rm -f ./pbscript\' | bash\"","Executing pbscript on $cptarget if needed","verbose");
1655        if ($cmt =~ /^V[EM]build/) {
1656                # Get back info on pkg produced, compute their name and get them from the VM
1657                pb_system("$cpcmd $cp2target/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'} $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $cp2target");
1658                # For VE we need to change the owner manually
1659                if ($cmt eq "VEbuild") {
1660                        pb_system("sudo chown $UID $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}","Adapt owner in $tdir to $UID");
1661                }
1662                # return here to avoid breaking the load on VMs/VEs in case of a bad one
1663                if (not -f "$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") {
1664                        pb_log(0,"Problem with VM $v on $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}");
1665                        return;
1666                }
1667                open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1668                my $src = <KEEP>;
1669                chomp($src);
1670                close(KEEP);
1671                $src =~ s/^ *//;
1672                pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
1673                # Change pgben to make the next send2target happy
1674                my $made = "";
1675                open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1676                foreach my $p (split(/ +/,$src)) {
1677                        my $j = basename($p);
1678                        # For VM we don't want shell expansion to hapen locally but remotely
1679                        my $delim = '\'';
1680                        if ($cmt =~ /^VEbuild/) {
1681                                # For VE we need to support shell expansion locally
1682                                $delim = "";
1683                        }       
1684                        pb_system("$cpcmd $cp2target/$delim$p$delim $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Recovery of package $j in $ENV{'PBBUILDDIR'}/$odir/$over");
1685                        $made="$made $odir/$over/$j"; # if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
1686                }
1687                print KEEP "$made\n";
1688                close(KEEP);
1689                pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
1690
1691                # Sign packages locally
1692                if ($dtype eq "rpm") {
1693                                #pb_system("rpm --addsign --define \"_signature gpg\" --define \"_gpg_name $ENV{'PBPACKAGER'}\" --define \"__gpg_sign_cmd /usr/bin/gpg --batch --no-verbose --no-armor --no-tty --no-secmem-warning -sbo %{__signature_filename} %{__plaintext_filename} --use-agent\" $made","Signing RPM packages packages");
1694                } elsif ($dtype eq "deb") {
1695                                #pb_system("debsign $made","Signing DEB packages");
1696                } else {
1697                        pb_log(0,"I don't know yet how to sign packages for type $dtype.\nPlease give feedback to dev team\n");
1698                }
1699
1700                # We want to send them to the ssh account so overwrite what has been done before
1701                undef $pbaccount;
1702                pb_log(2,"Before sending pkgs, vmexist: $vmexist, vmpid: $vmpid\n");
1703                pb_send2target("Packages",$odir."-".$over."-".$oarch,$vmexist,$vmpid);
1704                pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
1705        }
1706        pb_log(2,"Before halt, vmexist: $vmexist, vmpid: $vmpid\n");
1707        if ((! $vmexist) && ($cmt =~ /^VM/)) {
1708                # If in setupvm then takes a snapshot just before halting
1709                if ($snapme != 0) {
1710                        my ($vmmonport,$vmtype) = pb_conf_get("vmmonport","vmtype");
1711                        # For monitoring control
1712                        if ((($vmtype->{$ENV{'PBPROJ'}}) eq "kvm") || (($vmtype->{$ENV{'PBPROJ'}}) eq "qemu")) {
1713                                require Net::Telnet;
1714                                my $t = new Net::Telnet (Timeout => 120, Host => "localhost", Port => $vmmonport->{$ENV{'PBPROJ'}}) || die "Unable to dialog on the monitor";
1715                                # move to monitor mode
1716                                my @lines = $t->cmd("c");
1717                                # Create a snapshot named pb
1718                                @lines = $t->cmd("savevm pb");
1719                                # Write the new status in the VM
1720                                @lines = $t->cmd("commit all");
1721                                # End
1722                                @lines = $t->cmd("quit");
1723                        }
1724                }
1725                my $hoption = "-p";
1726                my $hpath = "/sbin";
1727                # Solaris doesn't support -h and has halt elsewhere
1728                if ($dtype eq "pkg") {
1729                        $hoption = "" ;
1730                        $hpath = "/usr/sbin";
1731                }
1732                pb_system("$shcmd \"sudo $hpath/halt $hoption \"; sleep $tm ; echo \'if [ -d /proc/$vmpid ]; then kill -9 $vmpid; fi \' | bash ; sleep 10","VM $v halt (pid $vmpid)");
1733        }
1734        if (($cmt =~ /^VE/) && ($snapme != 0)) {
1735                ($odir,$over,$oarch) = split(/-/,$v);
1736                my $tpdir = "$vepath->{$ENV{'PBPROJ'}}/$odir/$over/$oarch";
1737                pb_system("sudo tar cz -f $vepath->{$ENV{'PBPROJ'}}/$odir-$over-$oarch.tar.gz -C $tpdir .","Creating a snapshot of $tpdir");
1738        }
1739}
1740
1741sub pb_script2v {
1742        my $pbscript=shift;
1743        my $vtype=shift;
1744        my $pbforce=shift || 0; # Force stop of VM. Default not
1745        my $vm1=shift || undef; # Only that VM to treat
1746        my $snapme=shift || 0;  # Do we have to create a snapshot
1747        my $vm;
1748        my $all;
1749
1750        pb_log(2,"DEBUG: pb_script2v($pbscript,$vtype,$pbforce,".Dumper($vm1).",$snapme)\n");
1751        # Prepare the script to be executed on the VM
1752        # in $ENV{'PBDESTDIR'}/pbscript
1753        if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
1754                copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1755                chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1756        }
1757
1758        if (not defined $vm1) {
1759                ($vm,$all) = pb_get2v($vtype);
1760        } else {
1761                @$vm = ($vm1);
1762        }
1763        my ($vmexist,$vmpid) = (undef,undef);
1764
1765        foreach my $v (@$vm) {
1766                # Launch VM/VE
1767                ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,$snapme,$pbsnap);
1768
1769                if ($vtype eq "vm") {
1770                        pb_log(2,"DEBUG: After pb_launchv, vmexist: $vmexist, vmpid: $vmpid\n");
1771
1772                        # Skip that VM if something went wrong
1773                        next if (($vmpid == 0) && ($vmexist == 0));
1774
1775                        # If force stopping the VM then reset vmexist
1776                        if ($pbforce == 1) {
1777                                $vmpid = $vmexist;
1778                                $vmexist = 0;
1779                        }
1780                } else {
1781                        #VE
1782                        $vmexist = 0;
1783                        $vmpid = 0;
1784                }
1785
1786                # Gather all required files to send them to the VM
1787                # and launch the build through pbscript
1788                pb_log(2,"DEBUG: Before send2target, vmexist: $vmexist, vmpid: $vmpid\n");
1789                pb_send2target(uc($vtype)."Script","$v",$vmexist,$vmpid,$snapme);
1790
1791        }
1792}
1793
1794sub pb_launchv {
1795        my $vtype = shift;
1796        my $v = shift;
1797        my $create = shift || 0;                # By default do not create a VM/VE
1798        my $snapme = shift || 0;                # By default do not snap a VM/VE
1799        my $usesnap = shift || 1;               # By default study the usage of the snapshot feature of VM/VE
1800
1801        # If creation or snapshot creation mode, no snapshot usable
1802        if (($create == 1) || ($snapme == 1)) {
1803                $usesnap = 0;
1804        }
1805
1806        pb_log(2,"DEBUG: pb_launchv($vtype,$v,$create,$snapme,$usesnap)\n");
1807        die "No VM/VE defined, unable to launch" if (not defined $v);
1808        # Keep only the first VM in case many were given
1809        $v =~ s/,.*//;
1810
1811        my $arch = pb_get_arch();
1812
1813        # Launch the VMs/VEs
1814        if ($vtype eq "vm") {
1815                die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
1816
1817                # TODO: vmmonport should be optional
1818                my ($ptr,$ptr2,$vmpath,$vmport,$vmsize,$vmmonport) = pb_conf_get("vmtype","vmcmd","vmpath","vmport","vmsize","vmmonport");
1819                my ($vmopt,$vmtmout,$vmsnap) = pb_conf_get_if("vmopt","vmtmout","vmsnap");
1820
1821                my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1822                my $vmcmd = $ptr2->{$ENV{'PBPROJ'}};
1823                if (not defined $ENV{'PBVMOPT'}) {
1824                        $ENV{'PBVMOPT'} = "";
1825                }
1826                # Save the current status for later restoration
1827                $ENV{'PBOLDVMOPT'} = $ENV{'PBVMOPT'};
1828                # Set a default timeout of 2 minutes
1829                if (not defined $ENV{'PBVMTMOUT'}) {
1830                        $ENV{'PBVMTMOUT'} = "120";
1831                }
1832                if (defined $vmopt->{$v}) {
1833                        $ENV{'PBVMOPT'} .= " $vmopt->{$v}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$v}/);
1834                } elsif (defined $vmopt->{$ENV{'PBPROJ'}}) {
1835                        $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1836                }
1837
1838                # Are we allowed to use snapshot feature
1839                if ($usesnap == 1) {
1840                        if ((defined $vmsnap->{$v}) && ($vmsnap->{$v} =~ /true/i)) {
1841                                $ENV{'PBVMOPT'} .= " -snapshot";
1842                        } elsif ((defined $vmsnap->{$ENV{'PBPROJ'}}) && ($vmsnap->{$ENV{'PBPROJ'}} =~ /true/i)) {
1843                                $ENV{'PBVMOPT'} .= " -snapshot";
1844                        } elsif ($pbsnap eq 1) {
1845                                $ENV{'PBVMOPT'} .= " -snapshot";
1846                        }
1847                } 
1848                if ($snapme != 0) {
1849                        if (($vmtype eq "kvm") || ($vmtype eq "qemu")) {
1850                                # Configure the monitoring to automize the creation of the 'pb' snapshot
1851                                $ENV{'PBVMOPT'} .= " -serial mon:telnet::$vmmonport->{$ENV{'PBPROJ'}},server,nowait";
1852                                # In that case no snapshot call needed
1853                                $ENV{'PBVMOPT'} =~ s/ -snapshot//;
1854                        }
1855                }
1856                if (defined $vmtmout->{$v}) {
1857                        $ENV{'PBVMTMOUT'} = $vmtmout->{$v};
1858                } elsif (defined $vmtmout->{$ENV{'PBPROJ'}}) {
1859                        $ENV{'PBVMTMOUT'} = $vmtmout->{$ENV{'PBPROJ'}};
1860                }
1861                my $nport = $vmport->{$ENV{'PBPROJ'}};
1862                $nport = "$pbport" if (defined $pbport);
1863       
1864                my $cmd;
1865                my $vmm;                # has to be used for pb_check_ps
1866                if (($vmtype eq "qemu") || ($vmtype eq "kvm")) {
1867                        $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
1868                        if (($create != 0) || (defined $iso)) {
1869                                $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
1870                        }
1871                        # Always redirect the network and always try to use a 'pb' snapshot
1872                        $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 -loadvm pb $vmm"
1873                } elsif ($vmtype eq "xen") {
1874                } elsif ($vmtype eq "vmware") {
1875                } else {
1876                        die "VM of type $vmtype not supported. Report to the dev team";
1877                }
1878                # Restore the ENV VAR Value
1879                $ENV{'PBVMOPT'} = $ENV{'PBOLDVMOPT'};
1880
1881                my ($tmpcmd,$void) = split(/ +/,$cmd);
1882                my $vmexist = pb_check_ps($tmpcmd,$vmm);
1883                my $vmpid = 0;
1884                if (! $vmexist) {
1885                        if ($create != 0) {
1886                                die("Found an existing Virtual machine $vmm. Won't overwrite") if (-r $vmm);
1887                                if (($vmtype eq "qemu") || ($vmtype eq "xen") || ($vmtype eq "kvm")) {
1888                                        pb_system("/usr/bin/qemu-img create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
1889                                } elsif ($vmtype eq "vmware") {
1890                                } else {
1891                                }
1892                        }
1893                        if (! -f "$vmm") {
1894                                pb_log(0,"Unable to find VM $vmm\n");
1895                        } else {
1896                                pb_system("$cmd &","Launching the VM $vmm");
1897                                pb_system("sleep $ENV{'PBVMTMOUT'}","Waiting $ENV{'PBVMTMOUT'} s for VM $v to come up");
1898                                $vmpid = pb_check_ps($tmpcmd,$vmm);
1899                                pb_log(0,"VM $vmm launched (pid $vmpid)\n");
1900                        }
1901                } else {
1902                        pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
1903                }
1904                pb_log(2,"DEBUG: pb_launchv returns ($vmexist,$vmpid)\n");
1905                return($vmexist,$vmpid);
1906        # VE here
1907        } else {
1908                # Get distro context
1909                my ($name,$ver,$darch) = split(/-/,$v);
1910                chomp($darch);
1911                my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf) = pb_distro_init($name,$ver,$darch);
1912
1913                # Get VE context
1914                my ($ptr,$vepath) = pb_conf_get("vetype","vepath");
1915                my $vetype = $ptr->{$ENV{'PBPROJ'}};
1916
1917                # We can probably only get those params now we have the distro context
1918                my ($rbsb4pi,$rbspi,$vesnap,$oscodename,$osmindep,$verebuild,$rbsmirrorsrv) = pb_conf_get_if("rbsb4pi","rbspi","vesnap","oscodename","osmindep","verebuild","rbsmirrorsrv");
1919
1920                # We need to avoid umask propagation to the VE
1921                umask 0022;
1922
1923                if (($vetype eq "chroot") || ($vetype eq "schroot")) {
1924                        # Architecture consistency
1925                        if ($arch ne $darch) {
1926                                die "Unable to launch a VE of architecture $darch on a $arch platform" if (($darch eq "x86_64") && ($arch =~ /i?86/));
1927                        }
1928
1929                        my ($verpmtype,$vedebtype) = pb_conf_get("verpmtype","vedebtype");
1930                        if (($create != 0) || ((defined $verebuild) && ($verebuild->{$ENV{'PBPROJ'}} =~ /true/i)) || ($pbforce == 1)) {
1931                                my ($rbsopt1) = pb_conf_get_if("rbsopt");
1932
1933                                # We have to rebuild the chroot
1934                                if ($dtype eq "rpm") {
1935
1936                                        # Which tool is used
1937                                        my $verpmstyle = $verpmtype->{$ENV{'PBPROJ'}};
1938
1939                                        # Get potential rbs option
1940                                        my $rbsopt = "";
1941                                        if (defined $rbsopt1) {
1942                                                if (defined $rbsopt1->{$verpmstyle}) {
1943                                                        $rbsopt = $rbsopt1->{$verpmstyle};
1944                                                } elsif (defined $rbsopt1->{$ENV{'PBPROJ'}}) {
1945                                                        $rbsopt = $rbsopt1->{$ENV{'PBPROJ'}};
1946                                                } else {
1947                                                        $rbsopt = "";
1948                                                }
1949                                        }
1950
1951                                        my $postinstall = pb_get_postinstall($ddir,$dver,$darch,$rbspi,$verpmstyle);
1952                                        if ($verpmstyle eq "rinse") {
1953                                                # Need to reshape the mirrors generated with local before-post-install script
1954                                                my $b4post = "--before-post-install ";
1955                                                my $postparam = pb_distro_get_param($ddir,$dver,$darch,$rbsb4pi);
1956                                                if ($postparam eq "") {
1957                                                        $b4post = "";
1958                                                } else {
1959                                                        $b4post .= $postparam;
1960                                                }
1961
1962                                                # Need to reshape the package list for pb
1963                                                my $addpkgs;
1964                                                $postparam = "";
1965                                                $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
1966                                                if ($postparam eq "") {
1967                                                        $addpkgs = "";
1968                                                } else {
1969                                                        my $pkgfile = "$ENV{'PBTMP'}/addpkgs.lis";
1970                                                        open(PKG,"> $pkgfile") || die "Unable to create $pkgfile";
1971                                                        foreach my $p (split(/,/,$postparam)) {
1972                                                                print PKG "$p\n";
1973                                                        }
1974                                                        close(PKG);
1975                                                        $addpkgs = "--add-pkg-list $pkgfile";
1976                                                }
1977
1978                                                my $rinseverb = "";
1979                                                $rinseverb = "--verbose" if ($pbdebug gt 0);
1980                                                my ($rbsconf) = pb_conf_get("rbsconf");
1981
1982                                                pb_system("sudo /usr/sbin/rinse --directory \"$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch\" --arch \"$darch\" --distribution \"$ddir-$dver\" --config \"$rbsconf->{$ENV{'PBPROJ'}}\" $b4post $postinstall $rbsopt $addpkgs $rinseverb","Creating the rinse VE for $ddir-$dver ($darch)", "verbose");
1983                                        } elsif ($verpmstyle eq "rpmbootstrap") {
1984                                                my $rbsverb = "";
1985                                                foreach my $i (1..$pbdebug) {
1986                                                        $rbsverb .= " -v";
1987                                                }
1988                                                my $addpkgs = "";
1989                                                my $postparam = "";
1990                                                $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
1991                                                if ($postparam eq "") {
1992                                                        $addpkgs = "";
1993                                                } else {
1994                                                        $addpkgs = "-a $postparam";
1995                                                }
1996                                                pb_system("sudo /usr/bin/rpmbootstrap $rbsopt $postinstall $addpkgs $ddir-$dver-$darch $rbsverb","Creating the rpmbootstrap VE for $ddir-$dver ($darch)", "verbose");
1997                                        } elsif ($verpmstyle eq "mock") {
1998                                                my ($rbsconf) = pb_conf_get("rbsconf");
1999                                                pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$rbsconf->{$ENV{'PBPROJ'}}\" -r $v $rbsopt","Creating the mock VE for $ddir-$dver ($darch)");
2000                                                # Once setup we need to install some packages, the pb account, ...
2001                                                pb_system("sudo /usr/sbin/mock --install --configdir=\"$rbsconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
2002                                        } else {
2003                                                die "Unknown verpmtype type $verpmstyle. Report to dev team";
2004                                        }
2005                                } elsif ($dtype eq "deb") {
2006                                        my $vedebstyle = $vedebtype->{$ENV{'PBPROJ'}};
2007
2008                                        my $codename = pb_distro_get_param($ddir,$dver,$darch,$oscodename);
2009                                        my $postparam = "";
2010                                        my $addpkgs;
2011                                        $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
2012                                        if ($postparam eq "") {
2013                                                $addpkgs = "";
2014                                        } else {
2015                                                $addpkgs = "--include $postparam";
2016                                        }
2017                                        my $debmir = "";
2018                                        $debmir .= pb_distro_get_param($ddir,$dver,$darch,$rbsmirrorsrv);
2019
2020                                        # Get potential rbs option
2021                                        my $rbsopt = "";
2022                                        if (defined $rbsopt1) {
2023                                                if (defined $rbsopt1->{$vedebstyle}) {
2024                                                        $rbsopt = $rbsopt1->{$vedebstyle};
2025                                                } elsif (defined $rbsopt1->{$ENV{'PBPROJ'}}) {
2026                                                        $rbsopt = $rbsopt1->{$ENV{'PBPROJ'}};
2027                                                } else {
2028                                                        $rbsopt = "";
2029                                                }
2030                                        }
2031       
2032                                        # debootstrap works with amd64 not x86_64
2033                                        my $debarch = $darch;
2034                                        $debarch = "amd64" if ($darch eq "x86_64");
2035                                        if ($vedebstyle eq "debootstrap") {
2036                                                my $dbsverb = "";
2037                                                $dbsverb = "--verbose" if ($pbdebug gt 0);
2038
2039                                                # Some perl modules are in Universe on Ubuntu
2040                                                $rbsopt .= " --components=main,universe" if ($ddir eq "ubuntu");
2041
2042                                                pb_system("sudo /usr/sbin/debootstrap $dbsverb $rbsopt --arch=$debarch $addpkgs $codename \"$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch\" $debmir","Creating the debootstrap VE for $ddir-$dver ($darch)", "verbose");
2043                                                # debootstrap doesn't create an /etc/hosts file
2044                                                if (! -f "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch/etc/hosts" ) {
2045                                                        pb_system("sudo cp /etc/hosts $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch/etc/hosts");
2046                                                }
2047                                        } else {
2048                                                die "Unknown vedebtype type $vedebstyle. Report to dev team";
2049                                        }
2050                                } elsif ($dtype eq "ebuild") {
2051                                        die "Please teach the dev team how to build gentoo chroot";
2052                                } else {
2053                                        die "Unknown distribution type $dtype. Report to dev team";
2054                                }
2055                        }
2056                        # Fix modes to allow access to the VE for pb user
2057                        pb_system("sudo chmod 755 $vepath->{$ENV{'PBPROJ'}}/$ddir $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch","Fixing permissions");
2058
2059                        # Test if an existing snapshot exists and use it if appropriate
2060                        # And also use it of no local extracted VE is present
2061                        if ((-f "$vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz") &&
2062                                (((defined $vesnap->{$v}) && ($vesnap->{$v} =~ /true/i)) ||
2063                                        ((defined $vesnap->{$ENV{'PBPROJ'}}) && ($vesnap->{$ENV{'PBPROJ'}} =~ /true/i)) ||
2064                                        ($pbsnap eq 1) ||
2065                                        (! -d "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch"))) {
2066                                                pb_system("sudo rm -rf $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch ; sudo mkdir -p $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch ; sudo tar xz  -C $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch -f $vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz","Extracting snapshot of $ddir-$dver-$darch.tar.gz under $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch");
2067                        }
2068                        # Nothing more to do for VE. No real launch
2069                } else {
2070                        die "VE of type $vetype not supported. Report to the dev team";
2071                }
2072        }
2073}
2074
2075# Return string for date synchro
2076sub pb_date2v {
2077
2078my $vtype = shift;
2079my $v = shift;
2080
2081my ($ntp) = pb_conf_get_if($vtype."ntp");
2082my $vntp = $ntp->{$ENV{'PBPROJ'}} if (defined $ntp);
2083my $ntpline;
2084
2085if (defined $vntp) {
2086        my ($ntpcmd) = pb_conf_get($vtype."ntpcmd");
2087        my $vntpcmd;
2088        if (defined $ntpcmd->{$v}) {
2089                $vntpcmd = $ntpcmd->{$v};
2090        } elsif (defined $ntpcmd->{$ENV{'PBPROJ'}}) {
2091                $vntpcmd = $ntpcmd->{$ENV{'PBPROJ'}};
2092        } else {
2093                $vntpcmd = "/bin/true";
2094        }
2095        $ntpline = "sudo $vntpcmd $vntp";
2096} else {
2097        $ntpline = undef;
2098}
2099# Force new date to be in the future compared to the date
2100# of the host by adding 1 minute
2101my @date=pb_get_date();
2102$date[1]++;
2103my $upddate = strftime("%m%d%H%M%Y", @date);
2104my $dateline = "sudo date $upddate";
2105return($ntpline,$dateline);
2106}
2107
2108sub pb_build2v {
2109
2110my $vtype = shift;
2111my $action = shift || "build";
2112
2113my ($v,$all) = pb_get2v($vtype);
2114
2115# Send tar files when we do a global generation
2116pb_build2ssh() if (($all == 1) && ($action eq "build"));
2117
2118my ($vmexist,$vmpid) = (undef,undef);
2119
2120foreach my $v (@$v) {
2121        # Prepare the script to be executed on the VM/VE
2122        # in $ENV{'PBDESTDIR'}/pbscript
2123        open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
2124        print SCRIPT "#!/bin/bash\n";
2125
2126        # Transmit the verbosity level to the virtual env/mach.
2127        my $verbose = "";
2128        my $i = 0;                                                      # minimal debug level
2129        while ($i lt $pbdebug) {
2130                $verbose .= "-v ";
2131                $i++;
2132        }
2133        # Activate script verbosity if at least 2 for pbdebug
2134        print SCRIPT "set -x\n" if ($i gt 1);
2135        # Quiet if asked to be so on the original system
2136        $verbose = "-q" if ($pbdebug eq -1);
2137
2138        print SCRIPT "echo ... Execution needed\n";
2139        print SCRIPT "# This is in directory delivery\n";
2140        print SCRIPT "# Setup the variables required for building\n";
2141        print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
2142
2143        if ($action eq "build") {
2144                print SCRIPT "# Preparation for pb\n";
2145                print SCRIPT "mv .pbrc \$HOME\n";
2146                print SCRIPT "cd ..\n";
2147        }
2148
2149        # VE needs a good /proc
2150        if ($vtype eq "ve") {
2151                print SCRIPT "sudo mount -t proc /proc /proc\n";
2152        }
2153
2154        my ($ntpline,$dateline) = pb_date2v($vtype,$v);
2155        print SCRIPT "# Time sync\n";
2156        print SCRIPT "echo 'setting up date with '";
2157        if (defined $ntpline) {
2158                print SCRIPT "echo $ntpline\n";
2159                print SCRIPT "$ntpline\n";
2160        } else {
2161                print SCRIPT "echo $dateline\n";
2162                print SCRIPT "$dateline\n";
2163        }
2164        # Use potential local proxy declaration in case we need it to download repo, pkgs, ...
2165        if (defined $ENV{'http_proxy'}) {
2166                print SCRIPT "export http_proxy=\"$ENV{'http_proxy'}\"\n";
2167        }
2168
2169        if (defined $ENV{'ftp_proxy'}) {
2170                print SCRIPT "export ftp_proxy=\"$ENV{'ftp_proxy'}\"\n";
2171        }
2172
2173        # Get list of packages to build/test and get some ENV vars as well
2174        my $ptr = pb_get_pkg();
2175        @pkgs = @$ptr;
2176        my $p = join(' ',@pkgs) if (@pkgs);
2177        print SCRIPT "export PBPROJVER=$ENV{'PBPROJVER'}\n";
2178        print SCRIPT "export PBPROJTAG=$ENV{'PBPROJTAG'}\n";
2179        print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
2180
2181        # We may need to do some other tasks before building. Read a script here to finish setup
2182        if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".pre") {
2183                print SCRIPT "# Special pre-instructions to be launched\n";
2184                print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".pre");
2185        }
2186
2187        if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre") {
2188                print SCRIPT "# Special pre-$action instructions to be launched\n";
2189                print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre");
2190        }
2191
2192        print SCRIPT "# $action\n";
2193        print SCRIPT "echo $action"."ing packages on $vtype...\n";
2194
2195        if (($action eq "test") && (! -x "$ENV{'PBDESTDIR'}/pbtest")) {
2196                        die "No test script ($ENV{'PBDESTDIR'}/pbtest) found when in test mode. Aborting ...";
2197        }
2198        print SCRIPT "pb $verbose -p $ENV{'PBPROJ'} $action"."2pkg $p\n";
2199
2200        if ($vtype eq "ve") {
2201                print SCRIPT "sudo umount /proc\n";
2202        }
2203
2204        # We may need to do some other tasks after building. Read a script here to exit properly
2205        if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.post") {
2206                print SCRIPT "# Special post-$action instructions to be launched\n";
2207                print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.post");
2208        }
2209
2210        if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".post") {
2211                print SCRIPT "# Special post-instructions to be launched\n";
2212                print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".post");
2213        }
2214
2215        close(SCRIPT);
2216        chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
2217       
2218        # Launch the VM/VE
2219        ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
2220
2221        if ($vtype eq "vm") {
2222                # Skip that VM if it something went wrong
2223                next if (($vmpid == 0) && ($vmexist == 0));
2224        } else {
2225                # VE
2226                $vmexist = 0;
2227                $vmpid = 0;
2228        }
2229        # Gather all required files to send them to the VM/VE
2230        # and launch the build through pbscript
2231        pb_log(2,"Calling send2target $vtype,$v,$vmexist,$vmpid\n");
2232        pb_send2target(uc($vtype).$action,"$v",$vmexist,$vmpid);
2233}
2234}
2235
2236
2237sub pb_clean {
2238
2239        my $sleep=10;
2240        die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
2241        die "Unable to get env var PBBUILDDIR" if (not defined $ENV{'PBBUILDDIR'});
2242        pb_log(0,"We will now wait $sleep s before removing both directories\n$ENV{'PBDESTDIR'} and $ENV{'PBBUILDDIR'}.\nPlease break me if this is wrong\n");
2243        sleep $sleep;
2244        pb_rm_rf($ENV{'PBDESTDIR'});
2245        pb_rm_rf($ENV{'PBBUILDDIR'});
2246}
2247
2248sub pb_newver {
2249
2250        die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
2251
2252        # Need this call for PBDIR
2253        my ($scheme2,$uri) = pb_cms_init($pbinit);
2254
2255        my ($pbconf,$pburl) = pb_conf_get("pbconfurl","pburl");
2256        $uri = $pbconf->{$ENV{'PBPROJ'}};
2257        my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
2258
2259        # Checking CMS repositories status
2260        ($scheme2, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
2261
2262        if ($scheme !~ /^svn/) {
2263                die "Only SVN is supported at the moment";
2264        }
2265
2266        my $res = pb_cms_isdiff($scheme,$ENV{'PBROOTDIR'});
2267        die "ERROR: No differences accepted in CMS for $ENV{'PBROOTDIR'} before creating a new version" if ($res != 0);
2268
2269        $res = pb_cms_isdiff($scheme2,$ENV{'PBDIR'});
2270        die "ERROR: No differences accepted in CMS for $ENV{'PBDIR'} before creating a new version" if ($res != 0);
2271
2272        # Tree identical between PBCONFDIR and PBROOTDIR. The delta is what
2273        # we want to get for the root of the new URL
2274
2275        my $tmp = $ENV{'PBROOTDIR'};
2276        $tmp =~ s|^$ENV{'PBCONFDIR'}||;
2277
2278        my $newurl = "$uri/".dirname($tmp)."/$newver";
2279        # Should probably use projver in the old file
2280        my $oldver= basename($tmp);
2281
2282        # Duplicate and extract project-builder part
2283        pb_log(2,"Copying $uri/$tmp to $newurl\n");
2284        pb_cms_copy($scheme,"$uri/$tmp",$newurl);
2285        pb_log(2,"Checkout $newurl to $ENV{'PBROOTDIR'}/../$newver\n");
2286        pb_cms_up($scheme,"$ENV{'PBCONFDIR'}/..");
2287
2288        # Duplicate and extract project
2289        my $newurl2 = "$pburl->{$ENV{'PBPROJ'}}/".dirname($tmp)."/$newver";
2290
2291        pb_log(2,"Copying $pburl->{$ENV{'PBPROJ'}}/$tmp to $newurl2\n");
2292        pb_cms_copy($scheme2,"$pburl->{$ENV{'PBPROJ'}}/$tmp",$newurl2);
2293        pb_log(2,"Checkout $newurl2 to $ENV{'PBDIR'}/../$newver\n");
2294        pb_cms_up($scheme2,"$ENV{'PBDIR'}/..");
2295
2296        # Update the .pb file
2297        open(FILE,"$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb";
2298        open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new";
2299        while(<FILE>) {
2300                s/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
2301                pb_log(0,"Changing projver from $oldver to $newver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/);
2302                pb_log(0,"Commenting testver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^testver/);
2303                s/^testver/#testver/;
2304                print OUT $_;
2305                pb_log(0,"Please check delivery ($_) in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^delivery/);
2306        }
2307        close(FILE);
2308        close(OUT);
2309        rename("$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb");
2310
2311        # Checking pbcl files
2312        foreach my $f (<$ENV{'PBROOTDIR'}/*/pbcl>) {
2313                # Compute new pbcl file
2314                my $f2 = $f;
2315                $f2 =~ s|$ENV{'PBROOTDIR'}|$ENV{'PBROOTDIR'}/../$newver/|;
2316                open(PBCL,$f) || die "Unable to open $f";
2317                my $foundnew = 0;
2318                while (<PBCL>) {
2319                        $foundnew = 1 if (/^$newver \(/);
2320                }
2321                close(PBCL);
2322                open(OUT,"> $f2") || die "Unable to write to $f2: $!";
2323                open(PBCL,$f) || die "Unable to open $f";
2324                while (<PBCL>) {
2325                        print OUT "$_" if (not /^$oldver \(/);
2326                        if ((/^$oldver \(/) && ($foundnew == 0)) {
2327                                print OUT "$newver ($pbdate)\n";
2328                                print OUT "- TBD\n";
2329                                print OUT "\n";
2330                                pb_log(0,"WARNING: version $newver not found in $f so added to $f2...\n") if ($foundnew == 0);
2331                        }
2332                }
2333                close(OUT);
2334                close(PBCL);
2335        }
2336
2337        pb_log(2,"Checkin $ENV{'PBROOTDIR'}/../$newver\n");
2338        pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver",undef);
2339}
2340
2341#
2342# Return the list of VMs/VEs we are working on
2343# $all is a flag to know if we return all of them
2344# or only some (if all we publish also tar files in addition to pkgs
2345#
2346sub pb_get2v {
2347
2348my $vtype = shift;
2349my @v;
2350my $all = 0;
2351my $vlist;
2352my $pbv = 'PBV';
2353
2354if ($vtype eq "vm") {
2355        $vlist = "vmlist";
2356} elsif ($vtype eq "ve") {
2357        $vlist = "velist";
2358}
2359# Get VM/VE list
2360if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
2361        my ($ptr) = pb_conf_get($vlist);
2362        $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
2363        $all = 1;
2364}
2365pb_log(2,"$vtype: $ENV{$pbv}\n");
2366@v = split(/,/,$ENV{$pbv});
2367return(\@v,$all);
2368}
2369
2370# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
2371# Needs to use root account to connect to the VM/VE
2372# pb will take your local public SSH key to access
2373# the pb account in the VM later on if needed
2374sub pb_setup2v {
2375
2376my $vtype = shift;
2377
2378my ($vm,$all) = pb_get2v($vtype);
2379
2380# Script generated
2381my $pbscript = "$ENV{'PBDESTDIR'}/setupv";
2382
2383foreach my $v (@$vm) {
2384        # Deal with date sync.
2385        my ($ntpline,$dateline) = pb_date2v($vtype,$v);
2386
2387        # Get distro context
2388        my ($name,$ver,$darch) = split(/-/,$v);
2389        chomp($darch);
2390        my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins) = pb_distro_init($name,$ver,$darch);
2391       
2392        # Name of the account to deal with for VM/VE
2393        # Do not use the one passed potentially with -a
2394        my ($pbac) = pb_conf_get($vtype."login");
2395        my ($key,$zero0,$zero1,$zero2);
2396        my ($vmexist,$vmpid);
2397
2398        # Prepare the script to be executed on the VM/VE
2399        # in $ENV{'PBDESTDIR'}/setupv
2400        open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2401       
2402        print SCRIPT << 'EOF';
2403#!/usr/bin/perl -w
2404
2405use strict;
2406use File::Copy;
2407
2408# We should not need in this script more functions than what is provided
2409# by Base and Distribution to avoid problems at exec time.
2410# They are appended at the end.
2411
2412our $pbdebug;
2413our $pbLOG;
2414our $pbsynmsg = "pbscript";
2415our $pbdisplaytype = "text";
2416our $pblocale = "";
2417pb_log_init($pbdebug, $pbLOG);
2418pb_temp_init();
2419
2420EOF
2421
2422        # Launch the VM/VE - Usage of snapshot disabled
2423        ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,0,0);
2424
2425        if ($vtype eq "vm") {
2426                # Prepare the key to be used and transfered remotely
2427                my $keyfile = pb_ssh_get(1);
2428               
2429                my ($vmhost,$vmport,$vmntp) = pb_conf_get("vmhost","vmport","vmntp");
2430                my $nport = $vmport->{$ENV{'PBPROJ'}};
2431                $nport = "$pbport" if (defined $pbport);
2432       
2433                # Skip that VM if something went wrong
2434                next if (($vmpid == 0) && ($vmexist == 0));
2435       
2436                # Store the pub key part in a variable
2437                open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
2438                ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
2439                close(FILE);
2440
2441                $key = "\Q$zero1";
2442
2443                # We call true to avoid problems if SELinux is not activated, but chcon is present and returns in that case 1
2444                pb_system("cat $keyfile.pub | ssh -q -o UserKnownHostsFile=/dev/null -p $nport -i $keyfile root\@$vmhost->{$ENV{'PBPROJ'}} \"mkdir -p .ssh ; chmod 700 .ssh ; cat >> .ssh/authorized_keys ; chmod 600 .ssh/authorized_keys ; if [ -x /usr/bin/chcon ]; then /usr/bin/chcon -Rt home_ssh_t .ssh 2> /dev/null; /bin/true; fi\"","Copying local keys to $vtype. This may require the root password");
2445                # once this is done, we can do what we want on the VM remotely
2446        } elsif ($vtype eq "ve") {
2447                print SCRIPT << "EOF";
2448# For VE we need a good null dev
2449pb_system("rm -f /dev/null; mknod /dev/null c 1 3; chmod 777 /dev/null");
2450EOF
2451                print SCRIPT << "EOF";
2452# For VE we first need to mount some FS
2453pb_system("mount -t proc /proc /proc");
2454
2455EOF
2456        }
2457
2458if ($vtype eq "vm") {
2459                print SCRIPT << 'EOF';
2460# Removes duplicate in .ssh/authorized_keys of our key if needed
2461#
2462my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
2463open(PBFILE,$file1) || die "Unable to open $file1";
2464open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
2465my $count = 0;
2466while (<PBFILE>) {
2467
2468EOF
2469                print SCRIPT << "EOF";
2470        if (/ $key /) {
2471                \$count++;
2472        }
2473print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
2474}
2475close(PBFILE);
2476close(PBOUT);
2477rename("\$file1.new",\$file1);
2478chmod 0600,\$file1;
2479
2480# Sync date
2481EOF
2482                if (defined $ntpline) {
2483                        print SCRIPT "pb_system(\"$ntpline\");\n";
2484                } else {
2485                        print SCRIPT "pb_system(\"$dateline\");\n";
2486                }
2487        }
2488        print SCRIPT << 'EOF';
2489
2490# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
2491#
2492my $file="/etc/passwd";
2493open(PBFILE,$file) || die "Unable to open $file";
2494my $found = 0;
2495while (<PBFILE>) {
2496EOF
2497        print SCRIPT << "EOF";
2498        \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
2499EOF
2500
2501my $home = "/home";
2502# Solaris doesn't like that we use /home
2503$home = "/export/home" if ($dtype eq "pkg");
2504
2505        print SCRIPT << "EOF";
2506}
2507close(PBFILE);
2508
2509if ( \$found == 0 ) {
2510        if ( ! -d "$home" ) {
2511                pb_mkdir_p("$home");
2512        }
2513EOF
2514        print SCRIPT << "EOF";
2515pb_system("/usr/sbin/groupadd $pbac->{$ENV{'PBPROJ'}}","Adding group $pbac->{$ENV{'PBPROJ'}}");
2516pb_system("/usr/sbin/useradd -g $pbac->{$ENV{'PBPROJ'}} -m -d $home/$pbac->{$ENV{'PBPROJ'}} $pbac->{$ENV{'PBPROJ'}}","Adding user $pbac->{$ENV{'PBPROJ'}} (group $pbac->{$ENV{'PBPROJ'}} - home $home/$pbac->{$ENV{'PBPROJ'}})");
2517}
2518EOF
2519
2520        # Copy the content of our local conf file to the VM/VE
2521        my $content = pb_get_content(pb_distro_conffile());
2522        print SCRIPT << "EOF";
2523        #
2524        # Create a temporary local conf file for distribution support
2525        # This is created here before its use later. Its place is hardcoded, so no choice for the path
2526        #
2527        my \$tempconf = pb_distro_conffile();
2528        pb_mkdir_p(dirname(\$tempconf));
2529        open(CONF,"> \$tempconf") || die "Unable to create \$tempconf";
2530        print CONF q{$content};
2531        close(CONF);
2532EOF
2533
2534        if ($vtype eq "vm") {
2535                print SCRIPT << "EOF";
2536# allow ssh entry to build
2537#
2538mkdir "$home/$pbac->{$ENV{'PBPROJ'}}/.ssh",0700;
2539# Allow those accessing root to access the build account
2540copy("\$ENV{'HOME'}/.ssh/authorized_keys","$home/$pbac->{$ENV{'PBPROJ'}}/.ssh/authorized_keys");
2541chmod 0600,".ssh/authorized_keys";
2542pb_system("chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} $home/$pbac->{$ENV{'PBPROJ'}}","Finish setting up the account env for $pbac->{$ENV{'PBPROJ'}}");
2543
2544EOF
2545}
2546        print SCRIPT << 'EOF';
2547# No passwd for build account only keys
2548$file="/etc/shadow";
2549if (-f $file) {
2550        open(PBFILE,$file) || die "Unable to open $file";
2551        open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2552        while (<PBFILE>) {
2553EOF
2554        print SCRIPT << "EOF";
2555                s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
2556                s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;     #SLES 9 e.g.
2557                s/^$pbac->{$ENV{'PBPROJ'}}:\\*LK\\*:/$pbac->{$ENV{'PBPROJ'}}:NP:/;      #Solaris e.g.
2558EOF
2559                print SCRIPT << 'EOF';
2560                print PBOUT $_;
2561        }
2562        close(PBFILE);
2563        close(PBOUT);
2564        rename("$file.new",$file);
2565        chmod 0640,$file;
2566        }
2567
2568# Keep the VM in text mode
2569$file="/etc/inittab";
2570if (-f $file) {
2571        open(PBFILE,$file) || die "Unable to open $file";
2572        open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2573        while (<PBFILE>) {
2574                s/^(..):5:initdefault:$/$1:3:initdefault:/;
2575                print PBOUT $_;
2576        }
2577        close(PBFILE);
2578        close(PBOUT);
2579        rename("$file.new",$file);
2580        chmod 0640,$file;
2581}
2582
2583# pb has to be added to portage group on gentoo
2584
2585# We need to have that pb_distro_init function
2586# Get it from Project-Builder::Distribution
2587# And we now need the conf file required for this to work created above
2588
2589my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch) = pb_distro_init(); 
2590print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $darch))."\n";
2591
2592# Adapt sudoers
2593# sudo is not default on Solaris and needs to be installed first
2594# from http://www.sunfreeware.com/programlistsparc10.html#sudo
2595if ($dtype eq "pkg") {
2596        $file="/usr/local/etc/sudoers";
2597} else {
2598        $file="/etc/sudoers";
2599}
2600open(PBFILE,$file) || die "Unable to open $file";
2601open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2602while (<PBFILE>) {
2603EOF
2604        print SCRIPT << "EOF";
2605        next if (/^$pbac->{$ENV{'PBPROJ'}}   /);
2606EOF
2607        print SCRIPT << 'EOF';
2608        s/Defaults[ \t]+requiretty//;
2609        print PBOUT $_;
2610}
2611close(PBFILE);
2612EOF
2613        print SCRIPT << "EOF";
2614# Some distro force requiretty at compile time, so disable here
2615print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} !requiretty\n";
2616print PBOUT "Defaults:root !requiretty\n";
2617# This is needed in order to be able to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
2618print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} env_keep += \\\"http_proxy ftp_proxy\\\"\n";
2619print PBOUT "$pbac->{$ENV{'PBPROJ'}}   ALL=(ALL) NOPASSWD:ALL\n";
2620EOF
2621        print SCRIPT << 'EOF';
2622close(PBOUT);
2623rename("$file.new",$file);
2624chmod 0440,$file;
2625
2626EOF
2627
2628        # We may need a proxy configuration. Get it from the local env
2629
2630        if (defined $ENV{'http_proxy'}) {
2631                print SCRIPT "\$ENV\{'http_proxy'\}=\"$ENV{'http_proxy'}\";\n";
2632        }
2633
2634        if (defined $ENV{'ftp_proxy'}) {
2635                print SCRIPT "\$ENV\{'ftp_proxy'\}=\"$ENV{'ftp_proxy'}\";\n";
2636        }
2637
2638        print SCRIPT << 'EOF';
2639       
2640# Suse wants sudoers as 640
2641if ((($ddir eq "sles") && (($dver =~ /10/) || ($dver =~ /9/))) || (($ddir eq "opensuse") && ($dver =~ /10.[012]/))) {
2642        chmod 0640,$file;
2643}
2644
2645# First install all required packages
2646pb_system("yum clean all","Cleaning yum env") if (($ddir eq "fedora") || ($ddir eq "asianux") || ($ddir eq "rhel"));
2647my ($ospkgdep) = pb_conf_get_if("ospkgdep");
2648       
2649my $pkgdep = pb_distro_get_param($ddir,$dver,$darch,$ospkgdep,$dfam,$dtype,$dos);
2650pb_distro_installdeps(undef,$dtype,$pbins,pb_distro_only_deps_needed($dtype,join(' ',split(/,/,$pkgdep))));
2651
2652EOF
2653        my $itype = pb_conf_get("pbinstalltype");
2654        if ($itype->{$ENV{'PBPROJ'}} =~ /^file/) {
2655                print SCRIPT << 'EOF';
2656# Then install manually the missing perl modules
2657my ($osperldep,$osperlver) = pb_conf_get_if("osperldep","osperlver");
2658       
2659my $perldep = pb_distro_get_param($ddir,$dver,$darch,$osperldep,$dfam,$dtype,$dos);
2660foreach my $m (split(/,/,$perldep)) {
2661        # Skip empty deps
2662        next if ($m =~ /^\s*$/);
2663        my $dir = $m;
2664        $dir =~ s/-.*//;
2665        pb_system("echo \"rm -rf $m* ; wget http://search.cpan.org/CPAN/modules/by-module/$dir/$m-$osperlver->{$m}.tar.gz ; gzip -cd $m-$osperlver->{$m}.tar.gz | tar xf - ; cd $m* ; if [ -f Build.PL ]; then perl Build.PL; ./Build ; ./Build install ; else perl Makefile.PL; make ; make install ; fi; cd .. ; rm -rf $m*\" | bash" ,"Installing perl module $m-$osperlver->{$m}");
2666}
2667
2668pb_system("rm -rf ProjectBuilder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/ProjectBuilder-latest.tar.gz ; gzip -cd ProjectBuilder-latest.tar.gz | tar xf - ; cd ProjectBuilder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf ProjectBuilder-* ; rm -rf project-builder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/project-builder-latest.tar.gz ; gzip -cd project-builder-latest.tar.gz | tar xf - ; cd project-builder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf project-builder-* ;","Building Project-Builder");
2669EOF
2670        } elsif ($itype->{$ENV{'PBPROJ'}} =~ /^pkg/) {
2671                # pkg based install. We need to point to the project-builder.org repository
2672                print SCRIPT << 'EOF';
2673my ($pbpkg) = pb_conf_get_if("pbpkg");
2674
2675my $pkgforpb = pb_distro_get_param($ddir,$dver,$darch,$pbpkg,$dfam,$dtype,$depdos);
2676pb_distro_setuprepo($ddir,$dver,$darch,$dtype);
2677pb_distro_installdeps(undef,$dtype,$pbins,pb_distro_only_deps_needed($dtype,join(' ',split(/,/,$pkgforpb))));
2678EOF
2679        } else {
2680                # Unknown install type
2681                die("Unknown install type $itype->{$ENV{'PBPROJ'}} for param pbinstalltype");
2682        }
2683        print SCRIPT << 'EOF';
2684pb_system("pb 2>&1 | head -5",undef,"verbose");
2685EOF
2686        if ($vtype eq "ve") {
2687                        print SCRIPT << 'EOF';
2688# For VE we need to umount some FS at the end
2689
2690pb_system("umount /proc");
2691
2692# Create a basic network file if not already there
2693
2694my $nf="/etc/sysconfig/network";
2695if ((! -f $nf) && ($dtype eq "rpm")) {
2696        open(NF,"> $nf") || die "Unable to create $nf";
2697        print NF "NETWORKING=yes\n";
2698        print NF "HOSTNAME=localhost\n";
2699        close(NF);
2700}
2701chmod 0755,$nf;
2702EOF
2703        }
2704
2705        # Adds pb_distro_init and all functions needed from ProjectBuilder::Distribution and Base
2706        foreach my $d (@INC) {
2707                my @f = ("$d/ProjectBuilder/Base.pm","$d/ProjectBuilder/Distribution.pm","$d/ProjectBuilder/Conf.pm");
2708                foreach my $f (@f) {
2709                        if (-f "$f") {
2710                                open(PBD,"$f") || die "Unable to open $f";
2711                                while (<PBD>) {
2712                                        next if (/^package/);
2713                                        next if (/^use Exporter/);
2714                                        next if (/^use ProjectBuilder::/);
2715                                        next if (/^our /);
2716                                        print SCRIPT $_;
2717                                }
2718                                close(PBD);
2719                        }
2720                }
2721        }
2722        close(SCRIPT);
2723        chmod 0755,"$pbscript";
2724
2725        # That build script needs to be run as root and force stop of VM at end
2726        $pbaccount = "root";
2727
2728        # Force shutdown of VM except if it was already launched
2729        my $pbforce = 0;
2730        if ((! $vmexist) && ($vtype eq "vm")) {
2731                $pbforce = 1;
2732        }
2733       
2734        pb_script2v($pbscript,$vtype,$pbforce,$v);
2735}
2736return;
2737}
2738
2739# Function to create a snapshot named 'pb' for VMs and a compressed tar for VEs
2740sub pb_snap2v {
2741
2742my $vtype = shift;
2743
2744my ($vm,$all) = pb_get2v($vtype);
2745
2746# Script generated
2747my $pbscript = "$ENV{'PBDESTDIR'}/snapv";
2748
2749my ($pbac) = pb_conf_get($vtype."login");
2750
2751foreach my $v (@$vm) {
2752        # Get distro context
2753        my ($name,$ver,$darch) = split(/-/,$v);
2754        chomp($darch);
2755        my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf) = pb_distro_init($name,$ver,$darch);
2756        my ($vepath) = pb_conf_get("vepath");
2757
2758        # Test if an existing snapshot exists and remove it if there is a VE
2759        if ((-f "$vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz") &&
2760                (! -d "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch")) {
2761                        pb_system("sudo rm -f $vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz","Removing previous snapshot $ddir-$dver-$darch.tar.gz");
2762        }
2763
2764        # Prepare the script to be executed on the VM/VE
2765        # in $ENV{'PBDESTDIR'}/setupv
2766        open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2767       
2768        print SCRIPT << 'EOF';
2769        #!/bin/bash
2770        sleep 2
2771EOF
2772        close(SCRIPT);
2773        chmod 0755,"$pbscript";
2774
2775        # Force shutdown of VM/VE
2776        # Force snapshot of VM/VE
2777        pb_script2v($pbscript,$vtype,1,$v,1);
2778}
2779return;
2780}
2781
2782# Function to update a VMs or VEs with the latest distribution content
2783sub pb_update2v {
2784
2785my $vtype = shift;
2786
2787my ($vm,$all) = pb_get2v($vtype);
2788
2789# Script generated
2790my $pbscript = "$ENV{'PBDESTDIR'}/updatev";
2791
2792my ($pbac) = pb_conf_get($vtype."login");
2793
2794foreach my $v (@$vm) {
2795        # Get distro context
2796        my ($name,$ver,$darch) = split(/-/,$v);
2797        chomp($darch);
2798        my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins) = pb_distro_init($name,$ver,$darch);
2799
2800        # Prepare the script to be executed on the VM/VE
2801        # in $ENV{'PBDESTDIR'}/updatev
2802        open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2803       
2804        print SCRIPT << 'EOF';
2805        #!/bin/bash
2806        sleep 2
2807EOF
2808        # VE needs a good /proc
2809        if ($vtype eq "ve") {
2810                print SCRIPT "sudo mount -t proc /proc /proc\n";
2811        }
2812        print SCRIPT "$pbupd\n";
2813        if ($vtype eq "ve") {
2814                print SCRIPT "sudo umount /proc\n";
2815        }
2816        close(SCRIPT);
2817        chmod 0755,"$pbscript";
2818
2819        # Force shutdown of VM except
2820        pb_script2v($pbscript,$vtype,1,$v);
2821}
2822return;
2823}
2824
2825sub pb_announce {
2826
2827        # Get all required parameters
2828        my ($pbpackager,$pbrepo,$pbml,$pbsmtp) = pb_conf_get("pbpackager","pbrepo","pbml","pbsmtp");
2829        my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
2830        my $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
2831        my @pkgs = @$pkg;
2832        my %pkgs;
2833        my $first = 0;
2834
2835        # Command to find packages on repo
2836        my $findstr = "find . ";
2837        # Generated announce files
2838        my @files;
2839
2840        foreach my $pbpkg (@pkgs) {
2841                if ($first != 0) {
2842                        $findstr .= "-o ";
2843                }
2844                $first++;
2845                if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
2846                        $pbver = $pkgv->{$pbpkg};
2847                } else {
2848                        $pbver = $ENV{'PBPROJVER'};
2849                }
2850                if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
2851                        $pbtag = $pkgt->{$pbpkg};
2852                } else {
2853                        $pbtag = $ENV{'PBPROJTAG'};
2854                }
2855
2856                # TODO: use virtual/real names here now
2857                $findstr .= "-name \'$pbpkg-$pbver-$pbtag\.*.rpm\' -o -name \'$pbpkg"."_$pbver*\.deb\' -o -name \'$pbpkg-$pbver*\.ebuild\' ";
2858
2859                my $chglog;
2860
2861                # Get project info on log file and generate tmp files used later on
2862                pb_cms_init($pbinit);
2863                $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
2864                $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
2865                $chglog = undef if (! -f $chglog);
2866
2867                open(OUT,"> $ENV{'PBTMP'}/$pbpkg.ann") || die "Unable to create $ENV{'PBTMP'}/$pbpkg.ann: $!";
2868                my %pb;
2869                $pb{'dtype'} = "announce";
2870                $pb{'realpkg'} = $pbpkg;
2871                $pb{'ver'} = $pbver;
2872                $pb{'tag'} = $pbtag;
2873                $pb{'suf'} = "N/A";             # Should not be empty even if unused
2874                $pb{'date'} = $pbdate;
2875                $pb{'chglog'} = $chglog;
2876                $pb{'packager'} = $pbpackager;
2877                $pb{'proj'} = $ENV{'PBPROJ'};
2878                $pb{'repo'} = $pbrepo;
2879                pb_changelog(\%pb,\*OUT,"yes");
2880                close(OUT);
2881                push(@files,"$ENV{'PBTMP'}/$pbpkg.ann");
2882        }
2883        $findstr .= " | grep -Ev \'src.rpm\'";
2884
2885        # Prepare the command to run and execute it
2886        open(PBS,"> $ENV{'PBTMP'}/pbscript") || die "Unable to create $ENV{'PBTMP'}/pbscript";
2887        print PBS "$findstr\n";
2888        close(PBS);
2889        chmod 0755,"$ENV{'PBTMP'}/pbscript";
2890        pb_send2target("Announce");
2891
2892        # Get subject line
2893        my $sl = "Project $ENV{'PBPROJ'} version $ENV{'PBPROJVER'} is now available";
2894        pb_log(0,"Please enter the title of your announce\n");
2895        pb_log(0,"(By default: $sl)\n");
2896        my $sl2 = <STDIN>;
2897        $sl = $sl2 if ($sl2 !~ /^$/);
2898
2899        # Prepare a template of announce
2900        open(ANN,"> $ENV{'PBTMP'}/announce.html") || die "Unable to create $ENV{'PBTMP'}/announce.html: $!";
2901        print ANN << "EOF";
2902$sl</p>
2903
2904<p>The project team is happy to announce the availability of a newest version of $ENV{'PBPROJ'} $ENV{'PBPROJVER'}. Enjoy it as usual!</p>
2905<p>
2906Now available at <a href="$pbrepo->{$ENV{'PBPROJ'}}">$pbrepo->{$ENV{'PBPROJ'}}</a>
2907</p>
2908<p>
2909EOF
2910        open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to read $ENV{'PBTMP'}/system.log: $!";
2911        my $col = 2;
2912        my $i = 1;
2913        print ANN << 'EOF';
2914<TABLE WIDTH="700" CELLPADDING="0" CELLSPACING="0" BORDER="0">
2915<TR>
2916EOF
2917        while (<LOG>) {
2918                print ANN "<TD><A HREF=\"$pbrepo->{$ENV{'PBPROJ'}}/$_\">$_</A></TD>";
2919                $i++;
2920                if ($i > $col) {
2921                        print ANN "</TR>\n<TR>";
2922                        $i = 1;
2923                }
2924        }
2925        close(LOG);
2926        print ANN << "EOF";
2927</TR>
2928</TABLE>
2929</p>
2930
2931<p>As usual source packages are also available in the same directory.</p>
2932
2933<p>
2934Changes are :
2935</p>
2936<p>
2937EOF
2938        # Get each package changelog content
2939        foreach my $f (sort(@files)) {
2940                open(IN,"$f") || die "Unable to read $f:$!";
2941                while (<IN>) {
2942                        print ANN $_;
2943                }
2944                close(IN);
2945                print ANN "</p><p>\n";
2946        }
2947        print ANN "</p>\n";
2948        close(ANN);
2949
2950        # Allow for modification
2951        my $editor = "vi";
2952        $editor = $ENV{'EDITOR'} if (defined $ENV{'EDITOR'});
2953        pb_system("$editor $ENV{'PBTMP'}/announce.html","Allowing modification of the announce","noredir");
2954
2955        # Store it in DB for external usage (Web pages generation)
2956        my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
2957
2958        my $precmd = "";
2959        if (! -f $db) {
2960                $precmd = "CREATE TABLE announces (id INTEGER PRIMARY KEY AUTOINCREMENT, date DATE, announce VARCHAR[65535])";
2961        }
2962
2963        my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
2964                        { RaiseError => 1, AutoCommit => 1 })
2965                        || die "Unable to connect to $db";
2966
2967        if ($precmd ne "") {
2968                my $sth = $dbh->prepare(qq{$precmd})
2969                        || die "Unable to create table into $db";
2970                $sth->execute();
2971        }
2972
2973        # To read whole file
2974        local $/;
2975        open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
2976        my $announce = <ANN>;
2977        close(ANN);
2978       
2979        pb_log(2,"INSERT INTO announces VALUES (NULL, $pbdate, $announce)");
2980        my $sth = $dbh->prepare(qq{INSERT INTO announces VALUES (NULL,?,?)})
2981                        || die "Unable to insert into $db";
2982        $sth->execute($pbdate, $announce);
2983        $sth->finish();
2984        $dbh->disconnect;
2985
2986        # Then deliver it on the Web
2987        # $TOOLHOME/livwww www
2988
2989        # Mail it to project's ML
2990        open(ML,"| w3m -dump -T text/html > $ENV{'PBTMP'}/announce.txt") || die "Unable to create $ENV{'PBTMP'}/announce.txt: $!";
2991        print ML << 'EOF';
2992<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd">
2993
2994<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en" lang="en">
2995  <head>
2996  </head>
2997  <body>
2998  <p>
2999EOF
3000        open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
3001        while(<ANN>) {
3002                print ML $_;
3003        }
3004        print ML << 'EOF';
3005</body>
3006</html>
3007EOF
3008        close(ML);
3009
3010        # To read whole file
3011        local $/;
3012        open(ANN,"$ENV{'PBTMP'}/announce.txt") || die "Unable to read $ENV{'PBTMP'}/announce.txt: $!";
3013        my $msg = <ANN>;
3014        close(ANN);
3015       
3016        # Preparation of headers
3017        require Mail::Sendmail;
3018
3019        my %mail = (   
3020                        To                      =>      $pbml->{$ENV{'PBPROJ'}},
3021                        From            =>      $pbpackager->{$ENV{'PBPROJ'}},
3022                        Smtp            =>      $pbsmtp->{$ENV{'PBPROJ'}},
3023                        Body            =>      $msg,
3024                        Subject         =>      "[ANNOUNCE] $sl",
3025                );
3026                       
3027        # Send mail
3028        if (! sendmail(%mail)) {
3029                if ((defined $Mail::Sendmail::error) and (defined $Mail::Sendmail::log)) {
3030                        die "Unable to send mail ($Mail::Sendmail::error): $Mail::Sendmail::log";
3031                }
3032        }
3033}
3034
3035#
3036# Creates a set of HTML file containing the news for the project
3037# based on what has been generated by the pb_announce function
3038#
3039sub pb_web_news2html {
3040
3041        my $dest = shift || $ENV{'PBTMP'};
3042
3043        # Get all required parameters
3044        my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
3045
3046        # DB of announces for external usage (Web pages generation)
3047        my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
3048
3049        my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
3050                        { RaiseError => 1, AutoCommit => 1 })
3051                        || die "Unable to connect to $db";
3052        # For date handling
3053        $ENV{LANGUAGE}="C";
3054        my $firstjan = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year(), 0, 0, -1);
3055        my $oldfirst = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year()-1, 0, 0, -1);
3056        pb_log(2,"firstjan: $firstjan, oldfirst: $oldfirst, pbdate:$pbdate\n");
3057        my $all = $dbh->selectall_arrayref("SELECT id,date,announce FROM announces ORDER BY date DESC");
3058        my %news;
3059        $news{"cy"} = "";       # current year's news
3060        $news{"ly"} = "";       # last year news
3061        $news{"py"} = "";       # previous years news
3062        $news{"fp"} = "";       # first page news
3063        my $cpt = 4;            # how many news for first page
3064        # Extract info from DB
3065        foreach my $row (@$all) {
3066                my ($id, $date, $announce) = @$row;
3067                $news{"cy"} = $news{"cy"}."<p><B>$date</B> $announce\n" if ((($date cmp $pbdate) le 0) && (($firstjan cmp $date) le 0));
3068                $news{"ly"} = $news{"ly"}."<p><B>$date</B> $announce\n" if ((($date cmp $firstjan) le 0) && (($oldfirst cmp $date) le 0));
3069                $news{"py"} = $news{"py"}."<p><B>$date</B> $announce\n" if (($date cmp $oldfirst) le 0);
3070                $news{"fp"} = $news{"fp"}."<p><B>$date</B> $announce\n" if ($cpt > 0);
3071                $cpt--;
3072        }
3073        pb_log(1,"news{fp}: ".$news{"fp"}."\n");
3074        $dbh->disconnect;
3075
3076        # Generate the HTML content
3077        foreach my $pref (keys %news) {
3078                open(NEWS,"> $dest/pb_web_$pref"."news.html") || die "Unable to create $dest/pb_web_$pref"."news.html: $!";
3079                print NEWS "$news{$pref}";
3080                close(NEWS);
3081        }
3082}
3083
3084
3085# Return the SSH key file to use
3086# Potentially create it if needed
3087
3088sub pb_ssh_get {
3089
3090my $create = shift || 0;        # Do not create keys by default
3091
3092# Check the SSH environment
3093my $keyfile = undef;
3094
3095# We have specific keys by default
3096$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa";
3097if (!(-e $keyfile) && ($create eq 1)) {
3098        pb_system("ssh-keygen -q -b 1024 -N '' -f $keyfile -t dsa","Generating SSH keys for pb");
3099}
3100
3101$keyfile = "$ENV{'HOME'}/.ssh/id_rsa" if (-s "$ENV{'HOME'}/.ssh/id_rsa");
3102$keyfile = "$ENV{'HOME'}/.ssh/id_dsa" if (-s "$ENV{'HOME'}/.ssh/id_dsa");
3103$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa" if (-s "$ENV{'HOME'}/.ssh/pb_dsa");
3104die "Unable to find your public ssh key under $keyfile" if (not defined $keyfile);
3105return($keyfile);
3106}
3107
3108
3109# Returns the pid of a running VM command using a specific VM file
3110sub pb_check_ps {
3111        my $vmcmd = shift;
3112        my $vmm = shift;
3113        my $vmexist = 0;                # FALSE by default
3114
3115        open(PS, "ps auxhww|") || die "Unable to call ps";
3116        while (<PS>) {
3117                next if (! /$vmcmd/);
3118                next if (! /$vmm/);
3119                my ($void1, $void2);
3120                ($void1, $vmexist, $void2) = split(/ +/);
3121                last;
3122        }
3123        return($vmexist);
3124}
3125
3126
3127sub pb_extract_build_files {
3128
3129my $src=shift;
3130my $dir=shift;
3131my $ddir=shift;
3132my $mandatory=shift || "spec";
3133my @files;
3134
3135my $flag = "mayfail" if ($mandatory eq "patch");
3136my $res;
3137
3138if ($src =~ /tar\.gz$/) {
3139        $res = pb_system("tar xfpz $src $dir","Extracting $mandatory files from $src",$flag);
3140} elsif ($src =~ /tar\.bz2$/) {
3141        $res = pb_system("tar xfpj $src $dir","Extracting $mandatory files from $src",$flag);
3142} else {
3143        die "Unknown compression algorithm for $src";
3144}
3145# If not mandatory return now
3146return() if (($res != 0) and ($mandatory eq "patch"));
3147opendir(DIR,"$dir") || die "Unable to open directory $dir";
3148foreach my $f (readdir(DIR)) {
3149        next if ($f =~ /^\./);
3150        # Skip potential patch dir
3151        next if ($f =~ /^pbpatch/);
3152        move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
3153        pb_log(2,"mv $dir/$f $ddir\n");
3154        push @files,"$ddir/$f";
3155}
3156closedir(DIR);
3157# Not enough but still a first cleanup
3158pb_rm_rf("$dir");
3159return(@files);
3160}
3161
3162sub pb_list_bfiles {
3163
3164my $dir = shift;
3165my $pbpkg = shift;
3166my $bfiles = shift;
3167my $pkgfiles = shift;
3168my $supfiles = shift;
3169
3170opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
3171foreach my $f (readdir(BDIR)) {
3172        next if ($f =~ /^\./);
3173        if (-d $f) {
3174                # Recurse for directories (Debian 3.0 format e.g.)
3175                pb_list_bfiles($f,$pbpkg,$bfiles,$pkgfiles,$supfiles);
3176                next;
3177        }
3178        $bfiles->{$f} = "$dir/$f";
3179        $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
3180        if (defined $supfiles->{$pbpkg}) {
3181                $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
3182        }
3183}
3184closedir(BDIR);
3185}
3186
3187
3188#
3189# Return the list of packages we are working on in a non CMS action
3190#
3191sub pb_get_pkg {
3192
3193my @pkgs = ();
3194
3195my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
3196@pkgs = keys %$var;
3197
3198pb_log(0,"Packages: ".join(',',@pkgs)."\n");
3199return(\@pkgs);
3200}
3201
3202#
3203# Return the postinstall line if needed
3204#
3205
3206sub pb_get_postinstall {
3207
3208my $ddir = shift;
3209my $dver = shift;
3210my $darch = shift;
3211my $rbspi = shift;
3212my $vestyle = shift;
3213my $post = "";
3214
3215# Do we have a local post-install script
3216if ($vestyle eq "rinse") {
3217        $post = "--post-install ";
3218} elsif ($vestyle eq "rpmbootstrap") {
3219        $post = "-s ";
3220}
3221
3222my $postparam = pb_distro_get_param($ddir,$dver,$darch,$rbspi);
3223if ($postparam eq "") {
3224        $post = "";
3225} else {
3226        $post .= $postparam;
3227}
3228return($post);
3229}
3230
32311;
Note: See TracBrowser for help on using the repository browser.