Recognize Recommends relations of RPMs.
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Thu, 27 Oct 2016 05:26:00 +0000 (14:26 +0900)
committerSoonKyu Park <sk7.park@samsung.com>
Tue, 10 Jan 2017 10:25:48 +0000 (19:25 +0900)
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

Conflicts:
Build.pm
createdirdeps
expanddeps

Build.pm
expanddeps

index c1ebe1cef0f8bca077f8fd4e3da19b1b4a0a980e..8a0803c4542c4343496b13ec76a0d74a32d8be6d 100644 (file)
--- a/Build.pm
+++ b/Build.pm
@@ -488,6 +488,7 @@ sub readdeps {
   my ($config, $pkginfo, @depfiles) = @_;
 
   my %requires = ();
+  my %recommends = ();
   local *F;
   my %provides;
   my $dofileprovides = %{$config->{'fileprovides'}};
@@ -496,6 +497,7 @@ sub readdeps {
       for my $rr (keys %$depfile) {
        $provides{$rr} = $depfile->{$rr}->{'provides'};
        $requires{$rr} = $depfile->{$rr}->{'requires'};
+       $recommends{$rr} = $depfile->{$rr}->{'recommends'};
       }
       next;
     }
@@ -528,7 +530,7 @@ sub readdeps {
       }
       my %ss;
       @ss = grep {!$ss{$_}++} @ss;
-      if ($s =~ /^(P|R):(.*)\.(.*)-\d+\/\d+\/\d+:$/) {
+      if ($s =~ /^(P|R|r):(.*)\.(.*)-\d+\/\d+\/\d+:$/) {
        my $pkgid = $2;
        my $arch = $3;
        if ($1 eq "R") {
@@ -547,6 +549,11 @@ sub readdeps {
          $pkginfo->{$pkgid}->{'release'} = $r if defined($r);
          $pkginfo->{$pkgid}->{'arch'} = $arch;
          $pkginfo->{$pkgid}->{'provides'} = \@ss;
+       if ($1 eq "r") {
+         $recommends{$pkgid} = \@ss;
+         $pkginfo->{$pkgid}->{'recommends'} = \@ss if $pkginfo;
+         next;
+       }
        }
       }
     }
@@ -554,9 +561,39 @@ sub readdeps {
   }
   $config->{'providesh'} = \%provides;
   $config->{'requiresh'} = \%requires;
+  $config->{'recommendsh'} = \%recommends;
   makewhatprovidesh($config);
 }
 
+sub getbuildid {
+  my ($q) = @_;
+  my $evr = $q->{'version'};
+  $evr = "$q->{'epoch'}:$evr" if $q->{'epoch'};
+  $evr .= "-$q->{'release'}" if defined $q->{'release'};;
+  my $buildtime = $q->{'buildtime'} || 0;
+  $evr .= " $buildtime";
+  $evr .= "-$q->{'arch'}" if defined $q->{'arch'};
+  return "$q->{'name'}-$evr";
+}
+
+sub writedeps {
+  my ($fh, $pkg, $url) = @_;
+  $url = '' unless defined $url;
+  return unless defined($pkg->{'name'}) && defined($pkg->{'arch'});
+  return if $pkg->{'arch'} eq 'src' || $pkg->{'arch'} eq 'nosrc';
+  my $id = $pkg->{'id'};
+  $id = ($pkg->{'buildtime'} || 0)."/".($pkg->{'filetime'} || 0)."/0" unless $id;
+  $id = "$pkg->{'name'}.$pkg->{'arch'}-$id: ";
+  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";
+}
+
+>>>>>>> d6ff6eb... Recognize Recommends relations of RPMs.
 sub makewhatprovidesh {
   my ($config) = @_;
 
@@ -587,6 +624,7 @@ sub forgetdeps {
   delete $config->{'providesh'};
   delete $config->{'whatprovidesh'};
   delete $config->{'requiresh'};
+  delete $config->{'recommendsh'};
 }
 
 my %addproviders_fm = (
@@ -667,6 +705,7 @@ sub expand {
 
   my $whatprovides = $config->{'whatprovidesh'};
   my $requires = $config->{'requiresh'};
+  my $recommends = $config->{'recommendsh'};
 
   my %xignore = map {substr($_, 1) => 1} grep {/^-/} @p;
   @p = grep {!/^-/} @p;
@@ -745,6 +784,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";
@@ -782,6 +837,7 @@ sub order {
   my ($config, @p) = @_;
 
   my $requires = $config->{'requiresh'};
+  my $recommends = $config->{'recommendsh'};
   my $whatprovides = $config->{'whatprovidesh'};
   my %deps;
   my %rdeps;
@@ -879,6 +935,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]}) {
index 3a8d561c0aa0e67e346a4bede75ba0e555502f2d..e3151d8dc3e09e06405bb87606669c7de0ebdcfb 100755 (executable)
@@ -83,7 +83,7 @@ if ($spec =~ /(^|\/)PKGBUILD$/) {
   push @archs, 'noarch' unless grep {$_ eq 'noarch'} @archs;
 }
 
-my (%fn, %prov, %req);
+my (%fn, %prov, %req, %rec);
 
 my %packs;
 my %repo;
@@ -127,7 +127,7 @@ my $dofileprovides = %{$cf->{'fileprovides'}};
 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);
+my ($pkgF, $pkgP, $pkgR, $pkgr);
 while(<F>) {
   chomp;
   if (/^F:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
@@ -157,6 +157,8 @@ while(<F>) {
     $pkgR = $2;
     next if $req{$1};
     $req{$1} = $2;
+  } elsif (/^r:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
+    $pkgr = $2;
   } elsif (/^I:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
     my $r = 0;
     if ($usehigherdeps) {
@@ -178,6 +180,7 @@ while(<F>) {
         $fn{$i}   = $pkgF;
         $prov{$i} = $pkgP;
         $req{$i}  = $pkgR;
+        $rec{$i}  = $pkgr;
       }
     } else {
       next if $ids{$1};
@@ -186,6 +189,7 @@ while(<F>) {
     undef $pkgF;
     undef $pkgP;
     undef $pkgR;
+    undef $pkgr;
   } elsif ($_ eq 'D:') {
     %packs_done = %ids;
   }
@@ -197,7 +201,7 @@ for my $arch (@archs) {
 }
 for my $pack (keys %packs) {
   my $r = {};
-  my (@s, $s, @pr, @re);
+  my (@s, $s, @pr, @re, @rc);
   @s = split(' ', $prov{$packs{$pack}} || '');
   while (@s) {
     $s = shift @s;
@@ -222,6 +226,7 @@ for my $pack (keys %packs) {
   }
   $r->{'provides'} = \@pr;
   $r->{'requires'} = \@re;
+  $r->{'recommends'} = \@rc;
   $repo{$pack} = $r;
 }