summaryrefslogtreecommitdiff
path: root/apt-pkg/deb
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2016-07-08 09:40:46 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2016-08-10 23:18:04 +0200
commite7d4e0cf4f6d79810e4b4e7de505729e759213dd (patch)
treeba19ea1f8d96b71f20a16e07ec082332a6196002 /apt-pkg/deb
parentb820fd59c4fe6e3581901eee648e88209be56137 (diff)
select remove/purge packages early on for dpkg
Telling dpkg early on that we are going to remove these packages later helps it with auto-deconfiguration decisions and its another area where a planner can ignore the nitty gritty details and let dpkg decide the course of action if there are no special requirements.
Diffstat (limited to 'apt-pkg/deb')
-rw-r--r--apt-pkg/deb/dpkgpm.cc95
-rw-r--r--apt-pkg/deb/dpkgpm.h3
2 files changed, 84 insertions, 14 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 38285d14b..bc34e50e0 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -1372,6 +1372,50 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
return _error->Error("Couldn't clean the currently selected dpkg states");
}
}
+ APT::StateChanges approvedStates;
+ if (_config->FindB("dpkg::selection::remove::approved", true))
+ {
+ for (auto && I: List)
+ if (I.Op == Item::Remove && Cache[I.Pkg].Delete())
+ approvedStates.Remove(FindToBeRemovedVersion(I.Pkg));
+ else if (I.Op == Item::Purge && Cache[I.Pkg].Purge())
+ approvedStates.Purge(FindToBeRemovedVersion(I.Pkg));
+ if (approvedStates.Save(false) == false)
+ {
+ _error->Error("Couldn't record the approved state changes as dpkg selection states");
+ if (currentStates.Save(false) == false)
+ _error->Error("Couldn't restore dpkg selection states which were present before this interaction!");
+ return false;
+ }
+
+ {
+ std::vector<bool> toBeRemoved(Cache.Head().PackageCount, false);
+ std::vector<bool> toBePurged(Cache.Head().PackageCount, false);
+ for (auto Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
+ if (Cache[Pkg].Purge())
+ toBePurged[Pkg->ID] = true;
+ else if (Cache[Pkg].Delete())
+ toBeRemoved[Pkg->ID] = true;
+ for (auto && I: approvedStates.Remove())
+ toBeRemoved[I.ParentPkg()->ID] = false;
+ for (auto && I: approvedStates.Purge())
+ toBePurged[I.ParentPkg()->ID] = false;
+ if (std::find(toBeRemoved.begin(), toBeRemoved.end(), true) != toBeRemoved.end())
+ {
+ if (ConfigurePending)
+ List.emplace(std::prev(List.end()), Item::RemovePending, pkgCache::PkgIterator());
+ else
+ List.emplace_back(Item::RemovePending, pkgCache::PkgIterator());
+ }
+ if (std::find(toBePurged.begin(), toBePurged.end(), true) != toBePurged.end())
+ {
+ if (ConfigurePending)
+ List.emplace(std::prev(List.end()), Item::PurgePending, pkgCache::PkgIterator());
+ else
+ List.emplace_back(Item::PurgePending, pkgCache::PkgIterator());
+ }
+ }
+ }
d->stdin_is_dev_null = false;
@@ -1460,6 +1504,16 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
ADDARGC("--pending");
break;
+ case Item::RemovePending:
+ ADDARGC("--remove");
+ ADDARGC("--pending");
+ break;
+
+ case Item::PurgePending:
+ ADDARGC("--purge");
+ ADDARGC("--pending");
+ break;
+
case Item::Install:
ADDARGC("--unpack");
ADDARGC("--auto-deconfigure");
@@ -1741,6 +1795,17 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
StopPtyMagic();
CloseLog();
+ if (d->dpkg_error.empty() == false)
+ {
+ APT::StateChanges undo;
+ auto && undoRem = approvedStates.Remove();
+ std::move(undoRem.begin(), undoRem.end(), std::back_inserter(undo.Remove()));
+ auto && undoPur = approvedStates.Purge();
+ std::move(undoPur.begin(), undoPur.end(), std::back_inserter(undo.Purge()));
+ approvedStates.clear();
+ if (undo.Save(false) == false)
+ _error->Error("Couldn't revert dpkg selection for approved remove/purge after an error was encountered!");
+ }
if (currentStates.Save(false) == false)
_error->Error("Couldn't restore dpkg selection states which were present before this interaction!");
@@ -1991,20 +2056,24 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
}
// log the ordering, see dpkgpm.h and the "Ops" enum there
- const char *ops_str[] = {
- "Install",
- "Configure",
- "Remove",
- "Purge",
- "ConfigurePending",
- "TriggersPending",
- };
fprintf(report, "AptOrdering:\n");
- for (vector<Item>::iterator I = List.begin(); I != List.end(); ++I)
- if ((*I).Pkg != NULL)
- fprintf(report, " %s: %s\n", (*I).Pkg.Name(), ops_str[(*I).Op]);
- else
- fprintf(report, " %s: %s\n", "NULL", ops_str[(*I).Op]);
+ for (auto && I : List)
+ {
+ char const * opstr = nullptr;
+ switch (I.Op)
+ {
+ case Item::Install: opstr = "Install"; break;
+ case Item::Configure: opstr = "Configure"; break;
+ case Item::Remove: opstr = "Remove"; break;
+ case Item::Purge: opstr = "Purge"; break;
+ case Item::ConfigurePending: opstr = "ConfigurePending"; break;
+ case Item::TriggersPending: opstr = "TriggersPending"; break;
+ case Item::RemovePending: opstr = "RemovePending"; break;
+ case Item::PurgePending: opstr = "PurgePending"; break;
+ }
+ auto const pkgname = I.Pkg.end() ? "NULL" : I.Pkg.FullName();
+ fprintf(report, " %s: %s\n", pkgname.c_str(), opstr);
+ }
// attach dmesg log (to learn about segfaults)
if (FileExists("/bin/dmesg"))
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index 408a37334..07c99aead 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -79,7 +79,8 @@ class pkgDPkgPM : public pkgPackageManager
struct Item
{
- enum Ops {Install, Configure, Remove, Purge, ConfigurePending, TriggersPending} Op;
+ enum Ops {Install, Configure, Remove, Purge, ConfigurePending, TriggersPending,
+ RemovePending, PurgePending } Op;
std::string File;
PkgIterator Pkg;
Item(Ops Op,PkgIterator Pkg,std::string File = "") : Op(Op),