Handle UnicodeDecodeError from subprocess.getstatusoutput() calls, reported
authorZac Medico <zmedico@gentoo.org>
Sat, 24 Jul 2010 20:52:44 +0000 (13:52 -0700)
committerZac Medico <zmedico@gentoo.org>
Sat, 24 Jul 2010 20:52:44 +0000 (13:52 -0700)
with python3.1.

bin/dispatch-conf
pym/portage/dispatch_conf.py

index 43fe145ae82df5c058b215171b69fd746db0a145..fc9cdd513a127025f30587e75768d15e0452352f 100755 (executable)
@@ -19,12 +19,7 @@ if not hasattr(__builtins__, "set"):
 from stat import *
 from random import *
 import atexit, re, shutil, stat, sys
-try:
-    from subprocess import getoutput as subprocess_getoutput
-    from subprocess import getstatusoutput as subprocess_getstatusoutput
-except ImportError:
-    from commands import getoutput as subprocess_getoutput
-    from commands import getstatusoutput as subprocess_getstatusoutput
+
 try:
     import portage
 except ImportError:
@@ -35,6 +30,7 @@ except ImportError:
 from portage import os
 from portage import dispatch_conf
 from portage import _unicode_decode
+from portage.dispatch_conf import diffstatusoutput_len
 from portage.process import find_binary
 
 FIND_EXTANT_CONFIGS  = "find '%s' %s -name '._cfg????_%s' ! -name '.*~' ! -iname '.*.bak' -print"
@@ -137,11 +133,11 @@ class dispatch:
             else:
                 mrgfail = portage.dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf)
             if os.path.exists(archive + '.dist'):
-                unmodified = len(subprocess_getoutput(DIFF_CONTENTS % (conf['current'], archive + '.dist'))) == 0
+                unmodified = diffstatusoutput_len(DIFF_CONTENTS % (conf['current'], archive + '.dist'))[1] == 0
             else:
                 unmodified = 0
             if os.path.exists(mrgconf):
-                if mrgfail or len(subprocess_getoutput(DIFF_CONTENTS % (conf['new'], mrgconf))) == 0:
+                if mrgfail or diffstatusoutput_len(DIFF_CONTENTS % (conf['new'], mrgconf))[1] == 0:
                     os.unlink(mrgconf)
                     newconf = conf['new']
                 else:
@@ -152,24 +148,24 @@ class dispatch:
             if newconf == mrgconf and \
                 self.options.get('ignore-previously-merged') != 'yes' and \
                 os.path.exists(archive+'.dist') and \
-                len(subprocess_getoutput(DIFF_CONTENTS % (archive+'.dist', conf['new']))) == 0:
+                diffstatusoutput_len(DIFF_CONTENTS % (archive+'.dist', conf['new']))[1] == 0:
                 # The current update is identical to the archived .dist
                 # version that has previously been merged.
                 os.unlink(mrgconf)
                 newconf = conf['new']
 
-            mystatus, myoutput = subprocess_getstatusoutput(
+            mystatus, myoutput_len = diffstatusoutput_len(
                 DIFF_CONTENTS  % (conf ['current'], newconf))
-            same_file = 0 == len(myoutput)
+            same_file = 0 == myoutput_len
             if mystatus >> 8 == 2:
                 # Binary files differ
                 same_cvs = False
                 same_wsc = False
             else:
-                same_cvs = 0 == len(subprocess_getoutput(
-                    DIFF_CVS_INTERP % (conf ['current'], newconf)))
-                same_wsc = 0 == len(subprocess_getoutput(
-                    DIFF_WSCOMMENTS % (conf ['current'], newconf)))
+                same_cvs = 0 == diffstatusoutput_len(
+                    DIFF_CVS_INTERP % (conf ['current'], newconf))[1]
+                same_wsc = 0 == diffstatusoutput_len(
+                    DIFF_WSCOMMENTS % (conf ['current'], newconf))[1]
 
             # Do options permit?
             same_cvs = same_cvs and self.options['replace-cvs'] == 'yes'
index 956f5237344152b5d5fa49e91ac61e315a13a067..b4cded266fe683299669add6447a3785236b8ffc 100644 (file)
@@ -10,9 +10,9 @@ from __future__ import print_function
 
 import os, sys, shutil
 try:
-       from subprocess import getoutput as subprocess_getoutput
+    from subprocess import getstatusoutput as subprocess_getstatusoutput
 except ImportError:
-       from commands import getoutput as subprocess_getoutput
+    from commands import getstatusoutput as subprocess_getstatusoutput
 
 import portage
 from portage.localization import _
@@ -25,6 +25,21 @@ RCS_MERGE = "rcsmerge -p -r" + RCS_BRANCH + " '%s' > '%s'"
 
 DIFF3_MERGE = "diff3 -mE '%s' '%s' '%s' > '%s'"
 
+def diffstatusoutput_len(cmd):
+    """
+    Execute the string cmd in a shell with getstatusoutput() and return a
+    2-tuple (status, output_length). If getstatusoutput() raises
+    UnicodeDecodeError (known to happen with python3.1), return a
+    2-tuple (1, 1). This provides a simple way to check for non-zero
+    output length of diff commands, while providing simple handling of
+    UnicodeDecodeError when necessary.
+    """
+    try:
+        status, output = subprocess_getstatusoutput(cmd)
+        return (status, len(output))
+    except UnicodeDecodeError:
+        return (1, 1)
+
 def read_config(mandatory_opts):
     loader = portage.env.loaders.KeyValuePairFileLoader(
         '/etc/dispatch-conf.conf', None)
@@ -115,7 +130,7 @@ def file_archive(archive, curconf, newconf, mrgconf):
 
     # Archive the current config file if it isn't already saved
     if os.path.exists(archive) \
-     and len(subprocess_getoutput("diff -aq '%s' '%s'" % (curconf,archive))) != 0:
+     and diffstatusoutput_len("diff -aq '%s' '%s'" % (curconf,archive))[1] != 0:
         suf = 1
         while suf < 9 and os.path.exists(archive + '.' + str(suf)):
             suf += 1