diff options
-rw-r--r-- | builtin/fetch-pack.c | 40 | ||||
-rw-r--r-- | cache.h | 3 | ||||
-rw-r--r-- | fetch-pack.c | 79 | ||||
-rw-r--r-- | fetch-pack.h | 11 | ||||
-rw-r--r-- | transport.c | 9 |
5 files changed, 89 insertions, 53 deletions
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 940ae35dc2..670e81fd99 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -7,12 +7,31 @@ static const char fetch_pack_usage[] = "[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] " "[--no-progress] [-v] [<host>:]<directory> [<refs>...]"; +static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc, + const char *name, int namelen) +{ + struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1); + + memcpy(ref->name, name, namelen); + ref->name[namelen] = '\0'; + (*nr)++; + ALLOC_GROW(*sought, *nr, *alloc); + (*sought)[*nr - 1] = ref; +} + +static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, + const char *string) +{ + add_sought_entry_mem(sought, nr, alloc, string, strlen(string)); +} + int cmd_fetch_pack(int argc, const char **argv, const char *prefix) { int i, ret; struct ref *ref = NULL; const char *dest = NULL; - struct string_list sought = STRING_LIST_INIT_DUP; + struct ref **sought = NULL; + int nr_sought = 0, alloc_sought = 0; int fd[2]; char *pack_lockfile = NULL; char **pack_lockfile_ptr = NULL; @@ -94,7 +113,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) * refs from the standard input: */ for (; i < argc; i++) - string_list_append(&sought, xstrdup(argv[i])); + add_sought_entry(&sought, &nr_sought, &alloc_sought, argv[i]); if (args.stdin_refs) { if (args.stateless_rpc) { /* in stateless RPC mode we use pkt-line to read @@ -107,14 +126,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) break; if (line[n-1] == '\n') n--; - string_list_append(&sought, xmemdupz(line, n)); + add_sought_entry_mem(&sought, &nr_sought, &alloc_sought, line, n); } } else { /* read from stdin one ref per line, until EOF */ struct strbuf line = STRBUF_INIT; while (strbuf_getline(&line, stdin, '\n') != EOF) - string_list_append(&sought, strbuf_detach(&line, NULL)); + add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf); strbuf_release(&line); } } @@ -131,7 +150,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) get_remote_heads(fd[0], &ref, 0, NULL); ref = fetch_pack(&args, fd, conn, ref, dest, - &sought, pack_lockfile_ptr); + sought, nr_sought, pack_lockfile_ptr); if (pack_lockfile) { printf("lock %s\n", pack_lockfile); fflush(stdout); @@ -141,7 +160,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) if (finish_connect(conn)) return 1; - ret = !ref || sought.nr; + ret = !ref; /* * If the heads to pull were given, we should have consumed @@ -149,8 +168,13 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) * remote no-such-ref' would silently succeed without issuing * an error. */ - for (i = 0; i < sought.nr; i++) - error("no such remote ref %s", sought.items[i].string); + for (i = 0; i < nr_sought; i++) { + if (!sought[i] || sought[i]->matched) + continue; + error("no such remote ref %s", sought[i]->name); + ret = 1; + } + while (ref) { printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); @@ -1013,7 +1013,8 @@ struct ref { nonfastforward:1, not_forwardable:1, update:1, - deletion:1; + deletion:1, + matched:1; enum { REF_STATUS_NONE = 0, REF_STATUS_OK, diff --git a/fetch-pack.c b/fetch-pack.c index f0acdf7331..915c0b7887 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -520,47 +520,37 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args, } } -static int non_matching_ref(struct string_list_item *item, void *unused) -{ - if (item->util) { - item->util = NULL; - return 0; - } - else - return 1; -} - static void filter_refs(struct fetch_pack_args *args, - struct ref **refs, struct string_list *sought) + struct ref **refs, + struct ref **sought, int nr_sought) { struct ref *newlist = NULL; struct ref **newtail = &newlist; struct ref *ref, *next; - int sought_pos; + int i; - sought_pos = 0; + i = 0; for (ref = *refs; ref; ref = next) { int keep = 0; next = ref->next; + if (!memcmp(ref->name, "refs/", 5) && check_refname_format(ref->name + 5, 0)) ; /* trash */ else { - while (sought_pos < sought->nr) { - int cmp = strcmp(ref->name, sought->items[sought_pos].string); + while (i < nr_sought) { + int cmp = strcmp(ref->name, sought[i]->name); if (cmp < 0) break; /* definitely do not have it */ else if (cmp == 0) { keep = 1; /* definitely have it */ - sought->items[sought_pos++].util = "matched"; - break; + sought[i]->matched = 1; } - else - sought_pos++; /* might have it; keep looking */ + i++; } } - if (! keep && args->fetch_all && + if (!keep && args->fetch_all && (!args->depth || prefixcmp(ref->name, "refs/tags/"))) keep = 1; @@ -573,7 +563,6 @@ static void filter_refs(struct fetch_pack_args *args, } } - filter_string_list(sought, 0, non_matching_ref, NULL); *refs = newlist; } @@ -583,7 +572,8 @@ static void mark_alternate_complete(const struct ref *ref, void *unused) } static int everything_local(struct fetch_pack_args *args, - struct ref **refs, struct string_list *sought) + struct ref **refs, + struct ref **sought, int nr_sought) { struct ref *ref; int retval; @@ -634,7 +624,7 @@ static int everything_local(struct fetch_pack_args *args, } } - filter_refs(args, refs, sought); + filter_refs(args, refs, sought, nr_sought); for (retval = 1, ref = *refs; ref ; ref = ref->next) { const unsigned char *remote = ref->old_sha1; @@ -764,10 +754,17 @@ static int get_pack(struct fetch_pack_args *args, return 0; } +static int cmp_ref_by_name(const void *a_, const void *b_) +{ + const struct ref *a = *((const struct ref **)a_); + const struct ref *b = *((const struct ref **)b_); + return strcmp(a->name, b->name); +} + static struct ref *do_fetch_pack(struct fetch_pack_args *args, int fd[2], const struct ref *orig_ref, - struct string_list *sought, + struct ref **sought, int nr_sought, char **pack_lockfile) { struct ref *ref = copy_ref_list(orig_ref); @@ -776,6 +773,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, int agent_len; sort_ref_list(&ref, ref_compare_name); + qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name); if (is_repository_shallow() && !server_supports("shallow")) die("Server does not support shallow clients"); @@ -824,7 +822,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, agent_len, agent_feature); } - if (everything_local(args, &ref, sought)) { + if (everything_local(args, &ref, sought, nr_sought)) { packet_flush(fd[1]); goto all_done; } @@ -887,11 +885,32 @@ static void fetch_pack_setup(void) did_setup = 1; } +static int remove_duplicates_in_refs(struct ref **ref, int nr) +{ + struct string_list names = STRING_LIST_INIT_NODUP; + int src, dst; + + for (src = dst = 0; src < nr; src++) { + struct string_list_item *item; + item = string_list_insert(&names, ref[src]->name); + if (item->util) + continue; /* already have it */ + item->util = ref[src]; + if (src != dst) + ref[dst] = ref[src]; + dst++; + } + for (src = dst; src < nr; src++) + ref[src] = NULL; + string_list_clear(&names, 0); + return dst; +} + struct ref *fetch_pack(struct fetch_pack_args *args, int fd[], struct child_process *conn, const struct ref *ref, const char *dest, - struct string_list *sought, + struct ref **sought, int nr_sought, char **pack_lockfile) { struct stat st; @@ -903,16 +922,14 @@ struct ref *fetch_pack(struct fetch_pack_args *args, st.st_mtime = 0; } - if (sought->nr) { - sort_string_list(sought); - string_list_remove_duplicates(sought, 0); - } + if (nr_sought) + nr_sought = remove_duplicates_in_refs(sought, nr_sought); if (!ref) { packet_flush(fd[1]); die("no matching remote head"); } - ref_cpy = do_fetch_pack(args, fd, ref, sought, pack_lockfile); + ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, pack_lockfile); if (args->depth > 0) { static struct lock_file lock; diff --git a/fetch-pack.h b/fetch-pack.h index cb148719bf..dc5266c970 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -20,17 +20,16 @@ struct fetch_pack_args { }; /* - * sought contains the full names of remote references that should be - * updated from. On return, the names that were found on the remote - * will have been removed from the list. The util members of the - * string_list_items are used internally; they must be NULL on entry - * (and will be NULL on exit). + * sought represents remote references that should be updated from. + * On return, the names that were found on the remote will have been + * marked as such. */ struct ref *fetch_pack(struct fetch_pack_args *args, int fd[], struct child_process *conn, const struct ref *ref, const char *dest, - struct string_list *sought, + struct ref **sought, + int nr_sought, char **pack_lockfile); #endif diff --git a/transport.c b/transport.c index 2673d273ff..64ce6510f1 100644 --- a/transport.c +++ b/transport.c @@ -518,11 +518,9 @@ static int fetch_refs_via_pack(struct transport *transport, int nr_heads, struct ref **to_fetch) { struct git_transport_data *data = transport->data; - struct string_list sought = STRING_LIST_INIT_DUP; const struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; - int i; struct ref *refs_tmp = NULL; memset(&args, 0, sizeof(args)); @@ -536,9 +534,6 @@ static int fetch_refs_via_pack(struct transport *transport, args.no_progress = !transport->progress; args.depth = data->options.depth; - for (i = 0; i < nr_heads; i++) - string_list_append(&sought, to_fetch[i]->name); - if (!data->got_remote_heads) { connect_setup(transport, 0, 0); get_remote_heads(data->fd[0], &refs_tmp, 0, NULL); @@ -547,7 +542,8 @@ static int fetch_refs_via_pack(struct transport *transport, refs = fetch_pack(&args, data->fd, data->conn, refs_tmp ? refs_tmp : transport->remote_refs, - dest, &sought, &transport->pack_lockfile); + dest, to_fetch, nr_heads, + &transport->pack_lockfile); close(data->fd[0]); close(data->fd[1]); if (finish_connect(data->conn)) @@ -557,7 +553,6 @@ static int fetch_refs_via_pack(struct transport *transport, free_refs(refs_tmp); - string_list_clear(&sought, 0); free(dest); return (refs ? 0 : -1); } |