Skip to content

Commit 1bd8c8f

Browse files
dschoJunio C Hamano
authored and
Junio C Hamano
committed
git-upload-pack: Support the multi_ack protocol
This implements three things (trying very hard to be backwards compatible): It sends the "multi_ack" capability via the mechanism proposed by Sergey Vlasov. When the client sends "multi_ack" with at least one "want", multi_ack is enabled. When multi_ack is enabled, "continue" is appended to each "ACK" until either the server can not store more refs, or "done" is received. In contrast to the original protocol, as long as "continue" is sent, flushes are answered by a "NAK" (not just until an "ACK" was sent), and if "continue" was sent at least once, the last message is an "ACK" without "continue". Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 211b5f9 commit 1bd8c8f

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

upload-pack.c

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=n
1212
#define WANTED (1U << 2)
1313
#define MAX_HAS 256
1414
#define MAX_NEEDS 256
15-
static int nr_has = 0, nr_needs = 0, nr_our_refs = 0;
15+
static int nr_has = 0, nr_needs = 0, multi_ack = 0, nr_our_refs = 0;
1616
static unsigned char has_sha1[MAX_HAS][20];
1717
static unsigned char needs_sha1[MAX_NEEDS][20];
1818
static unsigned int timeout = 0;
@@ -119,7 +119,7 @@ static int got_sha1(char *hex, unsigned char *sha1)
119119
static int get_common_commits(void)
120120
{
121121
static char line[1000];
122-
unsigned char sha1[20];
122+
unsigned char sha1[20], last_sha1[20];
123123
int len;
124124

125125
track_object_refs = 0;
@@ -130,39 +130,36 @@ static int get_common_commits(void)
130130
reset_timeout();
131131

132132
if (!len) {
133-
packet_write(1, "NAK\n");
133+
if (nr_has == 0 || multi_ack)
134+
packet_write(1, "NAK\n");
134135
continue;
135136
}
136137
len = strip(line, len);
137138
if (!strncmp(line, "have ", 5)) {
138-
if (got_sha1(line+5, sha1)) {
139-
packet_write(1, "ACK %s\n", sha1_to_hex(sha1));
140-
break;
139+
if (got_sha1(line+5, sha1) &&
140+
(multi_ack || nr_has == 1)) {
141+
if (nr_has >= MAX_HAS)
142+
multi_ack = 0;
143+
packet_write(1, "ACK %s%s\n",
144+
sha1_to_hex(sha1),
145+
multi_ack ? " continue" : "");
146+
if (multi_ack)
147+
memcpy(last_sha1, sha1, 20);
141148
}
142149
continue;
143150
}
144151
if (!strcmp(line, "done")) {
152+
if (nr_has > 0) {
153+
if (multi_ack)
154+
packet_write(1, "ACK %s\n",
155+
sha1_to_hex(last_sha1));
156+
return 0;
157+
}
145158
packet_write(1, "NAK\n");
146159
return -1;
147160
}
148161
die("git-upload-pack: expected SHA1 list, got '%s'", line);
149162
}
150-
151-
for (;;) {
152-
len = packet_read_line(0, line, sizeof(line));
153-
reset_timeout();
154-
if (!len)
155-
continue;
156-
len = strip(line, len);
157-
if (!strncmp(line, "have ", 5)) {
158-
got_sha1(line+5, sha1);
159-
continue;
160-
}
161-
if (!strcmp(line, "done"))
162-
break;
163-
die("git-upload-pack: expected SHA1 list, got '%s'", line);
164-
}
165-
return 0;
166163
}
167164

168165
static int receive_needs(void)
@@ -192,6 +189,8 @@ static int receive_needs(void)
192189
if (strncmp("want ", line, 5) || get_sha1_hex(line+5, sha1_buf))
193190
die("git-upload-pack: protocol error, "
194191
"expected to get sha, not '%s'", line);
192+
if (strstr(line+45, "multi_ack"))
193+
multi_ack = 1;
195194

196195
/* We have sent all our refs already, and the other end
197196
* should have chosen out of them; otherwise they are
@@ -213,9 +212,11 @@ static int receive_needs(void)
213212

214213
static int send_ref(const char *refname, const unsigned char *sha1)
215214
{
215+
static char *capabilities = "\0multi_ack";
216216
struct object *o = parse_object(sha1);
217217

218-
packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname);
218+
packet_write(1, "%s %s%s\n", sha1_to_hex(sha1), refname, capabilities);
219+
capabilities = "";
219220
if (!(o->flags & OUR_REF)) {
220221
o->flags |= OUR_REF;
221222
nr_our_refs++;

0 commit comments

Comments
 (0)