diff options
-rw-r--r-- | pym/_emerge/EbuildPhase.py | 11 | ||||
-rw-r--r-- | pym/portage/__init__.py | 128 |
2 files changed, 110 insertions, 29 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/portage/__init__.py b/pym/portage/__init__.py index 7a1b80f15..f5cc1f41a 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -5525,7 +5525,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 @@ -5550,34 +5550,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') |