diff options
-rw-r--r-- | NEWS.rst | 5 | ||||
-rw-r--r-- | doc/dev-notes/TODO.rst | 6 | ||||
-rw-r--r-- | doc/dev-notes/feature-breakdown.rst | 4 | ||||
-rw-r--r-- | doc/dev-notes/tackling-domain.rst | 1 | ||||
-rw-r--r-- | pkgcore/const.py | 4 | ||||
-rw-r--r-- | pkgcore/ebuild/ebd.py | 66 | ||||
-rw-r--r-- | pkgcore/ebuild/processor.py | 64 | ||||
-rw-r--r-- | pkgcore/spawn.py | 94 | ||||
-rw-r--r-- | pkgcore/test/test_spawn.py | 60 |
9 files changed, 47 insertions, 257 deletions
@@ -5,9 +5,12 @@ Release Notes See ChangeLog for full commit logs; this is summarized/major changes. -------------------------- -pkgcore 0.9.3 (2015-??-??) +pkgcore 0.9.3 (2016-??-??) -------------------------- +- Remove FEATURES=fakeroot support, it hasn't fully worked for years, doesn't + work with with sandbox, and should be replaced with some namespacing support. + - pmaint regen: Fix cache compatibility issues with egencache, i.e. a cache generated by pmaint regen should be able to be used as is by portage without it regenerating the cache again. diff --git a/doc/dev-notes/TODO.rst b/doc/dev-notes/TODO.rst index e1fd1395..43803f07 100644 --- a/doc/dev-notes/TODO.rst +++ b/doc/dev-notes/TODO.rst @@ -49,12 +49,6 @@ Rough TODO _cpv is in use; 'nuff said, look in pkgcore.ebuild.cpv.cpy_ver_cmp -- testing of fakeroot integration - - it was working back in the ebd branch days; things have changed since then - (heavily), enabling/disabling should work fine, but will need to take a look - at the contentset generation to ensure perms/gid leaks through correctly. - - modify repository.prototype.tree.match to take an optional comparison reasoning being that if we're just going to do a max, pass in the max so it diff --git a/doc/dev-notes/feature-breakdown.rst b/doc/dev-notes/feature-breakdown.rst index 7855a49c..080a0fc5 100644 --- a/doc/dev-notes/feature-breakdown.rst +++ b/doc/dev-notes/feature-breakdown.rst @@ -35,7 +35,6 @@ relevant list of features * suidctl * test * userpriv -* userpriv_fakeroot * usersandbox Undefined @@ -55,8 +54,7 @@ Build ----- * keeptemp, keepwork, noclean, ccache, distcc -* sandbox, userpriv, fakeroot -* userpriv_fakeroot becomes fakeroot +* sandbox, userpriv * confcache * noauto (fun one) * test diff --git a/doc/dev-notes/tackling-domain.rst b/doc/dev-notes/tackling-domain.rst index 67238326..e42a85d8 100644 --- a/doc/dev-notes/tackling-domain.rst +++ b/doc/dev-notes/tackling-domain.rst @@ -7,7 +7,6 @@ tag a 'x' in front of stuff that's been implemented unhandled (eg, figure these out) vars/features - (user)?sandbox -- userpriv(_fakeroot)? - digest - cvs (this option is a hack) - fixpackages , which probably should be a sync thing (would need to diff --git a/pkgcore/const.py b/pkgcore/const.py index ebe6d784..8662a4e8 100644 --- a/pkgcore/const.py +++ b/pkgcore/const.py @@ -29,10 +29,6 @@ COPY_BINARY = find_binary('cp') HOST_NONROOT_PATHS = ("/usr/local/bin", "/usr/bin", "/bin") -# no longer used. -LIBFAKEROOT_PATH = "/usr/lib/libfakeroot.so" -FAKED_PATH = "/usr/bin/faked" - def _GET_CONST(attr, default_value, allow_environment_override=False): consts = mappings.ProxiedAttrs(sys.modules[__name__]) diff --git a/pkgcore/ebuild/ebd.py b/pkgcore/ebuild/ebd.py index d1dddf6e..7dedd2a3 100644 --- a/pkgcore/ebuild/ebd.py +++ b/pkgcore/ebuild/ebd.py @@ -34,8 +34,7 @@ from pkgcore.ebuild.processor import ( from pkgcore.operations import observer, format from pkgcore.os_data import portage_gid, portage_uid, xargs from pkgcore.spawn import ( - spawn_bash, spawn, is_sandbox_capable, is_fakeroot_capable, - is_userpriv_capable, spawn_get_output) + spawn_bash, spawn, is_sandbox_capable, is_userpriv_capable, spawn_get_output) demandload( 'textwrap', @@ -143,12 +142,8 @@ class ebd(object): self.restrict = pkg.restrict - for x in ("sandbox", "userpriv", "fakeroot"): + for x in ("sandbox", "userpriv"): 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 @@ -271,17 +266,14 @@ class ebd(object): logger.warning("%s ( %s ) is setgid" % (self.env[k], k)) - def _generic_phase(self, phase, userpriv, sandbox, fakeroot, - extra_handlers={}, failure_allowed=False, - suppress_bashrc=False): + def _generic_phase(self, phase, userpriv, sandbox, extra_handlers={}, + failure_allowed=False, suppress_bashrc=False): """ :param phase: phase to execute :param userpriv: will we drop to :obj:`pkgcore.os_data.portage_uid` and :obj:`pkgcore.os_data.portage_gid` access for this phase? :param sandbox: should this phase be sandboxed? - :param fakeroot: should the phase be fakeroot'd? Only really useful - for install phase, and is mutually exclusive with sandbox """ if phase not in self.pkg.mandatory_phases: # TODO(ferringb): Note the preinst hack; this will be removed once dyn_pkg_preinst @@ -292,13 +284,12 @@ class ebd(object): return True userpriv = self.userpriv and userpriv sandbox = self.sandbox and sandbox - fakeroot = self.fakeroot and fakeroot self._set_per_phase_env(phase, self.env) extra_handlers = extra_handlers.copy() if not suppress_bashrc: extra_handlers.setdefault("request_bashrcs", self._request_bashrcs) - return run_generic_phase(self.pkg, phase, self.env, - userpriv, sandbox, fakeroot, + return run_generic_phase( + self.pkg, phase, self.env, userpriv, sandbox, extra_handlers=extra_handlers, failure_allowed=failure_allowed, logging=self.logging) @@ -408,11 +399,11 @@ class setup_mixin(object): additional_commands["request_inherit"] = partial(inherit_handler, self.eclass_cache) - return self._generic_phase(phase_name, False, True, False, - extra_handlers=additional_commands) + return self._generic_phase( + phase_name, False, True, extra_handlers=additional_commands) -def run_generic_phase(pkg, phase, env, userpriv, sandbox, fakeroot, +def run_generic_phase(pkg, phase, env, userpriv, sandbox, extra_handlers=None, failure_allowed=False, logging=None): """ :param phase: phase to execute @@ -421,8 +412,6 @@ def run_generic_phase(pkg, phase, env, userpriv, sandbox, fakeroot, :obj:`pkgcore.os_data.portage_uid` and :obj:`pkgcore.os_data.portage_gid` access for this phase? :param sandbox: should this phase be sandboxed? - :param fakeroot: should the phase be fakeroot'd? Only really useful - for install phase, and is mutually exclusive with sandbox :param extra_handlers: extra command handlers :type extra_handlers: mapping from string to callable :param failure_allowed: allow failure without raising error @@ -433,13 +422,11 @@ def run_generic_phase(pkg, phase, env, userpriv, sandbox, fakeroot, userpriv = userpriv and is_userpriv_capable() sandbox = sandbox and is_sandbox_capable() - fakeroot = fakeroot and is_fakeroot_capable() if env is None: env = expected_ebuild_env(pkg) - ebd = request_ebuild_processor(userpriv=userpriv, sandbox=sandbox, - fakeroot=fakeroot) + ebd = request_ebuild_processor(userpriv=userpriv, sandbox=sandbox) # this is a bit of a hack; used until ebd accepts observers that handle # the output redirection on its own. Primary relevance is when # stdout/stderr are pointed at a file; we leave buffering on, just @@ -479,12 +466,12 @@ class install_op(ebd, format.install): preinst = pretty_docs( observer.decorate_build_method("preinst")( post_curry( - ebd._generic_phase, "preinst", False, False, False)), + ebd._generic_phase, "preinst", False, False)), "run the postinst phase") postinst = pretty_docs( observer.decorate_build_method("postinst")( post_curry( - ebd._generic_phase, "postinst", False, False, False)), + ebd._generic_phase, "postinst", False, False)), "run the postinst phase") def add_triggers(self, domain_op, engine): @@ -503,12 +490,12 @@ class uninstall_op(ebd, format.uninstall): prerm = pretty_docs( observer.decorate_build_method("prerm")( post_curry( - ebd._generic_phase, "prerm", False, False, False)), + ebd._generic_phase, "prerm", False, False)), "run the prerm phase") postrm = pretty_docs( observer.decorate_build_method("postrm")( post_curry( - ebd._generic_phase, "postrm", False, False, False, + ebd._generic_phase, "postrm", False, False, failure_allowed=True)), "run the postrm phase") @@ -769,7 +756,7 @@ class buildable(ebd, setup_mixin, format.build): separated configure phase). """ if "configure" in self.eapi_obj.phases: - return self._generic_phase("configure", True, True, False) + return self._generic_phase("configure", True, True) return True def prepare(self): @@ -779,7 +766,7 @@ class buildable(ebd, setup_mixin, format.build): does nothing if the pkg's EAPI is less than 2 """ if "prepare" in self.eapi_obj.phases: - return self._generic_phase("prepare", True, True, False) + return self._generic_phase("prepare", True, True) return True def nofetch(self): @@ -802,29 +789,26 @@ class buildable(ebd, setup_mixin, format.build): raise_from(format.GenericBuildError( "failed forcing %i uid for WORKDIR: %s" % (portage_uid, str(oe)))) - return self._generic_phase("unpack", True, True, False) + return self._generic_phase("unpack", True, True) compile = pretty_docs( observer.decorate_build_method("compile")( post_curry( - ebd._generic_phase, "compile", True, True, False)), + ebd._generic_phase, "compile", True, True)), "run the compile phase (maps to src_compile)") @observer.decorate_build_method("install") def install(self): """run the install phase (maps to src_install)""" - if self.fakeroot: - return self._generic_phase("install", True, False, True) - else: - return self._generic_phase("install", False, True, False) + return self._generic_phase("install", False, True) @observer.decorate_build_method("test") def test(self): """run the test phase (if enabled), maps to src_test""" if not self.run_test: return True - return self._generic_phase("test", True, True, False, - failure_allowed=self.allow_failed_test) + return self._generic_phase( + "test", True, True, failure_allowed=self.allow_failed_test) def finalize(self): """ @@ -893,8 +877,8 @@ class ebuild_mixin(object): try: logger.debug("running ebuild pkg_pretend sanity check for %s", pkg.cpvstr) start = time.time() - ret = run_generic_phase(pkg, "pretend", env, userpriv=True, sandbox=True, - fakeroot=False, extra_handlers=commands) + ret = run_generic_phase( + pkg, "pretend", env, userpriv=True, sandbox=True, extra_handlers=commands) logger.debug("pkg_pretend sanity check for %s took %2.2f seconds", pkg.cpvstr, time.time() - start) return ret @@ -937,10 +921,10 @@ class misc_operations(ebd): ebd.__init__(self, *args, **kwds) def configure(self, observer=None): - return self._generic_phase('config', False, True, False) + return self._generic_phase('config', False, True) def info(self, observer=None): - return self._generic_phase('info', True, True, False) + return self._generic_phase('info', True, True) class built_operations(ebuild_mixin, format.operations): diff --git a/pkgcore/ebuild/processor.py b/pkgcore/ebuild/processor.py index b7068037..376a02c2 100644 --- a/pkgcore/ebuild/processor.py +++ b/pkgcore/ebuild/processor.py @@ -108,37 +108,29 @@ pkgcore.spawn.atexit_register(shutdown_all_processors) @_single_thread_allowed -def request_ebuild_processor(userpriv=False, sandbox=None, fakeroot=False, - save_file=None): +def request_ebuild_processor(userpriv=False, sandbox=None): """ request an ebuild_processor instance, creating a new one if needed. - Note that fakeroot processes are B{never} reused due to the fact - the fakeroot env becomes localized to the pkg its handling. - :return: :obj:`EbuildProcessor` :param userpriv: should the processor be deprived to :obj:`pkgcore.os_data.portage_gid` and :obj:`pkgcore.os_data.portage_uid`? :param sandbox: should the processor be sandboxed? - :param fakeroot: should the processor be fakerooted? This option is - mutually exclusive to sandbox, and requires save_file to be set. - :param save_file: location to store fakeroot state dumps """ if sandbox is None: sandbox = pkgcore.spawn.is_sandbox_capable() - if not fakeroot: - for x in inactive_ebp_list: - if x.userprived() == userpriv and (x.sandboxed() or not sandbox): - if not x.is_alive: - inactive_ebp_list.remove(x) - continue + for x in inactive_ebp_list: + if x.userprived() == userpriv and (x.sandboxed() or not sandbox): + if not x.is_alive: inactive_ebp_list.remove(x) - active_ebp_list.append(x) - return x + continue + inactive_ebp_list.remove(x) + active_ebp_list.append(x) + return x - e = EbuildProcessor(userpriv, sandbox, fakeroot, save_file) + e = EbuildProcessor(userpriv, sandbox) active_ebp_list.append(e) return e @@ -150,7 +142,6 @@ def release_ebuild_processor(ebp): Any processor requested via request_ebuild_processor B{must} be released via this function once it's no longer in use. - This includes fakerooted processors. :param ebp: :obj:`EbuildProcessor` instance :return: boolean indicating release results- if the processor isn't known @@ -165,9 +156,7 @@ def release_ebuild_processor(ebp): return False assert ebp not in inactive_ebp_list - # if it's a fakeroot'd process, we throw it away. - # it's not useful outside of a chain of calls - if ebp.onetime() or ebp.locked: + if ebp.locked: # ok, so the thing is not reusable either way. ebp.shutdown_processor() else: @@ -264,14 +253,10 @@ class EbuildProcessor(object): __metaclass__ = WeakRefFinalizer - def __init__(self, userpriv, sandbox, fakeroot, save_file): + def __init__(self, userpriv, sandbox): """ :param sandbox: enables a sandboxed processor :param userpriv: enables a userpriv'd processor - :param fakeroot: enables a fakeroot'd processor- - this is a mutually exclusive option to sandbox, and - requires userpriv to be enabled. Violating this will - result in nastiness. """ self.lock() @@ -283,11 +268,6 @@ class EbuildProcessor(object): self._outstanding_expects = [] self._metadata_paths = None - if fakeroot and (sandbox or not userpriv): - traceback.print_stack() - logger.error("Both sandbox and fakeroot cannot be enabled at the same time") - raise InitializationError("cannot initialize with sandbox and fakeroot") - if userpriv: self.__userpriv = True spawn_opts.update({ @@ -304,10 +284,9 @@ class EbuildProcessor(object): cread, cwrite = os.pipe() dread, dwrite = os.pipe() self.__sandbox = False - self.__fakeroot = False # since it's questionable which spawn method we'll use (if - # sandbox or fakeroot fex), we ensure the bashrc is invalid. + # sandbox fex), we ensure the bashrc is invalid. env = {x: "/etc/portage/spork/not/valid/ha/ha" for x in ("BASHRC", "BASH_ENV")} @@ -329,22 +308,13 @@ class EbuildProcessor(object): if sandbox: if not pkgcore.spawn.is_sandbox_capable(): raise ValueError("spawn lacks sandbox capabilities") - if fakeroot: - raise InitializationError('fakeroot was on, but sandbox was also on') self.__sandbox = True spawn_func = pkgcore.spawn.spawn_sandbox # env.update({"SANDBOX_DEBUG":"1", "SANDBOX_DEBUG_LOG":"/var/tmp/test"}) - - elif fakeroot: - if not pkgcore.spawn.is_fakeroot_capable(): - raise ValueError("spawn lacks fakeroot capabilities") - self.__fakeroot = True - spawn_func = pkgcore.spawn.spawn_fakeroot - args.append(save_file) else: spawn_func = pkgcore.spawn.spawn - # force to a neutral dir so that sandbox/fakeroot won't explode if + # force to a neutral dir so that sandbox won't explode if # ran from a nonexistent dir spawn_opts["cwd"] = e_const.EAPI_BIN_PATH # Force the pipes to be high up fd wise so nobody stupidly hits 'em, we @@ -425,14 +395,6 @@ class EbuildProcessor(object): """is this instance userprived?""" return self.__userpriv - def fakerooted(self): - """is this instance fakerooted?""" - return self.__fakeroot - - def onetime(self): - """Is this instance going to be discarded after usage (fakerooted)?""" - return self.__fakeroot - def write(self, string, flush=True, disable_runtime_exceptions=False, append_newline=True): """send something to the bash side. diff --git a/pkgcore/spawn.py b/pkgcore/spawn.py index baac5137..c5e20622 100644 --- a/pkgcore/spawn.py +++ b/pkgcore/spawn.py @@ -9,7 +9,7 @@ subprocess related functionality """ __all__ = [ - "cleanup_pids", "spawn", "spawn_sandbox", "spawn_bash", "spawn_fakeroot", + "cleanup_pids", "spawn", "spawn_sandbox", "spawn_bash", "spawn_get_output", ] @@ -24,8 +24,7 @@ from snakeoil.mappings import ProtectedDict from snakeoil.osutils import access from snakeoil.process import find_binary, CommandNotFound, closerange -from pkgcore.const import ( - BASH_BINARY, SANDBOX_BINARY, FAKED_PATH, LIBFAKEROOT_PATH) +from pkgcore.const import BASH_BINARY, SANDBOX_BINARY demandload( 'pkgcore.log:logger', @@ -307,81 +306,13 @@ def _exec(binary, mycommand, name=None, fd_pipes=None, env=None, gid=None, os.execve(binary, myargs, env) -def spawn_fakeroot(mycommand, save_file, env=None, name=None, - returnpid=False, **keywords): - """spawn a process via fakeroot - - refer to the fakeroot manpage for specifics of using fakeroot - """ - if env is None: - env = {} - else: - env = ProtectedDict(env) - - if name is None: - name = "fakeroot %s" % mycommand - - args = [ - FAKED_PATH, - "--unknown-is-real", "--foreground", "--save-file", save_file] - - rd_fd, wr_fd = os.pipe() - daemon_fd_pipes = {1: wr_fd, 2: wr_fd} - if os.path.exists(save_file): - args.append("--load") - daemon_fd_pipes[0] = os.open(save_file, os.O_RDONLY) - else: - daemon_fd_pipes[0] = os.open("/dev/null", os.O_RDONLY) - - pids = None - pids = spawn(args, fd_pipes=daemon_fd_pipes, returnpid=True) - try: - try: - rd_f = os.fdopen(rd_fd) - line = rd_f.readline() - rd_f.close() - rd_fd = None - except: - cleanup_pids(pids) - raise - finally: - for x in (rd_fd, wr_fd, daemon_fd_pipes[0]): - if x is not None: - try: - os.close(x) - except OSError: - pass - - line = line.strip() - - try: - fakekey, fakepid = map(int, line.split(":")) - except ValueError: - raise ExecutionFailure("output from faked was unparsable- %s" % line) - - # by now we have our very own daemonized faked. yay. - env["FAKEROOTKEY"] = str(fakekey) - paths = [LIBFAKEROOT_PATH] + env.get("LD_PRELOAD", "").split(":") - env["LD_PRELOAD"] = ":".join(x for x in paths if x) - - try: - ret = spawn( - mycommand, name=name, env=env, returnpid=returnpid, - **keywords) - if returnpid: - return ret + [fakepid] + pids - return ret - finally: - if not returnpid: - cleanup_pids([fakepid] + pids) - def spawn_get_output(mycommand, spawn_type=None, raw_exit_code=False, collect_fds=(1,), fd_pipes=None, split_lines=True, **keywords): """Call spawn, collecting the output to fd's specified in collect_fds list. - :param spawn_type: the passed in function to call- typically :func:`spawn_bash`, - :func:`spawn`, :func:`spawn_sandbox`, or :func:`spawn_fakeroot`. + :param spawn_type: the passed in function to call- typically :func:`spawn_bash` + :func:`spawn`, or :func:`spawn_sandbox`. Defaults to :func:`spawn`. """ @@ -456,23 +387,6 @@ class ExecutionFailure(Exception): # cached capabilities -def is_fakeroot_capable(force=False): - if not force: - try: - return is_fakeroot_capable.cached_result - except AttributeError: - pass - if not (os.path.exists(FAKED_PATH) and os.path.exists(LIBFAKEROOT_PATH)): - res = False - else: - try: - r, s = spawn_get_output(["fakeroot", "--version"], fd_pipes={2: 1, 1: 1}) - res = (r == 0) and (len(s) == 1) and ("version 1." in s[0]) - except ExecutionFailure: - res = False - is_fakeroot_capable.cached_result = res - return res - def is_sandbox_capable(force=False): if not force: try: diff --git a/pkgcore/test/test_spawn.py b/pkgcore/test/test_spawn.py index 9b54d705..b2e533c1 100644 --- a/pkgcore/test/test_spawn.py +++ b/pkgcore/test/test_spawn.py @@ -108,66 +108,6 @@ class SpawnTest(TempDirMixin, TestCase): if cwd is not None: os.chdir(cwd) - @capability_based(spawn.is_fakeroot_capable, - "fakeroot binary wasn't found") - 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" % - process.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) - test_fakeroot.skip = "test is flakey w/ recent versions of fakeroot; capabilities unused atm also" - def test_process_exit_code(self): self.assertEqual(0, spawn.process_exit_code(0), "exit code failed") self.assertEqual( |