#!/usr/bin/perl -w # # Base subroutines for the Project-Builder project # # $Id$ # use strict; use lib qw (lib); use File::Basename; use File::Path; use File::Temp qw /tempdir/; use Data::Dumper; use ProjectBuilder::Changelog qw (pb_changelog); $ENV{'PBETC'} = "$ENV{'HOME'}/.pbrc"; sub pb_env_init { my $proj=shift || undef; my $pbinit=shift || undef; my $ver; my $tag; # For the moment not dynamic my $debug = 0; # Debug level my $LOG = *STDOUT; # Where to log # # Check project name # Could be with env var PBPROJ # or option -p # if not define take the first in conf file # if ((defined $ENV{'PBPROJ'}) && (not (defined $proj))) { $proj = $ENV{'PBPROJ'}; } # # We get the pbrc file for that project # and use its content # my ($pbrc) = pb_conf_read("$ENV{'PBETC'}","pbrc"); print "DEBUG pbrc: ".Dumper($pbrc)."\n" if ($debug >= 1); my %pbrc = %$pbrc; if (not defined $proj) { # Take the first as the default project $proj = (keys %pbrc)[0]; print $LOG "Using $proj as default project as none has been specified\n" if (($debug >= 0) and (defined $proj)); } die "No project defined - use env var PBPROJ or -p proj" if (not (defined $proj)); # # Set delivery directory # if (not defined ($pbrc{$proj})) { die "Please create a pbrc reference for project $proj in $ENV{'PBETC'}\n"; } my $topdir=dirname($pbrc{$proj}); # Expand potential env variable in it eval { $topdir =~ s/(\$ENV.+\})/$1/eeg }; chdir $topdir || die "Unable to change directory to $topdir"; $pbrc{$proj} = $topdir."/pbrc"; $ENV{'PBDESTDIR'}=$topdir."/delivery"; # # Use project configuration file if needed # if (not defined $ENV{'PBROOT'}) { if (-f $pbrc{$proj}) { my ($pbroot) = pb_conf_read($pbrc{$proj},"pbroot"); my %pbroot = %$pbroot; # All lines should point to the same pbroot so take the first $ENV{'PBROOT'} = (values %$pbroot)[0] if (defined $pbroot); print $LOG "Using $ENV{'PBROOT'} as default pbroot from $pbrc{$proj}\n" if (($debug >= 0) and (defined $ENV{'PBROOT'})); } die "No pbroot defined - use env var PBROOT or -r pbroot " if (not defined $ENV{'PBROOT'}); } # # Check pb conf compliance # $ENV{'PBCONF'} = "$ENV{'PBROOT'}/pbconf"; if (defined $pbinit) { print $LOG "Creating $ENV{'PBCONF'} directory\n"; pb_mkdir_p("$ENV{'PBCONF'}"); } die "Project $proj not Project-Builder compliant. Please populate $ENV{'PBCONF'}" if ( not -d "$ENV{'PBCONF'}"); my %version = (); my %defpkgdir = (); my %extpkgdir = (); my %filteredfiles = (); if ((-f "$ENV{'PBCONF'}/$proj.pb") and (not defined $pbinit)) { # List of pkg to build by default (mandatory) # List of additional pkg to build when all is called (optional) # Valid version names (optional) # List of files to filter (optional) my ($defpkgdir, $extpkgdir, $version, $filteredfiles, $pkgv, $pkgt) = pb_conf_read("$ENV{'PBCONF'}/$proj.pb","defpkgdir","extpkgdir","version","filteredfiles","projver","projtag"); print "DEBUG: defpkgdir: ".Dumper($defpkgdir)."\n" if ($debug >= 1); print "DEBUG: extpkgdir: ".Dumper($extpkgdir)."\n" if ($debug >= 1); print "DEBUG: version: ".Dumper($version)."\n" if ($debug >= 1); print "DEBUG: filteredfiles: ".Dumper($filteredfiles)."\n" if ($debug >= 1); die "Unable to find defpkgdir in $ENV{'PBCONF'}/$proj.pb" if (not defined $defpkgdir); # Global %defpkgdir = %$defpkgdir; # Global %extpkgdir = %$extpkgdir if (defined $extpkgdir); %version = %$version if (defined $version); # Global %filteredfiles = %$filteredfiles if (defined $filteredfiles); # # Get global Version/Tag # if (not defined $ENV{'PBVER'}) { if ((defined $pkgv) && (defined $pkgv->{$proj})) { $ENV{'PBVER'}=$pkgv->{$proj}; } else { die "No projver found in $ENV{'PBCONF'}/$proj.pb"; } } die "Invalid version name $ENV{'PBVER'} in $ENV{'PBCONF'}/$proj.pb" if (($ENV{'PBVER'} !~ /[0-9.]+/) && (not defined $version) && ($ENV{'PBVER'} =~ /$version{$proj}/)); if (not defined $ENV{'PBTAG'}) { if ((defined $pkgt) && (defined $pkgt->{$proj})) { $ENV{'PBTAG'}=$pkgt->{$proj}; } else { die "No projtag found in $ENV{'PBCONF'}/$proj.pb"; } } die "Invalid tag name $ENV{'PBTAG'} in $ENV{'PBCONF'}/$proj.pb" if ($ENV{'PBTAG'} !~ /[0-9.]+/); } else { if (defined $pbinit) { open(CONF,"> $ENV{'PBCONF'}/$proj.pb") || die "Unable to create $ENV{'PBCONF'}/$proj.pb"; print CONF << "EOF"; # # Project Builder configuration file # For project $proj # # \$Id\$ # # # Which CMS system is used (Subversion, CVS or tar file content extracted) # #cms $proj = svn #cms $proj = cvs #cms $proj = flat # # Packager label # #packager $proj = "William Porte " # # For delivery to a machine by SSH (potentially the FTP server) # Needs hostname, account and directory # #sshhost $proj = www.$proj.org #sshlogin $proj = bill #sshdir $proj = /$proj/ftp #sshport $proj = 22 # # For Virtual machines management # Naming convention to follow: distribution name (as per ProjectBuilder::Distribution) # followed by '_' and by release number # a .vmtype extension will be added to the resulting string # a QEMU rhel_3 here means that the VM will be named rhel_3.qemu # #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 # # Valid values for vmtype are # qemu, (vmware, xen, ... TBD) #vmtype $proj = qemu # Hash for VM stuff on vmtype #vmntp default = pool.ntp.org # We suppose we can commmunicate with the VM through SSH #vmhost $proj = localhost #vmlogin $proj = pb #vmport $proj = 2222 # Timeout to wait when VM is launched/stopped #vmtmout default = 120 # per VMs needed paramaters #vmopt $proj = -m 384 -daemonize #vmpath $proj = /home/qemu #vmsize $proj = 5G # # Global version/tag for the project # #projver $proj = devel #projtag $proj = 1 # Adapt to your needs: # Optional if you need to overwrite the global values above # #pkgver pkg1 = stable #pkgtag pkg1 = 3 #pkgver nil #pkgtag nil # Hash of default package/package directory #defpkgdir pkg1 = pkg1dir # Hash of additional package/package directory #extpkgdir pkg1-doc = pkg1-docdir # Hash of valid version names #version devel #version stable # List of files per pkg on which to apply filters # Files are mentioned relatively to pbroot/defpkgdir #filteredfiles pkg1 = Makefile.PL #filteredfiles pkg1-doc = configure.in EOF close(CONF); pb_mkdir_p("$ENV{'PBCONF'}/pbfilter") || die "Unable to create $ENV{'PBCONF'}/pbfilter"; open(CONF,"> $ENV{'PBCONF'}/pbfilter/all.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/all.pbf"; print CONF << "EOF"; # # \$Id\$ # # Filter for all files # # PBSRC is replaced by the source package format #filter PBSRC = ftp://ftp.$proj.org/src/%{name}-%{version}.tar.gz # PBVER is replaced by the version (\$pbver in code) #filter PBVER = \$pbver # PBDATE is replaced by the date (\$pbdate in code) #filter PBDATE = \$pbdate # PBLOG is replaced by the changelog if value is yes #filter PBLOG = yes # PBTAG is replaced by the tag (\$pbtag in code) #filter PBTAG = \$pbtag # PBREV is replaced by the revision (\$pbrev in code) #filter PBREV = \$pbrev # PBPKG is replaced by the package name (\$pbpkg in code) #filter PBPKG = \$pbpkg # PBPACKAGER is replaced by the packager name (\$pbpackager in code) #filter PBPACKAGER = \$pbpackager # PBDESC contains the description of the package #filter PBDESC = "Bla-Bla" # PBURL contains the URL of the Web site of the project #filter PBURL = http://www.$proj.org EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pbfilter/rpm.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/rpm.pbf"; print CONF << "EOF"; # # \$Id\$ # # Filter for rpm build # # PBGRP is replaced by the RPM group of apps # Cf: http://fedoraproject.org/wiki/RPMGroups #filter PBGRP = Applications/Archiving # PBDEP is replaced by the list of dependencies #filter PBDEP = # PBSUF is replaced by the package name (\$pbpkg in code) #filter PBSUF = \$pbsuf # PBOBS is replaced by the Obsolete line #filter PBOBS = EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pbfilter/deb.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/deb.pbf"; print CONF << "EOF"; # # \$Id\$ # # Filter for debian build # # PBGRP is replaced by the group of apps #filter PBGRP = utils # PBVER is replaced by the version (\$pbver in code) #filter PBVER = \$pbver # PBDEP is replaced by the list of dependencies #filter PBDEP = # PBSUG is replaced by the list of suggestions #filter PBSUG = # PBREC is replaced by the list of recommandations #filter PBREC = # PBLOG is replaced by the changelog if value is yes #filter PBLOG = yes # PBPKG is replaced by the package name (\$pbpkg in code) #filter PBPKG = \$pbpkg # PBPACKAGER is replaced by the packager name (\$pbpackager in code) #filter PBPACKAGER = \$pbpackager EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pbfilter/md.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/md.pbf"; print CONF << "EOF"; # Specific group for Mandriva for $proj filter PBGRP = Archiving/Backup EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pbfilter/novell.pbf") || die "Unable to create $ENV{'PBCONF'}/pbfilter/novell.pbf"; print CONF << "EOF"; # Specific group for SuSE for $proj filter PBGRP = Productivity/Archiving/Backup EOF close(CONF); pb_mkdir_p("$ENV{'PBCONF'}/pkg1/deb") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb"; open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/control") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/control"; print CONF << "EOF"; Source: PBPKG Section: PBGRP Priority: optional Maintainer: PBPACKAGER Build-Depends: debhelper (>= 4.2.20), PBDEP Standards-Version: 3.6.1 Package: PBPKG Architecture: amd64 i386 ia64 Section: PBGRP Priority: optional Depends: \${shlibs:Depends}, \${misc:Depends}, PBDEP Recommends: PBREC Suggests: PBSUG Description: PBDESC . Homepage: PBURL EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/copyright") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/copyright"; print CONF << "EOF"; This package is debianized by PBPACKAGER `date` The current upstream source was downloaded from ftp://ftp.$proj.org/src/. Upstream Authors: Put their name here Copyright: This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 dated June, 1991. This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/changelog") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/changelog"; print CONF << "EOF"; PBLOG EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/compat") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/compat"; print CONF << "EOF"; 4 EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/pkg1.dirs") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/pkg1.dirs"; print CONF << "EOF"; EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/pkg1.docs") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/pkg1.docs"; print CONF << "EOF"; INSTALL COPYING AUTHORS NEWS README EOF close(CONF); open(CONF,"> $ENV{'PBCONF'}/pkg1/deb/rules") || die "Unable to create $ENV{'PBCONF'}/pkg1/deb/rules"; print CONF << 'EOF'; #!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # GNU copyright 1997 to 1999 by Joey Hess. # # $Id$ # # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 # Define package name variable for a one-stop change. PACKAGE_NAME = PBPKG # These are used for cross-compiling and for saving the configure script # from having to guess our platform (since we know it already) DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) CFLAGS = -Wall -g ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) CFLAGS += -O0 else CFLAGS += -O2 endif ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) INSTALL_PROGRAM += -s endif config.status: configure dh_testdir # Configure the package. CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man # Build both architecture dependent and independent build: build-arch build-indep # Build architecture dependent build-arch: build-arch-stamp build-arch-stamp: config.status dh_testdir # Compile the package. $(MAKE) touch build-stamp # Build architecture independent build-indep: build-indep-stamp build-indep-stamp: config.status # Nothing to do, the only indep item is the manual which is available as html in original source touch build-indep-stamp # Clean up clean: dh_testdir dh_testroot rm -f build-arch-stamp build-indep-stamp #CONFIGURE-STAMP# # Clean temporary document directory rm -rf debian/doc-temp # Clean up. -$(MAKE) distclean rm -f config.log ifneq "$(wildcard /usr/share/misc/config.sub)" "" cp -f /usr/share/misc/config.sub config.sub endif ifneq "$(wildcard /usr/share/misc/config.guess)" "" cp -f /usr/share/misc/config.guess config.guess endif dh_clean # Install architecture dependent and independent install: install-arch install-indep # Install architecture dependent install-arch: build-arch dh_testdir dh_testroot dh_clean -k -s dh_installdirs -s # Install the package files into build directory: # - start with upstream make install $(MAKE) install prefix=$(CURDIR)/debian/$(PACKAGE_NAME)/usr mandir=$(CURDIR)/debian/$(PACKAGE_NAME)/us r/share/man # - copy html manual to temporary location for renaming mkdir -p debian/doc-temp dh_install -s # Install architecture independent install-indep: build-indep dh_testdir dh_testroot dh_clean -k -i dh_installdirs -i dh_install -i # Must not depend on anything. This is to be called by # binary-arch/binary-indep # in another 'make' thread. binary-common: dh_testdir dh_testroot dh_installchangelogs ChangeLog dh_installdocs dh_installman dh_link dh_strip dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb # Build architecture independant packages using the common target. binary-indep: build-indep install-indep $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common # Build architecture dependant packages using the common target. binary-arch: build-arch install-arch $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common # Build architecture depdendent and independent packages binary: binary-arch binary-indep .PHONY: clean binary EOF close(CONF); pb_mkdir_p("$ENV{'PBCONF'}/pkg1/rpm") || die "Unable to create $ENV{'PBCONF'}/pkg1/rpm"; open(CONF,"> $ENV{'PBCONF'}/pkg1/rpm/pkg1.spec") || die "Unable to create $ENV{'PBCONF'}/pkg1/rpm/pkg1.spec"; print CONF << 'EOF'; # # $Id$ # Summary: bla-bla Summary(fr): french bla-bla Name: PBPKG Version: PBVER Release: PBTAGPBSUF License: GPL Group: PBGRP Url: PBURL Source: PBSRC BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -u -n) Requires: PBDEP %description PBDESC %description -l fr french desc %prep %setup -q %build %configure make %{?_smp_mflags} %install %{__rm} -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install %clean %{__rm} -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc ChangeLog %doc INSTALL COPYING README AUTHORS NEWS %changelog PBLOG EOF close(CONF); pb_mkdir_p("$ENV{'PBCONF'}/pkg1/pbfilter") || die "Unable to create $ENV{'PBCONF'}/pkg1/pbfilter"; print "\nDo not to forget to commit the pbconf directory in your CMS if needed\n"; print "After having renamed the pkg1 directory to your package's name \n\n"; } else { die "Unable to open $ENV{'PBCONF'}/$proj.pb"; } } # # Set temp directory # if (not defined $ENV{'TMPDIR'}) { $ENV{'TMPDIR'}="/tmp"; } $ENV{'PBTMP'} = tempdir( "pb.XXXXXXXXXX", DIR => $ENV{'TMPDIR'}, CLEANUP => 1 ); # # Removes all directory existing below the delivery dir # as they are temp dir only # Files stay and have to be cleaned up manually # if (-d $ENV{'PBDESTDIR'}) { opendir(DIR,$ENV{'PBDESTDIR'}) || die "Unable to open directory $ENV{'PBDESTDIR'}: $!"; foreach my $d (readdir(DIR)) { next if ($d =~ /^\./); next if (-f "$ENV{'PBDESTDIR'}/$d"); pb_rm_rf("$ENV{'PBDESTDIR'}/$d") if (-d "$ENV{'PBDESTDIR'}/$d"); } closedir(DIR); } if (! -d "$ENV{'PBDESTDIR'}") { pb_mkdir_p($ENV{'PBDESTDIR'}) || die "Unable to recursively create $ENV{'PBDESTDIR'}"; } # # Set build directory # $ENV{'PBBUILDDIR'}=$topdir."/build"; if (! -d "$ENV{'PBBUILDDIR'}") { pb_mkdir_p($ENV{'PBBUILDDIR'}) || die "Unable to recursively create $ENV{'PBBUILDDIR'}"; } umask 0022; return($proj,$debug,$LOG,\%pbrc, \%filteredfiles, \%defpkgdir, \%extpkgdir); } # Internal mkdir -p function sub pb_mkdir_p { my @dir = @_; my $ret = mkpath(@dir, 0, 0755); return($ret); } # Internal rm -rf function sub pb_rm_rf { my @dir = @_; my $ret = rmtree(@dir, 0, 0); return($ret); } # Internal system function sub pb_system { my $cmd=shift; my $cmt=shift || $cmd; print "$cmt... "; #system("$cmd 2>&1 > $ENV{'PBTMP'}/system.log"); system($cmd); if ($? == -1) { print "failed to execute ($cmd) : $!\n"; pb_display_file("$ENV{'PBTMP'}/system.log"); } elsif ($? & 127) { printf "child ($cmd) died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; pb_display_file("$ENV{'PBTMP'}/system.log"); } elsif ($? == 0) { print "OK\n"; } else { printf "child ($cmd) exited with value %d\n", $? >> 8; pb_display_file("$ENV{'PBTMP'}/system.log"); } } sub pb_display_file { my $file=shift; return if (not -f $file); open(FILE,"$file"); while () { print $_; } close(FILE); } # Function which returns a pointer on a table # corresponding to a set of values queried in the conf file # and test the returned vaue as they need to exist in that case sub pb_conf_get { my @param = @_; # Everything is returned via ptr1 my @ptr1 = pb_conf_read("$ENV{'PBETC'}", @param); my @ptr2 = pb_conf_read("$ENV{'PBCONF'}/$ENV{'PBPROJ'}.pb", @param); my $p1; my $p2; #print "DEBUG: param1: ".Dumper(@ptr1)."\n"; # if ($debug >= 1); #print "DEBUG: param2: ".Dumper(@ptr2)."\n"; # if ($debug >= 1); foreach my $i (0..$#param) { $p1 = $ptr1[$i]; $p2 = $ptr2[$i]; die "No $param[$i] defined for $ENV{'PBPROJ'}" if ((not @ptr1) && (not @ptr2)); die "No $param[$i] defined for $ENV{'PBPROJ'}" if ((not defined $p1) && (not defined $p2)); # Always try to take the param from the home dir conf file in priority # in order to mask what could be defined under the CMS to allow for overloading if (not defined $p2) { # No ref in CMS project conf file so use the home dir one. $p1->{$ENV{'PBPROJ'}} = $p1->{'default'} if (not defined $p1->{$ENV{'PBPROJ'}}); } else { # Ref found in CMS project conf file if (not defined $p1) { # No ref in home dir project conf file so use the CMS one. $p2->{$ENV{'PBPROJ'}} = $p2->{'default'} if (not defined $p2->{$ENV{'PBPROJ'}}); $p1->{$ENV{'PBPROJ'}} = $p2->{$ENV{'PBPROJ'}}; } else { # Both are defined - handling the overloading if (not defined $p1->{'default'}) { if (defined $p2->{'default'}) { $p1->{'default'} = $p2->{'default'}; } } if (not defined $p1->{$ENV{'PBPROJ'}}) { if (defined $p2->{$ENV{'PBPROJ'}}) { $p1->{$ENV{'PBPROJ'}} = $p2->{$ENV{'PBPROJ'}}; } else { $p1->{$ENV{'PBPROJ'}} = $p1->{'default'}; } } } } die "No $param[$i] defined for $ENV{'PBPROJ'}" if (not defined $p1->{$ENV{'PBPROJ'}}); $ptr1[$i] = $p1; #print "DEBUG: param ptr1: ".Dumper(@ptr1)."\n"; # if ($debug >= 1); } return(@ptr1); } # Function which returns a pointer on a hash # corresponding to a declaration (arg2) in a conf file (arg1) sub pb_conf_read { my $conffile = shift; my @param = @_; my $trace; my @ptr; my %h; my $debug = 0; open(CONF,$conffile) || die "Unable to open $conffile"; while() { if (/^\s*([A-z0-9-_]+)\s+([[A-z0-9-_]+)\s*=\s*(.+)$/) { print "DEBUG: 1:$1 2:$2 3:$3\n" if ($debug >= 1); $h{$1}{$2}=$3; } } close(CONF); for my $param (@param) { push @ptr,$h{$param}; } print "DEBUG: h:".Dumper(%h)." param:".Dumper(@param)." ptr:".Dumper(@ptr)."\n" if ($debug >= 1); return(@ptr); } # Setup environment for CMS system sub pb_cms_init { my $proj = shift || undef; my $ret; my ($cms) = pb_conf_get("cms"); if ($cms->{$proj} eq "svn") { $ENV{'PBREVISION'}=`(cd "$ENV{'PBROOT'}" ; svnversion .)`; chomp($ENV{'PBREVISION'}); $ENV{'PBCMSLOGFILE'}="svn.log"; } elsif ($cms->{$proj} eq "flat") { $ENV{'PBREVISION'}="flat"; $ENV{'PBCMSLOGFILE'}="flat.log"; } elsif ($cms->{$proj} eq "cvs") { # Way too slow #$ENV{'PBREVISION'}=`(cd "$ENV{'PBROOT'}" ; cvs rannotate -f . 2>&1 | awk '{print \$1}' | grep -E '^[0-9]' | cut -d. -f2 |sort -nu | tail -1)`; #chomp($ENV{'PBREVISION'}); $ENV{'PBREVISION'}="CVS"; $ENV{'PBCMSLOGFILE'}="cvs.log"; # # Export content if needed # my ($cvsroot,$cvsrsh) = pb_conf_get("cvsroot","cvsrsh"); $ENV{'CVSROOT'} = $cvsroot->{$proj} if (defined $cvsroot->{$proj}); $ENV{'CVSRSH'} = $cvsrsh->{$proj} if (defined $cvsrsh->{$proj}); } else { die "cms $cms->{$proj} unknown"; } return($cms); } sub pb_cms_export { my $cms = shift; my $pbdate = shift || undef; my $source = shift; my $destdir = shift; my $tmp; my $tmp1; if ($cms->{$ENV{'PBPROJ'}} eq "svn") { if (-d $source) { $tmp = $destdir; } else { $tmp = $destdir."/".basename($source); } pb_system("svn export $source $tmp","Exporting $source from SVN to $tmp"); } elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") { if (-d $source) { $tmp = $destdir; } else { $tmp = $destdir."/".basename($source); } pb_system("cp -a $source $tmp","Exporting $source from DIR to $tmp"); } elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") { my $dir=dirname($destdir); my $base=basename($destdir); if (-d $source) { $tmp1 = $source; $tmp1 =~ s|$ENV{'PBROOT'}/||; } else { $tmp1 = dirname($source); $tmp1 =~ s|$ENV{'PBROOT'}/||; $tmp1 = $tmp1."/".basename($source); } # CVS needs a relative path ! pb_system("cd $dir ; cvs export -D \"$pbdate\" -d $base $tmp1","Exporting $source from CVS to $destdir"); } else { die "cms $cms->{$ENV{'PBPROJ'}} unknown"; } } sub pb_create_authors { my $authors=shift; my $dest=shift; my $cms=shift; return if ($authors eq "/dev/null"); open(SAUTH,$authors) || die "Unable to open $authors"; open(DAUTH,"> $dest/AUTHORS") || die "Unable to create $dest/AUTHORS"; print DAUTH "Authors of the project are:\n"; print DAUTH "===========================\n"; while () { my ($nick,$gcos) = split(/:/); chomp($gcos); print DAUTH "$gcos"; if (defined $cms) { print DAUTH " ($nick under $cms)\n"; } else { print DAUTH "\n"; } } close(DAUTH); close(SAUTH); } sub pb_cms_log { my $cms = shift; my $pkgdir = shift; my $dest = shift; my $chglog = shift; my $authors = shift; pb_create_authors($authors,$dest,$cms->{$ENV{'PBPROJ'}}); if ($cms->{$ENV{'PBPROJ'}} eq "svn") { if (! -f "$dest/ChangeLog") { if (-x "/usr/bin/svn2cl") { pb_system("/usr/bin/svn2cl --group-by-day --authors=$authors -i -o $dest/ChangeLog $pkgdir","Generating ChangeLog from SVN"); } else { # To be written from pbcl pb_system("svn log -v $pkgdir > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from SVN"); } } } elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") { if (! -f "$dest/ChangeLog") { pb_system("echo ChangeLog for $pkgdir > $dest/ChangeLog","Empty ChangeLog file created"); } } elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") { my $tmp=basename($pkgdir); # CVS needs a relative path ! if (! -f "$dest/ChangeLog") { if (-x "/usr/bin/cvs2cl") { pb_system("/usr/bin/cvs2cl --group-by-day -U $authors -f $dest/ChangeLog $pkgdir","Generating ChangeLog from CVS"); } else { # To be written from pbcl pb_system("cvs log $tmp > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from CVS"); } } } else { die "cms $cms->{$ENV{'PBPROJ'}} unknown"; } } sub pb_cms_getinfo { my $cms = shift; my $url = ""; my $void = ""; if ($cms->{$ENV{'PBPROJ'}} eq "svn") { open(PIPE,"LANGUAGE=C svn info $ENV{'PBROOT'} |") || die "Unable to get svn info from $ENV{'PBROOT'}"; while () { ($void,$url) = split(/^URL:/) if (/^URL:/); } close(PIPE); chomp($url); } elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") { } elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") { } else { die "cms $cms->{$ENV{'PBPROJ'}} unknown"; } return($url); } sub pb_cms_copy { my $cms = shift; my $oldurl = shift; my $newurl = shift; if ($cms->{$ENV{'PBPROJ'}} eq "svn") { pb_system("svn copy -m \"Creation of $newurl from $oldurl\" $oldurl $newurl","Copying $oldurl to $newurl "); } elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") { } elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") { } else { die "cms $cms->{$ENV{'PBPROJ'}} unknown"; } } sub pb_cms_checkout { my $cms = shift; my $url = shift; my $destination = shift; if ($cms->{$ENV{'PBPROJ'}} eq "svn") { pb_system("svn co $url $destination","Checking $url to $destination "); } elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") { } elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") { } else { die "cms $cms->{$ENV{'PBPROJ'}} unknown"; } } sub pb_cms_checkin { my $cms = shift; my $dir = shift; my $ver = basename($dir); if ($cms->{$ENV{'PBPROJ'}} eq "svn") { pb_system("svn ci -m \"Updated to $ver\" $dir","Checking in $dir"); pb_system("svn up $dir","Updating $dir"); } elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") { } elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") { } else { die "cms $cms->{$ENV{'PBPROJ'}} unknown"; } } sub pb_cms_isdiff { my $cms = shift; if ($cms->{$ENV{'PBPROJ'}} eq "svn") { open(PIPE,"svn diff $ENV{'PBROOT'} |") || die "Unable to get svn diff from $ENV{'PBROOT'}"; my $l = 0; while () { $l++; } return($l); } elsif ($cms->{$ENV{'PBPROJ'}} eq "flat") { } elsif ($cms->{$ENV{'PBPROJ'}} eq "cvs") { } else { die "cms $cms->{$ENV{'PBPROJ'}} unknown"; } } # Get all filters to apply # They're cumulative from less specific to most specific # suffix is .pbf sub pb_get_filters { # For the moment not dynamic my $debug = 0; # Debug level my $LOG = *STDOUT; # Where to log my @ffiles; my ($ffile00, $ffile0, $ffile1, $ffile2, $ffile3); my ($mfile00, $mfile0, $mfile1, $mfile2, $mfile3); my $pbpkg = shift || die "No package specified"; my $dtype = shift || ""; my $dfam = shift || ""; my $ddir = shift || ""; my $dver = shift || ""; my $ptr; # returned value pointer on the hash of filters my %ptr; my %h; # Global filter files first, then package specificities if (-d "$ENV{'PBCONF'}/pbfilter") { $mfile00 = "$ENV{'PBCONF'}/pbfilter/all.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/all.pbf"); $mfile0 = "$ENV{'PBCONF'}/pbfilter/$dtype.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/$dtype.pbf"); $mfile1 = "$ENV{'PBCONF'}/pbfilter/$dfam.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/$dfam.pbf"); $mfile2 = "$ENV{'PBCONF'}/pbfilter/$ddir.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/$ddir.pbf"); $mfile3 = "$ENV{'PBCONF'}/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBCONF'}/pbfilter/$ddir-$dver.pbf"); push @ffiles,$mfile00 if (defined $mfile00); push @ffiles,$mfile0 if (defined $mfile0); push @ffiles,$mfile1 if (defined $mfile1); push @ffiles,$mfile2 if (defined $mfile2); push @ffiles,$mfile3 if (defined $mfile3); } if (-d "$ENV{'PBCONF'}/$pbpkg/pbfilter") { $ffile00 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/all.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/all.pbf"); $ffile0 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dtype.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dtype.pbf"); $ffile1 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dfam.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$dfam.pbf"); $ffile2 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir.pbf"); $ffile3 = "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBCONF'}/$pbpkg/pbfilter/$ddir-$dver.pbf"); push @ffiles,$ffile00 if (defined $ffile00); push @ffiles,$ffile0 if (defined $ffile0); push @ffiles,$ffile1 if (defined $ffile1); push @ffiles,$ffile2 if (defined $ffile2); push @ffiles,$ffile3 if (defined $ffile3); } if (@ffiles) { print $LOG "DEBUG ffiles: ".Dumper(\@ffiles)."\n" if ($debug >= 1); foreach my $f (@ffiles) { open(CONF,$f) || next; while() { if (/^\s*([A-z0-9-_]+)\s+([[A-z0-9-_]+)\s*=\s*(.+)$/) { $h{$1}{$2}=$3; } } close(CONF); $ptr = $h{"filter"}; print $LOG "DEBUG f:".Dumper($ptr)."\n" if ($debug >= 1); } } else { $ptr = { }; } %ptr = %$ptr; return(\%ptr); } # Function which applies filter on pb build files sub pb_filter_file_pb { my $f=shift; my $ptr=shift; my %filter=%$ptr; my $destfile=shift; my $dtype=shift; my $pbsuf=shift; my $pbproj=shift; my $pbpkg=shift; my $pbver=shift; my $pbtag=shift; my $pbrev=shift; my $pbdate=shift; my $defpkgdir = shift; my $extpkgdir = shift; my $pbpackager = shift; my $chglog = shift || undef; # For the moment not dynamic my $debug = 0; # Debug level my $LOG = *STDOUT; # Where to log print $LOG "DEBUG: From $f to $destfile\n" if ($debug >= 1); pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile)); open(DEST,"> $destfile") || die "Unable to create $destfile"; open(FILE,"$f") || die "Unable to open $f: $!"; while () { my $line = $_; foreach my $s (keys %filter) { # Process single variables print $LOG "DEBUG filter{$s}: $filter{$s}\n" if ($debug >= 1); my $tmp = $filter{$s}; next if (not defined $tmp); # Expand variables if any single one found print $LOG "DEBUG tmp: $tmp\n" if ($debug >= 1); if ($tmp =~ /\$/) { eval { $tmp =~ s/(\$\w+)/$1/eeg }; # special case for ChangeLog only for pb } elsif (($s =~ /^PBLOG$/) && ($line =~ /^PBLOG$/)) { my $p = $defpkgdir->{$pbpkg}; $p = $extpkgdir->{$pbpkg} if (not defined $p); pb_changelog($dtype, $pbpkg, $pbver, $pbtag, $pbsuf, $p, \*DEST, $tmp, $chglog); $tmp = ""; } $line =~ s|$s|$tmp|; } print DEST $line; } close(FILE); close(DEST); } # Function which applies filter on files (external call) sub pb_filter_file { my $f=shift; my $ptr=shift; my %filter=%$ptr; my $destfile=shift; my $pbproj=shift; my $pbpkg=shift; my $pbver=shift; my $pbtag=shift; my $pbrev=shift; my $pbdate=shift; my $pbpackager=shift; # For the moment not dynamic my $debug = 0; # Debug level my $LOG = *STDOUT; # Where to log print $LOG "DEBUG: From $f to $destfile\n" if ($debug >= 1); pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile)); open(DEST,"> $destfile") || die "Unable to create $destfile"; open(FILE,"$f") || die "Unable to open $f: $!"; while () { my $line = $_; foreach my $s (keys %filter) { # Process single variables print $LOG "DEBUG filter{$s}: $filter{$s}\n" if ($debug > 1); my $tmp = $filter{$s}; next if (not defined $tmp); # Expand variables if any single one found if ($tmp =~ /\$/) { eval { $tmp =~ s/(\$\w+)/$1/eeg }; } $line =~ s|$s|$tmp|; } print DEST $line; } close(FILE); close(DEST); } 1;