diff options
author | Michael Schroeder <mls@suse.de> | 2014-10-10 16:08:52 +0200 |
---|---|---|
committer | Michael Schroeder <mls@suse.de> | 2014-10-10 16:08:52 +0200 |
commit | 4bd43378bc96476f078eb3558ea5811c40435556 (patch) | |
tree | aa81ba168b383e68681768ef50166c9ba2518470 | |
parent | 51a9a9243180956d1b0287f735382978f9b58590 (diff) |
Add support for conflicts/obsoletes handling in expander
-rw-r--r-- | Build.pm | 95 | ||||
-rwxr-xr-x | createrepomddeps | 4 | ||||
-rwxr-xr-x | createrpmdeps | 9 | ||||
-rwxr-xr-x | createyastdeps | 4 | ||||
-rwxr-xr-x | expanddeps | 26 |
5 files changed, 125 insertions, 13 deletions
@@ -570,15 +570,19 @@ sub get_cbinstalls { return @{[]}; } sub readdeps { my ($config, $pkginfo, @depfiles) = @_; - my %requires = (); + my %requires; local *F; my %provides; + my %pkgconflicts; + my %pkgobsoletes; my $dofileprovides = %{$config->{'fileprovides'}}; for my $depfile (@depfiles) { if (ref($depfile) eq 'HASH') { for my $rr (keys %$depfile) { $provides{$rr} = $depfile->{$rr}->{'provides'}; $requires{$rr} = $depfile->{$rr}->{'requires'}; + $pkgconflicts{$rr} = $depfile->{$rr}->{'conflicts'}; + $pkgobsoletes{$rr} = $depfile->{$rr}->{'obsoletes'}; } next; } @@ -607,7 +611,7 @@ sub readdeps { } my %ss; @ss = grep {!$ss{$_}++} @ss; - if ($s =~ /^(P|R):(.*)\.(.*)-\d+\/\d+\/\d+:$/) { + if ($s =~ /^(P|R|C|O):(.*)\.(.*)-\d+\/\d+\/\d+:$/) { my $pkgid = $2; my $arch = $3; if ($1 eq "R") { @@ -615,6 +619,16 @@ sub readdeps { $pkginfo->{$pkgid}->{'requires'} = \@ss if $pkginfo; next; } + if ($1 eq "C") { + $pkgconflicts{$pkgid} = \@ss; + $pkginfo->{$pkgid}->{'conflicts'} = \@ss if $pkginfo; + next; + } + if ($1 eq "O") { + $pkgobsoletes{$pkgid} = \@ss; + $pkginfo->{$pkgid}->{'obsoletes'} = \@ss if $pkginfo; + next; + } # handle provides $provides{$pkgid} = \@ss; if ($pkginfo) { @@ -633,6 +647,8 @@ sub readdeps { } $config->{'providesh'} = \%provides; $config->{'requiresh'} = \%requires; + $config->{'pkgconflictsh'} = \%pkgconflicts; + $config->{'pkgobsoletesh'} = \%pkgobsoletes; makewhatprovidesh($config); } @@ -666,6 +682,8 @@ sub forgetdeps { delete $config->{'providesh'}; delete $config->{'whatprovidesh'}; delete $config->{'requiresh'}; + delete $config->{'pkgconflictsh'}; + delete $config->{'pkgobsoletesh'}; } my %addproviders_fm = ( @@ -737,12 +755,47 @@ sub addproviders { return \@p; } +# XXX: should also check the package EVR +sub nevrmatch { + my ($config, $r, @p) = @_; + my $rn = $r; + $rn =~ s/\s*([<=>]{1,2}).*$//; + return grep {$_ eq $rn} @p; +} + +sub checkconflicts { + my ($config, $ins, $q, $eq, @r) = @_; + my $whatprovides = $config->{'whatprovidesh'}; + for my $r (@r) { + my @eq = grep {$ins->{$_}} @{$whatprovides->{$r} || addproviders($config, $r)}; + next unless @eq; + push @$eq, map {"provider $q conflicts with installed $_"} @eq; + return 1; + } + return 0; +} + +sub checkobsoletes { + my ($config, $ins, $q, $eq, @r) = @_; + my $whatprovides = $config->{'whatprovidesh'}; + for my $r (@r) { + my @eq = grep {$ins->{$_}} nevrmatch($config, $r, @{$whatprovides->{$r} || addproviders($config, $r)}); + next unless @eq; + push @$eq, map {"provider $q is obsoleted by installed $_"} @eq; + return 1; + } + return 0; +} + sub expand { my ($config, @p) = @_; my $conflicts = $config->{'conflicth'}; + my $pkgconflicts = $config->{'pkgconflictsh'} || {}; + my $pkgobsoletes = $config->{'pkgobsoletesh'} || {}; my $prefer = $config->{'preferh'}; my $ignore = $config->{'ignoreh'}; + my $ignoreconflicts = $config->{'expandflags:ignoreconflicts'}; my $whatprovides = $config->{'whatprovidesh'}; my $requires = $config->{'requiresh'}; @@ -777,10 +830,19 @@ sub expand { push @p, $p; next; } + return (undef, "$q[0] $aconflicts{$q[0]}") if $aconflicts{$q[0]}; print "added $q[0] because of $p (direct dep)\n" if $expand_dbg; push @p, $q[0]; $p{$q[0]} = 1; - $aconflicts{$_} = 1 for @{$conflicts->{$q[0]} || []}; + $aconflicts{$_} = "conflict from project config with $q[0]" for @{$conflicts->{$q[0]} || []}; + if (!$ignoreconflicts) { + for my $r (@{$pkgconflicts->{$q[0]}}) { + $aconflicts{$_} = "conflicts with installed $q[0]" for @{$whatprovides->{$r} || addproviders($config, $r)}; + } + for my $r (@{$pkgobsoletes->{$q[0]}}) { + $aconflicts{$_} = "is obsoleted by installed $q[0]" for nevrmatch($config, $r, @{$whatprovides->{$r} || addproviders($config, $r)}); + } + } } push @p, @directdepsend; @@ -798,13 +860,24 @@ sub expand { next if grep {$p{$_}} @q; next if grep {$xignore{$_}} @q; next if grep {$ignore->{"$p:$_"} || $xignore{"$p:$_"}} @q; + my @eq = map {"provider $_ $aconflicts{$_}"} grep {$aconflicts{$_}} @q; @q = grep {!$aconflicts{$_}} @q; + if (!$ignoreconflicts) { + for my $q (splice @q) { + push @q, $q unless @{$pkgconflicts->{$q} || []} && checkconflicts($config, \%p, $q, \@eq, @{$pkgconflicts->{$q}}); + } + for my $q (splice @q) { + push @q, $q unless @{$pkgobsoletes->{$q} || []} && checkobsoletes($config, \%p, $q, \@eq, @{$pkgobsoletes->{$q}}); + } + } if (!@q) { + my $eq = @eq ? " (".join(', ', @eq).")" : ''; + my $msg = @eq ? 'conflict for providers of' : 'nothing provides'; if ($r eq $p) { - push @rerror, "nothing provides $r"; + push @rerror, "$msg $r$eq"; } else { - next if $r =~ /^\//; - push @rerror, "nothing provides $r needed by $p"; + next if $r =~ /^\// && !@eq; + push @rerror, "$msg $r needed by $p$eq"; } next; } @@ -847,7 +920,15 @@ sub expand { push @p, $q[0]; print "added $q[0] because of $p:$r\n" if $expand_dbg; $p{$q[0]} = 1; - $aconflicts{$_} = 1 for @{$conflicts->{$q[0]} || []}; + $aconflicts{$_} = "conflict from project config with $q[0]" for @{$conflicts->{$q[0]} || []}; + if (!$ignoreconflicts) { + for my $r (@{$pkgconflicts->{$q[0]}}) { + $aconflicts{$_} = "conflicts with installed $q[0]" for @{$whatprovides->{$r} || addproviders($config, $r)}; + } + for my $r (@{$pkgobsoletes->{$q[0]}}) { + $aconflicts{$_} = "is obsoleted by installed $q[0]" for nevrmatch($config, $r, @{$whatprovides->{$r} || addproviders($config, $r)}); + } + } @error = (); $doamb = 0; } diff --git a/createrepomddeps b/createrepomddeps index 8d9105b..fe89a57 100755 --- a/createrepomddeps +++ b/createrepomddeps @@ -383,6 +383,10 @@ sub printasbuildcachefile(@) $deps = deps2string(@{$pkg->{'conflicts'}}); print "C:$id$deps\n"; } + if (@{$pkg->{'obsoletes'} || []}) { + $deps = deps2string(@{$pkg->{'obsoletes'}}); + print "O:$id$deps\n"; + } my $tag = sprintf("%s-%s-%s %s", $pkg->{'name'}, diff --git a/createrpmdeps b/createrpmdeps index 7a40dda..191c850 100755 --- a/createrpmdeps +++ b/createrpmdeps @@ -36,6 +36,7 @@ my %tag; my %oldp; my %oldr; my %oldc; +my %oldo; if (defined($rpmdepfile) && open(F, '<', $rpmdepfile)) { while (<F>) { chomp; @@ -45,6 +46,8 @@ if (defined($rpmdepfile) && open(F, '<', $rpmdepfile)) { $oldr{$1} = $_; } elsif (/^C:([^ ]): /) { $oldc{$1} = $_; + } elsif (/^O:([^ ]): /) { + $oldo{$1} = $_; } } close F; @@ -98,10 +101,12 @@ foreach my $dir (@ARGV) { my %newp; my %newr; my %newc; + my %newo; for (@known) { $newp{$_} = $oldp{$_} if $oldp{$_}; $newr{$_} = $oldr{$_} if $oldr{$_}; $newc{$_} = $oldc{$_} if $oldc{$_}; + $newo{$_} = $oldo{$_} if $oldo{$_}; } my @todo = grep {!($newp{$_} && $newr{$_})} @known; @@ -109,11 +114,12 @@ foreach my $dir (@ARGV) { for my $known (@todo) { my $path = $known2path{$known}; if ($path =~ /\.rpm$/) { - my %res = Build::Rpm::rpmq($path, 1000, 1001, 1002, 1006, 1022, 1047, 1049, 1048, 1050, 1053, 1054, 1055, 1112, 1113); + my %res = Build::Rpm::rpmq($path, 1000, 1001, 1002, 1006, 1022, 1047, 1049, 1048, 1050, 1053, 1054, 1055, 1090, 1112, 1113, 1114, 1115); next unless %res; Build::Rpm::add_flagsvers(\%res, 1047, 1112, 1113); Build::Rpm::add_flagsvers(\%res, 1049, 1048, 1050); Build::Rpm::add_flagsvers(\%res, 1054, 1053, 1055); + Build::Rpm::add_flagsvers(\%res, 1090, 1114, 1115); my $id = $known; $id =~ s/.*-//; if ($known ne "$res{1000}->[0].$res{1022}->[0]-$id") { @@ -134,6 +140,7 @@ foreach my $dir (@ARGV) { $newp{$known} = "P:$known: ".join(' ', @{$res{1047} || []}); $newr{$known} = "R:$known: ".join(' ', @{$res{1049} || []}); $newc{$known} = "C:$known: ".join(' ', @{$res{1054} || []}) if @{$res{1054} || []}; + $newo{$known} = "O:$known: ".join(' ', @{$res{1090} || []}) if @{$res{1090} || []}; #$tag{$known} = $res{1000}->[0]."-".$res{1001}->[0]."-".$res{1002}->[0]." ".$res{1007}->[0]."-".$res{1006}->[0]; $tag{$known} = $res{1000}->[0]."-".$res{1001}->[0]."-".$res{1002}->[0]." ".$res{1006}->[0]; } else { diff --git a/createyastdeps b/createyastdeps index e38c46b..b135ae2 100755 --- a/createyastdeps +++ b/createyastdeps @@ -42,6 +42,7 @@ sub print_pkg($) print "P:$id$pkg->{'provides'}\n"; print "R:$id$pkg->{'requires'}\n"; print "C:$id$pkg->{'conflicts'}\n" if $pkg->{'conflicts'}; + print "O:$id$pkg->{'obsoletes'}\n" if $pkg->{'obsoletes'}; my $tag = sprintf("%s-%s-%s %s", $pkg->{'name'}, $pkg->{'version'}, @@ -63,6 +64,7 @@ sub callback $pkg->{'provides'} = join(' ', @{$pkg->{'provides'}}); $pkg->{'requires'} = join(' ', @{$pkg->{'requires'}}) if $pkg->{'requires'}; $pkg->{'conflicts'} = join(' ', @{$pkg->{'conflicts'}}) if $pkg->{'conflicts'}; + $pkg->{'obsoletes'} = join(' ', @{$pkg->{'obsoletes'}}) if $pkg->{'obsoletes'}; $pkg->{'baseurl'} = $url; my @data = split(' ', $pkg->{'location'}); # multi cd support hack @@ -92,6 +94,6 @@ for my $url (@ARGV) { my @order = (); my $pkgs = Build::Susetags::parse($packages, - { 'Loc' => 'location', 'Prv' => 'provides', 'Req' => 'requires', 'Con' => 'conflicts', 'Tim' => 'buildtime' }, + { 'Loc' => 'location', 'Prv' => 'provides', 'Req' => 'requires', 'Con' => 'conflicts', 'Obs' => 'obsoletes', 'Tim' => 'buildtime' }, { cb => \&callback, data => $url }); } @@ -115,7 +115,7 @@ if (defined($dist) && $dist ne '') { $binarytype = $cf->{'binarytype'} if $cf->{'binarytype'} && $cf->{'binarytype'} ne 'UNDEFINED'; } -my (%fn, %prov, %req, %con); +my (%fn, %prov, %req, %con, %obs); my %packs; my %repo; @@ -125,7 +125,7 @@ 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, $pkgC); +my ($pkgF, $pkgP, $pkgR, $pkgC, $pkgO); my $verscmp = \&Build::Rpm::verscmp; @@ -146,6 +146,8 @@ while(<F>) { $pkgR = $2; } elsif (/^C:(.*?)-\d+\/\d+\/\d+: (.*)$/) { $pkgC = $2; + } elsif (/^O:(.*?)-\d+\/\d+\/\d+: (.*)$/) { + $pkgO = $2; } elsif (/^I:(.*?)-\d+\/\d+\/\d+: (.*)$/) { next if $packs_done{$1}; my ($i, $newid) = ($1, $2); @@ -159,13 +161,16 @@ while(<F>) { $prov{$i} = $pkgP; delete $req{$i}; delete $con{$i}; + delete $obs{$i}; $req{$i} = $pkgR; - $con{$i} = $pkgC; + $con{$i} = $pkgC if defined $pkgC; + $obs{$i} = $pkgO if defined $pkgO; } undef $pkgF; undef $pkgP; undef $pkgR; undef $pkgC; + undef $pkgO; } elsif ($_ eq 'D:') { %packs_done = %ids; } @@ -211,7 +216,7 @@ $dofileprovides = 1 if ($binarytype || 'rpm') ne 'rpm'; for my $pack (keys %packs) { my $r = {}; - my (@s, $s, @pr, @re, @co); + my (@s, $s, @pr, @re, @co, @ob); @s = split(' ', $prov{$packs{$pack}} || ''); while (@s) { $s = shift @s; @@ -256,9 +261,22 @@ for my $pack (keys %packs) { splice(@s, 0, 2); } } + @s = split(' ', $obs{$packs{$pack}} || ''); + while (@s) { + $s = shift @s; + next if !$dofileprovides && $s =~ /^\//; + push @ob, $s; + while (@s && $s[0] =~ /^[\(<=>|]/) { + $ob[-1] .= " $s[0] $s[1]"; + $ob[-1] =~ s/ \((.*)\)/ $1/; + $ob[-1] =~ s/(<|>){2}/$1/; + splice(@s, 0, 2); + } + } $r->{'provides'} = \@pr; $r->{'requires'} = \@re; $r->{'conflicts'} = \@co; + $r->{'obsoletes'} = \@ob; $repo{$pack} = $r; } |