summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc13
-rw-r--r--apt-pkg/aptconfiguration.cc15
-rw-r--r--apt-pkg/cachefile.cc106
-rw-r--r--apt-pkg/cachefile.h30
-rw-r--r--apt-pkg/cacheiterators.h15
-rw-r--r--apt-pkg/cacheset.cc280
-rw-r--r--apt-pkg/cacheset.h239
-rw-r--r--apt-pkg/contrib/cmndline.cc4
-rw-r--r--apt-pkg/deb/debindexfile.cc18
-rw-r--r--apt-pkg/deb/debindexfile.h6
-rw-r--r--apt-pkg/deb/debsystem.cc2
-rw-r--r--apt-pkg/deb/dpkgpm.cc80
-rw-r--r--apt-pkg/deb/dpkgpm.h17
-rw-r--r--apt-pkg/depcache.cc24
-rw-r--r--apt-pkg/indexfile.h8
-rw-r--r--apt-pkg/indexrecords.cc5
-rw-r--r--apt-pkg/indexrecords.h2
-rw-r--r--apt-pkg/makefile5
-rw-r--r--apt-pkg/pkgcache.cc21
-rw-r--r--apt-pkg/pkgcachegen.cc45
-rw-r--r--apt-pkg/pkgcachegen.h10
21 files changed, 842 insertions, 103 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index c035b9163..9e29f8189 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -1105,13 +1105,16 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/
return;
}
}
-
- // Queue Packages file (either diff or full packages files, depending
- // on the users option)
- if(_config->FindB("Acquire::PDiffs",true) == true)
+
+ /* Queue Packages file (either diff or full packages files, depending
+ on the users option) - we also check if the PDiff Index file is listed
+ in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this
+ instead, but passing the required info to it is to much hassle */
+ if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false ||
+ MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true))
new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
(*Target)->ShortDesc, ExpectedIndexHash);
- else
+ else
new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
(*Target)->ShortDesc, ExpectedIndexHash);
}
diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc
index 2acf8dd9f..0c050d9dc 100644
--- a/apt-pkg/aptconfiguration.cc
+++ b/apt-pkg/aptconfiguration.cc
@@ -327,11 +327,24 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
if (likely(Cached == true) && archs.empty() == false)
return archs;
- string const arch = _config->Find("APT::Architecture");
archs = _config->FindVector("APT::Architectures");
+ string const arch = _config->Find("APT::Architecture");
+ if (unlikely(arch.empty() == true))
+ return archs;
+
if (archs.empty() == true ||
std::find(archs.begin(), archs.end(), arch) == archs.end())
archs.push_back(arch);
+
+ // erase duplicates and empty strings
+ for (std::vector<string>::reverse_iterator a = archs.rbegin();
+ a != archs.rend(); ++a) {
+ if (a->empty() == true || std::find(a + 1, archs.rend(), *a) != archs.rend())
+ archs.erase(a.base()-1);
+ if (a == archs.rend())
+ break;
+ }
+
return archs;
}
/*}}}*/
diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc
index 790312dc8..01598386c 100644
--- a/apt-pkg/cachefile.cc
+++ b/apt-pkg/cachefile.cc
@@ -27,7 +27,8 @@
// CacheFile::CacheFile - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-pkgCacheFile::pkgCacheFile() : Map(0), Cache(0), DCache(0), Policy(0)
+pkgCacheFile::pkgCacheFile() : Map(NULL), Cache(NULL), DCache(NULL),
+ Policy(NULL), SrcList(NULL)
{
}
/*}}}*/
@@ -38,16 +39,30 @@ pkgCacheFile::~pkgCacheFile()
{
delete DCache;
delete Policy;
+ delete SrcList;
delete Cache;
delete Map;
_system->UnLock(true);
-}
+}
/*}}}*/
// CacheFile::BuildCaches - Open and build the cache files /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
+bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock)
{
+ if (Cache != NULL)
+ return true;
+
+ if (_config->FindB("pkgCacheFile::Generate", true) == false)
+ {
+ Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
+ FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
+ Cache = new pkgCache(Map);
+ if (_error->PendingError() == true)
+ return false;
+ return true;
+ }
+
const bool ErrorWasEmpty = _error->empty();
if (WithLock == true)
if (_system->Lock() == false)
@@ -58,15 +73,13 @@ bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
if (_error->PendingError() == true)
return false;
-
- // Read the source list
- pkgSourceList List;
- if (List.ReadMainList() == false)
- return _error->Error(_("The list of sources could not be read."));
+
+ BuildSourceList(Progress);
// Read the caches
- bool Res = pkgMakeStatusCache(List,Progress,&Map,!WithLock);
- Progress.Done();
+ bool Res = pkgCacheGenerator::MakeStatusCache(*SrcList,Progress,&Map,!WithLock);
+ if (Progress != NULL)
+ Progress->Done();
if (Res == false)
return _error->Error(_("The package lists or status file could not be parsed or opened."));
@@ -80,29 +93,70 @@ bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
return true;
}
/*}}}*/
-// CacheFile::Open - Open the cache files, creating if necessary /*{{{*/
+// CacheFile::BuildSourceList - Open and build all relevant sources.list/*{{{*/
// ---------------------------------------------------------------------
/* */
-bool pkgCacheFile::Open(OpProgress &Progress,bool WithLock)
+bool pkgCacheFile::BuildSourceList(OpProgress *Progress)
{
- if (BuildCaches(Progress,WithLock) == false)
- return false;
-
- // The policy engine
+ if (SrcList != NULL)
+ return true;
+
+ SrcList = new pkgSourceList();
+ if (SrcList->ReadMainList() == false)
+ return _error->Error(_("The list of sources could not be read."));
+ return true;
+}
+ /*}}}*/
+// CacheFile::BuildPolicy - Open and build all relevant preferences /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheFile::BuildPolicy(OpProgress *Progress)
+{
+ if (Policy != NULL)
+ return true;
+
Policy = new pkgPolicy(Cache);
if (_error->PendingError() == true)
return false;
if (ReadPinFile(*Policy) == false || ReadPinDir(*Policy) == false)
return false;
-
- // Create the dependency cache
+
+ return true;
+}
+ /*}}}*/
+// CacheFile::BuildDepCache - Open and build the dependency cache /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheFile::BuildDepCache(OpProgress *Progress)
+{
+ if (DCache != NULL)
+ return true;
+
DCache = new pkgDepCache(Cache,Policy);
if (_error->PendingError() == true)
return false;
-
- DCache->Init(&Progress);
- Progress.Done();
+
+ DCache->Init(Progress);
+ return true;
+}
+ /*}}}*/
+// CacheFile::Open - Open the cache files, creating if necessary /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheFile::Open(OpProgress *Progress, bool WithLock)
+{
+ if (BuildCaches(Progress,WithLock) == false)
+ return false;
+
+ if (BuildPolicy(Progress) == false)
+ return false;
+
+ if (BuildDepCache(Progress) == false)
+ return false;
+
+ if (Progress != NULL)
+ Progress->Done();
if (_error->PendingError() == true)
return false;
@@ -117,12 +171,14 @@ void pkgCacheFile::Close()
delete DCache;
delete Policy;
delete Cache;
+ delete SrcList;
delete Map;
_system->UnLock(true);
- Map = 0;
- DCache = 0;
- Policy = 0;
- Cache = 0;
+ Map = NULL;
+ DCache = NULL;
+ Policy = NULL;
+ Cache = NULL;
+ SrcList = NULL;
}
/*}}}*/
diff --git a/apt-pkg/cachefile.h b/apt-pkg/cachefile.h
index 3b057951c..1647aff8e 100644
--- a/apt-pkg/cachefile.h
+++ b/apt-pkg/cachefile.h
@@ -23,6 +23,7 @@
#include <apt-pkg/sourcelist.h>
class pkgPolicy;
+class pkgSourceList;
class pkgCacheFile
{
protected:
@@ -30,27 +31,42 @@ class pkgCacheFile
MMap *Map;
pkgCache *Cache;
pkgDepCache *DCache;
-
+ pkgPolicy *Policy;
+ pkgSourceList *SrcList;
+
public:
- pkgPolicy *Policy;
-
// We look pretty much exactly like a pointer to a dep cache
inline operator pkgCache &() {return *Cache;};
inline operator pkgCache *() {return Cache;};
inline operator pkgDepCache &() {return *DCache;};
inline operator pkgDepCache *() {return DCache;};
+ inline operator pkgPolicy &() {return *Policy;};
+ inline operator pkgPolicy *() {return Policy;};
+ inline operator pkgSourceList &() {return *SrcList;};
+ inline operator pkgSourceList *() {return SrcList;};
inline pkgDepCache *operator ->() {return DCache;};
inline pkgDepCache &operator *() {return *DCache;};
inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) {return (*DCache)[I];};
inline unsigned char &operator [](pkgCache::DepIterator const &I) {return (*DCache)[I];};
- bool BuildCaches(OpProgress &Progress,bool WithLock = true);
- bool Open(OpProgress &Progress,bool WithLock = true);
+ bool BuildCaches(OpProgress *Progress = NULL,bool WithLock = true);
+ __deprecated bool BuildCaches(OpProgress &Progress,bool const &WithLock = true) { return BuildCaches(&Progress, WithLock); };
+ bool BuildSourceList(OpProgress *Progress = NULL);
+ bool BuildPolicy(OpProgress *Progress = NULL);
+ bool BuildDepCache(OpProgress *Progress = NULL);
+ bool Open(OpProgress *Progress = NULL, bool WithLock = true);
+ inline bool ReadOnlyOpen(OpProgress *Progress = NULL) { return Open(Progress, false); };
+ __deprecated bool Open(OpProgress &Progress,bool const &WithLock = true) { return Open(&Progress, WithLock); };
void Close();
-
+
+ inline pkgCache* GetPkgCache() { BuildCaches(NULL, false); return Cache; };
+ inline pkgDepCache* GetDepCache() { BuildDepCache(); return DCache; };
+ inline pkgPolicy* GetPolicy() { BuildPolicy(); return Policy; };
+ inline pkgSourceList* GetSourceList() { BuildSourceList(); return SrcList; };
+
pkgCacheFile();
- ~pkgCacheFile();
+ virtual ~pkgCacheFile();
};
#endif
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h
index e2ca74683..f0b40dbb5 100644
--- a/apt-pkg/cacheiterators.h
+++ b/apt-pkg/cacheiterators.h
@@ -29,10 +29,12 @@
/*}}}*/
#ifndef PKGLIB_CACHEITERATORS_H
#define PKGLIB_CACHEITERATORS_H
+#include<iterator>
// abstract Iterator template /*{{{*/
/* This template provides the very basic iterator methods we
need to have for doing some walk-over-the-cache magic */
-template<typename Str, typename Itr> class pkgCache::Iterator {
+template<typename Str, typename Itr> class pkgCache::Iterator :
+ public std::iterator<std::forward_iterator_tag, Str> {
protected:
Str *S;
pkgCache *Owner;
@@ -64,7 +66,7 @@ template<typename Str, typename Itr> class pkgCache::Iterator {
inline operator Str const *() const {return S == OwnerPointer() ? 0 : S;};
inline Str &operator *() {return *S;};
inline Str const &operator *() const {return *S;};
- inline pkgCache *Cache() {return Owner;};
+ inline pkgCache *Cache() const {return Owner;};
// Mixed stuff
inline void operator =(const Itr &B) {S = B.S; Owner = B.Owner;};
@@ -102,6 +104,11 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;};
inline PkgIterator PackageList() const;
PkgIterator FindPkg(string Arch = "any");
+ /** \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);
// Constructors
@@ -198,8 +205,8 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
inline PrvIterator ProvidesList() const;
inline VerFileIterator FileList() const;
bool Downloadable() const;
- inline const char *PriorityType() {return Owner->Priority(S->Priority);};
- string RelStr();
+ inline const char *PriorityType() const {return Owner->Priority(S->Priority);};
+ string RelStr() const;
bool Automatic() const;
bool Pseudo() const;
diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc
new file mode 100644
index 000000000..43ade4b4e
--- /dev/null
+++ b/apt-pkg/cacheset.cc
@@ -0,0 +1,280 @@
+// -*- 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 <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/cacheset.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/versionmatch.h>
+
+#include <apti18n.h>
+
+#include <vector>
+
+#include <regex.h>
+ /*}}}*/
+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<std::string> archs = APT::Configuration::getArchitectures();
+ for (std::vector<std::string>::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<unsigned short, PackageSet> PackageSet::GroupedFromCommandLine(
+ pkgCacheFile &Cache, const char **cmdline,
+ std::list<PackageSet::Modifier> const &mods,
+ unsigned short const &fallback, std::ostream &out) {
+ std::map<unsigned short, PackageSet> pkgsets;
+ for (const char **I = cmdline; *I != 0; ++I) {
+ unsigned short modID = fallback;
+ std::string str = *I;
+ for (std::list<PackageSet::Modifier>::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;
+}
+ /*}}}*/
+// 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);
+ }
+ 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);
+ 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) {
+ if (unlikely(Cache.BuildDepCache() == false))
+ return pkgCache::VerIterator(*Cache);
+ pkgCache::VerIterator Cand = Cache[Pkg].CandidateVerIter(Cache);
+ 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
new file mode 100644
index 000000000..c9d121083
--- /dev/null
+++ b/apt-pkg/cacheset.h
@@ -0,0 +1,239 @@
+// -*- 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 <iostream>
+#include <fstream>
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/pkgcache.h>
+ /*}}}*/
+namespace APT {
+class PackageSet : public std::set<pkgCache::PkgIterator> { /*{{{*/
+/** \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<pkgCache::PkgIterator>::const_iterator {
+ public:
+ const_iterator(std::set<pkgCache::PkgIterator>::const_iterator x) :
+ std::set<pkgCache::PkgIterator>::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 typename APT::PackageSet::const_iterator iterator;
+
+ using std::set<pkgCache::PkgIterator>::insert;
+ inline void insert(pkgCache::PkgIterator const &P) { if (P.end() == false) std::set<pkgCache::PkgIterator>::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<unsigned short, PackageSet> GroupedFromCommandLine(
+ pkgCacheFile &Cache, const char **cmdline,
+ std::list<PackageSet::Modifier> const &mods,
+ unsigned short const &fallback, std::ostream &out);
+ static std::map<unsigned short, PackageSet> GroupedFromCommandLine(
+ pkgCacheFile &Cache, const char **cmdline,
+ std::list<PackageSet::Modifier> 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<pkgCache::VerIterator> { /*{{{*/
+/** \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<pkgCache::VerIterator>::const_iterator {
+ public:
+ const_iterator(std::set<pkgCache::VerIterator>::const_iterator x) :
+ std::set<pkgCache::VerIterator>::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 typename APT::VersionSet::const_iterator iterator;
+
+ using std::set<pkgCache::VerIterator>::insert;
+ inline void insert(pkgCache::VerIterator const &V) { if (V.end() == false) std::set<pkgCache::VerIterator>::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);
+ }
+ /*}}}*/
+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/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc
index 0b16bf51a..5a9944096 100644
--- a/apt-pkg/contrib/cmndline.cc
+++ b/apt-pkg/contrib/cmndline.cc
@@ -360,11 +360,11 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch)
than nothing after all. */
void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv)
{
- char cmdline[300];
+ char cmdline[100 + argc * 50];
unsigned int length = 0;
bool lastWasOption = false;
bool closeQuote = false;
- for (unsigned int i = 0; i < argc; ++i, ++length)
+ for (unsigned int i = 0; i < argc && length < sizeof(cmdline); ++i, ++length)
{
for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-1; ++j, ++length)
{
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc
index b89429d86..6d9e99497 100644
--- a/apt-pkg/deb/debindexfile.cc
+++ b/apt-pkg/deb/debindexfile.cc
@@ -262,15 +262,15 @@ unsigned long debPackagesIndex::Size() const
// PackagesIndex::Merge - Load the index file into a cache /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
{
string PackageFile = IndexFile("Packages");
FileFd Pkg(PackageFile,FileFd::ReadOnly);
debListParser Parser(&Pkg, Architecture);
if (_error->PendingError() == true)
return _error->Error("Problem opening %s",PackageFile.c_str());
-
- Prog.SubProgress(0,Info("Packages"));
+ if (Prog != NULL)
+ Prog->SubProgress(0,Info("Packages"));
::URI Tmp(URI);
if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
@@ -445,7 +445,7 @@ unsigned long debTranslationsIndex::Size() const
// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
{
// Check the translation file, if in use
string TranslationFile = IndexFile(Language);
@@ -456,7 +456,8 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
if (_error->PendingError() == true)
return false;
- Prog.SubProgress(0, Info(TranslationFile.c_str()));
+ if (Prog != NULL)
+ Prog->SubProgress(0, Info(TranslationFile.c_str()));
if (Gen.SelectFile(TranslationFile,string(),*this) == false)
return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
@@ -529,7 +530,7 @@ unsigned long debStatusIndex::Size() const
// StatusIndex::Merge - Load the index file into a cache /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
{
FileFd Pkg(File,FileFd::ReadOnly);
if (_error->PendingError() == true)
@@ -537,8 +538,9 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
debListParser Parser(&Pkg);
if (_error->PendingError() == true)
return false;
-
- Prog.SubProgress(0,File);
+
+ if (Prog != NULL)
+ Prog->SubProgress(0,File);
if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
return _error->Error("Problem with SelectFile %s",File.c_str());
diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h
index 766e8b214..b5085992d 100644
--- a/apt-pkg/deb/debindexfile.h
+++ b/apt-pkg/deb/debindexfile.h
@@ -35,7 +35,7 @@ class debStatusIndex : public pkgIndexFile
virtual bool Exists() const;
virtual bool HasPackages() const {return true;};
virtual unsigned long Size() const;
- virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+ virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
debStatusIndex(string File);
@@ -67,7 +67,7 @@ class debPackagesIndex : public pkgIndexFile
virtual bool Exists() const;
virtual bool HasPackages() const {return true;};
virtual unsigned long Size() const;
- virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+ virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
debPackagesIndex(string const &URI, string const &Dist, string const &Section,
@@ -99,7 +99,7 @@ class debTranslationsIndex : public pkgIndexFile
virtual bool Exists() const;
virtual bool HasPackages() const;
virtual unsigned long Size() const;
- virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+ virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
debTranslationsIndex(string URI,string Dist,string Section, char const * const Language);
diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc
index 59f826d96..31c26ab2f 100644
--- a/apt-pkg/deb/debsystem.cc
+++ b/apt-pkg/deb/debsystem.cc
@@ -158,7 +158,7 @@ bool debSystem::Initialize(Configuration &Cnf)
/* These really should be jammed into a generic 'Local Database' engine
which is yet to be determined. The functions in pkgcachegen should
be the only users of these */
- Cnf.CndSet("Dir::State::userstatus","status.user"); // Defunct
+ Cnf.CndSet("Dir::State::extended_states", Cnf.FindDir("Dir::State").append("extended_states"));
Cnf.CndSet("Dir::State::status","/var/lib/dpkg/status");
Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg");
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 8318fe37f..0ac6ac168 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -470,7 +470,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
std::clog << "send: '" << status.str() << "'" << endl;
if (strncmp(action, "disappear", strlen("disappear")) == 0)
- disappearedPkgs.insert(string(pkg_or_trigger));
+ handleDisappearAction(pkg_or_trigger);
return;
}
@@ -530,6 +530,51 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
<< " action: " << action << endl;
}
/*}}}*/
+// DPkgPM::handleDisappearAction /*{{{*/
+void pkgDPkgPM::handleDisappearAction(string const &pkgname)
+{
+ // record the package name for display and stuff later
+ disappearedPkgs.insert(pkgname);
+
+ pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname);
+ if (unlikely(Pkg.end() == true))
+ return;
+ // the disappeared package was auto-installed - nothing to do
+ if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
+ return;
+ pkgCache::VerIterator PkgVer = Pkg.CurrentVer();
+ if (unlikely(PkgVer.end() == true))
+ return;
+ /* search in the list of dependencies for (Pre)Depends,
+ check if this dependency has a Replaces on our package
+ and if so transfer the manual installed flag to it */
+ for (pkgCache::DepIterator Dep = PkgVer.DependsList(); Dep.end() != true; ++Dep)
+ {
+ if (Dep->Type != pkgCache::Dep::Depends &&
+ Dep->Type != pkgCache::Dep::PreDepends)
+ continue;
+ pkgCache::PkgIterator Tar = Dep.TargetPkg();
+ if (unlikely(Tar.end() == true))
+ continue;
+ // the package is already marked as manual
+ if ((Cache[Tar].Flags & pkgCache::Flag::Auto) != pkgCache::Flag::Auto)
+ continue;
+ pkgCache::VerIterator TarVer = Tar.CurrentVer();
+ for (pkgCache::DepIterator Rep = TarVer.DependsList(); Rep.end() != true; ++Rep)
+ {
+ if (Rep->Type != pkgCache::Dep::Replaces)
+ continue;
+ if (Pkg != Rep.TargetPkg())
+ continue;
+ // okay, they are strongly connected - transfer manual-bit
+ if (Debug == true)
+ std::clog << "transfer manual-bit from disappeared »" << pkgname << "« to »" << Tar.FullName() << "«" << std::endl;
+ Cache[Tar].Flags &= ~Flag::Auto;
+ break;
+ }
+ }
+}
+ /*}}}*/
// DPkgPM::DoDpkgStatusFd /*{{{*/
// ---------------------------------------------------------------------
/*
@@ -568,15 +613,15 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
}
/*}}}*/
// DPkgPM::WriteHistoryTag /*{{{*/
-void pkgDPkgPM::WriteHistoryTag(string tag, string value)
+void pkgDPkgPM::WriteHistoryTag(string const &tag, string value)
{
- if (value.size() > 0)
- {
- // poor mans rstrip(", ")
- if (value[value.size()-2] == ',' && value[value.size()-1] == ' ')
- value.erase(value.size() - 2, 2);
- fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
- }
+ size_t const length = value.length();
+ if (length == 0)
+ return;
+ // poor mans rstrip(", ")
+ if (value[length-2] == ',' && value[length-1] == ' ')
+ value.erase(length - 2, 2);
+ fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
} /*}}}*/
// DPkgPM::OpenLog /*{{{*/
bool pkgDPkgPM::OpenLog()
@@ -663,7 +708,22 @@ bool pkgDPkgPM::CloseLog()
if(history_out)
{
- if (dpkg_error.size() > 0)
+ if (disappearedPkgs.empty() == false)
+ {
+ string disappear;
+ for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
+ d != disappearedPkgs.end(); ++d)
+ {
+ pkgCache::PkgIterator P = Cache.FindPkg(*d);
+ disappear.append(*d);
+ if (P.end() == true)
+ disappear.append(", ");
+ else
+ disappear.append(" (").append(Cache[P].CurVersion).append("), ");
+ }
+ WriteHistoryTag("Disappeared", disappear);
+ }
+ if (dpkg_error.empty() == false)
fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
fprintf(history_out, "End-Date: %s\n", timestr);
fclose(history_out);
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index 330c788a2..9a4478f7c 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -32,6 +32,21 @@ class pkgDPkgPM : public pkgPackageManager
FILE *history_out;
string dpkg_error;
+ /** \brief record the disappear action and handle accordingly
+
+ dpkg let packages disappear then they have no files any longer and
+ nothing depends on them. We need to collect this as dpkg as well as
+ APT doesn't know beforehand that the package will disappear, so the
+ only possible option is to tell the user afterwards about it.
+ To enhance the experience we also try to forward the auto-install
+ flag so the disappear-causer(s) are not autoremoved next time -
+ for the transfer to happen the disappeared version needs to depend
+ on the package the flag should be forwarded to and this package
+ needs to declare a Replaces on the disappeared package.
+ \param pkgname Name of the package that disappeared
+ */
+ void handleDisappearAction(string const &pkgname);
+
protected:
// progress reporting
@@ -68,7 +83,7 @@ class pkgDPkgPM : public pkgPackageManager
// Helpers
bool RunScriptsWithPkgs(const char *Cnf);
bool SendV2Pkgs(FILE *F);
- void WriteHistoryTag(string tag, string value);
+ void WriteHistoryTag(string const &tag, string value);
// dpkg log
bool OpenLog();
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 786b20ec0..3ae5f5953 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -165,7 +165,7 @@ bool pkgDepCache::Init(OpProgress *Prog)
bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/
{
FileFd state_file;
- string const state = _config->FindDir("Dir::State") + "extended_states";
+ string const state = _config->FindFile("Dir::State::extended_states");
if(FileExists(state)) {
state_file.Open(state, FileFd::ReadOnly);
int const file_size = state_file.Size();
@@ -222,7 +222,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/
std::clog << "pkgDepCache::writeStateFile()" << std::endl;
FileFd StateFile;
- string const state = _config->FindDir("Dir::State") + "extended_states";
+ string const state = _config->FindFile("Dir::State::extended_states");
// if it does not exist, create a empty one
if(!FileExists(state))
@@ -875,7 +875,7 @@ void pkgDepCache::Update(OpProgress *Prog)
a bit we increase with a kill, but we should do something more clever… */
while(recheck.empty() == false)
for (std::set<unsigned long>::const_iterator p = recheck.begin();
- p != recheck.end(); ++p) {
+ p != recheck.end();) {
if (Prog != 0 && Done%20 == 0)
Prog->Progress(Done);
PkgIterator P = PkgIterator(*Cache, Cache->PkgP + *p);
@@ -883,7 +883,7 @@ void pkgDepCache::Update(OpProgress *Prog)
++killed;
++Done;
}
- recheck.erase(p);
+ recheck.erase(p++);
}
/* Okay, we have killed a great amount of pseudopackages -
@@ -918,7 +918,7 @@ void pkgDepCache::Update(OpProgress *Prog)
unsigned long const G = *g;
recheck.erase(g);
if (unlikely(ReInstallPseudoForGroup(G, recheck) == false))
- _error->Warning(_("Internal error, group '%s' has no installable pseudo package"), GrpIterator(*Cache, Cache->GrpP + *g).Name());
+ _error->Warning(_("Internal error, group '%s' has no installable pseudo package"), GrpIterator(*Cache, Cache->GrpP + G).Name());
}
}
@@ -1707,8 +1707,11 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
{
if(!(PkgState[p->ID].Flags & Flag::Auto) ||
(p->Flags & Flag::Essential) ||
- userFunc.InRootSet(p))
-
+ userFunc.InRootSet(p) ||
+ // be nice even then a required package violates the policy (#583517)
+ // and do the full mark process also for required packages
+ (p.CurrentVer().end() != true &&
+ p.CurrentVer()->Priority == pkgCache::State::Required))
{
// the package is installed (and set to keep)
if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
@@ -1785,10 +1788,6 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
// If the version belongs to a Multi-Arch all package
// we will mark all others in this Group with this version also
- // Beware: We compare versions here the lazy way: string comparision
- // this is bad if multiple repositories provide different versions
- // of the package with an identical version number - but even in this
- // case the dependencies are likely the same.
if (ver->MultiArch == pkgCache::Version::All &&
strcmp(ver.Arch(true), "all") == 0)
{
@@ -1800,7 +1799,8 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
for (VerIterator V = P.VersionList();
V.end() != true; ++V)
{
- if (strcmp(VerStr, V.VerStr()) != 0)
+ if (ver->Hash != V->Hash ||
+ strcmp(VerStr, V.VerStr()) != 0)
continue;
MarkPackage(P, V, follow_recommends, follow_suggests);
break;
diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h
index 3cc501629..2b5ae6342 100644
--- a/apt-pkg/indexfile.h
+++ b/apt-pkg/indexfile.h
@@ -74,8 +74,12 @@ class pkgIndexFile
virtual bool Exists() const = 0;
virtual bool HasPackages() const = 0;
virtual unsigned long Size() const = 0;
- virtual bool Merge(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return false;};
- virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return true;};
+ virtual bool Merge(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const { return false; };
+ __deprecated virtual bool Merge(pkgCacheGenerator &Gen, OpProgress &Prog) const
+ { return Merge(Gen, &Prog); };
+ virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const {return true;};
+ __deprecated virtual bool MergeFileProvides(pkgCacheGenerator &Gen, OpProgress &Prog) const
+ {return MergeFileProvides(Gen, &Prog);};
virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
static bool TranslationsAvailable();
diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc
index 1fc27b1a1..9a9600531 100644
--- a/apt-pkg/indexrecords.cc
+++ b/apt-pkg/indexrecords.cc
@@ -31,6 +31,11 @@ const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
return Entries[MetaKey];
}
+bool indexRecords::Exists(string const &MetaKey) const
+{
+ return Entries.count(MetaKey) == 1;
+}
+
bool indexRecords::Load(const string Filename) /*{{{*/
{
FileFd Fd(Filename, FileFd::ReadOnly);
diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h
index 468d2bd0f..2e3103b70 100644
--- a/apt-pkg/indexrecords.h
+++ b/apt-pkg/indexrecords.h
@@ -34,6 +34,8 @@ class indexRecords
// Lookup function
virtual const checkSum *Lookup(const string MetaKey);
+ /** \brief tests if a checksum for this file is available */
+ bool Exists(string const &MetaKey) const;
std::vector<std::string> MetaKeys();
virtual bool Load(string Filename);
diff --git a/apt-pkg/makefile b/apt-pkg/makefile
index 148ad581b..1a7078693 100644
--- a/apt-pkg/makefile
+++ b/apt-pkg/makefile
@@ -35,14 +35,15 @@ 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
+ aptconfiguration.cc cacheset.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
+ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \
+ cacheset.h
# Source code for the debian specific components
# In theory the deb headers do not need to be exported..
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index a59a06d65..30bb41470 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -343,6 +343,25 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
return PkgIterator(*Owner, 0);
}
/*}}}*/
+// GrpIterator::FindPreferredPkg - Locate the "best" package /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns an End-Pointer on error, pointer to the package otherwise */
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() {
+ pkgCache::PkgIterator Pkg = FindPkg("native");
+ if (Pkg.end() == false)
+ return Pkg;
+
+ std::vector<std::string> const archs = APT::Configuration::getArchitectures();
+ for (std::vector<std::string>::const_iterator a = archs.begin();
+ a != archs.end(); ++a) {
+ Pkg = FindPkg(*a);
+ if (Pkg.end() == false)
+ return Pkg;
+ }
+
+ return PkgIterator(*Owner, 0);
+}
+ /*}}}*/
// GrpIterator::NextPkg - Locate the next package in the group /*{{{*/
// ---------------------------------------------------------------------
/* Returns an End-Pointer on error, pointer to the package otherwise.
@@ -723,7 +742,7 @@ pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
// ---------------------------------------------------------------------
/* This describes the version from a release-centric manner. The output is a
list of Label:Version/Archive */
-string pkgCache::VerIterator::RelStr()
+string pkgCache::VerIterator::RelStr() const
{
bool First = true;
string Res;
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index d96d3370f..5649cd6f8 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -526,7 +526,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
// CacheGenerator::FinishCache - do various finish operations /*{{{*/
// ---------------------------------------------------------------------
/* This prepares the Cache for delivery */
-bool pkgCacheGenerator::FinishCache(OpProgress &Progress)
+bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
{
// FIXME: add progress reporting for this operation
// Do we have different architectures in your groups ?
@@ -923,7 +923,7 @@ static unsigned long ComputeSize(FileIterator Start,FileIterator End)
// ---------------------------------------------------------------------
/* */
static bool BuildCache(pkgCacheGenerator &Gen,
- OpProgress &Progress,
+ OpProgress *Progress,
unsigned long &CurrentSize,unsigned long TotalSize,
FileIterator Start, FileIterator End)
{
@@ -944,7 +944,8 @@ static bool BuildCache(pkgCacheGenerator &Gen,
}
unsigned long Size = (*I)->Size();
- Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
+ if (Progress != NULL)
+ Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
CurrentSize += Size;
if ((*I)->Merge(Gen,Progress) == false)
@@ -953,13 +954,15 @@ static bool BuildCache(pkgCacheGenerator &Gen,
if (Gen.HasFileDeps() == true)
{
- Progress.Done();
+ if (Progress != NULL)
+ Progress->Done();
TotalSize = ComputeSize(Start, End);
CurrentSize = 0;
for (I = Start; I != End; I++)
{
unsigned long Size = (*I)->Size();
- Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
+ if (Progress != NULL)
+ Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
CurrentSize += Size;
if ((*I)->MergeFileProvides(Gen,Progress) == false)
return false;
@@ -969,7 +972,7 @@ static bool BuildCache(pkgCacheGenerator &Gen,
return true;
}
/*}}}*/
-// MakeStatusCache - Construct the status cache /*{{{*/
+// CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
// ---------------------------------------------------------------------
/* This makes sure that the status cache (the cache that has all
index files from the sources list and all local ones) is ready
@@ -977,7 +980,10 @@ static bool BuildCache(pkgCacheGenerator &Gen,
the cache will be stored there. This is pretty much mandetory if you
are using AllowMem. AllowMem lets the function be run as non-root
where it builds the cache 'fast' into a memory buffer. */
-bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
+__deprecated bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
+ MMap **OutMap, bool AllowMem)
+ { return pkgCacheGenerator::MakeStatusCache(List, &Progress, OutMap, AllowMem); }
+bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
MMap **OutMap,bool AllowMem)
{
bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
@@ -1028,13 +1034,15 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
if (Writeable == false && AllowMem == false && CacheFile.empty() == false)
return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str());
-
- Progress.OverallProgress(0,1,1,_("Reading package lists"));
-
+
+ if (Progress != NULL)
+ Progress->OverallProgress(0,1,1,_("Reading package lists"));
+
// Cache is OK, Fin.
if (CheckValidity(CacheFile,Files.begin(),Files.end(),OutMap) == true)
{
- Progress.OverallProgress(1,1,1,_("Reading package lists"));
+ if (Progress != NULL)
+ Progress->OverallProgress(1,1,1,_("Reading package lists"));
if (Debug == true)
std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl;
return true;
@@ -1084,7 +1092,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
// Build the status cache
- pkgCacheGenerator Gen(Map.Get(),&Progress);
+ pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
@@ -1101,7 +1109,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
TotalSize = ComputeSize(Files.begin(),Files.end());
// Build the source cache
- pkgCacheGenerator Gen(Map.Get(),&Progress);
+ pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
@@ -1160,10 +1168,12 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
return true;
}
/*}}}*/
-// MakeOnlyStatusCache - Build a cache with just the status files /*{{{*/
+// CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
// ---------------------------------------------------------------------
/* */
-bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
+__deprecated bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
+ { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress, OutMap); }
+bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
{
unsigned long MapSize = _config->FindI("APT::Cache-Limit",20*1024*1024);
vector<pkgIndexFile *> Files;
@@ -1178,8 +1188,9 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
// Build the status cache
- Progress.OverallProgress(0,1,1,_("Reading package lists"));
- pkgCacheGenerator Gen(Map.Get(),&Progress);
+ if (Progress != NULL)
+ Progress->OverallProgress(0,1,1,_("Reading package lists"));
+ pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h
index 46d0cd893..ff0941e0c 100644
--- a/apt-pkg/pkgcachegen.h
+++ b/apt-pkg/pkgcachegen.h
@@ -76,7 +76,11 @@ class pkgCacheGenerator /*{{{*/
bool HasFileDeps() {return FoundFileDeps;};
bool MergeFileProvides(ListParser &List);
- bool FinishCache(OpProgress &Progress);
+ bool FinishCache(OpProgress *Progress);
+
+ static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
+ MMap **OutMap = 0,bool AllowMem = false);
+ static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap);
pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
~pkgCacheGenerator();
@@ -134,10 +138,12 @@ class pkgCacheGenerator::ListParser
virtual ~ListParser() {};
};
/*}}}*/
+
bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
MMap **OutMap = 0,bool AllowMem = false);
bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap);
+
#ifdef APT_COMPATIBILITY
#if APT_COMPATIBILITY != 986
#warning "Using APT_COMPATIBILITY"
@@ -145,7 +151,7 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap);
MMap *pkgMakeStatusCacheMem(pkgSourceList &List,OpProgress &Progress)
{
MMap *Map = 0;
- if (pkgMakeStatusCache(List,Progress,&Map,true) == false)
+ if (pkgCacheGenerator::MakeStatusCache(List,&Progress,&Map,true) == false)
return 0;
return Map;
}