Commit c6d7d877 by Vicent Martí

Merge pull request #1410 from phkelley/push_sideband

Advertise and support side-band-64k when calling receive-pack
parents 1ac10aae f5898324
...@@ -88,6 +88,7 @@ typedef git_pkt_data git_pkt_progress; ...@@ -88,6 +88,7 @@ typedef git_pkt_data git_pkt_progress;
typedef struct { typedef struct {
enum git_pkt_type type; enum git_pkt_type type;
int len;
char error[GIT_FLEX_ARRAY]; char error[GIT_FLEX_ARRAY];
} git_pkt_err; } git_pkt_err;
......
...@@ -122,6 +122,7 @@ static int err_pkt(git_pkt **out, const char *line, size_t len) ...@@ -122,6 +122,7 @@ static int err_pkt(git_pkt **out, const char *line, size_t len)
GITERR_CHECK_ALLOC(pkt); GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_ERR; pkt->type = GIT_PKT_ERR;
pkt->len = (int)len;
memcpy(pkt->error, line, len); memcpy(pkt->error, line, len);
pkt->error[len] = '\0'; pkt->error[len] = '\0';
...@@ -166,6 +167,25 @@ static int progress_pkt(git_pkt **out, const char *line, size_t len) ...@@ -166,6 +167,25 @@ static int progress_pkt(git_pkt **out, const char *line, size_t len)
return 0; return 0;
} }
static int sideband_error_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_err *pkt;
line++;
len--;
pkt = git__malloc(sizeof(git_pkt_err) + len + 1);
GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_ERR;
pkt->len = (int)len;
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.
*/ */
...@@ -380,6 +400,8 @@ int git_pkt_parse_line( ...@@ -380,6 +400,8 @@ int git_pkt_parse_line(
ret = data_pkt(head, line, len); ret = data_pkt(head, line, len);
else if (*line == GIT_SIDE_BAND_PROGRESS) else if (*line == GIT_SIDE_BAND_PROGRESS)
ret = progress_pkt(head, line, len); ret = progress_pkt(head, line, len);
else if (*line == GIT_SIDE_BAND_ERROR)
ret = sideband_error_pkt(head, line, len);
else if (!git__prefixcmp(line, "ACK")) else if (!git__prefixcmp(line, "ACK"))
ret = ack_pkt(head, line, len); ret = ack_pkt(head, line, len);
else if (!git__prefixcmp(line, "NAK")) else if (!git__prefixcmp(line, "NAK"))
......
...@@ -536,7 +536,8 @@ static int gen_pktline(git_buf *buf, git_push *push) ...@@ -536,7 +536,8 @@ static int gen_pktline(git_buf *buf, git_push *push)
if (i == 0) { if (i == 0) {
++len; /* '\0' */ ++len; /* '\0' */
if (push->report_status) if (push->report_status)
len += strlen(GIT_CAP_REPORT_STATUS); len += strlen(GIT_CAP_REPORT_STATUS) + 1;
len += strlen(GIT_CAP_SIDE_BAND_64K) + 1;
} }
git_oid_fmt(old_id, &spec->roid); git_oid_fmt(old_id, &spec->roid);
...@@ -546,9 +547,14 @@ static int gen_pktline(git_buf *buf, git_push *push) ...@@ -546,9 +547,14 @@ static int gen_pktline(git_buf *buf, git_push *push)
if (i == 0) { if (i == 0) {
git_buf_putc(buf, '\0'); git_buf_putc(buf, '\0');
if (push->report_status) /* Core git always starts their capabilities string with a space */
if (push->report_status) {
git_buf_putc(buf, ' ');
git_buf_printf(buf, GIT_CAP_REPORT_STATUS); git_buf_printf(buf, GIT_CAP_REPORT_STATUS);
} }
git_buf_putc(buf, ' ');
git_buf_printf(buf, GIT_CAP_SIDE_BAND_64K);
}
git_buf_putc(buf, '\n'); git_buf_putc(buf, '\n');
} }
...@@ -557,6 +563,74 @@ static int gen_pktline(git_buf *buf, git_push *push) ...@@ -557,6 +563,74 @@ static int gen_pktline(git_buf *buf, git_push *push)
return git_buf_oom(buf) ? -1 : 0; return git_buf_oom(buf) ? -1 : 0;
} }
static int add_push_report_pkt(git_push *push, git_pkt *pkt)
{
push_status *status;
switch (pkt->type) {
case GIT_PKT_OK:
status = git__malloc(sizeof(push_status));
GITERR_CHECK_ALLOC(status);
status->msg = NULL;
status->ref = git__strdup(((git_pkt_ok *)pkt)->ref);
if (!status->ref ||
git_vector_insert(&push->status, status) < 0) {
git_push_status_free(status);
return -1;
}
break;
case GIT_PKT_NG:
status = git__calloc(sizeof(push_status), 1);
GITERR_CHECK_ALLOC(status);
status->ref = git__strdup(((git_pkt_ng *)pkt)->ref);
status->msg = git__strdup(((git_pkt_ng *)pkt)->msg);
if (!status->ref || !status->msg ||
git_vector_insert(&push->status, status) < 0) {
git_push_status_free(status);
return -1;
}
break;
case GIT_PKT_UNPACK:
push->unpack_ok = ((git_pkt_unpack *)pkt)->unpack_ok;
break;
case GIT_PKT_FLUSH:
return GIT_ITEROVER;
default:
giterr_set(GITERR_NET, "report-status: protocol error");
return -1;
}
return 0;
}
static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
{
git_pkt *pkt;
const char *line = data_pkt->data, *line_end;
size_t line_len = data_pkt->len;
int error;
while (line_len > 0) {
error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
if (error < 0)
return error;
/* Advance in the buffer */
line_len -= (line_end - line);
line = line_end;
error = add_push_report_pkt(push, pkt);
git_pkt_free(pkt);
if (error < 0 && error != GIT_ITEROVER)
return error;
}
return 0;
}
static int parse_report(gitno_buffer *buf, git_push *push) static int parse_report(gitno_buffer *buf, git_push *push)
{ {
git_pkt *pkt; git_pkt *pkt;
...@@ -586,46 +660,33 @@ static int parse_report(gitno_buffer *buf, git_push *push) ...@@ -586,46 +660,33 @@ static int parse_report(gitno_buffer *buf, git_push *push)
gitno_consume(buf, line_end); gitno_consume(buf, line_end);
if (pkt->type == GIT_PKT_OK) { error = 0;
push_status *status = git__malloc(sizeof(push_status));
GITERR_CHECK_ALLOC(status);
status->ref = git__strdup(((git_pkt_ok *)pkt)->ref);
status->msg = NULL;
git_pkt_free(pkt);
if (git_vector_insert(&push->status, status) < 0) {
git__free(status);
return -1;
}
continue;
}
if (pkt->type == GIT_PKT_NG) { switch (pkt->type) {
push_status *status = git__malloc(sizeof(push_status)); case GIT_PKT_DATA:
GITERR_CHECK_ALLOC(status); /* This is a sideband packet which contains other packets */
status->ref = git__strdup(((git_pkt_ng *)pkt)->ref); error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt);
status->msg = git__strdup(((git_pkt_ng *)pkt)->msg); break;
git_pkt_free(pkt); case GIT_PKT_ERR:
if (git_vector_insert(&push->status, status) < 0) { giterr_set(GITERR_NET, "report-status: Error reported: %s",
git__free(status); ((git_pkt_err *)pkt)->error);
return -1; error = -1;
} break;
continue; case GIT_PKT_PROGRESS:
break;
default:
error = add_push_report_pkt(push, pkt);
break;
} }
if (pkt->type == GIT_PKT_UNPACK) {
push->unpack_ok = ((git_pkt_unpack *)pkt)->unpack_ok;
git_pkt_free(pkt); git_pkt_free(pkt);
continue;
}
if (pkt->type == GIT_PKT_FLUSH) { /* add_push_report_pkt returns GIT_ITEROVER when it receives a flush */
git_pkt_free(pkt); if (error == GIT_ITEROVER)
return 0; return 0;
}
git_pkt_free(pkt); if (error < 0)
giterr_set(GITERR_NET, "report-status: protocol error"); return error;
return -1;
} }
} }
......
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