]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/algorithms.cc
* merged with apt--main and apt--fixes
[apt.git] / apt-pkg / algorithms.cc
index 2799c2fddaca78b24f54c705b36076fb848b190e..98bd8dd8bac9be636be9ce3e1007e5bbf372e3d6 100644 (file)
@@ -1243,3 +1243,107 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    qsort(List,Count,sizeof(*List),PrioComp);
 }
                                                                        /*}}}*/
+
+
+// pkgMarkPkgUsed - Mark used packages as dirty                                /*{{{*/
+// ---------------------------------------------------------------------
+/* Mark all reachable packages as dirty. */
+void pkgMarkPkgUsed(pkgDepCache &Cache, pkgCache::PkgIterator Pkg, 
+                  pkgCache::State::PkgRemoveState DirtLevel)
+{
+   // If it is not installed, and we are in manual mode, ignore it
+   if ((Pkg->CurrentVer == 0 && Cache[Pkg].Install() == false || Cache[Pkg].Delete() == true) &&
+       DirtLevel == pkgCache::State::RemoveManual) 
+   {
+//      fprintf(stdout,"This one is not installed/virtual %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+      return;
+   }
+
+   // If it is not installed, and it is not virtual, ignore it
+   if ((Pkg->CurrentVer == 0 && Cache[Pkg].Install() == false || Cache[Pkg].Delete() == true) &&
+       Pkg->VersionList != 0)
+   {
+//      fprintf(stdout,"This one is not installed %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+      return;
+   }
+
+   // If it is similar or more dirty than we are ;-), because we've been here already, don't mark it
+   // This is necessary because virtual packages just relay the current level,
+   // so it may be possible e.g. that this was already seen with ::RemoveSuggested, but
+   // we are ::RemoveRequired
+   if (Cache[Pkg].Dirty() >= DirtLevel) 
+   {
+      //fprintf(stdout,"Seen already %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+      return;
+   }
+   
+   // If it is less important than the current DirtLevel, don't mark it
+   if (Cache[Pkg].AutomaticRemove != pkgCache::State::RemoveManual && 
+      Cache[Pkg].AutomaticRemove > DirtLevel) 
+   {
+//       fprintf(stdout,"We don't need %s %d %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel, Cache[Pkg].Dirty());
+       return;
+   }
+
+   // Mark it as used
+   Cache.SetDirty(Pkg, DirtLevel);
+       
+   //fprintf(stdout,"We keep %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+
+   // We are a virtual package
+   if (Pkg->VersionList == 0)
+   {
+//      fprintf(stdout,"We are virtual %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+      for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); ! Prv.end(); ++Prv)
+        pkgMarkPkgUsed (Cache, Prv.OwnerPkg(), DirtLevel);
+      return;
+   }
+
+   // Depending on the type of dependency, follow it
+   for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); ! D.end(); ++D) 
+   {
+//      fprintf(stdout,"We depend on %s %s\n", D.TargetPkg().Name(), D.DepType());
+
+      switch(D->Type) 
+      {
+        case pkgCache::Dep::Depends:
+        case pkgCache::Dep::PreDepends:
+           pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveRequired);
+           break;
+        case pkgCache::Dep::Recommends:
+            pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveRecommended);
+           break;
+         case pkgCache::Dep::Suggests:
+            pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveSuggested);
+           break;
+        case pkgCache::Dep::Conflicts:
+        case pkgCache::Dep::Replaces:
+        case pkgCache::Dep::Obsoletes:
+           // We don't handle these here
+           break;
+      }
+   }
+//   fprintf(stdout,"We keep %s %d %d <END>\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+}
+                                                                       /*}}}*/
+
+bool pkgMarkUsed(pkgDepCache &Cache)
+{
+   // debug only
+   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg)
+      if(!Cache[Pkg].Dirty() && Cache[Pkg].AutomaticRemove > 0)
+        std::cout << "has auto-remove information: " << Pkg.Name() 
+                  << " " << (int)Cache[Pkg].AutomaticRemove 
+                  << std::endl;
+
+   // init with defaults
+   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg)
+      Cache.SetDirty(Pkg, pkgCache::State::RemoveUnknown);
+
+   // go recursive over the cache
+   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg) 
+      pkgMarkPkgUsed (Cache, Pkg, pkgCache::State::RemoveManual);
+
+   
+   return true;
+}