aboutsummaryrefslogtreecommitdiff
path: root/git
diff options
context:
space:
mode:
Diffstat (limited to 'git')
-rw-r--r--git/cmd.py15
-rw-r--r--git/remote.py23
-rw-r--r--git/util.py14
3 files changed, 44 insertions, 8 deletions
diff --git a/git/cmd.py b/git/cmd.py
index a8afc144..fb00869c 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -307,19 +307,28 @@ class Git(LazyMixin):
def __getattr__(self, attr):
return getattr(self.proc, attr)
- def wait(self, stderr=None):
+ def wait(self, stderr=b''):
"""Wait for the process and return its status code.
:param stderr: Previously read value of stderr, in case stderr is already closed.
:warn: may deadlock if output or error pipes are used and not handled separately.
:raise GitCommandError: if the return status is not 0"""
+
+ # stderr must be a bytes object as it will
+ # combined with more data from the process and
+ # decoded by the caller
+ if stderr is None:
+ stderr = b''
+ elif type(stderr) == unicode:
+ stderr = stderr.encode(defenc)
+
status = self.proc.wait()
def read_all_from_possibly_closed_stream(stream):
try:
- return stream.read()
+ return stderr + stream.read()
except ValueError:
- return stderr or ''
+ return stderr or b''
if status != 0:
errstr = read_all_from_possibly_closed_stream(self.proc.stderr)
diff --git a/git/remote.py b/git/remote.py
index 42753977..12a681b0 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -570,11 +570,16 @@ class Remote(LazyMixin, Iterable):
progress_handler = progress.new_message_handler()
+ error_message = None
+ stderr_text = None
+
for line in proc.stderr:
line = force_text(line)
for pline in progress_handler(line):
if line.startswith('fatal:') or line.startswith('error:'):
- raise GitCommandError(("Error when fetching: %s" % line,), 2)
+ error_message = "Error when fetching: %s" % (line,)
+ break
+
# END handle special messages
for cmd in cmds:
if len(line) > 1 and line[0] == ' ' and line[1] == cmd:
@@ -582,9 +587,19 @@ class Remote(LazyMixin, Iterable):
continue
# end find command code
# end for each comand code we know
+
+ if error_message is not None:
+ break
# end for each line progress didn't handle
+
+ if error_message is not None:
+ stderr_text = proc.stderr.read()
+
# end
- finalize_process(proc)
+ finalize_process(proc, stderr=stderr_text)
+
+ if error_message is not None:
+ raise GitCommandError(error_message, 2, stderr=stderr_text)
# read head information
fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb')
@@ -631,6 +646,10 @@ class Remote(LazyMixin, Iterable):
try:
handle_process_output(proc, stdout_handler, progress_handler, finalize_process)
+ except GitCommandError as err:
+ # convert any error from wait() into the same error with stdout lines
+ raise GitCommandError(err.command, err.status, progress.get_stderr())
+
except Exception:
if len(output) == 0:
raise
diff --git a/git/util.py b/git/util.py
index 5ed014fc..706518b8 100644
--- a/git/util.py
+++ b/git/util.py
@@ -173,13 +173,17 @@ class RemoteProgress(object):
DONE_TOKEN = 'done.'
TOKEN_SEPARATOR = ', '
- __slots__ = ("_cur_line", "_seen_ops")
+ __slots__ = ("_cur_line", "_seen_ops", "_error_lines")
re_op_absolute = re.compile(r"(remote: )?([\w\s]+):\s+()(\d+)()(.*)")
re_op_relative = re.compile(r"(remote: )?([\w\s]+):\s+(\d+)% \((\d+)/(\d+)\)(.*)")
def __init__(self):
self._seen_ops = list()
self._cur_line = None
+ self._error_lines = []
+
+ def get_stderr(self):
+ return '\n'.join(self._error_lines)
def _parse_progress_line(self, line):
"""Parse progress information from the given line as retrieved by git-push
@@ -190,6 +194,10 @@ class RemoteProgress(object):
# Counting objects: 4, done.
# Compressing objects: 50% (1/2) \rCompressing objects: 100% (2/2) \rCompressing objects: 100% (2/2), done.
self._cur_line = line
+ if len(self._error_lines) > 0 or self._cur_line.startswith(('error:', 'fatal:')):
+ self._error_lines.append(self._cur_line)
+ return []
+
sub_lines = line.split('\r')
failed_lines = list()
for sline in sub_lines:
@@ -764,10 +772,10 @@ class WaitGroup(object):
self.cv.notify_all()
self.cv.release()
- def wait(self):
+ def wait(self, stderr=b''):
self.cv.acquire()
while self.count > 0:
- self.cv.wait()
+ self.cv.wait(strerr=stderr)
self.cv.release()