summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-08-27 10:59:51 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2021-08-29 10:39:28 -0400
commit72df17c659619707e4e5f27b2a51db60848a1d04 (patch)
treea89dda4f75833c96669446c94fd7e0ff56f19fff
parent672406773e677e69dba0ccf1c6a116cb2886b60a (diff)
downloadlibgit2-72df17c659619707e4e5f27b2a51db60848a1d04.tar.gz
remote: introduce git_remote_ready_cb
Introduce a new callback that fires when the remote is ready to connect.
-rw-r--r--include/git2/remote.h17
-rw-r--r--src/remote.c15
-rw-r--r--tests/network/remote/remotes.c42
-rw-r--r--tests/online/push_util.h2
4 files changed, 72 insertions, 4 deletions
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 5b67717eb..b75a9911c 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -514,6 +514,18 @@ typedef int GIT_CALLBACK(git_push_update_reference_cb)(const char *refname, cons
typedef int GIT_CALLBACK(git_url_resolve_cb)(git_buf *url_resolved, const char *url, int direction, void *payload);
/**
+ * Callback invoked immediately before we attempt to connect to the
+ * given url. Callers may change the URL before the connection by
+ * calling `git_remote_set_instance_url` in the callback.
+ *
+ * @param remote The remote to be connected
+ * @param direction GIT_DIRECTION_FETCH or GIT_DIRECTION_PUSH
+ * @param payload Payload provided by the caller
+ * @return 0 on success, or an error
+ */
+typedef int GIT_CALLBACK(git_remote_ready_cb)(git_remote *remote, int direction, void *payload);
+
+/**
* The callback settings structure
*
* Set the callbacks to be called by the remote when informing the user
@@ -598,6 +610,11 @@ struct git_remote_callbacks {
git_transport_cb transport;
/**
+ * Callback when the remote is ready to connect.
+ */
+ git_remote_ready_cb remote_ready;
+
+ /**
* This will be passed to each of the callbacks in this struct
* as the last parameter.
*/
diff --git a/src/remote.c b/src/remote.c
index 236f39aba..8050e65f3 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -709,11 +709,19 @@ int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int
GIT_ASSERT_ARG(remote);
GIT_ASSERT_ARG(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
- if (direction == GIT_DIRECTION_FETCH) {
+ if (callbacks && callbacks->remote_ready) {
+ int status = callbacks->remote_ready(remote, direction, callbacks->payload);
+
+ if (status != 0 && status != GIT_PASSTHROUGH) {
+ git_error_set_after_callback_function(status, "git_remote_ready_cb");
+ return status;
+ }
+ }
+
+ if (direction == GIT_DIRECTION_FETCH)
url = remote->url;
- } else if (direction == GIT_DIRECTION_PUSH) {
+ else if (direction == GIT_DIRECTION_PUSH)
url = remote->pushurl ? remote->pushurl : remote->url;
- }
if (!url) {
git_error_set(GIT_ERROR_INVALID,
@@ -722,6 +730,7 @@ int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int
direction == GIT_DIRECTION_FETCH ? "fetch" : "push");
return GIT_EINVALID;
}
+
return resolve_url(url_out, url, direction, callbacks);
}
diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c
index a962d9293..4a9f5ae72 100644
--- a/tests/network/remote/remotes.c
+++ b/tests/network/remote/remotes.c
@@ -56,6 +56,48 @@ void test_network_remote_remotes__parsing(void)
git_buf_dispose(&url);
}
+static int remote_ready_callback(git_remote *remote, int direction, void *payload)
+{
+ if (direction == GIT_DIRECTION_PUSH) {
+ const char *url = git_remote_pushurl(remote);
+
+ cl_assert_equal_p(url, NULL);;
+ cl_assert_equal_s(payload, "payload");
+ return git_remote_set_instance_pushurl(remote, "push_url");
+ }
+
+ if (direction == GIT_DIRECTION_FETCH) {
+ const char *url = git_remote_url(remote);
+
+ cl_assert_equal_s(url, "git://github.com/libgit2/libgit2");
+ cl_assert_equal_s(payload, "payload");
+ return git_remote_set_instance_url(remote, "fetch_url");
+ }
+
+ return -1;
+}
+
+void test_network_remote_remotes__remote_ready(void)
+{
+ git_buf url = GIT_BUF_INIT;
+
+ git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
+ callbacks.remote_ready = remote_ready_callback;
+ callbacks.payload = "payload";
+
+ cl_assert_equal_s(git_remote_name(_remote), "test");
+ cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2");
+ cl_assert(git_remote_pushurl(_remote) == NULL);
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, &callbacks));
+ cl_assert_equal_s(url.ptr, "fetch_url");
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, &callbacks));
+ cl_assert_equal_s(url.ptr, "push_url");
+
+ git_buf_dispose(&url);
+}
+
static int urlresolve_callback(git_buf *url_resolved, const char *url, int direction, void *payload)
{
cl_assert(strcmp(url, "git://github.com/libgit2/libgit2") == 0);
diff --git a/tests/online/push_util.h b/tests/online/push_util.h
index d829bbc4a..5f669feaf 100644
--- a/tests/online/push_util.h
+++ b/tests/online/push_util.h
@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO;
* @param data pointer to a record_callbacks_data instance
*/
#define RECORD_CALLBACKS_INIT(data) \
- { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, NULL, data, NULL }
+ { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, NULL, NULL, data, NULL }
typedef struct {
char *name;