diff options
author | Michael Vogt <michael.vogt@ubuntu.com> | 2010-05-04 10:06:57 +0200 |
---|---|---|
committer | Michael Vogt <michael.vogt@ubuntu.com> | 2010-05-04 10:06:57 +0200 |
commit | af8a8da9c1aa6506d230a0df8abc670661176ba3 (patch) | |
tree | 343935c56f2294c835082233398fdef5d5d5e2eb /apt-pkg/depcache.cc | |
parent | 549edd163e34a50091623b47881f2eefbdc53aca (diff) | |
parent | edde664d0cc5fe46f572696c605832700c553b9e (diff) |
merged from davids branch
Diffstat (limited to 'apt-pkg/depcache.cc')
-rw-r--r-- | apt-pkg/depcache.cc | 117 |
1 files changed, 82 insertions, 35 deletions
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 2c7cdd5c2..423161b13 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -841,42 +841,15 @@ void pkgDepCache::Update(OpProgress *Prog) if (installed == false) recheck.insert(G.Index()); } - std::vector<std::string> Archs = APT::Configuration::getArchitectures(); - bool checkChanged = false; - do { - for(std::set<unsigned long>::const_iterator g = recheck.begin(); - g != recheck.end(); ++g) { - GrpIterator G = GrpIterator(*Cache, Cache->GrpP + *g); - VerIterator allV = G.FindPkg("all").CurrentVer(); - for (std::vector<std::string>::const_iterator a = Archs.begin(); - a != Archs.end(); ++a) - { - PkgIterator P = G.FindPkg(*a); - if (P.end() == true) continue; - for (VerIterator V = P.VersionList(); V.end() != true; ++V) - { - // FIXME: String comparison isn't a save indicator! - if (strcmp(allV.VerStr(),V.VerStr()) != 0) - continue; - unsigned char const CurDepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); - if ((CurDepState & DepInstMin) != DepInstMin) - break; // we found the correct version, but it is broken. Better try another arch or later again - P->CurrentVer = V.Index(); - AddStates(P); - Update(P); - AddSizes(P); - checkChanged = true; - break; - } - } - recheck.erase(g); - } - } while (checkChanged == true && recheck.empty() == false); - if (_config->FindB("Debug::MultiArchKiller", false) == true) - for(std::set<unsigned long>::const_iterator g = recheck.begin(); - g != recheck.end(); ++g) - std::cout << "No pseudo package for »" << GrpIterator(*Cache, Cache->GrpP + *g).Name() << "« installed" << std::endl; + while (recheck.empty() != true) + { + std::set<unsigned long>::const_iterator g = recheck.begin(); + unsigned long const G = *g; + recheck.erase(g); + if (unlikely(ReInstallPseudoForGroup(G, recheck) == false)) + _error->Warning(_("Internal error, group »%s« has no installable pseudo package"), GrpIterator(*Cache, Cache->GrpP + *g).Name()); + } } if (Prog != 0) @@ -885,6 +858,80 @@ void pkgDepCache::Update(OpProgress *Prog) readStateFile(Prog); } /*}}}*/ +// DepCache::ReInstallPseudoForGroup - MultiArch helper for Update() /*{{{*/ +// --------------------------------------------------------------------- +/* RemovePseudoInstalledPkg() is very successful. It even kills packages + to an amount that no pseudo package is left, but we need a pseudo package + for upgrading senarios so we need to reinstall one pseudopackage which + doesn't break everything. Thankfully we can't have architecture depending + negative dependencies so this problem is already eliminated */ +bool pkgDepCache::ReInstallPseudoForGroup(pkgCache::PkgIterator const &P, std::set<unsigned long> &recheck) +{ + if (P->CurrentVer != 0) + return true; + // recursive call for packages which provide this package + for (pkgCache::PrvIterator Prv = P.ProvidesList(); Prv.end() != true; ++Prv) + ReInstallPseudoForGroup(Prv.OwnerPkg(), recheck); + // check if we actually need to look at this group + unsigned long const G = P->Group; + std::set<unsigned long>::const_iterator Pi = recheck.find(G); + if (Pi == recheck.end()) + return true; + recheck.erase(Pi); // remove here, so we can't fall into an endless loop + if (unlikely(ReInstallPseudoForGroup(G, recheck) == false)) + { + recheck.insert(G); + return false; + } + return true; +} +bool pkgDepCache::ReInstallPseudoForGroup(unsigned long const &G, std::set<unsigned long> &recheck) +{ + std::vector<std::string> static const Archs = APT::Configuration::getArchitectures(); + pkgCache::GrpIterator Grp(*Cache, Cache->GrpP + G); + if (unlikely(Grp.end() == true)) + return false; + for (std::vector<std::string>::const_iterator a = Archs.begin(); + a != Archs.end(); ++a) + { + pkgCache::PkgIterator P = Grp.FindPkg(*a); + if (P.end() == true) + continue; + pkgCache::VerIterator allV = Grp.FindPkg("all").CurrentVer(); + for (VerIterator V = P.VersionList(); V.end() != true; ++V) + { + // search for the same version as the all package + if (allV->Hash != V->Hash || strcmp(allV.VerStr(),V.VerStr()) != 0) + continue; + unsigned char const CurDepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); + // If it is broken, try to install dependencies first before retry + if ((CurDepState & DepInstMin) != DepInstMin) + { + for (pkgCache::DepIterator D = V.DependsList(); D.end() != true; ++D) + { + if (D->Type != pkgCache::Dep::PreDepends && D->Type != pkgCache::Dep::Depends) + continue; + ReInstallPseudoForGroup(D.TargetPkg(), recheck); + } + unsigned char const CurDepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); + // if package ist still broken… try another arch + if ((CurDepState & DepInstMin) != DepInstMin) + break; + } + // dependencies satisfied: reinstall the package + RemoveSizes(P); + RemoveStates(P); + P->CurrentVer = V.Index(); + PkgState[P->ID].InstallVer = V; + AddStates(P); + Update(P); + AddSizes(P); + return true; + } + } + return false; +} + /*}}}*/ // DepCache::Update - Update the deps list of a package /*{{{*/ // --------------------------------------------------------------------- /* This is a helper for update that only does the dep portion of the scan. |