]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/algorithms.cc
* merged the apt--DoListUpdate branch, this provides a common interface
[apt.git] / apt-pkg / algorithms.cc
index 0cc4388af130b54f6f1c74d2e3638ae25f86d107..6e2b9755730c11b824dde72ce199b791a5d4972b 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: algorithms.cc,v 1.40 2002/04/25 05:45:18 jgg Exp $
+// $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 jgg Exp $
 /* ######################################################################
 
    Algorithms - A set of misc algorithms
 /* ######################################################################
 
    Algorithms - A set of misc algorithms
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
    ##################################################################### */
                                                                        /*}}}*/
 // 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/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/sptr.h>
+#include <apt-pkg/acquire-item.h>
     
 #include <apti18n.h>
     
 #include <apti18n.h>
-    
+#include <sys/types.h>
+#include <cstdlib>
+#include <algorithm>
 #include <iostream>
                                                                        /*}}}*/
 #include <iostream>
                                                                        /*}}}*/
+using namespace std;
 
 pkgProblemResolver *pkgProblemResolver::This = 0;
 
 
 pkgProblemResolver *pkgProblemResolver::This = 0;
 
@@ -49,21 +51,29 @@ pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache),
                                                                        /*}}}*/
 // Simulate::Describe - Describe a package                             /*{{{*/
 // ---------------------------------------------------------------------
                                                                        /*}}}*/
 // Simulate::Describe - Describe a package                             /*{{{*/
 // ---------------------------------------------------------------------
-/* */
-void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Now)
+/* Parameter Current == true displays the current package version,
+   Parameter Candidate == true displays the candidate package version */
+void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candidate)
 {
    VerIterator Ver(Sim);
 {
    VerIterator Ver(Sim);
-   if (Now == true)
+   out << Pkg.Name();
+
+   if (Current == true)
+   {
       Ver = Pkg.CurrentVer();
       Ver = Pkg.CurrentVer();
-   else
-      Ver = Sim[Pkg].CandidateVerIter(Sim);
+      if (Ver.end() == false)
+         out << " [" << Ver.VerStr() << ']';
+   }
 
 
-   out << Pkg.Name();
-   
-   if (Ver.end() == true)
-      return;
+   if (Candidate == true)
+   {
+      Ver = Sim[Pkg].CandidateVerIter(Sim);
+      if (Ver.end() == true)
+         return;
    
    
-   out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
+      out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
+   }
 }
                                                                        /*}}}*/
 // Simulate::Install - Simulate unpacking of a package                 /*{{{*/
 }
                                                                        /*}}}*/
 // Simulate::Install - Simulate unpacking of a package                 /*{{{*/
@@ -76,7 +86,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
    Flags[Pkg->ID] = 1;
    
    cout << "Inst ";
    Flags[Pkg->ID] = 1;
    
    cout << "Inst ";
-   Describe(Pkg,cout,false);
+   Describe(Pkg,cout,true,true);
    Sim.MarkInstall(Pkg,false);
    
    // Look for broken conflicts+predepends.
    Sim.MarkInstall(Pkg,false);
    
    // Look for broken conflicts+predepends.
@@ -91,6 +101,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
         DepIterator End;
         D.GlobOr(Start,End);
         if (Start->Type == pkgCache::Dep::Conflicts ||
         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)
          {
             Start->Type == pkgCache::Dep::Obsoletes ||
             End->Type == pkgCache::Dep::PreDepends)
          {
@@ -140,6 +151,8 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
            cout << " Obsoletes:" << D.TargetPkg().Name();
         else if (D->Type == pkgCache::Dep::Conflicts)
            cout << " Conflicts:" << D.TargetPkg().Name();
            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();
       }            
         else
            cout << " Depends:" << D.TargetPkg().Name();
       }            
@@ -150,7 +163,7 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
    else
    {
       cout << "Conf "; 
    else
    {
       cout << "Conf "; 
-      Describe(Pkg,cout,false);
+      Describe(Pkg,cout,false,true);
    }
 
    if (Sim.BrokenCount() != 0)
    }
 
    if (Sim.BrokenCount() != 0)
@@ -175,7 +188,7 @@ bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
       cout << "Purg ";
    else
       cout << "Remv ";
       cout << "Purg ";
    else
       cout << "Remv ";
-   Describe(Pkg,cout,false);
+   Describe(Pkg,cout,true,false);
 
    if (Sim.BrokenCount() != 0)
       ShortBreaks();
 
    if (Sim.BrokenCount() != 0)
       ShortBreaks();
@@ -211,6 +224,8 @@ void pkgSimulate::ShortBreaks()
    the necessary calculations to deal with the problems. */
 bool pkgApplyStatus(pkgDepCache &Cache)
 {
    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)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
       if (I->VersionList == 0)
@@ -221,13 +236,13 @@ bool pkgApplyStatus(pkgDepCache &Cache)
          I->InstState == pkgCache::State::HoldReInstReq)
       {
         if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
          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)
         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());
            else
               return _error->Error(_("The package %s needs to be reinstalled, "
                                    "but I can't find an archive for it."),I.Name());
@@ -242,14 +257,16 @@ bool pkgApplyStatus(pkgDepCache &Cache)
            re-unpacked (probably) */
         case pkgCache::State::UnPacked:
         case pkgCache::State::HalfConfigured:
            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)
         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)
         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);
         }
            else
               Cache.MarkDelete(I);
         }
@@ -275,10 +292,12 @@ bool pkgApplyStatus(pkgDepCache &Cache)
    on the result. */
 bool pkgFixBroken(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)
    // 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 */
    
    /* Fix packages that are in a NeedArchive state but don't have a
       downloadable install version */
@@ -291,7 +310,7 @@ bool pkgFixBroken(pkgDepCache &Cache)
       if (Cache[I].InstVerIter(Cache).Downloadable() == false)
         continue;
 
       if (Cache[I].InstVerIter(Cache).Downloadable() == false)
         continue;
 
-      Cache.MarkInstall(I,true);      
+      Cache.MarkInstall(I, true, 0, false);
    }
    
    pkgProblemResolver Fix(&Cache);
    }
    
    pkgProblemResolver Fix(&Cache);
@@ -308,23 +327,25 @@ bool pkgFixBroken(pkgDepCache &Cache)
  */
 bool pkgDistUpgrade(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)
    /* 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)
 
    /* 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)
    
    /* 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);
 
 
    pkgProblemResolver Fix(&Cache);
 
@@ -336,7 +357,7 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
         if (I->SelectedState == pkgCache::State::Hold)
         {
            Fix.Protect(I);
         if (I->SelectedState == pkgCache::State::Hold)
         {
            Fix.Protect(I);
-           Cache.MarkKeep(I);
+           Cache.MarkKeep(I, false, false);
         }
       }
    }
         }
       }
    }
@@ -351,6 +372,8 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
    to install packages not marked for install */
 bool pkgAllUpgrade(pkgDepCache &Cache)
 {
    to install packages not marked for install */
 bool pkgAllUpgrade(pkgDepCache &Cache)
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    pkgProblemResolver Fix(&Cache);
 
    if (Cache.BrokenCount() != 0)
    pkgProblemResolver Fix(&Cache);
 
    if (Cache.BrokenCount() != 0)
@@ -367,7 +390,7 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
            continue;
       
       if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
            continue;
       
       if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
-        Cache.MarkInstall(I,false);
+        Cache.MarkInstall(I, false, 0, false);
    }
       
    return Fix.ResolveByKeep();
    }
       
    return Fix.ResolveByKeep();
@@ -380,6 +403,8 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
    the package is restored. */
 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 {   
    the package is restored. */
 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 {   
+   pkgDepCache::ActionGroup group(Cache);
+
    if (Cache.BrokenCount() != 0)
       return false;
    
    if (Cache.BrokenCount() != 0)
       return false;
    
@@ -396,9 +421,9 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
            continue;
 
         // Keep it and see if that is OK
            continue;
 
         // Keep it and see if that is OK
-        Cache.MarkKeep(I);
+        Cache.MarkKeep(I, false, false);
         if (Cache.BrokenCount() != 0)
         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..
         else
         {
            // If keep didnt actually do anything then there was no change..
@@ -485,8 +510,10 @@ void pkgProblemResolver::MakeScores()
         Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
       
       /* This helps to fix oddball problems with conflicting packages
         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)
+         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 += 1;
    }
 
         Score += 1;
    }
 
@@ -556,13 +583,17 @@ void pkgProblemResolver::MakeScores()
    installable */
 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 {
    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] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
       return false;
+   if ((Flags[Pkg->ID] & Protected) == Protected)
+      return false;
    
    Flags[Pkg->ID] &= ~Upgradable;
    
    bool WasKept = Cache[Pkg].Keep();
    
    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)
 
    // This must be a virtual package or something like that.
    if (Cache[Pkg].InstVerIter(Cache).end() == true)
@@ -626,6 +657,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 || 
               /* 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;
               
                   Start->Type == pkgCache::Dep::Obsoletes)
                   break;
               
@@ -647,7 +679,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    if (Fail == true)
    {
       if (WasKept == true)
    if (Fail == true)
    {
       if (WasKept == true)
-        Cache.MarkKeep(Pkg);
+        Cache.MarkKeep(Pkg, false, false);
       else
         Cache.MarkDelete(Pkg);
       return false;
       else
         Cache.MarkDelete(Pkg);
       return false;
@@ -674,6 +706,8 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    upgrade packages to advoid problems. */
 bool pkgProblemResolver::Resolve(bool BrokenFix)
 {
    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
    unsigned long Size = Cache.Head().PackageCount;
 
    // Record which packages are marked for install
@@ -689,7 +723,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
         {
            if (Cache[I].InstBroken() == true && BrokenFix == true)
            {
         {
            if (Cache[I].InstBroken() == true && BrokenFix == true)
            {
-              Cache.MarkInstall(I,false);
+              Cache.MarkInstall(I, false, 0, false);
               if (Cache[I].Install() == true)
                  Again = true;
            }
               if (Cache[I].Install() == true)
                  Again = true;
            }
@@ -755,14 +789,14 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
            pkgCache::Version *OldVer = Cache[I].InstallVer;
            Flags[I->ID] &= ReInstateTried;
            
            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
            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)
            }       
            else
               if (Debug == true)
@@ -773,7 +807,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
            continue;
         
         if (Debug == true)
            continue;
         
         if (Debug == true)
-           cout << "Investigating " << I.Name() << endl;
+           clog << "Investigating " << I.Name() << endl;
         
         // Isolate the problem dependency
         PackageKill KillList[100];
         
         // Isolate the problem dependency
         PackageKill KillList[100];
@@ -807,7 +841,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
                  {
                     if (Debug == true)
                        clog << "  Or group keep for " << I.Name() << endl;
                  {
                     if (Debug == true)
                        clog << "  Or group keep for " << I.Name() << endl;
-                    Cache.MarkKeep(I);
+                    Cache.MarkKeep(I, false, false);
                     Change = true;
                  }
               }
                     Change = true;
                  }
               }
@@ -828,7 +862,12 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
               OldEnd = LEnd;
            }
            else
               OldEnd = LEnd;
            }
            else
+            {
               Start++;
               Start++;
+              // We only worry about critical deps.
+              if (Start.IsCritical() != true)
+                  continue;
+            }
 
            // Dep is ok
            if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
 
            // Dep is ok
            if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
@@ -846,6 +885,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 &&
            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)
            {          
                Start->Type != pkgCache::Dep::Obsoletes &&
                Cache[I].NowBroken() == false)
            {          
@@ -857,7 +897,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
               }
               
               Change = true;
               }
               
               Change = true;
-              Cache.MarkKeep(I);                 
+              Cache.MarkKeep(I, false, false);
               break;
            }
            
               break;
            }
            
@@ -876,6 +916,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
               if (Scores[I->ID] <= Scores[Pkg->ID] ||
                   ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
                    End->Type != pkgCache::Dep::Conflicts &&
               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..
                    End->Type != pkgCache::Dep::Obsoletes))
               {
                  // Try a little harder to fix protected packages..
@@ -894,7 +935,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();
                  /* 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
                  if (Cache[I].InstBroken() == false)
                  {
                     // Unwind operation will be keep now
@@ -903,7 +944,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
                     
                     // Restore
                     if (InOr == true && Installed == true)
                     
                     // 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;
                     
                     if (Debug == true)
                        clog << "  Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
@@ -941,7 +982,22 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
                      (Start->Type == pkgCache::Dep::Conflicts ||
                       Start->Type == pkgCache::Dep::Obsoletes))
                     continue;
                      (Start->Type == pkgCache::Dep::Conflicts ||
                       Start->Type == pkgCache::Dep::Obsoletes))
                     continue;
-                 
+
+                 if (Start->Type == pkgCache::Dep::DpkgBreaks)
+                 {
+                    /* Would it help if we upgraded? */
+                    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;
+                    }
+                    if (Debug)
+                       clog << "  Will not break " << Pkg.Name() << " as stated in Breaks field in " << I.Name() <<endl;
+                    Cache.MarkKeep(I, false, false);
+                    continue;
+                 }
+
                  // Skip adding to the kill list if it is protected
                  if ((Flags[Pkg->ID] & Protected) != 0)
                     continue;
                  // Skip adding to the kill list if it is protected
                  if ((Flags[Pkg->ID] & Protected) != 0)
                     continue;
@@ -962,6 +1018,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
            // Hm, nothing can possibly satisify this dep. Nuke it.
            if (VList[0] == 0 && 
                Start->Type != pkgCache::Dep::Conflicts &&
            // 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)
            {
                Start->Type != pkgCache::Dep::Obsoletes &&
                (Flags[I->ID] & Protected) != Protected)
            {
@@ -975,7 +1032,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
                  
                  // Restore
                  if (InOr == true && Installed == true)
                  
                  // 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;
                  
                  if (Debug == true)
                     clog << "  Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
@@ -1020,7 +1077,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
               {
                  if (Debug == true)
                     clog << "  Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
               {
                  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)
               }
 
               if (Counter > 1)
@@ -1050,6 +1107,20 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
       return _error->Error(_("Unable to correct problems, you have held broken packages."));
    }
    
       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 
+   pkgCache::PkgIterator I = Cache.PkgBegin();
+   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.Name() 
+                     << " (now marking it as auto)" << std::endl;
+        }
+        Cache[I].Flags |= pkgCache::Flag::Auto;
+      }
+   }
+
+
    return true;
 }
                                                                        /*}}}*/
    return true;
 }
                                                                        /*}}}*/
@@ -1060,6 +1131,8 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
    system was non-broken previously. */
 bool pkgProblemResolver::ResolveByKeep()
 {
    system was non-broken previously. */
 bool pkgProblemResolver::ResolveByKeep()
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    unsigned long Size = Cache.Head().PackageCount;
 
    if (Debug == true)      
    unsigned long Size = Cache.Head().PackageCount;
 
    if (Debug == true)      
@@ -1093,7 +1166,7 @@ bool pkgProblemResolver::ResolveByKeep()
       {
         if (Debug == true)
            clog << "Keeping package " << I.Name() << endl;
       {
         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;
         if (Cache[I].InstBroken() == false)
         {
            K = PList - 1;
@@ -1141,7 +1214,7 @@ bool pkgProblemResolver::ResolveByKeep()
               {
                  if (Debug == true)
                     clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
               {
                  if (Debug == true)
                     clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
-                 Cache.MarkKeep(Pkg);
+                 Cache.MarkKeep(Pkg, false, false);
               }
               
               if (Cache[I].InstBroken() == false)
               }
               
               if (Cache[I].InstBroken() == false)
@@ -1178,14 +1251,21 @@ bool pkgProblemResolver::ResolveByKeep()
 /* This is used to make sure protected packages are installed */
 void pkgProblemResolver::InstallProtect()
 {
 /* 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);
    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);
+        }
       }
    }   
 }
       }
    }   
 }
@@ -1202,14 +1282,14 @@ static int PrioComp(const void *A,const void *B)
    pkgCache::VerIterator R(*PrioCache,*(pkgCache::Version **)B);
    
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
    pkgCache::VerIterator R(*PrioCache,*(pkgCache::Version **)B);
    
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
-       (L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
-   return 1;
+       (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
+     return 1;
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
-       (L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-   return -1;
+       (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+     return -1;
    
    if (L->Priority != R->Priority)
    
    if (L->Priority != R->Priority)
-      return L->Priority - R->Priority;
+      return R->Priority - L->Priority;
    return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
 }
 void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
 }
 void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
@@ -1221,3 +1301,78 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    qsort(List,Count,sizeof(*List),PrioComp);
 }
                                                                        /*}}}*/
    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(&Stat);
+
+   // 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();
+
+      _error->Warning(_("Failed to fetch %s  %s\n"),(*I)->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 scripts if all was fine
+   RunScripts("APT::Update::Post-Invoke");
+   return true;
+}
+                                                                       /*}}}*/