From 9384b93b8ee7fba7ca70f42e384cb4743515f848 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Fri, 22 Jun 2007 08:42:54 +0000 Subject: [PATCH] Merged from trunk 6868:6889 +------------------------------------------------------------------------+ | 6869 | Add PORTAGE_BIN_PATH to the environment since it's used by | | zmedico | dobin to locate isolated-functions.sh. | |---------+--------------------------------------------------------------| | 6870 | Add a test case for the logfile functionality of | | zmedico | portage.spawn(). | |---------+--------------------------------------------------------------| | 6871 | For bug #182428, make quickpkg use a more secure umask by | | zmedico | default and allow it to be overridden by a --umask option. | | | Add support for QUICKPKG_DEFAULT_OPTS so that default | | | options can be set in make.conf. | |---------+--------------------------------------------------------------| | 6873 | For bug #182571, handle curses.error if it's thrown inside | | zmedico | get_term_size(). | |---------+--------------------------------------------------------------| | 6875 | Return early from get_term_size() is stdout is not a tty. | | zmedico | | |---------+--------------------------------------------------------------| | 6877 | For bug #143340, give an appropriate message when there is | | zmedico | no read access to a binary package. | |---------+--------------------------------------------------------------| | 6879 | Fix cacheddir() to behave properly if os.listdir() raises | | zmedico | errno.EACCES (Permission denied). | |---------+--------------------------------------------------------------| | 6881 | For bug #180165, make portageq print a "Permission denied" | | zmedico | error when appropriate. A PermissionDenied exception is | | | raised from portage.listdir() enven when EmptyOnError is | | | True since errno.EACCES is very likely to indicate a | | | condition that should be reported in any case. | |---------+--------------------------------------------------------------| | 6882 | For bug #180165, make has_version dir if portageq has an | | zmedico | unexpected exit code. | |---------+--------------------------------------------------------------| | 6883 | If a package is in the world set but it's not installed, go | | zmedico | ahead and install it if it's available (instead of telling | | | the user to run emaint). | |---------+--------------------------------------------------------------| | 6886 | Make all the classes inherit from object. | | zmedico | | |---------+--------------------------------------------------------------| | 6887 | Show a "world problems" warning for packages that aren't | | zmedico | installed, even if they are available. | |---------+--------------------------------------------------------------| | 6889 | Make the progress bar percentage indicator stop at 100% | | zmedico | instead of just 99%. | +------------------------------------------------------------------------+ svn path=/main/branches/prefix/; revision=6943 --- bin/ebuild.sh | 32 ++++++++++++++--------- bin/emerge | 8 +++++- bin/portageq | 3 +++ bin/quickpkg | 13 ++++++++-- pym/emerge/__init__.py | 22 ++++++++++++---- pym/portage/__init__.py | 25 +++++++++++++----- pym/portage/dbapi/bintree.py | 6 +++++ pym/portage/eclass_cache.py | 2 +- pym/portage/exception.py | 1 + pym/portage/gpg.py | 2 +- pym/portage/output.py | 24 +++++++++++------ pym/portage/tests/__init__.py | 3 ++- pym/portage/tests/bin/setup_env.py | 2 ++ pym/portage/tests/ebuild/__init__.py | 3 +++ pym/portage/tests/ebuild/test_spawn.py | 36 ++++++++++++++++++++++++++ pym/portage/xpak.py | 2 +- 16 files changed, 146 insertions(+), 38 deletions(-) create mode 100644 pym/portage/tests/ebuild/__init__.py create mode 100644 pym/portage/tests/ebuild/test_spawn.py diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 66d86818c..bb17ad89a 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -67,7 +67,7 @@ unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR GLOBIGNORE export PATH="${DEFAULT_PATH}:${PORTAGE_BIN_PATH}:${ROOTPATH}" [ ! -z "$PREROOTPATH" ] && export PATH="${PREROOTPATH%%:}:$PATH" -source "@PORTAGE_BASE@"/bin/isolated-functions.sh &>/dev/null +source "${PORTAGE_BIN_PATH}/isolated-functions.sh" &>/dev/null OCC="$CC" OCXX="$CXX" @@ -182,18 +182,26 @@ has_version() { fi # return shell-true/shell-false if exists. # Takes single depend-type atoms. - if "@PORTAGE_BASE@"/bin/portageq 'has_version' "${ROOT}" "$1"; then - return 0 - else - return 1 - fi + "${PORTAGE_BIN_PATH}"/portageq has_version "${ROOT}" "$1" + local retval=$? + case "${retval}" in + 0) + return 0 + ;; + 1) + return 1 + ;; + *) + die "unexpected portageq exit code: ${retval}" + ;; + esac } portageq() { if [ "${EBUILD_PHASE}" == "depend" ]; then die "portageq calls are not allowed in the global scope" fi - "@PORTAGE_BASE@"/bin/portageq "$@" + "${PORTAGE_BIN_PATH}/portageq" "$@" } @@ -208,7 +216,7 @@ best_version() { fi # returns the best/most-current match. # Takes single depend-type atoms. - "@PORTAGE_BASE@"/bin/portageq 'best_version' "${ROOT}" "$1" + "${PORTAGE_BIN_PATH}/portageq" 'best_version' "${ROOT}" "$1" } use_with() { @@ -499,7 +507,7 @@ econf() { if ! ${CONFCACHE} ${CONFCACHE_ARG} ${TMP_CONFCACHE_DIR} "${ECONF_SOURCE}/configure" \ --prefix="${EPREFIX}"/usr \ - --host="${CHOST}" \ + --host=${CHOST} \ --mandir="${EPREFIX}"/usr/share/man \ --infodir="${EPREFIX}"/usr/share/info \ --datadir="${EPREFIX}"/usr/share \ @@ -1650,9 +1658,9 @@ if [ -n "${myarg}" ] && \ unset myarg # Save current environment and touch a success file. (echo for success) umask 002 - set | @EGREP@ -v "^SANDBOX_" > "${T}/environment" 2>/dev/null - export | @EGREP@ -v "^declare -x SANDBOX_" | \ - @SED@ 's:^declare -rx:declare -x:' >> "${T}/environment" 2>/dev/null + set | egrep -v "^SANDBOX_" > "${T}/environment" 2>/dev/null + export | egrep -v "^declare -x SANDBOX_" | \ + sed 's:^declare -rx:declare -x:' >> "${T}/environment" 2>/dev/null chown ${PORTAGE_USER:-portage}:${PORTAGE_GROUP:-portage} "${T}/environment" &>/dev/null chmod g+w "${T}/environment" &>/dev/null fi diff --git a/bin/emerge b/bin/emerge index 74262f11c..13bc5f394 100755 --- a/bin/emerge +++ b/bin/emerge @@ -13,4 +13,10 @@ except ImportError: if __name__ == "__main__": import sys - sys.exit(emerge_main()) + from portage.exception import PermissionDenied + try: + retval = emerge_main() + except PermissionDenied, e: + sys.stderr.write("Permission denied: '%s'\n" % str(e)) + sys.exit(e.errno) + sys.exit(retval) diff --git a/bin/portageq b/bin/portageq index 16c0c67c6..653bcf229 100755 --- a/bin/portageq +++ b/bin/portageq @@ -373,6 +373,9 @@ def main(): except KeyError: usage(sys.argv) sys.exit(os.EX_USAGE) + except portage.exception.PermissionDenied, e: + sys.stderr.write("Permission denied: '%s'\n" % str(e)) + sys.exit(e.errno) main() diff --git a/bin/quickpkg b/bin/quickpkg index ba3116941..0dd9c7fc8 100755 --- a/bin/quickpkg +++ b/bin/quickpkg @@ -121,11 +121,20 @@ if __name__ == "__main__": usage = "Usage: quickpkg [options] " from optparse import OptionParser parser = OptionParser(usage=usage) - options, args = parser.parse_args(sys.argv[1:]) + parser.add_option("--umask", + default="0077", + help="umask used during package creation (default is 0077)") + from portage import settings + default_opts = settings.get("QUICKPKG_DEFAULT_OPTS","").split() + options, args = parser.parse_args(default_opts + sys.argv[1:]) if not args: parser.error("no packages atoms given") + try: + umask = int(options.umask, 8) + except ValueError: + parser.error("invalid umask: %s" % options.umask) # We need to ensure a sane umask for the packages that will be created. - old_umask = os.umask(022) + old_umask = os.umask(umask) from portage.output import get_term_size, EOutput eout = EOutput() def sigwinch_handler(signum, frame): diff --git a/pym/emerge/__init__.py b/pym/emerge/__init__.py index eab3fcd9e..23d29c6bb 100644 --- a/pym/emerge/__init__.py +++ b/pym/emerge/__init__.py @@ -363,7 +363,7 @@ def create_depgraph_params(myopts, myaction): return myparams # search functionality -class search: +class search(object): # # class constants @@ -911,7 +911,7 @@ def show_invalid_depstring_notice(parent_node, depstring, error_msg): f.add_flowing_data(x) f.end_paragraph(1) -class depgraph: +class depgraph(object): pkg_tree_map = { "ebuild":"porttree", @@ -2218,10 +2218,22 @@ class depgraph: for x in worlddict.keys(): if not portage.isvalidatom(x): world_problems = True - elif not self.trees[self.target_root]["vartree"].dbapi.match(x): + continue + elif not vardb.match(x): world_problems = True - else: - mylist.append(x) + available = False + if "--usepkgonly" not in self.myopts and \ + portdb.match(x): + available = True + elif "--usepkg" in self.myopts: + mymatches = bindb.match(x) + if "--usepkgonly" not in self.myopts: + mymatches = visible(mymatches) + if mymatches: + available = True + if not available: + continue + mylist.append(x) newlist = [] for atom in mylist: diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index ec84a80b4..bd27baa7c 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -186,7 +186,14 @@ def cacheddir(my_original_path, ignorecvs, ignorelist, EmptyOnError, followSymli mtime = pathstat[stat.ST_MTIME] else: raise portage.exception.DirectoryNotFound(mypath) - except (IOError,OSError,portage.exception.PortageException): + except EnvironmentError, e: + if e.errno == portage.exception.PermissionDenied.errno: + raise portage.exception.PermissionDenied(mypath) + del e + if EmptyOnError: + return [], [] + return None, None + except portage.exception.PortageException: if EmptyOnError: return [], [] return None, None @@ -194,7 +201,13 @@ def cacheddir(my_original_path, ignorecvs, ignorelist, EmptyOnError, followSymli if mtime != cached_mtime or time.time() - mtime < 4: if dircache.has_key(mypath): cacheStale += 1 - list = os.listdir(mypath) + try: + list = os.listdir(mypath) + except EnvironmentError, e: + if e.errno != errno.EACCES: + raise + del e + raise portage.exception.PermissionDenied(mypath) ftype = [] for x in list: try: @@ -304,7 +317,7 @@ def flatten(mytokens): #beautiful directed graph object -class digraph: +class digraph(object): def __init__(self): """Create an empty digraph""" @@ -806,10 +819,10 @@ def autouse(myvartree, use_cache=1, mysettings=None): return myusevars def check_config_instance(test): - if not test or (str(test.__class__) != 'portage.config'): - raise TypeError, "Invalid type for config object: %s" % test.__class__ + if not isinstance(test, config): + raise TypeError("Invalid type for config object: %s" % test.__class__) -class config: +class config(object): """ This class encompasses the main portage configuration. Data is pulled from ROOT/PORTDIR/profiles/, from ROOT/etc/make.profile incrementally through all diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py index 7fb58748f..713a8c612 100644 --- a/pym/portage/dbapi/bintree.py +++ b/pym/portage/dbapi/bintree.py @@ -429,6 +429,12 @@ class binarytree(object): aux_cache[k] = d[k] self.dbapi._aux_cache[mycpv] = aux_cache continue + if not os.access(full_path, os.R_OK): + writemsg("!!! Permission denied to read " + \ + "binary package: '%s'\n" % full_path, + noiselevel=-1) + self.invalids.append(myfile[:-5]) + continue mytbz2 = portage.xpak.tbz2(full_path) # For invalid packages, mycat could be None. mycat = mytbz2.getfile("CATEGORY") diff --git a/pym/portage/eclass_cache.py b/pym/portage/eclass_cache.py index 40d4e360f..5a0d3c3ad 100644 --- a/pym/portage/eclass_cache.py +++ b/pym/portage/eclass_cache.py @@ -7,7 +7,7 @@ from portage.util import normalize_path, writemsg import os, sys from portage.data import portage_gid -class cache: +class cache(object): """ Maintains the cache information about eclasses used in ebuild. """ diff --git a/pym/portage/exception.py b/pym/portage/exception.py index 7d5ca82c2..11b455e97 100644 --- a/pym/portage/exception.py +++ b/pym/portage/exception.py @@ -53,6 +53,7 @@ class OperationNotPermitted(PortageException): """An operation was not permitted operating system""" class PermissionDenied(PortageException): + from errno import EACCES as errno """Permission denied""" class ReadOnlyFileSystem(PortageException): diff --git a/pym/portage/gpg.py b/pym/portage/gpg.py index d3061c5f9..5c8a856b1 100644 --- a/pym/portage/gpg.py +++ b/pym/portage/gpg.py @@ -30,7 +30,7 @@ def fileStats(filepath): return mya -class FileChecker: +class FileChecker(object): def __init__(self,keydir=None,keyring=None,requireSignedRing=False,minimumTrust=EXISTS): self.minimumTrust = TRUSTED # Default we require trust. For rings. self.keydir = None diff --git a/pym/portage/output.py b/pym/portage/output.py index 7efde92a9..33223d5b4 100644 --- a/pym/portage/output.py +++ b/pym/portage/output.py @@ -256,10 +256,15 @@ def get_term_size(): occurs. The curses module is used if available, otherwise the output of `stty size` is parsed. """ + if not sys.stdout.isatty(): + return -1, -1 try: import curses - curses.setupterm() - return curses.tigetnum('lines'), curses.tigetnum('cols') + try: + curses.setupterm() + return curses.tigetnum('lines'), curses.tigetnum('cols') + except curses.error: + pass except ImportError: pass st, out = commands.getstatusoutput('stty size') @@ -281,7 +286,7 @@ def set_term_size(lines, columns, fd): cmd = ["stty", "rows", str(lines), "columns", str(columns)] spawn(cmd, env=os.environ, fd_pipes={0:fd}) -class EOutput: +class EOutput(object): """ Performs fancy terminal formatting for status and informational messages. @@ -518,9 +523,11 @@ class TermProgressBar(ProgressBar): curval = self._curval maxval = self._maxval position = self._position - if cols < 3: + percentage_str_width = 4 + square_brackets_width = 2 + if cols < percentage_str_width: return "" - bar_space = cols - 6 + bar_space = cols - percentage_str_width - square_brackets_width if maxval == 0: max_bar_width = bar_space-3 image = " " @@ -545,11 +552,12 @@ class TermProgressBar(ProgressBar): "<=>" + ((max_bar_width - bar_width) * " ") + "]" return image else: - max_bar_width = bar_space-1 percentage = int(100 * float(curval) / maxval) if percentage == 100: - percentage = 99 - image = ("%d%% " % percentage).rjust(4) + percentage_str_width += 1 + bar_space -= 1 + max_bar_width = bar_space - 1 + image = ("%d%% " % percentage).rjust(percentage_str_width) if cols < min_columns: return image offset = float(curval) / maxval diff --git a/pym/portage/tests/__init__.py b/pym/portage/tests/__init__.py index 60a19de6c..e3702e08e 100644 --- a/pym/portage/tests/__init__.py +++ b/pym/portage/tests/__init__.py @@ -7,7 +7,8 @@ import os, sys, time, unittest import portage.tests def main(): - testDirs = ["bin", "util","versions", "dep", "xpak", "env/config"] + testDirs = ["bin", "dep", "ebuild", + "env/config", "util", "versions", "xpak"] suite = unittest.TestSuite() basedir = os.path.dirname(__file__) for mydir in testDirs: diff --git a/pym/portage/tests/bin/setup_env.py b/pym/portage/tests/bin/setup_env.py index 1f2491701..274d72654 100644 --- a/pym/portage/tests/bin/setup_env.py +++ b/pym/portage/tests/bin/setup_env.py @@ -7,6 +7,7 @@ import os, shutil, sys from os.path import dirname, abspath, join from portage.tests import TestCase from portage.process import spawn +from portage.const import PORTAGE_BIN_PATH bindir = join(dirname(dirname(abspath(__file__))), "..", "..", "..", "bin") basedir = join(dirname(dirname(abspath(__file__))), "bin", "root") @@ -15,6 +16,7 @@ os.environ["T"] = os.path.join(basedir, "temp") os.environ["S"] = os.path.join(basedir, "workdir") os.environ["PF"] = "portage-tests-0.09-r1" os.environ["PATH"] = bindir + ":" + os.environ["PATH"] +os.environ["PORTAGE_BIN_PATH"] = PORTAGE_BIN_PATH def binTestsCleanup(): if os.access(basedir, os.W_OK): diff --git a/pym/portage/tests/ebuild/__init__.py b/pym/portage/tests/ebuild/__init__.py new file mode 100644 index 000000000..d67b0cd85 --- /dev/null +++ b/pym/portage/tests/ebuild/__init__.py @@ -0,0 +1,3 @@ +# Copyright 1998-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ diff --git a/pym/portage/tests/ebuild/test_spawn.py b/pym/portage/tests/ebuild/test_spawn.py new file mode 100644 index 000000000..66e8f9ea7 --- /dev/null +++ b/pym/portage/tests/ebuild/test_spawn.py @@ -0,0 +1,36 @@ +# Copyright 1998-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +import errno, os, sys +from portage.tests import TestCase + +class SpawnTestCase(TestCase): + + def testLogfile(self): + from portage import settings, spawn + from tempfile import mkstemp + logfile = None + try: + fd, logfile = mkstemp() + os.close(fd) + null_fd = os.open('/dev/null', os.O_RDWR) + test_string = 2 * "blah blah blah\n" + spawn("echo -n '%s'" % test_string, settings, logfile=logfile, + fd_pipes={0:sys.stdin.fileno(), 1:null_fd, 2:null_fd}) + os.close(null_fd) + f = open(logfile, 'r') + log_content = f.read() + f.close() + # When logging passes through a pty, it's lines will be separated + # by '\r\n', so use splitlines before comparing results. + self.assertEqual(test_string.splitlines(), + log_content.splitlines()) + finally: + if logfile: + try: + os.unlink(logfile) + except EnvironmentError, e: + if e.errno != errno.ENOENT: + raise + del e diff --git a/pym/portage/xpak.py b/pym/portage/xpak.py index 2700bef09..e3588ab72 100644 --- a/pym/portage/xpak.py +++ b/pym/portage/xpak.py @@ -224,7 +224,7 @@ def xpand(myid,mydest): startpos=startpos+namelen+12 os.chdir(origdir) -class tbz2: +class tbz2(object): def __init__(self,myfile): self.file=myfile self.filestat=None -- 2.26.2