def prune(opt: Namespace) -> None: cache = Cache() cur = {PREFIX + uname()[2] + suffix for suffix in {"", "-signed"}} top = { "univention-kernel-image", PREFIX + "amd64", PREFIX + "rt-amd64", PREFIX + "686-pae", PREFIX + "686", PREFIX + "rt-686-pae", } meta = [ pkg.installed for pkg in (cache[pkg] for pkg in top if pkg in cache) if pkg.is_installed ] if opt.verbose: print("Installed kernel meta packages:\n %s" % ("\n ".join(sorted(str(pkg) for pkg in meta)), )) keep = ({ dep.name for pkg in meta for alt in pkg.dependencies for dep in alt if dep.name.startswith(PREFIX) } | cur | top) if opt.verbose: print("Exception list for kernel packages:\n %s" % ("\n ".join(sorted(keep)), )) cache.clear() for pkg in cache: if pkg.name.startswith(PREFIX) and pkg.is_installed: if pkg.name not in keep: if opt.verbose: print("Purging kernel package: %s" % (pkg.name, )) if not opt.dry_run: pkg.mark_delete(purge=True) else: if opt.verbose: print("Keeping kernel package: %s" % (pkg.name, )) cache.commit()
class RPCAPTCache(InChRootObject): # pylint: disable=too-many-public-methods def __init__(self, rfs, arch, notifier=None, norecommend=False, noauth=True): # pylint: disable=too-many-arguments InChRootObject.__init__(self, rfs) self.notifier = notifier config.set("APT::Architecture", arch) if norecommend: config.set("APT::Install-Recommends", "0") else: config.set("APT::Install-Recommends", "1") if noauth: config.set("APT::Get::AllowUnauthenticated", "1") else: config.set("APT::Get::AllowUnauthenticated", "0") self.cache = Cache(progress=ElbeOpProgress()) self.cache.open(progress=ElbeOpProgress()) def dbg_dump(self, filename): ts = time.localtime() filename = filename + ('_%02d%02d%02d' % (ts.tm_hour, ts.tm_min, ts.tm_sec)) with open(filename, 'w') as dbg: for p in self.cache: dbg.write( '%s %s %d %d %d %d %d %d %d %d %d %d %d %d\n' % (p.name, p.candidate.version, p.marked_keep, p.marked_delete, p.marked_upgrade, p.marked_downgrade, p.marked_install, p.marked_reinstall, p.is_auto_installed, p.is_installed, p.is_auto_removable, p.is_now_broken, p.is_inst_broken, p.is_upgradable)) def get_sections(self): ret = list(set([p.section for p in self.cache])) ret.sort() return ret def get_pkglist(self, section): if section == 'all': ret = [APTPackage(p) for p in self.cache] else: ret = [APTPackage(p) for p in self.cache if p.section == section] return ret def mark_install(self, pkgname, version, from_user=True, nodeps=False): print('Mark for install "%s"' % pkgname) p = self.cache[pkgname] if version: p.candidate = p.versions[version] p.mark_install(auto_fix=not nodeps, auto_inst=not nodeps, from_user=from_user) def mark_install_devpkgs(self, ignore_pkgs, ignore_dev_pkgs): ignore_pkgs.discard('libc6') # we don't want to ignore libc ignore_pkgs.discard('libstdc++5') ignore_pkgs.discard('libstdc++6') # list all debian src packages of all installed packages that don't # come from debootstrap src_list = [ p.candidate.source_name for p in self.cache if (p.is_installed and p.name not in ignore_pkgs) ] version_dict = { p.name: p.candidate.version for p in self.cache if (p.is_installed and p.name not in ignore_pkgs) } # go through all packages, remember package if its source package # matches one of the installed packages and the binary package is a # '-dev' package dev_list = [ s for s in self.cache if (s.candidate.source_name in src_list and ( s.name.endswith('-dev'))) ] for p in dev_list: if p.name not in ignore_dev_pkgs: name_no_suffix = p.name[:-len('-dev')] if name_no_suffix in version_dict: version = version_dict[name_no_suffix] candidate = p.versions.get(version) if candidate: p.candidate = candidate p.mark_install() # ensure that the symlinks package will be installed (it's needed for # fixing links inside the sysroot self.cache['symlinks'].mark_install() for p in ignore_dev_pkgs: self.cache[p].mark_delete() dbgsym_list = [ s.name + '-dbgsym' for s in self.cache if (s.is_installed or s.marked_install) ] for p in dbgsym_list: if p in self.cache: pkg = self.cache[p] name_no_suffix = pkg.name[:-len('-dbgsym')] if name_no_suffix in version_dict: version = version_dict[name_no_suffix] candidate = pkg.versions.get(version) if candidate: pkg.candidate = candidate pkg.mark_install() def cleanup(self, exclude_pkgs): for p in self.cache: if p.is_installed and not \ p.is_auto_installed or \ p.is_auto_removable: remove = True for x in exclude_pkgs: if x == p.name: remove = False if remove: p.mark_delete(auto_fix=True, purge=True) def mark_upgrade(self, pkgname, version): p = self.cache[pkgname] if version: p.candidate = p.versions[version] p.mark_upgrade() def mark_delete(self, pkgname): p = self.cache[pkgname] p.mark_delete(purge=True) def mark_keep(self, pkgname, version): p = self.cache[pkgname] p.mark_keep() def update(self): self.cache.update(fetch_progress=ElbeAcquireProgress()) self.cache.open(progress=ElbeOpProgress()) def commit(self): os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["DEBONF_NONINTERACTIVE_SEEN"] = "true" print("Commiting changes ...") self.cache.commit(ElbeAcquireProgress(), ElbeInstallProgress(fileno=sys.stdout.fileno())) self.cache.open(progress=ElbeOpProgress()) def clear(self): self.cache.clear() def get_dependencies(self, pkgname): deps = getalldeps(self.cache, pkgname) return [APTPackage(p, cache=self.cache) for p in deps] def get_installed_pkgs(self, section='all'): if section == 'all': pl = [APTPackage(p) for p in self.cache if p.is_installed] else: pl = [ APTPackage(p) for p in self.cache if (p.section == section and p.is_installed) ] return pl def get_fileindex(self): index = {} for p in self.cache: if p.is_installed: for f in p.installed_files: index[f] = p.name return index def get_marked_install(self, section='all'): if section == 'all': ret = [APTPackage(p) for p in self.cache if p.marked_install] else: ret = [ APTPackage(p) for p in self.cache if (p.section == section and p.marked_install) ] return ret def get_upgradeable(self, section='all'): if section == 'all': ret = [APTPackage(p) for p in self.cache if p.is_upgradable] else: ret = [ APTPackage(p) for p in self.cache if (p.section == section and p.is_upgradable) ] return ret def upgrade(self, dist_upgrade=False): self.cache.upgrade(dist_upgrade) def get_changes(self): changes = self.cache.get_changes() return [APTPackage(p) for p in changes] def has_pkg(self, pkgname): return pkgname in self.cache def is_installed(self, pkgname): if pkgname not in self.cache: return False return self.cache[pkgname].is_installed def get_pkg(self, pkgname): return APTPackage(self.cache[pkgname]) def get_pkgs(self, pkgname): return [ APTPackage(self.cache[p]) for p in sorted(self.cache.keys()) if pkgname in p.lower() ] def compare_versions(self, ver1, ver2): return version_compare(ver1, ver2) def download_binary(self, pkgname, path, version=None): p = self.cache[pkgname] if version is None: pkgver = p.installed else: pkgver = p.versions[version] rel_filename = fetch_binary(pkgver, path, ElbeAcquireProgress()) return self.rfs.fname(rel_filename) def download_source(self, pkgname, path, version=None): p = self.cache[pkgname] if version is None: pkgver = p.installed else: pkgver = p.versions[version] rel_filename = pkgver.fetch_source(path, ElbeAcquireProgress(), unpack=False) return self.rfs.fname(rel_filename)
class RPCAPTCache(InChRootObject): # pylint: disable=too-many-public-methods def __init__(self, rfs, arch, notifier=None, norecommend=False, noauth=True): # pylint: disable=too-many-arguments InChRootObject.__init__(self, rfs) self.notifier = notifier config.set("APT::Architecture", arch) if norecommend: config.set("APT::Install-Recommends", "0") else: config.set("APT::Install-Recommends", "1") if noauth: config.set("APT::Get::AllowUnauthenticated", "1") else: config.set("APT::Get::AllowUnauthenticated", "0") self.cache = Cache(progress=ElbeOpProgress()) self.cache.open(progress=ElbeOpProgress()) def dbg_dump(self, filename): ts = time.localtime() filename = filename + ('_%02d%02d%02d' % (ts.tm_hour, ts.tm_min, ts.tm_sec)) with open(filename, 'w') as dbg: for p in self.cache: dbg.write( '%s %s %d %d %d %d %d %d %d %d %d %d %d %d\n' % (p.name, p.candidate.version, p.marked_keep, p.marked_delete, p.marked_upgrade, p.marked_downgrade, p.marked_install, p.marked_reinstall, p.is_auto_installed, p.is_installed, p.is_auto_removable, p.is_now_broken, p.is_inst_broken, p.is_upgradable)) def get_sections(self): ret = list({p.section for p in self.cache}) ret.sort() return ret def get_pkglist(self, section): if section == 'all': ret = [APTPackage(p) for p in self.cache] else: ret = [APTPackage(p) for p in self.cache if p.section == section] return ret def mark_install(self, pkgname, version, from_user=True, nodeps=False): print('Mark for install "%s"' % pkgname) p = self.cache[pkgname] if version: p.candidate = p.versions[version] p.mark_install(auto_fix=not nodeps, auto_inst=not nodeps, from_user=from_user) def mark_install_devpkgs(self, ignore_pkgs, ignore_dev_pkgs): ignore_pkgs.discard('libc6') # we don't want to ignore libc ignore_pkgs.discard('libstdc++5') ignore_pkgs.discard('libstdc++6') # list all debian src packages of all installed packages that don't # come from debootstrap src_list = [ p.candidate.source_name for p in self.cache if (p.is_installed and p.name not in ignore_pkgs) ] version_dict = { p.name: p.candidate.version for p in self.cache if (p.is_installed and p.name not in ignore_pkgs) } # go through all packages, remember package if its source package # matches one of the installed packages and the binary package is a # '-dev' package dev_list = [ s for s in self.cache if (s.candidate.source_name in src_list and ( s.name.endswith('-dev'))) ] for p in dev_list: if p.name not in ignore_dev_pkgs: name_no_suffix = p.name[:-len('-dev')] if name_no_suffix in version_dict: version = version_dict[name_no_suffix] candidate = p.versions.get(version) if candidate: p.candidate = candidate p.mark_install() # ensure that the symlinks package will be installed (it's needed for # fixing links inside the sysroot self.cache['symlinks'].mark_install() for p in ignore_dev_pkgs: self.cache[p].mark_delete() dbgsym_list = [ s.name + '-dbgsym' for s in self.cache if (s.is_installed or s.marked_install) ] for p in dbgsym_list: if p in self.cache: pkg = self.cache[p] name_no_suffix = pkg.name[:-len('-dbgsym')] if name_no_suffix in version_dict: version = version_dict[name_no_suffix] candidate = pkg.versions.get(version) if candidate: pkg.candidate = candidate pkg.mark_install() def cleanup(self, exclude_pkgs): for p in self.cache: if p.is_installed and not \ p.is_auto_installed or \ p.is_auto_removable: remove = True for x in exclude_pkgs: if x == p.name: remove = False if remove: p.mark_delete(auto_fix=True, purge=True) def mark_upgrade(self, pkgname, version): p = self.cache[pkgname] if version: p.candidate = p.versions[version] p.mark_upgrade() def mark_delete(self, pkgname): p = self.cache[pkgname] p.mark_delete(purge=True) def mark_keep(self, pkgname, _version): p = self.cache[pkgname] p.mark_keep() def update(self): self.cache.update(fetch_progress=ElbeAcquireProgress()) self.cache.open(progress=ElbeOpProgress()) def commit(self): os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["DEBONF_NONINTERACTIVE_SEEN"] = "true" print("Commiting changes ...") self.cache.commit(ElbeAcquireProgress(), ElbeInstallProgress(fileno=sys.stdout.fileno())) self.cache.open(progress=ElbeOpProgress()) def clear(self): self.cache.clear() def get_dependencies(self, pkgname): deps = getalldeps(self.cache, pkgname) return [APTPackage(p, cache=self.cache) for p in deps] def get_installed_pkgs(self, section='all'): if section == 'all': pl = [APTPackage(p) for p in self.cache if p.is_installed] else: pl = [ APTPackage(p) for p in self.cache if (p.section == section and p.is_installed) ] return pl def get_fileindex(self): index = {} for p in self.cache: if p.is_installed: for f in p.installed_files: index[f] = p.name return index def get_marked_install(self, section='all'): if section == 'all': ret = [APTPackage(p) for p in self.cache if p.marked_install] else: ret = [ APTPackage(p) for p in self.cache if (p.section == section and p.marked_install) ] return ret def get_upgradeable(self, section='all'): if section == 'all': ret = [APTPackage(p) for p in self.cache if p.is_upgradable] else: ret = [ APTPackage(p) for p in self.cache if (p.section == section and p.is_upgradable) ] return ret def upgrade(self, dist_upgrade=False): self.cache.upgrade(dist_upgrade) def get_changes(self): changes = self.cache.get_changes() return [APTPackage(p) for p in changes] def has_pkg(self, pkgname): return pkgname in self.cache def is_installed(self, pkgname): if pkgname not in self.cache: return False return self.cache[pkgname].is_installed def get_pkg(self, pkgname): return APTPackage(self.cache[pkgname]) def get_pkgs(self, pkgname): return [ APTPackage(self.cache[p]) for p in sorted(self.cache.keys()) if pkgname in p.lower() ] def get_corresponding_source_packages(self, pkg_lst=None): if pkg_lst is None: pkg_lst = {p.name for p in self.cache if p.is_installed} src_set = set() with TagFile('/var/lib/dpkg/status') as tagfile: for section in tagfile: pkg = section['Package'] if pkg not in pkg_lst: continue tmp = self.cache[pkg].installed or self.cache[pkg].candidate src_set.add((tmp.source_name, tmp.source_version)) if "Built-Using" not in section: continue built_using_lst = section["Built-Using"].split(', ') for built_using in built_using_lst: name, version = built_using.split(' ', 1) version = version.strip('(= )') src_set.add((name, version)) return list(src_set) @staticmethod def compare_versions(self, ver1, ver2): return version_compare(ver1, ver2) def download_binary(self, pkgname, path, version=None): p = self.cache[pkgname] if version is None: pkgver = p.installed else: pkgver = p.versions[version] rel_filename = fetch_binary(pkgver, path, ElbeAcquireProgress()) return self.rfs.fname(rel_filename) def download_source(self, src_name, src_version, dest_dir): allow_untrusted = config.find_b("APT::Get::AllowUnauthenticated", False) rec = SourceRecords() acq = Acquire(ElbeAcquireProgress()) # poorman's iterator while True: next_p = rec.lookup(src_name) # End of the list? if not next_p: raise ("No source found for %s_%s" % (src_name, src_version)) if src_version == rec.version: break # We don't allow untrusted package and the package is not # marks as trusted if not (allow_untrusted or rec.index.is_trusted): raise FetchError( "Can't fetch source %s_%s; Source %r is not trusted" % (src_name, src_version, rec.index.describe)) # Copy from src to dst all files of the source package dsc = None files = [] for _file in rec.files: src = os.path.basename(_file.path) dst = os.path.join(dest_dir, src) if 'dsc' == _file.type: dsc = dst if not (allow_untrusted or _file.hashes.usable): raise FetchError( "Can't fetch file %s. No trusted hash found." % dst) # acq is accumlating the AcquireFile, the files list only # exists to prevent Python from GC the object .. I guess. # Anyway, if we don't keep the list, We will get an empty # directory files.append( AcquireFile(acq, rec.index.archive_uri(_file.path), _file.hashes, _file.size, src, destfile=dst)) acq.run() if dsc is None: raise ValueError("No source found for %s_%s" % (src_name, src_version)) for item in acq.items: if item.STAT_DONE != item.status: raise FetchError("Can't fetch item %s: %s" % (item.destfile, item.error_text)) return self.rfs.fname(os.path.abspath(dsc))
class RPCAPTCache(InChRootObject): def __init__(self, rfs, log, arch, notifier=None, norecommend=False, noauth=True): sys.stdout = open(log, 'a', buffering=0) sys.stderr = open(log, 'a', buffering=0) self.logfile = open(log, 'a', buffering=0) InChRootObject.__init__(self, rfs) self.notifier = notifier config.set("APT::Architecture", arch) if norecommend: config.set("APT::Install-Recommends", "1") else: config.set("APT::Install-Recommends", "0") if noauth: config.set("APT::Get::AllowUnauthenticated", "1") else: config.set("APT::Get::AllowUnauthenticated", "0") self.cache = Cache(progress=ElbeOpProgress()) self.cache.open(progress=ElbeOpProgress()) def dbg_dump(self, filename): ts = time.localtime() filename = filename + ('_%02d%02d%02d' % (ts.tm_hour, ts.tm_min, ts.tm_sec)) with open(filename, 'w') as dbg: for p in self.cache: dbg.write( '%s %s %d %d %d %d %d %d %d %d %d %d %d %d\n' % (p.name, p.candidate.version, p.marked_keep, p.marked_delete, p.marked_upgrade, p.marked_downgrade, p.marked_install, p.marked_reinstall, p.is_auto_installed, p.is_installed, p.is_auto_removable, p.is_now_broken, p.is_inst_broken, p.is_upgradable)) def get_sections(self): ret = list(set([p.section for p in self.cache])) ret.sort() return ret def get_pkglist(self, section): if section == 'all': ret = [APTPackage(p) for p in self.cache] else: ret = [APTPackage(p) for p in self.cache if p.section == section] return ret def mark_install(self, pkgname, version, from_user=True, nodeps=False): p = self.cache[pkgname] if version: p.candidate = p.versions[version] p.mark_install(auto_fix=not nodeps, auto_inst=not nodeps, from_user=from_user) def mark_install_devpkgs(self, ignore_pkgs, ignore_dev_pkgs): ignore_pkgs.remove('libc6') # we don't want to ignore libc # we don't want to ignore libstdc++ try: ignore_pkgs.remove('libstdc++5') except: pass try: ignore_pkgs.remove('libstdc++6') except: pass # list all debian src packages of all installed packages that don't # come from debootstrap src_list = [ p.candidate.source_name for p in self.cache if p.is_installed and p.name not in ignore_pkgs ] # go through all packages, remember package if its source package # matches one of the installed packages and the binary package is a # '-dev' package dev_list = [ s for s in self.cache if (s.candidate.source_name in src_list and s.name.endswith('-dev') ) ] for p in dev_list: if p.name not in ignore_dev_pkgs: p.mark_install() # ensure that the symlinks package will be installed (it's needed for # fixing links inside the sysroot self.cache['symlinks'].mark_install() for p in ignore_dev_pkgs: self.cache[p].mark_delete() def cleanup(self, exclude_pkgs): for p in self.cache: if (p.is_installed and not p.is_auto_installed) or p.is_auto_removable: remove = True for x in exclude_pkgs: if x == p.name: remove = False if remove: p.mark_delete(auto_fix=True, purge=True) def mark_upgrade(self, pkgname, version): p = self.cache[pkgname] if version: p.candidate = p.versions[version] p.mark_upgrade() def mark_delete(self, pkgname, version): p = self.cache[pkgname] p.mark_delete(purge=True) def mark_keep(self, pkgname, version): p = self.cache[pkgname] p.mark_keep() def update(self): self.cache.update(fetch_progress=ElbeAcquireProgress()) self.cache.open(progress=ElbeOpProgress()) def commit(self): os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["DEBONF_NONINTERACTIVE_SEEN"] = "true" self.cache.commit(ElbeAcquireProgress(), ElbeInstallProgress(fileno=self.logfile.fileno())) self.cache.open(progress=ElbeOpProgress()) def clear(self): self.cache.clear() def get_dependencies(self, pkgname): deps = getalldeps(self.cache, pkgname) return [APTPackage(p, cache=self.cache) for p in deps] def get_installed_pkgs(self, section='all'): # avoid DeprecationWarning: MD5Hash is deprecated, use Hashes instead # triggerd by python-apt with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) if section == 'all': pl = [APTPackage(p) for p in self.cache if p.is_installed] else: pl = [ APTPackage(p) for p in self.cache if (p.section == section and p.is_installed) ] return pl def get_fileindex(self): index = {} for p in self.cache: if p.is_installed: for f in p.installed_files: index[f] = p.name return index def get_marked_install(self, section='all'): if section == 'all': ret = [APTPackage(p) for p in self.cache if p.marked_install] else: ret = [ APTPackage(p) for p in self.cache if (p.section == section and p.marked_install) ] return ret def get_upgradeable(self, section='all'): if section == 'all': ret = [APTPackage(p) for p in self.cache if p.is_upgradable] else: ret = [ APTPackage(p) for p in self.cache if (p.section == section and p.is_upgradable) ] return ret def upgrade(self, dist_upgrade=False): self.cache.upgrade(dist_upgrade) def get_changes(self): changes = self.cache.get_changes() return [APTPackage(p) for p in changes] def has_pkg(self, pkgname): return pkgname in self.cache def is_installed(self, pkgname): if not pkgname in self.cache: return False return self.cache[pkgname].is_installed def get_pkg(self, pkgname): return APTPackage(self.cache[pkgname]) def get_pkgs(self, pkgname): return [ APTPackage(self.cache[p]) for p in sorted(self.cache.keys()) if pkgname in p.lower() ] def compare_versions(self, ver1, ver2): return version_compare(ver1, ver2) def download_binary(self, pkgname, path, version=None): p = self.cache[pkgname] if version is None: pkgver = p.installed else: pkgver = p.versions[version] rel_filename = pkgver.fetch_binary(path, ElbeAcquireProgress()) return self.rfs.fname(rel_filename) def download_source(self, pkgname, path, version=None): p = self.cache[pkgname] if version is None: pkgver = p.installed else: pkgver = p.versions[version] rel_filename = pkgver.fetch_source(path, ElbeAcquireProgress(), unpack=False) return self.rfs.fname(rel_filename)
class RPCAPTCache(InChRootObject): # pylint: disable=too-many-public-methods def __init__( self, rfs, log, arch, notifier=None, norecommend=False, noauth=True): # pylint: disable=too-many-arguments sys.stdout = open(log, 'a', buffering=0) sys.stderr = open(log, 'a', buffering=0) self.logfile = open(log, 'a', buffering=0) InChRootObject.__init__(self, rfs) self.notifier = notifier config.set("APT::Architecture", arch) if norecommend: config.set("APT::Install-Recommends", "0") else: config.set("APT::Install-Recommends", "1") if noauth: config.set("APT::Get::AllowUnauthenticated", "1") else: config.set("APT::Get::AllowUnauthenticated", "0") self.cache = Cache(progress=ElbeOpProgress()) self.cache.open(progress=ElbeOpProgress()) def dbg_dump(self, filename): ts = time.localtime() filename = filename + ( '_%02d%02d%02d' % (ts.tm_hour, ts.tm_min, ts.tm_sec)) with open(filename, 'w') as dbg: for p in self.cache: dbg.write( '%s %s %d %d %d %d %d %d %d %d %d %d %d %d\n' % (p.name, p.candidate.version, p.marked_keep, p.marked_delete, p.marked_upgrade, p.marked_downgrade, p.marked_install, p.marked_reinstall, p.is_auto_installed, p.is_installed, p.is_auto_removable, p.is_now_broken, p.is_inst_broken, p.is_upgradable)) def get_sections(self): ret = list(set([p.section for p in self.cache])) ret.sort() return ret def get_pkglist(self, section): if section == 'all': ret = [APTPackage(p) for p in self.cache] else: ret = [APTPackage(p) for p in self.cache if p.section == section] return ret def mark_install(self, pkgname, version, from_user=True, nodeps=False): p = self.cache[pkgname] if version: p.candidate = p.versions[version] p.mark_install(auto_fix=not nodeps, auto_inst=not nodeps, from_user=from_user) def mark_install_devpkgs(self, ignore_pkgs, ignore_dev_pkgs): ignore_pkgs.discard('libc6') # we don't want to ignore libc ignore_pkgs.discard('libstdc++5') ignore_pkgs.discard('libstdc++6') # list all debian src packages of all installed packages that don't # come from debootstrap src_list = [ p.candidate.source_name for p in self.cache if ( p.is_installed and p.name not in ignore_pkgs)] # go through all packages, remember package if its source package # matches one of the installed packages and the binary package is a # '-dev' package dev_list = [ s for s in self.cache if ( s.candidate.source_name in src_list and ( s.name.endswith('-dev')))] for p in dev_list: if p.name not in ignore_dev_pkgs: p.mark_install() # ensure that the symlinks package will be installed (it's needed for # fixing links inside the sysroot self.cache['symlinks'].mark_install() for p in ignore_dev_pkgs: self.cache[p].mark_delete() def cleanup(self, exclude_pkgs): for p in self.cache: if p.is_installed and not \ p.is_auto_installed or \ p.is_auto_removable: remove = True for x in exclude_pkgs: if x == p.name: remove = False if remove: p.mark_delete(auto_fix=True, purge=True) def mark_upgrade(self, pkgname, version): p = self.cache[pkgname] if version: p.candidate = p.versions[version] p.mark_upgrade() def mark_delete(self, pkgname): p = self.cache[pkgname] p.mark_delete(purge=True) def mark_keep(self, pkgname, version): p = self.cache[pkgname] p.mark_keep() def update(self): self.cache.update(fetch_progress=ElbeAcquireProgress()) self.cache.open(progress=ElbeOpProgress()) def commit(self): os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["DEBONF_NONINTERACTIVE_SEEN"] = "true" self.cache.commit(ElbeAcquireProgress(), ElbeInstallProgress(fileno=self.logfile.fileno())) self.cache.open(progress=ElbeOpProgress()) def clear(self): self.cache.clear() def get_dependencies(self, pkgname): deps = getalldeps(self.cache, pkgname) return [APTPackage(p, cache=self.cache) for p in deps] def get_installed_pkgs(self, section='all'): # avoid DeprecationWarning: MD5Hash is deprecated, use Hashes instead # triggerd by python-apt with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) if section == 'all': pl = [APTPackage(p) for p in self.cache if p.is_installed] else: pl = [APTPackage(p) for p in self.cache if ( p.section == section and p.is_installed)] return pl def get_fileindex(self): index = {} for p in self.cache: if p.is_installed: for f in p.installed_files: index[f] = p.name return index def get_marked_install(self, section='all'): if section == 'all': ret = [APTPackage(p) for p in self.cache if p.marked_install] else: ret = [APTPackage(p) for p in self.cache if (p.section == section and p.marked_install)] return ret def get_upgradeable(self, section='all'): if section == 'all': ret = [APTPackage(p) for p in self.cache if p.is_upgradable] else: ret = [APTPackage(p) for p in self.cache if (p.section == section and p.is_upgradable)] return ret def upgrade(self, dist_upgrade=False): self.cache.upgrade(dist_upgrade) def get_changes(self): changes = self.cache.get_changes() return [APTPackage(p) for p in changes] def has_pkg(self, pkgname): return pkgname in self.cache def is_installed(self, pkgname): if pkgname not in self.cache: return False return self.cache[pkgname].is_installed def get_pkg(self, pkgname): return APTPackage(self.cache[pkgname]) def get_pkgs(self, pkgname): return [ APTPackage( self.cache[p]) for p in sorted( self.cache.keys()) if pkgname in p.lower()] def compare_versions(self, ver1, ver2): return version_compare(ver1, ver2) def download_binary(self, pkgname, path, version=None): p = self.cache[pkgname] if version is None: pkgver = p.installed else: pkgver = p.versions[version] # avoid DeprecationWarning: # "MD5Hash is deprecated, use Hashes instead" # triggerd by python-apt with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) rel_filename = pkgver.fetch_binary(path, ElbeAcquireProgress()) return self.rfs.fname(rel_filename) def download_source(self, pkgname, path, version=None): p = self.cache[pkgname] if version is None: pkgver = p.installed else: pkgver = p.versions[version] # avoid DeprecationWarning: # "MD5Hash is deprecated, use Hashes instead" # triggerd by python-apt with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) rel_filename = pkgver.fetch_source(path, ElbeAcquireProgress(), unpack=False) return self.rfs.fname(rel_filename)
class QPackagesModel(QtCore.QAbstractTableModel): """ Model used to handle the packages listed in a .ini file """ def __init__(self, inifile): """ :param inifile: Path to the packages.ini ini file """ QtCore.QAbstractTableModel.__init__(self, None) self.packages = [] self.to_install = [] self.inifile = inifile self.cache = Cache() self._populate() def _populate(self): """ Load the inifile with the package names and description """ pkg_dict = DictIni(self.inifile) for section, packages in pkg_dict.items(): for pkg_name, pkg_description in packages.iteritems(): if self.cache.has_key(pkg_name): pkg = self.cache[pkg_name] if pkg.is_installed: status = 2 else: status = 0 else: pkg = None status = 1 print("This package : '%s:%s' isn't available in your \ configured repositories" % (pkg_name, pkg_description)) self.packages.append( {'name':pkg_name, 'description':pkg_description, 'package':pkg, 'status':status, 'section':section}) self.packages = sorted(self.packages, key=lambda a:a['status']) self.reset() def _get_pkg(self, index): """ Returns a pkg object for a given index """ return self.packages[index.row()]['package'] def _init_cache(self): """ Initialize our cache for apt """ self.cache = Cache() def rowCount(self, index=None): """ Required function Returns the number of rows """ return len(self.packages) def columnCount(self, index=None): """ Required function Returns the number of columns """ return len(TABLE_HEADER) def data(self, index, role): """ Required function Returns the model's datas """ if not index.isValid() or not (0 <= index.row() < self.rowCount()): return QtCore.QVariant() column = index.column() package = self.packages[index.row()] if role == QtCore.Qt.DisplayRole: return self.render_cell(package, column) elif role == QtCore.Qt.CheckStateRole: return self._cell_check_status(package['package'], column) elif role == QtCore.Qt.BackgroundColorRole: return self._cell_color(package['status']) @staticmethod def render_cell(package, column): """ Return the column's cell content for the given package """ if column == 0: return package['name'] elif column == 1: return package['description'].decode('utf-8') elif column == 2: if not package['package']: return "Not Available" def _cell_check_status(self, pkg, column): """ Returns the row's Qchecked status """ if column == 2: if pkg and (pkg.installed or pkg.marked_install): return QtCore.QVariant(QtCore.Qt.Checked) else: return QtCore.QVariant(QtCore.Qt.Unchecked) @staticmethod def _cell_color(status): """ Returns the cell color """ if status == 2: return QtGui.QColor(255, 0, 0, 127) elif status == 1: return QtGui.QColor(255, 255, 0, 127) elif status == 0: return QtGui.QColor(255, 255, 255, 127) else: return QtGui.QColor(255, 127, 0, 200) def setData(self, index, value, role): """ Changes datas informations """ if role == QtCore.Qt.CheckStateRole and index.column() == 2: pkg = self._get_pkg(index) if not pkg.installed: if value == QtCore.QVariant(QtCore.Qt.Checked): pkg.mark_install() self.packages[index.row()]['status'] = -1 self.to_install.append(True) self.emit(QtCore.SIGNAL("dataChanged(int)"), len(self.to_install)) else: pkg.mark_delete() self.packages[index.row()]['status'] = 0 self.to_install.pop() self.emit(QtCore.SIGNAL("dataChanged(int)"), len(self.to_install)) ans = True else: ans = QtCore.QAbstractTableModel.setData(self, modelIndex, variant, role) return ans def flags(self, index): """ Add a flag to indicate whether a field is editable/checkable ... """ if not index.isValid(): return QtCore.Qt.ItemIsEnabled pkg = self._get_pkg(index) ans = QtCore.QAbstractTableModel.flags(self, index) if pkg and not pkg.installed: if index.column() == 2: ans |= QtCore.Qt.ItemIsUserCheckable ans |= QtCore.Qt.ItemIsEditable ans |= QtCore.Qt.ItemIsSelectable else: ans &= ~QtCore.Qt.ItemIsEnabled return ans def headerData(self, section, orientation, role): """ Native optionnal function Returns the table's header infos :orientation: QtCore.Qt:Orientation :role: QtCore.Qt:Role """ # Alignement if role == QtCore.Qt.TextAlignmentRole: if orientation == QtCore.Qt.Horizontal: return QtCore.QVariant(int(QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)) return QtCore.QVariant(int(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)) # Headers if role != QtCore.Qt.DisplayRole: return QtCore.QVariant() if orientation == QtCore.Qt.Horizontal: ret_val = TABLE_HEADER[section] return QtCore.QVariant(ret_val) else: return QtCore.QVariant(int(section + 1)) #Cache update and file def update(self): """ Update our apt cache and our packages list """ acquire = QAcquireProgress() self._init_cache() print("Connecting slots") for sign in (QtCore.SIGNAL('statusChanged'), QtCore.SIGNAL('statusStarted()'), QtCore.SIGNAL('statusFinished()'),): self.connect(acquire, sign, self._reemit(sign)) self.connect(acquire, QtCore.SIGNAL('statusFinished()'), self._update_datas) self.cache.update(acquire) def _update_datas(self): """ Refresh the table's datas when a update has been called """ self.cache = Cache() self.packages = [] self.to_install = [] self._populate() def install(self): """ Install a list of packages @packages : a list of packages' names """ acquire = QAcquireProgress() #FIXME : Il y a encore deux trois trucs qui vont pas install = QInstallProgress() print("Connecting slots") for sign in (QtCore.SIGNAL('statusChanged'), QtCore.SIGNAL('statusStarted()'), QtCore.SIGNAL('statusFinished()'),): self.connect(acquire, sign, self._reemit(sign)) self.connect(install, sign, self._reemit(sign)) self.connect(install, QtCore.SIGNAL('statusFinished()'), self._update_datas) self.cache.commit(acquire, install) def _reemit(self, signal): """ Returns a _reemit func for the given signal """ em = self.emit def emitter(*args, **kw): em(signal, *args, **kw) return emitter
class ZfsRequires (object): """ Class manages installing additional packages TODO: - yum package handling - dnf package handling """ packages_required = ["zfsutils-linux", "debootstrap", "gdisk", "zfs-initramfs"] def __init__(self): if not self.packages_required: return False self.os = (self.detect_os()).strip() if self.os == 'debian': self._package_cache = Cache() # [ EXECUTOR ] def load_runner(self, cmd): """ Executes given command and returns errors if any :cmd: [list] :ret: [list] """ cmd = ' '.join(cmd) cmd_out = Popen(cmd, shell=True, bufsize=1, stdout=PIPE, stderr=PIPE) ret = [] for pipe in cmd_out.communicate(): ret.append(pipe.decode('utf-8')) return ret def detect_os(self): """ Detects OS family for correct package installation :returns: str """ return self.load_runner(['cat /etc/os-release', '| grep ID_LIKE', '| awk -F \'=\' \'{print $2}\''])[0] def apt_update(self): """ Updates apt package cahe :msg: Success or False if not needed """ print(" [ Checking that requied packages are present ]") msg = [] for this_package in self.packages_required: if not self._package_cache[this_package].is_installed: self._package_cache.update() msg.append('Package cache updated') msg.append(self.apt_install()) break else: msg.append('Package '+this_package+' present') return msg def apt_install(self): """ Installs packages from packages_required """ res = [] for this_package in self.packages_required: if not self._package_cache[this_package].is_installed: self._package_cache[this_package].mark_install() res.append(' '.join(['Package', this_package, 'marked for install.\n'])) self._package_cache.commit() return ''.join(res)