예제 #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 _validate_args(parser, namespace):
    namespace.pkg_dir = False

    if not namespace.targets:
        if namespace.selected_repo:
            # use repo restriction since no targets specified
            restriction = restricts.RepositoryDep(
                namespace.selected_repo.repo_id)
            token = namespace.selected_repo.repo_id
        else:
            # Use a path restriction if we're in a repo, obviously it'll work
            # faster if we're in an invididual ebuild dir but we're not that
            # restrictive.
            try:
                restriction = namespace.repo.path_restrict(namespace.cwd)
                token = namespace.cwd
            except (AttributeError, ValueError):
                parser.error(
                    'missing target argument and not in a supported repo')

            # determine if we're grabbing the keywords for a single pkg in cwd
            namespace.pkg_dir = any(
                isinstance(x, restricts.PackageDep)
                for x in reversed(restriction.restrictions))

        namespace.targets = [(token, restriction)]
예제 #3
0
    def path_restrict(self, path):
        """Return a restriction from a given path in a repo.

        :param path: full or partial path to an ebuild
        :return: a package restriction matching the given path if possible
        :raises ValueError: if the repo doesn't contain the given path, the
            path relates to a file that isn't an ebuild, or the ebuild isn't in the
            proper directory layout
        """
        if path not in self:
            raise ValueError(
                f"{self.repo_id!r} repo doesn't contain: {path!r}")

        if not path.startswith(os.sep) and os.path.exists(
                pjoin(self.location, path)):
            path_chunks = path.split(os.path.sep)
        else:
            path = os.path.realpath(os.path.abspath(path))
            relpath = path[len(os.path.realpath(self.location)):].strip('/')
            path_chunks = relpath.split(os.path.sep)

        if os.path.isfile(path):
            if not path.endswith('.ebuild'):
                raise ValueError(f"file is not an ebuild: {path!r}")
            elif len(path_chunks) != 3:
                # ebuild isn't in a category/PN directory
                raise ValueError(
                    f"ebuild not in the correct directory layout: {path!r}")

        restrictions = []

        # add restrictions until path components run out
        try:
            restrictions.append(restricts.RepositoryDep(self.repo_id))
            if path_chunks[0] in self.categories:
                restrictions.append(restricts.CategoryDep(path_chunks[0]))
                restrictions.append(restricts.PackageDep(path_chunks[1]))
                base = cpv.VersionedCPV(
                    f"{path_chunks[0]}/{os.path.splitext(path_chunks[2])[0]}")
                restrictions.append(
                    restricts.VersionMatch('=',
                                           base.version,
                                           rev=base.revision))
        except IndexError:
            pass
        return packages.AndRestriction(*restrictions)
예제 #4
0
def _validate_args(parser, namespace):
    namespace.pkg_dir = False

    # disable colors when not using the native output format
    if namespace.format != 'showkw':
        namespace.color = False

    if namespace.color:
        # default colors to use for keyword types
        _COLORS = {
            '+': '\u001b[32m',
            '~': '\u001b[33m',
            '-': '\u001b[31m',
            '*': '\u001b[31m',
            'o': '\u001b[30;1m',
            'reset': '\u001b[0m',
        }
    else:
        _COLORS = None
    namespace.colormap = partial(_colormap, _COLORS)

    if not namespace.targets:
        if namespace.selected_repo:
            # use repo restriction since no targets specified
            restriction = restricts.RepositoryDep(namespace.selected_repo.repo_id)
            token = namespace.selected_repo.repo_id
        else:
            # Use a path restriction if we're in a repo, obviously it'll work
            # faster if we're in an invididual ebuild dir but we're not that
            # restrictive.
            try:
                restriction = namespace.repo.path_restrict(namespace.cwd)
                token = namespace.cwd
            except (AttributeError, ValueError):
                parser.error('missing target argument and not in a supported repo')

            # determine if we're grabbing the keywords for a single pkg in cwd
            namespace.pkg_dir = any(
                isinstance(x, restricts.PackageDep)
                for x in reversed(restriction.restrictions))

        namespace.targets = [(token, restriction)]
예제 #5
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)