summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2014-10-10 16:08:52 +0200
committerMichael Schroeder <mls@suse.de>2014-10-10 16:08:52 +0200
commit4bd43378bc96476f078eb3558ea5811c40435556 (patch)
treeaa81ba168b383e68681768ef50166c9ba2518470
parent51a9a9243180956d1b0287f735382978f9b58590 (diff)
Add support for conflicts/obsoletes handling in expander
-rw-r--r--Build.pm95
-rwxr-xr-xcreaterepomddeps4
-rwxr-xr-xcreaterpmdeps9
-rwxr-xr-xcreateyastdeps4
-rwxr-xr-xexpanddeps26
5 files changed, 125 insertions, 13 deletions
diff --git a/Build.pm b/Build.pm
index 43021fe..089cb7f 100644
--- a/Build.pm
+++ b/Build.pm
@@ -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 });
}
diff --git a/expanddeps b/expanddeps
index 73a85e6..48272b7 100755
--- a/expanddeps
+++ b/expanddeps
@@ -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;
}