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

Last change on this file since 397 was 397, checked in by Bruno Cornec, 16 years ago
  • pb_syntax is now shared
  • creation of 2 new shared functions pb_syntax_init and pb_temp_init
  • Property svn:executable set to *
File size: 98.2 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 Date::Manip;
21use POSIX qw(strftime);
22use lib qw (lib);
23use ProjectBuilder::Distribution;
24use ProjectBuilder::Version;
25use ProjectBuilder::Base;
26
27# Global variables
28my %opts; # CLI Options
29my $action; # action to realize
30my $test = "FALSE"; # Not used
31my $force = 0; # Force VE/VM rebuild
32my $option = ""; # Not used
33my @pkgs; # list of packages
34my $pbtag; # Global Tag variable
35my $pbver; # Global Version variable
36my $pbscript; # Name of the script
37my %pbver; # per package
38my %pbtag; # per package
39my $pbrev; # Global REVISION variable
40my $pbaccount; # Login to use to connect to the VM
41my $pbport; # Port to use to connect to the VM
42my $newver; # New version to create
43my $iso; # ISO image for the VM to create
44
45my @date = pb_get_date();
46my $pbdate = strftime("%Y-%m-%d", @date);
47
48=pod
49
50=head1 NAME
51
52pb, aka project-builder.org - builds packages for your projects
53
54=head1 DESCRIPTION
55
56pb helps you build various packages directly from your project sources.
57Those sources could be handled by a CMS (Configuration Management System)
58such as Subversion, CVS, ... or being a simple reference to a compressed tar file.
59It's based on a set of configuration files, a set of provided macros to help
60you keeping build files as generic as possible. For example, a single .spec
61file should be required to generate for all rpm based distributions, even
62if you could also have multiple .spec files if required.
63
64=head1 SYNOPSIS
65
66pb [-vhq][-r pbroot][-p project][[-s script -a account -P port][-m mach-1[,...]]][-i iso] <action> [<pkg1> ...]
67
68pb [--verbose][--help][--man][--quiet][--revision pbroot][--project project][[--script script --account account --port port][--machine mach-1[,...]]][--iso iso] <action> [<pkg1> ...]
69
70=head1 OPTIONS
71
72=over 4
73
74=item B<-v|--verbose>
75
76Print a brief help message and exits.
77
78=item B<-q|--quiet>
79
80Do not print any output.
81
82=item B<-h|--help>
83
84Print a brief help message and exits.
85
86=item B<--man>
87
88Prints the manual page and exits.
89
90=item B<-m|--machine machine1[,machine2,...]>
91
92Name of the Virtual Machines (VM) or Virtual Environments (VE) you want to build on (coma separated).
93All if none precised (or use the env variable PBV).
94
95=item B<-s|--script script>
96
97Name of the script you want to execute on the related VMs or VEs.
98
99=item B<-i|--iso iso_image>
100
101Name of the ISO image of the distribution you want to install on the related VMs.
102
103=item B<-a|--account account>
104
105Name of the account to use to connect on the related VMs.
106
107=item B<-P|--port port_number>
108
109Port number to use to connect on the related VMs.\n";
110
111=item B<-p|--project project_name>
112
113Name of the project you're working on (or use the env variable PBPROJ)
114
115=item B<-r|--revision revision>
116
117Path Name of the project revision under the CMS (or use the env variable PBROOT)
118
119=item B<-V|--version new_version>
120
121New version of the project to create based on the current one.
122
123=back
124
125=head1 ARGUMENTS
126
127<action> can be:
128
129=over 4
130
131=item B<cms2build>
132
133Create tar files for the project under your CMS.
134CMS supported are SVN and CVS
135parameters are packages to build
136if not using default list
137
138=item B<build2pkg>
139
140Create packages for your running distribution
141
142=item B<cms2pkg>
143
144cms2build + build2pkg
145
146=item B<build2ssh>
147
148Send the tar files to a SSH host
149
150=item B<cms2ssh>
151
152cms2build + build2ssh
153
154=item B<pkg2ssh>
155
156Send the packages built to a SSH host
157
158=item B<build2vm>
159
160Create packages in VMs, launching them if needed
161and send those packages to a SSH host once built
162VM type supported are QEMU
163
164=item B<build2ve>
165
166Create packages in VEs, creating it if needed
167and send those packages to a SSH host once built
168
169=item B<cms2vm>
170
171cms2build + build2vm
172
173=item B<cms2ve>
174
175cms2build + build2ve
176
177=item B<launchvm>
178
179Launch one virtual machine
180
181=item B<launchve>
182
183Launch one virtual environment
184
185=item B<script2vm>
186
187Launch one virtual machine if needed
188and executes a script on it
189
190=item B<script2ve>
191
192Execute a script in a virtual environment
193
194=item B<newvm>
195
196Create a new virtual machine
197
198=item B<newve>
199
200Create a new virtual environment
201
202=item B<setupvm>
203
204Setup a virtual machine for pb usage
205
206=item B<setupve>
207
208Setup a virtual environment for pb usage
209
210=item B<newver>
211
212Create a new version of the project derived
213from the current one
214
215=item B<newproj>
216
217Create a new project and a template set of
218configuration files under pbconf
219
220=back
221
222<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).
223
224=head1 WEB SITES
225
226The 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/>.
227
228=head1 USER MAILING LIST
229
230None exists for the moment.
231
232=head1 CONFIGURATION FILES
233
234Each pb user may have a configuration in F<$HOME/.pbrc>. The values in this file may overwrite any other configuration file value.
235
236Here is an example of such a configuration file:
237
238 #
239 # Define for each project the URL of its pbconf repository
240 # No default option allowed here as they need to be all different
241 #
242 # URL of the pbconf content
243 # This is the format of a classical URL with the extension of additional schema such as
244 # svn+ssh, cvs+ssh, ...
245 #
246 pbconfurl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe/pbconf
247
248 # This is normaly defined in the project's configuration file
249 # Url of the project
250 #
251 pburl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe
252
253 # All these URLs needs to be defined here as the are the entry point
254 # for how to build packages for the project
255 #
256 pbconfurl pb = svn+ssh://svn.project-builder.org/mondo/svn/pb/pbconf
257 pbconfurl mondorescue = svn+ssh://svn.project-builder.org/mondo/svn/project-builder/mondorescue/pbconf
258 pbconfurl collectl = svn+ssh://bruno@svn.mondorescue.org/mondo/svn/project-builder/collectl/pbconf
259 pbconfurl netperf = svn+ssh://svn.mondorescue.org/mondo/svn/project-builder/netperf/pbconf
260
261 # Under that dir will take place everything related to pb
262 # If you want to use VMs/chroot/..., then use $ENV{'HOME'} to make it portable
263 # to your VMs/chroot/...
264 # if not defined then /var/cache
265 pbdefdir default = $ENV{'HOME'}/project-builder
266 pbdefdir pb = $ENV{'HOME'}
267 pbdefdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
268 pbdefdir mondorescue = $ENV{'HOME'}/mondo/svn
269
270 # pbconfdir points to the directory where the CMS content of the pbconfurl is checked out
271 # If not defined, pbconfdir is under pbdefdir/pbproj/pbconf
272 pbconfdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs/pbconf
273 pbconfdir mondorescue = $ENV{'HOME'}/mondo/svn/pbconf
274
275 # pbdir points to the directory where the CMS content of the pburl is checked out
276 # If not defined, pbdir is under pbdefdir/pbproj
277 # Only defined if we have access to the dev of the project
278 pbdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
279 pbdir mondorescue = $ENV{'HOME'}/mondo/svn
280
281 # -daemonize doesn't work with qemu 0.8.2
282 vmopt default = -m 384
283
284=head1 AUTHORS
285
286The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
287
288=head1 COPYRIGHT
289
290Project-Builder.org is distributed under the GPL v2.0 license
291described in the file C<COPYING> included with the distribution.
292
293=cut
294
295# ---------------------------------------------------------------------------
296
297# Old syntax
298#getopts('a:fhi:l:m:P:p:qr:s:vV:',\%opts);
299
300my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
301
302# Initialize the syntax string
303
304pb_syntax_init("pb (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n");
305
306GetOptions("help|?|h" => \$opts{'h'},
307 "man" => \$opts{'man'},
308 "verbose|v+" => \$opts{'v'},
309 "quiet|q" => \$opts{'q'},
310 "log-files|l=s" => \$opts{'l'},
311 "force|f" => \$opts{'f'},
312 "account|a=s" => \$opts{'a'},
313 "revision|r=s" => \$opts{'r'},
314 "script|s=s" => \$opts{'s'},
315 "machines|mock|m=s" => \$opts{'m'},
316 "port|P=i" => \$opts{'P'},
317 "project|p=s" => \$opts{'p'},
318 "iso|i=s" => \$opts{'i'},
319 "version|V=s" => \$opts{'V'},
320) || pb_syntax(-1,0);
321
322if (defined $opts{'h'}) {
323 pb_syntax(0,1);
324}
325if (defined $opts{'man'}) {
326 pb_syntax(0,2);
327}
328if (defined $opts{'v'}) {
329 $debug = $opts{'v'};
330 pb_log(0,"Debug value: $debug\n");
331}
332if (defined $opts{'f'}) {
333 $force=1;
334}
335if (defined $opts{'q'}) {
336 $debug=-1;
337}
338if (defined $opts{'l'}) {
339 open(LOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
340 $LOG = \*LOG;
341 $debug = 0 if ($debug == -1);
342 }
343pb_log_init($debug, $LOG);
344
345# Handle root of the project if defined
346if (defined $opts{'r'}) {
347 $ENV{'PBROOTDIR'} = $opts{'r'};
348}
349# Handle virtual machines if any
350if (defined $opts{'m'}) {
351 $ENV{'PBV'} = $opts{'m'};
352}
353if (defined $opts{'s'}) {
354 $pbscript = $opts{'s'};
355}
356if (defined $opts{'a'}) {
357 $pbaccount = $opts{'a'};
358 die "option -a requires a -s script option" if (not defined $pbscript);
359}
360if (defined $opts{'P'}) {
361 $pbport = $opts{'P'};
362}
363if (defined $opts{'V'}) {
364 $newver = $opts{'V'};
365}
366if (defined $opts{'i'}) {
367 $iso = $opts{'i'};
368}
369
370# Get Action
371$action = shift @ARGV;
372die pb_syntax(-1,1) if (not defined $action);
373
374my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
375my $pbinit = undef;
376$pbinit = 1 if ($action =~ /^newproj$/);
377
378# Handles project name if any
379# And get global params
380($filteredfiles, $supfiles, $defpkgdir, $extpkgdir) = pb_env_init($opts{'p'},$pbinit,$action);
381
382pb_log(0,"Project: $ENV{'PBPROJ'}\n");
383pb_log(0,"Action: $action\n");
384
385# Act depending on action
386if ($action =~ /^cms2build$/) {
387 pb_cms2build();
388} elsif ($action =~ /^build2pkg$/) {
389 pb_build2pkg();
390} elsif ($action =~ /^cms2pkg$/) {
391 pb_cms2build();
392 pb_build2pkg();
393} elsif ($action =~ /^build2ssh$/) {
394 pb_build2ssh();
395} elsif ($action =~ /^cms2ssh$/) {
396 pb_cms2build();
397 pb_build2ssh();
398} elsif ($action =~ /^pkg2ssh$/) {
399 pb_pkg2ssh();
400} elsif ($action =~ /^build2ve$/) {
401 pb_build2v("ve");
402} elsif ($action =~ /^build2vm$/) {
403 pb_build2v("vm");
404} elsif ($action =~ /^cms2ve$/) {
405 pb_cms2build();
406 pb_build2v("ve");
407} elsif ($action =~ /^cms2vm$/) {
408 pb_cms2build();
409 pb_build2v("vm");
410} elsif ($action =~ /^launchvm$/) {
411 pb_launchv("vm",$ENV{'PBV'},0);
412} elsif ($action =~ /^launchve$/) {
413 pb_launchv("ve",$ENV{'PBV'},0);
414} elsif ($action =~ /^script2vm$/) {
415 pb_script2v($pbscript,"vm");
416} elsif ($action =~ /^script2ve$/) {
417 pb_script2v($pbscript,"ve");
418} elsif ($action =~ /^newver$/) {
419 pb_newver();
420} elsif ($action =~ /^newve$/) {
421 pb_launchv("ve",$ENV{'PBV'},1);
422} elsif ($action =~ /^newvm$/) {
423 pb_launchv("vm",$ENV{'PBV'},1);
424} elsif ($action =~ /^setupve$/) {
425 pb_setup_v("ve");
426} elsif ($action =~ /^setupvm$/) {
427 pb_setup_v("vm");
428} elsif ($action =~ /^newproj$/) {
429 # Nothing to do - already done in pb_env_init
430} elsif ($action =~ /^clean$/) {
431} else {
432 pb_log(0,"\'$action\' is not available\n");
433 pb_syntax(-2,1);
434}
435
436sub pb_cms2build {
437
438 my $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
439 my @pkgs = @$pkg;
440 my %pkgs;
441
442 my ($scheme, $uri) = pb_cms_init($pbinit);
443
444 my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
445
446 # declare packager for filtering
447 my ($tmp) = pb_conf_get("pbpackager");
448 $ENV{'PBPACKAGER'} = $tmp->{$ENV{'PBPROJ'}};
449
450 foreach my $pbpkg (@pkgs) {
451 $ENV{'PBPKG'} = $pbpkg;
452 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
453 $pbver = $pkgv->{$pbpkg};
454 } else {
455 $pbver = $ENV{'PBPROJVER'};
456 }
457 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
458 $pbtag = $pkgt->{$pbpkg};
459 } else {
460 $pbtag = $ENV{'PBPROJTAG'};
461 }
462
463 $pbrev = $ENV{'PBREVISION'};
464 pb_log(0,"\n");
465 pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
466 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
467 # Clean up dest if necessary. The export will recreate it
468 my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
469 pb_rm_rf($dest) if (-d $dest);
470
471 # Export CMS tree for the concerned package to dest
472 # And generate some additional files
473 $OUTPUT_AUTOFLUSH=1;
474
475 # computes in which dir we have to work
476 my $dir = $defpkgdir->{$pbpkg};
477 $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
478 pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
479
480 # Exporting from CMS
481 pb_cms_export($uri,"$ENV{'PBDIR'}/$dir",$dest);
482
483 # Get project info on authors and log file
484 my $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
485 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
486 $chglog = undef if (! -f $chglog);
487
488 my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
489 $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
490 $authors = "/dev/null" if (! -f $authors);
491
492 # Extract cms log history and store it
493 if ((defined $chglog) && (! -f "$dest/NEWS")) {
494 pb_log(2,"Generating NEWS file from $chglog\n");
495 copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
496 }
497 pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors);
498
499 my %build;
500
501 my @pt;
502 @pt = pb_conf_get_if("vmlist","velist");
503 my $tmpl = "";
504 if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
505 $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
506 }
507 if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
508 # the 2 lists needs to be grouped with a ',' separated them
509 if ($tmpl ne "") {
510 $tmpl .= ",";
511 }
512 $tmpl .= $pt[1]->{$ENV{'PBPROJ'}}
513 }
514 foreach my $d (split(/,/,$tmpl)) {
515 my ($name,$ver,$arch) = split(/-/,$d);
516 chomp($arch);
517 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
518 pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $pbsuf)."\n");
519 pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
520
521 # Filter build files from the less precise up to the most with overloading
522 # Filter all files found, keeping the name, and generating in dest
523
524 # Find all build files first relatively to PBROOTDIR
525 # Find also all specific files referenced in the .pb conf file
526 my %bfiles = ();
527 my %pkgfiles = ();
528 $build{"$ddir-$dver"} = "yes";
529
530 if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dtype") {
531 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dtype",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
532 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
533 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
534 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
535 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
536 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
537 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
538 } else {
539 $build{"$ddir-$dver"} = "no";
540 next;
541 }
542 pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
543
544 # Get all filters to apply
545 my $ptr = pb_get_filters($pbpkg, $dtype, $dfam, $ddir, $dver);
546
547 # Apply now all the filters on all the files concerned
548 # destination dir depends on the type of file
549 if (defined $ptr) {
550 foreach my $f (values %bfiles,values %pkgfiles) {
551 pb_filter_file_pb("$ENV{'PBROOTDIR'}/$f",$ptr,"$dest/pbconf/$ddir-$dver/".basename($f),$dtype,$pbsuf,$ENV{'PBPROJ'},$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$defpkgdir,$extpkgdir,$ENV{'PBPACKAGER'},$chglog);
552 }
553 }
554 }
555 my @found;
556 my @notfound;
557 foreach my $b (keys %build) {
558 push @found,$b if ($build{$b} =~ /yes/);
559 push @notfound,$b if ($build{$b} =~ /no/);
560 }
561 pb_log(0,"Build files generated for ".join(',',@found)."\n");
562 pb_log(0,"No Build files found for ".join(',',@notfound)."\n") if (@notfound);
563 # Get the generic filter (all.pbf) and
564 # apply those to the non-build files including those
565 # generated by pbinit if applicable
566
567 # Get only all.pbf filter
568 my $ptr = pb_get_filters($pbpkg);
569
570 my $liste ="";
571 if (defined $filteredfiles->{$pbpkg}) {
572 foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
573 pb_filter_file_inplace($ptr,"$dest/$f",$ENV{'PBPROJ'},$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$ENV{'PBPACKAGER'});
574 $liste = "$f $liste";
575 }
576 }
577 pb_log(2,"Files ".$liste."have been filtered\n");
578
579 # Prepare the dest directory for archive
580 if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
581 pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",$ENV{'PBPROJ'},$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$ENV{'PBPACKAGER'});
582 chmod 0755,"$ENV{'PBTMP'}/pbinit";
583 pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit");
584 }
585
586 # Archive dest dir
587 chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
588 # Possibility to look at PBSRC to guess more the filename
589 pb_system("tar cfz $pbpkg-$pbver.tar.gz $pbpkg-$pbver","Creating $pbpkg tar files compressed");
590 pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
591
592 # Keep track of version-tag per pkg
593 $pkgs{$pbpkg} = "$pbver-$pbtag";
594
595 # Final cleanup
596 pb_rm_rf($dest) if (-d $dest);
597 }
598
599 # Keep track of per package version
600 pb_log(2,"DEBUG pkgs: ".Dumper(%pkgs)."\n");
601 open(PKG,"> $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb";
602 foreach my $pbpkg (@pkgs) {
603 print PKG "pbpkg $pbpkg = $pkgs{$pbpkg}\n";
604 }
605 close(PKG);
606
607 # Keep track of what is generated by default
608 # We need to store the dir and info on version-tag
609 # Base our content on the existing .pb file
610 copy("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb","$ENV{'PBDESTDIR'}/pbrc");
611 open(LAST,">> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
612 print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
613 print LAST "pbprojver $ENV{'PBPROJ'} = $ENV{'PBPROJVER'}\n";
614 print LAST "pbprojtag $ENV{'PBPROJ'} = $ENV{'PBPROJTAG'}\n";
615 print LAST "pbpackager $ENV{'PBPROJ'} = $ENV{'PBPACKAGER'}\n";
616 close(LAST);
617}
618
619sub pb_build2pkg {
620
621 # Get the running distro to build on
622 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
623 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
624
625 # Get list of packages to build
626 # Get content saved in cms2build
627 my $ptr = pb_get_pkg();
628 @pkgs = @$ptr;
629
630 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
631 $pkg = { } if (not defined $pkg);
632
633 chdir "$ENV{'PBBUILDDIR'}";
634 my $made = ""; # pkgs made during build
635 foreach my $pbpkg (@pkgs) {
636 my $vertag = $pkg->{$pbpkg};
637 # get the version of the current package - maybe different
638 ($pbver,$pbtag) = split(/-/,$vertag);
639
640 my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
641 pb_log(2,"Source file: $src\n");
642
643 pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
644 if ($dtype eq "rpm") {
645 foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
646 if (! -d "$ENV{'PBBUILDDIR'}/$d") {
647 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";
648 }
649 }
650
651 # Remove in case a previous link/file was there
652 unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
653 symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
654 # We need to first extract the spec file
655 my @specfile;
656 @specfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$ENV{'PBBUILDDIR'}/SPECS");
657
658 pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
659 # set LANGUAGE to check for correct log messages
660 $ENV{'LANGUAGE'}="C";
661 foreach my $f (@specfile) {
662 if ($f =~ /\.spec$/) {
663 pb_system("rpmbuild --define \'packager $ENV{'PBPACKAGER'}\' --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}");
664 last;
665 }
666 }
667 $made="$made RPMS/*/$pbpkg-$pbver-$pbtag$pbsuf.*.rpm SRPMS/$pbpkg-$pbver-$pbtag$pbsuf.src.rpm";
668 if (-f "/usr/bin/rpmlint") {
669 pb_system("rpmlint $made","Checking validity of rpms with rpmlint");
670 }
671 } elsif ($dtype eq "deb") {
672 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
673 pb_system("tar xfz $src","Extracting sources");
674
675 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
676 pb_rm_rf("debian");
677 symlink "pbconf/$ddir-$dver","debian" || die "Unable to symlink to pbconf/$ddir-$dver";
678 chmod 0755,"debian/rules";
679 pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package");
680 $made="$made $pbpkg"."_*.deb $pbpkg"."_*.dsc $pbpkg"."_*.tar.gz";
681 if (-f "/usr/bin/lintian") {
682 pb_system("lintian $made","Checking validity of debs with lintian");
683 }
684 } elsif ($dtype eq "ebuild") {
685 my @ebuildfile;
686 # For gentoo we need to take pb as subsystem name
687 # We put every apps here under sys-apps. hope it's correct
688 # We use pb's home dir in order o have a single OVERLAY line
689 my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
690 pb_mkdir_p($tmpd) if (! -d "$tmpd");
691 pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
692
693 # We need to first extract the ebuild file
694 @ebuildfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$tmpd");
695
696 # Prepare the build env for gentoo
697 my $found = 0;
698 my $pbbd = $ENV{'HOME'};
699 $pbbd =~ s|/|\\/|g;
700 if (-r "/etc/make.conf") {
701 open(MAKE,"/etc/make.conf");
702 while (<MAKE>) {
703 $found = 1 if (/$pbbd\/portage/);
704 }
705 close(MAKE);
706 }
707 if ($found == 0) {
708 pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
709 }
710 #$found = 0;
711 #if (-r "/etc/portage/package.keywords") {
712 #open(KEYW,"/etc/portage/package.keywords");
713 #while (<KEYW>) {
714 #$found = 1 if (/portage\/pb/);
715 #}
716 #close(KEYW);
717 #}
718 #if ($found == 0) {
719 #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
720 #}
721
722 # Build
723 foreach my $f (@ebuildfile) {
724 if ($f =~ /\.ebuild$/) {
725 move($f,"$tmpd/$pbpkg-$pbver.ebuild");
726 pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package");
727 # Now move it where pb expects it
728 pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
729 move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
730 }
731 }
732
733 $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver.ebuild";
734 } elsif ($dtype eq "slackware") {
735 $made="$made build-$pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
736 pb_mkdir_p("$ENV{'PBBUILDDIR'}/install") if (! -d "$ENV{'PBBUILDDIR'}/install");
737 } else {
738 die "Unknown dtype format $dtype";
739 }
740 }
741 # Keep track of what is generated so that we can get them back from VMs
742 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
743 print KEEP "$made\n";
744 close(KEEP);
745}
746
747sub pb_build2ssh {
748 pb_send2target("Sources");
749}
750
751sub pb_pkg2ssh {
752 pb_send2target("Packages");
753}
754
755# By default deliver to the the public site hosting the
756# ftp structure (or whatever) or a VM/VE
757sub pb_send2target {
758
759 my $cmt = shift;
760 my $v = shift || undef;
761 my $vmexist = shift || 0; # 0 is FALSE
762 my $vmpid = shift || 0; # 0 is FALSE
763
764 my $host = "sshhost";
765 my $login = "sshlogin";
766 my $dir = "sshdir";
767 my $port = "sshport";
768 my $tmout = "sshtmout";
769 my $path = "sshpath";
770 my $conf = "sshconf";
771 my $rebuild = "sshrebuild";
772 if (($cmt eq "vm") || ($cmt eq "Script")) {
773 $login = "vmlogin";
774 $dir = "pbdefdir";
775 $tmout = "vmtmout";
776 $rebuild = "vmrebuild";
777 # Specific VM
778 $host = "vmhost";
779 $port = "vmport";
780 } elsif ($cmt eq "ve") {
781 $login = "velogin";
782 $dir = "pbdefdir";
783 $tmout = "vetmout";
784 # Specific VE
785 $path = "vepath";
786 $conf = "veconf";
787 $rebuild = "verebuild";
788 }
789 my $cmd = "";
790
791 my $ptr = pb_get_pkg();
792 @pkgs = @$ptr;
793
794 # Get the running distro to consider
795 my ($odir,$over,$oarch) = (undef, undef, undef);
796 if (defined $v) {
797 ($odir,$over,$oarch) = split(/-/,$v);
798 }
799 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($odir,$over);
800 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
801
802 # Get list of packages to build
803 # Get content saved in cms2build
804 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
805 $pkg = { } if (not defined $pkg);
806
807 my $src = "";
808 chdir "$ENV{'PBBUILDDIR'}";
809 foreach my $pbpkg (@pkgs) {
810 my $vertag = $pkg->{$pbpkg};
811 # get the version of the current package - maybe different
812 ($pbver,$pbtag) = split(/-/,$vertag);
813
814 if (($cmt eq "Sources") || ($cmt eq "vm") || ($cmt eq "ve")) {
815 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
816 if ($cmd eq "") {
817 $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
818 } else {
819 $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
820 }
821 }
822 }
823 if (($cmt eq "vm") || ($cmt eq "ve")) {
824 $src="$src $ENV{'PBDESTDIR'}/pbscript $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc";
825 } elsif ($cmt eq "Script") {
826 $src="$src $ENV{'PBDESTDIR'}/pbscript";
827 } elsif ($cmt eq "Packages") {
828 # Get package list from file made during build2pkg
829 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
830 $src = <KEEP>;
831 chomp($src);
832 close(KEEP);
833 if ($dtype eq "rpm") {
834 # Also make a pbscript to generate yum/urpmi bases
835 # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
836 } elsif ($dtype eq "deb") {
837 # Also make a pbscript to generate apt bases
838 # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
839 }
840 }
841 # Remove potential leading spaces (cause problem with basename)
842 $src =~ s/^ *//;
843 my $basesrc = "";
844 foreach my $i (split(/ +/,$src)) {
845 $basesrc .= " ".basename($i);
846 }
847
848 pb_log(0,"Sources handled ($cmt): $src\n");
849 pb_log(2,"values: ".Dumper(($host,$login,$dir,$port,$tmout,$rebuild,$path,$conf))."\n");
850 my ($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf) = pb_conf_get($host,$login,$dir,$port,$tmout,$rebuild,$path,$conf);
851 pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf))."\n");
852 # Not mandatory
853 my ($testver) = pb_conf_get_if("testver");
854
855 my $mac;
856 # Useless for VE
857 if ($cmt ne "ve") {
858 $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
859 # Overwrite account value if passed as parameter
860 $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
861 pb_log(2, "DEBUG: pbaccount: $pbaccount => mac: $mac\n") if (defined $pbaccount);
862 }
863
864 my $tdir;
865 my $bdir;
866 if (($cmt eq "Sources") || ($cmt eq "Script")) {
867 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/src";
868 } elsif (($cmt eq "vm") || ($cmt eq "ve")) {
869 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
870 $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
871 # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
872 $bdir =~ s|\$ENV.+\}/||;
873 } elsif ($cmt eq "Packages") {
874 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$ddir/$dver";
875 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
876 # This is a test pkg => target dir is under test
877 $tdir .= "/test";
878 }
879 } else {
880 return;
881 }
882
883 # Useless for VE
884 my $nport;
885 if ($cmt ne "ve") {
886 $nport = $sshport->{$ENV{'PBPROJ'}};
887 $nport = "$pbport" if (defined $pbport);
888 }
889
890 # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
891 $tdir =~ s|\$ENV.+\}/||;
892
893 my $tm = $vtmout->{$ENV{'PBPROJ'}};
894
895 # ssh communication if not VE
896 # should use a hash instead...
897 my ($shcmd,$cpcmd,$cptarget,$cp2target);
898 if ($cmt ne "ve") {
899 my $keyfile = pb_ssh_get(0);
900 $shcmd = "ssh -i $keyfile -q -p $nport $mac";
901 $cpcmd = "scp -i $keyfile -p -P $nport";
902 $cptarget = "$mac:$tdir";
903 if ($cmt eq "vm") {
904 $cp2target = "$mac:$bdir";
905 }
906 } else {
907 my $tp = $vepath->{$ENV{'PBPROJ'}};
908 $shcmd = "sudo chroot $tp/$v /bin/su - $sshlogin->{$ENV{'PBPROJ'}} -c ";
909 $cpcmd = "cp -a ";
910 $cptarget = "$tp/$tdir";
911 $cp2target = "$tp/$bdir";
912 }
913
914 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");
915 pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
916 # For VE we need to change the owner manually - To be tested if needed
917 #if ($cmt eq "ve") {
918 #pb_system("cd $cptarget ; sudo chown -R $sshlogin->{$ENV{'PBPROJ'}} .","$cmt chown in $cptarget to $sshlogin->{$ENV{'PBPROJ'}}");
919 #}
920 pb_system("$shcmd \"echo \'cd $tdir ; if [ -f pbscript ]; then ./pbscript; fi\' | bash\"","Executing pbscript on $cptarget if needed");
921 if (($cmt eq "vm") || ($cmt eq "ve")) {
922 # Get back info on pkg produced, compute their name and get them from the VM
923 pb_system("$cpcmd $cp2target/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'} $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $cp2target");
924 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
925 my $src = <KEEP>;
926 chomp($src);
927 close(KEEP);
928 $src =~ s/^ *//;
929 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
930 # Change pgben to make the next send2target happy
931 my $made = "";
932 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
933 foreach my $p (split(/ +/,$src)) {
934 my $j = basename($p);
935 pb_system("$cpcmd $cp2target/\'$p\' $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Package recovery of $j in $cp2target");
936 $made="$made $odir/$over/$j" if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
937 }
938 print KEEP "$made\n";
939 close(KEEP);
940 pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
941
942 # We want to send them to the ssh account so overwrite what has been done before
943 undef $pbaccount;
944 pb_log(2,"Before sending pkgs, vmexist: $vmexist, vmpid: $vmpid\n");
945 pb_send2target("Packages",$odir."-".$over."-".$oarch,$vmexist,$vmpid);
946 if ((! $vmexist) && ($cmt eq "vm")) {
947 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)");
948 }
949 pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
950 }
951}
952
953sub pb_script2v {
954 my $pbscript=shift;
955 my $vtype=shift;
956
957 # Prepare the script to be executed on the VM
958 # in $ENV{'PBDESTDIR'}/pbscript
959 if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
960 copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
961 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
962 }
963
964 my ($vm,$all) = pb_get_v($vtype);
965 my ($vmexist,$vmpid) = (undef,undef);
966
967 foreach my $v (@$vm) {
968 # Launch the VM/VE
969 if ($vtype eq "vm") {
970 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
971
972 # Skip that VM if something went wrong
973 next if (($vmpid == 0) && ($vmexist ==0));
974 }
975
976 # Gather all required files to send them to the VM
977 # and launch the build through pbscript
978 pb_send2target("Script","$v",$vmexist,$vmpid);
979
980 }
981}
982
983sub pb_launchv {
984 my $vtype = shift;
985 my $v = shift;
986 my $create = shift || 0; # By default do not create a VM
987
988 die "No VM/VE defined, unable to launch" if (not defined $v);
989 # Keep only the first VM in case many were given
990 $v =~ s/,.*//;
991
992 # Which is our local arch ? (standardize on i386 for those platforms)
993 my $arch = `uname -m`;
994 chomp($arch);
995 $arch =~ s/i.86/i386/;
996
997 # Launch the VMs/VEs
998 if ($vtype eq "vm") {
999 die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
1000
1001 my ($ptr,$vmopt,$vmport,$vmpath,$vmtmout,$vmsize) = pb_conf_get("vmtype","vmopt","vmport","vmpath","vmtmout","vmsize");
1002
1003 my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1004 if (not defined $ENV{'PBVMOPT'}) {
1005 $ENV{'PBVMOPT'} = "";
1006 }
1007 if (defined $vmopt->{$ENV{'PBPROJ'}}) {
1008 $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1009 }
1010 my $nport = $vmport->{$ENV{'PBPROJ'}};
1011 $nport = "$pbport" if (defined $pbport);
1012
1013 my $cmd;
1014 my $vmcmd; # has to be used for pb_check_ps
1015 my $vmm; # has to be used for pb_check_ps
1016 if ($vmtype eq "qemu") {
1017 my $qemucmd32;
1018 my $qemucmd64;
1019 if ($arch eq "x86_64") {
1020 $qemucmd32 = "/usr/bin/qemu-system-i386";
1021 $qemucmd64 = "/usr/bin/qemu";
1022 } else {
1023 $qemucmd32 = "/usr/bin/qemu";
1024 $qemucmd64 = "/usr/bin/qemu-system-x86_64";
1025 }
1026 if ($v =~ /x86_64/) {
1027 $vmcmd = "$qemucmd64 -no-kqemu";
1028 } else {
1029 $vmcmd = "$qemucmd32";
1030 }
1031 $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
1032 if ($create != 0) {
1033 $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
1034 }
1035 $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 $vmm"
1036 } elsif ($vmtype eq "xen") {
1037 } elsif ($vmtype eq "vmware") {
1038 } else {
1039 die "VM of type $vmtype not supported. Report to the dev team";
1040 }
1041 my ($tmpcmd,$void) = split(/ +/,$cmd);
1042 my $vmexist = pb_check_ps($tmpcmd,$vmm);
1043 my $vmpid = 0;
1044 if (! $vmexist) {
1045 if ($create != 0) {
1046 if (($vmtype eq "qemu") || ($vmtype eq "xen")) {
1047 pb_system("/usr/bin/qemu-img create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
1048 } elsif ($vmtype eq "vmware") {
1049 } else {
1050 }
1051 }
1052 if (! -f "$vmm") {
1053 pb_log(0,"Unable to find VM $vmm\n");
1054 } else {
1055 pb_system("$cmd &","Launching the VM $vmm");
1056 pb_system("sleep $vmtmout->{$ENV{'PBPROJ'}}","Waiting for VM $v to come up");
1057 $vmpid = pb_check_ps($tmpcmd,$vmm);
1058 pb_log(0,"VM $vmm launched (pid $vmpid)\n");
1059 }
1060 } else {
1061 pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
1062 }
1063 return($vmexist,$vmpid);
1064 # VE here
1065 } else {
1066 # Get VE context
1067 my ($ptr,$vepath,$vetmout,$verebuild,$veconf) = pb_conf_get("vetype","vepath","vetmout","verebuild","veconf");
1068 my $vetype = $ptr->{$ENV{'PBPROJ'}};
1069
1070 # Get distro context
1071 my ($name,$ver,$darch) = split(/-/,$v);
1072 chomp($darch);
1073 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
1074
1075 if ($vetype eq "chroot") {
1076 # Architecture consistency
1077 if ($arch ne $darch) {
1078 die "Unable to launch a VE of architecture $darch on a $arch platform" if (not (($darch eq "x86_64") && ($arch =~ /i?86/)));
1079 }
1080
1081 if (($create != 0) || ($verebuild->{$ENV{'PBPROJ'}} eq "true") || ($force == 1)) {
1082 # We have to rebuild the chroot
1083 if ($dtype eq "rpm") {
1084 pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1085 # Once setup we need to install some packages, the pb account, ...
1086 pb_system("sudo /usr/sbin/mock --install --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
1087 #pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" --basedir=\"$vepath->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1088 } elsif ($dtype eq "deb") {
1089 pb_system("","Creating the pbuilder VE");
1090 } elsif ($dtype eq "ebuild") {
1091 die "Please teach the dev team how to build gentoo chroot";
1092 } else {
1093 die "Unknown distribution type $dtype. Report to dev team";
1094 }
1095 }
1096 # Nothing more to do for VE. No real launch
1097 } else {
1098 die "VE of type $vetype not supported. Report to the dev team";
1099 }
1100 }
1101}
1102
1103sub pb_build2v {
1104
1105my $vtype = shift;
1106
1107# Prepare the script to be executed on the VM/VE
1108# in $ENV{'PBDESTDIR'}/pbscript
1109#my ($ntp) = pb_conf_get($vtype."ntp");
1110#my $vntp = $ntp->{$ENV{'PBPROJ'}};
1111
1112open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1113print SCRIPT "#!/bin/bash\n";
1114print SCRIPT "echo ... Execution needed\n";
1115print SCRIPT "# This is in directory delivery\n";
1116print SCRIPT "# Setup the variables required for building\n";
1117print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
1118print SCRIPT "# Preparation for pb\n";
1119print SCRIPT "mv .pbrc \$HOME\n";
1120print SCRIPT "cd ..\n";
1121# Force new date to be in the future compared to the date of the tar file by adding 1 minute
1122my @date=pb_get_date();
1123$date[1]++;
1124my $upddate = strftime("%m%d%H%M%Y", @date);
1125#print SCRIPT "echo Setting up date on $vntp...\n";
1126# Or use ntpdate if available TBC
1127print SCRIPT "sudo date $upddate\n";
1128# Get list of packages to build and get some ENV vars as well
1129my $ptr = pb_get_pkg();
1130@pkgs = @$ptr;
1131my $p = join(' ',@pkgs) if (@pkgs);
1132print SCRIPT "export PBPROJVER=$ENV{'PBPROJVER'}\n";
1133print SCRIPT "export PBPROJTAG=$ENV{'PBPROJTAG'}\n";
1134print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
1135print SCRIPT "# Build\n";
1136print SCRIPT "echo Building packages on $vtype...\n";
1137print SCRIPT "pb -p $ENV{'PBPROJ'} build2pkg $p\n";
1138close(SCRIPT);
1139chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1140
1141my ($v,$all) = pb_get_v($vtype);
1142
1143# Send tar files when we do a global generation
1144pb_build2ssh() if ($all == 1);
1145
1146my ($vmexist,$vmpid) = (undef,undef);
1147
1148foreach my $v (@$v) {
1149 if ($vtype eq "vm") {
1150 # Launch the VM
1151 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1152
1153 # Skip that VM if it something went wrong
1154 next if (($vmpid == 0) && ($vmexist == 0));
1155 }
1156 # Gather all required files to send them to the VM/VE
1157 # and launch the build through pbscript
1158 pb_log(2,"Calling send2target $vtype,$v,$vmexist,$vmpid\n");
1159 pb_send2target($vtype,"$v",$vmexist,$vmpid);
1160}
1161}
1162
1163
1164sub pb_newver {
1165
1166 die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
1167
1168 # Need this call for PBDIR
1169 my ($scheme2,$uri) = pb_cms_init($pbinit);
1170
1171 my ($pbconf) = pb_conf_read("$ENV{'PBETC'}","pbconfurl");
1172 $uri = $pbconf->{$ENV{'PBPROJ'}};
1173 my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
1174
1175 # Checking CMS repositories status
1176 my ($pburl) = pb_conf_get("pburl");
1177 ($scheme2, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
1178
1179 if ($scheme !~ /^svn/) {
1180 die "Only SVN is supported at the moment";
1181 }
1182 my $res = pb_cms_isdiff($scheme,$ENV{'PBROOTDIR'});
1183 die "ERROR: No differences accepted in CMS for $ENV{'PBROOTDIR'} before creating a new version" if ($res != 0);
1184
1185 $res = pb_cms_isdiff($scheme2,$ENV{'PBDIR'});
1186 die "ERROR: No differences accepted in CMS for $ENV{'PBDIR'} before creating a new version" if ($res != 0);
1187
1188 # Tree identical between PBCONFDIR and PBROOTDIR. The delta is what
1189 # we want to get for the root of the new URL
1190
1191 my $tmp = $ENV{'PBROOTDIR'};
1192 $tmp =~ s|^$ENV{'PBCONFDIR'}||;
1193
1194 my $newurl = "$uri/".dirname($tmp)."/$newver";
1195 # Should probably use projver in the old file
1196 my $oldver= basename($tmp);
1197
1198 # Checking pbcl files
1199 foreach my $f (<$ENV{'PBROOTDIR'}/*/pbcl>) {
1200 open(PBCL,$f) || die "Unable to open $f";
1201 my $foundnew = 0;
1202 while (<PBCL>) {
1203 $foundnew = 1 if (/^$newver \(/);
1204 }
1205 close(PBCL);
1206 die "ERROR: version $newver not found in $f" if ($foundnew == 0);
1207 }
1208
1209 # Duplicate and extract project-builder part
1210 pb_log(2,"Copying $uri/$tmp to $newurl\n");
1211 pb_cms_copy($scheme,"$uri/$tmp",$newurl);
1212 pb_log(2,"Checkout $newurl to $ENV{'PBROOTDIR'}/../$newver\n");
1213 pb_cms_up($scheme,"$ENV{'PBCONFDIR'}/..");
1214
1215 # Duplicate and extract project
1216 my $newurl2 = "$pburl->{$ENV{'PBPROJ'}}/".dirname($tmp)."/$newver";
1217
1218 pb_log(2,"Copying $pburl->{$ENV{'PBPROJ'}}/$tmp to $newurl2\n");
1219 pb_cms_copy($scheme,"$pburl->{$ENV{'PBPROJ'}}/$tmp",$newurl2);
1220 pb_log(2,"Checkout $newurl2 to $ENV{'PBDIR'}/../$newver\n");
1221 pb_cms_up($scheme,"$ENV{'PBDIR'}/..");
1222
1223 # Update the .pb file
1224 open(FILE,"$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb";
1225 open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new";
1226 while(<FILE>) {
1227 s/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
1228 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/);
1229 s/^testver/#testver/;
1230 pb_log(0,"Commenting testver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^testver/);
1231 print OUT $_;
1232 }
1233 close(FILE);
1234 close(OUT);
1235 rename("$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb");
1236
1237 pb_log(2,"Checkin $ENV{'PBROOTDIR'}/../$newver\n");
1238 pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver");
1239}
1240
1241#
1242# Return the list of VMs/VEs we are working on
1243# $all is a flag to know if we return all of them
1244# or only some (if all we publish also tar files in addition to pkgs
1245#
1246sub pb_get_v {
1247
1248my $vtype = shift;
1249my @v;
1250my $all = 0;
1251my $vlist;
1252my $pbv = 'PBV';
1253
1254if ($vtype eq "vm") {
1255 $vlist = "vmlist";
1256} elsif ($vtype eq "ve") {
1257 $vlist = "velist";
1258}
1259# Get VM/VE list
1260if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
1261 my ($ptr) = pb_conf_get($vlist);
1262 $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
1263 $all = 1;
1264}
1265pb_log(2,"$vtype: $ENV{$pbv}\n");
1266@v = split(/,/,$ENV{$pbv});
1267return(\@v,$all);
1268}
1269
1270# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
1271# Needs to use root account to connect to the VM/VE
1272# pb will take your local public SSH key to access
1273# the pb account in the VM later on if needed
1274sub pb_setup_v {
1275
1276my $vtype = shift;
1277
1278my ($vm,$all) = pb_get_v($vtype);
1279
1280# Script generated
1281my $pbscript = "$ENV{'PBDESTDIR'}/setupv";
1282
1283foreach my $v (@$vm) {
1284 # Name of the account to deal with for VM/VE
1285 # Do not use the one passed potentially with -a
1286 my ($pbac) = pb_conf_get($vtype."login");
1287 my ($key,$zero0,$zero1,$zero2);
1288 my ($vmexist,$vmpid);
1289
1290 if ($vtype eq "vm") {
1291 # Prepare the key to be used and transfered remotely
1292 my $keyfile = pb_ssh_get(1);
1293
1294 my ($vmhost,$vmport) = pb_conf_get("vmhost","vmport");
1295 my $nport = $vmport->{$ENV{'PBPROJ'}};
1296 $nport = "$pbport" if (defined $pbport);
1297
1298 # Launch the VM
1299 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1300
1301 # Skip that VM if something went wrong
1302 return if (($vmpid == 0) && ($vmexist == 0));
1303
1304 # Store the pub key part in a variable
1305 open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
1306 ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
1307 close(FILE);
1308
1309 $key = "\Q$zero1";
1310
1311 pb_system("cat $keyfile.pub | ssh -q -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 will require the root password");
1312 # once this is done, we can do what we want on the VM remotely
1313 }
1314
1315 # Prepare the script to be executed on the VM/VE
1316 # in $ENV{'PBDESTDIR'}/setupv
1317
1318 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
1319 print SCRIPT << 'EOF';
1320#!/usr/bin/perl -w
1321
1322use strict;
1323use File::Copy;
1324
1325EOF
1326 if ($vtype eq "vm") {
1327 print SCRIPT << 'EOF';
1328# Removes duplicate in .ssh/authorized_keys of our key if needed
1329#
1330my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
1331open(PBFILE,$file1) || die "Unable to open $file1";
1332open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
1333my $count = 0;
1334while (<PBFILE>) {
1335EOF
1336 print SCRIPT << "EOF";
1337 if (/ $key /) {
1338 \$count++;
1339 }
1340print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
1341}
1342close(PBFILE);
1343close(PBOUT);
1344rename("\$file1.new",\$file1);
1345chmod 0600,\$file1;
1346EOF
1347 }
1348 print SCRIPT << 'EOF';
1349
1350# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
1351#
1352my $file="/etc/passwd";
1353open(PBFILE,$file) || die "Unable to open $file";
1354my $found = 0;
1355while (<PBFILE>) {
1356EOF
1357 print SCRIPT << "EOF";
1358 \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
1359EOF
1360 print SCRIPT << 'EOF';
1361}
1362close(PBFILE);
1363
1364if ( $found == 0 ) {
1365 if ( ! -d "/home" ) {
1366 mkdir "/home";
1367 }
1368EOF
1369 print SCRIPT << "EOF";
1370system "groupadd $pbac->{$ENV{'PBPROJ'}}";
1371system "useradd $pbac->{$ENV{'PBPROJ'}} -g $pbac->{$ENV{'PBPROJ'}} -m -d /home/$pbac->{$ENV{'PBPROJ'}}";
1372
1373# allow ssh entry to build
1374#
1375chdir "/home/$pbac->{$ENV{'PBPROJ'}}";
1376mkdir ".ssh",0700;
1377# Allow those accessing root to access the build account
1378copy("\$ENV{'HOME'}/.ssh/authorized_keys",".ssh/authorized_keys");
1379chmod 0600,".ssh/authorized_keys";
1380system 'chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} .ssh';
1381
1382EOF
1383 print SCRIPT << 'EOF';
1384}
1385
1386# No passwd for build account only keys
1387$file="/etc/shadow";
1388open(PBFILE,$file) || die "Unable to open $file";
1389open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1390while (<PBFILE>) {
1391EOF
1392 print SCRIPT << "EOF";
1393 s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
1394 s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/; #SLES 9 e.g.
1395EOF
1396 print SCRIPT << 'EOF';
1397 print PBOUT $_;
1398}
1399close(PBFILE);
1400close(PBOUT);
1401rename("$file.new",$file);
1402chmod 0640,$file;
1403
1404# pb has to be added to portage group on gentoo
1405
1406# Adapt sudoers
1407$file="/etc/sudoers";
1408open(PBFILE,$file) || die "Unable to open $file";
1409open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1410while (<PBFILE>) {
1411EOF
1412 print SCRIPT << "EOF";
1413 next if (/^$pbac->{$ENV{'PBPROJ'}} /);
1414EOF
1415 print SCRIPT << 'EOF';
1416 s/Defaults[ \t]+requiretty//;
1417 print PBOUT $_;
1418}
1419close(PBFILE);
1420EOF
1421 print SCRIPT << "EOF";
1422# This is needed in order to be able to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
1423print PBOUT "$pbac->{$ENV{'PBPROJ'}} ALL=(ALL) NOPASSWD:ALL\n";
1424EOF
1425 print SCRIPT << 'EOF';
1426close(PBOUT);
1427rename("$file.new",$file);
1428chmod 0440,$file;
1429
1430EOF
1431
1432 my $SCRIPT = \*SCRIPT;
1433
1434 pb_install_deps($SCRIPT);
1435
1436 print SCRIPT << 'EOF';
1437# Suse wants sudoers as 640
1438if (($ddir eq "sles") || (($ddir eq "suse")) && ($dver ne "10.3")) {
1439 chmod 0640,$file;
1440}
1441
1442# Sync date
1443#system "/usr/sbin/ntpdate ntp.pool.org";
1444
1445system "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-*";
1446system "pb 2>&1 | head -5";
1447EOF
1448 if ((! $vmexist) && ($vtype eq "vm")) {
1449 print SCRIPT << 'EOF';
1450system "sudo /sbin/halt -p";
1451EOF
1452 }
1453
1454 # Adds pb_distro_init from ProjectBuilder::Distribution
1455 foreach my $d (@INC) {
1456 my $f = "$d/ProjectBuilder/Distribution.pm";
1457 if (-f "$f") {
1458 open(PBD,"$f") || die "Unable to open $f";
1459 while (<PBD>) {
1460 next if (/^package/);
1461 next if (/^use Exporter/);
1462 next if (/^\@our /);
1463 print SCRIPT $_;
1464 }
1465 close(PBD);
1466 last;
1467 }
1468 }
1469 close(SCRIPT);
1470 chmod 0755,"$pbscript";
1471
1472 # That build script needs to be run as root
1473 $pbaccount = "root";
1474 pb_script2v($pbscript,$vtype);
1475}
1476return;
1477}
1478
1479sub pb_install_deps {
1480
1481my $SCRIPT = shift;
1482
1483print {$SCRIPT} << 'EOF';
1484# We need to have that pb_distro_init function
1485# Get it from Project-Builder::Distribution
1486my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
1487print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n";
1488
1489# Get and install pb
1490my $insdm = "rm -rf Date-Manip* ; wget http://search.cpan.org/CPAN/authors/id/S/SB/SBECK/Date-Manip-5.48.tar.gz ; tar xvfz Date-Manip-5.48.tar.gz ; cd Date-Manip* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Date-Manip*";
1491my $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*";
1492my $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*";
1493my $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*";
1494
1495if ( $ddir eq "fedora" ) {
1496 system "yum clean all";
1497 #system "yum update -y";
1498 my $arch=`uname -m`;
1499 my $opt = "";
1500 chomp($arch);
1501 if ($arch eq "x86_64") {
1502 $opt="--exclude=*.i?86";
1503 }
1504
1505 system "yum -y $opt install rpm-build wget patch ntp sudo perl-DateManip perl-File-MimeInfo perl-ExtUtils-MakeMaker";
1506 if ($dver eq 4) {
1507 system "$insmb";
1508 system "$insfm";
1509 system "$insfb";
1510 }
1511} elsif (( $dfam eq "rh" ) || ($ddir eq "sles") || (($ddir eq "suse") && (($dver eq "10.1") || ($dver eq "10.0"))) || ($ddir eq "slackware")) {
1512 # Suppose pkg are installed already as no online mirror available
1513 system "rpm -e lsb 2>&1 > /dev/null";
1514 system "$insdm";
1515 system "$insmb";
1516 system "$insfm";
1517 system "$insfb";
1518} elsif ($ddir eq "suse") {
1519 # New OpenSuSE
1520 system "$insmb";
1521 system "$insfm";
1522 system "$insfb";
1523 system "export TERM=linux ; liste=\"\" ; for i in make wget patch sudo perl-DateManip perl-File-HomeDir xntp; 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";
1524} elsif ( $dfam eq "md" ) {
1525 system "urpmi.update -a ; urpmi --auto rpm-build wget sudo patch ntp-client perl-File-MimeInfo";
1526 if (($ddir eq "mandrake") && ($dver eq "10.1")) {
1527 system "$insdm";
1528 } else {
1529 system "urpmi --auto perl-DateManip";
1530 }
1531} elsif ( $dfam eq "du" ) {
1532 if (( $dver eq "3.1" ) && ($ddir eq "debian")) {
1533 #system "apt-get update";
1534 system "$insfb";
1535 system "$insfm";
1536 system "apt-get -y install wget patch ssh sudo debian-builder dh-make fakeroot ntpdate libmodule-build-perl libdate-manip-perl";
1537 } else {
1538 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";
1539 }
1540} elsif ( $dfam eq "gen" ) {
1541 #system "emerge -u system ; emerge wget sudo ntp DateManip File-MimeInfo";
1542 system "emerge wget sudo ntp DateManip File-MimeInfo";
1543} else {
1544 print "No pkg to install\n";
1545}
1546EOF
1547}
1548
1549# Return the SSH key file to use
1550# Potentially create it if needed
1551
1552sub pb_ssh_get {
1553
1554my $create = shift || 0; # Do not create keys by default
1555
1556# Check the SSH environment
1557my $keyfile = undef;
1558
1559# We have specific keys by default
1560$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa";
1561if (!(-e $keyfile) && ($create eq 1)) {
1562 pb_system("ssh-keygen -q -b 1024 -N '' -f $keyfile -t dsa","Generating SSH keys for pb");
1563}
1564
1565$keyfile = "$ENV{'HOME'}/.ssh/id_rsa" if (-s "$ENV{'HOME'}/.ssh/id_rsa");
1566$keyfile = "$ENV{'HOME'}/.ssh/id_dsa" if (-s "$ENV{'HOME'}/.ssh/id_dsa");
1567$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa" if (-s "$ENV{'HOME'}/.ssh/pb_dsa");
1568die "Unable to find your public ssh key under $keyfile" if (not defined $keyfile);
1569return($keyfile);
1570}
1571
1572
1573# Returns the pid of a running VM command using a specific VM file
1574sub pb_check_ps {
1575 my $vmcmd = shift;
1576 my $vmm = shift;
1577 my $vmexist = 0; # FALSE by default
1578
1579 open(PS, "ps auxhww|") || die "Unable to call ps";
1580 while (<PS>) {
1581 next if (! /$vmcmd/);
1582 next if (! /$vmm/);
1583 my ($void1, $void2);
1584 ($void1, $vmexist, $void2) = split(/ +/);
1585 last;
1586 }
1587 return($vmexist);
1588}
1589
1590
1591sub pb_extract_build_files {
1592
1593my $src=shift;
1594my $dir=shift;
1595my $ddir=shift;
1596my @files;
1597
1598if ($src =~ /tar\.gz$/) {
1599 pb_system("tar xfpz $src $dir","Extracting build files");
1600} elsif ($src =~ /tar\.bz2$/) {
1601 pb_system("tar xfpj $src $dir","Extracting build files");
1602} else {
1603 die "Unknown compression algorithm for $src";
1604}
1605opendir(DIR,"$dir") || die "Unable to open directory $dir";
1606foreach my $f (readdir(DIR)) {
1607 next if ($f =~ /^\./);
1608 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
1609 pb_log(2,"mv $dir/$f $ddir\n");
1610 push @files,"$ddir/$f";
1611}
1612closedir(DIR);
1613# Not enough but still a first cleanup
1614pb_rm_rf("$dir");
1615return(@files);
1616}
1617
1618sub pb_list_bfiles {
1619
1620my $dir = shift;
1621my $pbpkg = shift;
1622my $bfiles = shift;
1623my $pkgfiles = shift;
1624my $supfiles = shift;
1625
1626opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
1627foreach my $f (readdir(BDIR)) {
1628 next if ($f =~ /^\./);
1629 $bfiles->{$f} = "$dir/$f";
1630 $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
1631 if (defined $supfiles->{$pbpkg}) {
1632 $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
1633 }
1634}
1635closedir(BDIR);
1636}
1637
1638sub pb_env_init {
1639
1640my $proj=shift || undef;
1641my $pbinit=shift || undef;
1642my $action=shift;
1643my $ver;
1644my $tag;
1645
1646$ENV{'PBETC'} = "$ENV{'HOME'}/.pbrc";
1647
1648#
1649# Check project name
1650# Could be with env var PBPROJ
1651# or option -p
1652# if not define take the first in conf file
1653#
1654if ((defined $ENV{'PBPROJ'}) &&
1655 (not (defined $proj))) {
1656 $proj = $ENV{'PBPROJ'};
1657}
1658
1659#
1660# We get the pbconf file for that project
1661# and use its content
1662#
1663my ($pbconf) = pb_conf_read("$ENV{'PBETC'}","pbconfurl");
1664pb_log(2,"DEBUG pbconfurl: ".Dumper($pbconf)."\n");
1665
1666my %pbconf = %$pbconf;
1667if (not defined $proj) {
1668 # Take the first as the default project
1669 $proj = (keys %pbconf)[0];
1670 if (defined $proj) {
1671 pb_log(1,"WARNING: using $proj as default project as none has been specified\n");
1672 pb_log(1," Please either create a pbconfurl reference for project $proj in $ENV{'PBETC'}\n");
1673 pb_log(1," or call pb with the -p project option or use the env var PBPROJ\n");
1674 pb_log(1," if you want to use another project\n");
1675 }
1676}
1677die "No project defined - use env var PBPROJ or -p proj or a pbconfurl entry in $ENV{'PBETC'}" if (not (defined $proj));
1678
1679# That's always the environment variable that will be used
1680$ENV{'PBPROJ'} = $proj;
1681pb_log(2,"PBPROJ: $ENV{'PBPROJ'}\n");
1682
1683if (not defined ($pbconf{$ENV{'PBPROJ'}})) {
1684 die "Please create a pbconfurl reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n";
1685}
1686
1687#
1688# Detect the root dir for hosting all the content generated with pb
1689#
1690# Tree will look like this:
1691#
1692# maint pbdefdir PBDEFDIR dev dir (optional)
1693# | |
1694# ------------------------ --------------------
1695# | | | |
1696# pbproj1 pbproj2 PBPROJ pbproj1 pbproj2 PBPROJDIR
1697# | |
1698# --------------------------------------------- ----------
1699# * * * | | | * *
1700# tag dev pbconf ... build delivery PBCONFDIR dev tag
1701# | | | PBDESTDIR |
1702# --- ------ pbrc PBBUILDDIR -------
1703# | | | | |
1704# 1.1 dev tag 1.0 1.1 PBDIR
1705# |
1706# -------
1707# | |
1708# 1.0 1.1 PBROOTDIR
1709# |
1710# ----------------------------------
1711# | | | |
1712# pkg1 pbproj1.pb pbfilter pbcl
1713# |
1714# -----------------
1715# | | |
1716# rpm deb pbfilter
1717#
1718#
1719# (*) By default, if no relocation in .pbrc, dev dir is taken in the maint pbdefdir (when appropriate)
1720# Names under a pbproj and the corresponding pbconf should be similar
1721#
1722
1723my ($pbdefdir) = pb_conf_get_if("pbdefdir");
1724
1725if (not defined $ENV{'PBDEFDIR'}) {
1726 if ((not defined $pbdefdir) || (not defined $pbdefdir->{$ENV{'PBPROJ'}})) {
1727 pb_log(1,"WARNING: no pbdefdir defined, using /var/cache\n");
1728 pb_log(1," Please create a pbdefdir reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n");
1729 pb_log(1," if you want to use another directory\n");
1730 $ENV{'PBDEFDIR'} = "/var/cache";
1731 } else {
1732 # That's always the environment variable that will be used
1733 $ENV{'PBDEFDIR'} = $pbdefdir->{$ENV{'PBPROJ'}};
1734 }
1735}
1736# Expand potential env variable in it
1737eval { $ENV{'PBDEFDIR'} =~ s/(\$ENV.+\})/$1/eeg };
1738
1739pb_log(2,"PBDEFDIR: $ENV{'PBDEFDIR'}\n");
1740#
1741# Set delivery directory
1742#
1743$ENV{'PBDESTDIR'}="$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/delivery";
1744
1745pb_log(2,"PBDESTDIR: $ENV{'PBDESTDIR'}\n");
1746#
1747# Removes all directory existing below the delivery dir
1748# as they are temp dir only
1749# Files stay and have to be cleaned up manually if needed
1750# those files serves as communication channels between pb phases
1751# Removing them prevents a following phase to detect what has been done before
1752#
1753if (-d $ENV{'PBDESTDIR'}) {
1754 opendir(DIR,$ENV{'PBDESTDIR'}) || die "Unable to open directory $ENV{'PBDESTDIR'}: $!";
1755 foreach my $d (readdir(DIR)) {
1756 next if ($d =~ /^\./);
1757 next if (-f "$ENV{'PBDESTDIR'}/$d");
1758 pb_rm_rf("$ENV{'PBDESTDIR'}/$d") if (-d "$ENV{'PBDESTDIR'}/$d");
1759 }
1760 closedir(DIR);
1761}
1762if (! -d "$ENV{'PBDESTDIR'}") {
1763 pb_mkdir_p($ENV{'PBDESTDIR'}) || die "Unable to recursively create $ENV{'PBDESTDIR'}";
1764}
1765
1766#
1767# Set build directory
1768#
1769$ENV{'PBBUILDDIR'}="$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/build";
1770if (! -d "$ENV{'PBBUILDDIR'}") {
1771 pb_mkdir_p($ENV{'PBBUILDDIR'}) || die "Unable to recursively create $ENV{'PBBUILDDIR'}";
1772}
1773
1774pb_log(2,"PBBUILDDIR: $ENV{'PBBUILDDIR'}\n");
1775
1776pb_temp_init();
1777pb_log(2,"PBTMP: $ENV{'PBTMP'}\n");
1778
1779#
1780# The following part is only useful when in cms2something of newver
1781# In VMs/VEs we want to skip that by providing good env vars.
1782# return values in that case are useless
1783#
1784if (($action =~ /^cms2/) || ($action =~ /^newver$/)) {
1785
1786 #
1787 # Check pbconf cms compliance
1788 #
1789 pb_cms_compliant("pbconfdir",'PBCONFDIR',"$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/pbconf",$pbconf{$ENV{'PBPROJ'}},$pbinit);
1790
1791 # Check where is our PBROOTDIR (release tag name can't be guessed the first time)
1792 #
1793 if (not defined $ENV{'PBROOTDIR'}) {
1794 if (! -f ("$ENV{'PBDESTDIR'}/pbrc")) {
1795 opendir(DIR,$ENV{'PBCONFDIR'}) || die "Unable to open directory $ENV{'PBCONFDIR'}: $!";
1796 my $maxmtime = 0;
1797 foreach my $d (readdir(DIR)) {
1798 pb_log(3,"Looking at \'$d\'...");
1799 next if ($d =~ /^\./);
1800 next if (! -d "$ENV{'PBCONFDIR'}/$d");
1801 my $s = stat("$ENV{'PBCONFDIR'}/$d");
1802 next if (not defined $s);
1803 pb_log(3,"KEEP\n");
1804 # Keep the most recent
1805 pb_log(2," $s->mtime\n");
1806 if ($s->mtime > $maxmtime) {
1807 $ENV{'PBROOTDIR'} = "$ENV{'PBCONFDIR'}/$d";
1808 $maxmtime = $s->mtime;
1809 }
1810 }
1811 closedir(DIR);
1812 die "No directory found under $ENV{'PBCONFDIR'}" if (not defined $ENV{'PBROOTDIR'});
1813 pb_log(1,"WARNING: no pbroot defined, using $ENV{'PBROOTDIR'}\n");
1814 pb_log(1," Please use -r release if you want to use another release\n");
1815 } else {
1816 my ($pbroot) = pb_conf_read_if("$ENV{'PBDESTDIR'}/pbrc","pbroot");
1817 # That's always the environment variable that will be used
1818 die "Please remove inconsistent $ENV{'PBDESTDIR'}/pbrc" if ((not defined $pbroot) || (not defined $pbroot->{$ENV{'PBPROJ'}}));
1819 $ENV{'PBROOTDIR'} = $pbroot->{$ENV{'PBPROJ'}};
1820 }
1821 } else {
1822 # transform in full path if relative
1823 $ENV{'PBROOTDIR'} = "$ENV{'PBCONFDIR'}/$ENV{'PBROOTDIR'}" if ($ENV{'PBROOTDIR'} !~ /^\//);
1824 pb_mkdir_p($ENV{'PBROOTDIR'}) if (defined $pbinit);
1825 die "$ENV{'PBROOTDIR'} is not a directory" if (not -d $ENV{'PBROOTDIR'});
1826 }
1827
1828 return if ($action =~ /^newver$/);
1829
1830 my %version = ();
1831 my %defpkgdir = ();
1832 my %extpkgdir = ();
1833 my %filteredfiles = ();
1834 my %supfiles = ();
1835
1836 if ((-f "$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb") and (not defined $pbinit)) {
1837 # List of pkg to build by default (mandatory)
1838 my ($defpkgdir,$pbpackager, $pkgv, $pkgt) = pb_conf_get("defpkgdir","pbpackager","projver","projtag");
1839 # List of additional pkg to build when all is called (optional)
1840 # Valid version names (optional)
1841 # List of files to filter (optional)
1842 # Project version and tag (optional)
1843 my ($extpkgdir, $version, $filteredfiles, $supfiles) = pb_conf_get_if("extpkgdir","version","filteredfiles","supfiles");
1844 pb_log(2,"DEBUG: defpkgdir: ".Dumper($defpkgdir)."\n");
1845 pb_log(2,"DEBUG: extpkgdir: ".Dumper($extpkgdir)."\n");
1846 pb_log(2,"DEBUG: version: ".Dumper($version)."\n");
1847 pb_log(2,"DEBUG: filteredfiles: ".Dumper($filteredfiles)."\n");
1848 pb_log(2,"DEBUG: supfiles: ".Dumper($supfiles)."\n");
1849 # Global
1850 %defpkgdir = %$defpkgdir;
1851 %extpkgdir = %$extpkgdir if (defined $extpkgdir);
1852 %version = %$version if (defined $version);
1853 %filteredfiles = %$filteredfiles if (defined $filteredfiles);
1854 %supfiles = %$supfiles if (defined $supfiles);
1855 #
1856 # Get global Version/Tag
1857 #
1858 if (not defined $ENV{'PBPROJVER'}) {
1859 if ((defined $pkgv) && (defined $pkgv->{$ENV{'PBPROJ'}})) {
1860 $ENV{'PBPROJVER'}=$pkgv->{$ENV{'PBPROJ'}};
1861 } else {
1862 die "No projver found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
1863 }
1864 }
1865 die "Invalid version name $ENV{'PBPROJVER'} in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb" if (($ENV{'PBPROJVER'} !~ /[0-9.]+/) && (not defined $version) && ($ENV{'PBPROJVER'} =~ /$version{$ENV{'PBPROJ'}}/));
1866
1867 if (not defined $ENV{'PBPROJTAG'}) {
1868 if ((defined $pkgt) && (defined $pkgt->{$ENV{'PBPROJ'}})) {
1869 $ENV{'PBPROJTAG'}=$pkgt->{$ENV{'PBPROJ'}};
1870 } else {
1871 die "No projtag found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
1872 }
1873 }
1874 die "Invalid tag name $ENV{'PBPROJTAG'} in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb" if ($ENV{'PBPROJTAG'} !~ /[0-9.]+/);
1875
1876
1877 if (not defined $ENV{'PBPACKAGER'}) {
1878 if ((defined $pbpackager) && (defined $pbpackager->{$ENV{'PBPROJ'}})) {
1879 $ENV{'PBPACKAGER'}=$pbpackager->{$ENV{'PBPROJ'}};
1880 } else {
1881 die "No pbpackager found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
1882 }
1883 }
1884 } else {
1885 if (defined $pbinit) {
1886 my $ptr = pb_get_pkg();
1887 my @pkgs = @$ptr;
1888 @pkgs = ("pkg1") if (not @pkgs);
1889
1890 open(CONF,"> $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb") || die "Unable to create $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
1891 print CONF << "EOF";
1892#
1893# Project Builder configuration file
1894# For project $ENV{'PBPROJ'}
1895#
1896# \$Id\$
1897#
1898
1899#
1900# What is the project URL
1901#
1902#pburl $ENV{'PBPROJ'} = svn://svn.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel
1903#pburl $ENV{'PBPROJ'} = svn://svn+ssh.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel
1904#pburl $ENV{'PBPROJ'} = cvs://cvs.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel
1905#pburl $ENV{'PBPROJ'} = http://www.$ENV{'PBPROJ'}.org/src/$ENV{'PBPROJ'}-devel.tar.gz
1906#pburl $ENV{'PBPROJ'} = ftp://ftp.$ENV{'PBPROJ'}.org/src/$ENV{'PBPROJ'}-devel.tar.gz
1907#pburl $ENV{'PBPROJ'} = file:///src/$ENV{'PBPROJ'}-devel.tar.gz
1908#pburl $ENV{'PBPROJ'} = dir:///src/$ENV{'PBPROJ'}-devel
1909
1910# Check whether project is well formed
1911# (containing already a directory with the project-version name)
1912#pbwf $ENV{'PBPROJ'} = 1
1913
1914#
1915# Packager label
1916#
1917#pbpackager $ENV{'PBPROJ'} = William Porte <bill\@$ENV{'PBPROJ'}.org>
1918#
1919
1920# For delivery to a machine by SSH (potentially the FTP server)
1921# Needs hostname, account and directory
1922#
1923#sshhost $ENV{'PBPROJ'} = www.$ENV{'PBPROJ'}.org
1924#sshlogin $ENV{'PBPROJ'} = bill
1925#sshdir $ENV{'PBPROJ'} = /$ENV{'PBPROJ'}/ftp
1926#sshport $ENV{'PBPROJ'} = 22
1927
1928#
1929# For Virtual machines management
1930# Naming convention to follow: distribution name (as per ProjectBuilder::Distribution)
1931# followed by '-' and by release number
1932# followed by '-' and by architecture
1933# a .vmtype extension will be added to the resulting string
1934# a QEMU rhel-3-i286 here means that the VM will be named rhel-3-i386.qemu
1935#
1936#vmlist $ENV{'PBPROJ'} = mandrake-10.1-i386,mandrake-10.2-i386,mandriva-2006.0-i386,mandriva-2007.0-i386,mandriva-2007.1-i386,mandriva-2008.0-i386,redhat-7.3-i386,redhat-9-i386,fedora-4-i386,fedora-5-i386,fedora-6-i386,fedora-7-i386,fedora-8-i386,rhel-3-i386,rhel-4-i386,rhel-5-i386,suse-10.0-i386,suse-10.1-i386,suse-10.2-i386,suse-10.3-i386,sles-9-i386,sles-10-i386,gentoo-nover-i386,debian-3.1-i386,debian-4.0-i386,ubuntu-6.06-i386,ubuntu-7.04-i386,ubuntu-7.10-i386,mandriva-2007.0-x86_64,mandriva-2007.1-x86_64,mandriva-2008.0-x86_64,fedora-6-x86_64,fedora-7-x86_64,fedora-8-x86_64,rhel-4-x86_64,rhel-5-x86_64,suse-10.2-x86_64,suse-10.3-x86_64,sles-10-x86_64,gentoo-nover-x86_64,debian-4.0-x86_64,ubuntu-7.04-x86_64,ubuntu-7.10-x86_64
1937
1938#
1939# Valid values for vmtype are
1940# qemu, (vmware, xen, ... TBD)
1941#vmtype $ENV{'PBPROJ'} = qemu
1942
1943# Hash for VM stuff on vmtype
1944#vmntp default = pool.ntp.org
1945
1946# We suppose we can commmunicate with the VM through SSH
1947#vmhost $ENV{'PBPROJ'} = localhost
1948#vmlogin $ENV{'PBPROJ'} = pb
1949#vmport $ENV{'PBPROJ'} = 2222
1950
1951# Timeout to wait when VM is launched/stopped
1952#vmtmout default = 120
1953
1954# per VMs needed paramaters
1955#vmopt $ENV{'PBPROJ'} = -m 384 -daemonize
1956#vmpath $ENV{'PBPROJ'} = /home/qemu
1957#vmsize $ENV{'PBPROJ'} = 5G
1958
1959#
1960# For Virtual environment management
1961# Naming convention to follow: distribution name (as per ProjectBuilder::Distribution)
1962# followed by '-' and by release number
1963# followed by '-' and by architecture
1964# a .vetype extension will be added to the resulting string
1965# a chroot rhel-3-i286 here means that the VE will be named rhel-3-i386.chroot
1966#
1967#velist $ENV{'PBPROJ'} = fedora-7-i386
1968
1969# VE params
1970#vetype $ENV{'PBPROJ'} = chroot
1971#ventp default = pool.ntp.org
1972#velogin $ENV{'PBPROJ'} = pb
1973#vepath $ENV{'PBPROJ'} = /var/lib/mock
1974#veconf $ENV{'PBPROJ'} = /etc/mock
1975#verebuild $ENV{'PBPROJ'} = false
1976
1977#
1978# Global version/tag for the project
1979#
1980#projver $ENV{'PBPROJ'} = devel
1981#projtag $ENV{'PBPROJ'} = 1
1982
1983# Hash of valid version names
1984#version $ENV{'PBPROJ'} = devel,stable
1985
1986# Adapt to your needs:
1987# Optional if you need to overwrite the global values above
1988#
1989EOF
1990
1991 foreach my $pp (@pkgs) {
1992 print CONF << "EOF";
1993#pkgver $pp = stable
1994#pkgtag $pp = 3
1995EOF
1996 }
1997 foreach my $pp (@pkgs) {
1998 print CONF << "EOF";
1999# Hash of default package/package directory
2000#defpkgdir $pp = dir-$pp
2001EOF
2002 }
2003
2004 print CONF << "EOF";
2005# Hash of additional package/package directory
2006#extpkgdir minor-pkg = dir-minor-pkg
2007
2008# List of files per pkg on which to apply filters
2009# Files are mentioned relatively to pbroot/defpkgdir
2010EOF
2011 foreach my $pp (@pkgs) {
2012 print CONF << "EOF";
2013#filteredfiles $pp = Makefile.PL,configure.in,install.sh,$pp.8
2014#supfiles $pp = $pp.init
2015EOF
2016 }
2017 close(CONF);
2018 pb_mkdir_p("$ENV{'PBROOTDIR'}/pbfilter") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter";
2019 open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/all.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/all.pbf";
2020 print CONF << "EOF";
2021#
2022# \$Id\$
2023#
2024# Filter for all files
2025#
2026# PBSRC is replaced by the source package format
2027#filter PBSRC = ftp://ftp.$ENV{'PBPROJ'}.org/src/%{name}-%{version}.tar.gz
2028
2029# PBVER is replaced by the version (\$pbver in code)
2030filter PBVER = \$pbver
2031
2032# PBDATE is replaced by the date (\$pbdate in code)
2033filter PBDATE = \$pbdate
2034
2035# PBLOG is replaced by the changelog if value is yes
2036#filter PBLOG = yes
2037
2038# PBTAG is replaced by the tag (\$pbtag in code)
2039filter PBTAG = \$pbtag
2040
2041# PBREV is replaced by the revision (\$pbrev in code)
2042filter PBREV = \$pbrev
2043
2044# PBPKG is replaced by the package name (\$pbpkg in code)
2045filter PBPKG = \$pbpkg
2046
2047# PBPACKAGER is replaced by the packager name (\$pbpackager in code)
2048filter PBPACKAGER = \$pbpackager
2049
2050# PBDESC contains the description of the package
2051#filter PBDESC = "Bla-Bla"
2052
2053# PBURL contains the URL of the Web site of the project
2054#filter PBURL = http://www.$ENV{'PBPROJ'}.org
2055EOF
2056 close(CONF);
2057 open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/rpm.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/rpm.pbf";
2058 print CONF << "EOF";
2059#
2060# \$Id\$
2061#
2062# Filter for rpm build
2063#
2064
2065# PBGRP is replaced by the RPM group of apps
2066# Cf: http://fedoraproject.org/wiki/RPMGroups
2067#filter PBGRP = Applications/Archiving
2068
2069# PBLIC is replaced by the license of the application
2070# Cf: http://fedoraproject.org/wiki/Licensing
2071#filter PBLIC = GPL
2072
2073# PBDEP is replaced by the list of dependencies
2074#filter PBDEP =
2075
2076# PBSUF is replaced by the package suffix (\$pbsuf in code)
2077filter PBSUF = \$pbsuf
2078
2079# PBOBS is replaced by the Obsolete line
2080#filter PBOBS =
2081
2082EOF
2083 close(CONF);
2084 open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/deb.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/deb.pbf";
2085 print CONF << "EOF";
2086#
2087# \$Id\$
2088#
2089# Filter for debian build
2090#
2091# PBGRP is replaced by the group of apps
2092filter PBGRP = utils
2093
2094# PBLIC is replaced by the license of the application
2095# Cf:
2096#filter PBLIC = GPL
2097
2098# PBDEP is replaced by the list of dependencies
2099#filter PBDEP =
2100
2101# PBSUG is replaced by the list of suggestions
2102#filter PBSUG =
2103
2104# PBREC is replaced by the list of recommandations
2105#filter PBREC =
2106
2107EOF
2108 close(CONF);
2109 open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/md.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/md.pbf";
2110 print CONF << "EOF";
2111# Specific group for Mandriva for $ENV{'PBPROJ'}
2112# Cf: http://wiki.mandriva.com/en/Development/Packaging/Groups
2113#filter PBGRP = Archiving/Backup
2114
2115# PBLIC is replaced by the license of the application
2116# Cf: http://wiki.mandriva.com/en/Development/Packaging/Licenses
2117#filter PBLIC = GPL
2118
2119EOF
2120 close(CONF);
2121 open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/novell.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/novell.pbf";
2122 print CONF << "EOF";
2123# Specific group for SuSE for $ENV{'PBPROJ'}
2124# Cf: http://en.opensuse.org/SUSE_Package_Conventions/RPM_Groups
2125#filter PBGRP = Productivity/Archiving/Backup
2126
2127# PBLIC is replaced by the license of the application
2128# Cf: http://en.opensuse.org/Packaging/SUSE_Package_Conventions/RPM_Style#1.6._License_Tag
2129#filter PBLIC = GPL
2130
2131EOF
2132 close(CONF);
2133 foreach my $pp (@pkgs) {
2134 pb_mkdir_p("$ENV{'PBROOTDIR'}/$pp/deb") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb";
2135 open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/control") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/control";
2136 print CONF << "EOF";
2137Source: PBPKG
2138Section: PBGRP
2139Priority: optional
2140Maintainer: PBPACKAGER
2141Build-Depends: debhelper (>= 4.2.20), PBDEP
2142Standards-Version: 3.6.1
2143
2144Package: PBPKG
2145Architecture: amd64 i386 ia64
2146Section: PBGRP
2147Priority: optional
2148Depends: \${shlibs:Depends}, \${misc:Depends}, PBDEP
2149Recommends: PBREC
2150Suggests: PBSUG
2151Description:
2152 PBDESC
2153 .
2154 Homepage: PBURL
2155
2156EOF
2157 close(CONF);
2158 open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/copyright") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/copyright";
2159 print CONF << "EOF";
2160This package is debianized by PBPACKAGER
2161`date`
2162
2163The current upstream source was downloaded from
2164ftp://ftp.$ENV{'PBPROJ'}.org/src/.
2165
2166Upstream Authors: Put their name here
2167
2168Copyright:
2169
2170 This package is free software; you can redistribute it and/or modify
2171 it under the terms of the GNU General Public License as published by
2172 the Free Software Foundation; version 2 dated June, 1991.
2173
2174 This package is distributed in the hope that it will be useful,
2175 but WITHOUT ANY WARRANTY; without even the implied warranty of
2176 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2177 GNU General Public License for more details.
2178
2179 You should have received a copy of the GNU General Public License
2180 along with this package; if not, write to the Free Software
2181 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
2182 MA 02110-1301, USA.
2183
2184On Debian systems, the complete text of the GNU General
2185Public License can be found in /usr/share/common-licenses/GPL.
2186
2187EOF
2188 close(CONF);
2189 open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/changelog") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/changelog";
2190 print CONF << "EOF";
2191PBLOG
2192EOF
2193 close(CONF);
2194 open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/compat") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/compat";
2195 print CONF << "EOF";
21964
2197EOF
2198 close(CONF);
2199 open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/$pp.dirs") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/$pp.dirs";
2200 print CONF << "EOF";
2201EOF
2202 close(CONF);
2203 open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/$pp.docs") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/$pp.docs";
2204 print CONF << "EOF";
2205INSTALL
2206COPYING
2207AUTHORS
2208NEWS
2209README
2210EOF
2211 close(CONF);
2212 open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/rules") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/rules";
2213 print CONF << 'EOF';
2214#!/usr/bin/make -f
2215# -*- makefile -*-
2216# Sample debian/rules that uses debhelper.
2217# GNU copyright 1997 to 1999 by Joey Hess.
2218#
2219# $Id$
2220#
2221
2222# Uncomment this to turn on verbose mode.
2223#export DH_VERBOSE=1
2224
2225# Define package name variable for a one-stop change.
2226PACKAGE_NAME = PBPKG
2227
2228# These are used for cross-compiling and for saving the configure script
2229# from having to guess our platform (since we know it already)
2230DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
2231DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
2232
2233CFLAGS = -Wall -g
2234
2235ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
2236 CFLAGS += -O0
2237else
2238 CFLAGS += -O2
2239endif
2240ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
2241 INSTALL_PROGRAM += -s
2242endif
2243config.status: configure
2244 dh_testdir
2245
2246 # Configure the package.
2247 CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr
2248 --mandir=\$${prefix}/share/man
2249
2250# Build both architecture dependent and independent
2251build: build-arch build-indep
2252
2253# Build architecture dependent
2254build-arch: build-arch-stamp
2255
2256build-arch-stamp: config.status
2257 dh_testdir
2258
2259 # Compile the package.
2260 $(MAKE)
2261
2262 touch build-stamp
2263
2264# Build architecture independent
2265build-indep: build-indep-stamp
2266
2267build-indep-stamp: config.status
2268 # Nothing to do, the only indep item is the manual which is available as html in original source
2269 touch build-indep-stamp
2270
2271# Clean up
2272clean:
2273 dh_testdir
2274 dh_testroot
2275 rm -f build-arch-stamp build-indep-stamp #CONFIGURE-STAMP#
2276 # Clean temporary document directory
2277 rm -rf debian/doc-temp
2278 # Clean up.
2279 -$(MAKE) distclean
2280 rm -f config.log
2281ifneq "$(wildcard /usr/share/misc/config.sub)" ""
2282 cp -f /usr/share/misc/config.sub config.sub
2283endif
2284ifneq "$(wildcard /usr/share/misc/config.guess)" ""
2285 cp -f /usr/share/misc/config.guess config.guess
2286endif
2287
2288 dh_clean
2289
2290# Install architecture dependent and independent
2291install: install-arch install-indep
2292
2293# Install architecture dependent
2294install-arch: build-arch
2295 dh_testdir
2296 dh_testroot
2297 dh_clean -k -s
2298 dh_installdirs -s
2299
2300 # Install the package files into build directory:
2301 # - start with upstream make install
2302 $(MAKE) install prefix=$(CURDIR)/debian/$(PACKAGE_NAME)/usr mandir=$(CURDIR)/debian/$(PACKAGE_NAME)/us
2303r/share/man
2304 # - copy html manual to temporary location for renaming
2305 mkdir -p debian/doc-temp
2306 dh_install -s
2307
2308# Install architecture independent
2309install-indep: build-indep
2310 dh_testdir
2311 dh_testroot
2312 dh_clean -k -i
2313 dh_installdirs -i
2314 dh_install -i
2315
2316# Must not depend on anything. This is to be called by
2317# binary-arch/binary-indep
2318# in another 'make' thread.
2319binary-common:
2320 dh_testdir
2321 dh_testroot
2322 dh_installchangelogs ChangeLog
2323 dh_installdocs
2324 dh_installman
2325 dh_link
2326 dh_strip
2327 dh_compress
2328 dh_fixperms
2329 dh_installdeb
2330 dh_shlibdeps
2331 dh_gencontrol
2332 dh_md5sums
2333 dh_builddeb
2334
2335# Build architecture independant packages using the common target.
2336binary-indep: build-indep install-indep
2337 $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common
2338
2339# Build architecture dependant packages using the common target.
2340binary-arch: build-arch install-arch
2341 $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common
2342
2343# Build architecture depdendent and independent packages
2344binary: binary-arch binary-indep
2345.PHONY: clean binary
2346
2347EOF
2348 close(CONF);
2349 pb_mkdir_p("$ENV{'PBROOTDIR'}/$pp/rpm") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/rpm";
2350 open(CONF,"> $ENV{'PBROOTDIR'}/$pp/rpm/$pp.spec") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/rpm/$pp.spec";
2351 print CONF << 'EOF';
2352#
2353# $Id$
2354#
2355
2356Summary: bla-bla
2357Summary(fr): french bla-bla
2358
2359Name: PBPKG
2360Version: PBVER
2361Release: PBTAGPBSUF
2362License: PBLIC
2363Group: PBGRP
2364Url: PBURL
2365Source: PBSRC
2366BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -u -n)
2367#Requires: PBDEP
2368
2369%description
2370PBDESC
2371
2372%description -l fr
2373french desc
2374
2375%prep
2376%setup -q
2377
2378%build
2379%configure
2380make %{?_smp_mflags}
2381
2382%install
2383%{__rm} -rf $RPM_BUILD_ROOT
2384make DESTDIR=$RPM_BUILD_ROOT install
2385
2386%clean
2387%{__rm} -rf $RPM_BUILD_ROOT
2388
2389%files
2390%defattr(-,root,root)
2391%doc ChangeLog
2392%doc INSTALL COPYING README AUTHORS NEWS
2393
2394%changelog
2395PBLOG
2396
2397EOF
2398 close(CONF);
2399 pb_mkdir_p("$ENV{'PBROOTDIR'}/$pp/pbfilter") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/pbfilter";
2400
2401 pb_log(0,"\nDo not to forget to commit the pbconf directory in your CMS if needed\n");
2402 }
2403 } else {
2404 die "Unable to open $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
2405 }
2406 }
2407 umask 0022;
2408 return(\%filteredfiles, \%supfiles, \%defpkgdir, \%extpkgdir);
2409} else {
2410 # Setup the variables from what has been stored at the end of cms2build
2411 my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","pbroot");
2412 $ENV{'PBROOTDIR'} = $var->{$ENV{'PBPROJ'}};
2413
2414 ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","projver");
2415 $ENV{'PBPROJVER'} = $var->{$ENV{'PBPROJ'}};
2416
2417 ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","projtag");
2418 $ENV{'PBPROJTAG'} = $var->{$ENV{'PBPROJ'}};
2419
2420 ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","pbpackager");
2421 $ENV{'PBPACKAGER'} = $var->{$ENV{'PBPROJ'}};
2422
2423 return;
2424}
2425}
2426
2427# Function which returns a pointer on a table
2428# corresponding to a set of values queried in the conf file
2429# and test the returned vaue as they need to exist in that case
2430sub pb_conf_get {
2431
2432my @param = @_;
2433my @return = pb_conf_get_if(@param);
2434
2435die "No params found for $ENV{'PBPROJ'}" if (not @return);
2436
2437foreach my $i (0..$#param) {
2438 die "No $param[$i] defined for $ENV{'PBPROJ'}" if (not defined $return[$i]);
2439}
2440return(@return);
2441}
2442
2443# Function which returns a pointer on a table
2444# corresponding to a set of values queried in the conf file
2445# Those value may be undef if they do not exist
2446sub pb_conf_get_if {
2447
2448my @param = @_;
2449
2450# Everything is returned via ptr1
2451my @ptr1 = ();
2452my @ptr2 = ();
2453@ptr1 = pb_conf_read_if("$ENV{'PBETC'}", @param) if (defined $ENV{'PBETC'});
2454@ptr2 = pb_conf_read_if("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb", @param) if ((defined $ENV{'PBROOTDIR'}) and (defined $ENV{'PBPROJ'}));
2455
2456my $p1;
2457my $p2;
2458
2459pb_log(2,"DEBUG: pb_conf_get param1: ".Dumper(@ptr1)."\n");
2460pb_log(2,"DEBUG: pb_conf_get param2: ".Dumper(@ptr2)."\n");
2461
2462foreach my $i (0..$#param) {
2463 $p1 = $ptr1[$i];
2464 $p2 = $ptr2[$i];
2465 # Always try to take the param from the home dir conf file in priority
2466 # in order to mask what could be defined under the CMS to allow for overloading
2467 if (not defined $p2) {
2468 # No ref in CMS project conf file so use the home dir one.
2469 $p1->{$ENV{'PBPROJ'}} = $p1->{'default'} if ((not defined $p1->{$ENV{'PBPROJ'}}) && (defined $p1->{'default'}));
2470 } else {
2471 # Ref found in CMS project conf file
2472 if (not defined $p1) {
2473 # No ref in home dir project conf file so use the CMS one.
2474 $p2->{$ENV{'PBPROJ'}} = $p2->{'default'} if ((not defined $p2->{$ENV{'PBPROJ'}}) && (defined $p2->{'default'}));
2475 $p1 = $p2;
2476 } else {
2477 # Both are defined - handling the overloading
2478 if (not defined $p1->{'default'}) {
2479 if (defined $p2->{'default'}) {
2480 $p1->{'default'} = $p2->{'default'};
2481 }
2482 }
2483
2484 if (not defined $p1->{$ENV{'PBPROJ'}}) {
2485 if (defined $p2->{$ENV{'PBPROJ'}}) {
2486 $p1->{$ENV{'PBPROJ'}} = $p2->{$ENV{'PBPROJ'}} if (defined $p2->{$ENV{'PBPROJ'}});
2487 } else {
2488 $p1->{$ENV{'PBPROJ'}} = $p1->{'default'} if (defined $p1->{'default'});
2489 }
2490 }
2491 # Now copy back into p1 all p2 content which doesn't exist in p1
2492 # p1 content (local) always has priority over p2 (project)
2493 foreach my $k (keys %$p2) {
2494 $p1->{$k} = $p2->{$k} if (not defined $p1->{$k});
2495 }
2496 }
2497 }
2498 $ptr1[$i] = $p1;
2499}
2500pb_log(2,"DEBUG: pb_conf_get param ptr1: ".Dumper(@ptr1)."\n");
2501return(@ptr1);
2502}
2503
2504# Setup environment for CMS system for URL passed
2505sub pb_cms_init {
2506
2507my $pbinit = shift || undef;
2508
2509my ($pburl) = pb_conf_get("pburl");
2510pb_log(2,"DEBUG: Project URL of $ENV{'PBPROJ'}: $pburl->{$ENV{'PBPROJ'}}\n");
2511my ($scheme, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
2512
2513my ($pbprojdir) = pb_conf_get_if("pbprojdir");
2514
2515if ((defined $pbprojdir) && (defined $pbprojdir->{$ENV{'PBPROJ'}})) {
2516 $ENV{'PBPROJDIR'} = $pbprojdir->{$ENV{'PBPROJ'}};
2517} else {
2518 $ENV{'PBPROJDIR'} = "$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}";
2519}
2520
2521# Computing the default dir for PBDIR.
2522# what we have is PBPROJDIR so work from that.
2523# Tree identical between PBCONFDIR and PBROOTDIR on one side and
2524# PBPROJDIR and PBDIR on the other side.
2525
2526my $tmp = $ENV{'PBROOTDIR'};
2527$tmp =~ s|^$ENV{'PBCONFDIR'}||;
2528
2529#
2530# Check project cms compliance
2531#
2532pb_cms_compliant(undef,'PBDIR',"$ENV{'PBPROJDIR'}/$tmp",$pburl->{$ENV{'PBPROJ'}},$pbinit);
2533
2534if ($scheme =~ /^svn/) {
2535 # svnversion more precise than svn info
2536 $tmp = `(cd "$ENV{'PBDIR'}" ; svnversion .)`;
2537 chomp($tmp);
2538 $ENV{'PBREVISION'}=$tmp;
2539 $ENV{'PBCMSLOGFILE'}="svn.log";
2540} elsif (($scheme eq "file") || ($scheme eq "ftp") || ($scheme eq "http")) {
2541 $ENV{'PBREVISION'}="flat";
2542 $ENV{'PBCMSLOGFILE'}="flat.log";
2543} elsif ($scheme =~ /^cvs/) {
2544 # Way too slow
2545 #$ENV{'PBREVISION'}=`(cd "$ENV{'PBROOTDIR'}" ; cvs rannotate -f . 2>&1 | awk '{print \$1}' | grep -E '^[0-9]' | cut -d. -f2 |sort -nu | tail -1)`;
2546 #chomp($ENV{'PBREVISION'});
2547 $ENV{'PBREVISION'}="cvs";
2548 $ENV{'PBCMSLOGFILE'}="cvs.log";
2549 $ENV{'CVS_RSH'} = "ssh" if ($scheme =~ /ssh/);
2550} else {
2551 die "cms $scheme unknown";
2552}
2553
2554return($scheme,$pburl->{$ENV{'PBPROJ'}});
2555}
2556
2557sub pb_cms_export {
2558
2559my $uri = shift;
2560my $source = shift;
2561my $destdir = shift;
2562my $tmp;
2563my $tmp1;
2564
2565my @date = pb_get_date();
2566# If it's not flat, then we have a real uri as source
2567my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
2568
2569if ($scheme =~ /^svn/) {
2570 if (-d $source) {
2571 $tmp = $destdir;
2572 } else {
2573 $tmp = "$destdir/".basename($source);
2574 }
2575 pb_system("svn export $source $tmp","Exporting $source from SVN to $tmp");
2576} elsif ($scheme eq "dir") {
2577 pb_system("cp -a $path $destdir","Copying $uri from DIR to $destdir");
2578} elsif (($scheme eq "http") || ($scheme eq "ftp")) {
2579 my $f = basename($path);
2580 unlink "$ENV{'PBTMP'}/$f";
2581 if (-x "/usr/bin/wget") {
2582 pb_system("/usr/bin/wget -nv -O $ENV{'PBTMP'}/$f $uri"," ");
2583 } elsif (-x "/usr/bin/curl") {
2584 pb_system("/usr/bin/curl $uri -o $ENV{'PBTMP'}/$f","Downloading $uri with curl to $ENV{'PBTMP'}/$f\n");
2585 } else {
2586 die "Unable to download $uri.\nNo wget/curl available, please install one of those";
2587 }
2588 pb_cms_export("file://$ENV{'PBTMP'}/$f",$source,$destdir);
2589} elsif ($scheme eq "file") {
2590 use File::MimeInfo;
2591 my $mm = mimetype($path);
2592 pb_log(2,"mimetype: $mm\n");
2593 pb_mkdir_p($destdir);
2594
2595 # Check whether the file is well formed
2596 # (containing already a directory with the project-version name)
2597 my ($pbwf) = pb_conf_get_if("pbwf");
2598 if ((defined $pbwf) && (defined $pbwf->{$ENV{'PBPROJ'}})) {
2599 $destdir = dirname($destdir);
2600 }
2601
2602 if ($mm =~ /\/x-bzip-compressed-tar$/) {
2603 # tar+bzip2
2604 pb_system("cd $destdir ; tar xfj $path","Extracting $path in $destdir");
2605 } elsif ($mm =~ /\/x-lzma-compressed-tar$/) {
2606 # tar+lzma
2607 pb_system("cd $destdir ; tar xfY $path","Extracting $path in $destdir");
2608 } elsif ($mm =~ /\/x-compressed-tar$/) {
2609 # tar+gzip
2610 pb_system("cd $destdir ; tar xfz $path","Extracting $path in $destdir");
2611 } elsif ($mm =~ /\/x-tar$/) {
2612 # tar
2613 pb_system("cd $destdir ; tar xf $path","Extracting $path in $destdir");
2614 } elsif ($mm =~ /\/zip$/) {
2615 # zip
2616 pb_system("cd $destdir ; unzip $path","Extracting $path in $destdir");
2617 }
2618} elsif ($scheme =~ /^cvs/) {
2619 # CVS needs a relative path !
2620 my $dir=dirname($destdir);
2621 my $base=basename($destdir);
2622 # CVS also needs a modules name not a dir
2623 #if (-d $source) {
2624 $tmp1 = basename($source);
2625 #} else {
2626 #$tmp1 = dirname($source);
2627 #$tmp1 = basename($tmp1);
2628 #}
2629 my $optcvs = "";
2630
2631 # If we're working on the CVS itself
2632 my $cvstag = basename($ENV{'PBROOTDIR'});
2633 my $cvsopt = "";
2634 if ($cvstag eq "cvs") {
2635 my $pbdate = strftime("%Y-%m-%d %H:%M:%S", @date);
2636 $cvsopt = "-D \"$pbdate\"";
2637 } else {
2638 # we're working on a tag which should be the last part of PBROOTDIR
2639 $cvsopt = "-r $cvstag";
2640 }
2641 pb_system("cd $dir ; cvs -d $account\@$host:$path export $cvsopt -d $base $tmp1","Exporting $tmp1 from $source under CVS to $destdir");
2642} else {
2643 die "cms $scheme unknown";
2644}
2645}
2646
2647
2648sub pb_create_authors {
2649
2650my $authors=shift;
2651my $dest=shift;
2652my $scheme=shift;
2653
2654return if ($authors eq "/dev/null");
2655open(SAUTH,$authors) || die "Unable to open $authors";
2656# Save a potentially existing AUTHORS file and write instead toi AUTHORS.pb
2657my $ext = "";
2658if (-f "$dest/AUTHORS") {
2659 $ext = ".pb";
2660}
2661open(DAUTH,"> $dest/AUTHORS$ext") || die "Unable to create $dest/AUTHORS$ext";
2662print DAUTH "Authors of the project are:\n";
2663print DAUTH "===========================\n";
2664while (<SAUTH>) {
2665 my ($nick,$gcos) = split(/:/);
2666 chomp($gcos);
2667 print DAUTH "$gcos";
2668 if (defined $scheme) {
2669 # Do not give a scheme for flat types
2670 my $endstr="";
2671 if ("$ENV{'PBREVISION'}" ne "flat") {
2672 $endstr = " under $scheme";
2673 }
2674 print DAUTH " ($nick$endstr)\n";
2675 } else {
2676 print DAUTH "\n";
2677 }
2678}
2679close(DAUTH);
2680close(SAUTH);
2681}
2682
2683sub pb_cms_log {
2684
2685my $scheme = shift;
2686my $pkgdir = shift;
2687my $dest = shift;
2688my $chglog = shift;
2689my $authors = shift;
2690
2691pb_create_authors($authors,$dest,$scheme);
2692
2693if ($scheme =~ /^svn/) {
2694 if (! -f "$dest/ChangeLog") {
2695 if (-x "/usr/bin/svn2cl") {
2696 # In case we have no network, just create an empty one before to allow correct build
2697 open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
2698 close(CL);
2699 pb_system("/usr/bin/svn2cl --group-by-day --authors=$authors -i -o $dest/ChangeLog $pkgdir","Generating ChangeLog from SVN with svn2cl");
2700 } else {
2701 # To be written from pbcl
2702 pb_system("svn log -v $pkgdir > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from SVN");
2703 }
2704 }
2705} elsif (($scheme eq "file") || ($scheme eq "dir") || ($scheme eq "http") || ($scheme eq "ftp")) {
2706 if (! -f "$dest/ChangeLog") {
2707 pb_system("echo ChangeLog for $pkgdir > $dest/ChangeLog","Empty ChangeLog file created");
2708 }
2709} elsif ($scheme =~ /^cvs/) {
2710 my $tmp=basename($pkgdir);
2711 # CVS needs a relative path !
2712 if (! -f "$dest/ChangeLog") {
2713 if (-x "/usr/bin/cvs2cl") {
2714 # In case we have no network, just create an empty one before to allow correct build
2715 open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
2716 close(CL);
2717 pb_system("/usr/bin/cvs2cl --group-by-day -U $authors -f $dest/ChangeLog $pkgdir","Generating ChangeLog from CVS with cvs2cl");
2718 } else {
2719 # To be written from pbcl
2720 pb_system("cvs log $tmp > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from CVS");
2721 }
2722 }
2723} else {
2724 die "cms $scheme unknown";
2725}
2726}
2727
2728# This function is only called with a real CMS system
2729sub pb_cms_get_uri {
2730
2731my $scheme = shift;
2732my $dir = shift;
2733
2734my $res = "";
2735my $void = "";
2736
2737if ($scheme =~ /^svn/) {
2738 open(PIPE,"LANGUAGE=C svn info $dir |") || return("");
2739 while (<PIPE>) {
2740 ($void,$res) = split(/^URL:/) if (/^URL:/);
2741 }
2742 $res =~ s/^\s*//;
2743 close(PIPE);
2744 chomp($res);
2745} elsif ($scheme =~ /^cvs/) {
2746 # This path is always the root path of CVS, but we may be below
2747 open(FILE,"$dir/CVS/Root") || die "$dir isn't CVS controlled";
2748 $res = <FILE>;
2749 chomp($res);
2750 close(FILE);
2751 # Find where we are in the tree
2752 my $rdir = $dir;
2753 while ((! -d "$rdir/CVSROOT") && ($rdir ne "/")) {
2754 $rdir = dirname($rdir);
2755 }
2756 die "Unable to find a CVSROOT dir in the parents of $dir" if (! -d "$rdir/CVSROOT");
2757 #compute our place under that root dir - should be a relative path
2758 $dir =~ s|^$rdir||;
2759 my $suffix = "";
2760 $suffix = "$dir" if ($dir ne "");
2761
2762 my $prefix = "";
2763 if ($scheme =~ /ssh/) {
2764 $prefix = "cvs+ssh://";
2765 } else {
2766 $prefix = "cvs://";
2767 }
2768 $res = $prefix.$res.$suffix;
2769} else {
2770 die "cms $scheme unknown";
2771}
2772pb_log(2,"Found CMS info: $res\n");
2773return($res);
2774}
2775
2776sub pb_cms_copy {
2777my $scheme = shift;
2778my $oldurl = shift;
2779my $newurl = shift;
2780
2781if ($scheme =~ /^svn/) {
2782 pb_system("svn copy -m \"Creation of $newurl from $oldurl\" $oldurl $newurl","Copying $oldurl to $newurl ");
2783} elsif ($scheme eq "flat") {
2784} elsif ($scheme =~ /^cvs/) {
2785} else {
2786 die "cms $scheme unknown";
2787}
2788}
2789
2790sub pb_cms_checkout {
2791my $scheme = shift;
2792my $url = shift;
2793my $destination = shift;
2794
2795if ($scheme =~ /^svn/) {
2796 pb_system("svn co $url $destination","Checking out $url to $destination ");
2797} elsif (($scheme eq "ftp") || ($scheme eq "http")) {
2798 return;
2799} elsif ($scheme =~ /^cvs/) {
2800 pb_system("cvs co $url $destination","Checking out $url to $destination ");
2801} else {
2802 die "cms $scheme unknown";
2803}
2804}
2805
2806sub pb_cms_up {
2807my $scheme = shift;
2808my $dir = shift;
2809
2810if ($scheme =~ /^svn/) {
2811 pb_system("svn up $dir","Updating $dir");
2812} elsif ($scheme eq "flat") {
2813} elsif ($scheme =~ /^cvs/) {
2814} else {
2815 die "cms $scheme unknown";
2816}
2817}
2818
2819sub pb_cms_checkin {
2820my $scheme = shift;
2821my $dir = shift;
2822
2823my $ver = basename($dir);
2824if ($scheme =~ /^svn/) {
2825 pb_system("svn ci -m \"updated to $ver\" $dir","Checking in $dir");
2826} elsif ($scheme eq "flat") {
2827} elsif ($scheme =~ /^cvs/) {
2828} else {
2829 die "cms $scheme unknown";
2830}
2831pb_cms_up($scheme,$dir);
2832}
2833
2834sub pb_cms_isdiff {
2835my $scheme = shift;
2836my $dir =shift;
2837
2838if ($scheme =~ /^svn/) {
2839 open(PIPE,"svn diff $dir |") || die "Unable to get svn diff from $dir";
2840 my $l = 0;
2841 while (<PIPE>) {
2842 $l++;
2843 }
2844 return($l);
2845} elsif ($scheme eq "flat") {
2846} elsif ($scheme =~ /^cvs/) {
2847 open(PIPE,"cvs diff $dir |") || die "Unable to get svn diff from $dir";
2848 my $l = 0;
2849 while (<PIPE>) {
2850 # Skipping normal messages
2851 next if (/^cvs diff:/);
2852 $l++;
2853 }
2854 return($l);
2855} else {
2856 die "cms $scheme unknown";
2857}
2858}
2859
2860# Get all filters to apply
2861# They're cumulative from less specific to most specific
2862# suffix is .pbf
2863
2864sub pb_get_filters {
2865
2866my @ffiles;
2867my ($ffile00, $ffile0, $ffile1, $ffile2, $ffile3);
2868my ($mfile00, $mfile0, $mfile1, $mfile2, $mfile3);
2869my $pbpkg = shift || die "No package specified";
2870my $dtype = shift || "";
2871my $dfam = shift || "";
2872my $ddir = shift || "";
2873my $dver = shift || "";
2874my $ptr = undef; # returned value pointer on the hash of filters
2875my %h;
2876
2877# Global filter files first, then package specificities
2878if (-d "$ENV{'PBROOTDIR'}/pbfilter") {
2879 $mfile00 = "$ENV{'PBROOTDIR'}/pbfilter/all.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/all.pbf");
2880 $mfile0 = "$ENV{'PBROOTDIR'}/pbfilter/$dtype.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$dtype.pbf");
2881 $mfile1 = "$ENV{'PBROOTDIR'}/pbfilter/$dfam.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$dfam.pbf");
2882 $mfile2 = "$ENV{'PBROOTDIR'}/pbfilter/$ddir.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$ddir.pbf");
2883 $mfile3 = "$ENV{'PBROOTDIR'}/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$ddir-$dver.pbf");
2884
2885 push @ffiles,$mfile00 if (defined $mfile00);
2886 push @ffiles,$mfile0 if (defined $mfile0);
2887 push @ffiles,$mfile1 if (defined $mfile1);
2888 push @ffiles,$mfile2 if (defined $mfile2);
2889 push @ffiles,$mfile3 if (defined $mfile3);
2890}
2891
2892if (-d "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter") {
2893 $ffile00 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/all.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/all.pbf");
2894 $ffile0 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dtype.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dtype.pbf");
2895 $ffile1 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dfam.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dfam.pbf");
2896 $ffile2 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir.pbf");
2897 $ffile3 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir-$dver.pbf");
2898
2899 push @ffiles,$ffile00 if (defined $ffile00);
2900 push @ffiles,$ffile0 if (defined $ffile0);
2901 push @ffiles,$ffile1 if (defined $ffile1);
2902 push @ffiles,$ffile2 if (defined $ffile2);
2903 push @ffiles,$ffile3 if (defined $ffile3);
2904}
2905if (@ffiles) {
2906 pb_log(2,"DEBUG ffiles: ".Dumper(\@ffiles)."\n");
2907
2908 foreach my $f (@ffiles) {
2909 open(CONF,$f) || next;
2910 while(<CONF>) {
2911 if (/^\s*([A-z0-9-_]+)\s+([[A-z0-9-_]+)\s*=\s*(.+)$/) {
2912 $h{$1}{$2}=$3;
2913 }
2914 }
2915 close(CONF);
2916
2917 $ptr = $h{"filter"};
2918 pb_log(2,"DEBUG f:".Dumper($ptr)."\n");
2919 }
2920}
2921return($ptr);
2922}
2923
2924# Function which applies filter on pb build files
2925sub pb_filter_file_pb {
2926
2927my $f=shift;
2928my $ptr=shift;
2929my %filter=%$ptr;
2930my $destfile=shift;
2931my $dtype=shift;
2932my $pbsuf=shift;
2933my $pbproj=shift;
2934my $pbpkg=shift;
2935my $pbver=shift;
2936my $pbtag=shift;
2937my $pbrev=shift;
2938my $pbdate=shift;
2939my $defpkgdir = shift;
2940my $extpkgdir = shift;
2941my $pbpackager = shift;
2942my $chglog = shift || undef;
2943
2944pb_log(2,"DEBUG: From $f to $destfile\n");
2945pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
2946open(DEST,"> $destfile") || die "Unable to create $destfile";
2947open(FILE,"$f") || die "Unable to open $f: $!";
2948while (<FILE>) {
2949 my $line = $_;
2950 foreach my $s (keys %filter) {
2951 # Process single variables
2952 pb_log(2,"DEBUG filter{$s}: $filter{$s}\n");
2953 my $tmp = $filter{$s};
2954 next if (not defined $tmp);
2955 # Expand variables if any single one found
2956 pb_log(2,"DEBUG tmp: $tmp\n");
2957 if ($tmp =~ /\$/) {
2958 eval { $tmp =~ s/(\$\w+)/$1/eeg };
2959 # special case for ChangeLog only for pb
2960 } elsif (($s =~ /^PBLOG$/) && ($line =~ /^PBLOG$/)) {
2961 my $p = $defpkgdir->{$pbpkg};
2962 $p = $extpkgdir->{$pbpkg} if (not defined $p);
2963 pb_changelog($dtype, $pbpkg, $pbver, $pbtag, $pbsuf, $p, \*DEST, $tmp, $chglog);
2964 $tmp = "";
2965 }
2966 $line =~ s|$s|$tmp|;
2967 }
2968 print DEST $line;
2969}
2970close(FILE);
2971close(DEST);
2972}
2973
2974# Function which applies filter on files (external call)
2975sub pb_filter_file_inplace {
2976
2977my $ptr=shift;
2978my %filter=%$ptr;
2979my $destfile=shift;
2980my $pbproj=shift;
2981my $pbpkg=shift;
2982my $pbver=shift;
2983my $pbtag=shift;
2984my $pbrev=shift;
2985my $pbdate=shift;
2986my $pbpackager=shift;
2987
2988my $cp = "$ENV{'PBTMP'}/".basename($destfile);
2989copy($destfile,$cp) || die "Unable to create $cp";
2990
2991pb_filter_file($cp,$ptr,$destfile,$pbproj,$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$pbpackager);
2992unlink $cp;
2993}
2994
2995# Function which applies filter on files (external call)
2996sub pb_filter_file {
2997
2998my $f=shift;
2999my $ptr=shift;
3000my %filter=%$ptr;
3001my $destfile=shift;
3002my $pbproj=shift;
3003my $pbpkg=shift;
3004my $pbver=shift;
3005my $pbtag=shift;
3006my $pbrev=shift;
3007my $pbdate=shift;
3008my $pbpackager=shift;
3009
3010pb_log(2,"DEBUG: From $f to $destfile\n");
3011pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
3012open(DEST,"> $destfile") || die "Unable to create $destfile";
3013open(FILE,"$f") || die "Unable to open $f: $!";
3014while (<FILE>) {
3015 my $line = $_;
3016 foreach my $s (keys %filter) {
3017 # Process single variables
3018 pb_log(2,"DEBUG filter{$s}: $filter{$s}\n");
3019 my $tmp = $filter{$s};
3020 next if (not defined $tmp);
3021 # Expand variables if any single one found
3022 if ($tmp =~ /\$/) {
3023 eval { $tmp =~ s/(\$\w+)/$1/eeg };
3024 }
3025 $line =~ s|$s|$tmp|;
3026 }
3027 print DEST $line;
3028}
3029close(FILE);
3030close(DEST);
3031}
3032
3033#
3034# Return the list of packages we are working on in a CMS action
3035#
3036sub pb_cms_get_pkg {
3037
3038my @pkgs = ();
3039my $defpkgdir = shift || undef;
3040my $extpkgdir = shift || undef;
3041
3042# Get packages list
3043if (not defined $ARGV[0]) {
3044 @pkgs = keys %$defpkgdir if (defined $defpkgdir);
3045} elsif ($ARGV[0] =~ /^all$/) {
3046 @pkgs = keys %$defpkgdir if (defined $defpkgdir);
3047 push(@pkgs, keys %$extpkgdir) if (defined $extpkgdir);
3048} else {
3049 @pkgs = @ARGV;
3050}
3051pb_log(0,"Packages: ".join(',',@pkgs)."\n");
3052return(\@pkgs);
3053}
3054
3055#
3056# Return the list of packages we are working on in a non CMS action
3057#
3058sub pb_get_pkg {
3059
3060my @pkgs = ();
3061
3062my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
3063@pkgs = keys %$var;
3064
3065pb_log(0,"Packages: ".join(',',@pkgs)."\n");
3066return(\@pkgs);
3067}
3068
3069#
3070# Check pbconf/project cms compliance
3071#
3072sub pb_cms_compliant {
3073
3074my $param = shift;
3075my $envar = shift;
3076my $defdir = shift;
3077my $uri = shift;
3078my $pbinit = shift;
3079my %pdir;
3080
3081my ($pdir) = pb_conf_get_if($param) if (defined $param);
3082if (defined $pdir) {
3083 %pdir = %$pdir;
3084}
3085
3086
3087if ((defined $pdir) && (%pdir) && (defined $pdir{$ENV{'PBPROJ'}})) {
3088 # That's always the environment variable that will be used
3089 $ENV{$envar} = $pdir{$ENV{'PBPROJ'}};
3090} else {
3091 if (defined $param) {
3092 pb_log(1,"WARNING: no $param defined, using $defdir\n");
3093 pb_log(1," Please create a $param reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n");
3094 pb_log(1," if you want to use another directory\n");
3095 }
3096 $ENV{$envar} = "$defdir";
3097}
3098
3099# Expand potential env variable in it
3100eval { $ENV{$envar} =~ s/(\$ENV.+\})/$1/eeg };
3101pb_log(2,"$envar: $ENV{$envar}\n");
3102
3103my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
3104
3105if ((! -d "$ENV{$envar}") || (defined $pbinit)) {
3106 if (defined $pbinit) {
3107 pb_mkdir_p("$ENV{$envar}");
3108 } else {
3109 pb_log(1,"Checking out $uri\n");
3110 pb_cms_checkout($scheme,$uri,$ENV{$envar});
3111 }
3112} elsif (($scheme !~ /^cvs/) || ($scheme !~ /^svn/)) {
3113 # Do not compare if it's not a real cms
3114 return;
3115} else {
3116 pb_log(1,"$uri found locally, checking content\n");
3117 my $cmsurl = pb_cms_get_uri($scheme,$ENV{$envar});
3118 my ($scheme2, $account2, $host2, $port2, $path2) = pb_get_uri($cmsurl);
3119 if ($cmsurl ne $uri) {
3120 # The local content doesn't correpond to the repository
3121 pb_log(0,"ERROR: Inconsistency detected:\n");
3122 pb_log(0," * $ENV{$envar} refers to $cmsurl but\n");
3123 pb_log(0," * $ENV{'PBETC'} refers to $uri\n");
3124 die "Project $ENV{'PBPROJ'} is not Project-Builder compliant.";
3125 } else {
3126 pb_log(1,"Content correct - doing nothing - you may want to update your repository however\n");
3127 # they match - do nothing - there may be local changes
3128 }
3129}
3130}
3131
3132sub pb_changelog {
3133
3134my $dtype = shift;
3135my $pkg = shift;
3136my $pbver = shift;
3137my $pbtag = shift;
3138my $dsuf = shift;
3139my $path = shift;
3140my $OUTPUT = shift;
3141my $doit = shift;
3142my $chglog = shift || undef;
3143
3144my $log = "";
3145
3146# For date handling
3147$ENV{LANG}="C";
3148
3149if ((not (defined $dtype)) || ($dtype eq "") ||
3150 (not (defined $pkg)) || ($pkg eq "") ||
3151 (not (defined $pbver)) || ($pbver eq "") ||
3152 (not (defined $pbtag)) || ($pbtag eq "") ||
3153 (not (defined $dsuf)) || ($dsuf eq "") ||
3154 (not (defined $path)) || ($path eq "") ||
3155 (not (defined $OUTPUT)) || ($OUTPUT eq "") ||
3156 (not (defined $doit)) || ($doit eq "")) {
3157 print $OUTPUT "\n";
3158 return;
3159}
3160
3161if (((not defined $chglog) || (! -f $chglog)) && ($doit eq "yes")) {
3162 #pb_log(2,"No ChangeLog file ($chglog) for $pkg\n";
3163 print $OUTPUT "\n";
3164 return;
3165}
3166
3167my $date;
3168my $ndate;
3169my $n2date;
3170my $ver;
3171my $ver2;
3172my ($pbpackager) = pb_conf_get("pbpackager");
3173
3174if (not defined $pbpackager->{$ENV{'PBPROJ'}}) {
3175 $pbpackager->{$ENV{'PBPROJ'}} = "undefined\@noproject.noorg";
3176}
3177
3178# If we don't need to do it, or don't have it fake something
3179if (((not defined $chglog) || (! -f $chglog)) && ($doit ne "yes")) {
3180 my @date = pb_get_date();
3181 $date = strftime("%Y-%m-%d", @date);
3182 $ndate = UnixDate($date,"%a", "%b", "%d", "%Y");
3183 $n2date = &UnixDate($date,"%a, %d %b %Y %H:%M:%S %z");
3184 if (($dtype eq "rpm") || ($dtype eq "fc")) {
3185 $ver2 = "$pbver-$pbtag$dsuf";
3186 print $OUTPUT "* $ndate $pbpackager->{$ENV{'PBPROJ'}} $ver2\n";
3187 print $OUTPUT "- Updated to $pbver\n";
3188 }
3189 if ($dtype eq "deb") {
3190 print $OUTPUT "$pkg ($pbver) unstable; urgency=low\n";
3191 print $OUTPUT "\n";
3192 print $OUTPUT " -- $pbpackager->{$ENV{'PBPROJ'}} $n2date\n\n\n";
3193 }
3194 return;
3195}
3196
3197open(INPUT,"$chglog") || die "Unable to open $chglog (read)";
3198
3199# Skip first 4 lines
3200my $tmp = <INPUT>;
3201$tmp = <INPUT>;
3202$tmp = <INPUT>;
3203if ($dtype eq "announce") {
3204 print $OUTPUT $tmp;
3205}
3206$tmp = <INPUT>;
3207if ($dtype eq "announce") {
3208 print $OUTPUT $tmp;
3209}
3210
3211my $first=1;
3212
3213# Handle each block separated by newline
3214while (<INPUT>) {
3215 ($ver, $date) = split(/ /);
3216 $ver =~ s/^v//;
3217 chomp($date);
3218 $date =~ s/\(([0-9-]+)\)/$1/;
3219 #pb_log(2,"**$date**\n";
3220 $ndate = UnixDate($date,"%a", "%b", "%d", "%Y");
3221 $n2date = &UnixDate($date,"%a, %d %b %Y %H:%M:%S %z");
3222 #pb_log(2,"**$ndate**\n";
3223
3224 if (($dtype eq "rpm") || ($dtype eq "fc")) {
3225 if ($ver !~ /-/) {
3226 if ($first eq 1) {
3227 $ver2 = "$ver-$pbtag$dsuf";
3228 $first=0;
3229 } else {
3230 $ver2 = "$ver-1$dsuf";
3231 }
3232 } else {
3233 $ver2 = "$ver$dsuf";
3234 }
3235 print $OUTPUT "* $ndate $pbpackager->{$ENV{'PBPROJ'}} $ver2\n";
3236 print $OUTPUT "- Updated to $ver\n";
3237 }
3238 if ($dtype eq "deb") {
3239 print $OUTPUT "$pkg ($ver) unstable; urgency=low\n";
3240 print $OUTPUT "\n";
3241 }
3242
3243 $tmp = <INPUT>;
3244 while ($tmp !~ /^$/) {
3245 if ($dtype eq "deb") {
3246 $tmp =~ s/^- //;
3247 print $OUTPUT " * $tmp";
3248 } elsif ($dtype eq "rpm") {
3249 print $OUTPUT "$tmp";
3250 } else {
3251 print $OUTPUT "$tmp";
3252 }
3253 last if (eof(INPUT));
3254 $tmp = <INPUT>;
3255 }
3256 print $OUTPUT "\n";
3257
3258 if ($dtype eq "deb") {
3259 # Cf: http://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog
3260 print $OUTPUT " -- $pbpackager->{$ENV{'PBPROJ'}} $n2date\n\n\n";
3261 }
3262
3263 last if (eof(INPUT));
3264 last if ($dtype eq "announce");
3265}
3266close(INPUT);
3267}
32681;
Note: See TracBrowser for help on using the repository browser.