#!/usr/bin/perl -w # # Base subroutines for the Project-Builder project # # $Id$ # package ProjectBuilder::Base; use strict; use lib qw (lib); use File::Basename; use File::Path; use File::stat; use File::Copy; use File::Temp qw(tempdir); use Data::Dumper; use POSIX qw(strftime); use Time::localtime qw(localtime); use Date::Manip; use English; # Inherit from the "Exporter" module which handles exporting functions. use Exporter; # Export, by default, all the functions into the namespace of # any code which uses this module. our $debug = 0; our $LOG = \*STDOUT; our @ISA = qw(Exporter); our @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_cms_get_pkg pb_get_uri pb_cms_get_uri $debug $LOG); sub pb_env_init { my $proj=shift || undef; my $pbinit=shift || undef; my $action=shift; my $ver; my $tag; $ENV{'PBETC'} = "$ENV{'HOME'}/.pbrc"; # # 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 pbconf file for that project # and use its content # my ($pbconf) = pb_conf_read("$ENV{'PBETC'}","pbconfurl"); pb_log(2,"DEBUG pbconfurl: ".Dumper($pbconf)."\n"); my %pbconf = %$pbconf; if (not defined $proj) { # Take the first as the default project $proj = (keys %pbconf)[0]; if (defined $proj) { pb_log(1,"WARNING: using $proj as default project as none has been specified\n"); pb_log(1," Please either create a pbconfurl reference for project $proj in $ENV{'PBETC'}\n"); pb_log(1," or call pb with the -p project option or use the env var PBPROJ\n"); pb_log(1," if you want to use another project\n"); } } die "No project defined - use env var PBPROJ or -p proj or a pbconfurl entry in $ENV{'PBETC'}" if (not (defined $proj)); # That's always the environment variable that will be used $ENV{'PBPROJ'} = $proj; pb_log(2,"PBPROJ: $ENV{'PBPROJ'}\n"); if (not defined ($pbconf{$ENV{'PBPROJ'}})) { die "Please create a pbconfurl reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n"; } # # Detect the root dir for hosting all the content generated with pb # # Tree will look like this: # # maint pbdefdir PBDEFDIR dev dir (optional) # | | # ------------------------ -------------------- # | | | | # pbproj1 pbproj2 PBPROJ pbproj1 pbproj2 PBPROJDIR # | | # --------------------------------------------- ---------- # * * * | | | * * # tag dev pbconf ... build delivery PBCONFDIR dev tag # | | | PBDESTDIR | # --- ------ pbrc PBBUILDDIR ------- # | | | | | # 1.1 dev tag 1.0 1.1 PBDIR # | # ------- # | | # 1.0 1.1 PBROOTDIR # | # ---------------------------------- # | | | | # pkg1 pbproj1.pb pbfilter pbcl # | # ----------------- # | | | # rpm deb pbfilter # # # (*) By default, if no relocation in .pbrc, dev dir is taken in the maint pbdefdir (when appropriate) # Names under a pbproj and the corresponding pbconf should be similar # my ($pbdefdir) = pb_conf_get_if("pbdefdir"); if (not defined $ENV{'PBDEFDIR'}) { if ((not defined $pbdefdir) || (not defined $pbdefdir->{$ENV{'PBPROJ'}})) { pb_log(1,"WARNING: no pbdefdir defined, using /var/cache\n"); pb_log(1," Please create a pbdefdir reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n"); pb_log(1," if you want to use another directory\n"); $ENV{'PBDEFDIR'} = "/var/cache"; } else { # That's always the environment variable that will be used $ENV{'PBDEFDIR'} = $pbdefdir->{$ENV{'PBPROJ'}}; } } # Expand potential env variable in it eval { $ENV{'PBDEFDIR'} =~ s/(\$ENV.+\})/$1/eeg }; pb_log(2,"PBDEFDIR: $ENV{'PBDEFDIR'}\n"); # # Set delivery directory # $ENV{'PBDESTDIR'}="$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/delivery"; pb_log(2,"PBDESTDIR: $ENV{'PBDESTDIR'}\n"); # # Removes all directory existing below the delivery dir # as they are temp dir only # Files stay and have to be cleaned up manually if needed # those files serves as communication channels between pb phases # Removing them prevents a following phase to detect what has been done before # 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'}="$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/build"; if (! -d "$ENV{'PBBUILDDIR'}") { pb_mkdir_p($ENV{'PBBUILDDIR'}) || die "Unable to recursively create $ENV{'PBBUILDDIR'}"; } pb_log(2,"PBBUILDDIR: $ENV{'PBBUILDDIR'}\n"); # # Set temp directory # if (not defined $ENV{'TMPDIR'}) { $ENV{'TMPDIR'}="/tmp"; } $ENV{'PBTMP'} = tempdir( "pb.XXXXXXXXXX", DIR => $ENV{'TMPDIR'}, CLEANUP => 1 ); pb_log(2,"PBTMP: $ENV{'PBTMP'}\n"); # # The following part is only useful when in cms2build # In VMs/VEs we want to skip that by providing good env vars. # return values in that case are useless # if ($action =~ /^cms2/) { # # Check pbconf cms compliance # pb_cms_compliant("pbconfdir",'PBCONFDIR',"$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}/pbconf",$pbconf{$ENV{'PBPROJ'}},$pbinit); # Check where is our PBROOTDIR (release tag name can't be guessed the first time) # if (not defined $ENV{'PBROOTDIR'}) { if (! -f ("$ENV{'PBDESTDIR'}/pbrc")) { opendir(DIR,$ENV{'PBCONFDIR'}) || die "Unable to open directory $ENV{'PBCONFDIR'}: $!"; my $maxmtime = 0; foreach my $d (readdir(DIR)) { pb_log(3,"Looking at \'$d\'..."); next if ($d =~ /^\./); next if (! -d "$ENV{'PBCONFDIR'}/$d"); my $s = stat("$ENV{'PBCONFDIR'}/$d"); next if (not defined $s); pb_log(3,"KEEP\n"); # Keep the most recent pb_log(2," $s->mtime\n"); if ($s->mtime > $maxmtime) { $ENV{'PBROOTDIR'} = "$ENV{'PBCONFDIR'}/$d"; $maxmtime = $s->mtime; } } closedir(DIR); die "No directory found under $ENV{'PBCONFDIR'}" if (not defined $ENV{'PBROOTDIR'}); pb_log(1,"WARNING: no pbroot defined, using $ENV{'PBROOTDIR'}\n"); pb_log(1," Please use -r release if you want to use another release\n"); } else { my ($pbroot) = pb_conf_read_if("$ENV{'PBDESTDIR'}/pbrc","pbroot"); # That's always the environment variable that will be used die "Please remove inconsistent $ENV{'PBDESTDIR'}/pbrc" if ((not defined $pbroot) || (not defined $pbroot->{$ENV{'PBPROJ'}})); $ENV{'PBROOTDIR'} = $pbroot->{$ENV{'PBPROJ'}}; } } else { # transform in full path if relative $ENV{'PBROOTDIR'} = "$ENV{'PBCONFDIR'}/$ENV{'PBROOTDIR'}" if ($ENV{'PBROOTDIR'} !~ /^\//); pb_mkdir_p($ENV{'PBROOTDIR'}) if (defined $pbinit); die "$ENV{'PBROOTDIR'} is not a directory" if (not -d $ENV{'PBROOTDIR'}); } my %version = (); my %defpkgdir = (); my %extpkgdir = (); my %filteredfiles = (); my %supfiles = (); if ((-f "$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb") and (not defined $pbinit)) { # List of pkg to build by default (mandatory) my ($defpkgdir,$pbpackager, $pkgv, $pkgt) = pb_conf_get("defpkgdir","pbpackager","projver","projtag"); # List of additional pkg to build when all is called (optional) # Valid version names (optional) # List of files to filter (optional) # Project version and tag (optional) my ($extpkgdir, $version, $filteredfiles, $supfiles) = pb_conf_get_if("extpkgdir","version","filteredfiles","supfiles"); pb_log(2,"DEBUG: defpkgdir: ".Dumper($defpkgdir)."\n"); pb_log(2,"DEBUG: extpkgdir: ".Dumper($extpkgdir)."\n"); pb_log(2,"DEBUG: version: ".Dumper($version)."\n"); pb_log(2,"DEBUG: filteredfiles: ".Dumper($filteredfiles)."\n"); pb_log(2,"DEBUG: supfiles: ".Dumper($supfiles)."\n"); # Global %defpkgdir = %$defpkgdir; %extpkgdir = %$extpkgdir if (defined $extpkgdir); %version = %$version if (defined $version); %filteredfiles = %$filteredfiles if (defined $filteredfiles); %supfiles = %$supfiles if (defined $supfiles); # # Get global Version/Tag # if (not defined $ENV{'PBPROJVER'}) { if ((defined $pkgv) && (defined $pkgv->{$ENV{'PBPROJ'}})) { $ENV{'PBPROJVER'}=$pkgv->{$ENV{'PBPROJ'}}; } else { die "No projver found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb"; } } die "Invalid version name $ENV{'PBPROJVER'} in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb" if (($ENV{'PBPROJVER'} !~ /[0-9.]+/) && (not defined $version) && ($ENV{'PBPROJVER'} =~ /$version{$ENV{'PBPROJ'}}/)); if (not defined $ENV{'PBPROJTAG'}) { if ((defined $pkgt) && (defined $pkgt->{$ENV{'PBPROJ'}})) { $ENV{'PBPROJTAG'}=$pkgt->{$ENV{'PBPROJ'}}; } else { die "No projtag found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb"; } } die "Invalid tag name $ENV{'PBPROJTAG'} in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb" if ($ENV{'PBPROJTAG'} !~ /[0-9.]+/); if (not defined $ENV{'PBPACKAGER'}) { if ((defined $pbpackager) && (defined $pbpackager->{$ENV{'PBPROJ'}})) { $ENV{'PBPACKAGER'}=$pbpackager->{$ENV{'PBPROJ'}}; } else { die "No pbpackager found in $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb"; } } } else { if (defined $pbinit) { my $ptr = pb_get_pkg(); my @pkgs = @$ptr; @pkgs = ("pkg1") if (not @pkgs); open(CONF,"> $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb") || die "Unable to create $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb"; print CONF << "EOF"; # # Project Builder configuration file # For project $ENV{'PBPROJ'} # # \$Id\$ # # # What is the project URL # #pburl $ENV{'PBPROJ'} = svn://svn.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel #pburl $ENV{'PBPROJ'} = svn://svn+ssh.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel #pburl $ENV{'PBPROJ'} = cvs://cvs.$ENV{'PBPROJ'}.org/$ENV{'PBPROJ'}/devel #pburl $ENV{'PBPROJ'} = http://www.$ENV{'PBPROJ'}.org/src/$ENV{'PBPROJ'}-devel.tar.gz #pburl $ENV{'PBPROJ'} = ftp://ftp.$ENV{'PBPROJ'}.org/src/$ENV{'PBPROJ'}-devel.tar.gz #pburl $ENV{'PBPROJ'} = file:///src/$ENV{'PBPROJ'}-devel.tar.gz #pburl $ENV{'PBPROJ'} = dir:///src/$ENV{'PBPROJ'}-devel # Check whether project is well formed # (containing already a directory with the project-version name) #pbwf $ENV{'PBPROJ'} = 1 # # Packager label # #pbpackager $ENV{'PBPROJ'} = William Porte # # For delivery to a machine by SSH (potentially the FTP server) # Needs hostname, account and directory # #sshhost $ENV{'PBPROJ'} = www.$ENV{'PBPROJ'}.org #sshlogin $ENV{'PBPROJ'} = bill #sshdir $ENV{'PBPROJ'} = /$ENV{'PBPROJ'}/ftp #sshport $ENV{'PBPROJ'} = 22 # # For Virtual machines management # Naming convention to follow: distribution name (as per ProjectBuilder::Distribution) # followed by '-' and by release number # followed by '-' and by architecture # a .vmtype extension will be added to the resulting string # a QEMU rhel-3-i286 here means that the VM will be named rhel-3-i386.qemu # #vmlist $ENV{'PBPROJ'} = mandrake-10.1-i386,mandrake-10.2-i386,mandriva-2006.0-i386,mandriva-2007.0-i386,mandriva-2007.1-i386,mandriva-2008.0-i386,redhat-7.3-i386,redhat-9-i386,fedora-4-i386,fedora-5-i386,fedora-6-i386,fedora-7-i386,fedora-8-i386,rhel-3-i386,rhel-4-i386,rhel-5-i386,suse-10.0-i386,suse-10.1-i386,suse-10.2-i386,suse-10.3-i386,sles-9-i386,sles-10-i386,gentoo-nover-i386,debian-3.1-i386,debian-4.0-i386,ubuntu-6.06-i386,ubuntu-7.04-i386,ubuntu-7.10-i386,mandriva-2007.0-x86_64,mandriva-2007.1-x86_64,mandriva-2008.0-x86_64,fedora-6-x86_64,fedora-7-x86_64,fedora-8-x86_64,rhel-4-x86_64,rhel-5-x86_64,suse-10.2-x86_64,suse-10.3-x86_64,sles-10-x86_64,gentoo-nover-x86_64,debian-4.0-x86_64,ubuntu-7.04-x86_64,ubuntu-7.10-x86_64 # # Valid values for vmtype are # qemu, (vmware, xen, ... TBD) #vmtype $ENV{'PBPROJ'} = qemu # Hash for VM stuff on vmtype #vmntp default = pool.ntp.org # We suppose we can commmunicate with the VM through SSH #vmhost $ENV{'PBPROJ'} = localhost #vmlogin $ENV{'PBPROJ'} = pb #vmport $ENV{'PBPROJ'} = 2222 # Timeout to wait when VM is launched/stopped #vmtmout default = 120 # per VMs needed paramaters #vmopt $ENV{'PBPROJ'} = -m 384 -daemonize #vmpath $ENV{'PBPROJ'} = /home/qemu #vmsize $ENV{'PBPROJ'} = 5G # # For Virtual environment management # Naming convention to follow: distribution name (as per ProjectBuilder::Distribution) # followed by '-' and by release number # followed by '-' and by architecture # a .vetype extension will be added to the resulting string # a chroot rhel-3-i286 here means that the VE will be named rhel-3-i386.chroot # #velist $ENV{'PBPROJ'} = fedora-7-i386 # VE params #vetype $ENV{'PBPROJ'} = chroot #ventp default = pool.ntp.org #velogin $ENV{'PBPROJ'} = pb #vepath $ENV{'PBPROJ'} = /var/lib/mock #veconf $ENV{'PBPROJ'} = /etc/mock #verebuild $ENV{'PBPROJ'} = false # # Global version/tag for the project # #projver $ENV{'PBPROJ'} = devel #projtag $ENV{'PBPROJ'} = 1 # Hash of valid version names #version $ENV{'PBPROJ'} = devel,stable # Adapt to your needs: # Optional if you need to overwrite the global values above # EOF foreach my $pp (@pkgs) { print CONF << "EOF"; #pkgver $pp = stable #pkgtag $pp = 3 EOF } foreach my $pp (@pkgs) { print CONF << "EOF"; # Hash of default package/package directory #defpkgdir $pp = dir-$pp EOF } print CONF << "EOF"; # Hash of additional package/package directory #extpkgdir minor-pkg = dir-minor-pkg # List of files per pkg on which to apply filters # Files are mentioned relatively to pbroot/defpkgdir EOF foreach my $pp (@pkgs) { print CONF << "EOF"; #filteredfiles $pp = Makefile.PL,configure.in,install.sh,$pp.8 #supfiles $pp = $pp.init EOF } close(CONF); pb_mkdir_p("$ENV{'PBROOTDIR'}/pbfilter") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter"; open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/all.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/all.pbf"; print CONF << "EOF"; # # \$Id\$ # # Filter for all files # # PBSRC is replaced by the source package format #filter PBSRC = ftp://ftp.$ENV{'PBPROJ'}.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.$ENV{'PBPROJ'}.org EOF close(CONF); open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/rpm.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/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 # PBLIC is replaced by the license of the application # Cf: http://fedoraproject.org/wiki/Licensing #filter PBLIC = GPL # PBDEP is replaced by the list of dependencies #filter PBDEP = # PBSUF is replaced by the package suffix (\$pbsuf in code) filter PBSUF = \$pbsuf # PBOBS is replaced by the Obsolete line #filter PBOBS = EOF close(CONF); open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/deb.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/deb.pbf"; print CONF << "EOF"; # # \$Id\$ # # Filter for debian build # # PBGRP is replaced by the group of apps filter PBGRP = utils # PBLIC is replaced by the license of the application # Cf: #filter PBLIC = GPL # 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 = EOF close(CONF); open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/md.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/md.pbf"; print CONF << "EOF"; # Specific group for Mandriva for $ENV{'PBPROJ'} # Cf: http://wiki.mandriva.com/en/Development/Packaging/Groups #filter PBGRP = Archiving/Backup # PBLIC is replaced by the license of the application # Cf: http://wiki.mandriva.com/en/Development/Packaging/Licenses #filter PBLIC = GPL EOF close(CONF); open(CONF,"> $ENV{'PBROOTDIR'}/pbfilter/novell.pbf") || die "Unable to create $ENV{'PBROOTDIR'}/pbfilter/novell.pbf"; print CONF << "EOF"; # Specific group for SuSE for $ENV{'PBPROJ'} # Cf: http://en.opensuse.org/SUSE_Package_Conventions/RPM_Groups #filter PBGRP = Productivity/Archiving/Backup # PBLIC is replaced by the license of the application # Cf: http://en.opensuse.org/Packaging/SUSE_Package_Conventions/RPM_Style#1.6._License_Tag #filter PBLIC = GPL EOF close(CONF); foreach my $pp (@pkgs) { pb_mkdir_p("$ENV{'PBROOTDIR'}/$pp/deb") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb"; open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/control") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/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{'PBROOTDIR'}/$pp/deb/copyright") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/copyright"; print CONF << "EOF"; This package is debianized by PBPACKAGER `date` The current upstream source was downloaded from ftp://ftp.$ENV{'PBPROJ'}.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{'PBROOTDIR'}/$pp/deb/changelog") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/changelog"; print CONF << "EOF"; PBLOG EOF close(CONF); open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/compat") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/compat"; print CONF << "EOF"; 4 EOF close(CONF); open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/$pp.dirs") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/$pp.dirs"; print CONF << "EOF"; EOF close(CONF); open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/$pp.docs") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/deb/$pp.docs"; print CONF << "EOF"; INSTALL COPYING AUTHORS NEWS README EOF close(CONF); open(CONF,"> $ENV{'PBROOTDIR'}/$pp/deb/rules") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/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{'PBROOTDIR'}/$pp/rpm") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/rpm"; open(CONF,"> $ENV{'PBROOTDIR'}/$pp/rpm/$pp.spec") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/rpm/$pp.spec"; print CONF << 'EOF'; # # $Id$ # Summary: bla-bla Summary(fr): french bla-bla Name: PBPKG Version: PBVER Release: PBTAGPBSUF License: PBLIC 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{'PBROOTDIR'}/$pp/pbfilter") || die "Unable to create $ENV{'PBROOTDIR'}/$pp/pbfilter"; pb_log(0,"\nDo not to forget to commit the pbconf directory in your CMS if needed\n"); } } else { die "Unable to open $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb"; } } umask 0022; return(\%filteredfiles, \%supfiles, \%defpkgdir, \%extpkgdir); } else { # Setup the variables from what has been stored at the end of cms2build my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","pbroot"); $ENV{'PBROOTDIR'} = $var->{$ENV{'PBPROJ'}}; ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","projver"); $ENV{'PBPROJVER'} = $var->{$ENV{'PBPROJ'}}; ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","projtag"); $ENV{'PBPROJTAG'} = $var->{$ENV{'PBPROJ'}}; ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","pbpackager"); $ENV{'PBPACKAGER'} = $var->{$ENV{'PBPROJ'}}; return; } } # 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; pb_log(0,"$cmt... "); #system("$cmd 2>&1 > $ENV{'PBTMP'}/system.log"); system($cmd); pb_log(1,"Executing $cmd\n"); my $res = $?; if ($res == -1) { pb_log(0,"failed to execute ($cmd) : $!\n"); pb_display_file("$ENV{'PBTMP'}/system.log"); } elsif ($res & 127) { pb_log(0, "child ($cmd) died with signal ".($? & 127).", ".($? & 128) ? 'with' : 'without'." coredump\n"); pb_display_file("$ENV{'PBTMP'}/system.log"); } elsif ($res == 0) { pb_log(0,"OK\n"); } else { pb_log(0, "child ($cmd) exited with value ".($? >> 8)."\n"); pb_display_file("$ENV{'PBTMP'}/system.log"); } return($res); } 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 = @_; my @return = pb_conf_get_if(@param); die "No params found for $ENV{'PBPROJ'}" if (not @return); foreach my $i (0..$#param) { die "No $param[$i] defined for $ENV{'PBPROJ'}" if (not defined $return[$i]); } return(@return); } # Function which returns a pointer on a table # corresponding to a set of values queried in the conf file # Those value may be undef if they do not exist sub pb_conf_get_if { my @param = @_; # Everything is returned via ptr1 my @ptr1 = (); my @ptr2 = (); @ptr1 = pb_conf_read_if("$ENV{'PBETC'}", @param) if (defined $ENV{'PBETC'}); @ptr2 = pb_conf_read_if("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb", @param) if ((defined $ENV{'PBROOTDIR'}) and (defined $ENV{'PBPROJ'})); my $p1; my $p2; pb_log(2,"DEBUG: pb_conf_get param1: ".Dumper(@ptr1)."\n"); pb_log(2,"DEBUG: pb_conf_get param2: ".Dumper(@ptr2)."\n"); foreach my $i (0..$#param) { $p1 = $ptr1[$i]; $p2 = $ptr2[$i]; # 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'}}) && (defined $p1->{'default'})); } 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'}}) && (defined $p2->{'default'})); $p1 = $p2; } 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'}} if (defined $p2->{$ENV{'PBPROJ'}}); } else { $p1->{$ENV{'PBPROJ'}} = $p1->{'default'} if (defined $p1->{'default'}); } } # Now copy back into p1 all p2 content which doesn't exist in p1 # p1 content (local) always has priority over p2 (project) foreach my $k (keys %$p2) { $p1->{$k} = $p2->{$k} if (not defined $p1->{$k}); } } } $ptr1[$i] = $p1; } pb_log(2,"DEBUG: pb_conf_get param ptr1: ".Dumper(@ptr1)."\n"); return(@ptr1); } # Function which returns a pointer on a hash # corresponding to a declaration (arg2) in a conf file (arg1) # if that conf file doesn't exist returns undef sub pb_conf_read_if { my $conffile = shift; my @param = @_; open(CONF,$conffile) || return((undef)); close(CONF); return(pb_conf_read($conffile,@param)); } # 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; open(CONF,$conffile) || die "Unable to open $conffile"; while() { if (/^\s*([A-z0-9-_]+)\s+([[A-z0-9-_]+)\s*=\s*(.+)$/) { pb_log(3,"DEBUG: 1:$1 2:$2 3:$3\n"); $h{$1}{$2}=$3; } } close(CONF); for my $param (@param) { push @ptr,$h{$param}; } return(@ptr); } # Analyze a url passed and return protocol, account, password, server, port, path sub pb_get_uri { my $uri = shift || undef; pb_log(2,"DEBUG: uri:$uri\n"); # A URL has the format protocol://[ac@]host[:port][path[?query][#fragment]]. # Cf man URI my ($scheme, $authority, $path, $query, $fragment) = $uri =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?| if (defined $uri); my ($account,$host,$port) = $authority =~ m|(?:([^\@]+)\@)?([^:]+)(:(?:[0-9]+))?| if (defined $authority); $scheme = "" if (not defined $scheme); $authority = "" if (not defined $authority); $path = "" if (not defined $path); $account = "" if (not defined $account); $host = "" if (not defined $host); $port = "" if (not defined $port); pb_log(2,"DEBUG: scheme:$scheme ac:$account host:$host port:$port path:$path\n"); return($scheme, $account, $host, $port, $path); } # Setup environment for CMS system for URL passed sub pb_cms_init { my $pbinit = shift || undef; my ($pburl) = pb_conf_get("pburl"); pb_log(2,"DEBUG: Project URL of $ENV{'PBPROJ'}: $pburl->{$ENV{'PBPROJ'}}\n"); my ($scheme, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}}); my ($pbprojdir) = pb_conf_get_if("pbprojdir"); if ((defined $pbprojdir) && (defined $pbprojdir->{$ENV{'PBPROJ'}})) { $ENV{'PBPROJDIR'} = $pbprojdir->{$ENV{'PBPROJ'}}; } else { $ENV{'PBPROJDIR'} = "$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}"; } # Computing the default dir for PBDIR. # what we have is PBPROJDIR so work from that. # Tree identical between PBCONFDIR and PBROOTDIR on one side and # PBPROJDIR and PBDIR on the other side. my $tmp = $ENV{'PBROOTDIR'}; $tmp =~ s|^$ENV{'PBCONFDIR'}||; # # Check project cms compliance # pb_cms_compliant(undef,'PBDIR',"$ENV{'PBPROJDIR'}/$tmp",$pburl->{$ENV{'PBPROJ'}},$pbinit); if ($scheme =~ /^svn/) { # svnversion more precise than svn info $tmp = `(cd "$ENV{'PBDIR'}" ; svnversion .)`; chomp($tmp); $ENV{'PBREVISION'}=$tmp; $ENV{'PBCMSLOGFILE'}="svn.log"; } elsif (($scheme eq "file") || ($scheme eq "ftp") || ($scheme eq "http")) { $ENV{'PBREVISION'}="flat"; $ENV{'PBCMSLOGFILE'}="flat.log"; } elsif ($scheme =~ /^cvs/) { # Way too slow #$ENV{'PBREVISION'}=`(cd "$ENV{'PBROOTDIR'}" ; 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"; $ENV{'CVS_RSH'} = "ssh" if ($scheme =~ /ssh/); } else { die "cms $scheme unknown"; } return($scheme,$pburl->{$ENV{'PBPROJ'}}); } sub pb_get_date { return(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst()); } sub pb_cms_export { my $uri = shift; my $source = shift; my $destdir = shift; my $tmp; my $tmp1; my @date = pb_get_date(); # If it's not flat, then we have a real uri as source my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri); if ($scheme =~ /^svn/) { if (-d $source) { $tmp = $destdir; } else { $tmp = "$destdir/".basename($source); } pb_system("svn export $source $tmp","Exporting $source from SVN to $tmp"); } elsif ($scheme eq "dir") { pb_system("cp -a $path $destdir","Copying $uri from DIR to $destdir"); } elsif (($scheme eq "http") || ($scheme eq "ftp")) { my $f = basename($path); unlink "$ENV{'PBTMP'}/$f"; if (-x "/usr/bin/wget") { pb_system("/usr/bin/wget -nv -O $ENV{'PBTMP'}/$f $uri"," "); } elsif (-x "/usr/bin/curl") { pb_system("/usr/bin/curl $uri -o $ENV{'PBTMP'}/$f","Downloading $uri with curl to $ENV{'PBTMP'}/$f\n"); } else { die "Unable to download $uri.\nNo wget/curl available, please install one of those"; } pb_cms_export("file://$ENV{'PBTMP'}/$f",$source,$destdir); } elsif ($scheme eq "file") { use File::MimeInfo; my $mm = mimetype($path); pb_log(2,"mimetype: $mm\n"); pb_mkdir_p($destdir); # Check whether the file is well formed # (containing already a directory with the project-version name) my ($pbwf) = pb_conf_get_if("pbwf"); if ((defined $pbwf) && (defined $pbwf->{$ENV{'PBPROJ'}})) { $destdir = dirname($destdir); } if ($mm =~ /\/x-bzip-compressed-tar$/) { # tar+bzip2 pb_system("cd $destdir ; tar xfj $path","Extracting $path in $destdir"); } elsif ($mm =~ /\/x-lzma-compressed-tar$/) { # tar+lzma pb_system("cd $destdir ; tar xfY $path","Extracting $path in $destdir"); } elsif ($mm =~ /\/x-compressed-tar$/) { # tar+gzip pb_system("cd $destdir ; tar xfz $path","Extracting $path in $destdir"); } elsif ($mm =~ /\/x-tar$/) { # tar pb_system("cd $destdir ; tar xf $path","Extracting $path in $destdir"); } elsif ($mm =~ /\/zip$/) { # zip pb_system("cd $destdir ; unzip $path","Extracting $path in $destdir"); } } elsif ($scheme =~ /^cvs/) { # CVS needs a relative path ! my $dir=dirname($destdir); my $base=basename($destdir); # CVS also needs a modules name not a dir #if (-d $source) { $tmp1 = basename($source); #} else { #$tmp1 = dirname($source); #$tmp1 = basename($tmp1); #} my $optcvs = ""; # If we're working on the CVS itself my $cvstag = basename($ENV{'PBROOTDIR'}); my $cvsopt = ""; if ($cvstag eq "cvs") { my $pbdate = strftime("%Y-%m-%d %H:%M:%S", @date); $cvsopt = "-D \"$pbdate\""; } else { # we're working on a tag which should be the last part of PBROOTDIR $cvsopt = "-r $cvstag"; } pb_system("cd $dir ; cvs -d $account\@$host:$path export $cvsopt -d $base $tmp1","Exporting $tmp1 from $source under CVS to $destdir"); } else { die "cms $scheme unknown"; } } sub pb_create_authors { my $authors=shift; my $dest=shift; my $scheme=shift; return if ($authors eq "/dev/null"); open(SAUTH,$authors) || die "Unable to open $authors"; # Save a potentially existing AUTHORS file and write instead toi AUTHORS.pb my $ext = ""; if (-f "$dest/AUTHORS") { $ext = ".pb"; } open(DAUTH,"> $dest/AUTHORS$ext") || die "Unable to create $dest/AUTHORS$ext"; print DAUTH "Authors of the project are:\n"; print DAUTH "===========================\n"; while () { my ($nick,$gcos) = split(/:/); chomp($gcos); print DAUTH "$gcos"; if (defined $scheme) { # Do not give a scheme for flat types my $endstr=""; if ("$ENV{'PBREVISION'}" ne "flat") { $endstr = " under $scheme"; } print DAUTH " ($nick$endstr)\n"; } else { print DAUTH "\n"; } } close(DAUTH); close(SAUTH); } sub pb_cms_log { my $scheme = shift; my $pkgdir = shift; my $dest = shift; my $chglog = shift; my $authors = shift; pb_create_authors($authors,$dest,$scheme); if ($scheme =~ /^svn/) { if (! -f "$dest/ChangeLog") { if (-x "/usr/bin/svn2cl") { # In case we have no network, just create an empty one before to allow correct build open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog"; close(CL); pb_system("/usr/bin/svn2cl --group-by-day --authors=$authors -i -o $dest/ChangeLog $pkgdir","Generating ChangeLog from SVN with svn2cl"); } else { # To be written from pbcl pb_system("svn log -v $pkgdir > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from SVN"); } } } elsif (($scheme eq "file") || ($scheme eq "dir") || ($scheme eq "http") || ($scheme eq "ftp")) { if (! -f "$dest/ChangeLog") { pb_system("echo ChangeLog for $pkgdir > $dest/ChangeLog","Empty ChangeLog file created"); } } elsif ($scheme =~ /^cvs/) { my $tmp=basename($pkgdir); # CVS needs a relative path ! if (! -f "$dest/ChangeLog") { if (-x "/usr/bin/cvs2cl") { # In case we have no network, just create an empty one before to allow correct build open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog"; close(CL); pb_system("/usr/bin/cvs2cl --group-by-day -U $authors -f $dest/ChangeLog $pkgdir","Generating ChangeLog from CVS with cvs2cl"); } else { # To be written from pbcl pb_system("cvs log $tmp > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from CVS"); } } } else { die "cms $scheme unknown"; } } # This function is only called with a real CMS system sub pb_cms_get_uri { my $scheme = shift; my $dir = shift; my $res = ""; my $void = ""; if ($scheme =~ /^svn/) { open(PIPE,"LANGUAGE=C svn info $dir |") || return(""); while () { ($void,$res) = split(/^URL:/) if (/^URL:/); } $res =~ s/^\s*//; close(PIPE); chomp($res); } elsif ($scheme =~ /^cvs/) { # This path is always the root path of CVS, but we may be below open(FILE,"$dir/CVS/Root") || die "$dir isn't CVS controlled"; $res = ; chomp($res); close(FILE); # Find where we are in the tree my $rdir = $dir; while ((! -d "$rdir/CVSROOT") && ($rdir ne "/")) { $rdir = dirname($rdir); } die "Unable to find a CVSROOT dir in the parents of $dir" if (! -d "$rdir/CVSROOT"); #compute our place under that root dir - should be a relative path $dir =~ s|^$rdir||; my $suffix = ""; $suffix = "$dir" if ($dir ne ""); my $prefix = ""; if ($scheme =~ /ssh/) { $prefix = "cvs+ssh://"; } else { $prefix = "cvs://"; } $res = $prefix.$res.$suffix; } else { die "cms $scheme unknown"; } pb_log(2,"Found CMS info: $res\n"); return($res); } sub pb_cms_copy { my $scheme = shift; my $oldurl = shift; my $newurl = shift; if ($scheme =~ /^svn/) { pb_system("svn copy -m \"Creation of $newurl from $oldurl\" $oldurl $newurl","Copying $oldurl to $newurl "); } elsif ($scheme eq "flat") { } elsif ($scheme =~ /^cvs/) { } else { die "cms $scheme unknown"; } } sub pb_cms_checkout { my $scheme = shift; my $url = shift; my $destination = shift; if ($scheme =~ /^svn/) { pb_system("svn co $url $destination","Checking out $url to $destination "); } elsif (($scheme eq "ftp") || ($scheme eq "http")) { return; } elsif ($scheme =~ /^cvs/) { pb_system("cvs co $url $destination","Checking out $url to $destination "); } else { die "cms $scheme unknown"; } } sub pb_cms_checkin { my $scheme = shift; my $dir = shift; my $ver = basename($dir); if ($scheme =~ /^svn/) { pb_system("svn ci -m \"Updated to $ver\" $dir","Checking in $dir"); pb_system("svn up $dir","Updating $dir"); } elsif ($scheme eq "flat") { } elsif ($scheme =~ /^cvs/) { } else { die "cms $scheme unknown"; } } sub pb_cms_isdiff { my $scheme = shift; if ($scheme =~ /^svn/) { open(PIPE,"svn diff $ENV{'PBROOTDIR'} |") || die "Unable to get svn diff from $ENV{'PBROOTDIR'}"; my $l = 0; while () { $l++; } return($l); } elsif ($scheme eq "flat") { } elsif ($scheme =~ /^cvs/) { } else { die "cms $scheme unknown"; } } # Get all filters to apply # They're cumulative from less specific to most specific # suffix is .pbf sub pb_get_filters { 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 = undef; # returned value pointer on the hash of filters my %h; # Global filter files first, then package specificities if (-d "$ENV{'PBROOTDIR'}/pbfilter") { $mfile00 = "$ENV{'PBROOTDIR'}/pbfilter/all.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/all.pbf"); $mfile0 = "$ENV{'PBROOTDIR'}/pbfilter/$dtype.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$dtype.pbf"); $mfile1 = "$ENV{'PBROOTDIR'}/pbfilter/$dfam.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$dfam.pbf"); $mfile2 = "$ENV{'PBROOTDIR'}/pbfilter/$ddir.pbf" if (-f "$ENV{'PBROOTDIR'}/pbfilter/$ddir.pbf"); $mfile3 = "$ENV{'PBROOTDIR'}/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBROOTDIR'}/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{'PBROOTDIR'}/$pbpkg/pbfilter") { $ffile00 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/all.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/all.pbf"); $ffile0 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dtype.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dtype.pbf"); $ffile1 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dfam.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$dfam.pbf"); $ffile2 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir.pbf" if (-f "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir.pbf"); $ffile3 = "$ENV{'PBROOTDIR'}/$pbpkg/pbfilter/$ddir-$dver.pbf" if (-f "$ENV{'PBROOTDIR'}/$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) { pb_log(2,"DEBUG ffiles: ".Dumper(\@ffiles)."\n"); 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"}; pb_log(2,"DEBUG f:".Dumper($ptr)."\n"); } } 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; pb_log(2,"DEBUG: From $f to $destfile\n"); 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 pb_log(2,"DEBUG filter{$s}: $filter{$s}\n"); my $tmp = $filter{$s}; next if (not defined $tmp); # Expand variables if any single one found pb_log(2,"DEBUG tmp: $tmp\n"); 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_inplace { 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; my $cp = "$ENV{'PBTMP'}/".basename($destfile); copy($destfile,$cp) || die "Unable to create $cp"; pb_filter_file($cp,$ptr,$destfile,$pbproj,$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$pbpackager); unlink $cp; } # 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; pb_log(2,"DEBUG: From $f to $destfile\n"); 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 pb_log(2,"DEBUG filter{$s}: $filter{$s}\n"); 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); } sub pb_log_init { $debug = shift || 0; $LOG = shift || \*STDOUT; } sub pb_log { my $dlevel = shift; my $msg = shift; print $LOG "$msg" if ($dlevel <= $debug); } # # Return the list of packages we are working on in a CMS action # sub pb_cms_get_pkg { my @pkgs = (); my $defpkgdir = shift || undef; my $extpkgdir = shift || undef; # Get packages list if (not defined $ARGV[0]) { @pkgs = keys %$defpkgdir if (defined $defpkgdir); } elsif ($ARGV[0] =~ /^all$/) { @pkgs = keys %$defpkgdir if (defined $defpkgdir); push(@pkgs, keys %$extpkgdir) if (defined $extpkgdir); } else { @pkgs = @ARGV; } pb_log(0,"Packages: ".join(',',@pkgs)."\n"); return(\@pkgs); } # # Return the list of packages we are working on in a non CMS action # sub pb_get_pkg { my @pkgs = (); my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg"); @pkgs = keys %$var; pb_log(0,"Packages: ".join(',',@pkgs)."\n"); return(\@pkgs); } # # Check pbconf/project cms compliance # sub pb_cms_compliant { my $param = shift; my $envar = shift; my $defdir = shift; my $uri = shift; my $pbinit = shift; my %pdir; my ($pdir) = pb_conf_get_if($param) if (defined $param); if (defined $pdir) { %pdir = %$pdir; } if ((defined $pdir) && (%pdir) && (defined $pdir{$ENV{'PBPROJ'}})) { # That's always the environment variable that will be used $ENV{$envar} = $pdir{$ENV{'PBPROJ'}}; } else { if (defined $param) { pb_log(1,"WARNING: no $param defined, using $defdir\n"); pb_log(1," Please create a $param reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n"); pb_log(1," if you want to use another directory\n"); } $ENV{$envar} = "$defdir"; } # Expand potential env variable in it eval { $ENV{$envar} =~ s/(\$ENV.+\})/$1/eeg }; pb_log(2,"$envar: $ENV{$envar}\n"); my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri); if ((! -d "$ENV{$envar}") || (defined $pbinit)) { if (defined $pbinit) { pb_mkdir_p("$ENV{$envar}"); } else { pb_log(1,"Checking out $uri\n"); pb_cms_checkout($scheme,$uri,$ENV{$envar}); } } elsif (($scheme !~ /^cvs/) || ($scheme !~ /^svn/)) { # Do not compare if it's not a real cms return; } else { pb_log(1,"$uri found locally, checking content\n"); my $cmsurl = pb_cms_get_uri($scheme,$ENV{$envar}); my ($scheme2, $account2, $host2, $port2, $path2) = pb_get_uri($cmsurl); if ($cmsurl ne $uri) { # The local content doesn't correpond to the repository pb_log(0,"ERROR: Inconsistency detected:\n"); pb_log(0," * $ENV{$envar} refers to $cmsurl but\n"); pb_log(0," * $ENV{'PBETC'} refers to $uri\n"); die "Project $ENV{'PBPROJ'} is not Project-Builder compliant."; } else { pb_log(1,"Content correct - doing nothing - you may want to update your repository however\n"); # they match - do nothing - there may be local changes } } } sub pb_changelog { my $dtype = shift; my $pkg = shift; my $pbver = shift; my $pbtag = shift; my $dsuf = shift; my $path = shift; my $OUTPUT = shift; my $doit = shift; my $chglog = shift || undef; my $log = ""; # For date handling $ENV{LANG}="C"; if ((not (defined $dtype)) || ($dtype eq "") || (not (defined $pkg)) || ($pkg eq "") || (not (defined $pbver)) || ($pbver eq "") || (not (defined $pbtag)) || ($pbtag eq "") || (not (defined $dsuf)) || ($dsuf eq "") || (not (defined $path)) || ($path eq "") || (not (defined $OUTPUT)) || ($OUTPUT eq "") || (not (defined $doit)) || ($doit eq "")) { print $OUTPUT "\n"; return; } if (((not defined $chglog) || (! -f $chglog)) && ($doit eq "yes")) { #pb_log(2,"No ChangeLog file ($chglog) for $pkg\n"; print $OUTPUT "\n"; return; } my $date; my $ndate; my $n2date; my $ver; my $ver2; my ($pbpackager) = pb_conf_get("pbpackager"); if (not defined $pbpackager->{$ENV{'PBPROJ'}}) { $pbpackager->{$ENV{'PBPROJ'}} = "undefined\@noproject.noorg"; } # If we don't need to do it, or don't have it fake something if (((not defined $chglog) || (! -f $chglog)) && ($doit ne "yes")) { my @date=(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst()); $date = strftime("%Y-%m-%d", @date); $ndate = UnixDate($date,"%a", "%b", "%d", "%Y"); $n2date = &UnixDate($date,"%a, %d %b %Y %H:%M:%S %z"); if (($dtype eq "rpm") || ($dtype eq "fc")) { $ver2 = "$pbver-$pbtag$dsuf"; print $OUTPUT "* $ndate $pbpackager->{$ENV{'PBPROJ'}} $ver2\n"; print $OUTPUT "- Updated to $pbver\n"; } if ($dtype eq "deb") { print $OUTPUT "$pkg ($pbver) unstable; urgency=low\n"; print $OUTPUT "\n"; print $OUTPUT " -- $pbpackager->{$ENV{'PBPROJ'}} $n2date\n\n\n"; } return; } open(INPUT,"$chglog") || die "Unable to open $chglog (read)"; # Skip first 4 lines my $tmp = ; $tmp = ; $tmp = ; if ($dtype eq "announce") { print $OUTPUT $tmp; } $tmp = ; if ($dtype eq "announce") { print $OUTPUT $tmp; } my $first=1; # Handle each block separated by newline while () { ($ver, $date) = split(/ /); $ver =~ s/^v//; chomp($date); $date =~ s/\(([0-9-]+)\)/$1/; #pb_log(2,"**$date**\n"; $ndate = UnixDate($date,"%a", "%b", "%d", "%Y"); $n2date = &UnixDate($date,"%a, %d %b %Y %H:%M:%S %z"); #pb_log(2,"**$ndate**\n"; if (($dtype eq "rpm") || ($dtype eq "fc")) { if ($ver !~ /-/) { if ($first eq 1) { $ver2 = "$ver-$pbtag$dsuf"; $first=0; } else { $ver2 = "$ver-1$dsuf"; } } else { $ver2 = "$ver$dsuf"; } print $OUTPUT "* $ndate $pbpackager->{$ENV{'PBPROJ'}} $ver2\n"; print $OUTPUT "- Updated to $ver\n"; } if ($dtype eq "deb") { print $OUTPUT "$pkg ($ver) unstable; urgency=low\n"; print $OUTPUT "\n"; } $tmp = ; while ($tmp !~ /^$/) { if ($dtype eq "deb") { $tmp =~ s/^- //; print $OUTPUT " * $tmp"; } elsif ($dtype eq "rpm") { print $OUTPUT "$tmp"; } else { print $OUTPUT "$tmp"; } last if (eof(INPUT)); $tmp = ; } print $OUTPUT "\n"; if ($dtype eq "deb") { # Cf: http://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog print $OUTPUT " -- $pbpackager->{$ENV{'PBPROJ'}} $n2date\n\n\n"; } last if (eof(INPUT)); last if ($dtype eq "announce"); } close(INPUT); } 1;