]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/depcache.cc
criss-cross merge with my sid branch
[apt.git] / apt-pkg / depcache.cc
index 5c011d743e20a3807b4b77af679cb518b824f817..eeb74a434eb6846304d1199fcf334c5c69046d6d 100644 (file)
@@ -17,6 +17,7 @@
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/tagfile.h>
 
@@ -127,12 +128,9 @@ bool pkgDepCache::Init(OpProgress *Prog)
    /* Set the current state of everything. In this state all of the
       packages are kept exactly as is. See AllUpgrade */
    int Done = 0;
-   int Update_interval = Head().PackageCount/100;
-   if (Update_interval == 0)
-      Update_interval = 1;
    for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
    {
-      if (Prog != 0 && Done%Update_interval == 0)
+      if (Prog != 0 && Done%20 == 0)
         Prog->Progress(Done);
       
       // Find the proper cache slot
@@ -195,10 +193,10 @@ bool pkgDepCache::readStateFile(OpProgress *Prog)                 /*{{{*/
               Prog->OverallProgress(amt, file_size, 1, 
                                     _("Reading state information"));
         }
-        if(Prog != NULL)
-           Prog->OverallProgress(file_size, file_size, 1, 
-                                 _("Reading state information"));
       }
+      if(Prog != NULL)
+        Prog->OverallProgress(file_size, file_size, 1,
+                              _("Reading state information"));
    }
 
    return true;
@@ -246,7 +244,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)      /*{{{*/
            continue;
         bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
         if(_config->FindB("Debug::pkgAutoRemove",false))
-           std::clog << "Update exisiting AutoInstall info: " 
+           std::clog << "Update existing AutoInstall info: " 
                      << pkg.Name() << std::endl;
         TFRewriteData rewrite[2];
         rewrite[0].Tag = "Auto-Installed";
@@ -599,6 +597,57 @@ void pkgDepCache::UpdateVerState(PkgIterator Pkg)
    }
 }
                                                                        /*}}}*/
+// DepCache::RemovePseudoInstalledPkg - MultiArch helper for Update()  /*{{{*/
+// ---------------------------------------------------------------------
+/* We "install" arch all packages for all archs if it is installed. Many
+   of these will be broken. This method will look at these broken Pkg and
+   "remove" it. */
+bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::set<unsigned long> &recheck) {
+   if (unlikely(Pkg->CurrentVer == 0))
+      return false;
+
+   VerIterator V = Pkg.CurrentVer();
+   if (V->MultiArch != Version::All)
+      return false;
+
+   unsigned char const DepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy);
+   if ((DepState & DepInstMin) == DepInstMin)
+      return false;
+
+   // Dependencies for this arch all are not statisfied
+   // so we installed it only for our convenience: get right of it now.
+   RemoveSizes(Pkg);
+   RemoveStates(Pkg);
+
+   Pkg->CurrentVer = 0;
+   PkgState[Pkg->ID].InstallVer = 0;
+
+   AddStates(Pkg);
+   Update(Pkg);
+   AddSizes(Pkg);
+
+   // After the remove previously satisfied pseudo pkg could be now
+   // no longer satisfied, so we need to recheck the reverse dependencies
+   for (DepIterator d = Pkg.RevDependsList(); d.end() != true; ++d)
+   {
+      PkgIterator const P = d.ParentPkg();
+      if (P->CurrentVer != 0)
+        recheck.insert(P.Index());
+   }
+
+   if (V.end() != true)
+      for (PrvIterator Prv = V.ProvidesList(); Prv.end() != true; Prv++)
+        for (DepIterator d = Prv.ParentPkg().RevDependsList();
+             d.end() != true; ++d)
+        {
+           PkgIterator const P = d.ParentPkg();
+           if (P->CurrentVer != 0)
+              recheck.insert(P.Index());
+        }
+
+   return true;
+}
+                                                                       /*}}}*/
 // DepCache::Update - Figure out all the state information             /*{{{*/
 // ---------------------------------------------------------------------
 /* This will figure out the state of all the packages and all the 
@@ -612,20 +661,21 @@ void pkgDepCache::Update(OpProgress *Prog)
    iKeepCount = 0;
    iBrokenCount = 0;
    iBadCount = 0;
-   
+
+   std::set<unsigned long> recheck;
+
    // Perform the depends pass
    int Done = 0;
-   int Update_interval = Head().PackageCount;
-   if (Update_interval == 0)
-      Update_interval = 1;
+   bool const checkMultiArch = APT::Configuration::getArchitectures().size() > 1;
+   unsigned long killed = 0;
    for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
    {
-      if (Prog != 0 && Done%Update_interval == 0)
+      if (Prog != 0 && Done%20 == 0)
         Prog->Progress(Done);
       for (VerIterator V = I.VersionList(); V.end() != true; V++)
       {
         unsigned char Group = 0;
-        
+
         for (DepIterator D = V.DependsList(); D.end() != true; D++)
         {
            // Build the dependency state.
@@ -643,16 +693,43 @@ void pkgDepCache::Update(OpProgress *Prog)
                D->Type == Dep::DpkgBreaks ||
                D->Type == Dep::Obsoletes)
               State = ~State;
-        }       
+        }
       }
 
-      // Compute the pacakge dependency state and size additions
+      // Compute the package dependency state and size additions
       AddSizes(I);
       UpdateVerState(I);
       AddStates(I);
+
+      if (checkMultiArch != true || I->CurrentVer == 0)
+        continue;
+
+      VerIterator const V = I.CurrentVer();
+      if (V->MultiArch != Version::All)
+        continue;
+
+      recheck.insert(I.Index());
+      --Done; // no progress if we need to recheck the package
+   }
+
+   if (checkMultiArch == true) {
+      /* FIXME: recheck breaks proper progress reporting as we don't know
+               how many packages we need to recheck. To lower the effect
+               a bit we increase with a kill, but we should do something more clever… */
+      for(std::set<unsigned long>::const_iterator p = recheck.begin();
+         p != recheck.end(); ++p) {
+        if (Prog != 0 && Done%20 == 0)
+           Prog->Progress(Done);
+        PkgIterator P = PkgIterator(*Cache, Cache->PkgP + *p);
+        if (RemovePseudoInstalledPkg(P, recheck) == true) {
+           ++killed;
+           ++Done;
+        }
+        recheck.erase(p);
+      }
    }
 
-   if (Prog != 0)      
+   if (Prog != 0)
       Prog->Progress(Done);
 
    readStateFile(Prog);
@@ -819,6 +896,10 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
    AddStates(Pkg);   
    Update(Pkg);
    AddSizes(Pkg);
+
+   // if we remove the pseudo package, we also need to remove the "real"
+   if (Pkg->CurrentVer != 0 && Pkg.CurrentVer().Pseudo() == true)
+      MarkDelete(Pkg.Group().FindPkg("all"), rPurge, Depth+1, FromUser);
 }
                                                                        /*}}}*/
 // DepCache::IsDeleteOk - check if it is ok to remove this package     /*{{{*/
@@ -829,7 +910,7 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
 bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge,
                              unsigned long Depth, bool FromUser)
 {
-   if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold)
+   if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false)
    {
       if (DebugMarker == true)
         std::clog << OutputInDepth(Depth) << "Hold prevents MarkDelete of " << Pkg << " FU=" << FromUser << std::endl;
@@ -1091,7 +1172,7 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
                              unsigned long Depth, bool FromUser)
 {
-   if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold)
+   if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false)
    {
       if (DebugMarker == true)
         std::clog << OutputInDepth(Depth) << "Hold prevents MarkInstall of " << Pkg << " FU=" << FromUser << std::endl;