def _check_running_kernel(yb, md_info, msg): kern_pkgtup = misc.get_running_kernel_pkgtup(yb.ts) if kern_pkgtup[0] is None: return found_sec = False for (pkgtup, notice) in md_info.get_applicable_notices(kern_pkgtup): if found_sec or notice['type'] != 'security': continue found_sec = True ipkg = yb.rpmdb.searchPkgTuple(pkgtup) if not ipkg: continue # Not installed ipkg = ipkg[0] e = '' if kern_pkgtup[2] != '0': e = '%s:' % kern_pkgtup[2] rpkg = '%s-%s%s-%s.%s' % (kern_pkgtup[0], e, kern_pkgtup[3], kern_pkgtup[4], kern_pkgtup[1]) msg(_('Security: %s is an installed security update') % ipkg) msg(_('Security: %s is the currently running version') % rpkg) break
def _wait(self, block=False): num = 0 while self.jobs: if block: pid, code = os.wait() else: pid, code = os.waitpid(-1, os.WNOHANG) if not pid: break # urlgrabber spawns child jobs, too. But they exit synchronously, # so we should never see an unknown pid here. assert pid in self.jobs po = self.jobs.pop(pid) if self.progress: self.done += po.rpm.size self.progress.update(self.done) if code != 0: unlink_f(po.rpm.localpath) self.adderror(po, _('Delta RPM rebuild failed')) elif not po.rpm.verifyLocalPkg(): self.adderror(po, _('Checksum of the delta-rebuilt RPM failed')) else: os.unlink(po.localpath) po.localpath = po.rpm.localpath # for --downloadonly num += 1 return num
def _wait(self, block=False): num = 0 while self.jobs: if block: pid, code = os.wait() else: pid, code = os.waitpid(-1, os.WNOHANG) if not pid: break # urlgrabber spawns child jobs, too. But they exit synchronously, # so we should never see an unknown pid here. assert pid in self.jobs po = self.jobs.pop(pid) if self.progress: self.done += po.rpm.size self.progress.update(self.done) if code != 0: unlink_f(po.rpm.localpath) self.adderror(po, _('Delta RPM rebuild failed')) elif not po.rpm.verifyLocalPkg(): self.adderror(po, _('Checksum of the delta-rebuilt RPM failed')) else: # done with drpm file, unlink when local if po.localpath.startswith(po.repo.pkgdir): os.unlink(po.localpath) po.localpath = po.rpm.localpath # for --downloadonly num += 1 # when blocking, one is enough if block: break return num
def exclude_updates(base, filters=None): ''' Exclude all packages to do with updates, using the updateinfo data. ''' def ysp_del_pkg(pkg, reason="updateinfo"): """ Deletes a package from all trees that yum knows about """ base.verbose_logger.log( INFO_1, _(" --> %s from %s excluded (%s)") % (pkg, pkg.repoid, reason)) pkg.repo.sack.delPackage(pkg) if filters is None: filters = base.updateinfo_filters opts = _updateinfofilter2opts(filters) if _no_options(opts): return 0, 0 md_info = base.upinfo used_map = _ysp_gen_used_map(opts) # In theory the official API is: # # pkgs = base.pkgSack.returnPackages() # # ...however that is _extremely_ slow, deleting all packages. So we ask # for the list of update packages, which is all we care about. upds = base.doPackageLists(pkgnarrow='updates') pkgs = upds.updates # In theory we don't need to do this in some cases, but meh. upds = base.doPackageLists(pkgnarrow='obsoletes') pkgs += upds.obsoletes name2tup = _get_name2oldpkgtup(base) tot = 0 cnt = 0 for pkg in pkgs: tot += 1 name = pkg.name if (name not in name2tup or not _ysp_should_keep_pkg( opts, name2tup[name], md_info, used_map)): ysp_del_pkg(pkg) continue cnt += 1 _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x)) if cnt: base.verbose_logger.log( INFO_1, _('%d package(s) needed for security, out of %d available') % (cnt, tot)) else: base.verbose_logger.log( INFO_1, _('No packages needed for security; %d packages available' % tot)) return cnt, tot
def exclude_updates(base, filters=None): ''' Exclude all packages to do with updates, using the updateinfo data. ''' def ysp_del_pkg(pkg, reason="updateinfo"): """ Deletes a package from all trees that yum knows about """ base.verbose_logger.log( INFO_1, _(" --> %s from %s excluded (%s)") % (pkg, pkg.repoid, reason)) pkg.repo.sack.delPackage(pkg) if filters is None: filters = base.updateinfo_filters opts = _ysp_gen_opts(filters) if _no_options(opts): return 0, 0 md_info = base.upinfo used_map = _ysp_gen_used_map(opts) upds = base.doPackageLists(pkgnarrow='updates') tot = len(upds.updates) # In theory we don't need to do this in some cases, but meh. upds = base.doPackageLists(pkgnarrow='obsoletes') tot += len(upds.obsoletes) pkgs = base.pkgSack.returnPackages() name2tup = _get_name2oldpkgtup(base) pkgs_to_del = [] for pkg in pkgs: name = pkg.name if (name not in name2tup or not _ysp_should_keep_pkg( opts, name2tup[name], md_info, used_map)): pkgs_to_del.append(pkg.name) continue if pkgs_to_del: for p in base.doPackageLists(pkgnarrow='available', patterns=pkgs_to_del, showdups=True).available: ysp_del_pkg(p) cnt = len(set(base.doPackageLists(pkgnarrow='updates').updates + \ base.doPackageLists(pkgnarrow='obsoletes').obsoletes)) _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x)) if cnt: base.verbose_logger.log( INFO_1, _('%d package(s) needed for security, out of %d available') % (cnt, tot)) else: base.verbose_logger.log( INFO_1, _('No packages needed for security; %d packages available' % tot)) return cnt, tot
def add(self, obj, mdtype='updateinfo'): """ Parse a metadata from a given YumRepository, file, or filename. """ def _rid(repoid, fmt=_('(from %s)'), unknown=_("<unknown>")): if not repoid: repoid = unknown return fmt % repoid if not obj: raise UpdateNoticeException repoid = None if type(obj) in (type(''), type('')): unfile = decompress(obj) infile = open(unfile, 'rt') elif isinstance(obj, YumRepository): if obj.id not in self._repos: repoid = obj.id self._repos.append(obj.id) md = obj.retrieveMD(mdtype) if not md: raise UpdateNoticeException() unfile = repo_gen_decompress(md, 'updateinfo.xml') infile = open(unfile, 'rt') elif isinstance(obj, FakeRepository): raise Errors.RepoMDError("No updateinfo for local pkg") else: # obj is a file object infile = obj have_dup = False for event, elem in safe_iterparse(infile, logger=self._logger): if elem.tag == 'update': try: un = UpdateNotice(elem, repoid, self._vlogger) except UpdateNoticeException as e: msg = _("An update notice %s is broken, skipping.") % _rid( repoid) if self._vlogger: self._vlogger.log(logginglevels.DEBUG_1, "%s", msg) else: print(msg, file=sys.stderr) continue if not self.add_notice(un): msg = _( "Update notice %s %s is broken, or a bad duplicate, skipping." ) % (un['update_id'], _rid(repoid)) if not have_dup: msg += _( '\nYou should report this problem to the owner of the %s repository.' ) % _rid(repoid, "%s") msg += _( '\nIf you are the owner, consider re-running the same command with --verbose to see the ' 'exact data that caused the conflict.') have_dup = True if self._vlogger: self._vlogger.warn("%s", msg) else: print(msg, file=sys.stderr)
def exclude_updates(base, filters=None): ''' Exclude all packages to do with updates, using the updateinfo data. ''' def ysp_del_pkg(pkg, reason="updateinfo"): """ Deletes a package from all trees that yum knows about """ base.verbose_logger.log(INFO_1, _(" --> %s from %s excluded (%s)") % (pkg,pkg.repoid, reason)) pkg.repo.sack.delPackage(pkg) if filters is None: filters = base.updateinfo_filters opts = _updateinfofilter2opts(filters) if _no_options(opts): return 0, 0 md_info = base.upinfo used_map = _ysp_gen_used_map(opts) # In theory the official API is: # # pkgs = base.pkgSack.returnPackages() # # ...however that is _extremely_ slow, deleting all packages. So we ask # for the list of update packages, which is all we care about. upds = base.doPackageLists(pkgnarrow='updates') pkgs = upds.updates # In theory we don't need to do this in some cases, but meh. upds = base.doPackageLists(pkgnarrow='obsoletes') pkgs += upds.obsoletes name2tup = _get_name2oldpkgtup(base) tot = 0 cnt = 0 for pkg in pkgs: tot += 1 name = pkg.name if (name not in name2tup or not _ysp_should_keep_pkg(opts, name2tup[name], md_info, used_map)): for p in base.doPackageLists(pkgnarrow='available', patterns=[pkg.name], showdups=True).available: ysp_del_pkg(p) continue cnt += 1 _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x)) if cnt: base.verbose_logger.log(INFO_1, _('%d package(s) needed for security, out of %d available') % (cnt, tot)) else: base.verbose_logger.log(INFO_1, _('No packages needed for security; %d packages available' % tot)) return cnt, tot
def add(self, obj, mdtype="updateinfo"): """ Parse a metadata from a given YumRepository, file, or filename. """ def _rid(repoid, fmt=_(" (from %s)")): if not repoid: return "" return fmt % repoid if not obj: raise UpdateNoticeException repoid = None if type(obj) in (type(""), type(u"")): unfile = decompress(obj) infile = open(unfile, "rt") elif isinstance(obj, YumRepository): if obj.id not in self._repos: repoid = obj.id self._repos.append(obj.id) md = obj.retrieveMD(mdtype) if not md: raise UpdateNoticeException() unfile = repo_gen_decompress(md, "updateinfo.xml") infile = open(unfile, "rt") elif isinstance(obj, FakeRepository): raise Errors.RepoMDError, "No updateinfo for local pkg" else: # obj is a file object infile = obj have_dup = False for event, elem in safe_iterparse(infile, logger=self._logger): if elem.tag == "update": try: un = UpdateNotice(elem) except UpdateNoticeException, e: msg = _("An update notice%s is broken, skipping.") % _rid(repoid) if self._vlogger: self._vlogger.log(logginglevels.DEBUG_1, "%s", msg) else: print >> sys.stderr, msg continue if not self.add_notice(un): msg = _("Update notice %s%s is broken, or a bad duplicate, skipping.") % ( un["update_id"], _rid(repoid), ) if not have_dup: msg += _("\nYou should report this problem to the owner of the %srepository.") % _rid( repoid, "%s " ) have_dup = True if self._vlogger: self._vlogger.warn("%s", msg) else: print >> sys.stderr, msg
def exclude_updates(base, filters=None): ''' Exclude all packages to do with updates, using the updateinfo data. ''' def ysp_del_pkg(pkg, reason="updateinfo"): """ Deletes a package from all trees that yum knows about """ base.verbose_logger.log(INFO_1, _(" --> %s from %s excluded (%s)") % (pkg,pkg.repoid, reason)) pkg.repo.sack.delPackage(pkg) if filters is None: filters = base.updateinfo_filters opts = _ysp_gen_opts(filters) if _no_options(opts): return 0, 0 md_info = base.upinfo used_map = _ysp_gen_used_map(opts) upds = base.doPackageLists(pkgnarrow='updates') tot = len(upds.updates) # In theory we don't need to do this in some cases, but meh. upds = base.doPackageLists(pkgnarrow='obsoletes') tot += len(upds.obsoletes) pkgs = base.pkgSack.returnPackages() name2tup = _get_name2oldpkgtup(base) pkgs_to_del = [] for pkg in pkgs: name = pkg.name if (name not in name2tup or not _ysp_should_keep_pkg(opts, name2tup[name], md_info, used_map)): pkgs_to_del.append(pkg.name) continue if pkgs_to_del: for p in base.doPackageLists(pkgnarrow='available', patterns=pkgs_to_del, showdups=True).available: ysp_del_pkg(p) cnt = len(base.doPackageLists(pkgnarrow='updates').updates) + \ len(base.doPackageLists(pkgnarrow='obsoletes').obsoletes) _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x)) if cnt: base.verbose_logger.log(INFO_1, _('%d package(s) needed for security, out of %d available') % (cnt, tot)) else: base.verbose_logger.log(INFO_1, _('No packages needed for security; %d packages available' % tot)) return cnt, tot
def exclude_all(base, filters=None): ''' Exclude all packages, using the updateinfo data. ''' def ysp_del_pkg(pkg, reason="updateinfo"): """ Deletes a package from all trees that yum knows about """ base.verbose_logger.log( INFO_1, _(" --> %s from %s excluded (%s)") % (pkg, pkg.repoid, reason)) pkg.repo.sack.delPackage(pkg) if filters is None: filters = base.updateinfo_filters opts = _updateinfofilter2opts(filters) if _no_options(opts): return 0, 0 md_info = base.upinfo used_map = _ysp_gen_used_map(opts) pkgs = base.pkgSack.returnPackages() name2tup = _get_name2aallpkgtup(base) tot = 0 cnt = 0 for pkg in pkgs: tot += 1 name = pkg.name if (name not in name2tup or not _ysp_should_keep_pkg( opts, name2tup[name], md_info, used_map)): ysp_del_pkg(pkg) continue cnt += 1 _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x)) if cnt: base.verbose_logger.log( INFO_1, _('%d package(s) needed for security, out of %d available') % (cnt, tot)) else: base.verbose_logger.log( INFO_1, _('No packages needed for security; %d packages available' % tot)) return cnt, tot
def exclude_all(base, filters=None): ''' Exclude all packages, using the updateinfo data. ''' def ysp_del_pkg(pkg, reason="updateinfo"): """ Deletes a package from all trees that yum knows about """ base.verbose_logger.log( INFO_1, _(" --> %s from %s excluded (%s)") % (pkg, pkg.repoid, reason)) pkg.repo.sack.delPackage(pkg) if filters is None: filters = base.updateinfo_filters opts = _ysp_gen_opts(filters) if _no_options(opts): return 0, 0 md_info = base.upinfo used_map = _ysp_gen_used_map(opts) pkgs = base.pkgSack.returnPackages() name2tup = _get_name2aallpkgtup(base) tot = 0 cnt = 0 for pkg in pkgs: tot += 1 name = pkg.name if (name not in name2tup or not _ysp_should_keep_pkg( opts, name2tup[name], md_info, used_map)): ysp_del_pkg(pkg) continue cnt += 1 _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x)) if cnt: base.verbose_logger.log( INFO_1, _('%d package(s) needed for security, out of %d available') % (cnt, tot)) else: base.verbose_logger.log( INFO_1, _('No packages needed for security; %d packages available' % tot)) return cnt, tot
def _ask_user(self, question): if self.base.conf.assumeyes and not self.base.conf.assumeno: return elif self.base.conf.assumeno and not self.base.conf.assumeyes: raise YError(_('Safe and good answer. Exiting.')) answer = raw_input(question).lower() answer = _(answer) while not ((answer in yes) or (answer in no)): answer = raw_input(question).lower() answer = _(answer) if answer in yes: return else: raise YError(_('Safe and good answer. Exiting.'))
def _get_data(cls, req): """ Wrapper around response from server check data and print nice error in case of some error (and return None) otherwise return json object. """ try: output = json.loads(req.text) except ValueError: YCliError(_("Unknown response from server.")) return if req.status_code != 200: YCliError(_("Something went wrong:\n {0}\n".format(output["error"]))) return return output
def _ask_user(self, question): if self.base.conf.assumeyes and not self.base.conf.assumeno: return elif self.base.conf.assumeno and not self.base.conf.assumeyes: raise YError(_("Safe and good answer. Exiting.")) answer = raw_input(question).lower() answer = _(answer) while not ((answer in yes) or (answer in no)): answer = raw_input(question).lower() answer = _(answer) if answer in yes: return else: raise YError(_("Safe and good answer. Exiting."))
def _cmd_enable(self, chroot): self._need_root() self._ask_user(""" You are about to enable a Playground repository. Do you want to continue? [y/N]: """) api_url = "{0}/api/playground/list/".format( self.copr_url) req = requests.get(api_url) output = self._get_data(req) if output["output"] != "ok": raise YCliError(_("Unknown response from server.")) for repo in output["repos"]: project_name = "{0}/{1}".format(repo["username"], repo["coprname"]) repo_filename = "/etc/yum.repos.d/_playground_{}.repo" \ .format(project_name.replace("/", "-")) try: # check if that repo exist? but that will result in twice # up calls api_url = "{0}/api/coprs/{1}/detail/{2}/".format( self.copr_url, project_name, chroot) req = requests.get(api_url) output2 = self._get_data(req) if output2 and ("output" in output2) and (output2["output"] == "ok"): self._download_repo(project_name, repo_filename, chroot) except YError: # likely 404 and that repo does not exist pass
def _get_data(cls, req): """ Wrapper around response from server check data and print nice error in case of some error (and return None) otherwise return json object. """ try: output = json.loads(req.text) except ValueError: YCliError(_("Unknown response from server.")) return if req.status_code != 200: YCliError(_( "Something went wrong:\n {0}\n".format(output["error"]))) return return output
def ysp_del_pkg(tspkg): """ Deletes a package within a transaction. """ base.verbose_logger.log( INFO_1, _(" --> %s from %s removed (updateinfo)") % (tspkg.po, tspkg.po.ui_from_repo)) tsinfo.remove(tspkg.pkgtup)
def dequeue(self, block=True): """ Try to De-Queue a delta rebuild and spawn the rebuild process. """ # Do this here, just to keep the zombies at bay... self._wait() if not self._future_jobs: return False if self.limit <= len(self.jobs): if not block: return False self.wait(len(self.jobs) - self.limit + 1) po = self._future_jobs.pop(0) args = ('-a', po.arch) if po.oldrpm: args += '-r', po.oldrpm args += po.localpath, po.rpm.localpath try: pid = os.spawnl(os.P_NOWAIT, APPLYDELTA, APPLYDELTA, *args) except OSError as e: raise MiscError( _('Couldn\'t spawn %s: %s') % (APPLYDELTA, exception2msg(e))) self.jobs[pid] = po return True
def dequeue_all(self): """ De-Queue all delta rebuilds and spawn the rebuild processes. """ count = total = 0 for po in self.jobs.values() + self._future_jobs: count += 1 total += po.rpm.size if total: self.verbose_logger.info( _('Finishing delta rebuilds of %d package(s) (%s)'), count, progress.format_number(total)) if po.repo.callback: if hasattr(progress, 'text_meter_total_size'): progress.text_meter_total_size(0) self.progress = po.repo.callback # default timescale 5s works fine with 0.3s dl updates. # drpm rebuild jobs do not finish that often, so bump it try: self.progress.re.timescale = 30 except: pass # accessing private api self.progress.start( filename=None, url=None, # BZ 963023 text='<locally rebuilding deltarpms>', size=total) self.done = 0 while self._future_jobs: self.dequeue()
def _cmd_enable(self, chroot): self._need_root() self._ask_user( """ You are about to enable a Playground repository. Do you want to continue? [y/N]: """ ) api_url = "{0}/api/playground/list/".format(self.copr_url) req = requests.get(api_url) output = self._get_data(req) if output["output"] != "ok": raise YCliError(_("Unknown response from server.")) for repo in output["repos"]: project_name = "{0}/{1}".format(repo["username"], repo["coprname"]) repo_filename = "/etc/yum.repos.d/_playground_{}.repo".format(project_name.replace("/", "-")) try: # check if that repo exist? but that will result in twice # up calls api_url = "{0}/api/coprs/{1}/detail/{2}/".format(self.copr_url, project_name, chroot) req = requests.get(api_url) output2 = self._get_data(req) if output2 and ("output" in output2) and (output2["output"] == "ok"): self._download_repo(project_name, repo_filename, chroot) except YError: # likely 404 and that repo does not exist pass
def dequeue_all(self): """ De-Queue all delta rebuilds and spawn the rebuild processes. """ count = total = 0 for po in self.jobs.values() + self._future_jobs: count += 1 total += po.rpm.size if total: self.verbose_logger.info( _("Finishing delta rebuilds of %d package(s) (%s)"), count, progress.format_number(total) ) if po.repo.callback: if hasattr(progress, "text_meter_total_size"): progress.text_meter_total_size(0) self.progress = po.repo.callback # default timescale 5s works fine with 0.3s dl updates. # drpm rebuild jobs do not finish that often, so bump it try: self.progress.re.timescale = 30 except: pass # accessing private api self.progress.start( filename=None, url=None, text="<locally rebuilding deltarpms>", size=total # BZ 963023 ) self.done = 0 while self._future_jobs: self.dequeue()
def doCommand(self, base, basecmd, extcmds): try: subcommand = extcmds[0] except (ValueError, IndexError): base.logger.critical( _('Error: ') + _('exactly one parameter to ' 'playground command are required')) # FIXME: # dnf.cli.commands.err_mini_usage(self.cli, self.cli.base.basecmd) raise YCliError( _('exactly one parameter to ' 'playground command are required')) chroot = self._guess_chroot() if subcommand == "enable": self._cmd_enable(chroot) base.logger.info(_("Playground repositories successfully enabled.")) elif subcommand == "disable": self._cmd_disable() base.logger.info(_("Playground repositories successfully disabled.")) elif subcommand == "upgrade": self._cmd_disable() self._cmd_enable(chroot) base.logger.info(_("Playground repositories successfully updated.")) else: raise YError( _('Unknown subcommand {}.').format(subcommand)) return 0, [basecmd + ' done']
def safe_iterparse(filename, logger=None): """ Works like iterparse, but hides XML errors (prints a warning). """ try: for event, elem in iterparse(filename): yield event, elem except SyntaxError: # Bad XML if logger: logger.critical(_("Updateinfo file is not valid XML: %s"), filename) else: print >> sys.stderr, "Updateinfo file is not valid XML:", filename
def _log_failure(data): """Log the mismatched data similarly to conflict markers in git.""" if self._vlogger is None: return msg = _('Duplicate of %s differs in some fields:\n') msg %= other._md['update_id'] msg += '<<<<<<< %s:%s\n' % (_rid(other), data) msg += '%r\n=======\n%r\n' % (other._md[data], self._md[data]) msg += '>>>>>>> %s:%s' % (_rid(self), data) # --verbose mode enables this self._vlogger.log(logginglevels.DEBUG_3, msg)
def _wait(self, block=False): num = 0 while self.jobs: if block: pid, code = os.wait() else: pid, code = os.waitpid(-1, os.WNOHANG) if not pid: break # urlgrabber spawns child jobs, too. But they exit synchronously, # so we should never see an unknown pid here. assert pid in self.jobs po = self.jobs.pop(pid) if self.progress: self.done += po.rpm.size self.progress.update(self.done) if code != 0: unlink_f(po.rpm.localpath) self.adderror(po, _("Delta RPM rebuild failed")) elif not po.rpm.verifyLocalPkg(): self.adderror(po, _("Checksum of the delta-rebuilt RPM failed")) else: # done with drpm file, unlink when local if po.localpath.startswith(po.repo.pkgdir): os.unlink(po.localpath) # rename the rpm if --downloadonly if po.rpm.localpath.endswith(".tmp"): rpmfile = po.rpm.localpath.rsplit(".", 2)[0] os.rename(po.rpm.localpath, rpmfile) po.rpm.localpath = rpmfile num += 1 # when blocking, one is enough if block: break return num
def dequeue(self, block=True): """ Try to De-Queue a delta rebuild and spawn the rebuild process. """ # Do this here, just to keep the zombies at bay... self._wait() if not self._future_jobs: return False if self.limit <= len(self.jobs): if not block: return False self.wait(len(self.jobs) - self.limit + 1) po = self._future_jobs.pop(0) args = ("-a", po.arch) if po.oldrpm: args += "-r", po.oldrpm args += po.localpath, po.rpm.localpath try: pid = os.spawnl(os.P_NOWAIT, APPLYDELTA, APPLYDELTA, *args) except OSError, e: raise MiscError, _("Couldn't spawn %s: %s") % (APPLYDELTA, exception2msg(e))
def dequeue_all(self): """ De-Queue all delta rebuilds and spawn the rebuild processes. """ count = total = 0 for po in self.jobs.values() + self._future_jobs: count += 1 total += po.rpm.size if total: self.verbose_logger.info(_('Finishing delta rebuilds of %d package(s) (%s)'), count, progress.format_number(total)) if po.repo.callback: if hasattr(progress, 'text_meter_total_size'): progress.text_meter_total_size(0) self.progress = po.repo.callback self.progress.start(filename=None, url=None, # BZ 963023 text='<locally rebuilding deltarpms>', size=total) self.done = 0 while self._future_jobs: self.dequeue()
def doCommand(self, base, basecmd, extcmds): try: subcommand = extcmds[0] except (ValueError, IndexError): base.logger.critical(_("Error: ") + _("exactly one parameter to " "playground command are required")) # FIXME: # dnf.cli.commands.err_mini_usage(self.cli, self.cli.base.basecmd) raise YCliError(_("exactly one parameter to " "playground command are required")) chroot = self._guess_chroot() if subcommand == "enable": self._cmd_enable(chroot) base.logger.info(_("Playground repositories successfully enabled.")) elif subcommand == "disable": self._cmd_disable() base.logger.info(_("Playground repositories successfully disabled.")) elif subcommand == "upgrade": self._cmd_disable() self._cmd_enable(chroot) base.logger.info(_("Playground repositories successfully updated.")) else: raise YError(_("Unknown subcommand {}.").format(subcommand)) return 0, [basecmd + " done"]
import yum import glob import json import os import platform import requests import urllib from yum.i18n import _ from yum.plugins import TYPE_INTERACTIVE requires_api_version = "2.5" plugin_type = (TYPE_INTERACTIVE,) yes = set([_("yes"), _("y")]) no = set([_("no"), _("n"), ""]) YError = yum.Errors.YumBaseError YCliError = yum.Errors.MiscError def config_hook(conduit): conduit.registerCommand(CoprCommand()) conduit.registerCommand(PlaygroundCommand()) class CoprCommand: """ Copr plugin for DNF """ def getNames(self):
def _rid(repoid, fmt=_('(from %s)'), unknown=_("<unknown>")): if not repoid: repoid = unknown return fmt % repoid
def ysp_del_pkg(pkg, reason="updateinfo"): """ Deletes a package from all trees that yum knows about """ base.verbose_logger.log(INFO_1, _(" --> %s from %s excluded (%s)") % (pkg,pkg.repoid, reason)) pkg.repo.sack.delPackage(pkg)
import yum import glob import json import os import platform import requests import urllib from yum.i18n import _ from yum.plugins import TYPE_INTERACTIVE requires_api_version = '2.5' plugin_type = (TYPE_INTERACTIVE,) yes = set([_('yes'), _('y')]) no = set([_('no'), _('n'), '']) YError = yum.Errors.YumBaseError YCliError = yum.Errors.MiscError def config_hook(conduit): conduit.registerCommand(CoprCommand()) conduit.registerCommand(PlaygroundCommand()) class CoprCommand: """ Copr plugin for DNF """ def getNames(self): return [self.aliases[0]]
def __init__(self, ayum, pkgs, adderror): self.verbose_logger = ayum.verbose_logger self.adderror = adderror self.jobs = {} self._future_jobs = [] self.progress = None self.limit = ayum.conf.deltarpm if self.limit < 0: nprocs = _num_cpus_online() self.limit *= -nprocs if not self.limit: # Turned off. return # calculate update sizes oldrpms = {} pinfo = {} reposize = {} for index, po in enumerate(pkgs): if po.repo.deltarpm_percentage == 1: continue # Allow people to turn off a repo. (meh) if po.state == TS_UPDATE: pass elif po.name in ayum.conf.installonlypkgs: pass else: names = oldrpms.get(po.repo) if names is None: # load all locally cached rpms names = oldrpms[po.repo] = {} for rpmfn in os.listdir(po.repo.pkgdir): m = re.match('^(.+)-(.+)-(.+)\.(.+)\.rpm$', rpmfn) if m: n, v, r, a = m.groups() names.setdefault((n, a), set()).add((v, r)) if (po.name, po.arch) not in names: continue pinfo.setdefault(po.repo, {})[po.pkgtup] = index reposize[po.repo] = reposize.get(po.repo, 0) + po.size # don't use deltas when deltarpm not installed if reposize and not os.access(APPLYDELTA, os.X_OK): self.verbose_logger.info(_('Delta RPMs disabled because %s not installed.'), APPLYDELTA) return # download delta metadata mdpath = {} for repo in reposize: for name in ('prestodelta', 'deltainfo'): try: data = repo.repoXML.getData(name); break except: pass else: self.verbose_logger.info(_('No Presto metadata available for %s'), repo) continue path = repo.cachedir +'/'+ os.path.basename(data.location[1]) if not os.path.exists(path) and int(data.size) > reposize[repo]: self.verbose_logger.info(_('Not downloading Presto metadata for %s'), repo) continue def failfunc(e, name=name, repo=repo): mdpath.pop(repo, None) if hasattr(e, 'exception'): e = e.exception self.verbose_logger.warn(_('Failed to download %s for repository %s: %s'), name, repo, exception2msg(e)) kwargs = {} if async and repo._async: kwargs['failfunc'] = failfunc kwargs['async'] = True try: mdpath[repo] = repo._retrieveMD(name, **kwargs) except RepoError, e: failfunc(e)
def doCommand(self, base, basecmd, extcmds): try: subcommand = extcmds[0] project_name = extcmds[1] except (ValueError, IndexError): base.logger.critical( _('Error: ') + _('exactly two additional parameters to ' 'copr command are required')) # FIXME # dnf.cli.commands.err_mini_usage(self.cli, self.cli.base.basecmd) raise YCliError( _('exactly two additional parameters to ' 'copr command are required')) try: chroot = extcmds[2] except IndexError: chroot = self._guess_chroot() repo_filename = "/etc/yum.repos.d/_copr_{}.repo" \ .format(project_name.replace("/", "-")) if subcommand == "enable": self._need_root() self._ask_user(""" You are about to enable a Copr repository. Please note that this repository is not part of the main Fedora distribution, and quality may vary. The Fedora Project does not exercise any power over the contents of this repository beyond the rules outlined in the Copr FAQ at <https://fedorahosted.org/copr/wiki/UserDocs#WhatIcanbuildinCopr>, and packages are not held to any quality or securty level. Please do not file bug reports about these packages in Fedora Bugzilla. In case of problems, contact the owner of this repository. Do you want to continue? [y/N]: """) self._download_repo(project_name, repo_filename, chroot) base.logger.info(_("Repository successfully enabled.")) elif subcommand == "disable": self._need_root() self._remove_repo(repo_filename) base.logger.info(_("Repository successfully disabled.")) elif subcommand == "list": #http://copr.fedoraproject.org/api/coprs/ignatenkobrain/ api_path = "/api/coprs/{}/".format(project_name) opener = urllib.FancyURLopener({}) res = opener.open(self.copr_url + api_path) try: json_parse = json.loads(res.read()) except ValueError: raise YError( _("Can't parse repositories for username '{}'.") .format(project_name)) section_text = _("List of {} coprs").format(project_name) self._print_match_section(section_text) i = 0 while i < len(json_parse["repos"]): msg = "{0}/{1} : ".format(project_name, json_parse["repos"][i]["name"]) desc = json_parse["repos"][i]["description"] if not desc: desc = _("No description given") msg = self.base.fmtKeyValFill(unicode(msg), desc) print(msg) i += 1 elif subcommand == "search": #http://copr.fedoraproject.org/api/coprs/search/tests/ api_path = "/api/coprs/search/{}/".format(project_name) opener = urllib.FancyURLopener({}) res = opener.open(self.copr_url + api_path) try: json_parse = json.loads(res.read()) except ValueError: raise YError(_("Can't parse search for '{}'.").format(project_name)) section_text = _("Matched: {}").format(project_name) self._print_match_section(section_text) i = 0 while i < len(json_parse["repos"]): msg = "{0}/{1} : ".format(json_parse["repos"][i]["username"], json_parse["repos"][i]["coprname"]) desc = json_parse["repos"][i]["description"] if not desc: desc = _("No description given.") msg = self.base.fmtKeyValFill(unicode(msg), desc) print(msg) i += 1 else: raise YError( _('Unknown subcommand {}.').format(subcommand)) return 0, [basecmd + ' done']
def remove_txmbrs(base, filters=None): ''' Remove packages from the transaction, using the updateinfo data. ''' def ysp_del_pkg(tspkg): """ Deletes a package within a transaction. """ base.verbose_logger.log( INFO_1, _(" --> %s from %s removed (updateinfo)") % (tspkg.po, tspkg.po.ui_from_repo)) tsinfo.remove(tspkg.pkgtup) if filters is None: filters = base.updateinfo_filters opts = _ysp_gen_opts(filters) if _no_options(opts): return 0, 0, 0 md_info = base.upinfo tot = 0 cnt = 0 used_map = _ysp_gen_used_map(opts) tsinfo = base.tsInfo tspkgs = tsinfo.getMembers() # Ok, here we keep any pkgs that pass "ysp" tests, then we keep all # related pkgs ... Ie. "installed" version marked for removal. keep_pkgs = set() count_states = set(TS_INSTALL_STATES + [TS_ERASE]) count_pkgs = set() for tspkg in tspkgs: if tspkg.output_state in count_states: count_pkgs.add(tspkg.po) name2tup = _get_name2oldpkgtup(base) for tspkg in tspkgs: if tspkg.output_state in count_states: tot += 1 name = tspkg.po.name if (name not in name2tup or not _ysp_should_keep_pkg( opts, name2tup[name], md_info, used_map)): continue if tspkg.output_state in count_states: cnt += 1 keep_pkgs.add(tspkg.po) scnt = cnt mini_depsolve_again = True while mini_depsolve_again: mini_depsolve_again = False for tspkg in tspkgs: if tspkg.po in keep_pkgs: # Find any related pkgs, and add them: for (rpkg, reason) in tspkg.relatedto: if rpkg not in keep_pkgs: if rpkg in count_pkgs: cnt += 1 keep_pkgs.add(rpkg) mini_depsolve_again = True else: # If related to any keep pkgs, add us for (rpkg, reason) in tspkg.relatedto: if rpkg in keep_pkgs: if rpkg in count_pkgs: cnt += 1 keep_pkgs.add(tspkg.po) mini_depsolve_again = True break for tspkg in tspkgs: if tspkg.po not in keep_pkgs: ysp_del_pkg(tspkg) _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x)) if cnt: base.verbose_logger.log( INFO_1, _('%d package(s) needed (+%d related) for security, out of %d available' ) % (scnt, cnt - scnt, tot)) else: base.verbose_logger.log( INFO_1, _('No packages needed for security; %d packages available') % tot) return cnt, scnt, tot
class CoprCommand: """ Copr plugin for DNF """ def getNames(self): return [self.aliases[0]] def getUsage(self): return self.usage def getSummary(self): return self.summary[1:] def doCheck(self, base, basecmd, extcmds): self.base = base copr_url = "https://copr.fedoraproject.org" aliases = ("copr",) summary = _("Interact with Copr repositories.") usage = _(""" enable name/project [chroot] disable name/project list name search project Examples: copr enable rhscl/perl516 epel-6-x86_64 copr enable ignatenkobrain/ocltoys copr disable rhscl/perl516 copr list ignatenkobrain copr search tests """) def doCommand(self, base, basecmd, extcmds): try: subcommand = extcmds[0] project_name = extcmds[1] except (ValueError, IndexError): base.logger.critical( _('Error: ') + _('exactly two additional parameters to ' 'copr command are required')) # FIXME # dnf.cli.commands.err_mini_usage(self.cli, self.cli.base.basecmd) raise YCliError( _('exactly two additional parameters to ' 'copr command are required')) try: chroot = extcmds[2] except IndexError: chroot = self._guess_chroot() repo_filename = "/etc/yum.repos.d/_copr_{}.repo" \ .format(project_name.replace("/", "-")) if subcommand == "enable": self._need_root() self._ask_user(""" You are about to enable a Copr repository. Please note that this repository is not part of the main Fedora distribution, and quality may vary. The Fedora Project does not exercise any power over the contents of this repository beyond the rules outlined in the Copr FAQ at <https://fedorahosted.org/copr/wiki/UserDocs#WhatIcanbuildinCopr>, and packages are not held to any quality or securty level. Please do not file bug reports about these packages in Fedora Bugzilla. In case of problems, contact the owner of this repository. Do you want to continue? [y/N]: """) self._download_repo(project_name, repo_filename, chroot) base.logger.info(_("Repository successfully enabled.")) elif subcommand == "disable": self._need_root() self._remove_repo(repo_filename) base.logger.info(_("Repository successfully disabled.")) elif subcommand == "list": #http://copr.fedoraproject.org/api/coprs/ignatenkobrain/ api_path = "/api/coprs/{}/".format(project_name) opener = urllib.FancyURLopener({}) res = opener.open(self.copr_url + api_path) try: json_parse = json.loads(res.read()) except ValueError: raise YError( _("Can't parse repositories for username '{}'.") .format(project_name)) section_text = _("List of {} coprs").format(project_name) self._print_match_section(section_text) i = 0 while i < len(json_parse["repos"]): msg = "{0}/{1} : ".format(project_name, json_parse["repos"][i]["name"]) desc = json_parse["repos"][i]["description"] if not desc: desc = _("No description given") msg = self.base.fmtKeyValFill(unicode(msg), desc) print(msg) i += 1 elif subcommand == "search": #http://copr.fedoraproject.org/api/coprs/search/tests/ api_path = "/api/coprs/search/{}/".format(project_name) opener = urllib.FancyURLopener({}) res = opener.open(self.copr_url + api_path) try: json_parse = json.loads(res.read()) except ValueError: raise YError(_("Can't parse search for '{}'.").format(project_name)) section_text = _("Matched: {}").format(project_name) self._print_match_section(section_text) i = 0 while i < len(json_parse["repos"]): msg = "{0}/{1} : ".format(json_parse["repos"][i]["username"], json_parse["repos"][i]["coprname"]) desc = json_parse["repos"][i]["description"] if not desc: desc = _("No description given.") msg = self.base.fmtKeyValFill(unicode(msg), desc) print(msg) i += 1 else: raise YError( _('Unknown subcommand {}.').format(subcommand)) return 0, [basecmd + ' done'] def _print_match_section(self, text): formatted = self.base.fmtSection(text) print(formatted) def _ask_user(self, question): if self.base.conf.assumeyes and not self.base.conf.assumeno: return elif self.base.conf.assumeno and not self.base.conf.assumeyes: raise YError(_('Safe and good answer. Exiting.')) answer = raw_input(question).lower() answer = _(answer) while not ((answer in yes) or (answer in no)): answer = raw_input(question).lower() answer = _(answer) if answer in yes: return else: raise YError(_('Safe and good answer. Exiting.')) @classmethod def _need_root(cls): # FIXME this should do dnf itself (BZ#1062889) if os.geteuid() != 0: raise YError( _('This command has to be run under the root user.')) @classmethod def _guess_chroot(cls): """ Guess which choot is equivalent to this machine """ # FIXME Copr should generate non-specific arch repo dist = platform.linux_distribution() if "Fedora" in dist: # x86_64 because repo-file is same for all arch # ($basearch is used) if "Rawhide" in dist: chroot = ("fedora-rawhide-x86_64") else: chroot = ("fedora-{}-x86_64".format(dist[1])) else: chroot = ("epel-%s-x86_64" % dist[1].split(".", 1)[0]) return chroot @classmethod def _download_repo(cls, project_name, repo_filename, chroot=None): if chroot is None: chroot = cls._guess_chroot() #http://copr.fedoraproject.org/coprs/larsks/rcm/repo/epel-7-x86_64/ api_path = "/coprs/{0}/repo/{1}/".format(project_name, chroot) ug = grabber.URLGrabber() # FIXME when we are full on python2 urllib.parse try: ug.urlgrab(cls.copr_url + api_path, filename=repo_filename) except grabber.URLGrabError as e: cls._remove_repo(repo_filename) raise YError(str(e)) @classmethod def _remove_repo(cls, repo_filename): # FIXME is it Copr repo ? try: os.remove(repo_filename) except OSError as e: raise YError(str(e)) @classmethod def _get_data(cls, req): """ Wrapper around response from server check data and print nice error in case of some error (and return None) otherwise return json object. """ try: output = json.loads(req.text) except ValueError: YCliError(_("Unknown response from server.")) return if req.status_code != 200: YCliError(_( "Something went wrong:\n {0}\n".format(output["error"]))) return return output
def failfunc(e, name=name, repo=repo): mdpath.pop(repo, None) if hasattr(e, "exception"): e = e.exception self.verbose_logger.warn(_("Failed to download %s for repository %s: %s"), name, repo, exception2msg(e))
def __init__(self, ayum, pkgs, adderror): self.verbose_logger = ayum.verbose_logger self.adderror = adderror self.jobs = {} self._future_jobs = [] self.progress = None self.limit = ayum.conf.deltarpm if self.limit < 0: nprocs = _num_cpus_online() self.limit *= -nprocs if not self.limit: # Turned off. return # calculate update sizes oldrpms = {} pinfo = {} reposize = {} for index, po in enumerate(pkgs): perc = po.repo.deltarpm_percentage if perc is None: urls = po.repo.urls perc = ayum.conf.deltarpm_percentage if len(urls) == 1 and urls[0].startswith("file:"): perc = 0 # for local repos, default to off. if perc == 0: continue # Allow people to turn off a repo. (meh) if po.state == TS_UPDATE: pass elif po.name in ayum.conf.installonlypkgs: pass else: names = oldrpms.get(po.repo) if names is None: # load all locally cached rpms names = oldrpms[po.repo] = {} for rpmfn in os.listdir(po.repo.pkgdir): m = re.match("^(.+)-(.+)-(.+)\.(.+)\.rpm$", rpmfn) if m: n, v, r, a = m.groups() names.setdefault((n, a), set()).add((v, r)) if (po.name, po.arch) not in names: continue pinfo.setdefault(po.repo, {})[po.pkgtup] = index reposize[po.repo] = reposize.get(po.repo, 0) + po.size # don't use deltas when deltarpm not installed if reposize and not os.access(APPLYDELTA, os.X_OK): self.verbose_logger.info(_("Delta RPMs disabled because %s not installed."), APPLYDELTA) return # download delta metadata mdpath = {} for repo in reposize: for name in ("prestodelta", "deltainfo"): try: data = repo.repoXML.getData(name) break except: pass else: self.verbose_logger.info(_("No Presto metadata available for %s"), repo) continue path = repo.cachedir + "/" + os.path.basename(data.location[1]) perc = repo.deltarpm_metadata_percentage data_size = int(data.size) * (perc / 100.0) if perc and not os.path.exists(path) and data_size > reposize[repo]: msg = _("Not downloading deltainfo for %s, MD is %s and rpms are %s") self.verbose_logger.info( msg, repo, progress.format_number(data_size), progress.format_number(reposize[repo]) ) continue def failfunc(e, name=name, repo=repo): mdpath.pop(repo, None) if hasattr(e, "exception"): e = e.exception self.verbose_logger.warn(_("Failed to download %s for repository %s: %s"), name, repo, exception2msg(e)) kwargs = {} if async and repo._async: kwargs["failfunc"] = failfunc kwargs["async"] = True try: mdpath[repo] = repo._retrieveMD(name, **kwargs) except RepoError, e: failfunc(e)
class PlaygroundCommand(CoprCommand): """ Playground plugin for DNF """ aliases = ("playground",) summary = _("Interact with Playground repository.") usage = " [enable|disable|upgrade]" def _cmd_enable(self, chroot): self._need_root() self._ask_user(""" You are about to enable a Playground repository. Do you want to continue? [y/N]: """) api_url = "{0}/api/playground/list/".format( self.copr_url) req = requests.get(api_url) output = self._get_data(req) if output["output"] != "ok": raise YCliError(_("Unknown response from server.")) for repo in output["repos"]: project_name = "{0}/{1}".format(repo["username"], repo["coprname"]) repo_filename = "/etc/yum.repos.d/_playground_{}.repo" \ .format(project_name.replace("/", "-")) try: # check if that repo exist? but that will result in twice # up calls api_url = "{0}/api/coprs/{1}/detail/{2}/".format( self.copr_url, project_name, chroot) req = requests.get(api_url) output2 = self._get_data(req) if output2 and ("output" in output2) and (output2["output"] == "ok"): self._download_repo(project_name, repo_filename, chroot) except YError: # likely 404 and that repo does not exist pass def _cmd_disable(self): self._need_root() for repo_filename in glob.glob('/etc/yum.repos.d/_playground_*.repo'): self._remove_repo(repo_filename) def doCommand(self, base, basecmd, extcmds): try: subcommand = extcmds[0] except (ValueError, IndexError): base.logger.critical( _('Error: ') + _('exactly one parameter to ' 'playground command are required')) # FIXME: # dnf.cli.commands.err_mini_usage(self.cli, self.cli.base.basecmd) raise YCliError( _('exactly one parameter to ' 'playground command are required')) chroot = self._guess_chroot() if subcommand == "enable": self._cmd_enable(chroot) base.logger.info(_("Playground repositories successfully enabled.")) elif subcommand == "disable": self._cmd_disable() base.logger.info(_("Playground repositories successfully disabled.")) elif subcommand == "upgrade": self._cmd_disable() self._cmd_enable(chroot) base.logger.info(_("Playground repositories successfully updated.")) else: raise YError( _('Unknown subcommand {}.').format(subcommand)) return 0, [basecmd + ' done']
def _rid(repoid, fmt=_(" (from %s)")): if not repoid: return "" return fmt % repoid
def _need_root(cls): # FIXME this should do dnf itself (BZ#1062889) if os.geteuid() != 0: raise YError(_("This command has to be run under the root user."))
def _need_root(cls): # FIXME this should do dnf itself (BZ#1062889) if os.geteuid() != 0: raise YError( _('This command has to be run under the root user.'))
def __init__(self, ayum, pkgs, adderror): self.verbose_logger = ayum.verbose_logger self.adderror = adderror self.jobs = {} self._future_jobs = [] self.progress = None self.limit = ayum.conf.deltarpm if self.limit < 0: nprocs = _num_cpus_online() self.limit *= -nprocs if not self.limit: # Turned off. return # calculate update sizes oldrpms = {} pinfo = {} reposize = {} for index, po in enumerate(pkgs): perc = po.repo.deltarpm_percentage if perc is None: urls = po.repo.urls perc = ayum.conf.deltarpm_percentage if len(urls) == 1 and urls[0].startswith('file:'): perc = 0 # for local repos, default to off. if perc == 0: continue # Allow people to turn off a repo. (meh) if po.state == TS_UPDATE: pass elif po.name in ayum.conf.installonlypkgs: pass else: names = oldrpms.get(po.repo) if names is None: # load all locally cached rpms names = oldrpms[po.repo] = {} for rpmfn in os.listdir(po.repo.pkgdir): m = re.match('^(.+)-(.+)-(.+)\.(.+)\.rpm$', rpmfn) if m: n, v, r, a = m.groups() names.setdefault((n, a), set()).add((v, r)) if (po.name, po.arch) not in names: continue pinfo.setdefault(po.repo, {})[po.pkgtup] = index reposize[po.repo] = reposize.get(po.repo, 0) + po.size # don't use deltas when deltarpm not installed if reposize and not os.access(APPLYDELTA, os.X_OK): self.verbose_logger.info( _('Delta RPMs disabled because %s not installed.'), APPLYDELTA) return # download delta metadata mdpath = {} for repo in reposize: for name in ('prestodelta', 'deltainfo'): try: data = repo.repoXML.getData(name) break except: pass else: self.verbose_logger.info( _('No Presto metadata available for %s'), repo) continue path = repo.cachedir + '/' + os.path.basename(data.location[1]) perc = repo.deltarpm_metadata_percentage data_size = int(data.size) * (perc / 100.0) if perc and not os.path.exists( path) and data_size > reposize[repo]: msg = _( 'Not downloading deltainfo for %s, MD is %s and rpms are %s' ) self.verbose_logger.info( msg, repo, progress.format_number(data_size), progress.format_number(reposize[repo])) continue def failfunc(e, name=name, repo=repo): mdpath.pop(repo, None) if hasattr(e, 'exception'): e = e.exception self.verbose_logger.warn( _('Failed to download %s for repository %s: %s'), name, repo, exception2msg(e)) kwargs = {} if async and repo._async: kwargs['failfunc'] = failfunc kwargs['async'] = True try: mdpath[repo] = repo._retrieveMD(name, **kwargs) except RepoError, e: failfunc(e)
def remove_txmbrs(base, filters=None): ''' Remove packages from the transaction, using the updateinfo data. ''' def ysp_del_pkg(tspkg): """ Deletes a package within a transaction. """ base.verbose_logger.log(INFO_1, _(" --> %s from %s removed (updateinfo)") % (tspkg.po, tspkg.po.ui_from_repo)) tsinfo.remove(tspkg.pkgtup) if filters is None: filters = base.updateinfo_filters opts = _updateinfofilter2opts(filters) if _no_options(opts): return 0, 0, 0 md_info = base.upinfo tot = 0 cnt = 0 used_map = _ysp_gen_used_map(opts) tsinfo = base.tsInfo tspkgs = tsinfo.getMembers() # Ok, here we keep any pkgs that pass "ysp" tests, then we keep all # related pkgs ... Ie. "installed" version marked for removal. keep_pkgs = set() count_states = set(TS_INSTALL_STATES + [TS_ERASE]) count_pkgs = set() for tspkg in tspkgs: if tspkg.output_state in count_states: count_pkgs.add(tspkg.po) name2tup = _get_name2oldpkgtup(base) for tspkg in tspkgs: if tspkg.output_state in count_states: tot += 1 name = tspkg.po.name if (name not in name2tup or not _ysp_should_keep_pkg(opts, name2tup[name], md_info, used_map)): continue if tspkg.output_state in count_states: cnt += 1 keep_pkgs.add(tspkg.po) scnt = cnt mini_depsolve_again = True while mini_depsolve_again: mini_depsolve_again = False for tspkg in tspkgs: if tspkg.po in keep_pkgs: # Find any related pkgs, and add them: for (rpkg, reason) in tspkg.relatedto: if rpkg not in keep_pkgs: if rpkg in count_pkgs: cnt += 1 keep_pkgs.add(rpkg) mini_depsolve_again = True else: # If related to any keep pkgs, add us for (rpkg, reason) in tspkg.relatedto: if rpkg in keep_pkgs: if rpkg in count_pkgs: cnt += 1 keep_pkgs.add(tspkg.po) mini_depsolve_again = True break for tspkg in tspkgs: if tspkg.po not in keep_pkgs: ysp_del_pkg(tspkg) _ysp_chk_used_map(used_map, lambda x: base.verbose_logger.warn("%s", x)) if cnt: base.verbose_logger.log(INFO_1, _('%d package(s) needed (+%d related) for security, out of %d available') % (scnt, cnt - scnt, tot)) else: base.verbose_logger.log(INFO_1, _('No packages needed for security; %d packages available') % tot) return cnt, scnt, tot
def doCommand(self, base, basecmd, extcmds): try: subcommand = extcmds[0] project_name = extcmds[1] except (ValueError, IndexError): base.logger.critical(_("Error: ") + _("exactly two additional parameters to " "copr command are required")) # FIXME # dnf.cli.commands.err_mini_usage(self.cli, self.cli.base.basecmd) raise YCliError(_("exactly two additional parameters to " "copr command are required")) try: chroot = extcmds[2] except IndexError: chroot = self._guess_chroot() repo_filename = "/etc/yum.repos.d/_copr_{}.repo".format(project_name.replace("/", "-")) if subcommand == "enable": self._need_root() self._ask_user( """ You are about to enable a Copr repository. Please note that this repository is not part of the main Fedora distribution, and quality may vary. The Fedora Project does not exercise any power over the contents of this repository beyond the rules outlined in the Copr FAQ at <https://fedorahosted.org/copr/wiki/UserDocs#WhatIcanbuildinCopr>, and packages are not held to any quality or securty level. Please do not file bug reports about these packages in Fedora Bugzilla. In case of problems, contact the owner of this repository. Do you want to continue? [y/N]: """ ) self._download_repo(project_name, repo_filename, chroot) base.logger.info(_("Repository successfully enabled.")) elif subcommand == "disable": self._need_root() self._remove_repo(repo_filename) base.logger.info(_("Repository successfully disabled.")) elif subcommand == "list": # http://copr.fedoraproject.org/api/coprs/ignatenkobrain/ api_path = "/api/coprs/{}/".format(project_name) opener = urllib.FancyURLopener({}) res = opener.open(self.copr_url + api_path) try: json_parse = json.loads(res.read()) except ValueError: raise YError(_("Can't parse repositories for username '{}'.").format(project_name)) section_text = _("List of {} coprs").format(project_name) self._print_match_section(section_text) i = 0 while i < len(json_parse["repos"]): msg = "{0}/{1} : ".format(project_name, json_parse["repos"][i]["name"]) desc = json_parse["repos"][i]["description"] if not desc: desc = _("No description given") msg = self.base.fmtKeyValFill(unicode(msg), desc) print(msg) i += 1 elif subcommand == "search": # http://copr.fedoraproject.org/api/coprs/search/tests/ api_path = "/api/coprs/search/{}/".format(project_name) opener = urllib.FancyURLopener({}) res = opener.open(self.copr_url + api_path) try: json_parse = json.loads(res.read()) except ValueError: raise YError(_("Can't parse search for '{}'.").format(project_name)) section_text = _("Matched: {}").format(project_name) self._print_match_section(section_text) i = 0 while i < len(json_parse["repos"]): msg = "{0}/{1} : ".format(json_parse["repos"][i]["username"], json_parse["repos"][i]["coprname"]) desc = json_parse["repos"][i]["description"] if not desc: desc = _("No description given.") msg = self.base.fmtKeyValFill(unicode(msg), desc) print(msg) i += 1 else: raise YError(_("Unknown subcommand {}.").format(subcommand)) return 0, [basecmd + " done"]
def ysp_del_pkg(pkg, reason="updateinfo"): """ Deletes a package from all trees that yum knows about """ base.verbose_logger.log( INFO_1, _(" --> %s from %s excluded (%s)") % (pkg, pkg.repoid, reason)) pkg.repo.sack.delPackage(pkg)
def _rid(repoid, fmt=_(' (from %s)')): if not repoid: return '' return fmt % repoid
def failfunc(e, name=name, repo=repo): mdpath.pop(repo, None) if hasattr(e, 'exception'): e = e.exception self.verbose_logger.warn( _('Failed to download %s for repository %s: %s'), name, repo, exception2msg(e))