Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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.
  • Loading branch information...
commit 39e6af6a7c526823b06f2c7bfe97c0c7bf9501d5 1 parent 8b9ec20
@carlosmn authored
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;
}
Please sign in to comment.
Something went wrong with that request. Please try again.