fetch-pack: respect --no-update-shallow in v2

In protocol v0, when sending "shallow" lines, the server distinguishes between lines caused by the remote repo being shallow and lines caused by client-specified depth settings. Unless "--update-shallow" is specified, there is a difference in behavior: refs that reach the former "shallow" lines, but not the latter, are rejected. But in v2, the server does not, and the client treats all "shallow" lines like lines caused by client-specified depth settings. Full restoration of v0 functionality is not possible without protocol change, but we can implement a heuristic: if we specify any depth setting, treat all "shallow" lines like lines caused by client-specified depth settings (that is, unaffected by "--no-update-shallow"), but otherwise, treat them like lines caused by the remote repo being shallow (that is, affected by "--no-update-shallow"). This restores most of v0 behavior, except in the case where a client fetches from a shallow repository with depth settings. This patch causes a test that previously failed with GIT_TEST_PROTOCOL_VERSION=2 to pass. Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Tan committed Mar 26, 2019 at 12:31 UTC 1339078f5e670e5eb084a4a64c81a0d0b5f1e223
1 file changed +34 -7
fetch-pack.c
+34 -7
@@ -1253,9 +1253,11 @@ static int process_acks(struct fetch_negotiator *negotiator,
1253 }
1254
1255 static void receive_shallow_info(struct fetch_pack_args *args,
1256 - struct packet_reader *reader)
1256 + struct packet_reader *reader,
1257 + struct oid_array *shallows,
1258 + struct shallow_info *si)
1259 {
1258 - int line_received = 0;
1260 + int unshallow_received = 0;
1261
1262 process_section_header(reader, "shallow-info", 0);
1263 while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
@@ -1265,8 +1267,7 @@ static void receive_shallow_info(struct fetch_pack_args *args,
1267 if (skip_prefix(reader->line, "shallow ", &arg)) {
1268 if (get_oid_hex(arg, &oid))
1269 die(_("invalid shallow line: %s"), reader->line);
1268 - register_shallow(the_repository, &oid);
1269 - line_received = 1;
1270 + oid_array_append(shallows, &oid);
1271 continue;
1272 }
1273 if (skip_prefix(reader->line, "unshallow ", &arg)) {
@@ -1279,7 +1280,7 @@ static void receive_shallow_info(struct fetch_pack_args *args,
1280 die(_("error in object: %s"), reader->line);
1281 if (unregister_shallow(&oid))
1282 die(_("no shallow found: %s"), reader->line);
1282 - line_received = 1;
1283 + unshallow_received = 1;
1284 continue;
1285 }
1286 die(_("expected shallow/unshallow, got %s"), reader->line);
@@ -1289,10 +1290,31 @@ static void receive_shallow_info(struct fetch_pack_args *args,
1290 reader->status != PACKET_READ_DELIM)
1291 die(_("error processing shallow info: %d"), reader->status);
1292
1292 - if (line_received) {
1293 + if (args->deepen || unshallow_received) {
1294 + /*
1295 + * Treat these as shallow lines caused by our depth settings.
1296 + * In v0, these lines cannot cause refs to be rejected; do the
1297 + * same.
1298 + */
1299 + int i;
1300 +
1301 + for (i = 0; i < shallows->nr; i++)
1302 + register_shallow(the_repository, &shallows->oid[i]);
1303 setup_alternate_shallow(&shallow_lock, &alternate_shallow_file,
1304 NULL);
1305 args->deepen = 1;
1306 + } else if (shallows->nr) {
1307 + /*
1308 + * Treat these as shallow lines caused by the remote being
1309 + * shallow. In v0, remote refs that reach these objects are
1310 + * rejected (unless --update-shallow is set); do the same.
1311 + */
1312 + prepare_shallow_info(si, shallows);
1313 + if (si->nr_ours || si->nr_theirs)
1314 + alternate_shallow_file =
1315 + setup_temporary_shallow(si->shallow);
1316 + else
1317 + alternate_shallow_file = NULL;
1318 } else {
1319 alternate_shallow_file = NULL;
1320 }
@@ -1337,6 +1359,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1359 int fd[2],
1360 const struct ref *orig_ref,
1361 struct ref **sought, int nr_sought,
1362 + struct oid_array *shallows,
1363 + struct shallow_info *si,
1364 char **pack_lockfile)
1365 {
1366 struct ref *ref = copy_ref_list(orig_ref);
@@ -1411,7 +1435,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1435 case FETCH_GET_PACK:
1436 /* Check for shallow-info section */
1437 if (process_section_header(&reader, "shallow-info", 1))
1414 - receive_shallow_info(args, &reader);
1438 + receive_shallow_info(args, &reader, shallows, si);
1439
1440 if (process_section_header(&reader, "wanted-refs", 1))
1441 receive_wanted_refs(&reader, sought, nr_sought);
@@ -1625,6 +1649,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
1649 {
1650 struct ref *ref_cpy;
1651 struct shallow_info si;
1652 + struct oid_array shallows_scratch = OID_ARRAY_INIT;
1653
1654 fetch_pack_setup();
1655 if (nr_sought)
@@ -1653,6 +1678,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
1678 BUG("Protocol V2 does not provide shallows at this point in the fetch");
1679 memset(&si, 0, sizeof(si));
1680 ref_cpy = do_fetch_pack_v2(args, fd, ref, sought, nr_sought,
1681 + &shallows_scratch, &si,
1682 pack_lockfile);
1683 } else {
1684 prepare_shallow_info(&si, shallow);
@@ -1680,6 +1706,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
1706 update_shallow(args, sought, nr_sought, &si);
1707 cleanup:
1708 clear_shallow_info(&si);
1709 + oid_array_clear(&shallows_scratch);
1710 return ref_cpy;
1711 }
1712