4 unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
12 use Digest::MD5 qw(md5 md5_hex md5_base64);
13 use File::Path qw(mkpath rmtree);
17 Getopt::Long::Configure("no_ignore_case");
20 my @primaryfiles = ();
23 my $baseurl; # current url
29 my $cachedir = "/var/cache/build";
36 _start => \&repomd_handle_data_start,
38 _start => \&repomd_handle_location,
47 _start => \&primary_handle_package_start,
48 _end => \&primary_handle_package_end,
49 name => { _text => \&primary_collect_text, _end => \&primary_store_text },
50 arch => { _text => \&primary_collect_text, _end => \&primary_store_text },
51 version => { _start => \&primary_handle_version },
52 'time' => { _start => \&primary_handle_time },
54 'rpm:provides' => { 'rpm:entry' => { _start => \&primary_handle_package_provides }, },
55 'rpm:requires' => { 'rpm:entry' => { _start => \&primary_handle_package_requires }, },
56 'rpm:conflicts' => { 'rpm:entry' => { _start => \&primary_handle_package_conflicts }, },
57 'rpm:obsoletes' => { 'rpm:entry' => { _start => \&primary_handle_package_obsoletes }, },
58 'rpm:buildhost' => { _text => \&primary_collect_text, _end => \&primary_store_text },
59 'rpm:sourcerpm' => { _text => \&primary_collect_text, _end => \&primary_store_text },
60 ### currently commented out, as we ignore file provides in createrpmdeps
62 # _start => \&primary_handle_file_start,
63 # _text => \&primary_collect_text,
64 # _end => \&primary_handle_file_end
67 location => { _start => \&primary_handle_package_location },
75 sub repomd_handle_data_start
80 my $attr = map_attrs(@_);
81 if($attr->{'type'} ne 'primary') {
86 sub repomd_handle_location
91 my $attr = map_attrs(@_);
92 if(exists $attr->{'href'}) {
93 push @primaryfiles, { location => $attr->{'href'} };
97 sub generic_handle_start
102 if(exists $cursor[-1]->[1]->{$el})
104 my $h = $cursor[-1]->[1]->{$el};
105 push @cursor, [$el, $h];
106 if(exists $h->{'_start'}) {
107 &{$h->{'_start'}}($p, $el, @_);
112 sub generic_handle_char
117 my $h = $cursor[-1]->[1];
119 if(exists $h->{'_text'}) {
120 &{$h->{'_text'}}($p, $text);
124 sub generic_handle_end
129 if(!defined $cursor[-1]->[0] || $cursor[-1]->[0] eq $el)
131 my $h = $cursor[-1]->[1];
133 if(exists $h->{'_end'}) {
134 &{$h->{'_end'}}($p, $el);
152 # expat does not guarantee that character data doesn't get split up
153 # between multiple calls
155 sub primary_collect_text
163 sub primary_store_text
168 $packages[-1]->{$cursor[-1]->[0]} = $textbuf;
172 sub primary_handle_package_start
177 my $attr = map_attrs(@_);
179 push @packages, { type => $attr->{'type'}, baseurl => $baseurl };
182 sub primary_handle_package_end
188 printasbuildcachefile(@packages);
191 foreach my $pkg (@packages) {
192 my $arch = $pkg->{'arch'};
193 $arch = 'src' if $pkg->{'arch'} eq 'nosrc';
194 next if ($arch eq 'src' && $opt_nosrc);
195 if(exists($old_seen->{$pkg->{'name'}}->{$arch})) {
196 my $pv = $old_seen->{$pkg->{'name'}}->{$arch}->{'ver'};
197 my $rv = $pkg->{'ver'}.'-'.$pkg->{'rel'};
198 my $vv = Build::Rpm::verscmp($pv, $rv, 0);
201 print $old_seen->{$pkg->{'name'}}->{$arch}->{'loc'}."\n";
202 $old_seen->{$pkg->{'name'}}->{$arch}->{'ver'} = $pkg->{'ver'}.'-'.$pkg->{'rel'};
203 $old_seen->{$pkg->{'name'}}->{$arch}->{'loc'} = $pkg->{'baseurl'} . $pkg->{'location'};
205 print $pkg->{'baseurl'} . $pkg->{'location'}."\n";
208 $old_seen->{$pkg->{'name'}}->{$arch}->{'ver'} = $pkg->{'ver'}.'-'.$pkg->{'rel'};
209 $old_seen->{$pkg->{'name'}}->{$arch}->{'loc'} = $pkg->{'baseurl'} . $pkg->{'location'};
216 sub primary_handle_version
221 my $attr = map_attrs(@_);
222 $packages[-1]->{'ver'} = $attr->{'ver'};
223 $packages[-1]->{'rel'} = $attr->{'rel'};
226 sub primary_handle_time
231 my $attr = map_attrs(@_);
232 $packages[-1]->{'filetime'} = $attr->{'file'};
233 $packages[-1]->{'buildtime'} = $attr->{'build'};
236 sub primary_handle_package_location
241 my $attr = map_attrs(@_);
242 $packages[-1]->{'location'} = $attr->{'href'};
245 sub primary_handle_file_start
250 my $attr = map_attrs(@_);
251 if(exists $attr->{'type'}) {
256 sub primary_handle_file_end
261 primary_handle_package_deps('provides', 'name', $textbuf);
274 sub primary_handle_package_deps
277 my $attr = map_attrs(@_);
279 if(exists $attr->{'flags'}) {
280 if(!exists($flagmap{$attr->{'flags'}})) {
281 print STDERR "bogus relation: ", $attr->{'flags'}, "\n";
284 $attr->{'flags'} = $flagmap{$attr->{'flags'}};
286 return if($attr->{'name'} =~ /^rpmlib\(/);
287 push @{$packages[-1]->{$dep}}, $attr;
291 sub primary_handle_package_conflicts
293 shift;shift; primary_handle_package_deps('conflicts', @_);
296 sub primary_handle_package_obsoletes
298 shift;shift; primary_handle_package_deps('obsoletes', @_);
301 sub primary_handle_package_requires
303 shift;shift; primary_handle_package_deps('requires', @_);
305 sub primary_handle_package_provides
307 shift;shift; primary_handle_package_deps('provides', @_);
312 return join(' ', map {
313 my $s = $_->{'name'};
314 if(exists $_->{'flags'}) {
315 $s .= ' '.$_->{'flags'}.' ';
316 $s .= $_->{'epoch'}.':' if(exists $_->{'epoch'} && $_->{'epoch'} != 0);
318 $s .= '-'.$_->{'rel'} if exists $_->{'rel'};
324 sub printasbuildcachefile(@)
326 foreach my $pkg (@_) {
327 next if $pkg->{'arch'} eq 'src' || $pkg->{'arch'} eq 'nosrc';
328 my $id = sprintf("%s.%s-%d/%d/%d: ",
334 print "F:".$id. $pkg->{'baseurl'} . $pkg->{'location'} . "\n";
336 my $deps = deps2string(@{$pkg->{'provides'}});
337 print "P:$id$deps\n";
339 $deps = deps2string(@{$pkg->{'requires'}});
340 print "R:$id$deps\n";
342 my $tag = sprintf("%s-%s-%s %s",
346 # $pkg->{'rpm:buildhost'},
347 $pkg->{'buildtime'});
357 my $dest = $dir . "repodata";
359 system($INC[0].'/download', $dest, $url . "repodata/repomd.xml");
365 "nosrc" => \$opt_nosrc,
366 "dump" => \$opt_dump,
368 "cachedir=s" => \$cachedir,
371 $opt_bc = 1 unless ($opt_dump || $opt_old);
373 my $p = new XML::Parser(
375 Start => \&generic_handle_start,
376 End => \&generic_handle_end,
377 Char => \&generic_handle_char
380 #my $url = '/mounts/mirror/SuSE/ftp.suse.com/pub/suse/update/10.1/';
381 for my $url (@ARGV) {
383 if ($url =~ /^zypp:\/\/([^\/]*)\/?/) {
385 my $repo = Build::Zypp::parsecfg($1);
386 die "can't parse $1\n" unless $repo;
387 my $type = $repo->{'type'};
388 if($type eq 'rpm-md') {
389 my $name = $repo->{'name'};
390 $dir = "/var/cache/zypp/raw/$name/";
392 $baseurl .= '/' unless $baseurl =~ /\/$/;
393 } elsif ($type eq 'yast2') {
395 exec ($INC[0].'/createyastdeps', $url);
397 die "unsupported repo type: $type\n";
399 } elsif ($url =~ /^http:\/\/([^\/]*)\/?/) {
400 my $repoid = md5_hex($url);
401 $dir = "$cachedir/$repoid/";
403 $baseurl .= '/' unless $baseurl =~ /\/$/;
404 getmetadata($baseurl, $dir);
405 } elsif ($url =~ /^arch\@/) {
406 exec ("$INC[0]/createarchdeps", "--cachedir=$cachedir", substr($url, 5));
409 $dir .= '/' unless $dir =~ /\/$/;
414 @cursor = ([undef, $repomdparser]);
416 $p->parsefile($dir . 'repodata/repomd.xml');
418 # print Dumper(\@primaryfiles);
420 foreach my $f (@primaryfiles) {
421 @cursor = ([undef, $primaryparser]);
423 my $u = $dir . $f->{'location'};
424 if ($url =~ /^http:\/\/([^\/]*)\/?/) {
425 if (system($INC[0].'/download', $dir . "repodata/", $baseurl . "repodata/" . basename($u))) {
426 die("download failed\n");
434 open($fh, '<', $u) or die "Error opening $u: $!\n";
436 use IO::Uncompress::Gunzip qw($GunzipError);
437 $fh = new IO::Uncompress::Gunzip $fh or die "Error opening $u: $GunzipError\n";
445 print Data::Dumper->Dump([\@packages], ['packages']); # caution: excessive memory consumption!
449 # my %amap = map { $_ => 1 } @archs;
450 # my $packages = do $rpmdepdump or die $!;
452 # foreach my $pkg (@$packages) {
453 # next if exists $packs{$pkg->{'name'}};
454 # next unless exists $amap{$pkg->{'arch'}};
455 # next if $pkg->{'arch'} eq 'src' || $pkg->{'arch'} eq 'nosrc';
456 # next if $pkg->{'location'} =~ /\.(?:patch|delta)\.rpm$/;
458 # my $pa = $pkg->{'name'}.'.'.$pkg->{'arch'};
459 # $packs{$pkg->{'name'}} = $pa;
460 # $fn{$pa} = $pkg->{'baseurl'}.$pkg->{'location'};
462 # # flags and version ignored
463 # my @pr = map { $_->{'name'} } @{$pkg->{'provides'}};
464 # my @re = map { $_->{'name'} } @{$pkg->{'requires'}};
465 # $r->{'provides'} = \@pr;
466 # $r->{'requires'} = \@re;
467 # $repo{$pkg->{'name'}} = $r;