def test_fakeroot(self): try: l = pwd.getpwnam("nobody") except KeyError: raise SkipTest( "system lacks nobody user, thus can't test fakeroot") if 'LD_PRELOAD' in os.environ: raise SkipTest( "disabling test due to LD_PRELOAD setting, which " "fakeroot relies upon") nobody_uid = l[2] nobody_gid = l[3] kw = {} if os.getuid() == 0: kw = {"uid": l[2], "gid": l[3]} fp2 = self.generate_script( "pkgcore-spawn-fakeroot2.sh", "#!%s\nimport os\ns=os.stat('/tmp')\n" "print(s.st_uid)\nprint(s.st_gid)\n" % spawn.find_binary("python")) fp1 = self.generate_script( "pkgcore-spawn-fakeroot.sh", "#!%s\nchown %i:%i /tmp;%s;\n" % ( self.bash_path, nobody_uid, nobody_gid, fp2)) savefile = os.path.join(self.dir, "fakeroot-savefile") self.assertNotEqual(long(os.stat("/tmp").st_uid), long(nobody_uid)) self.assertEqual( [0, ["%s\n" % x for x in (nobody_uid, nobody_gid)]], spawn.spawn_get_output( [self.bash_path, fp1], spawn_type=post_curry(spawn.spawn_fakeroot, savefile), **kw)) self.assertNotEqual( long(os.stat("/tmp").st_uid), long(nobody_uid), "bad voodoo; we managed to change /tmp to nobody- " "this shouldn't occur!") self.assertEqual( True, os.path.exists(savefile), "no fakeroot file was created, either fakeroot differs or our" + " args passed to it are bad") # yes this is a bit ugly, but fakeroot requires an arg- so we # have to curry it self.assertEqual( [0, ["%s\n" % x for x in (nobody_uid, nobody_gid)]], spawn.spawn_get_output( [fp2], spawn_type=post_curry(spawn.spawn_fakeroot, savefile), **kw)) os.unlink(fp1) os.unlink(fp2) os.unlink(savefile)
def test_sandbox_empty_dir(self): """ sandbox gets pissy if it's ran from a nonexistent dir this verifies our fix works. """ fp = self.generate_script( "pkgcore-spawn-sandbox.sh", "echo $LD_PRELOAD") dpath = os.path.join(self.dir, "dar") os.mkdir(dpath) try: cwd = os.getcwd() except OSError: cwd = None try: os.chdir(dpath) os.rmdir(dpath) self.assertIn( "libsandbox.so", [os.path.basename(x.strip()) for x in spawn.spawn_get_output( fp, spawn_type=spawn.spawn_sandbox, cwd='/')[1][0].split()]) os.unlink(fp) finally: if cwd is not None: os.chdir(cwd)
def test_sandbox_empty_dir(self): """sandbox gets pissy if it's ran from a nonexistent dir this verifies our fix works. """ if os.environ.get('SANDBOX_ON', False): raise SkipTest("sandbox doesn't like running inside itself") fp = self.generate_script("pkgcore-spawn-sandbox.sh", "echo $LD_PRELOAD") dpath = os.path.join(self.dir, "dar") os.mkdir(dpath) try: cwd = os.getcwd() except OSError: cwd = None try: os.chdir(dpath) os.rmdir(dpath) self.assertIn("libsandbox.so", [ os.path.basename(x.strip()) for x in spawn.spawn_get_output( fp, spawn_type=spawn.spawn_sandbox, cwd='/')[1][0].split() ]) os.unlink(fp) finally: if cwd is not None: os.chdir(cwd)
def test_sandbox(self): fp = self.generate_script( "pkgcore-spawn-sandbox.sh", "echo $LD_PRELOAD") ret = spawn.spawn_get_output(fp, spawn_type=spawn.spawn_sandbox) self.assertTrue(ret[1], msg="no output; exit code was %s; script " "location %s" % (ret[0], fp)) self.assertIn("libsandbox.so", [os.path.basename(x.strip()) for x in ret[1][0].split()]) os.unlink(fp)
def _fallback_file(path): ret, out = spawn_get_output(["file", path]) if ret != 0: raise ValueError("file output was non zero- ret:%r out:%r" % (ret, out)) out = ''.join(out) if out.startswith(path): out = out[len(path):] if out.startswith(":"): out = out[1:] return out
def test_sandbox(self): if os.environ.get('SANDBOX_ON', False): raise SkipTest("sandbox doesn't like running inside itself") fp = self.generate_script("pkgcore-spawn-sandbox.sh", "echo $LD_PRELOAD") ret = spawn.spawn_get_output(fp, spawn_type=spawn.spawn_sandbox) self.assertTrue(ret[1], msg="no output; exit code was %s; script " "location %s" % (ret[0], fp)) self.assertIn("libsandbox.so", [os.path.basename(x.strip()) for x in ret[1][0].split()]) os.unlink(fp)
def test_sandbox(self): if os.environ.get('SANDBOX_ON', False): raise SkipTest("sandbox doesn't like running inside itself") fp = self.generate_script( "pkgcore-spawn-sandbox.sh", "echo $LD_PRELOAD") ret = spawn.spawn_get_output(fp, spawn_type=spawn.spawn_sandbox) self.assertTrue( ret[1], msg="no output; exit code was %s; script " "location %s" % (ret[0], fp)) self.assertIn( "libsandbox.so", [os.path.basename(x.strip()) for x in ret[1][0].split()]) os.unlink(fp)
def test_get_output(self): filename = "pkgcore-spawn-getoutput.sh" for r, s, text, args in [ [0, ["dar\n"], "echo dar\n", {}], [0, ["dar"], "echo -n dar", {}], [1, ["blah\n", "dar\n"], "echo blah\necho dar\nexit 1", {}], [0, [], "echo dar 1>&2", {"fd_pipes": {1: 1, 2: self.null}}]]: fp = self.generate_script(filename, text) self.assertEqual( [r, s], spawn.spawn_get_output(fp, spawn_type=spawn.spawn_bash, **args)) os.unlink(fp)
def test_umask(self): fp = self.generate_script( "portage_spawn_umask.sh", "#!%s\numask" % self.bash_path) try: old_umask = os.umask(0) if old_umask == 0: # crap. desired = 022 os.umask(desired) else: desired = 0 self.assertEqual(str(desired).lstrip("0"), spawn.spawn_get_output(fp)[1][0].strip().lstrip("0")) finally: os.umask(old_umask)
def test_umask(self): fp = self.generate_script( "portage_spawn_umask.sh", "#!%s\numask" % self.bash_path) try: old_um = os.umask(0) if old_um == 0: # crap. desired = 022 os.umask(desired) else: desired = 0 self.assertEqual(str(desired).lstrip("0"), spawn.spawn_get_output(fp)[1][0].strip().lstrip("0")) finally: os.umask(old_um)
def is_usable_on_filepath(cls, path): svn_path = os.path.join(path, '.svn') if cls.disabled or not os.path.isdir(svn_path): return None code, data = spawn_get_output([cls.binary, "info", path]) if code != 0: # should alert the user somehow return None for line in data: line = line.strip().split(":", 1) if len(line) != 2: continue if line[0] == 'URL': uri = "svn+%s" % (line[1].strip(), ) return (cls._rewrite_uri_from_stat(svn_path, uri), ) return None
def is_usable_on_filepath(cls, path): bzr_path = os.path.join(path, '.bzr') if cls.disabled or not os.path.isdir(bzr_path): return None code, data = spawn_get_output([cls.binary, "info", path]) if code != 0: # should alert the user somehow return None for line in data: line = line.strip().split(":", 1) if len(line) != 2: continue if line[0] == 'parent branch': uri = "bzr+%s" % (line[1].strip(),) return (cls._rewrite_uri_from_stat(bzr_path, uri),) return None
def __init__(self, pkg, initial_env=None, env_data_source=None, features=None, observer=None, clean=True, tmp_offset=None, use_override=None, allow_fetching=False): """ :param pkg: :class:`pkgcore.ebuild.ebuild_src.package` instance this env is being setup for :param initial_env: initial environment to use for this ebuild :param env_data_source: a :obj:`snakeoil.data_source.base` instance to restore the environment from- used for restoring the state of an ebuild processing, whether for unmerging, or walking phases during building :param features: ebuild features, hold over from portage, will be broken down at some point """ if use_override is not None: use = use_override else: use = pkg.use self.allow_fetching = allow_fetching if not hasattr(self, "observer"): self.observer = observer if not pkg.eapi_obj.is_supported: raise TypeError( "package %s uses an unsupported eapi: %s" % (pkg, pkg.eapi)) if initial_env is not None: # copy. self.env = dict(initial_env) for x in ("USE", "ACCEPT_LICENSE"): if x in self.env: del self.env[x] else: self.env = {} # temp hack. for x in ('chost', 'cbuild', 'ctarget'): val = getattr(pkg, x) if val is not None: self.env[x.upper()] = val # special note... if CTARGET is the same as CHOST, suppress it. # certain ebuilds (nano for example) will misbehave w/ it. if pkg.ctarget is not None and pkg.ctarget == pkg.chost: self.env.pop("CTARGET") if "PYTHONPATH" in os.environ: self.env["PYTHONPATH"] = os.environ["PYTHONPATH"] if "PKGCORE_DEBUG" in os.environ: self.env["PKGCORE_DEBUG"] = str(int(os.environ["PKGCORE_DEBUG"])) if features is None: features = self.env.get("FEATURES", ()) # XXX: note this is just eapi3 compatibility; not full prefix, soon.. self.env["ROOT"] = self.domain.root self.prefix_mode = pkg.eapi_obj.options.prefix_capable or 'force-prefix' in features self.env["PKGCORE_PREFIX_SUPPORT"] = 'false' self.prefix = '/' if self.prefix_mode: self.env['EROOT'] = normpath(self.domain.root) self.prefix = self.domain.prefix.lstrip("/") eprefix = normpath(pjoin(self.env["EROOT"], self.prefix)) if eprefix == '/': # Set eprefix to '' if it's basically empty; this keeps certain crappy builds # (cmake for example) from puking over //usr/blah pathways eprefix = '' self.env["EPREFIX"] = eprefix self.env["PKGCORE_PREFIX_SUPPORT"] = 'true' self.env.update(pkg.eapi_obj.get_ebd_env()) # generate a list of internally implemented EAPI specific functions that shouldn't be exported ret, eapi_funcs = spawn_get_output([pjoin(const.EAPI_BIN_PATH, 'generate_eapi_func_list.bash'), str(pkg.eapi)]) if ret != 0: raise Exception("failed to generate list of EAPI %s specific functions" % str(pkg.eapi)) self.env["PKGCORE_EAPI_FUNCS"] = ' '.join(x.strip() for x in eapi_funcs) self.env_data_source = env_data_source if env_data_source is not None and \ not isinstance(env_data_source, data_source.base): raise TypeError( "env_data_source must be None, or a pkgcore.data_source.base " "derivative: %s: %s" % ( env_data_source.__class__, env_data_source)) self.features = set(x.lower() for x in features) self.env["FEATURES"] = ' '.join(sorted(self.features)) iuse_effective_regex = (re.escape(x) for x in pkg.iuse_effective) iuse_effective_regex = "^(%s)$" % "|".join(iuse_effective_regex) iuse_effective_regex = iuse_effective_regex.replace("\\.\\*", ".*") self.env["PKGCORE_IUSE_EFFECTIVE"] = iuse_effective_regex expected_ebuild_env(pkg, self.env, env_source_override=self.env_data_source) self.env["PKGCORE_FINALIZED_RESTRICT"] = ' '.join(str(x) for x in pkg.restrict) self.restrict = pkg.restrict for x in ("sandbox", "userpriv", "fakeroot"): setattr(self, x, self.feat_or_bool(x) and not (x in self.restrict)) if self.fakeroot: logger.warning("disabling fakeroot; unusable till coreutils/fakeroot" + " interaction is fixed") self.fakeroot = False if self.userpriv and os.getuid() != 0: self.userpriv = False if "PORT_LOGDIR" in self.env: self.logging = pjoin(self.env["PORT_LOGDIR"], "%s:%s:%s.log" % (pkg.cpvstr, self.__class__.__name__, time.strftime("%Y%m%d-%H%M%S", time.localtime()))) del self.env["PORT_LOGDIR"] else: self.logging = False self.env["XARGS"] = xargs self.bashrc = self.env.pop("bashrc", ()) self.pkg = pkg self.eapi = pkg.eapi self.eapi_obj = pkg.eapi_obj wipes = [k for k, v in self.env.iteritems() if not isinstance(v, basestring)] for k in wipes: del self.env[k] self.set_op_vars(tmp_offset) self.clean_at_start = clean self.clean_needed = False
def __init__(self, domain, pkg, verified_files, eclass_cache, observer=None, **kwargs): """ :param pkg: :obj:`pkgcore.ebuild.ebuild_src.package` instance we'll be building :param domain_settings: dict bled down from the domain configuration; basically initial env :param eclass_cache: the :class:`pkgcore.ebuild.eclass_cache` we'll be using :param files: mapping of fetchables mapped to their disk location """ use = kwargs.get("use_override", pkg.use) domain_settings = domain.settings format.build.__init__(self, domain, pkg, verified_files, observer) ebd.__init__(self, pkg, initial_env=domain_settings, features=domain_settings["FEATURES"], **kwargs) self.env["FILESDIR"] = pjoin(os.path.dirname(pkg.ebuild.path), "files") self.eclass_cache = eclass_cache self.env["ECLASSDIR"] = eclass_cache.eclassdir portdir = self.env["PORTDIR"] = eclass_cache.portdir if portdir is None: del self.env["PORTDIR"] self.run_test = self.feat_or_bool("test", domain_settings) self.allow_failed_test = self.feat_or_bool("test-fail-continue", domain_settings) if "test" in self.restrict: self.run_test = False elif "test" not in use: if self.run_test: logger.warning( "disabling test for %s due to test use flag being disabled" % pkg) self.run_test = False # XXX minor hack path = self.env["PATH"].split(":") for s, default in (("DISTCC", ".distcc"), ("CCACHE", "ccache")): b = (self.feat_or_bool(s, domain_settings) and not s in self.restrict) setattr(self, s.lower(), b) if b: # looks weird I realize, but # pjoin("/foor/bar", "/barr/foo") == "/barr/foo" # and pjoin("/foo/bar", ".asdf") == "/foo/bar/.asdf" self.env.setdefault(s + "_DIR", pjoin(self.tmpdir, default)) # gentoo bug 355283 libdir = self.env.get("ABI") if libdir is not None: libdir = self.env.get("LIBDIR_%s" % (libdir, )) if libdir is not None: libdir = self.env.get(libdir) if libdir is None: libdir = "lib" path.insert(0, "/usr/%s/%s/bin" % (libdir, s.lower())) else: for y in ("_PATH", "_DIR"): if s + y in self.env: del self.env[s + y] path = [piece for piece in path if piece] self.env["PATH"] = ":".join(path) self.env["A"] = ' '.join(set(x.filename for x in pkg.fetchables)) if self.eapi_obj.options.has_AA: pkg = getattr(self.pkg, '_raw_pkg', self.pkg) self.env["AA"] = ' '.join( set(x.filename for x in iflatten_instance( pkg.fetchables, fetch.fetchable))) if self.eapi_obj.options.has_KV: ret = spawn_get_output(['uname', '-r']) if ret[0] == 0: self.env["KV"] = ret[1][0].strip() if self.eapi_obj.options.has_merge_type: self.env["MERGE_TYPE"] = "source" if self.setup_is_for_src: self.init_distfiles_env()
def __init__(self, pkg, initial_env=None, env_data_source=None, features=None, observer=None, clean=True, tmp_offset=None, use_override=None, allow_fetching=False): """ :param pkg: :class:`pkgcore.ebuild.ebuild_src.package` instance this env is being setup for :param initial_env: initial environment to use for this ebuild :param env_data_source: a :obj:`snakeoil.data_source.base` instance to restore the environment from- used for restoring the state of an ebuild processing, whether for unmerging, or walking phases during building :param features: ebuild features, hold over from portage, will be broken down at some point """ if use_override is not None: use = use_override else: use = pkg.use self.allow_fetching = allow_fetching if not hasattr(self, "observer"): self.observer = observer if not pkg.eapi_obj.is_supported: raise TypeError("package %s uses an unsupported eapi: %s" % (pkg, pkg.eapi)) if initial_env is not None: # copy. self.env = dict(initial_env) for x in ("USE", "ACCEPT_LICENSE"): if x in self.env: del self.env[x] else: self.env = {} # temp hack. for x in ('chost', 'cbuild', 'ctarget'): val = getattr(pkg, x) if val is not None: self.env[x.upper()] = val # special note... if CTARGET is the same as CHOST, suppress it. # certain ebuilds (nano for example) will misbehave w/ it. if pkg.ctarget is not None and pkg.ctarget == pkg.chost: self.env.pop("CTARGET") if "PYTHONPATH" in os.environ: self.env["PYTHONPATH"] = os.environ["PYTHONPATH"] if "PKGCORE_DEBUG" in os.environ: self.env["PKGCORE_DEBUG"] = str(int(os.environ["PKGCORE_DEBUG"])) if features is None: features = self.env.get("FEATURES", ()) # XXX: note this is just eapi3 compatibility; not full prefix, soon.. self.env["ROOT"] = self.domain.root self.prefix_mode = pkg.eapi_obj.options.prefix_capable or 'force-prefix' in features self.env["PKGCORE_PREFIX_SUPPORT"] = 'false' self.prefix = '/' if self.prefix_mode: self.env['EROOT'] = normpath(self.domain.root) self.prefix = self.domain.prefix.lstrip("/") eprefix = normpath(pjoin(self.env["EROOT"], self.prefix)) if eprefix == '/': # Set eprefix to '' if it's basically empty; this keeps certain crappy builds # (cmake for example) from puking over //usr/blah pathways eprefix = '' self.env["EPREFIX"] = eprefix self.env["PKGCORE_PREFIX_SUPPORT"] = 'true' self.env.update(pkg.eapi_obj.get_ebd_env()) # generate a list of internally implemented EAPI specific functions that shouldn't be exported ret, eapi_funcs = spawn_get_output([ pjoin(const.EAPI_BIN_PATH, 'generate_eapi_func_list.bash'), str(pkg.eapi) ]) if ret != 0: raise Exception( "failed to generate list of EAPI %s specific functions" % str(pkg.eapi)) self.env["PKGCORE_EAPI_FUNCS"] = ' '.join(x.strip() for x in eapi_funcs) self.env_data_source = env_data_source if env_data_source is not None and \ not isinstance(env_data_source, data_source.base): raise TypeError( "env_data_source must be None, or a pkgcore.data_source.base " "derivative: %s: %s" % (env_data_source.__class__, env_data_source)) self.features = set(x.lower() for x in features) self.env["FEATURES"] = ' '.join(sorted(self.features)) iuse_effective_regex = (re.escape(x) for x in pkg.iuse_effective) iuse_effective_regex = "^(%s)$" % "|".join(iuse_effective_regex) iuse_effective_regex = iuse_effective_regex.replace("\\.\\*", ".*") self.env["PKGCORE_IUSE_EFFECTIVE"] = iuse_effective_regex expected_ebuild_env(pkg, self.env, env_source_override=self.env_data_source) self.env["PKGCORE_FINALIZED_RESTRICT"] = ' '.join( str(x) for x in pkg.restrict) self.restrict = pkg.restrict for x in ("sandbox", "userpriv", "fakeroot"): setattr(self, x, self.feat_or_bool(x) and not (x in self.restrict)) if self.fakeroot: logger.warning( "disabling fakeroot; unusable till coreutils/fakeroot" + " interaction is fixed") self.fakeroot = False if self.userpriv and os.getuid() != 0: self.userpriv = False if "PORT_LOGDIR" in self.env: self.logging = pjoin( self.env["PORT_LOGDIR"], "%s:%s:%s.log" % (pkg.cpvstr, self.__class__.__name__, time.strftime("%Y%m%d-%H%M%S", time.localtime()))) del self.env["PORT_LOGDIR"] else: self.logging = False self.env["XARGS"] = xargs self.bashrc = self.env.pop("bashrc", ()) self.pkg = pkg self.eapi = pkg.eapi self.eapi_obj = pkg.eapi_obj wipes = [ k for k, v in self.env.iteritems() if not isinstance(v, basestring) ] for k in wipes: del self.env[k] self.set_op_vars(tmp_offset) self.clean_at_start = clean self.clean_needed = False
def __init__( self, pkg, initial_env=None, env_data_source=None, features=None, observer=None, clean=True, tmp_offset=None, use_override=None, allow_fetching=False, ): """ :param pkg: :class:`pkgcore.ebuild.ebuild_src.package` instance this env is being setup for :param initial_env: initial environment to use for this ebuild :param env_data_source: a :obj:`snakeoil.data_source.base` instance to restore the environment from- used for restoring the state of an ebuild processing, whether for unmerging, or walking phases during building :param features: ebuild features, hold over from portage, will be broken down at some point """ if use_override is not None: use = use_override else: use = pkg.use self.allow_fetching = allow_fetching if not hasattr(self, "observer"): self.observer = observer if not pkg.eapi.is_supported: raise TypeError("package %s uses an unsupported eapi: %s" % (pkg, pkg.eapi)) if initial_env is not None: # copy. self.env = dict(initial_env) for x in ("USE", "ACCEPT_LICENSE"): if x in self.env: del self.env[x] else: self.env = {} if "PYTHONPATH" in os.environ: self.env["PYTHONPATH"] = os.environ["PYTHONPATH"] if features is None: features = self.env.get("FEATURES", ()) # XXX: note this is just EAPI 3 compatibility; not full prefix, soon.. self.env["ROOT"] = self.domain.root self.prefix_mode = pkg.eapi.options.prefix_capable or "force-prefix" in features self.env["PKGCORE_PREFIX_SUPPORT"] = "false" self.prefix = "/" if self.prefix_mode: self.prefix = self.domain.prefix self.env["EPREFIX"] = self.prefix.rstrip("/") self.env["EROOT"] = abspath(pjoin(self.domain.root, self.prefix.lstrip("/"))).rstrip("/") + "/" self.env["PKGCORE_PREFIX_SUPPORT"] = "true" # set the list of internally implemented EAPI specific functions that # shouldn't be exported if os.path.exists(pjoin(const.EBD_PATH, "funcnames", str(pkg.eapi))): with open(pjoin(const.EBD_PATH, "funcnames", str(pkg.eapi)), "r") as f: eapi_funcs = f.readlines() else: ret, eapi_funcs = spawn_get_output([pjoin(const.EBD_PATH, "generate_eapi_func_list.bash"), str(pkg.eapi)]) if ret != 0: raise Exception("failed to generate list of EAPI %s specific functions" % str(pkg.eapi)) self.env["PKGCORE_EAPI_FUNCS"] = " ".join(x.strip() for x in eapi_funcs) self.env_data_source = env_data_source if env_data_source is not None and not isinstance(env_data_source, data_source.base): raise TypeError( "env_data_source must be None, or a pkgcore.data_source.base " "derivative: %s: %s" % (env_data_source.__class__, env_data_source) ) self.features = set(x.lower() for x in features) self.env["FEATURES"] = " ".join(sorted(self.features)) iuse_effective_regex = (re.escape(x) for x in pkg.iuse_effective) iuse_effective_regex = "^(%s)$" % "|".join(iuse_effective_regex) iuse_effective_regex = iuse_effective_regex.replace("\\.\\*", ".*") self.env["PKGCORE_IUSE_EFFECTIVE"] = iuse_effective_regex expected_ebuild_env(pkg, self.env, env_source_override=self.env_data_source) self.env["PKGCORE_FINALIZED_RESTRICT"] = " ".join(str(x) for x in pkg.restrict) self.restrict = pkg.restrict for x in ("sandbox", "userpriv"): setattr(self, x, self.feat_or_bool(x) and not (x in self.restrict)) if self.userpriv and os.getuid() != 0: self.userpriv = False if "PORT_LOGDIR" in self.env: self.logging = pjoin( self.env["PORT_LOGDIR"], "%s:%s:%s.log" % (pkg.cpvstr, self.__class__.__name__, time.strftime("%Y%m%d-%H%M%S", time.localtime())), ) del self.env["PORT_LOGDIR"] else: self.logging = False self.env["XARGS"] = xargs self.bashrc = self.env.pop("bashrc", ()) self.pkg = pkg self.eapi = pkg.eapi wipes = [k for k, v in self.env.iteritems() if not isinstance(v, basestring)] for k in wipes: del self.env[k] self.set_op_vars(tmp_offset) self.clean_at_start = clean self.clean_needed = False
def __init__(self, pkg, initial_env=None, env_data_source=None, features=None, observer=None, clean=True, tmp_offset=None, use_override=None, allow_fetching=False): """ :param pkg: :class:`pkgcore.ebuild.ebuild_src.package` instance this env is being setup for :param initial_env: initial environment to use for this ebuild :param env_data_source: a :obj:`snakeoil.data_source.base` instance to restore the environment from- used for restoring the state of an ebuild processing, whether for unmerging, or walking phases during building :param features: ebuild features, hold over from portage, will be broken down at some point """ if use_override is not None: use = use_override else: use = pkg.use self.allow_fetching = allow_fetching if not hasattr(self, "observer"): self.observer = observer if not pkg.eapi.is_supported: raise TypeError("package %s uses an unsupported eapi: %s" % (pkg, pkg.eapi)) if initial_env is not None: # copy. self.env = dict(initial_env) for x in ("USE", "ACCEPT_LICENSE"): if x in self.env: del self.env[x] else: self.env = {} if "PYTHONPATH" in os.environ: self.env["PYTHONPATH"] = os.environ["PYTHONPATH"] if features is None: features = self.env.get("FEATURES", ()) # XXX: note this is just EAPI 3 compatibility; not full prefix, soon.. self.env["ROOT"] = self.domain.root self.prefix_mode = pkg.eapi.options.prefix_capable or 'force-prefix' in features self.env["PKGCORE_PREFIX_SUPPORT"] = 'false' self.prefix = '/' if self.prefix_mode: self.prefix = self.domain.prefix self.env['EPREFIX'] = self.prefix.rstrip('/') self.env['EROOT'] = abspath( pjoin(self.domain.root, self.prefix.lstrip('/'))).rstrip('/') + '/' self.env["PKGCORE_PREFIX_SUPPORT"] = 'true' # set the list of internally implemented EAPI specific functions that # shouldn't be exported if os.path.exists(pjoin(const.EBD_PATH, 'funcnames', str(pkg.eapi))): with open(pjoin(const.EBD_PATH, 'funcnames', str(pkg.eapi)), 'r') as f: eapi_funcs = f.readlines() else: ret, eapi_funcs = spawn_get_output([ pjoin(const.EBD_PATH, 'generate_eapi_func_list.bash'), str(pkg.eapi) ]) if ret != 0: raise Exception( "failed to generate list of EAPI %s specific functions" % str(pkg.eapi)) self.env["PKGCORE_EAPI_FUNCS"] = ' '.join(x.strip() for x in eapi_funcs) self.env_data_source = env_data_source if (env_data_source is not None and not isinstance(env_data_source, data_source.base)): raise TypeError( "env_data_source must be None, or a pkgcore.data_source.base " "derivative: %s: %s" % (env_data_source.__class__, env_data_source)) self.features = set(x.lower() for x in features) self.env["FEATURES"] = ' '.join(sorted(self.features)) iuse_effective_regex = (re.escape(x) for x in pkg.iuse_effective) iuse_effective_regex = "^(%s)$" % "|".join(iuse_effective_regex) iuse_effective_regex = iuse_effective_regex.replace("\\.\\*", ".*") self.env["PKGCORE_IUSE_EFFECTIVE"] = iuse_effective_regex expected_ebuild_env(pkg, self.env, env_source_override=self.env_data_source) self.env["PKGCORE_FINALIZED_RESTRICT"] = ' '.join( str(x) for x in pkg.restrict) self.restrict = pkg.restrict for x in ("sandbox", "userpriv"): setattr(self, x, self.feat_or_bool(x) and not (x in self.restrict)) if self.userpriv and os.getuid() != 0: self.userpriv = False if "PORT_LOGDIR" in self.env: self.logging = pjoin( self.env["PORT_LOGDIR"], "%s:%s:%s.log" % (pkg.cpvstr, self.__class__.__name__, time.strftime("%Y%m%d-%H%M%S", time.localtime()))) del self.env["PORT_LOGDIR"] else: self.logging = False self.env["XARGS"] = xargs self.bashrc = self.env.pop("bashrc", ()) self.pkg = pkg self.eapi = pkg.eapi wipes = [ k for k, v in self.env.iteritems() if not isinstance(v, basestring) ] for k in wipes: del self.env[k] self.set_op_vars(tmp_offset) self.clean_at_start = clean self.clean_needed = False
def __init__(self, domain, pkg, verified_files, eclass_cache, observer=None, **kwargs): """ :param pkg: :obj:`pkgcore.ebuild.ebuild_src.package` instance we'll be building :param domain_settings: dict bled down from the domain configuration; basically initial env :param eclass_cache: the :class:`pkgcore.ebuild.eclass_cache` we'll be using :param files: mapping of fetchables mapped to their disk location """ use = kwargs.get("use_override", pkg.use) domain_settings = domain.settings format.build.__init__(self, domain, pkg, verified_files, observer) ebd.__init__(self, pkg, initial_env=domain_settings, features=domain_settings["FEATURES"], **kwargs) self.env["FILESDIR"] = pjoin(os.path.dirname(pkg.ebuild.path), "files") self.eclass_cache = eclass_cache self.env["ECLASSDIR"] = eclass_cache.eclassdir portdir = self.env["PORTDIR"] = eclass_cache.portdir if portdir is None: del self.env["PORTDIR"] self.run_test = self.feat_or_bool("test", domain_settings) self.allow_failed_test = self.feat_or_bool("test-fail-continue", domain_settings) if "test" in self.restrict: self.run_test = False elif "test" not in use: if self.run_test: logger.warning("disabling test for %s due to test use flag being disabled" % pkg) self.run_test = False # XXX minor hack path = self.env["PATH"].split(":") for s, default in (("DISTCC", ".distcc"), ("CCACHE", "ccache")): b = (self.feat_or_bool(s, domain_settings) and not s in self.restrict) setattr(self, s.lower(), b) if b: # looks weird I realize, but # pjoin("/foor/bar", "/barr/foo") == "/barr/foo" # and pjoin("/foo/bar", ".asdf") == "/foo/bar/.asdf" self.env.setdefault(s+"_DIR", pjoin(self.tmpdir, default)) # gentoo bug 355283 libdir = self.env.get("ABI") if libdir is not None: libdir = self.env.get("LIBDIR_%s" % (libdir,)) if libdir is not None: libdir = self.env.get(libdir) if libdir is None: libdir = "lib" path.insert(0, "/usr/%s/%s/bin" % (libdir, s.lower())) else: for y in ("_PATH", "_DIR"): if s+y in self.env: del self.env[s+y] path = [piece for piece in path if piece] self.env["PATH"] = ":".join(path) self.env["A"] = ' '.join(set(x.filename for x in pkg.fetchables)) if self.eapi_obj.options.has_AA: pkg = getattr(self.pkg, '_raw_pkg', self.pkg) self.env["AA"] = ' '.join(set(x.filename for x in iflatten_instance(pkg.fetchables, fetch.fetchable))) if self.eapi_obj.options.has_KV: ret = spawn_get_output(['uname', '-r']) if ret[0] == 0: self.env["KV"] = ret[1][0].strip() if self.eapi_obj.options.has_merge_type: self.env["MERGE_TYPE"] = "source" if self.setup_is_for_src: self.init_distfiles_env()