diff options
28 files changed, 703 insertions, 246 deletions
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index b173979c3..65c5ff85d 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -25,22 +25,29 @@ #include <apt-pkg/pkgcache.h> #include <apt-pkg/cacheiterators.h> #include <apt-pkg/prettyprinters.h> +#include <apt-pkg/dpkgpm.h> #include <string.h> #include <string> #include <cstdlib> #include <iostream> +#include <utility> #include <apti18n.h> /*}}}*/ using namespace std; +class APT_HIDDEN pkgSimulatePrivate +{ +public: + std::vector<pkgDPkgPM::Item> List; +}; // Simulate::Simulate - Constructor /*{{{*/ // --------------------------------------------------------------------- /* The legacy translations here of input Pkg iterators is obsolete, this is not necessary since the pkgCaches are fully shared now. */ pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache), - d(NULL), iPolicy(Cache), + d(new pkgSimulatePrivate()), iPolicy(Cache), Sim(&Cache->GetCache(),&iPolicy), group(Sim) { @@ -58,6 +65,7 @@ pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache), pkgSimulate::~pkgSimulate() { delete[] Flags; + delete d; } /*}}}*/ // Simulate::Describe - Describe a package /*{{{*/ @@ -90,7 +98,14 @@ void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candid // Simulate::Install - Simulate unpacking of a package /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) +bool pkgSimulate::Install(PkgIterator iPkg,string File) +{ + if (iPkg.end() || File.empty()) + return false; + d->List.emplace_back(pkgDPkgPM::Item::Install, iPkg, File); + return true; +} +bool pkgSimulate::RealInstall(PkgIterator iPkg,string /*File*/) { // Adapt the iterator PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); @@ -138,6 +153,13 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) however. */ bool pkgSimulate::Configure(PkgIterator iPkg) { + if (iPkg.end()) + return false; + d->List.emplace_back(pkgDPkgPM::Item::Configure, iPkg); + return true; +} +bool pkgSimulate::RealConfigure(PkgIterator iPkg) +{ // Adapt the iterator PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); @@ -188,6 +210,13 @@ bool pkgSimulate::Configure(PkgIterator iPkg) /* */ bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge) { + if (iPkg.end()) + return false; + d->List.emplace_back(Purge ? pkgDPkgPM::Item::Purge : pkgDPkgPM::Item::Remove, iPkg); + return true; +} +bool pkgSimulate::RealRemove(PkgIterator iPkg,bool Purge) +{ // Adapt the iterator PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); if (Pkg.end() == true) @@ -232,6 +261,38 @@ void pkgSimulate::ShortBreaks() cout << ']' << endl; } /*}}}*/ +bool pkgSimulate::Go2(APT::Progress::PackageManager *) /*{{{*/ +{ + if (pkgDPkgPM::ExpandPendingCalls(d->List, Cache) == false) + return false; + for (auto && I : d->List) + switch (I.Op) + { + case pkgDPkgPM::Item::Install: + if (RealInstall(I.Pkg, I.File) == false) + return false; + break; + case pkgDPkgPM::Item::Configure: + if (RealConfigure(I.Pkg) == false) + return false; + break; + case pkgDPkgPM::Item::Remove: + if (RealRemove(I.Pkg, false) == false) + return false; + break; + case pkgDPkgPM::Item::Purge: + if (RealRemove(I.Pkg, true) == false) + return false; + break; + case pkgDPkgPM::Item::ConfigurePending: + case pkgDPkgPM::Item::TriggersPending: + case pkgDPkgPM::Item::RemovePending: + case pkgDPkgPM::Item::PurgePending: + return _error->Error("Internal error, simulation encountered unexpected pending item"); + } + return true; +} + /*}}}*/ // ApplyStatus - Adjust for non-ok packages /*{{{*/ // --------------------------------------------------------------------- /* We attempt to change the state of the all packages that have failed diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index c1a26587d..5148ff19d 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -52,9 +52,10 @@ using std::ostream; #endif +class pkgSimulatePrivate; class pkgSimulate : public pkgPackageManager /*{{{*/ { - void * const d; + pkgSimulatePrivate * const d; protected: class Policy : public pkgDepCache::Policy @@ -81,9 +82,16 @@ class pkgSimulate : public pkgPackageManager /*{{{*/ virtual bool Configure(PkgIterator Pkg) APT_OVERRIDE; virtual bool Remove(PkgIterator Pkg,bool Purge) APT_OVERRIDE; + // FIXME: trick to avoid ABI break for virtual reimplementation; fix on next ABI break +public: + APT_HIDDEN bool Go2(APT::Progress::PackageManager * progress); + private: APT_HIDDEN void ShortBreaks(); APT_HIDDEN void Describe(PkgIterator iPkg,std::ostream &out,bool Current,bool Candidate); + APT_HIDDEN bool RealInstall(PkgIterator Pkg,std::string File); + APT_HIDDEN bool RealConfigure(PkgIterator Pkg); + APT_HIDDEN bool RealRemove(PkgIterator Pkg,bool Purge); public: diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 3d0fd622c..54a8dffd7 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -19,9 +19,11 @@ #include <apt-pkg/install-progress.h> #include <apt-pkg/packagemanager.h> #include <apt-pkg/strutl.h> +#include <apt-pkg/statechanges.h> #include <apt-pkg/cacheiterators.h> #include <apt-pkg/macros.h> #include <apt-pkg/pkgcache.h> +#include <apt-pkg/version.h> #include <errno.h> #include <fcntl.h> @@ -36,6 +38,8 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/wait.h> +#include <sys/types.h> +#include <dirent.h> #include <termios.h> #include <time.h> #include <unistd.h> @@ -47,7 +51,9 @@ #include <map> #include <set> #include <string> +#include <type_traits> #include <utility> +#include <unordered_set> #include <vector> #include <sstream> #include <numeric> @@ -205,6 +211,14 @@ pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) return Ver; } /*}}}*/ +static pkgCache::VerIterator FindToBeRemovedVersion(pkgCache::PkgIterator const &Pkg)/*{{{*/ +{ + auto const PV = Pkg.CurrentVer(); + if (PV.end() == false) + return PV; + return FindNowVersion(Pkg); +} + /*}}}*/ // DPkgPM::pkgDPkgPM - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -656,27 +670,23 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // if there are multiple pkgs dpkg would send us a full pkgname:arch pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); if (Grp.end() == false) - { - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { + for (auto P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P)) if(Cache[P].Keep() == false || Cache[P].ReInstall() == true) { - pkgname = P.FullName(); + auto fullname = P.FullName(); + if (Cache[P].Delete() && PackageOps[fullname].size() <= PackageOpsDone[fullname]) + continue; + pkgname = std::move(fullname); break; } - } - } } - const char* const pkg = pkgname.c_str(); - std::string short_pkgname = StringSplit(pkgname, ":")[0]; std::string arch = ""; if (pkgname.find(":") != string::npos) arch = StringSplit(pkgname, ":")[1]; std::string i18n_pkgname = pkgname; if (arch.size() != 0) - strprintf(i18n_pkgname, "%s (%s)", short_pkgname.c_str(), arch.c_str()); + strprintf(i18n_pkgname, "%s (%s)", StringSplit(pkgname, ":")[0].c_str(), arch.c_str()); // 'processing' from dpkg looks like // 'processing: action: pkg' @@ -706,21 +716,21 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) if (prefix == "status") { - std::vector<struct DpkgState> &states = PackageOps[pkg]; + std::vector<struct DpkgState> &states = PackageOps[pkgname]; if (action == "triggers-pending") { if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << short_pkgname + std::clog << "(parsed from dpkg) pkg: " << pkgname << " action: " << action << " (prefix 2 to " - << PackageOpsDone[pkg] << " of " << states.size() << ")" << endl; + << PackageOpsDone[pkgname] << " of " << states.size() << ")" << endl; states.insert(states.begin(), {"installed", N_("Installed %s")}); states.insert(states.begin(), {"half-configured", N_("Configuring %s")}); PackagesTotal += 2; } - else if(PackageOpsDone[pkg] < states.size()) + else if(PackageOpsDone[pkgname] < states.size()) { - char const * next_action = states[PackageOpsDone[pkg]].state; + char const * next_action = states[PackageOpsDone[pkgname]].state; if (next_action) { /* @@ -737,24 +747,52 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) } */ if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << short_pkgname + std::clog << "(parsed from dpkg) pkg: " << pkgname << " action: " << action << " (expected: '" << next_action << "' " - << PackageOpsDone[pkg] << " of " << states.size() << ")" << endl; + << PackageOpsDone[pkgname] << " of " << states.size() << ")" << endl; // check if the package moved to the next dpkg state if(action == next_action) { // only read the translation if there is actually a next action - char const * const translation = _(states[PackageOpsDone[pkg]].str); + char const * const translation = _(states[PackageOpsDone[pkgname]].str); // we moved from one dpkg state to a new one, report that - ++PackageOpsDone[pkg]; + ++PackageOpsDone[pkgname]; ++PackagesDone; std::string msg; strprintf(msg, translation, i18n_pkgname.c_str()); d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); } + else if (action == "unpacked" && strcmp(next_action, "config-files") == 0) + { + // in a crossgrade what looked like a remove first is really an unpack over it + ++PackageOpsDone[pkgname]; + ++PackagesDone; + + auto const Pkg = Cache.FindPkg(pkgname); + if (likely(Pkg.end() == false)) + { + auto const Grp = Pkg.Group(); + if (likely(Grp.end() == false)) + { + for (auto P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P)) + if(Cache[P].Install()) + { + auto && Ops = PackageOps[P.FullName()]; + auto const unpackOp = std::find_if(Ops.cbegin(), Ops.cend(), [](DpkgState const &s) { return strcmp(s.state, "unpacked") == 0; }); + if (unpackOp != Ops.cend()) + { + auto const skipped = std::distance(Ops.cbegin(), unpackOp); + PackagesDone += skipped; + PackageOpsDone[P.FullName()] += skipped; + break; + } + } + } + } + } } } } @@ -1221,6 +1259,34 @@ void pkgDPkgPM::StopPtyMagic() /*{{{*/ d->master = -1; } } + /*}}}*/ +static void cleanUpTmpDir(char * const tmpdir) /*{{{*/ +{ + if (tmpdir == nullptr) + return; + DIR * const D = opendir(tmpdir); + if (D == nullptr) + _error->Errno("opendir", _("Unable to read %s"), tmpdir); + else + { + auto const dfd = dirfd(D); + for (struct dirent *Ent = readdir(D); Ent != nullptr; Ent = readdir(D)) + { + if (Ent->d_name[0] == '.') + continue; +#ifdef _DIRENT_HAVE_D_TYPE + if (unlikely(Ent->d_type != DT_LNK && Ent->d_type != DT_UNKNOWN)) + continue; +#endif + if (unlikely(unlinkat(dfd, Ent->d_name, 0) != 0)) + break; + } + closedir(D); + rmdir(tmpdir); + } + free(tmpdir); +} + /*}}}*/ // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- @@ -1231,8 +1297,59 @@ void pkgDPkgPM::StopPtyMagic() /*{{{*/ * through to human readable (and i10n-able) * names and calculates a percentage for each step. */ +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) +{ + { + 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::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)); + } + { + std::unordered_set<decltype(pkgCache::Package::ID)> alreadyConfigured; + for (auto && I : List) + if (I.Op == Item::Configure) + alreadyConfigured.insert(I.Pkg->ID); + 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 Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && alreadyConfigured.insert(Pkg->ID).second == true) + 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 StripAlreadyDoneFromPending = [&](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]; + }), Pending.end()); + }; + pkgPackageManager::SigINTStop = false; d->progress = progress; @@ -1254,7 +1371,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) OSArgMax = 32*1024; OSArgMax -= EnvironmentSize() - 2*1024; unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes", OSArgMax); - bool const NoTriggers = _config->FindB("DPkg::NoTriggers", false); + bool const NoTriggers = _config->FindB("DPkg::NoTriggers", true); if (RunScripts("DPkg::Pre-Invoke") == false) return false; @@ -1267,28 +1384,173 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (noopDPkgInvocation == false) Cache.writeStateFile(NULL); - decltype(List)::const_iterator::difference_type const notconfidx = - _config->FindB("Dpkg::ExplicitLastConfigure", false) ? std::numeric_limits<decltype(notconfidx)>::max() : - std::distance(List.cbegin(), std::find_if_not(List.crbegin(), List.crend(), [](Item const &i) { return i.Op == Item::Configure; }).base()); - - // support subpressing of triggers processing for special - // cases like d-i that runs the triggers handling manually - bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false); - bool const ConfigurePending = _config->FindB("DPkg::ConfigurePending", true); - if (ConfigurePending) - List.push_back(Item(Item::ConfigurePending, PkgIterator())); + bool dpkg_recursive_install = _config->FindB("dpkg::install::recursive", false); + if (_config->FindB("dpkg::install::recursive::force", false) == false) + { + // dpkg uses a sorted treewalk since that version which enables the workaround to work + auto const dpkgpkg = Cache.FindPkg("dpkg"); + if (likely(dpkgpkg.end() == false && dpkgpkg->CurrentVer != 0)) + dpkg_recursive_install = Cache.VS().CmpVersion("1.18.5", dpkgpkg.CurrentVer().VerStr()) <= 0; + } + // no point in doing this dance for a handful of packages only + unsigned int const dpkg_recursive_install_min = _config->FindB("dpkg::install::recursive::minimum", 5); + // FIXME: workaround for dpkg bug, see our ./test-bug-740843-versioned-up-down-breaks test + bool const dpkg_recursive_install_numbered = _config->FindB("dpkg::install::recursive::numbered", true); // for the progress BuildPackagesProgressMap(); - if (notconfidx != std::numeric_limits<decltype(notconfidx)>::max()) + APT::StateChanges approvedStates; + if (_config->FindB("dpkg::selection::remove::approved", true)) { - if (ConfigurePending) - List.erase(std::next(List.begin(), notconfidx), std::prev(List.end())); - else - List.erase(std::next(List.begin(), notconfidx), List.end()); + for (auto && I : List) + if (I.Op == Item::Purge) + approvedStates.Purge(FindToBeRemovedVersion(I.Pkg)); + else if (I.Op == Item::Remove) + approvedStates.Remove(FindToBeRemovedVersion(I.Pkg)); + } + + // Skip removes if we install another architecture of this package soon (crossgrade) + // We can't just skip them all the time as it could be an ordering requirement [of another package] + if ((approvedStates.Remove().empty() == false || approvedStates.Purge().empty() == false) && + _config->FindB("dpkg::remove::crossgrade::implicit", true) == true) + { + std::unordered_set<decltype(pkgCache::Package::ID)> crossgraded; + std::vector<std::pair<Item*, std::string>> toCrossgrade; + auto const PlanedEnd = std::next(List.begin(), explicitIdx); + for (auto I = List.begin(); I != PlanedEnd; ++I) + { + if (I->Op != Item::Remove && I->Op != Item::Purge) + continue; + + auto const Grp = I->Pkg.Group(); + size_t installedInstances = 0; + for (auto Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + if (Pkg->CurrentVer != 0 || Cache[Pkg].Install()) + ++installedInstances; + if (installedInstances == 2) + { + auto const FirstInstall = std::find_if_not(I, List.end(), + [](Item const &i) { return i.Op == Item::Remove || i.Op == Item::Purge; }); + auto const LastInstall = std::find_if_not(FirstInstall, List.end(), + [](Item const &i) { return i.Op == Item::Install; }); + auto const crosser = std::find_if(FirstInstall, LastInstall, + [&I](Item const &i) { return i.Pkg->Group == I->Pkg->Group; }); + if (crosser != LastInstall) + { + crossgraded.insert(I->Pkg->ID); + toCrossgrade.emplace_back(&(*I), crosser->Pkg.FullName()); + } + } + } + for (auto I = PlanedEnd; I != List.end(); ++I) + { + if (I->Op != Item::Remove && I->Op != Item::Purge) + continue; + + auto const Grp = I->Pkg.Group(); + for (auto Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + { + if (Pkg == I->Pkg || Cache[Pkg].Install() == false) + continue; + toCrossgrade.emplace_back(&(*I), Pkg.FullName()); + break; + } + } + for (auto C : toCrossgrade) + { + // we never do purges on packages which are crossgraded, even if "requested" + if (C.first->Op == Item::Purge) + { + C.first->Op = Item::Remove; // crossgrades should never be purged + auto && Purges = approvedStates.Purge(); + auto const Ver = std::find_if( +#if __GNUC__ >= 5 || (__GNUC_MINOR__ >= 9 && __GNUC__ >= 4) + Purges.cbegin(), Purges.cend(), +#else + Purges.begin(), Purges.end(), +#endif + [&C](pkgCache::VerIterator const &V) { return V.ParentPkg() == C.first->Pkg; }); + approvedStates.Remove(*Ver); + Purges.erase(Ver); + auto && RemOp = PackageOps[C.first->Pkg.FullName()]; + if (RemOp.size() == 5) + { + RemOp.erase(std::next(RemOp.begin(), 3), RemOp.end()); + PackagesTotal -= 2; + } + else + _error->Warning("Unexpected amount of planned ops for package %s: %lu", C.first->Pkg.FullName().c_str(), RemOp.size()); + } + } + if (crossgraded.empty() == false) + { + auto const oldsize = List.size(); + List.erase(std::remove_if(List.begin(), PlanedEnd, + [&crossgraded](Item const &i){ + return (i.Op == Item::Remove || i.Op == Item::Purge) && + crossgraded.find(i.Pkg->ID) != crossgraded.end(); + }), PlanedEnd); + explicitIdx -= (oldsize - List.size()); + } } + APT::StateChanges currentStates; + if (_config->FindB("dpkg::selection::current::saveandrestore", true)) + { + for (auto Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + if (Pkg->CurrentVer == 0) + continue; + else if (Pkg->SelectedState == pkgCache::State::Purge) + currentStates.Purge(FindToBeRemovedVersion(Pkg)); + else if (Pkg->SelectedState == pkgCache::State::DeInstall) + currentStates.Remove(FindToBeRemovedVersion(Pkg)); + if (currentStates.empty() == false) + { + APT::StateChanges cleanStates; + for (auto && P: currentStates.Remove()) + cleanStates.Install(P); + for (auto && P: currentStates.Purge()) + cleanStates.Install(P); + if (cleanStates.Save(false) == false) + return _error->Error("Couldn't clean the currently selected dpkg states"); + } + } + + if (_config->FindB("dpkg::selection::remove::approved", true)) + { + 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; + } + + List.erase(std::next(List.begin(), explicitIdx), List.end()); + + std::vector<bool> toBeRemoved(Cache.Head().PackageCount, false); + for (auto && I: approvedStates.Remove()) + toBeRemoved[I.ParentPkg()->ID] = true; + for (auto && I: approvedStates.Purge()) + toBeRemoved[I.ParentPkg()->ID] = true; + + for (auto && I: List) + if (I.Op == Item::Remove || I.Op == Item::Purge) + toBeRemoved[I.Pkg->ID] = false; + + if (std::find(toBeRemoved.begin(), toBeRemoved.end(), true) != toBeRemoved.end()) + List.emplace_back(Item::RemovePending, pkgCache::PkgIterator()); + if (approvedStates.Purge().empty() == false) + List.emplace_back(Item::PurgePending, pkgCache::PkgIterator()); + + // support subpressing of triggers processing for special + // cases like d-i that runs the triggers handling manually + if (_config->FindB("DPkg::ConfigurePending", true)) + List.emplace_back(Item::ConfigurePending, pkgCache::PkgIterator()); + } + bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false); + d->stdin_is_dev_null = false; // create log @@ -1303,7 +1565,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) d->progress->Start(d->master); // this loop is runs once per dpkg operation - vector<Item>::const_iterator I = List.begin(); + vector<Item>::const_iterator I = List.cbegin(); while (I != List.end()) { // Do all actions with the same Op in one run @@ -1320,9 +1582,10 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) continue; break; } + else if (J->Op == Item::Remove || J->Op == Item::Purge) + J = std::find_if(J, List.cend(), [](Item const &I) { return I.Op != Item::Remove && I.Op != Item::Purge; }); else - for (; J != List.end() && J->Op == I->Op; ++J) - /* nothing */; + J = std::find_if(J, List.cend(), [&J](Item const &I) { return I.Op != J->Op; }); auto const size = (J - I) + 10; @@ -1346,18 +1609,20 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) ADDARG(status_fd_buf); unsigned long const Op = I->Op; + if (NoTriggers == true && I->Op != Item::TriggersPending && + I->Op != Item::ConfigurePending) + { + ADDARGC("--no-triggers"); + } + switch (I->Op) { case Item::Remove: - ADDARGC("--force-depends"); - ADDARGC("--force-remove-essential"); - ADDARGC("--remove"); - break; - case Item::Purge: ADDARGC("--force-depends"); - ADDARGC("--force-remove-essential"); - ADDARGC("--purge"); + if (std::any_of(I, J, ItemIsEssential)) + ADDARGC("--force-remove-essential"); + ADDARGC("--remove"); break; case Item::Configure: @@ -1374,34 +1639,96 @@ 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"); break; } - if (NoTriggers == true && I->Op != Item::TriggersPending && - I->Op != Item::ConfigurePending) - { - ADDARGC("--no-triggers"); - } -#undef ADDARGC + char * tmpdir_to_free = nullptr; // Write in the file or package names if (I->Op == Item::Install) { - for (;I != J && Size < MaxArgBytes; ++I) + auto const installsToDo = J - I; + if (dpkg_recursive_install == true && dpkg_recursive_install_min < installsToDo) { - if (I->File[0] != '/') - return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str()); - Args.push_back(I->File.c_str()); - Size += I->File.length(); + std::string tmpdir; + strprintf(tmpdir, "%s/apt-dpkg-install-XXXXXX", GetTempDir().c_str()); + tmpdir_to_free = strndup(tmpdir.data(), tmpdir.length()); + if (mkdtemp(tmpdir_to_free) == nullptr) + return _error->Errno("DPkg::Go", "mkdtemp of %s failed in preparation of calling dpkg unpack", tmpdir_to_free); + + char p = 1; + for (auto c = installsToDo - 1; (c = c/10) != 0; ++p); + for (unsigned long n = 0; I != J; ++n, ++I) + { + 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); + std::string linkpath; + if (dpkg_recursive_install_numbered) + strprintf(linkpath, "%s/%.*lu-%s", tmpdir_to_free, p, n, file.c_str()); + else + strprintf(linkpath, "%s/%s", tmpdir_to_free, file.c_str()); + if (symlink(I->File.c_str(), linkpath.c_str()) != 0) + return _error->Errno("DPkg::Go", "Symlinking %s to %s failed!", I->File.c_str(), linkpath.c_str()); + } + ADDARGC("--recursive"); + ADDARG(tmpdir_to_free); + } + else + { + for (;I != J && Size < MaxArgBytes; ++I) + { + if (I->File[0] != '/') + return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str()); + Args.push_back(I->File.c_str()); + Size += I->File.length(); + } + } + } + else if (I->Op == Item::RemovePending) + { + ++I; + StripAlreadyDoneFromPending(approvedStates.Remove()); + if (approvedStates.Remove().empty()) + continue; + } + else if (I->Op == Item::PurgePending) + { + ++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()); + if (approvedStates.Purge().empty()) + continue; + std::remove_reference<decltype(approvedStates.Remove())>::type approvedRemoves; + std::swap(approvedRemoves, approvedStates.Remove()); + // we apply it again here as an explicit remove in the ordering will have cleared the purge state + if (approvedStates.Save(false) == false) + { + _error->Error("Couldn't record the approved purges 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::swap(approvedRemoves, approvedStates.Remove()); } else { string const nativeArch = _config->Find("APT::Architecture"); - unsigned long const oldSize = I->Op == Item::Configure ? Size : 0; + unsigned long const oldSize = I->Pkg.end() == false ? Size : 0; for (;I != J && Size < MaxArgBytes; ++I) { if((*I).Pkg.end() == true) @@ -1420,12 +1747,15 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { pkgCache::VerIterator PkgVer; std::string name = I->Pkg.Name(); - if (Op == Item::Remove || Op == Item::Purge) - { + if (Op == Item::Remove) + PkgVer = I->Pkg.CurrentVer(); + else if (Op == Item::Purge) + { + // we purge later with --purge --pending, so if it isn't installed (aka rc-only), skip it here PkgVer = I->Pkg.CurrentVer(); - if(PkgVer.end() == true) - PkgVer = FindNowVersion(I->Pkg); - } + if (PkgVer.end() == true) + continue; + } else PkgVer = Cache[I->Pkg].InstVerIter(Cache); if (strcmp(I->Pkg.Arch(), "none") == 0) @@ -1443,6 +1773,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (oldSize == Size) continue; } +#undef ADDARGC #undef ADDARG J = I; @@ -1459,6 +1790,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) Packages.clear(); close(fd[0]); close(fd[1]); + cleanUpTmpDir(tmpdir_to_free); continue; } Args.push_back(NULL); @@ -1594,6 +1926,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) signal(SIGINT,old_SIGINT); signal(SIGHUP,old_SIGHUP); + cleanUpTmpDir(tmpdir_to_free); + if (waitpid_failure == true) { strprintf(d->dpkg_error, "Sub-process %s couldn't be waited for.",Args[0]); @@ -1625,6 +1959,23 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) StopPtyMagic(); CloseLog(); + if (d->dpkg_error.empty() == false) + { + // no point in reseting packages we already completed removal for + StripAlreadyDoneFromPending(approvedStates.Remove()); + StripAlreadyDoneFromPending(approvedStates.Purge()); + APT::StateChanges undo; + auto && undoRem = approvedStates.Remove(); + std::move(undoRem.begin(), undoRem.end(), std::back_inserter(undo.Install())); + auto && undoPur = approvedStates.Purge(); + std::move(undoPur.begin(), undoPur.end(), std::back_inserter(undo.Install())); + 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!"); + if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); @@ -1764,7 +2115,17 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) // find the package version and source package name pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname); if (Pkg.end() == true) - return; + { + if (pos == std::string::npos || _config->FindB("dpkg::install::recursive::numbered", true) == false) + return; + auto const dash = pkgname.find_first_not_of("0123456789"); + if (dash == std::string::npos || pkgname[dash] != '-') + return; + pkgname.erase(0, dash + 1); + Pkg = Cache.FindPkg(pkgname); + if (Pkg.end() == true) + return; + } pkgCache::VerIterator Ver = Cache.GetCandidateVersion(Pkg); if (Ver.end() == true) return; @@ -1862,20 +2223,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..193754644 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -76,17 +76,19 @@ class pkgDPkgPM : public pkgPackageManager // progress reporting unsigned int PackagesDone; unsigned int PackagesTotal; - + + public: 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), File(File), Pkg(Pkg) {}; Item() {}; - }; + protected: std::vector<Item> List; // Helpers @@ -125,7 +127,7 @@ class pkgDPkgPM : public pkgPackageManager virtual bool Remove(PkgIterator Pkg,bool Purge = false) APT_OVERRIDE; virtual bool Go(APT::Progress::PackageManager *progress) APT_OVERRIDE; - virtual bool Go(int StatusFd=-1) APT_OVERRIDE; + APT_DEPRECATED_MSG("Use overload with explicit progress manager") virtual bool Go(int StatusFd=-1) APT_OVERRIDE; virtual void Reset() APT_OVERRIDE; @@ -133,6 +135,8 @@ class pkgDPkgPM : public pkgPackageManager pkgDPkgPM(pkgDepCache *Cache); virtual ~pkgDPkgPM(); + + APT_HIDDEN static bool ExpandPendingCalls(std::vector<Item> &List, pkgDepCache &Cache); }; void SigINT(int sig); diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 7fdd0393f..90dd3a3ee 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -315,8 +315,8 @@ bool pkgPackageManager::ConfigureAll() if (OList.OrderConfigure() == false) return false; - std::string const conf = _config->Find("PackageManager::Configure","all"); - bool const ConfigurePkgs = (conf == "all"); + std::string const conf = _config->Find("PackageManager::Configure", "smart"); + bool const ConfigurePkgs = (ImmConfigureAll || conf == "all"); // Perform the configuring for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); ++I) @@ -600,7 +600,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) if (PkgLoop) return true; - static std::string const conf = _config->Find("PackageManager::Configure","all"); + static std::string const conf = _config->Find("PackageManager::Configure", "smart"); static bool const ConfigurePkgs = (conf == "all" || conf == "smart"); if (List->IsFlag(Pkg,pkgOrderList::Configured)) @@ -1148,7 +1148,12 @@ pkgPackageManager::DoInstallPostFork(int statusFd) pkgPackageManager::OrderResult pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) { - bool goResult = Go(progress); + bool goResult; + auto simulation = dynamic_cast<pkgSimulate*>(this); + if (simulation == nullptr) + goResult = Go(progress); + else + goResult = simulation->Go2(progress); if(goResult == false) return Failed; diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 25b6ee7c9..5046e2dc0 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -99,7 +99,7 @@ class pkgPackageManager : protected pkgCache::Namespace virtual bool Configure(PkgIterator /*Pkg*/) {return false;}; virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;}; virtual bool Go(APT::Progress::PackageManager * /*progress*/) {return true;}; - virtual bool Go(int /*statusFd*/=-1) {return true;}; + APT_DEPRECATED_MSG("Use overload with explicit progress manager") virtual bool Go(int /*statusFd*/=-1) {return true;}; virtual void Reset() {}; diff --git a/apt-pkg/statechanges.cc b/apt-pkg/statechanges.cc index ed8f9f524..35af45538 100644 --- a/apt-pkg/statechanges.cc +++ b/apt-pkg/statechanges.cc @@ -25,7 +25,8 @@ public: #define APT_GETTERSETTER(Name, Container) \ void StateChanges::Name(pkgCache::VerIterator const &Ver) \ { \ - Container.push_back(Ver); \ + if (Ver.end() == false) \ + Container.push_back(Ver); \ }\ APT::VersionVector& StateChanges::Name() \ { \ diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 09db5a0e0..cfc840ae9 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -904,84 +904,14 @@ APT::Compressor::rev { <listitem><para>These options are passed to &dpkg-buildpackage; when compiling packages; the default is to disable signing and produce all binaries.</para></listitem> </varlistentry> - </variablelist> - <refsect2><title>dpkg trigger usage (and related options)</title> - <para>APT can call &dpkg; in such a way as to let it make aggressive use of triggers over - multiple calls of &dpkg;. Without further options &dpkg; will use triggers once each time it runs. - Activating these options can therefore decrease the time needed to perform the - install or upgrade. Note that it is intended to activate these options per default in the - future, but as it drastically changes the way APT calls &dpkg; it needs a lot more testing. - <emphasis>These options are therefore currently experimental and should not be used in - production environments.</emphasis> It also breaks progress reporting such that all front-ends will - currently stay around half (or more) of the time in the 100% state while it actually configures - all packages.</para> - <para>Note that it is not guaranteed that APT will support these options or that these options will - not cause (big) trouble in the future. If you have understand the current risks and problems with - these options, but are brave enough to help testing them, create a new configuration file and test a - combination of options. Please report any bugs, problems and improvements you encounter and make sure - to note which options you have used in your reports. Asking &dpkg; for help could also be useful for - debugging proposes, see e.g. <command>dpkg --audit</command>. A defensive option combination would be -<literallayout>DPkg::NoTriggers "true"; -PackageManager::Configure "smart"; -DPkg::ConfigurePending "true"; -DPkg::TriggersPending "true";</literallayout></para> - - <variablelist> - <varlistentry><term><option>DPkg::NoTriggers</option></term> - <listitem><para>Add the no triggers flag to all &dpkg; calls (except the ConfigurePending call). - See &dpkg; if you are interested in what this actually means. In short: &dpkg; will not run the - triggers when this flag is present unless it is explicitly called to do so in an extra call. - Note that this option exists (undocumented) also in older APT versions with a slightly different - meaning: Previously these option only append --no-triggers to the configure calls to &dpkg; - - now APT will also add this flag to the unpack and remove calls.</para></listitem> - </varlistentry> - <varlistentry><term><option>PackageManager::Configure</option></term> - <listitem><para>Valid values are "<literal>all</literal>", - "<literal>smart</literal>" and "<literal>no</literal>". - The default value is "<literal>all</literal>", which causes APT to - configure all packages. The "<literal>smart</literal>" way is to - configure only packages which need to be configured before another - package can be unpacked (Pre-Depends), and let the rest be configured - by &dpkg; with a call generated by the ConfigurePending option (see - below). On the other hand, "<literal>no</literal>" will not configure - anything, and totally relies on &dpkg; for configuration (which at the - moment will fail if a Pre-Depends is encountered). Setting this option - to any value other than <literal>all</literal> will implicitly also - activate the next option by default, as otherwise the system could end - in an unconfigured and potentially unbootable state.</para></listitem> - </varlistentry> - <varlistentry><term><option>DPkg::ConfigurePending</option></term> - <listitem><para>If this option is set APT will call <command>dpkg --configure --pending</command> - to let &dpkg; handle all required configurations and triggers. This option is activated automatically - per default if the previous option is not set to <literal>all</literal>, but deactivating it could be useful - if you want to run APT multiple times in a row - e.g. in an installer. In these sceneries you could - deactivate this option in all but the last run.</para></listitem> - </varlistentry> - <varlistentry><term><option>DPkg::TriggersPending</option></term> - <listitem><para>Useful for the <literal>smart</literal> configuration as a package which has pending - triggers is not considered as <literal>installed</literal>, and &dpkg; treats them as <literal>unpacked</literal> - currently which is a showstopper for Pre-Dependencies (see debbugs #526774). Note that this will - process all triggers, not only the triggers needed to configure this package.</para></listitem> - </varlistentry> - <varlistentry><term><option>OrderList::Score::Immediate</option></term> - <listitem><para>Essential packages (and their dependencies) should be configured immediately - after unpacking. It is a good idea to do this quite early in the upgrade process as these - configure calls also currently require <literal>DPkg::TriggersPending</literal> which - will run quite a few triggers (which may not be needed). Essentials get per default a high score - but the immediate flag is relatively low (a package which has a Pre-Depends is rated higher). - These option and the others in the same group can be used to change the scoring. The following - example shows the settings with their default values. - <literallayout>OrderList::Score { - Delete 500; - Essential 200; - Immediate 10; - PreDepends 50; -};</literallayout> - </para></listitem> - </varlistentry> - </variablelist> - </refsect2> + <varlistentry><term><option>DPkg::ConfigurePending</option></term> + <listitem><para>If this option is set APT will call <command>dpkg --configure --pending</command> + to let &dpkg; handle all required configurations and triggers. This option is activated by default, + but deactivating it could be useful if you want to run APT multiple times in a row - e.g. in an installer. + In this scenario you could deactivate this option in all but the last run.</para></listitem> + </varlistentry> + </variablelist> </refsect1> <refsect1> diff --git a/doc/external-installation-planner-protocol.txt b/doc/external-installation-planner-protocol.txt index 44fa8ff53..4bad9da0a 100644 --- a/doc/external-installation-planner-protocol.txt +++ b/doc/external-installation-planner-protocol.txt @@ -248,7 +248,9 @@ before it was unpacked, dependency relations must be satisfied, …), but they don't need to be complete: A planner can and should expect that any package which wasn't explicitly configured will be configured at the end automatically. That also means through that a planner is not allowed to -produce a solution in which a package remains unconfigured. +produce a solution in which a package remains unconfigured. Also, +packages which are requested to be removed will be automatically removed +at the end if not marked for removal explicitly earlier. In terms of expressivity, all stanzas can carry one single field each, as APT-IDs are enough to pinpoint packages to be installed/removed. diff --git a/test/integration/test-allow-scores-for-all-dependency-types b/test/integration/test-allow-scores-for-all-dependency-types index 1a08f2ed2..9b300b7a7 100755 --- a/test/integration/test-allow-scores-for-all-dependency-types +++ b/test/integration/test-allow-scores-for-all-dependency-types @@ -55,8 +55,8 @@ The following packages will be upgraded: Remv libdb5.1-dev [5.1.29-7] [libdb-dev:amd64 ] Inst libdb-dev [5.1.7] (5.3.0 unversioned [amd64]) [] Inst libdb5.3-dev (5.3.28-3 unversioned [amd64]) -Conf libdb5.3-dev (5.3.28-3 unversioned [amd64]) -Conf libdb-dev (5.3.0 unversioned [amd64])' aptget dist-upgrade -st unversioned +Conf libdb-dev (5.3.0 unversioned [amd64]) +Conf libdb5.3-dev (5.3.28-3 unversioned [amd64])' aptget dist-upgrade -st unversioned testsuccessequal 'Reading package lists... Building dependency tree... Calculating upgrade... @@ -70,8 +70,8 @@ The following packages will be upgraded: Remv libdb5.1-dev [5.1.29-7] [libdb-dev:amd64 ] Inst libdb-dev [5.1.7] (5.3.0 versioned [amd64]) [] Inst libdb5.3-dev (5.3.28-3 versioned [amd64]) -Conf libdb5.3-dev (5.3.28-3 versioned [amd64]) -Conf libdb-dev (5.3.0 versioned [amd64])' aptget dist-upgrade -st versioned +Conf libdb-dev (5.3.0 versioned [amd64]) +Conf libdb5.3-dev (5.3.28-3 versioned [amd64])' aptget dist-upgrade -st versioned cp -f rootdir/var/lib/dpkg/status-backup rootdir/var/lib/dpkg/status insertinstalledpackage 'foo' 'amd64' '1' diff --git a/test/integration/test-apt-get-autoremove b/test/integration/test-apt-get-autoremove index 17dba9aec..cfee748af 100755 --- a/test/integration/test-apt-get-autoremove +++ b/test/integration/test-apt-get-autoremove @@ -18,6 +18,8 @@ testmarkedauto 'po-debconf' testsuccess aptget remove debhelper -y testdpkgnotinstalled 'debhelper' testdpkginstalled 'po-debconf' 'unrelated' +echo 'unrelated purge' | dpkg --set-selections +testdpkgstatus 'pi' '1' 'unrelated' AUTOREMOVE='apt autoremove' if [ -n "$SUDO_USER" ]; then @@ -49,14 +51,17 @@ testdpkginstalled 'po-debconf' echo 'APT::NeverAutoRemove { "^po-debconf$"; };' > rootdir/etc/apt/apt.conf.d/00autoremove testsuccess aptget autoremove -y testdpkginstalled 'po-debconf' +testdpkgstatus 'pi' '1' 'unrelated' echo 'APT::NeverAutoRemove { "^po-.*$"; };' > rootdir/etc/apt/apt.conf.d/00autoremove testsuccess aptget autoremove -y testdpkginstalled "po-debconf" +testdpkgstatus 'pi' '1' 'unrelated' rm rootdir/etc/apt/apt.conf.d/00autoremove testsuccess aptget autoremove -y testdpkgnotinstalled 'po-debconf' +testdpkgstatus 'pi' '1' 'unrelated' testmarkedauto sed rootdir/var/log/apt/history.log -e '/^Commandline: / d' \ @@ -71,7 +76,8 @@ Remove: debhelper:i386 (8.0.0) Remove: po-debconf:i386 (1.0.16)' testsuccess aptget install debhelper -y -testdpkginstalled 'unrelated' 'debhelper' 'po-debconf' +testdpkgstatus 'pi' '1' 'unrelated' +testdpkginstalled 'debhelper' 'po-debconf' testsuccess aptmark auto debhelper testmarkedauto 'debhelper' 'po-debconf' @@ -105,9 +111,11 @@ Reading state information... testsuccess aptget autoremove debhelper -y --allow-change-held-packages testdpkgnotinstalled 'po-debconf' 'debhelper' +testdpkgstatus 'pi' '1' 'unrelated' testmarkedauto testsuccess aptget install debhelper --solver apt -y -o Debug::pkgDepCache::Marker=1 testmarkedauto 'po-debconf' +testdpkgstatus 'pi' '1' 'unrelated' insertinstalledpackage 'bar' 'all' '1' 'Depends: foo-provider' insertinstalledpackage 'foo-multi1-1' 'all' '1' 'Provides: foo-provider diff --git a/test/integration/test-apt-progress-fd-error b/test/integration/test-apt-progress-fd-error index e66210304..4439c042a 100755 --- a/test/integration/test-apt-progress-fd-error +++ b/test/integration/test-apt-progress-fd-error @@ -19,7 +19,7 @@ setupaptarchive exec 3> apt-progress.log testfailure aptget install foo1 foo2 -y -o APT::Status-Fd=3 msgtest 'Ensure correct error message' -testsuccess --nomsg grep "aptarchive/pool/foo2_0.8.15_[^.]\+.deb:36.3636:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log +testsuccess --nomsg grep "foo2_0.8.15_[^.]\+.deb:36.3636:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log testsuccess test -s rootdir/var/crash/foo2.0.crash testsuccess grep '^Package: foo2 0.8.15$' rootdir/var/crash/foo2.0.crash diff --git a/test/integration/test-bug-673536-pre-depends-breaks-loop b/test/integration/test-bug-673536-pre-depends-breaks-loop index bf3d2e2eb..a4cf66973 100755 --- a/test/integration/test-bug-673536-pre-depends-breaks-loop +++ b/test/integration/test-bug-673536-pre-depends-breaks-loop @@ -11,7 +11,7 @@ buildsimplenativepackage 'advanced' 'native' '2' 'unstable' 'Pre-Depends: basic' buildsimplenativepackage 'basic' 'native' '2' 'unstable' 'Pre-Depends: common' buildsimplenativepackage 'common' 'native' '2~conflict' 'unstable-conflict' 'Conflicts: advanced (<= 1)' -buildsimplenativepackage 'common' 'native' '2~break' 'unstable-break' 'Conflicts: advanced (<= 1)' +buildsimplenativepackage 'common' 'native' '2~break' 'unstable-break' 'Breaks: advanced (<= 1)' setupaptarchive diff --git a/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch b/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch index a15ac06ed..d9fd3d30d 100755 --- a/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch +++ b/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch @@ -48,33 +48,42 @@ DPkg::Tools::options::\"./${hook}-v${1}.sh\"::Version \"$1\";" > rootdir/etc/apt observehook() { rm -f ${hook}-v2.list ${hook}-v3.list msgtest 'Observe hooks while' "$*" - testsuccess --nomsg aptget "$@" -y --allow-downgrades + testsuccess --nomsg aptget "$@" -y --allow-downgrades --planner $planner + # different planners have different orders – we don't care in this test here + if [ -e ${hook}-v2.list ]; then + sort < ${hook}-v2.list > ${hook}-v2.list.new + mv ${hook}-v2.list.new ${hook}-v2.list + fi + if [ -e ${hook}-v3.list ]; then + sort < ${hook}-v3.list > ${hook}-v3.list.new + mv ${hook}-v3.list.new ${hook}-v3.list + fi } testrun() { observehook install stuff -t stable testfileequal "${hook}-v2.list" 'libsame - < 1 **CONFIGURE** -toolkit - < 1 **CONFIGURE** -stuff - < 1 **CONFIGURE**' +stuff - < 1 **CONFIGURE** +toolkit - < 1 **CONFIGURE**' testfileequal "${hook}-v3.list" 'libsame - - none < 1 amd64 same **CONFIGURE** -toolkit - - none < 1 all foreign **CONFIGURE** -stuff - - none < 1 amd64 none **CONFIGURE**' +stuff - - none < 1 amd64 none **CONFIGURE** +toolkit - - none < 1 all foreign **CONFIGURE**' observehook install stuff -t unstable testfileequal "${hook}-v2.list" 'libsame 1 < 2 **CONFIGURE** -toolkit 1 < 2 **CONFIGURE** -stuff 1 < 2 **CONFIGURE**' +stuff 1 < 2 **CONFIGURE** +toolkit 1 < 2 **CONFIGURE**' testfileequal "${hook}-v3.list" 'libsame 1 amd64 same < 2 amd64 same **CONFIGURE** -toolkit 1 all foreign < 2 amd64 foreign **CONFIGURE** -stuff 1 amd64 none < 2 amd64 none **CONFIGURE**' +stuff 1 amd64 none < 2 amd64 none **CONFIGURE** +toolkit 1 all foreign < 2 amd64 foreign **CONFIGURE**' observehook install stuff:i386 -t unstable - testfileequal "${hook}-v2.list" 'stuff 2 > - **REMOVE** -libsame - < 2 **CONFIGURE** -stuff - < 2 **CONFIGURE**' - testfileequal "${hook}-v3.list" 'stuff 2 amd64 none > - - none **REMOVE** -libsame - - none < 2 i386 same **CONFIGURE** -stuff - - none < 2 i386 none **CONFIGURE**' + testfileequal "${hook}-v2.list" 'libsame - < 2 **CONFIGURE** +stuff - < 2 **CONFIGURE** +stuff 2 > - **REMOVE**' + testfileequal "${hook}-v3.list" 'libsame - - none < 2 i386 same **CONFIGURE** +stuff - - none < 2 i386 none **CONFIGURE** +stuff 2 amd64 none > - - none **REMOVE**' observehook remove libsame testfileequal "${hook}-v2.list" 'libsame 2 > - **REMOVE**' @@ -82,30 +91,30 @@ stuff - - none < 2 i386 none **CONFIGURE**' observehook install stuff:i386/stable libsame:i386/stable toolkit/stable testfileequal "${hook}-v2.list" 'libsame 2 > 1 **CONFIGURE** -toolkit 2 > 1 **CONFIGURE** -stuff 2 > 1 **CONFIGURE**' +stuff 2 > 1 **CONFIGURE** +toolkit 2 > 1 **CONFIGURE**' testfileequal "${hook}-v3.list" 'libsame 2 i386 same > 1 i386 same **CONFIGURE** -toolkit 2 amd64 foreign > 1 all foreign **CONFIGURE** -stuff 2 i386 none > 1 i386 none **CONFIGURE**' +stuff 2 i386 none > 1 i386 none **CONFIGURE** +toolkit 2 amd64 foreign > 1 all foreign **CONFIGURE**' observehook install 'libsame:*' - testfileequal "${hook}-v2.list" 'libsame 1 < 2 **CONFIGURE** -libsame - < 2 **CONFIGURE** -toolkit 1 < 2 **CONFIGURE** -stuff 1 < 2 **CONFIGURE**' - testfileequal "${hook}-v3.list" 'libsame 1 i386 same < 2 i386 same **CONFIGURE** -libsame - - none < 2 amd64 same **CONFIGURE** -toolkit 1 all foreign < 2 amd64 foreign **CONFIGURE** -stuff 1 i386 none < 2 i386 none **CONFIGURE**' + testfileequal "${hook}-v2.list" 'libsame - < 2 **CONFIGURE** +libsame 1 < 2 **CONFIGURE** +stuff 1 < 2 **CONFIGURE** +toolkit 1 < 2 **CONFIGURE**' + testfileequal "${hook}-v3.list" 'libsame - - none < 2 amd64 same **CONFIGURE** +libsame 1 i386 same < 2 i386 same **CONFIGURE** +stuff 1 i386 none < 2 i386 none **CONFIGURE** +toolkit 1 all foreign < 2 amd64 foreign **CONFIGURE**' observehook purge stuff:i386 'libsame:*' toolkit testfileequal "${hook}-v2.list" 'libsame 2 > - **REMOVE** -stuff 2 > - **REMOVE** libsame 2 > - **REMOVE** +stuff 2 > - **REMOVE** toolkit 2 > - **REMOVE**' testfileequal "${hook}-v3.list" 'libsame 2 amd64 same > - - none **REMOVE** -stuff 2 i386 none > - - none **REMOVE** libsame 2 i386 same > - - none **REMOVE** +stuff 2 i386 none > - - none **REMOVE** toolkit 2 amd64 foreign > - - none **REMOVE**' observehook install confpkg @@ -127,10 +136,17 @@ toolkit 2 amd64 foreign > - - none **REMOVE**' dpkg -l confpkg 2>/dev/null | grep -q '^rc' && msgfail || msgpass } -enablehookversion 2 -enablehookversion 3 -testrun +runwithplanner() +{ + msgmsg 'Running with planner' "$1" + planner="$1" + enablehookversion 2 + enablehookversion 3 + testrun + + enablehookversion 2 13 + enablehookversion 3 13 + testrun +} -enablehookversion 2 13 -enablehookversion 3 13 -testrun +runwithplanner 'apt' diff --git a/test/integration/test-bug-735967-lib32-to-i386-unavailable b/test/integration/test-bug-735967-lib32-to-i386-unavailable index 290df8a3f..3b705d5f9 100755 --- a/test/integration/test-bug-735967-lib32-to-i386-unavailable +++ b/test/integration/test-bug-735967-lib32-to-i386-unavailable @@ -71,10 +71,10 @@ Inst lib32nss-mdns [0.9-1] (0.10-6 unstable [amd64]) [] Inst libnss-mdns [0.9-1] (0.10-6 unstable [amd64]) [] Inst libnss-mdns:i386 (0.10-6 unstable [i386]) [] Inst libnss-mdns-i386:i386 (0.10-6 unstable [i386]) -Conf libnss-mdns:i386 (0.10-6 unstable [i386]) +Conf lib32nss-mdns (0.10-6 unstable [amd64]) Conf libnss-mdns (0.10-6 unstable [amd64]) -Conf libnss-mdns-i386:i386 (0.10-6 unstable [i386]) -Conf lib32nss-mdns (0.10-6 unstable [amd64])' aptget dist-upgrade -s +Conf libnss-mdns:i386 (0.10-6 unstable [i386]) +Conf libnss-mdns-i386:i386 (0.10-6 unstable [i386])' aptget dist-upgrade -s testsuccessequal 'Reading package lists... Building dependency tree... diff --git a/test/integration/test-bug-740843-versioned-up-down-breaks b/test/integration/test-bug-740843-versioned-up-down-breaks index 143175cca..69adceffd 100755 --- a/test/integration/test-bug-740843-versioned-up-down-breaks +++ b/test/integration/test-bug-740843-versioned-up-down-breaks @@ -33,11 +33,11 @@ Inst libgl1-foo-glx:i386 [1] (2 stable [i386]) [foo-driver:amd64 on libgl1-foo-g Inst foo-driver [1] (2 stable [amd64]) [] Inst libfoo:i386 [1] (2 stable [i386]) [libfoo:amd64 on libfoo:i386] [libfoo:i386 on libfoo:amd64] [libfoo:amd64 ] Inst libfoo [1] (2 stable [amd64]) -Conf libfoo:i386 (2 stable [i386]) -Conf libfoo (2 stable [amd64]) -Conf libgl1-foo-glx:i386 (2 stable [i386]) Conf libgl1-foo-glx (2 stable [amd64]) -Conf foo-driver (2 stable [amd64])' 'Reading package lists... +Conf libgl1-foo-glx:i386 (2 stable [i386]) +Conf foo-driver (2 stable [amd64]) +Conf libfoo:i386 (2 stable [i386]) +Conf libfoo (2 stable [amd64])' 'Reading package lists... Building dependency tree... Calculating upgrade... The following packages will be upgraded: @@ -48,10 +48,10 @@ Inst libgl1-foo-glx:i386 [1] (2 stable [i386]) [foo-driver:amd64 on libgl1-foo-g Inst foo-driver [1] (2 stable [amd64]) [] Inst libfoo:i386 [1] (2 stable [i386]) [libfoo:amd64 on libfoo:i386] [libfoo:i386 on libfoo:amd64] [libfoo:amd64 ] Inst libfoo [1] (2 stable [amd64]) -Conf libfoo:i386 (2 stable [i386]) -Conf libfoo (2 stable [amd64]) -Conf libgl1-foo-glx:i386 (2 stable [i386]) Conf libgl1-foo-glx (2 stable [amd64]) -Conf foo-driver (2 stable [amd64])' aptget dist-upgrade -s +Conf libgl1-foo-glx:i386 (2 stable [i386]) +Conf foo-driver (2 stable [amd64]) +Conf libfoo:i386 (2 stable [i386]) +Conf libfoo (2 stable [amd64])' aptget dist-upgrade -s testsuccess aptget dist-upgrade -y -o Debug::pkgPackageManager=1 -o Debug::pkgOrderList=1 diff --git a/test/integration/test-bug-lp1562402-nomark-removals-as-keep b/test/integration/test-bug-lp1562402-nomark-removals-as-keep index 05f43701d..6e8225aa4 100755 --- a/test/integration/test-bug-lp1562402-nomark-removals-as-keep +++ b/test/integration/test-bug-lp1562402-nomark-removals-as-keep @@ -33,7 +33,7 @@ Inst maas-region-controller [2.0.0~alpha3+bzr4810-0ubuntu1] (2.0.0~alpha4+bzr484 Remv maas-region-controller-min [2.0.0~alpha3+bzr4810-0ubuntu1] [] Inst maas-common [2.0.0~alpha3+bzr4810-0ubuntu1] (2.0.0~alpha4+bzr4843-0ubuntu1~xenial2 unstable [all]) [] Inst maas-region-api (2.0.0~alpha4+bzr4843-0ubuntu1~xenial2 unstable [amd64]) +Conf maas-region-controller (2.0.0~alpha4+bzr4843-0ubuntu1~xenial2 unstable [all]) Conf maas-common (2.0.0~alpha4+bzr4843-0ubuntu1~xenial2 unstable [all]) -Conf maas-region-api (2.0.0~alpha4+bzr4843-0ubuntu1~xenial2 unstable [amd64]) -Conf maas-region-controller (2.0.0~alpha4+bzr4843-0ubuntu1~xenial2 unstable [all])' \ +Conf maas-region-api (2.0.0~alpha4+bzr4843-0ubuntu1~xenial2 unstable [amd64])' \ aptget dist-upgrade -s diff --git a/test/integration/test-bug-multiarch-upgrade b/test/integration/test-bug-multiarch-upgrade index cb5159c05..38e70531e 100755 --- a/test/integration/test-bug-multiarch-upgrade +++ b/test/integration/test-bug-multiarch-upgrade @@ -25,5 +25,5 @@ The following packages will be upgraded: 2 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. Inst libcups2 [1] (2 unstable [amd64]) [libcups2:amd64 on libcups2:i386] [libcups2:i386 on libcups2:amd64] [libcups2:i386 ] Inst libcups2:i386 [1] (2 unstable [i386]) -Conf libcups2:i386 (2 unstable [i386]) -Conf libcups2 (2 unstable [amd64])' aptget install -s libcups2:i386 +Conf libcups2 (2 unstable [amd64]) +Conf libcups2:i386 (2 unstable [i386])' aptget install -s libcups2:i386 diff --git a/test/integration/test-crossgrades b/test/integration/test-crossgrades new file mode 100755 index 000000000..d412546c1 --- /dev/null +++ b/test/integration/test-crossgrades @@ -0,0 +1,49 @@ +#!/bin/sh +set -e + +TESTDIR="$(readlink -f "$(dirname "$0")")" +. "$TESTDIR/framework" + +setupenvironment +configarchitecture 'i386' 'amd64' 'armel' +configdpkgnoopchroot + +buildsimplenativepackage 'unrelated' 'amd64' '1' 'stable' +buildsimplenativepackage 'crosser' 'i386,armel' '1' 'stable' 'Multi-Arch: same' +buildsimplenativepackage 'crosser' 'amd64' '2' 'unstable' +setupaptarchive + +singleinstance() { + testsuccess apt install crosser:i386=1 unrelated:amd64 -y --planner $1 + testdpkginstalled 'crosser:i386' 'unrelated' + + testsuccess apt install crosser:amd64 -y -o Debug::pkgDpkgPm=1 -o Dpkg::Use-Pty=0 --purge --planner $1 + cp -a rootdir/tmp/testsuccess.output crosser.output + testfailure grep -- '--remove.*crosser.*' crosser.output + testfailure grep -- '--purge' crosser.output + testsuccess apt install crosser:amd64 unrelated:amd64- -y -o Dpkg::Use-Pty=0 --purge -o Debug::pkgDPkgProgressReporting=1 --planner $1 + testdpkgnotinstalled 'crosser:i386' 'unrelated' + testdpkginstalled 'crosser:amd64' + + testsuccess apt purge crosser:amd64 -y --planner $1 + testdpkgnotinstalled 'crosser:amd64' +} +singleinstance 'internal' +singleinstance 'apt' + +multiinstance() { + testsuccess apt install crosser:i386=1 crosser:armel=1 unrelated:amd64 -y --planner $1 + testdpkginstalled 'crosser:i386' 'crosser:armel' 'unrelated' + + testsuccess apt install crosser:amd64 -y -o Debug::pkgDpkgPm=1 -o Dpkg::Use-Pty=0 --purge --planner $1 + cp -a rootdir/tmp/testsuccess.output crosser.output + testsuccess grep -- '--remove.*crosser.*' crosser.output + testsuccess grep -- '--purge' crosser.output + testsuccess apt install crosser:amd64 unrelated:amd64- -y -o Dpkg::Use-Pty=0 --purge -o Debug::pkgDPkgProgressReporting=1 --planner $1 + testdpkgnotinstalled 'crosser:i386' 'crosser:armel' 'unrelated' + testdpkginstalled 'crosser:amd64' + + testsuccess apt purge crosser:amd64 -y --planner $1 + testdpkgnotinstalled 'crosser:amd64' +} +multiinstance 'internal' diff --git a/test/integration/test-dpkg-assert-multi-arch b/test/integration/test-dpkg-assert-multi-arch index 678038cf2..a99f320b3 100755 --- a/test/integration/test-dpkg-assert-multi-arch +++ b/test/integration/test-dpkg-assert-multi-arch @@ -17,7 +17,7 @@ setupaptarchive testqualifier() { msgtest 'Test with' $1 'for correct qualifier mode' $2 #aptget install $1 -qq -o Debug::pkgDPkgPM=1 || true - aptget install $1 -qq -o Debug::pkgDPkgPM=1 -o Dpkg::ExplicitLastConfigure=1 > testqualifier.output 2>&1 || true + aptget install $1 -qq -o Debug::pkgDPkgPM=1 -o Dpkg::ExplicitLastConfigure=1 -o PackageManager::Configure=all > testqualifier.output 2>&1 || true GIVEN="$(grep -v -- '--unpack' testqualifier.output | sed -ne 's/^.*--[rpc][^ ]* \([^ ]*\).*$/\1/p')" if [ "$GIVEN" = "$2" ]; then msgpass diff --git a/test/integration/test-essential-force-loopbreak b/test/integration/test-essential-force-loopbreak index 6f7d99cb6..f585e9c42 100755 --- a/test/integration/test-essential-force-loopbreak +++ b/test/integration/test-essential-force-loopbreak @@ -43,6 +43,9 @@ E: Internal Error, Could not early remove sysvinit:$(dpkg --print-architecture) # with enough force however … cp -a dpkg.status.backup rootdir/var/lib/dpkg/status + testsuccess aptget install systemd-sysv -y -t "$1" -o APT::Force-LoopBreak=1 -o Debug::pkgDpkgPm=1 + cp rootdir/tmp/testsuccess.output apt.output + testsuccess grep -- '--force-remove-essential --remove sysvinit' apt.output testsuccess aptget install systemd-sysv -y -t "$1" -o APT::Force-LoopBreak=1 testdpkginstalled 'sysvinit' 'systemd-sysv' } diff --git a/test/integration/test-external-installation-planner-protocol b/test/integration/test-external-installation-planner-protocol index bd3c99c32..8d80930bc 100755 --- a/test/integration/test-external-installation-planner-protocol +++ b/test/integration/test-external-installation-planner-protocol @@ -45,9 +45,7 @@ Planner: internal' head -n 6 "$EIPPLOG" aptinternalplanner < "$EIPPLOG" > planner.log || true testsuccessequal 'Remove: 6 Unpack: 2 -Unpack: 4 -Configure: 2 -Configure: 4' grep -e '^Unpack:' -e '^Install:' -e '^Configure:' -e '^Remove:' planner.log +Unpack: 4' grep -e '^Unpack:' -e '^Install:' -e '^Configure:' -e '^Remove:' planner.log rm -f "$EIPPLOG" testsuccess aptget install foo -s --reinstall @@ -59,8 +57,7 @@ Architectures: amd64 ReInstall: foo:amd64 Planner: internal' head -n 5 "$EIPPLOG" aptinternalplanner < "$EIPPLOG" > planner.log || true -testsuccessequal 'Unpack: 4 -Configure: 4' grep -e '^Unpack:' -e '^Install:' -e '^Configure:' -e '^Remove:' planner.log +testsuccessequal 'Unpack: 4' grep -e '^Unpack:' -e '^Install:' -e '^Configure:' -e '^Remove:' planner.log rm -f "$EIPPLOG" testsuccess aptget purge foo -s diff --git a/test/integration/test-ignore-provides-if-versioned-breaks b/test/integration/test-ignore-provides-if-versioned-breaks index 8c3750acf..ebcbecf47 100755 --- a/test/integration/test-ignore-provides-if-versioned-breaks +++ b/test/integration/test-ignore-provides-if-versioned-breaks @@ -144,7 +144,7 @@ Inst foo-same [2.0] (4.0 unstable [i386]) [foo-same:i386 on foo-same:amd64] [foo Inst foo-same:amd64 [2.0] (4.0 unstable [amd64]) Inst foo-same-breaker-3 (1.0 unstable [i386]) Inst foo-same-provider (1.0 unstable [i386]) -Conf foo-same:amd64 (4.0 unstable [amd64]) Conf foo-same (4.0 unstable [i386]) +Conf foo-same:amd64 (4.0 unstable [amd64]) Conf foo-same-breaker-3 (1.0 unstable [i386]) Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider foo-same-breaker-3 -s diff --git a/test/integration/test-ignore-provides-if-versioned-conflicts b/test/integration/test-ignore-provides-if-versioned-conflicts index 839609431..3243cfb51 100755 --- a/test/integration/test-ignore-provides-if-versioned-conflicts +++ b/test/integration/test-ignore-provides-if-versioned-conflicts @@ -144,7 +144,7 @@ Inst foo-same [2.0] (4.0 unstable [i386]) [foo-same:i386 on foo-same:amd64] [foo Inst foo-same:amd64 [2.0] (4.0 unstable [amd64]) Inst foo-same-breaker-3 (1.0 unstable [i386]) Inst foo-same-provider (1.0 unstable [i386]) -Conf foo-same:amd64 (4.0 unstable [amd64]) Conf foo-same (4.0 unstable [i386]) +Conf foo-same:amd64 (4.0 unstable [amd64]) Conf foo-same-breaker-3 (1.0 unstable [i386]) Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider foo-same-breaker-3 -s diff --git a/test/integration/test-no-fds-leaked-to-maintainer-scripts b/test/integration/test-no-fds-leaked-to-maintainer-scripts index 56cbff095..21b394055 100755 --- a/test/integration/test-no-fds-leaked-to-maintainer-scripts +++ b/test/integration/test-no-fds-leaked-to-maintainer-scripts @@ -34,7 +34,7 @@ rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log testsuccess aptget install -y fdleaks -qq < /dev/null checkfdleak() { - msgtest 'Check if fds were not' 'leaked' + msgtest 'Check if fds were not' "leaked: expect $1" if [ "$(grep 'root root' rootdir/tmp/testsuccess.output | wc -l)" = "$1" ]; then msgpass else @@ -72,12 +72,15 @@ checkpurge() { tail -n +3 rootdir/var/log/apt/term.log | head -n -1 > terminal.log testfileequal 'terminal.log' "$(cat terminal.output)" - testequal "startup packages purge + testequal "startup packages remove status installed $PKGNAME 1.0 remove $PKGNAME 1.0 <none> status half-configured $PKGNAME 1.0 status half-installed $PKGNAME 1.0 status config-files $PKGNAME 1.0 +status config-files $PKGNAME 1.0 +startup packages purge +remove $PKGNAME 1.0 <none> purge $PKGNAME 1.0 <none> status config-files $PKGNAME 1.0 status config-files $PKGNAME 1.0 @@ -86,6 +89,7 @@ status config-files $PKGNAME 1.0 status config-files $PKGNAME 1.0 status not-installed $PKGNAME <none> startup packages configure" cut -f 3- -d' ' rootdir/var/log/dpkg.log + testequalor2 "dpkg-query: no packages found matching ${PKGNAME}" "No packages found matching ${PKGNAME}." dpkg -l "$PKGNAME" } checkpurge diff --git a/test/integration/test-prevent-markinstall-multiarch-same-versionscrew b/test/integration/test-prevent-markinstall-multiarch-same-versionscrew index a46f2292a..a45c0d55d 100755 --- a/test/integration/test-prevent-markinstall-multiarch-same-versionscrew +++ b/test/integration/test-prevent-markinstall-multiarch-same-versionscrew @@ -59,10 +59,10 @@ Inst fine-installed [1] (2 unstable [amd64]) [fine-installed:amd64 on fine-insta Inst fine-installed:i386 [1] (2 unstable [i386]) Inst out-of-sync-gone-foreign [1] (2 unstable [amd64]) Inst out-of-sync-gone-native:i386 [1] (2 unstable [i386]) -Conf fine:i386 (2 unstable [i386]) Conf fine (2 unstable [amd64]) -Conf fine-installed:i386 (2 unstable [i386]) +Conf fine:i386 (2 unstable [i386]) Conf fine-installed (2 unstable [amd64]) +Conf fine-installed:i386 (2 unstable [i386]) Conf out-of-sync-gone-foreign (2 unstable [amd64]) Conf out-of-sync-gone-native:i386 (2 unstable [i386])' aptget dist-upgrade -s #-o Debug::pkgDepCache::Marker=1 @@ -89,10 +89,10 @@ Inst fine-installed [1] (3 experimental [amd64]) [fine-installed:amd64 on fine-i Inst fine-installed:i386 [1] (3 experimental [i386]) Inst out-of-sync-gone-foreign [1] (2 unstable [amd64]) Inst out-of-sync-gone-native:i386 [1] (2 unstable [i386]) -Conf fine:i386 (3 experimental [i386]) Conf fine (3 experimental [amd64]) -Conf fine-installed:i386 (3 experimental [i386]) +Conf fine:i386 (3 experimental [i386]) Conf fine-installed (3 experimental [amd64]) +Conf fine-installed:i386 (3 experimental [i386]) Conf out-of-sync-gone-foreign (2 unstable [amd64]) Conf out-of-sync-gone-native:i386 (2 unstable [i386])' aptget dist-upgrade -s #-o Debug::pkgDepCache::Marker=1 diff --git a/test/integration/test-ubuntu-bug-761175-remove-purge b/test/integration/test-ubuntu-bug-761175-remove-purge index aae394ad8..6ae1a04e8 100755 --- a/test/integration/test-ubuntu-bug-761175-remove-purge +++ b/test/integration/test-ubuntu-bug-761175-remove-purge @@ -30,6 +30,8 @@ runtests() { testsuccess aptget install compiz-core-${PKG} -t "${RELEASE}" "$@" testdpkginstalled compiz-core-${PKG} + testsuccess aptget remove compiz-core-${PKG} -y "$@" -o Debug::pkgDpkgPm=1 + testfailure grep -- '--force-remove-essential' rootdir/tmp/testsuccess.output testsuccess aptget remove compiz-core-${PKG} -y "$@" testdpkgnotinstalled compiz-core-${PKG} testdpkgstatus 'rc' '1' "compiz-core-${PKG}" @@ -61,6 +63,8 @@ The following packages will be REMOVED: 0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded. Purg compiz-core-${PKG}" aptget purge compiz-core-${PKG} -s "$@" fi + testsuccess aptget purge compiz-core-${PKG} -y "$@" -o Debug::pkgDpkgPm=1 + testfailure grep -- '--force-remove-essential' rootdir/tmp/testsuccess.output testsuccess aptget purge compiz-core-${PKG} -y "$@" echo -n '' > rootdir/var/lib/dpkg/available # dpkg -l < 1.16.2 reads the available file by default, where the package can be found testequalor2 "dpkg-query: no packages found matching compiz-core-${PKG}" "No packages found matching compiz-core-${PKG}." dpkg -l compiz-core-${PKG} diff --git a/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages b/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages index 7fcf16ed5..09953e943 100755 --- a/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages +++ b/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages @@ -39,11 +39,11 @@ Inst libreoffice-style-galaxy [3] (4 sid [amd64]) [libreoffice-common:amd64 on l Inst libreoffice-core [3] (4 sid [amd64]) [libreoffice-core:amd64 on libreoffice-common:amd64] [libreoffice-common:amd64 on libreoffice-core:amd64] [libreoffice-common:amd64 on libreoffice-style-galaxy:amd64] [libreoffice-common:amd64 ] Inst libreoffice-common [3] (4 sid [all]) [] Inst ure (4 sid [amd64]) -Conf ure (4 sid [amd64]) -Conf libreoffice-common (4 sid [all]) -Conf libreoffice-core (4 sid [amd64]) +Conf libreoffice (4 sid [amd64]) Conf libreoffice-style-galaxy (4 sid [amd64]) -Conf libreoffice (4 sid [amd64])' 'Reading package lists... +Conf libreoffice-core (4 sid [amd64]) +Conf libreoffice-common (4 sid [all]) +Conf ure (4 sid [amd64])' 'Reading package lists... Building dependency tree... Calculating upgrade... The following NEW packages will be installed: @@ -56,8 +56,8 @@ Inst libreoffice-style-galaxy [3] (4 sid [amd64]) [libreoffice-common:amd64 on l Inst libreoffice-core [3] (4 sid [amd64]) [libreoffice-common:amd64 on libreoffice-core:amd64] [libreoffice-common:amd64 on libreoffice-style-galaxy:amd64] [libreoffice-core:amd64 on libreoffice-common:amd64] [libreoffice-common:amd64 ] Inst libreoffice-common [3] (4 sid [all]) [] Inst ure (4 sid [amd64]) -Conf ure (4 sid [amd64]) -Conf libreoffice-common (4 sid [all]) -Conf libreoffice-core (4 sid [amd64]) +Conf libreoffice (4 sid [amd64]) Conf libreoffice-style-galaxy (4 sid [amd64]) -Conf libreoffice (4 sid [amd64])' aptget dist-upgrade -s +Conf libreoffice-core (4 sid [amd64]) +Conf libreoffice-common (4 sid [all]) +Conf ure (4 sid [amd64])' aptget dist-upgrade -s |