summaryrefslogtreecommitdiff
path: root/apt
diff options
context:
space:
mode:
Diffstat (limited to 'apt')
-rw-r--r--apt/cache.py77
-rw-r--r--apt/package.py63
2 files changed, 84 insertions, 56 deletions
diff --git a/apt/cache.py b/apt/cache.py
index cfe6bedc..3679e4ba 100644
--- a/apt/cache.py
+++ b/apt/cache.py
@@ -64,6 +64,7 @@ class Cache(object):
self._callbacks = {}
self._weakref = weakref.WeakValueDictionary()
self._set = set()
+ self._sorted_set = None
if memonly:
# force apt to build its caches in memory
apt_pkg.config.set("Dir::Cache::pkgcache", "")
@@ -126,6 +127,7 @@ class Cache(object):
self._list = apt_pkg.SourceList()
self._list.read_main_list()
self._set.clear()
+ self._sorted_set = None
self._weakref.clear()
progress.op = _("Building data structures")
@@ -136,7 +138,7 @@ class Cache(object):
progress.update(i/float(size)*100)
last = i
# drop stuff with no versions (cruft)
- if len(pkg.version_list) > 0:
+ if pkg.has_versions:
self._set.add(pkg.name)
i += 1
@@ -157,7 +159,15 @@ class Cache(object):
raise KeyError('The cache has no package named %r' % key)
def __iter__(self):
- for pkgname in self._set:
+ # We iterate sorted over package names here. With this we read the
+ # package lists linearly if we need to access the package records,
+ # instead of having to do thousands of random seeks; the latter
+ # is disastrous if we use compressed package indexes, and slower than
+ # necessary for uncompressed indexes.
+ if self._sorted_set is None:
+ self._sorted_set = sorted(self._set)
+
+ for pkgname in self._sorted_set:
yield self[pkgname]
raise StopIteration
@@ -176,10 +186,14 @@ class Cache(object):
def get_changes(self):
""" Get the marked changes """
changes = []
- for pkg in self:
- if (pkg.marked_upgrade or pkg.marked_install or pkg.marked_delete
- or pkg.marked_downgrade or pkg.marked_reinstall):
- changes.append(pkg)
+ marked_keep = self._depcache.marked_keep
+ for pkg in self._cache.packages:
+ if not marked_keep(pkg):
+ try:
+ changes.append(self._weakref[pkg.name])
+ except KeyError:
+ package = self._weakref[pkg.name] = Package(self, pkg)
+ changes.append(package)
return changes
@deprecated_args
@@ -211,10 +225,12 @@ class Cache(object):
def req_reinstall_pkgs(self):
"""Return the packages not downloadable packages in reqreinst state."""
reqreinst = set()
- for pkg in self:
- if (not pkg.candidate.downloadable and
- (pkg._pkg.inst_state == apt_pkg.INSTSTATE_REINSTREQ or
- pkg._pkg.inst_state == apt_pkg.INSTSTATE_HOLD_REINSTREQ)):
+ get_candidate_ver = self._depcache.get_candidate_ver
+ states = frozenset((apt_pkg.INSTSTATE_REINSTREQ,
+ apt_pkg.INSTSTATE_HOLD_REINSTREQ))
+ for pkg in self._cache.packages:
+ cand = get_candidate_ver(pkg)
+ if cand and not cand.downloadable and pkg.inst_state in states:
reqreinst.add(pkg.name)
return reqreinst
@@ -269,29 +285,36 @@ class Cache(object):
except KeyError:
return False
else:
- return bool(pkg.provides_list and not pkg.version_list)
+ return bool(pkg.has_provides and not pkg.has_versions)
- def get_providing_packages(self, virtual):
- """
+ def get_providing_packages(self, virtual, candidate_only=True):
+ """Return a list of all packages providing a virtual package.
+
Return a list of packages which provide the virtual package of the
- specified name
+ specified name. If 'candidate_only' is False, return all packages
+ with at least one version providing the virtual package. Otherwise,
+ return only those packages where the candidate version provides
+ the virtual package.
"""
- providers = []
+
+ providers = set()
+ get_candidate_ver = self._depcache.get_candidate_ver
try:
vp = self._cache[virtual]
- if len(vp.version_list) != 0:
- return providers
+ if vp.has_versions:
+ return list(providers)
except KeyError:
- return providers
- for pkg in self:
- v = self._depcache.get_candidate_ver(pkg._pkg)
- if v is None:
- continue
- for p in v.provides_list:
- if virtual == p[0]:
- # we found a pkg that provides this virtual pkg
- providers.append(pkg)
- return providers
+ return list(providers)
+
+ for provides, providesver, version in vp.provides_list:
+ pkg = version.parent_pkg
+ if not candidate_only or (version == get_candidate_ver(pkg)):
+ try:
+ providers.add(self._weakref[pkg.name])
+ except KeyError:
+ package = self._weakref[pkg.name] = Package(self, pkg)
+ providers.add(package)
+ return list(providers)
@deprecated_args
def update(self, fetch_progress=None, pulse_interval=0,
diff --git a/apt/package.py b/apt/package.py
index 0c026504..228a3385 100644
--- a/apt/package.py
+++ b/apt/package.py
@@ -379,6 +379,14 @@ class Version(object):
return self.package.name
@property
+ def source_version(self):
+ """Return the version of the source package."""
+ try:
+ return self._records.source_ver or self._cand.ver_str
+ except IndexError:
+ return self._cand.ver_str
+
+ @property
def priority(self):
"""Return the priority of the package, as string."""
return self._cand.priority_str
@@ -536,13 +544,13 @@ class Version(object):
dsc = None
record = self._records
- src.lookup(record.source_pkg)
+ source_name = record.source_pkg or self.package.name
source_version = record.source_ver or self._cand.ver_str
+ source_lookup = src.lookup(source_name)
- try:
- while source_version != src.version:
- src.lookup(record.source_pkg)
- except AttributeError:
+ while source_lookup and source_version != src.version:
+ source_lookup = src.lookup(source_name)
+ if not source_lookup:
raise ValueError("No source for %r" % self)
files = list()
for md5, size, path, type_ in src.files:
@@ -955,9 +963,9 @@ class Package(object):
"""
path = "/var/lib/dpkg/info/%s.list" % self.name
try:
- file_list = open(path)
+ file_list = open(path, "rb")
try:
- return file_list.read().decode().split("\n")
+ return file_list.read().decode("utf-8").split(u"\n")
finally:
file_list.close()
except EnvironmentError:
@@ -1006,34 +1014,31 @@ class Package(object):
src_section = "main"
# use the section of the candidate as a starting point
section = self.candidate.section
-
- # get the source version, start with the binaries version
- bin_ver = self.candidate.version
- src_ver = self.candidate.version
- #print "bin: %s" % binver
+
+ # get the source version
+ src_ver = self.candidate.source_version
+
try:
- # FIXME: This try-statement is too long ...
# try to get the source version of the pkg, this differs
# for some (e.g. libnspr4 on ubuntu)
# this feature only works if the correct deb-src are in the
- # sources.list
- # otherwise we fall back to the binary version number
+ # sources.list otherwise we fall back to the binary version number
src_records = apt_pkg.SourceRecords()
- src_rec = src_records.lookup(src_pkg)
- if src_rec:
- src_ver = src_records.version
- #if apt_pkg.VersionCompare(binver, srcver) > 0:
- # srcver = binver
- if not src_ver:
- src_ver = bin_ver
- #print "srcver: %s" % src_ver
- section = src_records.section
- #print "srcsect: %s" % section
- else:
- # fail into the error handler
- raise SystemError
except SystemError:
- src_ver = bin_ver
+ pass
+ else:
+ while src_records.lookup(src_pkg):
+ if not src_records.version:
+ continue
+ if self.candidate.source_version == src_records.version:
+ # Direct match, use it and do not do more lookups.
+ src_ver = src_records.version
+ section = src_records.section
+ break
+ if apt_pkg.version_compare(src_records.version, src_ver) > 0:
+ # The version is higher, it seems to match.
+ src_ver = src_records.version
+ section = src_records.section
section_split = section.split("/", 1)
if len(section_split) > 1: