]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/depcache.cc
* apt-pkg/algorithms.cc:
[apt.git] / apt-pkg / depcache.cc
index 27b6134b4dfc22c9c8b1a65ed84807be0bcf5485..15d7bac4397c8c8b3ace996a04673184e8dcbe31 100644 (file)
@@ -273,7 +273,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
       we allow it anyhow because dpkg does. Technically it is a packaging
       bug. Conflicts may never self match */
    if (Dep.TargetPkg() != Dep.ParentPkg() || 
       we allow it anyhow because dpkg does. Technically it is a packaging
       bug. Conflicts may never self match */
    if (Dep.TargetPkg() != Dep.ParentPkg() || 
-       (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
+       (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
    {
       PkgIterator Pkg = Dep.TargetPkg();
       // Check the base package
    {
       PkgIterator Pkg = Dep.TargetPkg();
       // Check the base package
@@ -303,7 +303,8 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
    {
       /* Provides may never be applied against the same package if it is
          a conflicts. See the comment above. */
    {
       /* Provides may never be applied against the same package if it is
          a conflicts. See the comment above. */
-      if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
+      if (P.OwnerPkg() == Pkg &&
+         (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
         continue;
       
       // Check if the provides is a hit
         continue;
       
       // Check if the provides is a hit
@@ -399,9 +400,11 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
 {
    StateCache &State = PkgState[Pkg->ID];
    
 {
    StateCache &State = PkgState[Pkg->ID];
    
-   // The Package is broken
+   // The Package is broken (either minimal dep or policy dep)
    if ((State.DepState & DepInstMin) != DepInstMin)
       iBrokenCount += Add;
    if ((State.DepState & DepInstMin) != DepInstMin)
       iBrokenCount += Add;
+   if ((State.DepState & DepInstPolicy) != DepInstPolicy)
+      iPolicyBrokenCount += Add;
    
    // Bad state
    if (Pkg.State() != PkgIterator::NeedsNothing)
    
    // Bad state
    if (Pkg.State() != PkgIterator::NeedsNothing)
@@ -455,7 +458,9 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V)
 
       /* Invert for Conflicts. We have to do this twice to get the
          right sense for a conflicts group */
 
       /* Invert for Conflicts. We have to do this twice to get the
          right sense for a conflicts group */
-      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+      if (D->Type == Dep::Conflicts ||
+         D->Type == Dep::DpkgBreaks ||
+         D->Type == Dep::Obsoletes)
         State = ~State;
       
       // Add to the group if we are within an or..
         State = ~State;
       
       // Add to the group if we are within an or..
@@ -466,7 +471,9 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V)
         Group = 0;
       
       // Invert for Conflicts
         Group = 0;
       
       // Invert for Conflicts
-      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+      if (D->Type == Dep::Conflicts ||
+         D->Type == Dep::DpkgBreaks ||
+         D->Type == Dep::Obsoletes)
         State = ~State;
    }    
 }
         State = ~State;
    }    
 }
@@ -599,7 +606,9 @@ void pkgDepCache::Update(OpProgress *Prog)
               Group = 0;
 
            // Invert for Conflicts
               Group = 0;
 
            // Invert for Conflicts
-           if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+           if (D->Type == Dep::Conflicts ||
+               D->Type == Dep::DpkgBreaks ||
+               D->Type == Dep::Obsoletes)
               State = ~State;
         }       
       }
               State = ~State;
         }       
       }
@@ -629,7 +638,9 @@ void pkgDepCache::Update(DepIterator D)
       State = DependencyState(D);
     
       // Invert for Conflicts
       State = DependencyState(D);
     
       // Invert for Conflicts
-      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+      if (D->Type == Dep::Conflicts ||
+         D->Type == Dep::DpkgBreaks ||
+         D->Type == Dep::Obsoletes)
         State = ~State;
 
       RemoveStates(D.ParentPkg());
         State = ~State;
 
       RemoveStates(D.ParentPkg());
@@ -763,7 +774,8 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
 // ---------------------------------------------------------------------
 /* */
 void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 // ---------------------------------------------------------------------
 /* */
 void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
-                             unsigned long Depth, bool FromUser)
+                             unsigned long Depth, bool FromUser,
+                             bool ForceImportantDeps)
 {
    if (Depth > 100)
       return;
 {
    if (Depth > 100)
       return;
@@ -846,36 +858,43 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 
       /* Check if this dep should be consider for install. If it is a user
          defined important dep and we are installed a new package then 
 
       /* Check if this dep should be consider for install. If it is a user
          defined important dep and we are installed a new package then 
-        it will be installed. Otherwise we only worry about critical deps */
+        it will be installed. Otherwise we only check for important
+         deps that have changed from the installed version
+      */
       if (IsImportantDep(Start) == false)
         continue;
       if (IsImportantDep(Start) == false)
         continue;
-
+      
       /* check if any ImportantDep() (but not Critial) where added
       /* check if any ImportantDep() (but not Critial) where added
-       * since we installed the thing
+       * since we installed the package
        */
       bool isNewImportantDep = false;
        */
       bool isNewImportantDep = false;
-      if(IsImportantDep(Start) && !Start.IsCritical())
+      if(!ForceImportantDeps && !Start.IsCritical())
       {
         bool found=false;
         VerIterator instVer = Pkg.CurrentVer();
       {
         bool found=false;
         VerIterator instVer = Pkg.CurrentVer();
-        for (DepIterator D = instVer.DependsList(); !D.end(); D++)
+        if(!instVer.end())
         {
         {
-           //FIXME: deal better with or-groups(?)
-           DepIterator LocalStart = D;
-           
-           if(IsImportantDep(Dep) && Start.TargetPkg() == D.TargetPkg())
-              found=true;
+           for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
+           {
+              //FIXME: deal better with or-groups(?)
+              DepIterator LocalStart = D;
+              
+              if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
+                 found=true;
+           }
+           // this is a new dep if it was not found to be already
+           // a important dep of the installed pacakge
+           isNewImportantDep = !found;
         }
         }
-        // this is a new dep if it was not found to be already
-        // a important dep of the installed pacakge
-        isNewImportantDep = !found;
       }
       if(isNewImportantDep)
         if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
            std::clog << "new important dependency: " 
                      << Start.TargetPkg().Name() << std::endl;
 
       }
       if(isNewImportantDep)
         if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
            std::clog << "new important dependency: " 
                      << Start.TargetPkg().Name() << std::endl;
 
-      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false && !isNewImportantDep)
+      // skip important deps if the package is already installed
+      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
+         && !isNewImportantDep && !ForceImportantDeps)
         continue;
       
       /* If we are in an or group locate the first or that can 
         continue;
       
       /* If we are in an or group locate the first or that can 
@@ -886,7 +905,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
       /* This bit is for processing the possibilty of an install/upgrade
          fixing the problem */
       SPtrArray<Version *> List = Start.AllTargets();
       /* This bit is for processing the possibilty of an install/upgrade
          fixing the problem */
       SPtrArray<Version *> List = Start.AllTargets();
-      if ((DepState[Start->ID] & DepCVer) == DepCVer)
+      if (Start->Type != Dep::DpkgBreaks &&
+         (DepState[Start->ID] & DepCVer) == DepCVer)
       {
         // Right, find the best version to install..
         Version **Cur = List;
       {
         // Right, find the best version to install..
         Version **Cur = List;
@@ -923,21 +943,31 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
               std::clog << "Installing " << InstPkg.Name() 
                         << " as dep of " << Pkg.Name() 
                         << std::endl;
               std::clog << "Installing " << InstPkg.Name() 
                         << " as dep of " << Pkg.Name() 
                         << std::endl;
-          MarkInstall(InstPkg, true, Depth + 1, false);
+           MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
+
+           // Set the autoflag, after MarkInstall because MarkInstall unsets it
+           if (P->CurrentVer == 0)
+              PkgState[InstPkg->ID].Flags |= Flag::Auto;
         }
         continue;
       }
         }
         continue;
       }
-      
+
       /* For conflicts we just de-install the package and mark as auto,
       /* For conflicts we just de-install the package and mark as auto,
-         Conflicts may not have or groups */
-      if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
+         Conflicts may not have or groups.  For dpkg's Breaks we try to
+         upgrade the package. */
+      if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
+         Start->Type == Dep::DpkgBreaks)
       {
         for (Version **I = List; *I != 0; I++)
         {
            VerIterator Ver(*this,*I);
            PkgIterator Pkg = Ver.ParentPkg();
       {
         for (Version **I = List; *I != 0; I++)
         {
            VerIterator Ver(*this,*I);
            PkgIterator Pkg = Ver.ParentPkg();
-      
-           MarkDelete(Pkg);
+
+           if (Start->Type != Dep::DpkgBreaks)
+              MarkDelete(Pkg);
+           else
+              if (PkgState[Pkg->ID].CandidateVer != *I)
+                 MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
         }
         continue;
       }      
         }
         continue;
       }      
@@ -1302,8 +1332,22 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
 {
    if(Dep.IsCritical())
       return true;
 {
    if(Dep.IsCritical())
       return true;
-   else if(Dep->Type == pkgCache::Dep::Recommends)
-      return  _config->FindB("APT::Install-Recommends", false);
+   else if(Dep->Type == pkgCache::Dep::Recommends) 
+   {
+      if ( _config->FindB("APT::Install-Recommends", false))
+        return true;
+      // we suport a special mode to only install-recommends for certain
+      // sections
+      // FIXME: this is a meant as a temporarly solution until the 
+      //        recommends are cleaned up
+      string s = _config->Find("APT::Install-Recommends-Section","");
+      if(s.size() > 0) 
+      {
+        const char *sec = Dep.ParentVer().Section();
+        if (sec && strcmp(sec, s.c_str()) == 0)
+           return true;
+      }
+   }
    else if(Dep->Type == pkgCache::Dep::Suggests)
      return _config->FindB("APT::Install-Suggests", false);
 
    else if(Dep->Type == pkgCache::Dep::Suggests)
      return _config->FindB("APT::Install-Suggests", false);