[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#470115: Patch and explanation



package apt
tags 470115 + patch
thanks

  Background for debian-deity: we have

kdebase (V1) Recommends: kdm (>= V1)
kdebase (V2) Recommends: kdm (>= V2)

V1 < V2

kdebase (V1) and kdm (V1) are installed.

  When attempting to just upgrade kdebase to V2, we have a problem: it
causes kdm to become a target for auto-removal.  This would not happen
if the Recommends was followed -- but it's not, because it looks like an
"old" Recommends to apt.  The intent of that rule is to allow users to
remove, e.g., kdm, without having it get reinstalled whenever kdebase is
upgraded.  But there's no danger of that here: kdm is already installed.

  I propose the attached patch as a solution to this particular
situation.  The idea is to follow old Recommends, iff they are already
satisfied.  This should ensure that upgrades of recommended packages get
dragged in without 

  The one thing I'm not sure about is how OR groups are handled.
Consider this situation:

foo (V1) Recommends: woot | arg (>= V1)
foo (V2) Recommends: woot | arg (>= V2)

      arg (V1) is installed.
      foo (V1) is installed.
      woot is not installed.

  Here the result of installing foo (V2) is -- I think -- that arg is
autoremoved and woot is installed instead.  However, I don't know if
this ever actually happens, and apt will behave the same way with
Depends, so hopefully people aren't in the habit of writing dependencies
like that.  I think that this problem could be fixed by tweaking MarkInstall
to scan a whole OR group and preferentially try to install branches that are
currently satisfied but will break post-install. (i.e., are DepGNow but
not DepGInstall)

  Daniel
=== modified file 'apt-pkg/depcache.cc'
--- apt-pkg/depcache.cc	2008-03-08 18:47:10 +0000
+++ apt-pkg/depcache.cc	2008-03-09 23:01:39 +0000
@@ -895,24 +895,41 @@
       if (IsImportantDep(Start) == false)
 	 continue;
       
-      /* check if any ImportantDep() (but not Critial) where added
-       * since we installed the package
+      /* Check if any ImportantDep() (but not Critical) were added
+       * since we installed the package.  Also check for deps that
+       * were satisfied in the past: for instance, if a version
+       * restriction in a Recommends was tightened, upgrading the
+       * package should follow that Recommends rather than causing the
+       * dependency to be removed. (bug #470115)
        */
       bool isNewImportantDep = false;
+      bool isPreviouslySatisfiedImportantDep = false;
       if(!ForceImportantDeps && !Start.IsCritical())
       {
 	 bool found=false;
 	 VerIterator instVer = Pkg.CurrentVer();
 	 if(!instVer.end())
 	 {
-	    for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
-	    {
+	   for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
+	     {
 	       //FIXME: deal better with or-groups(?)
 	       DepIterator LocalStart = D;
 	       
 	       if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
-		  found=true;
-	    }
+		 {
+		   if(!isPreviouslySatisfiedImportantDep)
+		     {
+		       DepIterator D2 = D;
+		       while((D2->CompareOp & Dep::Or) != 0)
+			 ++D2;
+
+		       isPreviouslySatisfiedImportantDep =
+			 (((*this)[D2] & DepGNow) != 0);
+		     }
+
+		   found=true;
+		 }
+	     }
 	    // this is a new dep if it was not found to be already
 	    // a important dep of the installed pacakge
 	    isNewImportantDep = !found;
@@ -922,10 +939,15 @@
 	 if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
 	    std::clog << "new important dependency: " 
 		      << Start.TargetPkg().Name() << std::endl;
+      if(isPreviouslySatisfiedImportantDep)
+	if(_config->FindB("Debug::pkgDepCache::AutoInstall", false) == true)
+	  std::clog << "previously satisfied important dependency on "
+		    << Start.TargetPkg().Name() << std::endl;
 
       // skip important deps if the package is already installed
       if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
-	  && !isNewImportantDep && !ForceImportantDeps)
+	  && !isNewImportantDep && !isPreviouslySatisfiedImportantDep
+	  && !ForceImportantDeps)
 	 continue;
       
       /* If we are in an or group locate the first or that can 


Reply to: