X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/ef1dff93202fa61e0b8cda761906bbca31e217bc..3c54407f8783d5e27363eabf41dbc3d031526ffe:/apt-pkg/orderlist.cc?ds=sidebyside

diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc
index 01b150722..a53854a26 100644
--- a/apt-pkg/orderlist.cc
+++ b/apt-pkg/orderlist.cc
@@ -117,7 +117,8 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
       return false;
 
    // Skip Packages that need configure only.
-   if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && 
+   if ((Pkg.State() == pkgCache::PkgIterator::NeedsConfigure ||
+        Pkg.State() == pkgCache::PkgIterator::NeedsNothing) &&
        Cache[Pkg].Keep() == true)
       return false;
 
@@ -126,6 +127,11 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
    
    if (FileList[Pkg->ID].empty() == false)
       return false;
+
+   // Missing Pseudo packages are missing if the real package is missing
+   if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == true)
+      return IsMissing(Pkg.Group().FindPkg("all"));
+
    return true;
 }
 									/*}}}*/
@@ -174,22 +180,35 @@ bool pkgOrderList::DoRun()
 bool pkgOrderList::OrderCritical()
 {
    FileList = 0;
-   
-   Primary = &pkgOrderList::DepUnPackPre;
+
+   Primary = &pkgOrderList::DepUnPackPreD;
    Secondary = 0;
    RevDepends = 0;
    Remove = 0;
    LoopCount = 0;
-   
+
    // Sort
    Me = this;
-   qsort(List,End - List,sizeof(*List),&OrderCompareB);   
-   
+   qsort(List,End - List,sizeof(*List),&OrderCompareB);
+
    if (DoRun() == false)
       return false;
-   
+
    if (LoopCount != 0)
       return _error->Error("Fatal, predepends looping detected");
+
+   if (Debug == true)
+   {
+      clog << "** Critical Unpack ordering done" << endl;
+
+      for (iterator I = List; I != End; I++)
+      {
+	 PkgIterator P(Cache,*I);
+	 if (IsNow(P) == true)
+	    clog << "  " << P.FullName() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
+      }
+   }
+
    return true;
 }
 									/*}}}*/
@@ -205,7 +224,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
    if (FileList != 0)
    {
       WipeFlags(After);
-      
+
       // Set the inlist flag
       for (iterator I = List; I != End; I++)
       {
@@ -214,7 +233,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
 	     Flag(*I,After);
       }
    }
-   
+
    Primary = &pkgOrderList::DepUnPackCrit;
    Secondary = &pkgOrderList::DepConfigure;
    RevDepends = &pkgOrderList::DepUnPackDep;
@@ -229,7 +248,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
       clog << "** Pass A" << endl;
    if (DoRun() == false)
       return false;
-   
+
    if (Debug == true)
       clog << "** Pass B" << endl;
    Secondary = 0;
@@ -243,7 +262,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
    Remove = 0;             // Otherwise the libreadline remove problem occures
    if (DoRun() == false)
       return false;
-      
+
    if (Debug == true)
       clog << "** Pass D" << endl;
    LoopCount = 0;
@@ -259,9 +278,9 @@ bool pkgOrderList::OrderUnpack(string *FileList)
       {
 	 PkgIterator P(Cache,*I);
 	 if (IsNow(P) == true)
-	    clog << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
+	    clog << "  " << P.FullName() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
       }
-   }   
+   }
 
    return true;
 }
@@ -286,29 +305,35 @@ bool pkgOrderList::OrderConfigure()
 /* Higher scores order earlier */
 int pkgOrderList::Score(PkgIterator Pkg)
 {
+   static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 500);
+
    // Removal is always done first
    if (Cache[Pkg].Delete() == true)
-      return 200;
-   
+      return ScoreDelete;
+
    // This should never happen..
    if (Cache[Pkg].InstVerIter(Cache).end() == true)
       return -1;
-   
+
+   static int const ScoreEssential = _config->FindI("OrderList::Score::Essential", 200);
+   static int const ScoreImmediate = _config->FindI("OrderList::Score::Immediate", 10);
+   static int const ScorePreDepends = _config->FindI("OrderList::Score::PreDepends", 50);
+
    int Score = 0;
    if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-      Score += 100;
+      Score += ScoreEssential;
 
    if (IsFlag(Pkg,Immediate) == true)
-      Score += 10;
-   
-   for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); 
+      Score += ScoreImmediate;
+
+   for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
 	D.end() == false; D++)
       if (D->Type == pkgCache::Dep::PreDepends)
       {
-	 Score += 50;
+	 Score += ScorePreDepends;
 	 break;
       }
-      
+
    // Important Required Standard Optional Extra
    signed short PrioMap[] = {0,5,4,3,1,0};
    if (Cache[Pkg].InstVerIter(Cache)->Priority <= 5)
@@ -386,6 +411,7 @@ int pkgOrderList::OrderCompareA(const void *a, const void *b)
    
    int ScoreA = Me->Score(A);
    int ScoreB = Me->Score(B);
+
    if (ScoreA > ScoreB)
       return -1;
    
@@ -422,6 +448,7 @@ int pkgOrderList::OrderCompareB(const void *a, const void *b)
    
    int ScoreA = Me->Score(A);
    int ScoreB = Me->Score(B);
+
    if (ScoreA > ScoreB)
       return -1;
    
@@ -522,7 +549,7 @@ bool pkgOrderList::VisitNode(PkgIterator Pkg)
    if (Debug == true)
    {
       for (int j = 0; j != Depth; j++) clog << ' ';
-      clog << "Visit " << Pkg.Name() << endl;
+      clog << "Visit " << Pkg.FullName() << endl;
    }
    
    Depth++;
@@ -581,7 +608,7 @@ bool pkgOrderList::VisitNode(PkgIterator Pkg)
    if (Debug == true)
    {
       for (int j = 0; j != Depth; j++) clog << ' ';
-      clog << "Leave " << Pkg.Name() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;
+      clog << "Leave " << Pkg.FullName() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;
    }
    
    return true;
@@ -859,13 +886,16 @@ bool pkgOrderList::DepRemove(DepIterator D)
 	    continue;
 
 	 /* We wish to see if the dep on the parent package is okay
-	    in the removed (install) state of the target pkg. */	 
+	    in the removed (install) state of the target pkg. */
+	 bool tryFixDeps = false;
 	 if (CheckDep(D) == true)
 	 {
 	    // We want to catch loops with the code below.
 	    if (IsFlag(D.ParentPkg(),AddPending) == false)
 	       continue;
 	 }
+	 else
+	    tryFixDeps = true;
 
 	 // This is the loop detection
 	 if (IsFlag(D.ParentPkg(),Added) == true || 
@@ -876,6 +906,100 @@ bool pkgOrderList::DepRemove(DepIterator D)
 	    continue;
 	 }
 
+	 if (tryFixDeps == true)
+	 {
+	    for (pkgCache::DepIterator F = D.ParentPkg().CurrentVer().DependsList();
+		 F.end() == false; ++F)
+	    {
+	       if (F->Type != pkgCache::Dep::Depends && F->Type != pkgCache::Dep::PreDepends)
+		  continue;
+	       // Check the Providers
+	       if (F.TargetPkg()->ProvidesList != 0)
+	       {
+		  pkgCache::PrvIterator Prov = F.TargetPkg().ProvidesList();
+		  for (; Prov.end() == false; ++Prov)
+		  {
+		     pkgCache::PkgIterator const P = Prov.OwnerPkg();
+		     if (IsFlag(P, InList) == true &&
+			 IsFlag(P, AddPending) == true &&
+			 IsFlag(P, Added) == false &&
+			 Cache[P].InstallVer == 0)
+			break;
+		  }
+		  if (Prov.end() == false)
+		     for (pkgCache::PrvIterator Prv = F.TargetPkg().ProvidesList();
+			  Prv.end() == false; ++Prv)
+		     {
+			pkgCache::PkgIterator const P = Prv.OwnerPkg();
+			if (IsFlag(P, InList) == true &&
+			    IsFlag(P, AddPending) == false &&
+			    Cache[P].InstallVer != 0 &&
+			    VisitNode(P) == true)
+			{
+			   Flag(P, Immediate);
+			   tryFixDeps = false;
+			   break;
+			}
+		     }
+		  if (tryFixDeps == false)
+		     break;
+	       }
+
+	       // Check for Or groups
+	       if ((F->CompareOp & pkgCache::Dep::Or) != pkgCache::Dep::Or)
+		  continue;
+	       // Lets see if the package is part of the Or group
+	       pkgCache::DepIterator S = F;
+	       for (; S.end() == false; ++S)
+	       {
+		  if (S.TargetPkg() == D.TargetPkg())
+		     break;
+		  if ((S->CompareOp & pkgCache::Dep::Or) != pkgCache::Dep::Or ||
+		      CheckDep(S)) // Or group is satisfied by another package
+		     for (;S.end() == false; ++S);
+	       }
+	       if (S.end() == true)
+		  continue;
+	       // skip to the end of the or group
+	       for (;S.end() == false && (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; ++S);
+	       ++S;
+	       // The soon to be removed is part of the Or group
+	       // start again in the or group and find something which will serve as replacement
+	       for (; F.end() == false && F != S; ++F)
+	       {
+		  if (IsFlag(F.TargetPkg(), InList) == true &&
+		      IsFlag(F.TargetPkg(), AddPending) == false &&
+		      Cache[F.TargetPkg()].InstallVer != 0 &&
+		      VisitNode(F.TargetPkg()) == true)
+		  {
+		     Flag(F.TargetPkg(), Immediate);
+		     tryFixDeps = false;
+		     break;
+		  }
+		  else if (F.TargetPkg()->ProvidesList != 0)
+		  {
+		     pkgCache::PrvIterator Prv = F.TargetPkg().ProvidesList();
+		     for (; Prv.end() == false; ++Prv)
+		     {
+			if (IsFlag(Prv.OwnerPkg(), InList) == true &&
+			    IsFlag(Prv.OwnerPkg(), AddPending) == false &&
+			    Cache[Prv.OwnerPkg()].InstallVer != 0 &&
+			    VisitNode(Prv.OwnerPkg()) == true)
+			{
+			   Flag(Prv.OwnerPkg(), Immediate);
+			   tryFixDeps = false;
+			   break;
+			}
+		     }
+		     if (Prv.end() == false)
+			break;
+		  }
+	       }
+	       if (tryFixDeps == false)
+		  break;
+	    }
+	 }
+
 	 // Skip over missing files
 	 if (IsMissing(D.ParentPkg()) == true)
 	    continue;