]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/deb/dpkgpm.cc
Avoid wedging the entire system if recoverable :/.
[apt.git] / apt-pkg / deb / dpkgpm.cc
index abf91fe2a88bb1f2ebd8b9368d9e5aa6b15bf8b5..79c5f9bdf719cbf9483c51484aca7573c7d37f82 100644 (file)
@@ -1184,6 +1184,18 @@ void pkgDPkgPM::BuildPackagesProgressMap()
         ++PackagesTotal;
         return true;
       });
+      if ((I.Op == Item::Remove || I.Op == Item::Purge) && I.Pkg->CurrentVer != 0)
+      {
+        if (I.Pkg->CurrentState == pkgCache::State::UnPacked ||
+              I.Pkg->CurrentState == pkgCache::State::HalfInstalled)
+        {
+           if (likely(strcmp(PackageOps[name][0].state, "half-configured") == 0))
+           {
+              ++PackageOpsDone[name];
+              --PackagesTotal;
+           }
+        }
+      }
    }
    /* one extra: We don't want the progress bar to reach 100%, especially not
       if we call dpkg --configure --pending and process a bunch of triggers
@@ -1373,7 +1385,9 @@ static void cleanUpTmpDir(char * const tmpdir)                            /*{{{*/
         if (unlikely(Ent->d_type != DT_LNK && Ent->d_type != DT_UNKNOWN))
            continue;
 #endif
-        if (unlikely(unlinkat(dfd, Ent->d_name, 0) != 0))
+        char path[strlen(tmpdir) + 1 + strlen(Ent->d_name) + 1];
+        sprintf(path, "%s/%s", tmpdir, Ent->d_name);
+        if (unlikely(unlink(path) != 0))
            break;
       }
       closedir(D);
@@ -1424,7 +1438,8 @@ bool pkgDPkgPM::ExpandPendingCalls(std::vector<Item> &List, pkgDepCache &Cache)
         if (I.Op == Item::Install && alreadyConfigured.insert(I.Pkg->ID).second == true)
            AppendList.emplace_back(Item::Configure, I.Pkg);
       for (auto Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
-        if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && alreadyConfigured.insert(Pkg->ID).second == true)
+        if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
+              Cache[Pkg].Delete() == false && alreadyConfigured.insert(Pkg->ID).second == true)
            AppendList.emplace_back(Item::Configure, Pkg);
       std::move(AppendList.begin(), AppendList.end(), std::back_inserter(List));
    }
@@ -1525,11 +1540,30 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
            continue;
 
         auto const Grp = I->Pkg.Group();
-        size_t installedInstances = 0;
+        size_t installedInstances = 0, wannabeInstances = 0;
+        bool multiArchInstances = false;
         for (auto Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
-           if (Pkg->CurrentVer != 0 || Cache[Pkg].Install())
+        {
+           if (Pkg->CurrentVer != 0)
+           {
               ++installedInstances;
-        if (installedInstances == 2)
+              if (Cache[Pkg].Delete() == false)
+                 ++wannabeInstances;
+           }
+           else if (PackageOps.find(Pkg.FullName()) != PackageOps.end())
+              ++wannabeInstances;
+           if (multiArchInstances == false)
+           {
+              auto const V = Cache[Pkg].InstVerIter(Cache);
+              if (V.end() == false && (Pkg->CurrentVer == 0 || V != Pkg.CurrentVer()))
+                 multiArchInstances = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
+           }
+        }
+        /* theoretically the installed check would be enough as some wannabe will
+           be first and hence be the crossgrade we were looking for, but #844300
+           prevents this so we keep these situations explicit removes.
+           It is also the reason why neither of them can be a M-A:same package */
+        if (installedInstances == 1 && wannabeInstances == 1 && multiArchInstances == false)
         {
            auto const FirstInstall = std::find_if_not(I, List.end(),
                  [](Item const &i) { return i.Op == Item::Remove || i.Op == Item::Purge; });