source: devel/pb/lib/ProjectBuilder/Base.pm @ 344

Last change on this file since 344 was 344, checked in by Bruno Cornec, 12 years ago

Lots of fixes in order to make it work for netperf from scratch (newver, cms2build, build2pkg, pbcl)

File size: 49.9 KB
Line 
1#!/usr/bin/perl -w
2#
3# Base subroutines for the Project-Builder project
4#
5# $Id$
6#
7
8package ProjectBuilder::Base;
9
10use strict;
11use lib qw (lib);
12use File::Basename;
13use File::Path;
14use File::stat;
15use File::Copy;
16use File::Temp qw(tempdir);
17use Data::Dumper;
18use POSIX qw(strftime);
19use Time::localtime qw(localtime);
20use Date::Manip;
21use English;
22
23# Inherit from the "Exporter" module which handles exporting functions.
24 
25use Exporter;
26 
27# Export, by default, all the functions into the namespace of
28# any code which uses this module.
29 
30our $debug = 0;
31our $LOG = \*STDOUT;
32
33our @ISA = qw(Exporter);
34our @EXPORT = qw(pb_env_init pb_conf_read pb_conf_read_if pb_conf_get pb_conf_get_if pb_cms_init pb_mkdir_p pb_system pb_rm_rf pb_get_filters pb_filter_file pb_filter_file_pb pb_filter_file_inplace pb_cms_export pb_cms_log pb_cms_isdiff pb_cms_copy pb_cms_checkout pb_get_date pb_log pb_log_init pb_get_pkg pb_get_uri pb_cms_get_uri $debug $LOG);
35
36$ENV{'PBETC'} = "$ENV{'HOME'}/.pbrc";
37
38sub pb_env_init {
39
40my $proj=shift || undef;
41my $pbinit=shift || undef;
42my $ver;
43my $tag;
44
45#
46# Check project name
47# Could be with env var PBPROJ
48# or option -p
49# if not define take the first in conf file
50#
51if ((defined $ENV{'PBPROJ'}) &&
52    (not (defined $proj))) {
53    $proj = $ENV{'PBPROJ'};
54}
55
56#
57# We get the pbconf file for that project
58# and use its content
59#
60my ($pbconf) = pb_conf_read("$ENV{'PBETC'}","pbconfurl");
61pb_log(2,"DEBUG pbconfurl: ".Dumper($pbconf)."\n");
62
63my %pbconf = %$pbconf;
64if (not defined $proj) {
65    # Take the first as the default project
66    $proj = (keys %pbconf)[0];
67    if (defined $proj) {
68        pb_log(1,"WARNING: using $proj as default project as none has been specified\n");
69        pb_log(1,"         Please either create a pbconfurl reference for project $proj in $ENV{'PBETC'}\n");
70        pb_log(1,"         or call pb with the -p project option or use the env var PBPROJ\n");
71        pb_log(1,"         if you want to use another project\n");
72    }
73}
74die "No project defined - use env var PBPROJ or -p proj or a pbconfurl entry in $ENV{'PBETC'}" if (not (defined $proj));
75
76# That's always the environment variable that will be used
77$ENV{'PBPROJ'} = $proj;
78pb_log(2,"PBPROJ: $ENV{'PBPROJ'}\n");
79
80if (not defined ($pbconf{$ENV{'PBPROJ'}})) {
81    die "Please create a pbconfurl reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n";
82}
83
84#
85# Detect the root dir for hosting all the content generated with pb
86#
87# Tree will look like this:
88#
89#             maint pbdefdir                         PBDEFDIR            dev dir (optional)
90#                  |                                                        |
91#            ------------------------                                --------------------
92#            |                      |                                |                  |
93#         pbproj1                pbproj2             PBPROJ       pbproj1           pbproj2   PBPROJDIR
94#            |                                                       |
95#  ---------------------------------------------                ----------
96#  *      *        *       |        |          |                *        *
97# tag    dev    pbconf    ...     build     delivery PBCONFDIR dev      tag                 
98#  |               |                           |     PBDESTDIR           |
99#  ---          ------                        pbrc   PBBUILDDIR       -------
100#    |          |    |                                                |     |
101#   1.1        dev  tag                                              1.0   1.1                PBDIR
102#                    |
103#                 -------
104#                 |     |
105#                1.0   1.1                           PBROOTDIR
106#                       |
107#               ----------------------------------
108#               |          |           |         |
109#             pkg1      pbproj1.pb   pbfilter   pbcl
110#               |
111#        -----------------
112#        |      |        |
113#       rpm    deb    pbfilter
114#
115#
116# (*) By default, if no relocation in .pbrc, dev dir is taken in the maint pbdefdir (when appropriate)
117# Names under a pbproj and the corresponding pbconf should be similar
118#
119
120my ($pbdefdir) = pb_conf_get_if("pbdefdir");
121
122if (not defined $ENV{'PBDEFDIR'}) {
123    if ((not defined $pbdefdir) || (not defined $pbdefdir->{$ENV{'PBPROJ'}})) {
124        pb_log(1,"WARNING: no pbdefdir defined, using /var/cache\n");
125        pb_log(1,"         Please create a pbdefdir reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n");
126        pb_log(1,"         if you want to use another directory\n");
127        $ENV{'PBDEFDIR'} = "/var/cache";
128    } else {
129        # That's always the environment variable that will be used
130        $ENV{'PBDEFDIR'} = $pbdefdir->{$ENV{'PBPROJ'}};
131    }
132}
133# Expand potential env variable in it
134eval { $ENV{'PBDEFDIR'} =~ s/(\$ENV.+\})/$1/eeg };
135
136pb_log(2,"PBDEFDIR: $ENV{'PBDEFDIR'}\n");
137#
138# Set delivery directory
139#
140$ENV{'PBDESTDIR'}="$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/delivery";
141
142pb_log(2,"PBDESTDIR: $ENV{'PBDESTDIR'}\n");
143#
144# Removes all directory existing below the delivery dir
145# as they are temp dir only
146# Files stay and have to be cleaned up manually if needed
147# those files serves as communication channels between pb phases
148# Removing them prevents a following phase to detect what has been done before
149#
150if (-d $ENV{'PBDESTDIR'}) {
151    opendir(DIR,$ENV{'PBDESTDIR'}) || die "Unable to open directory $ENV{'PBDESTDIR'}: $!";
152    foreach my $d (readdir(DIR)) {
153        next if ($d =~ /^\./);
154        next if (-f "$ENV{'PBDESTDIR'}/$d");
155        pb_rm_rf("$ENV{'PBDESTDIR'}/$d") if (-d "$ENV{'PBDESTDIR'}/$d");
156    }
157    closedir(DIR);
158}
159if (! -d "$ENV{'PBDESTDIR'}") {
160    pb_mkdir_p($ENV{'PBDESTDIR'}) || die "Unable to recursively create $ENV{'PBDESTDIR'}";
161}
162
163#
164# Set build directory
165#
166$ENV{'PBBUILDDIR'}="$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/build";
167if (! -d "$ENV{'PBBUILDDIR'}") {
168    pb_mkdir_p($ENV{'PBBUILDDIR'}) || die "Unable to recursively create $ENV{'PBBUILDDIR'}";
169}
170
171pb_log(2,"PBBUILDDIR: $ENV{'PBBUILDDIR'}\n");
172#
173# Set temp directory
174#
175if (not defined $ENV{'TMPDIR'}) {
176    $ENV{'TMPDIR'}="/tmp";
177}
178$ENV{'PBTMP'} = tempdir( "pb.XXXXXXXXXX", DIR => $ENV{'TMPDIR'}, CLEANUP => 1 );
179pb_log(2,"PBTMP: $ENV{'PBTMP'}\n");
180
181#
182# The following part is only useful when in cms2build
183# In VMs/VEs we want to skip that by providing a good PBCONFDIR env var.
184# return values in that case are useless
185#
186return if (defined $ENV{'PBCONFDIR'});
187
188#
189# Check pbconf cms compliance
190#
191pb_cms_compliant("pbconfdir",'PBCONFDIR',"$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/pbconf",$pbconf{$ENV{'PBPROJ'}},$pbinit);
192
193# Check where is our PBROOTDIR (release tag name can't be guessed the first time)
194#
195if (not defined $ENV{'PBROOTDIR'}) {
196    if (! -f ("$ENV{'PBDESTDIR'}/pbrc")) {
197        opendir(DIR,$ENV{'PBCONFDIR'}) || die "Unable to open directory $ENV{'PBCONFDIR'}: $!";
198        my $maxmtime = 0;
199        foreach my $d (readdir(DIR)) {
200            pb_log(3,"Looking at \'$d\'...");
201            next if ($d =~ /^\./);
202            next if (! -d "$ENV{'PBCONFDIR'}/$d");
203            my $s = stat("$ENV{'PBCONFDIR'}/$d");
204            next if (not defined $s);
205            pb_log(3,"KEEP\n");
206            # Keep the most recent
207            pb_log(2," $s->mtime\n");
208            if ($s->mtime > $maxmtime) {
209                $ENV{'PBROOTDIR'} = "$ENV{'PBCONFDIR'}/$d";
210                $maxmtime = $s->mtime;
211            }
212        }
213        closedir(DIR);
214        die "No directory found under $ENV{'PBCONFDIR'}" if (not defined $ENV{'PBROOTDIR'});
215        pb_log(1,"WARNING: no pbroot defined, using $ENV{'PBROOTDIR'}\n");
216        pb_log(1,"         Please use -r release if you want to use another release\n");
217    } else {
218        my ($pbroot) = pb_conf_read_if("$ENV{'PBDESTDIR'}/pbrc","pbroot");
219        # That's always the environment variable that will be used
220        die "Please remove inconsistent $ENV{'PBDESTDIR'}/pbrc" if ((not defined $pbroot) || (not defined $pbroot->{$ENV{'PBPROJ'}}));
221        $ENV{'PBROOTDIR'} = $pbroot->{$ENV{'PBPROJ'}};
222    }
223} else {
224    # transform in full path if relative
225    $ENV{'PBROOTDIR'} = "$ENV{'PBCONFDIR'}/$ENV{'PBROOTDIR'}" if ($ENV{'PBROOTDIR'} !~ /^\//);
226    pb_mkdir_p($ENV{'PBROOTDIR'}) if (defined $pbinit);
227    die "$ENV{'PBROOTDIR'} is not a directory" if (not -d $ENV{'PBROOTDIR'});
228}
229
230my %version = ();
231my %defpkgdir = ();
232my %extpkgdir = ();
233my %filteredfiles = ();
234my %supfiles = ();
235
236if ((-f "$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb") and (not defined $pbinit)) {
237    # List of pkg to build by default (mandatory)
238    my ($defpkgdir,$pbpackager) = pb_conf_get("defpkgdir","pbpackager");
239    # List of additional pkg to build when all is called (optional)
240    # Valid version names (optional)
241    # List of files to filter (optional)
242    # Project version and tag (optional)
243    my ($extpkgdir, $version, $filteredfiles, $supfiles, $pkgv, $pkgt) = pb_conf_get_if("extpkgdir","version","filteredfiles","supfiles","projver","projtag");
244    pb_log(2,"DEBUG: defpkgdir: ".Dumper($defpkgdir)."\n");
245    pb_log(2,"DEBUG: extpkgdir: ".Dumper($extpkgdir)."\n");
246    pb_log(2,"DEBUG: version: ".Dumper($version)."\n");
247    pb_log(2,"DEBUG: filteredfiles: ".Dumper($filteredfiles)."\n");
248    pb_log(2,"DEBUG: supfiles: ".Dumper($supfiles)."\n");
249    # Global
250    %defpkgdir = %$defpkgdir;
251    %extpkgdir = %$extpkgdir if (defined $extpkgdir);
252    %version = %$version if (defined $version);
253    %filteredfiles = %$filteredfiles if (defined $filteredfiles);
254    %supfiles = %$supfiles if (defined $supfiles);
255    #
256    # Get global Version/Tag
257    #
258    if (not defined $ENV{'PBVER'}) {
259        if ((defined $pkgv) && (defined $pkgv->{$ENV{'PBPROJ'}})) {
260            $ENV{'PBVER'}=$pkgv->{$ENV{'PBPROJ'}};
261        } else {
262            die "No projver found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
263        }
264    }
265    die "Invalid version name $ENV{'PBVER'} in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb" if (($ENV{'PBVER'} !~ /[0-9.]+/) && (not defined $version) && ($ENV{'PBVER'} =~ /$version{$ENV{'PBPROJ'}}/));
266   
267    if (not defined $ENV{'PBTAG'}) {
268        if ((defined $pkgt) && (defined $pkgt->{$ENV{'PBPROJ'}})) {
269            $ENV{'PBTAG'}=$pkgt->{$ENV{'PBPROJ'}};
270        } else {
271            die "No projtag found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
272        }
273    }
274    die "Invalid tag name $ENV{'PBTAG'} in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb" if ($ENV{'PBTAG'} !~ /[0-9.]+/);
275
276
277    if (not defined $ENV{'PBPACKAGER'}) {
278        if ((defined $pbpackager) && (defined $pbpackager->{$ENV{'PBPROJ'}})) {
279            $ENV{'PBPACKAGER'}=$pbpackager->{$ENV{'PBPROJ'}};
280        } else {
281            die "No pbpackager found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
282        }
283    }
284} else {
285    if (defined $pbinit) {
286        my $ptr = pb_get_pkg();
287        my @pkgs = @$ptr;
288        @pkgs = ("pkg1") if (not @pkgs);
289
290        open(CONF,"> $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb") || die "Unable to create $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
291        print CONF << "EOF";
292#
293# Project Builder configuration file
294# For project $ENV{'PBPROJ'}
295#
296# \$Id\$
297#
298
299#
300# What is the project URL
301#
302#pburl $ENV{'PBPROJ'} = svn://svn.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel
303#pburl $ENV{'PBPROJ'} = svn://svn+ssh.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel
304#pburl $ENV{'PBPROJ'} = cvs://cvs.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel
305#pburl $ENV{'PBPROJ'} = http://www.$ENV{'PBPROJ'}.org/src/$ENV{'PBPROJ'}-devel.tar.gz
306#pburl $ENV{'PBPROJ'} = ftp://ftp.$ENV{'PBPROJ'}.org/src/$ENV{'PBPROJ'}-devel.tar.gz
307#pburl $ENV{'PBPROJ'} = file:///src/$ENV{'PBPROJ'}-devel.tar.gz
308#pburl $ENV{'PBPROJ'} = dir:///src/$ENV{'PBPROJ'}-devel
309
310# Check whether project is well formed
311# (containing already a directory with the project-version name)
312#pbwf $ENV{'PBPROJ'} = 1
313
314#
315# Packager label
316#
317#pbpackager $ENV{'PBPROJ'} = William Porte <bill\@$ENV{'PBPROJ'}.org>
318#
319
320# For delivery to a machine by SSH (potentially the FTP server)
321# Needs hostname, account and directory
322#
323#sshhost $ENV{'PBPROJ'} = www.$ENV{'PBPROJ'}.org
324#sshlogin $ENV{'PBPROJ'} = bill
325#sshdir $ENV{'PBPROJ'} = /$ENV{'PBPROJ'}/ftp
326#sshport $ENV{'PBPROJ'} = 22
327
328#
329# For Virtual machines management
330# Naming convention to follow: distribution name (as per ProjectBuilder::Distribution)
331# followed by '-' and by release number
332# followed by '-' and by architecture
333# a .vmtype extension will be added to the resulting string
334# a QEMU rhel-3-i286 here means that the VM will be named rhel-3-i386.qemu
335#
336#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
337
338#
339# Valid values for vmtype are
340# qemu, (vmware, xen, ... TBD)
341#vmtype $ENV{'PBPROJ'} = qemu
342
343# Hash for VM stuff on vmtype
344#vmntp default = pool.ntp.org
345
346# We suppose we can commmunicate with the VM through SSH
347#vmhost $ENV{'PBPROJ'} = localhost
348#vmlogin $ENV{'PBPROJ'} = pb
349#vmport $ENV{'PBPROJ'} = 2222
350
351# Timeout to wait when VM is launched/stopped
352#vmtmout default = 120
353
354# per VMs needed paramaters
355#vmopt $ENV{'PBPROJ'} = -m 384 -daemonize
356#vmpath $ENV{'PBPROJ'} = /home/qemu
357#vmsize $ENV{'PBPROJ'} = 5G
358
359#
360# For Virtual environment management
361# Naming convention to follow: distribution name (as per ProjectBuilder::Distribution)
362# followed by '-' and by release number
363# followed by '-' and by architecture
364# a .vetype extension will be added to the resulting string
365# a chroot rhel-3-i286 here means that the VE will be named rhel-3-i386.chroot
366#
367#velist $ENV{'PBPROJ'} = fedora-7-i386
368
369# VE params
370#vetype $ENV{'PBPROJ'} = chroot
371#ventp default = pool.ntp.org
372#velogin $ENV{'PBPROJ'} = pb
373#vepath $ENV{'PBPROJ'} = /var/lib/mock
374#veconf $ENV{'PBPROJ'} = /etc/mock
375#verebuild $ENV{'PBPROJ'} = false
376
377#
378# Global version/tag for the project
379#
380#projver $ENV{'PBPROJ'} = devel
381#projtag $ENV{'PBPROJ'} = 1
382
383# Hash of valid version names
384#version $ENV{'PBPROJ'} = devel,stable
385
386# Adapt to your needs:
387# Optional if you need to overwrite the global values above
388#
389EOF
390       
391        foreach my $pp (@pkgs) {
392            print CONF << "EOF";
393#pkgver $pp = stable
394#pkgtag $pp = 3
395EOF
396        }
397        foreach my $pp (@pkgs) {
398            print CONF << "EOF";
399# Hash of default package/package directory
400#defpkgdir $pp = dir-$pp
401EOF
402        }
403
404        print CONF << "EOF";
405# Hash of additional package/package directory
406#extpkgdir minor-pkg = dir-minor-pkg
407
408# List of files per pkg on which to apply filters
409# Files are mentioned relatively to pbroot/defpkgdir
410EOF
411        foreach my $pp (@pkgs) {
412            print CONF << "EOF";
413#filteredfiles $pp = Makefile.PL,configure.in,install.sh,$pp.8
414#supfiles $pp = $pp.init
415EOF
416        }
417        close(CONF);
418        pb_mkdir_p("$ENV{'PBROOTDIR'}/pbfilter") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter";
419        open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/all.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/all.pbf";
420        print CONF << "EOF";
421#
422# \$Id\$
423#
424# Filter for all files
425#
426# PBSRC is replaced by the source package format
427#filter PBSRC = ftp://ftp.$ENV{'PBPROJ'}.org/src/%{name}-%{version}.tar.gz
428
429# PBVER is replaced by the version (\$pbver in code)
430filter PBVER = \$pbver
431
432# PBDATE is replaced by the date (\$pbdate in code)
433filter PBDATE = \$pbdate
434
435# PBLOG is replaced by the changelog if value is yes
436#filter PBLOG = yes
437
438# PBTAG is replaced by the tag (\$pbtag in code)
439filter PBTAG = \$pbtag
440
441# PBREV is replaced by the revision (\$pbrev in code)
442filter PBREV = \$pbrev
443
444# PBPKG is replaced by the package name (\$pbpkg in code)
445filter PBPKG = \$pbpkg
446
447# PBPACKAGER is replaced by the packager name (\$pbpackager in code)
448filter PBPACKAGER = \$pbpackager
449
450# PBDESC contains the description of the package
451#filter PBDESC = "Bla-Bla"
452
453# PBURL contains the URL of the Web site of the project
454#filter PBURL = http://www.$ENV{'PBPROJ'}.org
455EOF
456        close(CONF);
457        open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/rpm.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/rpm.pbf";
458        print CONF << "EOF";
459#
460# \$Id\$
461#
462# Filter for rpm build
463#
464
465# PBGRP is replaced by the RPM group of apps
466# Cf: http://fedoraproject.org/wiki/RPMGroups
467#filter PBGRP = Applications/Archiving
468
469# PBLIC is replaced by the license of the application
470# Cf: http://fedoraproject.org/wiki/Licensing
471#filter PBLIC = GPL
472
473# PBDEP is replaced by the list of dependencies
474#filter PBDEP =
475
476# PBSUF is replaced by the package suffix (\$pbsuf in code)
477filter PBSUF = \$pbsuf
478
479# PBOBS is replaced by the Obsolete line
480#filter PBOBS =
481
482EOF
483        close(CONF);
484        open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/deb.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/deb.pbf";
485        print CONF << "EOF";
486#
487# \$Id\$
488#
489# Filter for debian build
490#
491# PBGRP is replaced by the group of apps
492filter PBGRP = utils
493
494# PBLIC is replaced by the license of the application
495# Cf:
496#filter PBLIC = GPL
497
498# PBDEP is replaced by the list of dependencies
499#filter PBDEP =
500
501# PBSUG is replaced by the list of suggestions
502#filter PBSUG =
503
504# PBREC is replaced by the list of recommandations
505#filter PBREC =
506
507EOF
508        close(CONF);
509        open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/md.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/md.pbf";
510        print CONF << "EOF";
511# Specific group for Mandriva for $ENV{'PBPROJ'}
512# Cf: http://wiki.mandriva.com/en/Development/Packaging/Groups
513#filter PBGRP = Archiving/Backup
514
515# PBLIC is replaced by the license of the application
516# Cf: http://wiki.mandriva.com/en/Development/Packaging/Licenses
517#filter PBLIC = GPL
518
519EOF
520        close(CONF);
521        open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/novell.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/novell.pbf";
522        print CONF << "EOF";
523# Specific group for SuSE for $ENV{'PBPROJ'}
524# Cf: http://en.opensuse.org/SUSE_Package_Conventions/RPM_Groups
525#filter PBGRP = Productivity/Archiving/Backup
526
527# PBLIC is replaced by the license of the application
528# Cf: http://en.opensuse.org/Packaging/SUSE_Package_Conventions/RPM_Style#1.6._License_Tag
529#filter PBLIC = GPL
530
531EOF
532        close(CONF);
533        foreach my $pp (@pkgs) {
534            pb_mkdir_p("$ENV{'PBROOTDIR'}/$pp/deb") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb";
535            open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/control") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/control";
536            print CONF << "EOF";
537Source: PBPKG
538Section: PBGRP
539Priority: optional
540Maintainer: PBPACKAGER
541Build-Depends: debhelper (>= 4.2.20), PBDEP
542Standards-Version: 3.6.1
543
544Package: PBPKG
545Architecture: amd64 i386 ia64
546Section: PBGRP
547Priority: optional
548Depends: \${shlibs:Depends}, \${misc:Depends}, PBDEP
549Recommends: PBREC
550Suggests: PBSUG
551Description:
552 PBDESC
553 .
554 Homepage: PBURL
555
556EOF
557            close(CONF);
558            open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/copyright") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/copyright";
559            print CONF << "EOF";
560This package is debianized by PBPACKAGER
561`date`
562
563The current upstream source was downloaded from
564ftp://ftp.$ENV{'PBPROJ'}.org/src/.
565
566Upstream Authors: Put their name here
567
568Copyright:
569
570   This package is free software; you can redistribute it and/or modify
571   it under the terms of the GNU General Public License as published by
572   the Free Software Foundation; version 2 dated June, 1991.
573
574   This package is distributed in the hope that it will be useful,
575   but WITHOUT ANY WARRANTY; without even the implied warranty of
576   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
577   GNU General Public License for more details.
578
579   You should have received a copy of the GNU General Public License
580   along with this package; if not, write to the Free Software
581   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
582   MA 02110-1301, USA.
583
584On Debian systems, the complete text of the GNU General
585Public License can be found in /usr/share/common-licenses/GPL.
586
587EOF
588            close(CONF);
589            open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/changelog") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/changelog";
590            print CONF << "EOF";
591PBLOG
592EOF
593            close(CONF);
594            open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/compat") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/compat";
595            print CONF << "EOF";
5964
597EOF
598            close(CONF);
599            open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/$pp.dirs") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/$pp.dirs";
600            print CONF << "EOF";
601EOF
602            close(CONF);
603            open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/$pp.docs") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/$pp.docs";
604            print CONF << "EOF";
605INSTALL
606COPYING
607AUTHORS
608NEWS
609README
610EOF
611            close(CONF);
612            open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/rules") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/rules";
613            print CONF << 'EOF';
614#!/usr/bin/make -f
615# -*- makefile -*-
616# Sample debian/rules that uses debhelper.
617# GNU copyright 1997 to 1999 by Joey Hess.
618#
619# $Id$
620#
621
622# Uncomment this to turn on verbose mode.
623#export DH_VERBOSE=1
624
625# Define package name variable for a one-stop change.
626PACKAGE_NAME = PBPKG
627
628# These are used for cross-compiling and for saving the configure script
629# from having to guess our platform (since we know it already)
630DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
631DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
632
633CFLAGS = -Wall -g
634
635ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
636        CFLAGS += -O0
637else
638        CFLAGS += -O2
639endif
640ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
641        INSTALL_PROGRAM += -s
642endif
643config.status: configure
644        dh_testdir
645
646        # Configure the package.
647        CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr
648 --mandir=\$${prefix}/share/man
649
650# Build both architecture dependent and independent
651build: build-arch build-indep
652
653# Build architecture dependent
654build-arch: build-arch-stamp
655
656build-arch-stamp:  config.status
657        dh_testdir
658
659        # Compile the package.
660        $(MAKE)
661
662        touch build-stamp
663
664# Build architecture independent
665build-indep: build-indep-stamp
666
667build-indep-stamp:  config.status
668        # Nothing to do, the only indep item is the manual which is available as html in original source
669        touch build-indep-stamp
670
671# Clean up
672clean:
673        dh_testdir
674        dh_testroot
675        rm -f build-arch-stamp build-indep-stamp #CONFIGURE-STAMP#
676        # Clean temporary document directory
677        rm -rf debian/doc-temp
678        # Clean up.
679        -$(MAKE) distclean
680        rm -f config.log
681ifneq "$(wildcard /usr/share/misc/config.sub)" ""
682        cp -f /usr/share/misc/config.sub config.sub
683endif
684ifneq "$(wildcard /usr/share/misc/config.guess)" ""
685        cp -f /usr/share/misc/config.guess config.guess
686endif
687
688        dh_clean
689
690# Install architecture dependent and independent
691install: install-arch install-indep
692
693# Install architecture dependent
694install-arch: build-arch
695        dh_testdir
696        dh_testroot
697        dh_clean -k -s
698        dh_installdirs -s
699
700        # Install the package files into build directory:
701        # - start with upstream make install
702        $(MAKE) install prefix=$(CURDIR)/debian/$(PACKAGE_NAME)/usr mandir=$(CURDIR)/debian/$(PACKAGE_NAME)/us
703r/share/man
704        # - copy html manual to temporary location for renaming
705        mkdir -p debian/doc-temp
706        dh_install -s
707
708# Install architecture independent
709install-indep: build-indep
710        dh_testdir
711        dh_testroot
712        dh_clean -k -i
713        dh_installdirs -i
714        dh_install -i
715
716# Must not depend on anything. This is to be called by
717# binary-arch/binary-indep
718# in another 'make' thread.
719binary-common:
720        dh_testdir
721        dh_testroot
722        dh_installchangelogs ChangeLog
723        dh_installdocs
724        dh_installman
725        dh_link
726        dh_strip
727        dh_compress
728        dh_fixperms
729        dh_installdeb
730        dh_shlibdeps
731        dh_gencontrol
732        dh_md5sums
733        dh_builddeb
734
735# Build architecture independant packages using the common target.
736binary-indep: build-indep install-indep
737        $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common
738
739# Build architecture dependant packages using the common target.
740binary-arch: build-arch install-arch
741        $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common
742
743# Build architecture depdendent and independent packages
744binary: binary-arch binary-indep
745.PHONY: clean binary
746
747EOF
748            close(CONF);
749            pb_mkdir_p("$ENV{'PBROOTDIR'}/$pp/rpm") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/rpm";
750            open(CONF,"> $ENV{'PBROOTDIR'}/$pp/rpm/$pp.spec") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/rpm/$pp.spec";
751            print CONF << 'EOF';
752#
753# $Id$
754#
755
756Summary:        bla-bla
757Summary(fr):    french bla-bla
758
759Name:           PBPKG
760Version:        PBVER
761Release:        PBTAGPBSUF
762License:        PBLIC
763Group:          PBGRP
764Url:            PBURL
765Source:         PBSRC
766BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -u -n)
767#Requires:       PBDEP
768
769%description
770PBDESC
771
772%description -l fr
773french desc
774
775%prep
776%setup -q
777
778%build
779%configure
780make %{?_smp_mflags}
781
782%install
783%{__rm} -rf $RPM_BUILD_ROOT
784make DESTDIR=$RPM_BUILD_ROOT install
785
786%clean
787%{__rm} -rf $RPM_BUILD_ROOT
788
789%files
790%defattr(-,root,root)
791%doc ChangeLog
792%doc INSTALL COPYING README AUTHORS NEWS
793
794%changelog
795PBLOG
796
797EOF
798            close(CONF);
799            pb_mkdir_p("$ENV{'PBROOTDIR'}/$pp/pbfilter") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/pbfilter";
800
801            pb_log(0,"\nDo not to forget to commit the pbconf directory in your CMS if needed\n");
802        }
803    } else {
804        die "Unable to open $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb";
805    }
806}
807umask 0022;
808return(\%filteredfiles, \%supfiles, \%defpkgdir, \%extpkgdir);
809}
810
811# Internal mkdir -p function
812sub pb_mkdir_p {
813my @dir = @_;
814my $ret = mkpath(@dir, 0, 0755);
815return($ret);
816}
817
818# Internal rm -rf function
819sub pb_rm_rf {
820my @dir = @_;
821my $ret = rmtree(@dir, 0, 0);
822return($ret);
823}
824
825# Internal system function
826sub pb_system {
827
828my $cmd=shift;
829my $cmt=shift || $cmd;
830
831pb_log(0,"$cmt... ");
832#system("$cmd 2>&1 > $ENV{'PBTMP'}/system.log");
833system($cmd);
834if ($? == -1) {
835    pb_log(0,"failed to execute ($cmd) : $!\n");
836    pb_display_file("$ENV{'PBTMP'}/system.log");
837} elsif ($? & 127) {
838    pb_log(0, "child ($cmd) died with signal ".($? & 127).", ".($? & 128) ? 'with' : 'without'." coredump\n");
839    pb_display_file("$ENV{'PBTMP'}/system.log");
840} elsif ($? == 0) {
841    pb_log(0,"OK\n");
842} else {
843    pb_log(0, "child ($cmd) exited with value ".($? >> 8)."\n");
844    pb_display_file("$ENV{'PBTMP'}/system.log");
845}
846}
847
848sub pb_display_file {
849
850my $file=shift;
851
852return if (not -f $file);
853open(FILE,"$file");
854while (<FILE>) {
855    print $_;
856}
857close(FILE);
858}
859
860# Function which returns a pointer on a table
861# corresponding to a set of values queried in the conf file
862# and test the returned vaue as they need to exist in that case
863sub pb_conf_get {
864
865my @param = @_;
866my @return = pb_conf_get_if(@param);
867
868die "No params found for $ENV{'PBPROJ'}" if (not @return);
869
870foreach my $i (0..$#param) {
871    die "No $param[$i] defined for $ENV{'PBPROJ'}" if (not defined $return[$i]);
872}
873return(@return);
874}
875
876# Function which returns a pointer on a table
877# corresponding to a set of values queried in the conf file
878# Those value may be undef if they do not exist
879sub pb_conf_get_if {
880
881my @param = @_;
882
883# Everything is returned via ptr1
884my @ptr1 = ();
885my @ptr2 = ();
886@ptr1 = pb_conf_read_if("$ENV{'PBETC'}", @param) if (defined $ENV{'PBETC'});
887@ptr2 = pb_conf_read_if("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb", @param) if ((defined $ENV{'PBROOTDIR'}) and (defined $ENV{'PBPROJ'}));
888
889my $p1;
890my $p2;
891
892pb_log(2,"DEBUG: param1: ".Dumper(@ptr1)."\n");
893pb_log(2,"DEBUG: param2: ".Dumper(@ptr2)."\n");
894
895foreach my $i (0..$#param) {
896    $p1 = $ptr1[$i];
897    $p2 = $ptr2[$i];
898    # Always try to take the param from the home dir conf file in priority
899    # in order to mask what could be defined under the CMS to allow for overloading
900    if (not defined $p2) {
901        # No ref in CMS project conf file so use the home dir one.
902        $p1->{$ENV{'PBPROJ'}} = $p1->{'default'} if ((not defined $p1->{$ENV{'PBPROJ'}}) && (defined $p1->{'default'}));
903    } else {
904        # Ref found in CMS project conf file
905        if (not defined $p1) {
906            # No ref in home dir project conf file so use the CMS one.
907            $p2->{$ENV{'PBPROJ'}} = $p2->{'default'} if ((not defined $p2->{$ENV{'PBPROJ'}}) && (defined $p2->{'default'}));
908            $p1 = $p2;
909        } else {
910            # Both are defined - handling the overloading
911            if (not defined $p1->{'default'}) {
912                if (defined $p2->{'default'}) {
913                    $p1->{'default'} = $p2->{'default'};
914                }
915            }
916
917            if (not defined $p1->{$ENV{'PBPROJ'}}) {
918                if (defined $p2->{$ENV{'PBPROJ'}}) {
919                    $p1->{$ENV{'PBPROJ'}} = $p2->{$ENV{'PBPROJ'}} if (defined $p2->{$ENV{'PBPROJ'}});
920                } else {
921                    $p1->{$ENV{'PBPROJ'}} = $p1->{'default'} if (defined $p1->{'default'});
922                }
923            }
924            # Now copy back into p1 all p2 content which doesn't exist in p1
925            # p1 content (local) always has priority over p2 (project)
926            foreach my $k (keys %$p2) {
927                $p1->{$k} = $p2->{$k} if (not defined $p1->{$k});
928            }
929        }
930    }
931    $ptr1[$i] = $p1;
932    pb_log(2,"DEBUG: param ptr1: ".Dumper(@ptr1)."\n");
933}
934return(@ptr1);
935}
936
937# Function which returns a pointer on a hash
938# corresponding to a declaration (arg2) in a conf file (arg1)
939# if that conf file doesn't exist returns undef
940sub pb_conf_read_if {
941
942my $conffile = shift;
943my @param = @_;
944
945open(CONF,$conffile) || return((undef));
946close(CONF);
947return(pb_conf_read($conffile,@param));
948}
949
950# Function which returns a pointer on a hash
951# corresponding to a declaration (arg2) in a conf file (arg1)
952sub pb_conf_read {
953
954my $conffile = shift;
955my @param = @_;
956my $trace;
957my @ptr;
958my %h;
959
960open(CONF,$conffile) || die "Unable to open $conffile";
961while(<CONF>) {
962    if (/^\s*([A-z0-9-_]+)\s+([[A-z0-9-_]+)\s*=\s*(.+)$/) {
963        pb_log(3,"DEBUG: 1:$1 2:$2 3:$3\n");
964        $h{$1}{$2}=$3;
965    }
966}
967close(CONF);
968
969for my $param (@param) {
970    push @ptr,$h{$param};
971}
972return(@ptr);
973}
974
975# Analyze a url passed and return protocol, account, password, server, port, path
976sub pb_get_uri {
977
978my $uri = shift || undef;
979
980pb_log(2,"DEBUG: uri:$uri\n");
981# A URL has the format protocol://[ac@]host[:port][path[?query][#fragment]].
982# Cf man URI
983my ($scheme, $authority, $path, $query, $fragment) =
984         $uri =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?| if (defined $uri);
985my ($account,$host,$port) = $authority =~ m|(?:([^\@]+)\@)?([^:]+)(:(?:[0-9]+))?| if (defined $authority);
986
987$scheme = "" if (not defined $scheme);
988$authority = "" if (not defined $authority);
989$path = "" if (not defined $path);
990$account = "" if (not defined $account);
991$host = "" if (not defined $host);
992$port = "" if (not defined $port);
993
994pb_log(2,"DEBUG: scheme:$scheme ac:$account host:$host port:$port path:$path\n");
995return($scheme, $account, $host, $port, $path);
996}
997
998
999# Setup environment for CMS system for URL passed
1000sub pb_cms_init {
1001
1002my $pbinit = shift || undef;
1003
1004my ($pburl) = pb_conf_get("pburl");
1005pb_log(2,"DEBUG: Project URL of $ENV{'PBPROJ'}: $pburl->{$ENV{'PBPROJ'}}\n");
1006my ($scheme, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
1007
1008my ($pbprojdir) = pb_conf_get_if("pbprojdir");
1009
1010if ((defined $pbprojdir) && (defined $pbprojdir->{$ENV{'PBPROJ'}})) {
1011    $ENV{'PBPROJDIR'} = $pbprojdir->{$ENV{'PBPROJ'}};
1012} else {
1013    $ENV{'PBPROJDIR'} = "$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}";
1014}
1015
1016# Computing the default dir for PBDIR.
1017# what we have is PBPROJDIR so work from that.
1018# Tree identical between PBCONFDIR and PBROOTDIR on one side and
1019# PBPROJDIR and PBDIR on the other side.
1020
1021my $tmp = $ENV{'PBROOTDIR'};
1022$tmp =~ s|^$ENV{'PBCONFDIR'}||;
1023
1024#
1025# Check project cms compliance
1026#
1027pb_cms_compliant(undef,'PBDIR',"$ENV{'PBPROJDIR'}/$tmp",$pburl->{$ENV{'PBPROJ'}},$pbinit);
1028
1029if ($scheme =~ /^svn/) {
1030    # svnversion more precise than svn info
1031    $tmp = `(cd "$ENV{'PBDIR'}" ; svnversion .)`;
1032    chomp($tmp);
1033    $ENV{'PBREVISION'}=$tmp;
1034    $ENV{'PBCMSLOGFILE'}="svn.log";
1035} elsif (($scheme eq "file") || ($scheme eq "ftp") || ($scheme eq "http")) {
1036    $ENV{'PBREVISION'}="flat";
1037    $ENV{'PBCMSLOGFILE'}="flat.log";
1038} elsif ($scheme =~ /^cvs/) {
1039    # Way too slow
1040    #$ENV{'PBREVISION'}=`(cd "$ENV{'PBROOTDIR'}" ; cvs rannotate  -f . 2>&1 | awk '{print \$1}' | grep -E '^[0-9]' | cut -d. -f2 |sort -nu | tail -1)`;
1041    #chomp($ENV{'PBREVISION'});
1042    $ENV{'PBREVISION'}="cvs";
1043    $ENV{'PBCMSLOGFILE'}="cvs.log";
1044    $ENV{'CVS_RSH'} = "ssh" if ($scheme =~ /ssh/);
1045} else {
1046    die "cms $scheme unknown";
1047}
1048
1049return($scheme,$pburl->{$ENV{'PBPROJ'}});
1050}
1051
1052sub pb_get_date {
1053   
1054return(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst());
1055}
1056
1057sub pb_cms_export {
1058
1059my $uri = shift;
1060my $source = shift;
1061my $destdir = shift;
1062my $tmp;
1063my $tmp1;
1064
1065my @date = pb_get_date();
1066# If it's not flat, then we have a real uri as source
1067my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
1068
1069if ($scheme =~ /^svn/) {
1070    if (-d $source) {
1071        $tmp = $destdir;
1072    } else {
1073        $tmp = "$destdir/".basename($source);
1074    }
1075    pb_system("svn export $source $tmp","Exporting $source from SVN to $tmp");
1076} elsif ($scheme eq "dir") {
1077    pb_system("cp -a $path $destdir","Copying $uri from DIR to $destdir");
1078} elsif (($scheme eq "http") || ($scheme eq "ftp")) {
1079    my $f = basename($path);
1080    unlink "$ENV{'PBTMP'}/$f";
1081    if (-x "/usr/bin/wget") {
1082        pb_system("/usr/bin/wget -nv -O $ENV{'PBTMP'}/$f $uri"," ");
1083    } elsif (-x "/usr/bin/curl") {
1084        pb_system("/usr/bin/curl $uri -o $ENV{'PBTMP'}/$f","Downloading $uri with curl to $ENV{'PBTMP'}/$f\n");
1085    } else {
1086        die "Unable to download $uri.\nNo wget/curl available, please install one of those";
1087    }
1088    pb_cms_export("file://$ENV{'PBTMP'}/$f",$source,$destdir);
1089} elsif ($scheme eq "file") {
1090    use File::MimeInfo;
1091    my $mm = mimetype($path);
1092    pb_log(2,"mimetype: $mm\n");
1093    pb_mkdir_p($destdir);
1094
1095    # Check whether the file is well formed
1096    # (containing already a directory with the project-version name)
1097    my ($pbwf) = pb_conf_get_if("pbwf");
1098    if ((defined $pbwf) && (defined $pbwf->{$ENV{'PBPROJ'}})) {
1099        $destdir = dirname($destdir);
1100    }
1101
1102    if ($mm =~ /\/x-bzip-compressed-tar$/) {
1103        # tar+bzip2
1104        pb_system("cd $destdir ; tar xfj $path","Extracting $path in $destdir");
1105    } elsif ($mm =~ /\/x-lzma-compressed-tar$/) {
1106        # tar+lzma
1107        pb_system("cd $destdir ; tar xfY $path","Extracting $path in $destdir");
1108    } elsif ($mm =~ /\/x-compressed-tar$/) {
1109        # tar+gzip
1110        pb_system("cd $destdir ; tar xfz $path","Extracting $path in $destdir");
1111    } elsif ($mm =~ /\/x-tar$/) {
1112        # tar
1113        pb_system("cd $destdir ; tar xf $path","Extracting $path in $destdir");
1114    } elsif ($mm =~ /\/zip$/) {
1115        # zip
1116        pb_system("cd $destdir ; unzip $path","Extracting $path in $destdir");
1117    }
1118} elsif ($scheme =~ /^cvs/) {
1119    # CVS needs a relative path !
1120    my $dir=dirname($destdir);
1121    my $base=basename($destdir);
1122    # CVS also needs a modules name not a dir
1123    #if (-d $source) {
1124        $tmp1 = basename($source);
1125        #} else {
1126        #$tmp1 = dirname($source);
1127        #$tmp1 = basename($tmp1);
1128        #}
1129    my $optcvs = "";
1130
1131    # If we're working on the CVS itself
1132    my $cvstag = basename($ENV{'PBROOTDIR'});
1133    my $cvsopt = "";
1134    if ($cvstag eq "cvs") {
1135        my $pbdate = strftime("%Y-%m-%d %H:%M:%S", @date);
1136        $cvsopt = "-D \"$pbdate\"";
1137    } else {
1138        # we're working on a tag which should be the last part of PBROOTDIR
1139        $cvsopt = "-r $cvstag";
1140    }
1141    pb_system("cd $dir ; cvs -d $account\@$host:$path export $cvsopt -d $base $tmp1","Exporting $tmp1 from $source under CVS to $destdir");
1142} else {
1143    die "cms $scheme unknown";
1144}
1145}
1146
1147
1148sub pb_create_authors {
1149
1150my $authors=shift;
1151my $dest=shift;
1152my $scheme=shift;
1153
1154return if ($authors eq "/dev/null");
1155open(SAUTH,$authors) || die "Unable to open $authors";
1156# Save a potentially existing AUTHORS file and write instead toi AUTHORS.pb
1157my $ext = "";
1158if (-f "$dest/AUTHORS") {
1159    $ext = ".pb";
1160}
1161open(DAUTH,"> $dest/AUTHORS$ext") || die "Unable to create $dest/AUTHORS$ext";
1162print DAUTH "Authors of the project are:\n";
1163print DAUTH "===========================\n";
1164while (<SAUTH>) {
1165    my ($nick,$gcos) = split(/:/);
1166    chomp($gcos);
1167    print DAUTH "$gcos";
1168    if (defined $scheme) {
1169        # Do not give a scheme for flat types
1170        my $endstr="";
1171        if ("$ENV{'PBREVISION'}" ne "flat") {
1172            $endstr = " under $scheme";
1173        }
1174        print DAUTH " ($nick$endstr)\n";
1175    } else {
1176        print DAUTH "\n";
1177    }
1178}
1179close(DAUTH);
1180close(SAUTH);
1181}
1182
1183sub pb_cms_log {
1184
1185my $scheme = shift;
1186my $pkgdir = shift;
1187my $dest = shift;
1188my $chglog = shift;
1189my $authors = shift;
1190
1191pb_create_authors($authors,$dest,$scheme);
1192
1193if ($scheme =~ /^svn/) {
1194    if (! -f "$dest/ChangeLog") {
1195        if (-x "/usr/bin/svn2cl") {
1196            # In case we have no network, just create an empty one before to allow correct build
1197            open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
1198            close(CL);
1199            pb_system("/usr/bin/svn2cl --group-by-day --authors=$authors -i -o $dest/ChangeLog $pkgdir","Generating ChangeLog from SVN with svn2cl");
1200        } else {
1201            # To be written from pbcl
1202            pb_system("svn log -v $pkgdir > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from SVN");
1203        }
1204    }
1205} elsif (($scheme eq "file") || ($scheme eq "dir") || ($scheme eq "http") || ($scheme eq "ftp")) {
1206    if (! -f "$dest/ChangeLog") {
1207        pb_system("echo ChangeLog for $pkgdir > $dest/ChangeLog","Empty ChangeLog file created");
1208    }
1209} elsif ($scheme =~ /^cvs/) {
1210    my $tmp=basename($pkgdir);
1211    # CVS needs a relative path !
1212    if (! -f "$dest/ChangeLog") {
1213        if (-x "/usr/bin/cvs2cl") {
1214            # In case we have no network, just create an empty one before to allow correct build
1215            open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
1216            close(CL);
1217            pb_system("/usr/bin/cvs2cl --group-by-day -U $authors -f $dest/ChangeLog $pkgdir","Generating ChangeLog from CVS with cvs2cl");
1218        } else {
1219            # To be written from pbcl
1220            pb_system("cvs log $tmp > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from CVS");
1221        }
1222    }
1223} else {
1224    die "cms $scheme unknown";
1225}
1226}
1227
1228# This function is only called with a real CMS system
1229sub pb_cms_get_uri {
1230
1231my $scheme = shift;
1232my $dir = shift;
1233
1234my $res = "";
1235my $void = "";
1236
1237if ($scheme =~ /^svn/) {
1238    open(PIPE,"LANGUAGE=C svn info $dir |") || return("");
1239    while (<PIPE>) {
1240        ($void,$res) = split(/^URL:/) if (/^URL:/);
1241    }
1242    $res =~ s/^\s*//;
1243    close(PIPE);
1244    chomp($res);
1245} elsif ($scheme =~ /^cvs/) {
1246    # This path is always the root path of CVS, but we may be below
1247    open(FILE,"$dir/CVS/Root") || die "$dir isn't CVS controlled";
1248    $res = <FILE>;
1249    chomp($res);
1250    close(FILE);
1251    # Find where we are in the tree
1252    my $rdir = $dir;
1253    while ((! -d "$rdir/CVSROOT") && ($rdir ne "/")) {
1254        $rdir = dirname($rdir);
1255    }
1256    die "Unable to find a CVSROOT dir in the parents of $dir" if (! -d "$rdir/CVSROOT");
1257    #compute our place under that root dir - should be a relative path
1258    $dir =~ s|^$rdir||;
1259    my $suffix = "";
1260    $suffix = "$dir" if ($dir ne "");
1261
1262    my $prefix = "";
1263    if ($scheme =~ /ssh/) {
1264        $prefix = "cvs+ssh://";
1265    } else {
1266        $prefix = "cvs://";
1267    }
1268    $res = $prefix.$res.$suffix;
1269} else {
1270    die "cms $scheme unknown";
1271}
1272pb_log(2,"Found CMS info: $res\n");
1273return($res);
1274}
1275
1276sub pb_cms_copy {
1277my $scheme = shift;
1278my $oldurl = shift;
1279my $newurl = shift;
1280
1281if ($scheme =~ /^svn/) {
1282    pb_system("svn copy -m \"Creation of $newurl from $oldurl\" $oldurl $newurl","Copying $oldurl to $newurl ");
1283} elsif ($scheme eq "flat") {
1284} elsif ($scheme =~ /^cvs/) {
1285} else {
1286    die "cms $scheme unknown";
1287}
1288}
1289
1290sub pb_cms_checkout {
1291my $scheme = shift;
1292my $url = shift;
1293my $destination = shift;
1294
1295if ($scheme =~ /^svn/) {
1296    pb_system("svn co $url $destination","Checking out $url to $destination ");
1297} elsif (($scheme eq "ftp") || ($scheme eq "http")) {
1298    return;
1299} elsif ($scheme =~ /^cvs/) {
1300    pb_system("cvs co $url $destination","Checking out $url to $destination ");
1301} else {
1302    die "cms $scheme unknown";
1303}
1304}
1305
1306sub pb_cms_checkin {
1307my $scheme = shift;
1308my $dir = shift;
1309
1310my $ver = basename($dir);
1311if ($scheme =~ /^svn/) {
1312    pb_system("svn ci -m \"Updated to $ver\" $dir","Checking in $dir");
1313    pb_system("svn up $dir","Updating $dir");
1314} elsif ($scheme eq "flat") {
1315} elsif ($scheme =~ /^cvs/) {
1316} else {
1317    die "cms $scheme unknown";
1318}
1319}
1320
1321sub pb_cms_isdiff {
1322my $scheme = shift;
1323
1324if ($scheme =~ /^svn/) {
1325    open(PIPE,"svn diff $ENV{'PBROOTDIR'} |") || die "Unable to get svn diff from $ENV{'PBROOTDIR'}";
1326    my $l = 0;
1327    while (<PIPE>) {
1328        $l++;
1329    }
1330    return($l);
1331} elsif ($scheme eq "flat") {
1332} elsif ($scheme =~ /^cvs/) {
1333} else {
1334    die "cms $scheme unknown";
1335}
1336}
1337
1338# Get all filters to apply
1339# They're cumulative from less specific to most specific
1340# suffix is .pbf
1341
1342sub pb_get_filters {
1343
1344my @ffiles;
1345my ($ffile00, $ffile0, $ffile1, $ffile2, $ffile3);
1346my ($mfile00, $mfile0, $mfile1, $mfile2, $mfile3);
1347my $pbpkg = shift || die "No package specified";
1348my $dtype = shift || "";
1349my $dfam = shift || "";
1350my $ddir = shift || "";
1351my $dver = shift || "";
1352my $ptr = undef; # returned value pointer on the hash of filters
1353my %h;
1354
1355# Global filter files first, then package specificities
1356if (-d "$ENV{'PBROOTDIR'}/pbfilter") {
1357    $mfile00 = "$ENV{'PBROOTDIR'}/pbfilter/all.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/all.pbf");
1358    $mfile0 = "$ENV{'PBROOTDIR'}/pbfilter/$dtype.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$dtype.pbf");
1359    $mfile1 = "$ENV{'PBROOTDIR'}/pbfilter/$dfam.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$dfam.pbf");
1360    $mfile2 = "$ENV{'PBROOTDIR'}/pbfilter/$ddir.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$ddir.pbf");
1361    $mfile3 = "$ENV{'PBROOTDIR'}/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$ddir-$dver.pbf");
1362
1363    push @ffiles,$mfile00 if (defined $mfile00);
1364    push @ffiles,$mfile0 if (defined $mfile0);
1365    push @ffiles,$mfile1 if (defined $mfile1);
1366    push @ffiles,$mfile2 if (defined $mfile2);
1367    push @ffiles,$mfile3 if (defined $mfile3);
1368}
1369
1370if (-d "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter") {
1371    $ffile00 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/all.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/all.pbf");
1372    $ffile0 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dtype.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dtype.pbf");
1373    $ffile1 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dfam.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dfam.pbf");
1374    $ffile2 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir.pbf");
1375    $ffile3 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir-$dver.pbf");
1376
1377    push @ffiles,$ffile00 if (defined $ffile00);
1378    push @ffiles,$ffile0 if (defined $ffile0);
1379    push @ffiles,$ffile1 if (defined $ffile1);
1380    push @ffiles,$ffile2 if (defined $ffile2);
1381    push @ffiles,$ffile3 if (defined $ffile3);
1382}
1383if (@ffiles) {
1384    pb_log(2,"DEBUG ffiles: ".Dumper(\@ffiles)."\n");
1385
1386    foreach my $f (@ffiles) {
1387        open(CONF,$f) || next;
1388        while(<CONF>)  {
1389            if (/^\s*([A-z0-9-_]+)\s+([[A-z0-9-_]+)\s*=\s*(.+)$/) {
1390                $h{$1}{$2}=$3;
1391            }
1392        }
1393        close(CONF);
1394
1395        $ptr = $h{"filter"};
1396        pb_log(2,"DEBUG f:".Dumper($ptr)."\n");
1397    }
1398}
1399return($ptr);
1400}
1401
1402# Function which applies filter on pb build files
1403sub pb_filter_file_pb {
1404
1405my $f=shift;
1406my $ptr=shift;
1407my %filter=%$ptr;
1408my $destfile=shift;
1409my $dtype=shift;
1410my $pbsuf=shift;
1411my $pbproj=shift;
1412my $pbpkg=shift;
1413my $pbver=shift;
1414my $pbtag=shift;
1415my $pbrev=shift;
1416my $pbdate=shift;
1417my $defpkgdir = shift;
1418my $extpkgdir = shift;
1419my $pbpackager = shift;
1420my $chglog = shift || undef;
1421
1422pb_log(2,"DEBUG: From $f to $destfile\n");
1423pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
1424open(DEST,"> $destfile") || die "Unable to create $destfile";
1425open(FILE,"$f") || die "Unable to open $f: $!";
1426while (<FILE>) {
1427    my $line = $_;
1428    foreach my $s (keys %filter) {
1429        # Process single variables
1430        pb_log(2,"DEBUG filter{$s}: $filter{$s}\n");
1431        my $tmp = $filter{$s};
1432        next if (not defined $tmp);
1433        # Expand variables if any single one found
1434        pb_log(2,"DEBUG tmp: $tmp\n");
1435        if ($tmp =~ /\$/) {
1436            eval { $tmp =~ s/(\$\w+)/$1/eeg };
1437        # special case for ChangeLog only for pb
1438        } elsif (($s =~ /^PBLOG$/) && ($line =~ /^PBLOG$/)) {
1439            my $p = $defpkgdir->{$pbpkg};
1440            $p = $extpkgdir->{$pbpkg} if (not defined $p);
1441            pb_changelog($dtype, $pbpkg, $pbver, $pbtag, $pbsuf, $p, \*DEST, $tmp, $chglog);
1442            $tmp = "";
1443        }
1444        $line =~ s|$s|$tmp|;
1445    }
1446    print DEST $line;
1447}
1448close(FILE);
1449close(DEST);
1450}
1451
1452# Function which applies filter on files (external call)
1453sub pb_filter_file_inplace {
1454
1455my $ptr=shift;
1456my %filter=%$ptr;
1457my $destfile=shift;
1458my $pbproj=shift;
1459my $pbpkg=shift;
1460my $pbver=shift;
1461my $pbtag=shift;
1462my $pbrev=shift;
1463my $pbdate=shift;
1464my $pbpackager=shift;
1465
1466my $cp = "$ENV{'PBTMP'}/".basename($destfile);
1467copy($destfile,$cp) || die "Unable to create $cp";
1468
1469pb_filter_file($cp,$ptr,$destfile,$pbproj,$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$pbpackager);
1470unlink $cp;
1471}
1472
1473# Function which applies filter on files (external call)
1474sub pb_filter_file {
1475
1476my $f=shift;
1477my $ptr=shift;
1478my %filter=%$ptr;
1479my $destfile=shift;
1480my $pbproj=shift;
1481my $pbpkg=shift;
1482my $pbver=shift;
1483my $pbtag=shift;
1484my $pbrev=shift;
1485my $pbdate=shift;
1486my $pbpackager=shift;
1487
1488pb_log(2,"DEBUG: From $f to $destfile\n");
1489pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
1490open(DEST,"> $destfile") || die "Unable to create $destfile";
1491open(FILE,"$f") || die "Unable to open $f: $!";
1492while (<FILE>) {
1493    my $line = $_;
1494    foreach my $s (keys %filter) {
1495        # Process single variables
1496        pb_log(2,"DEBUG filter{$s}: $filter{$s}\n");
1497        my $tmp = $filter{$s};
1498        next if (not defined $tmp);
1499        # Expand variables if any single one found
1500        if ($tmp =~ /\$/) {
1501            eval { $tmp =~ s/(\$\w+)/$1/eeg };
1502        }
1503        $line =~ s|$s|$tmp|;
1504    }
1505    print DEST $line;
1506}
1507close(FILE);
1508close(DEST);
1509}
1510
1511sub pb_log_init {
1512
1513$debug = shift || 0;
1514$LOG = shift || \*STDOUT;
1515
1516} 
1517
1518sub pb_log {
1519
1520my $dlevel = shift;
1521my $msg = shift;
1522
1523print $LOG "$msg" if ($dlevel <= $debug);
1524}
1525
1526#
1527# Return the list of packages we are working on
1528#
1529sub pb_get_pkg {
1530
1531my @pkgs = ();
1532my $defpkgdir = shift || undef;
1533my $extpkgdir = shift || undef;
1534
1535# Get packages list
1536if (not defined $ARGV[0]) {
1537    @pkgs = keys %$defpkgdir if (defined $defpkgdir);
1538} elsif ($ARGV[0] =~ /^all$/) {
1539    @pkgs = keys %$defpkgdir if (defined $defpkgdir);
1540    push(@pkgs, keys %$extpkgdir) if (defined $extpkgdir);
1541} else {
1542    @pkgs = @ARGV;
1543}
1544pb_log(0,"Packages: ".join(',',@pkgs)."\n");
1545return(\@pkgs);
1546}
1547
1548#
1549# Check pbconf/project cms compliance
1550#
1551sub pb_cms_compliant {
1552
1553my $param = shift;
1554my $envar = shift;
1555my $defdir = shift;
1556my $uri = shift;
1557my $pbinit = shift;
1558my %pdir;
1559
1560my ($pdir) = pb_conf_get_if($param) if (defined $param);
1561if (defined $pdir) {
1562    %pdir = %$pdir;
1563}
1564
1565
1566if ((defined $pdir) && (%pdir) && (defined $pdir{$ENV{'PBPROJ'}})) {
1567    # That's always the environment variable that will be used
1568    $ENV{$envar} = $pdir{$ENV{'PBPROJ'}};
1569} else {
1570    if (defined $param) {
1571        pb_log(1,"WARNING: no $param defined, using $defdir\n");
1572        pb_log(1,"         Please create a $param reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n");
1573        pb_log(1,"         if you want to use another directory\n");
1574    }
1575    $ENV{$envar} = "$defdir";
1576}
1577
1578# Expand potential env variable in it
1579eval { $ENV{$envar} =~ s/(\$ENV.+\})/$1/eeg };
1580pb_log(2,"$envar: $ENV{$envar}\n");
1581
1582my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
1583
1584if ((! -d "$ENV{$envar}") || (defined $pbinit)) {
1585    if (defined $pbinit) {
1586        pb_mkdir_p("$ENV{$envar}");
1587    } else {
1588        pb_log(1,"Checking out $uri\n");
1589        pb_cms_checkout($scheme,$uri,$ENV{$envar});
1590    }
1591} elsif (($scheme !~ /^cvs/) || ($scheme !~ /^svn/)) {
1592    # Do not compare if it's not a real cms
1593    return;
1594} else {
1595    pb_log(1,"$uri found locally, checking content\n");
1596    my $cmsurl = pb_cms_get_uri($scheme,$ENV{$envar});
1597    my ($scheme2, $account2, $host2, $port2, $path2) = pb_get_uri($cmsurl);
1598    if ($cmsurl ne $uri) {
1599        # The local content doesn't correpond to the repository
1600        pb_log(0,"ERROR: Inconsistency detected:\n");
1601        pb_log(0,"       * $ENV{$envar} refers to $cmsurl but\n");
1602        pb_log(0,"       * $ENV{'PBETC'} refers to $uri\n");
1603        die "Project $ENV{'PBPROJ'} is not Project-Builder compliant.";
1604    } else {
1605        pb_log(1,"Content correct - doing nothing - you may want to update your repository however\n");
1606        # they match - do nothing - there may be local changes
1607    }
1608}
1609}
1610
1611sub pb_changelog {
1612
1613my $dtype = shift;
1614my $pkg = shift;
1615my $pbver = shift;
1616my $pbtag = shift;
1617my $dsuf = shift;
1618my $path = shift;
1619my $OUTPUT = shift;
1620my $doit = shift;
1621my $chglog = shift || undef;
1622
1623my $log = "";
1624
1625# For date handling
1626$ENV{LANG}="C";
1627
1628if ((not (defined $dtype)) || ($dtype eq "") || 
1629        (not (defined $pkg)) || ($pkg eq "") || 
1630        (not (defined $pbver)) || ($pbver eq "") || 
1631        (not (defined $pbtag)) || ($pbtag eq "") || 
1632        (not (defined $dsuf)) || ($dsuf eq "") || 
1633        (not (defined $path)) || ($path eq "") || 
1634        (not (defined $OUTPUT)) || ($OUTPUT eq "") ||
1635        (not (defined $doit)) || ($doit eq "")) {
1636    print $OUTPUT "\n";
1637    return;
1638}
1639
1640if (((not defined $chglog) || (! -f $chglog)) && ($doit eq "yes")) {
1641    #pb_log(2,"No ChangeLog file ($chglog) for $pkg\n";
1642    print $OUTPUT "\n";
1643    return;
1644}
1645
1646my $date;
1647my $ndate;
1648my $n2date;
1649my $ver;
1650my $ver2;
1651my ($pbpackager) = pb_conf_get("pbpackager");
1652
1653if (not defined $pbpackager->{$ENV{'PBPROJ'}}) {
1654    $pbpackager->{$ENV{'PBPROJ'}} = "undefined\@noproject.noorg";
1655}
1656
1657# If we don't need to do it, or don't have it fake something
1658if (((not defined $chglog) || (! -f $chglog)) && ($doit ne "yes")) {
1659    my @date=(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst());
1660    $date = strftime("%Y-%m-%d", @date);
1661    $ndate = UnixDate($date,"%a", "%b", "%d", "%Y");
1662    $n2date = &UnixDate($date,"%a, %d %b %Y %H:%M:%S %z");
1663    if (($dtype eq "rpm") || ($dtype eq "fc")) {
1664        $ver2 = "$pbver-$pbtag$dsuf";
1665        print $OUTPUT "* $ndate $pbpackager->{$ENV{'PBPROJ'}} $ver2\n";
1666        print $OUTPUT "- Updated to $pbver\n";
1667        }
1668    if ($dtype eq "deb") {
1669        print $OUTPUT "$pkg ($pbver) unstable; urgency=low\n";
1670        print $OUTPUT "\n";
1671        print $OUTPUT " -- $pbpackager->{$ENV{'PBPROJ'}}  $n2date\n\n\n";
1672        }
1673    return;
1674}
1675
1676open(INPUT,"$chglog") || die "Unable to open $chglog (read)";
1677
1678# Skip first 4 lines
1679my $tmp = <INPUT>;
1680$tmp = <INPUT>;
1681$tmp = <INPUT>;
1682if ($dtype eq "announce") {
1683    print $OUTPUT $tmp;
1684}
1685$tmp = <INPUT>;
1686if ($dtype eq "announce") {
1687    print $OUTPUT $tmp;
1688}
1689
1690my $first=1;
1691
1692# Handle each block separated by newline
1693while (<INPUT>) {
1694    ($ver, $date) = split(/ /);
1695    $ver =~ s/^v//;
1696    chomp($date);
1697    $date =~ s/\(([0-9-]+)\)/$1/;
1698    #pb_log(2,"**$date**\n";
1699    $ndate = UnixDate($date,"%a", "%b", "%d", "%Y");
1700    $n2date = &UnixDate($date,"%a, %d %b %Y %H:%M:%S %z");
1701    #pb_log(2,"**$ndate**\n";
1702
1703    if (($dtype eq "rpm") || ($dtype eq "fc")) {
1704        if ($ver !~ /-/) {
1705            if ($first eq 1) {
1706                $ver2 = "$ver-$pbtag$dsuf";
1707                $first=0;
1708            } else {
1709                $ver2 = "$ver-1$dsuf";
1710            }
1711        } else {
1712            $ver2 = "$ver$dsuf";
1713        }
1714        print $OUTPUT "* $ndate $pbpackager->{$ENV{'PBPROJ'}} $ver2\n";
1715        print $OUTPUT "- Updated to $ver\n";
1716        }
1717    if ($dtype eq "deb") {
1718        print $OUTPUT "$pkg ($ver) unstable; urgency=low\n";
1719        print $OUTPUT "\n";
1720        }
1721
1722    $tmp = <INPUT>; 
1723    while ($tmp !~ /^$/) {
1724        if ($dtype eq "deb") {
1725            $tmp =~ s/^- //;
1726            print $OUTPUT "  * $tmp";
1727        } elsif ($dtype eq "rpm") {
1728            print $OUTPUT "$tmp";
1729        } else {
1730            print $OUTPUT "$tmp";
1731        }
1732        last if (eof(INPUT));
1733        $tmp = <INPUT>;
1734    }
1735    print $OUTPUT "\n";
1736
1737    if ($dtype eq "deb") {
1738        # Cf: http://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog
1739        print $OUTPUT " -- $pbpackager->{$ENV{'PBPROJ'}}  $n2date\n\n\n";
1740        }
1741
1742    last if (eof(INPUT));
1743    last if ($dtype eq "announce");
1744}
1745close(INPUT);
1746}
17471;
Note: See TracBrowser for help on using the repository browser.