X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/80fa0d8a1a77f4dab696dcf11d1908ecda761fab..115ba31b90e0d6643670d7d079f9f27b0e05f1c2:/apt-pkg/algorithms.cc

diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index 2799c2fdd..f17c76d6c 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -14,16 +14,17 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/algorithms.h"
-#endif 
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/version.h>
 #include <apt-pkg/sptr.h>
+#include <apt-pkg/acquire-item.h>
     
 #include <apti18n.h>
-    
+#include <sys/types.h>
+#include <cstdlib>
+#include <algorithm>
 #include <iostream>
 									/*}}}*/
 using namespace std;
@@ -36,7 +37,8 @@ pkgProblemResolver *pkgProblemResolver::This = 0;
    this is not necessary since the pkgCaches are fully shared now. */
 pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache),
 		            iPolicy(Cache),
-                            Sim(&Cache->GetCache(),&iPolicy)
+			    Sim(&Cache->GetCache(),&iPolicy),
+			    group(Sim)
 {
    Sim.Init(0);
    Flags = new unsigned char[Cache->Head().PackageCount];
@@ -81,13 +83,28 @@ void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candid
 bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
 {
    // Adapt the iterator
-   PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
+   PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
    Flags[Pkg->ID] = 1;
    
    cout << "Inst ";
    Describe(Pkg,cout,true,true);
    Sim.MarkInstall(Pkg,false);
-   
+
+   if (strcmp(Pkg.Arch(),"all") == 0)
+   {
+      pkgCache::GrpIterator G = Pkg.Group();
+      pkgCache::GrpIterator iG = iPkg.Group();
+      for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P))
+      {
+	 if (strcmp(P.Arch(), "all") == 0)
+	    continue;
+	 if (iG.FindPkg(P.Arch())->CurrentVer == 0)
+	    continue;
+	 Flags[P->ID] = 1;
+	 Sim.MarkInstall(P, false);
+      }
+   }
+
    // Look for broken conflicts+predepends.
    for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
    {
@@ -100,6 +117,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
 	 DepIterator End;
 	 D.GlobOr(Start,End);
 	 if (Start->Type == pkgCache::Dep::Conflicts ||
+	     Start->Type == pkgCache::Dep::DpkgBreaks ||
 	     Start->Type == pkgCache::Dep::Obsoletes ||
 	     End->Type == pkgCache::Dep::PreDepends)
          {
@@ -128,9 +146,22 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
 bool pkgSimulate::Configure(PkgIterator iPkg)
 {
    // Adapt the iterator
-   PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
+   PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
    
    Flags[Pkg->ID] = 2;
+
+   if (strcmp(Pkg.Arch(),"all") == 0)
+   {
+      pkgCache::GrpIterator G = Pkg.Group();
+      for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P))
+      {
+	 if (strcmp(P.Arch(), "all") == 0)
+	    continue;
+	 if (Flags[P->ID] == 1)
+	    Flags[P->ID] = 2;
+      }
+   }
+
 //   Sim.MarkInstall(Pkg,false);
    if (Sim[Pkg].InstBroken() == true)
    {
@@ -149,6 +180,8 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
 	    cout << " Obsoletes:" << D.TargetPkg().Name();
 	 else if (D->Type == pkgCache::Dep::Conflicts)
 	    cout << " Conflicts:" << D.TargetPkg().Name();
+	 else if (D->Type == pkgCache::Dep::DpkgBreaks)
+	    cout << " Breaks:" << D.TargetPkg().Name();
 	 else
 	    cout << " Depends:" << D.TargetPkg().Name();
       }	    
@@ -176,10 +209,26 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
 bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
 {
    // Adapt the iterator
-   PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
+   PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
 
    Flags[Pkg->ID] = 3;
    Sim.MarkDelete(Pkg);
+
+   if (strcmp(Pkg.Arch(),"all") == 0)
+   {
+      pkgCache::GrpIterator G = Pkg.Group();
+      pkgCache::GrpIterator iG = iPkg.Group();
+      for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P))
+      {
+	 if (strcmp(P.Arch(), "all") == 0)
+	    continue;
+	 if (iG.FindPkg(P.Arch())->CurrentVer == 0)
+	    continue;
+	 Flags[P->ID] = 3;
+	 Sim.MarkDelete(P);
+      }
+   }
+
    if (Purge == true)
       cout << "Purg ";
    else
@@ -220,6 +269,8 @@ void pkgSimulate::ShortBreaks()
    the necessary calculations to deal with the problems. */
 bool pkgApplyStatus(pkgDepCache &Cache)
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
       if (I->VersionList == 0)
@@ -230,13 +281,13 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 	  I->InstState == pkgCache::State::HoldReInstReq)
       {
 	 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
-	    Cache.MarkKeep(I);
+	    Cache.MarkKeep(I, false, false);
 	 else
 	 {
 	    // Is this right? Will dpkg choke on an upgrade?
 	    if (Cache[I].CandidateVer != 0 &&
 		 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
-	       Cache.MarkInstall(I);
+	       Cache.MarkInstall(I, false, 0, false);
 	    else
 	       return _error->Error(_("The package %s needs to be reinstalled, "
 				    "but I can't find an archive for it."),I.Name());
@@ -251,14 +302,16 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 	    re-unpacked (probably) */
 	 case pkgCache::State::UnPacked:
 	 case pkgCache::State::HalfConfigured:
+	 case pkgCache::State::TriggersAwaited:
+	 case pkgCache::State::TriggersPending:
 	 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
 	     I.State() != pkgCache::PkgIterator::NeedsUnpack)
-	    Cache.MarkKeep(I);
+	    Cache.MarkKeep(I, false, false);
 	 else
 	 {
 	    if (Cache[I].CandidateVer != 0 &&
 		 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
-	       Cache.MarkInstall(I);
+	       Cache.MarkInstall(I, true, 0, false);
 	    else
 	       Cache.MarkDelete(I);
 	 }
@@ -284,10 +337,12 @@ bool pkgApplyStatus(pkgDepCache &Cache)
    on the result. */
 bool pkgFixBroken(pkgDepCache &Cache)
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    // Auto upgrade all broken packages
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
       if (Cache[I].NowBroken() == true)
-	 Cache.MarkInstall(I,true);
+	 Cache.MarkInstall(I, true, 0, false);
    
    /* Fix packages that are in a NeedArchive state but don't have a
       downloadable install version */
@@ -300,7 +355,7 @@ bool pkgFixBroken(pkgDepCache &Cache)
       if (Cache[I].InstVerIter(Cache).Downloadable() == false)
 	 continue;
 
-      Cache.MarkInstall(I,true);      
+      Cache.MarkInstall(I, true, 0, false);
    }
    
    pkgProblemResolver Fix(&Cache);
@@ -317,23 +372,25 @@ bool pkgFixBroken(pkgDepCache &Cache)
  */
 bool pkgDistUpgrade(pkgDepCache &Cache)
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    /* Auto upgrade all installed packages, this provides the basis 
       for the installation */
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
       if (I->CurrentVer != 0)
-	 Cache.MarkInstall(I,true);
+	 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++)
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-	 Cache.MarkInstall(I,true);
+	 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++)
       if (I->CurrentVer != 0)
-	 Cache.MarkInstall(I,false);
+	 Cache.MarkInstall(I, false, 0, false);
 
    pkgProblemResolver Fix(&Cache);
 
@@ -345,7 +402,7 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
 	 if (I->SelectedState == pkgCache::State::Hold)
 	 {
 	    Fix.Protect(I);
-	    Cache.MarkKeep(I);
+	    Cache.MarkKeep(I, false, false);
 	 }
       }
    }
@@ -360,6 +417,8 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
    to install packages not marked for install */
 bool pkgAllUpgrade(pkgDepCache &Cache)
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    pkgProblemResolver Fix(&Cache);
 
    if (Cache.BrokenCount() != 0)
@@ -376,7 +435,7 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
 	    continue;
       
       if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
-	 Cache.MarkInstall(I,false);
+	 Cache.MarkInstall(I, false, 0, false);
    }
       
    return Fix.ResolveByKeep();
@@ -389,6 +448,8 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
    the package is restored. */
 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 {   
+   pkgDepCache::ActionGroup group(Cache);
+
    if (Cache.BrokenCount() != 0)
       return false;
    
@@ -405,9 +466,9 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 	    continue;
 
 	 // Keep it and see if that is OK
-	 Cache.MarkKeep(I);
+	 Cache.MarkKeep(I, false, false);
 	 if (Cache.BrokenCount() != 0)
-	    Cache.MarkInstall(I,false);
+	    Cache.MarkInstall(I, false, 0, false);
 	 else
 	 {
 	    // If keep didnt actually do anything then there was no change..
@@ -425,7 +486,6 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
    return true;
 }
 									/*}}}*/
-
 // ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -472,6 +532,36 @@ void pkgProblemResolver::MakeScores()
    unsigned long Size = Cache.Head().PackageCount;
    memset(Scores,0,sizeof(*Scores)*Size);
 
+   // Important Required Standard Optional Extra
+   signed short 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)
+   };
+   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);
+
+   if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
+      clog << "Settings used to calculate pkgProblemResolver::Scores::" << endl
+         << "  Important => " << PrioMap[1] << endl
+         << "  Required => " << PrioMap[2] << endl
+         << "  Standard => " << PrioMap[3] << endl
+         << "  Optional => " << PrioMap[4] << endl
+         << "  Extra => " << PrioMap[5] << endl
+         << "  Essentials => " << PrioEssentials << endl
+         << "  InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete << endl
+         << "  Depends => " << PrioDepends << endl
+         << "  Recommends => " << PrioRecommends << endl
+         << "  AddProtected => " << AddProtected << endl
+         << "  AddEssential => " << AddEssential << endl;
+
    // Generate the base scores for a package based on its properties
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
@@ -480,23 +570,23 @@ void pkgProblemResolver::MakeScores()
       
       signed short &Score = Scores[I->ID];
       
-      /* This is arbitary, it should be high enough to elevate an
+      /* This is arbitrary, it should be high enough to elevate an
          essantial package above most other packages but low enough
 	 to allow an obsolete essential packages to be removed by
 	 a conflicts on a powerfull normal package (ie libc6) */
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-	 Score += 100;
+	 Score += PrioEssentials;
 
       // We transform the priority
-      // Important Required Standard Optional Extra
-      signed short PrioMap[] = {0,3,2,1,-1,-2};
       if (Cache[I].InstVerIter(Cache)->Priority <= 5)
 	 Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
       
       /* This helps to fix oddball problems with conflicting packages
-         on the same level. We enhance the score of installed packages */
-      if (I->CurrentVer != 0)
-	 Score += 1;
+         on the same level. We enhance the score of installed packages 
+	 if those are not obsolete
+      */
+      if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
+	 Score += PrioInstalledAndNotObsolete;
    }
 
    // Now that we have the base scores we go and propogate dependencies
@@ -507,8 +597,11 @@ void pkgProblemResolver::MakeScores()
       
       for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
       {
-	 if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
-	    Scores[D.TargetPkg()->ID]++;
+	 if (D->Type == pkgCache::Dep::Depends || 
+	     D->Type == pkgCache::Dep::PreDepends)
+	    Scores[D.TargetPkg()->ID] += PrioDepends;
+	 else if (D->Type == pkgCache::Dep::Recommends)
+	    Scores[D.TargetPkg()->ID] += PrioRecommends;
       }
    }   
    
@@ -528,7 +621,9 @@ void pkgProblemResolver::MakeScores()
       {
 	 // Only do it for the install version
 	 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
-	     (D->Type != pkgCache::Dep::Depends && D->Type != pkgCache::Dep::PreDepends))
+	     (D->Type != pkgCache::Dep::Depends && 
+	      D->Type != pkgCache::Dep::PreDepends &&
+	      D->Type != pkgCache::Dep::Recommends))
 	    continue;	 
 	 
 	 Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
@@ -553,10 +648,10 @@ void pkgProblemResolver::MakeScores()
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
       if ((Flags[I->ID] & Protected) != 0)
-	 Scores[I->ID] += 10000;
+	 Scores[I->ID] += AddProtected;
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-	 Scores[I->ID] += 5000;
-   }   
+	 Scores[I->ID] += AddEssential;
+   }
 }
 									/*}}}*/
 // ProblemResolver::DoUpgrade - Attempt to upgrade this package		/*{{{*/
@@ -565,6 +660,8 @@ void pkgProblemResolver::MakeScores()
    installable */
 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
       return false;
    if ((Flags[Pkg->ID] & Protected) == Protected)
@@ -573,7 +670,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    Flags[Pkg->ID] &= ~Upgradable;
    
    bool WasKept = Cache[Pkg].Keep();
-   Cache.MarkInstall(Pkg,false);
+   Cache.MarkInstall(Pkg, false, 0, false);
 
    // This must be a virtual package or something like that.
    if (Cache[Pkg].InstVerIter(Cache).end() == true)
@@ -637,6 +734,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 	       /* We let the algorithm deal with conflicts on its next iteration,
 		it is much smarter than us */
 	       if (Start->Type == pkgCache::Dep::Conflicts || 
+		   Start->Type == pkgCache::Dep::DpkgBreaks || 
 		   Start->Type == pkgCache::Dep::Obsoletes)
 		   break;
 	       
@@ -658,7 +756,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    if (Fail == true)
    {
       if (WasKept == true)
-	 Cache.MarkKeep(Pkg);
+	 Cache.MarkKeep(Pkg, false, false);
       else
 	 Cache.MarkDelete(Pkg);
       return false;
@@ -685,6 +783,8 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    upgrade packages to advoid problems. */
 bool pkgProblemResolver::Resolve(bool BrokenFix)
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    unsigned long Size = Cache.Head().PackageCount;
 
    // Record which packages are marked for install
@@ -700,7 +800,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	 {
 	    if (Cache[I].InstBroken() == true && BrokenFix == true)
 	    {
-	       Cache.MarkInstall(I,false);
+	       Cache.MarkInstall(I, false, 0, false);
 	       if (Cache[I].Install() == true)
 		  Again = true;
 	    }
@@ -727,19 +827,21 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
       *PEnd++ = I;
    This = this;
    qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
-   
-/* for (pkgCache::Package **K = PList; K != PEnd; K++)
-      if (Scores[(*K)->ID] != 0)
-      {
-	 pkgCache::PkgIterator Pkg(Cache,*K);
-	 clog << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
-	    ' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' << 
-	    Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
-      } */
+
+   if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
+   {
+      clog << "Show Scores" << endl;
+      for (pkgCache::Package **K = PList; K != PEnd; K++)
+         if (Scores[(*K)->ID] != 0)
+         {
+           pkgCache::PkgIterator Pkg(Cache,*K);
+           clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
+         }
+   }
 
    if (Debug == true)
       clog << "Starting 2" << endl;
-   
+
    /* Now consider all broken packages. For each broken package we either
       remove the package or fix it's problem. We do this once, it should
       not be possible for a loop to form (that is a < b < c and fixing b by
@@ -766,14 +868,14 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    pkgCache::Version *OldVer = Cache[I].InstallVer;
 	    Flags[I->ID] &= ReInstateTried;
 	    
-	    Cache.MarkInstall(I,false);
+	    Cache.MarkInstall(I, false, 0, false);
 	    if (Cache[I].InstBroken() == true || 
 		OldBreaks < Cache.BrokenCount())
 	    {
 	       if (OldVer == 0)
 		  Cache.MarkDelete(I);
 	       else
-		  Cache.MarkKeep(I);
+		  Cache.MarkKeep(I, false, false);
 	    }	    
 	    else
 	       if (Debug == true)
@@ -784,7 +886,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    continue;
 	 
 	 if (Debug == true)
-	    cout << "Investigating " << I.Name() << endl;
+	    clog << "Investigating " << I.Name() << endl;
 	 
 	 // Isolate the problem dependency
 	 PackageKill KillList[100];
@@ -818,7 +920,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		  {
 		     if (Debug == true)
 			clog << "  Or group keep for " << I.Name() << endl;
-		     Cache.MarkKeep(I);
+		     Cache.MarkKeep(I, false, false);
 		     Change = true;
 		  }
 	       }
@@ -839,7 +941,12 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       OldEnd = LEnd;
 	    }
 	    else
+            {
 	       Start++;
+	       // We only worry about critical deps.
+	       if (Start.IsCritical() != true)
+                  continue;
+            }
 
 	    // Dep is ok
 	    if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
@@ -849,7 +956,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    }
 	    
 	    if (Debug == true)
-	       clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
+	       clog << "Package " << I.Name() << " has broken " << Start.DepType() << " on " << Start.TargetPkg().Name() << endl;
 
 	    /* Look across the version list. If there are no possible
 	       targets then we keep the package and bail. This is necessary
@@ -857,6 +964,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
 	    if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
 		Start->Type != pkgCache::Dep::Conflicts &&
+		Start->Type != pkgCache::Dep::DpkgBreaks &&
 		Start->Type != pkgCache::Dep::Obsoletes &&
 		Cache[I].NowBroken() == false)
 	    {	       
@@ -868,7 +976,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       }
 	       
 	       Change = true;
-	       Cache.MarkKeep(I);		  
+	       Cache.MarkKeep(I, false, false);
 	       break;
 	    }
 	    
@@ -887,6 +995,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       if (Scores[I->ID] <= Scores[Pkg->ID] ||
 		   ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
 		    End->Type != pkgCache::Dep::Conflicts &&
+		    End->Type != pkgCache::Dep::DpkgBreaks &&
 		    End->Type != pkgCache::Dep::Obsoletes))
 	       {
 		  // Try a little harder to fix protected packages..
@@ -905,7 +1014,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		  /* See if a keep will do, unless the package is protected,
 		     then installing it will be necessary */
 		  bool Installed = Cache[I].Install();
-		  Cache.MarkKeep(I);
+		  Cache.MarkKeep(I, false, false);
 		  if (Cache[I].InstBroken() == false)
 		  {
 		     // Unwind operation will be keep now
@@ -914,7 +1023,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		     
 		     // Restore
 		     if (InOr == true && Installed == true)
-			Cache.MarkInstall(I,false);
+			Cache.MarkInstall(I, false, 0, false);
 		     
 		     if (Debug == true)
 			clog << "  Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
@@ -929,12 +1038,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 			   if (Debug == true)
 			      clog << "  Removing " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
 			   Cache.MarkDelete(I);
-			   if (Counter > 1)
-			   {
-			      if (Scores[Pkg->ID] > Scores[I->ID])
-				 Scores[I->ID] = Scores[Pkg->ID];
-			   }			   
-			}			
+			   if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
+			      Scores[I->ID] = Scores[Pkg->ID];
+			}
 		     }
 		  }
 		  		  
@@ -952,7 +1058,22 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		      (Start->Type == pkgCache::Dep::Conflicts ||
 		       Start->Type == pkgCache::Dep::Obsoletes))
 		     continue;
-		  
+
+		  if (Start->Type == pkgCache::Dep::DpkgBreaks)
+		  {
+		     // first, try upgradring the package, if that
+		     // does not help, the breaks goes onto the
+		     // kill list
+		     // FIXME: use DoUpgrade(Pkg) instead?
+		     if (Cache[End] & pkgDepCache::DepGCVer) 
+		     {
+			if (Debug)
+			   clog << "  Upgrading " << Pkg.Name() << " due to Breaks field in " << I.Name() << endl;
+			Cache.MarkInstall(Pkg, false, 0, false);
+			continue;
+		     }
+		  }
+
 		  // Skip adding to the kill list if it is protected
 		  if ((Flags[Pkg->ID] & Protected) != 0)
 		     continue;
@@ -973,6 +1094,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    // Hm, nothing can possibly satisify this dep. Nuke it.
 	    if (VList[0] == 0 && 
 		Start->Type != pkgCache::Dep::Conflicts &&
+		Start->Type != pkgCache::Dep::DpkgBreaks &&
 		Start->Type != pkgCache::Dep::Obsoletes &&
 		(Flags[I->ID] & Protected) != Protected)
 	    {
@@ -986,7 +1108,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		  
 		  // Restore
 		  if (InOr == true && Installed == true)
-		     Cache.MarkInstall(I,false);
+		     Cache.MarkInstall(I, false, 0, false);
 		  
 		  if (Debug == true)
 		     clog << "  Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
@@ -1020,6 +1142,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
 	       {
 		  if (J->Dep->Type == pkgCache::Dep::Conflicts || 
+		      J->Dep->Type == pkgCache::Dep::DpkgBreaks ||
 		      J->Dep->Type == pkgCache::Dep::Obsoletes)
 		  {
 		     if (Debug == true)
@@ -1031,7 +1154,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       {
 		  if (Debug == true)
 		     clog << "  Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
-		  Cache.MarkKeep(J->Pkg);
+		  Cache.MarkKeep(J->Pkg, false, false);
 	       }
 
 	       if (Counter > 1)
@@ -1061,12 +1184,14 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
       return _error->Error(_("Unable to correct problems, you have held broken packages."));
    }
    
-   // set the auto-flags (mvo: I'm not sure if we _really_ need this, but
-   // I didn't managed 
+   // set the auto-flags (mvo: I'm not sure if we _really_ need this)
    pkgCache::PkgIterator I = Cache.PkgBegin();
    for (;I.end() != true; I++) {
       if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
-	 std::cout << "Resolve installed new pkg: " << I.Name() << " (now marking it as auto)" << std::endl;
+	 if(_config->FindI("Debug::pkgAutoRemove",false)) {
+	    std::clog << "Resolve installed new pkg: " << I.Name() 
+		      << " (now marking it as auto)" << std::endl;
+	 }
 	 Cache[I].Flags |= pkgCache::Flag::Auto;
       }
    }
@@ -1082,11 +1207,10 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
    system was non-broken previously. */
 bool pkgProblemResolver::ResolveByKeep()
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    unsigned long Size = Cache.Head().PackageCount;
 
-   if (Debug == true)      
-      clog << "Entering ResolveByKeep" << endl;
-   
    MakeScores();
    
    /* We have to order the packages so that the broken fixing pass 
@@ -1099,7 +1223,21 @@ bool pkgProblemResolver::ResolveByKeep()
       *PEnd++ = I;
    This = this;
    qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
-   
+
+   if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
+   {
+      clog << "Show Scores" << endl;
+      for (pkgCache::Package **K = PList; K != PEnd; K++)
+         if (Scores[(*K)->ID] != 0)
+         {
+           pkgCache::PkgIterator Pkg(Cache,*K);
+           clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
+         }
+   }
+
+   if (Debug == true)
+      clog << "Entering ResolveByKeep" << endl;
+
    // Consider each broken package 
    pkgCache::Package **LastStop = 0;
    for (pkgCache::Package **K = PList; K != PEnd; K++)
@@ -1115,7 +1253,7 @@ bool pkgProblemResolver::ResolveByKeep()
       {
 	 if (Debug == true)
 	    clog << "Keeping package " << I.Name() << endl;
-	 Cache.MarkKeep(I);
+	 Cache.MarkKeep(I, false, false);
 	 if (Cache[I].InstBroken() == false)
 	 {
 	    K = PList - 1;
@@ -1145,8 +1283,8 @@ bool pkgProblemResolver::ResolveByKeep()
 	 while (true)
 	 {
 	    if (Debug == true)
-	       clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
-	    
+	       clog << "Package " << I.Name() << " has broken " << Start.DepType() << " on " << Start.TargetPkg().Name() << endl;
+
 	    // Look at all the possible provides on this package
 	    SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
 	    for (pkgCache::Version **V = VList; *V != 0; V++)
@@ -1162,8 +1300,8 @@ bool pkgProblemResolver::ResolveByKeep()
 	       if ((Flags[I->ID] & Protected) == 0)
 	       {
 		  if (Debug == true)
-		     clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
-		  Cache.MarkKeep(Pkg);
+		     clog << "  Keeping Package " << Pkg.Name() << " due to " << Start.DepType() << endl;
+		  Cache.MarkKeep(Pkg, false, false);
 	       }
 	       
 	       if (Cache[I].InstBroken() == false)
@@ -1200,19 +1338,25 @@ bool pkgProblemResolver::ResolveByKeep()
 /* This is used to make sure protected packages are installed */
 void pkgProblemResolver::InstallProtect()
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
       if ((Flags[I->ID] & Protected) == Protected)
       {
 	 if ((Flags[I->ID] & ToRemove) == ToRemove)
 	    Cache.MarkDelete(I);
-	 else
-	    Cache.MarkInstall(I,false);
+	 else 
+	 {
+	    // preserve the information whether the package was auto
+	    // or manually installed
+	    bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
+	    Cache.MarkInstall(I, false, 0, !autoInst);
+	 }
       }
    }   
 }
 									/*}}}*/
-
 // PrioSortList - Sort a list of versions by priority			/*{{{*/
 // ---------------------------------------------------------------------
 /* This is ment to be used in conjunction with AllTargets to get a list 
@@ -1243,3 +1387,87 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    qsort(List,Count,sizeof(*List),PrioComp);
 }
 									/*}}}*/
+// CacheFile::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)
+ */
+bool ListUpdate(pkgAcquireStatus &Stat, 
+		pkgSourceList &List, 
+		int PulseInterval)
+{
+   pkgAcquire::RunResult res;
+   pkgAcquire Fetcher;
+   if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
+      return false;
+
+   // Populate it with the source selection
+   if (List.GetIndexes(&Fetcher) == false)
+	 return false;
+
+   // Run scripts
+   RunScripts("APT::Update::Pre-Invoke");
+   
+   // check arguments
+   if(PulseInterval>0)
+      res = Fetcher.Run(PulseInterval);
+   else
+      res = Fetcher.Run();
+
+   if (res == pkgAcquire::Failed)
+      return false;
+
+   bool Failed = false;
+   bool TransientNetworkFailure = false;
+   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); 
+	I != Fetcher.ItemsEnd(); I++)
+   {
+      if ((*I)->Status == pkgAcquire::Item::StatDone)
+	 continue;
+
+      (*I)->Finished();
+
+      ::URI uri((*I)->DescURI());
+      uri.User.clear();
+      uri.Password.clear();
+      string descUri = string(uri);
+      _error->Warning(_("Failed to fetch %s  %s\n"), descUri.c_str(),
+	      (*I)->ErrorText.c_str());
+
+      if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) 
+      {
+	 TransientNetworkFailure = true;
+	 continue;
+      }
+
+      Failed = true;
+   }
+   
+   // Clean out any old list files
+   // Keep "APT::Get::List-Cleanup" name for compatibility, but
+   // this is really a global option for the APT library now
+   if (!TransientNetworkFailure && !Failed &&
+       (_config->FindB("APT::Get::List-Cleanup",true) == true &&
+	_config->FindB("APT::List-Cleanup",true) == true))
+   {
+      if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
+	  Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
+	 // something went wrong with the clean
+	 return false;
+   }
+   
+   if (TransientNetworkFailure == true)
+      _error->Warning(_("Some index files failed to download, they have been ignored, or old ones used instead."));
+   else if (Failed == true)
+      return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
+
+
+   // Run the success scripts if all was fine
+   if(!TransientNetworkFailure && !Failed)
+      RunScripts("APT::Update::Post-Invoke-Success");
+
+   // Run the other scripts
+   RunScripts("APT::Update::Post-Invoke");
+   return true;
+}
+									/*}}}*/