Merge branch 'jt/fetch-v2-sideband'
"git fetch" and "git upload-pack" learned to send all exchange over
the sideband channel while talking the v2 protocol.
* jt/fetch-v2-sideband:
tests: define GIT_TEST_SIDEBAND_ALL
{fetch,upload}-pack: sideband v2 fetch response
sideband: reverse its dependency on pkt-line
pkt-line: introduce struct packet_writer
pack-protocol.txt: accept error packets in any context
Use packet_reader instead of packet_read_line
This commit is contained in:
78
fetch-pack.c
78
fetch-pack.c
@ -135,38 +135,42 @@ enum ack_type {
|
||||
ACK_ready
|
||||
};
|
||||
|
||||
static void consume_shallow_list(struct fetch_pack_args *args, int fd)
|
||||
static void consume_shallow_list(struct fetch_pack_args *args,
|
||||
struct packet_reader *reader)
|
||||
{
|
||||
if (args->stateless_rpc && args->deepen) {
|
||||
/* If we sent a depth we will get back "duplicate"
|
||||
* shallow and unshallow commands every time there
|
||||
* is a block of have lines exchanged.
|
||||
*/
|
||||
char *line;
|
||||
while ((line = packet_read_line(fd, NULL))) {
|
||||
if (starts_with(line, "shallow "))
|
||||
while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
|
||||
if (starts_with(reader->line, "shallow "))
|
||||
continue;
|
||||
if (starts_with(line, "unshallow "))
|
||||
if (starts_with(reader->line, "unshallow "))
|
||||
continue;
|
||||
die(_("git fetch-pack: expected shallow list"));
|
||||
}
|
||||
if (reader->status != PACKET_READ_FLUSH)
|
||||
die(_("git fetch-pack: expected a flush packet after shallow list"));
|
||||
}
|
||||
}
|
||||
|
||||
static enum ack_type get_ack(int fd, struct object_id *result_oid)
|
||||
static enum ack_type get_ack(struct packet_reader *reader,
|
||||
struct object_id *result_oid)
|
||||
{
|
||||
int len;
|
||||
char *line = packet_read_line(fd, &len);
|
||||
const char *arg;
|
||||
|
||||
if (!line)
|
||||
if (packet_reader_read(reader) != PACKET_READ_NORMAL)
|
||||
die(_("git fetch-pack: expected ACK/NAK, got a flush packet"));
|
||||
if (!strcmp(line, "NAK"))
|
||||
len = reader->pktlen;
|
||||
|
||||
if (!strcmp(reader->line, "NAK"))
|
||||
return NAK;
|
||||
if (skip_prefix(line, "ACK ", &arg)) {
|
||||
if (skip_prefix(reader->line, "ACK ", &arg)) {
|
||||
if (!get_oid_hex(arg, result_oid)) {
|
||||
arg += 40;
|
||||
len -= arg - line;
|
||||
len -= arg - reader->line;
|
||||
if (len < 1)
|
||||
return ACK;
|
||||
if (strstr(arg, "continue"))
|
||||
@ -178,9 +182,7 @@ static enum ack_type get_ack(int fd, struct object_id *result_oid)
|
||||
return ACK;
|
||||
}
|
||||
}
|
||||
if (skip_prefix(line, "ERR ", &arg))
|
||||
die(_("remote error: %s"), arg);
|
||||
die(_("git fetch-pack: expected ACK/NAK, got '%s'"), line);
|
||||
die(_("git fetch-pack: expected ACK/NAK, got '%s'"), reader->line);
|
||||
}
|
||||
|
||||
static void send_request(struct fetch_pack_args *args,
|
||||
@ -248,10 +250,15 @@ static int find_common(struct fetch_negotiator *negotiator,
|
||||
int got_ready = 0;
|
||||
struct strbuf req_buf = STRBUF_INIT;
|
||||
size_t state_len = 0;
|
||||
struct packet_reader reader;
|
||||
|
||||
if (args->stateless_rpc && multi_ack == 1)
|
||||
die(_("--stateless-rpc requires multi_ack_detailed"));
|
||||
|
||||
packet_reader_init(&reader, fd[0], NULL, 0,
|
||||
PACKET_READ_CHOMP_NEWLINE |
|
||||
PACKET_READ_DIE_ON_ERR_PACKET);
|
||||
|
||||
if (!args->no_dependents) {
|
||||
mark_tips(negotiator, args->negotiation_tips);
|
||||
for_each_cached_alternate(negotiator, insert_one_alternate_object);
|
||||
@ -341,31 +348,30 @@ static int find_common(struct fetch_negotiator *negotiator,
|
||||
state_len = req_buf.len;
|
||||
|
||||
if (args->deepen) {
|
||||
char *line;
|
||||
const char *arg;
|
||||
struct object_id oid;
|
||||
|
||||
send_request(args, fd[1], &req_buf);
|
||||
while ((line = packet_read_line(fd[0], NULL))) {
|
||||
if (skip_prefix(line, "shallow ", &arg)) {
|
||||
while (packet_reader_read(&reader) == PACKET_READ_NORMAL) {
|
||||
if (skip_prefix(reader.line, "shallow ", &arg)) {
|
||||
if (get_oid_hex(arg, &oid))
|
||||
die(_("invalid shallow line: %s"), line);
|
||||
die(_("invalid shallow line: %s"), reader.line);
|
||||
register_shallow(the_repository, &oid);
|
||||
continue;
|
||||
}
|
||||
if (skip_prefix(line, "unshallow ", &arg)) {
|
||||
if (skip_prefix(reader.line, "unshallow ", &arg)) {
|
||||
if (get_oid_hex(arg, &oid))
|
||||
die(_("invalid unshallow line: %s"), line);
|
||||
die(_("invalid unshallow line: %s"), reader.line);
|
||||
if (!lookup_object(the_repository, oid.hash))
|
||||
die(_("object not found: %s"), line);
|
||||
die(_("object not found: %s"), reader.line);
|
||||
/* make sure that it is parsed as shallow */
|
||||
if (!parse_object(the_repository, &oid))
|
||||
die(_("error in object: %s"), line);
|
||||
die(_("error in object: %s"), reader.line);
|
||||
if (unregister_shallow(&oid))
|
||||
die(_("no shallow found: %s"), line);
|
||||
die(_("no shallow found: %s"), reader.line);
|
||||
continue;
|
||||
}
|
||||
die(_("expected shallow/unshallow, got %s"), line);
|
||||
die(_("expected shallow/unshallow, got %s"), reader.line);
|
||||
}
|
||||
} else if (!args->stateless_rpc)
|
||||
send_request(args, fd[1], &req_buf);
|
||||
@ -402,9 +408,9 @@ static int find_common(struct fetch_negotiator *negotiator,
|
||||
if (!args->stateless_rpc && count == INITIAL_FLUSH)
|
||||
continue;
|
||||
|
||||
consume_shallow_list(args, fd[0]);
|
||||
consume_shallow_list(args, &reader);
|
||||
do {
|
||||
ack = get_ack(fd[0], result_oid);
|
||||
ack = get_ack(&reader, result_oid);
|
||||
if (ack)
|
||||
print_verbose(args, _("got %s %d %s"), "ack",
|
||||
ack, oid_to_hex(result_oid));
|
||||
@ -474,9 +480,9 @@ done:
|
||||
strbuf_release(&req_buf);
|
||||
|
||||
if (!got_ready || !no_done)
|
||||
consume_shallow_list(args, fd[0]);
|
||||
consume_shallow_list(args, &reader);
|
||||
while (flushes || multi_ack) {
|
||||
int ack = get_ack(fd[0], result_oid);
|
||||
int ack = get_ack(&reader, result_oid);
|
||||
if (ack) {
|
||||
print_verbose(args, _("got %s (%d) %s"), "ack",
|
||||
ack, oid_to_hex(result_oid));
|
||||
@ -1091,7 +1097,8 @@ static int add_haves(struct fetch_negotiator *negotiator,
|
||||
static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
|
||||
const struct fetch_pack_args *args,
|
||||
const struct ref *wants, struct oidset *common,
|
||||
int *haves_to_send, int *in_vain)
|
||||
int *haves_to_send, int *in_vain,
|
||||
int sideband_all)
|
||||
{
|
||||
int ret = 0;
|
||||
struct strbuf req_buf = STRBUF_INIT;
|
||||
@ -1117,6 +1124,8 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
|
||||
packet_buf_write(&req_buf, "include-tag");
|
||||
if (prefer_ofs_delta)
|
||||
packet_buf_write(&req_buf, "ofs-delta");
|
||||
if (sideband_all)
|
||||
packet_buf_write(&req_buf, "sideband-all");
|
||||
|
||||
/* Add shallow-info and deepen request */
|
||||
if (server_supports_feature("fetch", "shallow", 0))
|
||||
@ -1334,7 +1343,13 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
|
||||
struct fetch_negotiator negotiator;
|
||||
fetch_negotiator_init(&negotiator, negotiation_algorithm);
|
||||
packet_reader_init(&reader, fd[0], NULL, 0,
|
||||
PACKET_READ_CHOMP_NEWLINE);
|
||||
PACKET_READ_CHOMP_NEWLINE |
|
||||
PACKET_READ_DIE_ON_ERR_PACKET);
|
||||
if (git_env_bool("GIT_TEST_SIDEBAND_ALL", 1) &&
|
||||
server_supports_feature("fetch", "sideband-all", 0)) {
|
||||
reader.use_sideband = 1;
|
||||
reader.me = "fetch-pack";
|
||||
}
|
||||
|
||||
while (state != FETCH_DONE) {
|
||||
switch (state) {
|
||||
@ -1368,7 +1383,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
|
||||
case FETCH_SEND_REQUEST:
|
||||
if (send_fetch_request(&negotiator, fd[1], args, ref,
|
||||
&common,
|
||||
&haves_to_send, &in_vain))
|
||||
&haves_to_send, &in_vain,
|
||||
reader.use_sideband))
|
||||
state = FETCH_GET_PACK;
|
||||
else
|
||||
state = FETCH_PROCESS_ACKS;
|
||||
|
||||
Reference in New Issue
Block a user