source: devel/pb/bin/pb @ 1111

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