summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/algorithms.cc49
-rw-r--r--apt-pkg/contrib/gpgv.cc3
-rw-r--r--apt-pkg/contrib/srvrec.cc17
-rw-r--r--apt-pkg/contrib/strutl.cc2
-rw-r--r--apt-pkg/deb/deblistparser.cc11
-rw-r--r--apt-pkg/deb/debsystem.cc7
-rw-r--r--apt-pkg/deb/debsystem.h1
-rw-r--r--apt-pkg/deb/dpkgpm.cc14
-rw-r--r--apt-pkg/depcache.cc196
-rw-r--r--apt-pkg/depcache.h3
-rw-r--r--apt-pkg/edsp.cc28
-rw-r--r--apt-pkg/tagfile-keys.list1
-rw-r--r--apt-pkg/tagfile-order.c3
13 files changed, 216 insertions, 119 deletions
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index cba772d41..cd09a6944 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -517,18 +517,37 @@ void pkgProblemResolver::MakeScores()
Score += PrioInstalledAndNotObsolete;
// propagate score points along dependencies
- for (pkgCache::DepIterator D = InstVer.DependsList(); D.end() == false; ++D)
+ for (pkgCache::DepIterator D = InstVer.DependsList(); not D.end(); ++D)
{
if (DepMap[D->Type] == 0)
continue;
pkgCache::PkgIterator const T = D.TargetPkg();
- if (D->Version != 0)
+ if (not D.IsIgnorable(T))
{
- pkgCache::VerIterator const IV = Cache[T].InstVerIter(Cache);
- if (IV.end() == true || D.IsSatisfied(IV) == false)
+ if (D->Version != 0)
+ {
+ pkgCache::VerIterator const IV = Cache[T].InstVerIter(Cache);
+ if (IV.end() || not D.IsSatisfied(IV))
+ continue;
+ }
+ Scores[T->ID] += DepMap[D->Type];
+ }
+
+ std::vector<map_id_t> providers;
+ for (auto Prv = T.ProvidesList(); not Prv.end(); ++Prv)
+ {
+ if (D.IsIgnorable(Prv))
+ continue;
+ auto const PV = Prv.OwnerVer();
+ auto const PP = PV.ParentPkg();
+ if (PV != Cache[PP].InstVerIter(Cache) || not D.IsSatisfied(Prv))
continue;
+ providers.push_back(PP->ID);
}
- Scores[T->ID] += DepMap[D->Type];
+ std::sort(providers.begin(), providers.end());
+ providers.erase(std::unique(providers.begin(), providers.end()), providers.end());
+ for (auto const prv : providers)
+ Scores[prv] += DepMap[D->Type];
}
}
@@ -564,13 +583,25 @@ void pkgProblemResolver::MakeScores()
provide important packages extremely important */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
{
- for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; ++P)
+ auto const transfer = abs(Scores[I->ID] - OldScores[I->ID]);
+ if (transfer == 0)
+ continue;
+
+ std::vector<map_id_t> providers;
+ for (auto Prv = I.ProvidesList(); not Prv.end(); ++Prv)
{
- // Only do it once per package
- if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
+ if (Prv.IsMultiArchImplicit())
+ continue;
+ auto const PV = Prv.OwnerVer();
+ auto const PP = PV.ParentPkg();
+ if (PV != Cache[PP].InstVerIter(Cache))
continue;
- Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
+ providers.push_back(PP->ID);
}
+ std::sort(providers.begin(), providers.end());
+ providers.erase(std::unique(providers.begin(), providers.end()), providers.end());
+ for (auto const prv : providers)
+ Scores[prv] += transfer;
}
/* Protected things are pushed really high up. This number should put them
diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc
index d956eaf00..28f3150c3 100644
--- a/apt-pkg/contrib/gpgv.cc
+++ b/apt-pkg/contrib/gpgv.cc
@@ -251,6 +251,9 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
setenv("APT_CONFIG", conf.get(), 1);
}
+ // Tell apt-key not to emit warnings
+ setenv("APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE", "1", 1);
+
if (releaseSignature == DETACHED)
{
auto detached = make_unique_FILE(FileGPG, "r");
diff --git a/apt-pkg/contrib/srvrec.cc b/apt-pkg/contrib/srvrec.cc
index 7d9bf116e..4ca208273 100644
--- a/apt-pkg/contrib/srvrec.cc
+++ b/apt-pkg/contrib/srvrec.cc
@@ -137,17 +137,12 @@ bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result)
// sort them by priority
std::stable_sort(Result.begin(), Result.end());
- for(std::vector<SrvRec>::iterator I = Result.begin();
- I != Result.end(); ++I)
- {
- if (_config->FindB("Debug::Acquire::SrvRecs", false) == true)
- {
- std::cerr << "SrvRecs: got " << I->target
- << " prio: " << I->priority
- << " weight: " << I->weight
- << std::endl;
- }
- }
+ if (_config->FindB("Debug::Acquire::SrvRecs", false))
+ for(auto const &R : Result)
+ std::cerr << "SrvRecs: got " << R.target
+ << " prio: " << R.priority
+ << " weight: " << R.weight
+ << '\n';
return true;
}
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index 972472986..bd4856526 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -1771,7 +1771,7 @@ URI::operator string()
{
// FIXME: Technically userinfo is permitted even less
// characters than these, but this is not conveniently
- // expressed with a blacklist.
+ // expressed with a denylist.
Res << QuoteString(User, ":/?#[]@");
if (Password.empty() == false)
Res << ":" << QuoteString(Password, ":/?#[]@");
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index ab957a01a..240946529 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -318,6 +318,8 @@ bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg,
return false;
if (Section.FindFlag(pkgTagSection::Key::Important,Pkg->Flags,pkgCache::Flag::Important) == false)
return false;
+ if (Section.FindFlag(pkgTagSection::Key::Protected, Pkg->Flags, pkgCache::Flag::Important) == false)
+ return false;
if (std::find(forceEssential.begin(), forceEssential.end(), Pkg.Name()) != forceEssential.end())
{
@@ -1018,12 +1020,11 @@ debDebFileParser::debDebFileParser(FileFd *File, std::string const &DebFile)
bool debDebFileParser::UsePackage(pkgCache::PkgIterator &Pkg,
pkgCache::VerIterator &Ver)
{
- bool res = debListParser::UsePackage(Pkg, Ver);
- // we use the full file path as a provides so that the file is found
- // by its name
- if(NewProvides(Ver, DebFile, Pkg.Cache()->NativeArch(), Ver.VerStr(), 0) == false)
+ if (not debListParser::UsePackage(Pkg, Ver))
return false;
- return res;
+ // we use the full file path as a provides so that the file is found by its name
+ // using the MultiArchImplicit flag for this is a bit of a stretch
+ return NewProvides(Ver, DebFile, Pkg.Cache()->NativeArch(), Ver.VerStr(), pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific);
}
debListParser::~debListParser() {}
diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc
index 7d4bf7213..eac43c3b7 100644
--- a/apt-pkg/deb/debsystem.cc
+++ b/apt-pkg/deb/debsystem.cc
@@ -466,8 +466,13 @@ pid_t debSystem::ExecDpkg(std::vector<std::string> const &sArgs, int * const inp
/*}}}*/
bool debSystem::MultiArchSupported() const /*{{{*/
{
+ return AssertFeature("multi-arch");
+}
+ /*}}}*/
+bool debSystem::AssertFeature(std::string const &feature) /*{{{*/
+{
std::vector<std::string> Args = GetDpkgBaseCommand();
- Args.push_back("--assert-multi-arch");
+ Args.push_back("--assert-" + feature);
pid_t const dpkgAssertMultiArch = ExecDpkg(Args, nullptr, nullptr, true);
if (dpkgAssertMultiArch > 0)
{
diff --git a/apt-pkg/deb/debsystem.h b/apt-pkg/deb/debsystem.h
index 2e5a8550c..b3d241512 100644
--- a/apt-pkg/deb/debsystem.h
+++ b/apt-pkg/deb/debsystem.h
@@ -45,6 +45,7 @@ class debSystem : public pkgSystem
APT_HIDDEN static void DpkgChrootDirectory();
APT_HIDDEN static pid_t ExecDpkg(std::vector<std::string> const &sArgs, int * const inputFd, int * const outputFd, bool const DiscardOutput);
bool MultiArchSupported() const override;
+ static bool AssertFeature(std::string const &Feature);
std::vector<std::string> ArchitecturesSupported() const override;
bool LockInner(OpProgress *const Progress, int timeoutSec) override;
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index ef73881c8..c496538cc 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -1416,6 +1416,15 @@ static bool ItemIsEssential(pkgDPkgPM::Item const &I)
return true;
return (I.Pkg->Flags & pkgCache::Flag::Essential) != 0;
}
+static bool ItemIsProtected(pkgDPkgPM::Item const &I)
+{
+ static auto const cachegen = _config->Find("pkgCacheGen::Protected");
+ if (cachegen == "none" || cachegen == "native")
+ return true;
+ if (unlikely(I.Pkg.end()))
+ return true;
+ return (I.Pkg->Flags & pkgCache::Flag::Important) != 0;
+}
bool pkgDPkgPM::ExpandPendingCalls(std::vector<Item> &List, pkgDepCache &Cache)
{
{
@@ -1712,6 +1721,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
OpenLog();
bool dpkgMultiArch = _system->MultiArchSupported();
+ bool dpkgProtectedField = debSystem::AssertFeature("protected-field");
// start pty magic before the loop
StartPtyMagic();
@@ -1780,6 +1790,10 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
{
ADDARGC("--force-remove-essential");
}
+ if (dpkgProtectedField && std::any_of(I, J, ItemIsProtected))
+ {
+ ADDARGC("--force-remove-protected");
+ }
ADDARGC("--remove");
break;
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index f90a41e22..c7ef7a400 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -839,13 +839,73 @@ void pkgDepCache::Update(PkgIterator const &Pkg)
Update(P.ParentPkg().RevDependsList());
}
/*}}}*/
+// DepCache::IsModeChangeOk - check if it is ok to change the mode /*{{{*/
+// ---------------------------------------------------------------------
+/* this is used by all Mark methods on the very first line to check sanity
+ and prevents mode changes for packages on hold for example.
+ If you want to check Mode specific stuff you can use the virtual public
+ Is<Mode>Ok methods instead */
+static char const* PrintMode(char const mode)
+{
+ switch (mode)
+ {
+ case pkgDepCache::ModeInstall: return "Install";
+ case pkgDepCache::ModeKeep: return "Keep";
+ case pkgDepCache::ModeDelete: return "Delete";
+ case pkgDepCache::ModeGarbage: return "Garbage";
+ default: return "UNKNOWN";
+ }
+}
+static bool IsModeChangeOk(pkgDepCache &Cache, pkgDepCache::ModeList const mode, pkgCache::PkgIterator const &Pkg,
+ unsigned long const Depth, bool const FromUser, bool const DebugMarker)
+{
+ // we are not trying to hard…
+ if (unlikely(Depth > 100))
+ return false;
+
+ // general sanity
+ if (unlikely(Pkg.end() == true || Pkg->VersionList == 0))
+ return false;
+
+ // the user is always right
+ if (FromUser == true)
+ return true;
+
+ auto &P = Cache[Pkg];
+ // not changing the mode is obviously also fine as we might want to call
+ // e.g. MarkInstall multiple times with different arguments for the same package
+ if (P.Mode == mode)
+ return true;
+
+ // if previous state was set by user only user can reset it
+ if ((P.iFlags & pkgDepCache::Protected) == pkgDepCache::Protected)
+ {
+ if (unlikely(DebugMarker == true))
+ std::clog << OutputInDepth(Depth) << "Ignore Mark" << PrintMode(mode)
+ << " of " << APT::PrettyPkg(&Cache, Pkg) << " as its mode (" << PrintMode(P.Mode)
+ << ") is protected" << std::endl;
+ return false;
+ }
+ // enforce dpkg holds
+ else if (mode != pkgDepCache::ModeKeep && Pkg->SelectedState == pkgCache::State::Hold &&
+ _config->FindB("APT::Ignore-Hold",false) == false)
+ {
+ if (unlikely(DebugMarker == true))
+ std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode)
+ << " of " << APT::PrettyPkg(&Cache, Pkg) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+ /*}}}*/
// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
// ---------------------------------------------------------------------
/* */
bool pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
unsigned long Depth)
{
- if (IsModeChangeOk(ModeKeep, Pkg, Depth, FromUser) == false)
+ if (not IsModeChangeOk(*this, ModeKeep, Pkg, Depth, FromUser, DebugMarker))
return false;
/* Reject an attempt to keep a non-source broken installed package, those
@@ -905,7 +965,7 @@ bool pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
unsigned long Depth, bool FromUser)
{
- if (IsModeChangeOk(ModeDelete, Pkg, Depth, FromUser) == false)
+ if (not IsModeChangeOk(*this, ModeDelete, Pkg, Depth, FromUser, DebugMarker))
return false;
StateCache &P = PkgState[Pkg->ID];
@@ -1004,66 +1064,6 @@ bool pkgDepCache::IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg,
return true;
}
/*}}}*/
-// DepCache::IsModeChangeOk - check if it is ok to change the mode /*{{{*/
-// ---------------------------------------------------------------------
-/* this is used by all Mark methods on the very first line to check sanity
- and prevents mode changes for packages on hold for example.
- If you want to check Mode specific stuff you can use the virtual public
- Is<Mode>Ok methods instead */
-static char const* PrintMode(char const mode)
-{
- switch (mode)
- {
- case pkgDepCache::ModeInstall: return "Install";
- case pkgDepCache::ModeKeep: return "Keep";
- case pkgDepCache::ModeDelete: return "Delete";
- case pkgDepCache::ModeGarbage: return "Garbage";
- default: return "UNKNOWN";
- }
-}
-bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
- unsigned long const Depth, bool const FromUser)
-{
- // we are not trying to hard…
- if (unlikely(Depth > 100))
- return false;
-
- // general sanity
- if (unlikely(Pkg.end() == true || Pkg->VersionList == 0))
- return false;
-
- // the user is always right
- if (FromUser == true)
- return true;
-
- StateCache &P = PkgState[Pkg->ID];
- // not changing the mode is obviously also fine as we might want to call
- // e.g. MarkInstall multiple times with different arguments for the same package
- if (P.Mode == mode)
- return true;
-
- // if previous state was set by user only user can reset it
- if ((P.iFlags & Protected) == Protected)
- {
- if (unlikely(DebugMarker == true))
- std::clog << OutputInDepth(Depth) << "Ignore Mark" << PrintMode(mode)
- << " of " << APT::PrettyPkg(this, Pkg) << " as its mode (" << PrintMode(P.Mode)
- << ") is protected" << std::endl;
- return false;
- }
- // enforce dpkg holds
- else if (mode != ModeKeep && Pkg->SelectedState == pkgCache::State::Hold &&
- _config->FindB("APT::Ignore-Hold",false) == false)
- {
- if (unlikely(DebugMarker == true))
- std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode)
- << " of " << APT::PrettyPkg(this, Pkg) << std::endl;
- return false;
- }
-
- return true;
-}
- /*}}}*/
struct CompareProviders /*{{{*/
{
pkgDepCache const &Cache;
@@ -1279,32 +1279,55 @@ static APT::VersionVector getAllPossibleSolutions(pkgDepCache &Cache, pkgCache::
toNewInstall.emplace_back(std::move(Ver));
}
} while (Start++ != End);
- std::move(toNewInstall.begin(), toNewInstall.end(), std::back_inserter(toUpgrade));
+ if (toUpgrade.empty())
+ toUpgrade = std::move(toNewInstall);
+ else
+ std::move(toNewInstall.begin(), toNewInstall.end(), std::back_inserter(toUpgrade));
+
if (not sorted)
std::sort(toUpgrade.begin(), toUpgrade.end(), [](pkgCache::VerIterator const &A, pkgCache::VerIterator const &B) { return A->ID < B->ID; });
toUpgrade.erase(std::unique(toUpgrade.begin(), toUpgrade.end()), toUpgrade.end());
+
+ if (not End.IsNegative())
+ toUpgrade.erase(std::remove_if(toUpgrade.begin(), toUpgrade.end(), [&Cache](pkgCache::VerIterator const &V) {
+ auto const P = V.ParentPkg();
+ auto const &State = Cache[P];
+ return State.Protect() && (State.Delete() || (State.Keep() && P->CurrentVer == 0));
+ }),
+ toUpgrade.end());
+
return toUpgrade;
}
/*}}}*/
-static bool MarkInstall_MarkDeleteForNotUpgradeable(pkgDepCache &Cache, bool const DebugAutoInstall, pkgCache::VerIterator const &PV, unsigned long const Depth, pkgCache::PkgIterator const &Pkg, bool const propagateProctected)/*{{{*/
+static bool MarkInstall_MarkDeleteForNotUpgradeable(pkgDepCache &Cache, bool const DebugAutoInstall, pkgCache::VerIterator const &PV, unsigned long const Depth, pkgCache::PkgIterator const &Pkg, bool const propagateProctected, APT::PackageVector &delayedRemove)/*{{{*/
{
auto &State = Cache[Pkg];
- if (not State.Delete())
+ if (not propagateProctected)
{
+ if (State.Delete())
+ return true;
if(DebugAutoInstall)
- std::clog << OutputInDepth(Depth) << " Removing: " << Pkg.Name() << " as upgrade is not an option for " << PV.ParentPkg().FullName() << " (" << PV.VerStr() << ")\n";
- if (not Cache.MarkDelete(Pkg, false, Depth + 1, false))
+ std::clog << OutputInDepth(Depth) << " Delayed Removing: " << Pkg.FullName() << " as upgrade is not an option for " << PV.ParentPkg().FullName() << " (" << PV.VerStr() << ")\n";
+ if (not IsModeChangeOk(Cache, pkgDepCache::ModeDelete, Pkg, Depth, false, DebugAutoInstall) ||
+ not Cache.IsDeleteOk(Pkg, false, Depth, false))
return false;
+ delayedRemove.push_back(Pkg);
+ return true;
}
- if (propagateProctected)
+
+ if (not State.Delete())
{
- MarkInstall_DiscardCandidate(Cache, Pkg);
- Cache.MarkProtected(Pkg);
+ if(DebugAutoInstall)
+ std::clog << OutputInDepth(Depth) << " Removing: " << Pkg.FullName() << " as upgrade is not an option for " << PV.ParentPkg().FullName() << " (" << PV.VerStr() << ")\n";
+ if (not Cache.MarkDelete(Pkg, false, Depth + 1, false))
+ return false;
}
+ MarkInstall_DiscardCandidate(Cache, Pkg);
+ Cache.MarkProtected(Pkg);
return true;
}
/*}}}*/
-static bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgDepCache &Cache, bool const DebugAutoInstall, pkgCache::VerIterator const &PV, unsigned long Depth, std::vector<pkgCache::DepIterator> &toRemove, APT::PackageVector &toUpgrade, bool const propagateProctected, bool const FromUser) /*{{{*/
+static bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgDepCache &Cache, bool const DebugAutoInstall, pkgCache::VerIterator const &PV, unsigned long Depth, std::vector<pkgCache::DepIterator> &toRemove, APT::PackageVector &toUpgrade, APT::PackageVector &delayedRemove, bool const propagateProctected, bool const FromUser) /*{{{*/
{
/* Negative dependencies have no or-group
If the candidate is effected try to keep current and discard candidate
@@ -1336,7 +1359,7 @@ static bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgDepCache &Cache, bool
else
badCandidate.push_back(Pkg);
}
- else if (not MarkInstall_MarkDeleteForNotUpgradeable(Cache, DebugAutoInstall, PV, Depth, Pkg, propagateProctected))
+ else if (not MarkInstall_MarkDeleteForNotUpgradeable(Cache, DebugAutoInstall, PV, Depth, Pkg, propagateProctected, delayedRemove))
{
failedToRemoveSomething = true;
if (not propagateProctected && not FromUser)
@@ -1352,7 +1375,9 @@ static bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgDepCache &Cache, bool
if (State.CandidateVer != Ver && State.CandidateVer != nullptr &&
std::find(badCandidate.cbegin(), badCandidate.cend(), Pkg) == badCandidate.end())
toUpgrade.push_back(Pkg);
- else if (not MarkInstall_MarkDeleteForNotUpgradeable(Cache, DebugAutoInstall, PV, Depth, Pkg, propagateProctected))
+ else if (State.CandidateVer == Pkg.CurrentVer())
+ ; // already done in the first loop above
+ else if (not MarkInstall_MarkDeleteForNotUpgradeable(Cache, DebugAutoInstall, PV, Depth, Pkg, propagateProctected, delayedRemove))
{
failedToRemoveSomething = true;
if (not propagateProctected && not FromUser)
@@ -1510,10 +1535,12 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst,
unsigned long Depth, bool FromUser,
bool ForceImportantDeps)
{
- if (IsModeChangeOk(ModeInstall, Pkg, Depth, FromUser) == false)
+ StateCache &P = PkgState[Pkg->ID];
+ if (P.Protect() && P.Keep() && P.CandidateVer != nullptr && P.CandidateVer == Pkg.CurrentVer())
+ ; // we are here to mark our dependencies as protected, no state is changed
+ else if (not IsModeChangeOk(*this, ModeInstall, Pkg, Depth, FromUser, DebugMarker))
return false;
- StateCache &P = PkgState[Pkg->ID];
// See if there is even any possible installation candidate
if (P.CandidateVer == 0)
@@ -1545,7 +1572,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst,
bool hasFailed = false;
std::vector<pkgCache::DepIterator> toInstall, toRemove;
- APT::PackageVector toUpgrade;
+ APT::PackageVector toUpgrade, delayedRemove;
if (AutoSolve)
{
VerIterator const PV = P.CandidateVerIter(*this);
@@ -1554,7 +1581,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst,
if (not MarkInstall_CollectDependencies(*this, PV, toInstall, toRemove))
return false;
- if (not MarkInstall_RemoveConflictsIfNotUpgradeable(*this, DebugAutoInstall, PV, Depth, toRemove, toUpgrade, P.Protect(), FromUser))
+ if (not MarkInstall_RemoveConflictsIfNotUpgradeable(*this, DebugAutoInstall, PV, Depth, toRemove, toUpgrade, delayedRemove, P.Protect(), FromUser))
{
if (failEarly)
return false;
@@ -1628,6 +1655,19 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst,
hasFailed = true;
}
+ for (auto const &R : delayedRemove)
+ {
+ if (not MarkDelete(R, false, Depth, false))
+ {
+ if (failEarly)
+ {
+ MarkInstall_DiscardInstall(Pkg);
+ return false;
+ }
+ hasFailed = true;
+ }
+ }
+
if (MoveAutoBitToDependencies)
{
if (DebugAutoInstall)
@@ -2183,7 +2223,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
reason = "Required";
else if (userFunc.InRootSet(P))
reason = "Blacklisted [APT::NeverAutoRemove]";
- else if (IsModeChangeOk(ModeGarbage, P, 0, false) == false)
+ else if (not IsModeChangeOk(*this, ModeGarbage, P, 0, false, DebugMarker))
reason = "Hold";
else
continue;
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index d9bb69a18..78f88ba2f 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -518,9 +518,6 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace
private:
void * const d;
- APT_HIDDEN bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
- unsigned long const Depth, bool const FromUser);
-
APT_HIDDEN bool MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, bool FromUser);
APT_HIDDEN bool MarkInstall_DiscardInstall(PkgIterator const &Pkg);
diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc
index 3f8534234..7e3993be4 100644
--- a/apt-pkg/edsp.cc
+++ b/apt-pkg/edsp.cc
@@ -29,8 +29,10 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <algorithm>
#include <array>
#include <limits>
+#include <sstream>
#include <string>
#include <apti18n.h>
@@ -119,19 +121,25 @@ static bool WriteScenarioDependency(FileFd &output, pkgCache::VerIterator const
for (size_t i = 1; i < dependencies.size(); ++i)
if (dependencies[i].empty() == false)
WriteOkay(Okay, output, "\n", DepMap[i], ": ", dependencies[i]);
- string provides;
- for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv)
+ std::vector<std::string> provides;
+ for (auto Prv = Ver.ProvidesList(); not Prv.end(); ++Prv)
{
- if (Prv.IsMultiArchImplicit() == true)
+ if (Prv.IsMultiArchImplicit())
continue;
- if (provides.empty() == false)
- provides.append(", ");
- provides.append(Prv.Name());
+ std::string provide = Prv.Name();
if (Prv->ProvideVersion != 0)
- provides.append(" (= ").append(Prv.ProvideVersion()).append(")");
+ provide.append(" (= ").append(Prv.ProvideVersion()).append(")");
+ if ((Ver->MultiArch & pkgCache::Version::Foreign) != 0 && std::find(provides.cbegin(), provides.cend(), provide) != provides.cend())
+ continue;
+ provides.emplace_back(std::move(provide));
+ }
+ if (not provides.empty())
+ {
+ std::ostringstream out;
+ std::copy(provides.begin(), provides.end() - 1, std::ostream_iterator<std::string>(out, ", "));
+ out << provides.back();
+ WriteOkay(Okay, output, "\nProvides: ", out.str());
}
- if (provides.empty() == false)
- WriteOkay(Okay, output, "\nProvides: ", provides);
return WriteOkay(Okay, output, "\n");
}
/*}}}*/
@@ -262,7 +270,7 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FileFd &output, OpProgress *Progres
for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false && likely(Okay); ++Pkg)
{
std::string const arch = Pkg.Arch();
- if (std::find(archs.begin(), archs.end(), arch) == archs.end())
+ if (Pkg->CurrentVer == 0 && std::find(archs.begin(), archs.end(), arch) == archs.end())
continue;
for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false && likely(Okay); ++Ver, ++p)
{
diff --git a/apt-pkg/tagfile-keys.list b/apt-pkg/tagfile-keys.list
index a979a404b..a16bc686a 100644
--- a/apt-pkg/tagfile-keys.list
+++ b/apt-pkg/tagfile-keys.list
@@ -48,6 +48,7 @@ Package-Revision
Package-Type
Pre-Depends
Priority
+Protected
Provides
Recommended
Recommends
diff --git a/apt-pkg/tagfile-order.c b/apt-pkg/tagfile-order.c
index 4c2068c00..bb199b32e 100644
--- a/apt-pkg/tagfile-order.c
+++ b/apt-pkg/tagfile-order.c
@@ -11,7 +11,7 @@ static const char *iTFRewritePackageOrder[] = {
"Architecture",
"Subarchitecture", // Used only by d-i
"Version",
- "Revision", // Obsolete (warning in dpkg)
+ "Revision", // Obsolete (warning in dpkg)
"Package-Revision", // Obsolete (warning in dpkg)
"Package_Revision", // Obsolete (warning in dpkg)
"Kernel-Version", // Used only by d-i
@@ -23,6 +23,7 @@ static const char *iTFRewritePackageOrder[] = {
"Priority",
"Class", // dpkg nickname for Priority
"Build-Essential",
+ "Protected",
"Essential",
"Installer-Menu-Item", // Used only by d-i
"Section",