From 4a0f58b903f929b341d3e0274fd1d5ef30f3c3e5 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Fri, 14 Aug 2009 20:57:11 +0000 Subject: [PATCH] Merged from trunk -r14028:14042 | 14029 | Rename and log installed files that don't conform to | | zmedico | portage._merge_encoding (equal to | | | sys.getfilesystemencoding()). | | 14034 | Don't hold references to config instances, since all that's | | zmedico | really needed is $ROOT. | | 14042 | Add a clean_world attribute. | | zmedico | | svn path=/main/branches/prefix/; revision=14047 --- pym/_emerge/EbuildPhase.py | 11 ++- pym/_emerge/PackageUninstall.py | 6 +- pym/portage/__init__.py | 128 +++++++++++++++++++++++++------- pym/portage/elog/mod_echo.py | 8 +- 4 files changed, 118 insertions(+), 35 deletions(-) diff --git a/pym/_emerge/EbuildPhase.py b/pym/_emerge/EbuildPhase.py index 598dcf7e3..9d2ec632d 100644 --- a/pym/_emerge/EbuildPhase.py +++ b/pym/_emerge/EbuildPhase.py @@ -48,8 +48,17 @@ class EbuildPhase(CompositeTask): settings = self.settings if self.phase == "install": + out = None + log_path = self.settings.get("PORTAGE_LOG_FILE") + log_file = None + if self.background and log_path is not None: + log_file = codecs.open(log_path, mode='a', + encoding='utf_8', errors='replace') + out = log_file portage._post_src_install_chost_fix(settings) - portage._post_src_install_uid_fix(settings) + portage._post_src_install_uid_fix(settings, out=out) + if log_file is not None: + log_file.close() post_phase_cmds = self._post_phase_cmds.get(self.phase) if post_phase_cmds is not None: diff --git a/pym/_emerge/PackageUninstall.py b/pym/_emerge/PackageUninstall.py index ff1b5e189..24f08d451 100644 --- a/pym/_emerge/PackageUninstall.py +++ b/pym/_emerge/PackageUninstall.py @@ -12,12 +12,14 @@ from _emerge.UninstallFailure import UninstallFailure class PackageUninstall(AsynchronousTask): - __slots__ = ("ldpath_mtimes", "opts", "pkg", "scheduler", "settings") + __slots__ = ("clean_world", "ldpath_mtimes", "opts", + "pkg", "scheduler", "settings") def _start(self): try: unmerge(self.pkg.root_config, self.opts, "unmerge", - [self.pkg.cpv], self.ldpath_mtimes, clean_world=0, + [self.pkg.cpv], self.ldpath_mtimes, + clean_world=self.clean_world, clean_delay=0, raise_on_error=1, scheduler=self.scheduler, writemsg_level=self._writemsg_level) except UninstallFailure, e: diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 47b635941..3d8bcbd24 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -5547,7 +5547,7 @@ def _post_src_install_chost_fix(settings): write_atomic(os.path.join(settings['PORTAGE_BUILDDIR'], 'build-info', 'CHOST'), chost + '\n') -def _post_src_install_uid_fix(mysettings): +def _post_src_install_uid_fix(mysettings, out=None): """ Files in $D with user and group bits that match the "portage" user or group are automatically mapped to PORTAGE_INST_UID and @@ -5572,34 +5572,106 @@ def _post_src_install_uid_fix(mysettings): (_shell_quote(mysettings["D"]),)) destdir = mysettings["D"] + unicode_errors = [] - size = 0 - counted_inodes = set() - - for parent, dirs, files in os.walk(destdir): - parent = _unicode_decode(parent, encoding=_merge_encoding) - for fname in chain(dirs, files): - fname = _unicode_decode(fname, encoding=_merge_encoding) - fpath = os.path.join(parent, fname) - mystat = os.lstat(fpath) - if stat.S_ISREG(mystat.st_mode) and \ - mystat.st_ino not in counted_inodes: - counted_inodes.add(mystat.st_ino) - size += mystat.st_size - if mystat.st_uid != portage_uid and \ - mystat.st_gid != portage_gid: - continue - myuid = -1 - mygid = -1 - if mystat.st_uid == portage_uid: - myuid = inst_uid - if mystat.st_gid == portage_gid: - mygid = inst_gid - apply_secpass_permissions( - _unicode_encode(fpath, encoding=_merge_encoding), - uid=myuid, gid=mygid, - mode=mystat.st_mode, stat_cached=mystat, - follow_links=False) + while True: + + unicode_error = False + size = 0 + counted_inodes = set() + + for parent, dirs, files in os.walk(destdir): + try: + parent = _unicode_decode(parent, + encoding=_merge_encoding, errors='strict') + except UnicodeDecodeError: + new_parent = _unicode_decode(parent, + encoding=_merge_encoding, errors='replace') + new_parent = _unicode_encode(new_parent, + encoding=_merge_encoding, errors='backslashreplace') + new_parent = _unicode_decode(new_parent, + encoding=_merge_encoding, errors='replace') + os.rename(parent, new_parent) + unicode_error = True + unicode_errors.append(new_parent[len(destdir):]) + break + + for fname in chain(dirs, files): + try: + fname = _unicode_decode(fname, + encoding=_merge_encoding, errors='strict') + except UnicodeDecodeError: + fpath = _os.path.join( + parent.encode(_merge_encoding), fname) + new_fname = _unicode_decode(fname, + encoding=_merge_encoding, errors='replace') + new_fname = _unicode_encode(new_fname, + encoding=_merge_encoding, errors='backslashreplace') + new_fname = _unicode_decode(new_fname, + encoding=_merge_encoding, errors='replace') + new_fpath = os.path.join(parent, new_fname) + os.rename(fpath, new_fpath) + unicode_error = True + unicode_errors.append(new_fpath[len(destdir):]) + fname = new_fname + fpath = new_fpath + else: + fpath = os.path.join(parent, fname) + + mystat = os.lstat(fpath) + if stat.S_ISREG(mystat.st_mode) and \ + mystat.st_ino not in counted_inodes: + counted_inodes.add(mystat.st_ino) + size += mystat.st_size + if mystat.st_uid != portage_uid and \ + mystat.st_gid != portage_gid: + continue + myuid = -1 + mygid = -1 + if mystat.st_uid == portage_uid: + myuid = inst_uid + if mystat.st_gid == portage_gid: + mygid = inst_gid + apply_secpass_permissions( + _unicode_encode(fpath, encoding=_merge_encoding), + uid=myuid, gid=mygid, + mode=mystat.st_mode, stat_cached=mystat, + follow_links=False) + + if unicode_error: + break + + if not unicode_error: + break + + if unicode_errors: + from textwrap import wrap + from portage.elog.messages import eerror + def _eerror(l): + eerror(l, phase='install', key=mysettings.mycpv, out=out) + + msg = "This package installs one or more file names containing " + \ + "characters that do not match your current locale " + \ + "settings. The current setting for filesystem encoding is '%s'." \ + % _merge_encoding + for l in wrap(msg, 72): + _eerror(l) + + _eerror("") + for x in unicode_errors: + _eerror("\t" + x) + _eerror("") + + if _merge_encoding.lower().replace('_', '').replace('-', '') != 'utf8': + msg = "For best results, UTF-8 encoding is recommended. See " + \ + "the Gentoo Linux Localization Guide for instructions " + \ + "about how to configure your locale for UTF-8 encoding:" + for l in wrap(msg, 72): + _eerror(l) + _eerror("") + _eerror("\t" + \ + "http://www.gentoo.org/doc/en/guide-localization.xml") + _eerror("") open(_unicode_encode(os.path.join(mysettings['PORTAGE_BUILDDIR'], 'build-info', 'SIZE')), 'w').write(str(size) + '\n') diff --git a/pym/portage/elog/mod_echo.py b/pym/portage/elog/mod_echo.py index fa6577dc6..445b4308b 100644 --- a/pym/portage/elog/mod_echo.py +++ b/pym/portage/elog/mod_echo.py @@ -10,7 +10,7 @@ from portage.localization import _ _items = [] def process(mysettings, key, logentries, fulltext): global _items - _items.append((mysettings, key, logentries)) + _items.append((mysettings["ROOT"], key, logentries)) def finalize(mysettings=None): """The mysettings parameter is just for backward compatibility since @@ -18,14 +18,14 @@ def finalize(mysettings=None): when it upgrades itself.""" global _items printer = EOutput() - for mysettings, key, logentries in _items: + for root, key, logentries in _items: print - if mysettings["ROOT"] == "/": + if root == "/": printer.einfo(_("Messages for package %s:") % colorize("INFORM", key)) else: printer.einfo(_("Messages for package %(pkg)s merged to %(root)s:") % - {"pkg": colorize("INFORM", key), "root": mysettings["ROOT"]}) + {"pkg": colorize("INFORM", key), "root": root}) print for phase in EBUILD_PHASES: if phase not in logentries: -- 2.26.2