From d0808cc0eb7bf8655e33fc998cd99d55ba5a269e Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Wed, 3 Mar 2010 18:46:26 +0000 Subject: [PATCH] Merged from trunk -r15507:15517 | 15508 | Move imports to the top and use writemsg_stdout instead of | | zmedico | print(). | | 15509 | Use writemsg instead of print. Also don't use _ as a | | zmedico | variable name since it collides with _ from | | | portage.localization. | | 15510 | Add a note in _find_system_deps about needing the system set | | zmedico | added to the graph. | | 15511 | Fix legacy globals proxies to reset state when the portage | | zmedico | module is reloaded. This fixes ebuild(1) failing to generate | | | manifests when the ebuild is not in PORTDIR_OVERLAY, as | | | reported by Arfrever. | | 15512 | Test for python openpty breakage after freebsd7 to freebsd8 | | zmedico | upgrade, which results in a 'Function not implemented' error | | | and the process being killed. Thanks to Javier | | | Villavicenciom for reporting and helping to | | | develop this test. | | 15513 | Bug #306659 - For --rebuilt-binaries, only reinstall if | | zmedico | binary package BUILD_TIME is non-empty, in order to avoid | | | cases like to bug #306659 where BUILD_TIME fields are | | | missing in local and/or remote Packages file. | | 15514 | Move imports to top. | | zmedico | | | 15515 | Move _pty module to portage.util._pty. | | zmedico | | svn path=/main/branches/prefix/; revision=15736 --- pym/_emerge/AbstractEbuildProcess.py | 2 +- pym/_emerge/EbuildFetcher.py | 2 +- pym/_emerge/Scheduler.py | 3 ++ pym/_emerge/depgraph.py | 9 +++- pym/portage/__init__.py | 2 + pym/portage/_legacy_globals.py | 44 ++++++++++---------- pym/portage/dbapi/vartree.py | 34 ++++++++------- pym/portage/package/ebuild/doebuild.py | 18 ++++---- pym/portage/tests/ebuild/test_pty_eof.py | 2 +- pym/portage/{package/ebuild => util}/_pty.py | 23 +++++++--- 10 files changed, 81 insertions(+), 58 deletions(-) rename pym/portage/{package/ebuild => util}/_pty.py (89%) diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py index 0d8be6fbf..64846ff8c 100644 --- a/pym/_emerge/AbstractEbuildProcess.py +++ b/pym/_emerge/AbstractEbuildProcess.py @@ -5,7 +5,7 @@ from _emerge.SpawnProcess import SpawnProcess import portage from portage import os -from portage.package.ebuild._pty import _create_pty_or_pipe +from portage.util._pty import _create_pty_or_pipe class AbstractEbuildProcess(SpawnProcess): diff --git a/pym/_emerge/EbuildFetcher.py b/pym/_emerge/EbuildFetcher.py index b2ba07bcd..14c348483 100644 --- a/pym/_emerge/EbuildFetcher.py +++ b/pym/_emerge/EbuildFetcher.py @@ -13,7 +13,7 @@ from portage import _encodings from portage import _unicode_encode import codecs from portage.elog.messages import eerror -from portage.package.ebuild._pty import _create_pty_or_pipe +from portage.util._pty import _create_pty_or_pipe class EbuildFetcher(SpawnProcess): diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py index 0f113416f..a97adc041 100644 --- a/pym/_emerge/Scheduler.py +++ b/pym/_emerge/Scheduler.py @@ -357,6 +357,9 @@ class Scheduler(PollScheduler): Find system packages and their deep runtime dependencies. Before being merged, these packages go to merge_wait_queue, to be merged when no other packages are building. + NOTE: This can only find deep system deps if the system set has been + added to the graph and traversed deeply (the depgraph "complete" + parameter will do this, triggered by emerge --complete-graph option). """ deep_system_deps = self._deep_system_deps deep_system_deps.clear() diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 73ff21cf8..831b6e81f 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -2640,8 +2640,13 @@ class depgraph(object): elif pkg.built: built_pkg = pkg if built_pkg is not None and inst_pkg is not None: - if built_pkg.metadata['BUILD_TIME'] != \ - inst_pkg.metadata['BUILD_TIME']: + # Only reinstall if binary package BUILD_TIME is + # non-empty, in order to avoid cases like to + # bug #306659 where BUILD_TIME fields are missing + # in local and/or remote Packages file. + if built_pkg.metadata['BUILD_TIME'] and \ + (built_pkg.metadata['BUILD_TIME'] != \ + inst_pkg.metadata['BUILD_TIME']): return built_pkg, built_pkg if avoid_update: diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 8309fb03c..6679555a1 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -575,6 +575,8 @@ for k in _legacy_global_var_names: globals()[k] = _LegacyGlobalProxy(k) del k +_legacy_globals_constructed = set() + def _disable_legacy_globals(): """ This deletes the ObjectProxy instances that are used diff --git a/pym/portage/_legacy_globals.py b/pym/portage/_legacy_globals.py index f524cbe38..19fce20d1 100644 --- a/pym/portage/_legacy_globals.py +++ b/pym/portage/_legacy_globals.py @@ -6,25 +6,23 @@ import portage from portage import os from portage.const import CACHE_PATH, PROFILE_PATH -_legacy_globals = {} - def _get_legacy_global(name): - global _legacy_globals - target = _legacy_globals.get(name, _legacy_globals) - if target is not _legacy_globals: - return target + constructed = portage._legacy_globals_constructed + if name in constructed: + return getattr(portage, name) if name == 'portdb': portage.portdb = portage.db[portage.root]["porttree"].dbapi - _legacy_globals[name] = portage.portdb - return _legacy_globals[name] + constructed.add(name) + return getattr(portage, name) + elif name in ('mtimedb', 'mtimedbfile'): portage.mtimedbfile = os.path.join(portage.root, CACHE_PATH, "mtimedb") - _legacy_globals['mtimedbfile'] = portage.mtimedbfile + constructed.add('mtimedbfile') portage.mtimedb = portage.MtimeDB(portage.mtimedbfile) - _legacy_globals['mtimedb'] = portage.mtimedb - return _legacy_globals[name] + constructed.add('mtimedb') + return getattr(portage, name) # Portage needs to ensure a sane umask for the files it creates. os.umask(0o22) @@ -35,7 +33,7 @@ def _get_legacy_global(name): portage._initializing_globals = True portage.db = portage.create_trees(**kwargs) - _legacy_globals['db'] = portage.db + constructed.add('db') del portage._initializing_globals settings = portage.db["/"]["vartree"].settings @@ -48,40 +46,40 @@ def _get_legacy_global(name): portage.output._init(config_root=settings['PORTAGE_CONFIGROOT']) portage.settings = settings - _legacy_globals['settings'] = settings + constructed.add('settings') portage.root = root - _legacy_globals['root'] = root + constructed.add('root') # COMPATIBILITY # These attributes should not be used within # Portage under any circumstances. portage.archlist = settings.archlist() - _legacy_globals['archlist'] = portage.archlist + constructed.add('archlist') portage.features = settings.features - _legacy_globals['features'] = portage.features + constructed.add('features') portage.groups = settings["ACCEPT_KEYWORDS"].split() - _legacy_globals['groups'] = portage.groups + constructed.add('groups') portage.pkglines = settings.packages - _legacy_globals['pkglines'] = portage.pkglines + constructed.add('pkglines') portage.selinux_enabled = settings.selinux_enabled() - _legacy_globals['selinux_enabled'] = portage.selinux_enabled + constructed.add('selinux_enabled') portage.thirdpartymirrors = settings.thirdpartymirrors() - _legacy_globals['thirdpartymirrors'] = portage.thirdpartymirrors + constructed.add('thirdpartymirrors') portage.usedefaults = settings.use_defs - _legacy_globals['usedefaults'] = portage.usedefaults + constructed.add('usedefaults') profiledir = os.path.join(settings["PORTAGE_CONFIGROOT"], PROFILE_PATH) if not os.path.isdir(profiledir): profiledir = None portage.profiledir = profiledir - _legacy_globals['profiledir'] = portage.profiledir + constructed.add('profiledir') - return _legacy_globals[name] + return getattr(portage, name) diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 1e1d6c693..5f4c43720 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -2,8 +2,6 @@ # Distributed under the terms of the GNU General Public License v2 # $Id$ -from __future__ import print_function - __all__ = ["PreservedLibsRegistry", "LinkageMap", "LinkageMapMachO", "LinkageMapPeCoff", "LinkageMapXCoff" "vardbapi", "vartree", "dblink"] + \ @@ -501,7 +499,7 @@ class LinkageMap(object): if obj_key.file_exists(): # Get the arch and soname from LinkageMap._obj_properties if # it exists. Otherwise, None. - arch, _, _, soname, _ = \ + arch, _needed, _path, soname, _objs = \ self._obj_properties.get(obj_key, (None,)*5) return cache_self.cache.setdefault(obj, \ (arch, soname, obj_key, True)) @@ -515,7 +513,7 @@ class LinkageMap(object): # Iterate over all obj_keys and their providers. for obj_key, sonames in providers.items(): - arch, _, path, _, objs = self._obj_properties[obj_key] + arch, _needed, path, _soname, objs = self._obj_properties[obj_key] path = path.union(self._defpath) # Iterate over each needed soname and the set of library paths that # fulfill the soname to determine if the dependency is broken. @@ -545,19 +543,23 @@ class LinkageMap(object): # XXX This is most often due to soname symlinks not in # a library's directory. We could catalog symlinks in # LinkageMap to avoid checking for this edge case here. - print(_("Found provider outside of findProviders:"), \ - os.path.join(directory, soname), "->", \ - self._obj_properties[cachedKey][4], libraries) + writemsg( + _("Found provider outside of findProviders:") + \ + (" %s -> %s %s\n" % (os.path.join(directory, soname), + self._obj_properties[cachedKey][4], libraries)), + noiselevel=-1) # A valid library has been found, so there is no need to # continue. break if debug and cachedArch == arch and \ cachedKey in self._obj_properties: - print(_("Broken symlink or missing/bad soname: %(dir_soname)s -> %(cachedKey)s " + writemsg((_("Broken symlink or missing/bad soname: " + \ + "%(dir_soname)s -> %(cachedKey)s " + \ "with soname %(cachedSoname)s but expecting %(soname)s") % \ {"dir_soname":os.path.join(directory, soname), "cachedKey": self._obj_properties[cachedKey], - "cachedSoname": cachedSoname, "soname":soname}) + "cachedSoname": cachedSoname, "soname":soname}) + "\n", + noiselevel=-1) # This conditional checks if there are no libraries to satisfy the # soname (empty set). if not validLibraries: @@ -573,10 +575,12 @@ class LinkageMap(object): rValue.setdefault(lib, set()).add(soname) if debug: if not os.path.isfile(lib): - print(_("Missing library:"), lib) + writemsg(_("Missing library:") + " %s\n" % (lib,), + noiselevel=-1) else: - print(_("Possibly missing symlink:"), \ - os.path.join(os.path.dirname(lib), soname)) + writemsg(_("Possibly missing symlink:") + \ + "%s\n" % (os.path.join(os.path.dirname(lib), soname)), + noiselevel=-1) return rValue def listProviders(self): @@ -696,7 +700,7 @@ class LinkageMap(object): if obj_key not in self._obj_properties: raise KeyError("%s (%s) not in object list" % (obj_key, obj)) - arch, needed, path, _, _ = self._obj_properties[obj_key] + arch, needed, path, _soname, _objs = self._obj_properties[obj_key] path_keys = set(self._path_key(x) for x in path.union(self._defpath)) for soname in needed: rValue[soname] = set() @@ -783,12 +787,12 @@ class LinkageMap(object): objs_dir_keys = set(self._path_key(os.path.dirname(x)) for x in objs) defpath_keys = set(self._path_key(x) for x in self._defpath) - arch, _, _, soname, _ = self._obj_properties[obj_key] + arch, _needed, _path, soname, _objs = self._obj_properties[obj_key] if arch in self._libs and soname in self._libs[arch]: # For each potential consumer, add it to rValue if an object from the # arguments resides in the consumer's runpath. for consumer_key in self._libs[arch][soname].consumers: - _, _, path, _, consumer_objs = \ + _arch, _needed, path, _soname, consumer_objs = \ self._obj_properties[consumer_key] path_keys = defpath_keys.union(self._path_key(x) for x in path) if objs_dir_keys.intersection(path_keys): diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py index a900758b6..c7f852f07 100644 --- a/pym/portage/package/ebuild/doebuild.py +++ b/pym/portage/package/ebuild/doebuild.py @@ -2,19 +2,21 @@ # Distributed under the terms of the GNU General Public License v2 # $Id$ -from __future__ import print_function - __all__ = ['doebuild', 'doebuild_environment', 'spawn', 'spawnebuild'] +import array import codecs import errno +import fcntl from itertools import chain import logging import os as _os import re +import select import shutil import stat import sys +import tempfile from textwrap import wrap import time @@ -47,10 +49,10 @@ from portage.manifest import Manifest from portage.output import style_to_ansi_code from portage.package.ebuild.fetch import fetch from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs -from portage.package.ebuild._pty import _create_pty_or_pipe from portage.util import apply_recursive_permissions, \ apply_secpass_permissions, noiselimit, normalize_path, \ writemsg, writemsg_stdout, write_atomic +from portage.util._pty import _create_pty_or_pipe from portage.versions import _pkgsplit def doebuild_environment(myebuild, mydo, myroot, mysettings, @@ -525,8 +527,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, # so that there's no need for locking and it can be used even if the # user isn't in the portage group. if mydo in ("info",): - from tempfile import mkdtemp - tmpdir = mkdtemp() + tmpdir = tempfile.mkdtemp() tmpdir_orig = mysettings["PORTAGE_TMPDIR"] mysettings["PORTAGE_TMPDIR"] = tmpdir @@ -622,8 +623,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, noiselevel=-1) return 1 else: - from tempfile import NamedTemporaryFile - fd = NamedTemporaryFile(prefix="exectest-", dir=checkdir) + fd = tempfile.NamedTemporaryFile(prefix="exectest-", dir=checkdir) os.chmod(fd.name, 0o755) if not os.access(fd.name, os.X_OK): writemsg(_("Can not execute files in %s\n" @@ -1004,7 +1004,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, myebuild=mysettings["EBUILD"], mytree=tree, mydbapi=mydbapi, vartree=vartree, prev_mtimes=prev_mtimes) else: - print(_("!!! Unknown mydo: %s") % mydo) + writemsg_stdout(_("!!! Unknown mydo: %s\n") % mydo, noiselevel=-1) return 1 return retval @@ -1190,7 +1190,6 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero # process might have already exited and closed slave_fd so we # have to keep it open in order to avoid FreeBSD potentially # generating an EAGAIN exception). - import fcntl fcntl.fcntl(master_fd, fcntl.F_SETFL, fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK) @@ -1250,7 +1249,6 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero iwtd = [master_file] owtd = [] ewtd = [] - import array, select buffsize = 65536 eof = False while not eof: diff --git a/pym/portage/tests/ebuild/test_pty_eof.py b/pym/portage/tests/ebuild/test_pty_eof.py index b29c8f95f..6280eb263 100644 --- a/pym/portage/tests/ebuild/test_pty_eof.py +++ b/pym/portage/tests/ebuild/test_pty_eof.py @@ -4,7 +4,7 @@ import portage from portage.tests import TestCase -from portage.package.ebuild._pty import _can_test_pty_eof, _test_pty_eof +from portage.util._pty import _can_test_pty_eof, _test_pty_eof class PtyEofTestCase(TestCase): diff --git a/pym/portage/package/ebuild/_pty.py b/pym/portage/util/_pty.py similarity index 89% rename from pym/portage/package/ebuild/_pty.py rename to pym/portage/util/_pty.py index 7cc1e4422..c48584f58 100644 --- a/pym/portage/package/ebuild/_pty.py +++ b/pym/portage/util/_pty.py @@ -11,6 +11,7 @@ import sys import termios from portage import os, _unicode_decode, _unicode_encode +from portage.output import get_term_size, set_term_size from portage.process import spawn_bash from portage.util import writemsg @@ -132,6 +133,8 @@ if not _can_test_pty_eof(): # Skip _test_pty_eof() on systems where it hangs. _tested_pty = True +_fbsd_test_pty = platform.system() == 'FreeBSD' + def _create_pty_or_pipe(copy_term_size=None): """ Try to create a pty and if then fails then create a normal @@ -148,7 +151,7 @@ def _create_pty_or_pipe(copy_term_size=None): got_pty = False - global _disable_openpty, _tested_pty + global _disable_openpty, _fbsd_test_pty, _tested_pty if not (_tested_pty or _disable_openpty): try: if not _test_pty_eof(): @@ -160,12 +163,24 @@ def _create_pty_or_pipe(copy_term_size=None): del e _tested_pty = True + if _fbsd_test_pty and not _disable_openpty: + # Test for python openpty breakage after freebsd7 to freebsd8 + # upgrade, which results in a 'Function not implemented' error + # and the process being killed. + pid = os.fork() + if pid == 0: + pty.openpty() + os._exit(os.EX_OK) + pid, status = os.waitpid(pid, 0) + if (status & 0xff) == 140: + _disable_openpty = True + _fbsd_test_pty = False + if _disable_openpty: master_fd, slave_fd = os.pipe() else: - from pty import openpty try: - master_fd, slave_fd = openpty() + master_fd, slave_fd = pty.openpty() got_pty = True except EnvironmentError as e: _disable_openpty = True @@ -177,7 +192,6 @@ def _create_pty_or_pipe(copy_term_size=None): if got_pty: # Disable post-processing of output since otherwise weird # things like \n -> \r\n transformations may occur. - import termios mode = termios.tcgetattr(slave_fd) mode[1] &= ~termios.OPOST termios.tcsetattr(slave_fd, termios.TCSANOW, mode) @@ -185,7 +199,6 @@ def _create_pty_or_pipe(copy_term_size=None): if got_pty and \ copy_term_size is not None and \ os.isatty(copy_term_size): - from portage.output import get_term_size, set_term_size rows, columns = get_term_size() set_term_size(rows, columns, slave_fd) -- 2.26.2