]> 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 d14155d01616f4b0ee4c1f489f468606c5d25141..9d1739d68032988ab67247d43e8b9607ab02d0e8 100644 (file)
@@ -61,6 +61,8 @@
 #include <apti18n.h>
                                                                        /*}}}*/
 
 #include <apti18n.h>
                                                                        /*}}}*/
 
+extern char **environ;
+
 using namespace std;
 
 APT_PURE static string AptHistoryRequestingUser()                      /*{{{*/
 using namespace std;
 
 APT_PURE static string AptHistoryRequestingUser()                      /*{{{*/
@@ -417,7 +419,6 @@ bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version)
 bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
 {
    bool result = true;
 bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
 {
    bool result = true;
-   static bool interrupted = false;
 
    Configuration::Item const *Opts = _config->Tree(Cnf);
    if (Opts == 0 || Opts->Child == 0)
 
    Configuration::Item const *Opts = _config->Tree(Cnf);
    if (Opts == 0 || Opts->Child == 0)
@@ -425,9 +426,8 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
    Opts = Opts->Child;
 
    sighandler_t old_sigpipe = signal(SIGPIPE, SIG_IGN);
    Opts = Opts->Child;
 
    sighandler_t old_sigpipe = signal(SIGPIPE, SIG_IGN);
-   sighandler_t old_sigint = signal(SIGINT, [](int signum){
-        interrupted = true;
-   });
+   sighandler_t old_sigint = signal(SIGINT, SIG_IGN);
+   sighandler_t old_sigquit = signal(SIGQUIT, SIG_IGN);
 
    unsigned int Count = 1;
    for (; Opts != 0; Opts = Opts->Next, Count++)
 
    unsigned int Count = 1;
    for (; Opts != 0; Opts = Opts->Next, Count++)
@@ -528,9 +528,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
    }
    signal(SIGINT, old_sigint);
    signal(SIGPIPE, old_sigpipe);
    }
    signal(SIGINT, old_sigint);
    signal(SIGPIPE, old_sigpipe);
-
-   if (interrupted)
-      result = _error->Error("Interrupted");
+   signal(SIGQUIT, old_sigquit);
 
    return result;
 }
 
    return result;
 }
@@ -1297,37 +1295,34 @@ static void cleanUpTmpDir(char * const tmpdir)                          /*{{{*/
  * through to human readable (and i10n-able)
  * names and calculates a percentage for each step.
  */
  * through to human readable (and i10n-able)
  * names and calculates a percentage for each step.
  */
-bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
+static bool ItemIsEssential(pkgDPkgPM::Item const &I)
+{
+   static auto const cachegen = _config->Find("pkgCacheGen::Essential");
+   if (cachegen == "none" || cachegen == "native")
+      return true;
+   if (unlikely(I.Pkg.end()))
+      return true;
+   return (I.Pkg->Flags & pkgCache::Flag::Essential) != 0;
+}
+bool pkgDPkgPM::ExpandPendingCalls(std::vector<Item> &List, pkgDepCache &Cache)
 {
 {
-   // we remove the last configures (and after that removes) from the list here
-   // as they will be covered by the pending calls, so explicit calls are busy work
-   decltype(List)::const_iterator::difference_type explicitIdx =
-      std::distance(List.cbegin(),
-           _config->FindB("Dpkg::ExplicitLastConfigure", false) ? List.cend() :
-           std::find_if_not(
-              std::find_if_not(List.crbegin(), List.crend(), [](Item const &i) { return i.Op == Item::Configure; }),
-              List.crend(), [](Item const &i) { return i.Op == Item::Remove || i.Op == Item::Purge; }).base());
-
-   // explicitely remove everything for hookscripts and progress building
    {
       std::unordered_set<decltype(pkgCache::Package::ID)> alreadyRemoved;
       for (auto && I : List)
         if (I.Op == Item::Remove || I.Op == Item::Purge)
            alreadyRemoved.insert(I.Pkg->ID);
    {
       std::unordered_set<decltype(pkgCache::Package::ID)> alreadyRemoved;
       for (auto && I : List)
         if (I.Op == Item::Remove || I.Op == Item::Purge)
            alreadyRemoved.insert(I.Pkg->ID);
-      decltype(List) AppendList;
+      std::remove_reference<decltype(List)>::type AppendList;
       for (auto Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
         if (Cache[Pkg].Delete() && alreadyRemoved.insert(Pkg->ID).second == true)
            AppendList.emplace_back(Cache[Pkg].Purge() ? Item::Purge : Item::Remove, Pkg);
       std::move(AppendList.begin(), AppendList.end(), std::back_inserter(List));
    }
       for (auto Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
         if (Cache[Pkg].Delete() && alreadyRemoved.insert(Pkg->ID).second == true)
            AppendList.emplace_back(Cache[Pkg].Purge() ? Item::Purge : Item::Remove, Pkg);
       std::move(AppendList.begin(), AppendList.end(), std::back_inserter(List));
    }
-
-   // explicitely configure everything for hookscripts and progress building
    {
       std::unordered_set<decltype(pkgCache::Package::ID)> alreadyConfigured;
       for (auto && I : List)
         if (I.Op == Item::Configure)
            alreadyConfigured.insert(I.Pkg->ID);
    {
       std::unordered_set<decltype(pkgCache::Package::ID)> alreadyConfigured;
       for (auto && I : List)
         if (I.Op == Item::Configure)
            alreadyConfigured.insert(I.Pkg->ID);
-      decltype(List) AppendList;
+      std::remove_reference<decltype(List)>::type AppendList;
       for (auto && I : List)
         if (I.Op == Item::Install && alreadyConfigured.insert(I.Pkg->ID).second == true)
            AppendList.emplace_back(Item::Configure, I.Pkg);
       for (auto && I : List)
         if (I.Op == Item::Install && alreadyConfigured.insert(I.Pkg->ID).second == true)
            AppendList.emplace_back(Item::Configure, I.Pkg);
@@ -1336,20 +1331,26 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
            AppendList.emplace_back(Item::Configure, Pkg);
       std::move(AppendList.begin(), AppendList.end(), std::back_inserter(List));
    }
            AppendList.emplace_back(Item::Configure, Pkg);
       std::move(AppendList.begin(), AppendList.end(), std::back_inserter(List));
    }
+   return true;
+}
+bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
+{
+   // explicitely remove&configure everything for hookscripts and progress building
+   // we need them only temporarily through, so keep the length and erase afterwards
+   decltype(List)::const_iterator::difference_type explicitIdx =
+      std::distance(List.cbegin(), List.cend());
+   ExpandPendingCalls(List, Cache);
 
 
-   auto const ItemIsEssential = [](pkgDPkgPM::Item const &I) {
-      static auto const cachegen = _config->Find("pkgCacheGen::Essential");
-      if (cachegen == "none" || cachegen == "native")
-        return true;
-      if (unlikely(I.Pkg.end()))
-        return true;
-      return (I.Pkg->Flags & pkgCache::Flag::Essential) != 0;
-   };
-
-   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();
       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());
    };
 
         }), Pending.end());
    };
 
@@ -1542,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 (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());
         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
         List.emplace_back(Item::PurgePending, pkgCache::PkgIterator());
 
       // support subpressing of triggers processing for special
@@ -1613,7 +1618,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
       unsigned long const Op = I->Op;
 
       if (NoTriggers == true && I->Op != Item::TriggersPending &&
       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");
       }
       {
         ADDARGC("--no-triggers");
       }
@@ -1678,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());
            {
               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());
               std::string linkpath;
               if (dpkg_recursive_install_numbered)
                  strprintf(linkpath, "%s/%.*lu-%s", tmpdir_to_free, p, n, file.c_str());
@@ -1704,7 +1711,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
       else if (I->Op == Item::RemovePending)
       {
         ++I;
       else if (I->Op == Item::RemovePending)
       {
         ++I;
-        StripAlreadyDoneFromPending(approvedStates.Remove());
+        StripAlreadyDoneFrom(approvedStates.Remove());
         if (approvedStates.Remove().empty())
            continue;
       }
         if (approvedStates.Remove().empty())
            continue;
       }
@@ -1713,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
         ++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;
         if (approvedStates.Purge().empty())
            continue;
         std::remove_reference<decltype(approvedStates.Remove())>::type approvedRemoves;
@@ -1965,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
    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()));
       APT::StateChanges undo;
       auto && undoRem = approvedStates.Remove();
       std::move(undoRem.begin(), undoRem.end(), std::back_inserter(undo.Install()));
@@ -1976,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!");
    }
       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!");
 
    if (currentStates.Save(false) == false)
       _error->Error("Couldn't restore dpkg selection states which were present before this interaction!");