diff --git a/git/cmd.py b/git/cmd.py index b6305176b..081edf082 100644 --- a/git/cmd.py +++ b/git/cmd.py @@ -78,17 +78,19 @@ def handle_process_output(process, stdout_handler, stderr_handler, Set it to False if `universal_newline == True` (then streams are in text-mode) or if decoding must happen later (i.e. for Diffs). """ + pumped_lines = {'stdout': [], 'stderr': []} # Use 2 "pupm" threads and wait for both to finish. def pump_stream(cmdline, name, stream, is_decode, handler): try: for line in stream: + if is_decode: + line = line.decode(defenc) + pumped_lines[name].append(line) if handler: - if is_decode: - line = line.decode(defenc) handler(line) except Exception as ex: log.error("Pumping %r of cmd(%s) failed due to: %r", name, cmdline, ex) - raise CommandError(['<%s-pump>' % name] + cmdline, ex) + raise CommandError(['<%s-pump>' % name] + cmdline, ex, **pumped_lines) finally: stream.close() @@ -104,20 +106,29 @@ def pump_stream(cmdline, name, stream, is_decode, handler): threads = [] - for name, stream, handler in pumps: - t = threading.Thread(target=pump_stream, - args=(cmdline, name, stream, decode_streams, handler)) - t.setDaemon(True) - t.start() - threads.append(t) + try: + for name, stream, handler in pumps: + t = threading.Thread(target=pump_stream, + args=(cmdline, name, stream, decode_streams, handler)) + t.setDaemon(True) + t.start() + threads.append(t) + + ## FIXME: Why Join?? Will block if `stdin` needs feeding... + # + for t in threads: + t.join() + + if finalizer: + return finalizer(process) + except Exception as e: + for outname, out in pumped_lines.items(): + if out and hasattr(e, outname): + eout = getattr(e, outname) + if not eout: + setattr(e, outname, safe_decode(os.linesep.join(out))) + raise - ## FIXME: Why Join?? Will block if `stdin` needs feeding... - # - for t in threads: - t.join() - - if finalizer: - return finalizer(process) def dashify(string): diff --git a/git/exc.py b/git/exc.py index 4865da944..4f5ef7b2c 100644 --- a/git/exc.py +++ b/git/exc.py @@ -55,12 +55,16 @@ def __init__(self, command, status=None, stderr=None, stdout=None): self._cmd = safe_decode(command[0]) self._cmdline = u' '.join(safe_decode(i) for i in command) self._cause = status and u" due to: %s" % status or "!" - self.stdout = stdout and u"\n stdout: '%s'" % safe_decode(stdout) or '' - self.stderr = stderr and u"\n stderr: '%s'" % safe_decode(stderr) or '' + self.stdout = stdout and safe_decode(stdout) or '' + self.stderr = stderr and safe_decode(stderr) or '' def __unicode__(self): return (self._msg + "\n cmdline: %s%s%s") % ( - self._cmd, self._cause, self._cmdline, self.stdout, self.stderr) + self._cmd, self._cause, + self._cmdline, + u"\n stdout: '%s'" % self.stdout if self.stdout else '', + u"\n stderr: '%s'" % self.stderr if self.stderr else '' + ) class GitCommandNotFound(CommandError):