tImplement dependency alternatives parsing. - amprolla - devuan's apt repo merger
 (HTM) git clone git://parazyd.org/amprolla.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 4268288f669be5e023be2a53477caa81a95d4244
 (DIR) parent 6b27485f8e6a1ef3bc904db5ea47e01a4051ffa6
 (HTM) Author: KatolaZ <katolaz@freaknet.org>
       Date:   Sun, 24 Jun 2018 12:39:20 +0200
       
       Implement dependency alternatives parsing.
       
       This commit adds support for parsing dependencies which contain
       alternatives, e.g. "foo | bar".
       
       Currently it is utilized for banning packages.
       
       Diffstat:
         M LICENSE                             |       2 +-
         M lib/package.py                      |      39 +++++++++++++++++++++++++------
         M lib/parse.py                        |      41 +++++++++++++++++--------------
       
       3 files changed, 56 insertions(+), 26 deletions(-)
       ---
 (DIR) diff --git a/LICENSE b/LICENSE
       t@@ -1,6 +1,6 @@
        Copyright (c) 2017 Merlijn Wajer <merlijn@wizzup.org>
        Copyright (c) 2017 Evilham <devuan@evilham.com>
       -Copyright (c) 2017 KatolaZ <katolaz@freaknet.org>
       +Copyright (c) 2017-2018 KatolaZ <katolaz@freaknet.org>
        Copyright (c) 2017-2018 Ivan J. <parazyd@dyne.org>
        
                            GNU AFFERO GENERAL PUBLIC LICENSE
 (DIR) diff --git a/lib/package.py b/lib/package.py
       t@@ -75,6 +75,33 @@ def load_packages_file(filename):
            return None
        
        
       +def depends_on_all_banned(deps, banned_pkgs):
       +    """
       +    Gets a list of dicts of dep alternatives and a set of banned packages and
       +    returns True if any of the dicts consist exclusively of banned_pkgs.
       +    """
       +    for dep in deps:
       +        alt = set(dep.keys())
       +        if len(alt.intersection(banned_pkgs)) == len(alt):
       +            # All the alternatives are banned
       +            return True
       +    return False
       +
       +
       +def depends_on(deps, package_set):
       +    """
       +    Gets a list of dicts of dep alternatives and a set of packages and returns
       +    True if any of the dicts include at least one of the elements in
       +    package_set.
       +    """
       +    for dep in deps:
       +        alt = set(dep.keys())
       +        if alt.intersection(package_set):
       +            # At least one alternative is in package_set
       +            return True
       +    return False
       +
       +
        def package_banned(pkg, banned_pkgs):
            """
            Returns True is the package contains a banned dependency.
       t@@ -89,19 +116,17 @@ def package_banned(pkg, banned_pkgs):
            depends = parse_dependencies(pkg.get('Depends', ''))
            pre_depends = parse_dependencies(pkg.get('Pre-Depends', ''))
        
       -    depends = [v for v in depends]
       -    pre_depends = [v for v in pre_depends]
       -
       -    deps = set(depends).union(set(pre_depends))
       +    depends.extend(pre_depends)
        
       -    if 'libsystemd0' in deps:
       +    if depends_on(depends, set(['libsystemd0'])):
                logtofile('libsystemd.txt', '%s,%s\n' % (globalvars.suite,
                                                         pkg.get('Package')))
        
       -    if bool(deps.intersection(banned_pkgs)):
       +    isbanned = depends_on_all_banned(depends, banned_pkgs)
       +    if isbanned:
                logtofile('bannedpackages.txt', '%s,%s\n' % (globalvars.suite,
                                                             pkg.get('Package')))
       -    return bool(deps.intersection(banned_pkgs))
       +    return isbanned
        
        
        def package_newer(pkg1, pkg2):
 (DIR) diff --git a/lib/parse.py b/lib/parse.py
       t@@ -127,28 +127,33 @@ def parse_dependencies(dependencies):
        
            Example line::
        
       -        'lib6 (>= 2.4), libdbus-1-3 (>= 1.0.2), foo'
       +        'lib6 (>= 2.4), libdbus-1-3 (>= 1.0.2), foo | bar (>= 4.5.6)'
        
            Output::
        
       -        {'lib6': '(>= 2.4)', 'libdbus-1-3': '(>= 1.0.2)', 'foo': None}
       -    """
       -    ret = {}
       -
       -    for pkg_plus_version in dependencies.split(', '):
       -        ver = pkg_plus_version.split(' ', 1)
       -        name = ver[0]
       -
       -        # If we get passed an empty string, the name is '', and we just
       -        # outright stop
       -        if not name:
       -            return {}
       +        A list of dep alternatives, whose elements are dicts, in the form:
        
       -        if len(ver) == 2:
       -            version = ver[1]
       -            ret[name] = version
       -        else:
       -            ret[name] = None
       +        [{'lib6': '(>= 2.4)'}, {'libdbus-1-3': '(>= 1.0.2)'},
       +         {'foo': None, 'bar': '(>= 4.5.6)'}]
       +    """
       +    ret = []
       +
       +    for alternatives in dependencies.split(', '):
       +        depset = {}
       +        for pkg_plus_version in alternatives.split('|'):
       +            ver = pkg_plus_version.strip(' ').split(' ', 1)
       +            name = ver[0]
       +
       +            # If we get passed an empty string, the name is '', and we just
       +            # outright stop.
       +            if not name:
       +                return []
       +            if len(ver) == 2:
       +                version = ver[1]
       +                depset[name] = version
       +            else:
       +                depset[name] = None
       +        ret.append(depset)
        
            return ret