diff options
author | Edward Thomson <ethomson@microsoft.com> | 2014-07-09 17:58:39 -0400 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2014-08-14 08:52:20 -0500 |
commit | c180c06586050a33f6e8a6d25cc30b7bcbef702d (patch) | |
tree | b05d0f67ad9c3320bd7c3dd42a4b53334119619b /src | |
parent | e62f96dea5a46098cbca5a287f29ca811003bd68 (diff) | |
download | libgit2-c180c06586050a33f6e8a6d25cc30b7bcbef702d.tar.gz |
Custom transport: minor cleanups
* Move the transport registration mechanisms into a new header under
'sys/' because this is advanced stuff.
* Remove the 'priority' argument from the registration as it adds
unnecessary complexity. (Since transports cannot decline to operate,
only the highest priority transport is ever executed.) Users who
require per-priority transports can implement that in their custom
transport themselves.
* Simplify registration further by taking a scheme (eg "http") instead
of a prefix (eg "http://").
Diffstat (limited to 'src')
-rw-r--r-- | src/remote.h | 1 | ||||
-rw-r--r-- | src/transport.c | 148 | ||||
-rw-r--r-- | src/transports/git.c | 1 | ||||
-rw-r--r-- | src/transports/smart.h | 1 |
4 files changed, 89 insertions, 62 deletions
diff --git a/src/remote.h b/src/remote.h index 47c4f7221..c471756b8 100644 --- a/src/remote.h +++ b/src/remote.h @@ -9,6 +9,7 @@ #include "git2/remote.h" #include "git2/transport.h" +#include "git2/sys/transport.h" #include "refspec.h" #include "vector.h" diff --git a/src/transport.c b/src/transport.c index fbcda5a53..c0311fa90 100644 --- a/src/transport.c +++ b/src/transport.c @@ -9,11 +9,11 @@ #include "git2/remote.h" #include "git2/net.h" #include "git2/transport.h" +#include "git2/sys/transport.h" #include "path.h" typedef struct transport_definition { char *prefix; - unsigned priority; git_transport_cb fn; void *param; } transport_definition; @@ -24,51 +24,54 @@ static git_smart_subtransport_definition git_subtransport_definition = { git_sma static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0 }; #endif -static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL }; +static transport_definition local_transport_definition = { "file://", git_transport_local, NULL }; #ifdef GIT_SSH -static transport_definition ssh_transport_definition = { "ssh://", 1, git_transport_smart, &ssh_subtransport_definition }; +static transport_definition ssh_transport_definition = { "ssh://", git_transport_smart, &ssh_subtransport_definition }; #else -static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL }; +static transport_definition dummy_transport_definition = { NULL, git_transport_dummy, NULL }; #endif static transport_definition transports[] = { - {"git://", 1, git_transport_smart, &git_subtransport_definition}, - {"http://", 1, git_transport_smart, &http_subtransport_definition}, - {"https://", 1, git_transport_smart, &http_subtransport_definition}, - {"file://", 1, git_transport_local, NULL}, + { "git://", git_transport_smart, &git_subtransport_definition }, + { "http://", git_transport_smart, &http_subtransport_definition }, + { "https://", git_transport_smart, &http_subtransport_definition }, + { "file://", git_transport_local, NULL }, #ifdef GIT_SSH - {"ssh://", 1, git_transport_smart, &ssh_subtransport_definition}, + { "ssh://", git_transport_smart, &ssh_subtransport_definition }, #endif - {NULL, 0, 0} + { NULL, 0, 0 } }; -static git_vector additional_transports = GIT_VECTOR_INIT; +static git_vector custom_transports = GIT_VECTOR_INIT; #define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1 -static int transport_find_fn(const char *url, git_transport_cb *callback, void **param) +static int transport_find_fn( + git_transport_cb *out, + const char *url, + void **param) { size_t i = 0; - unsigned priority = 0; - transport_definition *definition = NULL, *definition_iter; + transport_definition *d, *definition = NULL; - // First, check to see if it's an obvious URL, which a URL scheme - for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) { - definition_iter = &transports[i]; - - if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix))) - continue; - - if (definition_iter->priority > priority) - definition = definition_iter; + /* Find a user transport who wants to deal with this URI */ + git_vector_foreach(&custom_transports, i, d) { + if (strncasecmp(url, d->prefix, strlen(d->prefix)) == 0) { + definition = d; + break; + } } - git_vector_foreach(&additional_transports, i, definition_iter) { - if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix))) - continue; + /* Find a system transport for this URI */ + if (!definition) { + for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) { + d = &transports[i]; - if (definition_iter->priority > priority) - definition = definition_iter; + if (strncasecmp(url, d->prefix, strlen(d->prefix)) == 0) { + definition = d; + break; + } + } } #ifdef GIT_WIN32 @@ -90,7 +93,7 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void * #ifdef GIT_SSH definition = &ssh_transport_definition; #else - definition = &dummy_transport_definition; + definition = &dummy_transport_definition; #endif #ifndef GIT_WIN32 @@ -100,9 +103,9 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void * #endif if (!definition) - return -1; + return GIT_ENOTFOUND; - *callback = definition->fn; + *out = definition->fn; *param = definition->param; return 0; @@ -128,10 +131,11 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url) void *param; int error; - if (transport_find_fn(url, &fn, ¶m) < 0) { + if ((error = transport_find_fn(&fn, url, ¶m)) == GIT_ENOTFOUND) { giterr_set(GITERR_NET, "Unsupported URL protocol"); return -1; - } + } else if (error < 0) + return error; if ((error = fn(&transport, owner, param)) < 0) return error; @@ -144,59 +148,79 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url) } int git_transport_register( - const char *prefix, - unsigned priority, + const char *scheme, git_transport_cb cb, void *param) { - transport_definition *d; - - d = git__calloc(sizeof(transport_definition), 1); - GITERR_CHECK_ALLOC(d); + git_buf prefix = GIT_BUF_INIT; + transport_definition *d, *definition = NULL; + size_t i; + int error = 0; - d->prefix = git__strdup(prefix); + assert(scheme); + assert(cb); - if (!d->prefix) + if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0) goto on_error; - d->priority = priority; - d->fn = cb; - d->param = param; + git_vector_foreach(&custom_transports, i, d) { + if (strcasecmp(d->prefix, prefix.ptr) == 0) { + error = GIT_EEXISTS; + goto on_error; + } + } + + definition = git__calloc(1, sizeof(transport_definition)); + GITERR_CHECK_ALLOC(definition); + + definition->prefix = git_buf_detach(&prefix); + definition->fn = cb; + definition->param = param; - if (git_vector_insert(&additional_transports, d) < 0) + if (git_vector_insert(&custom_transports, definition) < 0) goto on_error; return 0; on_error: - git__free(d->prefix); - git__free(d); - return -1; + git_buf_free(&prefix); + git__free(definition); + return error; } -int git_transport_unregister( - const char *prefix, - unsigned priority) +int git_transport_unregister(const char *scheme) { + git_buf prefix = GIT_BUF_INIT; transport_definition *d; - unsigned i; + size_t i; + int error = 0; + + assert(scheme); - git_vector_foreach(&additional_transports, i, d) { - if (d->priority == priority && !strcasecmp(d->prefix, prefix)) { - if (git_vector_remove(&additional_transports, i) < 0) - return -1; + if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0) + goto done; + + git_vector_foreach(&custom_transports, i, d) { + if (strcasecmp(d->prefix, prefix.ptr) == 0) { + if ((error = git_vector_remove(&custom_transports, i)) < 0) + goto done; git__free(d->prefix); git__free(d); - if (!additional_transports.length) - git_vector_free(&additional_transports); + if (!custom_transports.length) + git_vector_free(&custom_transports); - return 0; + error = 0; + goto done; } } - return GIT_ENOTFOUND; + error = GIT_ENOTFOUND; + +done: + git_buf_free(&prefix); + return error; } /* from remote.h */ @@ -205,7 +229,7 @@ int git_remote_valid_url(const char *url) git_transport_cb fn; void *param; - return !transport_find_fn(url, &fn, ¶m); + return !transport_find_fn(&fn, url, ¶m); } int git_remote_supported_url(const char* url) @@ -213,7 +237,7 @@ int git_remote_supported_url(const char* url) git_transport_cb fn; void *param; - if (transport_find_fn(url, &fn, ¶m) < 0) + if (transport_find_fn(&fn, url, ¶m) < 0) return 0; return fn != &git_transport_dummy; diff --git a/src/transports/git.c b/src/transports/git.c index 21507c1c7..e2690fe36 100644 --- a/src/transports/git.c +++ b/src/transports/git.c @@ -8,6 +8,7 @@ #include "git2.h" #include "buffer.h" #include "netops.h" +#include "git2/sys/transport.h" #define OWNING_SUBTRANSPORT(s) ((git_subtransport *)(s)->parent.subtransport) diff --git a/src/transports/smart.h b/src/transports/smart.h index f1fc29520..b29faae44 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -9,6 +9,7 @@ #include "netops.h" #include "buffer.h" #include "push.h" +#include "git2/sys/transport.h" #define GIT_SIDE_BAND_DATA 1 #define GIT_SIDE_BAND_PROGRESS 2 |