Commit 1c176883880c4f487597074c70f9bb6f96198737

Etienne Samson 2018-09-07T10:36:15

remote: store the connection data in a private struct This makes it easier to pass connection-related options around (proxy & custom headers for now). This fixes a bug in git_push_finish, which didn't reuse the provided proxy if the connection closed between the call to `git_remote_push` and the finish step.

diff --git a/src/push.c b/src/push.c
index 88b74b5..ea12210 100644
--- a/src/push.c
+++ b/src/push.c
@@ -73,7 +73,8 @@ int git_push_set_options(git_push *push, const git_push_options *opts)
 	GITERR_CHECK_VERSION(opts, GIT_PUSH_OPTIONS_VERSION, "git_push_options");
 
 	push->pb_parallelism = opts->pb_parallelism;
-	push->custom_headers = &opts->custom_headers;
+	push->connection.custom_headers = &opts->custom_headers;
+	push->connection.proxy = &opts->proxy_opts;
 
 	return 0;
 }
@@ -475,7 +476,7 @@ int git_push_finish(git_push *push, const git_remote_callbacks *callbacks)
 	int error;
 
 	if (!git_remote_connected(push->remote) &&
-	    (error = git_remote_connect(push->remote, GIT_DIRECTION_PUSH, callbacks, NULL, push->custom_headers)) < 0)
+	    (error = git_remote__connect(push->remote, GIT_DIRECTION_PUSH, callbacks, &push->connection)) < 0)
 		return error;
 
 	if ((error = filter_refs(push->remote)) < 0 ||
diff --git a/src/push.h b/src/push.h
index 31ac436..8675639 100644
--- a/src/push.h
+++ b/src/push.h
@@ -11,6 +11,7 @@
 
 #include "git2.h"
 #include "refspec.h"
+#include "remote.h"
 
 typedef struct push_spec {
 	struct git_refspec refspec;
@@ -40,7 +41,7 @@ struct git_push {
 
 	/* options */
 	unsigned pb_parallelism;
-	const git_strarray *custom_headers;
+	git_remote_connection_opts connection;
 };
 
 /**
diff --git a/src/remote.c b/src/remote.c
index 9c0e88a..06d86c1 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -657,7 +657,7 @@ static int set_transport_custom_headers(git_transport *t, const git_strarray *cu
 	return t->set_custom_headers(t, custom_headers);
 }
 
-int git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_proxy_options *proxy, const git_strarray *custom_headers)
+int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn)
 {
 	git_transport *t;
 	const char *url;
@@ -676,8 +676,8 @@ int git_remote_connect(git_remote *remote, git_direction direction, const git_re
 		payload     = callbacks->payload;
 	}
 
-	if (proxy)
-		GITERR_CHECK_VERSION(proxy, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
+	if (conn->proxy)
+		GITERR_CHECK_VERSION(conn->proxy, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
 
 	t = remote->transport;
 
@@ -701,11 +701,11 @@ int git_remote_connect(git_remote *remote, git_direction direction, const git_re
 	if (!t && (error = git_transport_new(&t, remote, url)) < 0)
 		return error;
 
-	if ((error = set_transport_custom_headers(t, custom_headers)) != 0)
+	if ((error = set_transport_custom_headers(t, conn->custom_headers)) != 0)
 		goto on_error;
 
 	if ((error = set_transport_callbacks(t, callbacks)) < 0 ||
-	    (error = t->connect(t, url, credentials, payload, proxy, direction, flags)) != 0)
+	    (error = t->connect(t, url, credentials, payload, conn->proxy, direction, flags)) != 0)
 		goto on_error;
 
 	remote->transport = t;
@@ -721,6 +721,16 @@ on_error:
 	return error;
 }
 
+int git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_proxy_options *proxy, const git_strarray *custom_headers)
+{
+	git_remote_connection_opts conn;
+
+	conn.proxy = proxy;
+	conn.custom_headers = custom_headers;
+
+	return git_remote__connect(remote, direction, callbacks, &conn);
+}
+
 int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote)
 {
 	assert(remote);
@@ -949,21 +959,20 @@ int git_remote_fetch(
 	bool prune = false;
 	git_buf reflog_msg_buf = GIT_BUF_INIT;
 	const git_remote_callbacks *cbs = NULL;
-	const git_strarray *custom_headers = NULL;
-	const git_proxy_options *proxy = NULL;
+	git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
 
 	if (opts) {
 		GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
 		cbs = &opts->callbacks;
-		custom_headers = &opts->custom_headers;
+		conn.custom_headers = &opts->custom_headers;
 		update_fetchhead = opts->update_fetchhead;
 		tagopt = opts->download_tags;
 		GITERR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
-		proxy = &opts->proxy_opts;
+		conn.proxy = &opts->proxy_opts;
 	}
 
 	/* Connect and download everything */
-	if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs, proxy, custom_headers)) != 0)
+	if ((error = git_remote__connect(remote, GIT_DIRECTION_FETCH, cbs, &conn)) != 0)
 		return error;
 
 	error = git_remote_download(remote, refspecs, opts);
@@ -2373,8 +2382,7 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
 	git_push *push;
 	git_refspec *spec;
 	const git_remote_callbacks *cbs = NULL;
-	const git_strarray *custom_headers = NULL;
-	const git_proxy_options *proxy = NULL;
+	git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
 
 	assert(remote);
 
@@ -2385,12 +2393,12 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
 
 	if (opts) {
 		cbs = &opts->callbacks;
-		custom_headers = &opts->custom_headers;
-		proxy = &opts->proxy_opts;
+		conn.custom_headers = &opts->custom_headers;
+		conn.proxy = &opts->proxy_opts;
 	}
 
 	if (!git_remote_connected(remote) &&
-	    (error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
+	    (error = git_remote__connect(remote, GIT_DIRECTION_PUSH, cbs, &conn)) < 0)
 		goto cleanup;
 
 	free_refspecs(&remote->active_refspecs);
diff --git a/src/remote.h b/src/remote.h
index a94481f..62bd1d2 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -36,6 +36,15 @@ struct git_remote {
 	int passed_refspecs;
 };
 
+typedef struct git_remote_connection_opts {
+	const git_strarray *custom_headers;
+	const git_proxy_options *proxy;
+} git_remote_connection_opts;
+
+#define GIT_REMOTE_CONNECTION_OPTIONS_INIT { NULL, NULL }
+
+int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn);
+
 const char* git_remote__urlfordirection(struct git_remote *remote, int direction);
 int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url);