]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/deb/dpkgpm.cc
CMake: Add coverage build type
[apt.git] / apt-pkg / deb / dpkgpm.cc
index 5759e6ba5d9091f1451c4f553a5b4ea6eef78009..9d1739d68032988ab67247d43e8b9607ab02d0e8 100644 (file)
@@ -61,6 +61,8 @@
 #include <apti18n.h>
                                                                        /*}}}*/
 
+extern char **environ;
+
 using namespace std;
 
 APT_PURE static string AptHistoryRequestingUser()                      /*{{{*/
@@ -1339,10 +1341,16 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
       std::distance(List.cbegin(), List.cend());
    ExpandPendingCalls(List, Cache);
 
-   auto const StripAlreadyDoneFromPending = [&](APT::VersionVector & Pending) {
+   /* if dpkg told us that it has already done everything to the package we wanted it to do,
+      we shouldn't ask it for "more" later. That can e.g. happen if packages without conffiles
+      are purged as they will have pass through the purge states on remove already */
+   auto const StripAlreadyDoneFrom = [&](APT::VersionVector & Pending) {
       Pending.erase(std::remove_if(Pending.begin(), Pending.end(), [&](pkgCache::VerIterator const &Ver) {
            auto const PN = Ver.ParentPkg().FullName();
-           return PackageOps[PN].size() <= PackageOpsDone[PN];
+           auto const POD = PackageOpsDone.find(PN);
+           if (POD == PackageOpsDone.end())
+              return false;
+           return PackageOps[PN].size() <= POD->second;
         }), Pending.end());
    };
 
@@ -1535,9 +1543,13 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
         if (I.Op == Item::Remove || I.Op == Item::Purge)
            toBeRemoved[I.Pkg->ID] = false;
 
-      if (std::find(toBeRemoved.begin(), toBeRemoved.end(), true) != toBeRemoved.end())
+      bool const RemovePending = std::find(toBeRemoved.begin(), toBeRemoved.end(), true) != toBeRemoved.end();
+      bool const PurgePending = approvedStates.Purge().empty() == false;
+      if (RemovePending != false || PurgePending != false)
+        List.emplace_back(Item::ConfigurePending, pkgCache::PkgIterator());
+      if (RemovePending)
         List.emplace_back(Item::RemovePending, pkgCache::PkgIterator());
-      if (approvedStates.Purge().empty() == false)
+      if (PurgePending)
         List.emplace_back(Item::PurgePending, pkgCache::PkgIterator());
 
       // support subpressing of triggers processing for special
@@ -1606,7 +1618,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
       unsigned long const Op = I->Op;
 
       if (NoTriggers == true && I->Op != Item::TriggersPending &&
-         I->Op != Item::ConfigurePending)
+         (I->Op != Item::ConfigurePending || std::next(I) != List.end()))
       {
         ADDARGC("--no-triggers");
       }
@@ -1671,7 +1683,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
            {
               if (I->File[0] != '/')
                  return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str());
-              auto const file = flNotDir(I->File);
+              auto file = flNotDir(I->File);
+              if (flExtension(file) != "deb")
+                 file.append(".deb");
               std::string linkpath;
               if (dpkg_recursive_install_numbered)
                  strprintf(linkpath, "%s/%.*lu-%s", tmpdir_to_free, p, n, file.c_str());
@@ -1697,7 +1711,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
       else if (I->Op == Item::RemovePending)
       {
         ++I;
-        StripAlreadyDoneFromPending(approvedStates.Remove());
+        StripAlreadyDoneFrom(approvedStates.Remove());
         if (approvedStates.Remove().empty())
            continue;
       }
@@ -1706,7 +1720,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
         ++I;
         // explicit removes of packages without conffiles passthrough the purge states instantly, too.
         // Setting these non-installed packages up for purging generates 'unknown pkg' warnings from dpkg
-        StripAlreadyDoneFromPending(approvedStates.Purge());
+        StripAlreadyDoneFrom(approvedStates.Purge());
         if (approvedStates.Purge().empty())
            continue;
         std::remove_reference<decltype(approvedStates.Remove())>::type approvedRemoves;
@@ -1958,8 +1972,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
    if (d->dpkg_error.empty() == false)
    {
       // no point in reseting packages we already completed removal for
-      StripAlreadyDoneFromPending(approvedStates.Remove());
-      StripAlreadyDoneFromPending(approvedStates.Purge());
+      StripAlreadyDoneFrom(approvedStates.Remove());
+      StripAlreadyDoneFrom(approvedStates.Purge());
       APT::StateChanges undo;
       auto && undoRem = approvedStates.Remove();
       std::move(undoRem.begin(), undoRem.end(), std::back_inserter(undo.Install()));
@@ -1969,6 +1983,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
       if (undo.Save(false) == false)
         _error->Error("Couldn't revert dpkg selection for approved remove/purge after an error was encountered!");
    }
+
+   StripAlreadyDoneFrom(currentStates.Remove());
+   StripAlreadyDoneFrom(currentStates.Purge());
    if (currentStates.Save(false) == false)
       _error->Error("Couldn't restore dpkg selection states which were present before this interaction!");