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

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