Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Recognize and report server-side error messages #654

Merged
merged 1 commit into from

3 participants

@carlosmn
Owner

When e.g. a repository isn't found, the server sends an error saying
so. Put that error message in our error buffer.

This actually produces a better error message than git, as we pretend that the dumb HTTP transport never existed and actually say what the other end gave us. If you typo really bad and hit a real HTTP server, we'll probably get HTML in return, but I'm going to say that's outside of the library's scope.

@carlosmn carlosmn net: recognize and report server-side error messages
When e.g. a repository isn't found, the server sends an error saying
so. Put that error message in our error buffer.
39e6af6
@travisbot

This pull request passes (merged 39e6af6 into 8b9ec20).

@vmg vmg merged commit ced9da5 into libgit2:new-error-handling
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 30, 2012
  1. @carlosmn

    net: recognize and report server-side error messages

    carlosmn authored
    When e.g. a repository isn't found, the server sends an error saying
    so. Put that error message in our error buffer.
This page is out of date. Refresh to see the latest.
Showing with 50 additions and 0 deletions.
  1. +21 −0 src/pkt.c
  2. +6 −0 src/pkt.h
  3. +7 −0 src/protocol.c
  4. +16 −0 src/transports/http.c
View
21 src/pkt.c
@@ -97,6 +97,25 @@ static int comment_pkt(git_pkt **out, const char *line, size_t len)
return 0;
}
+static int err_pkt(git_pkt **out, const char *line, size_t len)
+{
+ git_pkt_err *pkt;
+
+ /* Remove "ERR " from the line */
+ line += 4;
+ len -= 4;
+ pkt = git__malloc(sizeof(git_pkt_err) + len + 1);
+ GITERR_CHECK_ALLOC(pkt);
+
+ pkt->type = GIT_PKT_ERR;
+ memcpy(pkt->error, line, len);
+ pkt->error[len] = '\0';
+
+ *out = (git_pkt *) pkt;
+
+ return 0;
+}
+
/*
* Parse an other-ref line.
*/
@@ -234,6 +253,8 @@ int git_pkt_parse_line(
ret = ack_pkt(head, line, len);
else if (!git__prefixcmp(line, "NAK"))
ret = nak_pkt(head);
+ else if (!git__prefixcmp(line, "ERR "))
+ ret = err_pkt(head, line, len);
else if (*line == '#')
ret = comment_pkt(head, line, len);
else
View
6 src/pkt.h
@@ -23,6 +23,7 @@ enum git_pkt_type {
GIT_PKT_NAK,
GIT_PKT_PACK,
GIT_PKT_COMMENT,
+ GIT_PKT_ERR,
};
/* Used for multi-ack */
@@ -64,6 +65,11 @@ typedef struct {
char comment[GIT_FLEX_ARRAY];
} git_pkt_comment;
+typedef struct {
+ enum git_pkt_type type;
+ char error[GIT_FLEX_ARRAY];
+} git_pkt_err;
+
int git_pkt_parse_line(git_pkt **head, const char *line, const char **out, size_t len);
int git_pkt_buffer_flush(git_buf *buf);
int git_pkt_send_flush(GIT_SOCKET s);
View
7 src/protocol.c
@@ -40,6 +40,13 @@ int git_protocol_store_refs(git_protocol *p, const char *data, size_t len)
return p->error = -1;
git_buf_consume(buf, line_end);
+
+ if (pkt->type == GIT_PKT_ERR) {
+ giterr_set(GITERR_NET, "Remote error: %s", ((git_pkt_err *)pkt)->error);
+ git__free(pkt);
+ return -1;
+ }
+
if (git_vector_insert(refs, pkt) < 0)
return p->error = -1;
View
16 src/transports/http.c
@@ -165,6 +165,12 @@ static int on_headers_complete(http_parser *parser)
transport_http *t = (transport_http *) parser->data;
git_buf *buf = &t->buf;
+ /* The content-type is text/plain for 404, so don't validate */
+ if (parser->status_code == 404) {
+ git_buf_clear(buf);
+ return 0;
+ }
+
if (t->content_type == NULL) {
t->content_type = git__strdup(git_buf_cstr(buf));
if (t->content_type == NULL)
@@ -187,6 +193,10 @@ static int on_body_store_refs(http_parser *parser, const char *str, size_t len)
{
transport_http *t = (transport_http *) parser->data;
+ if (parser->status_code == 404) {
+ return git_buf_put(&t->buf, str, len);
+ }
+
return git_protocol_store_refs(&t->proto, str, len);
}
@@ -195,6 +205,12 @@ static int on_message_complete(http_parser *parser)
transport_http *t = (transport_http *) parser->data;
t->transfer_finished = 1;
+
+ if (parser->status_code == 404) {
+ giterr_set(GITERR_NET, "Remote error: %s", git_buf_cstr(&t->buf));
+ t->error = -1;
+ }
+
return 0;
}
Something went wrong with that request. Please try again.