Merge branch 'ew/force-ipv4'
"git fetch" and friends that make network connections can now be told to only use ipv4 (or ipv6). * ew/force-ipv4: connect & http: support -4 and -6 switches for remote operationsmaint
						commit
						e84d5e9fa1
					
				|  | @ -158,3 +158,11 @@ endif::git-pull[] | ||||||
| 	by default when it is attached to a terminal, unless -q | 	by default when it is attached to a terminal, unless -q | ||||||
| 	is specified. This flag forces progress status even if the | 	is specified. This flag forces progress status even if the | ||||||
| 	standard error stream is not directed to a terminal. | 	standard error stream is not directed to a terminal. | ||||||
|  |  | ||||||
|  | -4:: | ||||||
|  | --ipv4:: | ||||||
|  | 	Use IPv4 addresses only, ignoring IPv6 addresses. | ||||||
|  |  | ||||||
|  | -6:: | ||||||
|  | --ipv6:: | ||||||
|  | 	Use IPv6 addresses only, ignoring IPv4 addresses. | ||||||
|  |  | ||||||
|  | @ -277,6 +277,13 @@ origin +master` to force a push to the `master` branch). See the | ||||||
| 	default is --verify, giving the hook a chance to prevent the | 	default is --verify, giving the hook a chance to prevent the | ||||||
| 	push.  With --no-verify, the hook is bypassed completely. | 	push.  With --no-verify, the hook is bypassed completely. | ||||||
|  |  | ||||||
|  | -4:: | ||||||
|  | --ipv4:: | ||||||
|  | 	Use IPv4 addresses only, ignoring IPv6 addresses. | ||||||
|  |  | ||||||
|  | -6:: | ||||||
|  | --ipv6:: | ||||||
|  | 	Use IPv6 addresses only, ignoring IPv4 addresses. | ||||||
|  |  | ||||||
| include::urls-remotes.txt[] | include::urls-remotes.txt[] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -47,6 +47,7 @@ static const char *real_git_dir; | ||||||
| static char *option_upload_pack = "git-upload-pack"; | static char *option_upload_pack = "git-upload-pack"; | ||||||
| static int option_verbosity; | static int option_verbosity; | ||||||
| static int option_progress = -1; | static int option_progress = -1; | ||||||
|  | static enum transport_family family; | ||||||
| static struct string_list option_config; | static struct string_list option_config; | ||||||
| static struct string_list option_reference; | static struct string_list option_reference; | ||||||
| static int option_dissociate; | static int option_dissociate; | ||||||
|  | @ -92,6 +93,10 @@ static struct option builtin_clone_options[] = { | ||||||
| 		   N_("separate git dir from working tree")), | 		   N_("separate git dir from working tree")), | ||||||
| 	OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), | 	OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), | ||||||
| 			N_("set config inside the new repository")), | 			N_("set config inside the new repository")), | ||||||
|  | 	OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), | ||||||
|  | 			TRANSPORT_FAMILY_IPV4), | ||||||
|  | 	OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), | ||||||
|  | 			TRANSPORT_FAMILY_IPV6), | ||||||
| 	OPT_END() | 	OPT_END() | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -970,6 +975,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) | ||||||
| 	remote = remote_get(option_origin); | 	remote = remote_get(option_origin); | ||||||
| 	transport = transport_get(remote, remote->url[0]); | 	transport = transport_get(remote, remote->url[0]); | ||||||
| 	transport_set_verbosity(transport, option_verbosity, option_progress); | 	transport_set_verbosity(transport, option_verbosity, option_progress); | ||||||
|  | 	transport->family = family; | ||||||
|  |  | ||||||
| 	path = get_repo_path(remote->url[0], &is_bundle); | 	path = get_repo_path(remote->url[0], &is_bundle); | ||||||
| 	is_local = option_local != 0 && path && !is_bundle; | 	is_local = option_local != 0 && path && !is_bundle; | ||||||
|  |  | ||||||
|  | @ -38,6 +38,7 @@ static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosit | ||||||
| static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; | static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; | ||||||
| static int tags = TAGS_DEFAULT, unshallow, update_shallow; | static int tags = TAGS_DEFAULT, unshallow, update_shallow; | ||||||
| static int max_children = 1; | static int max_children = 1; | ||||||
|  | static enum transport_family family; | ||||||
| static const char *depth; | static const char *depth; | ||||||
| static const char *upload_pack; | static const char *upload_pack; | ||||||
| static struct strbuf default_rla = STRBUF_INIT; | static struct strbuf default_rla = STRBUF_INIT; | ||||||
|  | @ -127,6 +128,10 @@ static struct option builtin_fetch_options[] = { | ||||||
| 		 N_("accept refs that update .git/shallow")), | 		 N_("accept refs that update .git/shallow")), | ||||||
| 	{ OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"), | 	{ OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"), | ||||||
| 	  N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg }, | 	  N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg }, | ||||||
|  | 	OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), | ||||||
|  | 			TRANSPORT_FAMILY_IPV4), | ||||||
|  | 	OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), | ||||||
|  | 			TRANSPORT_FAMILY_IPV6), | ||||||
| 	OPT_END() | 	OPT_END() | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -864,6 +869,7 @@ static struct transport *prepare_transport(struct remote *remote) | ||||||
| 	struct transport *transport; | 	struct transport *transport; | ||||||
| 	transport = transport_get(remote, NULL); | 	transport = transport_get(remote, NULL); | ||||||
| 	transport_set_verbosity(transport, verbosity, progress); | 	transport_set_verbosity(transport, verbosity, progress); | ||||||
|  | 	transport->family = family; | ||||||
| 	if (upload_pack) | 	if (upload_pack) | ||||||
| 		set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack); | 		set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack); | ||||||
| 	if (keep) | 	if (keep) | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ static const char *receivepack; | ||||||
| static int verbosity; | static int verbosity; | ||||||
| static int progress = -1; | static int progress = -1; | ||||||
| static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; | static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; | ||||||
|  | static enum transport_family family; | ||||||
|  |  | ||||||
| static struct push_cas_option cas; | static struct push_cas_option cas; | ||||||
|  |  | ||||||
|  | @ -346,6 +347,7 @@ static int push_with_options(struct transport *transport, int flags) | ||||||
| 	unsigned int reject_reasons; | 	unsigned int reject_reasons; | ||||||
|  |  | ||||||
| 	transport_set_verbosity(transport, verbosity, progress); | 	transport_set_verbosity(transport, verbosity, progress); | ||||||
|  | 	transport->family = family; | ||||||
|  |  | ||||||
| 	if (receivepack) | 	if (receivepack) | ||||||
| 		transport_set_option(transport, | 		transport_set_option(transport, | ||||||
|  | @ -565,6 +567,10 @@ int cmd_push(int argc, const char **argv, const char *prefix) | ||||||
| 		  0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"), | 		  0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"), | ||||||
| 		  PARSE_OPT_OPTARG, option_parse_push_signed }, | 		  PARSE_OPT_OPTARG, option_parse_push_signed }, | ||||||
| 		OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC), | 		OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC), | ||||||
|  | 		OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), | ||||||
|  | 				TRANSPORT_FAMILY_IPV4), | ||||||
|  | 		OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), | ||||||
|  | 				TRANSPORT_FAMILY_IPV6), | ||||||
| 		OPT_END() | 		OPT_END() | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -357,6 +357,10 @@ static int git_tcp_connect_sock(char *host, int flags) | ||||||
| 		port = "<none>"; | 		port = "<none>"; | ||||||
|  |  | ||||||
| 	memset(&hints, 0, sizeof(hints)); | 	memset(&hints, 0, sizeof(hints)); | ||||||
|  | 	if (flags & CONNECT_IPV4) | ||||||
|  | 		hints.ai_family = AF_INET; | ||||||
|  | 	else if (flags & CONNECT_IPV6) | ||||||
|  | 		hints.ai_family = AF_INET6; | ||||||
| 	hints.ai_socktype = SOCK_STREAM; | 	hints.ai_socktype = SOCK_STREAM; | ||||||
| 	hints.ai_protocol = IPPROTO_TCP; | 	hints.ai_protocol = IPPROTO_TCP; | ||||||
|  |  | ||||||
|  | @ -783,6 +787,10 @@ struct child_process *git_connect(int fd[2], const char *url, | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			argv_array_push(&conn->args, ssh); | 			argv_array_push(&conn->args, ssh); | ||||||
|  | 			if (flags & CONNECT_IPV4) | ||||||
|  | 				argv_array_push(&conn->args, "-4"); | ||||||
|  | 			else if (flags & CONNECT_IPV6) | ||||||
|  | 				argv_array_push(&conn->args, "-6"); | ||||||
| 			if (tortoiseplink) | 			if (tortoiseplink) | ||||||
| 				argv_array_push(&conn->args, "-batch"); | 				argv_array_push(&conn->args, "-batch"); | ||||||
| 			if (port) { | 			if (port) { | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ | ||||||
|  |  | ||||||
| #define CONNECT_VERBOSE       (1u << 0) | #define CONNECT_VERBOSE       (1u << 0) | ||||||
| #define CONNECT_DIAG_URL      (1u << 1) | #define CONNECT_DIAG_URL      (1u << 1) | ||||||
|  | #define CONNECT_IPV4          (1u << 2) | ||||||
|  | #define CONNECT_IPV6          (1u << 3) | ||||||
| extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags); | extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags); | ||||||
| extern int finish_connect(struct child_process *conn); | extern int finish_connect(struct child_process *conn); | ||||||
| extern int git_connection_is_socket(struct child_process *conn); | extern int git_connection_is_socket(struct child_process *conn); | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								http.c
								
								
								
								
							
							
						
						
									
										9
									
								
								http.c
								
								
								
								
							|  | @ -11,6 +11,11 @@ | ||||||
| #include "gettext.h" | #include "gettext.h" | ||||||
| #include "transport.h" | #include "transport.h" | ||||||
|  |  | ||||||
|  | #if LIBCURL_VERSION_NUM >= 0x070a08 | ||||||
|  | long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER; | ||||||
|  | #else | ||||||
|  | long int git_curl_ipresolve; | ||||||
|  | #endif | ||||||
| int active_requests; | int active_requests; | ||||||
| int http_is_verbose; | int http_is_verbose; | ||||||
| size_t http_post_buffer = 16 * LARGE_PACKET_MAX; | size_t http_post_buffer = 16 * LARGE_PACKET_MAX; | ||||||
|  | @ -824,6 +829,10 @@ struct active_request_slot *get_active_slot(void) | ||||||
| 	curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); | 	curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); | ||||||
| 	curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1); | 	curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1); | ||||||
| 	curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL); | 	curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL); | ||||||
|  |  | ||||||
|  | #if LIBCURL_VERSION_NUM >= 0x070a08 | ||||||
|  | 	curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve); | ||||||
|  | #endif | ||||||
| #ifdef LIBCURL_CAN_HANDLE_AUTH_ANY | #ifdef LIBCURL_CAN_HANDLE_AUTH_ANY | ||||||
| 	curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods); | 	curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								http.h
								
								
								
								
							
							
						
						
									
										1
									
								
								http.h
								
								
								
								
							|  | @ -107,6 +107,7 @@ extern void http_init(struct remote *remote, const char *url, | ||||||
| 		      int proactive_auth); | 		      int proactive_auth); | ||||||
| extern void http_cleanup(void); | extern void http_cleanup(void); | ||||||
|  |  | ||||||
|  | extern long int git_curl_ipresolve; | ||||||
| extern int active_requests; | extern int active_requests; | ||||||
| extern int http_is_verbose; | extern int http_is_verbose; | ||||||
| extern size_t http_post_buffer; | extern size_t http_post_buffer; | ||||||
|  |  | ||||||
|  | @ -119,6 +119,19 @@ static int set_option(const char *name, const char *value) | ||||||
| 		else | 		else | ||||||
| 			return -1; | 			return -1; | ||||||
| 		return 0; | 		return 0; | ||||||
|  |  | ||||||
|  | #if LIBCURL_VERSION_NUM >= 0x070a08 | ||||||
|  | 	} else if (!strcmp(name, "family")) { | ||||||
|  | 		if (!strcmp(value, "ipv4")) | ||||||
|  | 			git_curl_ipresolve = CURL_IPRESOLVE_V4; | ||||||
|  | 		else if (!strcmp(value, "ipv6")) | ||||||
|  | 			git_curl_ipresolve = CURL_IPRESOLVE_V6; | ||||||
|  | 		else if (!strcmp(value, "all")) | ||||||
|  | 			git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER; | ||||||
|  | 		else | ||||||
|  | 			return -1; | ||||||
|  | 		return 0; | ||||||
|  | #endif /* LIBCURL_VERSION_NUM >= 0x070a08 */ | ||||||
| 	} else { | 	} else { | ||||||
| 		return 1 /* unsupported */; | 		return 1 /* unsupported */; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -321,6 +321,21 @@ static void standard_options(struct transport *t) | ||||||
| 	if (n >= sizeof(buf)) | 	if (n >= sizeof(buf)) | ||||||
| 		die("impossibly large verbosity value"); | 		die("impossibly large verbosity value"); | ||||||
| 	set_helper_option(t, "verbosity", buf); | 	set_helper_option(t, "verbosity", buf); | ||||||
|  |  | ||||||
|  | 	switch (t->family) { | ||||||
|  | 	case TRANSPORT_FAMILY_ALL: | ||||||
|  | 		/* | ||||||
|  | 		 * this is already the default, | ||||||
|  | 		 * do not break old remote helpers by setting "all" here | ||||||
|  | 		 */ | ||||||
|  | 		break; | ||||||
|  | 	case TRANSPORT_FAMILY_IPV4: | ||||||
|  | 		set_helper_option(t, "family", "ipv4"); | ||||||
|  | 		break; | ||||||
|  | 	case TRANSPORT_FAMILY_IPV6: | ||||||
|  | 		set_helper_option(t, "family", "ipv6"); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static int release_helper(struct transport *transport) | static int release_helper(struct transport *transport) | ||||||
|  |  | ||||||
|  | @ -163,6 +163,12 @@ static int connect_setup(struct transport *transport, int for_push) | ||||||
| 	if (data->conn) | 	if (data->conn) | ||||||
| 		return 0; | 		return 0; | ||||||
|  |  | ||||||
|  | 	switch (transport->family) { | ||||||
|  | 	case TRANSPORT_FAMILY_ALL: break; | ||||||
|  | 	case TRANSPORT_FAMILY_IPV4: flags |= CONNECT_IPV4; break; | ||||||
|  | 	case TRANSPORT_FAMILY_IPV6: flags |= CONNECT_IPV6; break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	data->conn = git_connect(data->fd, transport->url, | 	data->conn = git_connect(data->fd, transport->url, | ||||||
| 				 for_push ? data->options.receivepack : | 				 for_push ? data->options.receivepack : | ||||||
| 				 data->options.uploadpack, | 				 data->options.uploadpack, | ||||||
|  |  | ||||||
|  | @ -18,6 +18,12 @@ struct git_transport_options { | ||||||
| 	struct push_cas_option *cas; | 	struct push_cas_option *cas; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | enum transport_family { | ||||||
|  | 	TRANSPORT_FAMILY_ALL = 0, | ||||||
|  | 	TRANSPORT_FAMILY_IPV4, | ||||||
|  | 	TRANSPORT_FAMILY_IPV6 | ||||||
|  | }; | ||||||
|  |  | ||||||
| struct transport { | struct transport { | ||||||
| 	struct remote *remote; | 	struct remote *remote; | ||||||
| 	const char *url; | 	const char *url; | ||||||
|  | @ -110,6 +116,8 @@ struct transport { | ||||||
| 	 * actually turns out to be smart. | 	 * actually turns out to be smart. | ||||||
| 	 */ | 	 */ | ||||||
| 	struct git_transport_options *smart_options; | 	struct git_transport_options *smart_options; | ||||||
|  |  | ||||||
|  | 	enum transport_family family; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define TRANSPORT_PUSH_ALL 1 | #define TRANSPORT_PUSH_ALL 1 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano