Просмотр исходного кода

Pre-MultiArch a package which depends on a package with architecture "all"
can be sure that a package comeing in as a dependency of this package
will be of the same architecture as itself (or all). We don't want to break
this, so internal an arch all package is represented as many arch depending
packages. The only problem we have now is that we only know that a arch
all package is installed or not - we don't know for which architecture it
was installed: So we will look at all these broken arch all pseudo packages
and "remove" them.

David Kalnischkies лет назад: 16
Родитель
Сommit
8b32e9209e
3 измененных файлов с 110 добавлено и 11 удалено
  1. 88 5
      apt-pkg/depcache.cc
  2. 8 4
      apt-pkg/depcache.h
  3. 14 2
      apt-pkg/pkgcachegen.cc

+ 88 - 5
apt-pkg/depcache.cc

@@ -17,6 +17,7 @@
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/tagfile.h>
 
 
@@ -596,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		/*{{{*/
 // DepCache::Update - Figure out all the state information		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This will figure out the state of all the packages and all the 
 /* This will figure out the state of all the packages and all the 
@@ -609,9 +661,13 @@ void pkgDepCache::Update(OpProgress *Prog)
    iKeepCount = 0;
    iKeepCount = 0;
    iBrokenCount = 0;
    iBrokenCount = 0;
    iBadCount = 0;
    iBadCount = 0;
-   
+
+   std::set<unsigned long> recheck;
+
    // Perform the depends pass
    // Perform the depends pass
    int Done = 0;
    int Done = 0;
+   bool const checkMultiArch = APT::Configuration::getArchitectures().size() > 1;
+   unsigned long killed = 0;
    for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
    for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
    {
    {
       if (Prog != 0 && Done%20 == 0)
       if (Prog != 0 && Done%20 == 0)
@@ -619,7 +675,7 @@ void pkgDepCache::Update(OpProgress *Prog)
       for (VerIterator V = I.VersionList(); V.end() != true; V++)
       for (VerIterator V = I.VersionList(); V.end() != true; V++)
       {
       {
 	 unsigned char Group = 0;
 	 unsigned char Group = 0;
-	 
+
 	 for (DepIterator D = V.DependsList(); D.end() != true; D++)
 	 for (DepIterator D = V.DependsList(); D.end() != true; D++)
 	 {
 	 {
 	    // Build the dependency state.
 	    // Build the dependency state.
@@ -637,16 +693,43 @@ void pkgDepCache::Update(OpProgress *Prog)
 		D->Type == Dep::DpkgBreaks ||
 		D->Type == Dep::DpkgBreaks ||
 		D->Type == Dep::Obsoletes)
 		D->Type == Dep::Obsoletes)
 	       State = ~State;
 	       State = ~State;
-	 }	 
+	 }
       }
       }
 
 
-      // Compute the pacakge dependency state and size additions
+      // Compute the package dependency state and size additions
       AddSizes(I);
       AddSizes(I);
       UpdateVerState(I);
       UpdateVerState(I);
       AddStates(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 (Prog != 0)      
+   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)
       Prog->Progress(Done);
       Prog->Progress(Done);
 
 
    readStateFile(Prog);
    readStateFile(Prog);

+ 8 - 4
apt-pkg/depcache.h

@@ -46,6 +46,7 @@
 
 
 #include <vector>
 #include <vector>
 #include <memory>
 #include <memory>
+#include <set>
 
 
 class pkgDepCache : protected pkgCache::Namespace
 class pkgDepCache : protected pkgCache::Namespace
 {
 {
@@ -442,9 +443,6 @@ class pkgDepCache : protected pkgCache::Namespace
    virtual bool IsDeleteOk(const PkgIterator &Pkg,bool Purge = false,
    virtual bool IsDeleteOk(const PkgIterator &Pkg,bool Purge = false,
 			    unsigned long Depth = 0, bool FromUser = true);
 			    unsigned long Depth = 0, bool FromUser = true);
 
 
-   // This is for debuging
-   void Update(OpProgress *Prog = 0);
-
    // read persistent states
    // read persistent states
    bool readStateFile(OpProgress *prog);
    bool readStateFile(OpProgress *prog);
    bool writeStateFile(OpProgress *prog, bool InstalledOnly=false);
    bool writeStateFile(OpProgress *prog, bool InstalledOnly=false);
@@ -460,9 +458,15 @@ class pkgDepCache : protected pkgCache::Namespace
    inline unsigned long BadCount() {return iBadCount;};
    inline unsigned long BadCount() {return iBadCount;};
 
 
    bool Init(OpProgress *Prog);
    bool Init(OpProgress *Prog);
-   
+   // Generate all state information
+   void Update(OpProgress *Prog = 0);
+
    pkgDepCache(pkgCache *Cache,Policy *Plcy = 0);
    pkgDepCache(pkgCache *Cache,Policy *Plcy = 0);
    virtual ~pkgDepCache();
    virtual ~pkgDepCache();
+
+   private:
+   // Helper for Update(OpProgress) to remove pseudoinstalled arch all packages
+   bool RemovePseudoInstalledPkg(PkgIterator &Pkg, std::set<unsigned long> &recheck);
 };
 };
 
 
 #endif
 #endif

+ 14 - 2
apt-pkg/pkgcachegen.cc

@@ -108,13 +108,24 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
    unsigned int Counter = 0;
    unsigned int Counter = 0;
    while (List.Step() == true)
    while (List.Step() == true)
    {
    {
-      // Get a pointer to the package structure
       string const PackageName = List.Package();
       string const PackageName = List.Package();
       if (PackageName.empty() == true)
       if (PackageName.empty() == true)
 	 return false;
 	 return false;
 
 
+      /* As we handle Arch all packages as architecture bounded
+         we add all information to every (simulated) arch package */
+      std::vector<string> genArch;
+      if (List.ArchitectureAll() == true)
+	 genArch = APT::Configuration::getArchitectures();
+      else
+	 genArch.push_back(List.Architecture());
+
+      for (std::vector<string>::const_iterator arch = genArch.begin();
+	   arch != genArch.end(); ++arch)
+      {
+      // Get a pointer to the package structure
       pkgCache::PkgIterator Pkg;
       pkgCache::PkgIterator Pkg;
-      if (NewPackage(Pkg, PackageName, List.Architecture()) == false)
+      if (NewPackage(Pkg, PackageName, *arch) == false)
 	 return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str());
 	 return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str());
       Counter++;
       Counter++;
       if (Counter % 100 == 0 && Progress != 0)
       if (Counter % 100 == 0 && Progress != 0)
@@ -257,6 +268,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 
 
       if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
       if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
 	 return _error->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName.c_str());
 	 return _error->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName.c_str());
+      }
    }
    }
 
 
    FoundFileDeps |= List.HasFileDeps();
    FoundFileDeps |= List.HasFileDeps();