diff options
| author | lhchavez <lhchavez@lhchavez.com> | 2022-04-16 08:19:38 -0700 |
|---|---|---|
| committer | lhchavez <lhchavez@lhchavez.com> | 2022-04-16 08:23:22 -0700 |
| commit | 1d88605ca9d51f9e8695030853d5914743fbb091 (patch) | |
| tree | da42e9d207be0f21116c424da6507c337739fc96 | |
| parent | 63970244fb2d49794e7b5d268a2defe4299fd3ad (diff) | |
| download | libgit2-1d88605ca9d51f9e8695030853d5914743fbb091.tar.gz | |
transport: introduce `git_transport_smart_remote_connect_options`
6fc6eeb66c40310086c8f059cae41de69ad4c6da removed
`git_transport_smart_proxy_option`, and there was nothing added to
replace it. That made it hard for custom transports / smart
subtransports to know what remote connect options to use (e.g. proxy
options).
This change introduces `git_transport_smart_remote_connect_options` to
replace it.
| -rw-r--r-- | include/git2/sys/remote.h | 13 | ||||
| -rw-r--r-- | include/git2/sys/transport.h | 18 | ||||
| -rw-r--r-- | src/libgit2/remote.h | 2 | ||||
| -rw-r--r-- | src/libgit2/transports/smart.c | 12 | ||||
| -rw-r--r-- | tests/libgit2/transport/register.c | 145 |
5 files changed, 187 insertions, 3 deletions
diff --git a/include/git2/sys/remote.h b/include/git2/sys/remote.h index dd243ca55..bde1b168c 100644 --- a/include/git2/sys/remote.h +++ b/include/git2/sys/remote.h @@ -8,6 +8,8 @@ #ifndef INCLUDE_sys_git_remote_h #define INCLUDE_sys_git_remote_h +#include "git2/remote.h" + /** * @file git2/sys/remote.h * @brief Low-level remote functionality for custom transports @@ -26,6 +28,17 @@ typedef enum { GIT_REMOTE_CAPABILITY_REACHABLE_OID = (1 << 1), } git_remote_capability_t; +/** + * Disposes libgit2-initialized fields from a git_remote_connect_options. + * + * Note that this does not free the `git_remote_connect_options` itself, just + * the memory pointed to by it. + * + * @param opts The `git_remote_connect_options` struct to dispose. + */ +GIT_EXTERN(void) git_remote_connect_options_dispose( + git_remote_connect_options *opts); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h index f0c2a3eab..8191f1557 100644 --- a/include/git2/sys/transport.h +++ b/include/git2/sys/transport.h @@ -9,10 +9,11 @@ #define INCLUDE_sys_git_transport_h #include "git2/net.h" +#include "git2/proxy.h" +#include "git2/remote.h" +#include "git2/strarray.h" #include "git2/transport.h" #include "git2/types.h" -#include "git2/strarray.h" -#include "git2/proxy.h" /** * @file git2/sys/transport.h @@ -270,6 +271,19 @@ GIT_EXTERN(int) git_transport_smart_credentials(git_credential **out, git_transp */ GIT_EXTERN(int) git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport); +/** + * Get a copy of the remote connect options + * + * All data is copied and must be freed by the caller by calling + * `git_remote_connect_options_dispose`. + * + * @param out options struct to fill + * @param transport the transport to extract the data from. + */ +GIT_EXTERN(int) git_transport_smart_remote_connect_options( + git_remote_connect_options *out, + git_transport *transport); + /* *** End of base transport interface *** *** Begin interface for subtransports for the smart transport *** diff --git a/src/libgit2/remote.h b/src/libgit2/remote.h index ea9c7d17f..41ee58e0f 100644 --- a/src/libgit2/remote.h +++ b/src/libgit2/remote.h @@ -11,6 +11,7 @@ #include "git2/remote.h" #include "git2/transport.h" +#include "git2/sys/remote.h" #include "git2/sys/transport.h" #include "refspec.h" @@ -53,7 +54,6 @@ int git_remote_connect_options_normalize( git_remote_connect_options *dst, git_repository *repo, const git_remote_connect_options *src); -void git_remote_connect_options_dispose(git_remote_connect_options *opts); int git_remote_capabilities(unsigned int *out, git_remote *remote); diff --git a/src/libgit2/transports/smart.c b/src/libgit2/transports/smart.c index 801fcbe53..264f21341 100644 --- a/src/libgit2/transports/smart.c +++ b/src/libgit2/transports/smart.c @@ -425,6 +425,18 @@ int git_transport_smart_credentials(git_credential **out, git_transport *transpo return connect_opts->callbacks.credentials(out, t->url, user, methods, connect_opts->callbacks.payload); } +int git_transport_smart_remote_connect_options( + git_remote_connect_options *out, + git_transport *transport) +{ + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); + + GIT_ASSERT_ARG(out); + GIT_ASSERT_ARG(transport); + + return git_remote_connect_options_dup(out, &t->connect_opts); +} + int git_transport_smart(git_transport **out, git_remote *owner, void *param) { transport_smart *t; diff --git a/tests/libgit2/transport/register.c b/tests/libgit2/transport/register.c index 88ba247de..216f11e82 100644 --- a/tests/libgit2/transport/register.c +++ b/tests/libgit2/transport/register.c @@ -1,6 +1,8 @@ #include "clar_libgit2.h" +#include "git2/sys/remote.h" #include "git2/sys/transport.h" +static const char *proxy_url = "https://proxy"; static git_transport _transport = GIT_TRANSPORT_INIT; static int dummy_transport(git_transport **transport, git_remote *owner, void *param) @@ -77,3 +79,146 @@ void test_transport_register__custom_transport_ssh(void) #endif } } + +static int custom_subtransport_stream__read( + git_smart_subtransport_stream *stream, + char *buffer, + size_t buf_size, + size_t *bytes_read) +{ + GIT_UNUSED(stream); + GIT_UNUSED(buffer); + GIT_UNUSED(buf_size); + + *bytes_read = 0; + + git_error_set_str(42, "unimplemented"); + return GIT_EUSER; +} + +static int custom_subtransport_stream__write( + git_smart_subtransport_stream *stream, + const char *buffer, + size_t len) +{ + GIT_UNUSED(stream); + GIT_UNUSED(buffer); + GIT_UNUSED(len); + + git_error_set_str(42, "unimplemented"); + return GIT_EUSER; +} + +static void custom_subtransport_stream__free( + git_smart_subtransport_stream *stream) +{ + git__free(stream); +} + +struct custom_subtransport { + git_smart_subtransport subtransport; + git_transport *owner; + int *called; +}; + +static int custom_subtransport__action( + git_smart_subtransport_stream **out, + git_smart_subtransport *transport, + const char *url, + git_smart_service_t action) +{ + struct custom_subtransport *t = (struct custom_subtransport *)transport; + git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT; + int ret; + + GIT_UNUSED(url); + GIT_UNUSED(action); + + ret = git_transport_smart_remote_connect_options(&opts, t->owner); + + /* increase the counter once if this function was called at all and once more if the URL matches. */ + (*t->called)++; + if (strcmp(proxy_url, opts.proxy_opts.url) == 0) + (*t->called)++; + + git_remote_connect_options_dispose(&opts); + + *out = git__calloc(1, sizeof(git_smart_subtransport_stream)); + (*out)->subtransport = transport; + (*out)->read = custom_subtransport_stream__read; + (*out)->write = custom_subtransport_stream__write; + (*out)->free = custom_subtransport_stream__free; + + return ret; +} + +static int custom_subtransport__close(git_smart_subtransport *transport) +{ + GIT_UNUSED(transport); + + return 0; +} + +static void custom_subtransport__free(git_smart_subtransport *transport) +{ + GIT_UNUSED(transport); + + git__free(transport); +} + +static int custom_transport_callback(git_smart_subtransport **out, git_transport *owner, void *param) +{ + struct custom_subtransport *subtransport = git__calloc(1, sizeof(struct custom_subtransport)); + subtransport->called = (int *)param; + subtransport->owner = owner; + subtransport->subtransport.action = custom_subtransport__action; + subtransport->subtransport.close = custom_subtransport__close; + subtransport->subtransport.free = custom_subtransport__free; + + *out = &subtransport->subtransport; + + return 0; +} + + +static int custom_transport(git_transport **out, git_remote *owner, void *param) +{ + struct git_smart_subtransport_definition definition; + definition.callback = custom_transport_callback; + definition.rpc = false; + definition.param = param; + return git_transport_smart(out, owner, &definition); +} + +void test_transport_register__custom_transport_callbacks(void) +{ + git_transport *transport; + int called = 0; + const char *url = "custom://somepath"; + git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT; + git_repository *repo; + git_remote *remote; + + cl_git_pass(git_repository_init(&repo, "./transport", 0)); + cl_git_pass(git_remote_create(&remote, repo, "test", + cl_fixture("testrepo.git"))); + + cl_git_pass(git_transport_register("custom", custom_transport, &called)); + + cl_git_pass(git_transport_new(&transport, remote, url)); + + opts.follow_redirects = GIT_REMOTE_REDIRECT_NONE; + opts.proxy_opts.url = proxy_url; + + /* This is expected to fail, since the subtransport_stream is not implemented */ + transport->connect(transport, url, GIT_SERVICE_UPLOADPACK_LS, &opts); + /* the counter is increased twice if everything goes as planned */ + cl_assert_equal_i(2, called); + cl_git_pass(transport->close(transport)); + transport->free(transport); + + cl_git_pass(git_transport_unregister("custom")); + git_remote_free(remote); + git_repository_free(repo); + cl_fixture_cleanup("testrepo.git"); +} |
