From: Zac Medico Date: Thu, 25 Feb 2010 07:17:51 +0000 (-0000) Subject: Move env_update to portage.util.env_update.envupdate. X-Git-Tag: v2.2_rc64~61 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=e3c8fdd6e9b5bcb39163e5b8c0413bd85ef35753;p=portage.git Move env_update to portage.util.env_update.envupdate. svn path=/main/trunk/; revision=15452 --- diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 2a0c3a6d5..6c872af9a 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -42,8 +42,6 @@ try: # which is unavailable. from StringIO import StringIO - from time import sleep - from itertools import chain import platform import warnings @@ -122,6 +120,7 @@ try: 'stack_lists,unique_array,varexpand,writedict,writemsg,' + \ 'writemsg_stdout,write_atomic', 'portage.util.digraph:digraph', + 'portage.util.env_update:env_update', 'portage.util.listdir:cacheddir,listdir', 'portage.versions', 'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,' + \ @@ -534,267 +533,6 @@ def abssymlink(symlink): mylink=mydir+"/"+mylink return os.path.normpath(mylink) -#parse /etc/env.d and generate /etc/profile.env - -def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None, - env=None, writemsg_level=None): - if writemsg_level is None: - writemsg_level = portage.util.writemsg_level - if target_root is None: - global settings - target_root = settings["ROOT"] - if prev_mtimes is None: - global mtimedb - prev_mtimes = mtimedb["ldpath"] - if env is None: - env = os.environ - envd_dir = os.path.join(target_root, "etc", "env.d") - portage.util.ensure_dirs(envd_dir, mode=0o755) - fns = listdir(envd_dir, EmptyOnError=1) - fns.sort() - templist = [] - for x in fns: - if len(x) < 3: - continue - if not x[0].isdigit() or not x[1].isdigit(): - continue - if x.startswith(".") or x.endswith("~") or x.endswith(".bak"): - continue - templist.append(x) - fns = templist - del templist - - space_separated = set(["CONFIG_PROTECT", "CONFIG_PROTECT_MASK"]) - colon_separated = set(["ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH", - "CLASSPATH", "INFODIR", "INFOPATH", "KDEDIRS", "LDPATH", "MANPATH", - "PATH", "PKG_CONFIG_PATH", "PRELINK_PATH", "PRELINK_PATH_MASK", - "PYTHONPATH", "ROOTPATH"]) - - config_list = [] - - for x in fns: - file_path = os.path.join(envd_dir, x) - try: - myconfig = getconfig(file_path, expand=False) - except portage.exception.ParseError as e: - writemsg("!!! '%s'\n" % str(e), noiselevel=-1) - del e - continue - if myconfig is None: - # broken symlink or file removed by a concurrent process - writemsg("!!! File Not Found: '%s'\n" % file_path, noiselevel=-1) - continue - - config_list.append(myconfig) - if "SPACE_SEPARATED" in myconfig: - space_separated.update(myconfig["SPACE_SEPARATED"].split()) - del myconfig["SPACE_SEPARATED"] - if "COLON_SEPARATED" in myconfig: - colon_separated.update(myconfig["COLON_SEPARATED"].split()) - del myconfig["COLON_SEPARATED"] - - env = {} - specials = {} - for var in space_separated: - mylist = [] - for myconfig in config_list: - if var in myconfig: - for item in myconfig[var].split(): - if item and not item in mylist: - mylist.append(item) - del myconfig[var] # prepare for env.update(myconfig) - if mylist: - env[var] = " ".join(mylist) - specials[var] = mylist - - for var in colon_separated: - mylist = [] - for myconfig in config_list: - if var in myconfig: - for item in myconfig[var].split(":"): - if item and not item in mylist: - mylist.append(item) - del myconfig[var] # prepare for env.update(myconfig) - if mylist: - env[var] = ":".join(mylist) - specials[var] = mylist - - for myconfig in config_list: - """Cumulative variables have already been deleted from myconfig so that - they won't be overwritten by this dict.update call.""" - env.update(myconfig) - - ldsoconf_path = os.path.join(target_root, "etc", "ld.so.conf") - try: - myld = codecs.open(_unicode_encode(ldsoconf_path, - encoding=_encodings['fs'], errors='strict'), - mode='r', encoding=_encodings['content'], errors='replace') - myldlines=myld.readlines() - myld.close() - oldld=[] - for x in myldlines: - #each line has at least one char (a newline) - if x[0]=="#": - continue - oldld.append(x[:-1]) - except (IOError, OSError) as e: - if e.errno != errno.ENOENT: - raise - oldld = None - - ld_cache_update=False - - newld = specials["LDPATH"] - if (oldld!=newld): - #ld.so.conf needs updating and ldconfig needs to be run - myfd = atomic_ofstream(ldsoconf_path) - myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n") - myfd.write("# contents of /etc/env.d directory\n") - for x in specials["LDPATH"]: - myfd.write(x+"\n") - myfd.close() - ld_cache_update=True - - # Update prelink.conf if we are prelink-enabled - if prelink_capable: - newprelink = atomic_ofstream( - os.path.join(target_root, "etc", "prelink.conf")) - newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n") - newprelink.write("# contents of /etc/env.d directory\n") - - for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]: - newprelink.write("-l "+x+"\n"); - for x in specials["LDPATH"]+specials["PATH"]+specials["PRELINK_PATH"]: - if not x: - continue - if x[-1]!='/': - x=x+"/" - plmasked=0 - for y in specials["PRELINK_PATH_MASK"]: - if not y: - continue - if y[-1]!='/': - y=y+"/" - if y==x[0:len(y)]: - plmasked=1 - break - if not plmasked: - newprelink.write("-h "+x+"\n") - for x in specials["PRELINK_PATH_MASK"]: - newprelink.write("-b "+x+"\n") - newprelink.close() - - # Portage stores mtimes with 1 second granularity but in >=python-2.5 finer - # granularity is possible. In order to avoid the potential ambiguity of - # mtimes that differ by less than 1 second, sleep here if any of the - # directories have been modified during the current second. - sleep_for_mtime_granularity = False - current_time = long(time.time()) - mtime_changed = False - lib_dirs = set() - for lib_dir in portage.util.unique_array(specials["LDPATH"]+['usr/lib','usr/lib64','usr/lib32','lib','lib64','lib32']): - x = os.path.join(target_root, lib_dir.lstrip(os.sep)) - try: - newldpathtime = os.stat(x)[stat.ST_MTIME] - lib_dirs.add(normalize_path(x)) - except OSError as oe: - if oe.errno == errno.ENOENT: - try: - del prev_mtimes[x] - except KeyError: - pass - # ignore this path because it doesn't exist - continue - raise - if newldpathtime == current_time: - sleep_for_mtime_granularity = True - if x in prev_mtimes: - if prev_mtimes[x] == newldpathtime: - pass - else: - prev_mtimes[x] = newldpathtime - mtime_changed = True - else: - prev_mtimes[x] = newldpathtime - mtime_changed = True - - if mtime_changed: - ld_cache_update = True - - if makelinks and \ - not ld_cache_update and \ - contents is not None: - libdir_contents_changed = False - for mypath, mydata in contents.items(): - if mydata[0] not in ("obj","sym"): - continue - head, tail = os.path.split(mypath) - if head in lib_dirs: - libdir_contents_changed = True - break - if not libdir_contents_changed: - makelinks = False - - ldconfig = "/sbin/ldconfig" - if "CHOST" in env and "CBUILD" in env and \ - env["CHOST"] != env["CBUILD"]: - from portage.process import find_binary - ldconfig = find_binary("%s-ldconfig" % env["CHOST"]) - - # Only run ldconfig as needed - if (ld_cache_update or makelinks) and ldconfig: - # ldconfig has very different behaviour between FreeBSD and Linux - if ostype=="Linux" or ostype.lower().endswith("gnu"): - # We can't update links if we haven't cleaned other versions first, as - # an older package installed ON TOP of a newer version will cause ldconfig - # to overwrite the symlinks we just made. -X means no links. After 'clean' - # we can safely create links. - writemsg_level(_(">>> Regenerating %setc/ld.so.cache...\n") % \ - (target_root,)) - if makelinks: - os.system("cd / ; %s -r '%s'" % (ldconfig, target_root)) - else: - os.system("cd / ; %s -X -r '%s'" % (ldconfig, target_root)) - elif ostype in ("FreeBSD","DragonFly"): - writemsg_level(_(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % \ - target_root) - os.system(("cd / ; %s -elf -i " + \ - "-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'") % \ - (ldconfig, target_root, target_root)) - - del specials["LDPATH"] - - penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n" - penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n" - cenvnotice = penvnotice[:] - penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n" - cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n" - - #create /etc/profile.env for bash support - outfile = atomic_ofstream(os.path.join(target_root, "etc", "profile.env")) - outfile.write(penvnotice) - - env_keys = [ x for x in env if x != "LDPATH" ] - env_keys.sort() - for k in env_keys: - v = env[k] - if v.startswith('$') and not v.startswith('${'): - outfile.write("export %s=$'%s'\n" % (k, v[1:])) - else: - outfile.write("export %s='%s'\n" % (k, v)) - outfile.close() - - #create /etc/csh.env for (t)csh support - outfile = atomic_ofstream(os.path.join(target_root, "etc", "csh.env")) - outfile.write(cenvnotice) - for x in env_keys: - outfile.write("setenv %s '%s'\n" % (x, env[x])) - outfile.close() - - if sleep_for_mtime_granularity: - while current_time == long(time.time()): - sleep(1) - def ExtractKernelVersion(base_dir): """ Try to figure out what kernel version we are running diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index e99bef8ca..80ae5bebe 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -24,6 +24,7 @@ portage.proxy.lazyimport.lazyimport(globals(), 'writemsg,writemsg_level,write_atomic,atomic_ofstream,writedict,' + \ 'grabfile,grabdict,normalize_path,new_protect_filename,getlibpaths', 'portage.util.digraph:digraph', + 'portage.util.env_update:env_update', 'portage.util.listdir:dircache,listdir', 'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,pkgcmp,' + \ '_pkgsplit@pkgsplit', @@ -38,7 +39,7 @@ from portage.exception import CommandNotFound, \ FileNotFound, PermissionDenied, UnsupportedAPIException from portage.localization import _ -from portage import dep_expand, env_update, \ +from portage import dep_expand, \ abssymlink, movefile, _movefile, bsd_chflags # This is a special version of the os module, wrapped for unicode support. diff --git a/pym/portage/util/env_update.py b/pym/portage/util/env_update.py new file mode 100644 index 000000000..ebae63446 --- /dev/null +++ b/pym/portage/util/env_update.py @@ -0,0 +1,287 @@ +# Copyright 2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +__all__ = ['env_update'] + +import codecs +import errno +import stat +import time + +import portage +from portage import os, _encodings, _unicode_encode +from portage.checksum import prelink_capable +from portage.data import ostype +from portage.exception import ParseError +from portage.localization import _ +from portage.process import find_binary +from portage.util import atomic_ofstream, ensure_dirs, getconfig, \ + normalize_path, writemsg +from portage.util.listdir import listdir + +def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None, + env=None, writemsg_level=None): + """ + Parse /etc/env.d and use it to generate /etc/profile.env, csh.env, + ld.so.conf, and prelink.conf. Finally, run ldconfig. + """ + if writemsg_level is None: + writemsg_level = portage.util.writemsg_level + if target_root is None: + target_root = portage.settings["ROOT"] + if prev_mtimes is None: + prev_mtimes = portage.mtimedb["ldpath"] + if env is None: + env = os.environ + envd_dir = os.path.join(target_root, "etc", "env.d") + ensure_dirs(envd_dir, mode=0o755) + fns = listdir(envd_dir, EmptyOnError=1) + fns.sort() + templist = [] + for x in fns: + if len(x) < 3: + continue + if not x[0].isdigit() or not x[1].isdigit(): + continue + if x.startswith(".") or x.endswith("~") or x.endswith(".bak"): + continue + templist.append(x) + fns = templist + del templist + + space_separated = set(["CONFIG_PROTECT", "CONFIG_PROTECT_MASK"]) + colon_separated = set(["ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH", + "CLASSPATH", "INFODIR", "INFOPATH", "KDEDIRS", "LDPATH", "MANPATH", + "PATH", "PKG_CONFIG_PATH", "PRELINK_PATH", "PRELINK_PATH_MASK", + "PYTHONPATH", "ROOTPATH"]) + + config_list = [] + + for x in fns: + file_path = os.path.join(envd_dir, x) + try: + myconfig = getconfig(file_path, expand=False) + except ParseError as e: + writemsg("!!! '%s'\n" % str(e), noiselevel=-1) + del e + continue + if myconfig is None: + # broken symlink or file removed by a concurrent process + writemsg("!!! File Not Found: '%s'\n" % file_path, noiselevel=-1) + continue + + config_list.append(myconfig) + if "SPACE_SEPARATED" in myconfig: + space_separated.update(myconfig["SPACE_SEPARATED"].split()) + del myconfig["SPACE_SEPARATED"] + if "COLON_SEPARATED" in myconfig: + colon_separated.update(myconfig["COLON_SEPARATED"].split()) + del myconfig["COLON_SEPARATED"] + + env = {} + specials = {} + for var in space_separated: + mylist = [] + for myconfig in config_list: + if var in myconfig: + for item in myconfig[var].split(): + if item and not item in mylist: + mylist.append(item) + del myconfig[var] # prepare for env.update(myconfig) + if mylist: + env[var] = " ".join(mylist) + specials[var] = mylist + + for var in colon_separated: + mylist = [] + for myconfig in config_list: + if var in myconfig: + for item in myconfig[var].split(":"): + if item and not item in mylist: + mylist.append(item) + del myconfig[var] # prepare for env.update(myconfig) + if mylist: + env[var] = ":".join(mylist) + specials[var] = mylist + + for myconfig in config_list: + """Cumulative variables have already been deleted from myconfig so that + they won't be overwritten by this dict.update call.""" + env.update(myconfig) + + ldsoconf_path = os.path.join(target_root, "etc", "ld.so.conf") + try: + myld = codecs.open(_unicode_encode(ldsoconf_path, + encoding=_encodings['fs'], errors='strict'), + mode='r', encoding=_encodings['content'], errors='replace') + myldlines=myld.readlines() + myld.close() + oldld=[] + for x in myldlines: + #each line has at least one char (a newline) + if x[:1] == "#": + continue + oldld.append(x[:-1]) + except (IOError, OSError) as e: + if e.errno != errno.ENOENT: + raise + oldld = None + + ld_cache_update=False + + newld = specials["LDPATH"] + if (oldld != newld): + #ld.so.conf needs updating and ldconfig needs to be run + myfd = atomic_ofstream(ldsoconf_path) + myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n") + myfd.write("# contents of /etc/env.d directory\n") + for x in specials["LDPATH"]: + myfd.write(x + "\n") + myfd.close() + ld_cache_update=True + + # Update prelink.conf if we are prelink-enabled + if prelink_capable: + newprelink = atomic_ofstream( + os.path.join(target_root, "etc", "prelink.conf")) + newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n") + newprelink.write("# contents of /etc/env.d directory\n") + + for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]: + newprelink.write("-l %s\n" % (x,)); + prelink_paths = [] + prelink_paths += specials.get("LDPATH", []) + prelink_paths += specials.get("PATH", []) + prelink_paths += specials.get("PRELINK_PATH", []) + prelink_path_mask = specials.get("PRELINK_PATH_MASK", []) + for x in prelink_paths: + if not x: + continue + if x[-1:] != '/': + x += "/" + plmasked = 0 + for y in prelink_path_mask: + if not y: + continue + if y[-1] != '/': + y += "/" + if y == x[0:len(y)]: + plmasked = 1 + break + if not plmasked: + newprelink.write("-h %s\n" % (x,)) + for x in prelink_path_mask: + newprelink.write("-b %s\n" % (x,)) + newprelink.close() + + # Portage stores mtimes with 1 second granularity but in >=python-2.5 finer + # granularity is possible. In order to avoid the potential ambiguity of + # mtimes that differ by less than 1 second, sleep here if any of the + # directories have been modified during the current second. + sleep_for_mtime_granularity = False + current_time = long(time.time()) + mtime_changed = False + lib_dirs = set() + for lib_dir in set(specials["LDPATH"] + \ + ['usr/lib','usr/lib64','usr/lib32','lib','lib64','lib32']): + x = os.path.join(target_root, lib_dir.lstrip(os.sep)) + try: + newldpathtime = os.stat(x)[stat.ST_MTIME] + lib_dirs.add(normalize_path(x)) + except OSError as oe: + if oe.errno == errno.ENOENT: + try: + del prev_mtimes[x] + except KeyError: + pass + # ignore this path because it doesn't exist + continue + raise + if newldpathtime == current_time: + sleep_for_mtime_granularity = True + if x in prev_mtimes: + if prev_mtimes[x] == newldpathtime: + pass + else: + prev_mtimes[x] = newldpathtime + mtime_changed = True + else: + prev_mtimes[x] = newldpathtime + mtime_changed = True + + if mtime_changed: + ld_cache_update = True + + if makelinks and \ + not ld_cache_update and \ + contents is not None: + libdir_contents_changed = False + for mypath, mydata in contents.items(): + if mydata[0] not in ("obj", "sym"): + continue + head, tail = os.path.split(mypath) + if head in lib_dirs: + libdir_contents_changed = True + break + if not libdir_contents_changed: + makelinks = False + + ldconfig = "/sbin/ldconfig" + if "CHOST" in env and "CBUILD" in env and \ + env["CHOST"] != env["CBUILD"]: + ldconfig = find_binary("%s-ldconfig" % env["CHOST"]) + + # Only run ldconfig as needed + if (ld_cache_update or makelinks) and ldconfig: + # ldconfig has very different behaviour between FreeBSD and Linux + if ostype == "Linux" or ostype.lower().endswith("gnu"): + # We can't update links if we haven't cleaned other versions first, as + # an older package installed ON TOP of a newer version will cause ldconfig + # to overwrite the symlinks we just made. -X means no links. After 'clean' + # we can safely create links. + writemsg_level(_(">>> Regenerating %setc/ld.so.cache...\n") % \ + (target_root,)) + if makelinks: + os.system("cd / ; %s -r '%s'" % (ldconfig, target_root)) + else: + os.system("cd / ; %s -X -r '%s'" % (ldconfig, target_root)) + elif ostype in ("FreeBSD","DragonFly"): + writemsg_level(_(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % \ + target_root) + os.system(("cd / ; %s -elf -i " + \ + "-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'") % \ + (ldconfig, target_root, target_root)) + + del specials["LDPATH"] + + penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n" + penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n" + cenvnotice = penvnotice[:] + penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n" + cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n" + + #create /etc/profile.env for bash support + outfile = atomic_ofstream(os.path.join(target_root, "etc", "profile.env")) + outfile.write(penvnotice) + + env_keys = [ x for x in env if x != "LDPATH" ] + env_keys.sort() + for k in env_keys: + v = env[k] + if v.startswith('$') and not v.startswith('${'): + outfile.write("export %s=$'%s'\n" % (k, v[1:])) + else: + outfile.write("export %s='%s'\n" % (k, v)) + outfile.close() + + #create /etc/csh.env for (t)csh support + outfile = atomic_ofstream(os.path.join(target_root, "etc", "csh.env")) + outfile.write(cenvnotice) + for x in env_keys: + outfile.write("setenv %s '%s'\n" % (x, env[x])) + outfile.close() + + if sleep_for_mtime_granularity: + while current_time == long(time.time()): + time.sleep(1)