Skip to content

Commit 989b8c4

Browse files
bmwillgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6d1700d commit 989b8c4

File tree

8 files changed

+77
-24
lines changed

8 files changed

+77
-24
lines changed

builtin/clone.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11551155
}
11561156

11571157
if (!is_local && !complete_refs_before_fetch)
1158-
transport_fetch_refs(transport, mapped_refs);
1158+
transport_fetch_refs(transport, mapped_refs, NULL);
11591159

11601160
remote_head = find_ref_by_name(refs, "HEAD");
11611161
remote_head_points_at =
@@ -1197,7 +1197,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11971197
if (is_local)
11981198
clone_local(path, git_dir);
11991199
else if (refs && complete_refs_before_fetch)
1200-
transport_fetch_refs(transport, mapped_refs);
1200+
transport_fetch_refs(transport, mapped_refs, NULL);
12011201

12021202
update_remote_refs(refs, mapped_refs, remote_head_points_at,
12031203
branch_top.buf, reflog_msg.buf, transport,

builtin/fetch.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -946,11 +946,13 @@ static int quickfetch(struct ref *ref_map)
946946
return check_connected(iterate_ref_map, &rm, &opt);
947947
}
948948

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)
950951
{
951952
int ret = quickfetch(ref_map);
952953
if (ret)
953-
ret = transport_fetch_refs(transport, ref_map);
954+
ret = transport_fetch_refs(transport, ref_map,
955+
updated_remote_refs);
954956
if (!ret)
955957
/*
956958
* 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)
11121114
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
11131115
transport_set_option(transport, TRANS_OPT_DEPTH, "0");
11141116
transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
1115-
if (!fetch_refs(transport, ref_map))
1117+
if (!fetch_refs(transport, ref_map, NULL))
11161118
consume_refs(transport, ref_map);
11171119

11181120
if (gsecondary) {
@@ -1128,6 +1130,7 @@ static int do_fetch(struct transport *transport,
11281130
int autotags = (transport->remote->fetch_tags == 1);
11291131
int retcode = 0;
11301132
const struct ref *remote_refs;
1133+
struct ref *updated_remote_refs = NULL;
11311134
struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
11321135

11331136
if (tags == TAGS_DEFAULT) {
@@ -1178,7 +1181,24 @@ static int do_fetch(struct transport *transport,
11781181
transport->url);
11791182
}
11801183
}
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)) {
11821202
free_refs(ref_map);
11831203
retcode = 1;
11841204
goto cleanup;

fetch-object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static void fetch_refs(const char *remote_name, struct ref *ref)
1919

2020
transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
2121
transport_set_option(transport, TRANS_OPT_NO_DEPENDENTS, "1");
22-
transport_fetch_refs(transport, ref);
22+
transport_fetch_refs(transport, ref, NULL);
2323
fetch_if_missing = original_fetch_if_missing;
2424
}
2525

fetch-pack.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,12 +1470,13 @@ static int remove_duplicates_in_refs(struct ref **ref, int nr)
14701470
}
14711471

14721472
static void update_shallow(struct fetch_pack_args *args,
1473-
struct ref **sought, int nr_sought,
1473+
struct ref *refs,
14741474
struct shallow_info *si)
14751475
{
14761476
struct oid_array ref = OID_ARRAY_INIT;
14771477
int *status;
14781478
int i;
1479+
struct ref *r;
14791480

14801481
if (args->deepen && alternate_shallow_file) {
14811482
if (*alternate_shallow_file == '\0') { /* --unshallow */
@@ -1517,8 +1518,8 @@ static void update_shallow(struct fetch_pack_args *args,
15171518
remove_nonexistent_theirs_shallow(si);
15181519
if (!si->nr_ours && !si->nr_theirs)
15191520
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);
15221523
si->ref = &ref;
15231524

15241525
if (args->update_shallow) {
@@ -1552,12 +1553,12 @@ static void update_shallow(struct fetch_pack_args *args,
15521553
* remote is also shallow, check what ref is safe to update
15531554
* without updating .git/shallow
15541555
*/
1555-
status = xcalloc(nr_sought, sizeof(*status));
1556+
status = xcalloc(ref.nr, sizeof(*status));
15561557
assign_shallow_commits_to_refs(si, NULL, status);
15571558
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++)
15591560
if (status[i])
1560-
sought[i]->status = REF_STATUS_REJECT_SHALLOW;
1561+
r->status = REF_STATUS_REJECT_SHALLOW;
15611562
}
15621563
free(status);
15631564
oid_array_clear(&ref);
@@ -1591,7 +1592,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
15911592
ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
15921593
&si, pack_lockfile);
15931594
reprepare_packed_git(the_repository);
1594-
update_shallow(args, sought, nr_sought, &si);
1595+
update_shallow(args, ref_cpy, &si);
15951596
clear_shallow_info(&si);
15961597
return ref_cpy;
15971598
}

transport-helper.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -651,14 +651,16 @@ static int connect_helper(struct transport *transport, const char *name,
651651
}
652652

653653
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)
655656
{
656657
struct helper_data *data = transport->data;
657658
int i, count;
658659

659660
if (process_connect(transport, 0)) {
660661
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);
662664
}
663665

664666
count = 0;

transport-internal.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,18 @@ struct transport_vtable {
3636
* Fetch the objects for the given refs. Note that this gets
3737
* an array, and should ignore the list structure.
3838
*
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+
*
3945
* If the transport did not get hashes for refs in
4046
* get_refs_list(), it should set the old_sha1 fields in the
4147
* provided refs now.
4248
**/
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);
4451

4552
/**
4653
* Push the objects and refs. Send the necessary objects, and

transport.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ static struct ref *get_refs_from_bundle(struct transport *transport,
151151
}
152152

153153
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)
155156
{
156157
struct bundle_transport_data *data = transport->data;
157158
return unbundle(&data->header, data->fd,
@@ -287,7 +288,8 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
287288
}
288289

289290
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)
291293
{
292294
int ret = 0;
293295
struct git_transport_data *data = transport->data;
@@ -354,8 +356,12 @@ static int fetch_refs_via_pack(struct transport *transport,
354356
if (report_unmatched_refs(to_fetch, nr_heads))
355357
ret = -1;
356358

359+
if (fetched_refs)
360+
*fetched_refs = refs;
361+
else
362+
free_refs(refs);
363+
357364
free_refs(refs_tmp);
358-
free_refs(refs);
359365
free(dest);
360366
return ret;
361367
}
@@ -1215,19 +1221,31 @@ const struct ref *transport_get_remote_refs(struct transport *transport,
12151221
return transport->remote_refs;
12161222
}
12171223

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)
12191226
{
12201227
int rc;
12211228
int nr_heads = 0, nr_alloc = 0, nr_refs = 0;
12221229
struct ref **heads = NULL;
1230+
struct ref *nop_head = NULL, **nop_tail = &nop_head;
12231231
struct ref *rm;
12241232

12251233
for (rm = refs; rm; rm = rm->next) {
12261234
nr_refs++;
12271235
if (rm->peer_ref &&
12281236
!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+
}
12301247
continue;
1248+
}
12311249
ALLOC_GROW(heads, nr_heads + 1, nr_alloc);
12321250
heads[nr_heads++] = rm;
12331251
}
@@ -1245,7 +1263,11 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
12451263
heads[nr_heads++] = rm;
12461264
}
12471265

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+
}
12491271

12501272
free(heads);
12511273
return rc;

transport.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ int transport_push(struct transport *connection,
218218
const struct ref *transport_get_remote_refs(struct transport *transport,
219219
const struct argv_array *ref_prefixes);
220220

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);
222223
void transport_unlock_pack(struct transport *transport);
223224
int transport_disconnect(struct transport *transport);
224225
char *transport_anonymize_url(const char *url);

0 commit comments

Comments
 (0)