From e3435673b8ed862266b5351b9e18cb55ed55d335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 18 May 2015 15:51:55 +0200 Subject: [PATCH 1/2] ssh: read from stderr if stdout is empty When we fail to read from stdout, it's typically because the URL was wrong and the server process has sent some output over its stderr output. Read that output and set the error message to whatever we read from it. --- CHANGELOG.md | 4 ++++ src/transports/ssh.c | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 810538c64..ad127aa55 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 diff --git a/src/transports/ssh.c b/src/transports/ssh.c index c5b081151..0d179e715 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -125,10 +125,17 @@ 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; } + /* Having something in stderr is typically a not-found error */ + if (rc == 0 && (rc = libssh2_channel_read_stderr(s->channel, buffer, buf_size)) > 0) { + giterr_set(GITERR_SSH, "%*s", rc, buffer); + return -1; + } + + *bytes_read = rc; return 0; From 1396c381782f446ae5ea177b0f5c407f90197c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 18 May 2015 16:04:55 +0200 Subject: [PATCH 2/2] errors: add GIT_EEOF to indicate early EOF This can be used by tools to show mesages about failing to communicate with the server. The error message in this case will often contain the server's error message, as far as it managed to send anything. --- CHANGELOG.md | 5 +++++ include/git2/errors.h | 1 + src/openssl_stream.c | 1 + src/transports/smart_protocol.c | 4 ++-- src/transports/ssh.c | 8 ++++++-- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad127aa55..8a0ae0e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,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 ef4fabb7d..31fc6035a 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 2ebfac738..78f705e49 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 66f78f73c..0920f2eef 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 0d179e715..55f715b1d 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -129,10 +129,14 @@ static int ssh_stream_read( return -1; } - /* Having something in stderr is typically a not-found error */ + /* + * 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 -1; + return GIT_EEOF; }