diff options
Diffstat (limited to 'fetch-pack.c')
| -rw-r--r-- | fetch-pack.c | 129 | 
1 files changed, 69 insertions, 60 deletions
| diff --git a/fetch-pack.c b/fetch-pack.c index eeee2bb7e0..820251a8d8 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) @@ -939,7 +948,7 @@ static void update_shallow(struct fetch_pack_args *args,  	if (args->depth > 0 && alternate_shallow_file) {  		if (*alternate_shallow_file == '\0') { /* --unshallow */ -			unlink_or_warn(git_path("shallow")); +			unlink_or_warn(git_path_shallow());  			rollback_lock_file(&shallow_lock);  		} else  			commit_lock_file(&shallow_lock); | 
