예제 #1
0
    def restrictions(self):
        # ordering here matters; against 24702 ebuilds for
        # a non matchable atom with package as the first restriction
        # 10 loops, best of 3: 206 msec per loop
        # with category as the first(the obvious ordering)
        # 10 loops, best of 3: 209 msec per loop
        # why?  because category is more likely to collide;
        # at the time of this profiling, there were 151 categories.
        # over 11k packages however.
        r = [restricts.PackageDep(self.package), restricts.CategoryDep(self.category)]

        if self.repo_id is not None:
            r.insert(0, restricts.RepositoryDep(self.repo_id))

        if self.fullver is not None:
            if self.op == '=*':
                r.append(packages.PackageRestriction(
                    "fullver", values.StrGlobMatch(self.fullver)))
            else:
                r.append(restricts.VersionMatch(
                    self.op, self.version, self.revision, negate=self.negate_vers))

        if self.slot is not None:
            r.append(restricts.SlotDep(self.slot))
            if self.subslot is not None:
                r.append(restricts.SubSlotDep(self.subslot))

        if self.use is not None:
            r.extend(restricts._parse_nontransitive_use(self.use))

        return tuple(r)
예제 #2
0
    def generate_restrict_from_range(self, node, negate=False):
        op = str(node.get("range").strip())
        slot = str(node.get("slot", "").strip())

        try:
            restrict = self.op_translate[op.lstrip("r")]
        except KeyError:
            raise ValueError(f'unknown operator: {op!r}')
        if node.text is None:
            raise ValueError(f"{op!r} node missing version")

        base = str(node.text.strip())
        glob = base.endswith("*")
        if glob:
            base = base[:-1]
        base = cpv.VersionedCPV(f"cat/pkg-{base}")

        if glob:
            if op != "eq":
                raise ValueError(f"glob cannot be used with {op} ops")
            return packages.PackageRestriction(
                "fullver", values.StrGlobMatch(base.fullver))
        restrictions = []
        if op.startswith("r"):
            if not base.revision:
                if op == "rlt":  # rlt -r0 can never match
                    # this is a non-range.
                    raise ValueError(
                        "range %s version %s is a guaranteed empty set" %
                        (op, str(node.text.strip())))
                elif op == "rle":  # rle -r0 -> = -r0
                    return atom_restricts.VersionMatch("=",
                                                       base.version,
                                                       negate=negate)
                elif op == "rge":  # rge -r0 -> ~
                    return atom_restricts.VersionMatch("~",
                                                       base.version,
                                                       negate=negate)
            # rgt -r0 passes through to regular ~ + >
            restrictions.append(atom_restricts.VersionMatch("~", base.version))
        restrictions.append(
            atom_restricts.VersionMatch(restrict,
                                        base.version,
                                        rev=base.revision), )
        if slot:
            restrictions.append(atom_restricts.SlotDep(slot))
        return packages.AndRestriction(*restrictions, negate=negate)
예제 #3
0
def parse_match(text):
    """generate appropriate restriction for text

    Parsing basically breaks it down into chunks split by /, with each
    chunk allowing for prefix/postfix globbing- note that a postfixed
    glob on package token is treated as package attribute matching,
    not as necessarily a version match.

    If only one chunk is found, it's treated as a package chunk.
    Finally, it supports a nonstandard variation of atom syntax where
    the category can be dropped.

    Examples:

    - `*`: match all
    - `dev-*/*`: category must start with 'dev-'
    - `dev-*`: package must start with 'dev-'
    - `*-apps/portage*`: category must end in '-apps', package must start with
      'portage'
    - `>=portage-2.1`: atom syntax, package 'portage', version greater then or
      equal to '2.1'
    - dev-qt/*:5: all Qt 5 libs
    - boost:0/1.60: all packages named boost with a slot/subslot of 0/1.60.0

    :param text: string to attempt to parse
    :type text: string
    :return: :obj:`pkgcore.restrictions.packages` derivative
    """

    # Ensure the text var is a string if we're under py3k.
    if not is_py3k:
        text = text.encode('ascii')
    orig_text = text = text.strip()
    if "!" in text:
        raise ParseError(
            "'!' or any form of blockers make no sense in this usage: '%s'" %
            (text, ))

    restrictions = []
    if '::' in text:
        text, repo_id = text.rsplit('::', 1)
        restrictions.append(restricts.RepositoryDep(repo_id))
    if ':' in text:
        text, slot = text.rsplit(':', 1)
        slot, _sep, subslot = slot.partition('/')
        if slot:
            restrictions.append(restricts.SlotDep(slot))
        if subslot:
            restrictions.append(restricts.SubSlotDep(subslot))

    tsplit = text.rsplit("/", 1)
    if len(tsplit) == 1:
        ops, text = collect_ops(text)
        if not ops:
            if "*" in text:
                r = convert_glob(text)
                if r is None:
                    restrictions.append(packages.AlwaysTrue)
                else:
                    restrictions.append(
                        packages.PackageRestriction("package", r))
                if len(restrictions) == 1:
                    return restrictions[0]
                return packages.AndRestriction(*restrictions)
        elif text.startswith("*"):
            raise ParseError(
                "cannot do prefix glob matches with version ops: %s" %
                (orig_text, ))
        # ok... fake category.  whee.
        try:
            r = list(
                collect_package_restrictions(atom.atom(
                    "%scategory/%s" % (ops, text)).restrictions,
                                             attrs=("category", ),
                                             invert=True))
        except errors.MalformedAtom as e:
            e.atom = orig_text
            raise_from(ParseError(str(e)))
        if not restrictions and len(r) == 1:
            return r[0]
        restrictions.extend(r)
        return packages.AndRestriction(*restrictions)
    elif text[0] in "=<>~" or "*" not in text:
        try:
            return atom.atom(orig_text)
        except errors.MalformedAtom as e:
            raise_from(ParseError(str(e)))

    r = map(convert_glob, tsplit)
    if not r[0] and not r[1]:
        restrictions.append(packages.AlwaysTrue)
    elif not r[0]:
        restrictions.append(packages.PackageRestriction("package", r[1]))
    elif not r[1]:
        restrictions.append(packages.PackageRestriction("category", r[0]))
    else:
        restrictions.extend((
            packages.PackageRestriction("category", r[0]),
            packages.PackageRestriction("package", r[1]),
        ))
    if len(restrictions) == 1:
        return restrictions[0]
    return packages.AndRestriction(*restrictions)