diff options
author | MyungJoo Ham <myungjoo.ham@samsung.com> | 2016-10-27 14:26:00 +0900 |
---|---|---|
committer | yang.zhang <y0169.zhang@samsung.com> | 2017-03-07 13:22:08 +0800 |
commit | 292ed284159c7726aa283d7bfb75d3c7a597f0da (patch) | |
tree | 42e0131a1fba858ec97da409a329d211d263917d | |
parent | 5e86f63fe845ed8d19c3f7247b8efc57e93bf749 (diff) | |
download | build-292ed284159c7726aa283d7bfb75d3c7a597f0da.tar.gz build-292ed284159c7726aa283d7bfb75d3c7a597f0da.tar.bz2 build-292ed284159c7726aa283d7bfb75d3c7a597f0da.zip |
Recognize Recommends relations of RPMs
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 #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 #302
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Conflicts:
createdirdeps
expanddeps
Change-Id: I65dc6dd16a6874b7c1ae47932d37c23ec98b9cdf
-rw-r--r-- | Build.pm | 32 | ||||
-rwxr-xr-x | createdirdeps | 6 | ||||
-rwxr-xr-x | expanddeps | 28 |
3 files changed, 58 insertions, 8 deletions
@@ -585,8 +585,8 @@ sub get_cbinstalls { return @{[]}; } sub readdeps { my ($config, $pkginfo, @depfiles) = @_; - my %requires; + my %recommends; local *F; my %provides; my %pkgconflicts; @@ -597,6 +597,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'}; } @@ -640,7 +641,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") { @@ -656,6 +657,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; @@ -687,6 +693,7 @@ sub readdeps { } $config->{'providesh'} = \%provides; $config->{'requiresh'} = \%requires; + $config->{'recommendsh'} = \%recommends; $config->{'pkgconflictsh'} = \%pkgconflicts; $config->{'pkgobsoletesh'} = \%pkgobsoletes; makewhatprovidesh($config); @@ -714,6 +721,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"; @@ -749,6 +757,7 @@ sub forgetdeps { delete $config->{'providesh'}; delete $config->{'whatprovidesh'}; delete $config->{'requiresh'}; + delete $config->{'recommendsh'}; delete $config->{'pkgconflictsh'}; delete $config->{'pkgobsoletesh'}; } @@ -866,6 +875,7 @@ sub expand { my $whatprovides = $config->{'whatprovidesh'}; my $requires = $config->{'requiresh'}; + my $recommends = $config->{'recommendsh'}; my %xignore = map {substr($_, 1) => 1} grep {/^-/} @p; my @directdepsend; @@ -975,6 +985,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"; @@ -1020,6 +1046,7 @@ sub order { my ($config, @p) = @_; my $requires = $config->{'requiresh'}; + my $recommends = $config->{'recommendsh'}; my $whatprovides = $config->{'whatprovidesh'}; my %deps; my %rdeps; @@ -1117,6 +1144,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]}) { diff --git a/createdirdeps b/createdirdeps index 280e4f5..b50739f 100755 --- a/createdirdeps +++ b/createdirdeps @@ -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; } @@ -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, 'alldeps' => 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}; @@ -126,7 +126,7 @@ 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; @@ -170,7 +170,7 @@ my %exportfilters = %{$cf->{'exportfilter'}}; 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; @@ -210,6 +210,8 @@ while(<F>) { $pkgR = $2; next if $req{$1}; $req{$1} = $2; + } elsif (/^r:(.*?)-\d+\/\d+\/\d+: (.*)$/) { + $pkgr = $2; } elsif (/^C:(.*?)-\d+\/\d+\/\d+: (.*)$/) { $pkgC = $2; next if $con{$1}; @@ -241,9 +243,11 @@ 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; } else { @@ -253,6 +257,7 @@ while(<F>) { undef $pkgF; undef $pkgP; undef $pkgR; + undef $pkgr; undef $pkgC; undef $pkgO; } elsif ($_ eq 'D:') { @@ -267,7 +272,7 @@ for my $arch (@archs) { 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; @@ -300,6 +305,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; @@ -326,6 +347,7 @@ for my $pack (keys %packs) { } $r->{'provides'} = \@pr; $r->{'requires'} = \@re; + $r->{'recommends'} = \@rc; $r->{'conflicts'} = \@co; $r->{'obsoletes'} = \@ob; $repo{$pack} = $r; |