Added instruction how to work around MMap error in MMap error message.
[ntk/apt.git] / apt-pkg / depcache.cc
index 7f57194..2411bfe 100644 (file)
 
 #include <apti18n.h>    
 
+// helper for Install-Recommends-Sections and Never-MarkAuto-Sections
+static bool 
+ConfigValueInSubTree(const char* SubTree, const char *needle)
+{
+   Configuration::Item const *Opts;
+   Opts = _config->Tree(SubTree);
+   if (Opts != 0 && Opts->Child != 0)
+   {
+      Opts = Opts->Child;
+      for (; Opts != 0; Opts = Opts->Next)
+      {
+        if (Opts->Value.empty() == true)
+           continue;
+        if (strcmp(needle, Opts->Value.c_str()) == 0)
+           return true;
+      }
+   }
+   return false;
+}
+
+
 pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
   cache(cache), released(false)
 {
@@ -248,7 +269,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
         ostr.str(string(""));
         ostr << "Package: " << pkg.Name() 
              << "\nAuto-Installed: 1\n\n";
-        fprintf(OutFile,ostr.str().c_str());
+        fprintf(OutFile,"%s",ostr.str().c_str());
         fprintf(OutFile,"\n");
       }
    }
@@ -874,24 +895,42 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
       if (IsImportantDep(Start) == false)
         continue;
       
-      /* check if any ImportantDep() (but not Critial) where added
-       * since we installed the package
+      /* Check if any ImportantDep() (but not Critical) were added
+       * since we installed the package.  Also check for deps that
+       * were satisfied in the past: for instance, if a version
+       * restriction in a Recommends was tightened, upgrading the
+       * package should follow that Recommends rather than causing the
+       * dependency to be removed. (bug #470115)
        */
       bool isNewImportantDep = false;
+      bool isPreviouslySatisfiedImportantDep = false;
       if(!ForceImportantDeps && !Start.IsCritical())
       {
         bool found=false;
         VerIterator instVer = Pkg.CurrentVer();
         if(!instVer.end())
         {
-           for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
-           {
+          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;
-           }
+
+              if(IsImportantDep(D) && !D.IsCritical() &&
+                 Start.TargetPkg() == D.TargetPkg())
+                {
+                  if(!isPreviouslySatisfiedImportantDep)
+                    {
+                      DepIterator D2 = D;
+                      while((D2->CompareOp & Dep::Or) != 0)
+                        ++D2;
+
+                      isPreviouslySatisfiedImportantDep =
+                        (((*this)[D2] & DepGNow) != 0);
+                    }
+
+                  found=true;
+                }
+            }
            // this is a new dep if it was not found to be already
            // a important dep of the installed pacakge
            isNewImportantDep = !found;
@@ -901,10 +940,15 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
         if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
            std::clog << "new important dependency: " 
                      << Start.TargetPkg().Name() << std::endl;
+      if(isPreviouslySatisfiedImportantDep)
+       if(_config->FindB("Debug::pkgDepCache::AutoInstall", false) == true)
+         std::clog << "previously satisfied important dependency on "
+                   << Start.TargetPkg().Name() << std::endl;
 
       // skip important deps if the package is already installed
       if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
-         && !isNewImportantDep && !ForceImportantDeps)
+         && !isNewImportantDep && !isPreviouslySatisfiedImportantDep
+         && !ForceImportantDeps)
         continue;
       
       /* If we are in an or group locate the first or that can 
@@ -954,11 +998,10 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
                         << " as dep of " << Pkg.Name() 
                         << std::endl;
            // now check if we should consider it a automatic dependency or not
-           string sec = _config->Find("APT::Never-MarkAuto-Section","");
-           if(Pkg.Section() && (string(Pkg.Section()) ==  sec))
+           if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
            {
               if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
-                 std::clog << "Setting NOT as auto-installed because its a direct dep of a package in section " << sec << std::endl;
+                 std::clog << "Setting NOT as auto-installed (direct dep of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
               MarkInstall(InstPkg,true,Depth + 1, true);
            }
            else 
@@ -1131,6 +1174,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
    return Last;
 }
                                                                        /*}}}*/
+
 // Policy::IsImportantDep - True if the dependency is important                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1146,13 +1190,9 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
       // 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;
-      }
+      const char *sec = Dep.ParentVer().Section();
+      if (sec && ConfigValueInSubTree("APT::Install-Recommends-Sections", sec))
+        return true;
    }
    else if(Dep->Type == pkgCache::Dep::Suggests)
      return _config->FindB("APT::Install-Suggests", false);
@@ -1266,7 +1306,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
       {
         // the package is installed (and set to keep)
         if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
-           MarkPackage(p, p.CurrentVer(),
+           MarkPackage(p, p.CurrentVer(),
                        follow_recommends, follow_suggests);
         // the package is to be installed 
         else if(PkgState[p->ID].Install())
@@ -1317,7 +1357,18 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
    if(state.Marked)
       return;
 
-   //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
+   if(_config->FindB("Debug::pkgAutoRemove",false))
+     {
+       std::clog << "Marking: " << pkg.Name();
+       if(!ver.end())
+        std::clog << " " << ver.VerStr();
+       if(!currver.end())
+        std::clog << ", Curr=" << currver.VerStr();
+       if(!instver.end())
+        std::clog << ", Inst=" << instver.VerStr();
+       std::clog << std::endl;
+     }
+
    state.Marked=true;
 
    if(!ver.end())
@@ -1337,6 +1388,19 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
           {
              if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
              {
+               if(_config->FindB("Debug::pkgAutoRemove",false))
+                 {
+                   std::clog << "Following dep: " << d.ParentPkg().Name()
+                             << " " << d.ParentVer().VerStr() << " "
+                             << d.DepType() << " "
+                             << d.TargetPkg().Name();
+                   if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
+                     {
+                       std::clog << " (" << d.CompType() << " "
+                                 << d.TargetVer() << ")";
+                     }
+                   std::clog << std::endl;
+                 }
                 MarkPackage(V.ParentPkg(), V, 
                             follow_recommends, follow_suggests);
              }
@@ -1348,6 +1412,23 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
              if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
                                       d.TargetVer()))
              {
+               if(_config->FindB("Debug::pkgAutoRemove",false))
+                 {
+                   std::clog << "Following dep: " << d.ParentPkg().Name()
+                             << " " << d.ParentVer().VerStr() << " "
+                             << d.DepType() << " "
+                             << d.TargetPkg().Name();
+                   if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
+                     {
+                       std::clog << " (" << d.CompType() << " "
+                                 << d.TargetVer() << ")";
+                     }
+                   std::clog << ", provided by "
+                             << prv.OwnerPkg().Name() << " "
+                             << prv.OwnerVer().VerStr()
+                             << std::endl;
+                 }
+
                 MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
                             follow_recommends, follow_suggests);
              }