summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2014-07-09 17:58:39 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2014-08-14 08:52:20 -0500
commitc180c06586050a33f6e8a6d25cc30b7bcbef702d (patch)
treeb05d0f67ad9c3320bd7c3dd42a4b53334119619b /src
parente62f96dea5a46098cbca5a287f29ca811003bd68 (diff)
downloadlibgit2-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.h1
-rw-r--r--src/transport.c148
-rw-r--r--src/transports/git.c1
-rw-r--r--src/transports/smart.h1
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, &param) < 0) {
+ if ((error = transport_find_fn(&fn, url, &param)) == 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, &param);
+ return !transport_find_fn(&fn, url, &param);
}
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, &param) < 0)
+ if (transport_find_fn(&fn, url, &param) < 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