Skip to content

Commit

Permalink
Recognize Recommends relations of RPMs.
Browse files Browse the repository at this point in the history
When there are multiple candidate packages as a result of
Provides, the current obs-build gives an error: "have choice for".

However, according to http://www.rpm.org/wiki/PackagerDocs/Dependencies ,
Recommends tells the system to install the corresponding package
unless there is a conflict; thus, if there is a package recommended
(as described in issue openSUSE#302), obs-build shall install the recommended
package, resolving "have choice for" error.

To enable, OBS project should declare:
"BuildFlags: UseRecommendsForChoices=1"
or
"BuildFlags: UseRecommendsForChoices"
in its project config.

Fixes openSUSE#302

Signed-off-by: MyungJoo Ham <[email protected]>
  • Loading branch information
myungjoo committed Nov 21, 2016
1 parent cf84b41 commit 9558b05
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 8 deletions.
32 changes: 30 additions & 2 deletions Build.pm
Original file line number Diff line number Diff line change
Expand Up @@ -678,8 +678,8 @@ sub get_cbinstalls { return (); }

sub readdeps {
my ($config, $pkginfo, @depfiles) = @_;

my %requires;
my %recommends;
local *F;
my %provides;
my %pkgconflicts;
Expand All @@ -690,6 +690,7 @@ sub readdeps {
for my $rr (keys %$depfile) {
$provides{$rr} = $depfile->{$rr}->{'provides'};
$requires{$rr} = $depfile->{$rr}->{'requires'};
$recommends{$rr} = $depfile->{$rr}->{'recommends'};
$pkgconflicts{$rr} = $depfile->{$rr}->{'conflicts'};
$pkgobsoletes{$rr} = $depfile->{$rr}->{'obsoletes'};
}
Expand Down Expand Up @@ -733,7 +734,7 @@ sub readdeps {
}
my %ss;
@ss = grep {!$ss{$_}++} @ss;
if ($s =~ /^(P|R|C|O):(.*)\.(.*)-\d+\/\d+\/\d+:$/) {
if ($s =~ /^(P|R|C|O|r):(.*)\.(.*)-\d+\/\d+\/\d+:$/) {
my $pkgid = $2;
my $arch = $3;
if ($1 eq "P") {
Expand All @@ -749,6 +750,11 @@ sub readdeps {
$pkginfo->{$pkgid}->{'requires'} = \@ss if $pkginfo;
next;
}
if ($1 eq "r") {
$recommends{$pkgid} = \@ss;
$pkginfo->{$pkgid}->{'recommends'} = \@ss if $pkginfo;
next;
}
if ($1 eq "C") {
$pkgconflicts{$pkgid} = \@ss;
$pkginfo->{$pkgid}->{'conflicts'} = \@ss if $pkginfo;
Expand Down Expand Up @@ -780,6 +786,7 @@ sub readdeps {
}
$config->{'providesh'} = \%provides;
$config->{'requiresh'} = \%requires;
$config->{'recommendsh'} = \%recommends;
$config->{'pkgconflictsh'} = \%pkgconflicts;
$config->{'pkgobsoletesh'} = \%pkgobsoletes;
makewhatprovidesh($config);
Expand Down Expand Up @@ -807,6 +814,7 @@ sub writedeps {
print $fh "F:$id$url$pkg->{'location'}\n";
print $fh "P:$id".join(' ', @{$pkg->{'provides'} || []})."\n";
print $fh "R:$id".join(' ', @{$pkg->{'requires'}})."\n" if $pkg->{'requires'};
print $fh "r:$id".join(' ', @{$pkg->{'recommends'}})."\n" if $pkg->{'recommends'};
print $fh "C:$id".join(' ', @{$pkg->{'conflicts'}})."\n" if $pkg->{'conflicts'};
print $fh "O:$id".join(' ', @{$pkg->{'obsoletes'}})."\n" if $pkg->{'obsoletes'};
print $fh "I:$id".getbuildid($pkg)."\n";
Expand Down Expand Up @@ -842,6 +850,7 @@ sub forgetdeps {
delete $config->{'providesh'};
delete $config->{'whatprovidesh'};
delete $config->{'requiresh'};
delete $config->{'recommendsh'};
delete $config->{'pkgconflictsh'};
delete $config->{'pkgobsoletesh'};
}
Expand Down Expand Up @@ -964,6 +973,7 @@ sub expand {

my $whatprovides = $config->{'whatprovidesh'};
my $requires = $config->{'requiresh'};
my $recommends = $config->{'recommendsh'};

my %xignore = map {substr($_, 1) => 1} grep {/^-/} @p;
$ignore = {} if $xignore{'-ignoreignore--'};
Expand Down Expand Up @@ -1086,6 +1096,22 @@ sub expand {
last;
}
}
if (@q > 1 && $config->{"buildflags:userecommendsforchoices"} && @{$recommends->{$p} || []} > 0) {
my @recommendedq;
my $i;

for my $iq (@q) {
for my $rpkg (@{$recommends->{$p}}) {
if ($rpkg =~ /$iq/) {
push @recommendedq, $iq;
}
}
}
if (@recommendedq > 0) {
print "recommended [@recommendedq] among [@q]\n" if $expand_dbg;
@q = @recommendedq;
}
}
if (@q > 1) {
if ($r ne $p) {
push @error, "have choice for $r needed by $p: @q";
Expand Down Expand Up @@ -1131,6 +1157,7 @@ sub order {
my ($config, @p) = @_;

my $requires = $config->{'requiresh'};
my $recommends = $config->{'recommendsh'};
my $whatprovides = $config->{'whatprovidesh'};
my %deps;
my %rdeps;
Expand Down Expand Up @@ -1228,6 +1255,7 @@ sub add_all_providers {
my ($config, @p) = @_;
my $whatprovides = $config->{'whatprovidesh'};
my $requires = $config->{'requiresh'};
my $recommends = $config->{'recommendsh'};
my %a;
for my $p (@p) {
for my $r (@{$requires->{$p} || [$p]}) {
Expand Down
6 changes: 3 additions & 3 deletions createdirdeps
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ my %old;
if (defined($oldfile) && open(F, '<', $oldfile)) {
while (<F>) {
chomp;
$old{$1} = $_ if /^([PRCOI]:[^ ]+): /;
$old{$1} = $_ if /^([PRrCOI]:[^ ]+): /;
}
close F;
}
Expand All @@ -78,14 +78,14 @@ for my $dir (@ARGV) {
next if $seen{$idx};
$seen{$idx} = 1;
print "F:$idx: $path\n";
for (qw{P R C O I}) {
for (qw{P R r C O I}) {
print $old{"$_:$idx"}."\n" if $old{"$_:$idx"};
}
next;
}
}
}
my $q = Build::query($path, 'addselfprovides' => 1, 'conflicts' => 1, 'evra' => 1, 'buildtime' => 1);
my $q = Build::query($path, 'addselfprovides' => 1, 'conflicts' => 1, 'evra' => 1, 'buildtime' => 1, 'weakdeps' => 1);
next unless $q && defined($q->{'name'}) && defined($q->{'arch'}) && defined($q->{'version'});
my $idx = "$q->{'name'}.$q->{'arch'}-$id";
next if $seen{$idx};
Expand Down
29 changes: 26 additions & 3 deletions expanddeps
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,18 @@ if (defined($dist) && $dist ne '') {
$binarytype = $cf->{'binarytype'} if $cf->{'binarytype'} && $cf->{'binarytype'} ne 'UNDEFINED';
}

my (%fn, %prov, %req, %con, %obs);
my (%fn, %prov, %req, %rec, %con, %obs);

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, $pkgC, $pkgO);
my ($pkgF, $pkgP, $pkgR, $pkgr, $pkgC, $pkgO);

my $verscmp = \&Build::Rpm::verscmp;

Expand All @@ -149,6 +150,8 @@ while(<F>) {
$pkgP = $2;
} elsif (/^R:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
$pkgR = $2;
} elsif (/^r:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
$pkgr = $2;
} elsif (/^C:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
$pkgC = $2;
} elsif (/^O:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
Expand All @@ -165,15 +168,18 @@ while(<F>) {
$fn{$i} = $pkgF;
$prov{$i} = $pkgP;
delete $req{$i};
delete $rec{$i};
delete $con{$i};
delete $obs{$i};
$req{$i} = $pkgR;
$rec{$i} = $pkgr;
$con{$i} = $pkgC if defined $pkgC;
$obs{$i} = $pkgO if defined $pkgO;
}
undef $pkgF;
undef $pkgP;
undef $pkgR;
undef $pkgr;
undef $pkgC;
undef $pkgO;
} elsif ($_ eq 'D:') {
Expand Down Expand Up @@ -221,7 +227,7 @@ $dofileprovides = 1 if ($binarytype || 'rpm') ne 'rpm';

for my $pack (keys %packs) {
my $r = {};
my (@s, $s, @pr, @re, @co, @ob);
my (@s, $s, @pr, @re, @rc, @co, @ob);
@s = split(' ', $prov{$packs{$pack}} || '');
while (@s) {
$s = shift @s;
Expand Down Expand Up @@ -254,6 +260,22 @@ for my $pack (keys %packs) {
splice(@s, 0, 2);
}
}
@s = split(' ', $rec{$packs{$pack}} || '');
while (@s) {
$s = shift @s;
next if !$dofileprovides && $s =~ /^\//;
if ($s =~ /^rpmlib\(/) {
splice(@s, 0, 2);
next;
}
push @rc, $s;
while (@s && $s[0] =~ /^[\(<=>|]/) {
$rc[-1] .= " $s[0] $s[1]";
$rc[-1] =~ s/ \((.*)\)/ $1/;
$rc[-1] =~ s/(<|>){2}/$1/;
splice(@s, 0, 2);
}
}
@s = split(' ', $con{$packs{$pack}} || '');
while (@s) {
$s = shift @s;
Expand All @@ -280,6 +302,7 @@ for my $pack (keys %packs) {
}
$r->{'provides'} = \@pr;
$r->{'requires'} = \@re;
$r->{'recommends'} = \@rc;
$r->{'conflicts'} = \@co;
$r->{'obsoletes'} = \@ob;
$repo{$pack} = $r;
Expand Down

0 comments on commit 9558b05

Please sign in to comment.