Skip to content

Commit 26f4f2c

Browse files
committed
Merge branch 'mh/fetch-filter-refs'
Code simplification and clarification. * mh/fetch-filter-refs: test-string-list.c: Fix some sparse warnings fetch-pack: eliminate spurious error messages cmd_fetch_pack(): simplify computation of return value fetch-pack: report missing refs even if no existing refs were received cmd_fetch_pack(): return early if finish_connect() fails filter_refs(): simplify logic filter_refs(): build refs list as we go filter_refs(): delete matched refs from sought list fetch_pack(): update sought->nr to reflect number of unique entries filter_refs(): do not check the same sought_pos twice Change fetch_pack() and friends to take string_list arguments fetch_pack(): reindent function decl and defn Rename static function fetch_pack() to http_fetch_pack() t5500: add tests of fetch-pack --all --depth=N $URL $REF t5500: add tests of error output for missing refs
2 parents 9e40b6e + 6511987 commit 26f4f2c

File tree

6 files changed

+134
-126
lines changed

6 files changed

+134
-126
lines changed

builtin/fetch-pack.c

Lines changed: 64 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -525,72 +525,59 @@ static void mark_recent_complete_commits(unsigned long cutoff)
525525
}
526526
}
527527

528-
static void filter_refs(struct ref **refs, int nr_match, char **match)
528+
static int non_matching_ref(struct string_list_item *item, void *unused)
529+
{
530+
if (item->util) {
531+
item->util = NULL;
532+
return 0;
533+
}
534+
else
535+
return 1;
536+
}
537+
538+
static void filter_refs(struct ref **refs, struct string_list *sought)
529539
{
530-
struct ref **return_refs;
531540
struct ref *newlist = NULL;
532541
struct ref **newtail = &newlist;
533542
struct ref *ref, *next;
534-
struct ref *fastarray[32];
535-
int match_pos;
536-
537-
if (nr_match && !args.fetch_all) {
538-
if (ARRAY_SIZE(fastarray) < nr_match)
539-
return_refs = xcalloc(nr_match, sizeof(struct ref *));
540-
else {
541-
return_refs = fastarray;
542-
memset(return_refs, 0, sizeof(struct ref *) * nr_match);
543-
}
544-
}
545-
else
546-
return_refs = NULL;
543+
int sought_pos;
547544

548-
match_pos = 0;
545+
sought_pos = 0;
549546
for (ref = *refs; ref; ref = next) {
547+
int keep = 0;
550548
next = ref->next;
551549
if (!memcmp(ref->name, "refs/", 5) &&
552550
check_refname_format(ref->name + 5, 0))
553551
; /* trash */
554-
else if (args.fetch_all &&
555-
(!args.depth || prefixcmp(ref->name, "refs/tags/") )) {
556-
*newtail = ref;
557-
ref->next = NULL;
558-
newtail = &ref->next;
559-
continue;
560-
}
561552
else {
562-
int cmp = -1;
563-
while (match_pos < nr_match) {
564-
cmp = strcmp(ref->name, match[match_pos]);
565-
if (cmp < 0) /* definitely do not have it */
566-
break;
567-
else if (cmp == 0) { /* definitely have it */
568-
match[match_pos][0] = '\0';
569-
return_refs[match_pos] = ref;
553+
while (sought_pos < sought->nr) {
554+
int cmp = strcmp(ref->name, sought->items[sought_pos].string);
555+
if (cmp < 0)
556+
break; /* definitely do not have it */
557+
else if (cmp == 0) {
558+
keep = 1; /* definitely have it */
559+
sought->items[sought_pos++].util = "matched";
570560
break;
571561
}
572-
else /* might have it; keep looking */
573-
match_pos++;
562+
else
563+
sought_pos++; /* might have it; keep looking */
574564
}
575-
if (!cmp)
576-
continue; /* we will link it later */
577565
}
578-
free(ref);
579-
}
580566

581-
if (!args.fetch_all) {
582-
int i;
583-
for (i = 0; i < nr_match; i++) {
584-
ref = return_refs[i];
585-
if (ref) {
586-
*newtail = ref;
587-
ref->next = NULL;
588-
newtail = &ref->next;
589-
}
567+
if (! keep && args.fetch_all &&
568+
(!args.depth || prefixcmp(ref->name, "refs/tags/")))
569+
keep = 1;
570+
571+
if (keep) {
572+
*newtail = ref;
573+
ref->next = NULL;
574+
newtail = &ref->next;
575+
} else {
576+
free(ref);
590577
}
591-
if (return_refs != fastarray)
592-
free(return_refs);
593578
}
579+
580+
filter_string_list(sought, 0, non_matching_ref, NULL);
594581
*refs = newlist;
595582
}
596583

@@ -599,7 +586,7 @@ static void mark_alternate_complete(const struct ref *ref, void *unused)
599586
mark_complete(NULL, ref->old_sha1, 0, NULL);
600587
}
601588

602-
static int everything_local(struct ref **refs, int nr_match, char **match)
589+
static int everything_local(struct ref **refs, struct string_list *sought)
603590
{
604591
struct ref *ref;
605592
int retval;
@@ -650,7 +637,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
650637
}
651638
}
652639

653-
filter_refs(refs, nr_match, match);
640+
filter_refs(refs, sought);
654641

655642
for (retval = 1, ref = *refs; ref ; ref = ref->next) {
656643
const unsigned char *remote = ref->old_sha1;
@@ -781,8 +768,7 @@ static int get_pack(int xd[2], char **pack_lockfile)
781768

782769
static struct ref *do_fetch_pack(int fd[2],
783770
const struct ref *orig_ref,
784-
int nr_match,
785-
char **match,
771+
struct string_list *sought,
786772
char **pack_lockfile)
787773
{
788774
struct ref *ref = copy_ref_list(orig_ref);
@@ -839,7 +825,7 @@ static struct ref *do_fetch_pack(int fd[2],
839825
agent_len, agent_feature);
840826
}
841827

842-
if (everything_local(&ref, nr_match, match)) {
828+
if (everything_local(&ref, sought)) {
843829
packet_flush(fd[1]);
844830
goto all_done;
845831
}
@@ -859,19 +845,6 @@ static struct ref *do_fetch_pack(int fd[2],
859845
return ref;
860846
}
861847

862-
static int remove_duplicates(int nr_heads, char **heads)
863-
{
864-
int src, dst;
865-
866-
if (!nr_heads)
867-
return 0;
868-
869-
for (src = dst = 1; src < nr_heads; src++)
870-
if (strcmp(heads[src], heads[dst-1]))
871-
heads[dst++] = heads[src];
872-
return dst;
873-
}
874-
875848
static int fetch_pack_config(const char *var, const char *value, void *cb)
876849
{
877850
if (strcmp(var, "fetch.unpacklimit") == 0) {
@@ -922,8 +895,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
922895
int i, ret;
923896
struct ref *ref = NULL;
924897
const char *dest = NULL;
925-
int alloc_heads = 0, nr_heads = 0;
926-
char **heads = NULL;
898+
struct string_list sought = STRING_LIST_INIT_DUP;
927899
int fd[2];
928900
char *pack_lockfile = NULL;
929901
char **pack_lockfile_ptr = NULL;
@@ -1000,9 +972,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
1000972
* Copy refs from cmdline to growable list, then append any
1001973
* refs from the standard input:
1002974
*/
1003-
ALLOC_GROW(heads, argc - i, alloc_heads);
1004975
for (; i < argc; i++)
1005-
heads[nr_heads++] = xstrdup(argv[i]);
976+
string_list_append(&sought, xstrdup(argv[i]));
1006977
if (args.stdin_refs) {
1007978
if (args.stateless_rpc) {
1008979
/* in stateless RPC mode we use pkt-line to read
@@ -1015,17 +986,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
1015986
break;
1016987
if (line[n-1] == '\n')
1017988
n--;
1018-
ALLOC_GROW(heads, nr_heads + 1, alloc_heads);
1019-
heads[nr_heads++] = xmemdupz(line, n);
989+
string_list_append(&sought, xmemdupz(line, n));
1020990
}
1021991
}
1022992
else {
1023993
/* read from stdin one ref per line, until EOF */
1024994
struct strbuf line = STRBUF_INIT;
1025-
while (strbuf_getline(&line, stdin, '\n') != EOF) {
1026-
ALLOC_GROW(heads, nr_heads + 1, alloc_heads);
1027-
heads[nr_heads++] = strbuf_detach(&line, NULL);
1028-
}
995+
while (strbuf_getline(&line, stdin, '\n') != EOF)
996+
string_list_append(&sought, strbuf_detach(&line, NULL));
1029997
strbuf_release(&line);
1030998
}
1031999
}
@@ -1042,29 +1010,26 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
10421010
get_remote_heads(fd[0], &ref, 0, NULL);
10431011

10441012
ref = fetch_pack(&args, fd, conn, ref, dest,
1045-
nr_heads, heads, pack_lockfile_ptr);
1013+
&sought, pack_lockfile_ptr);
10461014
if (pack_lockfile) {
10471015
printf("lock %s\n", pack_lockfile);
10481016
fflush(stdout);
10491017
}
10501018
close(fd[0]);
10511019
close(fd[1]);
10521020
if (finish_connect(conn))
1053-
ref = NULL;
1054-
ret = !ref;
1055-
1056-
if (!ret && nr_heads) {
1057-
/* If the heads to pull were given, we should have
1058-
* consumed all of them by matching the remote.
1059-
* Otherwise, 'git fetch remote no-such-ref' would
1060-
* silently succeed without issuing an error.
1061-
*/
1062-
for (i = 0; i < nr_heads; i++)
1063-
if (heads[i] && heads[i][0]) {
1064-
error("no such remote ref %s", heads[i]);
1065-
ret = 1;
1066-
}
1067-
}
1021+
return 1;
1022+
1023+
ret = !ref || sought.nr;
1024+
1025+
/*
1026+
* If the heads to pull were given, we should have consumed
1027+
* all of them by matching the remote. Otherwise, 'git fetch
1028+
* remote no-such-ref' would silently succeed without issuing
1029+
* an error.
1030+
*/
1031+
for (i = 0; i < sought.nr; i++)
1032+
error("no such remote ref %s", sought.items[i].string);
10681033
while (ref) {
10691034
printf("%s %s\n",
10701035
sha1_to_hex(ref->old_sha1), ref->name);
@@ -1074,18 +1039,12 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
10741039
return ret;
10751040
}
10761041

1077-
static int compare_heads(const void *a, const void *b)
1078-
{
1079-
return strcmp(*(const char **)a, *(const char **)b);
1080-
}
1081-
10821042
struct ref *fetch_pack(struct fetch_pack_args *my_args,
10831043
int fd[], struct child_process *conn,
10841044
const struct ref *ref,
1085-
const char *dest,
1086-
int nr_heads,
1087-
char **heads,
1088-
char **pack_lockfile)
1045+
const char *dest,
1046+
struct string_list *sought,
1047+
char **pack_lockfile)
10891048
{
10901049
struct stat st;
10911050
struct ref *ref_cpy;
@@ -1098,16 +1057,16 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
10981057
st.st_mtime = 0;
10991058
}
11001059

1101-
if (heads && nr_heads) {
1102-
qsort(heads, nr_heads, sizeof(*heads), compare_heads);
1103-
nr_heads = remove_duplicates(nr_heads, heads);
1060+
if (sought->nr) {
1061+
sort_string_list(sought);
1062+
string_list_remove_duplicates(sought, 0);
11041063
}
11051064

11061065
if (!ref) {
11071066
packet_flush(fd[1]);
11081067
die("no matching remote head");
11091068
}
1110-
ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);
1069+
ref_cpy = do_fetch_pack(fd, ref, sought, pack_lockfile);
11111070

11121071
if (args.depth > 0) {
11131072
struct cache_time mtime;

fetch-pack.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef FETCH_PACK_H
22
#define FETCH_PACK_H
33

4+
#include "string-list.h"
5+
46
struct fetch_pack_args {
57
const char *uploadpack;
68
int unpacklimit;
@@ -17,12 +19,18 @@ struct fetch_pack_args {
1719
stateless_rpc:1;
1820
};
1921

22+
/*
23+
* sought contains the full names of remote references that should be
24+
* updated from. On return, the names that were found on the remote
25+
* will have been removed from the list. The util members of the
26+
* string_list_items are used internally; they must be NULL on entry
27+
* (and will be NULL on exit).
28+
*/
2029
struct ref *fetch_pack(struct fetch_pack_args *args,
21-
int fd[], struct child_process *conn,
22-
const struct ref *ref,
23-
const char *dest,
24-
int nr_heads,
25-
char **heads,
26-
char **pack_lockfile);
30+
int fd[], struct child_process *conn,
31+
const struct ref *ref,
32+
const char *dest,
33+
struct string_list *sought,
34+
char **pack_lockfile);
2735

2836
#endif

http-walker.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo)
396396
return ret;
397397
}
398398

399-
static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned char *sha1)
399+
static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigned char *sha1)
400400
{
401401
struct packed_git *target;
402402
int ret;
@@ -524,7 +524,7 @@ static int fetch(struct walker *walker, unsigned char *sha1)
524524
if (!fetch_object(walker, altbase, sha1))
525525
return 0;
526526
while (altbase) {
527-
if (!fetch_pack(walker, altbase, sha1))
527+
if (!http_fetch_pack(walker, altbase, sha1))
528528
return 0;
529529
fetch_alternates(walker, data->alt->base);
530530
altbase = altbase->next;

0 commit comments

Comments
 (0)