]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/depcache.cc
merge with lp:apt/debian-sid
[apt.git] / apt-pkg / depcache.cc
index fe981ea763a339a35e44e5f7c4df2cb3cebb8551..e17b7b0e82308240aeadab5d2855b6671987f046 100644 (file)
@@ -15,6 +15,7 @@
 #include <apt-pkg/algorithms.h>
 
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/algorithms.h>
 
 #include <apt-pkg/fileutl.h>
+#include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/tagfile.h>
 #include <sys/stat.h>
 
 #include <apti18n.h>    
 #include <sys/stat.h>
 
 #include <apti18n.h>    
-
-pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
+                                                                       /*}}}*/
+// helper for Install-Recommends-Sections and Never-MarkAuto-Sections  /*{{{*/
+static bool 
+ConfigValueInSubTree(const char* SubTree, const char *needle)
+{
+   Configuration::Item const *Opts;
+   Opts = _config->Tree(SubTree);
+   if (Opts != 0 && Opts->Child != 0)
+   {
+      Opts = Opts->Child;
+      for (; Opts != 0; Opts = Opts->Next)
+      {
+        if (Opts->Value.empty() == true)
+           continue;
+        if (strcmp(needle, Opts->Value.c_str()) == 0)
+           return true;
+      }
+   }
+   return false;
+}
+                                                                       /*}}}*/
+pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :            /*{{{*/
   cache(cache), released(false)
 {
   ++cache.group_level;
   cache(cache), released(false)
 {
   ++cache.group_level;
@@ -55,13 +76,15 @@ pkgDepCache::ActionGroup::~ActionGroup()
 {
   release();
 }
 {
   release();
 }
-
+                                                                       /*}}}*/
 // DepCache::pkgDepCache - Constructors                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
   group_level(0), Cache(pCache), PkgState(0), DepState(0)
 {
 // DepCache::pkgDepCache - Constructors                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
   group_level(0), Cache(pCache), PkgState(0), DepState(0)
 {
+   DebugMarker = _config->FindB("Debug::pkgDepCache::Marker", false);
+   DebugAutoInstall = _config->FindB("Debug::pkgDepCache::AutoInstall", false);
    delLocalPolicy = 0;
    LocalPolicy = Plcy;
    if (LocalPolicy == 0)
    delLocalPolicy = 0;
    LocalPolicy = Plcy;
    if (LocalPolicy == 0)
@@ -138,8 +161,7 @@ bool pkgDepCache::Init(OpProgress *Prog)
    return true;
 } 
                                                                        /*}}}*/
    return true;
 } 
                                                                        /*}}}*/
-
-bool pkgDepCache::readStateFile(OpProgress *Prog)
+bool pkgDepCache::readStateFile(OpProgress *Prog)                      /*{{{*/
 {
    FileFd state_file;
    string state = _config->FindDir("Dir::State") + "extended_states";
 {
    FileFd state_file;
    string state = _config->FindDir("Dir::State") + "extended_states";
@@ -177,8 +199,8 @@ bool pkgDepCache::readStateFile(OpProgress *Prog)
 
    return true;
 }
 
    return true;
 }
-
-bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
+                                                                       /*}}}*/
+bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/
 {
    if(_config->FindB("Debug::pkgAutoRemove",false))
       std::clog << "pkgDepCache::writeStateFile()" << std::endl;
 {
    if(_config->FindB("Debug::pkgAutoRemove",false))
       std::clog << "pkgDepCache::writeStateFile()" << std::endl;
@@ -216,7 +238,6 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
         pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
         if(pkg.end() || pkg.VersionList().end()) 
            continue;
         pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
         if(pkg.end() || pkg.VersionList().end()) 
            continue;
-        bool oldAuto = section.FindI("Auto-Installed");
         bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
         if(_config->FindB("Debug::pkgAutoRemove",false))
            std::clog << "Update exisiting AutoInstall info: " 
         bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
         if(_config->FindB("Debug::pkgAutoRemove",false))
            std::clog << "Update exisiting AutoInstall info: " 
@@ -249,7 +270,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
         ostr.str(string(""));
         ostr << "Package: " << pkg.Name() 
              << "\nAuto-Installed: 1\n\n";
         ostr.str(string(""));
         ostr << "Package: " << pkg.Name() 
              << "\nAuto-Installed: 1\n\n";
-        fprintf(OutFile,ostr.str().c_str());
+        fprintf(OutFile,"%s",ostr.str().c_str());
         fprintf(OutFile,"\n");
       }
    }
         fprintf(OutFile,"\n");
       }
    }
@@ -261,7 +282,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
 
    return true;
 }
 
    return true;
 }
-
+                                                                       /*}}}*/
 // DepCache::CheckDep - Checks a single dependency                     /*{{{*/
 // ---------------------------------------------------------------------
 /* This first checks the dependency against the main target package and
 // DepCache::CheckDep - Checks a single dependency                     /*{{{*/
 // ---------------------------------------------------------------------
 /* This first checks the dependency against the main target package and
@@ -679,13 +700,12 @@ void pkgDepCache::Update(PkgIterator const &Pkg)
           P.end() != true; P++)
         Update(P.ParentPkg().RevDependsList());
 }
           P.end() != true; P++)
         Update(P.ParentPkg().RevDependsList());
 }
-
                                                                        /*}}}*/
                                                                        /*}}}*/
-
 // DepCache::MarkKeep - Put the package in the keep state              /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // DepCache::MarkKeep - Put the package in the keep state              /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
+void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
+                           unsigned long Depth)
 {
    // Simplifies other routines.
    if (Pkg.end() == true)
 {
    // Simplifies other routines.
    if (Pkg.end() == true)
@@ -726,6 +746,9 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
      P.Flags &= ~Flag::Auto;
 #endif
 
      P.Flags &= ~Flag::Auto;
 #endif
 
+   if (DebugMarker == true)
+      std::clog << OutputInDepth(Depth) << "MarkKeep " << Pkg << " FU=" << FromUser << std::endl;
+
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
 
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
 
@@ -745,7 +768,8 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
 // DepCache::MarkDelete - Put the package in the delete state          /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // DepCache::MarkDelete - Put the package in the delete state          /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
+void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
+                             unsigned long Depth, bool FromUser)
 {
    // Simplifies other routines.
    if (Pkg.end() == true)
 {
    // Simplifies other routines.
    if (Pkg.end() == true)
@@ -767,6 +791,13 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
    if (Pkg->VersionList == 0)
       return;
 
    if (Pkg->VersionList == 0)
       return;
 
+   // check if we are allowed to install the package
+   if (IsDeleteOk(Pkg,rPurge,Depth,FromUser) == false)
+      return;
+
+   if (DebugMarker == true)
+      std::clog << OutputInDepth(Depth) << "MarkDelete " << Pkg << " FU=" << FromUser << std::endl;
+
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
    
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
    
@@ -781,6 +812,23 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
    AddSizes(Pkg);
 }
                                                                        /*}}}*/
    AddSizes(Pkg);
 }
                                                                        /*}}}*/
+// DepCache::IsDeleteOk - check if it is ok to remove this package     /*{{{*/
+// ---------------------------------------------------------------------
+/* The default implementation just honors dpkg hold
+   But an application using this library can override this method
+   to control the MarkDelete behaviour */
+bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge,
+                             unsigned long Depth, bool FromUser)
+{
+   if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold)
+   {
+      if (DebugMarker == true)
+        std::clog << OutputInDepth(Depth) << "Hold prevents MarkDelete of " << Pkg << " FU=" << FromUser << std::endl;
+      return false;
+   }
+   return true;
+}
+                                                                       /*}}}*/
 // DepCache::MarkInstall - Put the package in the install state                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // DepCache::MarkInstall - Put the package in the install state                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -806,7 +854,7 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
        P.CandidateVer == (Version *)Pkg.CurrentVer()))
    {
       if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
        P.CandidateVer == (Version *)Pkg.CurrentVer()))
    {
       if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
-        MarkKeep(Pkg, false, FromUser);
+        MarkKeep(Pkg, false, FromUser, Depth+1);
       return;
    }
 
       return;
    }
 
@@ -816,6 +864,11 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
    // We dont even try to install virtual packages..
    if (Pkg->VersionList == 0)
       return;
    // We dont even try to install virtual packages..
    if (Pkg->VersionList == 0)
       return;
+
+   // check if we are allowed to install the package
+   if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false)
+      return;
+
    /* Target the candidate version and remove the autoflag. We reset the
       autoflag below if this was called recursively. Otherwise the user
       should have the ability to de-auto a package by changing its state */
    /* Target the candidate version and remove the autoflag. We reset the
       autoflag below if this was called recursively. Otherwise the user
       should have the ability to de-auto a package by changing its state */
@@ -844,10 +897,13 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
    AddStates(Pkg);
    Update(Pkg);
    AddSizes(Pkg);
    AddStates(Pkg);
    Update(Pkg);
    AddSizes(Pkg);
-   
+
    if (AutoInst == false)
       return;
 
    if (AutoInst == false)
       return;
 
+   if (DebugMarker == true)
+      std::clog << OutputInDepth(Depth) << "MarkInstall " << Pkg << " FU=" << FromUser << std::endl;
+
    DepIterator Dep = P.InstVerIter(*this).DependsList();
    for (; Dep.end() != true;)
    {
    DepIterator Dep = P.InstVerIter(*this).DependsList();
    for (; Dep.end() != true;)
    {
@@ -875,37 +931,60 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
       if (IsImportantDep(Start) == false)
         continue;
       
       if (IsImportantDep(Start) == false)
         continue;
       
-      /* check if any ImportantDep() (but not Critial) where added
-       * since we installed the package
+      /* Check if any ImportantDep() (but not Critical) were added
+       * since we installed the package.  Also check for deps that
+       * were satisfied in the past: for instance, if a version
+       * restriction in a Recommends was tightened, upgrading the
+       * package should follow that Recommends rather than causing the
+       * dependency to be removed. (bug #470115)
        */
       bool isNewImportantDep = false;
        */
       bool isNewImportantDep = false;
+      bool isPreviouslySatisfiedImportantDep = false;
       if(!ForceImportantDeps && !Start.IsCritical())
       {
         bool found=false;
         VerIterator instVer = Pkg.CurrentVer();
         if(!instVer.end())
         {
       if(!ForceImportantDeps && !Start.IsCritical())
       {
         bool found=false;
         VerIterator instVer = Pkg.CurrentVer();
         if(!instVer.end())
         {
-           for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
-           {
+          for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
+            {
               //FIXME: deal better with or-groups(?)
               DepIterator LocalStart = D;
               //FIXME: deal better with or-groups(?)
               DepIterator LocalStart = D;
-              
-              if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
-                 found=true;
-           }
+
+              if(IsImportantDep(D) && !D.IsCritical() &&
+                 Start.TargetPkg() == D.TargetPkg())
+                {
+                  if(!isPreviouslySatisfiedImportantDep)
+                    {
+                      DepIterator D2 = D;
+                      while((D2->CompareOp & Dep::Or) != 0)
+                        ++D2;
+
+                      isPreviouslySatisfiedImportantDep =
+                        (((*this)[D2] & DepGNow) != 0);
+                    }
+
+                  found=true;
+                }
+            }
            // this is a new dep if it was not found to be already
            // a important dep of the installed pacakge
            isNewImportantDep = !found;
         }
       }
       if(isNewImportantDep)
            // this is a new dep if it was not found to be already
            // a important dep of the installed pacakge
            isNewImportantDep = !found;
         }
       }
       if(isNewImportantDep)
-        if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
-           std::clog << "new important dependency: " 
+        if(DebugAutoInstall == true)
+           std::clog << OutputInDepth(Depth) << "new important dependency: "
                      << Start.TargetPkg().Name() << std::endl;
                      << Start.TargetPkg().Name() << std::endl;
+      if(isPreviouslySatisfiedImportantDep)
+       if(DebugAutoInstall == true)
+         std::clog << OutputInDepth(Depth) << "previously satisfied important dependency on "
+                   << Start.TargetPkg().Name() << std::endl;
 
       // skip important deps if the package is already installed
       if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
 
       // skip important deps if the package is already installed
       if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
-         && !isNewImportantDep && !ForceImportantDeps)
+         && !isNewImportantDep && !isPreviouslySatisfiedImportantDep
+         && !ForceImportantDeps)
         continue;
       
       /* If we are in an or group locate the first or that can 
         continue;
       
       /* If we are in an or group locate the first or that can 
@@ -948,18 +1027,18 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
            }
         }
         
            }
         }
         
-        if (InstPkg.end() == false) 
+        if (InstPkg.end() == false)
         {
         {
-           if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
-              std::clog << "Installing " << InstPkg.Name() 
-                        << " as dep of " << Pkg.Name() 
+           if(DebugAutoInstall == true)
+              std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
+                        << " as " << Start.DepType() << " of " << Pkg.Name()
                         << std::endl;
            // now check if we should consider it a automatic dependency or not
                         << std::endl;
            // now check if we should consider it a automatic dependency or not
-           string sec = _config->Find("APT::Never-MarkAuto-Section","");
-           if(Pkg.Section() && (string(Pkg.Section()) ==  sec))
+           if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
            {
            {
-              if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
-                 std::clog << "Setting NOT as auto-installed because its a direct dep of a package in section " << sec << std::endl;
+              if(DebugAutoInstall == true)
+                 std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct "
+                            << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
               MarkInstall(InstPkg,true,Depth + 1, true);
            }
            else 
               MarkInstall(InstPkg,true,Depth + 1, true);
            }
            else 
@@ -986,16 +1065,32 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
            PkgIterator Pkg = Ver.ParentPkg();
 
            if (Start->Type != Dep::DpkgBreaks)
            PkgIterator Pkg = Ver.ParentPkg();
 
            if (Start->Type != Dep::DpkgBreaks)
-              MarkDelete(Pkg);
-           else
-              if (PkgState[Pkg->ID].CandidateVer != *I)
-                 MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
+              MarkDelete(Pkg,false,Depth + 1, false);
+           else if (PkgState[Pkg->ID].CandidateVer != *I)
+              MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
         }
         continue;
       }      
    }
 }
                                                                        /*}}}*/
         }
         continue;
       }      
    }
 }
                                                                        /*}}}*/
+// DepCache::IsInstallOk - check if it is ok to install this package   /*{{{*/
+// ---------------------------------------------------------------------
+/* The default implementation just honors dpkg hold
+   But an application using this library can override this method
+   to control the MarkInstall behaviour */
+bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
+                             unsigned long Depth, bool FromUser)
+{
+   if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold)
+   {
+      if (DebugMarker == true)
+        std::clog << OutputInDepth(Depth) << "Hold prevents MarkInstall of " << Pkg << " FU=" << FromUser << std::endl;
+      return false;
+   }
+   return true;
+}
+                                                                       /*}}}*/
 // DepCache::SetReInstall - Set the reinstallation flag                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // DepCache::SetReInstall - Set the reinstallation flag                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1095,7 +1190,6 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
    return Ver;
 }
                                                                        /*}}}*/
    return Ver;
 }
                                                                        /*}}}*/
-
 // Policy::GetCandidateVer - Returns the Candidate install version     /*{{{*/
 // ---------------------------------------------------------------------
 /* The default just returns the highest available version that is not
 // Policy::GetCandidateVer - Returns the Candidate install version     /*{{{*/
 // ---------------------------------------------------------------------
 /* The default just returns the highest available version that is not
@@ -1147,13 +1241,9 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
       // sections
       // FIXME: this is a meant as a temporarly solution until the 
       //        recommends are cleaned up
       // sections
       // FIXME: this is a meant as a temporarly solution until the 
       //        recommends are cleaned up
-      string s = _config->Find("APT::Install-Recommends-Section","");
-      if(s.size() > 0) 
-      {
-        const char *sec = Dep.TargetPkg().Section();
-        if (sec && strcmp(sec, s.c_str()) == 0)
-           return true;
-      }
+      const char *sec = Dep.ParentVer().Section();
+      if (sec && ConfigValueInSubTree("APT::Install-Recommends-Sections", sec))
+        return true;
    }
    else if(Dep->Type == pkgCache::Dep::Suggests)
      return _config->FindB("APT::Install-Suggests", false);
    }
    else if(Dep->Type == pkgCache::Dep::Suggests)
      return _config->FindB("APT::Install-Suggests", false);
@@ -1161,8 +1251,7 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
    return false;
 }
                                                                        /*}}}*/
    return false;
 }
                                                                        /*}}}*/
-
-pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
+pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()                  /*{{{*/
   : constructedSuccessfully(false)
 {
   Configuration::Item const *Opts;
   : constructedSuccessfully(false)
 {
   Configuration::Item const *Opts;
@@ -1191,8 +1280,8 @@ pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
 
   constructedSuccessfully = true;
 }
 
   constructedSuccessfully = true;
 }
-
-pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
+                                                                       /*}}}*/
+pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()                 /*{{{*/
 {
   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
     {
 {
   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
     {
@@ -1200,9 +1289,8 @@ pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
       delete rootSetRegexp[i];
     }
 }
       delete rootSetRegexp[i];
     }
 }
-
-
-bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
+                                                                       /*}}}*/
+bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg) /*{{{*/
 {
    for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
       if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
 {
    for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
       if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
@@ -1210,8 +1298,8 @@ bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg
 
    return false;
 }
 
    return false;
 }
-
-pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
+                                                                       /*}}}*/
+pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()              /*{{{*/
 {
   DefaultRootSetFunc *f = new DefaultRootSetFunc;
   if(f->wasConstructedSuccessfully())
 {
   DefaultRootSetFunc *f = new DefaultRootSetFunc;
   if(f->wasConstructedSuccessfully())
@@ -1222,7 +1310,7 @@ pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
       return NULL;
     }
 }
       return NULL;
     }
 }
-
+                                                                       /*}}}*/
 bool pkgDepCache::MarkFollowsRecommends()
 {
   return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
 bool pkgDepCache::MarkFollowsRecommends()
 {
   return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
@@ -1233,7 +1321,7 @@ bool pkgDepCache::MarkFollowsSuggests()
   return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
 }
 
   return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
 }
 
-// the main mark algorithm
+// pkgDepCache::MarkRequired - the main mark algorithm                 /*{{{*/
 bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 {
    bool follow_recommends;
 bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 {
    bool follow_recommends;
@@ -1267,7 +1355,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
       {
         // the package is installed (and set to keep)
         if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
       {
         // the package is installed (and set to keep)
         if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
-           MarkPackage(p, p.CurrentVer(),
+           MarkPackage(p, p.CurrentVer(),
                        follow_recommends, follow_suggests);
         // the package is to be installed 
         else if(PkgState[p->ID].Install())
                        follow_recommends, follow_suggests);
         // the package is to be installed 
         else if(PkgState[p->ID].Install())
@@ -1278,14 +1366,15 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 
    return true;
 }
 
    return true;
 }
-
-// mark a single package in Mark-and-Sweep
+                                                                       /*}}}*/
+// MarkPackage - mark a single package in Mark-and-Sweep               /*{{{*/
 void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
                              const pkgCache::VerIterator &ver,
                              bool follow_recommends,
                              bool follow_suggests)
 {
    pkgDepCache::StateCache &state = PkgState[pkg->ID];
 void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
                              const pkgCache::VerIterator &ver,
                              bool follow_recommends,
                              bool follow_suggests)
 {
    pkgDepCache::StateCache &state = PkgState[pkg->ID];
+   VerIterator currver            = pkg.CurrentVer();
    VerIterator candver            = state.CandidateVerIter(*this);
    VerIterator instver            = state.InstVerIter(*this);
 
    VerIterator candver            = state.CandidateVerIter(*this);
    VerIterator instver            = state.InstVerIter(*this);
 
@@ -1306,16 +1395,29 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
    }
 #endif
 
    }
 #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()))
+   // For packages that are not going to be removed, ignore versions
+   // other than the InstVer.  For packages that are going to be
+   // removed, ignore versions other than the current version.
+   if(!(ver == instver && !instver.end()) &&
+      !(ver == currver && instver.end() && !ver.end()))
       return;
 
    // if we are marked already we are done
    if(state.Marked)
       return;
 
       return;
 
    // if we are marked already we are done
    if(state.Marked)
       return;
 
-   //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
+   if(_config->FindB("Debug::pkgAutoRemove",false))
+     {
+       std::clog << "Marking: " << pkg.Name();
+       if(!ver.end())
+        std::clog << " " << ver.VerStr();
+       if(!currver.end())
+        std::clog << ", Curr=" << currver.VerStr();
+       if(!instver.end())
+        std::clog << ", Inst=" << instver.VerStr();
+       std::clog << std::endl;
+     }
+
    state.Marked=true;
 
    if(!ver.end())
    state.Marked=true;
 
    if(!ver.end())
@@ -1335,6 +1437,19 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
           {
              if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
              {
           {
              if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
              {
+               if(_config->FindB("Debug::pkgAutoRemove",false))
+                 {
+                   std::clog << "Following dep: " << d.ParentPkg().Name()
+                             << " " << d.ParentVer().VerStr() << " "
+                             << d.DepType() << " "
+                             << d.TargetPkg().Name();
+                   if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
+                     {
+                       std::clog << " (" << d.CompType() << " "
+                                 << d.TargetVer() << ")";
+                     }
+                   std::clog << std::endl;
+                 }
                 MarkPackage(V.ParentPkg(), V, 
                             follow_recommends, follow_suggests);
              }
                 MarkPackage(V.ParentPkg(), V, 
                             follow_recommends, follow_suggests);
              }
@@ -1346,6 +1461,23 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
              if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
                                       d.TargetVer()))
              {
              if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
                                       d.TargetVer()))
              {
+               if(_config->FindB("Debug::pkgAutoRemove",false))
+                 {
+                   std::clog << "Following dep: " << d.ParentPkg().Name()
+                             << " " << d.ParentVer().VerStr() << " "
+                             << d.DepType() << " "
+                             << d.TargetPkg().Name();
+                   if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
+                     {
+                       std::clog << " (" << d.CompType() << " "
+                                 << d.TargetVer() << ")";
+                     }
+                   std::clog << ", provided by "
+                             << prv.OwnerPkg().Name() << " "
+                             << prv.OwnerVer().VerStr()
+                             << std::endl;
+                 }
+
                 MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
                             follow_recommends, follow_suggests);
              }
                 MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
                             follow_recommends, follow_suggests);
              }
@@ -1354,8 +1486,8 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
      }
    }
 }
      }
    }
 }
-
-bool pkgDepCache::Sweep()
+                                                                       /*}}}*/
+bool pkgDepCache::Sweep()                                              /*{{{*/
 {
    // do the sweep
    for(PkgIterator p=PkgBegin(); !p.end(); ++p)
 {
    // do the sweep
    for(PkgIterator p=PkgBegin(); !p.end(); ++p)
@@ -1378,3 +1510,4 @@ bool pkgDepCache::Sweep()
 
    return true;
 }
 
    return true;
 }
+                                                                       /*}}}*/