From dde0c674e423e5f06d1e319e3a096054607a5f72 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 20 Mar 2011 19:52:53 +0100 Subject: reorganize the marker methods a bit by moving the common part to a seperate IsModeChangeOk which checks sanity and dpkg holds --- apt-pkg/depcache.cc | 130 +++++++++++---------- apt-pkg/depcache.h | 4 + debian/changelog | 2 +- ...est-bug-549968-install-depends-of-not-installed | 2 +- 4 files changed, 77 insertions(+), 61 deletions(-) diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index fba6ad054..46fbc9e58 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -819,8 +819,7 @@ void pkgDepCache::Update(PkgIterator const &Pkg) void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser, unsigned long Depth) { - // Simplifies other routines. - if (Pkg.end() == true) + if (IsModeChangeOk(ModeKeep, Pkg, Depth, FromUser) == false) return; /* Reject an attempt to keep a non-source broken installed package, those @@ -828,25 +827,22 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser, if (Pkg.State() == PkgIterator::NeedsUnpack && Pkg.CurrentVer().Downloadable() == false) return; - - /** \todo Can this be moved later in the method? */ - ActionGroup group(*this); /* We changed the soft state all the time so the UI is a bit nicer to use */ StateCache &P = PkgState[Pkg->ID]; + + // Check that it is not already kept + if (P.Mode == ModeKeep) + return; + if (Soft == true) P.iFlags |= AutoKept; else P.iFlags &= ~AutoKept; - - // Check that it is not already kept - if (P.Mode == ModeKeep) - return; - // We dont even try to keep virtual packages.. - if (Pkg->VersionList == 0) - return; + ActionGroup group(*this); + #if 0 // reseting the autoflag here means we lose the // auto-mark information if a user selects a package for removal // but changes his mind then and sets it for keep again @@ -883,30 +879,26 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser, void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, unsigned long Depth, bool FromUser) { - // Simplifies other routines. - if (Pkg.end() == true) + if (IsModeChangeOk(ModeDelete, Pkg, Depth, FromUser) == false) return; - ActionGroup group(*this); + StateCache &P = PkgState[Pkg->ID]; // Check that it is not already marked for delete - StateCache &P = PkgState[Pkg->ID]; - P.iFlags &= ~(AutoKept | Purge); - if (rPurge == true) - P.iFlags |= Purge; - if ((P.Mode == ModeDelete || P.InstallVer == 0) && (Pkg.Purge() == true || rPurge == false)) return; - - // We dont even try to delete virtual packages.. - if (Pkg->VersionList == 0) - return; - // check if we are allowed to install the package + // check if we are allowed to remove the package if (IsDeleteOk(Pkg,rPurge,Depth,FromUser) == false) return; + P.iFlags &= ~(AutoKept | Purge); + if (rPurge == true) + P.iFlags |= Purge; + + ActionGroup group(*this); + if (DebugMarker == true) std::clog << OutputInDepth(Depth) << (rPurge ? "MarkPurge " : "MarkDelete ") << Pkg << " FU=" << FromUser << std::endl; @@ -927,19 +919,12 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, /*}}}*/ // DepCache::IsDeleteOk - check if it is ok to remove this package /*{{{*/ // --------------------------------------------------------------------- -/* The default implementation just honors dpkg hold - But an application using this library can override this method - to control the MarkDelete behaviour */ +/* The default implementation tries to prevent deletion of install requests. + dpkg holds are enforced by the private IsModeChangeOk */ bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge, unsigned long Depth, bool FromUser) { - if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false) - { - if (DebugMarker == true) - std::clog << OutputInDepth(Depth) << "Hold prevents MarkDelete of " << Pkg << " FU=" << FromUser << std::endl; - return false; - } - else if (FromUser == false && Pkg->CurrentVer == 0) + if (FromUser == false && Pkg->CurrentVer == 0) { StateCache &P = PkgState[Pkg->ID]; if (P.InstallVer != 0 && P.Status == 2 && (P.Flags & Flag::Auto) != Flag::Auto) @@ -949,6 +934,46 @@ bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge, return false; } } + 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 + IsOk methods instead */ +char const* PrintMode(char const mode) +{ + switch (mode) + { + case pkgDepCache::ModeInstall: return "Install"; + case pkgDepCache::ModeKeep: return "Keep"; + case pkgDepCache::ModeDelete: return "Delete"; + 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; + + // enforce dpkg holds + if (FromUser == false && mode != ModeKeep && Pkg->SelectedState == pkgCache::State::Hold && + _config->FindB("APT::Ignore-Hold",false) == false) + { + if (unlikely(DebugMarker == true) && PkgState[Pkg->ID].Mode != mode) + std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode) + << " of " << Pkg << std::endl; + return false; + } + return true; } /*}}}*/ @@ -959,19 +984,17 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, unsigned long Depth, bool FromUser, bool ForceImportantDeps) { - if (Depth > 100) + if (IsModeChangeOk(ModeInstall, Pkg, Depth, FromUser) == false) return; - - // Simplifies other routines. - if (Pkg.end() == true) + + StateCache &P = PkgState[Pkg->ID]; + + // See if there is even any possible instalation candidate + if (P.CandidateVer == 0) return; - - ActionGroup group(*this); /* Check that it is not already marked for install and that it can be installed */ - StateCache &P = PkgState[Pkg->ID]; - P.iFlags &= ~AutoKept; if ((P.InstPolicyBroken() == false && P.InstBroken() == false) && (P.Mode == ModeInstall || P.CandidateVer == (Version *)Pkg.CurrentVer())) @@ -981,17 +1004,13 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, return; } - // See if there is even any possible instalation candidate - if (P.CandidateVer == 0) - return; - // We dont even try to install virtual packages.. - if (Pkg->VersionList == 0) - return; - // check if we are allowed to install the package if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false) return; + ActionGroup group(*this); + P.iFlags &= ~AutoKept; + /* Target the candidate version and remove the autoflag. We reset the autoflag below if this was called recursively. Otherwise the user should have the ability to de-auto a package by changing its state */ @@ -1204,18 +1223,11 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, /*}}}*/ // DepCache::IsInstallOk - check if it is ok to install this package /*{{{*/ // --------------------------------------------------------------------- -/* The default implementation just honors dpkg hold - But an application using this library can override this method - to control the MarkInstall behaviour */ +/* The default implementation does nothing. + dpkg holds are enforced by the private IsModeChangeOk */ bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst, unsigned long Depth, bool FromUser) { - if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false) - { - if (DebugMarker == true) - std::clog << OutputInDepth(Depth) << "Hold prevents MarkInstall of " << Pkg << " FU=" << FromUser << std::endl; - return false; - } return true; } /*}}}*/ diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index b95681118..8cf7db80a 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -486,6 +486,10 @@ class pkgDepCache : protected pkgCache::Namespace __deprecated bool RemovePseudoInstalledPkg(PkgIterator &Pkg, std::set &recheck) { return true; }; __deprecated bool ReInstallPseudoForGroup(unsigned long const &Grp, std::set &recheck) { return true; }; __deprecated bool ReInstallPseudoForGroup(pkgCache::PkgIterator const &P, std::set &recheck) { return true; }; + + + bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, + unsigned long const Depth, bool const FromUser); }; #endif diff --git a/debian/changelog b/debian/changelog index c6df16bb9..b691a1938 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,7 +6,7 @@ apt (0.8.13.1) UNRELEASED; urgency=low * apt-pkg/vendor.cc, apt-pkg/vendorlist.cc: - mark them as deprecated as they are unused - -- David Kalnischkies Wed, 16 Mar 2011 21:23:32 +0100 + -- David Kalnischkies Sun, 20 Mar 2011 19:51:41 +0100 apt (0.8.13) unstable; urgency=low diff --git a/test/integration/test-bug-549968-install-depends-of-not-installed b/test/integration/test-bug-549968-install-depends-of-not-installed index 871d236b9..d5eae1ae6 100755 --- a/test/integration/test-bug-549968-install-depends-of-not-installed +++ b/test/integration/test-bug-549968-install-depends-of-not-installed @@ -17,7 +17,7 @@ setupaptarchive testequal 'Reading package lists... Building dependency tree... MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1 - Hold prevents MarkInstall of extracoolstuff [ i386 ] < none -> 1.0 > ( other ) FU=0 + Hold prevents MarkInstall of extracoolstuff [ i386 ] < none -> 1.0 > ( other ) Package extracoolstuff is not installed, so not removed The following NEW packages will be installed: coolstuff -- cgit v1.2.3