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

Last change on this file since 560 was 560, checked in by Bruno Cornec, 16 years ago
  • Adds script for website installation on remote site
  • Use apache account for mondo's delivery
  • Update announces to fix html errors
  • web2ssh is now working (tested fully with mondo)
  • Property svn:executable set to *
File size: 75.5 KB
Line 
1#!/usr/bin/perl -w
2#
3# Project Builder main application
4#
5# $Id$
6#
7# Copyright B. Cornec 2007
8# Provided under the GPL v2
9
10# Syntax: see at end
11
12use strict 'vars';
13use Getopt::Long qw(:config auto_abbrev no_ignore_case);
14use Data::Dumper;
15use English;
16use File::Basename;
17use File::Copy;
18use File::stat;
19use File::Temp qw(tempdir);
20use Time::localtime qw(localtime);
21use POSIX qw(strftime);
22use lib qw (lib);
23use ProjectBuilder::Version;
24use ProjectBuilder::Base;
25use ProjectBuilder::Display;
26use ProjectBuilder::Conf;
27use ProjectBuilder::Distribution;
28use ProjectBuilder::CMS;
29use ProjectBuilder::Env;
30use ProjectBuilder::Filter;
31use ProjectBuilder::Changelog;
32use Mail::Sendmail;
33
34# Global variables
35my %opts; # CLI Options
36my $action; # action to realize
37my $test = "FALSE"; # Not used
38my $force = 0; # Force VE/VM rebuild
39my $option = ""; # Not used
40my @pkgs; # list of packages
41my $pbtag; # Global Tag variable
42my $pbver; # Global Version variable
43my $pbscript; # Name of the script
44my %pbver; # per package
45my %pbtag; # per package
46my $pbrev; # Global REVISION variable
47my $pbaccount; # Login to use to connect to the VM
48my $pbport; # Port to use to connect to the VM
49my $newver; # New version to create
50my $iso; # ISO image for the VM to create
51
52my @date = pb_get_date();
53my $pbdate = strftime("%Y-%m-%d", @date);
54
55=pod
56
57=head1 NAME
58
59pb, aka project-builder.org - builds packages for your projects
60
61=head1 DESCRIPTION
62
63pb helps you build various packages directly from your project sources.
64Those sources could be handled by a CMS (Configuration Management System)
65such as Subversion, CVS, ... or being a simple reference to a compressed tar file.
66It's based on a set of configuration files, a set of provided macros to help
67you keeping build files as generic as possible. For example, a single .spec
68file should be required to generate for all rpm based distributions, even
69if you could also have multiple .spec files if required.
70
71=head1 SYNOPSIS
72
73pb [-vhq][-r pbroot][-p project][[-s script -a account -P port][-m mach-1[,...]]][-i iso] <action> [<pkg1> ...]
74
75pb [--verbose][--help][--man][--quiet][--revision pbroot][--project project][[--script script --account account --port port][--machine mach-1[,...]]][--iso iso] <action> [<pkg1> ...]
76
77=head1 OPTIONS
78
79=over 4
80
81=item B<-v|--verbose>
82
83Print a brief help message and exits.
84
85=item B<-q|--quiet>
86
87Do not print any output.
88
89=item B<-h|--help>
90
91Print a brief help message and exits.
92
93=item B<--man>
94
95Prints the manual page and exits.
96
97=item B<-m|--machine machine1[,machine2,...]>
98
99Name of the Virtual Machines (VM) or Virtual Environments (VE) you want to build on (coma separated).
100All if none precised (or use the env variable PBV).
101
102=item B<-s|--script script>
103
104Name of the script you want to execute on the related VMs or VEs.
105
106=item B<-i|--iso iso_image>
107
108Name of the ISO image of the distribution you want to install on the related VMs.
109
110=item B<-a|--account account>
111
112Name of the account to use to connect on the related VMs.
113
114=item B<-P|--port port_number>
115
116Port number to use to connect on the related VMs.\n";
117
118=item B<-p|--project project_name>
119
120Name of the project you're working on (or use the env variable PBPROJ)
121
122=item B<-r|--revision revision>
123
124Path Name of the project revision under the CMS (or use the env variable PBROOT)
125
126=item B<-V|--version new_version>
127
128New version of the project to create based on the current one.
129
130=back
131
132=head1 ARGUMENTS
133
134<action> can be:
135
136=over 4
137
138=item B<cms2build>
139
140Create tar files for the project under your CMS.
141CMS supported are SVN and CVS
142parameters are packages to build
143if not using default list
144
145=item B<build2pkg>
146
147Create packages for your running distribution
148
149=item B<cms2pkg>
150
151cms2build + build2pkg
152
153=item B<build2ssh>
154
155Send the tar files to a SSH host
156
157=item B<cms2ssh>
158
159cms2build + build2ssh
160
161=item B<pkg2ssh>
162
163Send the packages built to a SSH host
164
165=item B<build2vm>
166
167Create packages in VMs, launching them if needed
168and send those packages to a SSH host once built
169VM type supported are QEMU
170
171=item B<build2ve>
172
173Create packages in VEs, creating it if needed
174and send those packages to a SSH host once built
175
176=item B<cms2vm>
177
178cms2build + build2vm
179
180=item B<cms2ve>
181
182cms2build + build2ve
183
184=item B<launchvm>
185
186Launch one virtual machine
187
188=item B<launchve>
189
190Launch one virtual environment
191
192=item B<script2vm>
193
194Launch one virtual machine if needed
195and executes a script on it
196
197=item B<script2ve>
198
199Execute a script in a virtual environment
200
201=item B<newvm>
202
203Create a new virtual machine
204
205=item B<newve>
206
207Create a new virtual environment
208
209=item B<setupvm>
210
211Setup a virtual machine for pb usage
212
213=item B<setupve>
214
215Setup a virtual environment for pb usage
216
217=item B<newver>
218
219Create a new version of the project derived
220from the current one
221
222=item B<newproj>
223
224Create a new project and a template set of
225configuration files under pbconf
226
227=item B<announce>
228
229Announce the availability of the project through various means
230
231=back
232
233=item B<web2ssh>
234
235Deliver the Web site content to the target server using ssh.
236
237=back
238
239<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).
240
241=head1 WEB SITES
242
243The 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/>.
244
245=head1 USER MAILING LIST
246
247None exists for the moment.
248
249=head1 CONFIGURATION FILES
250
251Each pb user may have a configuration in F<$HOME/.pbrc>. The values in this file may overwrite any other configuration file value.
252
253Here is an example of such a configuration file:
254
255 #
256 # Define for each project the URL of its pbconf repository
257 # No default option allowed here as they need to be all different
258 #
259 # URL of the pbconf content
260 # This is the format of a classical URL with the extension of additional schema such as
261 # svn+ssh, cvs+ssh, ...
262 #
263 pbconfurl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe/pbconf
264
265 # This is normaly defined in the project's configuration file
266 # Url of the project
267 #
268 pburl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe
269
270 # All these URLs needs to be defined here as the are the entry point
271 # for how to build packages for the project
272 #
273 pbconfurl pb = svn+ssh://svn.project-builder.org/mondo/svn/pb/pbconf
274 pbconfurl mondorescue = svn+ssh://svn.project-builder.org/mondo/svn/project-builder/mondorescue/pbconf
275 pbconfurl collectl = svn+ssh://bruno@svn.mondorescue.org/mondo/svn/project-builder/collectl/pbconf
276 pbconfurl netperf = svn+ssh://svn.mondorescue.org/mondo/svn/project-builder/netperf/pbconf
277
278 # Under that dir will take place everything related to pb
279 # If you want to use VMs/chroot/..., then use $ENV{'HOME'} to make it portable
280 # to your VMs/chroot/...
281 # if not defined then /var/cache
282 pbdefdir default = $ENV{'HOME'}/project-builder
283 pbdefdir pb = $ENV{'HOME'}
284 pbdefdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
285 pbdefdir mondorescue = $ENV{'HOME'}/mondo/svn
286
287 # pbconfdir points to the directory where the CMS content of the pbconfurl is checked out
288 # If not defined, pbconfdir is under pbdefdir/pbproj/pbconf
289 pbconfdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs/pbconf
290 pbconfdir mondorescue = $ENV{'HOME'}/mondo/svn/pbconf
291
292 # pbdir points to the directory where the CMS content of the pburl is checked out
293 # If not defined, pbdir is under pbdefdir/pbproj
294 # Only defined if we have access to the dev of the project
295 pbdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
296 pbdir mondorescue = $ENV{'HOME'}/mondo/svn
297
298 # -daemonize doesn't work with qemu 0.8.2
299 vmopt default = -m 384
300
301=head1 AUTHORS
302
303The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
304
305=head1 COPYRIGHT
306
307Project-Builder.org is distributed under the GPL v2.0 license
308described in the file C<COPYING> included with the distribution.
309
310=cut
311
312# ---------------------------------------------------------------------------
313
314# Old syntax
315#getopts('a:fhi:l:m:P:p:qr:s:vV:',\%opts);
316
317my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
318
319# Initialize the syntax string
320
321pb_syntax_init("pb (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n");
322
323GetOptions("help|?|h" => \$opts{'h'},
324 "man" => \$opts{'man'},
325 "verbose|v+" => \$opts{'v'},
326 "quiet|q" => \$opts{'q'},
327 "log-files|l=s" => \$opts{'l'},
328 "force|f" => \$opts{'f'},
329 "account|a=s" => \$opts{'a'},
330 "revision|r=s" => \$opts{'r'},
331 "script|s=s" => \$opts{'s'},
332 "machines|mock|m=s" => \$opts{'m'},
333 "port|P=i" => \$opts{'P'},
334 "project|p=s" => \$opts{'p'},
335 "iso|i=s" => \$opts{'i'},
336 "version|V=s" => \$opts{'V'},
337) || pb_syntax(-1,0);
338
339if (defined $opts{'h'}) {
340 pb_syntax(0,1);
341}
342if (defined $opts{'man'}) {
343 pb_syntax(0,2);
344}
345if (defined $opts{'v'}) {
346 $pbdebug = $opts{'v'};
347}
348if (defined $opts{'f'}) {
349 $force=1;
350}
351if (defined $opts{'q'}) {
352 $pbdebug=-1;
353}
354if (defined $opts{'l'}) {
355 open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
356 $pbLOG = \*pbLOG;
357 $pbdebug = 0 if ($pbdebug == -1);
358 }
359pb_log_init($pbdebug, $pbLOG);
360pb_display_init("text","");
361
362# Handle root of the project if defined
363if (defined $opts{'r'}) {
364 $ENV{'PBROOTDIR'} = $opts{'r'};
365}
366# Handle virtual machines if any
367if (defined $opts{'m'}) {
368 $ENV{'PBV'} = $opts{'m'};
369}
370if (defined $opts{'s'}) {
371 $pbscript = $opts{'s'};
372}
373if (defined $opts{'a'}) {
374 $pbaccount = $opts{'a'};
375 die "option -a requires a -s script option" if (not defined $pbscript);
376}
377if (defined $opts{'P'}) {
378 $pbport = $opts{'P'};
379}
380if (defined $opts{'V'}) {
381 $newver = $opts{'V'};
382}
383if (defined $opts{'i'}) {
384 $iso = $opts{'i'};
385}
386
387# Get Action
388$action = shift @ARGV;
389die pb_syntax(-1,1) if (not defined $action);
390
391my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
392my $pbinit = undef;
393$pbinit = 1 if ($action =~ /^newproj$/);
394
395# Handles project name if any
396# And get global params
397($filteredfiles, $supfiles, $defpkgdir, $extpkgdir) = pb_env_init($opts{'p'},$pbinit,$action);
398
399pb_log(0,"Project: $ENV{'PBPROJ'}\n");
400pb_log(0,"Action: $action\n");
401
402# Act depending on action
403if ($action =~ /^cms2build$/) {
404 pb_cms2build();
405} elsif ($action =~ /^build2pkg$/) {
406 pb_build2pkg();
407} elsif ($action =~ /^cms2pkg$/) {
408 pb_cms2build();
409 pb_build2pkg();
410} elsif ($action =~ /^build2ssh$/) {
411 pb_build2ssh();
412} elsif ($action =~ /^cms2ssh$/) {
413 pb_cms2build();
414 pb_build2ssh();
415} elsif ($action =~ /^pkg2ssh$/) {
416 pb_pkg2ssh();
417} elsif ($action =~ /^build2ve$/) {
418 pb_build2v("ve");
419} elsif ($action =~ /^build2vm$/) {
420 pb_build2v("vm");
421} elsif ($action =~ /^cms2ve$/) {
422 pb_cms2build();
423 pb_build2v("ve");
424} elsif ($action =~ /^cms2vm$/) {
425 pb_cms2build();
426 pb_build2v("vm");
427} elsif ($action =~ /^launchvm$/) {
428 pb_launchv("vm",$ENV{'PBV'},0);
429} elsif ($action =~ /^launchve$/) {
430 pb_launchv("ve",$ENV{'PBV'},0);
431} elsif ($action =~ /^script2vm$/) {
432 pb_script2v($pbscript,"vm");
433} elsif ($action =~ /^script2ve$/) {
434 pb_script2v($pbscript,"ve");
435} elsif ($action =~ /^newver$/) {
436 pb_newver();
437} elsif ($action =~ /^newve$/) {
438 pb_launchv("ve",$ENV{'PBV'},1);
439} elsif ($action =~ /^newvm$/) {
440 pb_launchv("vm",$ENV{'PBV'},1);
441} elsif ($action =~ /^setupve$/) {
442 pb_setup_v("ve");
443} elsif ($action =~ /^setupvm$/) {
444 pb_setup_v("vm");
445} elsif ($action =~ /^newproj$/) {
446 # Nothing to do - already done in pb_env_init
447} elsif ($action =~ /^clean$/) {
448 # TBC
449} elsif ($action =~ /^announce$/) {
450 # For announce only. Require avoids the systematic load of these modules
451 require DBI;
452 require DBD::SQLite;
453
454 pb_announce();
455} elsif ($action =~ /^web2ssh$/) {
456 require DBI;
457 require DBD::SQLite;
458
459 pb_cms2build("Web");
460 pb_send2target("Web");
461} else {
462 pb_log(0,"\'$action\' is not available\n");
463 pb_syntax(-2,1);
464}
465
466sub pb_cms2build {
467
468 my $param = shift || undef;
469
470 my $pkg;
471 my @pkgs;
472 my $webdir;
473
474 my %pkgs;
475 my %pb; # Structure to store conf info
476
477 # If Website, then pkg is only the website
478 if ((defined $param) && ($param eq "Web")) {
479 ($webdir) = pb_conf_get("webdir");
480 pb_log(2,"webdir: ".Dumper($webdir)."\n");
481 $pkgs[0] = $webdir->{$ENV{'PBPROJ'}};
482 $extpkgdir = $webdir;
483 pb_log(0,"Package: $pkgs[0]\n");
484 } else {
485 $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
486 @pkgs = @$pkg;
487 }
488
489 my ($scheme, $uri) = pb_cms_init($pbinit);
490
491 my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
492
493 # declare packager and repo for filtering
494 my ($tmp1, $tmp2) = pb_conf_get("pbpackager","pbrepo");
495 $ENV{'PBPACKAGER'} = $tmp1->{$ENV{'PBPROJ'}};
496 $ENV{'PBREPO'} = $tmp2->{$ENV{'PBPROJ'}};
497
498 foreach my $pbpkg (@pkgs) {
499 $ENV{'PBPKG'} = $pbpkg;
500 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
501 $pbver = $pkgv->{$pbpkg};
502 } else {
503 $pbver = $ENV{'PBPROJVER'};
504 }
505 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
506 $pbtag = $pkgt->{$pbpkg};
507 } else {
508 $pbtag = $ENV{'PBPROJTAG'};
509 }
510
511 $pbrev = $ENV{'PBREVISION'};
512 pb_log(0,"\n");
513 pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
514 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
515
516 # Clean up dest if necessary. The export will recreate it
517 my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
518 pb_rm_rf($dest) if (-d $dest);
519
520 # Export CMS tree for the concerned package to dest
521 # And generate some additional files
522 $OUTPUT_AUTOFLUSH=1;
523
524 # computes in which dir we have to work
525 my $dir = $defpkgdir->{$pbpkg};
526 $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
527 $dir = $webdir->{$ENV{'PBPROJ'}} if ((defined $param) && ($param eq "Web"));
528 pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
529
530 # Exporting content from CMS
531 my $preserve = pb_cms_export($uri,"$ENV{'PBDIR'}/$dir",$dest);
532
533 # Generated fake content for test versions to speed up stuff
534 my ($testver) = pb_conf_get_if("testver");
535 my $chglog;
536
537 # Get project info on authors and log file
538 $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
539 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
540 $chglog = undef if (! -f $chglog);
541
542 my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
543 $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
544 $authors = "/dev/null" if (! -f $authors);
545
546 # Extract cms log history and store it
547 if ((defined $chglog) && (! -f "$dest/NEWS")) {
548 pb_log(2,"Generating NEWS file from $chglog\n");
549 copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
550 }
551 pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors,$testver);
552
553 my %build;
554 my @pt;
555 my $tmpl = "";
556 my %patches;
557
558 @pt = pb_conf_get_if("vmlist","velist");
559 if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
560 $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
561 }
562 if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
563 # the 2 lists needs to be grouped with a ',' separated them
564 if ($tmpl ne "") {
565 $tmpl .= ",";
566 }
567 $tmpl .= $pt[1]->{$ENV{'PBPROJ'}}
568 }
569
570 # Setup %pb structure to allow filtering later on, on files using that structure
571 $pb{'tag'} = $pbtag;
572 $pb{'rev'} = $pbrev;
573 $pb{'ver'} = $pbver;
574 $pb{'pkg'} = $pbpkg;
575 $pb{'date'} = $pbdate;
576 $pb{'defpkgdir'} = $defpkgdir;
577 $pb{'extpkgdir'} = $extpkgdir;
578 $pb{'chglog'} = $chglog;
579 $pb{'packager'} = $ENV{'PBPACKAGER'};
580 $pb{'proj'} = $ENV{'PBPROJ'};
581 $pb{'repo'} = $ENV{'PBREPO'};
582 $pb{'patches'} = \%patches;
583 pb_log(2,"DEBUG: pb: ".Dumper(%pb)."\n");
584
585 # Do not do that for website
586 if ((not defined $param) || ($param ne "Web")) {
587 foreach my $d (split(/,/,$tmpl)) {
588 my ($name,$ver,$arch) = split(/-/,$d);
589 chomp($arch);
590 my ($ddir, $dver, $dfam);
591 ($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'suf'}) = pb_distro_init($name,$ver);
592 pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'suf'})."\n");
593 pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
594
595 # We need to compute the real name of the package
596 my $pbrealpkg = pb_cms_get_real_pkg($pbpkg,$pb{'dtype'});
597 $pb{'realpkg'} = $pbrealpkg;
598 pb_log(1,"Virtual package $pbpkg has a real package name of $pbrealpkg on $ddir-$dver\n") if ($pbrealpkg ne $pbpkg);
599
600 # Filter build files from the less precise up to the most with overloading
601 # Filter all files found, keeping the name, and generating in dest
602
603 # Find all build files first relatively to PBROOTDIR
604 # Find also all specific files referenced in the .pb conf file
605 my %bfiles = ();
606 my %pkgfiles = ();
607 $build{"$ddir-$dver-$arch"} = "yes";
608
609 if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}") {
610 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
611 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
612 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
613 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
614 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
615 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
616 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
617 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch") {
618 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
619 } else {
620 $build{"$ddir-$dver-$arch"} = "no";
621 next;
622 }
623 pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
624
625 # Get all filters to apply
626 my $ptr = pb_get_filters($pbpkg, $pb{'dtype'}, $dfam, $ddir, $dver);
627
628 # Prepare local patches for this distro - They are always applied first - May be a problem one day
629 foreach my $p (sort(<$ENV{'PBROOTDIR'}/$pbpkg/pbpatch/*>)) {
630 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.all$/));
631 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.all$/);
632 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$pb{'dtype'}$/));
633 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$pb{'dtype'}$/);
634 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$dfam$/));
635 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$dfam$/);
636 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir$/));
637 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir$/);
638 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver$/));
639 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver$/);
640 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver-$arch$/));
641 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver-$arch$/);
642 }
643
644 # Prepare also remote patches to be included - Applied after the local ones
645 foreach my $p ("all","$pb{'dtype'}","$dfam","$ddir","$ddir-$dver","$ddir-$dver-$arch") {
646 my $f = "$ENV{'PBROOTDIR'}/$pbpkg/pbextpatch.$p";
647 next if (not -f $f);
648 if (not open(PATCH,$f)) {
649 pb_display("Unable to open existing external patch file content $f\n");
650 next;
651 }
652 while (<PATCH>) {
653 chomp();
654 $patches{"$ddir-$dver-$arch"} .= "," if (defined $patches{"$ddir-$dver-$arch"});
655 $patches{"$ddir-$dver-$arch"} .= "$_";
656 }
657 close(PATCH);
658 }
659 pb_log(2,"DEBUG: pb->patches: ".Dumper($pb{'patches'})."\n");
660
661 # Apply now all the filters on all the files concerned
662 # destination dir depends on the type of file
663 if (defined $ptr) {
664 # For patch support
665 $pb{'tuple'} = "$ddir-$dver-$arch";
666 foreach my $f (values %bfiles,values %pkgfiles) {
667 pb_filter_file("$ENV{'PBROOTDIR'}/$f",$ptr,"$dest/pbconf/$ddir-$dver-$arch/".basename($f),\%pb);
668 }
669 }
670 }
671 my @found;
672 my @notfound;
673 foreach my $b (keys %build) {
674 push @found,$b if ($build{$b} =~ /yes/);
675 push @notfound,$b if ($build{$b} =~ /no/);
676 }
677 pb_log(0,"Build files generated for ".join(',',sort(@found))."\n");
678 pb_log(0,"No Build files found for ".join(',',sort(@notfound))."\n") if (@notfound);
679 pb_log(2,"DEBUG: patches: ".Dumper(%patches)."\n");
680 }
681
682 # Get the generic filter (all.pbf) and
683 # apply those to the non-build files including those
684 # generated by pbinit if applicable
685
686 # Get only all.pbf filter
687 my $ptr = pb_get_filters($pbpkg);
688
689 my $liste ="";
690 if (defined $filteredfiles->{$pbpkg}) {
691 foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
692 pb_filter_file_inplace($ptr,"$dest/$f",\%pb);
693 $liste = "$f $liste";
694 }
695 }
696 pb_log(2,"Files ".$liste."have been filtered\n");
697
698 # Do not do that for website
699 if ((not defined $param) || ($param ne "Web")) {
700 my %tmp;
701 # Filter potential patches (local + remote)
702 pb_log(0,"Delivering and compressing patches ");
703 foreach my $v (keys %patches) {
704 pb_mkdir_p("$dest/pbconf/$v/pbpatch");
705 foreach my $pf (split(/,/,$patches{$v})) {
706 my $pp = basename($pf);
707 pb_cms_export($pf,undef,"$dest/pbconf/$v/pbpatch");
708 pb_filter_file_inplace($ptr,"$dest/pbconf/$v/pbpatch/$pp",\%pb);
709 pb_system("gzip -9f $dest/pbconf/$v/pbpatch/$pp","","quiet");
710 $tmp{$pf} = "";
711 }
712 }
713 foreach my $v (keys %tmp) {
714 pb_log(0,"$v ");
715 }
716 pb_log(0,"\n");
717 } else {
718 # Instead call News generation
719 pb_web_news2html($dest);
720 # And create an empty pbconf
721 pb_mkdir_p("$dest/pbconf");
722 # And prepare the pbscript to execute remotely
723 open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
724 print SCRIPT "#!/bin/bash\n";
725 print SCRIPT "#set -x\n";
726 print SCRIPT "echo ... Extracting Website content\n";
727 print SCRIPT "find . -type f | grep -Ev '^./$pbpkg-$pbver.tar.gz|^./pbscript' | xargs rm -f non-existent\n";
728 print SCRIPT "find * -type d -depth | xargs rmdir 2> /dev/null \n";
729 print SCRIPT "tar xfz $pbpkg-$pbver.tar.gz\n";
730 print SCRIPT "mv $pbpkg-$pbver/* .\n";
731 print SCRIPT "rm -f $pbpkg-$pbver.tar.gz\n";
732 print SCRIPT "rmdir $pbpkg-$pbver\n";
733 close(SCRIPT);
734 }
735
736 # Prepare the dest directory for archive
737 if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
738 pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",\%pb);
739 chmod 0755,"$ENV{'PBTMP'}/pbinit";
740 pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit","verbose");
741 }
742
743 # Archive dest dir
744 chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
745 if (defined $preserve) {
746 # In that case we want to preserve the original tar file for checksum purposes
747 # The one created is btw equivalent in that case to this one
748 # Maybe check basename of both to be sure they are the same ?
749 pb_log(0,"Preserving original tar file ");
750 move("$preserve","$pbpkg-$pbver.tar.gz");
751 } else {
752 # Possibility to look at PBSRC to guess more the filename
753 pb_system("tar cfz $pbpkg-$pbver.tar.gz --exclude=$pbpkg-$pbver/pbconf $pbpkg-$pbver","Creating $pbpkg tar files compressed");
754 }
755 pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
756 pb_system("tar cfz $pbpkg-$pbver.pbconf.tar.gz $pbpkg-$pbver/pbconf","Creating pbconf tar files compressed");
757 pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz\n");
758
759 # Keep track of version-tag per pkg
760 $pkgs{$pbpkg} = "$pbver-$pbtag";
761
762 # Final cleanup
763 pb_rm_rf($dest) if (-d $dest);
764 }
765
766 # Keep track of per package version
767 pb_log(2,"DEBUG pkgs: ".Dumper(%pkgs)."\n");
768 open(PKG,"> $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb";
769 foreach my $pbpkg (keys %pkgs) {
770 print PKG "pbpkg $pbpkg = $pkgs{$pbpkg}\n";
771 }
772 close(PKG);
773
774 # Keep track of what is generated by default
775 # We need to store the dir and info on version-tag
776 # Base our content on the existing .pb file
777 copy("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb","$ENV{'PBDESTDIR'}/pbrc");
778 open(LAST,">> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
779 print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
780 print LAST "pbprojver $ENV{'PBPROJ'} = $ENV{'PBPROJVER'}\n";
781 print LAST "pbprojtag $ENV{'PBPROJ'} = $ENV{'PBPROJTAG'}\n";
782 print LAST "pbpackager $ENV{'PBPROJ'} = $ENV{'PBPACKAGER'}\n";
783 close(LAST);
784}
785
786sub pb_build2pkg {
787
788 # Get the running distro to build on
789 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
790 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
791
792 # Get list of packages to build
793 # Get content saved in cms2build
794 my $ptr = pb_get_pkg();
795 @pkgs = @$ptr;
796
797 my $arch = pb_get_arch();
798
799 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
800 $pkg = { } if (not defined $pkg);
801
802 chdir "$ENV{'PBBUILDDIR'}";
803 my $made = ""; # pkgs made during build
804 foreach my $pbpkg (@pkgs) {
805 my $vertag = $pkg->{$pbpkg};
806 # get the version of the current package - maybe different
807 ($pbver,$pbtag) = split(/-/,$vertag);
808
809 my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
810 my $src2="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
811 pb_log(2,"Source file: $src\n");
812 pb_log(2,"Pbconf file: $src2\n");
813
814 pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
815 if ($dtype eq "rpm") {
816 foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
817 if (! -d "$ENV{'PBBUILDDIR'}/$d") {
818 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$d") || die "Please ensure that you can write into $ENV{'PBBUILDDIR'} to create $d\nchown the $ENV{'PBBUILDDIR'} directory to your uid";
819 }
820 }
821
822 # Remove in case a previous link/file was there
823 unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
824 symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
825 # We need to first extract the spec file
826 my @specfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$ENV{'PBBUILDDIR'}/SPECS","spec");
827
828 # We need to handle potential patches to upstream sources
829 pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/pbpatch/","$ENV{'PBBUILDDIR'}/SOURCES","patch");
830
831 pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
832 # set LANGUAGE to check for correct log messages
833 $ENV{'LANGUAGE'}="C";
834 # Older Redhat use _target_platform in %configure incorrectly
835 my $specialdef = "";
836 if (($ddir eq "redhat") || (($ddir eq "rhel") && ($dver eq "2.1"))) {
837 $specialdef = "--define \'_target_platform \"\"\'";
838 }
839 foreach my $f (@specfile) {
840 if ($f =~ /\.spec$/) {
841 pb_system("rpmbuild $specialdef --define \'packager $ENV{'PBPACKAGER'}\' --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}","verbose");
842 last;
843 }
844 }
845 # Get the name of the generated packages
846 open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to open $ENV{'PBTMP'}/system.log";
847 while (<LOG>) {
848 chomp();
849 next if ($_ !~ /^Wrote:/);
850 s|.*/([S]*RPMS.*)|$1|;
851 $made="$made $_";
852 }
853 close(LOG);
854
855 } elsif ($dtype eq "deb") {
856 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
857 pb_system("tar xfz $src","Extracting sources");
858 pb_system("tar xfz $src2","Extracting pbconf");
859
860 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
861 pb_rm_rf("debian");
862 symlink "pbconf/$ddir-$dver-$arch","debian" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
863 chmod 0755,"debian/rules";
864
865 pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package","verbose");
866 # Get the name of the generated packages
867 open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to open $ENV{'PBTMP'}/system.log";
868 while (<LOG>) {
869 chomp();
870 my $tmp = $_;
871 next if ($tmp !~ /^dpkg-deb.:/);
872 $tmp =~ s|.*../(.*)_(.*).deb.*|$1|;
873 $made="$made $tmp.dsc $tmp.tar.gz $tmp"."_*.deb $tmp"."_*.changes";
874 }
875 close(LOG);
876 } elsif ($dtype eq "ebuild") {
877 my @ebuildfile;
878 # For gentoo we need to take pb as subsystem name
879 # We put every apps here under sys-apps. hope it's correct
880 # We use pb's home dir in order to have a single OVERLAY line
881 my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
882 pb_mkdir_p($tmpd) if (! -d "$tmpd");
883 pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
884
885 # We need to first extract the ebuild file
886 @ebuildfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$tmpd","ebuild");
887
888 # Prepare the build env for gentoo
889 my $found = 0;
890 my $pbbd = $ENV{'HOME'};
891 $pbbd =~ s|/|\\/|g;
892 if (-r "/etc/make.conf") {
893 open(MAKE,"/etc/make.conf");
894 while (<MAKE>) {
895 $found = 1 if (/$pbbd\/portage/);
896 }
897 close(MAKE);
898 }
899 if ($found == 0) {
900 pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
901 }
902 #$found = 0;
903 #if (-r "/etc/portage/package.keywords") {
904 #open(KEYW,"/etc/portage/package.keywords");
905 #while (<KEYW>) {
906 #$found = 1 if (/portage\/pb/);
907 #}
908 #close(KEYW);
909 #}
910 #if ($found == 0) {
911 #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
912 #}
913
914 # Build
915 foreach my $f (@ebuildfile) {
916 if ($f =~ /\.ebuild$/) {
917 move($f,"$tmpd/$pbpkg-$pbver.ebuild");
918 pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package","verbose");
919 # Now move it where pb expects it
920 pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
921 move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
922 }
923 }
924
925 $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver.ebuild";
926 } elsif ($dtype eq "tgz") {
927 # Slackware family
928 $made="$made $pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
929
930 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
931 pb_system("tar xfz $src","Extracting sources");
932 pb_system("tar xfz $src2","Extracting pbconf");
933 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
934 symlink "pbconf/$ddir-$dver-$arch","install" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
935 if (-x "install/pbslack") {
936 pb_system("./install/pbslack","Building package");
937 pb_system("sudo /sbin/makepkg -p -l y -c y $pbpkg","Packaging $pbpkg","verbose");
938 }
939 } else {
940 die "Unknown dtype format $dtype";
941 }
942 }
943 # Packages check if needed
944 if ($dtype eq "rpm") {
945 if (-f "/usr/bin/rpmlint") {
946 pb_system("rpmlint $made","Checking validity of rpms with rpmlint","verbose");
947 }
948 } elsif ($dtype eq "deb") {
949 if (-f "/usr/bin/lintian") {
950 my $made2 = "";
951 foreach my $f (split(/ /,$made)) {
952 $made2 .= "$f " if ($f =~ /\.changes$/);
953 }
954 pb_system("lintian $made2","Checking validity of debs with lintian","verbose");
955 }
956 } else {
957 pb_log(0, "No check done for $dtype yet");
958 }
959
960 # Keep track of what is generated so that we can get them back from VMs
961 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
962 print KEEP "$made\n";
963 close(KEEP);
964}
965
966sub pb_build2ssh {
967 pb_send2target("Sources");
968}
969
970sub pb_pkg2ssh {
971 pb_send2target("Packages");
972}
973
974# By default deliver to the the public site hosting the
975# ftp structure (or whatever) or a VM/VE
976sub pb_send2target {
977
978 my $cmt = shift;
979 my $v = shift || undef;
980 my $vmexist = shift || 0; # 0 is FALSE
981 my $vmpid = shift || 0; # 0 is FALSE
982
983 pb_log(2,"DEBUG: pb_send2target($cmt,".Dumper($v).",$vmexist,$vmpid)\n");
984 my $host = "sshhost";
985 my $login = "sshlogin";
986 my $dir = "sshdir";
987 my $port = "sshport";
988 my $conf = "sshconf";
989 my $rebuild = "sshrebuild";
990 my $tmout = "vmtmout";
991 my $path = "vmpath";
992 if (($cmt eq "vm") || ($cmt eq "Script")) {
993 $login = "vmlogin";
994 $dir = "pbdefdir";
995 $tmout = "vmtmout";
996 $rebuild = "vmrebuild";
997 # Specific VM
998 $host = "vmhost";
999 $port = "vmport";
1000 } elsif ($cmt eq "ve") {
1001 $login = "velogin";
1002 $dir = "pbdefdir";
1003 $tmout = "vetmout";
1004 # Specific VE
1005 $path = "vepath";
1006 $conf = "veconf";
1007 $rebuild = "verebuild";
1008 } elsif ($cmt eq "Web") {
1009 $host = "websshhost";
1010 $login = "websshlogin";
1011 $dir = "websshdir";
1012 $port = "websshport";
1013 }
1014 my $cmd = "";
1015 my $src = "";
1016 my ($odir,$over,$oarch) = (undef, undef, undef);
1017 my ($ddir, $dver, $dfam, $dtype, $pbsuf);
1018
1019 if ($cmt ne "Announce") {
1020 my $ptr = pb_get_pkg();
1021 @pkgs = @$ptr;
1022
1023 # Get the running distro to consider
1024 if (defined $v) {
1025 ($odir,$over,$oarch) = split(/-/,$v);
1026 }
1027 ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($odir,$over);
1028 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
1029
1030 # Get list of packages to build
1031 # Get content saved in cms2build
1032 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1033 $pkg = { } if (not defined $pkg);
1034
1035 chdir "$ENV{'PBBUILDDIR'}";
1036 foreach my $pbpkg (@pkgs) {
1037 my $vertag = $pkg->{$pbpkg};
1038 # get the version of the current package - maybe different
1039 ($pbver,$pbtag) = split(/-/,$vertag);
1040
1041 if (($cmt eq "Sources") || ($cmt eq "vm") || ($cmt eq "ve")) {
1042 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
1043 if ($cmd eq "") {
1044 $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1045 } else {
1046 $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1047 }
1048 } elsif ($cmt eq "Web") {
1049 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz"
1050 }
1051 }
1052 # Adds conf file for availability of conf elements
1053 pb_conf_add("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb");
1054 }
1055
1056 if (($cmt eq "vm") || ($cmt eq "ve")) {
1057 $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript";
1058 } elsif (($cmt eq "Script") || ($cmt eq "Web")) {
1059 $src="$src $ENV{'PBDESTDIR'}/pbscript";
1060 } elsif ($cmt eq "Announce") {
1061 $src="$src $ENV{'PBTMP'}/pbscript";
1062 } elsif ($cmt eq "Packages") {
1063 # Get package list from file made during build2pkg
1064 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1065 $src = <KEEP>;
1066 chomp($src);
1067 close(KEEP);
1068 $src="$src $ENV{'PBBUILDDIR'}/pbscript" if ($cmt ne "Sources");
1069 }
1070 # Remove potential leading spaces (cause problem with basename)
1071 $src =~ s/^ *//;
1072 my $basesrc = "";
1073 foreach my $i (split(/ +/,$src)) {
1074 $basesrc .= " ".basename($i);
1075 }
1076
1077 pb_log(0,"Sources handled ($cmt): $src\n");
1078 pb_log(2,"values: ".Dumper(($host,$login,$dir,$port,$tmout,$rebuild,$path,$conf))."\n");
1079 my ($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vepath) = pb_conf_get($host,$login,$dir,$port,$tmout,$path);
1080 my ($vrebuild,$veconf) = pb_conf_get_if($rebuild,$conf);
1081 pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf))."\n");
1082 # Not mandatory
1083 my ($testver) = pb_conf_get_if("testver");
1084
1085 my $mac;
1086 # Useless for VE
1087 if ($cmt ne "ve") {
1088 $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
1089 # Overwrite account value if passed as parameter
1090 $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
1091 pb_log(2, "DEBUG: pbaccount: $pbaccount => mac: $mac\n") if (defined $pbaccount);
1092 }
1093
1094 my $tdir;
1095 my $bdir;
1096 if (($cmt eq "Sources") || ($cmt eq "Script")) {
1097 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/src";
1098 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
1099 # This is a test pkg => target dir is under test
1100 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/test/src";
1101 }
1102 } elsif (($cmt eq "vm") || ($cmt eq "ve")) {
1103 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
1104 $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
1105 # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
1106 $bdir =~ s|\$ENV.+\}/||;
1107 } elsif ($cmt eq "Announce") {
1108 $tdir = "$sshdir->{$ENV{'PBPROJ'}}";
1109 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
1110 # This is a test pkg => target dir is under test
1111 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/test";
1112 }
1113 } elsif ($cmt eq "Web") {
1114 $tdir = "$sshdir->{$ENV{'PBPROJ'}}";
1115 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
1116 # This is a test website => target dir is under test
1117 $tdir = $sshdir->{$ENV{'PBPROJ'}}."../test";
1118 }
1119 } elsif ($cmt eq "Packages") {
1120 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ddir/$dver";
1121
1122 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
1123 # This is a test pkg => target dir is under test
1124 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/test/$ddir/$dver";
1125 }
1126
1127 my $repodir = $tdir;
1128 $repodir =~ s|^$sshdir->{$ENV{'PBPROJ'}}/||;
1129
1130 my ($pbrepo) = pb_conf_get("pbrepo");
1131
1132 # Repository management
1133 open(PBS,"> $ENV{'PBBUILDDIR'}/pbscript") || die "Unable to create $ENV{'PBBUILDDIR'}/pbscript";
1134 if ($dtype eq "rpm") {
1135 # Also make a pbscript to generate yum/urpmi bases
1136 print PBS << "EOF";
1137#!/bin/bash
1138# Prepare a script to ease yum setup
1139cat > $ENV{'PBPROJ'}.repo << EOT
1140[$ENV{'PBPROJ'}]
1141name=$ddir $dver - $ENV{'PBPROJ'} Vanilla Packages
1142baseurl=$pbrepo->{$ENV{'PBPROJ'}}/$repodir
1143enabled=1
1144gpgcheck=0
1145EOT
1146chmod 644 $ENV{'PBPROJ'}.repo
1147
1148# Clean up old repo content
1149rm -rf headers/ repodata/
1150# Create yum repo
1151yum-arch .
1152# Create repodata
1153createrepo .
1154EOF
1155 if ($dfam eq "md") {
1156 # For Mandriva add urpmi management
1157 print PBS << "EOF";
1158# Prepare a script to ease urpmi setup
1159cat > $ENV{'PBPROJ'}.addmedia << EOT
1160urpmi.addmedia $ENV{'PBPROJ'} $pbrepo->{$ENV{'PBPROJ'}}/$repodir with hdlist.cz
1161EOT
1162chmod 755 $ENV{'PBPROJ'}.addmedia
1163
1164# Clean up old repo content
1165rm -f hdlist.cz synthesis.hdlist.cz
1166# Create urpmi repo
1167genhdlist .
1168EOF
1169 }
1170 if ($ddir eq "fedora") {
1171 # Extract the spec file to please Fedora maintainers :-(
1172 print PBS << "EOF";
1173for p in $basesrc; do
1174 echo \$p | grep -q 'src.rpm'
1175 if [ \$\? -eq 0 ]; then
1176 rpm2cpio \$p | cpio -ivdum --quiet '*.spec'
1177 fi
1178done
1179EOF
1180 }
1181 } elsif ($dtype eq "deb") {
1182 # Also make a pbscript to generate apt bases
1183 # Cf: http://www.debian.org/doc/manuals/repository-howto/repository-howto.fr.html
1184 my $rpd = dirname("$pbrepo->{$ENV{'PBPROJ'}}/$repodir");
1185 print PBS << "EOF";
1186#!/bin/bash
1187# Prepare a script to ease apt setup
1188cat > $ENV{'PBPROJ'}.sources.list << EOT
1189deb $rpd $dver contrib
1190deb-src $rpd $dver contrib
1191EOT
1192chmod 644 $ENV{'PBPROJ'}.sources.list
1193
1194# Prepare a script to create apt info file
1195(cd .. ; for a in i386 amd64 ia64; do mkdir -p dists/$dver/contrib/binary-\$a; dpkg-scanpackages -a\$a $dver /dev/null | gzip -c9 > dists/$dver/contrib/binary-\$a/Packages.gz; done; mkdir -p dists/$dver/contrib/source; dpkg-scansources $dver /dev/null | gzip -c9 > dists/$dver/contrib/source/Sources.gz)
1196#(cd .. ; rm -f dists/$dver/Release ; apt-ftparchive release dists/$dver > dists/$dver/Release; gpg --sign -ba -o dists/$dver/Release.gpg dists/$dver/Release)
1197EOF
1198 }
1199 close(PBS);
1200 chmod 0755,"$ENV{'PBBUILDDIR'}/pbscript";
1201
1202 } else {
1203 return;
1204 }
1205
1206 # Useless for VE
1207 my $nport;
1208 if ($cmt ne "ve") {
1209 $nport = $sshport->{$ENV{'PBPROJ'}};
1210 $nport = "$pbport" if (defined $pbport);
1211 }
1212
1213 # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
1214 $tdir =~ s|\$ENV.+\}/||;
1215
1216 my $tm = $vtmout->{$ENV{'PBPROJ'}};
1217
1218 # ssh communication if not VE
1219 # should use a hash instead...
1220 my ($shcmd,$cpcmd,$cptarget,$cp2target);
1221 if ($cmt ne "ve") {
1222 my $keyfile = pb_ssh_get(0);
1223 $shcmd = "ssh -i $keyfile -q -o UserKnownHostsFile=/dev/null -p $nport $mac";
1224 $cpcmd = "scp -i $keyfile -p -o UserKnownHostsFile=/dev/null -P $nport";
1225 $cptarget = "$mac:$tdir";
1226 if ($cmt eq "vm") {
1227 $cp2target = "$mac:$bdir";
1228 }
1229 } else {
1230 my $tp = $vepath->{$ENV{'PBPROJ'}};
1231 $shcmd = "sudo chroot $tp/$v /bin/su - $sshlogin->{$ENV{'PBPROJ'}} -c ";
1232 $cpcmd = "cp -a ";
1233 $cptarget = "$tp/$tdir";
1234 $cp2target = "$tp/$bdir";
1235 }
1236
1237 my $logres = "";
1238 # Do not touch when just announcing
1239 if ($cmt ne "Announce") {
1240 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");
1241 } else {
1242 $logres = "> ";
1243 }
1244 pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
1245
1246 # For VE we need to change the owner manually - To be tested if needed
1247 #if ($cmt eq "ve") {
1248 #pb_system("cd $cptarget ; sudo chown -R $sshlogin->{$ENV{'PBPROJ'}} .","$cmt chown in $cptarget to $sshlogin->{$ENV{'PBPROJ'}}");
1249 #}
1250 pb_system("$shcmd \"echo \'cd $tdir ; if [ -f pbscript ]; then ./pbscript; fi ; rm -f ./pbscript\' | bash\"","Executing pbscript on $cptarget if needed","verbose");
1251 if (($cmt eq "vm") || ($cmt eq "ve")) {
1252 # Get back info on pkg produced, compute their name and get them from the VM
1253 pb_system("$cpcmd $cp2target/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'} $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $cp2target");
1254 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1255 my $src = <KEEP>;
1256 chomp($src);
1257 close(KEEP);
1258 $src =~ s/^ *//;
1259 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
1260 # Change pgben to make the next send2target happy
1261 my $made = "";
1262 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1263 foreach my $p (split(/ +/,$src)) {
1264 my $j = basename($p);
1265 pb_system("$cpcmd $cp2target/\'$p\' $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Package recovery of $j in $cp2target");
1266 $made="$made $odir/$over/$j" if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
1267 }
1268 print KEEP "$made\n";
1269 close(KEEP);
1270 pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
1271
1272 # We want to send them to the ssh account so overwrite what has been done before
1273 undef $pbaccount;
1274 pb_log(2,"Before sending pkgs, vmexist: $vmexist, vmpid: $vmpid\n");
1275 pb_send2target("Packages",$odir."-".$over."-".$oarch,$vmexist,$vmpid);
1276 pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
1277 }
1278 pb_log(2,"Before halt, vmexist: $vmexist, vmpid: $vmpid\n");
1279 if ((! $vmexist) && (($cmt eq "vm") || ($cmt eq "Script"))) {
1280 pb_system("$shcmd \"sudo /sbin/halt -p \"; sleep $tm ; echo \'if [ -d /proc/$vmpid ]; then kill -9 $vmpid; fi \' | bash ; sleep 10","VM $v halt (pid $vmpid)");
1281 }
1282}
1283
1284sub pb_script2v {
1285 my $pbscript=shift;
1286 my $vtype=shift;
1287 my $force=shift || 0; # Force stop of VM. Default not
1288 my $vm1=shift || undef; # Only that VM to treat
1289 my $vm;
1290 my $all;
1291
1292 pb_log(2,"DEBUG: pb_script2v($pbscript,$vtype,$force,$vm1)\n");
1293 # Prepare the script to be executed on the VM
1294 # in $ENV{'PBDESTDIR'}/pbscript
1295 if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
1296 copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1297 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1298 }
1299
1300 if (not defined $vm1) {
1301 ($vm,$all) = pb_get_v($vtype);
1302 } else {
1303 @$vm = ($vm1);
1304 }
1305 my ($vmexist,$vmpid) = (undef,undef);
1306
1307 foreach my $v (@$vm) {
1308 # Launch the VM/VE
1309 if ($vtype eq "vm") {
1310 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1311 pb_log(2,"DEBUG: After pb_launchv, vmexist: $vmexist, vmpid: $vmpid\n");
1312
1313 # Skip that VM if something went wrong
1314 next if (($vmpid == 0) && ($vmexist == 0));
1315
1316 # If force stopping the VM then reset vmexist
1317 if ($force == 1) {
1318 $vmpid = $vmexist;
1319 $vmexist = 0;
1320 }
1321 }
1322
1323 # Gather all required files to send them to the VM
1324 # and launch the build through pbscript
1325 pb_log(2,"DEBUG: Before send2target, vmexist: $vmexist, vmpid: $vmpid\n");
1326 pb_send2target("Script","$v",$vmexist,$vmpid);
1327
1328 }
1329}
1330
1331sub pb_launchv {
1332 my $vtype = shift;
1333 my $v = shift;
1334 my $create = shift || 0; # By default do not create a VM
1335
1336 pb_log(2,"DEBUG: pb_launchv($vtype,$v,$create)\n");
1337 die "No VM/VE defined, unable to launch" if (not defined $v);
1338 # Keep only the first VM in case many were given
1339 $v =~ s/,.*//;
1340
1341 my $arch = pb_get_arch();
1342
1343 # Launch the VMs/VEs
1344 if ($vtype eq "vm") {
1345 die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
1346
1347 my ($ptr,$vmopt,$vmpath,$vmport,$vmtmout,$vmsize) = pb_conf_get("vmtype","vmopt","vmpath","vmport","vmtmout","vmsize");
1348
1349 my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1350 if (not defined $ENV{'PBVMOPT'}) {
1351 $ENV{'PBVMOPT'} = "";
1352 }
1353 # Set a default timeout of 2 minutes
1354 if (not defined $ENV{'PBVMTMOUT'}) {
1355 $ENV{'PBVMTMOUT'} = "120";
1356 }
1357 if (defined $vmopt->{$v}) {
1358 $ENV{'PBVMOPT'} .= " $vmopt->{$v}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$v}/);
1359 } elsif (defined $vmopt->{$ENV{'PBPROJ'}}) {
1360 $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1361 }
1362 if (defined $vmtmout->{$v}) {
1363 $ENV{'PBVMTMOUT'} = $vmtmout->{$v};
1364 } elsif (defined $vmtmout->{$ENV{'PBPROJ'}}) {
1365 $ENV{'PBVMTMOUT'} = $vmtmout->{$ENV{'PBPROJ'}};
1366 }
1367 my $nport = $vmport->{$ENV{'PBPROJ'}};
1368 $nport = "$pbport" if (defined $pbport);
1369
1370 my $cmd;
1371 my $vmcmd; # has to be used for pb_check_ps
1372 my $vmm; # has to be used for pb_check_ps
1373 if ($vmtype eq "qemu") {
1374 my $qemucmd32;
1375 my $qemucmd64;
1376 if ($arch eq "x86_64") {
1377 $qemucmd32 = "/usr/bin/qemu-system-i386";
1378 $qemucmd64 = "/usr/bin/qemu";
1379 } else {
1380 $qemucmd32 = "/usr/bin/qemu";
1381 $qemucmd64 = "/usr/bin/qemu-system-x86_64";
1382 }
1383 if ($v =~ /x86_64/) {
1384 $vmcmd = "$qemucmd64";
1385 # Not needed with latest versions of qemu it seems
1386 #$vmcmd = "$qemucmd64 -no-kqemu";
1387 # This one may now be needed
1388 #$vmcmd = "$qemucmd64 -no-kvm";
1389 } else {
1390 $vmcmd = "$qemucmd32";
1391 }
1392 $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
1393 if ($create != 0) {
1394 $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
1395 }
1396 $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 $vmm"
1397 } elsif ($vmtype eq "xen") {
1398 } elsif ($vmtype eq "vmware") {
1399 } else {
1400 die "VM of type $vmtype not supported. Report to the dev team";
1401 }
1402 my ($tmpcmd,$void) = split(/ +/,$cmd);
1403 my $vmexist = pb_check_ps($tmpcmd,$vmm);
1404 my $vmpid = 0;
1405 if (! $vmexist) {
1406 if ($create != 0) {
1407 if (($vmtype eq "qemu") || ($vmtype eq "xen")) {
1408 pb_system("/usr/bin/qemu-img create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
1409 } elsif ($vmtype eq "vmware") {
1410 } else {
1411 }
1412 }
1413 if (! -f "$vmm") {
1414 pb_log(0,"Unable to find VM $vmm\n");
1415 } else {
1416 pb_system("$cmd &","Launching the VM $vmm");
1417 pb_system("sleep $ENV{'PBVMTMOUT'}","Waiting $ENV{'PBVMTMOUT'} s for VM $v to come up");
1418 $vmpid = pb_check_ps($tmpcmd,$vmm);
1419 pb_log(0,"VM $vmm launched (pid $vmpid)\n");
1420 }
1421 } else {
1422 pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
1423 }
1424 pb_log(2,"DEBUG: pb_launchv returns ($vmexist,$vmpid)\n");
1425 return($vmexist,$vmpid);
1426 # VE here
1427 } else {
1428 # Get VE context
1429 my ($ptr,$vetmout,$vepath,$verebuild,$veconf) = pb_conf_get("vetype","vetmout","vepath","verebuild","veconf");
1430 my $vetype = $ptr->{$ENV{'PBPROJ'}};
1431
1432 # Get distro context
1433 my ($name,$ver,$darch) = split(/-/,$v);
1434 chomp($darch);
1435 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
1436
1437 if ($vetype eq "chroot") {
1438 # Architecture consistency
1439 if ($arch ne $darch) {
1440 die "Unable to launch a VE of architecture $darch on a $arch platform" if (not (($darch eq "x86_64") && ($arch =~ /i?86/)));
1441 }
1442
1443 if (($create != 0) || ($verebuild->{$ENV{'PBPROJ'}} eq "true") || ($force == 1)) {
1444 # We have to rebuild the chroot
1445 if ($dtype eq "rpm") {
1446 pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1447 # Once setup we need to install some packages, the pb account, ...
1448 pb_system("sudo /usr/sbin/mock --install --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
1449 #pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" --basedir=\"$vepath->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1450 } elsif ($dtype eq "deb") {
1451 pb_system("","Creating the pbuilder VE");
1452 } elsif ($dtype eq "ebuild") {
1453 die "Please teach the dev team how to build gentoo chroot";
1454 } else {
1455 die "Unknown distribution type $dtype. Report to dev team";
1456 }
1457 }
1458 # Nothing more to do for VE. No real launch
1459 } else {
1460 die "VE of type $vetype not supported. Report to the dev team";
1461 }
1462 }
1463}
1464
1465sub pb_build2v {
1466
1467my $vtype = shift;
1468
1469# Prepare the script to be executed on the VM/VE
1470# in $ENV{'PBDESTDIR'}/pbscript
1471#my ($ntp) = pb_conf_get($vtype."ntp");
1472#my $vntp = $ntp->{$ENV{'PBPROJ'}};
1473
1474open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1475print SCRIPT "#!/bin/bash\n";
1476print SCRIPT "echo ... Execution needed\n";
1477print SCRIPT "# This is in directory delivery\n";
1478print SCRIPT "# Setup the variables required for building\n";
1479print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
1480print SCRIPT "# Preparation for pb\n";
1481print SCRIPT "mv .pbrc \$HOME\n";
1482print SCRIPT "cd ..\n";
1483# Force new date to be in the future compared to the date of the tar file by adding 1 minute
1484my @date=pb_get_date();
1485$date[1]++;
1486my $upddate = strftime("%m%d%H%M%Y", @date);
1487#print SCRIPT "echo Setting up date on $vntp...\n";
1488# Or use ntpdate if available TBC
1489print SCRIPT "sudo date $upddate\n";
1490# Get list of packages to build and get some ENV vars as well
1491my $ptr = pb_get_pkg();
1492@pkgs = @$ptr;
1493my $p = join(' ',@pkgs) if (@pkgs);
1494print SCRIPT "export PBPROJVER=$ENV{'PBPROJVER'}\n";
1495print SCRIPT "export PBPROJTAG=$ENV{'PBPROJTAG'}\n";
1496print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
1497print SCRIPT "# Build\n";
1498print SCRIPT "echo Building packages on $vtype...\n";
1499print SCRIPT "pb -p $ENV{'PBPROJ'} build2pkg $p\n";
1500close(SCRIPT);
1501chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1502
1503my ($v,$all) = pb_get_v($vtype);
1504
1505# Send tar files when we do a global generation
1506pb_build2ssh() if ($all == 1);
1507
1508my ($vmexist,$vmpid) = (undef,undef);
1509
1510foreach my $v (@$v) {
1511 if ($vtype eq "vm") {
1512 # Launch the VM
1513 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1514
1515 # Skip that VM if it something went wrong
1516 next if (($vmpid == 0) && ($vmexist == 0));
1517 }
1518 # Gather all required files to send them to the VM/VE
1519 # and launch the build through pbscript
1520 pb_log(2,"Calling send2target $vtype,$v,$vmexist,$vmpid\n");
1521 pb_send2target($vtype,"$v",$vmexist,$vmpid);
1522}
1523}
1524
1525
1526sub pb_newver {
1527
1528 die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
1529
1530 # Need this call for PBDIR
1531 my ($scheme2,$uri) = pb_cms_init($pbinit);
1532
1533 my ($pbconf) = pb_conf_get("pbconfurl");
1534 $uri = $pbconf->{$ENV{'PBPROJ'}};
1535 my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
1536
1537 # Checking CMS repositories status
1538 my ($pburl) = pb_conf_get("pburl");
1539 ($scheme2, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
1540
1541 if ($scheme !~ /^svn/) {
1542 die "Only SVN is supported at the moment";
1543 }
1544
1545 my $res = pb_cms_isdiff($scheme,$ENV{'PBROOTDIR'});
1546 die "ERROR: No differences accepted in CMS for $ENV{'PBROOTDIR'} before creating a new version" if ($res != 0);
1547
1548 $res = pb_cms_isdiff($scheme2,$ENV{'PBDIR'});
1549 die "ERROR: No differences accepted in CMS for $ENV{'PBDIR'} before creating a new version" if ($res != 0);
1550
1551 # Tree identical between PBCONFDIR and PBROOTDIR. The delta is what
1552 # we want to get for the root of the new URL
1553
1554 my $tmp = $ENV{'PBROOTDIR'};
1555 $tmp =~ s|^$ENV{'PBCONFDIR'}||;
1556
1557 my $newurl = "$uri/".dirname($tmp)."/$newver";
1558 # Should probably use projver in the old file
1559 my $oldver= basename($tmp);
1560
1561 # Duplicate and extract project-builder part
1562 pb_log(2,"Copying $uri/$tmp to $newurl\n");
1563 pb_cms_copy($scheme,"$uri/$tmp",$newurl);
1564 pb_log(2,"Checkout $newurl to $ENV{'PBROOTDIR'}/../$newver\n");
1565 pb_cms_up($scheme,"$ENV{'PBCONFDIR'}/..");
1566
1567 # Duplicate and extract project
1568 my $newurl2 = "$pburl->{$ENV{'PBPROJ'}}/".dirname($tmp)."/$newver";
1569
1570 pb_log(2,"Copying $pburl->{$ENV{'PBPROJ'}}/$tmp to $newurl2\n");
1571 pb_cms_copy($scheme,"$pburl->{$ENV{'PBPROJ'}}/$tmp",$newurl2);
1572 pb_log(2,"Checkout $newurl2 to $ENV{'PBDIR'}/../$newver\n");
1573 pb_cms_up($scheme,"$ENV{'PBDIR'}/..");
1574
1575 # Update the .pb file
1576 open(FILE,"$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb";
1577 open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new";
1578 while(<FILE>) {
1579 s/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
1580 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/);
1581 s/^testver/#testver/;
1582 pb_log(0,"Commenting testver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^testver/);
1583 print OUT $_;
1584 }
1585 close(FILE);
1586 close(OUT);
1587 rename("$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb");
1588
1589 # Checking pbcl files
1590 foreach my $f (<$ENV{'PBROOTDIR'}/*/pbcl>) {
1591 open(PBCL,$f) || die "Unable to open $f";
1592 my $foundnew = 0;
1593 while (<PBCL>) {
1594 $foundnew = 1 if (/^$newver \(/);
1595 }
1596 close(PBCL);
1597 open(OUT,"> $f.new") || die "Unable to write to $f.new: $!";
1598 open(PBCL,$f) || die "Unable to open $f";
1599 while (<PBCL>) {
1600 print OUT "$_" if (not /^$oldver \(/);
1601 if ((/^$oldver \(/) && ($foundnew == 0)) {
1602 print OUT "$newver ($pbdate)\n";
1603 print OUT "- TBD\n";
1604 print OUT "\n";
1605 pb_log(0,"WARNING: version $newver not found in $f so added...") if ($foundnew == 0);
1606 }
1607 }
1608 close(OUT);
1609 close(PBCL);
1610 rename("$f.new","$f");
1611 }
1612
1613 pb_log(2,"Checkin $ENV{'PBROOTDIR'}/../$newver\n");
1614 pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver",undef);
1615}
1616
1617#
1618# Return the list of VMs/VEs we are working on
1619# $all is a flag to know if we return all of them
1620# or only some (if all we publish also tar files in addition to pkgs
1621#
1622sub pb_get_v {
1623
1624my $vtype = shift;
1625my @v;
1626my $all = 0;
1627my $vlist;
1628my $pbv = 'PBV';
1629
1630if ($vtype eq "vm") {
1631 $vlist = "vmlist";
1632} elsif ($vtype eq "ve") {
1633 $vlist = "velist";
1634}
1635# Get VM/VE list
1636if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
1637 my ($ptr) = pb_conf_get($vlist);
1638 $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
1639 $all = 1;
1640}
1641pb_log(2,"$vtype: $ENV{$pbv}\n");
1642@v = split(/,/,$ENV{$pbv});
1643return(\@v,$all);
1644}
1645
1646# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
1647# Needs to use root account to connect to the VM/VE
1648# pb will take your local public SSH key to access
1649# the pb account in the VM later on if needed
1650sub pb_setup_v {
1651
1652my $vtype = shift;
1653
1654my ($vm,$all) = pb_get_v($vtype);
1655
1656# Script generated
1657my $pbscript = "$ENV{'PBDESTDIR'}/setupv";
1658
1659foreach my $v (@$vm) {
1660 # Name of the account to deal with for VM/VE
1661 # Do not use the one passed potentially with -a
1662 my ($pbac) = pb_conf_get($vtype."login");
1663 my ($key,$zero0,$zero1,$zero2);
1664 my ($vmexist,$vmpid,$ntps);
1665
1666 if ($vtype eq "vm") {
1667 # Prepare the key to be used and transfered remotely
1668 my $keyfile = pb_ssh_get(1);
1669
1670 my ($vmhost,$vmport,$vmntp) = pb_conf_get("vmhost","vmport","vmntp");
1671 my $nport = $vmport->{$ENV{'PBPROJ'}};
1672 $ntps = $vmntp->{$ENV{'PBPROJ'}};
1673 $nport = "$pbport" if (defined $pbport);
1674
1675 # Launch the VM
1676 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1677
1678 # Skip that VM if something went wrong
1679 next if (($vmpid == 0) && ($vmexist == 0));
1680
1681 # Store the pub key part in a variable
1682 open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
1683 ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
1684 close(FILE);
1685
1686 $key = "\Q$zero1";
1687
1688 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\"","Copying local keys to $vtype. This may require the root password");
1689 # once this is done, we can do what we want on the VM remotely
1690 }
1691
1692 # Prepare the script to be executed on the VM/VE
1693 # in $ENV{'PBDESTDIR'}/setupv
1694
1695 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
1696 print SCRIPT << 'EOF';
1697#!/usr/bin/perl -w
1698
1699use strict;
1700use File::Copy;
1701
1702# We should not need in this script more functions than what is provided
1703# by Base and Distribution to avoid problems at exec time.
1704# They are appended at the end.
1705
1706our $pbdebug;
1707our $pbLOG;
1708our $pbsynmsg = "pbscript";
1709our $pbdisplaytype = "text";
1710our $pblocale = "";
1711pb_log_init($pbdebug, $pbLOG);
1712pb_temp_init();
1713
1714EOF
1715 if ($vtype eq "vm") {
1716 print SCRIPT << 'EOF';
1717# Removes duplicate in .ssh/authorized_keys of our key if needed
1718#
1719my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
1720open(PBFILE,$file1) || die "Unable to open $file1";
1721open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
1722my $count = 0;
1723while (<PBFILE>) {
1724
1725EOF
1726 print SCRIPT << "EOF";
1727 if (/ $key /) {
1728 \$count++;
1729 }
1730print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
1731}
1732close(PBFILE);
1733close(PBOUT);
1734rename("\$file1.new",\$file1);
1735chmod 0600,\$file1;
1736
1737# Sync date
1738pb_system("/usr/sbin/ntpdate $ntps","Syncing date to $ntps");
1739
1740EOF
1741 }
1742 print SCRIPT << 'EOF';
1743
1744# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
1745#
1746my $file="/etc/passwd";
1747open(PBFILE,$file) || die "Unable to open $file";
1748my $found = 0;
1749while (<PBFILE>) {
1750EOF
1751 print SCRIPT << "EOF";
1752 \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
1753EOF
1754 print SCRIPT << 'EOF';
1755}
1756close(PBFILE);
1757
1758if ( $found == 0 ) {
1759 if ( ! -d "/home" ) {
1760 pb_mkdir("/home");
1761 }
1762EOF
1763 print SCRIPT << "EOF";
1764pb_system("groupadd $pbac->{$ENV{'PBPROJ'}}","Adding group $pbac->{$ENV{'PBPROJ'}}");
1765pb_system("useradd $pbac->{$ENV{'PBPROJ'}} -g $pbac->{$ENV{'PBPROJ'}} -m -d /home/$pbac->{$ENV{'PBPROJ'}}","Adding user $pbac->{$ENV{'PBPROJ'}} (group $pbac->{$ENV{'PBPROJ'}} - home /home/$pbac->{$ENV{'PBPROJ'}}");
1766}
1767
1768# allow ssh entry to build
1769#
1770mkdir "/home/$pbac->{$ENV{'PBPROJ'}}/.ssh",0700;
1771# Allow those accessing root to access the build account
1772copy("\$ENV{'HOME'}/.ssh/authorized_keys","/home/$pbac->{$ENV{'PBPROJ'}}/.ssh/authorized_keys");
1773chmod 0600,".ssh/authorized_keys";
1774pb_system("chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} /home/$pbac->{$ENV{'PBPROJ'}}/.ssh","Finish setting up the SSH env for $pbac->{$ENV{'PBPROJ'}}");
1775
1776EOF
1777 print SCRIPT << 'EOF';
1778# No passwd for build account only keys
1779$file="/etc/shadow";
1780open(PBFILE,$file) || die "Unable to open $file";
1781open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1782while (<PBFILE>) {
1783EOF
1784 print SCRIPT << "EOF";
1785 s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
1786 s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/; #SLES 9 e.g.
1787EOF
1788 print SCRIPT << 'EOF';
1789 print PBOUT $_;
1790}
1791close(PBFILE);
1792close(PBOUT);
1793rename("$file.new",$file);
1794chmod 0640,$file;
1795
1796# Keep the VM in text mode
1797$file="/etc/inittab";
1798if (-f $file) {
1799 open(PBFILE,$file) || die "Unable to open $file";
1800 open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1801 while (<PBFILE>) {
1802 s/^(..):5:initdefault:$/$1:3:initdefault:/;
1803 print PBOUT $_;
1804 }
1805 close(PBFILE);
1806 close(PBOUT);
1807 rename("$file.new",$file);
1808 chmod 0640,$file;
1809}
1810
1811# pb has to be added to portage group on gentoo
1812
1813# Adapt sudoers
1814$file="/etc/sudoers";
1815open(PBFILE,$file) || die "Unable to open $file";
1816open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1817while (<PBFILE>) {
1818EOF
1819 print SCRIPT << "EOF";
1820 next if (/^$pbac->{$ENV{'PBPROJ'}} /);
1821EOF
1822 print SCRIPT << 'EOF';
1823 s/Defaults[ \t]+requiretty//;
1824 print PBOUT $_;
1825}
1826close(PBFILE);
1827EOF
1828 print SCRIPT << "EOF";
1829# This is needed in order to be able to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
1830print PBOUT "$pbac->{$ENV{'PBPROJ'}} ALL=(ALL) NOPASSWD:ALL\n";
1831EOF
1832 print SCRIPT << 'EOF';
1833close(PBOUT);
1834rename("$file.new",$file);
1835chmod 0440,$file;
1836
1837EOF
1838
1839 my $SCRIPT = \*SCRIPT;
1840
1841 pb_install_deps($SCRIPT);
1842
1843 print SCRIPT << 'EOF';
1844# Suse wants sudoers as 640
1845if (($ddir eq "sles") || (($ddir eq "suse")) && ($dver =~ /10.[012]/)) {
1846 chmod 0640,$file;
1847}
1848
1849pb_system("rm -rf perl-ProjectBuilder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/perl-ProjectBuilder-latest.tar.gz ; tar xvfz perl-ProjectBuilder-latest.tar.gz ; cd perl-ProjectBuilder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf perl-ProjectBuilder-* ; rm -rf project-builder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/project-builder-latest.tar.gz ; tar xvfz project-builder-latest.tar.gz ; cd project-builder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf project-builder-* ;","Building Project-Builder");
1850system "pb 2>&1 | head -5";
1851EOF
1852 # Adds pb_distro_init from ProjectBuilder::Distribution and Base
1853 foreach my $d (@INC) {
1854 my @f = ("$d/ProjectBuilder/Base.pm","$d/ProjectBuilder/Distribution.pm");
1855 foreach my $f (@f) {
1856 if (-f "$f") {
1857 open(PBD,"$f") || die "Unable to open $f";
1858 while (<PBD>) {
1859 next if (/^package/);
1860 next if (/^use Exporter/);
1861 next if (/^use ProjectBuilder::/);
1862 next if (/^our /);
1863 print SCRIPT $_;
1864 }
1865 close(PBD);
1866 }
1867 }
1868 }
1869 close(SCRIPT);
1870 chmod 0755,"$pbscript";
1871
1872 # That build script needs to be run as root and force stop of VM at end
1873 $pbaccount = "root";
1874
1875 # Force shutdown of VM exept if it was already launched
1876 my $force = 0;
1877 if ((! $vmexist) && ($vtype eq "vm")) {
1878 $force = 1;
1879 }
1880
1881 pb_script2v($pbscript,$vtype,$force,$v);
1882}
1883return;
1884}
1885
1886sub pb_install_deps {
1887
1888my $SCRIPT = shift;
1889
1890print {$SCRIPT} << 'EOF';
1891# We need to have that pb_distro_init function
1892# Get it from Project-Builder::Distribution
1893my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
1894print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n";
1895
1896# Get and install pb
1897my $insdm = "rm -rf Date-Manip* ; wget http://search.cpan.org/CPAN/authors/id/S/SB/SBECK/Date-Manip-5.54.tar.gz ; tar xvfz Date-Manip-5.54.tar.gz ; cd Date-Manip* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Date-Manip*";
1898my $insmb = "rm -rf Module-Build* ; wget http://search.cpan.org/CPAN/authors/id/K/KW/KWILLIAMS/Module-Build-0.2808.tar.gz ; tar xvfz Module-Build-0.2808.tar.gz ; cd Module-Build* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Module-Build*";
1899my $insfm = "rm -rf File-MimeInfo* ; wget http://search.cpan.org/CPAN/authors/id/P/PA/PARDUS/File-MimeInfo/File-MimeInfo-0.15.tar.gz ; tar xvfz File-MimeInfo-0.15.tar.gz ; cd File-MimeInfo* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf File-MimeInfo*";
1900my $insfb = "rm -rf File-Basedir* ; wget http://search.cpan.org/CPAN/authors/id/P/PA/PARDUS/File-BaseDir-0.03.tar.gz ; tar xvfz File-BaseDir-0.03.tar.gz ; cd File-BaseDir* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf File-BaseDir*";
1901my $insms = "rm -rf Mail-Sendmail* ; wget http://search.cpan.org/CPAN/authors/id/M/MI/MIVKOVIC/Mail-Sendmail-0.79.tar.gz ; tar xvfz Mail-Sendmail-0.79.tar.gz ; cd Mail-Sendmail* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Mail-Sendmail*";
1902my $inslg = "rm -rf gettext* ; wget http://search.cpan.org/CPAN/authors/id/P/PV/PVANDRY/gettext-1.05.tar.gz ; tar xvfz gettext-1.05.tar.gz ; cd gettext* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf gettext*";
1903my $cmtdm = "Installing Date-Manip perl module";
1904my $cmtmb = "Installing Module-Build perl module";
1905my $cmtfm = "Installing File-MimeInfo perl module";
1906my $cmtfb = "Installing File-Basedir perl module";
1907my $cmtms = "Installing Perl-Sendmail perl module";
1908my $cmtlg = "Installing Perl-Locale-gettext perl module";
1909my $cmtall = "Installing required modules";
1910
1911if ( $ddir eq "fedora" ) {
1912 pb_system("yum clean all","Cleaning yum env");
1913 #system "yum update -y";
1914 my $arch=`uname -m`;
1915 my $opt = "";
1916 chomp($arch);
1917 if ($arch eq "x86_64") {
1918 $opt="--exclude=*.i?86";
1919 }
1920
1921 if ($dver eq 4) {
1922 pb_system("yum -y $opt install rpm-build wget patch ntp sudo perl-DateManip perl-ExtUtils-MakeMaker",$cmtall);
1923 pb_system("$insmb","$cmtmb");
1924 pb_system("$insfm","$cmtfm");
1925 pb_system("$insfb","$cmtfb");
1926 pb_system("$insms","$cmtms");
1927 pb_system("$inslg","$cmtlg");
1928 } else {
1929 pb_system("yum -y $opt install rpm-build wget patch ntp sudo perl-DateManip perl-ExtUtils-MakeMaker perl-File-MimeInfo perl-Mail-Sendmail",$cmtall);
1930 pb_system("$inslg","$cmtlg");
1931 }
1932} elsif (( $dfam eq "rh" ) || ($ddir eq "sles") || (($ddir eq "suse") && (($dver eq "10.1") || ($dver eq "10.0"))) || ($ddir eq "slackware")) {
1933 # Suppose pkg are installed already as no online mirror available
1934 pb_system("rpm -e lsb 2>&1 > /dev/null","Removing lsb package");
1935 pb_system("$insdm","$cmtdm");
1936 pb_system("$insmb","$cmtmb");
1937 pb_system("$insfm","$cmtfm");
1938 pb_system("$insfb","$cmtfb");
1939 pb_system("$insms","$cmtms");
1940 pb_system("$inslg","$cmtlg");
1941} elsif ($ddir eq "suse") {
1942 # New OpenSuSE
1943 pb_system("$insmb","$cmtmb");
1944 pb_system("$insfm","$cmtfm");
1945 pb_system("$insfb","$cmtfb");
1946 pb_system("$insms","$cmtms");
1947 pb_system("export TERM=linux ; liste=\"\" ; for i in make wget patch sudo perl-DateManip perl-File-HomeDir perl-Mail-Sendmail ntp; do rpm -q \$i 1> /dev/null 2> /dev/null ; if [ \$\? != 0 ]; then liste=\"\$liste \$i\"; fi; done; echo \"Liste: \$liste\" ; if [ \"\$liste\" != \"\" ]; then yast2 -i \$liste ; fi","$cmtall");
1948} elsif ( $dfam eq "md" ) {
1949 pb_system("urpmi.update -a ; urpmi --auto rpm-build wget sudo patch ntp-client perl-File-MimeInfo perl-Mail-Sendmail perl-Locale-gettext","$cmtall");
1950 if (($ddir eq "mandrake") && ($dver eq "10.1")) {
1951 pb_system("$insdm","$cmtdm");
1952 pb_system("$inslg","$cmtlg");
1953 } else {
1954 pb_system("urpmi --auto perl-DateManip","$cmtdm");
1955 pb_system("urpmi --auto perl-Locale-gettext","$cmtdm");
1956 }
1957} elsif ( $dfam eq "du" ) {
1958 if (( $dver eq "3.1" ) && ($ddir eq "debian")) {
1959 #system "apt-get update";
1960 pb_system("$insfb","$cmtfb");
1961 pb_system("$insfm","$cmtfm");
1962 pb_system("apt-get -y install wget patch ssh sudo debian-builder dh-make fakeroot ntpdate libmodule-build-perl libdate-manip-perl libmail-sendmail-perl liblocale-gettext-perl","$cmtall");
1963 } else {
1964 pb_system("apt-get update; apt-get -y install wget patch openssh-server dpkg-dev sudo debian-builder dh-make fakeroot ntpdate libfile-mimeinfo-perl libmodule-build-perl libdate-manip-perl libmail-sendmail-perl liblocale-gettext-perl","$cmtall");
1965 }
1966} elsif ( $dfam eq "gen" ) {
1967 #system "emerge -u system";
1968 pb_system("emerge wget sudo ntp DateManip File-MimeInfo Mail-Sendmail Locale-gettext","$cmtall");
1969} else {
1970 pb_log(0,"No pkg to install\n");
1971}
1972EOF
1973}
1974
1975sub pb_announce {
1976
1977 # Get all required parameters
1978 my ($pbpackager,$pbrepo,$pbml,$pbsmtp) = pb_conf_get("pbpackager","pbrepo","pbml","pbsmtp");
1979 my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
1980 my $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
1981 my @pkgs = @$pkg;
1982 my %pkgs;
1983 my $first = 0;
1984
1985 # Command to find packages on repo
1986 my $findstr = "find . ";
1987 # Generated announce files
1988 my @files;
1989
1990 foreach my $pbpkg (@pkgs) {
1991 if ($first != 0) {
1992 $findstr .= "-o ";
1993 }
1994 $first++;
1995 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
1996 $pbver = $pkgv->{$pbpkg};
1997 } else {
1998 $pbver = $ENV{'PBPROJVER'};
1999 }
2000 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
2001 $pbtag = $pkgt->{$pbpkg};
2002 } else {
2003 $pbtag = $ENV{'PBPROJTAG'};
2004 }
2005
2006 # TODO: use virtual/real names here now
2007 $findstr .= "-name \'$pbpkg-$pbver-$pbtag\.*.rpm\' -o -name \'$pbpkg"."_$pbver*\.deb\' -o -name \'$pbpkg-$pbver\.ebuild\' ";
2008
2009 my $chglog;
2010
2011 # Get project info on log file and generate tmp files used later on
2012 pb_cms_init($pbinit);
2013 $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
2014 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
2015 $chglog = undef if (! -f $chglog);
2016
2017 open(OUT,"> $ENV{'PBTMP'}/$pbpkg.ann") || die "Unable to create $ENV{'PBTMP'}/$pbpkg.ann: $!";
2018 pb_changelog("announce",$pbpkg,$pbver,"N/A","N/A","N/A",\*OUT,"yes",$chglog);
2019 close(OUT);
2020 push(@files,"$ENV{'PBTMP'}/$pbpkg.ann");
2021 }
2022 $findstr .= " | grep -Ev \'src.rpm\'";
2023 if ((not defined $testver) || (not defined $testver->{$ENV{'PBPROJ'}}) || ($testver->{$ENV{'PBPROJ'}} !~ /true/i)) {
2024 $findstr .= " | grep -v ./test/";
2025 }
2026
2027 # Prepare the command to run and execute it
2028 open(PBS,"> $ENV{'PBTMP'}/pbscript") || die "Unable to create $ENV{'PBTMP'}/pbscript";
2029 print PBS "$findstr\n";
2030 close(PBS);
2031 chmod 0755,"$ENV{'PBTMP'}/pbscript";
2032 pb_send2target("Announce");
2033
2034 # Get subject line
2035 my $sl = "Project $ENV{'PBPROJ'} version $ENV{'PBPROJVER'} is now available";
2036 pb_log(0,"Please enter the title of your announce\n");
2037 pb_log(0,"(By default: $sl)\n");
2038 my $sl2 = <STDIN>;
2039 $sl = $sl2 if ($sl2 !~ /^$/);
2040
2041 # Prepare a template of announce
2042 open(ANN,"> $ENV{'PBTMP'}/announce.html") || die "Unable to create $ENV{'PBTMP'}/announce.html: $!";
2043 print ANN << "EOF";
2044$sl</p>
2045
2046<p>The project team is happy to announce the availability of a newest version of $ENV{'PBPROJ'} $ENV{'PBPROJVER'}. Enjoy it as usual!</p>
2047<p>
2048Now available at <a href="$pbrepo->{$ENV{'PBPROJ'}}">$pbrepo->{$ENV{'PBPROJ'}}</a>
2049</p>
2050<p>
2051EOF
2052 open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to read $ENV{'PBTMP'}/system.log: $!";
2053 my $col = 2;
2054 my $i = 1;
2055 print ANN << 'EOF';
2056<TABLE WIDTH="700" CELLPADDING="0" CELLSPACING="0" BORDER="0">
2057<TR>
2058EOF
2059 while (<LOG>) {
2060 print ANN "<TD>$_</TD>";
2061 $i++;
2062 if ($i > $col) {
2063 print ANN "</TR>\n<TR>";
2064 $i = 1;
2065 }
2066 }
2067 close(LOG);
2068 print ANN << "EOF";
2069</TR>
2070</TABLE>
2071</p>
2072
2073<p>As usual source packages are also available in the same directory.</p>
2074
2075<p>
2076Changes are :
2077</p>
2078<p>
2079EOF
2080 # Get each package changelog content
2081 foreach my $f (sort(@files)) {
2082 open(IN,"$f") || die "Unable to read $f:$!";
2083 while (<IN>) {
2084 print ANN $_;
2085 }
2086 close(IN);
2087 print ANN "</p><p>\n";
2088 }
2089 print ANN "</p>\n";
2090 close(ANN);
2091
2092 # Allow for modification
2093 pb_system("vi $ENV{'PBTMP'}/announce.html","Allowing modification of the announce","noredir");
2094
2095 # Store it in DB for external usage (Web pages generation)
2096 my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
2097
2098 my $precmd = "";
2099 if (! -f $db) {
2100 $precmd = "CREATE TABLE announces (id INTEGER PRIMARY KEY AUTOINCREMENT, date DATE, announce VARCHAR[65535])";
2101 }
2102
2103 my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
2104 { RaiseError => 1, AutoCommit => 1 })
2105 || die "Unable to connect to $db";
2106
2107 if ($precmd ne "") {
2108 my $sth = $dbh->prepare(qq{$precmd})
2109 || die "Unable to create table into $db";
2110 $sth->execute();
2111 }
2112
2113 # To read whole file
2114 local $/;
2115 open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
2116 my $announce = <ANN>;
2117 close(ANN);
2118
2119 pb_log(2,"INSERT INTO announces VALUES (NULL, $pbdate, $announce)");
2120 my $sth = $dbh->prepare(qq{INSERT INTO announces VALUES (NULL,?,?)})
2121 || die "Unable to insert into $db";
2122 $sth->execute($pbdate, $announce);
2123 $dbh->disconnect;
2124
2125 # Then deliver it on the Web
2126 # $TOOLHOME/livwww www
2127
2128 # Mail it to project's ML
2129 open(ML,"| w3m -dump -T text/html > $ENV{'PBTMP'}/announce.txt") || die "Unable to create $ENV{'PBTMP'}/announce.txt: $!";
2130 print ML << 'EOF';
2131<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd">
2132
2133<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en" lang="en">
2134 <head>
2135 </head>
2136 <body>
2137 <p>
2138EOF
2139 open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
2140 while(<ANN>) {
2141 print ML $_;
2142 }
2143 print ML << 'EOF';
2144</body>
2145</html>
2146EOF
2147 close(ML);
2148
2149 # To read whole file
2150 local $/;
2151 open(ANN,"$ENV{'PBTMP'}/announce.txt") || die "Unable to read $ENV{'PBTMP'}/announce.txt: $!";
2152 my $msg = <ANN>;
2153 close(ANN);
2154
2155 # Preparation of headers
2156
2157 my %mail = (
2158 To => $pbml->{$ENV{'PBPROJ'}},
2159 From => $pbpackager->{$ENV{'PBPROJ'}},
2160 Smtp => $pbsmtp->{$ENV{'PBPROJ'}},
2161 Body => $msg,
2162 Subject => "[ANNOUNCE] $sl",
2163 );
2164
2165 # Send mail
2166 sendmail(%mail) or die "Unable to send mail ($Mail::Sendmail::error): $Mail::Sendmail::log";
2167}
2168
2169#
2170# Creates a set of HTML file containing the news for the project
2171# based on what has been generated by the pb_announce function
2172#
2173sub pb_web_news2html {
2174
2175 my $dest = shift || $ENV{'PBTMP'};
2176
2177 # Get all required parameters
2178 my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
2179
2180 # DB of announces for external usage (Web pages generation)
2181 my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
2182
2183 my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
2184 { RaiseError => 1, AutoCommit => 1 })
2185 || die "Unable to connect to $db";
2186 # For date handling
2187 $ENV{LANGUAGE}="C";
2188 my $firstjan = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year(), 0, 0, -1);
2189 my $oldfirst = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year()-1, 0, 0, -1);
2190 pb_log(2,"firstjan: $firstjan, oldfirst: $oldfirst, pbdate:$pbdate\n");
2191 my $all = $dbh->selectall_arrayref("SELECT id,date,announce FROM announces ORDER BY date DESC");
2192 my %news;
2193 $news{"cy"} = ""; # current year's news
2194 $news{"ly"} = ""; # last year news
2195 $news{"py"} = ""; # previous years news
2196 $news{"fp"} = ""; # first page news
2197 my $cpt = 4; # how many news for first page
2198 # Extract info from DB
2199 foreach my $row (@$all) {
2200 my ($id, $date, $announce) = @$row;
2201 $news{"cy"} = $news{"cy"}."<p><B>$date</B> $announce\n" if ((($date cmp $pbdate) le 0) && (($firstjan cmp $date) le 0));
2202 $news{"ly"} = $news{"ly"}."<p><B>$date</B> $announce\n" if ((($date cmp $firstjan) le 0) && (($oldfirst cmp $date) le 0));
2203 $news{"py"} = $news{"py"}."<p><B>$date</B> $announce\n" if (($date cmp $oldfirst) le 0);
2204 $news{"fp"} = $news{"fp"}."<p><B>$date</B> $announce\n" if ($cpt > 0);
2205 $cpt--;
2206 }
2207 pb_log(1,"news{fp}: ".$news{"fp"}."\n");
2208 $dbh->disconnect;
2209
2210 # Generate the HTML content
2211 foreach my $pref (keys %news) {
2212 open(NEWS,"> $dest/pb_web_$pref"."news.html") || die "Unable to create $dest/pb_web_$pref"."news.html: $!";
2213 print NEWS "$news{$pref}";
2214 close(NEWS);
2215 }
2216}
2217
2218
2219# Return the SSH key file to use
2220# Potentially create it if needed
2221
2222sub pb_ssh_get {
2223
2224my $create = shift || 0; # Do not create keys by default
2225
2226# Check the SSH environment
2227my $keyfile = undef;
2228
2229# We have specific keys by default
2230$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa";
2231if (!(-e $keyfile) && ($create eq 1)) {
2232 pb_system("ssh-keygen -q -b 1024 -N '' -f $keyfile -t dsa","Generating SSH keys for pb");
2233}
2234
2235$keyfile = "$ENV{'HOME'}/.ssh/id_rsa" if (-s "$ENV{'HOME'}/.ssh/id_rsa");
2236$keyfile = "$ENV{'HOME'}/.ssh/id_dsa" if (-s "$ENV{'HOME'}/.ssh/id_dsa");
2237$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa" if (-s "$ENV{'HOME'}/.ssh/pb_dsa");
2238die "Unable to find your public ssh key under $keyfile" if (not defined $keyfile);
2239return($keyfile);
2240}
2241
2242
2243# Returns the pid of a running VM command using a specific VM file
2244sub pb_check_ps {
2245 my $vmcmd = shift;
2246 my $vmm = shift;
2247 my $vmexist = 0; # FALSE by default
2248
2249 open(PS, "ps auxhww|") || die "Unable to call ps";
2250 while (<PS>) {
2251 next if (! /$vmcmd/);
2252 next if (! /$vmm/);
2253 my ($void1, $void2);
2254 ($void1, $vmexist, $void2) = split(/ +/);
2255 last;
2256 }
2257 return($vmexist);
2258}
2259
2260
2261sub pb_extract_build_files {
2262
2263my $src=shift;
2264my $dir=shift;
2265my $ddir=shift;
2266my $mandatory=shift || "spec";
2267my @files;
2268
2269my $flag = "mayfail" if ($mandatory eq "patch");
2270my $res;
2271
2272if ($src =~ /tar\.gz$/) {
2273 $res = pb_system("tar xfpz $src $dir","Extracting $mandatory files from $src",$flag);
2274} elsif ($src =~ /tar\.bz2$/) {
2275 $res = pb_system("tar xfpj $src $dir","Extracting $mandatory files from $src",$flag);
2276} else {
2277 die "Unknown compression algorithm for $src";
2278}
2279# If not mandatory return now
2280return() if (($res != 0) and ($mandatory eq "patch"));
2281opendir(DIR,"$dir") || die "Unable to open directory $dir";
2282foreach my $f (readdir(DIR)) {
2283 next if ($f =~ /^\./);
2284 # Skip potential patch dir
2285 next if ($f =~ /^pbpatch/);
2286 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
2287 pb_log(2,"mv $dir/$f $ddir\n");
2288 push @files,"$ddir/$f";
2289}
2290closedir(DIR);
2291# Not enough but still a first cleanup
2292pb_rm_rf("$dir");
2293return(@files);
2294}
2295
2296sub pb_list_bfiles {
2297
2298my $dir = shift;
2299my $pbpkg = shift;
2300my $bfiles = shift;
2301my $pkgfiles = shift;
2302my $supfiles = shift;
2303
2304opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
2305foreach my $f (readdir(BDIR)) {
2306 next if ($f =~ /^\./);
2307 $bfiles->{$f} = "$dir/$f";
2308 $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
2309 if (defined $supfiles->{$pbpkg}) {
2310 $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
2311 }
2312}
2313closedir(BDIR);
2314}
2315
2316
2317#
2318# Return the list of packages we are working on in a non CMS action
2319#
2320sub pb_get_pkg {
2321
2322my @pkgs = ();
2323
2324my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
2325@pkgs = keys %$var;
2326
2327pb_log(0,"Packages: ".join(',',@pkgs)."\n");
2328return(\@pkgs);
2329}
2330
2331# Which is our local arch ? (standardize on i386 for those platforms)
2332sub pb_get_arch {
2333
2334my $arch = `uname -m`;
2335chomp($arch);
2336$arch =~ s/i.86/i386/;
2337return($arch);
2338}
2339
23401;
Note: See TracBrowser for help on using the repository browser.