From 8b32e9209ecfab776f064e3c4ccab249307ae49d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Feb 2010 17:42:39 +0100 Subject: 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. --- apt-pkg/depcache.cc | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 5 deletions(-) (limited to 'apt-pkg/depcache.cc') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 228750b74..b04181d76 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -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 &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 @@ -609,9 +661,13 @@ void pkgDepCache::Update(OpProgress *Prog) iKeepCount = 0; iBrokenCount = 0; iBadCount = 0; - + + std::set recheck; + // Perform the depends pass int Done = 0; + 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%20 == 0) @@ -619,7 +675,7 @@ void pkgDepCache::Update(OpProgress *Prog) 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. @@ -637,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 (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::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); readStateFile(Prog); -- cgit v1.2.3-70-g09d2 From 803ea2a87f81252b2c0d541b8502ed206ce57c84 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Feb 2010 00:04:31 +0100 Subject: Add yet another pseudo package which isn't as pseudo as the others: Arch all packages are now represented by arch depending packages which all depend on a package with the same name and the special arch "all". This packages has NO dependencies, but beside this the same information. It is the only package which has a size, the arch depending ones all have a zero size. While the arch depending pseudo packages are used for dependency resolution the arch "all" package is used for downloading and ordering of the package. --- apt-pkg/algorithms.cc | 52 ++++++++++++++++++++++++++++++++++++++++---- apt-pkg/cacheiterators.h | 1 + apt-pkg/deb/deblistparser.cc | 22 +++++++++++++++++-- apt-pkg/depcache.cc | 4 ++++ apt-pkg/depcache.h | 1 + apt-pkg/orderlist.cc | 4 ++++ apt-pkg/packagemanager.cc | 23 +++++++++++++++----- apt-pkg/pkgcache.cc | 12 ++++++++++ apt-pkg/pkgcache.h | 2 +- apt-pkg/pkgcachegen.cc | 20 +++++++++++++---- cmdline/apt-cache.cc | 2 ++ cmdline/apt-get.cc | 14 +++++++++--- 12 files changed, 137 insertions(+), 20 deletions(-) (limited to 'apt-pkg/depcache.cc') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 34da745de..c905cffa9 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -83,13 +83,28 @@ void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candid bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) { // Adapt the iterator - PkgIterator Pkg = Sim.FindPkg(iPkg.Name()); + PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); Flags[Pkg->ID] = 1; cout << "Inst "; Describe(Pkg,cout,true,true); Sim.MarkInstall(Pkg,false); - + + if (strcmp(Pkg.Arch(),"all") == 0) + { + pkgCache::GrpIterator G = Pkg.Group(); + pkgCache::GrpIterator iG = iPkg.Group(); + for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) + { + if (strcmp(P.Arch(), "all") == 0) + continue; + if (iG.FindPkg(P.Arch())->CurrentVer == 0) + continue; + Flags[P->ID] = 1; + Sim.MarkInstall(P, false); + } + } + // Look for broken conflicts+predepends. for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++) { @@ -131,9 +146,22 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) bool pkgSimulate::Configure(PkgIterator iPkg) { // Adapt the iterator - PkgIterator Pkg = Sim.FindPkg(iPkg.Name()); + PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); Flags[Pkg->ID] = 2; + + if (strcmp(Pkg.Arch(),"all") == 0) + { + pkgCache::GrpIterator G = Pkg.Group(); + for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) + { + if (strcmp(P.Arch(), "all") == 0) + continue; + if (Flags[P->ID] == 1) + Flags[P->ID] = 2; + } + } + // Sim.MarkInstall(Pkg,false); if (Sim[Pkg].InstBroken() == true) { @@ -181,10 +209,26 @@ bool pkgSimulate::Configure(PkgIterator iPkg) bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge) { // Adapt the iterator - PkgIterator Pkg = Sim.FindPkg(iPkg.Name()); + PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); Flags[Pkg->ID] = 3; Sim.MarkDelete(Pkg); + + if (strcmp(Pkg.Arch(),"all") == 0) + { + pkgCache::GrpIterator G = Pkg.Group(); + pkgCache::GrpIterator iG = iPkg.Group(); + for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) + { + if (strcmp(P.Arch(), "all") == 0) + continue; + if (iG.FindPkg(P.Arch())->CurrentVer == 0) + continue; + Flags[P->ID] = 3; + Sim.MarkDelete(P); + } + } + if (Purge == true) cout << "Purg "; else diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index e8cf28496..43cbe1377 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -200,6 +200,7 @@ class pkgCache::VerIterator : public Iterator { string RelStr(); bool Automatic() const; + bool Pseudo() const; VerFileIterator NewestFile() const; inline VerIterator(pkgCache &Owner,Version *Trg = 0) : Iterator(Owner, Trg) { diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 3726a6a04..b3d95164a 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -148,6 +148,24 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) Ver->Priority = pkgCache::State::Extra; } + if (Ver->MultiArch == pkgCache::Version::All) + { + /* We maintain a "pseudo" arch=all package for architecture all versions + on which these versions can depend on. This pseudo package is many used + for downloading/installing: The other pseudo-packages will degenerate + to a NOP in the download/install step - this package will ensure that + it is downloaded only one time and installed only one time -- even if + the architecture bound versions coming in and out on regular basis. */ + if (strcmp(Ver.Arch(true),"all") == 0) + return true; + else + { + // our pseudo packages have no size to not confuse the fetcher + Ver->Size = 0; + Ver->InstalledSize = 0; + } + } + if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false) return false; if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false) @@ -593,7 +611,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, return true; string Package; - string const pkgArch = Ver.Arch(); + string const pkgArch = Ver.Arch(true); string Version; unsigned int Op; @@ -622,7 +640,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver) { string Package; string Version; - string const Arch = Ver.Arch(); + string const Arch = Ver.Arch(true); unsigned int Op; while (1) diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index b04181d76..e817adb77 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -896,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 /*{{{*/ diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 63cd954ad..ab1021a44 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -333,6 +333,7 @@ class pkgDepCache : protected pkgCache::Namespace inline Header &Head() {return *Cache->HeaderP;}; inline PkgIterator PkgBegin() {return Cache->PkgBegin();}; inline PkgIterator FindPkg(string const &Name) {return Cache->FindPkg(Name);}; + inline PkgIterator FindPkg(string const &Name, string const &Arch) {return Cache->FindPkg(Name, Arch);}; inline pkgCache &GetCache() {return *Cache;}; inline pkgVersioningSystem &VS() {return *Cache->VS;}; diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc index 0ee2e2bc8..2e7618b55 100644 --- a/apt-pkg/orderlist.cc +++ b/apt-pkg/orderlist.cc @@ -126,6 +126,10 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg) if (FileList[Pkg->ID].empty() == false) return false; + + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == true) + return false; + return true; } /*}}}*/ diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 1ab3203a1..08e7fc00f 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -80,7 +80,10 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, // Skip already processed packages if (List->IsNow(Pkg) == false) continue; - + + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == true) + continue; + new pkgAcqArchive(Owner,Sources,Recs,Cache[Pkg].InstVerIter(Cache), FileNames[Pkg->ID]); } @@ -277,8 +280,10 @@ bool pkgPackageManager::ConfigureAll() for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++) { PkgIterator Pkg(Cache,*I); - - if (ConfigurePkgs == true && Configure(Pkg) == false) + + if (ConfigurePkgs == true && + pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false && + Configure(Pkg) == false) return false; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); @@ -310,7 +315,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) { PkgIterator Pkg(Cache,*I); - if (ConfigurePkgs == true && Configure(Pkg) == false) + if (ConfigurePkgs == true && + pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false && + Configure(Pkg) == false) return false; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); @@ -457,7 +464,10 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg) return true; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); - return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge); + + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false) + return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge); + return true; } /*}}}*/ // PM::SmartUnPack - Install helper /*{{{*/ @@ -565,7 +575,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) P.end() == false; P++) CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion()); - if (Install(Pkg,FileNames[Pkg->ID]) == false) + if (pkgCache::VerIterator(Cache, Cache[Pkg].CandidateVer).Pseudo() == false && + Install(Pkg,FileNames[Pkg->ID]) == false) return false; List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 2d4ee1010..04a2c7234 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -649,6 +649,18 @@ bool pkgCache::VerIterator::Automatic() const return false; } /*}}}*/ +// VerIterator::Pseudo - Check if this version is a pseudo one /*{{{*/ +// --------------------------------------------------------------------- +/* Sometimes you have the need to express dependencies with versions + which doesn't really exist or exist multiply times for "different" + packages. We need these versions for dependency resolution but they + are a problem everytime we need to download/install something. */ +bool pkgCache::VerIterator::Pseudo() const +{ + return (S->MultiArch == pkgCache::Version::All && + strcmp(Arch(true),"all") != 0); +} + /*}}}*/ // VerIterator::NewestFile - Return the newest file version relation /*{{{*/ // --------------------------------------------------------------------- /* This looks at the version numbers associated with all of the sources diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 5edeedfd1..012caac76 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -357,7 +357,7 @@ inline pkgCache::PkgFileIterator pkgCache::FileEnd() class pkgCache::Namespace /*{{{*/ { public: - + typedef pkgCache::GrpIterator GrpIterator; typedef pkgCache::PkgIterator PkgIterator; typedef pkgCache::VerIterator VerIterator; typedef pkgCache::DescIterator DescIterator; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index ebda325f7..c1b546a00 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -115,9 +115,10 @@ bool pkgCacheGenerator::MergeList(ListParser &List, /* As we handle Arch all packages as architecture bounded we add all information to every (simulated) arch package */ std::vector genArch; - if (List.ArchitectureAll() == true) + if (List.ArchitectureAll() == true) { genArch = APT::Configuration::getArchitectures(); - else + genArch.push_back("all"); + } else genArch.push_back(List.Architecture()); for (std::vector::const_iterator arch = genArch.begin(); @@ -531,8 +532,11 @@ bool pkgCacheGenerator::FinishCache(OpProgress &Progress) { for (pkgCache::GrpIterator G = GetCache().GrpBegin(); G.end() != true; G++) { string const PkgName = G.Name(); for (pkgCache::PkgIterator P = G.PackageList(); P.end() != true; P = G.NextPkg(P)) { + if (strcmp(P.Arch(),"all") == 0) + continue; + pkgCache::PkgIterator allPkg; for (pkgCache::VerIterator V = P.VersionList(); V.end() != true; V++) { - string const Arch = V.Arch(); + string const Arch = V.Arch(true); map_ptrloc *OldDepLast = NULL; /* MultiArch handling introduces a lot of implicit Dependencies: - MultiArch: same → Co-Installable if they have the same version @@ -540,6 +544,8 @@ bool pkgCacheGenerator::FinishCache(OpProgress &Progress) { - All others conflict with all other group members */ bool const coInstall = (V->MultiArch == pkgCache::Version::All || V->MultiArch == pkgCache::Version::Same); + if (V->MultiArch == pkgCache::Version::All && allPkg.end() == true) + allPkg = G.FindPkg("all"); for (vector::const_iterator A = archs.begin(); A != archs.end(); ++A) { if (*A == Arch) continue; @@ -561,6 +567,12 @@ bool pkgCacheGenerator::FinishCache(OpProgress &Progress) { NewDepends(D, V, V.VerStr(), pkgCache::Dep::Greater, pkgCache::Dep::DpkgBreaks, OldDepLast); + if (V->MultiArch == pkgCache::Version::All) { + // Depend on ${self}:all which does depend on nothing + NewDepends(allPkg, V, V.VerStr(), + pkgCache::Dep::Equals, pkgCache::Dep::Depends, + OldDepLast); + } } else { // Conflicts: ${self}:other NewDepends(D, V, "", @@ -675,7 +687,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver, pkgCache &Cache = Owner->Cache; // We do not add self referencing provides - if (Ver.ParentPkg().Name() == PkgName && PkgArch == Ver.Arch()) + if (Ver.ParentPkg().Name() == PkgName && PkgArch == Ver.Arch(true)) return true; // Get a structure diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index cd806286c..275daa187 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1587,6 +1587,8 @@ bool Policy(CommandLine &CmdL) } for (; Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) { + if (strcmp(Pkg.Arch(),"all") == 0) + continue; if (myArch == Pkg.Arch()) cout << Pkg.Name() << ":" << endl; diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 2597a6acb..93065004c 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -233,7 +233,7 @@ bool ShowList(ostream &out,string Title,string List,string VersionsList) if it is not the main architecture */ string ShowPkg(pkgCache::PkgIterator const Pkg) { string p = Pkg.Name(); - if (_config->Find("APT::Architecture") != Pkg.Arch()) + if (strcmp(Pkg.Arch(),"all") != 0 && _config->Find("APT::Architecture") != Pkg.Arch()) p.append(":").append(Pkg.Arch()); return p; } @@ -385,6 +385,8 @@ void ShowNew(ostream &out,CacheFile &Cache) { pkgCache::PkgIterator I(Cache,Cache.List[J]); if (Cache[I].NewInstall() == true) { + if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) + continue; List += ShowPkg(I) + " "; VersionsList += string(Cache[I].CandVersion) + "\n"; } @@ -407,6 +409,8 @@ void ShowDel(ostream &out,CacheFile &Cache) pkgCache::PkgIterator I(Cache,Cache.List[J]); if (Cache[I].Delete() == true) { + if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) + continue; if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) List += ShowPkg(I) + "* "; else @@ -455,7 +459,9 @@ void ShowUpgraded(ostream &out,CacheFile &Cache) // Not interesting if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) continue; - + if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) + continue; + List += ShowPkg(I) + " "; VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; } @@ -476,7 +482,9 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache) // Not interesting if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true) continue; - + if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) + continue; + List += ShowPkg(I) + " "; VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; } -- cgit v1.2.3-70-g09d2 From e0b94b97b179812e5a0b3b72ea9fcae106d545c5 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 27 Feb 2010 17:01:12 +0100 Subject: 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(-) (limited to 'apt-pkg/depcache.cc') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index eeb74a434..45c614c6f 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 ab1021a44..23b29cc13 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. * -- cgit v1.2.3-70-g09d2 From 1ec1653cd4849423e0d5f769ecbfab2d6f16c4ad Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 1 Mar 2010 21:59:03 +0100 Subject: We need to kill also pseudo packages which have no dependency, no installed reverse dependency and which also doesn't provide something. They cause problems if this pseudo packages get new dependencies. As a consequence we also need to recheck the dependencies of a killed pseudo package (and especially the providers of these dependencies) to really kill all non required packages. --- apt-pkg/depcache.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++--------- apt-pkg/depcache.h | 1 + 2 files changed, 66 insertions(+), 12 deletions(-) (limited to 'apt-pkg/depcache.cc') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 45c614c6f..893164ea1 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -630,11 +630,46 @@ bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::setMultiArch != Version::All) return false; - unsigned char const DepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); - if ((DepState & DepInstMin) == DepInstMin) + // Never ever kill an "all" package - they have no dependency so they can't be broken + if (strcmp(Pkg.Arch(),"all") == 0) return false; - // Dependencies for this arch all are not statisfied +// std::cout << "CHECK " << Pkg << std::endl; + + unsigned char const DepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy); + if ((DepState & DepInstMin) == DepInstMin) { + // okay, the package isn't broken, but is the package also required? + // If it has no real dependencies, no installed rdepends and doesn't + // provide something of value, we will kill it as not required. + // These pseudopackages have otherwise interesting effects if they get + // a new dependency in a newer version… + for (pkgCache::DepIterator D = V.DependsList(); + D.end() != true; ++D) + if ((D->Type == pkgCache::Dep::Depends || + D->Type == pkgCache::Dep::PreDepends) && + D.ParentPkg()->Group != Pkg->Group) + return false; + for (DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D) + { + if (D->Type != pkgCache::Dep::Depends && + D->Type != pkgCache::Dep::PreDepends) + continue; + PkgIterator const P = D.ParentPkg(); + if (P->CurrentVer != 0) + return false; + } + 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 && + P->Group != Pkg->Group) + return false; + } + } + + // Dependencies for this arch all package are not statisfied // so we installed it only for our convenience: get right of it now. RemoveSizes(Pkg); RemoveStates(Pkg); @@ -655,15 +690,33 @@ bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::setCurrentVer != 0) - recheck.insert(P.Index()); - } + for (DepIterator d = V.DependsList(); d.end() != true; ++d) + { + PkgIterator const P = d.TargetPkg(); + for (PrvIterator Prv = P.ProvidesList(); Prv.end() != true; ++Prv) + { + PkgIterator const O = Prv.OwnerPkg(); + if (O->CurrentVer != 0) + recheck.insert(O.Index()); + } + + if (P->CurrentVer != 0) + recheck.insert(P.Index()); + } + + 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) + continue; + + recheck.insert(P.Index()); + } + } + return true; } diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 23b29cc13..ea605f199 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -332,6 +332,7 @@ class pkgDepCache : protected pkgCache::Namespace inline operator pkgCache &() {return *Cache;}; inline Header &Head() {return *Cache->HeaderP;}; inline PkgIterator PkgBegin() {return Cache->PkgBegin();}; + inline GrpIterator FindGrp(string const &Name) {return Cache->FindGrp(Name);}; inline PkgIterator FindPkg(string const &Name) {return Cache->FindPkg(Name);}; inline PkgIterator FindPkg(string const &Name, string const &Arch) {return Cache->FindPkg(Name, Arch);}; -- cgit v1.2.3-70-g09d2 From 1f530ccb32c17b70b05dd5feee706dc1098a7251 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 14 Mar 2010 14:45:00 +0100 Subject: Ensure that for each all package at least one pseudopackage is installed Removing pseudo packages is cool so far, the problem is that we will remove with the not required removing so many pseudo packages that we will have after the remove a few packages with NO installed pseudo package (e.g. metapackages are good candidates) - so we will walk over all these packages and try to find a pseudopackage for this package we can install without breaking something. --- apt-pkg/depcache.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 9 deletions(-) (limited to 'apt-pkg/depcache.cc') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 893164ea1..ffa4fe71c 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -634,10 +634,8 @@ bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::setType == pkgCache::Dep::Depends || - D->Type == pkgCache::Dep::PreDepends) && - D.ParentPkg()->Group != Pkg->Group) + if (D.IsCritical() == true && D.ParentPkg()->Group != Pkg->Group) return false; for (DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D) { - if (D->Type != pkgCache::Dep::Depends && - D->Type != pkgCache::Dep::PreDepends) + if (D.IsCritical() == false) continue; PkgIterator const P = D.ParentPkg(); + if (P->Group == Pkg->Group) + continue; if (P->CurrentVer != 0) return false; } @@ -800,6 +797,68 @@ void pkgDepCache::Update(OpProgress *Prog) } recheck.erase(p); } + + /* Okay, we have killed a great amount of pseudopackages - + we have killed so many that we have now arch "all" packages + without an installed pseudo package, but we NEED an installed + pseudo package, so we will search now for a pseudo package + we can install without breaking everything. */ + for (GrpIterator G = Cache->GrpBegin(); G.end() != true; ++G) + { + PkgIterator P = G.FindPkg("all"); + if (P.end() == true) + continue; + if (P->CurrentVer == 0) + continue; + bool installed = false; + for (P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P)) + { + if (strcmp(P.Arch(), "all") == 0) + continue; + if (P->CurrentVer == 0) + continue; + installed = true; + break; + } + if (installed == false) + recheck.insert(G.Index()); + } + std::vector Archs = APT::Configuration::getArchitectures(); + bool checkChanged = false; + do { + for(std::set::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::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::const_iterator g = recheck.begin(); + g != recheck.end(); ++g) + std::cout << "No pseudo package for »" << GrpIterator(*Cache, Cache->GrpP + *g).Name() << "« installed" << std::endl; } if (Prog != 0) -- cgit v1.2.3-70-g09d2 From c176c4d0adad246ac0768f9e2b60aa8e4c56fffb Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 14 Mar 2010 21:48:14 +0100 Subject: * apt-pkg/depcache.cc: - remove Auto-Installed information from extended_states together with the package itself (Closes: #572364) --- apt-pkg/depcache.cc | 31 ++++++++++++++++++++++++------- apt-pkg/depcache.h | 2 +- apt-pkg/tagfile.cc | 13 ++----------- apt-pkg/tagfile.h | 15 ++++++++++++++- debian/changelog | 3 +++ 5 files changed, 44 insertions(+), 20 deletions(-) (limited to 'apt-pkg/depcache.cc') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 5943d858a..e9fb5f76a 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -235,16 +235,30 @@ 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"); // Silently ignore unknown packages and packages with no actual // version. pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname); if(pkg.end() || pkg.VersionList().end()) continue; - bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto); + StateCache const &P = PkgState[pkg->ID]; + bool newAuto = (P.Flags & Flag::Auto); + // skip not installed or now-removed ones if requested + if (InstalledOnly && ( + (pkg->CurrentVer == 0 && P.Mode != ModeInstall) || + (pkg->CurrentVer != 0 && P.Mode == ModeDelete))) + { + // The section is obsolete if it contains no other tag + unsigned int const count = section.Count(); + if (count < 2 || + (count == 2 && section.Exists("Auto-Installed"))) + continue; + else + newAuto = false; + } if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "Update existing AutoInstall info: " - << pkg.Name() << std::endl; + << pkgname << std::endl; TFRewriteData rewrite[2]; rewrite[0].Tag = "Auto-Installed"; rewrite[0].Rewrite = newAuto ? "1" : "0"; @@ -258,15 +272,18 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/ // 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) { + StateCache const &P = PkgState[pkg->ID]; + if(P.Flags & Flag::Auto) { if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) { if(debug_autoremove) std::clog << "Skipping already written " << pkg.Name() << 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 && P.Mode != ModeInstall) || + (pkg->CurrentVer != 0 && P.Mode == ModeDelete))) + continue; if(debug_autoremove) std::clog << "Writing new AutoInstall: " << pkg.Name() << std::endl; diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 0306861a1..fd1f202be 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -447,7 +447,7 @@ class pkgDepCache : protected pkgCache::Namespace // read persistent states bool readStateFile(OpProgress *prog); - bool writeStateFile(OpProgress *prog, bool InstalledOnly=false); + bool writeStateFile(OpProgress *prog, bool InstalledOnly=true); // Size queries inline double UsrSize() {return iUsrSize;}; diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 7c5d15a58..0d4999ee7 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -193,17 +193,8 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset) /*}}}*/ // TagSection::Scan - Scan for the end of the header information /*{{{*/ // --------------------------------------------------------------------- -/* This looks for the first double new line in the data stream. It also - indexes the tags in the section. This very simple hash function for the - last 8 letters gives very good performance on the debian package files */ -inline static unsigned long AlphaHash(const char *Text, const char *End = 0) -{ - unsigned long Res = 0; - for (; Text != End && *Text != ':' && *Text != 0; Text++) - Res = ((unsigned long)(*Text) & 0xDF) ^ (Res << 1); - return Res & 0xFF; -} - +/* This looks for the first double new line in the data stream. + It also indexes the tags in the section. */ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength) { const char *End = Start + MaxLength; diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 321329a23..f63a51d07 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -33,7 +33,18 @@ class pkgTagSection unsigned int AlphaIndexes[0x100]; unsigned int TagCount; - + + /* This very simple hash function for the last 8 letters gives + very good performance on the debian package files */ + inline static unsigned long AlphaHash(const char *Text, const char *End = 0) + { + unsigned long Res = 0; + for (; Text != End && *Text != ':' && *Text != 0; Text++) + Res = ((unsigned long)(*Text) & 0xDF) ^ (Res << 1); + return Res & 0xFF; + } + + protected: const char *Stop; @@ -54,6 +65,8 @@ class pkgTagSection virtual void TrimRecord(bool BeforeRecord, const char* &End); inline unsigned int Count() const {return TagCount;}; + inline bool Exists(const char* const Tag) {return AlphaIndexes[AlphaHash(Tag)] != 0;} + inline void Get(const char *&Start,const char *&Stop,unsigned int I) const {Start = Section + Indexes[I]; Stop = Section + Indexes[I+1];} diff --git a/debian/changelog b/debian/changelog index 142577e42..415a6fd8d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,6 +6,9 @@ apt (0.7.26) UNRELEASED; urgency=low [ David Kalnischkies ] * Switch to dpkg-source 3.0 (native) format + * apt-pkg/depcache.cc: + - remove Auto-Installed information from extended_states + together with the package itself (Closes: #572364) * cmdline/apt-mark: - don't crash if no arguments are given (Closes: #570962) * debian/control: -- cgit v1.2.3-70-g09d2