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

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

setupvm seems better now

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