Update exception handling to use `except X as Y` syntax.
[update-copyright.git] / update_copyright / vcs / utils.py
index 3c3c1ba3234aa505da4c2101f0ca27c067915469..bafc1da62af7b5cb58d905e44d4aa5405ca9db8a 100644 (file)
@@ -1,4 +1,19 @@
-# Copyright
+# Copyright (C) 2012 W. Trevor King <wking@tremily.us>
+#
+# This file is part of update-copyright.
+#
+# update-copyright is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# update-copyright is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# update-copyright.  If not, see <http://www.gnu.org/licenses/>.
 
 """Useful utilities for backend classes."""
 
@@ -7,29 +22,46 @@ import os.path as _os_path
 import subprocess as _subprocess
 import sys as _sys
 
+from .. import LOG as LOG
+from ..utils import ENCODING as _ENCODING
+
 
 _MSWINDOWS = _sys.platform == 'win32'
 _POSIX = not _MSWINDOWS
 
 
 def invoke(args, stdin=None, stdout=_subprocess.PIPE, stderr=_subprocess.PIPE,
-           expect=(0,)):
-    """
-    expect should be a tuple of allowed exit codes.
+           cwd=None, expect=(0,), unicode_output=False, encoding=None):
+    """Invoke an external program and return the results
+
+    ``expect`` should be a tuple of allowed exit codes.
+
+    When ``unicode_output`` is ``True``, convert stdout and stdin
+    strings to unicode before returing them.
     """
+    LOG.debug('{}$ {}'.format(cwd, args))
     try :
         if _POSIX:
             q = _subprocess.Popen(args, stdin=_subprocess.PIPE,
-                                  stdout=stdout, stderr=stderr)
+                                  stdout=stdout, stderr=stderr,
+                                  close_fds=True, cwd=cwd)
         else:
             assert _MSWINDOWS == True, 'invalid platform'
             # win32 don't have os.execvp() so run the command in a shell
             q = _subprocess.Popen(args, stdin=_subprocess.PIPE,
-                                  stdout=stdout, stderr=stderr, shell=True)
-    except OSError, e:
+                                  stdout=stdout, stderr=stderr, shell=True,
+                                  cwd=cwd)
+    except OSError as e:
         raise ValueError([args, e])
     stdout,stderr = q.communicate(input=stdin)
     status = q.wait()
+    if unicode_output == True:
+        if encoding is None:
+            encoding = _ENCODING
+        if stdout is not None:
+            stdout = unicode(stdout, encoding)
+        if stderr is not None:
+            stderr = unicode(stderr, encoding)
     if status not in expect:
         raise ValueError([args, status, stdout, stderr])
     return status, stdout, stderr
@@ -51,7 +83,7 @@ def splitpath(path):
     while True:
         dirname,basename = _os_path.split(path)
         elements.insert(0,basename)
-        if dirname in ['', '.']:
+        if dirname in ['/', '', '.']:
             break
         path = dirname
     return tuple(elements)
@@ -130,6 +162,7 @@ def replace_aliases(authors, with_email=True, aliases=None):
     if aliases == None:
         aliases = ALIASES
     rev_aliases = reverse_aliases(aliases)
+    authors = list(authors)
     for i,author in enumerate(authors):
         if author in rev_aliases:
             authors[i] = rev_aliases[author]