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)
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)
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)
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')
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
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
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
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)
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)
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)
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)
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)
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
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
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')
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)
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)
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')
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()