/[wait]/trunk/script/cpan.PL
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/script/cpan.PL

Parent Directory Parent Directory | Revision Log Revision Log


Revision 88 - (hide annotations)
Mon May 24 13:44:01 2004 UTC (19 years, 11 months ago) by dpavlin
File MIME type: text/plain
File size: 19637 byte(s)
move cvs-head to trunk

1 ulpfr 10 #!/bin/sh -- # -*- perl -*- -w
2     eval 'exec perl -S $0 "$@"'
3     if 0;
4    
5     use strict;
6    
7     use Config;
8     use File::Basename qw(fileparse);
9    
10     my($file, $path) = fileparse($0);
11     $file =~ s!\.PL$!!i;
12     chdir($path) or die "Couldn't chdir to `$path': $!\n";
13    
14     print "Extracting $file\n";
15    
16     open(OUT, "> $file") or die "Couldn't create `$file': $!\n";
17     print OUT "$Config{'startperl'} -w\n";
18     while (<DATA>) {
19     print OUT
20     }
21     close(OUT) or die "Couldn't close `$file': $!\n";
22    
23     chmod(0755, $file) or die "Couldn't chmod 744 on `$file': $!\n";
24    
25     exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
26    
27     __END__
28     ######################### -*- Mode: Perl -*- #########################
29     ##
30     ## $Basename: cpan.PL $
31     ## $Revision: 1.6 $
32     ##
33     ## Author : Ulrich Pfeifer
34     ## Created On : Sat Jan 4 18:09:28 1997
35     ##
36     ## Last Modified By : Ulrich Pfeifer
37     ## Last Modified On : Sun Nov 22 18:44:36 1998
38     ##
39     ## Copyright (c) 1996-1997, Ulrich Pfeifer
40     ##
41     ##
42     ######################################################################
43    
44     eval 'exec perl -S $0 "$@"'
45     if 0;
46    
47    
48     use strict;
49    
50     use File::Path;
51     use DB_File;
52     use Getopt::Long;
53     use File::Find;
54     use File::Basename;
55     use IO::File;
56    
57     require WAIT::Config;
58     require WAIT::Database;
59     require WAIT::Parse::Pod;
60     require WAIT::Document::Tar;
61    
62    
63     my %OPT = (database => 'DB',
64     dir => $WAIT::Config->{WAIT_home} || '/tmp',
65     table => 'cpan',
66     clean => 0,
67     remove => [],
68     force => 0,
69     cpan => '/usr/src/perl/CPAN/sources',
70     trust_mtime => 1,
71     match => 'authors/id/',
72     test => 0,
73     # cpan => 'ftp://ftp.rz.ruhr-uni-bochum.de/pub/CPAN',
74     cpan => 'ftp://ftp.uni-hamburg.de:/pub/soft/lang/perl/CPAN',
75     keep => '/app/unido-i06/src/share/lang/perl/96a/CPAN/sources',
76     );
77    
78     GetOptions(\%OPT,
79     'database=s',
80     'dir=s',
81     'cpan=s',
82     'table=s',
83     'keep=s',
84     'match=s',
85     'clean!',
86     'test=i', # test level 0: normal
87     # 1: don't change db
88     # 2: don't look at archives even
89    
90     'remove=s@',
91     'force!', # force indexing even if seen
92     'trust_mtime!', # use mtime instead of version number
93     ) || die "Usage: ...\n";
94    
95    
96     clean_database(
97     database => $OPT{database},
98     dir => $OPT{dir},
99     table => $OPT{table},
100     ) if $OPT{clean};
101    
102     my $db = WAIT::Database->open(
103     name => $OPT{database},
104     'directory' => $OPT{dir},
105     )
106     || WAIT::Database->create(
107     name => $OPT{database},
108     'directory' => $OPT{dir},
109     )
110     or die "Could not open/create database '$OPT{dir}/$OPT{database}': $@";
111    
112     my $layout= new WAIT::Parse::Pod;
113    
114     my $tb = $db->table(name => $OPT{table})
115     || create_table(db => $db, table => $OPT{table}, layout => $layout);
116    
117     # Map e.g. '.../latest' to 'perl'. Used in wanted(). Effects version
118     # considerations. Value *must* match common prefix. Aliasing should be
119     # used if CPAN contains serveral distributions with different name but
120     # same root directory.
121     # We still have a problem if there are different root directories!
122    
123     my %ALIAS = (# tar name real (root) name
124     'latest' => 'perl',
125     'perl5db-kit' => 'DB',
126     'SGI-FM' => 'FM',
127     'net-ext' => 'Net',
128     'VelocisSQL' => 'Velocis',
129     'Net-ext' => 'Net',
130     'Curses-DevKit' => 'Cdk',
131     'PostgresPerl' => 'Postgres',
132     'perlpdf' => 'PERLPDF',
133     'Des-perl' => 'Des',
134     'SGI-GL' => 'GL',
135     'DBD-DB2' => 'DB2',
136     );
137     my %NEW_ALIAS; # found in this pass
138    
139     # Map module names to pathes. Generated by wanted() doing alisaing.
140     my %ARCHIVE;
141    
142     # Map module names to latest version. Generated by wanted()
143     my %VERSION;
144    
145    
146     # Mapping for modules with common root not matching modules name that
147     # are not aliased. This is just for prefix stripping and not strictly
148     # necessary. Takes effect after version considerations.
149     my %TR = (# tar name root to strip
150     'Net_SSLeay.pm' => 'SSLeay/',
151     'EventDrivenServer' => 'Server/',
152     'bio_lib.pl.' => '',
153     'AlarmCall' => 'Sys/',
154     'Cdk-ext' => 'Cdk/',
155     'Sx' => '\d.\d/',
156     'DumpStack' => 'Devel/',
157     'StatisticsDescriptive'=> 'Statistics/',
158     'Term-Gnuplot' => 'Gnuplot/',
159     'iodbc_ext' => 'iodbc-ext-\d.\d/',
160     'UNIVERSAL' => '',
161     'Term-Query' => 'Query/',
162     'SelfStubber' => 'Devel/',
163     'CallerItem' => 'Devel/',
164     );
165    
166     my $DIR = $tb->dir;
167     my $DATA = $tb->dir . "/data";
168     my $LWP;
169    
170    
171     if (@{$OPT{remove}}) {
172     my $pod;
173     for $pod (@{$OPT{remove}}) {
174     unless (-e $pod) {
175     $pod = "$DIR/$pod";
176     }
177     index_pod(file => $pod, remove => 1) if -f $pod;
178     unlink $pod or warn "Could not unlink '$pod': $!\n";
179     #$tb->sync;
180     }
181     $tb->close;
182     $db->close;
183     exit;
184     }
185    
186     # Now get the beef
187     if ($OPT{cpan} =~ /^(http|ftp):/) {
188     $LWP = 1;
189     require LWP::Simple;
190     LWP::Simple->import();
191    
192     mkpath($DATA,1,0755) or
193     die "Could not generate '$DATA/': $!"
194     unless -d $DATA;
195    
196     if (! -f "$DATA/find-ls.gz" or -M "$DATA/find-ls.gz" > 0.5) {
197     my $status = mirror("$OPT{cpan}/indices/find-ls.gz", "$DATA/find-ls.gz");
198     if ($status != &RC_OK and $status != &RC_NOT_MODIFIED) {
199     # we could use Net:FTP here ...
200     die "Was unable to mirror '$OPT{cpan}/indices/find-ls.gz'\n";
201     }
202     }
203     my $fh = new IO::File "gzip -cd $DATA/find-ls.gz |";
204     die "Could not open 'gzip -cd $DATA/find-ls.gz': !$\n" unless $fh;
205    
206     my $line;
207     while (defined ($line = <$fh>)) {
208     chomp($line);
209     my ($mon, $mday, $time, $file, $is_link) = (split ' ', $line)[7..11];
210    
211     next if defined $is_link;
212     my $mtime = mtime($mon, $mday, $time);
213    
214     $file =~ s:^\./::;
215     ($_) = fileparse($file);
216     $File::Find::name = $file;
217     wanted($mtime);
218     }
219     } else {
220     find(sub {&wanted((stat($_))[9])}, $OPT{cpan});
221     }
222    
223     ARCHIVE:
224     for my $tar (sort keys %ARCHIVE) {
225     next if $OPT{match} and $ARCHIVE{$tar} !~ /$OPT{match}/o;
226     my $base = (split /\//, $ARCHIVE{$tar})[-1];
227     my $parent;
228    
229     # logging
230     if ($OPT{trust_mtime}) {
231     printf "%-20s %10s %s\t", $tar,
232     substr(scalar(localtime($VERSION{$tar})),0,10), $base;
233     } else {
234     printf "%-20s %10.5f %s\t", $tar, $VERSION{$tar}, $base;
235     }
236    
237     # Remember the archive
238     # We should have an extra table for the tar file data ...
239     if (!$OPT{force} and $tb->have(docid => $base)) {
240     print "skipping\n";
241     next ARCHIVE;
242     } else {
243     $parent = $tb->insert(docid => $base,
244     headline => $ARCHIVE{$tar}) unless $OPT{test};
245     print "indexing\n";
246     }
247    
248     next ARCHIVE if $OPT{test} > 1;
249    
250     my $TAR = myget($tar);
251    
252     next ARCHIVE unless $TAR; # not able to fetch it
253    
254     my %tar;
255     tie (%tar,
256     'WAIT::Document::Tar',
257     sub { $_[0] =~ /\.(pm|pod|PL)$/ or $_[0] =~ /readme/i},
258     #sub { $_[0] !~ m:/$: },
259     $TAR)
260     or warn "Could not tie '$TAR'\n";
261    
262     my $sloppy;
263     my ($key, $val);
264    
265     FILE:
266     while (($key, $val) = each %tar) {
267     my $file = fname($key);
268    
269     # don't index directories
270     next if $file =~ /\/$/;
271    
272     # is it a POD file?
273     next FILE unless $file =~ /readme/i or $val =~ /\n=head/;
274    
275     # remove directory prefix
276     unless ($sloppy # no common root
277     or $file =~ s:^\Q$tar\E[^/]*/:: # common root, maybe alias
278     or ($TR{$tar} # common root, not aliased
279     and $file =~ s:^\Q$TR{$tar}\E::)
280     ) {
281     # try to determine an alias
282     warn "Bad directory prefix: '$file'\n";
283     my ($prefix) = split /\//, $file;
284    
285     while ($key = (tied %tar)->NEXTKEY) {
286     my $file = fname($key);
287    
288     next if $file =~ /\/$/;
289     unless ($file =~ m:^$prefix/: or $file eq $prefix) {
290     warn "Archive contains different prefixes: $prefix,$file\n";
291     $prefix = '';
292     last;
293     }
294     }
295     if ($prefix) {
296     print "Please alias '$tar' to '$prefix' next time!\n";
297     print "See alias table later.\n";
298     $NEW_ALIAS{$tar} = $prefix;
299     $tb->delete_by_key($parent);
300     next ARCHIVE;
301     } else {
302     print "Assuming that tar file name $tar is a valid prefix\n";
303     $sloppy = 1;
304    
305     # We may reset too much here! But that this is not exact
306     # science anyway. Maybe we should ignore using 'next ARCHIVE'.
307    
308     $key = (tied %tar)->FIRSTKEY;
309     redo FILE;
310     }
311     }
312    
313     # remove /lib prefix
314     $file =~ s:^lib/::;
315    
316     # generate new path
317     my $path = "$DATA/$tar/$file";
318    
319     my ($sbase, $sdir) = fileparse($path);
320     my $fh;
321    
322     unless ($OPT{test}) {
323     if (-f $path) {
324     index_pod(file => $path, remove => 1);
325     unlink $path or warn "Could not unlink '$path' $!\n";
326     } elsif (!-d $sdir) {
327     mkpath($sdir,1,0755) or die "Could not mkpath($sdir): $!\n";
328     }
329     $fh = new IO::File "> $path";
330     die "Could not write '$path': $!\n" unless $fh;
331     }
332    
333     if ($file =~ /readme|install/i) { # make READMEs verbatim pods
334     $val =~ s/\n/\n /g;
335     $val = "=head1 NAME\n\n$tar $file\n\n=head1 DESCRIPTION\n\n $val"
336     unless $val =~ /^=head/m;
337     } else { # remove non-pod stuff
338     my $nval = $val; $val = '';
339     my $cutting = 1;
340    
341     for (split /\n/, $nval) {
342     if (/^=cut|!NO!SUBS!/) {
343     $cutting = 1;
344     } elsif ($cutting and /^=head/) {
345     $cutting = 0;
346     }
347     unless ($cutting) {
348     $val .= $_ . "\n";
349     }
350     }
351     }
352     unless ($OPT{test}) {
353     $fh->print($val);
354     index_pod(file => $path, parent => $parent,
355     text => $val, source => $ARCHIVE{$tar});
356     }
357     }
358    
359     if ($LWP and !$OPT{keep}) {
360     unlink $TAR or warn
361     "Could not unlink '$TAR': $!\n";
362     }
363     }
364    
365     if (%NEW_ALIAS) {
366     print "\%ALIAS = (\n";
367     for (keys %NEW_ALIAS) {
368     print "\t'$_'\t=> '$NEW_ALIAS{$_}',\n";
369     }
370     print "\t);\n";
371     }
372    
373     # we are done
374     $db->close();
375     exit;
376    
377     sub fname ($) {
378     my $key = shift;
379     my ($ntar, $file) = split $;, $key;
380    
381     # remove leading './' - shudder
382     $file =~ s/^\.\///;
383    
384     return($file);
385     }
386    
387     sub myget {
388     my $tar = shift;
389     my $TAR;
390    
391     if ($LWP) { # fetch the archive
392     if ($OPT{keep}) {
393     $TAR = "$OPT{keep}/$ARCHIVE{$tar}";
394     print "Keeping in '$TAR'\n" unless -e $TAR;
395     my ($base, $path) = fileparse($TAR);
396     unless (-d $path) {
397     mkpath($path,1,0755) or
398     die "Could not mkpath($path)\n";
399     }
400     } else {
401     $TAR = "/tmp/$tar.tar.gz";
402     }
403     unless (-e $TAR) { # lwp mirror seems to fetch ftp: in any case?
404     print "Fetching $OPT{cpan}/$ARCHIVE{$tar}\n";
405     my $status = mirror("$OPT{cpan}/$ARCHIVE{$tar}", $TAR);
406     if ($status != &RC_OK and $status != &RC_NOT_MODIFIED) {
407     warn "Was unable to mirror '$ARCHIVE{$tar}, skipping'\n";
408     return;
409     }
410     }
411     }
412     $TAR;
413     }
414    
415     sub index_pod {
416     my %parm = @_;
417     my $did = $parm{file};
418     my $rel_did = $did;
419     my $abs_did = $did;
420    
421     if ($rel_did =~ s:$DIR/::) {
422     $abs_did = "$DIR/$rel_did";
423     }
424    
425     undef $did;
426    
427     # check for both variants
428     if ($tb->have('docid' => $rel_did)) {
429     $did = $rel_did;
430     } elsif ($tb->have('docid' => $abs_did)) {
431     $did = $abs_did;
432     }
433     if ($did) { # have it version
434     if (!$parm{remove}) {
435     warn "duplicate: $did\n";
436     return;
437     }
438     } else { # not seen yet
439     $did = $rel_did;
440     if ($parm{remove}) {
441     print "missing: $did\n";
442     return;
443     }
444     }
445    
446     $parm{'text'} ||= WAIT::Document::Find->FETCH($abs_did);
447    
448     unless (defined $parm{'text'}) {
449     print "unavailable: $did\n";
450     return;
451     }
452    
453     my $record = $layout->split($parm{'text'});
454     $record->{size} = length($parm{'text'});
455     my $headline = $record->{name} || $did;
456    
457     $headline =~ s/^$DATA//o; # $did
458     $headline =~ s/\s+/ /g; $headline =~ s/^\s+//;
459    
460     printf "%s %s\n", ($parm{remove})?'-':'+', substr($headline,0,70);
461     if ($parm{remove}) {
462     $tb->delete('docid' => $did,
463     headline => $headline,
464     %{$record});
465     } else {
466     $tb->insert('docid' => $did,
467     headline => $headline,
468     source => $parm{source},
469     parent => $parm{parent},
470     %{$record});
471     }
472     }
473    
474     # This *must* remove the version in *any* case. It should compute a
475     # resonable version number - but usually mtimes should be used.
476     sub version {
477     local ($_) = @_;
478    
479     # remove alpha/beta postfix
480     s/([-_\d])(a|b|alpha|beta|src)$/$1/;
481    
482     # jperl1.3@4.019.tar.gz
483     s/@\d.\d+//;
484    
485     # oraperl-v2.4-gk.tar.gz
486     s/-v(\d)/$1/;
487    
488     # lettered versions - shudder
489     s/([-_\d\.])([a-z])([\d\._])/sprintf "$1%02d$3", ord(lc $2) - ord('a') /ei;
490     s/([-_\d\.])([a-z])$/sprintf "$1%02d", ord(lc $2) - ord('a') /ei;
491    
492     # thanks libwww-5b12 ;-)
493     s/(\d+)b/($1-1).'.'/e;
494     s/(\d+)a/($1-2).'.'/e;
495    
496     # replace '-pre' by '0.'
497     s/-pre([\.\d])/-0.$1/;
498     s/\.\././g;
499     s/(\d)_(\d)/$1$2/g;
500    
501     # chop '[-.]' and thelike
502     s/\W$//;
503    
504     # ram's versions Storable-0.4@p
505     s/\@/./;
506    
507     if (s/[-_]?(\d+)\.(0\d+)\.(\d+)$//) {
508     return($_, $1 + "0.$2" + $3 / 1000000);
509     } elsif (s/[-_]?(\d+)\.(\d+)\.(\d+)$//) {
510     return($_, $1 + $2/1000 + $3 / 1000000);
511     } elsif (s/[-_]?(\d+\.[\d_]+)$//) {
512     return($_, $1);
513     } elsif (s/[-_]?([\d_]+)$//) {
514     return($_, $1);
515     } elsif (s/-(\d+.\d+)-/-/) { # perl-4.019-ref-guide
516     return($_, $1);
517     } else {
518     if ($_ =~ /\d/) { # smells like an unknown scheme
519     warn "Odd version Numbering: '$File::Find::name'\n";
520     return($_, undef);
521     } else { # assume version 0
522     warn "No version Numbering: '$File::Find::name'\n";
523     return($_, 0);
524     }
525    
526     }
527     }
528    
529     sub wanted {
530     my $mtime = shift; # called by parse_file_ls();
531    
532     return unless /^(.*)\.tar(\.gz|\.Z)$/;
533     my ($archive, $version) = version($1);
534    
535     unless (defined $version) {
536     warn "Skipping $1\n";
537     return;
538     }
539    
540     # Check for file alias
541     $archive = $ALIAS{$archive} if $ALIAS{$archive};
542    
543     # Check for path alias.
544     if ($File::Find::name =~ m(/CPAN/(?:source/)?(.*\Q$archive\E))) {
545     if ($ALIAS{$1}) {
546     $archive = $ALIAS{$1};
547     }
548     }
549    
550     if ($OPT{trust_mtime}) {
551     $version = $mtime;
552     } else {
553     $version =~ s/(\d)_/$1/;
554     $version ||= $mtime; # mtime
555     }
556    
557     if (!exists $ARCHIVE{$archive}
558     or $VERSION{$archive} < $version) {
559     $ARCHIVE{$archive} = $File::Find::name;
560     $VERSION{$archive} = $version;
561     }
562     }
563    
564     sub clean_database {
565     my %parm = @_;
566    
567     my $db = WAIT::Database->open(
568     name => $parm{database},
569     'directory' => $parm{dir},
570     )
571     or die "Could not open database '$parm{dir}/$parm{database}': $@";
572     my $tbl = $db->table(name => $parm{table});
573     if ($tbl) {
574     $tbl->drop or
575     die "Could not open table '$parm{tabel}': $@";
576     }
577    
578     $db->close;
579     }
580    
581     sub create_table {
582     my %parm = @_;
583    
584     my $access = bless {}, 'WAIT::Document::Find';
585    
586     my $stem = [{
587     'prefix' => ['isotr', 'isolc'],
588     'intervall' => ['isotr', 'isolc'],
589     }, 'isotr', 'isolc', 'split2', 'stop', 'Stem'];
590     my $text = [{
591     'prefix' => ['isotr', 'isolc'],
592     'intervall' => ['isotr', 'isolc'],
593     },
594     'isotr', 'isolc', 'split2', 'stop'];
595     my $sound = ['isotr', 'isolc', 'split2', 'Soundex'],;
596    
597     my $tb =
598     $parm{db}->create_table
599     (name => $parm{table},
600     attr => ['docid', 'headline', 'source', 'size', 'parent'],
601     keyset => [['docid']],
602     layout => $parm{layout},
603     access => $access,
604     invindex =>
605     [
606     'name' => $stem,
607     'synopsis' => $stem,
608     'bugs' => $stem,
609     'description' => $stem,
610     'text' => $stem,
611     'environment' => $text,
612     'example' => $text, 'example' => $stem,
613     'author' => $sound, 'author' => $stem,
614     ]
615     );
616     die "Could not create table '$parm{table}'" unless $tb;
617     $tb;
618     }
619    
620     my %MON;
621     my $YEAR;
622    
623     BEGIN {
624     my $i = 1;
625     for (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)) {
626     $MON{$_} = $i++;
627     }
628     $YEAR = (localtime(time))[5];
629     }
630    
631     # We could/should use Date::GetDate here
632     use Time::Local;
633     sub mtime {
634     my ($mon, $mday, $time) = @_;
635     my ($hour, $min, $year, $monn) = (0,0);
636    
637     if ($time =~ /(\d+):(\d+)/) {
638     ($hour, $min) = ($1, $2);
639     $year = $YEAR;
640     } else {
641     $year = $time;
642     }
643     $monn = $MON{$mon} || $MON{ucfirst lc $mon} || warn "Unknown month: '$mon'";
644     my $guess = timelocal(0,$min,$hour,$mday,$monn-1,$year);
645     if ($guess > time) {
646     $guess = timelocal(0,$min,$hour,$mday,$monn-1,$year-1);
647     }
648     $guess;
649     }
650    
651    
652     __END__
653     ## ###################################################################
654     ## pod
655     ## ###################################################################
656    
657     =head1 NAME
658    
659     cpan - generate an WAIT index for CPAN
660    
661     =head1 SYNOPSIS
662    
663     B<cpan>
664     [B<-clean>] [B<-noclean>]
665     [B<-cpan> I<url or directory>]
666     [B<-database> I<dbname>]
667     [B<-dir> I<directory>]
668     [B<-force>] [B<-noforce>]
669     [B<-keep> I<directory>]
670     [B<-match> I<regexp>]
671     [B<-table> I<table name>]
672     [B<-test> I<level>]
673     [B<-trust_mtime>] [B<-notrust_mtime>]
674    
675     =head1 DESCRIPTION
676    
677     TBS
678    
679     =head1 OPTIONS
680    
681     =over 5
682    
683     =item B<-clean> / B<-noclean>
684    
685     Clean the table befor indexing. Default is B<off>.
686    
687     =item B<-cpan> I<url or directory>
688    
689     Default directory or URL for indexing. If an URL is given, there
690     currently must be a file F<indices/find-ls.gz> relative to it which
691     contains the output of C<find . -ls | gzip>.
692     Default is F<ftp://ftp.rz.ruhr-uni-bochum.de/pub/CPAN>.
693    
694    
695     =item B<-database> I<dbname>
696    
697     Specify database name. Default is F<DB>.
698    
699     =item B<-dir> I<directory>
700    
701     Alternate directory were databases are located. Default is the
702     directory specified during configuration of WAIT.
703    
704     =item B<-force>
705    
706     Force reindexing, even if B<cpan> thinks files are up to date.
707     Default is B<off>
708    
709     =item B<-keep> I<directory>
710    
711     If fetching from a remote server, keep files in I<directory>. Default is
712     F</app/unido-i06/src/share/lang/perl/96a/CPAN/sources>.
713    
714     =item B<-match> I<regexp>
715    
716     Limit to patches matching I<regexp>. Default is F<authors/id/>.
717    
718     =item B<-table> I<table name>
719    
720     Specify an alternate table name. Default is C<cpan>.
721    
722     =item B<-test> I<level>
723    
724     Set test level, were B<0> means normal operation, B<1> means, don't
725     really index and B<2> means, don't even get archives and examine them.
726    
727     =item B<-trust_mtime> / B<-notrust_mtime>
728    
729     If B<on>, the files mtimes are used to decide, which version of an
730     archive is the newest. If b<off>, the version extracted is used
731     (beware, there are far more version numbering schemes than B<cpan> can
732     parse).
733    
734     =head1 AUTHOR
735    
736     Ulrich Pfeifer E<lt>F<pfeifer@ls6.informatik.uni-dortumund.de>E<gt>

Properties

Name Value
cvs2svn:cvs-rev 1.1
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26