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

Last change on this file since 300 was 300, checked in by bruno, 12 years ago

Adds support for supplemental files in projects (such as init scripts different for different distributions such as in collectl)

File size: 31.3 KB
Line 
1#!/usr/bin/perl -w
2#
3# Base subroutines for the Project-Builder project
4#
5# $Id$
6#
7
8use strict;
9use lib qw (lib);
10use File::Basename;
11use File::Path;
12use File::Temp qw /tempdir/;
13use Data::Dumper;
14
15use ProjectBuilder::Changelog qw (pb_changelog);
16
17$ENV{'PBETC'} = "$ENV{'HOME'}/.pbrc";
18
19sub pb_env_init {
20
21my $proj=shift || undef;
22my $pbinit=shift || undef;
23my $ver;
24my $tag;
25
26# For the moment not dynamic
27my $debug = 0;                  # Debug level
28my $LOG = *STDOUT;              # Where to log
29
30#
31# Check project name
32# Could be with env var PBPROJ
33# or option -p
34# if not define take the first in conf file
35#
36if ((defined $ENV{'PBPROJ'}) &&
37    (not (defined $proj))) {
38    $proj = $ENV{'PBPROJ'};
39}
40
41#
42# We get the pbrc file for that project
43# and use its content
44#
45my ($pbrc) = pb_conf_read("$ENV{'PBETC'}","pbrc");
46print "DEBUG pbrc: ".Dumper($pbrc)."\n" if ($debug >= 1);
47
48my %pbrc = %$pbrc;
49if (not defined $proj) {
50    # Take the first as the default project
51    $proj = (keys %pbrc)[0];
52    print $LOG "Using $proj as default project as none has been specified\n" if (($debug >= 0) and (defined $proj));
53}
54die "No project defined - use env var PBPROJ or -p proj" if (not (defined $proj));
55
56#
57# Set delivery directory
58#
59if (not defined ($pbrc{$proj})) {
60    die "Please create a pbrc reference for project $proj in $ENV{'PBETC'}\n";
61}
62
63my $topdir=dirname($pbrc{$proj});
64# Expand potential env variable in it
65eval { $topdir =~ s/(\$ENV.+\})/$1/eeg };
66chdir $topdir || die "Unable to change directory to $topdir";
67$pbrc{$proj} = $topdir."/pbrc";
68$ENV{'PBDESTDIR'}=$topdir."/delivery";
69
70#
71# Use project configuration file if needed
72#
73if (not defined $ENV{'PBROOT'}) {
74    if (-f $pbrc{$proj}) {
75        my ($pbroot) = pb_conf_read($pbrc{$proj},"pbroot");
76        my %pbroot = %$pbroot;
77        # All lines should point to the same pbroot so take the first
78        $ENV{'PBROOT'} = (values %$pbroot)[0] if (defined $pbroot); 
79        print $LOG "Using $ENV{'PBROOT'} as default pbroot from $pbrc{$proj}\n" if (($debug >= 0) and (defined $ENV{'PBROOT'}));
80    }
81    die "No pbroot defined - use env var PBROOT or -r pbroot " if (not defined $ENV{'PBROOT'});
82}
83
84#
85# Check pb conf compliance
86#
87$ENV{'PBCONF'} = "$ENV{'PBROOT'}/pbconf";
88if (defined $pbinit) {
89    print $LOG "Creating $ENV{'PBCONF'} directory\n";
90    pb_mkdir_p("$ENV{'PBCONF'}");
91    }
92die "Project $proj not Project-Builder compliant. Please populate $ENV{'PBCONF'}" if ( not -d "$ENV{'PBCONF'}");
93
94my %version = ();
95my %defpkgdir = ();
96my %extpkgdir = ();
97my %filteredfiles = ();
98my %supfiles = ();
99
100if ((-f "$ENV{'PBCONF'}/$proj.pb") and (not defined $pbinit)) {
101    # List of pkg to build by default (mandatory)
102    # List of additional pkg to build when all is called (optional)
103    # Valid version names (optional)
104    # List of files to filter (optional)
105    my ($defpkgdir, $extpkgdir, $version, $filteredfiles, $supfiles, $pkgv, $pkgt) = pb_conf_read("$ENV{'PBCONF'}/$proj.pb","defpkgdir","extpkgdir","version","filteredfiles","supfiles","projver","projtag");
106    print "DEBUG: defpkgdir: ".Dumper($defpkgdir)."\n" if ($debug >= 1);
107    print "DEBUG: extpkgdir: ".Dumper($extpkgdir)."\n" if ($debug >= 1);
108    print "DEBUG: version: ".Dumper($version)."\n" if ($debug >= 1);
109    print "DEBUG: filteredfiles: ".Dumper($filteredfiles)."\n" if ($debug >= 1);
110    print "DEBUG: supfiles: ".Dumper($supfiles)."\n" if ($debug >= 1);
111    die "Unable to find defpkgdir in $ENV{'PBCONF'}/$proj.pb" if (not defined $defpkgdir);
112    # Global
113    %defpkgdir = %$defpkgdir;
114    # Global
115    %extpkgdir = %$extpkgdir if (defined $extpkgdir);
116    %version = %$version if (defined $version);
117    # Global
118    %filteredfiles = %$filteredfiles if (defined $filteredfiles);
119    %supfiles = %$supfiles if (defined $supfiles);
120    #
121    # Get global Version/Tag
122    #
123
124    if (not defined $ENV{'PBVER'}) {
125        if ((defined $pkgv) && (defined $pkgv->{$proj})) {
126            $ENV{'PBVER'}=$pkgv->{$proj};
127        } else {
128            die "No projver found in $ENV{'PBCONF'}/$proj.pb";
129        }
130    }
131    die "Invalid version name $ENV{'PBVER'} in $ENV{'PBCONF'}/$proj.pb" if (($ENV{'PBVER'} !~ /[0-9.]+/) && (not defined $version) && ($ENV{'PBVER'} =~ /$version{$proj}/));
132   
133    if (not defined $ENV{'PBTAG'}) {
134        if ((defined $pkgt) && (defined $pkgt->{$proj})) {
135            $ENV{'PBTAG'}=$pkgt->{$proj};
136        } else {
137            die "No projtag found in $ENV{'PBCONF'}/$proj.pb";
138        }
139    }
140    die "Invalid tag name $ENV{'PBTAG'} in $ENV{'PBCONF'}/$proj.pb" if ($ENV{'PBTAG'} !~ /[0-9.]+/);
141} else {
142    if (defined $pbinit) {
143        open(CONF,"> $ENV{'PBCONF'}/$proj.pb") || die "Unable to create $ENV{'PBCONF'}/$proj.pb";
144        print CONF << "EOF";
145#
146# Project Builder configuration file
147# For project $proj
148#
149# \$Id\$
150#
151
152#
153# Which CMS system is used (Subversion, CVS or tar file content extracted)
154#
155#cms $proj = svn
156#cms $proj = cvs
157#cms $proj = flat
158
159#
160# Packager label
161#
162#packager $proj = "William Porte <bill\@$proj.org>"
163#
164
165# For delivery to a machine by SSH (potentially the FTP server)
166# Needs hostname, account and directory
167#
168#sshhost $proj = www.$proj.org
169#sshlogin $proj = bill
170#sshdir $proj = /$proj/ftp
171#sshport $proj = 22
172
173#
174# For Virtual machines management
175# Naming convention to follow: distribution name (as per ProjectBuilder::Distribution)
176# followed by '_' and by release number
177# a .vmtype extension will be added to the resulting string
178# a QEMU rhel_3 here means that the VM will be named rhel_3.qemu
179#
180#vmlist $proj = 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
181
182#
183# Valid values for vmtype are
184# qemu, (vmware, xen, ... TBD)
185#vmtype $proj = qemu
186
187# Hash for VM stuff on vmtype
188#vmntp default = pool.ntp.org
189
190# We suppose we can commmunicate with the VM through SSH
191#vmhost $proj = localhost
192#vmlogin $proj = pb
193#vmport $proj = 2222
194
195# Timeout to wait when VM is launched/stopped
196#vmtmout default = 120
197
198# per VMs needed paramaters
199#vmopt $proj = -m 384 -daemonize
200#vmpath $proj = /home/qemu
201#vmsize $proj = 5G
202
203#
204# Global version/tag for the project
205#
206#projver $proj = devel
207#projtag $proj = 1
208
209# Adapt to your needs:
210# Optional if you need to overwrite the global values above
211#
212#pkgver pkg1 = stable
213#pkgtag pkg1 = 3
214#pkgver nil
215#pkgtag nil
216
217# Hash of default package/package directory
218#defpkgdir pkg1 = pkg1dir
219
220# Hash of additional package/package directory
221#extpkgdir pkg1-doc = pkg1-docdir
222
223# Hash of valid version names
224#version devel
225#version stable
226
227# List of files per pkg on which to apply filters
228# Files are mentioned relatively to pbroot/defpkgdir
229#filteredfiles pkg1 = Makefile.PL
230#filteredfiles pkg1-doc = configure.in
231#supfiles pkg1 = pkg1.init
232EOF
233        close(CONF);
234        pb_mkdir_p("$ENV{'PBCONF'}/pbfilter") || die "Unable to create $ENV{'PBCONF'}/pbfilter";
235        open(CONF,"> $ENV{'PBCONF'}/pbfilter/all.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/all.pbf";
236        print CONF << "EOF";
237#
238# \$Id\$
239#
240# Filter for all files
241#
242# PBSRC is replaced by the source package format
243#filter PBSRC = ftp://ftp.$proj.org/src/%{name}-%{version}.tar.gz
244
245# PBVER is replaced by the version (\$pbver in code)
246#filter PBVER = \$pbver
247
248# PBDATE is replaced by the date (\$pbdate in code)
249#filter PBDATE = \$pbdate
250
251# PBLOG is replaced by the changelog if value is yes
252#filter PBLOG = yes
253
254# PBTAG is replaced by the tag (\$pbtag in code)
255#filter PBTAG = \$pbtag
256
257# PBREV is replaced by the revision (\$pbrev in code)
258#filter PBREV = \$pbrev
259
260# PBPKG is replaced by the package name (\$pbpkg in code)
261#filter PBPKG = \$pbpkg
262
263# PBPACKAGER is replaced by the packager name (\$pbpackager in code)
264#filter PBPACKAGER = \$pbpackager
265
266# PBDESC contains the description of the package
267#filter PBDESC = "Bla-Bla"
268
269# PBURL contains the URL of the Web site of the project
270#filter PBURL = http://www.$proj.org
271EOF
272        close(CONF);
273        open(CONF,"> $ENV{'PBCONF'}/pbfilter/rpm.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/rpm.pbf";
274        print CONF << "EOF";
275#
276# \$Id\$
277#
278# Filter for rpm build
279#
280
281# PBGRP is replaced by the RPM group of apps
282# Cf: http://fedoraproject.org/wiki/RPMGroups
283#filter PBGRP = Applications/Archiving
284
285# PBDEP is replaced by the list of dependencies
286#filter PBDEP =
287
288# PBSUF is replaced by the package name (\$pbpkg in code)
289#filter PBSUF = \$pbsuf
290
291# PBOBS is replaced by the Obsolete line
292#filter PBOBS =
293
294EOF
295        close(CONF);
296        open(CONF,"> $ENV{'PBCONF'}/pbfilter/deb.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/deb.pbf";
297        print CONF << "EOF";
298#
299# \$Id\$
300#
301# Filter for debian build
302#
303# PBGRP is replaced by the group of apps
304#filter PBGRP = utils
305
306# PBVER is replaced by the version (\$pbver in code)
307#filter PBVER = \$pbver
308
309# PBDEP is replaced by the list of dependencies
310#filter PBDEP =
311
312# PBSUG is replaced by the list of suggestions
313#filter PBSUG =
314
315# PBREC is replaced by the list of recommandations
316#filter PBREC =
317
318# PBLOG is replaced by the changelog if value is yes
319#filter PBLOG = yes
320
321# PBPKG is replaced by the package name (\$pbpkg in code)
322#filter PBPKG = \$pbpkg
323
324# PBPACKAGER is replaced by the packager name (\$pbpackager in code)
325#filter PBPACKAGER = \$pbpackager
326
327EOF
328        close(CONF);
329        open(CONF,"> $ENV{'PBCONF'}/pbfilter/md.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/md.pbf";
330        print CONF << "EOF";
331# Specific group for Mandriva for $proj
332filter PBGRP = Archiving/Backup
333EOF
334        close(CONF);
335        open(CONF,"> $ENV{'PBCONF'}/pbfilter/novell.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/novell.pbf";
336        print CONF << "EOF";
337# Specific group for SuSE for $proj
338filter PBGRP = Productivity/Archiving/Backup
339EOF
340        close(CONF);
341        pb_mkdir_p("$ENV{'PBCONF'}/pkg1/deb") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb";
342        open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/control") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/control";
343        print CONF << "EOF";
344Source: PBPKG
345Section: PBGRP
346Priority: optional
347Maintainer: PBPACKAGER
348Build-Depends: debhelper (>= 4.2.20), PBDEP
349Standards-Version: 3.6.1
350
351Package: PBPKG
352Architecture: amd64 i386 ia64
353Section: PBGRP
354Priority: optional
355Depends: \${shlibs:Depends}, \${misc:Depends}, PBDEP
356Recommends: PBREC
357Suggests: PBSUG
358Description:
359 PBDESC
360 .
361 Homepage: PBURL
362
363EOF
364        close(CONF);
365        open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/copyright") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/copyright";
366        print CONF << "EOF";
367This package is debianized by PBPACKAGER
368`date`
369
370The current upstream source was downloaded from
371ftp://ftp.$proj.org/src/.
372
373Upstream Authors: Put their name here
374
375Copyright:
376
377   This package is free software; you can redistribute it and/or modify
378   it under the terms of the GNU General Public License as published by
379   the Free Software Foundation; version 2 dated June, 1991.
380
381   This package is distributed in the hope that it will be useful,
382   but WITHOUT ANY WARRANTY; without even the implied warranty of
383   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
384   GNU General Public License for more details.
385
386   You should have received a copy of the GNU General Public License
387   along with this package; if not, write to the Free Software
388   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
389   MA 02110-1301, USA.
390
391On Debian systems, the complete text of the GNU General
392Public License can be found in /usr/share/common-licenses/GPL.
393
394EOF
395        close(CONF);
396        open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/changelog") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/changelog";
397        print CONF << "EOF";
398PBLOG
399EOF
400        close(CONF);
401        open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/compat") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/compat";
402        print CONF << "EOF";
4034
404EOF
405        close(CONF);
406        open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/pkg1.dirs") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/pkg1.dirs";
407        print CONF << "EOF";
408EOF
409        close(CONF);
410        open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/pkg1.docs") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/pkg1.docs";
411        print CONF << "EOF";
412INSTALL
413COPYING
414AUTHORS
415NEWS
416README
417EOF
418        close(CONF);
419        open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/rules") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/rules";
420        print CONF << 'EOF';
421#!/usr/bin/make -f
422# -*- makefile -*-
423# Sample debian/rules that uses debhelper.
424# GNU copyright 1997 to 1999 by Joey Hess.
425#
426# $Id$
427#
428
429# Uncomment this to turn on verbose mode.
430#export DH_VERBOSE=1
431
432# Define package name variable for a one-stop change.
433PACKAGE_NAME = PBPKG
434
435# These are used for cross-compiling and for saving the configure script
436# from having to guess our platform (since we know it already)
437DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
438DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
439
440CFLAGS = -Wall -g
441
442ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
443        CFLAGS += -O0
444else
445        CFLAGS += -O2
446endif
447ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
448        INSTALL_PROGRAM += -s
449endif
450config.status: configure
451        dh_testdir
452
453        # Configure the package.
454        CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr
455 --mandir=\$${prefix}/share/man
456
457# Build both architecture dependent and independent
458build: build-arch build-indep
459
460# Build architecture dependent
461build-arch: build-arch-stamp
462
463build-arch-stamp:  config.status
464        dh_testdir
465
466        # Compile the package.
467        $(MAKE)
468
469        touch build-stamp
470
471# Build architecture independent
472build-indep: build-indep-stamp
473
474build-indep-stamp:  config.status
475        # Nothing to do, the only indep item is the manual which is available as html in original source
476        touch build-indep-stamp
477
478# Clean up
479clean:
480        dh_testdir
481        dh_testroot
482        rm -f build-arch-stamp build-indep-stamp #CONFIGURE-STAMP#
483        # Clean temporary document directory
484        rm -rf debian/doc-temp
485        # Clean up.
486        -$(MAKE) distclean
487        rm -f config.log
488ifneq "$(wildcard /usr/share/misc/config.sub)" ""
489        cp -f /usr/share/misc/config.sub config.sub
490endif
491ifneq "$(wildcard /usr/share/misc/config.guess)" ""
492        cp -f /usr/share/misc/config.guess config.guess
493endif
494
495        dh_clean
496
497# Install architecture dependent and independent
498install: install-arch install-indep
499
500# Install architecture dependent
501install-arch: build-arch
502        dh_testdir
503        dh_testroot
504        dh_clean -k -s
505        dh_installdirs -s
506
507        # Install the package files into build directory:
508        # - start with upstream make install
509        $(MAKE) install prefix=$(CURDIR)/debian/$(PACKAGE_NAME)/usr mandir=$(CURDIR)/debian/$(PACKAGE_NAME)/us
510r/share/man
511        # - copy html manual to temporary location for renaming
512        mkdir -p debian/doc-temp
513        dh_install -s
514
515# Install architecture independent
516install-indep: build-indep
517        dh_testdir
518        dh_testroot
519        dh_clean -k -i
520        dh_installdirs -i
521        dh_install -i
522
523# Must not depend on anything. This is to be called by
524# binary-arch/binary-indep
525# in another 'make' thread.
526binary-common:
527        dh_testdir
528        dh_testroot
529        dh_installchangelogs ChangeLog
530        dh_installdocs
531        dh_installman
532        dh_link
533        dh_strip
534        dh_compress
535        dh_fixperms
536        dh_installdeb
537        dh_shlibdeps
538        dh_gencontrol
539        dh_md5sums
540        dh_builddeb
541
542# Build architecture independant packages using the common target.
543binary-indep: build-indep install-indep
544        $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common
545
546# Build architecture dependant packages using the common target.
547binary-arch: build-arch install-arch
548        $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common
549
550# Build architecture depdendent and independent packages
551binary: binary-arch binary-indep
552.PHONY: clean binary
553
554EOF
555        close(CONF);
556        pb_mkdir_p("$ENV{'PBCONF'}/pkg1/rpm") || die "Unable to create $ENV{'PBCONF'}/pkg1/rpm";
557        open(CONF,"> $ENV{'PBCONF'}/pkg1/rpm/pkg1.spec") || die "Unable to create $ENV{'PBCONF'}/pkg1/rpm/pkg1.spec";
558        print CONF << 'EOF';
559#
560# $Id$
561#
562
563Summary:        bla-bla
564Summary(fr):    french bla-bla
565
566Name:           PBPKG
567Version:        PBVER
568Release:        PBTAGPBSUF
569License:        GPL
570Group:          PBGRP
571Url:            PBURL
572Source:         PBSRC
573BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -u -n)
574Requires:       PBDEP
575
576%description
577PBDESC
578
579%description -l fr
580french desc
581
582%prep
583%setup -q
584
585%build
586%configure
587make %{?_smp_mflags}
588
589%install
590%{__rm} -rf $RPM_BUILD_ROOT
591make DESTDIR=$RPM_BUILD_ROOT install
592
593%clean
594%{__rm} -rf $RPM_BUILD_ROOT
595
596%files
597%defattr(-,root,root)
598%doc ChangeLog
599%doc INSTALL COPYING README AUTHORS NEWS
600
601%changelog
602PBLOG
603
604EOF
605        close(CONF);
606        pb_mkdir_p("$ENV{'PBCONF'}/pkg1/pbfilter") || die "Unable to create $ENV{'PBCONF'}/pkg1/pbfilter";
607
608        print "\nDo not to forget to commit the pbconf directory in your CMS if needed\n";
609        print "After having renamed the pkg1 directory to your package's name      \n\n";
610    } else {
611        die "Unable to open $ENV{'PBCONF'}/$proj.pb";
612    }
613}
614
615#
616# Set temp directory
617#
618if (not defined $ENV{'TMPDIR'}) {
619    $ENV{'TMPDIR'}="/tmp";
620}
621$ENV{'PBTMP'} = tempdir( "pb.XXXXXXXXXX", DIR => $ENV{'TMPDIR'}, CLEANUP => 1 );
622
623#
624# Removes all directory existing below the delivery dir
625# as they are temp dir only
626# Files stay and have to be cleaned up manually
627#
628if (-d $ENV{'PBDESTDIR'}) {
629    opendir(DIR,$ENV{'PBDESTDIR'}) || die "Unable to open directory $ENV{'PBDESTDIR'}: $!";
630    foreach my $d (readdir(DIR)) {
631        next if ($d =~ /^\./);
632        next if (-f "$ENV{'PBDESTDIR'}/$d");
633        pb_rm_rf("$ENV{'PBDESTDIR'}/$d") if (-d "$ENV{'PBDESTDIR'}/$d");
634    }
635    closedir(DIR);
636}
637if (! -d "$ENV{'PBDESTDIR'}") {
638    pb_mkdir_p($ENV{'PBDESTDIR'}) || die "Unable to recursively create $ENV{'PBDESTDIR'}";
639}
640
641#
642# Set build directory
643#
644$ENV{'PBBUILDDIR'}=$topdir."/build";
645if (! -d "$ENV{'PBBUILDDIR'}") {
646    pb_mkdir_p($ENV{'PBBUILDDIR'}) || die "Unable to recursively create $ENV{'PBBUILDDIR'}";
647}
648
649umask 0022;
650return($proj,$debug,$LOG,\%pbrc, \%filteredfiles, \%supfiles, \%defpkgdir, \%extpkgdir);
651}
652
653# Internal mkdir -p function
654sub pb_mkdir_p {
655my @dir = @_;
656my $ret = mkpath(@dir, 0, 0755);
657return($ret);
658}
659
660# Internal rm -rf function
661sub pb_rm_rf {
662my @dir = @_;
663my $ret = rmtree(@dir, 0, 0);
664return($ret);
665}
666
667# Internal system function
668sub pb_system {
669
670my $cmd=shift;
671my $cmt=shift || $cmd;
672
673print "$cmt... ";
674#system("$cmd 2>&1 > $ENV{'PBTMP'}/system.log");
675system($cmd);
676if ($? == -1) {
677    print "failed to execute ($cmd) : $!\n";
678    pb_display_file("$ENV{'PBTMP'}/system.log");
679} elsif ($? & 127) {
680    printf "child ($cmd) died with signal %d, %s coredump\n", ($? & 127),  ($? & 128) ? 'with' : 'without';
681    pb_display_file("$ENV{'PBTMP'}/system.log");
682} elsif ($? == 0) {
683    print "OK\n";
684} else {
685    printf "child ($cmd) exited with value %d\n", $? >> 8;
686    pb_display_file("$ENV{'PBTMP'}/system.log");
687}
688}
689
690sub pb_display_file {
691
692my $file=shift;
693
694return if (not -f $file);
695open(FILE,"$file");
696while (<FILE>) {
697    print $_;
698}
699close(FILE);
700}
701
702# Function which returns a pointer on a table
703# corresponding to a set of values queried in the conf file
704# and test the returned vaue as they need to exist in that case
705sub pb_conf_get {
706
707my @param = @_;
708
709# Everything is returned via ptr1
710my @ptr1 = pb_conf_read("$ENV{'PBETC'}", @param);
711my @ptr2 = pb_conf_read("$ENV{'PBCONF'}/$ENV{'PBPROJ'}.pb", @param);
712
713my $p1;
714my $p2;
715
716#print "DEBUG: param1: ".Dumper(@ptr1)."\n"; # if ($debug >= 1);
717#print "DEBUG: param2: ".Dumper(@ptr2)."\n"; # if ($debug >= 1);
718
719foreach my $i (0..$#param) {
720    $p1 = $ptr1[$i];
721    $p2 = $ptr2[$i];
722    die "No $param[$i] defined for $ENV{'PBPROJ'}" if ((not @ptr1) && (not @ptr2));
723    die "No $param[$i] defined for $ENV{'PBPROJ'}" if ((not defined $p1) && (not defined $p2));
724    # Always try to take the param from the home dir conf file in priority
725    # in order to mask what could be defined under the CMS to allow for overloading
726    if (not defined $p2) {
727        # No ref in CMS project conf file so use the home dir one.
728        $p1->{$ENV{'PBPROJ'}} = $p1->{'default'} if (not defined $p1->{$ENV{'PBPROJ'}});
729    } else {
730        # Ref found in CMS project conf file
731        if (not defined $p1) {
732            # No ref in home dir project conf file so use the CMS one.
733            $p2->{$ENV{'PBPROJ'}} = $p2->{'default'} if (not defined $p2->{$ENV{'PBPROJ'}});
734            $p1->{$ENV{'PBPROJ'}} = $p2->{$ENV{'PBPROJ'}};
735        } else {
736            # Both are defined - handling the overloading
737            if (not defined $p1->{'default'}) {
738                if (defined $p2->{'default'}) {
739                    $p1->{'default'} = $p2->{'default'};
740                }
741            }
742
743            if (not defined $p1->{$ENV{'PBPROJ'}}) {
744                if (defined $p2->{$ENV{'PBPROJ'}}) {
745                    $p1->{$ENV{'PBPROJ'}} = $p2->{$ENV{'PBPROJ'}};
746                } else {
747                    $p1->{$ENV{'PBPROJ'}} = $p1->{'default'};
748                }
749            }
750        }
751    }
752    die "No $param[$i] defined for $ENV{'PBPROJ'}" if (not defined $p1->{$ENV{'PBPROJ'}});
753    $ptr1[$i] = $p1;
754    #print "DEBUG: param ptr1: ".Dumper(@ptr1)."\n"; # if ($debug >= 1);
755}
756return(@ptr1);
757}
758
759# Function which returns a pointer on a hash
760# corresponding to a declaration (arg2) in a conf file (arg1)
761sub pb_conf_read {
762
763my $conffile = shift;
764my @param = @_;
765my $trace;
766my @ptr;
767my %h;
768
769my $debug = 0;
770
771open(CONF,$conffile) || die "Unable to open $conffile";
772while(<CONF>) {
773    if (/^\s*([A-z0-9-_]+)\s+([[A-z0-9-_]+)\s*=\s*(.+)$/) {
774        print "DEBUG: 1:$1 2:$2 3:$3\n" if ($debug >= 1);
775        $h{$1}{$2}=$3;
776    }
777}
778close(CONF);
779
780for my $param (@param) {
781    push @ptr,$h{$param};
782}
783print "DEBUG: h:".Dumper(%h)." param:".Dumper(@param)." ptr:".Dumper(@ptr)."\n" if ($debug >= 1);
784return(@ptr);
785}
786
787# Setup environment for CMS system
788sub pb_cms_init {
789
790my $proj = shift || undef;
791my $ret;
792
793my ($cms) = pb_conf_get("cms");
794
795if ($cms->{$proj} eq "svn") {
796    $ENV{'PBREVISION'}=`(cd "$ENV{'PBROOT'}" ; svnversion .)`;
797    chomp($ENV{'PBREVISION'});
798    $ENV{'PBCMSLOGFILE'}="svn.log";
799} elsif ($cms->{$proj} eq "flat") {
800    $ENV{'PBREVISION'}="flat";
801    $ENV{'PBCMSLOGFILE'}="flat.log";
802} elsif ($cms->{$proj} eq "cvs") {
803    # Way too slow
804    #$ENV{'PBREVISION'}=`(cd "$ENV{'PBROOT'}" ; cvs rannotate  -f . 2>&1 | awk '{print \$1}' | grep -E '^[0-9]' | cut -d. -f2 |sort -nu | tail -1)`;
805    #chomp($ENV{'PBREVISION'});
806    $ENV{'PBREVISION'}="CVS";
807    $ENV{'PBCMSLOGFILE'}="cvs.log";
808    #
809    # Export content if needed
810    #
811    my ($cvsroot,$cvsrsh) = pb_conf_get("cvsroot","cvsrsh");
812    $ENV{'CVSROOT'} = $cvsroot->{$proj} if (defined $cvsroot->{$proj});
813    $ENV{'CVS_RSH'} = $cvsrsh->{$proj} if (defined $cvsrsh->{$proj});
814} else {
815    die "cms $cms->{$proj} unknown";
816}
817return($cms);
818}
819
820sub pb_cms_export {
821my $cms = shift;
822my $pbdate = shift || undef;
823my $source = shift;
824my $destdir = shift;
825my $tmp;
826my $tmp1;
827
828if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
829    if (-d $source) {
830        $tmp = $destdir;
831    } else {
832        $tmp = $destdir."/".basename($source);
833    }
834    pb_system("svn export $source $tmp","Exporting $source from SVN to $tmp");
835} elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") {
836    if (-d $source) {
837        $tmp = $destdir;
838    } else {
839        $tmp = $destdir."/".basename($source);
840    }
841    pb_system("cp -a $source $tmp","Exporting $source from DIR to $tmp");
842} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
843    my $dir=dirname($destdir);
844    my $base=basename($destdir);
845    if (-d $source) {
846        $tmp1 = $source;
847        $tmp1 =~ s|$ENV{'PBROOT'}/||;
848    } else {
849        $tmp1 = dirname($source);
850        $tmp1 =~ s|$ENV{'PBROOT'}/||;
851        $tmp1 = $tmp1."/".basename($source);
852    }
853    # CVS needs a relative path !
854    pb_system("cd $dir ; cvs export -D \"$pbdate\" -d $base $tmp1","Exporting $source from CVS to $destdir");
855} else {
856    die "cms $cms->{$ENV{'PBPROJ'}} unknown";
857}
858}
859
860
861sub pb_create_authors {
862
863my $authors=shift;
864my $dest=shift;
865my $cms=shift;
866
867return if ($authors eq "/dev/null");
868open(SAUTH,$authors) || die "Unable to open $authors";
869open(DAUTH,"> $dest/AUTHORS") || die "Unable to create $dest/AUTHORS";
870print DAUTH "Authors of the project are:\n";
871print DAUTH "===========================\n";
872while (<SAUTH>) {
873    my ($nick,$gcos) = split(/:/);
874    chomp($gcos);
875    print DAUTH "$gcos";
876    if (defined $cms) {
877        print DAUTH " ($nick under $cms)\n";
878    } else {
879        print DAUTH "\n";
880    }
881}
882close(DAUTH);
883close(SAUTH);
884}
885
886sub pb_cms_log {
887my $cms = shift;
888my $pkgdir = shift;
889my $dest = shift;
890my $chglog = shift;
891my $authors = shift;
892
893pb_create_authors($authors,$dest,$cms->{$ENV{'PBPROJ'}});
894
895if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
896    if (! -f "$dest/ChangeLog") {
897        if (-x "/usr/bin/svn2cl") {
898            pb_system("/usr/bin/svn2cl --group-by-day --authors=$authors -i -o $dest/ChangeLog $pkgdir","Generating ChangeLog from SVN");
899        } else {
900            # To be written from pbcl
901            pb_system("svn log -v $pkgdir > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from SVN");
902        }
903    }
904} elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") {
905    if (! -f "$dest/ChangeLog") {
906        pb_system("echo ChangeLog for $pkgdir > $dest/ChangeLog","Empty ChangeLog file created");
907    }
908} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
909    my $tmp=basename($pkgdir);
910    # CVS needs a relative path !
911    if (! -f "$dest/ChangeLog") {
912        if (-x "/usr/bin/cvs2cl") {
913            pb_system("/usr/bin/cvs2cl --group-by-day -U $authors -f $dest/ChangeLog $pkgdir","Generating ChangeLog from CVS");
914        } else {
915            # To be written from pbcl
916            pb_system("cvs log $tmp > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from CVS");
917        }
918    }
919} else {
920    die "cms $cms->{$ENV{'PBPROJ'}} unknown";
921}
922}
923
924sub pb_cms_getinfo {
925my $cms = shift;
926my $url = "";
927my $void = "";
928
929if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
930    open(PIPE,"LANGUAGE=C svn info $ENV{'PBROOT'} |") || die "Unable to get svn info from $ENV{'PBROOT'}";
931    while (<PIPE>) {
932        ($void,$url) = split(/^URL:/) if (/^URL:/);
933    }
934    close(PIPE);
935    chomp($url);
936} elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") {
937} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
938} else {
939    die "cms $cms->{$ENV{'PBPROJ'}} unknown";
940}
941return($url);
942}
943
944sub pb_cms_copy {
945my $cms = shift;
946my $oldurl = shift;
947my $newurl = shift;
948
949if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
950    pb_system("svn copy -m \"Creation of $newurl from $oldurl\" $oldurl $newurl","Copying $oldurl to $newurl ");
951} elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") {
952} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
953} else {
954    die "cms $cms->{$ENV{'PBPROJ'}} unknown";
955}
956}
957
958sub pb_cms_checkout {
959my $cms = shift;
960my $url = shift;
961my $destination = shift;
962
963if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
964    pb_system("svn co $url $destination","Checking $url to $destination ");
965} elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") {
966} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
967} else {
968    die "cms $cms->{$ENV{'PBPROJ'}} unknown";
969}
970}
971
972sub pb_cms_checkin {
973my $cms = shift;
974my $dir = shift;
975
976my $ver = basename($dir);
977if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
978    pb_system("svn ci -m \"Updated to $ver\" $dir","Checking in $dir");
979    pb_system("svn up $dir","Updating $dir");
980} elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") {
981} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
982} else {
983    die "cms $cms->{$ENV{'PBPROJ'}} unknown";
984}
985}
986
987sub pb_cms_isdiff {
988my $cms = shift;
989
990if ($cms->{$ENV{'PBPROJ'}} eq "svn") {
991    open(PIPE,"svn diff $ENV{'PBROOT'} |") || die "Unable to get svn diff from $ENV{'PBROOT'}";
992    my $l = 0;
993    while (<PIPE>) {
994        $l++;
995    }
996    return($l);
997} elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") {
998} elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") {
999} else {
1000    die "cms $cms->{$ENV{'PBPROJ'}} unknown";
1001}
1002}
1003
1004# Get all filters to apply
1005# They're cumulative from less specific to most specific
1006# suffix is .pbf
1007
1008sub pb_get_filters {
1009
1010# For the moment not dynamic
1011my $debug = 0;                  # Debug level
1012my $LOG = *STDOUT;              # Where to log
1013
1014my @ffiles;
1015my ($ffile00, $ffile0, $ffile1, $ffile2, $ffile3);
1016my ($mfile00, $mfile0, $mfile1, $mfile2, $mfile3);
1017my $pbpkg = shift || die "No package specified";
1018my $dtype = shift || "";
1019my $dfam = shift || "";
1020my $ddir = shift || "";
1021my $dver = shift || "";
1022my $ptr; # returned value pointer on the hash of filters
1023my %ptr;
1024my %h;
1025
1026# Global filter files first, then package specificities
1027if (-d "$ENV{'PBCONF'}/pbfilter") {
1028    $mfile00 = "$ENV{'PBCONF'}/pbfilter/all.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/all.pbf");
1029    $mfile0 = "$ENV{'PBCONF'}/pbfilter/$dtype.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/$dtype.pbf");
1030    $mfile1 = "$ENV{'PBCONF'}/pbfilter/$dfam.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/$dfam.pbf");
1031    $mfile2 = "$ENV{'PBCONF'}/pbfilter/$ddir.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/$ddir.pbf");
1032    $mfile3 = "$ENV{'PBCONF'}/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/$ddir-$dver.pbf");
1033
1034    push @ffiles,$mfile00 if (defined $mfile00);
1035    push @ffiles,$mfile0 if (defined $mfile0);
1036    push @ffiles,$mfile1 if (defined $mfile1);
1037    push @ffiles,$mfile2 if (defined $mfile2);
1038    push @ffiles,$mfile3 if (defined $mfile3);
1039}
1040
1041if (-d "$ENV{'PBCONF'}/$pbpkg/pbfilter") {
1042    $ffile00 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/all.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/all.pbf");
1043    $ffile0 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dtype.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dtype.pbf");
1044    $ffile1 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dfam.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dfam.pbf");
1045    $ffile2 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir.pbf");
1046    $ffile3 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir-$dver.pbf");
1047
1048    push @ffiles,$ffile00 if (defined $ffile00);
1049    push @ffiles,$ffile0 if (defined $ffile0);
1050    push @ffiles,$ffile1 if (defined $ffile1);
1051    push @ffiles,$ffile2 if (defined $ffile2);
1052    push @ffiles,$ffile3 if (defined $ffile3);
1053}
1054if (@ffiles) {
1055    print $LOG "DEBUG ffiles: ".Dumper(\@ffiles)."\n" if ($debug >= 1);
1056
1057    foreach my $f (@ffiles) {
1058        open(CONF,$f) || next;
1059        while(<CONF>)  {
1060            if (/^\s*([A-z0-9-_]+)\s+([[A-z0-9-_]+)\s*=\s*(.+)$/) {
1061                $h{$1}{$2}=$3;
1062            }
1063        }
1064        close(CONF);
1065
1066        $ptr = $h{"filter"};
1067        print $LOG "DEBUG f:".Dumper($ptr)."\n" if ($debug >= 1);
1068    }
1069} else {
1070    $ptr = { };
1071}
1072%ptr = %$ptr;
1073return(\%ptr);
1074}
1075
1076# Function which applies filter on pb build files
1077sub pb_filter_file_pb {
1078
1079my $f=shift;
1080my $ptr=shift;
1081my %filter=%$ptr;
1082my $destfile=shift;
1083my $dtype=shift;
1084my $pbsuf=shift;
1085my $pbproj=shift;
1086my $pbpkg=shift;
1087my $pbver=shift;
1088my $pbtag=shift;
1089my $pbrev=shift;
1090my $pbdate=shift;
1091my $defpkgdir = shift;
1092my $extpkgdir = shift;
1093my $pbpackager = shift;
1094my $chglog = shift || undef;
1095
1096# For the moment not dynamic
1097my $debug = 0;                  # Debug level
1098my $LOG = *STDOUT;              # Where to log
1099
1100print $LOG "DEBUG: From $f to $destfile\n" if ($debug >= 1);
1101pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
1102open(DEST,"> $destfile") || die "Unable to create $destfile";
1103open(FILE,"$f") || die "Unable to open $f: $!";
1104while (<FILE>) {
1105    my $line = $_;
1106    foreach my $s (keys %filter) {
1107        # Process single variables
1108        print $LOG "DEBUG filter{$s}: $filter{$s}\n" if ($debug >= 1);
1109        my $tmp = $filter{$s};
1110        next if (not defined $tmp);
1111        # Expand variables if any single one found
1112        print $LOG "DEBUG tmp: $tmp\n" if ($debug >= 1);
1113        if ($tmp =~ /\$/) {
1114            eval { $tmp =~ s/(\$\w+)/$1/eeg };
1115        # special case for ChangeLog only for pb
1116        } elsif (($s =~ /^PBLOG$/) && ($line =~ /^PBLOG$/)) {
1117            my $p = $defpkgdir->{$pbpkg};
1118            $p = $extpkgdir->{$pbpkg} if (not defined $p);
1119            pb_changelog($dtype, $pbpkg, $pbver, $pbtag, $pbsuf, $p, \*DEST, $tmp, $chglog);
1120            $tmp = "";
1121        }
1122        $line =~ s|$s|$tmp|;
1123    }
1124    print DEST $line;
1125}
1126close(FILE);
1127close(DEST);
1128}
1129
1130# Function which applies filter on files (external call)
1131sub pb_filter_file {
1132
1133my $f=shift;
1134my $ptr=shift;
1135my %filter=%$ptr;
1136my $destfile=shift;
1137my $pbproj=shift;
1138my $pbpkg=shift;
1139my $pbver=shift;
1140my $pbtag=shift;
1141my $pbrev=shift;
1142my $pbdate=shift;
1143my $pbpackager=shift;
1144
1145# For the moment not dynamic
1146my $debug = 0;                  # Debug level
1147my $LOG = *STDOUT;              # Where to log
1148
1149print $LOG "DEBUG: From $f to $destfile\n" if ($debug >= 1);
1150pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
1151open(DEST,"> $destfile") || die "Unable to create $destfile";
1152open(FILE,"$f") || die "Unable to open $f: $!";
1153while (<FILE>) {
1154    my $line = $_;
1155    foreach my $s (keys %filter) {
1156        # Process single variables
1157        print $LOG "DEBUG filter{$s}: $filter{$s}\n" if ($debug > 1);
1158        my $tmp = $filter{$s};
1159        next if (not defined $tmp);
1160        # Expand variables if any single one found
1161        if ($tmp =~ /\$/) {
1162            eval { $tmp =~ s/(\$\w+)/$1/eeg };
1163        }
1164        $line =~ s|$s|$tmp|;
1165    }
1166    print DEST $line;
1167}
1168close(FILE);
1169close(DEST);
1170}
1171
1172
11731;
Note: See TracBrowser for help on using the repository browser.