From e0b94b97b179812e5a0b3b72ea9fcae106d545c5 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 27 Feb 2010 17:01:12 +0100 Subject: [PATCH] Enable the AutoRemover to talk "Multi-Arch" by marking all pseudo packages in a group if one is marked. The auto-installed flag is from now on Architecture bound: A section without an architecture tag will be treated as applying to all architectures - the next write operation will take care of this by creating separate sections for the architectures. --- apt-pkg/depcache.cc | 170 ++++++++++++++++++++++++++++---------------- apt-pkg/depcache.h | 4 +- 2 files changed, 109 insertions(+), 65 deletions(-) diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index eeb74a43..45c614c6 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -165,34 +165,46 @@ bool pkgDepCache::Init(OpProgress *Prog) bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ { FileFd state_file; - string state = _config->FindDir("Dir::State") + "extended_states"; + string const state = _config->FindDir("Dir::State") + "extended_states"; if(FileExists(state)) { state_file.Open(state, FileFd::ReadOnly); - int file_size = state_file.Size(); + int const file_size = state_file.Size(); if(Prog != NULL) Prog->OverallProgress(0, file_size, 1, _("Reading state information")); pkgTagFile tagfile(&state_file); pkgTagSection section; - int amt=0; - bool debug_autoremove=_config->FindB("Debug::pkgAutoRemove",false); + int amt = 0; + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); while(tagfile.Step(section)) { - string pkgname = section.FindS("Package"); - pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname); - // Silently ignore unknown packages and packages with no actual - // version. - if(!pkg.end() && !pkg.VersionList().end()) { - short reason = section.FindI("Auto-Installed", 0); - if(reason > 0) - PkgState[pkg->ID].Flags |= Flag::Auto; - if(debug_autoremove) - std::cout << "Auto-Installed : " << pkgname << std::endl; - amt+=section.size(); - if(Prog != NULL) - Prog->OverallProgress(amt, file_size, 1, - _("Reading state information")); + string const pkgname = section.FindS("Package"); + string pkgarch = section.FindS("Architecture"); + if (pkgarch.empty() == true) + pkgarch = "any"; + pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch); + // Silently ignore unknown packages and packages with no actual version. + if(pkg.end() == true || pkg->VersionList == 0) + continue; + + short const reason = section.FindI("Auto-Installed", 0); + if(reason > 0) + { + PkgState[pkg->ID].Flags |= Flag::Auto; + if (unlikely(debug_autoremove)) + std::cout << "Auto-Installed : " << pkg.FullName() << std::endl; + if (pkgarch == "any") + { + pkgCache::GrpIterator G = pkg.Group(); + for (pkg = G.NextPkg(pkg); pkg.end() != true; pkg = G.NextPkg(pkg)) + if (pkg->VersionList != 0) + PkgState[pkg->ID].Flags |= Flag::Auto; + } } + amt += section.size(); + if(Prog != NULL) + Prog->OverallProgress(amt, file_size, 1, + _("Reading state information")); } if(Prog != NULL) Prog->OverallProgress(file_size, file_size, 1, @@ -204,13 +216,13 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ /*}}}*/ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ { - bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); if(debug_autoremove) std::clog << "pkgDepCache::writeStateFile()" << std::endl; FileFd StateFile; - string state = _config->FindDir("Dir::State") + "extended_states"; + string const state = _config->FindDir("Dir::State") + "extended_states"; // if it does not exist, create a empty one if(!FileExists(state)) @@ -225,7 +237,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ state.c_str()); FILE *OutFile; - string outfile = state + ".tmp"; + string const outfile = state + ".tmp"; if((OutFile = fopen(outfile.c_str(),"w")) == NULL) return _error->Error(_("Failed to write temporary StateFile %s"), outfile.c_str()); @@ -236,46 +248,54 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ std::set pkgs_seen; const char *nullreorderlist[] = {0}; while(tagfile.Step(section)) { - string pkgname = section.FindS("Package"); + string const pkgname = section.FindS("Package"); + string pkgarch = section.FindS("Architecture"); + if (pkgarch.empty() == true) + pkgarch = "native"; // Silently ignore unknown packages and packages with no actual // version. - pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname); + pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch); if(pkg.end() || pkg.VersionList().end()) continue; - bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto); + bool const newAuto = (PkgState[pkg->ID].Flags & Flag::Auto); if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "Update existing AutoInstall info: " - << pkg.Name() << std::endl; - TFRewriteData rewrite[2]; - rewrite[0].Tag = "Auto-Installed"; - rewrite[0].Rewrite = newAuto ? "1" : "0"; + << pkg.FullName() << std::endl; + TFRewriteData rewrite[3]; + rewrite[0].Tag = "Architecture"; + rewrite[0].Rewrite = pkg.Arch(); rewrite[0].NewTag = 0; - rewrite[1].Tag = 0; + rewrite[1].Tag = "Auto-Installed"; + rewrite[1].Rewrite = newAuto ? "1" : "0"; + rewrite[1].NewTag = 0; + rewrite[2].Tag = 0; TFRewrite(OutFile, section, nullreorderlist, rewrite); fprintf(OutFile,"\n"); - pkgs_seen.insert(pkgname); + pkgs_seen.insert(pkg.FullName()); } // then write the ones we have not seen yet std::ostringstream ostr; for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) { if(PkgState[pkg->ID].Flags & Flag::Auto) { - if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) { + if (pkgs_seen.find(pkg.FullName()) != pkgs_seen.end()) { if(debug_autoremove) - std::clog << "Skipping already written " << pkg.Name() << std::endl; + std::clog << "Skipping already written " << pkg.FullName() << std::endl; continue; } - // skip not installed ones if requested - if(InstalledOnly && pkg->CurrentVer == 0) - continue; + // skip not installed ones if requested + if(InstalledOnly && pkg->CurrentVer == 0) + continue; + const char* const pkgarch = pkg.Arch(); + if (strcmp(pkgarch, "all") == 0) + continue; if(debug_autoremove) - std::clog << "Writing new AutoInstall: " - << pkg.Name() << std::endl; + std::clog << "Writing new AutoInstall: " << pkg.FullName() << std::endl; ostr.str(string("")); - ostr << "Package: " << pkg.Name() + ostr << "Package: " << pkg.Name() + << "\nArchitecture: " << pkgarch << "\nAuto-Installed: 1\n\n"; fprintf(OutFile,"%s",ostr.str().c_str()); - fprintf(OutFile,"\n"); } } fclose(OutFile); @@ -1426,7 +1446,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) // debug output if(debug_autoremove && PkgState[p->ID].Flags & Flag::Auto) - std::clog << "AutoDep: " << p.Name() << std::endl; + std::clog << "AutoDep: " << p.FullName() << std::endl; } // init vars @@ -1460,13 +1480,18 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) // MarkPackage - mark a single package in Mark-and-Sweep /*{{{*/ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, const pkgCache::VerIterator &ver, - bool follow_recommends, - bool follow_suggests) + bool const &follow_recommends, + bool const &follow_suggests) { pkgDepCache::StateCache &state = PkgState[pkg->ID]; - VerIterator currver = pkg.CurrentVer(); - VerIterator candver = state.CandidateVerIter(*this); - VerIterator instver = state.InstVerIter(*this); + + // if we are marked already we are done + if(state.Marked) + return; + + VerIterator const currver = pkg.CurrentVer(); + VerIterator const candver = state.CandidateVerIter(*this); + VerIterator const instver = state.InstVerIter(*this); #if 0 // If a package was garbage-collected but is now being marked, we @@ -1492,15 +1517,11 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, !(ver == currver && instver.end() && !ver.end())) return; - // if we are marked already we are done - if(state.Marked) - return; + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false); - bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false); - if(debug_autoremove) { - std::clog << "Marking: " << pkg.Name(); + std::clog << "Marking: " << pkg.FullName(); if(!ver.end()) std::clog << " " << ver.VerStr(); if(!currver.end()) @@ -1512,8 +1533,34 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, state.Marked=true; - if(!ver.end()) + if(ver.end() == true) + return; + + // If the version belongs to a Multi-Arch all package + // we will mark all others in this Group with this version also + // Beware: We compare versions here the lazy way: string comparision + // this is bad if multiple repositories provide different versions + // of the package with an identical version number - but even in this + // case the dependencies are likely the same. + if (ver->MultiArch == pkgCache::Version::All && + strcmp(ver.Arch(true), "all") == 0) { + GrpIterator G = pkg.Group(); + const char* const VerStr = ver.VerStr(); + for (PkgIterator P = G.FindPkg("any"); + P.end() != true; P = G.NextPkg(P)) + { + for (VerIterator V = P.VersionList(); + V.end() != true; ++V) + { + if (strcmp(VerStr, V.VerStr()) != 0) + continue; + MarkPackage(P, V, follow_recommends, follow_suggests); + break; + } + } + } + for(DepIterator d = ver.DependsList(); !d.end(); ++d) { if(d->Type == Dep::Depends || @@ -1531,10 +1578,9 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, { if(debug_autoremove) { - std::clog << "Following dep: " << d.ParentPkg().Name() + std::clog << "Following dep: " << d.ParentPkg().FullName() << " " << d.ParentVer().VerStr() << " " - << d.DepType() << " " - << d.TargetPkg().Name(); + << d.DepType() << " " << d.TargetPkg().FullName(); if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp) { std::clog << " (" << d.CompType() << " " @@ -1542,7 +1588,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, } std::clog << std::endl; } - MarkPackage(V.ParentPkg(), V, + MarkPackage(V.ParentPkg(), V, follow_recommends, follow_suggests); } } @@ -1555,17 +1601,16 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, { if(debug_autoremove) { - std::clog << "Following dep: " << d.ParentPkg().Name() - << " " << d.ParentVer().VerStr() << " " - << d.DepType() << " " - << d.TargetPkg().Name(); + std::clog << "Following dep: " << d.ParentPkg().FullName() << " " + << d.ParentVer().VerStr() << " " + << d.DepType() << " " << d.TargetPkg().FullName() << " "; if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp) { std::clog << " (" << d.CompType() << " " << d.TargetVer() << ")"; } std::clog << ", provided by " - << prv.OwnerPkg().Name() << " " + << prv.OwnerPkg().FullName() << " " << prv.OwnerVer().VerStr() << std::endl; } @@ -1576,7 +1621,6 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, } } } - } } /*}}}*/ bool pkgDepCache::Sweep() /*{{{*/ @@ -1598,7 +1642,7 @@ bool pkgDepCache::Sweep() /*{{{*/ { state.Garbage=true; if(debug_autoremove) - std::cout << "Garbage: " << p.Name() << std::endl; + std::cout << "Garbage: " << p.FullName() << std::endl; } } diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index ab1021a4..23b29cc1 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -79,8 +79,8 @@ class pkgDepCache : protected pkgCache::Namespace */ void MarkPackage(const pkgCache::PkgIterator &pkg, const pkgCache::VerIterator &ver, - bool follow_recommends, - bool follow_suggests); + bool const &follow_recommends, + bool const &follow_suggests); /** \brief Update the Marked field of all packages. * -- 2.20.1