OpenPKG CVS Repository
  http://cvs.openpkg.org/
  ____________________________________________________________________________

  Server: cvs.openpkg.org                  Name:   Michael van Elst
  Root:   /e/openpkg/cvs                   Email:  [EMAIL PROTECTED]
  Module: openpkg-re                       Date:   25-Nov-2002 14:25:45
  Branch: HEAD                             Handle: 2002112513254400

  Modified files:
    openpkg-re              openpkg-index

  Log:
    now supports indexing of RPM files

  Summary:
    Revision    Changes     Path
    1.14        +254 -32    openpkg-re/openpkg-index
  ____________________________________________________________________________

  Index: openpkg-re/openpkg-index
  ============================================================
  $ cvs diff -u -r1.13 -r1.14 openpkg-index
  --- openpkg-re/openpkg-index  19 Nov 2002 22:35:27 -0000      1.13
  +++ openpkg-re/openpkg-index  25 Nov 2002 13:25:44 -0000      1.14
  @@ -27,14 +27,35 @@
   
   use strict;
   
  +use Getopt::Std;
  +getopts('r:p:o:i');
  +use vars qw/$opt_r $opt_p $opt_o $opt_i/;
  +
  +use FileHandle;
   use DirHandle;
   
  +my $RPM = 'rpm';
  +my $R2C = 'rpm2cpio';
  +
  +#########################################################################
  +
   #
   # escape XML special characters for output in RDF file
   #
  +# remove trailing whitespace
  +# remove common leading whitespace
  +#
   sub e ($) {
       my($s) = @_;
  +    my($i);
   
  +    $i = undef;
  +    while ($s =~ /^(\s+)/g) {
  +        $i = $1 if !defined $i || length($1) < length($i);
  +    }
  +
  +    $s =~ s/^$i//mg;
  +    $s =~ s/\s+$//mg;
       $s =~ s/&/&amp;/sg;
       $s =~ s/</&lt;/sg;
       $s =~ s/>/&gt;/sg;
  @@ -285,7 +306,7 @@
       $o = find_options($map{'description'});
       $a = package2data($map{'*'}, $o);
       if (exists $map{'description'}) {
  -        $a->{'Description'} = $map{'description'};
  +        $a->{'Description'} = { '' => [ $map{'description'} ] };
       }
   
       return $a;
  @@ -334,10 +355,12 @@
       $tag = $k unless defined $tag;
       $i = ' ' x $i;
   
  -    $out = e($a->{$k});
  -    $out .= "\n" unless $out =~ /\n$/s;
  +    $out = e(n($a,$k));
  +    $out =~ s/\n+$//s;
   
  -    return "$i<$tag>\n$out$i</$tag>\n";
  +    return if $out eq '';
  +
  +    return "$i<$tag>\n$out\n$i</$tag>\n";
   }
   
   #
  @@ -403,18 +426,18 @@
   #
   sub xml_record ($$$) {
       my($fh, $a, $href) = @_;
  -    my($maj,$min,$rel,$srcrpm);
  +    my($maj,$min,$rel,$about);
   
  -    $srcrpm =
  +    $about =
           n($a,'Name').'-'.
           n($a,'Version').'-'.
  -        n($a,'Release').'.src.rpm';
  +        n($a,'Release');
   
       unless (defined $href) {
   
           # guess location from Information in Specfile
   
  -        $href = $srcrpm;
  +        $href = "$about.src.rpm";
           ($maj,$min,$rel) = n($a,'Release') =~ /^(\d+)\.(\d+)\.(\d+)/;
   
           if (defined $min) {
  @@ -437,7 +460,7 @@
       }
       
       print $fh <<EOFEOF;
  -    <rdf:Description about="$srcrpm" href="$href">
  +    <rdf:Description about="$about" href="$href">
   EOFEOF
   
       # fake Source attribute from Source\d attribtutes
  @@ -462,6 +485,7 @@
               /^Source\d*$/
           } keys %$a
       ]};
  +    delete $a->{'Source'} unless @{$a->{'Source'}->{''}};
   
       print $fh
           xml_tag(6, $a, 'Name'),
  @@ -474,11 +498,23 @@
           xml_tag(6, $a, 'Summary'),
           xml_tag(6, $a, 'URL'),
           xml_tag(6, $a, 'Vendor'),
  +        xml_tag(6, $a, 'SourceRPM'),
  +        xml_tag(6, $a, 'Arch'),
  +        xml_tag(6, $a, 'Os'),
  +        xml_tag(6, $a, 'BuildRoot'),
  +        xml_tag(6, $a, 'BuildHost'),
  +        xml_tag(6, $a, 'BuildSystem'),
  +        xml_tag(6, $a, 'BuildTime'),
  +        xml_tag(6, $a, 'Relocations'),
  +        xml_tag(6, $a, 'Size'),
  +        xml_tag(6, $a, 'Prefixes'),
  +        xml_tag(6, $a, 'Platform'),
           xml_bag(6, $a, 'BuildPreReq'),
           xml_bag(6, $a, 'PreReq'),
           xml_bag(6, $a, 'Provides'),
           xml_bag(6, $a, 'Conflicts'),
           xml_bag(6, $a, 'Source'),
  +        xml_bag(6, $a, 'Filenames'),
           xml_text(6, $a, 'Description');
   
       print $fh <<EOFEOF;
  @@ -488,38 +524,224 @@
   
   #####################################################################
   
  -my($prefix,$release,$dh,$d,$s,$a,$specpath);
  +sub rpm2spec ($) {
  +    my($fn) = @_;
  +    my($pipe) = new FileHandle("$R2C '$fn' |")
  +        or die "FATAL: cannot read '$fn' ($!)\n";
  +    my($buf,@hdr,$n,$m,$name,$step);
  +    my($spec);
  +
  +    while (read($pipe,$buf,110) == 110) {
  +        @hdr = unpack('a6a8a8a8a8a8a8a8a8a8a8a8a8a8',$buf);
  +        $n = hex($hdr[12]);      # filename length
  +        $m = int(($n+5)/4)*4-2;  # filename size (padded)
  +        last unless read($pipe,$buf,$m) == $m;
  +        $name = substr($buf,0,$n-1);
  +        $n = hex($hdr[7]);       # file length
  +        $m = int(($n+3)/4)*4;    # file size (padded)
  +        if ($name !~ /.spec$/) {
  +            while ($m > 0) {
  +                $step = $m > 8192 ? 8192 : $m;
  +                last unless read($pipe,$buf,$step);
  +                $m -= length($buf);
  +            }
  +        } else {
  +            if (read($pipe,$buf,$n) == $n) {
  +                $spec = $buf;
  +            }
  +            last;
  +        }
  +    }
  +    $pipe->close;
   
  -if ($#ARGV < 0) {
  -    print "usage: $0 [openpkg-src [release]]\n";
  -    die "\n";
  +    return $spec;
   }
   
  -$prefix = $ARGV[0];
  -die "FATAL: '$prefix' is not a directory\n" unless -d $prefix;
  +#####################################################################
   
  -if (defined $ARGV[1]) {
  -    $release = $ARGV[1];
  -} else {
  -    ($release) = $prefix =~ /.*(\d+\.\d+)/;
  +sub rpm2data ($$) {
  +    my($fn,$platform) = @_;
  +    my($q,$pipe,%a);
  +    my($t,$v);
  +
  +    $q = <<EOFEOF;
  +Name %{Name}
  +Version %{Version}
  +Release %{Release}
  +URL %{URL}
  +Summary %{Summary}
  +Copyright %{Copyright}
  +License %{License}
  +Distribution %{Distribution}
  +Vendor %{Vendor}
  +Group %{Group}
  +Packager %{Packager}
  +Prefixes %{Prefixes}
  +BuildRoot %{BuildRoot}
  +BuildHost %{BuildHost}
  +BuildTime %{BuildTime}
  +Arch %{Arch}
  +Os %{Os}
  +Size %{Size}
  +SigSize %{SigSize}
  +SigMD5 %{SigMD5}
  +SigPGP %{SigPGP}
  +SigGPG %{SigGPG}
  +SourceRPM %{SourceRPM}
  +[Patch %{Patch}
  +]
  +[Source %{Source}
  +]
  +[Filenames %{Filenames}
  +]
  +[Conflicts %{CONFLICTNAME} %|CONFLICTFLAGS?{%{CONFLICTFLAGS:depflags} 
%{CONFLICTVERSION}}:{}|
  +]
  +[PreReq %{REQUIRENAME} %|REQUIREFLAGS?{%{REQUIREFLAGS:depflags} 
%{REQUIREVERSION}}:{}|
  +]
  +[Provides %{PROVIDENAME} %|PROVIDEFLAGS?{%{PROVIDEFLAGS:depflags} 
%{PROVIDEVERSION}}:{}|
  +]
  +Description %{Description}
  +EOFEOF
  +
  +    $pipe = new FileHandle("$RPM -qp --qf '$q' '$fn' |")
  +        or die "FATAL: cannot read '$fn' ($!)\n";
  +    while (<$pipe>) {
  +        if (/^(\S+)\s+(.*?)\s*$/) {
  +            $t = $1;
  +            $v = $2;
  +        } elsif (/^(\s+.+?)\s*$/) {
  +            next unless defined $t;
  +            $v = $1;
  +        } else {
  +            $t = undef;
  +            next;
  +        }
  +
  +        if (exists $a{$t}) {
  +            $a{$t} .= "\n$v";
  +        } else {
  +            $a{$t} = $v;
  +        }
  +    }
  +    $pipe->close;
  +
  +    %a = map { $_ => $a{$_} }
  +         grep { $a{$_} ne '(none)' }
  +         keys %a;
  +    if ($a{'Relocations'} eq '(non relocatable)') {
  +        delete $a{'Relocations'}
  +    }
  +    $a{'Platform'} = "$a{'Arch'}-$platform-$a{'Os'}";
  +    $a{'PreReq'} =~ s/^rpmlib\(.*$//mg;
  +    $a{'Description'} = [ $a{'Description'} ];
  +
  +    return { map {
  +        $_ => { '' => (ref $a{$_} ? $a{$_} : [ split(/\n+/, $a{$_}) ]) }
  +    } keys %a };
   }
  -$release = 'CURRENT' if $release eq '';
   
  -$dh = new DirHandle($prefix)
  -    or die $!;
  +#####################################################################
  +
  +sub list_specdir ($) {
  +    my($dir) = @_;
  +    my($dh,$d,$path);
  +    my(@list);
  +
  +    $dh = new DirHandle($dir);
  +    while ($d = $dh->read) {
  +        next if $d =~ /^\.$/;
  +        $path = "$dir/$d/$d.spec";
  +        push @list, $path if -f $path;
  +    }
   
  -xml_head(\*STDOUT, $release);
  -while ($d = $dh->read) {
  -    next if $d =~ /^\./;
  -    $specpath = "$prefix/$d/$d.spec";
  -    if (-f $specpath) {
  -        $s = `cat $specpath`;
  -        if ($a = spec2data($s)) {
  -            xml_record(\*STDOUT, $a, undef);
  +    return \@list;
  +}
  +
  +sub list_rpmdir ($) {
  +    my($dir) = @_;
  +    my($dh,$d,$path);
  +    my(@list);
  +
  +    $dh = new DirHandle($dir);
  +    while ($d = $dh->read) {
  +        next if $d =~ /^\.$/ || $d !~ /\.rpm$/;
  +        $path = "$dir/$d";
  +        push @list, $path if -f $path;
  +    }
  +
  +    return \@list;
  +}
  +
  +sub readfile ($) {
  +    my($fn) = @_;
  +    my($fh) = new FileHandle $fn,'r'
  +        or die "FATAL: cannot read '$fn' ($!)\n";
  +    my(@l) = <$fh>;
  +    $fh->close;
  +    return join('',@l);
  +}
  +
  +#####################################################################
  +
  +sub write_index ($$$$) {
  +    my($fh,$release,$platform,$list) = @_;
  +    my($a,$h,$s);
  +
  +    foreach (@$list) {
  +        $a = undef;
  +        $h = undef;
  +        if (/\.spec$/) {
  +            $s = readfile($_);
  +            $a = spec2data($s);
  +        } elsif (/([^\/]+\.src\.rpm)$/) {
  +            $h = $1;
  +            $s = rpm2spec($_);
  +            $a = spec2data($s);
  +        } elsif (/([^\/]+\.rpm)$/) {
  +            $h = $1;
  +            $a = rpm2data($_, $platform);
  +        }
  +        if ($a) {
  +            xml_record($fh, $a, $h);
           } else {
  -            die "ERROR: cannot parse $specpath\n";
  +            warn "ERROR: cannot process $_\n";
           }
       }
   }
  -xml_foot(\*STDOUT);
  +
  +#####################################################################
  +
  +my($prefix,$list,$fh);
  +
  +if ($#ARGV < 0) {
  +    print "usage: $0 [-r release] [-p platform] [-o index.rdf] [-i] dir ...\n";
  +    die "\n";
  +}
  +
  +$opt_r = 'CURRENT' unless defined $opt_r;
  +$opt_p = 'unknown' unless defined $opt_p;
  +
  +if ($opt_r !~ /^(CURRENT|\d+\.\d+)$/) {
  +    die "FATAL: you must specify a release tag (CURRENT or x.y)\n";
  +}
  +
  +if (defined $opt_o) {
  +    $fh = new FileHandle $opt_o,'w'
  +        or die "FATAL: cannot write '$opt_o' ($!)\n";
  +} else {
  +    $fh = \*STDOUT;
  +}
  +
  +xml_head($fh, $opt_r);
  +foreach $prefix (@ARGV) {
  +    die "FATAL: $prefix is not a directory\n" unless -d $prefix;
  +    if ($opt_i) {
  +        $list = list_rpmdir($prefix);
  +    } else {
  +        $list = list_specdir($prefix);
  +    }
  +    write_index($fh, $opt_r, $opt_p, $list);
  +}
  +xml_foot($fh);
  +$fh->close if defined $opt_o;
   
______________________________________________________________________
The OpenPKG Project                                    www.openpkg.org
CVS Repository Commit List                     [EMAIL PROTECTED]

Reply via email to