From 50daef1ab961c42a3352281e915da5a89297e3a9 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 30 Aug 2010 20:55:11 -0700 Subject: Bug #335340 - Add support for PORTAGE_BZIP2_COMMAND and PORTAGE_BUNZIP2_COMMAND settings in make.conf. This only adds support for binary packages, since that's where pbzip2 can provide the most benefit in common cases. --- pym/_emerge/Binpkg.py | 1 + pym/_emerge/BinpkgEnvExtractor.py | 2 +- pym/_emerge/BinpkgExtractorAsync.py | 3 +- .../package/ebuild/_config/env_var_validation.py | 23 +++++++++++++ .../package/ebuild/_config/special_env_vars.py | 14 +++++--- pym/portage/package/ebuild/config.py | 39 +++++++++++++++++++++- 6 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 pym/portage/package/ebuild/_config/env_var_validation.py (limited to 'pym') diff --git a/pym/_emerge/Binpkg.py b/pym/_emerge/Binpkg.py index cfb32ad5d..ac9a68a0f 100644 --- a/pym/_emerge/Binpkg.py +++ b/pym/_emerge/Binpkg.py @@ -274,6 +274,7 @@ class Binpkg(CompositeTask): return extractor = BinpkgExtractorAsync(background=self.background, + env=self.settings.environ(), image_dir=self._image_dir, pkg=self.pkg, pkg_path=self._pkg_path, logfile=self.settings.get("PORTAGE_LOG_FILE"), diff --git a/pym/_emerge/BinpkgEnvExtractor.py b/pym/_emerge/BinpkgEnvExtractor.py index 77060589a..f68971b35 100644 --- a/pym/_emerge/BinpkgEnvExtractor.py +++ b/pym/_emerge/BinpkgEnvExtractor.py @@ -30,7 +30,7 @@ class BinpkgEnvExtractor(CompositeTask): def _start(self): saved_env_path = self._get_saved_env_path() dest_env_path = self._get_dest_env_path() - shell_cmd = "bzip2 -dc %s > %s" % \ + shell_cmd = "${PORTAGE_BUNZIP2_COMMAND:-${PORTAGE_BZIP2_COMMAND} -d} -c -- %s > %s" % \ (_shell_quote(saved_env_path), _shell_quote(dest_env_path)) extractor_proc = SpawnProcess( diff --git a/pym/_emerge/BinpkgExtractorAsync.py b/pym/_emerge/BinpkgExtractorAsync.py index a2bbe7a45..004544e92 100644 --- a/pym/_emerge/BinpkgExtractorAsync.py +++ b/pym/_emerge/BinpkgExtractorAsync.py @@ -16,7 +16,7 @@ class BinpkgExtractorAsync(SpawnProcess): # SIGPIPE handling (128 + SIGPIPE) should be compatible with # assert_sigpipe_ok() that's used by the ebuild unpack() helper. self.args = [self._shell_binary, "-c", - ("bzip2 -dqc -- %s | tar -xp -C %s -f - ; " + \ + ("${PORTAGE_BUNZIP2_COMMAND:-${PORTAGE_BZIP2_COMMAND} -d} -c -- %s | tar -xp -C %s -f - ; " + \ "p=(${PIPESTATUS[@]}) ; " + \ "if [[ ${p[0]} != 0 && ${p[0]} != %d ]] ; then " % (128 + signal.SIGPIPE) + \ "echo bzip2 failed with status ${p[0]} ; exit ${p[0]} ; fi ; " + \ @@ -26,5 +26,4 @@ class BinpkgExtractorAsync(SpawnProcess): (portage._shell_quote(self.pkg_path), portage._shell_quote(self.image_dir))] - self.env = os.environ.copy() SpawnProcess._start(self) diff --git a/pym/portage/package/ebuild/_config/env_var_validation.py b/pym/portage/package/ebuild/_config/env_var_validation.py new file mode 100644 index 000000000..d3db545cb --- /dev/null +++ b/pym/portage/package/ebuild/_config/env_var_validation.py @@ -0,0 +1,23 @@ +# Copyright 2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage import os +from portage.process import find_binary +from portage.util import shlex_split + +def validate_cmd_var(v): + """ + Validate an evironment variable value to see if it + contains an executable command as the first token. + returns (valid, token_list) where 'valid' is boolean and 'token_list' + is the (possibly empty) list of tokens split by shlex. + """ + invalid = False + v_split = shlex_split(v) + if not v_split: + invalid = True + elif os.path.isabs(v_split[0]): + invalid = not os.access(v_split[0], os.EX_OK) + elif find_binary(v_split[0]) is None: + invalid = True + return (not invalid, v_split) diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py index 2a515dd0d..4a29b1446 100644 --- a/pym/portage/package/ebuild/_config/special_env_vars.py +++ b/pym/portage/package/ebuild/_config/special_env_vars.py @@ -43,7 +43,8 @@ environ_whitelist += [ "PORTAGE_BINPKG_FILE", "PORTAGE_BINPKG_TAR_OPTS", "PORTAGE_BINPKG_TMPFILE", "PORTAGE_BIN_PATH", - "PORTAGE_BUILDDIR", "PORTAGE_COLORMAP", + "PORTAGE_BUILDDIR", "PORTAGE_BUNZIP2_COMMAND", "PORTAGE_BZIP2_COMMAND", + "PORTAGE_COLORMAP", "PORTAGE_CONFIGROOT", "PORTAGE_DEBUG", "PORTAGE_DEPCACHEDIR", "PORTAGE_EBUILD_EXIT_FILE", "PORTAGE_FEATURES", "PORTAGE_GID", "PORTAGE_GRPNAME", @@ -152,10 +153,13 @@ environ_filter += [ environ_filter = frozenset(environ_filter) -default_globals = ( - ('ACCEPT_LICENSE', '* -@EULA'), - ('ACCEPT_PROPERTIES', '*'), -) +default_globals = { + 'ACCEPT_LICENSE': '* -@EULA', + 'ACCEPT_PROPERTIES': '*', + 'PORTAGE_BZIP2_COMMAND': 'bzip2', +} + +validate_commands = ('PORTAGE_BZIP2_COMMAND', 'PORTAGE_BUNZIP2_COMMAND',) # To enhance usability, make some vars case insensitive # by forcing them to lower case. diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index 847ac1ccb..01950f9af 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -46,6 +46,7 @@ from portage.util import ensure_dirs, getconfig, grabdict, \ from portage.versions import catpkgsplit, catsplit, cpv_getkey from portage.package.ebuild._config import special_env_vars +from portage.package.ebuild._config.env_var_validation import validate_cmd_var from portage.package.ebuild._config.features_set import features_set from portage.package.ebuild._config.LicenseManager import LicenseManager from portage.package.ebuild._config.UseManager import UseManager @@ -444,7 +445,7 @@ class config(object): if self.mygcfg is None: self.mygcfg = {} - for k, v in self._default_globals: + for k, v in self._default_globals.items(): self.mygcfg.setdefault(k, v) self.configlist.append(self.mygcfg) @@ -773,6 +774,8 @@ class config(object): self._iuse_implicit_match = _iuse_implicit_match_cache(self) + self._validate_commands() + for k in self._case_insensitive_vars: if k in self: self[k] = self[k].lower() @@ -781,6 +784,40 @@ class config(object): if mycpv: self.setcpv(mycpv) + def _validate_commands(self): + for k in special_env_vars.validate_commands: + v = self.get(k) + if v is not None: + valid, v_split = validate_cmd_var(v) + + if not valid: + if v_split: + writemsg_level(_("%s setting is invalid: '%s'\n") % \ + (k, v), level=logging.ERROR, noiselevel=-1) + + # before deleting the invalid setting, backup + # the default value if available + v = self.configdict['globals'].get(k) + if v is not None: + default_valid, v_split = validate_cmd_var(v) + if not default_valid: + if v_split: + writemsg_level( + _("%s setting from make.globals" + \ + " is invalid: '%s'\n") % \ + (k, v), level=logging.ERROR, noiselevel=-1) + # make.globals seems corrupt, so try for + # a hardcoded default instead + v = self._default_globals.get(k) + + # delete all settings for this key, + # including the invalid one + del self[k] + self.backupenv.pop(k, None) + if v: + # restore validated default + self.configdict['globals'][k] = v + def _init_dirs(self): """ Create a few directories that are critical to portage operation -- cgit v1.2.3-1-g7c22