source: ProjectBuilder/devel/pb/lib/ProjectBuilder/CMS.pm@ 527

Last change on this file since 527 was 527, checked in by Bruno Cornec, 16 years ago
  • Fix CVS export functin to also use tags passed in param.
  • Backport build fixes from 0.9.3
File size: 19.3 KB
Line 
1#!/usr/bin/perl -w
2#
3# Project Builder CMS module
4# CMS subroutines brought by the the Project-Builder project
5# which can be easily used by pbinit scripts
6#
7# $Id$
8#
9# Copyright B. Cornec 2007
10# Provided under the GPL v2
11
12package ProjectBuilder::CMS;
13
14use strict 'vars';
15use Data::Dumper;
16use English;
17use File::Basename;
18use File::Copy;
19use POSIX qw(strftime);
20use lib qw (lib);
21use ProjectBuilder::Base;
22use ProjectBuilder::Conf;
23
24# Inherit from the "Exporter" module which handles exporting functions.
25
26use Exporter;
27
28# Export, by default, all the functions into the namespace of
29# any code which uses this module.
30
31our @ISA = qw(Exporter);
32our @EXPORT = qw(pb_cms_init pb_cms_export pb_cms_get_uri pb_cms_copy pb_cms_checkout pb_cms_up pb_cms_checkin pb_cms_isdiff pb_cms_get_pkg pb_cms_compliant pb_cms_log pb_cms_add);
33
34=pod
35
36=head1 NAME
37
38ProjectBuilder::CMS, part of the project-builder.org
39
40=head1 DESCRIPTION
41
42This modules provides configuration management system functions suitable for pbinit calls.
43
44=head1 USAGE
45
46=over 4
47
48=item B<pb_cms_init>
49
50This function setup the environment for the CMS system related to the URL given by the pburl configuration parameter.
51The potential parameter indicates whether we should inititate the context or not.
52It sets up environement variables (PBPROJDIR, PBDIR, PBREVISION, PBCMSLOGFILE)
53
54=cut
55
56sub pb_cms_init {
57
58my $pbinit = shift || undef;
59
60my ($pburl) = pb_conf_get("pburl");
61pb_log(2,"DEBUG: Project URL of $ENV{'PBPROJ'}: $pburl->{$ENV{'PBPROJ'}}\n");
62my ($scheme, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
63
64my ($pbprojdir) = pb_conf_get_if("pbprojdir");
65
66if ((defined $pbprojdir) && (defined $pbprojdir->{$ENV{'PBPROJ'}})) {
67 $ENV{'PBPROJDIR'} = $pbprojdir->{$ENV{'PBPROJ'}};
68} else {
69 $ENV{'PBPROJDIR'} = "$ENV{'PBDEFDIR'}/$ENV{'PBPROJ'}";
70}
71
72# Computing the default dir for PBDIR.
73# what we have is PBPROJDIR so work from that.
74# Tree identical between PBCONFDIR and PBROOTDIR on one side and
75# PBPROJDIR and PBDIR on the other side.
76
77my $tmp = $ENV{'PBROOTDIR'};
78$tmp =~ s|^$ENV{'PBCONFDIR'}||;
79
80#
81# Check project cms compliance
82#
83pb_cms_compliant(undef,'PBDIR',"$ENV{'PBPROJDIR'}/$tmp",$pburl->{$ENV{'PBPROJ'}},$pbinit);
84
85if ($scheme =~ /^svn/) {
86 # svnversion more precise than svn info
87 $tmp = `(cd "$ENV{'PBDIR'}" ; svnversion .)`;
88 chomp($tmp);
89 $ENV{'PBREVISION'}=$tmp;
90 $ENV{'PBCMSLOGFILE'}="svn.log";
91} elsif (($scheme eq "file") || ($scheme eq "ftp") || ($scheme eq "http")) {
92 $ENV{'PBREVISION'}="flat";
93 $ENV{'PBCMSLOGFILE'}="flat.log";
94} elsif ($scheme =~ /^cvs/) {
95 # Way too slow
96 #$ENV{'PBREVISION'}=`(cd "$ENV{'PBROOTDIR'}" ; cvs rannotate -f . 2>&1 | awk '{print \$1}' | grep -E '^[0-9]' | cut -d. -f2 |sort -nu | tail -1)`;
97 #chomp($ENV{'PBREVISION'});
98 $ENV{'PBREVISION'}="cvs";
99 $ENV{'PBCMSLOGFILE'}="cvs.log";
100 $ENV{'CVS_RSH'} = "ssh" if ($scheme =~ /ssh/);
101} else {
102 die "cms $scheme unknown";
103}
104
105return($scheme,$pburl->{$ENV{'PBPROJ'}});
106}
107
108=item B<pb_cms_export>
109
110This function exports a CMS content to a directory.
111The first parameter is the URL of the CMS content.
112The second parameter is the directory in which it is locally exposed (result of a checkout). If undef, then use the original CMS content.
113The third parameter is the directory where we want to deliver it (result of export).
114
115=cut
116
117sub pb_cms_export {
118
119my $uri = shift;
120my $source = shift;
121my $destdir = shift;
122my $tmp;
123my $tmp1;
124
125my @date = pb_get_date();
126# If it's not flat, then we have a real uri as source
127my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
128
129if ($scheme =~ /^svn/) {
130 if (defined $source) {
131 if (-d $source) {
132 $tmp = $destdir;
133 } else {
134 $tmp = "$destdir/".basename($source);
135 }
136 pb_system("svn export $source $tmp","Exporting $source from SVN to $tmp");
137 } else {
138 pb_system("svn export $uri $destdir","Exporting $uri from SVN to $destdir");
139 }
140} elsif ($scheme eq "dir") {
141 pb_system("cp -a $path $destdir","Copying $uri from DIR to $destdir");
142} elsif (($scheme eq "http") || ($scheme eq "ftp")) {
143 my $f = basename($path);
144 unlink "$ENV{'PBTMP'}/$f";
145 if (-x "/usr/bin/wget") {
146 pb_system("/usr/bin/wget -nv -O $ENV{'PBTMP'}/$f $uri"," ");
147 } elsif (-x "/usr/bin/curl") {
148 pb_system("/usr/bin/curl $uri -o $ENV{'PBTMP'}/$f","Downloading $uri with curl to $ENV{'PBTMP'}/$f\n");
149 } else {
150 die "Unable to download $uri.\nNo wget/curl available, please install one of those";
151 }
152 pb_cms_export("file://$ENV{'PBTMP'}/$f",$source,$destdir);
153} elsif ($scheme eq "file") {
154 use File::MimeInfo;
155 my $mm = mimetype($path);
156 pb_log(2,"mimetype: $mm\n");
157 pb_mkdir_p($destdir);
158
159 if (defined $source) {
160 # Check whether the file is well formed
161 # (containing already a directory with the project-version name)
162 my ($pbwf) = pb_conf_get_if("pbwf");
163 if ((defined $pbwf) && (defined $pbwf->{$ENV{'PBPROJ'}})) {
164 $destdir = dirname($destdir);
165 }
166 }
167
168 if ($mm =~ /\/x-bzip-compressed-tar$/) {
169 # tar+bzip2
170 pb_system("cd $destdir ; tar xfj $path","Extracting $path in $destdir");
171 } elsif ($mm =~ /\/x-lzma-compressed-tar$/) {
172 # tar+lzma
173 pb_system("cd $destdir ; tar xfY $path","Extracting $path in $destdir");
174 } elsif ($mm =~ /\/x-compressed-tar$/) {
175 # tar+gzip
176 pb_system("cd $destdir ; tar xfz $path","Extracting $path in $destdir");
177 } elsif ($mm =~ /\/x-tar$/) {
178 # tar
179 pb_system("cd $destdir ; tar xf $path","Extracting $path in $destdir");
180 } elsif ($mm =~ /\/zip$/) {
181 # zip
182 pb_system("cd $destdir ; unzip $path","Extracting $path in $destdir");
183 } else {
184 # simple file: copy it (patch e.g.)
185 copy($path,$destdir);
186 }
187} elsif ($scheme =~ /^cvs/) {
188 # CVS needs a relative path !
189 my $dir=dirname($destdir);
190 my $base=basename($destdir);
191 if (defined $source) {
192 # CVS also needs a modules name not a dir
193 $tmp1 = basename($source);
194 } else {
195 # Probably not right, should be checked, but that way I'll notice it :-)
196 $tmp1 = $uri;
197 }
198 # If we're working on the CVS itself
199 my $cvstag = basename($ENV{'PBROOTDIR'});
200 my $cvsopt = "";
201 if ($cvstag eq "cvs") {
202 my $pbdate = strftime("%Y-%m-%d %H:%M:%S", @date);
203 $cvsopt = "-D \"$pbdate\"";
204 } else {
205 # we're working on a tag which should be the last part of PBROOTDIR
206 $cvsopt = "-r $cvstag";
207 }
208 pb_system("cd $dir ; cvs -d $account\@$host:$path export $cvsopt -d $base $tmp1","Exporting $tmp1 from $source under CVS to $destdir");
209} else {
210 die "cms $scheme unknown";
211}
212}
213
214=item B<pb_cms_get_uri>
215
216This function is only called with a real CMS system and gives the URL stored in the checked out directory.
217The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
218The second parameter is the directory in which it is locally exposed (result of a checkout).
219
220=cut
221
222sub pb_cms_get_uri {
223
224my $scheme = shift;
225my $dir = shift;
226
227my $res = "";
228my $void = "";
229
230if ($scheme =~ /^svn/) {
231 open(PIPE,"LANGUAGE=C svn info $dir |") || return("");
232 while (<PIPE>) {
233 ($void,$res) = split(/^URL:/) if (/^URL:/);
234 }
235 $res =~ s/^\s*//;
236 close(PIPE);
237 chomp($res);
238} elsif ($scheme =~ /^cvs/) {
239 # This path is always the root path of CVS, but we may be below
240 open(FILE,"$dir/CVS/Root") || die "$dir isn't CVS controlled";
241 $res = <FILE>;
242 chomp($res);
243 close(FILE);
244 # Find where we are in the tree
245 my $rdir = $dir;
246 while ((! -d "$rdir/CVSROOT") && ($rdir ne "/")) {
247 $rdir = dirname($rdir);
248 }
249 die "Unable to find a CVSROOT dir in the parents of $dir" if (! -d "$rdir/CVSROOT");
250 #compute our place under that root dir - should be a relative path
251 $dir =~ s|^$rdir||;
252 my $suffix = "";
253 $suffix = "$dir" if ($dir ne "");
254
255 my $prefix = "";
256 if ($scheme =~ /ssh/) {
257 $prefix = "cvs+ssh://";
258 } else {
259 $prefix = "cvs://";
260 }
261 $res = $prefix.$res.$suffix;
262} else {
263 die "cms $scheme unknown";
264}
265pb_log(2,"Found CMS info: $res\n");
266return($res);
267}
268
269=item B<pb_cms_copy>
270
271This function copies a CMS content to another.
272The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
273The second parameter is the URL of the original CMS content.
274The third parameter is the URL of the destination CMS content.
275
276Only coded for SVN now.
277
278=cut
279
280sub pb_cms_copy {
281my $scheme = shift;
282my $oldurl = shift;
283my $newurl = shift;
284
285if ($scheme =~ /^svn/) {
286 pb_system("svn copy -m \"Creation of $newurl from $oldurl\" $oldurl $newurl","Copying $oldurl to $newurl ");
287} elsif ($scheme eq "flat") {
288} elsif ($scheme =~ /^cvs/) {
289} else {
290 die "cms $scheme unknown";
291}
292}
293
294=item B<pb_cms_checkout>
295
296This function checks a CMS content out to a directory.
297The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
298The second parameter is the URL of the CMS content.
299The third parameter is the directory where we want to deliver it (result of export).
300
301=cut
302
303sub pb_cms_checkout {
304my $scheme = shift;
305my $url = shift;
306my $destination = shift;
307
308if ($scheme =~ /^svn/) {
309 pb_system("svn co $url $destination","Checking out $url to $destination ");
310} elsif (($scheme eq "ftp") || ($scheme eq "http")) {
311 return;
312} elsif ($scheme =~ /^cvs/) {
313 my ($scheme, $account, $host, $port, $path) = pb_get_uri($url);
314
315 # If we're working on the CVS itself
316 my $cvstag = basename($ENV{'PBROOTDIR'});
317 my $cvsopt = "";
318 if ($cvstag eq "cvs") {
319 my @date = pb_get_date();
320 my $pbdate = strftime("%Y-%m-%d %H:%M:%S", @date);
321 $cvsopt = "-D \"$pbdate\"";
322 } else {
323 # we're working on a tag which should be the last part of PBROOTDIR
324 $cvsopt = "-r $cvstag";
325 }
326 pb_mkdir_p("$destination");
327 pb_system("cd $destination ; cvs -d $account\@$host:$path co $cvsopt .","Checking out $url to $destination");
328} elsif ($scheme =~ /^file/) {
329 pb_cms_export($url,undef,$destination);
330} else {
331 die "cms $scheme unknown";
332}
333}
334
335=item B<pb_cms_up>
336
337This function updates a local directory with the CMS content.
338The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
339The second parameter is the directory to update.
340
341=cut
342
343sub pb_cms_up {
344my $scheme = shift;
345my $dir = shift;
346
347if ($scheme =~ /^svn/) {
348 pb_system("svn up $dir","Updating $dir");
349} elsif ($scheme eq "flat") {
350} elsif ($scheme =~ /^cvs/) {
351 pb_system("cvs up $dir","Updating $dir");
352} else {
353 die "cms $scheme unknown";
354}
355}
356
357=item B<pb_cms_checkin>
358
359This function updates a CMS content from a local directory.
360The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
361The second parameter is the directory to update from.
362The third parameter indicates if we are in a new version creation (undef) or in a new project creation (1)
363
364=cut
365
366sub pb_cms_checkin {
367my $scheme = shift;
368my $dir = shift;
369my $pbinit = shift || undef;
370
371my $ver = basename($dir);
372my $msg = "updated to $ver";
373$msg = "Project $ENV{PBPROJ} creation" if (defined $pbinit);
374
375if ($scheme =~ /^svn/) {
376 pb_system("svn ci -m \"$msg\" $dir","Checking in $dir");
377} elsif ($scheme eq "flat") {
378} elsif ($scheme =~ /^cvs/) {
379 pb_system("cvs ci -m \"$msg\" $dir","Checking in $dir");
380} else {
381 die "cms $scheme unknown";
382}
383pb_cms_up($scheme,$dir);
384}
385
386=item B<pb_cms_add>
387
388This function adds to a CMS content from a local directory.
389The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
390The second parameter is the directory/file to add.
391
392=cut
393
394sub pb_cms_add {
395my $scheme = shift;
396my $f = shift;
397
398if ($scheme =~ /^svn/) {
399 pb_system("svn add $f","Adding $f to SVN");
400} elsif ($scheme eq "flat") {
401} elsif ($scheme =~ /^cvs/) {
402 pb_system("cvs add $f","Adding $f to CVS");
403} else {
404 die "cms $scheme unknown";
405}
406pb_cms_up($scheme,$f);
407}
408
409=item B<pb_cms_isdiff>
410
411This function returns a integer indicating the number f differences between the CMS content and the local directory where it's checked out.
412The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
413The second parameter is the directory to consider.
414
415=cut
416
417sub pb_cms_isdiff {
418my $scheme = shift;
419my $dir =shift;
420
421if ($scheme =~ /^svn/) {
422 open(PIPE,"svn diff $dir |") || die "Unable to get svn diff from $dir";
423 my $l = 0;
424 while (<PIPE>) {
425 $l++;
426 }
427 return($l);
428} elsif ($scheme eq "flat") {
429} elsif ($scheme =~ /^cvs/) {
430 open(PIPE,"cvs diff $dir |") || die "Unable to get svn diff from $dir";
431 my $l = 0;
432 while (<PIPE>) {
433 # Skipping normal messages
434 next if (/^cvs diff:/);
435 $l++;
436 }
437 return($l);
438} else {
439 die "cms $scheme unknown";
440}
441}
442
443=item B<pb_cms_getpkg>
444
445This function returns the list of packages we are working on in a CMS action.
446The first parameter is the default list of packages from the configuration file.
447The second parameter is the optional list of packages from the configuration file.
448
449=cut
450
451sub pb_cms_get_pkg {
452
453my @pkgs = ();
454my $defpkgdir = shift || undef;
455my $extpkgdir = shift || undef;
456
457# Get packages list
458if (not defined $ARGV[0]) {
459 @pkgs = keys %$defpkgdir if (defined $defpkgdir);
460} elsif ($ARGV[0] =~ /^all$/) {
461 @pkgs = keys %$defpkgdir if (defined $defpkgdir);
462 push(@pkgs, keys %$extpkgdir) if (defined $extpkgdir);
463} else {
464 @pkgs = @ARGV;
465}
466pb_log(0,"Packages: ".join(',',@pkgs)."\n");
467return(\@pkgs);
468}
469
470=item B<pb_cms_compliant>
471
472This function checks the compliance of the project and the pbconf directory.
473The first parameter is the key name of the value that needs to be read in the configuration file.
474The second parameter is the environment variable this key will populate.
475The third parameter is the location of the pbconf dir.
476The fourth parameter is the URI of the CMS content related to the pbconf dir.
477The fifth parameter indicates whether we should inititate the context or not.
478
479=cut
480
481sub pb_cms_compliant {
482
483my $param = shift;
484my $envar = shift;
485my $defdir = shift;
486my $uri = shift;
487my $pbinit = shift;
488my %pdir;
489
490my ($pdir) = pb_conf_get_if($param) if (defined $param);
491if (defined $pdir) {
492 %pdir = %$pdir;
493}
494
495
496if ((defined $pdir) && (%pdir) && (defined $pdir{$ENV{'PBPROJ'}})) {
497 # That's always the environment variable that will be used
498 $ENV{$envar} = $pdir{$ENV{'PBPROJ'}};
499} else {
500 if (defined $param) {
501 pb_log(1,"WARNING: no $param defined, using $defdir\n");
502 pb_log(1," Please create a $param reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n");
503 pb_log(1," if you want to use another directory\n");
504 }
505 $ENV{$envar} = "$defdir";
506}
507
508# Expand potential env variable in it
509eval { $ENV{$envar} =~ s/(\$ENV.+\})/$1/eeg };
510pb_log(2,"$envar: $ENV{$envar}\n");
511
512my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
513
514if ((! -d "$ENV{$envar}") || (defined $pbinit)) {
515 if (defined $pbinit) {
516 pb_mkdir_p("$ENV{$envar}");
517 } else {
518 pb_log(1,"Checking out $uri\n");
519 pb_cms_checkout($scheme,$uri,$ENV{$envar});
520 }
521} elsif (($scheme !~ /^cvs/) || ($scheme !~ /^svn/)) {
522 # Do not compare if it's not a real cms
523 return;
524} else {
525 pb_log(1,"$uri found locally, checking content\n");
526 my $cmsurl = pb_cms_get_uri($scheme,$ENV{$envar});
527 my ($scheme2, $account2, $host2, $port2, $path2) = pb_get_uri($cmsurl);
528 if ($cmsurl ne $uri) {
529 # The local content doesn't correpond to the repository
530 pb_log(0,"ERROR: Inconsistency detected:\n");
531 pb_log(0," * $ENV{$envar} refers to $cmsurl but\n");
532 pb_log(0," * $ENV{'PBETC'} refers to $uri\n");
533 die "Project $ENV{'PBPROJ'} is not Project-Builder compliant.";
534 } else {
535 pb_log(1,"Content correct - doing nothing - you may want to update your repository however\n");
536 # they match - do nothing - there may be local changes
537 }
538}
539}
540
541=item B<pb_cms_create_authors>
542
543This function creates a AUTHORS files for the project. It call it AUTHORS.pb if an AUTHORS file already exists.
544The first parameter is the source file for authors information.
545The second parameter is the directory where to create the final AUTHORS file.
546The third parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
547
548=cut
549
550sub pb_cms_create_authors {
551
552my $authors=shift;
553my $dest=shift;
554my $scheme=shift;
555
556return if ($authors eq "/dev/null");
557open(SAUTH,$authors) || die "Unable to open $authors";
558# Save a potentially existing AUTHORS file and write instead to AUTHORS.pb
559my $ext = "";
560if (-f "$dest/AUTHORS") {
561 $ext = ".pb";
562}
563open(DAUTH,"> $dest/AUTHORS$ext") || die "Unable to create $dest/AUTHORS$ext";
564print DAUTH "Authors of the project are:\n";
565print DAUTH "===========================\n";
566while (<SAUTH>) {
567 my ($nick,$gcos) = split(/:/);
568 chomp($gcos);
569 print DAUTH "$gcos";
570 if (defined $scheme) {
571 # Do not give a scheme for flat types
572 my $endstr="";
573 if ("$ENV{'PBREVISION'}" ne "flat") {
574 $endstr = " under $scheme";
575 }
576 print DAUTH " ($nick$endstr)\n";
577 } else {
578 print DAUTH "\n";
579 }
580}
581close(DAUTH);
582close(SAUTH);
583}
584
585=item B<pb_cms_log>
586
587This function creates a ChangeLog file for the project.
588The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
589The second parameter is the directory where the CMS content was checked out.
590The third parameter is the directory where to create the final ChangeLog file.
591The fourth parameter is unused.
592The fifth parameter is the source file for authors information.
593
594It may use a tool like svn2cl or cvs2cl to generate it if present, or the log file from the CMS if not.
595
596=cut
597
598
599sub pb_cms_log {
600
601my $scheme = shift;
602my $pkgdir = shift;
603my $dest = shift;
604my $chglog = shift;
605my $authors = shift;
606my $testver = shift || undef;
607
608pb_cms_create_authors($authors,$dest,$scheme);
609
610if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
611 if (! -f "$dest/ChangeLog") {
612 open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
613 # We need a minimal version for debian type of build
614 print CL "\n";
615 print CL "\n";
616 print CL "\n";
617 print CL "\n";
618 print CL "1990-01-01 none\n";
619 print CL "\n";
620 print CL " * test version\n";
621 print CL "\n";
622 close(CL);
623 pb_log(0,"Generating fake ChangeLog for test version\n");
624 open(CL,"> $dest/$ENV{'PBCMSLOGFILE'}") || die "Unable to create $dest/$ENV{'PBCMSLOGFILE'}";
625 close(CL);
626 }
627}
628
629if ($scheme =~ /^svn/) {
630 if (! -f "$dest/ChangeLog") {
631 # In case we have no network, just create an empty one before to allow correct build
632 open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
633 close(CL);
634 if (-x "/usr/bin/svn2cl") {
635 pb_system("/usr/bin/svn2cl --group-by-day --authors=$authors -i -o $dest/ChangeLog $pkgdir","Generating ChangeLog from SVN with svn2cl");
636 } else {
637 # To be written from pbcl
638 pb_system("svn log -v $pkgdir > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from SVN");
639 }
640 }
641} elsif (($scheme eq "file") || ($scheme eq "dir") || ($scheme eq "http") || ($scheme eq "ftp")) {
642 if (! -f "$dest/ChangeLog") {
643 pb_system("echo ChangeLog for $pkgdir > $dest/ChangeLog","Empty ChangeLog file created");
644 }
645} elsif ($scheme =~ /^cvs/) {
646 my $tmp=basename($pkgdir);
647 # CVS needs a relative path !
648 if (! -f "$dest/ChangeLog") {
649 # In case we have no network, just create an empty one before to allow correct build
650 open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
651 close(CL);
652 if (-x "/usr/bin/cvs2cl") {
653 pb_system("/usr/bin/cvs2cl --group-by-day -U $authors -f $dest/ChangeLog $pkgdir","Generating ChangeLog from CVS with cvs2cl");
654 } else {
655 # To be written from pbcl
656 pb_system("cvs log $tmp > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from CVS");
657 }
658 }
659} else {
660 die "cms $scheme unknown";
661}
662}
663
664=back
665
666=head1 WEB SITES
667
668The main Web site of the project is available at L<http://www.project-builder.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
669
670=head1 USER MAILING LIST
671
672None exists for the moment.
673
674=head1 AUTHORS
675
676The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
677
678=head1 COPYRIGHT
679
680Project-Builder.org is distributed under the GPL v2.0 license
681described in the file C<COPYING> included with the distribution.
682
683=cut
684
6851;
Note: See TracBrowser for help on using the repository browser.