Merged from trunk -r14028:14042
authorFabian Groffen <grobian@gentoo.org>
Fri, 14 Aug 2009 20:57:11 +0000 (20:57 -0000)
committerFabian Groffen <grobian@gentoo.org>
Fri, 14 Aug 2009 20:57:11 +0000 (20:57 -0000)
   | 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
pym/_emerge/PackageUninstall.py
pym/portage/__init__.py
pym/portage/elog/mod_echo.py

index 598dcf7e3faef3bbabcb0c4006083c3efa22f23a..9d2ec632d8e69511ab0bd4dc588cf00c5d6e07c3 100644 (file)
@@ -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:
index ff1b5e189ef4a32558c4f8c7ff992b99be8fc9df..24f08d451a9b3966a5dea74ea157dd8b88199083 100644 (file)
@@ -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:
index 47b635941f81a8d8efe55a8c80d2736f1c0833cd..3d8bcbd24a77038b538cb01161bfa63c59c30502 100644 (file)
@@ -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')
index fa6577dc6d59f8f397d56bd3208aaf22fb5f8544..445b4308bf54985a6322b98f6d5c50a7b264e1b1 100644 (file)
@@ -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: