]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/orderlist.cc
cherry pick from donkult
[apt.git] / apt-pkg / orderlist.cc
index 2e7618b5582f0d2f7e9c2ed564f33a7b1edcb913..19661fc2dfb7fc151b6e458d90620aeb3f6b2278 100644 (file)
@@ -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;
 
@@ -127,9 +128,6 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
    if (FileList[Pkg->ID].empty() == false)
       return false;
 
-   if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == true)
-      return false;
-
    return true;
 }
                                                                        /*}}}*/
@@ -203,7 +201,7 @@ bool pkgOrderList::OrderCritical()
       {
         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;
       }
    }
 
@@ -276,7 +274,7 @@ 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;
       }
    }
 
@@ -492,7 +490,7 @@ bool pkgOrderList::VisitRProvides(DepFunc F,VerIterator Ver)
    bool Res = true;
    for (PrvIterator P = Ver.ProvidesList(); P.end() == false; P++)
       Res &= (this->*F)(P.ParentPkg().RevDependsList());
-   return true;
+   return Res;
 }
                                                                        /*}}}*/
 // OrderList::VisitProvides - Visit all of the providing packages      /*{{{*/
@@ -509,15 +507,11 @@ bool pkgOrderList::VisitProvides(DepIterator D,bool Critical)
       if (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)
         continue;
       
-      if (D->Type != pkgCache::Dep::Conflicts &&
-         D->Type != pkgCache::Dep::DpkgBreaks &&
-         D->Type != pkgCache::Dep::Obsoletes &&
+      if (D.IsNegative() == false &&
          Cache[Pkg].InstallVer != *I)
         continue;
       
-      if ((D->Type == pkgCache::Dep::Conflicts ||
-          D->Type == pkgCache::Dep::DpkgBreaks ||
-          D->Type == pkgCache::Dep::Obsoletes) &&
+      if (D.IsNegative() == true &&
          (Version *)Pkg.CurrentVer() != *I)
         continue;
       
@@ -547,7 +541,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++;
@@ -606,7 +600,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;
@@ -649,9 +643,7 @@ bool pkgOrderList::DepUnPackCrit(DepIterator D)
       {
         /* Forward critical dependencies MUST be correct before the 
            package can be unpacked. */
-        if (D->Type != pkgCache::Dep::Conflicts &&
-            D->Type != pkgCache::Dep::DpkgBreaks &&
-            D->Type != pkgCache::Dep::Obsoletes &&
+        if (D.IsNegative() == false &&
             D->Type != pkgCache::Dep::PreDepends)
            continue;
                                 
@@ -884,13 +876,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 || 
@@ -901,6 +896,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;
@@ -982,10 +1071,14 @@ bool pkgOrderList::CheckDep(DepIterator D)
       
       /* Conflicts requires that all versions are not present, depends
          just needs one */
-      if (D->Type != pkgCache::Dep::Conflicts && 
-         D->Type != pkgCache::Dep::DpkgBreaks && 
-         D->Type != pkgCache::Dep::Obsoletes)
+      if (D.IsNegative() == false)
       {
+        // ignore provides by older versions of this package
+        if (((D.Reverse() == false && Pkg == D.ParentPkg()) ||
+             (D.Reverse() == true && Pkg == D.TargetPkg())) &&
+            Cache[Pkg].InstallVer != *I)
+           continue;
+
         /* Try to find something that does not have the after flag set
            if at all possible */
         if (IsFlag(Pkg,After) == true)