mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-05 13:48:41 +00:00
network: implement multi_ack for the git transport
This commit is contained in:
parent
64d01de8a7
commit
114dc6e14c
62
src/fetch.c
62
src/fetch.c
@ -75,13 +75,24 @@ static int filter_wants(git_remote *remote)
|
||||
}
|
||||
|
||||
/* Wait until we get an ack from the */
|
||||
static int recv_pkt(gitno_buffer *buf)
|
||||
static int recv_pkt(git_pkt **out, gitno_buffer *buf)
|
||||
{
|
||||
const char *ptr = buf->data, *line_end;
|
||||
const char *ptr = buf->data, *line_end = ptr;
|
||||
git_pkt *pkt;
|
||||
int pkt_type, error;
|
||||
int pkt_type, error = 0;
|
||||
|
||||
do {
|
||||
if (buf->offset > 0)
|
||||
error = git_pkt_parse_line(&pkt, ptr, &line_end, buf->offset);
|
||||
else
|
||||
error = GIT_EBUFS;
|
||||
|
||||
if (error == 0)
|
||||
break; /* return the pkt */
|
||||
|
||||
if (error < 0 && error != GIT_EBUFS)
|
||||
return -1;
|
||||
|
||||
/* Wait for max. 1 second */
|
||||
if ((error = gitno_select_in(buf, 1, 0)) < 0) {
|
||||
return -1;
|
||||
@ -97,21 +108,41 @@ static int recv_pkt(gitno_buffer *buf)
|
||||
|
||||
if ((error = gitno_recv(buf)) < 0)
|
||||
return -1;
|
||||
|
||||
error = git_pkt_parse_line(&pkt, ptr, &line_end, buf->offset);
|
||||
if (error == GIT_EBUFS)
|
||||
continue;
|
||||
if (error < 0)
|
||||
return -1;
|
||||
} while (error);
|
||||
|
||||
gitno_consume(buf, line_end);
|
||||
pkt_type = pkt->type;
|
||||
if (out != NULL)
|
||||
*out = pkt;
|
||||
else
|
||||
git__free(pkt);
|
||||
|
||||
return pkt_type;
|
||||
}
|
||||
|
||||
static int store_common(git_transport *t)
|
||||
{
|
||||
int done = 0;
|
||||
git_pkt *pkt = NULL;
|
||||
gitno_buffer *buf = &t->buffer;
|
||||
|
||||
do {
|
||||
if (recv_pkt(&pkt, buf) < 0)
|
||||
return -1;
|
||||
|
||||
if (pkt->type == GIT_PKT_ACK) {
|
||||
if (git_vector_insert(&t->common, pkt) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
git__free(pkt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* In this first version, we push all our refs in and start sending
|
||||
* them out. When we get an ACK we hide that commit and continue
|
||||
@ -169,7 +200,11 @@ int git_fetch_negotiate(git_remote *remote)
|
||||
goto on_error;
|
||||
|
||||
git_buf_clear(&data);
|
||||
pkt_type = recv_pkt(buf);
|
||||
if (t->caps.multi_ack) {
|
||||
if (store_common(t) < 0)
|
||||
goto on_error;
|
||||
} else {
|
||||
pkt_type = recv_pkt(NULL, buf);
|
||||
|
||||
if (pkt_type == GIT_PKT_ACK) {
|
||||
break;
|
||||
@ -179,10 +214,13 @@ int git_fetch_negotiate(git_remote *remote)
|
||||
giterr_set(GITERR_NET, "Unexpected pkt type");
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (t->common.length > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error < 0 && error != GIT_REVWALKOVER)
|
||||
goto on_error;
|
||||
|
||||
@ -195,7 +233,7 @@ int git_fetch_negotiate(git_remote *remote)
|
||||
git_revwalk_free(walk);
|
||||
|
||||
/* Now let's eat up whatever the server gives us */
|
||||
pkt_type = recv_pkt(buf);
|
||||
pkt_type = recv_pkt(NULL, buf);
|
||||
if (pkt_type != GIT_PKT_ACK && pkt_type != GIT_PKT_NAK) {
|
||||
giterr_set(GITERR_NET, "Unexpected pkt type");
|
||||
return -1;
|
||||
|
18
src/pkt.c
18
src/pkt.c
@ -283,20 +283,28 @@ int git_pkt_buffer_flush(git_buf *buf)
|
||||
|
||||
static int buffer_want_with_caps(git_remote_head *head, git_transport_caps *caps, git_buf *buf)
|
||||
{
|
||||
char capstr[20];
|
||||
git_buf str = GIT_BUF_INIT;
|
||||
char oid[GIT_OID_HEXSZ +1] = {0};
|
||||
unsigned int len;
|
||||
|
||||
if (caps->ofs_delta)
|
||||
strncpy(capstr, GIT_CAP_OFS_DELTA, sizeof(capstr));
|
||||
git_buf_puts(&str, GIT_CAP_OFS_DELTA " ");
|
||||
|
||||
if (caps->multi_ack)
|
||||
git_buf_puts(&str, GIT_CAP_MULTI_ACK " ");
|
||||
|
||||
if (git_buf_oom(&str))
|
||||
return -1;
|
||||
|
||||
len = (unsigned int)
|
||||
(strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ +
|
||||
strlen(capstr) + 1 /* LF */);
|
||||
git_buf_len(&str) + 1 /* LF */);
|
||||
git_buf_grow(buf, git_buf_len(buf) + len);
|
||||
|
||||
git_oid_fmt(oid, &head->oid);
|
||||
return git_buf_printf(buf, "%04xwant %s %s\n", len, oid, capstr);
|
||||
git_buf_printf(buf, "%04xwant %s %s\n", len, oid, git_buf_cstr(&str));
|
||||
git_buf_free(&str);
|
||||
|
||||
return git_buf_oom(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -20,10 +20,12 @@
|
||||
|
||||
|
||||
#define GIT_CAP_OFS_DELTA "ofs-delta"
|
||||
#define GIT_CAP_MULTI_ACK "multi_ack"
|
||||
|
||||
typedef struct git_transport_caps {
|
||||
int common:1,
|
||||
ofs_delta:1;
|
||||
ofs_delta:1,
|
||||
multi_ack: 1;
|
||||
} git_transport_caps;
|
||||
|
||||
#ifdef GIT_SSL
|
||||
@ -76,6 +78,7 @@ struct git_transport {
|
||||
#ifdef GIT_SSL
|
||||
struct gitno_ssl ssl;
|
||||
#endif
|
||||
git_vector common;
|
||||
gitno_buffer buffer;
|
||||
GIT_SOCKET socket;
|
||||
git_transport_caps caps;
|
||||
|
@ -179,6 +179,12 @@ static int detect_caps(transport_git *t)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!git__prefixcmp(ptr, GIT_CAP_MULTI_ACK)) {
|
||||
caps->common = caps->multi_ack = 1;
|
||||
ptr += strlen(GIT_CAP_MULTI_ACK);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We don't know this capability, so skip it */
|
||||
ptr = strchr(ptr, ' ');
|
||||
}
|
||||
@ -303,6 +309,10 @@ int git_transport_git(git_transport **out)
|
||||
GITERR_CHECK_ALLOC(t);
|
||||
|
||||
memset(t, 0x0, sizeof(transport_git));
|
||||
if (git_vector_init(&t->parent.common, 8, NULL)) {
|
||||
git__free(t);
|
||||
return -1;
|
||||
}
|
||||
|
||||
t->parent.connect = git_connect;
|
||||
t->parent.negotiation_step = git_negotiation_step;
|
||||
|
Loading…
Reference in New Issue
Block a user