From 58ba428870cc665ef32ddfbc80727f433be19d92 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Tue, 28 Oct 2008 19:09:53 +0000 Subject: [PATCH] Merged from trunk -r11724:11733 | 11725 | When creating the temporary $DISTDIR, do not try to set the | | zmedico | uid since it will fail when not running as root. | | 11726 | Enable bashrc even when $EBUILD_PHASE is unset, so it's | | zmedico | possible to override things like INSTALL_MASK. | | 11727 | In fetch(), avoid the "Adjusting permissions recursively" | | zmedico | message in cases when the directory has just been created | | | and therefore it must be empty. | | 11728 | Return early from fetch() if no uris are given. | | zmedico | | | 11729 | Pass $ROOT into portage.util.getlibpaths(). | | zmedico | | | 11730 | Pass $ROOT into the LinkageMap._ObjectKey constructor since | | zmedico | it's needed for os.stat() and realpath() calls. | | 11731 | Fix incorrect $ROOT handling inside dblink._preserve_libs(). | | zmedico | | | 11732 | Make SetConfig.getSetAtoms() raise a PackageSetNotFound | | zmedico | exception when necessary and add handling code in emerge. | | | This solves an unhandled KeyError that was raise when a | | | nested set did not exist. Thanks to ABCD for reporting. | | 11733 | Fix some incorrect $ROOT handling inside LinkageMap. | | zmedico | | svn path=/main/branches/prefix/; revision=11736 --- bin/ebuild.sh | 3 +- pym/_emerge/__init__.py | 11 +++- pym/portage/__init__.py | 16 +++++- pym/portage/dbapi/vartree.py | 98 +++++++++++++++++++++++------------- pym/portage/sets/__init__.py | 20 ++++++-- pym/portage/util.py | 9 ++-- 6 files changed, 109 insertions(+), 48 deletions(-) diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 4f6cefebe..6a935f829 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -1535,10 +1535,9 @@ _ebuild_phase_funcs() { # function for the current phase. # source_all_bashrcs() { - [ -n "$EBUILD_PHASE" ] || return local x - if [[ -n ${EAPI/prefix/} ]] ; then + if [[ -n $EBUILD_PHASE && -n ${EAPI/prefix/} ]] ; then # PREFIX HACK: just remove "prefix" from EAPI here, this file # currently assumes EAPI to contain a single token, and "prefix" # is ortogonal to all supported EAPIs here. diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 82e08cef4..d567e2b1e 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -13788,15 +13788,22 @@ def expand_set_arguments(myfiles, myaction, root_config): display_missing_pkg_set(root_config, s) return (None, 1) setconfig.active.append(s) + try: + set_atoms = setconfig.getSetAtoms(s) + except portage.exception.PackageSetNotFound, e: + writemsg_level(("emerge: the given set '%s' " + \ + "contains a non-existent set named '%s'.\n") % \ + (s, e), level=logging.ERROR, noiselevel=-1) + return (None, 1) if myaction in unmerge_actions and \ not sets[s].supportsOperation("unmerge"): sys.stderr.write("emerge: the given set '%s' does " % s + \ "not support unmerge operations\n") retval = 1 - elif not setconfig.getSetAtoms(s): + elif not set_atoms: print "emerge: '%s' is an empty set" % s elif myaction not in do_not_expand: - newargs.extend(setconfig.getSetAtoms(s)) + newargs.extend(set_atoms) else: newargs.append(SETPREFIX+s) for e in sets[s].errors: diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 575a59511..eed7321fd 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -3359,6 +3359,9 @@ _size_suffix_map = { def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks",use_locks=1, try_mirrors=1): "fetch files. Will use digest file if available." + if not myuris: + return 1 + features = mysettings.features restrict = mysettings.get("PORTAGE_RESTRICT","").split() @@ -3603,7 +3606,12 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", write_test_file = os.path.join( mydir, ".__portage_test_write__") - if os.path.isdir(mydir): + try: + st = os.stat(mydir) + except OSError: + st = None + + if st is not None and stat.S_ISDIR(st.st_mode): if not (userfetch or userpriv): continue if _userpriv_test_write_file(mysettings, write_test_file): @@ -3611,6 +3619,10 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", _userpriv_test_write_file_cache.pop(write_test_file, None) if portage.util.ensure_dirs(mydir, gid=dir_gid, mode=dirmode, mask=modemask): + if st is None: + # The directory has just been created + # and therefore it must be empty. + continue writemsg("Adjusting permissions recursively: '%s'\n" % mydir, noiselevel=-1) def onerror(e): @@ -5704,7 +5716,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, mysettings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir edpath = mysettings["DISTDIR"] = \ os.path.join(mysettings["PORTAGE_BUILDDIR"], "distdir") - portage.util.ensure_dirs(edpath, uid=portage_uid, mode=0755) + portage.util.ensure_dirs(edpath, gid=portage_gid, mode=0755) # Remove any unexpected files or directories. for x in os.listdir(edpath): diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 996fa517b..77ac7ebaf 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -144,9 +144,10 @@ class LinkageMap(object): def __init__(self, vardbapi): self._dbapi = vardbapi + self._root = self._dbapi.root self._libs = {} self._obj_properties = {} - self._defpath = set(getlibpaths()) + self._defpath = set(getlibpaths(self._root)) self._obj_key_cache = {} class _ObjectKey(object): @@ -155,7 +156,7 @@ class LinkageMap(object): __slots__ = ("__weakref__", "_key") - def __init__(self, object): + def __init__(self, object, root): """ This takes a path to an object. @@ -163,7 +164,7 @@ class LinkageMap(object): @type object: string (example: '/usr/bin/bar') """ - self._key = self._generate_object_key(object) + self._key = self._generate_object_key(object, root) def __hash__(self): return hash(self._key) @@ -171,7 +172,7 @@ class LinkageMap(object): def __eq__(self, other): return self._key == other._key - def _generate_object_key(self, object): + def _generate_object_key(self, object, root): """ Generate object key for a given object. @@ -185,12 +186,13 @@ class LinkageMap(object): 2. realpath of object if object does not exist. """ + abs_path = os.path.join(root, object.lstrip(os.path.sep)) try: - object_stat = os.stat(object) + object_stat = os.stat(abs_path) except OSError: # Use the realpath as the key if the file does not exists on the # filesystem. - return os.path.realpath(object) + return os.path.realpath(abs_path) # Return a tuple of the device and inode. return (object_stat.st_dev, object_stat.st_ino) @@ -207,6 +209,7 @@ class LinkageMap(object): return isinstance(self._key, tuple) def rebuild(self, include_file=None): + root = self._root libs = {} obj_key_cache = {} obj_properties = {} @@ -239,9 +242,10 @@ class LinkageMap(object): continue arch = fields[0] obj = fields[1] - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, root) soname = fields[2] - path = set([normalize_path(x) + path = set([ + normalize_path(os.path.join(self._root, x.lstrip(os.path.sep))) for x in filter(None, fields[3].replace( "${ORIGIN}", os.path.dirname(obj)).replace( "$ORIGIN", os.path.dirname(obj)).split(":"))]) @@ -313,7 +317,7 @@ class LinkageMap(object): if obj in self._obj_key_cache: obj_key = self._obj_key_cache.get(obj) else: - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, self._root) # Check that the library exists on the filesystem. if obj_key.file_exists(): # Get the arch and soname from LinkageMap._obj_properties if @@ -427,7 +431,7 @@ class LinkageMap(object): """ basename = os.path.basename(obj) - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, self._root) if obj_key not in self._obj_properties: raise KeyError("%s (%s) not in object list" % (obj_key, obj)) soname = self._obj_properties[obj_key][3] @@ -501,7 +505,7 @@ class LinkageMap(object): else: obj_key = self._obj_key_cache.get(obj) if obj_key not in self._obj_properties: - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, self._root) if obj_key not in self._obj_properties: raise KeyError("%s (%s) not in object list" % (obj_key, obj)) @@ -516,7 +520,8 @@ class LinkageMap(object): for provider_key in self._libs[soname][arch]["providers"]: providers = self._obj_properties[provider_key][4] for provider in providers: - if os.path.dirname(provider) in path: + if os.path.join(self._root, + os.path.dirname(provider).lstrip(os.path.sep)) in path: rValue[soname].add(provider) return rValue @@ -555,7 +560,7 @@ class LinkageMap(object): objs = set([obj]) obj_key = self._obj_key_cache.get(obj) if obj_key not in self._obj_properties: - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, self._root) if obj_key not in self._obj_properties: raise KeyError("%s (%s) not in object list" % (obj_key, obj)) @@ -568,8 +573,8 @@ class LinkageMap(object): # have any consumers. if not isinstance(obj, self._ObjectKey): soname = self._obj_properties[obj_key][3] - obj_dir = os.path.dirname(obj) - master_link = os.path.join(obj_dir, soname) + master_link = os.path.join(self._root, + os.path.dirname(obj).lstrip(os.path.sep), soname) try: master_st = os.stat(master_link) obj_st = os.stat(obj) @@ -598,6 +603,7 @@ class LinkageMapMachO(object): def __init__(self, vardbapi): self._dbapi = vardbapi + self._root = self._dbapi.root self._libs = {} self._obj_properties = {} self._obj_key_cache = {} @@ -608,7 +614,7 @@ class LinkageMapMachO(object): __slots__ = ("__weakref__", "_key") - def __init__(self, object): + def __init__(self, object, root): """ This takes a path to an object. @@ -616,7 +622,7 @@ class LinkageMapMachO(object): @type object: string (example: '/usr/bin/bar') """ - self._key = self._generate_object_key(object) + self._key = self._generate_object_key(object, root) def __hash__(self): return hash(self._key) @@ -624,7 +630,7 @@ class LinkageMapMachO(object): def __eq__(self, other): return self._key == other._key - def _generate_object_key(self, object): + def _generate_object_key(self, object, root): """ Generate object key for a given object. @@ -638,12 +644,13 @@ class LinkageMapMachO(object): 2. realpath of object if object does not exist. """ + abs_path = os.path.join(root, object.lstrip(os.path.sep)) try: - object_stat = os.stat(object) + object_stat = os.stat(abs_path) except OSError: # Use the realpath as the key if the file does not exists on the # filesystem. - return os.path.realpath(object) + return os.path.realpath(abs_path) # Return a tuple of the device and inode. return (object_stat.st_dev, object_stat.st_ino) @@ -660,6 +667,7 @@ class LinkageMapMachO(object): return isinstance(self._key, tuple) def rebuild(self, include_file=None): + root = self._root libs = {} obj_key_cache = {} obj_properties = {} @@ -695,7 +703,7 @@ class LinkageMapMachO(object): # the install_name of the library in the object. arch = fields[0] obj = fields[1] - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, root) install_name = os.path.normpath(fields[2]) needed = filter(None, fields[3].split(",")) @@ -772,7 +780,7 @@ class LinkageMapMachO(object): if obj in self._obj_key_cache: obj_key = self._obj_key_cache.get(obj) else: - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, self._root) # Check that the library exists on the filesystem. if obj_key.file_exists(): # Get the install_name from LinkageMapMachO._obj_properties if @@ -870,7 +878,7 @@ class LinkageMapMachO(object): """ basename = os.path.basename(obj) - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, self._root) if obj_key not in self._obj_properties: raise KeyError("%s (%s) not in object list" % (obj_key, obj)) install_name = self._obj_properties[obj_key][2] @@ -944,7 +952,7 @@ class LinkageMapMachO(object): else: obj_key = self._obj_key_cache.get(obj) if obj_key not in self._obj_properties: - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, self._root) if obj_key not in self._obj_properties: raise KeyError("%s (%s) not in object list" % (obj_key, obj)) @@ -958,7 +966,8 @@ class LinkageMapMachO(object): for provider_key in self._libs[install_name][arch]["providers"]: providers = self._obj_properties[provider_key][3] for provider in providers: - if os.path.exists(provider): + if os.path.exists(os.path.join(self._root, + provider.lstrip(os.path.sep))): rValue[install_name].add(provider) return rValue @@ -997,7 +1006,7 @@ class LinkageMapMachO(object): objs = set([obj]) obj_key = self._obj_key_cache.get(obj) if obj_key not in self._obj_properties: - obj_key = self._ObjectKey(obj) + obj_key = self._ObjectKey(obj, self._root) if obj_key not in self._obj_properties: raise KeyError("%s (%s) not in object list" % (obj_key, obj)) @@ -1006,7 +1015,8 @@ class LinkageMapMachO(object): # other version, this lib will be shadowed and won't # have any consumers. if not isinstance(obj, self._ObjectKey): - master_link = self._obj_properties[obj_key][2] + master_link = os.path.join(self._root, + self._obj_properties[obj_key][2].lstrip(os.path.sep)) try: master_st = os.stat(master_link) obj_st = os.stat(obj) @@ -2863,13 +2873,30 @@ class dblink(object): old_libs = old_contents.intersection(liblist) # get list of libraries from new package instance - mylibs = set([os.path.join(os.sep, x) for x in mycontents]).intersection(liblist) + mycontents = set(os.path.join(os.path.sep, x) for x in mycontents) + mylibs = mycontents.intersection(liblist) # check which libs are present in the old, but not the new package instance candidates = old_libs.difference(mylibs) - + candidates_inodes = set() + for x in candidates: + x_destroot = os.path.join(destroot, x.lstrip(os.path.sep)) + try: + st = os.stat(x_destroot) + except OSError: + continue + candidates_inodes.add((st.st_dev, st.st_ino)) + for x in old_contents: - if os.path.islink(x) and os.path.realpath(x) in candidates and x not in mycontents: + x_destroot = os.path.join(destroot, x.lstrip(os.path.sep)) + if not os.path.islink(x_destroot): + continue + try: + st = os.stat(x_destroot) + except OSError: + continue + if (st.st_dev, st.st_ino) in candidates_inodes and \ + x not in mycontents: candidates.add(x) provider_cache = {} @@ -2941,12 +2968,14 @@ class dblink(object): candidates_stack = list(candidates) while candidates_stack: x = candidates_stack.pop() + x_srcroot = os.path.join(srcroot, x.lstrip(os.path.sep)) + x_destroot = os.path.join(destroot, x.lstrip(os.path.sep)) # skip existing files so the 'new' libs aren't overwritten if os.path.exists(os.path.join(srcroot, x.lstrip(os.sep))): continue showMessage("injecting %s into %s\n" % (x, srcroot), noiselevel=-1) - if not os.path.exists(os.path.join(destroot, x.lstrip(os.sep))): + if not os.path.exists(x_destroot): showMessage("%s does not exist so can't be preserved\n" % x, noiselevel=-1) continue @@ -2957,8 +2986,8 @@ class dblink(object): # resolve symlinks and extend preserve list # NOTE: we're extending the list in the loop to emulate recursion to # also get indirect symlinks - if os.path.islink(x): - linktarget = os.readlink(x) + if os.path.islink(x_destroot): + linktarget = os.readlink(x_destroot) os.symlink(linktarget, os.path.join(srcroot, x.lstrip(os.sep))) if linktarget[0] != os.sep: linktarget = os.path.join(os.path.dirname(x), linktarget) @@ -2966,8 +2995,7 @@ class dblink(object): candidates.add(linktarget) candidates_stack.append(linktarget) else: - shutil.copy2(os.path.join(destroot, x.lstrip(os.sep)), - os.path.join(srcroot, x.lstrip(os.sep))) + shutil.copy2(x_destroot, x_srcroot) preserve_paths.append(x) del candidates diff --git a/pym/portage/sets/__init__.py b/pym/portage/sets/__init__.py index b892bb308..a668c8324 100644 --- a/pym/portage/sets/__init__.py +++ b/pym/portage/sets/__init__.py @@ -2,10 +2,14 @@ # Distributed under the terms of the GNU General Public License v2 # $Id$ +__all__ = ["SETPREFIX", "get_boolean", "SetConfigError", + "SetConfig", "load_default_config"] + import os from ConfigParser import SafeConfigParser, NoOptionError from portage import load_mod from portage.const import USER_CONFIG_PATH, GLOBAL_CONFIG_PATH +from portage.exception import PackageSetNotFound SETPREFIX = "@" @@ -131,7 +135,13 @@ class SetConfig(object): return self.psets.copy() def getSetAtoms(self, setname, ignorelist=None): - myset = self.getSets()[setname] + """ + This raises PackageSetNotFound if the give setname does not exist. + """ + try: + myset = self.getSets()[setname] + except KeyError: + raise PackageSetNotFound(setname) myatoms = myset.getAtoms() parser = self._parser extend = set() @@ -150,8 +160,12 @@ class SetConfig(object): ignorelist.add(setname) for n in myset.getNonAtoms(): - if n.startswith(SETPREFIX) and n[len(SETPREFIX):] in self.psets: - extend.add(n[len(SETPREFIX):]) + if n.startswith(SETPREFIX): + s = n[len(SETPREFIX):] + if s in self.psets: + extend.add(n[len(SETPREFIX):]) + else: + raise PackageSetNotFound(s) for s in ignorelist: extend.discard(s) diff --git a/pym/portage/util.py b/pym/portage/util.py index 5f0460e0f..47339dee9 100644 --- a/pym/portage/util.py +++ b/pym/portage/util.py @@ -1213,7 +1213,7 @@ def new_protect_filename(mydest, newmd5=None): return old_pfile return new_pfile -def getlibpaths(): +def getlibpaths(root): """ Return a list of paths that are used for library lookups """ # PREFIX HACK: LD_LIBRARY_PATH isn't portable, and considered @@ -1229,11 +1229,12 @@ def getlibpaths(): else: # the following is based on the information from ld.so(8) rval = os.environ.get("LD_LIBRARY_PATH", "").split(":") - rval.extend(grabfile("/etc/ld.so.conf")) + rval.extend(grabfile(os.path.join(root, "etc", "ld.so.conf"))) rval.append("/usr/lib") rval.append("/lib") - rval = [normalize_path(x) for x in rval if x != ""] - + rval = [normalize_path(os.path.join(root, x.lstrip(os.path.sep))) \ + for x in rval if x] + return rval -- 2.26.2