[yum-git] 2 commits - plugins/filter-data plugins/security yum-utils.spec

James Antill james at linux.duke.edu
Fri Feb 1 21:25:56 UTC 2008


 plugins/filter-data/filter-data.conf |    2 
 plugins/filter-data/filter-data.py   |  393 +++++++++++++++++++++++++++++++++++
 plugins/security/security.py         |    2 
 yum-utils.spec                       |   27 ++
 4 files changed, 420 insertions(+), 4 deletions(-)

New commits:
commit af1e791560078899b286d32604b2c85c96869acb
Author: James Antill <james at and.org>
Date:   Fri Feb 1 16:25:52 2008 -0500

    Add upgrade as a valid command to security

diff --git a/plugins/security/security.py b/plugins/security/security.py
index b7e02cb..fbf4852 100755
--- a/plugins/security/security.py
+++ b/plugins/security/security.py
@@ -336,7 +336,7 @@ def ysp_check_func_enter(conduit):
     if len(args):
         if (args[0] == "check-update"):
             ret = {"skip": ndata, "list_cmd": True}
-        if (args[0] == "update"):
+        if (args[0] in ["update", "upgrade"]):
             ret = {"skip": ndata, "list_cmd": False}
         if (args[0] == "list-sec") or (args[0] == "list-security"):
             return (opts, {"skip": True, "list_cmd": True})
commit 492ce8cd8b31df7ff66274263d86b50794ab0944
Author: James Antill <james at and.org>
Date:   Fri Feb 1 16:25:38 2008 -0500

     The compliment to the list-data plugin, allows you to filter packages based
    on arbitrary package data.

diff --git a/plugins/filter-data/filter-data.conf b/plugins/filter-data/filter-data.conf
new file mode 100644
index 0000000..8e4d76c
--- /dev/null
+++ b/plugins/filter-data/filter-data.conf
@@ -0,0 +1,2 @@
+[main]
+enabled=1
diff --git a/plugins/filter-data/filter-data.py b/plugins/filter-data/filter-data.py
new file mode 100644
index 0000000..a18e1e5
--- /dev/null
+++ b/plugins/filter-data/filter-data.py
@@ -0,0 +1,393 @@
+#! /usr/bin/python -tt
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#
+# Copyright Red Hat Inc. 2007, 2008
+#
+# Author: James Antill <james.antill at redhat.com>
+#
+#  This is the compliment to the list-data plugin, allowing you to filter on
+# any of the information given in that plugin.
+#
+# Examples:
+#
+#  yum --filter-groups='App*/Sys*' list updates
+
+import yum
+from yum.plugins import TYPE_INTERACTIVE
+
+import fnmatch
+
+# For baseurl
+import urlparse
+
+
+requires_api_version = '2.5'
+plugin_type = (TYPE_INTERACTIVE,)
+
+
+fd__unknown = lambda x: x
+fd__max     = 9999999999999
+def fd__get_data(pkg, attr, strip=True):
+    if not hasattr(pkg, attr):
+        return fd__unknown
+
+    val = getattr(pkg, attr)
+    if val is None:
+        return fd__unknown
+    if type(val) == type([]):
+        return fd__unknown
+
+    tval = str(val).strip()
+    if tval == "":
+        return fd__unknown
+
+    if strip:
+        return tval
+
+    return val
+
+def range_match(sz, rang):
+    return sz >= rang[0] and sz <= rang[1]
+
+def fd_should_filter_pkg(opts, pkg, used_map):
+    """ Do the package filtering for. """
+
+    for (attrs, attr) in [('vendors', 'vendor'),
+                          ('groups', 'group'),
+                          ('packagers', 'packager'),
+                          ('licenses', 'license'),
+                          ('arches', 'arch'),
+                          ('committers', 'committer'),
+                          ('buildhosts', 'buildhost'),
+                          ('urls', 'url')]:
+        pats = getattr(opts, 'filter_' + attrs)
+        done = len(pats)
+        for pat in pats:
+            data = fd__get_data(pkg, attr)
+            if data == fd__unknown or fnmatch.fnmatch(data, pat):
+                used_map[attrs][pat] = True
+                done = False
+                break
+        if done:
+            return (attrs, attr)
+
+    for (attrs, attr) in [('package-sizes', 'packagesize'),
+                          ('archive-sizes', 'archivesize'),
+                          ('installed-sizes', 'installedsize')]:
+        rangs = getattr(opts, 'filter_' + attrs.replace('-', '_'))
+        done = len(rangs)
+        for rang in rangs:
+            data = fd__get_data(pkg, attr, strip=False)
+            if data == fd__unknown or range_match(data, rang):
+                used_map[attrs][rang] = True
+                done = False
+                break
+        if done:
+            return (attrs, attr)
+
+    return None
+
+def fd_gen_used_map(opts):
+    used_map = {}
+    for (attrs, attr) in [('vendors', 'vendor'),
+                          ('groups', 'group'),
+                          ('packagers', 'packager'),
+                          ('licenses', 'license'),
+                          ('arches', 'arch'),
+                          ('committers', 'committer'),
+                          ('buildhosts', 'buildhost'),
+                          ('urls', 'url'),
+                          ('package-sizes', 'packagesize'),
+                          ('archive-sizes', 'archivesize'),
+                          ('installed-sizes', 'installedsize')]:
+        used_map[attrs] = {}
+        vattrs = attrs.replace('-', '_')
+        for i in getattr(opts, 'filter_' + vattrs):
+            used_map[attrs][i] = False
+
+    return used_map
+
+def fd_chk_used_map(used_map, msg):
+    for (attrs, attr) in [('vendors', 'vendor'),
+                          ('groups', 'group'),
+                          ('packagers', 'packager'),
+                          ('licenses', 'license'),
+                          ('arches', 'arch'),
+                          ('committers', 'committer'),
+                          ('buildhosts', 'buildhost'),
+                          ('urls', 'url')]:
+        for i in used_map[attrs]:
+            if not used_map[attrs][i]:
+                msg(attr.capitalize() +
+                    ' wildcard \"%s\" did not match any packages' % i)
+
+    for (attrs, attr) in [('package-sizes', 'packagesize'),
+                          ('archive-sizes', 'archivesize'),
+                          ('installed-sizes', 'installedsize')]:
+        for i in used_map[attrs]:
+            if not used_map[attrs][i]:
+                if i[1] == fd__max:
+                    msg(attrs[:-1].capitalize() +
+                        ' range \"%d-\" did not match any packages' % i[0])
+                else:
+                    msg(attrs[:-1].capitalize() +
+                        ' range \"%d-%d\" did not match any packages' % i)
+        
+#  You might think we'd just use the exclude_hook, and 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 fd_check_func_enter(conduit):
+    """ Stuff we need to do in both list and update modes. """
+    
+    opts, args = conduit.getCmdLine()
+
+    # Quick match, so we don't do lots of work when nothing has been specified
+    ndata = True
+    for (attrs, attr) in [('vendors', 'vendor'),
+                          ('groups', 'group'),
+                          ('packagers', 'packager'),
+                          ('licenses', 'license'),
+                          ('arches', 'arch'),
+                          ('committers', 'committer'),
+                          ('buildhosts', 'buildhost'),
+                          ('urls', 'url'),
+                          ('package-sizes', 'packagesize'),
+                          ('archive-sizes', 'archivesize'),
+                          ('installed-sizes', 'installedsize')]:
+        vattrs = attrs.replace('-', '_')
+        if len(getattr(opts, 'filter_' + vattrs)):
+            ndata = False
+    
+    ret = None
+    if len(args) >= 1:
+        if (args[0] in ["update", "upgrade", "install"]):
+            ret = {"skip": ndata, "list_cmd": False}
+        if (args[0] in ["check-update"]): # Pretend it's: list updates
+            ret = {"skip": ndata, "list_cmd": True,
+                   "ret_pkg_lists": ["updates"] + args[1:]}
+
+    # FIXME: delPackage() only works for updates atm.
+    valid_list_cmds = ["list", "info"]
+    for cmd in ["vendors", 'groups', 'packagers', 'licenses', 'arches',
+                'committers', 'buildhosts', 'baseurls', 'package-sizes',
+                'archive-sizes', 'installed-sizes', 'security', 'sec']:
+        valid_list_cmds.append("list-" + cmd)
+        valid_list_cmds.append("info-" + cmd)
+
+    if (len(args) >= 2 and args[0] in valid_list_cmds and args[1] == "updates"):
+        ret = {"skip": ndata, "list_cmd": True, "ret_pkg_lists": args[1:]}
+
+    if ret:
+        if ndata:
+            conduit.info(2, 'Skipping filters plugin, no data')
+        return (opts, ret)
+    
+    if not ndata:
+        conduit.error(2, 'Skipping filters plugin, other command')
+    return (opts, {"skip": True, "list_cmd": False, "msg": True})
+
+
+_in_plugin = False
+def exclude_hook(conduit):
+    '''
+    Yum Plugin Exclude Hook:
+    Check and remove packages that don\'t align with the filters.
+    '''
+
+    global _in_plugin
+    
+    opts, info = fd_check_func_enter(conduit)
+    if info["skip"]:
+        return
+
+    if not info["list_cmd"]:
+        return
+
+    if _in_plugin:
+        return
+    
+    _in_plugin = True
+    conduit.info(2, 'Limiting package lists to filtered ones')
+    
+    def fd_del_pkg(pkg, which):
+        """ Deletes a package from all trees that yum knows about """
+        conduit.info(3," --> %s from %s excluded (filter: %s)" %
+                     (pkg, pkg.repoid, which[0]))
+        conduit.delPackage(pkg)
+
+    used_map = fd_gen_used_map(opts)
+
+    # NOTE: excludes/delPackage() doesn't work atm. for non-"list upgrades"
+    if not info['ret_pkg_lists']:
+        pkgs = conduit.getPackages()
+    else:
+        args = info['ret_pkg_lists']
+        special = ['updates']
+        pn = None
+        pkgs = []
+        if len(args) >= 1 and args[0] in special:
+            pn = args[0]
+            args = args[1:]
+        else:
+            pkgs = conduit.getPackages()
+
+        if not len(args):
+            args = None
+        if pn:
+            data = conduit._base.doPackageLists(pkgnarrow=pn, patterns=args)
+            pkgs.extend(data.updates)
+            del data
+            
+    tot = 0
+    cnt = 0
+    for pkg in pkgs:
+        tot += 1
+        which = fd_should_filter_pkg(opts, pkg, used_map)
+        if which:
+            fd_del_pkg(pkg, which)
+        else:
+            cnt += 1
+    fd_chk_used_map(used_map, lambda x: conduit.error(2, x))
+    if cnt:
+        conduit.info(2, 'Left with %d of %d packages, after filters applied' % (cnt, tot))
+    else:
+        conduit.info(2, 'No packages passed the filters, %d available' % tot)
+
+    _in_plugin = False
+
+def preresolve_hook(conduit):
+    '''
+    Yum Plugin PreResolve Hook:
+    Check and remove packages that don\'t align with the filters.
+    '''
+
+    opts, info = fd_check_func_enter(conduit)
+    if info["skip"]:
+        return
+
+    if info["list_cmd"]:
+        return
+    
+    conduit.info(2, 'Limiting package lists to filtered ones')
+
+    def fd_del_pkg(tspkg, which):
+        """ Deletes a package within a transaction. """
+        conduit.info(3," --> %s from %s excluded (filter: %s)" %
+                     (tspkg.po, tspkg.po.repoid, which[0]))
+        tsinfo.remove(tspkg.pkgtup)
+
+    tot = 0
+    cnt = 0
+    used_map = fd_gen_used_map(opts)
+    tsinfo = conduit.getTsInfo()
+    tspkgs = tsinfo.getMembers()
+    for tspkg in tspkgs:
+        tot += 1
+        which = fd_should_filter_pkg(opts, tspkg.po, used_map)
+        if which:
+            fd_del_pkg(tspkg, which)
+        else:
+            cnt += 1
+    fd_chk_used_map(used_map, lambda x: conduit.error(2, x))
+    
+    if cnt:
+        conduit.info(2, 'Left with %d of %d packages, after filters applied' % (cnt, tot))
+    else:
+        conduit.info(2, 'No packages passed the filters, %d available' % tot)
+
+def config_hook(conduit):
+    '''
+    Yum Plugin Config Hook: 
+    Setup the option parser with the '--filter-*' command line options.
+    '''
+
+    parser = conduit.getOptParser()
+    if not parser:
+        return
+
+    parser.values.filter_vendors         = []
+    parser.values.filter_groups          = []
+    parser.values.filter_packagers       = []
+    parser.values.filter_licenses        = []
+    parser.values.filter_arches          = []
+    parser.values.filter_committers      = []
+    parser.values.filter_buildhosts      = []
+    parser.values.filter_urls            = []
+    parser.values.filter_packages_sizes  = []
+    parser.values.filter_archive_sizes   = []
+    parser.values.filter_installed_sizes = []
+    def ogroups(opt, key, val, parser):
+        parser.values.filter_groups.extend(str(val).split(","))
+    def make_nopt(attrs):
+        def func(opt, key, val, parser):
+            vals = str(val).replace(",", " ").split()
+            getattr(parser.values, 'filter_' + attrs).extend(vals)
+        return func
+    def make_szopt(attrs):
+        attrs = attrs.replace("-", "_")
+        def func(opt, key, val, parser):
+            def sz_int(x, empty_sz):
+                if x == '':
+                    return empty_sz
+                mul = 1
+                conv = {'k' : 1024, 'm' : 1024 * 1024, 'g' : 1024 * 1024 * 1024}
+                if x[-1].lower() in conv:
+                    mul = conv[x[-1]]
+                    x = x[:-1]
+                return int(x) * mul
+            vals = str(val).replace(",", " ").split()
+            for val in vals:
+                rang = val.split("-")
+                if len(rang) > 2:
+                    msg = "%s was passed an invalid range: %s" % (attrs, val)
+                    raise OptionValueError, msg
+                if len(rang) < 2:
+                    rang = (rang[0], rang[0])
+                else:
+                    rang = (sz_int(rang[0], 0), sz_int(rang[1], fd__max))
+
+                getattr(parser.values, 'filter_' + attrs).append(rang)
+        return func
+    
+    for (attrs, attr) in [('vendors', 'vendor'),
+                          ('groups', 'group'),
+                          ('packagers', 'packager'),
+                          ('licenses', 'license'),
+                          ('arches', 'arch'),
+                          ('committers', 'committer'),
+                          ('buildhosts', 'buildhost'),
+                          ('urls', 'url')]:
+        parser.add_option('--filter-' + attrs, action="callback",
+                          callback=make_nopt(attrs), default=[], type="string",
+                          help='Filter to packages with a matching ' + attr)
+
+    for (attrs, attr) in [('package-sizes', 'packagesize'),
+                          ('archive-sizes', 'archivesize'),
+                          ('installed-sizes', 'installedsize')]:
+        parser.add_option('--filter-' + attrs, action="callback",
+                          callback=make_szopt(attrs), default=[], type="string",
+                          help='Filter to packages with a %s in the given range'
+                          % attr)
+
+if __name__ == '__main__':
+    print "This is a plugin that is supposed to run from inside YUM"
diff --git a/yum-utils.spec b/yum-utils.spec
index db79ce3..3bf8bdc 100644
--- a/yum-utils.spec
+++ b/yum-utils.spec
@@ -209,8 +209,20 @@ Group: System Environment/Base
 Requires: yum >= 3.0.5
 
 %description -n yum-list-data
-This plugin adds the commands list-vendors, groups, baseurls, packagers,
-buildhosts, licenses and arches.
+This plugin adds the commands list- vendors, groups, packagers, licenses,
+arches, committers, buildhosts, baseurls, package-sizes, archive-sizes and
+installed-sizes.
+
+%package -n yum-filter-data
+Summary: Yum plugin to list filter based on package data
+Group: System Environment/Base
+Requires: yum >= 3.0.5
+
+%description -n yum-filter-data
+This plugin adds the options --filter- vendors, groups, packagers, licenses,
+arches, committers, buildhosts, baseurls, package-sizes, archive-sizes and
+installed-sizes. Note that each package must match at least one pattern/range in
+each category, if any were specified.
 
 %package -n yum-tmprepo
 Summary: Yum plugin to add temporary repositories
@@ -234,7 +246,7 @@ make -C updateonboot DESTDIR=$RPM_BUILD_ROOT install
 # Plugins to install
 plugins="changelog fastestmirror fedorakmod protectbase versionlock tsflags kernel-module \
          downloadonly allowdowngrade skip-broken priorities refresh-updatesd merge-conf \
-         security protect-packages basearchonly upgrade-helper aliases list-data tmprepo"
+         security protect-packages basearchonly upgrade-helper aliases list-data filter-data tmprepo"
 
 mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/yum/pluginconf.d/ $RPM_BUILD_ROOT/usr/lib/yum-plugins/
 
@@ -390,6 +402,11 @@ fi
 %config(noreplace) %{_sysconfdir}/yum/pluginconf.d/list-data.conf
 /usr/lib/yum-plugins/list-data.*
 
+%files -n yum-filter-data
+%defattr(-, root, root)
+%config(noreplace) %{_sysconfdir}/yum/pluginconf.d/filter-data.conf
+/usr/lib/yum-plugins/filter-data.*
+
 %files -n yum-tmprepo
 %defattr(-, root, root)
 %config(noreplace) %{_sysconfdir}/yum/pluginconf.d/tmprepo.conf
@@ -397,8 +414,12 @@ fi
 
 
 %changelog
+* Fri Fed  1 2008 James Antill <james at fedoraproject.org>
+- Add filter-data plugin
+
 * Wed Jan 30 2008 Tim Lauridsen <timlau at fedoraproject.org>
 - mark as 1.1.11
+
 * Sun Jan 13 2008 Seth Vidal <skvidal at fedoraproject.org>
 - add repodiff
 



More information about the Yum-cvs-commits mailing list