[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH] Delete dependency packages more thoroughly when removing a package.



Hello All,

My name is Ulrik Sjolin and I have been assigned to solve an issue with apt-get at $DAYJOB. The bug we encounter is related to the fact that we have an or-package pretty high up in our dependency tree. This leads to the problem where apt adds a bunch of packages that it later on decides should be removed. In the removal process apt-get does not remove the all packages it added in the first pass (looks a bit like bug 122304) . This forces us to use the auto-remove functionality. Unfortunately that switch does not work for us since this will remove packages that we want.

So I have created a patch that I would appreciate if you would review/approve/merge ;-)  I am sure that this is not the most efficient way of writing this code, I am new to the apt code base so advice and or suggestions on how to improve the patch is greatly appreciated. I have run our test cases on the patch and it seems to work....

Best Regards,

Ulrik Sjolin
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index 34da745..3d6d5f5 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -715,6 +715,42 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 	 Cache.MarkKeep(Pkg, false, false);
       else
 	 Cache.MarkDelete(Pkg);
+
+      // Loop over all the packages and look for further packages to remove.
+      // The specific case that we need to handle here is the one where a package
+      // that is removed has a target package that has no other parent package.
+      for(PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+      {
+        for (pkgCache::DepIterator D = P.RevDependsList(); D.end() == false; D++)
+        {
+	  if (D.ParentPkg()->ID == Pkg->ID)
+	  {
+	    int count = 0;
+	    for(DepIterator childDeps = D.TargetPkg().RevDependsList(); childDeps.end() == false; childDeps++) {
+		if ((Flags[childDeps.ParentPkg()->ID] & PreInstalled) == PreInstalled) {
+		    count++;
+		}
+            }
+
+	    // If the child package only had the parent that we are going to remove and
+	    // the child package was not marked as protected we should get rid of the
+	    // child package.
+	    if(count == 1 && ((Flags[D.TargetPkg()->ID] & Protected) != Protected))
+	    {
+	      if (Debug == true)
+	        clog << "    Killed sibling: " << D.TargetPkg() << endl;
+	      if(WasKept == true)
+		Cache.MarkKeep(D.TargetPkg(), false, false);
+	      else
+	        Cache.MarkDelete(D.TargetPkg());
+            }
+          }
+	}
+      }
+
+     if (Debug == true)
+        clog << "  Killed " << Pkg << endl;
+
       return false;
    }	 
    

Reply to: