Commit c06e180a98db734036614b32d55d63df7356aba5

Carlos Martín Nieto 2015-05-20T17:13:49

Merge pull request #3137 from libgit2/cmn/server-errors Improve server error reporting

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 810538c..8a0ae0e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,10 @@ support for HTTPS connections insead of OpenSSL.
 * The index now uses diffs for `add_all()` and `update_all()` which
   gives it a speed boost and closer semantics to git.
 
+* The ssh transport now reports the stderr output from the server as
+  the error message, which allows you to get the "repository not
+  found" messages.
+
 
 ### API additions
 
@@ -89,6 +93,11 @@ support for HTTPS connections insead of OpenSSL.
 * `git_stash_pop()` will apply a stashed state (like `git_stash_apply()`)
   but will remove the stashed state after a successful application.
 
+* A new error code `GIT_EEOF` indicates an early EOF from the
+  server. This typically indicates an error with the URL or
+  configuration of the server, and tools can use this to show messages
+  about failing to communicate with the server.
+
 ### API removals
 
 * `git_remote_save()` and `git_remote_clear_refspecs()` has been
diff --git a/include/git2/errors.h b/include/git2/errors.h
index ef4fabb..31fc603 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -45,6 +45,7 @@ typedef enum {
 	GIT_ECERTIFICATE    = -17,      /**< Server certificate is invalid */
 	GIT_EAPPLIED        = -18,	/**< Patch/merge has already been applied */
 	GIT_EPEEL           = -19,      /**< The requested peel operation is not possible */
+	GIT_EEOF            = -20,      /**< Unexpected EOF */
 
 	GIT_PASSTHROUGH     = -30,	/**< Internal only */
 	GIT_ITEROVER        = -31,	/**< Signals end of iteration with iterator */
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index 2ebfac7..78f705e 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -55,6 +55,7 @@ static int ssl_set_error(SSL *ssl, int error)
 			break;
 		}
 		giterr_set(GITERR_NET, "SSL error: received early EOF");
+		return GIT_EEOF;
 		break;
 	case SSL_ERROR_SSL:
 		e = ERR_get_error();
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 66f78f7..0920f2e 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -52,7 +52,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
 
 			if (recvd == 0 && !flush) {
 				giterr_set(GITERR_NET, "early EOF");
-				return -1;
+				return GIT_EEOF;
 			}
 
 			continue;
@@ -770,7 +770,7 @@ static int parse_report(transport_smart *transport, git_push *push)
 
 			if (recvd == 0) {
 				giterr_set(GITERR_NET, "early EOF");
-				return -1;
+				return GIT_EEOF;
 			}
 			continue;
 		}
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index c5b0811..55f715b 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -125,10 +125,21 @@ static int ssh_stream_read(
 		return -1;
 
 	if ((rc = libssh2_channel_read(s->channel, buffer, buf_size)) < LIBSSH2_ERROR_NONE) {
-		ssh_error(s->session, "SSH could not read data");;
+		ssh_error(s->session, "SSH could not read data");
 		return -1;
 	}
 
+	/*
+	 * If we can't get anything out of stdout, it's typically a
+	 * not-found error, so read from stderr and signal EOF on
+	 * stderr.
+	 */
+	if (rc == 0 && (rc = libssh2_channel_read_stderr(s->channel, buffer, buf_size)) > 0) {
+		giterr_set(GITERR_SSH, "%*s", rc, buffer);
+		return GIT_EEOF;
+	}
+
+
 	*bytes_read = rc;
 
 	return 0;