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/&/&/sg; $s =~ s/</</sg; $s =~ s/>/>/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]