Explorar el Código

reorganize the marker methods a bit by moving the common part to a
seperate IsModeChangeOk which checks sanity and dpkg holds

David Kalnischkies hace 15 años
padre
commit
dde0c674e4

+ 71 - 59
apt-pkg/depcache.cc

@@ -819,8 +819,7 @@ void pkgDepCache::Update(PkgIterator const &Pkg)
 void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
 void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
                            unsigned long Depth)
                            unsigned long Depth)
 {
 {
-   // Simplifies other routines.
-   if (Pkg.end() == true)
+   if (IsModeChangeOk(ModeKeep, Pkg, Depth, FromUser) == false)
       return;
       return;
 
 
    /* Reject an attempt to keep a non-source broken installed package, those
    /* 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 && 
    if (Pkg.State() == PkgIterator::NeedsUnpack && 
        Pkg.CurrentVer().Downloadable() == false)
        Pkg.CurrentVer().Downloadable() == false)
       return;
       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
    /* We changed the soft state all the time so the UI is a bit nicer
       to use */
       to use */
    StateCache &P = PkgState[Pkg->ID];
    StateCache &P = PkgState[Pkg->ID];
+
+   // Check that it is not already kept
+   if (P.Mode == ModeKeep)
+      return;
+
    if (Soft == true)
    if (Soft == true)
       P.iFlags |= AutoKept;
       P.iFlags |= AutoKept;
    else
    else
       P.iFlags &= ~AutoKept;
       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 
 #if 0 // reseting the autoflag here means we lose the 
       // auto-mark information if a user selects a package for removal
       // auto-mark information if a user selects a package for removal
       // but changes  his mind then and sets it for keep again
       // 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,
 void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
                              unsigned long Depth, bool FromUser)
                              unsigned long Depth, bool FromUser)
 {
 {
-   // Simplifies other routines.
-   if (Pkg.end() == true)
+   if (IsModeChangeOk(ModeDelete, Pkg, Depth, FromUser) == false)
       return;
       return;
 
 
-   ActionGroup group(*this);
+   StateCache &P = PkgState[Pkg->ID];
 
 
    // Check that it is not already marked for delete
    // 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) && 
    if ((P.Mode == ModeDelete || P.InstallVer == 0) && 
        (Pkg.Purge() == true || rPurge == false))
        (Pkg.Purge() == true || rPurge == false))
       return;
       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)
    if (IsDeleteOk(Pkg,rPurge,Depth,FromUser) == false)
       return;
       return;
 
 
+   P.iFlags &= ~(AutoKept | Purge);
+   if (rPurge == true)
+      P.iFlags |= Purge;
+
+   ActionGroup group(*this);
+
    if (DebugMarker == true)
    if (DebugMarker == true)
       std::clog << OutputInDepth(Depth) << (rPurge ? "MarkPurge " : "MarkDelete ") << Pkg << " FU=" << FromUser << std::endl;
       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	/*{{{*/
 // 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,
 bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge,
 			      unsigned long Depth, bool FromUser)
 			      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];
       StateCache &P = PkgState[Pkg->ID];
       if (P.InstallVer != 0 && P.Status == 2 && (P.Flags & Flag::Auto) != Flag::Auto)
       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 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
+   Is<Mode>Ok 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;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -959,19 +984,17 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 			      unsigned long Depth, bool FromUser,
 			      unsigned long Depth, bool FromUser,
 			      bool ForceImportantDeps)
 			      bool ForceImportantDeps)
 {
 {
-   if (Depth > 100)
+   if (IsModeChangeOk(ModeInstall, Pkg, Depth, FromUser) == false)
       return;
       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;
       return;
-   
-   ActionGroup group(*this);
 
 
    /* Check that it is not already marked for install and that it can be 
    /* Check that it is not already marked for install and that it can be 
       installed */
       installed */
-   StateCache &P = PkgState[Pkg->ID];
-   P.iFlags &= ~AutoKept;
    if ((P.InstPolicyBroken() == false && P.InstBroken() == false) && 
    if ((P.InstPolicyBroken() == false && P.InstBroken() == false) && 
        (P.Mode == ModeInstall ||
        (P.Mode == ModeInstall ||
 	P.CandidateVer == (Version *)Pkg.CurrentVer()))
 	P.CandidateVer == (Version *)Pkg.CurrentVer()))
@@ -981,17 +1004,13 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
       return;
       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
    // check if we are allowed to install the package
    if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false)
    if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false)
       return;
       return;
 
 
+   ActionGroup group(*this);
+   P.iFlags &= ~AutoKept;
+
    /* Target the candidate version and remove the autoflag. We reset the
    /* Target the candidate version and remove the autoflag. We reset the
       autoflag below if this was called recursively. Otherwise the user
       autoflag below if this was called recursively. Otherwise the user
       should have the ability to de-auto a package by changing its state */
       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	/*{{{*/
 // 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,
 bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
 			      unsigned long Depth, bool FromUser)
 			      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;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 4 - 0
apt-pkg/depcache.h

@@ -486,6 +486,10 @@ class pkgDepCache : protected pkgCache::Namespace
    __deprecated bool RemovePseudoInstalledPkg(PkgIterator &Pkg, std::set<unsigned long> &recheck) { return true; };
    __deprecated bool RemovePseudoInstalledPkg(PkgIterator &Pkg, std::set<unsigned long> &recheck) { return true; };
    __deprecated bool ReInstallPseudoForGroup(unsigned long const &Grp, std::set<unsigned long> &recheck) { return true; };
    __deprecated bool ReInstallPseudoForGroup(unsigned long const &Grp, std::set<unsigned long> &recheck) { return true; };
    __deprecated bool ReInstallPseudoForGroup(pkgCache::PkgIterator const &P, std::set<unsigned long> &recheck) { return true; };
    __deprecated bool ReInstallPseudoForGroup(pkgCache::PkgIterator const &P, std::set<unsigned long> &recheck) { return true; };
+
+
+   bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
+			unsigned long const Depth, bool const FromUser);
 };
 };
 
 
 #endif
 #endif

+ 1 - 1
debian/changelog

@@ -6,7 +6,7 @@ apt (0.8.13.1) UNRELEASED; urgency=low
   * apt-pkg/vendor.cc, apt-pkg/vendorlist.cc:
   * apt-pkg/vendor.cc, apt-pkg/vendorlist.cc:
     - mark them as deprecated as they are unused
     - mark them as deprecated as they are unused
 
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Wed, 16 Mar 2011 21:23:32 +0100
+ -- David Kalnischkies <kalnischkies@gmail.com>  Sun, 20 Mar 2011 19:51:41 +0100
 
 
 apt (0.8.13) unstable; urgency=low
 apt (0.8.13) unstable; urgency=low
 
 

+ 1 - 1
test/integration/test-bug-549968-install-depends-of-not-installed

@@ -17,7 +17,7 @@ setupaptarchive
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
   MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1
   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
 Package extracoolstuff is not installed, so not removed
 The following NEW packages will be installed:
 The following NEW packages will be installed:
   coolstuff
   coolstuff