diff options
Diffstat (limited to 'apt')
| -rw-r--r-- | apt/cache.py | 77 | ||||
| -rw-r--r-- | apt/package.py | 63 |
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: |
