forward manual-installed bit on package disappearance
authorDavid Kalnischkies <kalnischkies@gmail.com>
Thu, 27 May 2010 16:13:52 +0000 (18:13 +0200)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Thu, 27 May 2010 16:13:52 +0000 (18:13 +0200)
apt-pkg/deb/dpkgpm.cc
apt-pkg/deb/dpkgpm.h
debian/changelog

index 35b1097..0ac6ac1 100644 (file)
@@ -470,7 +470,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
         std::clog << "send: '" << status.str() << "'" << endl;
 
       if (strncmp(action, "disappear", strlen("disappear")) == 0)
-        disappearedPkgs.insert(string(pkg_or_trigger));
+        handleDisappearAction(pkg_or_trigger);
       return;
    }
 
@@ -530,6 +530,51 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
                << " action: " << action << endl;
 }
                                                                        /*}}}*/
+// DPkgPM::handleDisappearAction                                       /*{{{*/
+void pkgDPkgPM::handleDisappearAction(string const &pkgname)
+{
+   // record the package name for display and stuff later
+   disappearedPkgs.insert(pkgname);
+
+   pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname);
+   if (unlikely(Pkg.end() == true))
+      return;
+   // the disappeared package was auto-installed - nothing to do
+   if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
+      return;
+   pkgCache::VerIterator PkgVer = Pkg.CurrentVer();
+   if (unlikely(PkgVer.end() == true))
+      return;
+   /* search in the list of dependencies for (Pre)Depends,
+      check if this dependency has a Replaces on our package
+      and if so transfer the manual installed flag to it */
+   for (pkgCache::DepIterator Dep = PkgVer.DependsList(); Dep.end() != true; ++Dep)
+   {
+      if (Dep->Type != pkgCache::Dep::Depends &&
+         Dep->Type != pkgCache::Dep::PreDepends)
+        continue;
+      pkgCache::PkgIterator Tar = Dep.TargetPkg();
+      if (unlikely(Tar.end() == true))
+        continue;
+      // the package is already marked as manual
+      if ((Cache[Tar].Flags & pkgCache::Flag::Auto) != pkgCache::Flag::Auto)
+        continue;
+      pkgCache::VerIterator TarVer = Tar.CurrentVer();
+      for (pkgCache::DepIterator Rep = TarVer.DependsList(); Rep.end() != true; ++Rep)
+      {
+        if (Rep->Type != pkgCache::Dep::Replaces)
+           continue;
+        if (Pkg != Rep.TargetPkg())
+           continue;
+        // okay, they are strongly connected - transfer manual-bit
+        if (Debug == true)
+           std::clog << "transfer manual-bit from disappeared »" << pkgname << "« to »" << Tar.FullName() << "«" << std::endl;
+        Cache[Tar].Flags &= ~Flag::Auto;
+        break;
+      }
+   }
+}
+                                                                       /*}}}*/
 // DPkgPM::DoDpkgStatusFd                                              /*{{{*/
 // ---------------------------------------------------------------------
 /*
index b1459b1..9a4478f 100644 (file)
@@ -32,6 +32,21 @@ class pkgDPkgPM : public pkgPackageManager
    FILE *history_out;
    string dpkg_error;
 
+   /** \brief record the disappear action and handle accordingly
+
+      dpkg let packages disappear then they have no files any longer and
+      nothing depends on them. We need to collect this as dpkg as well as
+      APT doesn't know beforehand that the package will disappear, so the
+      only possible option is to tell the user afterwards about it.
+      To enhance the experience we also try to forward the auto-install
+      flag so the disappear-causer(s) are not autoremoved next time -
+      for the transfer to happen the disappeared version needs to depend
+      on the package the flag should be forwarded to and this package
+      needs to declare a Replaces on the disappeared package.
+      \param pkgname Name of the package that disappeared
+   */
+   void handleDisappearAction(string const &pkgname);
+
    protected:
 
    // progress reporting
index ee571a5..9fa0405 100644 (file)
@@ -3,8 +3,9 @@ apt (0.7.26~exp6) UNRELEASED; urgency=low
   [ David Kalnischkies ]
   * apt-pkg/deb/dpkgpm.cc:
     - write Disappeared also to the history.log
+    - forward manual-installed bit on package disappearance
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Thu, 27 May 2010 15:12:02 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Thu, 27 May 2010 17:34:51 +0200
 
 apt (0.7.26~exp5) experimental; urgency=low