fetch-pack: put shallow info in output parameter
Expand the transport fetch method signature, by adding an output parameter, to allow transports to return information about the refs they have fetched. Then communicate shallow status information through this mechanism instead of by modifying the input list of refs. This does require clients to sometimes generate the ref map twice: once from the list of refs provided by the remote (as is currently done) and potentially once from the new list of refs that the fetch mechanism provides. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Brandon Williams committed
Jun 27, 2018 at 15:30 UTC
989b8c4452f63f415c276df348defce6df613696
8 files changed
+77
-24
builtin/clone.c
+2
-2
@@ -1155,7 +1155,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
1155
}
1156
1157
if (!is_local && !complete_refs_before_fetch)
1158
- transport_fetch_refs(transport, mapped_refs);
1158
+ transport_fetch_refs(transport, mapped_refs, NULL);
1159
1160
remote_head = find_ref_by_name(refs, "HEAD");
1161
remote_head_points_at =
@@ -1197,7 +1197,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
1197
if (is_local)
1198
clone_local(path, git_dir);
1199
else if (refs && complete_refs_before_fetch)
1200
- transport_fetch_refs(transport, mapped_refs);
1200
+ transport_fetch_refs(transport, mapped_refs, NULL);
1201
1202
update_remote_refs(refs, mapped_refs, remote_head_points_at,
1203
branch_top.buf, reflog_msg.buf, transport,
builtin/fetch.c
+24
-4
@@ -946,11 +946,13 @@ static int quickfetch(struct ref *ref_map)
946
return check_connected(iterate_ref_map, &rm, &opt);
947
}
948
949
-static int fetch_refs(struct transport *transport, struct ref *ref_map)
949
+static int fetch_refs(struct transport *transport, struct ref *ref_map,
950
+ struct ref **updated_remote_refs)
951
{
952
int ret = quickfetch(ref_map);
953
if (ret)
953
- ret = transport_fetch_refs(transport, ref_map);
954
+ ret = transport_fetch_refs(transport, ref_map,
955
+ updated_remote_refs);
956
if (!ret)
957
/*
958
* Keep the new pack's ".keep" file around to allow the caller
@@ -1112,7 +1114,7 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map)
1114
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
1115
transport_set_option(transport, TRANS_OPT_DEPTH, "0");
1116
transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
1115
- if (!fetch_refs(transport, ref_map))
1117
+ if (!fetch_refs(transport, ref_map, NULL))
1118
consume_refs(transport, ref_map);
1119
1120
if (gsecondary) {
@@ -1128,6 +1130,7 @@ static int do_fetch(struct transport *transport,
1130
int autotags = (transport->remote->fetch_tags == 1);
1131
int retcode = 0;
1132
const struct ref *remote_refs;
1133
+ struct ref *updated_remote_refs = NULL;
1134
struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
1135
1136
if (tags == TAGS_DEFAULT) {
@@ -1178,7 +1181,24 @@ static int do_fetch(struct transport *transport,
1181
transport->url);
1182
}
1183
}
1181
- if (fetch_refs(transport, ref_map) || consume_refs(transport, ref_map)) {
1184
+
1185
+ if (fetch_refs(transport, ref_map, &updated_remote_refs)) {
1186
+ free_refs(ref_map);
1187
+ retcode = 1;
1188
+ goto cleanup;
1189
+ }
1190
+ if (updated_remote_refs) {
1191
+ /*
1192
+ * Regenerate ref_map using the updated remote refs. This is
1193
+ * to account for additional information which may be provided
1194
+ * by the transport (e.g. shallow info).
1195
+ */
1196
+ free_refs(ref_map);
1197
+ ref_map = get_ref_map(transport->remote, updated_remote_refs, rs,
1198
+ tags, &autotags);
1199
+ free_refs(updated_remote_refs);
1200
+ }
1201
+ if (consume_refs(transport, ref_map)) {
1202
free_refs(ref_map);
1203
retcode = 1;
1204
goto cleanup;
fetch-object.c
+1
-1
@@ -19,7 +19,7 @@ static void fetch_refs(const char *remote_name, struct ref *ref)
19
20
transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
21
transport_set_option(transport, TRANS_OPT_NO_DEPENDENTS, "1");
22
- transport_fetch_refs(transport, ref);
22
+ transport_fetch_refs(transport, ref, NULL);
23
fetch_if_missing = original_fetch_if_missing;
24
}
25
fetch-pack.c
+8
-7
@@ -1470,12 +1470,13 @@ static int remove_duplicates_in_refs(struct ref **ref, int nr)
1470
}
1471
1472
static void update_shallow(struct fetch_pack_args *args,
1473
- struct ref **sought, int nr_sought,
1473
+ struct ref *refs,
1474
struct shallow_info *si)
1475
{
1476
struct oid_array ref = OID_ARRAY_INIT;
1477
int *status;
1478
int i;
1479
+ struct ref *r;
1480
1481
if (args->deepen && alternate_shallow_file) {
1482
if (*alternate_shallow_file == '\0') { /* --unshallow */
@@ -1517,8 +1518,8 @@ static void update_shallow(struct fetch_pack_args *args,
1518
remove_nonexistent_theirs_shallow(si);
1519
if (!si->nr_ours && !si->nr_theirs)
1520
return;
1520
- for (i = 0; i < nr_sought; i++)
1521
- oid_array_append(&ref, &sought[i]->old_oid);
1521
+ for (r = refs; r; r = r->next)
1522
+ oid_array_append(&ref, &r->old_oid);
1523
si->ref = &ref;
1524
1525
if (args->update_shallow) {
@@ -1552,12 +1553,12 @@ static void update_shallow(struct fetch_pack_args *args,
1553
* remote is also shallow, check what ref is safe to update
1554
* without updating .git/shallow
1555
*/
1555
- status = xcalloc(nr_sought, sizeof(*status));
1556
+ status = xcalloc(ref.nr, sizeof(*status));
1557
assign_shallow_commits_to_refs(si, NULL, status);
1558
if (si->nr_ours || si->nr_theirs) {
1558
- for (i = 0; i < nr_sought; i++)
1559
+ for (r = refs, i = 0; r; r = r->next, i++)
1560
if (status[i])
1560
- sought[i]->status = REF_STATUS_REJECT_SHALLOW;
1561
+ r->status = REF_STATUS_REJECT_SHALLOW;
1562
}
1563
free(status);
1564
oid_array_clear(&ref);
@@ -1591,7 +1592,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
1592
ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
1593
&si, pack_lockfile);
1594
reprepare_packed_git(the_repository);
1594
- update_shallow(args, sought, nr_sought, &si);
1595
+ update_shallow(args, ref_cpy, &si);
1596
clear_shallow_info(&si);
1597
return ref_cpy;
1598
}
transport-helper.c
+4
-2
@@ -651,14 +651,16 @@ static int connect_helper(struct transport *transport, const char *name,
651
}
652
653
static int fetch(struct transport *transport,
654
- int nr_heads, struct ref **to_fetch)
654
+ int nr_heads, struct ref **to_fetch,
655
+ struct ref **fetched_refs)
656
{
657
struct helper_data *data = transport->data;
658
int i, count;
659
660
if (process_connect(transport, 0)) {
661
do_take_over(transport);
661
- return transport->vtable->fetch(transport, nr_heads, to_fetch);
662
+ return transport->vtable->fetch(transport, nr_heads, to_fetch,
663
+ fetched_refs);
664
}
665
666
count = 0;
transport-internal.h
+8
-1
@@ -36,11 +36,18 @@ struct transport_vtable {
36
* Fetch the objects for the given refs. Note that this gets
37
* an array, and should ignore the list structure.
38
*
39
+ * The transport *may* provide, in fetched_refs, the list of refs that
40
+ * it fetched. If the transport knows anything about the fetched refs
41
+ * that the caller does not know (for example, shallow status), it
42
+ * should provide that list of refs and include that information in the
43
+ * list.
44
+ *
45
* If the transport did not get hashes for refs in
46
* get_refs_list(), it should set the old_sha1 fields in the
47
* provided refs now.
48
**/
43
- int (*fetch)(struct transport *transport, int refs_nr, struct ref **refs);
49
+ int (*fetch)(struct transport *transport, int refs_nr, struct ref **refs,
50
+ struct ref **fetched_refs);
51
52
/**
53
* Push the objects and refs. Send the necessary objects, and
transport.c
+28
-6
@@ -151,7 +151,8 @@ static struct ref *get_refs_from_bundle(struct transport *transport,
151
}
152
153
static int fetch_refs_from_bundle(struct transport *transport,
154
- int nr_heads, struct ref **to_fetch)
154
+ int nr_heads, struct ref **to_fetch,
155
+ struct ref **fetched_refs)
156
{
157
struct bundle_transport_data *data = transport->data;
158
return unbundle(&data->header, data->fd,
@@ -287,7 +288,8 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
288
}
289
290
static int fetch_refs_via_pack(struct transport *transport,
290
- int nr_heads, struct ref **to_fetch)
291
+ int nr_heads, struct ref **to_fetch,
292
+ struct ref **fetched_refs)
293
{
294
int ret = 0;
295
struct git_transport_data *data = transport->data;
@@ -354,8 +356,12 @@ static int fetch_refs_via_pack(struct transport *transport,
356
if (report_unmatched_refs(to_fetch, nr_heads))
357
ret = -1;
358
359
+ if (fetched_refs)
360
+ *fetched_refs = refs;
361
+ else
362
+ free_refs(refs);
363
+
364
free_refs(refs_tmp);
358
- free_refs(refs);
365
free(dest);
366
return ret;
367
}
@@ -1215,19 +1221,31 @@ const struct ref *transport_get_remote_refs(struct transport *transport,
1221
return transport->remote_refs;
1222
}
1223
1218
-int transport_fetch_refs(struct transport *transport, struct ref *refs)
1224
+int transport_fetch_refs(struct transport *transport, struct ref *refs,
1225
+ struct ref **fetched_refs)
1226
{
1227
int rc;
1228
int nr_heads = 0, nr_alloc = 0, nr_refs = 0;
1229
struct ref **heads = NULL;
1230
+ struct ref *nop_head = NULL, **nop_tail = &nop_head;
1231
struct ref *rm;
1232
1233
for (rm = refs; rm; rm = rm->next) {
1234
nr_refs++;
1235
if (rm->peer_ref &&
1236
!is_null_oid(&rm->old_oid) &&
1229
- !oidcmp(&rm->peer_ref->old_oid, &rm->old_oid))
1237
+ !oidcmp(&rm->peer_ref->old_oid, &rm->old_oid)) {
1238
+ /*
1239
+ * These need to be reported as fetched, but we don't
1240
+ * actually need to fetch them.
1241
+ */
1242
+ if (fetched_refs) {
1243
+ struct ref *nop_ref = copy_ref(rm);
1244
+ *nop_tail = nop_ref;
1245
+ nop_tail = &nop_ref->next;
1246
+ }
1247
continue;
1248
+ }
1249
ALLOC_GROW(heads, nr_heads + 1, nr_alloc);
1250
heads[nr_heads++] = rm;
1251
}
@@ -1245,7 +1263,11 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
1263
heads[nr_heads++] = rm;
1264
}
1265
1248
- rc = transport->vtable->fetch(transport, nr_heads, heads);
1266
+ rc = transport->vtable->fetch(transport, nr_heads, heads, fetched_refs);
1267
+ if (fetched_refs && nop_head) {
1268
+ *nop_tail = *fetched_refs;
1269
+ *fetched_refs = nop_head;
1270
+ }
1271
1272
free(heads);
1273
return rc;
transport.h
+2
-1
@@ -218,7 +218,8 @@ int transport_push(struct transport *connection,
218
const struct ref *transport_get_remote_refs(struct transport *transport,
219
const struct argv_array *ref_prefixes);
220
221
-int transport_fetch_refs(struct transport *transport, struct ref *refs);
221
+int transport_fetch_refs(struct transport *transport, struct ref *refs,
222
+ struct ref **fetched_refs);
223
void transport_unlock_pack(struct transport *transport);
224
int transport_disconnect(struct transport *transport);
225
char *transport_anonymize_url(const char *url);