source: devel/pb/bin/pb @ 397

Last change on this file since 397 was 397, checked in by bruno, 11 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.