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

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

linuxcoe version cvs now builds. Rest to see tags for cvs

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