]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/algorithms.cc
* apt-pkg/deb/dpkgpm.cc:
[apt.git] / apt-pkg / algorithms.cc
index c679e76f67ba0fbdf3c95965afb72954eb8207e7..f17c76d6c5aa8892f8db6b7d0a5c9565d9e6c835 100644 (file)
    ##################################################################### */
                                                                        /*}}}*/
 // 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/pkgsystem.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/version.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>
                                                                        /*}}}*/
 using namespace std;
 #include <iostream>
                                                                        /*}}}*/
 using namespace std;
@@ -39,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),
    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];
 {
    Sim.Init(0);
    Flags = new unsigned char[Cache->Head().PackageCount];
@@ -84,13 +83,28 @@ void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candid
 bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
 {
    // Adapt the iterator
 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);
    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++)
    {
    // Look for broken conflicts+predepends.
    for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
    {
@@ -103,6 +117,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)
          {
@@ -131,9 +146,22 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
 bool pkgSimulate::Configure(PkgIterator iPkg)
 {
    // Adapt the iterator
 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;
    
    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)
    {
 //   Sim.MarkInstall(Pkg,false);
    if (Sim[Pkg].InstBroken() == true)
    {
@@ -152,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();
            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();
       }            
@@ -179,10 +209,26 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
 bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
 {
    // Adapt the iterator
 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);
 
    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
    if (Purge == true)
       cout << "Purg ";
    else
@@ -223,6 +269,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)
@@ -233,13 +281,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());
@@ -254,14 +302,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);
         }
@@ -287,10 +337,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 */
@@ -303,7 +355,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);
@@ -320,23 +372,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);
 
@@ -348,7 +402,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);
         }
       }
    }
         }
       }
    }
@@ -363,6 +417,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)
@@ -379,7 +435,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();
@@ -392,6 +448,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;
    
@@ -408,9 +466,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..
@@ -428,7 +486,6 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
    return true;
 }
                                                                        /*}}}*/
    return true;
 }
                                                                        /*}}}*/
-
 // ProblemResolver::pkgProblemResolver - Constructor                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // ProblemResolver::pkgProblemResolver - Constructor                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -475,6 +532,36 @@ void pkgProblemResolver::MakeScores()
    unsigned long Size = Cache.Head().PackageCount;
    memset(Scores,0,sizeof(*Scores)*Size);
 
    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++)
    {
    // Generate the base scores for a package based on its properties
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
@@ -483,23 +570,23 @@ void pkgProblemResolver::MakeScores()
       
       signed short &Score = Scores[I->ID];
       
       
       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)
          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
 
       // 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
       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
    }
 
    // Now that we have the base scores we go and propogate dependencies
@@ -510,8 +597,11 @@ void pkgProblemResolver::MakeScores()
       
       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)
-           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;
       }
    }   
    
       }
    }   
    
@@ -531,7 +621,9 @@ void pkgProblemResolver::MakeScores()
       {
         // Only do it for the install version
         if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
       {
         // 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]);
            continue;    
         
         Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
@@ -556,10 +648,10 @@ void pkgProblemResolver::MakeScores()
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
       if ((Flags[I->ID] & Protected) != 0)
    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)
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-        Scores[I->ID] += 5000;
-   }   
+        Scores[I->ID] += AddEssential;
+   }
 }
                                                                        /*}}}*/
 // ProblemResolver::DoUpgrade - Attempt to upgrade this package                /*{{{*/
 }
                                                                        /*}}}*/
 // ProblemResolver::DoUpgrade - Attempt to upgrade this package                /*{{{*/
@@ -568,6 +660,8 @@ 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] & Protected) == Protected)
    if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
       return false;
    if ((Flags[Pkg->ID] & Protected) == Protected)
@@ -576,7 +670,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    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)
@@ -640,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 || 
               /* 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;
               
@@ -661,7 +756,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;
@@ -688,6 +783,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
@@ -703,7 +800,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;
            }
@@ -730,19 +827,21 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
       *PEnd++ = I;
    This = this;
    qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
       *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;
 
    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
    /* 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
@@ -769,14 +868,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)
@@ -787,7 +886,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];
@@ -821,7 +920,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;
                  }
               }
@@ -842,7 +941,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)
@@ -852,7 +956,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
            }
            
            if (Debug == 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 across the version list. If there are no possible
               targets then we keep the package and bail. This is necessary
 
            /* Look across the version list. If there are no possible
               targets then we keep the package and bail. This is necessary
@@ -860,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 &&
            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)
            {          
@@ -871,7 +976,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
               }
               
               Change = true;
               }
               
               Change = true;
-              Cache.MarkKeep(I);                 
+              Cache.MarkKeep(I, false, false);
               break;
            }
            
               break;
            }
            
@@ -890,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 &&
               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..
@@ -908,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();
                  /* 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
@@ -917,7 +1023,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;
@@ -932,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 (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];
+                       }
                     }
                  }
                                  
                     }
                  }
                                  
@@ -955,7 +1058,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)
+                 {
+                    // 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;
                  // Skip adding to the kill list if it is protected
                  if ((Flags[Pkg->ID] & Protected) != 0)
                     continue;
@@ -976,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 &&
            // 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)
            {
@@ -989,7 +1108,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;
@@ -1023,6 +1142,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
               if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
               {
                  if (J->Dep->Type == pkgCache::Dep::Conflicts || 
               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)
                      J->Dep->Type == pkgCache::Dep::Obsoletes)
                  {
                     if (Debug == true)
@@ -1034,7 +1154,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)
@@ -1064,8 +1184,7 @@ 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 
+   // 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)) {
    pkgCache::PkgIterator I = Cache.PkgBegin();
    for (;I.end() != true; I++) {
       if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
@@ -1088,11 +1207,10 @@ 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;
 
    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 
    MakeScores();
    
    /* We have to order the packages so that the broken fixing pass 
@@ -1105,7 +1223,21 @@ bool pkgProblemResolver::ResolveByKeep()
       *PEnd++ = I;
    This = this;
    qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
       *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++)
    // Consider each broken package 
    pkgCache::Package **LastStop = 0;
    for (pkgCache::Package **K = PList; K != PEnd; K++)
@@ -1121,7 +1253,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;
@@ -1151,8 +1283,8 @@ bool pkgProblemResolver::ResolveByKeep()
         while (true)
         {
            if (Debug == true)
         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++)
            // Look at all the possible provides on this package
            SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
            for (pkgCache::Version **V = VList; *V != 0; V++)
@@ -1168,8 +1300,8 @@ bool pkgProblemResolver::ResolveByKeep()
               if ((Flags[I->ID] & Protected) == 0)
               {
                  if (Debug == true)
               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)
               }
               
               if (Cache[I].InstBroken() == false)
@@ -1206,19 +1338,25 @@ 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);
+        }
       }
    }   
 }
                                                                        /*}}}*/
       }
    }   
 }
                                                                        /*}}}*/
-
 // PrioSortList - Sort a list of versions by priority                  /*{{{*/
 // ---------------------------------------------------------------------
 /* This is ment to be used in conjunction with AllTargets to get a list 
 // PrioSortList - Sort a list of versions by priority                  /*{{{*/
 // ---------------------------------------------------------------------
 /* This is ment to be used in conjunction with AllTargets to get a list 
@@ -1249,188 +1387,87 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    qsort(List,Count,sizeof(*List),PrioComp);
 }
                                                                        /*}}}*/
    qsort(List,Count,sizeof(*List),PrioComp);
 }
                                                                        /*}}}*/
-
-
-// mark a single package in Mark-and-Sweep
-void pkgMarkPackage(pkgDepCache &Cache,
-                   const pkgCache::PkgIterator &pkg,
-                   const pkgCache::VerIterator &ver,
-                   bool follow_recommends,
-                   bool follow_suggests)
+// 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)
 {
 {
-   pkgDepCache::StateCache &state=Cache[pkg];
-   pkgCache::VerIterator candver=state.CandidateVerIter(Cache);
-   pkgCache::VerIterator instver=state.InstVerIter(Cache);
-
-#if 0
-   // If a package was garbage-collected but is now being marked, we
-   // should re-select it 
-   // For cases when a pkg is set to upgrade and this trigger the
-   // removal of a no-longer used dependency.  if the pkg is set to
-   // keep again later it will result in broken deps
-   if(state.Delete() && state.RemoveReason=pkgDepCache::Unused) 
-   {
-      if(ver==candver)
-        mark_install(pkg, false, false, NULL);
-      else if(ver==pkg.CurrentVer())
-        MarkKeep(pkg);
-      
-      instver=state.InstVerIter(*this);
-   }
-#endif
-
-   // Ignore versions other than the InstVer, and ignore packages
-   // that are already going to be removed or just left uninstalled.
-   if(!(ver==instver && !instver.end()))
-      return;
-
-   // if we are marked already we are done
-   if(state.Marked)
-      return;
+   pkgAcquire::RunResult res;
+   pkgAcquire Fetcher;
+   if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
+      return false;
 
 
-   //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
-   state.Marked=true;
-
-   if(!ver.end())
-   {
-     for(pkgCache::DepIterator d=ver.DependsList(); !d.end(); ++d)
-     {
-       if(d->Type==pkgCache::Dep::Depends ||
-          d->Type==pkgCache::Dep::PreDepends ||
-          (follow_recommends &&
-           d->Type==pkgCache::Dep::Recommends) ||
-          (follow_suggests &&
-           d->Type==pkgCache::Dep::Suggests))
-        {
-          // Try all versions of this package.
-          for(pkgCache::VerIterator V=d.TargetPkg().VersionList(); 
-              !V.end(); ++V)
-          {
-             if(_system->VS->CheckDep(V.VerStr(),d->CompareOp, d.TargetVer()))
-             {
-                pkgMarkPackage(Cache, V.ParentPkg(), V, 
-                               follow_recommends, follow_suggests);
-             }
-          }
-          // Now try virtual packages
-          for(pkgCache::PrvIterator prv=d.TargetPkg().ProvidesList(); 
-              !prv.end(); ++prv)
-          {
-             if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
-                                      d.TargetVer()))
-             {
-                pkgMarkPackage(Cache, prv.OwnerPkg(), prv.OwnerVer(),
-                               follow_recommends, follow_suggests);
-             }
-          }
-       }
-     }
-   }
-}
+   // 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();
 
 
-bool pkgMarkUsed(pkgDepCache &Cache)
-{
-   bool follow_recommends;
-   bool follow_suggests;
+   if (res == pkgAcquire::Failed)
+      return false;
 
 
-   // init the states
-   for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p)
+   bool Failed = false;
+   bool TransientNetworkFailure = false;
+   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); 
+       I != Fetcher.ItemsEnd(); I++)
    {
    {
-      Cache[p].Marked=false;
-      Cache[p].Garbage=false;
-   }
+      if ((*I)->Status == pkgAcquire::Item::StatDone)
+        continue;
 
 
-   // init vars
-   follow_recommends=_config->FindB("APT::AutoRemove::RecommendsImportant",false);
-   follow_suggests=_config->FindB("APT::AutoRemove::SuggestsImportend", false);
+      (*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());
 
 
-   // do the mark part
-   for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p)
-   {
-      if(!(Cache[p].Flags & pkgCache::Flag::Auto) ||
-        (p->Flags & pkgCache::Flag::Essential))
+      if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) 
       {
       {
-        if(Cache[p].Keep() && !p.CurrentVer().end())
-           pkgMarkPackage(Cache, p, p.CurrentVer(),
-                          follow_recommends, follow_suggests);
-        else if(Cache[p].Install())
-           pkgMarkPackage(Cache, p, Cache[p].InstVerIter(Cache),
-                          follow_recommends, follow_suggests);
+        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."));
 
 
 
 
-   // do the sweep
-   for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p)
-  {
-     pkgDepCache::StateCache &state=Cache[p];
-
-     if(!state.Marked)
-     {
-       // mark installed but not yet marked stuff as garbage
-       if(p->CurrentVer != 0) {
-          state.Garbage=true;
-          std::cout << "Garbage: " << p.Name() << std::endl;
-       }
-
-#if 0   // mvo: the below bits still needs to be ported
-
-       // Be sure not to re-delete already deleted packages.
-       if(delete_unused && (!p.CurrentVer().end() || state.Install()) &&
-          !state.Delete())
-       {
-             bool do_delete=true;
-
-             // If the package is being upgraded, check if we're
-             // losing a versioned dep.  If the dependency matches
-             // the previous version and not the new version, keep
-             // the package back instead of removing it.
-             if(!p.CurrentVer().end() && state.Install())
-               {
-                 const char *vs=p.CurrentVer().VerStr();
-
-                 // Check direct revdeps only.  THIS ASSUMES NO
-                 // VERSIONED PROVIDES, but Debian probably won't
-                 // have them for ages if ever.
-                 for(pkgCache::DepIterator revdep=p.RevDependsList();
-                     !revdep.end(); ++revdep)
-                   {
-                     pkgCache::PkgIterator depender=revdep.ParentPkg();
-                     // Find which version of the depending package
-                     // will be installed.
-                     pkgCache::VerIterator instver=(*this)[depender].InstVerIter(*this);
-
-                     // Only pay attention to strong positive
-                     // dependencies whose parents will be installed.
-                     if(revdep.ParentVer()==instver &&
-                        (revdep->Type==pkgCache::Dep::Depends ||
-                         revdep->Type==pkgCache::Dep::PreDepends ||
-                         (revdep->Type==pkgCache::Dep::Recommends &&
-                          follow_recommends)))
-                       {
-                         // If the previous version matched, cancel the
-                         // deletion.  (note that I assume that the new
-                         // version does NOT match; otherwise it would
-                         // not be unused!)
-                         if(_system->VS->CheckDep(vs,
-                                                  revdep->CompareOp,
-                                                  revdep.TargetVer()))
-                           {
-                             mark_keep(p, false, false, undo);
-                             do_delete=false;
-                             break;
-                           }
-                       }
-                   }
-               }
+   // Run the success scripts if all was fine
+   if(!TransientNetworkFailure && !Failed)
+      RunScripts("APT::Update::Post-Invoke-Success");
 
 
-             if(do_delete)
-               mark_delete(p, false, true, undo);
-           }
-#endif
-     }
-  }
+   // Run the other scripts
+   RunScripts("APT::Update::Post-Invoke");
    return true;
 }
    return true;
 }
+                                                                       /*}}}*/