Quellcode durchsuchen

* apt-pkg/algorithms.cc:
- let the problem resolver install packages to fix or-groups
as a needed remove nuked another or-member (helps for #591882)

The resolver sometimes need to break or-groups because he need to
remove the previous satisfier as a result of a breaks/conflicts.
In such broken or-groups he now tries to install a non-installed
non-deleted member of the or-group to statisfy it again.
This move is dangerous as it introduces the possibility of a
bunch of "new" broken breaks/conflicts on the new statisfier or
its dependencies and we don't know about them beforehand.
We also don't have the infrastructure to undo the decision later,
so we just do it and pray!

For now a test option is provided to disable this behavior on the
fly to test if the situation is worse: pkgProblemResolver::FixByInstall

David Kalnischkies vor 16 Jahren
Ursprung
Commit
09a10f9cd2
2 geänderte Dateien mit 32 neuen und 12 gelöschten Zeilen
  1. 29 11
      apt-pkg/algorithms.cc
  2. 3 1
      debian/changelog

+ 29 - 11
apt-pkg/algorithms.cc

@@ -187,7 +187,7 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
       }	    
       }	    
       cout << endl;
       cout << endl;
 
 
-      _error->Error("Conf Broken %s",Pkg.FullName(false));
+      _error->Error("Conf Broken %s",Pkg.FullName(false).c_str());
    }   
    }   
    else
    else
    {
    {
@@ -290,7 +290,7 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 	       Cache.MarkInstall(I, false, 0, false);
 	       Cache.MarkInstall(I, false, 0, false);
 	    else
 	    else
 	       return _error->Error(_("The package %s needs to be reinstalled, "
 	       return _error->Error(_("The package %s needs to be reinstalled, "
-				    "but I can't find an archive for it."),I.FullName(true));
+				    "but I can't find an archive for it."),I.FullName(true).c_str());
 	 }
 	 }
 	 
 	 
 	 continue;
 	 continue;
@@ -325,7 +325,7 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 	 default:
 	 default:
 	 if (I->InstState != pkgCache::State::Ok)
 	 if (I->InstState != pkgCache::State::Ok)
 	    return _error->Error("The package %s is not ok and I "
 	    return _error->Error("The package %s is not ok and I "
-				 "don't know how to fix it!",I.FullName(false));
+				 "don't know how to fix it!",I.FullName(false).c_str());
       }
       }
    }
    }
    return true;
    return true;
@@ -847,6 +847,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
       not be possible for a loop to form (that is a < b < c and fixing b by
       not be possible for a loop to form (that is a < b < c and fixing b by
       changing a breaks c) */
       changing a breaks c) */
    bool Change = true;
    bool Change = true;
+   bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true);
    for (int Counter = 0; Counter != 10 && Change == true; Counter++)
    for (int Counter = 0; Counter != 10 && Change == true; Counter++)
    {
    {
       Change = false;
       Change = false;
@@ -863,7 +864,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	     (Flags[I->ID] & ReInstateTried) == 0)
 	     (Flags[I->ID] & ReInstateTried) == 0)
 	 {
 	 {
 	    if (Debug == true)
 	    if (Debug == true)
-	       clog << " Try to Re-Instate " << I.FullName(false) << endl;
+	       clog << " Try to Re-Instate (" << Counter << ") " << I.FullName(false) << endl;
 	    unsigned long OldBreaks = Cache.BrokenCount();
 	    unsigned long OldBreaks = Cache.BrokenCount();
 	    pkgCache::Version *OldVer = Cache[I].InstallVer;
 	    pkgCache::Version *OldVer = Cache[I].InstallVer;
 	    Flags[I->ID] &= ReInstateTried;
 	    Flags[I->ID] &= ReInstateTried;
@@ -886,7 +887,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    continue;
 	    continue;
 	 
 	 
 	 if (Debug == true)
 	 if (Debug == true)
-	    clog << "Investigating " << I << endl;
+	    clog << "Investigating (" << Counter << ") " << I << endl;
 	 
 	 
 	 // Isolate the problem dependency
 	 // Isolate the problem dependency
 	 PackageKill KillList[100];
 	 PackageKill KillList[100];
@@ -904,9 +905,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    if (Start == End)
 	    if (Start == End)
 	    {
 	    {
 	       // Decide what to do
 	       // Decide what to do
-	       if (InOr == true)
+	       if (InOr == true && OldEnd == LEnd)
 	       {
 	       {
-		  if (OldEnd == LEnd && OrOp == OrRemove)
+		  if (OrOp == OrRemove)
 		  {
 		  {
 		     if ((Flags[I->ID] & Protected) != Protected)
 		     if ((Flags[I->ID] & Protected) != Protected)
 		     {
 		     {
@@ -914,9 +915,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 			   clog << "  Or group remove for " << I.FullName(false) << endl;
 			   clog << "  Or group remove for " << I.FullName(false) << endl;
 			Cache.MarkDelete(I);
 			Cache.MarkDelete(I);
 			Change = true;
 			Change = true;
-		     }		     
-		  }		  
-		  if (OldEnd == LEnd && OrOp == OrKeep)
+		     }
+		  }
+		  else if (OrOp == OrKeep)
 		  {
 		  {
 		     if (Debug == true)
 		     if (Debug == true)
 			clog << "  Or group keep for " << I.FullName(false) << endl;
 			clog << "  Or group keep for " << I.FullName(false) << endl;
@@ -1041,6 +1042,23 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 			   if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
 			   if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
 			      Scores[I->ID] = Scores[Pkg->ID];
 			      Scores[I->ID] = Scores[Pkg->ID];
 			}
 			}
+			else if (TryFixByInstall == true &&
+				 Start.TargetPkg()->CurrentVer == 0 &&
+				 Cache[Start.TargetPkg()].Delete() == false &&
+				 Cache.GetCandidateVer(Start.TargetPkg()).end() == false)
+			{
+			   /* Before removing or keeping the package with the broken dependency
+			      try instead to install the first not previously installed package
+			      solving this dependency. This helps every time a previous solver
+			      is removed by the resolver because of a conflict or alike but it is
+			      dangerous as it could trigger new breaks/conflicts… */
+			   std::cout << "  Try Installing " << Start.TargetPkg() << " before changing " << I.FullName(false) << std::endl;
+			   unsigned long const OldBroken = Cache.BrokenCount();
+			   Cache.MarkInstall(Start.TargetPkg(), true, 1, false);
+			   // FIXME: we should undo the complete MarkInstall process here
+			   if (Cache[Start.TargetPkg()].InstBroken() == true || Cache.BrokenCount() > OldBroken)
+			      Cache.MarkDelete(Start.TargetPkg(), false, 1, false);
+			}
 		     }
 		     }
 		  }
 		  }
 		  		  
 		  		  
@@ -1325,7 +1343,7 @@ bool pkgProblemResolver::ResolveByKeep()
       
       
       // Restart again.
       // Restart again.
       if (K == LastStop)
       if (K == LastStop)
-	 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false));
+	 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false).c_str());
       LastStop = K;
       LastStop = K;
       K = PList - 1;
       K = PList - 1;
    }   
    }   

+ 3 - 1
debian/changelog

@@ -27,6 +27,8 @@ apt (0.8.0~pre1) UNRELASED; urgency=low
 
 
   [ David Kalnischkies ]
   [ David Kalnischkies ]
   * apt-pkg/algorithms.cc:
   * apt-pkg/algorithms.cc:
+    - let the problem resolver install packages to fix or-groups
+      as a needed remove nuked another or-member (helps for #591882)
     - change the debug outputs to display also arch of the
     - change the debug outputs to display also arch of the
       package and version dependencies information
       package and version dependencies information
   * cmdline/apt-get.cc:
   * cmdline/apt-get.cc:
@@ -34,7 +36,7 @@ apt (0.8.0~pre1) UNRELASED; urgency=low
       (Closes: #592628) Thanks Mohamed Amine IL Idrissi for report!
       (Closes: #592628) Thanks Mohamed Amine IL Idrissi for report!
     - purge packages in 'rc' state, thanks Rogier! (Closes: #150831)
     - purge packages in 'rc' state, thanks Rogier! (Closes: #150831)
 
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Wed, 11 Aug 2010 19:36:21 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Fri, 13 Aug 2010 14:24:27 +0200
 
 
 apt (0.7.26~exp12) experimental; urgency=low
 apt (0.7.26~exp12) experimental; urgency=low