Commit 39e6af6a by Carlos Martín Nieto

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.
parent 8b9ec201
...@@ -97,6 +97,25 @@ static int comment_pkt(git_pkt **out, const char *line, size_t len) ...@@ -97,6 +97,25 @@ static int comment_pkt(git_pkt **out, const char *line, size_t len)
return 0; 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. * Parse an other-ref line.
*/ */
...@@ -234,6 +253,8 @@ int git_pkt_parse_line( ...@@ -234,6 +253,8 @@ int git_pkt_parse_line(
ret = ack_pkt(head, line, len); ret = ack_pkt(head, line, len);
else if (!git__prefixcmp(line, "NAK")) else if (!git__prefixcmp(line, "NAK"))
ret = nak_pkt(head); ret = nak_pkt(head);
else if (!git__prefixcmp(line, "ERR "))
ret = err_pkt(head, line, len);
else if (*line == '#') else if (*line == '#')
ret = comment_pkt(head, line, len); ret = comment_pkt(head, line, len);
else else
......
...@@ -23,6 +23,7 @@ enum git_pkt_type { ...@@ -23,6 +23,7 @@ enum git_pkt_type {
GIT_PKT_NAK, GIT_PKT_NAK,
GIT_PKT_PACK, GIT_PKT_PACK,
GIT_PKT_COMMENT, GIT_PKT_COMMENT,
GIT_PKT_ERR,
}; };
/* Used for multi-ack */ /* Used for multi-ack */
...@@ -64,6 +65,11 @@ typedef struct { ...@@ -64,6 +65,11 @@ typedef struct {
char comment[GIT_FLEX_ARRAY]; char comment[GIT_FLEX_ARRAY];
} git_pkt_comment; } 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_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_buffer_flush(git_buf *buf);
int git_pkt_send_flush(GIT_SOCKET s); int git_pkt_send_flush(GIT_SOCKET s);
......
...@@ -40,6 +40,13 @@ int git_protocol_store_refs(git_protocol *p, const char *data, size_t len) ...@@ -40,6 +40,13 @@ int git_protocol_store_refs(git_protocol *p, const char *data, size_t len)
return p->error = -1; return p->error = -1;
git_buf_consume(buf, line_end); 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) if (git_vector_insert(refs, pkt) < 0)
return p->error = -1; return p->error = -1;
......
...@@ -165,6 +165,12 @@ static int on_headers_complete(http_parser *parser) ...@@ -165,6 +165,12 @@ static int on_headers_complete(http_parser *parser)
transport_http *t = (transport_http *) parser->data; transport_http *t = (transport_http *) parser->data;
git_buf *buf = &t->buf; 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) { if (t->content_type == NULL) {
t->content_type = git__strdup(git_buf_cstr(buf)); t->content_type = git__strdup(git_buf_cstr(buf));
if (t->content_type == NULL) if (t->content_type == NULL)
...@@ -187,6 +193,10 @@ static int on_body_store_refs(http_parser *parser, const char *str, size_t len) ...@@ -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; 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); return git_protocol_store_refs(&t->proto, str, len);
} }
...@@ -195,6 +205,12 @@ static int on_message_complete(http_parser *parser) ...@@ -195,6 +205,12 @@ static int on_message_complete(http_parser *parser)
transport_http *t = (transport_http *) parser->data; transport_http *t = (transport_http *) parser->data;
t->transfer_finished = 1; 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; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment