mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-05 20:33:41 +00:00
network: implement multi_ack for the git transport
This commit is contained in:
parent
64d01de8a7
commit
114dc6e14c
78
src/fetch.c
78
src/fetch.c
@ -75,13 +75,24 @@ static int filter_wants(git_remote *remote)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until we get an ack from the */
|
/* 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;
|
git_pkt *pkt;
|
||||||
int pkt_type, error;
|
int pkt_type, error = 0;
|
||||||
|
|
||||||
do {
|
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 */
|
/* Wait for max. 1 second */
|
||||||
if ((error = gitno_select_in(buf, 1, 0)) < 0) {
|
if ((error = gitno_select_in(buf, 1, 0)) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -97,21 +108,41 @@ static int recv_pkt(gitno_buffer *buf)
|
|||||||
|
|
||||||
if ((error = gitno_recv(buf)) < 0)
|
if ((error = gitno_recv(buf)) < 0)
|
||||||
return -1;
|
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);
|
} while (error);
|
||||||
|
|
||||||
gitno_consume(buf, line_end);
|
gitno_consume(buf, line_end);
|
||||||
pkt_type = pkt->type;
|
pkt_type = pkt->type;
|
||||||
git__free(pkt);
|
if (out != NULL)
|
||||||
|
*out = pkt;
|
||||||
|
else
|
||||||
|
git__free(pkt);
|
||||||
|
|
||||||
return pkt_type;
|
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
|
* 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
|
* them out. When we get an ACK we hide that commit and continue
|
||||||
@ -169,18 +200,25 @@ int git_fetch_negotiate(git_remote *remote)
|
|||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
git_buf_clear(&data);
|
git_buf_clear(&data);
|
||||||
pkt_type = recv_pkt(buf);
|
if (t->caps.multi_ack) {
|
||||||
|
if (store_common(t) < 0)
|
||||||
if (pkt_type == GIT_PKT_ACK) {
|
goto on_error;
|
||||||
break;
|
|
||||||
} else if (pkt_type == GIT_PKT_NAK) {
|
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
giterr_set(GITERR_NET, "Unexpected pkt type");
|
pkt_type = recv_pkt(NULL, buf);
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (pkt_type == GIT_PKT_ACK) {
|
||||||
|
break;
|
||||||
|
} else if (pkt_type == GIT_PKT_NAK) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
giterr_set(GITERR_NET, "Unexpected pkt type");
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (t->common.length > 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error < 0 && error != GIT_REVWALKOVER)
|
if (error < 0 && error != GIT_REVWALKOVER)
|
||||||
@ -195,7 +233,7 @@ int git_fetch_negotiate(git_remote *remote)
|
|||||||
git_revwalk_free(walk);
|
git_revwalk_free(walk);
|
||||||
|
|
||||||
/* Now let's eat up whatever the server gives us */
|
/* 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) {
|
if (pkt_type != GIT_PKT_ACK && pkt_type != GIT_PKT_NAK) {
|
||||||
giterr_set(GITERR_NET, "Unexpected pkt type");
|
giterr_set(GITERR_NET, "Unexpected pkt type");
|
||||||
return -1;
|
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)
|
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};
|
char oid[GIT_OID_HEXSZ +1] = {0};
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|
||||||
if (caps->ofs_delta)
|
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)
|
len = (unsigned int)
|
||||||
(strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ +
|
(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_buf_grow(buf, git_buf_len(buf) + len);
|
||||||
|
|
||||||
git_oid_fmt(oid, &head->oid);
|
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_OFS_DELTA "ofs-delta"
|
||||||
|
#define GIT_CAP_MULTI_ACK "multi_ack"
|
||||||
|
|
||||||
typedef struct git_transport_caps {
|
typedef struct git_transport_caps {
|
||||||
int common:1,
|
int common:1,
|
||||||
ofs_delta:1;
|
ofs_delta:1,
|
||||||
|
multi_ack: 1;
|
||||||
} git_transport_caps;
|
} git_transport_caps;
|
||||||
|
|
||||||
#ifdef GIT_SSL
|
#ifdef GIT_SSL
|
||||||
@ -76,6 +78,7 @@ struct git_transport {
|
|||||||
#ifdef GIT_SSL
|
#ifdef GIT_SSL
|
||||||
struct gitno_ssl ssl;
|
struct gitno_ssl ssl;
|
||||||
#endif
|
#endif
|
||||||
|
git_vector common;
|
||||||
gitno_buffer buffer;
|
gitno_buffer buffer;
|
||||||
GIT_SOCKET socket;
|
GIT_SOCKET socket;
|
||||||
git_transport_caps caps;
|
git_transport_caps caps;
|
||||||
|
@ -179,6 +179,12 @@ static int detect_caps(transport_git *t)
|
|||||||
continue;
|
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 */
|
/* We don't know this capability, so skip it */
|
||||||
ptr = strchr(ptr, ' ');
|
ptr = strchr(ptr, ' ');
|
||||||
}
|
}
|
||||||
@ -303,6 +309,10 @@ int git_transport_git(git_transport **out)
|
|||||||
GITERR_CHECK_ALLOC(t);
|
GITERR_CHECK_ALLOC(t);
|
||||||
|
|
||||||
memset(t, 0x0, sizeof(transport_git));
|
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.connect = git_connect;
|
||||||
t->parent.negotiation_step = git_negotiation_step;
|
t->parent.negotiation_step = git_negotiation_step;
|
||||||
|
Loading…
Reference in New Issue
Block a user