diff options
Diffstat (limited to 'fetch-pack.c')
| -rw-r--r-- | fetch-pack.c | 106 | 
1 files changed, 64 insertions, 42 deletions
| diff --git a/fetch-pack.c b/fetch-pack.c index 48526aa54b..2dabee97b2 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -43,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)  { @@ -60,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); @@ -70,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, @@ -226,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 @@ -263,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; @@ -466,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); @@ -487,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)  { @@ -542,7 +560,8 @@ 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]; @@ -564,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, @@ -599,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) @@ -662,11 +681,10 @@ static int get_pack(struct fetch_pack_args *args,  		    int xd[2], char **pack_lockfile)  {  	struct async demux; -	const char *argv[22]; -	char keep_arg[256]; -	char hdr_arg[256]; -	const char **av, *cmd_name;  	int do_keep = args->keep_pack; +	const char *cmd_name; +	struct pack_header header; +	int pass_header = 0;  	struct child_process cmd = CHILD_PROCESS_INIT;  	int ret; @@ -686,17 +704,11 @@ static int get_pack(struct fetch_pack_args *args,  	else  		demux.out = xd[0]; -	cmd.argv = argv; -	av = argv; -	*hdr_arg = 0;  	if (!args->keep_pack && unpack_limit) { -		struct pack_header header;  		if (read_pack_header(demux.out, &header))  			die("protocol error: bad pack header"); -		snprintf(hdr_arg, sizeof(hdr_arg), -			 "--pack_header=%"PRIu32",%"PRIu32, -			 ntohl(header.hdr_version), ntohl(header.hdr_entries)); +		pass_header = 1;  		if (ntohl(header.hdr_entries) < unpack_limit)  			do_keep = 0;  		else @@ -704,44 +716,49 @@ static int get_pack(struct fetch_pack_args *args,  	}  	if (alternate_shallow_file) { -		*av++ = "--shallow-file"; -		*av++ = alternate_shallow_file; +		argv_array_push(&cmd.args, "--shallow-file"); +		argv_array_push(&cmd.args, alternate_shallow_file);  	}  	if (do_keep) {  		if (pack_lockfile)  			cmd.out = -1; -		*av++ = cmd_name = "index-pack"; -		*av++ = "--stdin"; +		cmd_name = "index-pack"; +		argv_array_push(&cmd.args, cmd_name); +		argv_array_push(&cmd.args, "--stdin");  		if (!args->quiet && !args->no_progress) -			*av++ = "-v"; +			argv_array_push(&cmd.args, "-v");  		if (args->use_thin_pack) -			*av++ = "--fix-thin"; +			argv_array_push(&cmd.args, "--fix-thin");  		if (args->lock_pack || unpack_limit) { -			int s = sprintf(keep_arg, -					"--keep=fetch-pack %"PRIuMAX " on ", (uintmax_t) getpid()); -			if (gethostname(keep_arg + s, sizeof(keep_arg) - s)) -				strcpy(keep_arg + s, "localhost"); -			*av++ = keep_arg; +			char hostname[256]; +			if (gethostname(hostname, sizeof(hostname))) +				xsnprintf(hostname, sizeof(hostname), "localhost"); +			argv_array_pushf(&cmd.args, +					"--keep=fetch-pack %"PRIuMAX " on %s", +					(uintmax_t)getpid(), hostname);  		}  		if (args->check_self_contained_and_connected) -			*av++ = "--check-self-contained-and-connected"; +			argv_array_push(&cmd.args, "--check-self-contained-and-connected");  	}  	else { -		*av++ = cmd_name = "unpack-objects"; +		cmd_name = "unpack-objects"; +		argv_array_push(&cmd.args, cmd_name);  		if (args->quiet || args->no_progress) -			*av++ = "-q"; +			argv_array_push(&cmd.args, "-q");  		args->check_self_contained_and_connected = 0;  	} -	if (*hdr_arg) -		*av++ = hdr_arg; + +	if (pass_header) +		argv_array_pushf(&cmd.args, "--pack_header=%"PRIu32",%"PRIu32, +				 ntohl(header.hdr_version), +				 ntohl(header.hdr_entries));  	if (fetch_fsck_objects >= 0  	    ? fetch_fsck_objects  	    : transfer_fsck_objects >= 0  	    ? transfer_fsck_objects  	    : 0) -		*av++ = "--strict"; -	*av++ = NULL; +		argv_array_push(&cmd.args, "--strict");  	cmd.in = demux.out;  	cmd.git_cmd = 1; @@ -790,7 +807,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) @@ -821,7 +838,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; @@ -924,7 +946,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); | 
