From e9f8f159ebad405b2c08aa75f735146bb8e216ef Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 8 Apr 2015 11:00:32 +0200 Subject: [PATCH] fix(remote): allow to raise during push/fetch Do not swallow non-zero exit status during push and fetch unless we managed to parse head information. This behaviour will effetively handle cases were no work was done due to invalid refspecs or insufficient permissions. Fixes #271 --- doc/source/changes.rst | 4 ++++ git/remote.py | 13 +++++++++++-- git/test/test_remote.py | 3 +-- git/util.py | 32 ++------------------------------ 4 files changed, 18 insertions(+), 34 deletions(-) diff --git a/doc/source/changes.rst b/doc/source/changes.rst index 52d70c0f1..35c2f15c3 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -7,6 +7,10 @@ Changelog * `IndexFile.add()` will now write the index without any extension data by default. However, you may override this behaviour with the new `write_extension_data` keyword argument. - Renamed `ignore_tree_extension_data` keyword argument in `IndexFile.write(...)` to `ignore_extension_data` +* If the git command executed during `Remote.push(...)|fetch(...)` returns with an non-zero exit code and GitPython didn't + obtain any head-information, the corresponding `GitCommandError` will be raised. This may break previous code which expected + these operations to never raise. However, that behavious is undesirable as it would effectively hide the fact that there + was an error. See `this issue `_ for more information. 0.3.6 - Features ================ diff --git a/git/remote.py b/git/remote.py index 6a15c9c4f..4baa2838c 100644 --- a/git/remote.py +++ b/git/remote.py @@ -568,7 +568,12 @@ def _get_fetch_info_from_stderr(self, proc, progress): # end # We are only interested in stderr here ... - finalize_process(proc) + try: + finalize_process(proc) + except Exception: + if len(fetch_info_lines) == 0: + raise + # end exception handler # read head information fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb') @@ -601,7 +606,11 @@ def stdout_handler(line): # END exception handling # END for each line - handle_process_output(proc, stdout_handler, progress_handler, finalize_process) + try: + handle_process_output(proc, stdout_handler, progress_handler, finalize_process) + except Exception: + if len(output) == 0: + raise return output def fetch(self, refspec=None, progress=None, **kwargs): diff --git a/git/test/test_remote.py b/git/test/test_remote.py index 8500a295a..c419ecee9 100644 --- a/git/test/test_remote.py +++ b/git/test/test_remote.py @@ -313,8 +313,7 @@ def _assert_push_and_pull(self, remote, rw_repo, remote_repo): self._do_test_push_result(res, remote) # invalid refspec - res = remote.push("hellothere") - assert len(res) == 0 + self.failUnlessRaises(GitCommandError, remote.push, "hellothere") # push new tags progress = TestRemoteProgress() diff --git a/git/util.py b/git/util.py index f41f20fb4..1147cb535 100644 --- a/git/util.py +++ b/git/util.py @@ -16,10 +16,7 @@ # NOTE: Some of the unused imports might be used/imported by others. # Handle once test-cases are back up and running. -from .exc import ( - GitCommandError, - InvalidGitRepositoryError -) +from .exc import InvalidGitRepositoryError from .compat import ( MAXSIZE, @@ -154,32 +151,7 @@ def get_user_id(): def finalize_process(proc): """Wait for the process (clone, fetch, pull or push) and handle its errors accordingly""" - try: - proc.wait() - except GitCommandError: - # if a push has rejected items, the command has non-zero return status - # a return status of 128 indicates a connection error - reraise the previous one - # Everything else will still be parsed and made available through PushInfo flags - # Estimated error results look like this: - # ```bash - # To /var/folders/xp/m48gs2tx2vg95tmtzw7tprs40000gn/T/tmpk5jeBeremote_repo_test_base - # ! refs/heads/master:refs/heads/master [rejected] (non-fast-forward) - # Done - # error: failed to push some refs to - # '/var/folders/xp/m48gs2tx2vg95tmtzw7tprs40000gn/T/tmpk5jeBeremote_repo_test_base' - # hint: Updates were rejected because the tip of your current branch is behind - # hint: its remote counterpart. Integrate the remote changes (e.g. - # hint: 'git pull ...') before pushing again. - # hint: See the 'Note about fast-forwards' in 'git push --help' for details. - # ``` - # See https://github.com/gitpython-developers/GitPython/blob/master/git/test/test_remote.py#L305 - # on how to check for these kinds of errors. - # Also see this issue for a reason for this verbosity: - # https://github.com/gitpython-developers/GitPython/issues/271 - if proc.poll() == 128: - raise - pass - # END exception handling + proc.wait() #} END utilities