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

Last change on this file since 500 was 500, checked in by Bruno Cornec, 16 years ago
  • Working patch support added to pb (tested with buffer)
  • Filtering functions now handle also pointer on hashes (such as the new pb hash)
  • Filtering functions support new macro for patch support (PBPATCHSRC and PBPATCHCMD)
  • Env.pm now generates correct templates for patch support and uses the new pb hash
  • pb_cms_export extended to support file:// URI, and also supports an undef second param (no local export available)
  • In pb, hashes now include also the arch (for better patch support)
  • pb supports local CMS based patches, as well as external references (not tested yet)
  • New pb_get_arch function provided
  • New parameters for pb_system (mayfail and quiet)
File size: 18.9 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 my $optcvs = "";
199
200 # If we're working on the CVS itself
201 my $cvstag = basename($ENV{'PBROOTDIR'});
202 my $cvsopt = "";
203 if ($cvstag eq "cvs") {
204 my $pbdate = strftime("%Y-%m-%d %H:%M:%S", @date);
205 $cvsopt = "-D \"$pbdate\"";
206 } else {
207 # we're working on a tag which should be the last part of PBROOTDIR
208 $cvsopt = "-r $cvstag";
209 }
210 pb_system("cd $dir ; cvs -d $account\@$host:$path export $cvsopt -d $base $tmp1","Exporting $tmp1 from $source under CVS to $destdir");
211} else {
212 die "cms $scheme unknown";
213}
214}
215
216=item B<pb_cms_get_uri>
217
218This function is only called with a real CMS system and gives the URL stored in the checked out directory.
219The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
220The second parameter is the directory in which it is locally exposed (result of a checkout).
221
222=cut
223
224sub pb_cms_get_uri {
225
226my $scheme = shift;
227my $dir = shift;
228
229my $res = "";
230my $void = "";
231
232if ($scheme =~ /^svn/) {
233 open(PIPE,"LANGUAGE=C svn info $dir |") || return("");
234 while (<PIPE>) {
235 ($void,$res) = split(/^URL:/) if (/^URL:/);
236 }
237 $res =~ s/^\s*//;
238 close(PIPE);
239 chomp($res);
240} elsif ($scheme =~ /^cvs/) {
241 # This path is always the root path of CVS, but we may be below
242 open(FILE,"$dir/CVS/Root") || die "$dir isn't CVS controlled";
243 $res = <FILE>;
244 chomp($res);
245 close(FILE);
246 # Find where we are in the tree
247 my $rdir = $dir;
248 while ((! -d "$rdir/CVSROOT") && ($rdir ne "/")) {
249 $rdir = dirname($rdir);
250 }
251 die "Unable to find a CVSROOT dir in the parents of $dir" if (! -d "$rdir/CVSROOT");
252 #compute our place under that root dir - should be a relative path
253 $dir =~ s|^$rdir||;
254 my $suffix = "";
255 $suffix = "$dir" if ($dir ne "");
256
257 my $prefix = "";
258 if ($scheme =~ /ssh/) {
259 $prefix = "cvs+ssh://";
260 } else {
261 $prefix = "cvs://";
262 }
263 $res = $prefix.$res.$suffix;
264} else {
265 die "cms $scheme unknown";
266}
267pb_log(2,"Found CMS info: $res\n");
268return($res);
269}
270
271=item B<pb_cms_copy>
272
273This function copies a CMS content to another.
274The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
275The second parameter is the URL of the original CMS content.
276The third parameter is the URL of the destination CMS content.
277
278Only coded for SVN now.
279
280=cut
281
282sub pb_cms_copy {
283my $scheme = shift;
284my $oldurl = shift;
285my $newurl = shift;
286
287if ($scheme =~ /^svn/) {
288 pb_system("svn copy -m \"Creation of $newurl from $oldurl\" $oldurl $newurl","Copying $oldurl to $newurl ");
289} elsif ($scheme eq "flat") {
290} elsif ($scheme =~ /^cvs/) {
291} else {
292 die "cms $scheme unknown";
293}
294}
295
296=item B<pb_cms_checkout>
297
298This function checks a CMS content out to a directory.
299The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
300The second parameter is the URL of the CMS content.
301The third parameter is the directory where we want to deliver it (result of export).
302
303=cut
304
305sub pb_cms_checkout {
306my $scheme = shift;
307my $url = shift;
308my $destination = shift;
309
310if ($scheme =~ /^svn/) {
311 pb_system("svn co $url $destination","Checking out $url to $destination ");
312} elsif (($scheme eq "ftp") || ($scheme eq "http")) {
313 return;
314} elsif ($scheme =~ /^cvs/) {
315 pb_system("cvs co $url $destination","Checking out $url to $destination ");
316} elsif ($scheme =~ /^file/) {
317 pb_cms_export($url,undef,$destination);
318} else {
319 die "cms $scheme unknown";
320}
321}
322
323=item B<pb_cms_up>
324
325This function updates a local directory with the CMS content.
326The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
327The second parameter is the directory to update.
328
329=cut
330
331sub pb_cms_up {
332my $scheme = shift;
333my $dir = shift;
334
335if ($scheme =~ /^svn/) {
336 pb_system("svn up $dir","Updating $dir");
337} elsif ($scheme eq "flat") {
338} elsif ($scheme =~ /^cvs/) {
339 pb_system("cvs up $dir","Updating $dir");
340} else {
341 die "cms $scheme unknown";
342}
343}
344
345=item B<pb_cms_checkin>
346
347This function updates a CMS content from a local directory.
348The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
349The second parameter is the directory to update from.
350The third parameter indicates if we are in a new version creation (undef) or in a new project creation (1)
351
352=cut
353
354sub pb_cms_checkin {
355my $scheme = shift;
356my $dir = shift;
357my $pbinit = shift || undef;
358
359my $ver = basename($dir);
360my $msg = "updated to $ver";
361$msg = "Project $ENV{PBPROJ} creation" if (defined $pbinit);
362
363if ($scheme =~ /^svn/) {
364 pb_system("svn ci -m \"$msg\" $dir","Checking in $dir");
365} elsif ($scheme eq "flat") {
366} elsif ($scheme =~ /^cvs/) {
367 pb_system("cvs ci -m \"$msg\" $dir","Checking in $dir");
368} else {
369 die "cms $scheme unknown";
370}
371pb_cms_up($scheme,$dir);
372}
373
374=item B<pb_cms_add>
375
376This function adds to a CMS content from a local directory.
377The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
378The second parameter is the directory/file to add.
379
380=cut
381
382sub pb_cms_add {
383my $scheme = shift;
384my $f = shift;
385
386if ($scheme =~ /^svn/) {
387 pb_system("svn add $f","Adding $f to SVN");
388} elsif ($scheme eq "flat") {
389} elsif ($scheme =~ /^cvs/) {
390 pb_system("cvs add $f","Adding $f to CVS");
391} else {
392 die "cms $scheme unknown";
393}
394pb_cms_up($scheme,$f);
395}
396
397=item B<pb_cms_isdiff>
398
399This function returns a integer indicating the number f differences between the CMS content and the local directory where it's checked out.
400The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
401The second parameter is the directory to consider.
402
403=cut
404
405sub pb_cms_isdiff {
406my $scheme = shift;
407my $dir =shift;
408
409if ($scheme =~ /^svn/) {
410 open(PIPE,"svn diff $dir |") || die "Unable to get svn diff from $dir";
411 my $l = 0;
412 while (<PIPE>) {
413 $l++;
414 }
415 return($l);
416} elsif ($scheme eq "flat") {
417} elsif ($scheme =~ /^cvs/) {
418 open(PIPE,"cvs diff $dir |") || die "Unable to get svn diff from $dir";
419 my $l = 0;
420 while (<PIPE>) {
421 # Skipping normal messages
422 next if (/^cvs diff:/);
423 $l++;
424 }
425 return($l);
426} else {
427 die "cms $scheme unknown";
428}
429}
430
431=item B<pb_cms_getpkg>
432
433This function returns the list of packages we are working on in a CMS action.
434The first parameter is the default list of packages from the configuration file.
435The second parameter is the optional list of packages from the configuration file.
436
437=cut
438
439sub pb_cms_get_pkg {
440
441my @pkgs = ();
442my $defpkgdir = shift || undef;
443my $extpkgdir = shift || undef;
444
445# Get packages list
446if (not defined $ARGV[0]) {
447 @pkgs = keys %$defpkgdir if (defined $defpkgdir);
448} elsif ($ARGV[0] =~ /^all$/) {
449 @pkgs = keys %$defpkgdir if (defined $defpkgdir);
450 push(@pkgs, keys %$extpkgdir) if (defined $extpkgdir);
451} else {
452 @pkgs = @ARGV;
453}
454pb_log(0,"Packages: ".join(',',@pkgs)."\n");
455return(\@pkgs);
456}
457
458=item B<pb_cms_compliant>
459
460This function checks the compliance of the project and the pbconf directory.
461The first parameter is the key name of the value that needs to be read in the configuration file.
462The second parameter is the environment variable this key will populate.
463The third parameter is the location of the pbconf dir.
464The fourth parameter is the URI of the CMS content related to the pbconf dir.
465The fifth parameter indicates whether we should inititate the context or not.
466
467=cut
468
469sub pb_cms_compliant {
470
471my $param = shift;
472my $envar = shift;
473my $defdir = shift;
474my $uri = shift;
475my $pbinit = shift;
476my %pdir;
477
478my ($pdir) = pb_conf_get_if($param) if (defined $param);
479if (defined $pdir) {
480 %pdir = %$pdir;
481}
482
483
484if ((defined $pdir) && (%pdir) && (defined $pdir{$ENV{'PBPROJ'}})) {
485 # That's always the environment variable that will be used
486 $ENV{$envar} = $pdir{$ENV{'PBPROJ'}};
487} else {
488 if (defined $param) {
489 pb_log(1,"WARNING: no $param defined, using $defdir\n");
490 pb_log(1," Please create a $param reference for project $ENV{'PBPROJ'} in $ENV{'PBETC'}\n");
491 pb_log(1," if you want to use another directory\n");
492 }
493 $ENV{$envar} = "$defdir";
494}
495
496# Expand potential env variable in it
497eval { $ENV{$envar} =~ s/(\$ENV.+\})/$1/eeg };
498pb_log(2,"$envar: $ENV{$envar}\n");
499
500my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
501
502if ((! -d "$ENV{$envar}") || (defined $pbinit)) {
503 if (defined $pbinit) {
504 pb_mkdir_p("$ENV{$envar}");
505 } else {
506 pb_log(1,"Checking out $uri\n");
507 pb_cms_checkout($scheme,$uri,$ENV{$envar});
508 }
509} elsif (($scheme !~ /^cvs/) || ($scheme !~ /^svn/)) {
510 # Do not compare if it's not a real cms
511 return;
512} else {
513 pb_log(1,"$uri found locally, checking content\n");
514 my $cmsurl = pb_cms_get_uri($scheme,$ENV{$envar});
515 my ($scheme2, $account2, $host2, $port2, $path2) = pb_get_uri($cmsurl);
516 if ($cmsurl ne $uri) {
517 # The local content doesn't correpond to the repository
518 pb_log(0,"ERROR: Inconsistency detected:\n");
519 pb_log(0," * $ENV{$envar} refers to $cmsurl but\n");
520 pb_log(0," * $ENV{'PBETC'} refers to $uri\n");
521 die "Project $ENV{'PBPROJ'} is not Project-Builder compliant.";
522 } else {
523 pb_log(1,"Content correct - doing nothing - you may want to update your repository however\n");
524 # they match - do nothing - there may be local changes
525 }
526}
527}
528
529=item B<pb_cms_create_authors>
530
531This function creates a AUTHORS files for the project. It call it AUTHORS.pb if an AUTHORS file already exists.
532The first parameter is the source file for authors information.
533The second parameter is the directory where to create the final AUTHORS file.
534The third parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
535
536=cut
537
538sub pb_cms_create_authors {
539
540my $authors=shift;
541my $dest=shift;
542my $scheme=shift;
543
544return if ($authors eq "/dev/null");
545open(SAUTH,$authors) || die "Unable to open $authors";
546# Save a potentially existing AUTHORS file and write instead to AUTHORS.pb
547my $ext = "";
548if (-f "$dest/AUTHORS") {
549 $ext = ".pb";
550}
551open(DAUTH,"> $dest/AUTHORS$ext") || die "Unable to create $dest/AUTHORS$ext";
552print DAUTH "Authors of the project are:\n";
553print DAUTH "===========================\n";
554while (<SAUTH>) {
555 my ($nick,$gcos) = split(/:/);
556 chomp($gcos);
557 print DAUTH "$gcos";
558 if (defined $scheme) {
559 # Do not give a scheme for flat types
560 my $endstr="";
561 if ("$ENV{'PBREVISION'}" ne "flat") {
562 $endstr = " under $scheme";
563 }
564 print DAUTH " ($nick$endstr)\n";
565 } else {
566 print DAUTH "\n";
567 }
568}
569close(DAUTH);
570close(SAUTH);
571}
572
573=item B<pb_cms_log>
574
575This function creates a ChangeLog file for the project.
576The first parameter is the schema of the CMS systems (svn, cvs, svn+ssh, ...)
577The second parameter is the directory where the CMS content was checked out.
578The third parameter is the directory where to create the final ChangeLog file.
579The fourth parameter is unused.
580The fifth parameter is the source file for authors information.
581
582It may use a tool like svn2cl or cvs2cl to generate it if present, or the log file from the CMS if not.
583
584=cut
585
586
587sub pb_cms_log {
588
589my $scheme = shift;
590my $pkgdir = shift;
591my $dest = shift;
592my $chglog = shift;
593my $authors = shift;
594my $testver = shift || undef;
595
596pb_cms_create_authors($authors,$dest,$scheme);
597
598if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
599 if (! -f "$dest/ChangeLog") {
600 open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
601 # We need a minimal version for debian type of build
602 print CL "\n";
603 print CL "\n";
604 print CL "\n";
605 print CL "\n";
606 print CL "1990-01-01 none\n";
607 print CL "\n";
608 print CL " * test version\n";
609 print CL "\n";
610 close(CL);
611 pb_log(0,"Generating fake ChangeLog for test version\n");
612 open(CL,"> $dest/$ENV{'PBCMSLOGFILE'}") || die "Unable to create $dest/$ENV{'PBCMSLOGFILE'}";
613 close(CL);
614 }
615}
616
617if ($scheme =~ /^svn/) {
618 if (! -f "$dest/ChangeLog") {
619 # In case we have no network, just create an empty one before to allow correct build
620 open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
621 close(CL);
622 if (-x "/usr/bin/svn2cl") {
623 pb_system("/usr/bin/svn2cl --group-by-day --authors=$authors -i -o $dest/ChangeLog $pkgdir","Generating ChangeLog from SVN with svn2cl");
624 } else {
625 # To be written from pbcl
626 pb_system("svn log -v $pkgdir > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from SVN");
627 }
628 }
629} elsif (($scheme eq "file") || ($scheme eq "dir") || ($scheme eq "http") || ($scheme eq "ftp")) {
630 if (! -f "$dest/ChangeLog") {
631 pb_system("echo ChangeLog for $pkgdir > $dest/ChangeLog","Empty ChangeLog file created");
632 }
633} elsif ($scheme =~ /^cvs/) {
634 my $tmp=basename($pkgdir);
635 # CVS needs a relative path !
636 if (! -f "$dest/ChangeLog") {
637 # In case we have no network, just create an empty one before to allow correct build
638 open(CL,"> $dest/ChangeLog") || die "Unable to create $dest/ChangeLog";
639 close(CL);
640 if (-x "/usr/bin/cvs2cl") {
641 pb_system("/usr/bin/cvs2cl --group-by-day -U $authors -f $dest/ChangeLog $pkgdir","Generating ChangeLog from CVS with cvs2cl");
642 } else {
643 # To be written from pbcl
644 pb_system("cvs log $tmp > $dest/$ENV{'PBCMSLOGFILE'}","Extracting log info from CVS");
645 }
646 }
647} else {
648 die "cms $scheme unknown";
649}
650}
651
652=back
653
654=head1 WEB SITES
655
656The 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/>.
657
658=head1 USER MAILING LIST
659
660None exists for the moment.
661
662=head1 AUTHORS
663
664The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
665
666=head1 COPYRIGHT
667
668Project-Builder.org is distributed under the GPL v2.0 license
669described in the file C<COPYING> included with the distribution.
670
671=cut
672
6731;
Note: See TracBrowser for help on using the repository browser.