[yum-commits] 8 commits - cli.py etc/yum-cron.conf etc/yum-cron-hourly.conf yumcommands.py yum-cron/yum-cron.py yum-cron/yum-hourly.cron.sh yum/__init__.py yum.spec yum/updateinfo.py
James Antill
james at osuosl.org
Fri Apr 19 04:16:40 UTC 2013
cli.py | 26 ++
etc/yum-cron-hourly.conf | 9
etc/yum-cron.conf | 9
yum-cron/yum-cron.py | 75 +++---
yum-cron/yum-hourly.cron.sh | 2
yum.spec | 4
yum/__init__.py | 38 +++
yum/updateinfo.py | 515 ++++++++++++++++++++++++++++++++++++++++++++
yumcommands.py | 427 ++++++++++++++++++++++++++++++++++++
9 files changed, 1062 insertions(+), 43 deletions(-)
New commits:
commit 36ce5ff91ee0f1cecb51e4f0cd4b810353de7bd3
Author: James Antill <james at and.org>
Date: Thu Apr 18 17:12:59 2013 -0400
Add comment documentation about update_cmd to yum-cron.conf files.
diff --git a/etc/yum-cron-hourly.conf b/etc/yum-cron-hourly.conf
index ece67c4..b17448c 100644
--- a/etc/yum-cron-hourly.conf
+++ b/etc/yum-cron-hourly.conf
@@ -1,4 +1,13 @@
[commands]
+# What kind of update to use:
+# default = yum upgrade
+# security = yum --security upgrade
+# security-severity:Critical = yum --sec-severity=Critical upgrade
+# minimal = yum --bugfix upgrade-minimal
+# minimal-security = yum --security upgrade-minimal
+# minimal-security-severity:Critical = --sec-severity=Critical upgrade-minimal
+update_cmd = default
+
# Whether a message should emitted when updates are available.
update_messages = no
diff --git a/etc/yum-cron.conf b/etc/yum-cron.conf
index d19fce3..3221802 100644
--- a/etc/yum-cron.conf
+++ b/etc/yum-cron.conf
@@ -1,4 +1,13 @@
[commands]
+# What kind of update to use:
+# default = yum upgrade
+# security = yum --security upgrade
+# security-severity:Critical = yum --sec-severity=Critical upgrade
+# minimal = yum --bugfix upgrade-minimal
+# minimal-security = yum --security upgrade-minimal
+# minimal-security-severity:Critical = --sec-severity=Critical upgrade-minimal
+update_cmd = default
+
# Whether a message should emitted when updates are available.
update_messages = yes
commit b90840d1aa733811bbb9165272d09159a1018e35
Merge: d99089b f32d39f
Author: James Antill <james at and.org>
Date: Thu Apr 18 17:07:40 2013 -0400
Merge branch 'master' of ssh://yum.baseurl.org/srv/projects/yum/git/yum
* 'master' of ssh://yum.baseurl.org/srv/projects/yum/git/yum: (4 commits)
support socks4/5 proxies. BZ 428588
...
commit d99089b628497bcaf24ae43e50a89e9254227096
Author: James Antill <james at and.org>
Date: Thu Apr 18 17:06:57 2013 -0400
Add update_cmd to yum-cron, so we can do security/minimal/etc. updates.
diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py
index 30a147b..0b6af7d 100755
--- a/yum-cron/yum-cron.py
+++ b/yum-cron/yum-cron.py
@@ -701,6 +701,7 @@ class YumCronConfig(BaseConfig):
email_host = Option("localhost")
email_port = IntOption(25)
update_messages = BoolOption(False)
+ update_cmd = Option("default")
apply_updates = BoolOption(False)
download_updates = BoolOption(False)
yum_config_file = Option("/etc/yum.conf")
@@ -831,27 +832,37 @@ class YumCronBase(yum.YumBase):
available
"""
try:
- updatesTuples = self.up.getUpdatesTuples()
- # If there are no updates, return False
- if not updatesTuples:
- return False
-
- # figure out the updates
- for (new, old) in updatesTuples:
- updates_available = True
- updating = self.getPackageObject(new)
- updated = self.rpmdb.searchPkgTuple(old)[0]
-
- self.tsInfo.addUpdate(updating, updated)
-
- # and the obsoletes
- if self.conf.obsoletes:
- for (obs, inst) in self.up.getObsoletesTuples():
- obsoleting = self.getPackageObject(obs)
- installed = self.rpmdb.searchPkgTuple(inst)[0]
-
- self.tsInfo.addObsoleting(obsoleting, installed)
- self.tsInfo.addObsoleted(installed, obsoleting)
+ # Just call .update() because it does obsoletes loops, and group
+ # objects. etc.
+
+ update_cmd = self.opts.update_cmd
+ idx = update_cmd.find("security-severity:")
+ if idx != -1:
+ sevs = update_cmd[idx + len("security-severity:"):]
+ update_cmd = update_cmd[:idx + len("security")]
+ self.updateinfo_filters['sevs'] = sevs.split(",")
+
+
+ if self.opts.update_cmd in ('minimal', 'minimal-security'):
+ if not updateinfo.update_minimal(self):
+ return False
+ self.updateinfo_filters['bugfix'] = True
+ elif self.opts.update_cmd in ('default', 'security',
+ 'default-security'):
+ if not self.update():
+ return False
+ else:
+ # return False ?
+ self.opts.update_cmd = 'default'
+ if not self.update():
+ return False
+
+ if self.opts.update_cmd.endswith("security"):
+ self.updateinfo_filters['security'] = True
+ updateinfo.remove_txmbrs(self)
+ elif self.opts.update_cmd == 'minimal':
+ self.updateinfo_filters['bugfix'] = True
+ updateinfo.remove_txmbrs(self)
except Exception, e:
self.emitCheckFailed("%s" %(e,))
commit d63aee13e8145852f970156ab9fe220367123eb1
Author: James Antill <james at and.org>
Date: Thu Apr 18 17:06:25 2013 -0400
Fixes for yum-cron: use .upinfo, group as objects, use quiet.
diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py
index 089cad4..30a147b 100755
--- a/yum-cron/yum-cron.py
+++ b/yum-cron/yum-cron.py
@@ -10,7 +10,6 @@ from yum.config import BaseConfig, Option, IntOption, ListOption, BoolOption
from yum.parser import ConfigPreProcessor
from ConfigParser import ConfigParser, ParsingError
from yum.constants import *
-from yum.update_md import UpdateMetadata
from email.mime.text import MIMEText
from yum.i18n import to_str, to_utf8, to_unicode, utf8_width, utf8_width_fill, utf8_text_fill
from yum import _, P_
@@ -796,6 +795,9 @@ class YumCronBase(yum.YumBase):
if os.geteuid() != 0:
self.setCacheDir()
+ # Turn off the plugins line
+ self.preconf.debuglevel = 0
+
# Create the configuration
self.conf
@@ -820,22 +822,7 @@ class YumCronBase(yum.YumBase):
def populateUpdateMetadata(self):
"""Populate the metadata for the packages in the update."""
-
- self.updateMetadata = UpdateMetadata()
- repos = []
-
- for (new, old) in self.up.getUpdatesTuples():
- pkg = self.getPackageObject(new)
- if pkg.repoid not in repos:
- repo = self.repos.getRepo(pkg.repoid)
- repos.append(repo.id)
- try: # grab the updateinfo.xml.gz from the repodata
- md = repo.retrieveMD('updateinfo')
- except Exception: # can't find any; silently move on
- continue
- md = gzip.open(md)
- self.updateMetadata.add(md)
- md.close()
+ self.upinfo
def refreshUpdates(self):
"""Check whether updates are available.
@@ -880,6 +867,9 @@ class YumCronBase(yum.YumBase):
:return: Boolean indicating whether there are any updates to
the group available
"""
+ if self.conf.group_command == 'objects':
+ return False
+
update_available = False
try:
for group_string in self.opts.group_list:
commit c6a12f1b0597404a83cf20a741dcff5cd59c5360
Author: James Antill <james at and.org>
Date: Thu Apr 18 17:04:32 2013 -0400
Add updateinfo/update-minimal commands, and --security/etc. options.
diff --git a/cli.py b/cli.py
index 8ea5d1f..ba2e343 100755
--- a/cli.py
+++ b/cli.py
@@ -109,6 +109,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
self.registerCommand(yumcommands.LoadTransactionCommand())
self.registerCommand(yumcommands.SwapCommand())
self.registerCommand(yumcommands.RepoPkgsCommand())
+ self.registerCommand(yumcommands.UpdateinfoCommand())
+ self.registerCommand(yumcommands.UpdateMinimalCommand())
def registerCommand(self, command):
"""Register a :class:`yumcommands.YumCommand` so that it can be called by
@@ -2130,6 +2132,14 @@ class YumOptionParser(OptionParser):
self.base.conf.downloadonly = opts.dlonly
self.base.conf.downloaddir = opts.dldir
+ # Store all the updateinfo filters somewhere...
+ self.base.updateinfo_filters['security'] = opts.security
+ self.base.updateinfo_filters['bugfix'] = opts.bugfix
+ self.base.updateinfo_filters['advs'] = self._splitArg(opts.advs)
+ self.base.updateinfo_filters['bzs'] = self._splitArg(opts.bzs)
+ self.base.updateinfo_filters['cves'] = self._splitArg(opts.cves)
+ self.base.updateinfo_filters['sevs'] = self._splitArg(opts.sevs)
+
# Treat users like root as much as possible:
if not self.base.setCacheDir():
self.base.conf.cache = 1
@@ -2357,6 +2367,22 @@ class YumOptionParser(OptionParser):
group.add_option("", "--setopt", dest="setopts", default=[],
action="append", help=_("set arbitrary config and repo options"))
+ # Updateinfo options...
+ group.add_option("--bugfix", action="store_true",
+ help=_("Include bugfix relevant packages, in updates"))
+ group.add_option("--security", action="store_true",
+ help=_("Include security relevant packages, in updates"))
+
+ group.add_option("--advisory", "--advisories", dest="advs", default=[],
+ action="append", help=_("Include packages needed to fix the given advisory, in updates"))
+ group.add_option("--bzs", default=[],
+ action="append", help=_("Include packages needed to fix the given BZ, in updates"))
+ group.add_option("--cves", default=[],
+ action="append", help=_("Include packages needed to fix the given CVE, in updates"))
+ group.add_option("--sec-severity", "--secseverity", default=[],
+ dest="sevs", action="append",
+ help=_("Include security relevant packages matching the severity, in updates"))
+
def _filtercmdline(novalopts, valopts, args):
'''Keep only specific options from the command line argument list
diff --git a/yum.spec b/yum.spec
index a270de5..455c3ae 100644
--- a/yum.spec
+++ b/yum.spec
@@ -110,6 +110,8 @@ Obsoletes: yum-plugin-downloadonly <= 1.1.31-7.fc18
Provides: yum-plugin-downloadonly = 3.4.3-44.yum
Obsoletes: yum-presto < 3.4.3-66.yum
Provides: yum-presto = 3.4.3-66.yum
+Obsoletes: yum-plugin-security < 1.1.32
+Provides: yum-plugin-security = 3.4.3-84.yum
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -139,7 +141,7 @@ can notify you when they are available via email, syslog or dbus.
%package cron
Summary: Files needed to run yum updates as a cron job
Group: System Environment/Base
-Requires: yum >= 3.0 cronie crontabs findutils
+Requires: yum >= 3.4.3-84 cronie crontabs findutils
%if %{yum_cron_systemd}
BuildRequires: systemd-units
Requires(post): systemd
diff --git a/yumcommands.py b/yumcommands.py
index 968f231..e5f2363 100644
--- a/yumcommands.py
+++ b/yumcommands.py
@@ -13,6 +13,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2006 Duke University
+# Copyright 2013 Red Hat
# Written by Seth Vidal
"""
@@ -34,6 +35,7 @@ import tempfile
import glob
import yum.config
+from yum import updateinfo
def _err_mini_usage(base, basecmd):
if basecmd not in base.yum_cli_commands:
@@ -484,7 +486,9 @@ class UpdateCommand(YumCommand):
"""
self.doneCommand(base, _("Setting up Update Process"))
try:
- return base.updatePkgs(extcmds, update_to=(basecmd == 'update-to'))
+ ret = base.updatePkgs(extcmds, update_to=(basecmd == 'update-to'))
+ updateinfo.remove_txmbrs(base)
+ return ret
except yum.Errors.YumBaseError, e:
return 1, [exception2msg(e)]
@@ -545,7 +549,9 @@ class DistroSyncCommand(YumCommand):
self.doneCommand(base, _("Setting up Distribution Synchronization Process"))
try:
base.conf.obsoletes = 1
- return base.distroSyncPkgs(extcmds)
+ ret = base.distroSyncPkgs(extcmds)
+ updateinfo.remove_txmbrs(base)
+ return ret
except yum.Errors.YumBaseError, e:
return 1, [exception2msg(e)]
@@ -618,6 +624,12 @@ class InfoCommand(YumCommand):
1 = we've errored, exit with error string
2 = we've got work yet to do, onto the next stage
"""
+
+ if extcmds and extcmds[0] in ('updates', 'obsoletes'):
+ updateinfo.exclude_updates(base)
+ else:
+ updateinfo.exclude_all(base)
+
try:
highlight = base.term.MODE['bold']
# If we are doing: "yum info installed blah" don't do the highlight
@@ -1028,7 +1040,9 @@ class GroupsCommand(YumCommand):
if cmd == 'install':
return base.installGroups(extcmds)
if cmd == 'upgrade':
- return base.installGroups(extcmds, upgrade=True)
+ ret = base.installGroups(extcmds, upgrade=True)
+ updateinfo.remove_txmbrs(base)
+ return ret
if cmd == 'remove':
return base.removeGroups(extcmds)
@@ -1490,6 +1504,7 @@ class ProvidesCommand(YumCommand):
"""
base.logger.debug("Searching Packages: ")
try:
+ updateinfo.exclude_updates(base)
return base.provides(extcmds)
except yum.Errors.YumBaseError, e:
return 1, [exception2msg(e)]
@@ -1556,6 +1571,7 @@ class CheckUpdateCommand(YumCommand):
1 = we've errored, exit with error string
2 = we've got work yet to do, onto the next stage
"""
+ updateinfo.exclude_updates(base)
obscmds = ['obsoletes'] + extcmds
base.extcmds.insert(0, 'updates')
result = 0
@@ -1591,6 +1607,12 @@ class CheckUpdateCommand(YumCommand):
base.updatesObsoletesList(obtup, 'obsoletes',
columns=columns)
result = 100
+
+ # Add check_running_kernel call, if updateinfo is available.
+ if updateinfo._repos_downloaded(base.repos.listEnabled()):
+ def _msg(x):
+ base.verbose_logger.info("%s", x)
+ updateinfo._check_running_kernel(base, base.upinfo, _msg)
except yum.Errors.YumBaseError, e:
return 1, [exception2msg(e)]
else:
@@ -1660,6 +1682,7 @@ class SearchCommand(YumCommand):
"""
base.logger.debug(_("Searching Packages: "))
try:
+ updateinfo.exclude_updates(base)
return base.search(extcmds)
except yum.Errors.YumBaseError, e:
return 1, [exception2msg(e)]
@@ -1743,7 +1766,9 @@ class UpgradeCommand(YumCommand):
base.conf.obsoletes = 1
self.doneCommand(base, _("Setting up Upgrade Process"))
try:
- return base.updatePkgs(extcmds, update_to=(basecmd == 'upgrade-to'))
+ ret = base.updatePkgs(extcmds, update_to=(basecmd == 'upgrade-to'))
+ updateinfo.remove_txmbrs(base)
+ return ret
except yum.Errors.YumBaseError, e:
return 1, [exception2msg(e)]
@@ -1872,6 +1897,7 @@ class ResolveDepCommand(YumCommand):
"""
base.logger.debug(_("Searching Packages for Dependency:"))
try:
+ updateinfo.exclude_updates(base)
return base.resolveDepCli(extcmds)
except yum.Errors.YumBaseError, e:
return 1, [exception2msg(e)]
@@ -2010,6 +2036,7 @@ class DepListCommand(YumCommand):
"""
self.doneCommand(base, _("Finding dependencies: "))
try:
+ updateinfo.exclude_updates(base)
return base.deplist(extcmds)
except yum.Errors.YumBaseError, e:
return 1, [exception2msg(e)]
@@ -3489,6 +3516,7 @@ class RepoPkgsCommand(YumCommand):
num += len(txmbrs)
if num:
+ updateinfo.remove_txmbrs(base)
return 2, P_('%d package to update', '%d packages to update',
num)
@@ -3499,6 +3527,7 @@ class RepoPkgsCommand(YumCommand):
num += len(txmbrs)
if num:
+ updateinfo.remove_txmbrs(base)
return 2, P_('%d package to update', '%d packages to update',
num)
@@ -3676,3 +3705,393 @@ class RepoPkgsCommand(YumCommand):
if cmd in ('info', 'list'):
return InfoCommand().cacheRequirement(base, cmd, extcmds[2:])
return 'write'
+
+# Using this a lot, so make it easier...
+_upi = updateinfo
+class UpdateinfoCommand(YumCommand):
+ # Old command names...
+ direct_cmds = {'list-updateinfo' : 'list',
+ 'list-security' : 'list',
+ 'list-sec' : 'list',
+ 'info-updateinfo' : 'info',
+ 'info-security' : 'info',
+ 'info-sec' : 'info',
+ 'summary-updateinfo' : 'summary'}
+
+ # Note that this code (instead of using inheritance and multiple
+ # cmd classes) means that "yum help" only displays the updateinfo command.
+ # Which is what we want, because the other commands are just backwards
+ # compatible gunk we don't want the user using).
+ def getNames(self):
+ return ['updateinfo'] + sorted(self.direct_cmds.keys())
+
+ def getUsage(self):
+ return "[info|list|...] [security|...] [installed|available|all] [pkgs|id]"
+
+ def getSummary(self):
+ return "Acts on repository update information"
+
+ def doCheck(self, base, basecmd, extcmds):
+ pass
+
+ def list_show_pkgs(self, base, md_info, list_type, show_type,
+ iname2tup, data, msg):
+ n_maxsize = 0
+ r_maxsize = 0
+ t_maxsize = 0
+ for (notice, pkgtup, pkg) in data:
+ n_maxsize = max(len(notice['update_id']), n_maxsize)
+ tn = notice['type']
+ if tn == 'security' and notice['severity']:
+ tn = notice['severity'] + '/Sec.'
+ t_maxsize = max(len(tn), t_maxsize)
+ if show_type:
+ for ref in _upi._ysp_safe_refs(notice['references']):
+ if ref['type'] != show_type:
+ continue
+ r_maxsize = max(len(str(ref['id'])), r_maxsize)
+
+ for (notice, pkgtup, pkg) in data:
+ mark = ''
+ if list_type == 'all':
+ mark = ' '
+ if _upi._rpm_tup_vercmp(iname2tup[pkgtup[0]], pkgtup) >= 0:
+ mark = 'i '
+ tn = notice['type']
+ if tn == 'security' and notice['severity']:
+ tn = notice['severity'] + '/Sec.'
+
+ if show_type and _upi._ysp_has_info_md(show_type, notice):
+ for ref in _upi._ysp_safe_refs(notice['references']):
+ if ref['type'] != show_type:
+ continue
+ msg("%s %-*s %-*s %s" % (mark, r_maxsize, str(ref['id']),
+ t_maxsize, tn, pkg))
+ elif hasattr(pkg, 'name'):
+ print base.fmtKeyValFill("%s: " % pkg.name,
+ base._enc(pkg.summary))
+ else:
+ msg("%s%-*s %-*s %s" % (mark, n_maxsize, notice['update_id'],
+ t_maxsize, tn, pkg))
+
+ def info_show_pkgs(self, base, md_info, list_type, show_type,
+ iname2tup, data, msg):
+ show_pkg_info_done = {}
+ for (notice, pkgtup, pkg) in data:
+ if notice['update_id'] in show_pkg_info_done:
+ continue
+ show_pkg_info_done[notice['update_id']] = notice
+
+ if hasattr(notice, 'text'):
+ debug_log_lvl = yum.logginglevels.DEBUG_3
+ vlog = base.verbose_logger
+ if vlog.isEnabledFor(debug_log_lvl):
+ obj = notice.text(skip_data=[])
+ else:
+ obj = notice.text()
+ else:
+ # Python-2.4.* doesn't understand str(x) returning unicode
+ obj = notice.__str__()
+
+ if list_type == 'all':
+ if _upi._rpm_tup_vercmp(iname2tup[pkgtup[0]], pkgtup) >= 0:
+ obj = obj + "\n Installed : true"
+ else:
+ obj = obj + "\n Installed : false"
+ msg(obj)
+
+ def summary_show_pkgs(self, base, md_info, list_type, show_type,
+ iname2tup, data, msg):
+ def _msg(x):
+ base.verbose_logger.info("%s", x)
+ counts = {}
+ sev_counts = {}
+ show_pkg_info_done = {}
+ for (notice, pkgtup, pkg) in data:
+ if notice['update_id'] in show_pkg_info_done:
+ continue
+ show_pkg_info_done[notice['update_id']] = notice
+ counts[notice['type']] = counts.get(notice['type'], 0) + 1
+ if notice['type'] == 'security':
+ sev = notice['severity']
+ if sev is None:
+ sev = ''
+ sev_counts[sev] = sev_counts.get(sev, 0) + 1
+
+ maxsize = 0
+ for T in ('newpackage', 'security', 'bugfix', 'enhancement'):
+ if T not in counts:
+ continue
+ size = len(str(counts[T]))
+ if maxsize < size:
+ maxsize = size
+ if not maxsize:
+ _upi._check_running_kernel(base, md_info, _msg)
+ return
+
+ outT = {'newpackage' : 'New Package',
+ 'security' : 'Security',
+ 'bugfix' : 'Bugfix',
+ 'enhancement' : 'Enhancement'}
+ print "Updates Information Summary:", list_type
+ for T in ('newpackage', 'security', 'bugfix', 'enhancement'):
+ if T not in counts:
+ continue
+ n = outT[T]
+ if T == 'security' and len(sev_counts) == 1:
+ sn = sev_counts.keys()[0]
+ if sn != '':
+ n = sn + " " + n
+ print " %*u %s notice(s)" % (maxsize, counts[T], n)
+ if T == 'security' and len(sev_counts) != 1:
+ def _sev_sort_key(key):
+ # We want these in order, from "highest" to "lowest".
+ # Anything unknown is "higher". meh.
+ return {'Critical' : "zz1",
+ 'Important': "zz2",
+ 'Moderate' : "zz3",
+ 'Low' : "zz4",
+ }.get(key, key)
+
+ for sn in sorted(sev_counts, key=_sev_sort_key):
+ args = (maxsize, sev_counts[sn],sn or '?', outT['security'])
+ print " %*u %s %s notice(s)" % args
+ _upi._check_running_kernel(base, md_info, _msg)
+ self.show_pkg_info_done = {}
+
+ def _get_new_pkgs(self, md_info):
+ for notice in md_info.notices:
+ if notice['type'] != "newpackage":
+ continue
+ for upkg in notice['pkglist']:
+ for pkg in upkg['packages']:
+ pkgtup = (pkg['name'], pkg['arch'], pkg['epoch'] or '0',
+ pkg['version'], pkg['release'])
+ yield (notice, pkgtup)
+
+ _cmd2filt = {"bugzillas" : "bugzilla",
+ "bugzilla" : "bugzilla",
+ "bzs" : "bugzilla",
+ "bz" : "bugzilla",
+
+ "sec" : "security",
+
+ "cves" : "cve",
+ "cve" : "cve",
+
+ "newpackages" : "newpackage",
+ "new-packages" : "newpackage",
+ "newpackage" : "newpackage",
+ "new-package" : "newpackage",
+ "new" : "newpackage"}
+ for filt_type in _upi._update_info_types_:
+ _cmd2filt[filt_type] = filt_type
+
+ def doCommand(self, base, basecmd, extcmds):
+ if basecmd in self.direct_cmds:
+ subcommand = self.direct_cmds[basecmd]
+ elif extcmds and extcmds[0] in ('list', 'info', 'summary',
+ 'remove-pkgs-ts', 'exclude-updates',
+ 'exclude-all',
+ 'check-running-kernel'):
+ subcommand = extcmds[0]
+ extcmds = extcmds[1:]
+ elif extcmds and extcmds[0] in self._cmd2filt:
+ subcommand = 'list'
+ elif extcmds:
+ subcommand = 'info'
+ else:
+ subcommand = 'summary'
+
+ if subcommand == 'list':
+ return self.doCommand_li(base, 'updateinfo list', extcmds,
+ self.list_show_pkgs)
+ if subcommand == 'info':
+ return self.doCommand_li(base, 'updateinfo info', extcmds,
+ self.info_show_pkgs)
+
+ if subcommand == 'summary':
+ return self.doCommand_li(base, 'updateinfo summary', extcmds,
+ self.summary_show_pkgs)
+
+ if subcommand == 'remove-pkgs-ts':
+ filters = None
+ if extcmds:
+ filters = updateinfo._args2filters(extcmds)
+ updateinfo.remove_txmbrs(base, filters)
+ return 0, [basecmd + ' ' + subcommand + ' done']
+
+ if subcommand == 'exclude-all':
+ filters = None
+ if extcmds:
+ filters = updateinfo._args2filters(extcmds)
+ updateinfo.exclude_all(base, filters)
+ return 0, [basecmd + ' ' + subcommand + ' done']
+
+ if subcommand == 'exclude-updates':
+ filters = None
+ if extcmds:
+ filters = updateinfo._args2filters(extcmds)
+ updateinfo.exclude_updates(base, filters)
+ return 0, [basecmd + ' ' + subcommand + ' done']
+
+ if subcommand == 'check-running-kernel':
+ def _msg(x):
+ base.verbose_logger.info("%s", x)
+ updateinfo._check_running_kernel(base, base.upinfo, _msg)
+ return 0, [basecmd + ' ' + subcommand + ' done']
+
+ def doCommand_li_new(self, base, list_type, extcmds, md_info, msg,
+ show_pkgs):
+ done_pkgs = set()
+ data = []
+ for (notice, pkgtup) in sorted(self._get_new_pkgs(md_info),
+ key=lambda x: x[1][0]):
+ if extcmds and not _upi._match_sec_cmd(extcmds, pkgtup[0], notice):
+ continue
+ n = pkgtup[0]
+ if n in done_pkgs:
+ continue
+ ipkgs = list(reversed(sorted(base.rpmdb.searchNames([n]))))
+ if list_type in ('installed', 'updates') and not ipkgs:
+ done_pkgs.add(n)
+ continue
+ if list_type == 'available' and ipkgs:
+ done_pkgs.add(n)
+ continue
+
+ pkgs = base.pkgSack.searchPkgTuple(pkgtup)
+ if not pkgs:
+ continue
+ if list_type == "updates" and pkgs[0].verLE(ipkgs[0]):
+ done_pkgs.add(n)
+ continue
+ done_pkgs.add(n)
+ data.append((notice, pkgtup, pkgs[0]))
+ show_pkgs(base, md_info, list_type, None, {}, data, msg)
+
+ def _parse_extcmds(self, extcmds):
+ filt_type = None
+ show_type = None
+ if len(extcmds) >= 1:
+ filt_type = None
+
+ if extcmds[0] in self._cmd2filt:
+ filt_type = self._cmd2filt[extcmds.pop(0)]
+ show_type = filt_type
+ if filt_type and filt_type in _upi._update_info_types_:
+ show_type = None
+ return extcmds, show_type, filt_type
+
+ def doCommand_li(self, base, basecmd, extcmds, show_pkgs):
+ md_info = base.upinfo
+ def msg(x):
+ # Don't use: logger.log(logginglevels.INFO_2, x)
+ # or -q deletes everything.
+ print x
+
+ opts = _upi._updateinfofilter2opts(base.updateinfo_filters)
+ extcmds, show_type, filt_type = self._parse_extcmds(extcmds)
+
+ list_type = "available"
+ if extcmds and extcmds[0] in ("updates","available","installed", "all"):
+ list_type = extcmds.pop(0)
+
+ if filt_type == "newpackage":
+ # No filtering here, as we want what isn't installed...
+ self.doCommand_li_new(base, list_type, extcmds, md_info, msg,
+ show_pkgs)
+ return 0, [basecmd + ' new done']
+
+ opts.sec_cmds = extcmds
+ used_map = _upi._ysp_gen_used_map(base.updateinfo_filters)
+ iname2tup = {}
+ if False: pass
+ elif list_type in ('installed', 'all'):
+ name2tup = _upi._get_name2allpkgtup(base)
+ iname2tup = _upi._get_name2instpkgtup(base)
+ elif list_type == 'updates':
+ name2tup = _upi._get_name2oldpkgtup(base)
+ elif list_type == 'available':
+ name2tup = _upi._get_name2instpkgtup(base)
+
+ def _show_pkgtup(pkgtup):
+ name = pkgtup[0]
+ notices = reversed(md_info.get_applicable_notices(pkgtup))
+ for (pkgtup, notice) in notices:
+ if filt_type and not _upi._ysp_has_info_md(filt_type, notice):
+ continue
+
+ if list_type == 'installed':
+ # Remove any that are newer than what we have installed
+ if _upi._rpm_tup_vercmp(iname2tup[name], pkgtup) < 0:
+ continue
+
+ if _upi._ysp_should_filter_pkg(opts, name, notice, used_map):
+ yield (pkgtup, notice)
+
+ data = []
+ for pkgname in sorted(name2tup):
+ for (pkgtup, notice) in _show_pkgtup(name2tup[pkgname]):
+ d = {}
+ (d['n'], d['a'], d['e'], d['v'], d['r']) = pkgtup
+ if d['e'] == '0':
+ d['epoch'] = ''
+ else:
+ d['epoch'] = "%s:" % d['e']
+ data.append((notice, pkgtup,
+ "%(n)s-%(epoch)s%(v)s-%(r)s.%(a)s" % d))
+ show_pkgs(base, md_info, list_type, show_type, iname2tup, data, msg)
+
+ _upi._ysp_chk_used_map(used_map, msg)
+
+ return 0, [basecmd + ' done']
+
+
+class UpdateMinimalCommand(YumCommand):
+ def getNames(self):
+ return ['update-minimal', 'upgrade-minimal']
+
+ def getUsage(self):
+ return "[PACKAGE-wildcard]"
+
+ def getSummary(self):
+ return _("Works like upgrade, but goes to the 'newest' package match which fixes a problem that affects your system")
+
+ def doCheck(self, base, basecmd, extcmds):
+ """Verify that conditions are met so that this command can run.
+ These include that the program is being run by the root user,
+ that there are enabled repositories with gpg keys, and that
+ this command is called with appropriate arguments.
+
+ :param base: a :class:`yum.Yumbase` object
+ :param basecmd: the name of the command
+ :param extcmds: the command line arguments passed to *basecmd*
+ """
+ checkRootUID(base)
+ checkGPGKey(base)
+
+ def doCommand(self, base, basecmd, extcmds):
+ """Execute this command.
+
+ :param base: a :class:`yum.Yumbase` object
+ :param basecmd: the name of the command
+ :param extcmds: the command line arguments passed to *basecmd*
+ :return: (exit_code, [ errors ])
+
+ exit_code is::
+
+ 0 = we're done, exit
+ 1 = we've errored, exit with error string
+ 2 = we've got work yet to do, onto the next stage
+ """
+
+ num = len(base.tsInfo)
+ _upi.update_minimal(base, extcmds)
+ num -= len(base.tsInfo)
+
+ if num > 0:
+ msg = '%d packages marked for minimal Update' % num
+ return 2, [msg]
+ else:
+ return 0, ['No Packages marked for minimal Update']
commit 286ab16df34d50aa814301b81d23977eadcc2840
Author: James Antill <james at and.org>
Date: Thu Apr 18 17:03:34 2013 -0400
Add updateinfo helper functions from plugin.
diff --git a/yum/updateinfo.py b/yum/updateinfo.py
new file mode 100644
index 0000000..7d37a76
--- /dev/null
+++ b/yum/updateinfo.py
@@ -0,0 +1,515 @@
+
+import os.path
+
+from yum.i18n import _, P_
+
+from yum.constants import *
+
+from yum.logginglevels import INFO_1
+
+import rpmUtils.miscutils
+
+import misc
+
+import fnmatch
+
+# newpackages is weird, in that we'll never display that because we filter to
+# things relevant to installed pkgs...
+_update_info_types_ = ("security", "bugfix", "enhancement",
+ "recommended", "newpackage")
+
+def _rpm_tup_vercmp(tup1, tup2):
+ """ Compare two "std." tuples, (n, a, e, v, r). """
+ return rpmUtils.miscutils.compareEVR((tup1[2], tup1[3], tup1[4]),
+ (tup2[2], tup2[3], tup2[4]))
+
+
+def _ysp_safe_refs(refs):
+ """ Sometimes refs == None, if so return the empty list here.
+ So we don't have to check everywhere. """
+ if not refs:
+ return []
+ return refs
+
+def _match_sec_cmd(sec_cmds, pkgname, notice):
+ for i in sec_cmds:
+ if fnmatch.fnmatch(pkgname, i):
+ return i
+ if notice['update_id'] == i:
+ return i
+ return None
+
+def _has_id(used_map, refs, ref_type, ref_ids):
+ ''' Check if the given ID is a match. '''
+ for ref in _ysp_safe_refs(refs):
+ if ref['type'] != ref_type:
+ continue
+ if ref['id'] not in ref_ids:
+ continue
+ used_map[ref_type][ref['id']] = True
+ return ref
+ return None
+
+def _ysp_should_filter_pkg(opts, pkgname, notice, used_map):
+ """ Do the package filtering for should_show and should_keep. """
+
+ rcmd = _match_sec_cmd(opts.sec_cmds, pkgname, notice)
+ if rcmd:
+ used_map['cmd'][rcmd] = True
+ return True
+ elif opts.advisory and notice['update_id'] in opts.advisory:
+ used_map['id'][notice['update_id']] = True
+ return True
+ elif (opts.severity and notice['type'] == 'security' and
+ notice['severity'] in opts.severity):
+ used_map['sev'][notice['severity']] = True
+ return True
+ elif opts.cve and _has_id(used_map, notice['references'], "cve", opts.cve):
+ return True
+ elif opts.bz and _has_id(used_map, notice['references'],"bugzilla",opts.bz):
+ return True
+ # FIXME: Add opts for enhancement/etc.? -- __update_info_types__
+ elif (opts.security and notice['type'] == 'security' and
+ (not opts.severity or 'severity' not in notice or
+ not notice['severity'])):
+ return True
+ elif opts.bugfixes and notice['type'] == 'bugfix':
+ return True
+ elif not (opts.advisory or opts.cve or opts.bz or
+ opts.security or opts.bugfixes or opts.sec_cmds or opts.severity):
+ return True # This is only possible from should_show_pkg
+
+ return False
+
+def _ysp_has_info_md(rname, md):
+ if rname in _update_info_types_:
+ if md['type'] == rname:
+ return md
+ for ref in _ysp_safe_refs(md['references']):
+ if ref['type'] != rname:
+ continue
+ return md
+
+def _no_options(opts):
+ return not (opts.security or opts.bugfixes or
+ opts.advisory or opts.bz or opts.cve or opts.severity)
+
+def _updateinfofilter2opts(updateinfo_filters):
+ opts = misc.GenericHolder()
+ opts.sec_cmds = []
+
+ opts.advisory = updateinfo_filters.get('advs', [])
+ opts.bz = updateinfo_filters.get('bzs', [])
+ opts.cve = updateinfo_filters.get('cves', [])
+ opts.severity = updateinfo_filters.get('sevs', [])
+
+ opts.bugfixes = updateinfo_filters.get('bugfix', False)
+ opts.security = updateinfo_filters.get('security', False)
+
+ return opts
+
+def _args2filters(args):
+ # Basically allow args to turn into security filters, for shell command etc.
+
+ T_map = {'advs' : 'advs',
+ 'advisory' : 'advs',
+ 'advisories' : 'advs',
+
+ 'bzs' : 'bzs',
+ 'bz' : 'bzs',
+
+ 'cves' : 'cves',
+ 'cve' : 'cves',
+
+ 'security-severity' : 'sevs',
+ 'security-severities' : 'sevs',
+ 'severity' : 'sevs',
+ 'severities' : 'sevs',
+ 'sevs' : 'sevs',
+ 'sev' : 'sevs',
+
+ 'security' : 'security',
+ 'sec' : 'security',
+
+ 'bugfix' : 'bugfix',
+ 'bugfixes' : 'bugfix',
+ 'bugs' : 'bugfix',
+
+ }
+
+ filters = {'security' : False, 'bugfix' : False}
+
+ for arg0 in args:
+ arg0 = arg0.replace(" ", ',')
+ T = 'advs'
+ if '=' in arg0:
+ T, arg1 = arg0.split('=', 1)
+ elif arg0 not in T_map:
+ arg1 = arg0
+ else:
+ T = arg0
+ arg1 = 'true'
+
+ if T not in T_map:
+ continue # Error message?
+
+ T = T_map[T]
+
+ if T in ('security', 'bugfix'):
+ filters[T] = not filters[T]
+ else:
+ filters[T] = filters.get(T, []) + arg1.split(',')
+ return filters
+
+def _ysp_gen_used_map(opts):
+ used_map = {'bugzilla' : {}, 'cve' : {}, 'id' : {}, 'cmd' : {}, 'sev' : {}}
+ if True:
+ return used_map
+ for i in opts.sec_cmds:
+ used_map['cmd'][i] = False
+ for i in opts.advisory:
+ used_map['id'][i] = False
+ for i in opts.bz:
+ used_map['bugzilla'][i] = False
+ for i in opts.cve:
+ used_map['cve'][i] = False
+ for i in opts.severity:
+ used_map['sev'][i] = False
+ return used_map
+
+def _ysp_chk_used_map(used_map, msg):
+ for i in used_map['cmd']:
+ if not used_map['cmd'][i]:
+ msg('No update information found for \"%s\"' % i)
+ for i in used_map['id']:
+ if not used_map['id'][i]:
+ msg('Advisory \"%s\" not found applicable for this system' % i)
+ for i in used_map['bugzilla']:
+ if not used_map['bugzilla'][i]:
+ msg('BZ \"%s\" not found applicable for this system' % i)
+ for i in used_map['cve']:
+ if not used_map['cve'][i]:
+ msg('CVE \"%s\" not found applicable for this system' % i)
+ for i in used_map['sev']:
+ if not used_map['sev'][i]:
+ msg('Severity \"%s\" not found applicable for this system' % i)
+
+
+def _get_name2pkgtup(base, pkgtups):
+ name2tup = {}
+ for pkgtup in pkgtups:
+ # Get the latest "old" pkgtups
+ if (pkgtup[0] in name2tup and
+ _rpm_tup_vercmp(name2tup[pkgtup[0]], pkgtup) > 0):
+ continue
+ name2tup[pkgtup[0]] = pkgtup
+ return name2tup
+def _get_name2oldpkgtup(base):
+ """ Get the pkgtups for all installed pkgs. which have an update. """
+ oupdates = map(lambda x: x[1], base.up.getUpdatesTuples())
+ return _get_name2pkgtup(base, oupdates)
+def _get_name2instpkgtup(base):
+ """ Get the pkgtups for all installed pkgs. """
+ return _get_name2pkgtup(base, base.rpmdb.simplePkgList())
+def _get_name2allpkgtup(base):
+ """ Get the pkgtups for all installed pkgs. and munge that to be the
+ first possible pkgtup. """
+ ofirst = [(pt[0], pt[1], '0','0','0') for pt in base.rpmdb.simplePkgList()]
+ return _get_name2pkgtup(base, ofirst)
+def _get_name2aallpkgtup(base):
+ """ Get the pkgtups for all available pkgs. and munge that to be the
+ first possible pkgtup. """
+ ofirst = [(pt[0], pt[1],'0','0','0') for pt in base.pkgSack.simplePkgList()]
+ return _get_name2pkgtup(base, ofirst)
+
+
+# You might think we'd just call delPackage
+# and indeed that works for list updates etc.
+#
+# __but__ that doesn't work for dependancies on real updates
+#
+# So to fix deps. we need to do it at the preresolve stage and take the
+# "transaction package list" and then remove packages from that.
+#
+# __but__ that doesn't work for lists ... so we do it two ways
+#
+def _ysp_should_keep_pkg(opts, pkgtup, md_info, used_map):
+ """ Do we want to keep this package to satisfy the security limits. """
+ name = pkgtup[0]
+ for (pkgtup, notice) in md_info.get_applicable_notices(pkgtup):
+ if _ysp_should_filter_pkg(opts, name, notice, used_map):
+ return True
+ return False
+
+def _repos_downloaded(repos):
+ dled = True
+ for repo in repos:
+ try:
+ data = repo.repoXML.getData('updateinfo');
+ except:
+ continue # No data is fine...
+
+ # Note that this doesn't check that it's decompressed...
+ path = repo.cachedir +'/'+ os.path.basename(data.location[1])
+ if not os.path.exists(path):
+ dled = False
+ break
+
+ return dled
+
+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 remove_txmbrs(base, filters=None):
+ '''
+ Remove packages from the transaction, using the updateinfo data.
+ '''
+ md_info = base.upinfo
+
+ 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
+
+ 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 exclude_updates(base, filters=None):
+ '''
+ Exclude all packages to do with updates, using the updateinfo data.
+ '''
+
+ md_info = base.upinfo
+
+ 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
+
+ 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_all(base, filters=None):
+ '''
+ Exclude all packages, using the updateinfo data.
+ '''
+
+ md_info = base.upinfo
+
+ 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
+
+ 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 update_minimal(base, extcmds=[]):
+ """Mark the specified items to be updated, in the minimal way.
+ :param extcmds: the user specified arguments
+ :return: a list of transaction members added to the
+ transaction set by this function
+ """
+ txmbrs = []
+
+ used_map = _ysp_gen_used_map(base.updateinfo_filters)
+ opts = _updateinfofilter2opts(base.updateinfo_filters)
+ ndata = _no_options(opts)
+
+ # NOTE: Not doing obsoletes processing atm. ... maybe we should? --
+ # Also worth pointing out we don't go backwards for obsoletes in the:
+ # update --security case etc.
+
+ # obsoletes = base.up.getObsoletesTuples(newest=False)
+ # for (obsoleting, installed) in sorted(obsoletes, key=lambda x: x[0]):
+ # pass
+
+ # Tuples == (n, a, e, v, r)
+ oupdates = map(lambda x: x[1], base.up.getUpdatesTuples())
+ for oldpkgtup in sorted(oupdates):
+ data = base.upinfo.get_applicable_notices(oldpkgtup)
+ if ndata: # No options means pick the oldest update
+ data.reverse()
+
+ for (pkgtup, notice) in data:
+ name = pkgtup[0]
+ if extcmds and not _match_sec_cmd(extcmds, name, notice):
+ continue
+ if (not ndata and
+ not _ysp_should_filter_pkg(base, name, notice, used_map)):
+ continue
+ txmbrs.extend(base.update(name=pkgtup[0], arch=pkgtup[1],
+ epoch=pkgtup[2],
+ version=pkgtup[3], release=pkgtup[4]))
+ break
+
+ # _ysp_chk_used_map(used_map, msg)
+
+ return txmbrs
+
commit 61a84a1b187287ebbb8a4050b6f20a3b3d2bcf48
Author: James Antill <james at and.org>
Date: Thu Apr 18 17:02:39 2013 -0400
Add .upinfo property to Base.
diff --git a/yum/__init__.py b/yum/__init__.py
index d1ab41a..766f960 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -80,6 +80,7 @@ import yumRepo
import callbacks
import yum.history
import yum.igroups
+import update_md
import warnings
warnings.simplefilter("ignore", Errors.YumFutureDeprecationWarning)
@@ -194,6 +195,7 @@ class YumBase(depsolve.Depsolve):
self._pkgSack = None
self._lockfile = None
self._tags = None
+ self._upinfo = None
self._ts_save_file = None
self.skipped_packages = [] # packages skip by the skip-broken code
self._not_found_a = {}
@@ -220,6 +222,8 @@ class YumBase(depsolve.Depsolve):
self._cleanup = []
self.exit_code = 0
+ self.updateinfo_filters = {}
+
def __del__(self):
self.close()
self.closeRpmDB()
@@ -971,6 +975,35 @@ class YumBase(depsolve.Depsolve):
self.verbose_logger.debug('tags time: %0.3f' % (time.time() - tag_st))
return self._tags
+
+ def _getUpdateinfo(self):
+ """ create the Update Info object used to search/report the updateinfo
+ metadata"""
+
+ upi_st = time.time()
+ self.verbose_logger.log(logginglevels.DEBUG_4,
+ _('Getting updateinfo metadata'))
+
+ if self._upinfo is None:
+ self._upinfo = update_md.UpdateMetadata()
+
+ for repo in self.repos.listEnabled():
+ if 'updateinfo' not in repo.repoXML.fileTypes():
+ continue
+
+ self.verbose_logger.log(logginglevels.DEBUG_4,
+ _('Adding Update Info from repository: %s'), repo)
+
+ try:
+ self._upinfo.add(repo)
+ except Errors.RepoMDError, e:
+ msg = _('Failed to add Update Info for repository: %s - %s') % (repo, exception2msg(e))
+ self.logger.critical(msg)
+
+ self.verbose_logger.debug('updateinfo time: %0.3f' %
+ (time.time() - upi_st))
+ return self._upinfo
+
def _getHistory(self):
"""auto create the history object that to access/append the transaction
history information. """
@@ -1035,6 +1068,11 @@ class YumBase(depsolve.Depsolve):
fset=lambda self, value: setattr(self, "_tags",value),
fdel=lambda self: setattr(self, "_tags", None),
doc="Yum Package Tags Object")
+
+ upinfo = property(fget=lambda self: self._getUpdateinfo(),
+ fset=lambda self, value: setattr(self, "_upinfo", value),
+ fdel=lambda self: setattr(self, "_upinfo", None),
+ doc="Yum Update Info Object")
def doSackFilelistPopulate(self):
commit 1f613b7b3268aa083377ad54a5374cec31c45741
Author: Orion Poplawski <orion at nwra.com>
Date: Wed Apr 17 10:35:38 2013 -0600
yum-cron does not use -C to specify config file
diff --git a/yum-cron/yum-hourly.cron.sh b/yum-cron/yum-hourly.cron.sh
index 557dd4d..f0b77a9 100755
--- a/yum-cron/yum-hourly.cron.sh
+++ b/yum-cron/yum-hourly.cron.sh
@@ -8,4 +8,4 @@ if [[ ! -f /var/lock/subsys/yum-cron ]]; then
fi
# Action!
-exec /usr/sbin/yum-cron -C /etc/yum/yum-cron-hourly.conf
+exec /usr/sbin/yum-cron /etc/yum/yum-cron-hourly.conf
More information about the Yum-commits
mailing list