From a8ef7efd6df81d4fb9e52419695f10df9fe76cda Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 10 Jun 2010 13:09:23 +0200 Subject: * apt-pkg/cacheset.cc: - get the candidate either from an already built depcache or use the policy which is a bit faster than depcache generation --- apt-pkg/cachefile.h | 8 ++++++-- apt-pkg/cacheset.cc | 11 ++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cachefile.h b/apt-pkg/cachefile.h index 1647aff8e..c68f06ed8 100644 --- a/apt-pkg/cachefile.h +++ b/apt-pkg/cachefile.h @@ -20,10 +20,9 @@ #include #include +#include #include -class pkgPolicy; -class pkgSourceList; class pkgCacheFile { protected: @@ -65,6 +64,11 @@ class pkgCacheFile inline pkgPolicy* GetPolicy() { BuildPolicy(); return Policy; }; inline pkgSourceList* GetSourceList() { BuildSourceList(); return SrcList; }; + inline bool IsPkgCacheBuilt() const { return (Cache != NULL); }; + inline bool IsDepCacheBuilt() const { return (DCache != NULL); }; + inline bool IsPolicyBuilt() const { return (Policy != NULL); }; + inline bool IsSrcListBuilt() const { return (SrcList != NULL); }; + pkgCacheFile(); virtual ~pkgCacheFile(); }; diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 43ade4b4e..e91b56997 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -261,9 +261,14 @@ bool VersionSet::AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset, // getCandidateVer - Returns the candidate version of the given package /*{{{*/ pkgCache::VerIterator VersionSet::getCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg, bool const &AllowError) { - if (unlikely(Cache.BuildDepCache() == false)) - return pkgCache::VerIterator(*Cache); - pkgCache::VerIterator Cand = Cache[Pkg].CandidateVerIter(Cache); + pkgCache::VerIterator Cand; + if (Cache.IsDepCacheBuilt() == true) + Cand = Cache[Pkg].CandidateVerIter(Cache); + else { + if (unlikely(Cache.BuildPolicy() == false)) + return pkgCache::VerIterator(*Cache); + Cand = Cache.GetPolicy()->GetCandidateVer(Pkg); + } if (AllowError == false && Cand.end() == true) _error->Error(_("Can't select candidate version from package %s as it has no candidate"), Pkg.FullName(true).c_str()); return Cand; -- cgit v1.2.3-70-g09d2 From c0ba35fc916d2adf0ba1fbd8cca62a83ce83d789 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 10 Jun 2010 15:10:38 +0200 Subject: * apt-pkg/orderlist.cc: - untouched packages are never missing * apt-pkg/packagemanager.cc: - packages that are not touched doesn't need to be unpacked --- apt-pkg/orderlist.cc | 3 ++- apt-pkg/packagemanager.cc | 3 ++- debian/changelog | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc index 7c950292a..55f9cb9cc 100644 --- a/apt-pkg/orderlist.cc +++ b/apt-pkg/orderlist.cc @@ -117,7 +117,8 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg) return false; // Skip Packages that need configure only. - if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && + if ((Pkg.State() == pkgCache::PkgIterator::NeedsConfigure || + Pkg.State() == pkgCache::PkgIterator::NeedsNothing) && Cache[Pkg].Keep() == true) return false; diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index eef79cccd..49776aac7 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -602,7 +602,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) // configured we don't need to unpack it again… PkgIterator const P = Pkg.Group().FindPkg("all"); if (List->IsFlag(P,pkgOrderList::UnPacked) != true && - List->IsFlag(P,pkgOrderList::Configured) != true) { + List->IsFlag(P,pkgOrderList::Configured) != true && + P.State() != pkgCache::PkgIterator::NeedsNothing) { if (SmartUnPack(P) == false) return false; } diff --git a/debian/changelog b/debian/changelog index 8470a0d85..edea3400a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,10 @@ apt (0.7.26~exp7) UNRELEASED; urgency=low * apt-pkg/cacheset.cc: - get the candidate either from an already built depcache or use the policy which is a bit faster than depcache generation + * apt-pkg/orderlist.cc: + - untouched packages are never missing + * apt-pkg/packagemanager.cc: + - packages that are not touched doesn't need to be unpacked -- David Kalnischkies Thu, 10 Jun 2010 13:04:47 +0200 -- cgit v1.2.3-70-g09d2 From 55c59998a046e8d60b5bf51772bd7db5cd43ca7c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 15 Jun 2010 20:29:50 +0200 Subject: Add a GroupedFromCommandLine for the VersionSet similar to the one for PackageSet and refactor the existing VersionSet methods to simplify that. --- apt-pkg/cacheset.cc | 123 +++++++++++++++++++++++++++++++++++----------------- apt-pkg/cacheset.h | 35 +++++++++++++++ 2 files changed, 119 insertions(+), 39 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index e91b56997..fde52168a 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -91,7 +91,7 @@ std::map PackageSet::GroupedFromCommandLine( switch(mod->Pos) { case PackageSet::Modifier::POSTFIX: if (str.compare(str.length() - alength, alength, - mod->Alias, 0, alength) != 0) + mod->Alias, 0, alength) != 0) continue; str.erase(str.length() - alength); modID = mod->ID; @@ -148,53 +148,98 @@ PackageSet PackageSet::FromString(pkgCacheFile &Cache, std::string const &str, s return regex; } /*}}}*/ +// GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/ +std::map VersionSet::GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback, std::ostream &out) { + std::map versets; + for (const char **I = cmdline; *I != 0; ++I) { + unsigned short modID = fallback; + VersionSet::Version select = VersionSet::NEWEST; + std::string str = *I; + for (std::list::const_iterator mod = mods.begin(); + mod != mods.end(); ++mod) { + if (modID == fallback && mod->ID == fallback) + select = mod->SelectVersion; + size_t const alength = strlen(mod->Alias); + switch(mod->Pos) { + case VersionSet::Modifier::POSTFIX: + if (str.compare(str.length() - alength, alength, + mod->Alias, 0, alength) != 0) + continue; + str.erase(str.length() - alength); + modID = mod->ID; + select = mod->SelectVersion; + break; + case VersionSet::Modifier::PREFIX: + continue; + case VersionSet::Modifier::NONE: + continue; + } + break; + } + VersionSet vset = VersionSet::FromString(Cache, str, select , out); + versets[modID].insert(vset.begin(), vset.end()); + } + return versets; +} + /*}}}*/ // FromCommandLine - Return all versions specified on commandline /*{{{*/ APT::VersionSet VersionSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline, APT::VersionSet::Version const &fallback, std::ostream &out) { VersionSet verset; for (const char **I = cmdline; *I != 0; ++I) { - std::string pkg = *I; - std::string ver; - bool verIsRel = false; - size_t const vertag = pkg.find_last_of("/="); - if (vertag != string::npos) { - ver = pkg.substr(vertag+1); - verIsRel = (pkg[vertag] == '/'); - pkg.erase(vertag); + VersionSet vset = VersionSet::FromString(Cache, *I, fallback, out); + verset.insert(vset.begin(), vset.end()); + } + return verset; +} + /*}}}*/ +// FromString - Returns all versions spedcified by a string /*{{{*/ +APT::VersionSet VersionSet::FromString(pkgCacheFile &Cache, std::string pkg, + APT::VersionSet::Version const &fallback, std::ostream &out) { + std::string ver; + bool verIsRel = false; + size_t const vertag = pkg.find_last_of("/="); + if (vertag != string::npos) { + ver = pkg.substr(vertag+1); + verIsRel = (pkg[vertag] == '/'); + pkg.erase(vertag); + } + PackageSet pkgset = PackageSet::FromString(Cache, pkg.c_str(), out); + VersionSet verset; + for (PackageSet::const_iterator P = pkgset.begin(); + P != pkgset.end(); ++P) { + if (vertag == string::npos) { + AddSelectedVersion(Cache, verset, P, fallback); + continue; } - PackageSet pkgset = PackageSet::FromString(Cache, pkg.c_str(), out); - for (PackageSet::const_iterator P = pkgset.begin(); - P != pkgset.end(); ++P) { - if (vertag == string::npos) { - AddSelectedVersion(Cache, verset, P, fallback); + pkgCache::VerIterator V; + if (ver == "installed") + V = getInstalledVer(Cache, P); + else if (ver == "candidate") + V = getCandidateVer(Cache, P); + else { + pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release : + pkgVersionMatch::Version)); + V = Match.Find(P); + if (V.end() == true) { + if (verIsRel == true) + _error->Error(_("Release '%s' for '%s' was not found"), + ver.c_str(), P.FullName(true).c_str()); + else + _error->Error(_("Version '%s' for '%s' was not found"), + ver.c_str(), P.FullName(true).c_str()); continue; } - pkgCache::VerIterator V; - if (ver == "installed") - V = getInstalledVer(Cache, P); - else if (ver == "candidate") - V = getCandidateVer(Cache, P); - else { - pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release : - pkgVersionMatch::Version)); - V = Match.Find(P); - if (V.end() == true) { - if (verIsRel == true) - _error->Error(_("Release '%s' for '%s' was not found"), - ver.c_str(), P.FullName(true).c_str()); - else - _error->Error(_("Version '%s' for '%s' was not found"), - ver.c_str(), P.FullName(true).c_str()); - continue; - } - } - if (V.end() == true) - continue; - if (ver == V.VerStr()) - ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"), - V.VerStr(), V.RelStr().c_str(), P.FullName(true).c_str()); - verset.insert(V); } + if (V.end() == true) + continue; + if (ver == V.VerStr()) + ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"), + V.VerStr(), V.RelStr().c_str(), P.FullName(true).c_str()); + verset.insert(V); } return verset; } diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 668d8039e..2bc268380 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -209,6 +209,41 @@ public: /*{{{*/ static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) { return APT::VersionSet::FromCommandLine(Cache, cmdline, CANDINST); } + + static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg, + APT::VersionSet::Version const &fallback, std::ostream &out); + static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg, + APT::VersionSet::Version const &fallback) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::VersionSet::FromString(Cache, pkg, fallback, out); + } + static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg) { + return APT::VersionSet::FromString(Cache, pkg, CANDINST); + } + + struct Modifier { + enum Position { NONE, PREFIX, POSTFIX }; + unsigned short ID; + const char * const Alias; + Position Pos; + VersionSet::Version SelectVersion; + Modifier (unsigned short const &id, const char * const alias, Position const &pos, + VersionSet::Version const &select) : ID(id), Alias(alias), Pos(pos), + SelectVersion(select) {}; + }; + + static std::map GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback, std::ostream &out); + static std::map GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::VersionSet::GroupedFromCommandLine(Cache, cmdline, + mods, fallback, out); + } /*}}}*/ protected: /*{{{*/ -- cgit v1.2.3-70-g09d2 From d8276801a1c84582a85ed9ea1f2eb4e66e052e6b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 15 Jun 2010 20:46:09 +0200 Subject: * cmdline/cacheset.cc: - doesn't include it in the library for now as it is too volatile --- apt-pkg/cacheset.cc | 330 ---------------------------------------------------- apt-pkg/cacheset.h | 274 ------------------------------------------- apt-pkg/makefile | 5 +- cmdline/cacheset.cc | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++++ cmdline/cacheset.h | 274 +++++++++++++++++++++++++++++++++++++++++++ cmdline/makefile | 4 +- debian/changelog | 3 +- 7 files changed, 610 insertions(+), 610 deletions(-) delete mode 100644 apt-pkg/cacheset.cc delete mode 100644 apt-pkg/cacheset.h create mode 100644 cmdline/cacheset.cc create mode 100644 cmdline/cacheset.h (limited to 'apt-pkg') diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc deleted file mode 100644 index fde52168a..000000000 --- a/apt-pkg/cacheset.cc +++ /dev/null @@ -1,330 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -/* ###################################################################### - - Simple wrapper around a std::set to provide a similar interface to - a set of cache structures as to the complete set of all structures - in the pkgCache. Currently only Package is supported. - - ##################################################################### */ - /*}}}*/ -// Include Files /*{{{*/ -#include -#include -#include -#include -#include - -#include - -#include - -#include - /*}}}*/ -namespace APT { -// FromRegEx - Return all packages in the cache matching a pattern /*{{{*/ -PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out) { - PackageSet pkgset; - std::string arch = "native"; - static const char * const isregex = ".?+*|[^$"; - - if (pattern.find_first_of(isregex) == std::string::npos) - return pkgset; - - size_t archfound = pattern.find_last_of(':'); - if (archfound != std::string::npos) { - arch = pattern.substr(archfound+1); - if (arch.find_first_of(isregex) == std::string::npos) - pattern.erase(archfound); - else - arch = "native"; - } - - regex_t Pattern; - int Res; - if ((Res = regcomp(&Pattern, pattern.c_str() , REG_EXTENDED | REG_ICASE | REG_NOSUB)) != 0) { - char Error[300]; - regerror(Res, &Pattern, Error, sizeof(Error)); - _error->Error(_("Regex compilation error - %s"), Error); - return pkgset; - } - - for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp) - { - if (regexec(&Pattern, Grp.Name(), 0, 0, 0) != 0) - continue; - pkgCache::PkgIterator Pkg = Grp.FindPkg(arch); - if (Pkg.end() == true) { - if (archfound == std::string::npos) { - std::vector archs = APT::Configuration::getArchitectures(); - for (std::vector::const_iterator a = archs.begin(); - a != archs.end() && Pkg.end() != true; ++a) - Pkg = Grp.FindPkg(*a); - } - if (Pkg.end() == true) - continue; - } - - ioprintf(out, _("Note, selecting %s for regex '%s'\n"), - Pkg.FullName(true).c_str(), pattern.c_str()); - - pkgset.insert(Pkg); - } - - regfree(&Pattern); - - return pkgset; -} - /*}}}*/ -// GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/ -std::map PackageSet::GroupedFromCommandLine( - pkgCacheFile &Cache, const char **cmdline, - std::list const &mods, - unsigned short const &fallback, std::ostream &out) { - std::map pkgsets; - for (const char **I = cmdline; *I != 0; ++I) { - unsigned short modID = fallback; - std::string str = *I; - for (std::list::const_iterator mod = mods.begin(); - mod != mods.end(); ++mod) { - size_t const alength = strlen(mod->Alias); - switch(mod->Pos) { - case PackageSet::Modifier::POSTFIX: - if (str.compare(str.length() - alength, alength, - mod->Alias, 0, alength) != 0) - continue; - str.erase(str.length() - alength); - modID = mod->ID; - break; - case PackageSet::Modifier::PREFIX: - continue; - case PackageSet::Modifier::NONE: - continue; - } - break; - } - PackageSet pset = PackageSet::FromString(Cache, str, out); - pkgsets[modID].insert(pset.begin(), pset.end()); - } - return pkgsets; -} - /*}}}*/ -// FromCommandLine - Return all packages specified on commandline /*{{{*/ -PackageSet PackageSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out) { - PackageSet pkgset; - for (const char **I = cmdline; *I != 0; ++I) { - PackageSet pset = FromString(Cache, *I, out); - pkgset.insert(pset.begin(), pset.end()); - } - return pkgset; -} - /*}}}*/ -// FromString - Return all packages matching a specific string /*{{{*/ -PackageSet PackageSet::FromString(pkgCacheFile &Cache, std::string const &str, std::ostream &out) { - std::string pkg = str; - size_t archfound = pkg.find_last_of(':'); - std::string arch; - if (archfound != std::string::npos) { - arch = pkg.substr(archfound+1); - pkg.erase(archfound); - } - - pkgCache::PkgIterator Pkg; - if (arch.empty() == true) { - pkgCache::GrpIterator Grp = Cache.GetPkgCache()->FindGrp(pkg); - if (Grp.end() == false) - Pkg = Grp.FindPreferredPkg(); - } else - Pkg = Cache.GetPkgCache()->FindPkg(pkg, arch); - - if (Pkg.end() == false) { - PackageSet pkgset; - pkgset.insert(Pkg); - return pkgset; - } - PackageSet regex = FromRegEx(Cache, str, out); - if (regex.empty() == true) - _error->Warning(_("Unable to locate package %s"), str.c_str()); - return regex; -} - /*}}}*/ -// GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/ -std::map VersionSet::GroupedFromCommandLine( - pkgCacheFile &Cache, const char **cmdline, - std::list const &mods, - unsigned short const &fallback, std::ostream &out) { - std::map versets; - for (const char **I = cmdline; *I != 0; ++I) { - unsigned short modID = fallback; - VersionSet::Version select = VersionSet::NEWEST; - std::string str = *I; - for (std::list::const_iterator mod = mods.begin(); - mod != mods.end(); ++mod) { - if (modID == fallback && mod->ID == fallback) - select = mod->SelectVersion; - size_t const alength = strlen(mod->Alias); - switch(mod->Pos) { - case VersionSet::Modifier::POSTFIX: - if (str.compare(str.length() - alength, alength, - mod->Alias, 0, alength) != 0) - continue; - str.erase(str.length() - alength); - modID = mod->ID; - select = mod->SelectVersion; - break; - case VersionSet::Modifier::PREFIX: - continue; - case VersionSet::Modifier::NONE: - continue; - } - break; - } - VersionSet vset = VersionSet::FromString(Cache, str, select , out); - versets[modID].insert(vset.begin(), vset.end()); - } - return versets; -} - /*}}}*/ -// FromCommandLine - Return all versions specified on commandline /*{{{*/ -APT::VersionSet VersionSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline, - APT::VersionSet::Version const &fallback, std::ostream &out) { - VersionSet verset; - for (const char **I = cmdline; *I != 0; ++I) { - VersionSet vset = VersionSet::FromString(Cache, *I, fallback, out); - verset.insert(vset.begin(), vset.end()); - } - return verset; -} - /*}}}*/ -// FromString - Returns all versions spedcified by a string /*{{{*/ -APT::VersionSet VersionSet::FromString(pkgCacheFile &Cache, std::string pkg, - APT::VersionSet::Version const &fallback, std::ostream &out) { - std::string ver; - bool verIsRel = false; - size_t const vertag = pkg.find_last_of("/="); - if (vertag != string::npos) { - ver = pkg.substr(vertag+1); - verIsRel = (pkg[vertag] == '/'); - pkg.erase(vertag); - } - PackageSet pkgset = PackageSet::FromString(Cache, pkg.c_str(), out); - VersionSet verset; - for (PackageSet::const_iterator P = pkgset.begin(); - P != pkgset.end(); ++P) { - if (vertag == string::npos) { - AddSelectedVersion(Cache, verset, P, fallback); - continue; - } - pkgCache::VerIterator V; - if (ver == "installed") - V = getInstalledVer(Cache, P); - else if (ver == "candidate") - V = getCandidateVer(Cache, P); - else { - pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release : - pkgVersionMatch::Version)); - V = Match.Find(P); - if (V.end() == true) { - if (verIsRel == true) - _error->Error(_("Release '%s' for '%s' was not found"), - ver.c_str(), P.FullName(true).c_str()); - else - _error->Error(_("Version '%s' for '%s' was not found"), - ver.c_str(), P.FullName(true).c_str()); - continue; - } - } - if (V.end() == true) - continue; - if (ver == V.VerStr()) - ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"), - V.VerStr(), V.RelStr().c_str(), P.FullName(true).c_str()); - verset.insert(V); - } - return verset; -} - /*}}}*/ -// AddSelectedVersion - add version from package based on fallback /*{{{*/ -bool VersionSet::AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset, - pkgCache::PkgIterator const &P, VersionSet::Version const &fallback, - bool const &AllowError) { - pkgCache::VerIterator V; - switch(fallback) { - case VersionSet::ALL: - if (P->VersionList != 0) - for (V = P.VersionList(); V.end() != true; ++V) - verset.insert(V); - else if (AllowError == false) - return _error->Error(_("Can't select versions from package '%s' as it purely virtual"), P.FullName(true).c_str()); - else - return false; - break; - case VersionSet::CANDANDINST: - verset.insert(getInstalledVer(Cache, P, AllowError)); - verset.insert(getCandidateVer(Cache, P, AllowError)); - break; - case VersionSet::CANDIDATE: - verset.insert(getCandidateVer(Cache, P, AllowError)); - break; - case VersionSet::INSTALLED: - verset.insert(getInstalledVer(Cache, P, AllowError)); - break; - case VersionSet::CANDINST: - V = getCandidateVer(Cache, P, true); - if (V.end() == true) - V = getInstalledVer(Cache, P, true); - if (V.end() == false) - verset.insert(V); - else if (AllowError == false) - return _error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), P.FullName(true).c_str()); - else - return false; - break; - case VersionSet::INSTCAND: - V = getInstalledVer(Cache, P, true); - if (V.end() == true) - V = getCandidateVer(Cache, P, true); - if (V.end() == false) - verset.insert(V); - else if (AllowError == false) - return _error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), P.FullName(true).c_str()); - else - return false; - break; - case VersionSet::NEWEST: - if (P->VersionList != 0) - verset.insert(P.VersionList()); - else if (AllowError == false) - return _error->Error(_("Can't select newest version from package '%s' as it is purely virtual"), P.FullName(true).c_str()); - else - return false; - break; - } - return true; -} - /*}}}*/ -// getCandidateVer - Returns the candidate version of the given package /*{{{*/ -pkgCache::VerIterator VersionSet::getCandidateVer(pkgCacheFile &Cache, - pkgCache::PkgIterator const &Pkg, bool const &AllowError) { - pkgCache::VerIterator Cand; - if (Cache.IsDepCacheBuilt() == true) - Cand = Cache[Pkg].CandidateVerIter(Cache); - else { - if (unlikely(Cache.BuildPolicy() == false)) - return pkgCache::VerIterator(*Cache); - Cand = Cache.GetPolicy()->GetCandidateVer(Pkg); - } - if (AllowError == false && Cand.end() == true) - _error->Error(_("Can't select candidate version from package %s as it has no candidate"), Pkg.FullName(true).c_str()); - return Cand; -} - /*}}}*/ -// getInstalledVer - Returns the installed version of the given package /*{{{*/ -pkgCache::VerIterator VersionSet::getInstalledVer(pkgCacheFile &Cache, - pkgCache::PkgIterator const &Pkg, bool const &AllowError) { - if (AllowError == false && Pkg->CurrentVer == 0) - _error->Error(_("Can't select installed version from package %s as it is not installed"), Pkg.FullName(true).c_str()); - return Pkg.CurrentVer(); -} - /*}}}*/ -} diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h deleted file mode 100644 index 2bc268380..000000000 --- a/apt-pkg/cacheset.h +++ /dev/null @@ -1,274 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -/** \file cacheset.h - Wrappers around std::set to have set::iterators which behave - similar to the Iterators of the cache structures. - - Provides also a few helper methods which work with these sets */ - /*}}}*/ -#ifndef APT_CACHESET_H -#define APT_CACHESET_H -// Include Files /*{{{*/ -#include -#include -#include -#include -#include -#include - -#include -#include - /*}}}*/ -namespace APT { -class PackageSet : public std::set { /*{{{*/ -/** \class APT::PackageSet - - Simple wrapper around a std::set to provide a similar interface to - a set of packages as to the complete set of all packages in the - pkgCache. */ -public: /*{{{*/ - /** \brief smell like a pkgCache::PkgIterator */ - class const_iterator : public std::set::const_iterator { - public: - const_iterator(std::set::const_iterator x) : - std::set::const_iterator(x) {} - - operator pkgCache::PkgIterator(void) { return **this; } - - inline const char *Name() const {return (**this).Name(); } - inline std::string FullName(bool const &Pretty) const { return (**this).FullName(Pretty); } - inline std::string FullName() const { return (**this).FullName(); } - inline const char *Section() const {return (**this).Section(); } - inline bool Purge() const {return (**this).Purge(); } - inline const char *Arch() const {return (**this).Arch(); } - inline pkgCache::GrpIterator Group() const { return (**this).Group(); } - inline pkgCache::VerIterator VersionList() const { return (**this).VersionList(); } - inline pkgCache::VerIterator CurrentVer() const { return (**this).CurrentVer(); } - inline pkgCache::DepIterator RevDependsList() const { return (**this).RevDependsList(); } - inline pkgCache::PrvIterator ProvidesList() const { return (**this).ProvidesList(); } - inline pkgCache::PkgIterator::OkState State() const { return (**this).State(); } - inline const char *CandVersion() const { return (**this).CandVersion(); } - inline const char *CurVersion() const { return (**this).CurVersion(); } - inline pkgCache *Cache() const { return (**this).Cache(); }; - inline unsigned long Index() const {return (**this).Index();}; - // we have only valid iterators here - inline bool end() const { return false; }; - - friend std::ostream& operator<<(std::ostream& out, const_iterator i) { return operator<<(out, (*i)); } - - inline pkgCache::Package const * operator->() const { - return &***this; - }; - }; - // 103. set::iterator is required to be modifiable, but this allows modification of keys - typedef APT::PackageSet::const_iterator iterator; - - using std::set::insert; - inline void insert(pkgCache::PkgIterator const &P) { if (P.end() == false) std::set::insert(P); }; - - /** \brief returns all packages in the cache whose name matchs a given pattern - - A simple helper responsible for executing a regular expression on all - package names in the cache. Optional it prints a a notice about the - packages chosen cause of the given package. - \param Cache the packages are in - \param pattern regular expression for package names - \param out stream to print the notice to */ - static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out); - static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string const &pattern) { - std::ostream out (std::ofstream("/dev/null").rdbuf()); - return APT::PackageSet::FromRegEx(Cache, pattern, out); - } - - /** \brief returns all packages specified by a string - - \param Cache the packages are in - \param string String the package name(s) should be extracted from - \param out stream to print various notices to */ - static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string, std::ostream &out); - static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string) { - std::ostream out (std::ofstream("/dev/null").rdbuf()); - return APT::PackageSet::FromString(Cache, string, out); - } - - /** \brief returns all packages specified on the commandline - - Get all package names from the commandline and executes regex's if needed. - No special package command is supported, just plain names. - \param Cache the packages are in - \param cmdline Command line the package names should be extracted from - \param out stream to print various notices to */ - static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out); - static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) { - std::ostream out (std::ofstream("/dev/null").rdbuf()); - return APT::PackageSet::FromCommandLine(Cache, cmdline, out); - } - - struct Modifier { - enum Position { NONE, PREFIX, POSTFIX }; - unsigned short ID; - const char * const Alias; - Position Pos; - Modifier (unsigned short const &id, const char * const alias, Position const &pos) : ID(id), Alias(alias), Pos(pos) {}; - }; - - static std::map GroupedFromCommandLine( - pkgCacheFile &Cache, const char **cmdline, - std::list const &mods, - unsigned short const &fallback, std::ostream &out); - static std::map GroupedFromCommandLine( - pkgCacheFile &Cache, const char **cmdline, - std::list const &mods, - unsigned short const &fallback) { - std::ostream out (std::ofstream("/dev/null").rdbuf()); - return APT::PackageSet::GroupedFromCommandLine(Cache, cmdline, - mods, fallback, out); - } - /*}}}*/ -}; /*}}}*/ -class VersionSet : public std::set { /*{{{*/ -/** \class APT::VersionSet - - Simple wrapper around a std::set to provide a similar interface to - a set of versions as to the complete set of all versions in the - pkgCache. */ -public: /*{{{*/ - /** \brief smell like a pkgCache::VerIterator */ - class const_iterator : public std::set::const_iterator { - public: - const_iterator(std::set::const_iterator x) : - std::set::const_iterator(x) {} - - operator pkgCache::VerIterator(void) { return **this; } - - inline pkgCache *Cache() const { return (**this).Cache(); }; - inline unsigned long Index() const {return (**this).Index();}; - // we have only valid iterators here - inline bool end() const { return false; }; - - inline pkgCache::Version const * operator->() const { - return &***this; - }; - - inline int CompareVer(const pkgCache::VerIterator &B) const { return (**this).CompareVer(B); }; - inline const char *VerStr() const { return (**this).VerStr(); }; - inline const char *Section() const { return (**this).Section(); }; - inline const char *Arch() const { return (**this).Arch(); }; - inline const char *Arch(bool const pseudo) const { return (**this).Arch(pseudo); }; - inline pkgCache::PkgIterator ParentPkg() const { return (**this).ParentPkg(); }; - inline pkgCache::DescIterator DescriptionList() const { return (**this).DescriptionList(); }; - inline pkgCache::DescIterator TranslatedDescription() const { return (**this).TranslatedDescription(); }; - inline pkgCache::DepIterator DependsList() const { return (**this).DependsList(); }; - inline pkgCache::PrvIterator ProvidesList() const { return (**this).ProvidesList(); }; - inline pkgCache::VerFileIterator FileList() const { return (**this).FileList(); }; - inline bool Downloadable() const { return (**this).Downloadable(); }; - inline const char *PriorityType() const { return (**this).PriorityType(); }; - inline string RelStr() const { return (**this).RelStr(); }; - inline bool Automatic() const { return (**this).Automatic(); }; - inline bool Pseudo() const { return (**this).Pseudo(); }; - inline pkgCache::VerFileIterator NewestFile() const { return (**this).NewestFile(); }; - }; - // 103. set::iterator is required to be modifiable, but this allows modification of keys - typedef APT::VersionSet::const_iterator iterator; - - using std::set::insert; - inline void insert(pkgCache::VerIterator const &V) { if (V.end() == false) std::set::insert(V); }; - - /** \brief specifies which version(s) will be returned if non is given */ - enum Version { - /** All versions */ - ALL, - /** Candidate and installed version */ - CANDANDINST, - /** Candidate version */ - CANDIDATE, - /** Installed version */ - INSTALLED, - /** Candidate or if non installed version */ - CANDINST, - /** Installed or if non candidate version */ - INSTCAND, - /** Newest version */ - NEWEST - }; - - /** \brief returns all versions specified on the commandline - - Get all versions from the commandline, uses given default version if - non specifically requested and executes regex's if needed on names. - \param Cache the packages and versions are in - \param cmdline Command line the versions should be extracted from - \param out stream to print various notices to */ - static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, - APT::VersionSet::Version const &fallback, std::ostream &out); - static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, - APT::VersionSet::Version const &fallback) { - std::ostream out (std::ofstream("/dev/null").rdbuf()); - return APT::VersionSet::FromCommandLine(Cache, cmdline, fallback, out); - } - static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) { - return APT::VersionSet::FromCommandLine(Cache, cmdline, CANDINST); - } - - static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg, - APT::VersionSet::Version const &fallback, std::ostream &out); - static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg, - APT::VersionSet::Version const &fallback) { - std::ostream out (std::ofstream("/dev/null").rdbuf()); - return APT::VersionSet::FromString(Cache, pkg, fallback, out); - } - static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg) { - return APT::VersionSet::FromString(Cache, pkg, CANDINST); - } - - struct Modifier { - enum Position { NONE, PREFIX, POSTFIX }; - unsigned short ID; - const char * const Alias; - Position Pos; - VersionSet::Version SelectVersion; - Modifier (unsigned short const &id, const char * const alias, Position const &pos, - VersionSet::Version const &select) : ID(id), Alias(alias), Pos(pos), - SelectVersion(select) {}; - }; - - static std::map GroupedFromCommandLine( - pkgCacheFile &Cache, const char **cmdline, - std::list const &mods, - unsigned short const &fallback, std::ostream &out); - static std::map GroupedFromCommandLine( - pkgCacheFile &Cache, const char **cmdline, - std::list const &mods, - unsigned short const &fallback) { - std::ostream out (std::ofstream("/dev/null").rdbuf()); - return APT::VersionSet::GroupedFromCommandLine(Cache, cmdline, - mods, fallback, out); - } - /*}}}*/ -protected: /*{{{*/ - - /** \brief returns the candidate version of the package - - \param Cache to be used to query for information - \param Pkg we want the candidate version from this package - \param AllowError add an error to the stack if not */ - static pkgCache::VerIterator getCandidateVer(pkgCacheFile &Cache, - pkgCache::PkgIterator const &Pkg, bool const &AllowError = false); - - /** \brief returns the installed version of the package - - \param Cache to be used to query for information - \param Pkg we want the installed version from this package - \param AllowError add an error to the stack if not */ - static pkgCache::VerIterator getInstalledVer(pkgCacheFile &Cache, - pkgCache::PkgIterator const &Pkg, bool const &AllowError = false); - - - static bool AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset, - pkgCache::PkgIterator const &P, VersionSet::Version const &fallback, - bool const &AllowError = false); - - /*}}}*/ -}; /*}}}*/ -} -#endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 1a7078693..a5be462ce 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -35,15 +35,14 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ srcrecords.cc cachefile.cc versionmatch.cc policy.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ - aptconfiguration.cc cacheset.cc + aptconfiguration.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ acquire.h acquire-worker.h acquire-item.h acquire-method.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ - vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cacheset.h + vendorlist.h cdrom.h indexcopy.h aptconfiguration.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. diff --git a/cmdline/cacheset.cc b/cmdline/cacheset.cc new file mode 100644 index 000000000..fde52168a --- /dev/null +++ b/cmdline/cacheset.cc @@ -0,0 +1,330 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Simple wrapper around a std::set to provide a similar interface to + a set of cache structures as to the complete set of all structures + in the pkgCache. Currently only Package is supported. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include +#include + +#include + +#include + +#include + /*}}}*/ +namespace APT { +// FromRegEx - Return all packages in the cache matching a pattern /*{{{*/ +PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out) { + PackageSet pkgset; + std::string arch = "native"; + static const char * const isregex = ".?+*|[^$"; + + if (pattern.find_first_of(isregex) == std::string::npos) + return pkgset; + + size_t archfound = pattern.find_last_of(':'); + if (archfound != std::string::npos) { + arch = pattern.substr(archfound+1); + if (arch.find_first_of(isregex) == std::string::npos) + pattern.erase(archfound); + else + arch = "native"; + } + + regex_t Pattern; + int Res; + if ((Res = regcomp(&Pattern, pattern.c_str() , REG_EXTENDED | REG_ICASE | REG_NOSUB)) != 0) { + char Error[300]; + regerror(Res, &Pattern, Error, sizeof(Error)); + _error->Error(_("Regex compilation error - %s"), Error); + return pkgset; + } + + for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp) + { + if (regexec(&Pattern, Grp.Name(), 0, 0, 0) != 0) + continue; + pkgCache::PkgIterator Pkg = Grp.FindPkg(arch); + if (Pkg.end() == true) { + if (archfound == std::string::npos) { + std::vector archs = APT::Configuration::getArchitectures(); + for (std::vector::const_iterator a = archs.begin(); + a != archs.end() && Pkg.end() != true; ++a) + Pkg = Grp.FindPkg(*a); + } + if (Pkg.end() == true) + continue; + } + + ioprintf(out, _("Note, selecting %s for regex '%s'\n"), + Pkg.FullName(true).c_str(), pattern.c_str()); + + pkgset.insert(Pkg); + } + + regfree(&Pattern); + + return pkgset; +} + /*}}}*/ +// GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/ +std::map PackageSet::GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback, std::ostream &out) { + std::map pkgsets; + for (const char **I = cmdline; *I != 0; ++I) { + unsigned short modID = fallback; + std::string str = *I; + for (std::list::const_iterator mod = mods.begin(); + mod != mods.end(); ++mod) { + size_t const alength = strlen(mod->Alias); + switch(mod->Pos) { + case PackageSet::Modifier::POSTFIX: + if (str.compare(str.length() - alength, alength, + mod->Alias, 0, alength) != 0) + continue; + str.erase(str.length() - alength); + modID = mod->ID; + break; + case PackageSet::Modifier::PREFIX: + continue; + case PackageSet::Modifier::NONE: + continue; + } + break; + } + PackageSet pset = PackageSet::FromString(Cache, str, out); + pkgsets[modID].insert(pset.begin(), pset.end()); + } + return pkgsets; +} + /*}}}*/ +// FromCommandLine - Return all packages specified on commandline /*{{{*/ +PackageSet PackageSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out) { + PackageSet pkgset; + for (const char **I = cmdline; *I != 0; ++I) { + PackageSet pset = FromString(Cache, *I, out); + pkgset.insert(pset.begin(), pset.end()); + } + return pkgset; +} + /*}}}*/ +// FromString - Return all packages matching a specific string /*{{{*/ +PackageSet PackageSet::FromString(pkgCacheFile &Cache, std::string const &str, std::ostream &out) { + std::string pkg = str; + size_t archfound = pkg.find_last_of(':'); + std::string arch; + if (archfound != std::string::npos) { + arch = pkg.substr(archfound+1); + pkg.erase(archfound); + } + + pkgCache::PkgIterator Pkg; + if (arch.empty() == true) { + pkgCache::GrpIterator Grp = Cache.GetPkgCache()->FindGrp(pkg); + if (Grp.end() == false) + Pkg = Grp.FindPreferredPkg(); + } else + Pkg = Cache.GetPkgCache()->FindPkg(pkg, arch); + + if (Pkg.end() == false) { + PackageSet pkgset; + pkgset.insert(Pkg); + return pkgset; + } + PackageSet regex = FromRegEx(Cache, str, out); + if (regex.empty() == true) + _error->Warning(_("Unable to locate package %s"), str.c_str()); + return regex; +} + /*}}}*/ +// GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/ +std::map VersionSet::GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback, std::ostream &out) { + std::map versets; + for (const char **I = cmdline; *I != 0; ++I) { + unsigned short modID = fallback; + VersionSet::Version select = VersionSet::NEWEST; + std::string str = *I; + for (std::list::const_iterator mod = mods.begin(); + mod != mods.end(); ++mod) { + if (modID == fallback && mod->ID == fallback) + select = mod->SelectVersion; + size_t const alength = strlen(mod->Alias); + switch(mod->Pos) { + case VersionSet::Modifier::POSTFIX: + if (str.compare(str.length() - alength, alength, + mod->Alias, 0, alength) != 0) + continue; + str.erase(str.length() - alength); + modID = mod->ID; + select = mod->SelectVersion; + break; + case VersionSet::Modifier::PREFIX: + continue; + case VersionSet::Modifier::NONE: + continue; + } + break; + } + VersionSet vset = VersionSet::FromString(Cache, str, select , out); + versets[modID].insert(vset.begin(), vset.end()); + } + return versets; +} + /*}}}*/ +// FromCommandLine - Return all versions specified on commandline /*{{{*/ +APT::VersionSet VersionSet::FromCommandLine(pkgCacheFile &Cache, const char **cmdline, + APT::VersionSet::Version const &fallback, std::ostream &out) { + VersionSet verset; + for (const char **I = cmdline; *I != 0; ++I) { + VersionSet vset = VersionSet::FromString(Cache, *I, fallback, out); + verset.insert(vset.begin(), vset.end()); + } + return verset; +} + /*}}}*/ +// FromString - Returns all versions spedcified by a string /*{{{*/ +APT::VersionSet VersionSet::FromString(pkgCacheFile &Cache, std::string pkg, + APT::VersionSet::Version const &fallback, std::ostream &out) { + std::string ver; + bool verIsRel = false; + size_t const vertag = pkg.find_last_of("/="); + if (vertag != string::npos) { + ver = pkg.substr(vertag+1); + verIsRel = (pkg[vertag] == '/'); + pkg.erase(vertag); + } + PackageSet pkgset = PackageSet::FromString(Cache, pkg.c_str(), out); + VersionSet verset; + for (PackageSet::const_iterator P = pkgset.begin(); + P != pkgset.end(); ++P) { + if (vertag == string::npos) { + AddSelectedVersion(Cache, verset, P, fallback); + continue; + } + pkgCache::VerIterator V; + if (ver == "installed") + V = getInstalledVer(Cache, P); + else if (ver == "candidate") + V = getCandidateVer(Cache, P); + else { + pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release : + pkgVersionMatch::Version)); + V = Match.Find(P); + if (V.end() == true) { + if (verIsRel == true) + _error->Error(_("Release '%s' for '%s' was not found"), + ver.c_str(), P.FullName(true).c_str()); + else + _error->Error(_("Version '%s' for '%s' was not found"), + ver.c_str(), P.FullName(true).c_str()); + continue; + } + } + if (V.end() == true) + continue; + if (ver == V.VerStr()) + ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"), + V.VerStr(), V.RelStr().c_str(), P.FullName(true).c_str()); + verset.insert(V); + } + return verset; +} + /*}}}*/ +// AddSelectedVersion - add version from package based on fallback /*{{{*/ +bool VersionSet::AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset, + pkgCache::PkgIterator const &P, VersionSet::Version const &fallback, + bool const &AllowError) { + pkgCache::VerIterator V; + switch(fallback) { + case VersionSet::ALL: + if (P->VersionList != 0) + for (V = P.VersionList(); V.end() != true; ++V) + verset.insert(V); + else if (AllowError == false) + return _error->Error(_("Can't select versions from package '%s' as it purely virtual"), P.FullName(true).c_str()); + else + return false; + break; + case VersionSet::CANDANDINST: + verset.insert(getInstalledVer(Cache, P, AllowError)); + verset.insert(getCandidateVer(Cache, P, AllowError)); + break; + case VersionSet::CANDIDATE: + verset.insert(getCandidateVer(Cache, P, AllowError)); + break; + case VersionSet::INSTALLED: + verset.insert(getInstalledVer(Cache, P, AllowError)); + break; + case VersionSet::CANDINST: + V = getCandidateVer(Cache, P, true); + if (V.end() == true) + V = getInstalledVer(Cache, P, true); + if (V.end() == false) + verset.insert(V); + else if (AllowError == false) + return _error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), P.FullName(true).c_str()); + else + return false; + break; + case VersionSet::INSTCAND: + V = getInstalledVer(Cache, P, true); + if (V.end() == true) + V = getCandidateVer(Cache, P, true); + if (V.end() == false) + verset.insert(V); + else if (AllowError == false) + return _error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), P.FullName(true).c_str()); + else + return false; + break; + case VersionSet::NEWEST: + if (P->VersionList != 0) + verset.insert(P.VersionList()); + else if (AllowError == false) + return _error->Error(_("Can't select newest version from package '%s' as it is purely virtual"), P.FullName(true).c_str()); + else + return false; + break; + } + return true; +} + /*}}}*/ +// getCandidateVer - Returns the candidate version of the given package /*{{{*/ +pkgCache::VerIterator VersionSet::getCandidateVer(pkgCacheFile &Cache, + pkgCache::PkgIterator const &Pkg, bool const &AllowError) { + pkgCache::VerIterator Cand; + if (Cache.IsDepCacheBuilt() == true) + Cand = Cache[Pkg].CandidateVerIter(Cache); + else { + if (unlikely(Cache.BuildPolicy() == false)) + return pkgCache::VerIterator(*Cache); + Cand = Cache.GetPolicy()->GetCandidateVer(Pkg); + } + if (AllowError == false && Cand.end() == true) + _error->Error(_("Can't select candidate version from package %s as it has no candidate"), Pkg.FullName(true).c_str()); + return Cand; +} + /*}}}*/ +// getInstalledVer - Returns the installed version of the given package /*{{{*/ +pkgCache::VerIterator VersionSet::getInstalledVer(pkgCacheFile &Cache, + pkgCache::PkgIterator const &Pkg, bool const &AllowError) { + if (AllowError == false && Pkg->CurrentVer == 0) + _error->Error(_("Can't select installed version from package %s as it is not installed"), Pkg.FullName(true).c_str()); + return Pkg.CurrentVer(); +} + /*}}}*/ +} diff --git a/cmdline/cacheset.h b/cmdline/cacheset.h new file mode 100644 index 000000000..2bc268380 --- /dev/null +++ b/cmdline/cacheset.h @@ -0,0 +1,274 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/** \file cacheset.h + Wrappers around std::set to have set::iterators which behave + similar to the Iterators of the cache structures. + + Provides also a few helper methods which work with these sets */ + /*}}}*/ +#ifndef APT_CACHESET_H +#define APT_CACHESET_H +// Include Files /*{{{*/ +#include +#include +#include +#include +#include +#include + +#include +#include + /*}}}*/ +namespace APT { +class PackageSet : public std::set { /*{{{*/ +/** \class APT::PackageSet + + Simple wrapper around a std::set to provide a similar interface to + a set of packages as to the complete set of all packages in the + pkgCache. */ +public: /*{{{*/ + /** \brief smell like a pkgCache::PkgIterator */ + class const_iterator : public std::set::const_iterator { + public: + const_iterator(std::set::const_iterator x) : + std::set::const_iterator(x) {} + + operator pkgCache::PkgIterator(void) { return **this; } + + inline const char *Name() const {return (**this).Name(); } + inline std::string FullName(bool const &Pretty) const { return (**this).FullName(Pretty); } + inline std::string FullName() const { return (**this).FullName(); } + inline const char *Section() const {return (**this).Section(); } + inline bool Purge() const {return (**this).Purge(); } + inline const char *Arch() const {return (**this).Arch(); } + inline pkgCache::GrpIterator Group() const { return (**this).Group(); } + inline pkgCache::VerIterator VersionList() const { return (**this).VersionList(); } + inline pkgCache::VerIterator CurrentVer() const { return (**this).CurrentVer(); } + inline pkgCache::DepIterator RevDependsList() const { return (**this).RevDependsList(); } + inline pkgCache::PrvIterator ProvidesList() const { return (**this).ProvidesList(); } + inline pkgCache::PkgIterator::OkState State() const { return (**this).State(); } + inline const char *CandVersion() const { return (**this).CandVersion(); } + inline const char *CurVersion() const { return (**this).CurVersion(); } + inline pkgCache *Cache() const { return (**this).Cache(); }; + inline unsigned long Index() const {return (**this).Index();}; + // we have only valid iterators here + inline bool end() const { return false; }; + + friend std::ostream& operator<<(std::ostream& out, const_iterator i) { return operator<<(out, (*i)); } + + inline pkgCache::Package const * operator->() const { + return &***this; + }; + }; + // 103. set::iterator is required to be modifiable, but this allows modification of keys + typedef APT::PackageSet::const_iterator iterator; + + using std::set::insert; + inline void insert(pkgCache::PkgIterator const &P) { if (P.end() == false) std::set::insert(P); }; + + /** \brief returns all packages in the cache whose name matchs a given pattern + + A simple helper responsible for executing a regular expression on all + package names in the cache. Optional it prints a a notice about the + packages chosen cause of the given package. + \param Cache the packages are in + \param pattern regular expression for package names + \param out stream to print the notice to */ + static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string pattern, std::ostream &out); + static APT::PackageSet FromRegEx(pkgCacheFile &Cache, std::string const &pattern) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::PackageSet::FromRegEx(Cache, pattern, out); + } + + /** \brief returns all packages specified by a string + + \param Cache the packages are in + \param string String the package name(s) should be extracted from + \param out stream to print various notices to */ + static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string, std::ostream &out); + static APT::PackageSet FromString(pkgCacheFile &Cache, std::string const &string) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::PackageSet::FromString(Cache, string, out); + } + + /** \brief returns all packages specified on the commandline + + Get all package names from the commandline and executes regex's if needed. + No special package command is supported, just plain names. + \param Cache the packages are in + \param cmdline Command line the package names should be extracted from + \param out stream to print various notices to */ + static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, std::ostream &out); + static APT::PackageSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::PackageSet::FromCommandLine(Cache, cmdline, out); + } + + struct Modifier { + enum Position { NONE, PREFIX, POSTFIX }; + unsigned short ID; + const char * const Alias; + Position Pos; + Modifier (unsigned short const &id, const char * const alias, Position const &pos) : ID(id), Alias(alias), Pos(pos) {}; + }; + + static std::map GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback, std::ostream &out); + static std::map GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::PackageSet::GroupedFromCommandLine(Cache, cmdline, + mods, fallback, out); + } + /*}}}*/ +}; /*}}}*/ +class VersionSet : public std::set { /*{{{*/ +/** \class APT::VersionSet + + Simple wrapper around a std::set to provide a similar interface to + a set of versions as to the complete set of all versions in the + pkgCache. */ +public: /*{{{*/ + /** \brief smell like a pkgCache::VerIterator */ + class const_iterator : public std::set::const_iterator { + public: + const_iterator(std::set::const_iterator x) : + std::set::const_iterator(x) {} + + operator pkgCache::VerIterator(void) { return **this; } + + inline pkgCache *Cache() const { return (**this).Cache(); }; + inline unsigned long Index() const {return (**this).Index();}; + // we have only valid iterators here + inline bool end() const { return false; }; + + inline pkgCache::Version const * operator->() const { + return &***this; + }; + + inline int CompareVer(const pkgCache::VerIterator &B) const { return (**this).CompareVer(B); }; + inline const char *VerStr() const { return (**this).VerStr(); }; + inline const char *Section() const { return (**this).Section(); }; + inline const char *Arch() const { return (**this).Arch(); }; + inline const char *Arch(bool const pseudo) const { return (**this).Arch(pseudo); }; + inline pkgCache::PkgIterator ParentPkg() const { return (**this).ParentPkg(); }; + inline pkgCache::DescIterator DescriptionList() const { return (**this).DescriptionList(); }; + inline pkgCache::DescIterator TranslatedDescription() const { return (**this).TranslatedDescription(); }; + inline pkgCache::DepIterator DependsList() const { return (**this).DependsList(); }; + inline pkgCache::PrvIterator ProvidesList() const { return (**this).ProvidesList(); }; + inline pkgCache::VerFileIterator FileList() const { return (**this).FileList(); }; + inline bool Downloadable() const { return (**this).Downloadable(); }; + inline const char *PriorityType() const { return (**this).PriorityType(); }; + inline string RelStr() const { return (**this).RelStr(); }; + inline bool Automatic() const { return (**this).Automatic(); }; + inline bool Pseudo() const { return (**this).Pseudo(); }; + inline pkgCache::VerFileIterator NewestFile() const { return (**this).NewestFile(); }; + }; + // 103. set::iterator is required to be modifiable, but this allows modification of keys + typedef APT::VersionSet::const_iterator iterator; + + using std::set::insert; + inline void insert(pkgCache::VerIterator const &V) { if (V.end() == false) std::set::insert(V); }; + + /** \brief specifies which version(s) will be returned if non is given */ + enum Version { + /** All versions */ + ALL, + /** Candidate and installed version */ + CANDANDINST, + /** Candidate version */ + CANDIDATE, + /** Installed version */ + INSTALLED, + /** Candidate or if non installed version */ + CANDINST, + /** Installed or if non candidate version */ + INSTCAND, + /** Newest version */ + NEWEST + }; + + /** \brief returns all versions specified on the commandline + + Get all versions from the commandline, uses given default version if + non specifically requested and executes regex's if needed on names. + \param Cache the packages and versions are in + \param cmdline Command line the versions should be extracted from + \param out stream to print various notices to */ + static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, + APT::VersionSet::Version const &fallback, std::ostream &out); + static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline, + APT::VersionSet::Version const &fallback) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::VersionSet::FromCommandLine(Cache, cmdline, fallback, out); + } + static APT::VersionSet FromCommandLine(pkgCacheFile &Cache, const char **cmdline) { + return APT::VersionSet::FromCommandLine(Cache, cmdline, CANDINST); + } + + static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg, + APT::VersionSet::Version const &fallback, std::ostream &out); + static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg, + APT::VersionSet::Version const &fallback) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::VersionSet::FromString(Cache, pkg, fallback, out); + } + static APT::VersionSet FromString(pkgCacheFile &Cache, std::string pkg) { + return APT::VersionSet::FromString(Cache, pkg, CANDINST); + } + + struct Modifier { + enum Position { NONE, PREFIX, POSTFIX }; + unsigned short ID; + const char * const Alias; + Position Pos; + VersionSet::Version SelectVersion; + Modifier (unsigned short const &id, const char * const alias, Position const &pos, + VersionSet::Version const &select) : ID(id), Alias(alias), Pos(pos), + SelectVersion(select) {}; + }; + + static std::map GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback, std::ostream &out); + static std::map GroupedFromCommandLine( + pkgCacheFile &Cache, const char **cmdline, + std::list const &mods, + unsigned short const &fallback) { + std::ostream out (std::ofstream("/dev/null").rdbuf()); + return APT::VersionSet::GroupedFromCommandLine(Cache, cmdline, + mods, fallback, out); + } + /*}}}*/ +protected: /*{{{*/ + + /** \brief returns the candidate version of the package + + \param Cache to be used to query for information + \param Pkg we want the candidate version from this package + \param AllowError add an error to the stack if not */ + static pkgCache::VerIterator getCandidateVer(pkgCacheFile &Cache, + pkgCache::PkgIterator const &Pkg, bool const &AllowError = false); + + /** \brief returns the installed version of the package + + \param Cache to be used to query for information + \param Pkg we want the installed version from this package + \param AllowError add an error to the stack if not */ + static pkgCache::VerIterator getInstalledVer(pkgCacheFile &Cache, + pkgCache::PkgIterator const &Pkg, bool const &AllowError = false); + + + static bool AddSelectedVersion(pkgCacheFile &Cache, VersionSet &verset, + pkgCache::PkgIterator const &P, VersionSet::Version const &fallback, + bool const &AllowError = false); + + /*}}}*/ +}; /*}}}*/ +} +#endif diff --git a/cmdline/makefile b/cmdline/makefile index 917ccc96a..4ffe49ee0 100644 --- a/cmdline/makefile +++ b/cmdline/makefile @@ -9,14 +9,14 @@ include ../buildlib/defaults.mak PROGRAM=apt-cache SLIBS = -lapt-pkg $(INTLLIBS) LIB_MAKES = apt-pkg/makefile -SOURCE = apt-cache.cc +SOURCE = apt-cache.cc cacheset.cc include $(PROGRAM_H) # The apt-get program PROGRAM=apt-get SLIBS = -lapt-pkg -lutil $(INTLLIBS) LIB_MAKES = apt-pkg/makefile -SOURCE = apt-get.cc acqprogress.cc +SOURCE = apt-get.cc acqprogress.cc cacheset.cc include $(PROGRAM_H) # The apt-config program diff --git a/debian/changelog b/debian/changelog index f2a18d397..2648730ec 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low - * apt-pkg/cacheset.cc: + * cmdline/cacheset.cc: + - doesn't include it in the library for now as it is too volatile - get the candidate either from an already built depcache or use the policy which is a bit faster than depcache generation * apt-pkg/orderlist.cc: -- cgit v1.2.3-70-g09d2 From 8ceeb9d695f7c8fc5d856aa4f8647e88c4a8659f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 16 Jun 2010 17:19:21 +0200 Subject: add a simple method to VerIterator to check if two Versions are similar --- apt-pkg/cacheiterators.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index f0b40dbb5..51bf6819e 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -30,6 +30,8 @@ #ifndef PKGLIB_CACHEITERATORS_H #define PKGLIB_CACHEITERATORS_H #include + +#include // abstract Iterator template /*{{{*/ /* This template provides the very basic iterator methods we need to have for doing some walk-over-the-cache magic */ @@ -183,6 +185,13 @@ class pkgCache::VerIterator : public Iterator { // Comparison int CompareVer(const VerIterator &B) const; + /** \brief compares two version and returns if they are similar + + This method should be used to identify if two pseudo versions are + refering to the same "real" version */ + inline bool SimilarVer(const VerIterator &B) const { + return (B.end() == false && S->Hash == B->Hash && strcmp(VerStr(), B.VerStr()) == 0); + }; // Accessors inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;}; -- cgit v1.2.3-70-g09d2 From 1019948cea2e6adbd4b0df3f07b52c90187b1a05 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 16 Jun 2010 17:48:37 +0200 Subject: * apt-pkg/depcache.cc: - SetCandidateVer for all pseudo packages - SetReInstall for the "all" package of a pseudo package --- apt-pkg/depcache.cc | 32 +++++++++++++++++++++++++++++++- apt-pkg/depcache.h | 2 +- debian/changelog | 3 +++ 3 files changed, 35 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 3ae5f5953..d082b8404 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1453,6 +1453,9 @@ bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst, /* */ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To) { + if (unlikely(Pkg.end() == true)) + return; + ActionGroup group(*this); RemoveSizes(Pkg); @@ -1466,12 +1469,17 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To) AddStates(Pkg); AddSizes(Pkg); + + if (unlikely(Pkg.CurrentVer().end() == true) || Pkg.CurrentVer().Pseudo() == false) + return; + + SetReInstall(Pkg.Group().FindPkg("all"), To); } /*}}}*/ // DepCache::SetCandidateVersion - Change the candidate version /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgDepCache::SetCandidateVersion(VerIterator TargetVer) +void pkgDepCache::SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo) { ActionGroup group(*this); @@ -1489,6 +1497,28 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer) AddStates(Pkg); Update(Pkg); AddSizes(Pkg); + + if (TargetVer.Pseudo() == false || Pseudo == false) + return; + + // the version was pseudo: set all other pseudos also + pkgCache::GrpIterator Grp = Pkg.Group(); + for (Pkg = Grp.FindPkg("any"); Pkg.end() == false; ++Pkg) + { + StateCache &P = PkgState[Pkg->ID]; + if (TargetVer.SimilarVer(P.CandidateVerIter(*this)) == true || + (P.CandidateVerIter(*this).Pseudo() == false && + strcmp(Pkg.Arch(), "all") != 0)) + continue; + + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) + { + if (TargetVer.SimilarVer(Ver) == false) + continue; + SetCandidateVersion(Ver, false); + break; + } + } } void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto) diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index c6f245a80..72d7cce5d 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -405,7 +405,7 @@ class pkgDepCache : protected pkgCache::Namespace bool ForceImportantDeps = false); void SetReInstall(PkgIterator const &Pkg,bool To); - void SetCandidateVersion(VerIterator TargetVer); + void SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo = true); /** Set the "is automatically installed" flag of Pkg. */ void MarkAuto(const PkgIterator &Pkg, bool Auto); diff --git a/debian/changelog b/debian/changelog index 2648730ec..4de21d343 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,6 +10,9 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low - packages that are not touched doesn't need to be unpacked * debian/control: - remove intltool's dependency as it is an ubuntu artefact + * apt-pkg/depcache.cc: + - SetCandidateVer for all pseudo packages + - SetReInstall for the "all" package of a pseudo package -- David Kalnischkies Thu, 10 Jun 2010 16:36:58 +0200 -- cgit v1.2.3-70-g09d2 From a5de4117b60617ace639fb1e09e8903279185c2e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 19 Jun 2010 09:13:33 +0200 Subject: fix the gcc warning about the initialisation order of variables caused by moving Policy to public again (and therefore after SrcList) --- apt-pkg/cachefile.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc index 01598386c..964c5bd8b 100644 --- a/apt-pkg/cachefile.cc +++ b/apt-pkg/cachefile.cc @@ -28,7 +28,7 @@ // --------------------------------------------------------------------- /* */ pkgCacheFile::pkgCacheFile() : Map(NULL), Cache(NULL), DCache(NULL), - Policy(NULL), SrcList(NULL) + SrcList(NULL), Policy(NULL) { } /*}}}*/ -- cgit v1.2.3-70-g09d2 From 98ee7cd35cf205c52b3698ee91cec76d704a3937 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 25 Jun 2010 08:01:48 +0200 Subject: * apt-pkg/contrib/error.{cc,h}: - complete rewrite but use the same API - add NOTICE and DEBUG as new types of a message --- apt-pkg/contrib/error.cc | 333 ++++++++++++++++++++++------------------------- apt-pkg/contrib/error.h | 230 +++++++++++++++++++++++++++----- debian/changelog | 5 +- 3 files changed, 360 insertions(+), 208 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index 927b7e05c..837d9e615 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -1,16 +1,15 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: error.cc,v 1.11 2002/03/26 07:38:58 jgg Exp $ /* ###################################################################### - - Global Erorr Class - Global error mechanism + + Global Error Class - Global error mechanism We use a simple STL vector to store each error record. A PendingFlag is kept which indicates when the vector contains a Sever error. - + This source is placed in the Public Domain, do with it what you will It was originally written by Jason Gunthorpe. - + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -19,7 +18,6 @@ #include #include #include -#include #include #include @@ -28,209 +26,188 @@ #include "config.h" /*}}}*/ -using namespace std; - // Global Error Object /*{{{*/ /* If the implementation supports posix threads then the accessor function is compiled to be thread safe otherwise a non-safe version is used. A Per-Thread error object is maintained in much the same manner as libc manages errno */ #if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD) - #include - - static pthread_key_t ErrorKey; - static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;}; - static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);}; - - GlobalError *_GetErrorObj() - { - static pthread_once_t Once = PTHREAD_ONCE_INIT; - pthread_once(&Once,KeyAlloc); - - void *Res = pthread_getspecific(ErrorKey); - if (Res == 0) - pthread_setspecific(ErrorKey,Res = new GlobalError); - return (GlobalError *)Res; - } + #include + + static pthread_key_t ErrorKey; + static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;}; + static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);}; + + GlobalError *_GetErrorObj() { + static pthread_once_t Once = PTHREAD_ONCE_INIT; + pthread_once(&Once,KeyAlloc); + + void *Res = pthread_getspecific(ErrorKey); + if (Res == 0) + pthread_setspecific(ErrorKey,Res = new GlobalError); + return (GlobalError *)Res; + } #else - GlobalError *_GetErrorObj() - { - static GlobalError *Obj = new GlobalError; - return Obj; - } + GlobalError *_GetErrorObj() { + static GlobalError *Obj = new GlobalError; + return Obj; + } #endif /*}}}*/ - // GlobalError::GlobalError - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -GlobalError::GlobalError() : List(0), PendingFlag(false) -{ +GlobalError::GlobalError() : PendingFlag(false) {} + /*}}}*/ +// GlobalError::FatalE - Get part of the error string from errno /*{{{*/ +bool GlobalError::FatalE(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(FATAL, Function, Description, args); } /*}}}*/ // GlobalError::Errno - Get part of the error string from errno /*{{{*/ -// --------------------------------------------------------------------- -/* Function indicates the stdlib function that failed and Description is - a user string that leads the text. Form is: - Description - Function (errno: strerror) - Carefull of the buffer overrun, sprintf. - */ -bool GlobalError::Errno(const char *Function,const char *Description,...) -{ - va_list args; - va_start(args,Description); - - // sprintf the description - char S[400]; - vsnprintf(S,sizeof(S),Description,args); - snprintf(S + strlen(S),sizeof(S) - strlen(S), - " - %s (%i: %s)",Function,errno,strerror(errno)); - - // Put it on the list - Item *Itm = new Item; - Itm->Text = S; - Itm->Error = true; - Insert(Itm); - - PendingFlag = true; - - return false; +bool GlobalError::Errno(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(ERROR, Function, Description, args); } /*}}}*/ -// GlobalError::WarningE - Get part of the warn string from errno /*{{{*/ -// --------------------------------------------------------------------- -/* Function indicates the stdlib function that failed and Description is - a user string that leads the text. Form is: - Description - Function (errno: strerror) - Carefull of the buffer overrun, sprintf. - */ -bool GlobalError::WarningE(const char *Function,const char *Description,...) -{ - va_list args; - va_start(args,Description); - - // sprintf the description - char S[400]; - vsnprintf(S,sizeof(S),Description,args); - snprintf(S + strlen(S),sizeof(S) - strlen(S), - " - %s (%i: %s)",Function,errno,strerror(errno)); - - // Put it on the list - Item *Itm = new Item; - Itm->Text = S; - Itm->Error = false; - Insert(Itm); - - return false; +// GlobalError::WarningE - Get part of the warning string from errno /*{{{*/ +bool GlobalError::WarningE(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(WARNING, Function, Description, args); +} + /*}}}*/ +// GlobalError::NoticeE - Get part of the notice string from errno /*{{{*/ +bool GlobalError::NoticeE(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(NOTICE, Function, Description, args); +} + /*}}}*/ +// GlobalError::DebugE - Get part of the debug string from errno /*{{{*/ +bool GlobalError::DebugE(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(DEBUG, Function, Description, args); +} + /*}}}*/ +// GlobalError::InsertErrno - formats an error message with the errno /*{{{*/ +bool GlobalError::InsertErrno(MsgType type, const char* Function, + const char* Description, va_list const &args) { + char S[400]; + vsnprintf(S,sizeof(S),Description,args); + snprintf(S + strlen(S),sizeof(S) - strlen(S), + " - %s (%i: %s)", Function, errno, strerror(errno)); + return Insert(type, S, args); +} + /*}}}*/ +// GlobalError::Fatal - Add a fatal error to the list /*{{{*/ +bool GlobalError::Fatal(const char *Description,...) { + va_list args; + va_start(args,Description); + return Insert(FATAL, Description, args); } /*}}}*/ // GlobalError::Error - Add an error to the list /*{{{*/ -// --------------------------------------------------------------------- -/* Just vsprintfs and pushes */ -bool GlobalError::Error(const char *Description,...) -{ - va_list args; - va_start(args,Description); - - // sprintf the description - char S[400]; - vsnprintf(S,sizeof(S),Description,args); - - // Put it on the list - Item *Itm = new Item; - Itm->Text = S; - Itm->Error = true; - Insert(Itm); - - PendingFlag = true; - - return false; +bool GlobalError::Error(const char *Description,...) { + va_list args; + va_start(args,Description); + return Insert(ERROR, Description, args); } /*}}}*/ // GlobalError::Warning - Add a warning to the list /*{{{*/ -// --------------------------------------------------------------------- -/* This doesn't set the pending error flag */ -bool GlobalError::Warning(const char *Description,...) +bool GlobalError::Warning(const char *Description,...) { + va_list args; + va_start(args,Description); + return Insert(WARNING, Description, args); +} + /*}}}*/ +// GlobalError::Notice - Add a notice to the list /*{{{*/ +bool GlobalError::Notice(const char *Description,...) { - va_list args; - va_start(args,Description); - - // sprintf the description - char S[400]; - vsnprintf(S,sizeof(S),Description,args); - - // Put it on the list - Item *Itm = new Item; - Itm->Text = S; - Itm->Error = false; - Insert(Itm); - - return false; + va_list args; + va_start(args,Description); + return Insert(NOTICE, Description, args); } /*}}}*/ -// GlobalError::PopMessage - Pulls a single message out /*{{{*/ -// --------------------------------------------------------------------- -/* This should be used in a loop checking empty() each cycle. It returns - true if the message is an error. */ -bool GlobalError::PopMessage(string &Text) +// GlobalError::Debug - Add a debug to the list /*{{{*/ +bool GlobalError::Debug(const char *Description,...) { - if (List == 0) - return false; - - bool Ret = List->Error; - Text = List->Text; - Item *Old = List; - List = List->Next; - delete Old; - - // This really should check the list to see if only warnings are left.. - if (List == 0) - PendingFlag = false; - - return Ret; + va_list args; + va_start(args,Description); + return Insert(DEBUG, Description, args); +} + /*}}}*/ +// GlobalError::Insert - Insert a new item at the end /*{{{*/ +bool GlobalError::Insert(MsgType type, const char* Description, + va_list const &args) { + char S[400]; + vsnprintf(S,sizeof(S),Description,args); + + Item const m(S, type); + Messages.push_back(m); + + if (type == ERROR || type == FATAL) + PendingFlag = true; + + if (type == FATAL || type == DEBUG) + std::clog << m << std::endl; + + return false; +} + /*}}}*/ +// GlobalError::PopMessage - Pulls a single message out /*{{{*/ +bool GlobalError::PopMessage(std::string &Text) { + if (Messages.empty() == true) + return false; + + Item const msg = Messages.front(); + Messages.pop_front(); + + bool const Ret = (msg.Type == ERROR || msg.Type == FATAL); + Text = msg.Text; + if (PendingFlag == false || Ret == false) + return Ret; + + // check if another error message is pending + for (std::list::const_iterator m = Messages.begin(); + m != Messages.end(); m++) + if (m->Type == ERROR || m->Type == FATAL) + return Ret; + + PendingFlag = false; + return Ret; } /*}}}*/ // GlobalError::DumpErrors - Dump all of the errors/warns to cerr /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void GlobalError::DumpErrors() -{ - // Print any errors or warnings found - string Err; - while (empty() == false) - { - bool Type = PopMessage(Err); - if (Type == true) - cerr << "E: " << Err << endl; - else - cerr << "W: " << Err << endl; - } +void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold) { + for (std::list::const_iterator m = Messages.begin(); + m != Messages.end(); m++) + if (m->Type >= trashhold) + out << (*m) << std::endl; + Discard(); } /*}}}*/ -// GlobalError::Discard - Discard /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void GlobalError::Discard() -{ - while (List != 0) - { - Item *Old = List; - List = List->Next; - delete Old; - } - - PendingFlag = false; +// GlobalError::Discard - Discard /*{{{*/ +void GlobalError::Discard() { + Messages.clear(); + PendingFlag = false; }; /*}}}*/ -// GlobalError::Insert - Insert a new item at the end /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void GlobalError::Insert(Item *Itm) -{ - Item **End = &List; - for (Item *I = List; I != 0; I = I->Next) - End = &I->Next; - Itm->Next = *End; - *End = Itm; +// GlobalError::empty - does our error list include anything? /*{{{*/ +bool GlobalError::empty(MsgType const &trashhold) const { + if (PendingFlag == true) + return false; + + if (Messages.empty() == true) + return true; + + for (std::list::const_iterator m = Messages.begin(); + m != Messages.end(); m++) + if (m->Type >= trashhold) + return false; + + return true; } /*}}}*/ diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index 8d5ec05ea..fc7b38f1b 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -42,43 +42,215 @@ #include +#include +#include #include -class GlobalError +#include + +class GlobalError /*{{{*/ { - struct Item - { - std::string Text; - bool Error; - Item *Next; - }; - - Item *List; - bool PendingFlag; - void Insert(Item *I); - - public: +public: /*{{{*/ + /** \brief a message can have one of following severity */ + enum MsgType { + /** \brief Message will be printed instantly as it is likely that + this error will lead to a complete crash */ + FATAL = 40, + /** \brief An error does hinder the correct execution and should be corrected */ + ERROR = 30, + /** \brief indicates problem that can lead to errors later on */ + WARNING = 20, + /** \brief deprecation warnings, old fallback behavior, … */ + NOTICE = 10, + /** \brief for developers only in areas it is hard to print something directly */ + DEBUG = 0 + }; - // Call to generate an error from a library call. - bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold; - bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold; + /** \brief add a fatal error message with errno to the list + * + * \param Function name of the function generating the error + * \param Description format string for the error message + * + * \return \b false + */ + bool FatalE(const char *Function,const char *Description,...) __like_printf(3) __cold; - /* A warning should be considered less severe than an error, and may be - ignored by the client. */ - bool Error(const char *Description,...) __like_printf(2) __cold; - bool Warning(const char *Description,...) __like_printf(2) __cold; + /** \brief add an Error message with errno to the list + * + * \param Function name of the function generating the error + * \param Description format string for the error message + * + * \return \b false + */ + bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold; - // Simple accessors - inline bool PendingError() {return PendingFlag;}; - inline bool empty() {return List == 0;}; - bool PopMessage(std::string &Text); - void Discard(); + /** \brief add a warning message with errno to the list + * + * A warning should be considered less severe than an error and + * may be ignored by the client. + * + * \param Function Name of the function generates the warning. + * \param Description Format string for the warning message. + * + * \return \b false + */ + bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold; - // Usefull routine to dump to cerr - void DumpErrors(); - - GlobalError(); + /** \brief add a notice message with errno to the list + * + * \param Function name of the function generating the error + * \param Description format string for the error message + * + * \return \b false + */ + bool NoticeE(const char *Function,const char *Description,...) __like_printf(3) __cold; + + /** \brief add a debug message with errno to the list + * + * \param Function name of the function generating the error + * \param Description format string for the error message + * + * \return \b false + */ + bool DebugE(const char *Function,const char *Description,...) __like_printf(3) __cold; + + /** \brief add an fatal error message to the list + * + * Most of the stuff we consider as "error" is also "fatal" for + * the user as the application will not have the expected result, + * but a fatal message here means that it gets printed directly + * to stderr in addiction to adding it to the list as the error + * leads sometimes to crashes and a maybe duplicated message + * is better than "Segfault" as the only displayed text + * + * \param Description Format string for the fatal error message. + * + * \return \b false + */ + bool Fatal(const char *Description,...) __like_printf(2) __cold; + + /** \brief add an Error message to the list + * + * \param Description Format string for the error message. + * + * \return \b false + */ + bool Error(const char *Description,...) __like_printf(2) __cold; + + /** \brief add a warning message to the list + * + * A warning should be considered less severe than an error and + * may be ignored by the client. + * + * \param Description Format string for the message + * + * \return \b false + */ + bool Warning(const char *Description,...) __like_printf(2) __cold; + + /** \brief add a notice message to the list + * + * A notice should be considered less severe than an error or a + * warning and can be ignored by the client without further problems + * for some times, but he should consider fixing the problem. + * This error type can be used for e.g. deprecation warnings of options. + * + * \param Description Format string for the message + * + * \return \b false + */ + bool Notice(const char *Description,...) __like_printf(2) __cold; + + /** \brief add a debug message to the list + * + * \param Description Format string for the message + * + * \return \b false + */ + bool Debug(const char *Description,...) __like_printf(2) __cold; + + /** \brief is an error in the list? + * + * \return \b true if an error is included in the list, \b false otherwise + */ + inline bool PendingError() const {return PendingFlag;}; + + /** \brief is the list empty? + * + * The default checks if the list is empty or contains only notices, + * if you want to check if also no notices happend set the parameter + * flag to \b false. + * + * \param WithoutNotice does notices count, default is \b true, so no + * + * \return \b true if an the list is empty, \b false otherwise + */ + bool empty(MsgType const &trashhold = WARNING) const; + + /** \brief returns and removes the first (or last) message in the list + * + * \param[out] Text message of the first/last item + * + * \return \b true if the message was an error, \b false otherwise + */ + bool PopMessage(std::string &Text); + + /** \brief clears the list of messages */ + void Discard(); + + /** \brief outputs the list of messages to the given stream + * + * Note that all messages are discarded, also the notices + * displayed or not. + * + * \param[out] out output stream to write the messages in + * \param WithoutNotice output notices or not + */ + void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING); + + /** \brief dumps the list of messages to std::cerr + * + * Note that all messages are discarded, also the notices + * displayed or not. + * + * \param WithoutNotice print notices or not + */ + void inline DumpErrors(MsgType const &trashhold = WARNING) { + DumpErrors(std::cerr, trashhold); + } + + GlobalError(); + /*}}}*/ +private: /*{{{*/ + struct Item { + std::string Text; + MsgType Type; + + Item(char const *Text, MsgType const &Type) : + Text(Text), Type(Type) {}; + + friend std::ostream& operator<< (std::ostream &out, Item i) { + switch(i.Type) { + case FATAL: + case ERROR: out << "E"; break; + case WARNING: out << "W"; break; + case NOTICE: out << "N"; break; + case DEBUG: out << "D"; break; + } + return out << ": " << i.Text; + } + }; + + std::list Messages; + bool PendingFlag; + + bool InsertErrno(MsgType type, const char* Function, + const char* Description, va_list const &args); + bool Insert(MsgType type, const char* Description, + va_list const &args); + /*}}}*/ }; + /*}}}*/ // The 'extra-ansi' syntax is used to help with collisions. GlobalError *_GetErrorObj(); diff --git a/debian/changelog b/debian/changelog index 00877eefb..3e7b16d62 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,8 +16,11 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/depcache.cc: - SetCandidateVer for all pseudo packages - SetReInstall for the "all" package of a pseudo package + * apt-pkg/contrib/error.{cc,h}: + - complete rewrite but use the same API + - add NOTICE and DEBUG as new types of a message - -- David Kalnischkies Thu, 10 Jun 2010 16:36:58 +0200 + -- David Kalnischkies Fri, 25 Jun 2010 08:01:14 +0200 apt (0.7.26~exp7) experimental; urgency=low -- cgit v1.2.3-70-g09d2 From c4ba7c44ff03d67ff982bbab26dc48d796041e02 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 25 Jun 2010 19:16:12 +0200 Subject: add a simple stack handling to be able to delay error handling --- apt-pkg/contrib/error.cc | 32 ++++++++++++++++- apt-pkg/contrib/error.h | 35 ++++++++++++++++++- debian/changelog | 3 +- test/libapt/globalerror_test.cc | 77 +++++++++++++++++++++++++++++++++++++++++ test/libapt/makefile | 10 ++++-- 5 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 test/libapt/globalerror_test.cc (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index 837d9e615..8cee21c9c 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -181,7 +181,13 @@ bool GlobalError::PopMessage(std::string &Text) { } /*}}}*/ // GlobalError::DumpErrors - Dump all of the errors/warns to cerr /*{{{*/ -void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold) { +void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold, + bool const &mergeStack) { + if (mergeStack == true) + for (std::list::const_reverse_iterator s = Stacks.rbegin(); + s != Stacks.rend(); ++s) + Messages.insert(Messages.begin(), s->Messages.begin(), s->Messages.end()); + for (std::list::const_iterator m = Messages.begin(); m != Messages.end(); m++) if (m->Type >= trashhold) @@ -211,3 +217,27 @@ bool GlobalError::empty(MsgType const &trashhold) const { return true; } /*}}}*/ +// GlobalError::PushToStack /*{{{*/ +void GlobalError::PushToStack() { + MsgStack pack(Messages, PendingFlag); + Stacks.push_back(pack); + Discard(); +} + /*}}}*/ +// GlobalError::RevertToStack /*{{{*/ +void GlobalError::RevertToStack() { + Discard(); + MsgStack pack = Stacks.back(); + Messages = pack.Messages; + PendingFlag = pack.PendingFlag; + Stacks.pop_back(); +} + /*}}}*/ +// GlobalError::MergeWithStack /*{{{*/ +void GlobalError::MergeWithStack() { + MsgStack pack = Stacks.back(); + Messages.insert(Messages.begin(), pack.Messages.begin(), pack.Messages.end()); + PendingFlag = PendingFlag || pack.PendingFlag; + Stacks.pop_back(); +} + /*}}}*/ diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index fc7b38f1b..73735162d 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -206,7 +206,8 @@ public: /*{{{*/ * \param[out] out output stream to write the messages in * \param WithoutNotice output notices or not */ - void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING); + void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING, + bool const &mergeStack = true); /** \brief dumps the list of messages to std::cerr * @@ -219,6 +220,28 @@ public: /*{{{*/ DumpErrors(std::cerr, trashhold); } + /** \brief put the current Messages into the stack + * + * All "old" messages will be pushed into a stack to + * them later back, but for now the Message query will be + * empty and performs as no messages were present before. + * + * The stack can be as deep as you want - all stack operations + * will only operate on the last element in the stack. + */ + void PushToStack(); + + /** \brief throw away all current messages */ + void RevertToStack(); + + /** \brief merge current and stack together */ + void MergeWithStack(); + + /** \brief return the deep of the stack */ + size_t StackCount() const { + return Stacks.size(); + } + GlobalError(); /*}}}*/ private: /*{{{*/ @@ -244,6 +267,16 @@ private: /*{{{*/ std::list Messages; bool PendingFlag; + struct MsgStack { + std::list const Messages; + bool const PendingFlag; + + MsgStack(std::list const &Messages, bool const &Pending) : + Messages(Messages), PendingFlag(Pending) {}; + }; + + std::list Stacks; + bool InsertErrno(MsgType type, const char* Function, const char* Description, va_list const &args); bool Insert(MsgType type, const char* Description, diff --git a/debian/changelog b/debian/changelog index 3e7b16d62..46e371165 100644 --- a/debian/changelog +++ b/debian/changelog @@ -19,8 +19,9 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/contrib/error.{cc,h}: - complete rewrite but use the same API - add NOTICE and DEBUG as new types of a message + - add a simple stack handling to be able to delay error handling - -- David Kalnischkies Fri, 25 Jun 2010 08:01:14 +0200 + -- David Kalnischkies Fri, 25 Jun 2010 19:15:21 +0200 apt (0.7.26~exp7) experimental; urgency=low diff --git a/test/libapt/globalerror_test.cc b/test/libapt/globalerror_test.cc new file mode 100644 index 000000000..b2752255f --- /dev/null +++ b/test/libapt/globalerror_test.cc @@ -0,0 +1,77 @@ +#include + +#include "assert.h" +#include + +int main(int argc,char *argv[]) +{ + equals(_error->empty(), true); + equals(_error->PendingError(), false); + equals(_error->Notice("%s Notice", "A"), false); + equals(_error->empty(), true); + equals(_error->empty(GlobalError::DEBUG), false); + equals(_error->PendingError(), false); + equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false); + equals(_error->PendingError(), true); + std::string text; + equals(_error->PopMessage(text), false); + equals(_error->PendingError(), true); + equals(text, "A Notice"); + equals(_error->PopMessage(text), true); + equals(text, "Something horrible happend 2 times"); + equals(_error->empty(GlobalError::DEBUG), true); + equals(_error->PendingError(), false); + equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false); + equals(_error->PendingError(), true); + equals(_error->empty(GlobalError::FATAL), false); + _error->Discard(); + + equals(_error->empty(), true); + equals(_error->PendingError(), false); + equals(_error->Notice("%s Notice", "A"), false); + equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false); + equals(_error->PendingError(), true); + equals(_error->empty(GlobalError::NOTICE), false); + _error->PushToStack(); + equals(_error->empty(GlobalError::NOTICE), true); + equals(_error->PendingError(), false); + equals(_error->Warning("%s Warning", "A"), false); + equals(_error->empty(GlobalError::ERROR), true); + equals(_error->PendingError(), false); + _error->RevertToStack(); + equals(_error->empty(GlobalError::ERROR), false); + equals(_error->PendingError(), true); + equals(_error->PopMessage(text), false); + equals(_error->PendingError(), true); + equals(text, "A Notice"); + equals(_error->PopMessage(text), true); + equals(text, "Something horrible happend 2 times"); + equals(_error->PendingError(), false); + equals(_error->empty(), true); + + equals(_error->Notice("%s Notice", "A"), false); + equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false); + equals(_error->PendingError(), true); + equals(_error->empty(GlobalError::NOTICE), false); + _error->PushToStack(); + equals(_error->empty(GlobalError::NOTICE), true); + equals(_error->PendingError(), false); + equals(_error->Warning("%s Warning", "A"), false); + equals(_error->empty(GlobalError::ERROR), true); + equals(_error->PendingError(), false); + _error->MergeWithStack(); + equals(_error->empty(GlobalError::ERROR), false); + equals(_error->PendingError(), true); + equals(_error->PopMessage(text), false); + equals(_error->PendingError(), true); + equals(text, "A Notice"); + equals(_error->PopMessage(text), true); + equals(text, "Something horrible happend 2 times"); + equals(_error->PendingError(), false); + equals(_error->empty(), false); + equals(_error->PopMessage(text), false); + equals(text, "A Warning"); + equals(_error->empty(), true); + + return 0; +} diff --git a/test/libapt/makefile b/test/libapt/makefile index ee3401b35..50058262e 100644 --- a/test/libapt/makefile +++ b/test/libapt/makefile @@ -30,13 +30,19 @@ SOURCE = getlistoffilesindir_test.cc include $(PROGRAM_H) # Program for testing CommandLine reconstruction -PROGRAM = commandlineasstring${BASENAME} +PROGRAM = CommandlineAsString${BASENAME} SLIBS = -lapt-pkg SOURCE = commandlineasstring_test.cc include $(PROGRAM_H) # Program for testing debians version comparing -PROGRAM = compareversion${BASENAME} +PROGRAM = CompareVersion${BASENAME} SLIBS = -lapt-pkg SOURCE = compareversion_test.cc include $(PROGRAM_H) + +# test the GlobalError stack class +PROGRAM = GlobalError${BASENAME} +SLIBS = -lapt-pkg +SOURCE = globalerror_test.cc +include $(PROGRAM_H) -- cgit v1.2.3-70-g09d2 From 9f9717fa6bca13817cf9cf84d513e59d258af154 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 Jun 2010 09:03:26 +0200 Subject: * apt-pkg/aptconfiguration.cc: - show a deprecation notice for APT::Acquire::Translation --- apt-pkg/aptconfiguration.cc | 4 ++++ debian/changelog | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 0c050d9dc..44f1f318a 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -10,6 +10,7 @@ // Include Files /*{{{*/ #include #include +#include #include #include #include @@ -196,6 +197,9 @@ std::vector const Configuration::getLanguages(bool const &All, // it was undocumented and so it should be not very widthly used string const oldAcquire = _config->Find("APT::Acquire::Translation",""); if (oldAcquire.empty() == false && oldAcquire != "environment") { + // TRANSLATORS: the two %s are APT configuration options + _error->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.", + "APT::Acquire::Translation", "Acquire::Languages"); if (oldAcquire != "none") codes.push_back(oldAcquire); codes.push_back("en"); diff --git a/debian/changelog b/debian/changelog index 46e371165..06bde48fc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -20,8 +20,10 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low - complete rewrite but use the same API - add NOTICE and DEBUG as new types of a message - add a simple stack handling to be able to delay error handling + * apt-pkg/aptconfiguration.cc: + - show a deprecation notice for APT::Acquire::Translation - -- David Kalnischkies Fri, 25 Jun 2010 19:15:21 +0200 + -- David Kalnischkies Sat, 26 Jun 2010 09:01:40 +0200 apt (0.7.26~exp7) experimental; urgency=low -- cgit v1.2.3-70-g09d2 From 1f2933a8de0f3a26f51b4a0a2112cbdfd4461e9b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 Jun 2010 13:29:24 +0200 Subject: - use the new MatchAgainstConfig for the DefaultRootSetFunc * apt-pkg/contrib/configuration.{cc,h}: - add a wrapper to match strings against configurable regex patterns --- apt-pkg/contrib/configuration.cc | 43 +++++++++++++++++++++++++++++++++++ apt-pkg/contrib/configuration.h | 19 +++++++++++++++- apt-pkg/depcache.cc | 48 ---------------------------------------- apt-pkg/depcache.h | 22 +++++------------- debian/changelog | 5 ++++- 5 files changed, 71 insertions(+), 66 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 9129d92f0..81cc87d15 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -843,3 +843,46 @@ bool ReadConfigDir(Configuration &Conf,const string &Dir, return true; } /*}}}*/ +// MatchAgainstConfig Constructor /*{{{*/ +Configuration::MatchAgainstConfig::MatchAgainstConfig(char const * Config) +{ + std::vector const strings = _config->FindVector(Config); + for (std::vector::const_iterator s = strings.begin(); + s != strings.end(); ++s) + { + regex_t *p = new regex_t; + if (regcomp(p, s->c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB) == 0) + patterns.push_back(p); + else + { + regfree(p); + delete p; + _error->Warning("Regex compilation error for '%s' in configuration option '%s'", + s->c_str(), Config); + } + } + +} + /*}}}*/ +// MatchAgainstConfig Destructor /*{{{*/ +Configuration::MatchAgainstConfig::~MatchAgainstConfig() +{ + for(std::vector::const_iterator p = patterns.begin(); + p != patterns.end(); ++p) + { + regfree(*p); + delete *p; + } +} + /*}}}*/ +// MatchAgainstConfig::Match - returns true if a pattern matches /*{{{*/ +bool Configuration::MatchAgainstConfig::Match(char const * str) const +{ + for(std::vector::const_iterator p = patterns.begin(); + p != patterns.end(); ++p) + if (regexec(*p, str, 0, 0, 0) == 0) + return true; + + return false; +} + /*}}}*/ diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index 2494c1d7c..cbe18e4e5 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -28,7 +28,7 @@ #ifndef PKGLIB_CONFIGURATION_H #define PKGLIB_CONFIGURATION_H - +#include #include #include @@ -104,6 +104,23 @@ class Configuration Configuration(const Item *Root); Configuration(); ~Configuration(); + + /** \brief match a string against a configurable list of patterns */ + class MatchAgainstConfig + { + std::vector patterns; + + public: + MatchAgainstConfig(char const * Config); + virtual ~MatchAgainstConfig(); + + /** \brief Returns \b true for a string matching one of the patterns */ + bool Match(char const * str) const; + bool Match(std::string const &str) const { return Match(str.c_str()); }; + + /** \brief returns if the matcher setup was successful */ + bool wasConstructedSuccessfully() const { return patterns.empty() == false; } + }; }; extern Configuration *_config; diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index d082b8404..8bca3e36e 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1635,54 +1635,6 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep) else if(Dep->Type == pkgCache::Dep::Suggests) return _config->FindB("APT::Install-Suggests", false); - return false; -} - /*}}}*/ -pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc() /*{{{*/ - : constructedSuccessfully(false) -{ - Configuration::Item const *Opts; - Opts = _config->Tree("APT::NeverAutoRemove"); - if (Opts != 0 && Opts->Child != 0) - { - Opts = Opts->Child; - for (; Opts != 0; Opts = Opts->Next) - { - if (Opts->Value.empty() == true) - continue; - - regex_t *p = new regex_t; - if(regcomp(p,Opts->Value.c_str(), - REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0) - { - regfree(p); - delete p; - _error->Error("Regex compilation error for APT::NeverAutoRemove"); - return; - } - - rootSetRegexp.push_back(p); - } - } - - constructedSuccessfully = true; -} - /*}}}*/ -pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc() /*{{{*/ -{ - for(unsigned int i = 0; i < rootSetRegexp.size(); i++) - { - regfree(rootSetRegexp[i]); - delete rootSetRegexp[i]; - } -} - /*}}}*/ -bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg) /*{{{*/ -{ - for(unsigned int i = 0; i < rootSetRegexp.size(); i++) - if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0) - return true; - return false; } /*}}}*/ diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 72d7cce5d..66c099b80 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -38,11 +38,10 @@ #ifndef PKGLIB_DEPCACHE_H #define PKGLIB_DEPCACHE_H - +#include #include #include - -#include +#include #include #include @@ -184,22 +183,13 @@ class pkgDepCache : protected pkgCache::Namespace /** \brief Returns \b true for packages matching a regular * expression in APT::NeverAutoRemove. */ - class DefaultRootSetFunc : public InRootSetFunc + class DefaultRootSetFunc : public InRootSetFunc, public Configuration::MatchAgainstConfig { - std::vector rootSetRegexp; - bool constructedSuccessfully; - public: - DefaultRootSetFunc(); - ~DefaultRootSetFunc(); - - /** \return \b true if the class initialized successfully, \b - * false otherwise. Used to avoid throwing an exception, since - * APT classes generally don't. - */ - bool wasConstructedSuccessfully() const { return constructedSuccessfully; } + DefaultRootSetFunc() : Configuration::MatchAgainstConfig("APT::NeverRemove") {}; + virtual ~DefaultRootSetFunc() {}; - bool InRootSet(const pkgCache::PkgIterator &pkg); + bool InRootSet(const pkgCache::PkgIterator &pkg) { return pkg.end() == true && Match(pkg.Name()); }; }; struct StateCache diff --git a/debian/changelog b/debian/changelog index 06bde48fc..4500614a0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,14 +16,17 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/depcache.cc: - SetCandidateVer for all pseudo packages - SetReInstall for the "all" package of a pseudo package + - use the new MatchAgainstConfig for the DefaultRootSetFunc * apt-pkg/contrib/error.{cc,h}: - complete rewrite but use the same API - add NOTICE and DEBUG as new types of a message - add a simple stack handling to be able to delay error handling * apt-pkg/aptconfiguration.cc: - show a deprecation notice for APT::Acquire::Translation + * apt-pkg/contrib/configuration.{cc,h}: + - add a wrapper to match strings against configurable regex patterns - -- David Kalnischkies Sat, 26 Jun 2010 09:01:40 +0200 + -- David Kalnischkies Sat, 26 Jun 2010 13:28:48 +0200 apt (0.7.26~exp7) experimental; urgency=low -- cgit v1.2.3-70-g09d2 From 1408e219e76e577fb84ef1c48e58337b6569feec Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 Jun 2010 18:40:15 +0200 Subject: * apt-pkg/contrib/fileutl.cc: - show notice about ignored file instead of being always silent - add a Dir::Ignore-Files-Silently list option to control the notice * --- apt-pkg/contrib/fileutl.cc | 4 ++++ apt-pkg/init.cc | 5 +++++ debian/changelog | 6 +++++- doc/apt.conf.5.xml | 9 +++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 16f7ce929..e95ddf562 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -281,6 +281,7 @@ std::vector GetListOfFilesInDir(string const &Dir, std::vector c } std::vector List; + Configuration::MatchAgainstConfig SilentIgnore("Dir::Ignore-Files-Silently"); DIR *D = opendir(Dir.c_str()); if (D == 0) { @@ -306,6 +307,7 @@ std::vector GetListOfFilesInDir(string const &Dir, std::vector c { if (Debug == true) std::clog << "Bad file: " << Ent->d_name << " → no extension" << std::endl; + _error->Notice("Ignoring file '%s' in directory '%s' as it has no filename extension", Ent->d_name, Dir.c_str()); continue; } } @@ -313,6 +315,8 @@ std::vector GetListOfFilesInDir(string const &Dir, std::vector c { if (Debug == true) std::clog << "Bad file: " << Ent->d_name << " → bad extension »" << flExtension(Ent->d_name) << "«" << std::endl; + if (SilentIgnore.Match(Ent->d_name) == false) + _error->Notice("Ignoring file '%s' in directory '%s' as it has an invalid filename extension", Ent->d_name, Dir.c_str()); continue; } } diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index 21472eb3b..7a332c86e 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -78,6 +78,11 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.Set("Dir::Log::Terminal","term.log"); Cnf.Set("Dir::Log::History","history.log"); + Cnf.Set("Dir::Ignore-Files-Silently::", "~$"); + Cnf.Set("Dir::Ignore-Files-Silently::", "\\.disabled$"); + Cnf.Set("Dir::Ignore-Files-Silently::", "\\.bak$"); + Cnf.Set("Dir::Ignore-Files-Silently::", "\\.dpkg-[a-z]+$"); + // Translation Cnf.Set("APT::Acquire::Translation", "environment"); diff --git a/debian/changelog b/debian/changelog index 4500614a0..722e7ffc4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -25,8 +25,12 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low - show a deprecation notice for APT::Acquire::Translation * apt-pkg/contrib/configuration.{cc,h}: - add a wrapper to match strings against configurable regex patterns + * apt-pkg/contrib/fileutl.cc: + - show notice about ignored file instead of being always silent + - add a Dir::Ignore-Files-Silently list option to control the notice + * - -- David Kalnischkies Sat, 26 Jun 2010 13:28:48 +0200 + -- David Kalnischkies Sat, 26 Jun 2010 18:40:01 +0200 apt (0.7.26~exp7) experimental; urgency=low diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 0cf4bb663..39e2c8e6b 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -507,6 +507,15 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; will be looked up in /tmp/staging/var/lib/dpkg/status. + + + The Ignore-Files-Silently list can be used to specify + which files APT should silently ignore while parsing the files in the + fragment directories. Per default a file which end with .disabled, + ~, .bak or .dpkg-[a-z]+ + is silently ignored. As seen in the last default value these patterns can use regular + expression syntax. + APT in DSelect -- cgit v1.2.3-70-g09d2 From 5afa55c6703a71a198aac950db30ffc6ca49f269 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 Jun 2010 18:42:42 +0200 Subject: make the MMap Grow Error a fatal one as while in theory the code should never segfault it still tend to do it so better show it directly --- apt-pkg/contrib/mmap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index d233e51bc..d71066243 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -297,7 +297,7 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln) { if(!Grow()) { - _error->Error(_("Dynamic MMap ran out of room. Please increase the size " + _error->Fatal(_("Dynamic MMap ran out of room. Please increase the size " "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace); return 0; } -- cgit v1.2.3-70-g09d2 From 5c640e864f8b5f1c175682a94f6c6d0dff42d4bc Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 Jun 2010 20:49:47 +0200 Subject: always mark the all package if a pseudo package is marked for install --- apt-pkg/depcache.cc | 4 ++++ debian/changelog | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 8bca3e36e..c93993ab1 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1255,6 +1255,10 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, Update(Pkg); AddSizes(Pkg); + // always trigger the install of the all package for a pseudo package + if (P.CandidateVerIter(*Cache).Pseudo() == true) + MarkInstall(Pkg.Group().FindPkg("all"), AutoInst, Depth, FromUser, ForceImportantDeps); + if (AutoInst == false) return; diff --git a/debian/changelog b/debian/changelog index 722e7ffc4..fbe814d84 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,7 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low - SetCandidateVer for all pseudo packages - SetReInstall for the "all" package of a pseudo package - use the new MatchAgainstConfig for the DefaultRootSetFunc + - always mark the all package if a pseudo package is marked for install * apt-pkg/contrib/error.{cc,h}: - complete rewrite but use the same API - add NOTICE and DEBUG as new types of a message @@ -28,9 +29,8 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/contrib/fileutl.cc: - show notice about ignored file instead of being always silent - add a Dir::Ignore-Files-Silently list option to control the notice - * - -- David Kalnischkies Sat, 26 Jun 2010 18:40:01 +0200 + -- David Kalnischkies Sat, 26 Jun 2010 20:43:09 +0200 apt (0.7.26~exp7) experimental; urgency=low -- cgit v1.2.3-70-g09d2 From e841200b9389ffc90e290310207bcb47e8a52be2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 4 Jul 2010 14:23:20 +0200 Subject: * apt-pkg/policy.h: - add another round of const& madness as the previous round accidently NOT override the virtual GetCandidateVer() method (Closes: #587725) --- apt-pkg/algorithms.h | 2 +- apt-pkg/cacheiterators.h | 32 ++++++++++++++++---------------- apt-pkg/depcache.cc | 4 ++-- apt-pkg/depcache.h | 6 +++--- apt-pkg/pkgcache.cc | 12 ++++++------ apt-pkg/policy.h | 2 +- debian/changelog | 4 +++- 7 files changed, 32 insertions(+), 30 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index cee30b679..cf4a98c4f 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -48,7 +48,7 @@ class pkgSimulate : public pkgPackageManager /*{{{*/ pkgDepCache *Cache; public: - virtual VerIterator GetCandidateVer(PkgIterator Pkg) + virtual VerIterator GetCandidateVer(PkgIterator const &Pkg) { return (*Cache)[Pkg].CandidateVerIter(*Cache); } diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 51bf6819e..dfe5707e1 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -105,13 +105,13 @@ class pkgCache::GrpIterator: public Iterator { inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;}; inline PkgIterator PackageList() const; - PkgIterator FindPkg(string Arch = "any"); + PkgIterator FindPkg(string Arch = "any") const; /** \brief find the package with the "best" architecture The best architecture is either the "native" or the first in the list of Architectures which is not an end-Pointer */ - PkgIterator FindPreferredPkg(); - PkgIterator NextPkg(PkgIterator const &Pkg); + PkgIterator FindPreferredPkg() const; + PkgIterator NextPkg(PkgIterator const &Pkg) const; // Constructors inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator(Owner, Trg), HashIndex(0) { @@ -272,17 +272,17 @@ class pkgCache::DepIterator : public Iterator { // Accessors inline const char *TargetVer() const {return S->Version == 0?0:Owner->StrP + S->Version;}; - inline PkgIterator TargetPkg() {return PkgIterator(*Owner,Owner->PkgP + S->Package);}; - inline PkgIterator SmartTargetPkg() {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;}; - inline VerIterator ParentVer() {return VerIterator(*Owner,Owner->VerP + S->ParentVer);}; - inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->ParentVer].ParentPkg);}; - inline bool Reverse() {return Type == DepRev;}; - bool IsCritical(); + inline PkgIterator TargetPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->Package);}; + inline PkgIterator SmartTargetPkg() const {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;}; + inline VerIterator ParentVer() const {return VerIterator(*Owner,Owner->VerP + S->ParentVer);}; + inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->ParentVer].ParentPkg);}; + inline bool Reverse() const {return Type == DepRev;}; + bool IsCritical() const; void GlobOr(DepIterator &Start,DepIterator &End); - Version **AllTargets(); - bool SmartTargetPkg(PkgIterator &Result); - inline const char *CompType() {return Owner->CompType(S->CompareOp);}; - inline const char *DepType() {return Owner->DepType(S->Type);}; + Version **AllTargets() const; + bool SmartTargetPkg(PkgIterator &Result) const; + inline const char *CompType() const {return Owner->CompType(S->CompareOp);}; + inline const char *DepType() const {return Owner->DepType(S->Type);}; inline DepIterator(pkgCache &Owner, Dependency *Trg, Version* = 0) : Iterator(Owner, Trg), Type(DepVer) { @@ -315,9 +315,9 @@ class pkgCache::PrvIterator : public Iterator { // Accessors inline const char *Name() const {return Owner->StrP + Owner->PkgP[S->ParentPkg].Name;}; inline const char *ProvideVersion() const {return S->ProvideVersion == 0?0:Owner->StrP + S->ProvideVersion;}; - inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);}; - inline VerIterator OwnerVer() {return VerIterator(*Owner,Owner->VerP + S->Version);}; - inline PkgIterator OwnerPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);}; + inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->ParentPkg);}; + inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);}; + inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);}; inline PrvIterator() : Iterator(), Type(PrvVer) {}; diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index c93993ab1..05127fe18 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1585,7 +1585,7 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver) // --------------------------------------------------------------------- /* The default just returns the highest available version that is not a source and automatic. */ -pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg) +pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pkg) { /* Not source/not automatic versions cannot be a candidate version unless they are already installed */ @@ -1620,7 +1620,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg) // Policy::IsImportantDep - True if the dependency is important /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep) +bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) { if(Dep.IsCritical()) return true; diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 66c099b80..45276dc95 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -256,8 +256,8 @@ class pkgDepCache : protected pkgCache::Namespace { public: - virtual VerIterator GetCandidateVer(PkgIterator Pkg); - virtual bool IsImportantDep(DepIterator Dep); + virtual VerIterator GetCandidateVer(PkgIterator const &Pkg); + virtual bool IsImportantDep(DepIterator const &Dep); virtual ~Policy() {}; }; @@ -334,7 +334,7 @@ class pkgDepCache : protected pkgCache::Namespace inline pkgVersioningSystem &VS() {return *Cache->VS;}; // Policy implementation - inline VerIterator GetCandidateVer(PkgIterator Pkg) {return LocalPolicy->GetCandidateVer(Pkg);}; + inline VerIterator GetCandidateVer(PkgIterator const &Pkg) {return LocalPolicy->GetCandidateVer(Pkg);}; inline bool IsImportantDep(DepIterator Dep) {return LocalPolicy->IsImportantDep(Dep);}; inline Policy &GetPolicy() {return *LocalPolicy;}; diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 30bb41470..68aa83d0c 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -307,7 +307,7 @@ const char *pkgCache::Priority(unsigned char Prio) // GrpIterator::FindPkg - Locate a package by arch /*{{{*/ // --------------------------------------------------------------------- /* Returns an End-Pointer on error, pointer to the package otherwise */ -pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) { +pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const { if (unlikely(IsGood() == false || S->FirstPackage == 0)) return PkgIterator(*Owner, 0); @@ -346,7 +346,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) { // GrpIterator::FindPreferredPkg - Locate the "best" package /*{{{*/ // --------------------------------------------------------------------- /* Returns an End-Pointer on error, pointer to the package otherwise */ -pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() { +pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() const { pkgCache::PkgIterator Pkg = FindPkg("native"); if (Pkg.end() == false) return Pkg; @@ -367,7 +367,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() { /* Returns an End-Pointer on error, pointer to the package otherwise. We can't simply ++ to the next as the next package of the last will be from a different group (with the same hash value) */ -pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) { +pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) const { if (unlikely(IsGood() == false || S->FirstPackage == 0 || LastPkg.end() == true)) return PkgIterator(*Owner, 0); @@ -504,7 +504,7 @@ std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const // --------------------------------------------------------------------- /* Currently critical deps are defined as depends, predepends and conflicts (including dpkg's Breaks fields). */ -bool pkgCache::DepIterator::IsCritical() +bool pkgCache::DepIterator::IsCritical() const { if (S->Type == pkgCache::Dep::Conflicts || S->Type == pkgCache::Dep::DpkgBreaks || @@ -528,7 +528,7 @@ bool pkgCache::DepIterator::IsCritical() In Conjunction with the DepCache the value of Result may not be super-good since the policy may have made it uninstallable. Using AllTargets is better in this case. */ -bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) +bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const { Result = TargetPkg(); @@ -577,7 +577,7 @@ bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) provides. It includes every possible package-version that could satisfy the dependency. The last item in the list has a 0. The resulting pointer must be delete [] 'd */ -pkgCache::Version **pkgCache::DepIterator::AllTargets() +pkgCache::Version **pkgCache::DepIterator::AllTargets() const { Version **Res = 0; unsigned long Size =0; diff --git a/apt-pkg/policy.h b/apt-pkg/policy.h index 28cb3ccbb..f8b2678de 100644 --- a/apt-pkg/policy.h +++ b/apt-pkg/policy.h @@ -76,7 +76,7 @@ class pkgPolicy : public pkgDepCache::Policy // Things for the cache interface. virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg); - virtual bool IsImportantDep(pkgCache::DepIterator Dep) {return pkgDepCache::Policy::IsImportantDep(Dep);}; + virtual bool IsImportantDep(pkgCache::DepIterator const &Dep) {return pkgDepCache::Policy::IsImportantDep(Dep);}; bool InitDefaults(); pkgPolicy(pkgCache *Owner); diff --git a/debian/changelog b/debian/changelog index d7c6b8d0c..0b1ca3cf1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -32,7 +32,9 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/contrib/fileutl.cc: - show notice about ignored file instead of being always silent - add a Dir::Ignore-Files-Silently list option to control the notice - * + * apt-pkg/policy.h: + - add another round of const& madness as the previous round accidently + NOT override the virtual GetCandidateVer() method (Closes: #587725) -- David Kalnischkies Mon, 28 Jun 2010 22:12:24 +0200 -- cgit v1.2.3-70-g09d2 From dcfa253fa4b3c563b3ed085c40d3336933840d55 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 4 Jul 2010 17:04:07 +0200 Subject: clean deblistparser a bit by get the Architectures at one place instead of distributed in a few methods --- apt-pkg/deb/deblistparser.cc | 23 ++++++++++------------- apt-pkg/deb/deblistparser.h | 4 +++- 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 83c5b8d2e..d1931f909 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -38,6 +38,8 @@ debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File), Arch(Arch) { if (Arch == "native") this->Arch = _config->Find("APT::Architecture"); + Architectures = APT::Configuration::getArchitectures(); + MultiArchEnabled = Architectures.size() > 1; } /*}}}*/ // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/ @@ -155,10 +157,9 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) 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. */ - bool const static multiArch = APT::Configuration::getArchitectures().size() > 1; if (strcmp(Ver.Arch(true),"all") == 0) return true; - else if (multiArch == true) + else if (MultiArchEnabled == true) { // our pseudo packages have no size to not confuse the fetcher Ver->Size = 0; @@ -620,9 +621,6 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, if (Section.Find(Tag,Start,Stop) == false) return true; - static std::vector const archs = APT::Configuration::getArchitectures(); - static bool const multiArch = archs.size() <= 1; - string Package; string const pkgArch = Ver.Arch(true); string Version; @@ -634,13 +632,13 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, if (Start == 0) return _error->Error("Problem parsing dependency %s",Tag); - if (multiArch == true && + if (MultiArchEnabled == true && (Type == pkgCache::Dep::Conflicts || Type == pkgCache::Dep::DpkgBreaks || Type == pkgCache::Dep::Replaces)) { - for (std::vector::const_iterator a = archs.begin(); - a != archs.end(); ++a) + for (std::vector::const_iterator a = Architectures.begin(); + a != Architectures.end(); ++a) if (NewDepends(Ver,Package,*a,Version,Op,Type) == false) return false; } @@ -692,14 +690,13 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver) if (Ver->MultiArch != pkgCache::Version::Foreign) return true; - std::vector const archs = APT::Configuration::getArchitectures(); - if (archs.size() <= 1) + if (MultiArchEnabled == false) return true; string const Package = Ver.ParentPkg().Name(); string const Version = Ver.VerStr(); - for (std::vector::const_iterator a = archs.begin(); - a != archs.end(); ++a) + for (std::vector::const_iterator a = Architectures.begin(); + a != Architectures.end(); ++a) { if (NewProvides(Ver, Package, *a, Version) == false) return false; @@ -739,7 +736,7 @@ bool debListParser::Step() if (Architecture.empty() == true) return true; - if (Arch.empty() == true) + if (Arch.empty() == true || MultiArchEnabled == false) { if (APT::Configuration::checkArchitecture(Architecture) == true) return true; diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 8da051530..6c81d9fa0 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -32,7 +32,9 @@ class debListParser : public pkgCacheGenerator::ListParser pkgTagSection Section; unsigned long iOffset; string Arch; - + std::vector Architectures; + bool MultiArchEnabled; + unsigned long UniqFindTagWrite(const char *Tag); bool ParseStatus(pkgCache::PkgIterator Pkg,pkgCache::VerIterator Ver); bool ParseDepends(pkgCache::VerIterator Ver,const char *Tag, -- cgit v1.2.3-70-g09d2 From 3b5272950a1ac62178f7b8a0144c4c52e194be40 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 5 Jul 2010 11:42:57 +0200 Subject: Try to use NotEquals for the MultiArch Breaks dependencies instead of Less and Greater -> half the dependencies :) --- apt-pkg/pkgcachegen.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 5649cd6f8..05c01494b 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -572,10 +572,7 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress) OldDepLast); // Breaks: ${self}:other (!= ${binary:Version}) NewDepends(D, V, V.VerStr(), - pkgCache::Dep::Less, pkgCache::Dep::DpkgBreaks, - OldDepLast); - NewDepends(D, V, V.VerStr(), - pkgCache::Dep::Greater, pkgCache::Dep::DpkgBreaks, + pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks, OldDepLast); if (V->MultiArch == pkgCache::Version::All) { -- cgit v1.2.3-70-g09d2 From 7e58ab0c0db9e5f27ae91251bf692bf79a046534 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 6 Jul 2010 10:21:45 +0200 Subject: wrap the mmap actions in the CacheGenerator in their own methods to be able to react on condition changes later then we can move mmap --- apt-pkg/pkgcachegen.cc | 53 ++++++++++++++++++++++++++++++++------------------ apt-pkg/pkgcachegen.h | 12 ++++++++---- 2 files changed, 42 insertions(+), 23 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 05c01494b..6a9da4a92 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -61,8 +61,8 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : // Starting header *Cache.HeaderP = pkgCache::Header(); - Cache.HeaderP->VerSysName = Map.WriteString(_system->VS->Label); - Cache.HeaderP->Architecture = Map.WriteString(_config->Find("APT::Architecture")); + Cache.HeaderP->VerSysName = WriteStringInMap(_system->VS->Label); + Cache.HeaderP->Architecture = WriteStringInMap(_config->Find("APT::Architecture")); Cache.ReMap(); } else @@ -96,6 +96,21 @@ pkgCacheGenerator::~pkgCacheGenerator() Map.Sync(0,sizeof(pkgCache::Header)); } /*}}}*/ +// CacheGenerator::WriteStringInMap /*{{{*/ +unsigned long pkgCacheGenerator::WriteStringInMap(const char *String, + const unsigned long &Len) { + return Map.WriteString(String, Len); +} + /*}}}*/ +// CacheGenerator::WriteStringInMap /*{{{*/ +unsigned long pkgCacheGenerator::WriteStringInMap(const char *String) { + return Map.WriteString(String); +} + /*}}}*/ +unsigned long pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/ + return Map.Allocate(size); +} + /*}}}*/ // CacheGenerator::MergeList - Merge the package list /*{{{*/ // --------------------------------------------------------------------- /* This provides the generation of the entries in the cache. Each loop @@ -342,12 +357,12 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) return true; // Get a structure - unsigned long const Group = Map.Allocate(sizeof(pkgCache::Group)); + unsigned long const Group = AllocateInMap(sizeof(pkgCache::Group)); if (unlikely(Group == 0)) return false; Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group); - Grp->Name = Map.WriteString(Name); + Grp->Name = WriteStringInMap(Name); if (unlikely(Grp->Name == 0)) return false; @@ -374,7 +389,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name return true; // Get a structure - unsigned long const Package = Map.Allocate(sizeof(pkgCache::Package)); + unsigned long const Package = AllocateInMap(sizeof(pkgCache::Package)); if (unlikely(Package == 0)) return false; Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package); @@ -418,7 +433,7 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, return true; // Get a structure - unsigned long VerFile = Map.Allocate(sizeof(pkgCache::VerFile)); + unsigned long VerFile = AllocateInMap(sizeof(pkgCache::VerFile)); if (VerFile == 0) return 0; @@ -449,7 +464,7 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, unsigned long Next) { // Get a structure - unsigned long Version = Map.Allocate(sizeof(pkgCache::Version)); + unsigned long Version = AllocateInMap(sizeof(pkgCache::Version)); if (Version == 0) return 0; @@ -457,7 +472,7 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version); Ver->NextVer = Next; Ver->ID = Cache.HeaderP->VersionCount++; - Ver->VerStr = Map.WriteString(VerStr); + Ver->VerStr = WriteStringInMap(VerStr); if (Ver->VerStr == 0) return 0; @@ -474,7 +489,7 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc, return true; // Get a structure - unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile)); + unsigned long DescFile = AllocateInMap(sizeof(pkgCache::DescFile)); if (DescFile == 0) return false; @@ -507,7 +522,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, map_ptrloc Next) { // Get a structure - map_ptrloc Description = Map.Allocate(sizeof(pkgCache::Description)); + map_ptrloc Description = AllocateInMap(sizeof(pkgCache::Description)); if (Description == 0) return 0; @@ -515,8 +530,8 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description); Desc->NextDesc = Next; Desc->ID = Cache.HeaderP->DescriptionCount++; - Desc->language_code = Map.WriteString(Lang); - Desc->md5sum = Map.WriteString(md5sum.Value()); + Desc->language_code = WriteStringInMap(Lang); + Desc->md5sum = WriteStringInMap(md5sum.Value()); if (Desc->language_code == 0 || Desc->md5sum == 0) return 0; @@ -607,7 +622,7 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, map_ptrloc *OldDepLast) { // Get a structure - unsigned long const Dependency = Map.Allocate(sizeof(pkgCache::Dependency)); + unsigned long const Dependency = AllocateInMap(sizeof(pkgCache::Dependency)); if (unlikely(Dependency == 0)) return false; @@ -625,7 +640,7 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, if (I->Version != 0 && I.TargetVer() == Version) Dep->Version = I->Version;*/ if (Dep->Version == 0) - if (unlikely((Dep->Version = Map.WriteString(Version)) == 0)) + if (unlikely((Dep->Version = WriteStringInMap(Version)) == 0)) return false; } @@ -699,7 +714,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver, return true; // Get a structure - unsigned long const Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides)); + unsigned long const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides)); if (unlikely(Provides == 0)) return false; Cache.HeaderP->ProvidesCount++; @@ -734,12 +749,12 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site, unsigned long Flags) { // Get some space for the structure - CurrentFile = Cache.PkgFileP + Map.Allocate(sizeof(*CurrentFile)); + CurrentFile = Cache.PkgFileP + AllocateInMap(sizeof(*CurrentFile)); if (CurrentFile == Cache.PkgFileP) return false; // Fill it in - CurrentFile->FileName = Map.WriteString(File); + CurrentFile->FileName = WriteStringInMap(File); CurrentFile->Site = WriteUniqString(Site); CurrentFile->NextFile = Cache.HeaderP->FileList; CurrentFile->Flags = Flags; @@ -791,7 +806,7 @@ unsigned long pkgCacheGenerator::WriteUniqString(const char *S, } // Get a structure - unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem)); + unsigned long Item = AllocateInMap(sizeof(pkgCache::StringItem)); if (Item == 0) return 0; @@ -799,7 +814,7 @@ unsigned long pkgCacheGenerator::WriteUniqString(const char *S, pkgCache::StringItem *ItemP = Cache.StringItemP + Item; ItemP->NextItem = I - Cache.StringItemP; *Last = Item; - ItemP->String = Map.WriteString(S,Size); + ItemP->String = WriteStringInMap(S,Size); if (ItemP->String == 0) return 0; diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index ff0941e0c..a88c49451 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -31,9 +31,13 @@ class pkgIndexFile; class pkgCacheGenerator /*{{{*/ { private: - + pkgCache::StringItem *UniqHash[26]; - + unsigned long WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); }; + unsigned long WriteStringInMap(const char *String); + unsigned long WriteStringInMap(const char *String, const unsigned long &Len); + unsigned long AllocateInMap(const unsigned long &size); + public: class ListParser; @@ -103,8 +107,8 @@ class pkgCacheGenerator::ListParser inline unsigned long WriteUniqString(string S) {return Owner->WriteUniqString(S);}; inline unsigned long WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; - inline unsigned long WriteString(const string &S) {return Owner->Map.WriteString(S);}; - inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->Map.WriteString(S,Size);}; + inline unsigned long WriteString(const string &S) {return Owner->WriteStringInMap(S);}; + inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; bool NewDepends(pkgCache::VerIterator Ver,const string &Package, const string &Arch, const string &Version,unsigned int Op, unsigned int Type); -- cgit v1.2.3-70-g09d2 From 32b9a14cb4c6bdcddfe84c4451c225ced1a34bb7 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 8 Jul 2010 11:10:46 +0200 Subject: use references instead of copies in the Cache generation methods --- apt-pkg/deb/deblistparser.cc | 16 ++++++++-------- apt-pkg/deb/deblistparser.h | 14 +++++++------- apt-pkg/pkgcachegen.cc | 9 +++++---- apt-pkg/pkgcachegen.h | 12 ++++++------ 4 files changed, 26 insertions(+), 25 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 24df57a5c..2cfeb23e9 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -106,7 +106,7 @@ string debListParser::Version() // ListParser::NewVersion - Fill in the version structure /*{{{*/ // --------------------------------------------------------------------- /* */ -bool debListParser::NewVersion(pkgCache::VerIterator Ver) +bool debListParser::NewVersion(pkgCache::VerIterator &Ver) { // Parse the section Ver->Section = UniqFindTagWrite("Section"); @@ -251,8 +251,8 @@ MD5SumValue debListParser::Description_md5() // --------------------------------------------------------------------- /* This is called to update the package with any new information that might be found in the section */ -bool debListParser::UsePackage(pkgCache::PkgIterator Pkg, - pkgCache::VerIterator Ver) +bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver) { if (Pkg->Section == 0) Pkg->Section = UniqFindTagWrite("Section"); @@ -332,8 +332,8 @@ unsigned short debListParser::VersionHash() Some of the above are obsolete (I think?) flag = hold-* and status = post-inst-failed, removal-failed at least. */ -bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg, - pkgCache::VerIterator Ver) +bool debListParser::ParseStatus(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver) { const char *Start; const char *Stop; @@ -634,7 +634,7 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, // --------------------------------------------------------------------- /* This is the higher level depends parser. It takes a tag and generates a complete depends tree for the given version. */ -bool debListParser::ParseDepends(pkgCache::VerIterator Ver, +bool debListParser::ParseDepends(pkgCache::VerIterator &Ver, const char *Tag,unsigned int Type) { const char *Start; @@ -674,7 +674,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, // ListParser::ParseProvides - Parse the provides list /*{{{*/ // --------------------------------------------------------------------- /* */ -bool debListParser::ParseProvides(pkgCache::VerIterator Ver) +bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) { const char *Start; const char *Stop; @@ -779,7 +779,7 @@ bool debListParser::Step() // ListParser::LoadReleaseInfo - Load the release information /*{{{*/ // --------------------------------------------------------------------- /* */ -bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, +bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, FileFd &File, string component) { pkgTagFile Tags(&File, File.Size() + 256); // XXX diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 6c81d9fa0..4bc1bd93c 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -36,10 +36,10 @@ class debListParser : public pkgCacheGenerator::ListParser bool MultiArchEnabled; unsigned long UniqFindTagWrite(const char *Tag); - bool ParseStatus(pkgCache::PkgIterator Pkg,pkgCache::VerIterator Ver); - bool ParseDepends(pkgCache::VerIterator Ver,const char *Tag, + bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); + bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag, unsigned int Type); - bool ParseProvides(pkgCache::VerIterator Ver); + bool ParseProvides(pkgCache::VerIterator &Ver); static bool GrabWord(string Word,WordList *List,unsigned char &Out); public: @@ -51,19 +51,19 @@ class debListParser : public pkgCacheGenerator::ListParser virtual string Architecture(); virtual bool ArchitectureAll(); virtual string Version(); - virtual bool NewVersion(pkgCache::VerIterator Ver); + virtual bool NewVersion(pkgCache::VerIterator &Ver); virtual string Description(); virtual string DescriptionLanguage(); virtual MD5SumValue Description_md5(); virtual unsigned short VersionHash(); - virtual bool UsePackage(pkgCache::PkgIterator Pkg, - pkgCache::VerIterator Ver); + virtual bool UsePackage(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver); virtual unsigned long Offset() {return iOffset;}; virtual unsigned long Size() {return Section.size();}; virtual bool Step(); - bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File, + bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File, string section); static const char *ParseDepends(const char *Start,const char *Stop, diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 6a9da4a92..62e457734 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -157,13 +157,14 @@ bool pkgCacheGenerator::MergeList(ListParser &List, // we first process the package, then the descriptions // (this has the bonus that we get MMap error when we run out // of MMap space) - if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false) + pkgCache::VerIterator Ver(Cache); + if (List.UsePackage(Pkg, Ver) == false) return _error->Error(_("Error occurred while processing %s (UsePackage1)"), PackageName.c_str()); // Find the right version to write the description MD5SumValue CurMd5 = List.Description_md5(); - pkgCache::VerIterator Ver = Pkg.VersionList(); + Ver = Pkg.VersionList(); map_ptrloc *LastVer = &Pkg->VersionList; for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) @@ -668,7 +669,7 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, // --------------------------------------------------------------------- /* This creates a Group and the Package to link this dependency to if needed and handles also the caching of the old endpoint */ -bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver, +bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, const string &PackageName, const string &Arch, const string &Version, @@ -702,7 +703,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver, // ListParser::NewProvides - Create a Provides element /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver, +bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, const string &PkgName, const string &PkgArch, const string &Version) diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index a88c49451..8f7739165 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -109,10 +109,10 @@ class pkgCacheGenerator::ListParser inline unsigned long WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);}; inline unsigned long WriteString(const string &S) {return Owner->WriteStringInMap(S);}; inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; - bool NewDepends(pkgCache::VerIterator Ver,const string &Package, const string &Arch, + bool NewDepends(pkgCache::VerIterator &Ver,const string &Package, const string &Arch, const string &Version,unsigned int Op, unsigned int Type); - bool NewProvides(pkgCache::VerIterator Ver,const string &PkgName, + bool NewProvides(pkgCache::VerIterator &Ver,const string &PkgName, const string &PkgArch, const string &Version); public: @@ -122,13 +122,13 @@ class pkgCacheGenerator::ListParser virtual string Architecture() = 0; virtual bool ArchitectureAll() = 0; virtual string Version() = 0; - virtual bool NewVersion(pkgCache::VerIterator Ver) = 0; + virtual bool NewVersion(pkgCache::VerIterator &Ver) = 0; virtual string Description() = 0; virtual string DescriptionLanguage() = 0; virtual MD5SumValue Description_md5() = 0; virtual unsigned short VersionHash() = 0; - virtual bool UsePackage(pkgCache::PkgIterator Pkg, - pkgCache::VerIterator Ver) = 0; + virtual bool UsePackage(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver) = 0; virtual unsigned long Offset() = 0; virtual unsigned long Size() = 0; @@ -136,7 +136,7 @@ class pkgCacheGenerator::ListParser inline bool HasFileDeps() {return FoundFileDeps;}; virtual bool CollectFileProvides(pkgCache &Cache, - pkgCache::VerIterator Ver) {return true;}; + pkgCache::VerIterator &Ver) {return true;}; ListParser() : FoundFileDeps(false) {}; virtual ~ListParser() {}; -- cgit v1.2.3-70-g09d2 From a9fe592842bfa17d91f4904d7fb0e3af3adebb17 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 8 Jul 2010 15:28:53 +0200 Subject: * apt-pkg/pkgcachegen.{cc,h}: - make the used MMap moveable (and therefore dynamic resizeable) by applying (some) mad pointer magic (Closes: #195018) --- apt-pkg/cacheiterators.h | 6 ++ apt-pkg/contrib/mmap.cc | 27 ++++-- apt-pkg/deb/debindexfile.cc | 1 + apt-pkg/pkgcache.cc | 5 +- apt-pkg/pkgcache.h | 2 +- apt-pkg/pkgcachegen.cc | 229 ++++++++++++++++++++++++++++++++------------ apt-pkg/pkgcachegen.h | 30 ++++-- debian/changelog | 3 + 8 files changed, 226 insertions(+), 77 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index dfe5707e1..eb8dee5e3 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -75,6 +75,12 @@ template class pkgCache::Iterator : inline bool IsGood() const { return S && Owner && ! end();}; inline unsigned long Index() const {return S - OwnerPointer();}; + void ReOwn(pkgCache &newOwner, void const * const oldMap, void const * const newMap) { + if (S == 0) + return; + S += (Str*)(newMap) - (Str*)(oldMap); + } + // Constructors - look out for the variable assigning inline Iterator() : S(0), Owner(0) {}; inline Iterator(pkgCache &Owner,Str *T = 0) : S(T), Owner(&Owner) {}; diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index d71066243..aa184b130 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -225,22 +225,22 @@ DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace, // disable Moveable if we don't grow if (Grow == 0) - Flags &= ~Moveable; + this->Flags &= ~Moveable; #ifndef __linux__ // kfreebsd doesn't have mremap, so we use the fallback - if ((Flags & Moveable) == Moveable) - Flags |= Fallback; + if ((this->Flags & Moveable) == Moveable) + this->Flags |= Fallback; #endif #ifdef _POSIX_MAPPED_FILES - if ((Flags & Fallback) != Fallback) { + if ((this->Flags & Fallback) != Fallback) { // Set the permissions. int Prot = PROT_READ; int Map = MAP_PRIVATE | MAP_ANONYMOUS; - if ((Flags & ReadOnly) != ReadOnly) + if ((this->Flags & ReadOnly) != ReadOnly) Prot |= PROT_WRITE; - if ((Flags & Public) == Public) + if ((this->Flags & Public) == Public) Map = MAP_SHARED | MAP_ANONYMOUS; // use anonymous mmap() to get the memory @@ -314,7 +314,7 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) // Look for a matching pool entry Pool *I; Pool *Empty = 0; - for (I = Pools; I != Pools + PoolCount; I++) + for (I = Pools; I != Pools + PoolCount; ++I) { if (I->ItemSize == 0) Empty = I; @@ -342,7 +342,11 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) { const unsigned long size = 20*1024; I->Count = size/ItemSize; + Pool* oldPools = Pools; Result = RawAllocate(size,ItemSize); + if (Pools != oldPools) + I += Pools - oldPools; + // Does the allocation failed ? if (Result == 0 && _error->PendingError()) return 0; @@ -365,7 +369,7 @@ unsigned long DynamicMMap::WriteString(const char *String, if (Len == (unsigned long)-1) Len = strlen(String); - unsigned long Result = RawAllocate(Len+1,0); + unsigned long const Result = RawAllocate(Len+1,0); if (Result == 0 && _error->PendingError()) return 0; @@ -395,16 +399,20 @@ bool DynamicMMap::Grow() { return _error->Error(_("Unable to increase the size of the MMap as the " "limit of %lu bytes is already reached."), Limit); - unsigned long const newSize = WorkSpace + 1024*1024; + unsigned long const newSize = WorkSpace + GrowFactor; if(Fd != 0) { Fd->Seek(newSize - 1); char C = 0; Fd->Write(&C,sizeof(C)); } + + unsigned long const poolOffset = Pools - ((Pool*) Base); + if ((Flags & Fallback) != Fallback) { #if defined(_POSIX_MAPPED_FILES) && defined(__linux__) #ifdef MREMAP_MAYMOVE + if ((Flags & Moveable) == Moveable) Base = mremap(Base, WorkSpace, newSize, MREMAP_MAYMOVE); else @@ -425,6 +433,7 @@ bool DynamicMMap::Grow() { return false; } + Pools =(Pool*) Base + poolOffset; WorkSpace = newSize; return true; } diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 6d9e99497..5e6db3f38 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -277,6 +277,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const // Store the IMS information pkgCache::PkgFileIterator File = Gen.GetCurFile(); + pkgCacheGenerator::Dynamic DynFile(File); struct stat St; if (fstat(Pkg.Fd(),&St) != 0) return _error->Errno("fstat","Failed to stat"); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 68aa83d0c..8af8ef7de 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -119,7 +119,7 @@ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map) // Cache::ReMap - Reopen the cache file /*{{{*/ // --------------------------------------------------------------------- /* If the file is already closed then this will open it open it. */ -bool pkgCache::ReMap() +bool pkgCache::ReMap(bool const &Errorchecks) { // Apply the typecasts. HeaderP = (Header *)Map.Data(); @@ -135,6 +135,9 @@ bool pkgCache::ReMap() StringItemP = (StringItem *)Map.Data(); StrP = (char *)Map.Data(); + if (Errorchecks == false) + return true; + if (Map.Size() == 0 || HeaderP == 0) return _error->Error(_("Empty package cache")); diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 426bb9f13..799521784 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -174,7 +174,7 @@ class pkgCache /*{{{*/ StringItem *StringItemP; char *StrP; - virtual bool ReMap(); + virtual bool ReMap(bool const &Errorchecks = true); inline bool Sync() {return Map.Sync();}; inline MMap &GetMap() {return Map;}; inline void *DataEnd() {return ((unsigned char *)Map.Data()) + Map.Size();}; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 62e457734..18bad6727 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -36,6 +36,7 @@ #include /*}}}*/ typedef vector::iterator FileIterator; +template std::set pkgCacheGenerator::Dynamic::toReMap; // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -61,8 +62,12 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : // Starting header *Cache.HeaderP = pkgCache::Header(); - Cache.HeaderP->VerSysName = WriteStringInMap(_system->VS->Label); - Cache.HeaderP->Architecture = WriteStringInMap(_config->Find("APT::Architecture")); + map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label); + Cache.HeaderP->VerSysName = idxVerSysName; + map_ptrloc const idxArchitecture = WriteStringInMap(_config->Find("APT::Architecture")); + Cache.HeaderP->Architecture = idxArchitecture; + if (unlikely(idxVerSysName == 0 || idxArchitecture == 0)) + return; Cache.ReMap(); } else @@ -96,19 +101,65 @@ pkgCacheGenerator::~pkgCacheGenerator() Map.Sync(0,sizeof(pkgCache::Header)); } /*}}}*/ +void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap) {/*{{{*/ + if (oldMap == newMap) + return; + + Cache.ReMap(false); + + CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap; + + for (size_t i = 0; i < _count(UniqHash); ++i) + if (UniqHash[i] != 0) + UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap; + + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); +} /*}}}*/ // CacheGenerator::WriteStringInMap /*{{{*/ -unsigned long pkgCacheGenerator::WriteStringInMap(const char *String, +map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String, const unsigned long &Len) { - return Map.WriteString(String, Len); + void const * const oldMap = Map.Data(); + map_ptrloc const index = Map.WriteString(String, Len); + if (index != 0) + ReMap(oldMap, Map.Data()); + return index; } /*}}}*/ // CacheGenerator::WriteStringInMap /*{{{*/ -unsigned long pkgCacheGenerator::WriteStringInMap(const char *String) { - return Map.WriteString(String); +map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String) { + void const * const oldMap = Map.Data(); + map_ptrloc const index = Map.WriteString(String); + if (index != 0) + ReMap(oldMap, Map.Data()); + return index; } /*}}}*/ -unsigned long pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/ - return Map.Allocate(size); +map_ptrloc pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/ + void const * const oldMap = Map.Data(); + map_ptrloc const index = Map.Allocate(size); + if (index != 0) + ReMap(oldMap, Map.Data()); + return index; } /*}}}*/ // CacheGenerator::MergeList - Merge the package list /*{{{*/ @@ -142,6 +193,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List, { // Get a pointer to the package structure pkgCache::PkgIterator Pkg; + Dynamic DynPkg(Pkg); if (NewPackage(Pkg, PackageName, *arch) == false) return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str()); Counter++; @@ -158,6 +210,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List, // (this has the bonus that we get MMap error when we run out // of MMap space) pkgCache::VerIterator Ver(Cache); + Dynamic DynVer(Ver); if (List.UsePackage(Pkg, Ver) == false) return _error->Error(_("Error occurred while processing %s (UsePackage1)"), PackageName.c_str()); @@ -165,11 +218,11 @@ bool pkgCacheGenerator::MergeList(ListParser &List, // Find the right version to write the description MD5SumValue CurMd5 = List.Description_md5(); Ver = Pkg.VersionList(); - map_ptrloc *LastVer = &Pkg->VersionList; - for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) + for (; Ver.end() == false; ++Ver) { pkgCache::DescIterator Desc = Ver.DescriptionList(); + Dynamic DynDesc(Desc); map_ptrloc *LastDesc = &Ver->DescriptionList; bool duplicate=false; @@ -189,7 +242,11 @@ bool pkgCacheGenerator::MergeList(ListParser &List, if (MD5SumValue(Desc.md5()) == CurMd5) { // Add new description - *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc); + void const * const oldMap = Map.Data(); + map_ptrloc const descindex = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc); + if (oldMap != Map.Data()) + LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + *LastDesc = descindex; Desc->ParentPkg = Pkg.Index(); if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false) @@ -203,7 +260,9 @@ bool pkgCacheGenerator::MergeList(ListParser &List, } pkgCache::VerIterator Ver = Pkg.VersionList(); + Dynamic DynVer(Ver); map_ptrloc *LastVer = &Pkg->VersionList; + void const * oldMap = Map.Data(); int Res = 1; unsigned long const Hash = List.VersionHash(); for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) @@ -242,21 +301,28 @@ bool pkgCacheGenerator::MergeList(ListParser &List, } // Add a new version - *LastVer = NewVersion(Ver,Version,*LastVer); + map_ptrloc const verindex = NewVersion(Ver,Version,*LastVer); + if (verindex == 0 && _error->PendingError()) + return _error->Error(_("Error occurred while processing %s (NewVersion%d)"), + PackageName.c_str(), 1); + + if (oldMap != Map.Data()) + LastVer += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + *LastVer = verindex; Ver->ParentPkg = Pkg.Index(); Ver->Hash = Hash; - if ((*LastVer == 0 && _error->PendingError()) || List.NewVersion(Ver) == false) - return _error->Error(_("Error occurred while processing %s (NewVersion1)"), - PackageName.c_str()); + if (List.NewVersion(Ver) == false) + return _error->Error(_("Error occurred while processing %s (NewVersion%d)"), + PackageName.c_str(), 2); if (List.UsePackage(Pkg,Ver) == false) return _error->Error(_("Error occurred while processing %s (UsePackage3)"), PackageName.c_str()); if (NewFileVer(Ver,List) == false) - return _error->Error(_("Error occurred while processing %s (NewVersion2)"), - PackageName.c_str()); + return _error->Error(_("Error occurred while processing %s (NewVersion%d)"), + PackageName.c_str(), 3); // Read only a single record and return if (OutVer != 0) @@ -269,13 +335,18 @@ bool pkgCacheGenerator::MergeList(ListParser &List, /* Record the Description data. Description data always exist in Packages and Translation-* files. */ pkgCache::DescIterator Desc = Ver.DescriptionList(); + Dynamic DynDesc(Desc); map_ptrloc *LastDesc = &Ver->DescriptionList; - + // Skip to the end of description set for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++); // Add new description - *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc); + oldMap = Map.Data(); + map_ptrloc const descindex = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc); + if (oldMap != Map.Data()) + LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + *LastDesc = descindex; Desc->ParentPkg = Pkg.Index(); if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false) @@ -322,6 +393,7 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List) continue; pkgCache::PkgIterator Pkg = Cache.FindPkg(PackageName); + Dynamic DynPkg(Pkg); if (Pkg.end() == true) return _error->Error(_("Error occurred while processing %s (FindPkg)"), PackageName.c_str()); @@ -331,6 +403,7 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List) unsigned long Hash = List.VersionHash(); pkgCache::VerIterator Ver = Pkg.VersionList(); + Dynamic DynVer(Ver); for (; Ver.end() == false; Ver++) { if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr()) @@ -358,14 +431,15 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) return true; // Get a structure - unsigned long const Group = AllocateInMap(sizeof(pkgCache::Group)); + map_ptrloc const Group = AllocateInMap(sizeof(pkgCache::Group)); if (unlikely(Group == 0)) return false; Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group); - Grp->Name = WriteStringInMap(Name); - if (unlikely(Grp->Name == 0)) + map_ptrloc const idxName = WriteStringInMap(Name); + if (unlikely(idxName == 0)) return false; + Grp->Name = idxName; // Insert it into the hash table unsigned long const Hash = Cache.Hash(Name); @@ -382,6 +456,7 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name, const string &Arch) { pkgCache::GrpIterator Grp; + Dynamic DynGrp(Grp); if (unlikely(NewGroup(Grp, Name) == false)) return false; @@ -390,7 +465,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name return true; // Get a structure - unsigned long const Package = AllocateInMap(sizeof(pkgCache::Package)); + map_ptrloc const Package = AllocateInMap(sizeof(pkgCache::Package)); if (unlikely(Package == 0)) return false; Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package); @@ -416,9 +491,10 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name // Set the name, arch and the ID Pkg->Name = Grp->Name; Pkg->Group = Grp.Index(); - Pkg->Arch = WriteUniqString(Arch.c_str()); - if (unlikely(Pkg->Arch == 0)) + map_ptrloc const idxArch = WriteUniqString(Arch.c_str()); + if (unlikely(idxArch == 0)) return false; + Pkg->Arch = idxArch; Pkg->ID = Cache.HeaderP->PackageCount++; return true; @@ -434,7 +510,7 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, return true; // Get a structure - unsigned long VerFile = AllocateInMap(sizeof(pkgCache::VerFile)); + map_ptrloc const VerFile = AllocateInMap(sizeof(pkgCache::VerFile)); if (VerFile == 0) return 0; @@ -465,7 +541,7 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, unsigned long Next) { // Get a structure - unsigned long Version = AllocateInMap(sizeof(pkgCache::Version)); + map_ptrloc const Version = AllocateInMap(sizeof(pkgCache::Version)); if (Version == 0) return 0; @@ -473,9 +549,10 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version); Ver->NextVer = Next; Ver->ID = Cache.HeaderP->VersionCount++; - Ver->VerStr = WriteStringInMap(VerStr); - if (Ver->VerStr == 0) + map_ptrloc const idxVerStr = WriteStringInMap(VerStr); + if (unlikely(idxVerStr == 0)) return 0; + Ver->VerStr = idxVerStr; return Version; } @@ -490,7 +567,7 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc, return true; // Get a structure - unsigned long DescFile = AllocateInMap(sizeof(pkgCache::DescFile)); + map_ptrloc const DescFile = AllocateInMap(sizeof(pkgCache::DescFile)); if (DescFile == 0) return false; @@ -523,7 +600,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, map_ptrloc Next) { // Get a structure - map_ptrloc Description = AllocateInMap(sizeof(pkgCache::Description)); + map_ptrloc const Description = AllocateInMap(sizeof(pkgCache::Description)); if (Description == 0) return 0; @@ -531,10 +608,12 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description); Desc->NextDesc = Next; Desc->ID = Cache.HeaderP->DescriptionCount++; - Desc->language_code = WriteStringInMap(Lang); - Desc->md5sum = WriteStringInMap(md5sum.Value()); - if (Desc->language_code == 0 || Desc->md5sum == 0) + map_ptrloc const idxlanguage_code = WriteStringInMap(Lang); + map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value()); + if (unlikely(idxlanguage_code == 0 || idxmd5sum == 0)) return 0; + Desc->language_code = idxlanguage_code; + Desc->md5sum = idxmd5sum; return Description; } @@ -550,15 +629,22 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress) if (archs.size() > 1) { // Create Conflicts in between the group - for (pkgCache::GrpIterator G = GetCache().GrpBegin(); G.end() != true; G++) + pkgCache::GrpIterator G = GetCache().GrpBegin(); + Dynamic DynG(G); + for (; G.end() != true; G++) { string const PkgName = G.Name(); - for (pkgCache::PkgIterator P = G.PackageList(); P.end() != true; P = G.NextPkg(P)) + pkgCache::PkgIterator P = G.PackageList(); + Dynamic DynP(P); + for (; 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++) + Dynamic DynallPkg(allPkg); + pkgCache::VerIterator V = P.VersionList(); + Dynamic DynV(V); + for (; V.end() != true; V++) { string const Arch = V.Arch(true); map_ptrloc *OldDepLast = NULL; @@ -578,6 +664,7 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress) per group, therefore each group member conflicts with all other group members */ pkgCache::PkgIterator D = G.FindPkg(*A); + Dynamic DynD(D); if (D.end() == true) continue; if (coInstall == true) @@ -622,13 +709,15 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, unsigned int const &Type, map_ptrloc *OldDepLast) { + void const * const oldMap = Map.Data(); // Get a structure - unsigned long const Dependency = AllocateInMap(sizeof(pkgCache::Dependency)); + map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency)); if (unlikely(Dependency == 0)) return false; // Fill it in pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency); + Dynamic DynDep(Dep); Dep->ParentVer = Ver.Index(); Dep->Type = Type; Dep->CompareOp = Op; @@ -640,9 +729,12 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++) if (I->Version != 0 && I.TargetVer() == Version) Dep->Version = I->Version;*/ - if (Dep->Version == 0) - if (unlikely((Dep->Version = WriteStringInMap(Version)) == 0)) + if (Dep->Version == 0) { + map_ptrloc const index = WriteStringInMap(Version); + if (unlikely(index == 0)) return false; + Dep->Version = index; + } } // Link it to the package @@ -656,7 +748,8 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, OldDepLast = &Ver->DependsList; for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++) OldDepLast = &D->NextDepends; - } + } else if (oldMap != Map.Data()) + OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; Dep->NextDepends = *OldDepLast; *OldDepLast = Dep.Index(); @@ -677,11 +770,13 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, unsigned int Type) { pkgCache::GrpIterator Grp; + Dynamic DynGrp(Grp); if (unlikely(Owner->NewGroup(Grp, PackageName) == false)) return false; // Locate the target package pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch); + Dynamic DynPkg(Pkg); if (Pkg.end() == true) { if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false)) return false; @@ -715,13 +810,14 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, return true; // Get a structure - unsigned long const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides)); + map_ptrloc const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides)); if (unlikely(Provides == 0)) return false; Cache.HeaderP->ProvidesCount++; // Fill it in pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP); + Dynamic DynPrv(Prv); Prv->Version = Ver.Index(); Prv->NextPkgProv = Ver->ProvidesList; Ver->ProvidesList = Prv.Index(); @@ -730,6 +826,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, // Locate the target package pkgCache::PkgIterator Pkg; + Dynamic DynPkg(Pkg); if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) return false; @@ -750,24 +847,29 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site, unsigned long Flags) { // Get some space for the structure - CurrentFile = Cache.PkgFileP + AllocateInMap(sizeof(*CurrentFile)); - if (CurrentFile == Cache.PkgFileP) + map_ptrloc const idxFile = AllocateInMap(sizeof(*CurrentFile)); + if (unlikely(idxFile == 0)) return false; - + CurrentFile = Cache.PkgFileP + idxFile; + // Fill it in - CurrentFile->FileName = WriteStringInMap(File); - CurrentFile->Site = WriteUniqString(Site); + map_ptrloc const idxFileName = WriteStringInMap(File); + map_ptrloc const idxSite = WriteUniqString(Site); + if (unlikely(idxFileName == 0 || idxSite == 0)) + return false; + CurrentFile->FileName = idxFileName; + CurrentFile->Site = idxSite; CurrentFile->NextFile = Cache.HeaderP->FileList; CurrentFile->Flags = Flags; CurrentFile->ID = Cache.HeaderP->PackageFileCount; - CurrentFile->IndexType = WriteUniqString(Index.GetType()->Label); + map_ptrloc const idxIndexType = WriteUniqString(Index.GetType()->Label); + if (unlikely(idxIndexType == 0)) + return false; + CurrentFile->IndexType = idxIndexType; PkgFileName = File; Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP; Cache.HeaderP->PackageFileCount++; - if (CurrentFile->FileName == 0) - return false; - if (Progress != 0) Progress->SubProgress(Index.Size()); return true; @@ -807,18 +909,25 @@ unsigned long pkgCacheGenerator::WriteUniqString(const char *S, } // Get a structure - unsigned long Item = AllocateInMap(sizeof(pkgCache::StringItem)); + void const * const oldMap = Map.Data(); + map_ptrloc const Item = AllocateInMap(sizeof(pkgCache::StringItem)); if (Item == 0) return 0; + map_ptrloc const idxString = WriteStringInMap(S,Size); + if (unlikely(idxString == 0)) + return 0; + if (oldMap != Map.Data()) { + Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap; + } + *Last = Item; + // Fill in the structure pkgCache::StringItem *ItemP = Cache.StringItemP + Item; ItemP->NextItem = I - Cache.StringItemP; - *Last = Item; - ItemP->String = WriteStringInMap(S,Size); - if (ItemP->String == 0) - return 0; - + ItemP->String = idxString; + Bucket = ItemP; return ItemP->String; } @@ -1072,7 +1181,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress unlink(CacheFile.c_str()); CacheF = new FileFd(CacheFile,FileFd::WriteEmpty); fchmod(CacheF->Fd(),0644); - Map = new DynamicMMap(*CacheF,MMap::Public,MapSize); + Map = new DynamicMMap(*CacheF,MMap::Public | MMap::Moveable, MapSize); if (_error->PendingError() == true) return false; if (Debug == true) @@ -1081,7 +1190,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress else { // Just build it in memory.. - Map = new DynamicMMap(0,MapSize); + Map = new DynamicMMap(MMap::Moveable, MapSize); if (Debug == true) std::clog << "Open memory Map (not filebased)" << std::endl; } @@ -1194,7 +1303,7 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O if (_system->AddStatusFiles(Files) == false) return false; - SPtr Map = new DynamicMMap(0,MapSize); + SPtr Map = new DynamicMMap(MMap::Moveable, MapSize); unsigned long CurrentSize = 0; unsigned long TotalSize = 0; diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 8f7739165..3bee1f958 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -23,6 +23,8 @@ #include #include +#include + class pkgSourceList; class OpProgress; class MMap; @@ -33,18 +35,32 @@ class pkgCacheGenerator /*{{{*/ private: pkgCache::StringItem *UniqHash[26]; - unsigned long WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); }; - unsigned long WriteStringInMap(const char *String); - unsigned long WriteStringInMap(const char *String, const unsigned long &Len); - unsigned long AllocateInMap(const unsigned long &size); + map_ptrloc WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); }; + map_ptrloc WriteStringInMap(const char *String); + map_ptrloc WriteStringInMap(const char *String, const unsigned long &Len); + map_ptrloc AllocateInMap(const unsigned long &size); public: class ListParser; friend class ListParser; - + + template class Dynamic { + Iter *I; + + public: + static std::set toReMap; + Dynamic(Iter &It) : I(&It) { + toReMap.insert(I); + } + + ~Dynamic() { + toReMap.erase(I); + } + }; + protected: - + DynamicMMap ⤅ pkgCache Cache; OpProgress *Progress; @@ -86,6 +102,8 @@ class pkgCacheGenerator /*{{{*/ MMap **OutMap = 0,bool AllowMem = false); static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap); + void ReMap(void const * const oldMap, void const * const newMap); + pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress); ~pkgCacheGenerator(); }; diff --git a/debian/changelog b/debian/changelog index 878d5238a..dab703c6b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -37,6 +37,9 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/policy.h: - add another round of const& madness as the previous round accidentally NOT overrides the virtual GetCandidateVer() method (Closes: #587725) + * apt-pkg/pkgcachegen.{cc,h}: + - make the used MMap moveable (and therefore dynamic resizeable) by + applying (some) mad pointer magic (Closes: #195018) [ Julian Andres Klode ] * methods/ftp.h: -- cgit v1.2.3-70-g09d2