]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/depcache.cc
fix priority sorting by prefering higher in MarkInstall
[apt.git] / apt-pkg / depcache.cc
index 9449c73066e4f61996163f67ef94b1fa802c91ca..5ca0c2ea5cb957f2ef98bb263198604767f0a572 100644 (file)
@@ -346,23 +346,20 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
    /* Check simple depends. A depends -should- never self match but 
       we allow it anyhow because dpkg does. Technically it is a packaging
       bug. Conflicts may never self match */
-   if (Dep.TargetPkg() != Dep.ParentPkg() || Dep.IsNegative() == false)
+   if (Dep.IsIgnorable(Res) == false)
    {
       PkgIterator Pkg = Dep.TargetPkg();
       // Check the base package
       if (Type == NowVersion && Pkg->CurrentVer != 0)
-        if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp,
-                                Dep.TargetVer()) == true)
+        if (Dep.IsSatisfied(Pkg.CurrentVer()) == true)
            return true;
       
       if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
-        if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
-                                Dep->CompareOp,Dep.TargetVer()) == true)
+        if (Dep.IsSatisfied(PkgState[Pkg->ID].InstVerIter(*this)) == true)
            return true;
       
       if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
-        if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
-                                Dep->CompareOp,Dep.TargetVer()) == true)
+        if (Dep.IsSatisfied(PkgState[Pkg->ID].CandidateVerIter(*this)) == true)
            return true;
    }
    
@@ -398,7 +395,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
       }
       
       // Compare the versions.
-      if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true)
+      if (Dep.IsSatisfied(P) == true)
       {
         Res = P.OwnerPkg();
         return true;
@@ -913,11 +910,15 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
       return true;
 
    StateCache &P = PkgState[Pkg->ID];
+   // not changing the mode is obviously also fine as we might want to call
+   // e.g. MarkInstall multiple times with different arguments for the same package
+   if (P.Mode == mode)
+      return true;
 
    // if previous state was set by user only user can reset it
    if ((P.iFlags & Protected) == Protected)
    {
-      if (unlikely(DebugMarker == true) && P.Mode != mode)
+      if (unlikely(DebugMarker == true))
         std::clog << OutputInDepth(Depth) << "Ignore Mark" << PrintMode(mode)
                   << " of " << Pkg << " as its mode (" << PrintMode(P.Mode)
                   << ") is protected" << std::endl;
@@ -927,7 +928,7 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
    else if (mode != ModeKeep && Pkg->SelectedState == pkgCache::State::Hold &&
            _config->FindB("APT::Ignore-Hold",false) == false)
    {
-      if (unlikely(DebugMarker == true) && P.Mode != mode)
+      if (unlikely(DebugMarker == true))
         std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode)
                   << " of " << Pkg << std::endl;
       return false;
@@ -947,6 +948,37 @@ struct CompareProviders {
    {
       pkgCache::PkgIterator const A = AV.ParentPkg();
       pkgCache::PkgIterator const B = BV.ParentPkg();
+      // Prefer MA:same packages if other architectures for it are installed
+      if ((AV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same ||
+         (BV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
+      {
+        bool instA = false;
+        if ((AV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
+        {
+           pkgCache::GrpIterator Grp = A.Group();
+           for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P))
+              if (P->CurrentVer != 0)
+              {
+                 instA = true;
+                 break;
+              }
+        }
+        bool instB = false;
+        if ((BV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
+        {
+           pkgCache::GrpIterator Grp = B.Group();
+           for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P))
+           {
+              if (P->CurrentVer != 0)
+              {
+                 instB = true;
+                 break;
+              }
+           }
+        }
+        if (instA != instB)
+           return instA == false;
+      }
       // Prefer packages in the same group as the target; e.g. foo:i386, foo:amd64
       if (A->Group != B->Group)
       {
@@ -963,9 +995,16 @@ struct CompareProviders {
         else if ((B->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
            return true;
       }
+      if ((A->Flags & pkgCache::Flag::Important) != (B->Flags & pkgCache::Flag::Important))
+      {
+        if ((A->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
+           return false;
+        else if ((B->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
+           return true;
+      }
       // higher priority seems like a good idea
       if (AV->Priority != BV->Priority)
-        return AV->Priority < BV->Priority;
+        return AV->Priority > BV->Priority;
       // prefer native architecture
       if (strcmp(A.Arch(), B.Arch()) != 0)
       {
@@ -1145,20 +1184,18 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
       }
 
       /* This bit is for processing the possibilty of an install/upgrade
-         fixing the problem */
-      if (Start->Type != Dep::DpkgBreaks &&
-         (DepState[Start->ID] & DepCVer) == DepCVer)
+         fixing the problem for "positive" dependencies */
+      if (Start.IsNegative() == false && (DepState[Start->ID] & DepCVer) == DepCVer)
       {
         APT::VersionList verlist;
         pkgCache::VerIterator Cand = PkgState[Start.TargetPkg()->ID].CandidateVerIter(*this);
-        if (Cand.end() == false && VS().CheckDep(Cand.VerStr(), Start->CompareOp, Start.TargetVer()) == true)
+        if (Cand.end() == false && Start.IsSatisfied(Cand) == true)
            verlist.insert(Cand);
         for (PrvIterator Prv = Start.TargetPkg().ProvidesList(); Prv.end() != true; ++Prv)
         {
            pkgCache::VerIterator V = Prv.OwnerVer();
            pkgCache::VerIterator Cand = PkgState[Prv.OwnerPkg()->ID].CandidateVerIter(*this);
-           if (Cand.end() == true || V != Cand ||
-               VS().CheckDep(Cand.VerStr(), Start->CompareOp, Start.TargetVer()) == false)
+           if (Cand.end() == true || V != Cand || Start.IsSatisfied(Prv) == false)
               continue;
            verlist.insert(Cand);
         }
@@ -1172,32 +1209,25 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
               std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
                         << " as " << Start.DepType() << " of " << Pkg.Name()
                         << std::endl;
-           // now check if we should consider it a automatic dependency or not
-           if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
-           {
+           MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps);
+           // now check if we should consider it a automatic dependency or not
+           if(InstPkg->CurrentVer == 0 && Pkg->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
+           {
               if(DebugAutoInstall == true)
                  std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct "
                             << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
-              MarkInstall(InstPkg,true,Depth + 1, true);
-           }
-           else 
-           {
-              // mark automatic dependency
-              MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
-              // Set the autoflag, after MarkInstall because MarkInstall unsets it
-              if (InstPkg->CurrentVer == 0)
-                 PkgState[InstPkg->ID].Flags |= Flag::Auto;
-           }
+              MarkAuto(InstPkg, false);
+           }
         }
         continue;
       }
-
-      /* For conflicts we just de-install the package and mark as auto,
-         Conflicts may not have or groups.  For dpkg's Breaks we try to
-         upgrade the package. */
-      if (Start.IsNegative() == true)
+      /* Negative dependencies have no or-group
+        If the dependency isn't versioned, we try if an upgrade might solve the problem.
+        Otherwise we remove the offender if needed */
+      else if (Start.IsNegative() == true && Start->Type != pkgCache::Dep::Obsoletes)
       {
         SPtrArray<Version *> List = Start.AllTargets();
+        pkgCache::PkgIterator TrgPkg = Start.TargetPkg();
         for (Version **I = List; *I != 0; I++)
         {
            VerIterator Ver(*this,*I);
@@ -1208,15 +1238,17 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
            if (PkgState[Pkg->ID].InstallVer == 0)
               continue;
 
-           if (PkgState[Pkg->ID].CandidateVer != *I &&
-               Start->Type == Dep::DpkgBreaks &&
+           if ((Start->Version != 0 || TrgPkg != Pkg) &&
+               PkgState[Pkg->ID].CandidateVer != PkgState[Pkg->ID].InstallVer &&
+               PkgState[Pkg->ID].CandidateVer != *I &&
                MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps) == true)
               continue;
-           else if (MarkDelete(Pkg,false,Depth + 1, false) == false)
+           else if ((Start->Type == pkgCache::Dep::Conflicts || Start->Type == pkgCache::Dep::DpkgBreaks) &&
+                    MarkDelete(Pkg,false,Depth + 1, false) == false)
               break;
         }
         continue;
-      }      
+      }
    }
 
    return Dep.end() == true;
@@ -1371,7 +1403,7 @@ bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer,
         if (Cand.end() == true)
            continue;
         // check if the current candidate is enough for the versioned dependency - and installable?
-        if (VS().CheckDep(P.CandVersion(), Start->CompareOp, Start.TargetVer()) == true &&
+        if (Start.IsSatisfied(Cand) == true &&
             (VersionState(Cand.DependsList(), DepInstall, DepCandMin, DepCandPolicy) & DepCandMin) == DepCandMin)
         {
            itsFine = true;
@@ -1405,7 +1437,7 @@ bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer,
            V = Match.Find(D.TargetPkg());
 
         // check if the version from this release could satisfy the dependency
-        if (V.end() == true || VS().CheckDep(V.VerStr(), D->CompareOp, D.TargetVer()) == false)
+        if (V.end() == true || D.IsSatisfied(V) == false)
         {
            if (stillOr == true)
               continue;
@@ -1641,6 +1673,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
    {
       if(!(PkgState[p->ID].Flags & Flag::Auto) ||
          (p->Flags & Flag::Essential) ||
+         (p->Flags & Flag::Important) ||
          userFunc.InRootSet(p) ||
          // be nice even then a required package violates the policy (#583517)
          // and do the full mark process also for required packages
@@ -1734,7 +1767,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
           for(VerIterator V = d.TargetPkg().VersionList(); 
               !V.end(); ++V)
           {
-             if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
+             if(d.IsSatisfied(V))
              {
                if(debug_autoremove)
                  {
@@ -1756,8 +1789,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
           for(PrvIterator prv=d.TargetPkg().ProvidesList(); 
               !prv.end(); ++prv)
           {
-             if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
-                                      d.TargetVer()))
+             if(d.IsSatisfied(prv))
              {
                if(debug_autoremove)
                  {