X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/a6bfe58397c488da3b4fff94b27f80e6b3dbdab2..5e972bffae68a75aafc9f9b639e82e252fde3b8b:/apt-pkg/algorithms.cc

diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index 0fcad42eb..479927d65 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: algorithms.cc,v 1.33 2001/03/23 07:53:19 jgg Exp $
+// $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 jgg Exp $
 /* ######################################################################
 
    Algorithms - A set of misc algorithms
@@ -24,8 +24,9 @@
     
 #include <apti18n.h>
     
-#include <iostream.h>
+#include <iostream>
 									/*}}}*/
+using namespace std;
 
 pkgProblemResolver *pkgProblemResolver::This = 0;
 
@@ -49,21 +50,29 @@ pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache),
 									/*}}}*/
 // Simulate::Describe - Describe a package				/*{{{*/
 // ---------------------------------------------------------------------
-/* */
-void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Now)
+/* Parameter Current == true displays the current package version,
+   Parameter Candidate == true displays the candidate package version */
+void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candidate)
 {
    VerIterator Ver(Sim);
-   if (Now == true)
+ 
+   out << Pkg.Name();
+
+   if (Current == true)
+   {
       Ver = Pkg.CurrentVer();
-   else
-      Ver = Sim[Pkg].CandidateVerIter(Sim);
+      if (Ver.end() == false)
+         out << " [" << Ver.VerStr() << ']';
+   }
 
-   out << Pkg.Name();
-   
-   if (Ver.end() == true)
-      return;
+   if (Candidate == true)
+   {
+      Ver = Sim[Pkg].CandidateVerIter(Sim);
+      if (Ver.end() == true)
+         return;
    
-   out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
+      out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
+   }
 }
 									/*}}}*/
 // Simulate::Install - Simulate unpacking of a package			/*{{{*/
@@ -76,7 +85,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
    Flags[Pkg->ID] = 1;
    
    cout << "Inst ";
-   Describe(Pkg,cout,false);
+   Describe(Pkg,cout,true,true);
    Sim.MarkInstall(Pkg,false);
    
    // Look for broken conflicts+predepends.
@@ -150,7 +159,7 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
    else
    {
       cout << "Conf "; 
-      Describe(Pkg,cout,false);
+      Describe(Pkg,cout,false,true);
    }
 
    if (Sim.BrokenCount() != 0)
@@ -175,7 +184,7 @@ bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
       cout << "Purg ";
    else
       cout << "Remv ";
-   Describe(Pkg,cout,false);
+   Describe(Pkg,cout,true,false);
 
    if (Sim.BrokenCount() != 0)
       ShortBreaks();
@@ -213,16 +222,20 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 {
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
+      if (I->VersionList == 0)
+	 continue;
+	 
       // Only choice for a ReInstReq package is to reinstall
       if (I->InstState == pkgCache::State::ReInstReq ||
 	  I->InstState == pkgCache::State::HoldReInstReq)
       {
-	 if (I.CurrentVer().Downloadable() == true)
+	 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
 	    Cache.MarkKeep(I);
 	 else
 	 {
 	    // Is this right? Will dpkg choke on an upgrade?
-	    if (Cache[I].CandidateVerIter(Cache).Downloadable() == true)
+	    if (Cache[I].CandidateVer != 0 &&
+		 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
 	       Cache.MarkInstall(I);
 	    else
 	       return _error->Error(_("The package %s needs to be reinstalled, "
@@ -238,12 +251,13 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 	    re-unpacked (probably) */
 	 case pkgCache::State::UnPacked:
 	 case pkgCache::State::HalfConfigured:
-	 if (I.CurrentVer().Downloadable() == true || 
+	 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
 	     I.State() != pkgCache::PkgIterator::NeedsUnpack)
 	    Cache.MarkKeep(I);
 	 else
 	 {
-	    if (Cache[I].CandidateVerIter(Cache).Downloadable() == true)
+	    if (Cache[I].CandidateVer != 0 &&
+		 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
 	       Cache.MarkInstall(I);
 	    else
 	       Cache.MarkDelete(I);
@@ -378,7 +392,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
    if (Cache.BrokenCount() != 0)
       return false;
    
-   // We loop indefinately to get the minimal set size.
+   // We loop for 10 tries to get the minimal set size.
    bool Change = false;
    unsigned int Count = 0;
    do
@@ -553,6 +567,8 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 {
    if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
       return false;
+   if ((Flags[Pkg->ID] & Protected) == Protected)
+      return false;
    
    Flags[Pkg->ID] &= ~Upgradable;
    
@@ -795,6 +811,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 			if (Debug == true)
 			   clog << "  Or group remove for " << I.Name() << endl;
 			Cache.MarkDelete(I);
+			Change = true;
 		     }		     
 		  }		  
 		  if (OldEnd == LEnd && OrOp == OrKeep)
@@ -802,6 +819,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		     if (Debug == true)
 			clog << "  Or group keep for " << I.Name() << endl;
 		     Cache.MarkKeep(I);
+		     Change = true;
 		  }
 	       }
 	       
@@ -812,21 +830,24 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       D.GlobOr(Start,End);
 	       if (Start.end() == true)
 		  break;
-	       
+
 	       // We only worry about critical deps.
 	       if (End.IsCritical() != true)
 		  continue;
-	       
+
 	       InOr = Start != End;
 	       OldEnd = LEnd;
-	    }	    
+	    }
 	    else
 	       Start++;
-	    
+
 	    // Dep is ok
 	    if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
+	    {
+	       InOr = false;
 	       continue;
-	    	    
+	    }
+	    
 	    if (Debug == true)
 	       clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
 
@@ -1094,18 +1115,10 @@ bool pkgProblemResolver::ResolveByKeep()
       // Isolate the problem dependencies
       for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
       {
-	 // Compute a single dependency element (glob or)
-	 pkgCache::DepIterator Start = D;
-	 pkgCache::DepIterator End = D;
-	 unsigned char State = 0;
-	 for (bool LastOR = true; D.end() == false && LastOR == true; D++)
-	 {
-	    State |= Cache[D];
-	    LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
-	    if (LastOR == true)
-	       End = D;
-	 }
-	 
+	 DepIterator Start;
+	 DepIterator End;
+	 D.GlobOr(Start,End);
+
 	 // We only worry about critical deps.
 	 if (End.IsCritical() != true)
 	    continue;
@@ -1113,42 +1126,47 @@ bool pkgProblemResolver::ResolveByKeep()
 	 // Dep is ok
 	 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
 	    continue;
-	 
-	 // Hm, the group is broken.. I have no idea how to handle this
-	 if (Start != End)
-	 {
-	    clog << "Note, a broken or group was found in " << I.Name() << "." << endl;
-	    if ((Flags[I->ID] & Protected) == 0)
-	       Cache.MarkKeep(I);
-	    break;
-	 }
-	 
-	 if (Debug == true)
-	    clog << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl;
-	 
-	 // Look at all the possible provides on this package
-	 SPtrArray<pkgCache::Version *> VList = End.AllTargets();
-	 for (pkgCache::Version **V = VList; *V != 0; V++)
+
+	 /* Hm, the group is broken.. I suppose the best thing to do is to
+	    is to try every combination of keep/not-keep for the set, but thats
+	    slow, and this never happens, just be conservative and assume the
+	    list of ors is in preference and keep till it starts to work. */
+	 while (true)
 	 {
-	    pkgCache::VerIterator Ver(Cache,*V);
-	    pkgCache::PkgIterator Pkg = Ver.ParentPkg();
-	    
-	    // It is not keepable
-	    if (Cache[Pkg].InstallVer == 0 || 
-		Pkg->CurrentVer == 0)
-	       continue;
+	    if (Debug == true)
+	       clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
 	    
-	    if ((Flags[I->ID] & Protected) == 0)
+	    // Look at all the possible provides on this package
+	    SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
+	    for (pkgCache::Version **V = VList; *V != 0; V++)
 	    {
-	       if (Debug == true)
-		  clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
-	       Cache.MarkKeep(Pkg);
+	       pkgCache::VerIterator Ver(Cache,*V);
+	       pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+	       
+	       // It is not keepable
+	       if (Cache[Pkg].InstallVer == 0 ||
+		   Pkg->CurrentVer == 0)
+		  continue;
+	       
+	       if ((Flags[I->ID] & Protected) == 0)
+	       {
+		  if (Debug == true)
+		     clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
+		  Cache.MarkKeep(Pkg);
+	       }
+	       
+	       if (Cache[I].InstBroken() == false)
+		  break;
 	    }
 	    
 	    if (Cache[I].InstBroken() == false)
 	       break;
-	 }
 
+	    if (Start == End)
+	       break;
+	    Start++;
+	 }
+	      
 	 if (Cache[I].InstBroken() == false)
 	    break;
       }
@@ -1195,14 +1213,14 @@ static int PrioComp(const void *A,const void *B)
    pkgCache::VerIterator R(*PrioCache,*(pkgCache::Version **)B);
    
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
-       (L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
-   return 1;
+       (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
+     return 1;
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
-       (L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-   return -1;
+       (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+     return -1;
    
    if (L->Priority != R->Priority)
-      return L->Priority - R->Priority;
+      return R->Priority - L->Priority;
    return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
 }
 void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)