From 6c319fe147813dd63422a1b9491a820e11a77045 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Mon, 23 Jul 2012 20:29:41 +0100 Subject: [PATCH] better dep resolver Change-Id: Id14236857dfef28e524b3ddeb7259383f7ef8f7e --- do_expanddeps | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100755 do_expanddeps diff --git a/do_expanddeps b/do_expanddeps new file mode 100755 index 0000000..85ec9c3 --- /dev/null +++ b/do_expanddeps @@ -0,0 +1,270 @@ +#!/usr/bin/perl -w + +BEGIN { + unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build'); +} + +use strict; + +use Build; + +my ($dist, $rpmdeps, $archs, $configdir, $useusedforbuild); + +while (@ARGV) { + if ($ARGV[0] eq '--dist') { + shift @ARGV; + $dist = shift @ARGV; + next; + } + if ($ARGV[0] eq '--depfile') { + shift @ARGV; + $rpmdeps = shift @ARGV; + next; + } + if ($ARGV[0] eq '--archpath') { + shift @ARGV; + $archs = shift @ARGV; + next; + } + if ($ARGV[0] eq '--configdir') { + shift @ARGV; + $configdir = shift @ARGV; + next; + } + if ($ARGV[0] eq '--useusedforbuild') { + shift @ARGV; + $useusedforbuild = 1; + next; + } + if ($ARGV[0] eq '--define') { + shift @ARGV; + my $def = shift @ARGV; + Build::define($def); + next; + } + if ($ARGV[0] eq '--with') { + shift @ARGV; + my $def = shift @ARGV; + Build::define("_with_$def --with-$def"); + next; + } + if ($ARGV[0] eq '--without') { + shift @ARGV; + my $def = shift @ARGV; + Build::define("_without_$def --without-$def"); + next; + } + last; +} +$configdir = '.' unless defined $configdir; +$archs = '' unless defined $archs; +die("you must specfiy a depfile!\n") unless defined $rpmdeps; + +my @extradeps = grep {!/(^|\/)PKGBUILD$/ && !/\.(?:spec|dsc|kiwi)$/} @ARGV; +my @specs = grep {/(^|\/)PKGBUILD$/ || /\.(?:spec|dsc|kiwi)$/} @ARGV; +die("can only work with at most one spec\n") if @specs > 1; +my $spec = $specs[0]; + +my @archs = split(':', $archs); +if ($spec && $spec =~ /(^|\/)PKGBUILD$/) { + push @archs, 'any' unless grep {$_ eq 'any'} @archs; +} else { + push @archs, 'noarch' unless grep {$_ eq 'noarch'} @archs; +} + +my (%fn, %prov, %req); + +my %packs; +my %repo; +my %ids; + +my %packs_arch; +my %packs_done; +open(F, '<', $rpmdeps) || die("$rpmdeps: $!\n"); +# WARNING: the following code assumes that the 'I' tag comes last +my ($pkgF, $pkgP, $pkgR); +while() { + chomp; + if (/^F:(.*?)-\d+\/\d+\/\d+: (.*)$/) { + $pkgF = $2; + next if $fn{$1}; + $fn{$1} = $2; + my $pack = $1; + $pack =~ /^(.*)\.([^\.]+)$/ or die; + push @{$packs_arch{$2}}, $1; + } elsif (/^P:(.*?)-\d+\/\d+\/\d+: (.*)$/) { + $pkgP = $2; + next if $prov{$1}; + $prov{$1} = $2; + } elsif (/^R:(.*?)-\d+\/\d+\/\d+: (.*)$/) { + $pkgR = $2; + next if $req{$1}; + $req{$1} = $2; + } elsif (/^I:(.*?)-\d+\/\d+\/\d+: (.*)$/) { + if ($ids{$1} && $packs_done{$1} && defined($pkgF) && defined($pkgP) && defined($pkgR)) { + my $i = $1; + my $oldid = $ids{$1}; + my $newid = $2; + if (Build::Rpm::verscmp($oldid, $newid) < 0) { + $ids{$i} = $newid; + $fn{$i} = $pkgF; + $prov{$i} = $pkgP; + $req{$i} = $pkgR; + } + } else { + next if $ids{$1}; + $ids{$1} = $2; + } + undef $pkgF; + undef $pkgP; + undef $pkgR; + } elsif ($_ eq 'D:') { + %packs_done = %ids; + } +} +close F; + +for my $arch (@archs) { + $packs{$_} ||= "$_.$arch" for @{$packs_arch{$arch} || []}; +} + +# XXX: move to separate tool +if (!defined($dist) || $dist eq '') { + my $rpmarch = (grep {$fn{"rpm.$_"}} @archs)[0]; + if (!$rpmarch) { + $dist = 'default'; + } else { + my $rpmfn = $fn{"rpm.$rpmarch"}; + if ($rpmfn =~ /^[a-z]+:\/\//) { + require File::Temp; + my $tmpdir = File::Temp::tempdir('CLEANUP' => 1); + $rpmfn =~ s/.*\//$tmpdir\// unless system("$INC[0]/download", $tmpdir, $rpmfn); + } + my $rpmdist = ''; + if ($rpmfn =~ /^\// && -e $rpmfn) { + my %res = Build::Rpm::rpmq($rpmfn, 1010); + $rpmdist = $res{1010}->[0] || ''; + } + $dist = Build::dist_canon($rpmdist, $archs[0]); + # need some extra work for sles11 :( + if ($dist =~ /^sles11-/) { + my %res = Build::Rpm::rpmq($rpmfn, 1049); + $dist =~ s/^sles11-/sles11sp2-/ if grep {/^liblzma/} @{$res{1049} || []}; + } + } + print STDERR "Warning: distribution not specified, assuming '$dist' (see $configdir).\n"; +} + +my $cf = Build::read_config_dist($dist, $archs[0], $configdir); +$cf->{'warnings'} = 1; + +my $dofileprovides = %{$cf->{'fileprovides'}}; + +for my $pack (keys %packs) { + my $r = {}; + my (@s, $s, @pr, @re); + @s = split(' ', $prov{$packs{$pack}} || ''); + while (@s) { + $s = shift @s; + next if !$dofileprovides && $s =~ /^\//; + if ($s =~ /^rpmlib\(/) { + splice(@s, 0, 2); + next; + } + push @pr, $s; + splice(@s, 0, 2) if @s && $s[0] =~ /^[<=>]/; + } + @s = split(' ', $req{$packs{$pack}} || ''); + while (@s) { + $s = shift @s; + next if !$dofileprovides && $s =~ /^\//; + if ($s =~ /^rpmlib\(/) { + splice(@s, 0, 2); + next; + } + push @re, $s; + splice(@s, 0, 2) if @s && $s[0] =~ /^[<=>]/; + } + $r->{'provides'} = \@pr; + $r->{'requires'} = \@re; + $repo{$pack} = $r; +} + + +####################################################################### + +sub print_rpmlist +{ + for (@_) { + #print "$_ $fn{$packs{$_}}\n"; + print "$_\n" if exists $ids{$packs{$_}}; + } +} + +if ($useusedforbuild) { + die("Need a specfile/dscfile for --usedforbuild\n") unless defined $spec; + local *F; + open(F, '<', $spec) || die("$spec: $!\n"); + my @usedforbuild; + my @buildrequires; + while() { + chomp; + if (/^#\s*usedforbuild\s*(.*)$/) { + push @usedforbuild, split(' ', $1); + } + if (/^buildrequires:\s*(.*)$/i) { + push @buildrequires, split(' ', $1); + } + } + close F; + @usedforbuild = @buildrequires unless @usedforbuild; + @usedforbuild = Build::unify(@usedforbuild) if @usedforbuild; + my @errors; + for (@usedforbuild) { + push @errors, "package $_ not found" unless $packs{$_} && $fn{$packs{$_}}; + } + if (@errors) { + print STDERR "expansion error\n"; + print STDERR " $_\n" for @errors; + exit(1); + } + print_rpmlist(@usedforbuild); + exit(0); +} + +####################################################################### + +my ($packname, $packvers, $subpacks, @packdeps); +$subpacks = []; + +if ($spec) { + my $d; + if ($spec =~ /\.kiwi$/) { + # just set up kiwi root for now + $d = { + 'deps' => [ 'kiwi', 'zypper', 'createrepo', 'squashfs' ], + 'subpacks' => [], + }; + } else { + $d = Build::parse($cf, $spec); + } + $packname = $d->{'name'}; + $packvers = $d->{'version'}; + $subpacks = $d->{'subpacks'}; + @packdeps = @{$d->{'deps'} || []}; + push(@packdeps, @{$d->{'prereqs'}}) if $d->{'prereqs'}; +} + +Build::readdeps($cf, undef, \%repo); + +####################################################################### + +my @bdeps = Build::get_build($cf, $subpacks, @packdeps, @extradeps); + +if (!shift @bdeps) { + print STDERR "expansion error\n"; + print STDERR " $_\n" for @bdeps; + exit(1); +} + +print_rpmlist(@bdeps); -- 2.7.4