]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/depcache.cc
more explicit MarkRequired algorithm code (part 2)
[apt.git] / apt-pkg / depcache.cc
index ee40b879c04328110262d4ef7d04b24f9b8abc9f..eb8f6460d1454fe2995c3e1de7c05ce6d2be1aaf 100644 (file)
@@ -1824,6 +1824,20 @@ bool pkgDepCache::MarkFollowsSuggests()
 }
 
 // pkgDepCache::MarkRequired - the main mark algorithm                 /*{{{*/
+static bool IsPkgInBoringState(pkgCache::PkgIterator const &Pkg, pkgDepCache::StateCache const * const PkgState)
+{
+   if (Pkg->CurrentVer == 0)
+   {
+      if (PkgState[Pkg->ID].Keep())
+        return true;
+   }
+   else
+   {
+      if (PkgState[Pkg->ID].Delete())
+        return true;
+   }
+   return false;
+}
 bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 {
    if (_config->Find("APT::Solver", "internal") != "internal")
@@ -1832,8 +1846,8 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
    bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false);
 
    // init the states
-   map_id_t const PackagesCount = Head().PackageCount;
-   for(map_id_t i = 0; i < PackagesCount; ++i)
+   auto const PackagesCount = Head().PackageCount;
+   for(auto i = decltype(PackagesCount){0}; i < PackagesCount; ++i)
    {
       PkgState[i].Marked  = false;
       PkgState[i].Garbage = false;
@@ -1849,16 +1863,8 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
    // do the mark part, this is the core bit of the algorithm
    for (PkgIterator P = PkgBegin(); !P.end(); ++P)
    {
-      if (P->CurrentVer == 0)
-      {
-        if (PkgState[P->ID].Keep())
-           continue;
-      }
-      else
-      {
-        if (PkgState[P->ID].Delete())
-           continue;
-      }
+      if (PkgState[P->ID].Marked || IsPkgInBoringState(P, PkgState))
+        continue;
 
       if ((PkgState[P->ID].Flags & Flag::Auto) == 0)
         ;
@@ -1888,124 +1894,70 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 }
                                                                        /*}}}*/
 // MarkPackage - mark a single package in Mark-and-Sweep               /*{{{*/
-void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
-                             const pkgCache::VerIterator &ver,
+void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &Pkg,
+                             const pkgCache::VerIterator &Ver,
                              bool const &follow_recommends,
                              bool const &follow_suggests)
 {
-   pkgDepCache::StateCache &state = PkgState[pkg->ID];
+   {
+      pkgDepCache::StateCache &state = PkgState[Pkg->ID];
+      // if we are marked already we are done
+      if(state.Marked || unlikely(Ver.end()))
+        return;
+      state.Marked=true;
+   }
 
-   // if we are marked already we are done
-   if(state.Marked)
+   if (IsPkgInBoringState(Pkg, PkgState))
       return;
 
-   VerIterator const currver = pkg.CurrentVer();
-   VerIterator const instver = state.InstVerIter(*this);
-
-#if 0
-   VerIterator const candver = state.CandidateVerIter(*this);
+   bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false);
+   if(debug_autoremove)
+      std::clog << "Marking: " << Pkg.FullName() << " " << Ver.VerStr() << std::endl;
 
-   // 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 = Unused) 
+   for (auto D = Ver.DependsList(); D.end() == false; ++D)
    {
-      if(ver==candver)
-        mark_install(pkg, false, false, NULL);
-      else if(ver==pkg.CurrentVer())
-        MarkKeep(pkg, false, false);
-      
-      instver=state.InstVerIter(*this);
-   }
-#endif
+      auto const T = D.TargetPkg();
+      if (PkgState[T->ID].Marked)
+        continue;
 
-   // 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 (D->Type != Dep::Depends &&
+           D->Type != Dep::PreDepends &&
+           (follow_recommends == false || D->Type != Dep::Recommends) &&
+           (follow_suggests == false || D->Type != Dep::Suggests))
+        continue;
 
-   bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false);
+      // handle the virtual part first
+      for(auto Prv = T.ProvidesList(); Prv.end() == false; ++Prv)
+      {
+        auto PP = Prv.OwnerPkg();
+        if (PkgState[PP->ID].Marked || IsPkgInBoringState(PP, PkgState))
+           continue;
 
-   if(debug_autoremove)
-     {
-       std::clog << "Marking: " << pkg.FullName();
-       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;
-     }
+        // we want to ignore provides from uninteresting versions
+        auto const PV = (PkgState[PP->ID].Install()) ?
+           PkgState[PP->ID].InstVerIter(*this) : PP.CurrentVer();
+        if (unlikely(PV.end()) || PV != Prv.OwnerVer() || D.IsSatisfied(Prv) == false)
+           continue;
 
-   state.Marked=true;
+        if (debug_autoremove)
+           std::clog << "Following dep: " << APT::PrettyDep(this, D)
+              << ", provided by " << PP.FullName() << " " << PV.VerStr() << std::endl;
+        MarkPackage(PP, PV, follow_recommends, follow_suggests);
+      }
 
-   if(ver.end() == true)
-      return;
+      // now deal with the real part of the package
+      if (IsPkgInBoringState(T, PkgState))
+        continue;
 
-     for(DepIterator d = ver.DependsList(); !d.end(); ++d)
-     {
-       if(d->Type == Dep::Depends ||
-          d->Type == Dep::PreDepends ||
-          (follow_recommends &&
-           d->Type == Dep::Recommends) ||
-          (follow_suggests &&
-           d->Type == Dep::Suggests))
-        {
-          // Try all versions of this package.
-          for(VerIterator V = d.TargetPkg().VersionList(); 
-              !V.end(); ++V)
-          {
-             if(d.IsSatisfied(V))
-             {
-               if(debug_autoremove)
-                 {
-                   std::clog << "Following dep: " << d.ParentPkg().FullName()
-                             << " " << d.ParentVer().VerStr() << " "
-                             << d.DepType() << " " << d.TargetPkg().FullName();
-                   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);
-             }
-          }
-          // Now try virtual packages
-          for(PrvIterator prv=d.TargetPkg().ProvidesList(); 
-              !prv.end(); ++prv)
-          {
-             if(d.IsSatisfied(prv))
-             {
-               if(debug_autoremove)
-                 {
-                   std::clog << "Following dep: " << d.ParentPkg().FullName() << " "
-                             << d.ParentVer().VerStr() << " "
-                             << d.DepType() << " " << d.TargetPkg().FullName() << " ";
-                   if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
-                     {
-                       std::clog << " (" << d.CompType() << " "
-                                 << d.TargetVer() << ")";
-                     }
-                   std::clog << ", provided by "
-                             << prv.OwnerPkg().FullName() << " "
-                             << prv.OwnerVer().VerStr()
-                             << std::endl;
-                 }
-
-                MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
-                            follow_recommends, follow_suggests);
-             }
-          }
-       }
-     }
+      auto const TV = (PkgState[T->ID].Install()) ?
+        PkgState[T->ID].InstVerIter(*this) : T.CurrentVer();
+      if (unlikely(TV.end()) || D.IsSatisfied(TV) == false)
+        continue;
+
+      if (debug_autoremove)
+        std::clog << "Following dep: " << APT::PrettyDep(this, D) << std::endl;
+      MarkPackage(T, TV, follow_recommends, follow_suggests);
+   }
 }
                                                                        /*}}}*/
 bool pkgDepCache::Sweep()                                              /*{{{*/