summaryrefslogtreecommitdiff
path: root/Build.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Build.pm')
-rw-r--r--Build.pm129
1 files changed, 113 insertions, 16 deletions
diff --git a/Build.pm b/Build.pm
index 9e6fda3..089cb7f 100644
--- a/Build.pm
+++ b/Build.pm
@@ -1,3 +1,23 @@
+################################################################
+#
+# Copyright (c) 1995-2014 SUSE Linux Products GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or 3 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program (see the file COPYING); if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#
+################################################################
+
package Build;
use strict;
@@ -550,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;
}
@@ -578,20 +602,16 @@ sub readdeps {
next;
}
push @ss, shift @s;
- while (@s) {
- if ($s[0] =~ /^[\(<=>|]/) {
- $ss[-1] .= " $s[0] $s[1]";
- $ss[-1] =~ s/ \((.*)\)/ $1/;
- $ss[-1] =~ s/(<|>){2}/$1/;
- splice(@s, 0, 2);
- } else {
- last;
- }
+ while (@s && $s[0] =~ /^[\(<=>|]/) {
+ $ss[-1] .= " $s[0] $s[1]";
+ $ss[-1] =~ s/ \((.*)\)/ $1/;
+ $ss[-1] =~ s/(<|>){2}/$1/;
+ splice(@s, 0, 2);
}
}
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") {
@@ -599,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) {
@@ -617,6 +647,8 @@ sub readdeps {
}
$config->{'providesh'} = \%provides;
$config->{'requiresh'} = \%requires;
+ $config->{'pkgconflictsh'} = \%pkgconflicts;
+ $config->{'pkgobsoletesh'} = \%pkgobsoletes;
makewhatprovidesh($config);
}
@@ -650,6 +682,8 @@ sub forgetdeps {
delete $config->{'providesh'};
delete $config->{'whatprovidesh'};
delete $config->{'requiresh'};
+ delete $config->{'pkgconflictsh'};
+ delete $config->{'pkgobsoletesh'};
}
my %addproviders_fm = (
@@ -721,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'};
@@ -761,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;
@@ -782,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;
}
@@ -831,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;
}