More fixes
[ntk/apt.git] / apt-pkg / orderlist.cc
index f79a063..fbd21d4 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: orderlist.cc,v 1.1 1998/07/07 04:17:01 jgg Exp $
+// $Id: orderlist.cc,v 1.10 2000/01/16 05:36:17 jgg Exp $
 /* ######################################################################
 
    Order List - Represents and Manipulates an ordered list of packages.
@@ -42,7 +42,7 @@
    arbitary priority to give quite abit of control over the final unpacking
    order.
 
-   The rules listed above my never be violated and are called Critical.
+   The rules listed above may never be violated and are called Critical.
    When a critical rule is violated then a loop condition is recorded
    and will have to be delt with in the caller.
    
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
 #ifdef __GNUG__
-#pragma implementation "pkglib/orderlist.h"
+#pragma implementation "apt-pkg/orderlist.h"
 #endif 
-#include <pkglib/orderlist.h>
-#include <pkglib/depcache.h>
-#include <pkglib/error.h>
-#include <pkglib/version.h>
+#include <apt-pkg/orderlist.h>
+#include <apt-pkg/depcache.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/version.h>
                                                                        /*}}}*/
 
 pkgOrderList *pkgOrderList::Me = 0;
@@ -65,6 +65,7 @@ pkgOrderList *pkgOrderList::Me = 0;
 /* */
 pkgOrderList::pkgOrderList(pkgDepCache &Cache) : Cache(Cache)
 {
+   FileList = 0;
    Primary = 0;
    Secondary = 0;
    RevDepends = 0;
@@ -88,12 +89,31 @@ pkgOrderList::~pkgOrderList()
    delete [] Flags;
 }
                                                                        /*}}}*/
+// OrderList::IsMissing - Check if a file is missing                   /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgOrderList::IsMissing(PkgIterator Pkg) 
+{
+   // Skip packages to erase
+   if (Cache[Pkg].Delete() == true)
+      return false;
+
+   // Skip Packages that need configure only.
+   if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && 
+       Cache[Pkg].Keep() == true)
+      return false;
+   
+   if (FileList != 0 && FileList[Pkg->ID].empty() == false)
+      return false;
+   return true;
+}
+                                                                       /*}}}*/
 
 // OrderList::DoRun - Does an order run                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* The caller is expeted to have setup the desired probe state */
 bool pkgOrderList::DoRun()
-{
+{   
    // Temp list
    unsigned long Size = Cache.HeaderP->PackageCount;
    Package **NList = new Package *[Size];
@@ -128,7 +148,9 @@ bool pkgOrderList::DoRun()
    fatal and indicate that the packages cannot be installed. */
 bool pkgOrderList::OrderCritical()
 {
-   Primary = &DepUnPackPre;
+   FileList = 0;
+   
+   Primary = &pkgOrderList::DepUnPackPre;
    Secondary = 0;
    RevDepends = 0;
    Remove = 0;
@@ -150,18 +172,20 @@ bool pkgOrderList::OrderCritical()
 // ---------------------------------------------------------------------
 /* This performs complete unpacking ordering and creates an order that is
    suitable for unpacking */
-bool pkgOrderList::OrderUnpack()
+bool pkgOrderList::OrderUnpack(string *FileList)
 {
-   Primary = &DepUnPackCrit;
-   Secondary = &DepConfigure;
-   RevDepends = &DepUnPackDep;
-   Remove = &DepRemove;
+   this->FileList = FileList;
+
+   Primary = &pkgOrderList::DepUnPackCrit;
+   Secondary = &pkgOrderList::DepConfigure;
+   RevDepends = &pkgOrderList::DepUnPackDep;
+   Remove = &pkgOrderList::DepRemove;
    LoopCount = -1;
 
    // Sort
    Me = this;
    qsort(List,End - List,sizeof(*List),&OrderCompareA);
-   
+
    if (DoRun() == false)
       return false;
    
@@ -176,7 +200,7 @@ bool pkgOrderList::OrderUnpack()
       return false;
 
    LoopCount = 0;
-   Primary = &DepUnPackPre;
+   Primary = &pkgOrderList::DepUnPackPre;
    if (DoRun() == false)
       return false;
 
@@ -185,7 +209,7 @@ bool pkgOrderList::OrderUnpack()
    for (iterator I = List; I != End; I++)
    {
       PkgIterator P(Cache,*I);
-      cout << P.Name() << endl;
+      cout << P.Name() << ' ' << IsMissing(P) << endl;
    }*/
 
    return true;
@@ -197,7 +221,8 @@ bool pkgOrderList::OrderUnpack()
    for configuration */
 bool pkgOrderList::OrderConfigure()
 {
-   Primary = &DepConfigure;
+   FileList = 0;
+   Primary = &pkgOrderList::DepConfigure;
    Secondary = 0;
    RevDepends = 0;
    Remove = 0;
@@ -214,7 +239,11 @@ int pkgOrderList::Score(PkgIterator Pkg)
    // Removal is always done first
    if (Cache[Pkg].Delete() == true)
       return 200;
-
+   
+   // This should never happen..
+   if (Cache[Pkg].InstVerIter(Cache).end() == true)
+      return -1;
+   
    int Score = 0;
    if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
       Score += 100;
@@ -248,7 +277,7 @@ int pkgOrderList::FileCmp(PkgIterator A,PkgIterator B)
    
    if (Cache[A].InstVerIter(Cache).FileList().end() == true)
       return -1;
-   if (Cache[A].InstVerIter(Cache).FileList().end() == true)
+   if (Cache[B].InstVerIter(Cache).FileList().end() == true)
       return 1;
    
    pkgCache::PackageFile *FA = Cache[A].InstVerIter(Cache).FileList().File();
@@ -260,6 +289,18 @@ int pkgOrderList::FileCmp(PkgIterator A,PkgIterator B)
    return 0;
 }
                                                                        /*}}}*/
+// BoolCompare - Comparison function for two booleans                  /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static int BoolCompare(bool A,bool B)
+{
+   if (A == B)
+      return 0;
+   if (A == false)
+      return -1;
+   return 1;
+}
+                                                                       /*}}}*/
 // OrderList::OrderCompareA - Order the installation by op             /*{{{*/
 // ---------------------------------------------------------------------
 /* This provides a first-pass sort of the list and gives a decent starting
@@ -269,6 +310,19 @@ int pkgOrderList::OrderCompareA(const void *a, const void *b)
    PkgIterator A(Me->Cache,*(Package **)a);
    PkgIterator B(Me->Cache,*(Package **)b);
 
+   // We order packages with a set state toward the front
+   int Res;
+   if ((Res = BoolCompare(Me->IsNow(A),Me->IsNow(B))) != 0)
+      return -1*Res;
+   
+   // We order missing files to toward the end
+   if (Me->FileList != 0)
+   {
+      if ((Res = BoolCompare(Me->IsMissing(A),
+                            Me->IsMissing(B))) != 0)
+        return Res;
+   }
+   
    if (A.State() != pkgCache::PkgIterator::NeedsNothing && 
        B.State() == pkgCache::PkgIterator::NeedsNothing)
       return -1;
@@ -367,15 +421,15 @@ bool pkgOrderList::VisitRProvides(DepFunc F,VerIterator Ver)
 // OrderList::VisitProvides - Visit all of the providing packages      /*{{{*/
 // ---------------------------------------------------------------------
 /* This routine calls visit on all providing packages. */
-bool pkgOrderList::VisitProvides(DepIterator D)
-{
+bool pkgOrderList::VisitProvides(DepIterator D,bool Critical)
+{   
    Version **List = D.AllTargets();
    for (Version **I = List; *I != 0; I++)
    {
       VerIterator Ver(Cache,*I);
       PkgIterator Pkg = Ver.ParentPkg();
-      
-      if (Cache[Pkg].Keep() == true)
+
+      if (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)
         continue;
       
       if (D->Type != pkgCache::Dep::Conflicts && Cache[Pkg].InstallVer != *I)
@@ -384,6 +438,10 @@ bool pkgOrderList::VisitProvides(DepIterator D)
       if (D->Type == pkgCache::Dep::Conflicts && (Version *)Pkg.CurrentVer() != *I)
         continue;
       
+      // Skip over missing files
+      if (Critical == false && IsMissing(D.ParentPkg()) == true)
+        continue;
+
       if (VisitNode(Pkg) == false)
       {
         delete [] List;
@@ -402,6 +460,7 @@ bool pkgOrderList::VisitProvides(DepIterator D)
 bool pkgOrderList::VisitNode(PkgIterator Pkg)
 {
    // Looping or irrelevent.
+   // This should probably trancend not installed packages
    if (Pkg.end() == true || IsFlag(Pkg,Added) == true || 
        IsFlag(Pkg,AddPending) == true || IsFlag(Pkg,InList) == false)
       return true;
@@ -416,36 +475,39 @@ bool pkgOrderList::VisitNode(PkgIterator Pkg)
    DepFunc Old = Primary;
    
    // Perform immedate configuration of the package if so flagged.
-   if (IsFlag(Pkg,Immediate) == true && Primary != &DepUnPackPre)
-      Primary = &DepUnPackPreD;
-      
-   bool Res = true;
-   if (Cache[Pkg].Delete() == false)
+   if (IsFlag(Pkg,Immediate) == true && Primary != &pkgOrderList::DepUnPackPre)
+      Primary = &pkgOrderList::DepUnPackPreD;
+
+   if (IsNow(Pkg) == true)
    {
-      // Primary
-      Res &= Res && VisitDeps(Primary,Pkg);
-      Res &= Res && VisitRDeps(Primary,Pkg);
-      Res &= Res && VisitRProvides(Primary,Pkg.CurrentVer());
-      Res &= Res && VisitRProvides(Primary,Cache[Pkg].InstVerIter(Cache));
-      
-      // RevDep
-      Res &= Res && VisitRDeps(RevDepends,Pkg);
-      Res &= Res && VisitRProvides(RevDepends,Pkg.CurrentVer());
-      Res &= Res && VisitRProvides(RevDepends,Cache[Pkg].InstVerIter(Cache));
-       
-      // Secondary
-      Res &= Res && VisitDeps(Secondary,Pkg);
-      Res &= Res && VisitRDeps(Secondary,Pkg);
-      Res &= Res && VisitRProvides(Secondary,Pkg.CurrentVer());
-      Res &= Res && VisitRProvides(Secondary,Cache[Pkg].InstVerIter(Cache));
-   }
-   else
-   { 
-      // RevDep
-      Res &= Res && VisitRDeps(Remove,Pkg);
-      Res &= Res && VisitRProvides(Remove,Pkg.CurrentVer());
+      bool Res = true;
+      if (Cache[Pkg].Delete() == false)
+      {
+        // Primary
+        Res &= Res && VisitDeps(Primary,Pkg);
+        Res &= Res && VisitRDeps(Primary,Pkg);
+        Res &= Res && VisitRProvides(Primary,Pkg.CurrentVer());
+        Res &= Res && VisitRProvides(Primary,Cache[Pkg].InstVerIter(Cache));
+        
+        // RevDep
+        Res &= Res && VisitRDeps(RevDepends,Pkg);
+        Res &= Res && VisitRProvides(RevDepends,Pkg.CurrentVer());
+        Res &= Res && VisitRProvides(RevDepends,Cache[Pkg].InstVerIter(Cache));
+        
+        // Secondary
+        Res &= Res && VisitDeps(Secondary,Pkg);
+        Res &= Res && VisitRDeps(Secondary,Pkg);
+        Res &= Res && VisitRProvides(Secondary,Pkg.CurrentVer());
+        Res &= Res && VisitRProvides(Secondary,Cache[Pkg].InstVerIter(Cache));
+      }
+      else
+      { 
+        // RevDep
+        Res &= Res && VisitRDeps(Remove,Pkg);
+        Res &= Res && VisitRProvides(Remove,Pkg.CurrentVer());
+      }
    }
-
+   
    if (IsFlag(Pkg,Added) == false)
    {
       Flag(Pkg,Added,Added | AddPending);
@@ -527,8 +589,8 @@ bool pkgOrderList::DepUnPackCrit(DepIterator D)
         DepFunc Old = Primary;
         bool Res = false;
         if (D->Type == pkgCache::Dep::PreDepends)
-           Primary = &DepUnPackPreD;
-        Res = VisitProvides(D);
+           Primary = &pkgOrderList::DepUnPackPreD;
+        Res = VisitProvides(D,true);
         Primary = Old;
         if (Res == false)
            return false;
@@ -574,7 +636,7 @@ bool pkgOrderList::DepUnPackPreD(DepIterator D)
         continue;
       }
       
-      if (VisitProvides(D) == false)
+      if (VisitProvides(D,true) == false)
         return false;
    }   
    return true;
@@ -627,7 +689,7 @@ bool pkgOrderList::DepUnPackPre(DepIterator D)
         continue;
       }
       
-      if (VisitProvides(D) == false)
+      if (VisitProvides(D,true) == false)
         return false;
    }   
    return true;
@@ -663,12 +725,16 @@ bool pkgOrderList::DepUnPackDep(DepIterator D)
            if (CheckDep(D) == true)
               continue;
            
+           // Skip over missing files
+           if (IsMissing(D.ParentPkg()) == true)
+              continue;
+           
            if (VisitNode(D.ParentPkg()) == false)
               return false;
         }
         else
            if (D->Type == pkgCache::Dep::Depends)
-              if (VisitProvides(D) == false)
+              if (VisitProvides(D,false) == false)
                  return false;
       }
    return true;
@@ -689,7 +755,7 @@ bool pkgOrderList::DepConfigure(DepIterator D)
    
    for (; D.end() == false; D++)
       if (D->Type == pkgCache::Dep::Depends)
-        if (VisitProvides(D) == false)
+        if (VisitProvides(D,false) == false)
            return false;
    return true;
 }
@@ -734,6 +800,10 @@ bool pkgOrderList::DepRemove(DepIterator D)
            continue;
         }
 
+        // Skip over missing files
+        if (IsMissing(D.ParentPkg()) == true)
+           continue;
+        
         if (VisitNode(D.ParentPkg()) == false)
            return false;
       }