X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/f5b622ed48fdbe235d81b61b3edd8dbb84d9cc9c..6b92f60c38c2d50040bc3f07d52e8da80ef23bff:/apt-pkg/algorithms.cc

diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index 47bdd4aba..c337ace87 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -14,6 +14,8 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#include <config.h>
+
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
@@ -21,14 +23,17 @@
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/edsp.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/progress.h>
 
-#include <apti18n.h>
 #include <sys/types.h>
 #include <cstdlib>
 #include <algorithm>
 #include <iostream>
-
 #include <stdio.h>
+
+#include <apti18n.h>
 									/*}}}*/
 using namespace std;
 
@@ -94,7 +99,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
    Sim.MarkInstall(Pkg,false);
 
    // Look for broken conflicts+predepends.
-   for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
+   for (PkgIterator I = Sim.PkgBegin(); I.end() == false; ++I)
    {
       if (Sim[I].InstallVer == 0)
 	 continue;
@@ -143,7 +148,7 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
       Sim.Update();
       
       // Print out each package and the failed dependencies
-      for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; D++)
+      for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; ++D)
       {
 	 if (Sim.IsImportantDep(D) == false || 
 	     (Sim[D] & pkgDepCache::DepInstall) != 0)
@@ -207,7 +212,7 @@ bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
 void pkgSimulate::ShortBreaks()
 {
    cout << " [";
-   for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
+   for (PkgIterator I = Sim.PkgBegin(); I.end() == false; ++I)
    {
       if (Sim[I].InstBroken() == true)
       {
@@ -229,7 +234,7 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 {
    pkgDepCache::ActionGroup group(Cache);
 
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if (I->VersionList == 0)
 	 continue;
@@ -298,13 +303,13 @@ bool pkgFixBroken(pkgDepCache &Cache)
    pkgDepCache::ActionGroup group(Cache);
 
    // Auto upgrade all broken packages
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       if (Cache[I].NowBroken() == true)
 	 Cache.MarkInstall(I, true, 0, false);
    
    /* Fix packages that are in a NeedArchive state but don't have a
       downloadable install version */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if (I.State() != pkgCache::PkgIterator::NeedsUnpack ||
 	  Cache[I].Delete() == true)
@@ -347,19 +352,19 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
 
    /* Auto upgrade all installed packages, this provides the basis 
       for the installation */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       if (I->CurrentVer != 0)
 	 Cache.MarkInstall(I, true, 0, false);
 
    /* Now, auto upgrade all essential packages - this ensures that
       the essential packages are present and working */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
 	 Cache.MarkInstall(I, true, 0, false);
    
    /* We do it again over all previously installed packages to force 
       conflict resolution on them all. */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       if (I->CurrentVer != 0)
 	 Cache.MarkInstall(I, false, 0, false);
 
@@ -368,7 +373,7 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
    // Hold back held packages.
    if (_config->FindB("APT::Ignore-Hold",false) == false)
    {
-      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       {
 	 if (I->SelectedState == pkgCache::State::Hold)
 	 {
@@ -402,7 +407,7 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
       return false;
    
    // Upgrade all installed packages
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if (Cache[I].Install() == true)
 	 Fix.Protect(I);
@@ -436,7 +441,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
    do
    {
       Change = false;
-      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       {
 	 // Not interesting
 	 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
@@ -453,7 +458,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 	       Change = true;
 	 }	 
       }      
-      Count++;
+      ++Count;
    }
    while (Change == true && Count < 10);
 
@@ -470,7 +475,7 @@ pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
 {
    // Allocate memory
    unsigned long Size = Cache.Head().PackageCount;
-   Scores = new signed short[Size];
+   Scores = new int[Size];
    Flags = new unsigned char[Size];
    memset(Flags,0,sizeof(*Flags)*Size);
    
@@ -510,20 +515,20 @@ void pkgProblemResolver::MakeScores()
    memset(Scores,0,sizeof(*Scores)*Size);
 
    // Important Required Standard Optional Extra
-   signed short PrioMap[] = {
+   int PrioMap[] = {
       0,
-      (signed short) _config->FindI("pkgProblemResolver::Scores::Important",3),
-      (signed short) _config->FindI("pkgProblemResolver::Scores::Required",2),
-      (signed short) _config->FindI("pkgProblemResolver::Scores::Standard",1),
-      (signed short) _config->FindI("pkgProblemResolver::Scores::Optional",-1),
-      (signed short) _config->FindI("pkgProblemResolver::Scores::Extra",-2)
+      _config->FindI("pkgProblemResolver::Scores::Important",3),
+      _config->FindI("pkgProblemResolver::Scores::Required",2),
+      _config->FindI("pkgProblemResolver::Scores::Standard",1),
+      _config->FindI("pkgProblemResolver::Scores::Optional",-1),
+      _config->FindI("pkgProblemResolver::Scores::Extra",-2)
    };
-   signed short PrioEssentials = _config->FindI("pkgProblemResolver::Scores::Essentials",100);
-   signed short PrioInstalledAndNotObsolete = _config->FindI("pkgProblemResolver::Scores::NotObsolete",1);
-   signed short PrioDepends = _config->FindI("pkgProblemResolver::Scores::Depends",1);
-   signed short PrioRecommends = _config->FindI("pkgProblemResolver::Scores::Recommends",1);
-   signed short AddProtected = _config->FindI("pkgProblemResolver::Scores::AddProtected",10000);
-   signed short AddEssential = _config->FindI("pkgProblemResolver::Scores::AddEssential",5000);
+   int PrioEssentials = _config->FindI("pkgProblemResolver::Scores::Essentials",100);
+   int PrioInstalledAndNotObsolete = _config->FindI("pkgProblemResolver::Scores::NotObsolete",1);
+   int PrioDepends = _config->FindI("pkgProblemResolver::Scores::Depends",1);
+   int PrioRecommends = _config->FindI("pkgProblemResolver::Scores::Recommends",1);
+   int AddProtected = _config->FindI("pkgProblemResolver::Scores::AddProtected",10000);
+   int AddEssential = _config->FindI("pkgProblemResolver::Scores::AddEssential",5000);
 
    if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
       clog << "Settings used to calculate pkgProblemResolver::Scores::" << endl
@@ -540,12 +545,12 @@ void pkgProblemResolver::MakeScores()
          << "  AddEssential => " << AddEssential << endl;
 
    // Generate the base scores for a package based on its properties
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if (Cache[I].InstallVer == 0)
 	 continue;
       
-      signed short &Score = Scores[I->ID];
+      int &Score = Scores[I->ID];
       
       /* This is arbitrary, it should be high enough to elevate an
          essantial package above most other packages but low enough
@@ -567,12 +572,12 @@ void pkgProblemResolver::MakeScores()
    }
 
    // Now that we have the base scores we go and propogate dependencies
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if (Cache[I].InstallVer == 0)
 	 continue;
       
-      for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
+      for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; ++D)
       {
 	 if (D->Type == pkgCache::Dep::Depends || 
 	     D->Type == pkgCache::Dep::PreDepends)
@@ -583,18 +588,18 @@ void pkgProblemResolver::MakeScores()
    }   
    
    // Copy the scores to advoid additive looping
-   SPtrArray<signed short> OldScores = new signed short[Size];
+   SPtrArray<int> OldScores = new int[Size];
    memcpy(OldScores,Scores,sizeof(*Scores)*Size);
       
    /* Now we cause 1 level of dependency inheritance, that is we add the 
       score of the packages that depend on the target Package. This 
       fortifies high scoring packages */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if (Cache[I].InstallVer == 0)
 	 continue;
       
-      for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
+      for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; ++D)
       {
 	 // Only do it for the install version
 	 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
@@ -609,9 +614,9 @@ void pkgProblemResolver::MakeScores()
 
    /* Now we propogate along provides. This makes the packages that 
       provide important packages extremely important */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
-      for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; P++)
+      for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; ++P)
       {
 	 // Only do it once per package
 	 if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
@@ -622,7 +627,7 @@ void pkgProblemResolver::MakeScores()
 
    /* Protected things are pushed really high up. This number should put them
       ahead of everything */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if ((Flags[I->ID] & Protected) != 0)
 	 Scores[I->ID] += AddProtected;
@@ -719,7 +724,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 	 
 	 if (Start == End)
 	    break;
-	 Start++;
+	 ++Start;
       }
       if (Fail == true)
 	 break;
@@ -776,7 +781,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
    do
    {
       Again = false;
-      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       {
 	 if (Cache[I].Install() == true)
 	    Flags[I->ID] |= PreInstalled;
@@ -809,7 +814,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
       would cause the removal of even lower score packages. */
    SPtrArray<pkgCache::Package *> PList = new pkgCache::Package *[Size];
    pkgCache::Package **PEnd = PList;
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       *PEnd++ = I;
    This = this;
    qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
@@ -929,7 +934,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 	    }
 	    else
             {
-	       Start++;
+	       ++Start;
 	       // We only worry about critical deps.
 	       if (Start.IsCritical() != true)
                   continue;
@@ -1030,7 +1035,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 		     if (BrokenFix == false || DoUpgrade(I) == false)
 		     {
 			// Consider other options
-			if (InOr == false)
+			if (InOr == false || Cache[I].Garbage == true)
 			{
 			   if (Debug == true)
 			      clog << "  Removing " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
@@ -1093,8 +1098,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 		  LEnd->Dep = End;
 		  LEnd++;
 		  
-		  if (Start->Type != pkgCache::Dep::Conflicts &&
-		      Start->Type != pkgCache::Dep::Obsoletes)
+		  if (Start.IsNegative() == false)
 		     break;
 	       }
 	    }
@@ -1178,7 +1182,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
    {
       // See if this is the result of a hold
       pkgCache::PkgIterator I = Cache.PkgBegin();
-      for (;I.end() != true; I++)
+      for (;I.end() != true; ++I)
       {
 	 if (Cache[I].InstBroken() == false)
 	    continue;
@@ -1190,7 +1194,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
    
    // set the auto-flags (mvo: I'm not sure if we _really_ need this)
    pkgCache::PkgIterator I = Cache.PkgBegin();
-   for (;I.end() != true; I++) {
+   for (;I.end() != true; ++I) {
       if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
 	 if(_config->FindI("Debug::pkgAutoRemove",false)) {
 	    std::clog << "Resolve installed new pkg: " << I.FullName(false) 
@@ -1204,6 +1208,37 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
    return true;
 }
 									/*}}}*/
+// ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
+// ---------------------------------------------------------------------
+/* This checks if the given package is broken either by a hard dependency
+   (InstBroken()) or by introducing a new policy breakage e.g. new
+   unsatisfied recommends for a package that was in "policy-good" state
+
+   Note that this is not perfect as it will ignore further breakage
+   for already broken policy (recommends)
+*/
+bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I)
+{
+   // a broken install is always a problem
+   if (Cache[I].InstBroken() == true)
+   {
+      if (Debug == true)
+	 std::clog << "  Dependencies are not satisfied for " << I << std::endl;
+      return true;
+   }
+
+   // a newly broken policy (recommends/suggests) is a problem
+   if (Cache[I].NowPolicyBroken() == false &&
+       Cache[I].InstPolicyBroken() == true)
+   {
+      if (Debug == true)
+	 std::clog << "  Policy breaks with upgrade of " << I << std::endl;
+      return true;
+   }
+
+   return false;
+}
+									/*}}}*/
 // ProblemResolver::ResolveByKeep - Resolve problems using keep		/*{{{*/
 // ---------------------------------------------------------------------
 /* This is the work horse of the soft upgrade routine. It is very gental 
@@ -1238,7 +1273,7 @@ bool pkgProblemResolver::ResolveByKeepInternal()
       would cause the removal of even lower score packages. */
    pkgCache::Package **PList = new pkgCache::Package *[Size];
    pkgCache::Package **PEnd = PList;
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
       *PEnd++ = I;
    This = this;
    qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
@@ -1263,9 +1298,12 @@ bool pkgProblemResolver::ResolveByKeepInternal()
    {
       pkgCache::PkgIterator I(Cache,*K);
 
-      if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
+      if (Cache[I].InstallVer == 0)
 	 continue;
 
+      if (InstOrNewPolicyBroken(I) == false)
+         continue;
+
       /* Keep the package. If this works then great, otherwise we have
        	 to be significantly more agressive and manipulate its dependencies */
       if ((Flags[I->ID] & Protected) == 0)
@@ -1273,7 +1311,7 @@ bool pkgProblemResolver::ResolveByKeepInternal()
 	 if (Debug == true)
 	    clog << "Keeping package " << I.FullName(false) << endl;
 	 Cache.MarkKeep(I, false, false);
-	 if (Cache[I].InstBroken() == false)
+	 if (InstOrNewPolicyBroken(I) == false)
 	 {
 	    K = PList - 1;
 	    continue;
@@ -1323,23 +1361,23 @@ bool pkgProblemResolver::ResolveByKeepInternal()
 		  Cache.MarkKeep(Pkg, false, false);
 	       }
 	       
-	       if (Cache[I].InstBroken() == false)
+	       if (InstOrNewPolicyBroken(I) == false)
 		  break;
 	    }
 	    
-	    if (Cache[I].InstBroken() == false)
+	    if (InstOrNewPolicyBroken(I) == false)
 	       break;
 
 	    if (Start == End)
 	       break;
-	    Start++;
+	    ++Start;
 	 }
 	      
-	 if (Cache[I].InstBroken() == false)
+	 if (InstOrNewPolicyBroken(I) == false)
 	    break;
       }
 
-      if (Cache[I].InstBroken() == true)
+      if (InstOrNewPolicyBroken(I) == true)
 	 continue;
       
       // Restart again.
@@ -1359,7 +1397,7 @@ void pkgProblemResolver::InstallProtect()
 {
    pkgDepCache::ActionGroup group(Cache);
 
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if ((Flags[I->ID] & Protected) == Protected)
       {
@@ -1406,7 +1444,7 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    qsort(List,Count,sizeof(*List),PrioComp);
 }
 									/*}}}*/
-// CacheFile::ListUpdate - update the cache files                    	/*{{{*/
+// ListUpdate - update the cache files					/*{{{*/
 // ---------------------------------------------------------------------
 /* This is a simple wrapper to update the cache. it will fetch stuff
  * from the network (or any other sources defined in sources.list)
@@ -1439,7 +1477,7 @@ bool ListUpdate(pkgAcquireStatus &Stat,
    bool Failed = false;
    bool TransientNetworkFailure = false;
    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); 
-	I != Fetcher.ItemsEnd(); I++)
+	I != Fetcher.ItemsEnd(); ++I)
    {
       if ((*I)->Status == pkgAcquire::Item::StatDone)
 	 continue;