Merge branch 'mm/fetch-show-error-message-on-unadvertised-object'
"git fetch" that requests a commit by object name, when the other side does not allow such an request, failed without much explanation. * mm/fetch-show-error-message-on-unadvertised-object: fetch-pack: add specific error for fetching an unadvertised object fetch_refs_via_pack: call report_unmatched_refs fetch-pack: move code to report unmatched refs to a functionmaint
						commit
						07198afbd1
					
				|  | @ -219,12 +219,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) | ||||||
| 	 * remote no-such-ref' would silently succeed without issuing | 	 * remote no-such-ref' would silently succeed without issuing | ||||||
| 	 * an error. | 	 * an error. | ||||||
| 	 */ | 	 */ | ||||||
| 	for (i = 0; i < nr_sought; i++) { | 	ret |= report_unmatched_refs(sought, nr_sought); | ||||||
| 		if (!sought[i] || sought[i]->matched) |  | ||||||
| 			continue; |  | ||||||
| 		error("no such remote ref %s", sought[i]->name); |  | ||||||
| 		ret = 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	while (ref) { | 	while (ref) { | ||||||
| 		printf("%s %s\n", | 		printf("%s %s\n", | ||||||
|  |  | ||||||
							
								
								
									
										35
									
								
								fetch-pack.c
								
								
								
								
							
							
						
						
									
										35
									
								
								fetch-pack.c
								
								
								
								
							|  | @ -614,7 +614,7 @@ static void filter_refs(struct fetch_pack_args *args, | ||||||
| 					break; /* definitely do not have it */ | 					break; /* definitely do not have it */ | ||||||
| 				else if (cmp == 0) { | 				else if (cmp == 0) { | ||||||
| 					keep = 1; /* definitely have it */ | 					keep = 1; /* definitely have it */ | ||||||
| 					sought[i]->matched = 1; | 					sought[i]->match_status = REF_MATCHED; | ||||||
| 				} | 				} | ||||||
| 				i++; | 				i++; | ||||||
| 			} | 			} | ||||||
|  | @ -634,22 +634,24 @@ static void filter_refs(struct fetch_pack_args *args, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Append unmatched requests to the list */ | 	/* Append unmatched requests to the list */ | ||||||
| 	if ((allow_unadvertised_object_request & |  | ||||||
| 	    (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) { |  | ||||||
| 	for (i = 0; i < nr_sought; i++) { | 	for (i = 0; i < nr_sought; i++) { | ||||||
| 		unsigned char sha1[20]; | 		unsigned char sha1[20]; | ||||||
|  |  | ||||||
| 		ref = sought[i]; | 		ref = sought[i]; | ||||||
| 			if (ref->matched) | 		if (ref->match_status != REF_NOT_MATCHED) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (get_sha1_hex(ref->name, sha1) || | 		if (get_sha1_hex(ref->name, sha1) || | ||||||
| 		    ref->name[40] != '\0' || | 		    ref->name[40] != '\0' || | ||||||
| 		    hashcmp(sha1, ref->old_oid.hash)) | 		    hashcmp(sha1, ref->old_oid.hash)) | ||||||
| 			continue; | 			continue; | ||||||
|  |  | ||||||
| 			ref->matched = 1; | 		if ((allow_unadvertised_object_request & | ||||||
|  | 		    (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) { | ||||||
|  | 			ref->match_status = REF_MATCHED; | ||||||
| 			*newtail = copy_ref(ref); | 			*newtail = copy_ref(ref); | ||||||
| 			newtail = &(*newtail)->next; | 			newtail = &(*newtail)->next; | ||||||
|  | 		} else { | ||||||
|  | 			ref->match_status = REF_UNADVERTISED_NOT_ALLOWED; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	*refs = newlist; | 	*refs = newlist; | ||||||
|  | @ -1130,3 +1132,26 @@ struct ref *fetch_pack(struct fetch_pack_args *args, | ||||||
| 	clear_shallow_info(&si); | 	clear_shallow_info(&si); | ||||||
| 	return ref_cpy; | 	return ref_cpy; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int report_unmatched_refs(struct ref **sought, int nr_sought) | ||||||
|  | { | ||||||
|  | 	int i, ret = 0; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < nr_sought; i++) { | ||||||
|  | 		if (!sought[i]) | ||||||
|  | 			continue; | ||||||
|  | 		switch (sought[i]->match_status) { | ||||||
|  | 		case REF_MATCHED: | ||||||
|  | 			continue; | ||||||
|  | 		case REF_NOT_MATCHED: | ||||||
|  | 			error(_("no such remote ref %s"), sought[i]->name); | ||||||
|  | 			break; | ||||||
|  | 		case REF_UNADVERTISED_NOT_ALLOWED: | ||||||
|  | 			error(_("Server does not allow request for unadvertised object %s"), | ||||||
|  | 			      sought[i]->name); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		ret = 1; | ||||||
|  | 	} | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -45,4 +45,10 @@ struct ref *fetch_pack(struct fetch_pack_args *args, | ||||||
| 		       struct sha1_array *shallow, | 		       struct sha1_array *shallow, | ||||||
| 		       char **pack_lockfile); | 		       char **pack_lockfile); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Print an appropriate error message for each sought ref that wasn't | ||||||
|  |  * matched.  Return 0 if all sought refs were matched, otherwise 1. | ||||||
|  |  */ | ||||||
|  | int report_unmatched_refs(struct ref **sought, int nr_sought); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								remote.h
								
								
								
								
							
							
						
						
									
										9
									
								
								remote.h
								
								
								
								
							|  | @ -89,8 +89,13 @@ struct ref { | ||||||
| 		force:1, | 		force:1, | ||||||
| 		forced_update:1, | 		forced_update:1, | ||||||
| 		expect_old_sha1:1, | 		expect_old_sha1:1, | ||||||
| 		deletion:1, | 		deletion:1; | ||||||
| 		matched:1; |  | ||||||
|  | 	enum { | ||||||
|  | 		REF_NOT_MATCHED = 0, /* initial value */ | ||||||
|  | 		REF_MATCHED, | ||||||
|  | 		REF_UNADVERTISED_NOT_ALLOWED | ||||||
|  | 	} match_status; | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * Order is important here, as we write to FETCH_HEAD | 	 * Order is important here, as we write to FETCH_HEAD | ||||||
|  |  | ||||||
|  | @ -484,7 +484,7 @@ test_expect_success 'test lonely missing ref' ' | ||||||
| 		cd client && | 		cd client && | ||||||
| 		test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy | 		test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy | ||||||
| 	) >/dev/null 2>error-m && | 	) >/dev/null 2>error-m && | ||||||
| 	test_cmp expect-error error-m | 	test_i18ncmp expect-error error-m | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_success 'test missing ref after existing' ' | test_expect_success 'test missing ref after existing' ' | ||||||
|  | @ -492,7 +492,7 @@ test_expect_success 'test missing ref after existing' ' | ||||||
| 		cd client && | 		cd client && | ||||||
| 		test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy | 		test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy | ||||||
| 	) >/dev/null 2>error-em && | 	) >/dev/null 2>error-em && | ||||||
| 	test_cmp expect-error error-em | 	test_i18ncmp expect-error error-em | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_success 'test missing ref before existing' ' | test_expect_success 'test missing ref before existing' ' | ||||||
|  | @ -500,7 +500,7 @@ test_expect_success 'test missing ref before existing' ' | ||||||
| 		cd client && | 		cd client && | ||||||
| 		test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A | 		test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A | ||||||
| 	) >/dev/null 2>error-me && | 	) >/dev/null 2>error-me && | ||||||
| 	test_cmp expect-error error-me | 	test_i18ncmp expect-error error-me | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_success 'test --all, --depth, and explicit head' ' | test_expect_success 'test --all, --depth, and explicit head' ' | ||||||
|  |  | ||||||
|  | @ -1098,7 +1098,8 @@ test_expect_success 'fetch exact SHA1' ' | ||||||
| 		test_must_fail git cat-file -t $the_commit && | 		test_must_fail git cat-file -t $the_commit && | ||||||
|  |  | ||||||
| 		# fetching the hidden object should fail by default | 		# fetching the hidden object should fail by default | ||||||
| 		test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy && | 		test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err && | ||||||
|  | 		test_i18ngrep "Server does not allow request for unadvertised object" err && | ||||||
| 		test_must_fail git rev-parse --verify refs/heads/copy && | 		test_must_fail git rev-parse --verify refs/heads/copy && | ||||||
|  |  | ||||||
| 		# the server side can allow it to succeed | 		# the server side can allow it to succeed | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								transport.c
								
								
								
								
							
							
						
						
									
										14
									
								
								transport.c
								
								
								
								
							|  | @ -204,6 +204,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus | ||||||
| static int fetch_refs_via_pack(struct transport *transport, | static int fetch_refs_via_pack(struct transport *transport, | ||||||
| 			       int nr_heads, struct ref **to_fetch) | 			       int nr_heads, struct ref **to_fetch) | ||||||
| { | { | ||||||
|  | 	int ret = 0; | ||||||
| 	struct git_transport_data *data = transport->data; | 	struct git_transport_data *data = transport->data; | ||||||
| 	struct ref *refs; | 	struct ref *refs; | ||||||
| 	char *dest = xstrdup(transport->url); | 	char *dest = xstrdup(transport->url); | ||||||
|  | @ -241,19 +242,22 @@ static int fetch_refs_via_pack(struct transport *transport, | ||||||
| 			  &transport->pack_lockfile); | 			  &transport->pack_lockfile); | ||||||
| 	close(data->fd[0]); | 	close(data->fd[0]); | ||||||
| 	close(data->fd[1]); | 	close(data->fd[1]); | ||||||
| 	if (finish_connect(data->conn)) { | 	if (finish_connect(data->conn)) | ||||||
| 		free_refs(refs); | 		ret = -1; | ||||||
| 		refs = NULL; |  | ||||||
| 	} |  | ||||||
| 	data->conn = NULL; | 	data->conn = NULL; | ||||||
| 	data->got_remote_heads = 0; | 	data->got_remote_heads = 0; | ||||||
| 	data->options.self_contained_and_connected = | 	data->options.self_contained_and_connected = | ||||||
| 		args.self_contained_and_connected; | 		args.self_contained_and_connected; | ||||||
|  |  | ||||||
|  | 	if (refs == NULL) | ||||||
|  | 		ret = -1; | ||||||
|  | 	if (report_unmatched_refs(to_fetch, nr_heads)) | ||||||
|  | 		ret = -1; | ||||||
|  |  | ||||||
| 	free_refs(refs_tmp); | 	free_refs(refs_tmp); | ||||||
| 	free_refs(refs); | 	free_refs(refs); | ||||||
| 	free(dest); | 	free(dest); | ||||||
| 	return (refs ? 0 : -1); | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int push_had_errors(struct ref *ref) | static int push_had_errors(struct ref *ref) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano