Exemple #1
0
    def __init__(self,
                 location,
                 cache_location=None,
                 repo_id='vdb',
                 disable_cache=False):
        prototype.tree.__init__(self, frozen=False)
        self.repo_id = repo_id
        self.location = location
        if disable_cache:
            cache_location = None
        elif cache_location is None:
            cache_location = pjoin("/var/cache/edb/dep", location.lstrip("/"))
        self.cache_location = cache_location
        self._versions_tmp_cache = {}
        try:
            st = os.stat(self.location)
            if not stat.S_ISDIR(st.st_mode):
                raise errors.InitializationError("base not a dir: %r" %
                                                 self.location)
            elif not st.st_mode & (os.X_OK | os.R_OK):
                raise errors.InitializationError(
                    "base lacks read/executable: %r" % self.location)

        except OSError as e:
            if e.errno != errno.ENOENT:
                compatibility.raise_from(
                    errors.InitializationError("lstat failed on base %r" %
                                               self.location))

        self.package_class = self.package_factory(self)
Exemple #2
0
    def __init__(self, location, repo_id=None, cache_version='0'):
        """
        :param location: root of the tbz2 repository
        :keyword repo_id: unique repository id to use; else defaults to
            the location
        """
        super().__init__()
        self.base = self.location = location
        if repo_id is None:
            repo_id = location
        self.repo_id = repo_id
        self._versions_tmp_cache = {}

        # XXX rewrite this when snakeoil.osutils grows an access equivalent.
        if not access(self.base, os.X_OK | os.R_OK):
            # either it doesn't exist, or we don't have perms.
            if not os.path.exists(self.base):
                raise errors.InitializationError(
                    f"base {self.base!r} doesn't exist")
            raise errors.InitializationError(
                "base directory %r with mode 0%03o isn't readable/executable"
                " by this user" %
                (self.base, os.stat(self.base).st_mode & 0o4777))

        self.cache = remote.get_cache_kls(cache_version)(pjoin(
            self.base, self.cache_name))
        self.package_class = BinPkg(self)
Exemple #3
0
    def __init__(self, location, cache_location=None, repo_id='vdb',
                 disable_cache=False):
        super().__init__(frozen=False)
        self.repo_id = repo_id
        self.location = location
        if disable_cache:
            cache_location = None
        elif cache_location is None:
            cache_location = pjoin("/var/cache/edb/dep", location.lstrip("/"))
        self.cache_location = cache_location
        self._versions_tmp_cache = {}
        try:
            st = os.stat(self.location)
            if not stat.S_ISDIR(st.st_mode):
                raise errors.InitializationError(
                    f"base not a dir: {self.location!r}")
            elif not st.st_mode & (os.X_OK|os.R_OK):
                raise errors.InitializationError(
                    f"base lacks read/executable: {self.location!r}")
        except FileNotFoundError:
            pass
        except OSError as e:
            raise errors.InitializationError(f'lstat failed on base: {self.location!r}') from e

        self.package_class = self.package_factory(self)
Exemple #4
0
    def _umount_archive(self):
        """Unmount the squashfs archive."""
        try:
            umount(self.location)
            return
        except FileNotFoundError as e:
            raise repo_errors.InitializationError(
                f'failed unmounting squashfs archive: {e.filename} required')
        except OSError as e:
            # fail out if not a permissions issue (regular or loopback failure inside userns)
            if e.errno not in (errno.EPERM, errno.EPIPE):
                raise repo_errors.InitializationError(
                    f'failed unmounting squashfs archive: {e.strerror}')

        # fallback to using fusermount
        try:
            # TODO: switch to capture_output=True when >= py3.7
            ret = subprocess.run(['fusermount', '-u', self.location],
                                 stderr=subprocess.PIPE,
                                 stdout=subprocess.PIPE)
        except FileNotFoundError as e:
            raise repo_errors.InitializationError(
                f'failed unmounting squashfs archive: {e.filename} required')

        if ret.returncode:
            self._failed_cmd(ret, 'unmounting')
Exemple #5
0
 def __init__(self, repo, restrict, sentinel_val=False):
     self.raw_repo = repo
     self.sentinel_val = sentinel_val
     if not hasattr(self.raw_repo, 'itermatch'):
         raise errors.InitializationError(
             f"{self.raw_repo} is not a repository tree derivative")
     if not isinstance(restrict, restriction.base):
         raise errors.InitializationError(f"{restrict} is not a restriction")
     self.restrict = restrict
     self.raw_repo = repo
     if sentinel_val:
         self._filterfunc = filter
     else:
         self._filterfunc = filterfalse
Exemple #6
0
 def __init__(self, repo, restriction, sentinel_val=False):
     self.raw_repo = repo
     self.sentinel_val = sentinel_val
     if not hasattr(self.raw_repo, 'itermatch'):
         raise errors.InitializationError(
             "%s is not a repository tree derivative" % (self.raw_repo, ))
     if not isinstance(restriction, base):
         raise errors.InitializationError("%s is not a restriction" %
                                          (restriction, ))
     self.restriction = restriction
     self.raw_repo = repo
     if sentinel_val:
         self._filterfunc = ifilter
     else:
         self._filterfunc = filterfalse
Exemple #7
0
 def __init__(self, *trees):
     super(tree, self).__init__()
     for x in trees:
         if not hasattr(x, 'itermatch'):
             raise errors.InitializationError(
                 "%s is not a repository tree derivative" % (x, ))
     self.trees = trees
Exemple #8
0
    def __init__(self,
                 location,
                 repo_id=None,
                 ignore_paludis_versioning=False,
                 cache_version='0'):
        """
        :param location: root of the tbz2 repository
        :keyword repo_id: unique repository id to use; else defaults to
            the location
        :keyword ignore_paludis_versioning: if False, error when -scm is seen.
            If True, silently ignore -scm ebuilds.
        """
        super(tree, self).__init__()
        self.base = self.location = location
        if repo_id is None:
            repo_id = location
        self.repo_id = repo_id
        self._versions_tmp_cache = {}
        self.ignore_paludis_versioning = ignore_paludis_versioning

        # XXX rewrite this when snakeoil.osutils grows an access equivalent.
        if not access(self.base, os.X_OK | os.R_OK):
            # either it doesn't exist, or we don't have perms.
            if not os.path.exists(self.base):
                raise errors.InitializationError("base %r doesn't exist: %s" %
                                                 self.base)
            raise errors.InitializationError(
                "base directory %r with mode 0%03o isn't readable/executable"
                " by this user" %
                (self.base, os.stat(self.base).st_mode & 04777))

        self.cache = remote.get_cache_kls(cache_version)(pjoin(
            self.base, self.cache_name))
        self.package_class = wrap_factory(self.package_factory, self)
Exemple #9
0
def tree(config,
         repo_config,
         cache=(),
         eclass_override=None,
         default_mirrors=None,
         ignore_paludis_versioning=False,
         allow_missing_manifests=False):
    eclass_override = _sort_eclasses(config, repo_config, eclass_override)

    try:
        masters = tuple(config.objects['repo'][r] for r in repo_config.masters)
    except RuntimeError as e:
        # TODO: migrate to RecursionError when going >=py3.5
        if e.message.startswith('maximum recursion depth exceeded'):
            raise_from(
                errors.InitializationError(
                    "'%s' repo has cyclic masters: %s" %
                    (repo_config.repo_id, ', '.join(repo_config.masters))))
        raise

    return _UnconfiguredTree(
        repo_config.location,
        eclass_override,
        masters=masters,
        cache=cache,
        default_mirrors=default_mirrors,
        ignore_paludis_versioning=ignore_paludis_versioning,
        allow_missing_manifests=allow_missing_manifests,
        repo_config=repo_config)
Exemple #10
0
def tree(config,
         repo_config,
         cache=(),
         eclass_cache=None,
         default_mirrors=None,
         allow_missing_manifests=False):
    """Initialize an unconfigured ebuild repository."""
    repo_id = repo_config.repo_id
    repo_path = repo_config.location

    if repo_config.masters is None:
        # if it's None, that means it's not a standalone, and is PMS, or misconfigured.
        # empty tuple means it's a standalone repository
        default = config.get_default('repo_config')
        if default is None:
            raise errors.InitializationError(
                f"repo {repo_id!r} at {repo_path!r} requires missing default repo"
            )

    configured_repos = tuple(r.repo_id
                             for r in config.objects['repo_config'].values())
    missing = set(repo_config.masters).difference(configured_repos)
    if missing:
        missing = ', '.join(map(repr, sorted(missing)))
        raise errors.InitializationError(
            f'repo {repo_id!r} at path {repo_path!r} has missing masters: {missing}'
        )

    try:
        masters = tuple(config.objects['repo'][r] for r in repo_config.masters)
    except RecursionError:
        repo_id = repo_config.repo_id
        masters = ', '.join(repo_config.masters)
        raise errors.InitializationError(
            f'{repo_id!r} repo has cyclic masters: {masters}')

    if eclass_cache is None:
        eclass_cache = _sort_eclasses(config, repo_config)

    return UnconfiguredTree(repo_config.location,
                            eclass_cache=eclass_cache,
                            masters=masters,
                            cache=cache,
                            default_mirrors=default_mirrors,
                            allow_missing_manifests=allow_missing_manifests,
                            repo_config=repo_config)
Exemple #11
0
 def _failed_cmd(self, ret, action):
     if ret.returncode:
         stderr = ret.stderr.decode().strip().lower()
         msg = f'failed {action} squashfs archive: {stderr}'
         if ret.returncode == 1:
             raise PermissionDenied(self._sqfs, msg)
         else:
             raise repo_errors.InitializationError(msg)
Exemple #12
0
    def __init__(self, raw_repo, domain, domain_settings, fetcher=None):
        """
        :param raw_repo: :obj:`_UnconfiguredTree` instance
        :param domain_settings: environment settings to bind
        :param fetcher: :obj:`pkgcore.fetch.base.fetcher` instance to use
            for getting access to fetchable files
        """

        if "USE" not in domain_settings:
            raise errors.InitializationError(
                "%s requires the following settings: 'USE', not supplied" %
                (self.__class__, ))

        elif 'CHOST' not in domain_settings:
            raise errors.InitializationError(
                "%s requires the following settings: 'CHOST', not supplied" %
                (self.__class__, ))

        chost = domain_settings['CHOST']
        scope_update = {'chost': chost}
        scope_update.update((x, domain_settings.get(x.upper(), chost))
                            for x in ('cbuild', 'ctarget'))
        scope_update.update((x, domain_settings[x.upper()])
                            for x in ('cflags', 'cxxflags', 'ldflags'))
        scope_update['operations_callback'] = self._generate_pkg_operations

        # update wrapped attr funcs requiring access to the class instance
        for k, v in self.config_wrappables.iteritems():
            if isinstance(v, basestring):
                self.config_wrappables[k] = getattr(self, v)

        configured.tree.__init__(self,
                                 raw_repo,
                                 self.config_wrappables,
                                 pkg_kls_injections=scope_update)

        self._get_pkg_use = domain.get_package_use_unconfigured
        self._get_pkg_use_for_building = domain.get_package_use_buildable
        self.domain = domain
        self.domain_settings = domain_settings
        self._fetcher_override = fetcher
        self._delayed_iuse = partial(make_kls(InvertedContains),
                                     InvertedContains)
Exemple #13
0
 def __init__(self, *trees):
     """
     :param trees: :obj:`pkgcore.repository.prototype.tree` instances
         to combines into one
     """
     super(tree, self).__init__()
     for x in trees:
         if not hasattr(x, 'itermatch'):
             raise errors.InitializationError(
                 "%s is not a repository tree derivative" % (x, ))
     self.trees = trees
Exemple #14
0
 def __init__(self, repo, package_class):
     """
     :param repo: :obj:`pkgcore.repository.prototype.tree` instance to wrap
     :param package_class: callable to yield the package instance
     """
     self.raw_repo = repo
     if not isinstance(self.raw_repo, prototype.tree):
         raise errors.InitializationError(
             f'{self.raw_repo!r} is not a repository tree derivative')
     self.package_class = package_class
     self.raw_repo = repo
Exemple #15
0
    def _mount_archive(self):
        """Mount the squashfs archive onto the repo in a mount namespace."""
        # enable a user namespace if not running as root
        unshare_kwds = {'mount': True, 'user': not os.getuid() == 0}
        try:
            simple_unshare(**unshare_kwds)
        except OSError as e:
            raise repo_errors.InitializationError(
                f'namespace support unavailable: {e.strerror}')

        # First try using mount binary to automatically handle setting up loop
        # device -- this only works with real root perms since loopback device
        # mounting (losetup) doesn't work in user namespaces.
        #
        # TODO: switch to capture_output=True when >= py3.7
        ret = subprocess.run(
            ['mount', self._sqfs, self.location],
            stderr=subprocess.PIPE,
            stdout=subprocess.PIPE,
        )

        if ret.returncode == 0:
            return
        elif ret.returncode not in (1, 32):
            # fail out if not a permissions issue (regular or loopback failure inside userns)
            self._failed_cmd(ret, 'mounting')

        # fallback to using squashfuse
        try:
            ret = subprocess.run(
                ['squashfuse', '-o', 'nonempty', self._sqfs, self.location],
                stderr=subprocess.PIPE,
                stdout=subprocess.PIPE)
        except FileNotFoundError as e:
            raise repo_errors.InitializationError(
                f'failed mounting squashfs archive: {e.filename} required')

        if ret.returncode:
            self._failed_cmd(ret, 'mounting')
Exemple #16
0
 def __init__(self, sqfs_file, location, *args, **kwargs):
     sqfs_path = pjoin(location, sqfs_file)
     object.__setattr__(self, '_sqfs', sqfs_path)
     object.__setattr__(self, 'location', location)
     # if squashfs archive exists in the repo, try to mount it over itself
     if os.path.exists(self._sqfs):
         try:
             self._mount_archive()
         except PermissionError as e:
             if platform.uname().release < '4.18':
                 raise repo_errors.InitializationError(
                     'fuse mounts in user namespaces require linux >= 4.18')
             raise
     super().__init__(location, *args, **kwargs)
Exemple #17
0
    def __init__(self, raw_repo, domain, domain_settings, fetcher=None):
        """
        :param raw_repo: :obj:`UnconfiguredTree` instance
        :param domain_settings: environment settings to bind
        :param fetcher: :obj:`pkgcore.fetch.base.fetcher` instance to use
            for getting access to fetchable files
        """
        required_settings = {'USE', 'CHOST'}
        missing_settings = required_settings.difference(domain_settings)
        if missing_settings:
            raise errors.InitializationError(
                f"{self.__class__} missing required setting{_pl(missing_settings)}: "
                f"{', '.join(map(repr, missing_settings))}")

        chost = domain_settings['CHOST']
        scope_update = {'chost': chost}
        scope_update.update((x, domain_settings.get(x.upper(), chost))
                            for x in ('cbuild', 'ctarget'))
        scope_update.update((x, domain_settings[x.upper()])
                            for x in ('cflags', 'cxxflags', 'ldflags'))
        scope_update['operations_callback'] = self._generate_pkg_operations

        # update wrapped attr funcs requiring access to the class instance
        for k, v in self.config_wrappables.items():
            if isinstance(v, str):
                self.config_wrappables[k] = getattr(self, v)

        super().__init__(raw_repo,
                         self.config_wrappables,
                         pkg_kls_injections=scope_update)

        self.domain = domain
        self.domain_settings = domain_settings
        self._fetcher_override = fetcher
        self._delayed_iuse = partial(make_kls(InvertedContains),
                                     InvertedContains)
Exemple #18
0
    def __init__(self,
                 location,
                 eclass_cache=None,
                 masters=(),
                 cache=(),
                 default_mirrors=None,
                 allow_missing_manifests=False,
                 repo_config=None):
        """
        :param location: on disk location of the tree
        :param cache: sequence of :obj:`pkgcore.cache.template.database` instances
            to use for storing metadata
        :param masters: repo masters this repo inherits from
        :param eclass_cache: If not None, :obj:`pkgcore.ebuild.eclass_cache`
            instance representing the eclasses available,
            if None, generates the eclass_cache itself
        :param default_mirrors: Either None, or sequence of mirrors to try
            fetching from first, then falling back to other uri
        """
        super().__init__()
        self.base = self.location = location
        try:
            if not stat.S_ISDIR(os.stat(self.base).st_mode):
                raise errors.InitializationError(
                    f"base not a dir: {self.base}")
        except OSError as e:
            raise errors.InitializationError(
                f"lstat failed: {self.base}") from e

        if repo_config is None:
            repo_config = repo_objs.RepoConfig(location)
        self.config = repo_config

        # profiles dir is required by PMS
        if not os.path.isdir(self.config.profiles_base):
            raise errors.InvalidRepo(
                f'missing required profiles dir: {self.location!r}')

        # verify we support the repo's EAPI
        if not self.is_supported:
            raise errors.UnsupportedRepo(self)

        if eclass_cache is None:
            eclass_cache = eclass_cache_mod.cache(pjoin(
                self.location, 'eclass'),
                                                  location=self.location)
        self.eclass_cache = eclass_cache

        self.masters = masters
        self.trees = tuple(masters) + (self, )
        self.licenses = repo_objs.Licenses(self.location)
        if masters:
            self.licenses = repo_objs.OverlayedLicenses(*self.trees)

        mirrors = {}
        fp = pjoin(self.location, 'profiles', "thirdpartymirrors")
        try:
            for k, v in read_dict(fp, splitter=None).items():
                v = v.split()
                shuffle(v)
                mirrors[k] = v
        except FileNotFoundError:
            pass

        # use mirrors from masters if not defined in the repo
        for master in masters:
            for k, v in master.mirrors.items():
                if k not in mirrors:
                    mirrors[k] = v

        if isinstance(cache, (tuple, list)):
            cache = tuple(cache)
        else:
            cache = (cache, )

        self.mirrors = mirrors
        self.default_mirrors = default_mirrors
        self.cache = cache
        self._allow_missing_chksums = allow_missing_manifests
        self.package_class = self.package_factory(self, cache,
                                                  self.eclass_cache,
                                                  self.mirrors,
                                                  self.default_mirrors)
        self._shared_pkg_cache = WeakValCache()
        self._masked = RestrictionRepo(repo_id='masked')
Exemple #19
0
    def __init__(self,
                 location,
                 eclass_cache,
                 cache=(),
                 default_mirrors=None,
                 override_repo_id=None,
                 ignore_paludis_versioning=False,
                 allow_missing_manifests=False,
                 repo_config=None):
        """
        :param location: on disk location of the tree
        :param cache: sequence of :obj:`pkgcore.cache.template.database` instances
            to use for storing metadata
        :param eclass_cache: If not None, :obj:`pkgcore.ebuild.eclass_cache`
            instance representing the eclasses available,
            if None, generates the eclass_cache itself
        :param default_mirrors: Either None, or sequence of mirrors to try
            fetching from first, then falling back to other uri
        :param override_repo_id: Either None, or string to force as the
            repository unique id
        :param ignore_paludis_versioning: If False, fail when -scm is encountred.  if True,
            silently ignore -scm ebuilds.
        """

        prototype.tree.__init__(self)
        if repo_config is None:
            repo_config = repo_objs.RepoConfig(location)
        self.config = repo_config
        self._repo_id = override_repo_id
        self.base = self.location = location
        try:
            if not stat.S_ISDIR(os.stat(self.base).st_mode):
                raise errors.InitializationError("base not a dir: %s" %
                                                 self.base)

        except OSError:
            raise_from(
                errors.InitializationError("lstat failed on base %s" %
                                           (self.base, )))
        self.eclass_cache = eclass_cache

        self.licenses = repo_objs.Licenses(location)

        fp = pjoin(self.base, metadata_offset, "thirdpartymirrors")
        mirrors = {}
        try:
            for k, v in read_dict(fp, splitter=None).iteritems():
                v = v.split()
                shuffle(v)
                mirrors[k] = v
        except EnvironmentError as ee:
            if ee.errno != errno.ENOENT:
                raise

        if isinstance(cache, (tuple, list)):
            cache = tuple(cache)
        else:
            cache = (cache, )

        self.mirrors = mirrors
        self.default_mirrors = default_mirrors
        self.cache = cache
        self.ignore_paludis_versioning = ignore_paludis_versioning
        self._allow_missing_chksums = allow_missing_manifests
        self.package_class = self.package_factory(self, cache,
                                                  self.eclass_cache,
                                                  self.mirrors,
                                                  self.default_mirrors)
        self._shared_pkg_cache = WeakValCache()