diff options
Diffstat (limited to 'fetch-pack.c')
-rw-r--r-- | fetch-pack.c | 127 |
1 files changed, 68 insertions, 59 deletions
diff --git a/fetch-pack.c b/fetch-pack.c index eeee2bb7e0..a136772152 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "lockfile.h" #include "refs.h" #include "pkt-line.h" #include "commit.h" @@ -42,7 +43,12 @@ static int marked; #define MAX_IN_VAIN 256 static struct prio_queue rev_list = { compare_commits_by_commit_date }; -static int non_common_revs, multi_ack, use_sideband, allow_tip_sha1_in_want; +static int non_common_revs, multi_ack, use_sideband; +/* Allow specifying sha1 if it is a ref tip. */ +#define ALLOW_TIP_SHA1 01 +/* Allow request of a sha1 if it is reachable from a ref (possibly hidden ref). */ +#define ALLOW_REACHABLE_SHA1 02 +static unsigned int allow_unadvertised_object_request; static void rev_list_push(struct commit *commit, int mark) { @@ -59,7 +65,7 @@ static void rev_list_push(struct commit *commit, int mark) } } -static int rev_list_insert_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data) +static int rev_list_insert_ref(const char *refname, const unsigned char *sha1) { struct object *o = deref_tag(parse_object(sha1), refname, 0); @@ -69,9 +75,16 @@ static int rev_list_insert_ref(const char *refname, const unsigned char *sha1, i return 0; } -static int clear_marks(const char *refname, const unsigned char *sha1, int flag, void *cb_data) +static int rev_list_insert_ref_oid(const char *refname, const struct object_id *oid, + int flag, void *cb_data) { - struct object *o = deref_tag(parse_object(sha1), refname, 0); + return rev_list_insert_ref(refname, oid->hash); +} + +static int clear_marks(const char *refname, const struct object_id *oid, + int flag, void *cb_data) +{ + struct object *o = deref_tag(parse_object(oid->hash), refname, 0); if (o && o->type == OBJ_COMMIT) clear_commit_marks((struct commit *)o, @@ -189,20 +202,23 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1) { int len; char *line = packet_read_line(fd, &len); + const char *arg; if (!len) die("git fetch-pack: expected ACK/NAK, got EOF"); if (!strcmp(line, "NAK")) return NAK; - if (starts_with(line, "ACK ")) { - if (!get_sha1_hex(line+4, result_sha1)) { - if (len < 45) + if (skip_prefix(line, "ACK ", &arg)) { + if (!get_sha1_hex(arg, result_sha1)) { + arg += 40; + len -= arg - line; + if (len < 1) return ACK; - if (strstr(line+45, "continue")) + if (strstr(arg, "continue")) return ACK_continue; - if (strstr(line+45, "common")) + if (strstr(arg, "common")) return ACK_common; - if (strstr(line+45, "ready")) + if (strstr(arg, "ready")) return ACK_ready; return ACK; } @@ -222,7 +238,7 @@ static void send_request(struct fetch_pack_args *args, static void insert_one_alternate_ref(const struct ref *ref, void *unused) { - rev_list_insert_ref(NULL, ref->old_sha1, 0, NULL); + rev_list_insert_ref(NULL, ref->old_sha1); } #define INITIAL_FLUSH 16 @@ -259,7 +275,7 @@ static int find_common(struct fetch_pack_args *args, for_each_ref(clear_marks, NULL); marked = 1; - for_each_ref(rev_list_insert_ref, NULL); + for_each_ref(rev_list_insert_ref_oid, NULL); for_each_alternate_ref(insert_one_alternate_ref, NULL); fetching = 0; @@ -319,18 +335,19 @@ static int find_common(struct fetch_pack_args *args, if (args->depth > 0) { char *line; + const char *arg; unsigned char sha1[20]; send_request(args, fd[1], &req_buf); while ((line = packet_read_line(fd[0], NULL))) { - if (starts_with(line, "shallow ")) { - if (get_sha1_hex(line + 8, sha1)) + if (skip_prefix(line, "shallow ", &arg)) { + if (get_sha1_hex(arg, sha1)) die("invalid shallow line: %s", line); register_shallow(sha1); continue; } - if (starts_with(line, "unshallow ")) { - if (get_sha1_hex(line + 10, sha1)) + if (skip_prefix(line, "unshallow ", &arg)) { + if (get_sha1_hex(arg, sha1)) die("invalid unshallow line: %s", line); if (!lookup_object(sha1)) die("object not found: %s", line); @@ -461,7 +478,7 @@ done: static struct commit_list *complete; -static int mark_complete(const char *refname, const unsigned char *sha1, int flag, void *cb_data) +static int mark_complete(const unsigned char *sha1) { struct object *o = parse_object(sha1); @@ -482,6 +499,12 @@ static int mark_complete(const char *refname, const unsigned char *sha1, int fla return 0; } +static int mark_complete_oid(const char *refname, const struct object_id *oid, + int flag, void *cb_data) +{ + return mark_complete(oid->hash); +} + static void mark_recent_complete_commits(struct fetch_pack_args *args, unsigned long cutoff) { @@ -507,7 +530,7 @@ static void filter_refs(struct fetch_pack_args *args, int keep = 0; next = ref->next; - if (!memcmp(ref->name, "refs/", 5) && + if (starts_with(ref->name, "refs/") && check_refname_format(ref->name, 0)) ; /* trash */ else { @@ -537,18 +560,22 @@ static void filter_refs(struct fetch_pack_args *args, } /* Append unmatched requests to the list */ - if (allow_tip_sha1_in_want) { + if ((allow_unadvertised_object_request & + (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) { for (i = 0; i < nr_sought; i++) { + unsigned char sha1[20]; + ref = sought[i]; if (ref->matched) continue; - if (get_sha1_hex(ref->name, ref->old_sha1)) + if (get_sha1_hex(ref->name, sha1) || + ref->name[40] != '\0' || + hashcmp(sha1, ref->old_sha1)) continue; ref->matched = 1; - *newtail = ref; - ref->next = NULL; - newtail = &ref->next; + *newtail = copy_ref(ref); + newtail = &(*newtail)->next; } } *refs = newlist; @@ -556,7 +583,7 @@ static void filter_refs(struct fetch_pack_args *args, static void mark_alternate_complete(const struct ref *ref, void *unused) { - mark_complete(NULL, ref->old_sha1, 0, NULL); + mark_complete(ref->old_sha1); } static int everything_local(struct fetch_pack_args *args, @@ -591,7 +618,7 @@ static int everything_local(struct fetch_pack_args *args, } if (!args->depth) { - for_each_ref(mark_complete, NULL); + for_each_ref(mark_complete_oid, NULL); for_each_alternate_ref(mark_alternate_complete, NULL); commit_list_sort_by_date(&complete); if (cutoff) @@ -620,7 +647,6 @@ static int everything_local(struct fetch_pack_args *args, for (retval = 1, ref = *refs; ref ; ref = ref->next) { const unsigned char *remote = ref->old_sha1; - unsigned char local[20]; struct object *o; o = lookup_object(remote); @@ -633,8 +659,6 @@ static int everything_local(struct fetch_pack_args *args, ref->name); continue; } - - hashcpy(ref->new_sha1, local); if (!args->verbose) continue; fprintf(stderr, @@ -662,7 +686,7 @@ static int get_pack(struct fetch_pack_args *args, char hdr_arg[256]; const char **av, *cmd_name; int do_keep = args->keep_pack; - struct child_process cmd; + struct child_process cmd = CHILD_PROCESS_INIT; int ret; memset(&demux, 0, sizeof(demux)); @@ -681,7 +705,6 @@ static int get_pack(struct fetch_pack_args *args, else demux.out = xd[0]; - memset(&cmd, 0, sizeof(cmd)); cmd.argv = argv; av = argv; *hdr_arg = 0; @@ -786,7 +809,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, sort_ref_list(&ref, ref_compare_name); qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name); - if (is_repository_shallow() && !server_supports("shallow")) + if ((args->depth > 0 || is_repository_shallow()) && !server_supports("shallow")) die("Server does not support shallow clients"); if (server_supports("multi_ack_detailed")) { if (args->verbose) @@ -817,7 +840,12 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, if (server_supports("allow-tip-sha1-in-want")) { if (args->verbose) fprintf(stderr, "Server supports allow-tip-sha1-in-want\n"); - allow_tip_sha1_in_want = 1; + allow_unadvertised_object_request |= ALLOW_TIP_SHA1; + } + if (server_supports("allow-reachable-sha1-in-want")) { + if (args->verbose) + fprintf(stderr, "Server supports allow-reachable-sha1-in-want\n"); + allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1; } if (!server_supports("thin-pack")) args->use_thin_pack = 0; @@ -865,34 +893,15 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, return ref; } -static int fetch_pack_config(const char *var, const char *value, void *cb) +static void fetch_pack_config(void) { - if (strcmp(var, "fetch.unpacklimit") == 0) { - fetch_unpack_limit = git_config_int(var, value); - return 0; - } - - if (strcmp(var, "transfer.unpacklimit") == 0) { - transfer_unpack_limit = git_config_int(var, value); - return 0; - } - - if (strcmp(var, "repack.usedeltabaseoffset") == 0) { - prefer_ofs_delta = git_config_bool(var, value); - return 0; - } - - if (!strcmp(var, "fetch.fsckobjects")) { - fetch_fsck_objects = git_config_bool(var, value); - return 0; - } - - if (!strcmp(var, "transfer.fsckobjects")) { - transfer_fsck_objects = git_config_bool(var, value); - return 0; - } + git_config_get_int("fetch.unpacklimit", &fetch_unpack_limit); + git_config_get_int("transfer.unpacklimit", &transfer_unpack_limit); + git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta); + git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects); + git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects); - return git_default_config(var, value, cb); + git_config(git_default_config, NULL); } static void fetch_pack_setup(void) @@ -900,7 +909,7 @@ static void fetch_pack_setup(void) static int did_setup; if (did_setup) return; - git_config(fetch_pack_config, NULL); + fetch_pack_config(); if (0 <= transfer_unpack_limit) unpack_limit = transfer_unpack_limit; else if (0 <= fetch_unpack_limit) |