]> git.proxmox.com Git - libgit2.git/commitdiff
Add git_transport_register, git_transport_unregister
authorPhilip Kelley <phkelley@hotmail.com>
Fri, 4 Jan 2013 19:39:05 +0000 (14:39 -0500)
committerEdward Thomson <ethomson@microsoft.com>
Tue, 1 Oct 2013 20:49:41 +0000 (16:49 -0400)
include/git2/transport.h
src/transport.c

index e61b104235a8090360b993d33fb5a9ad8aebbacb..9901b15de1385115a1f8a25a059feedc4240cd77 100644 (file)
@@ -253,6 +253,40 @@ GIT_EXTERN(int) git_transport_new(git_transport **out, git_remote *owner, const
 /* Signature of a function which creates a transport */
 typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param);
 
+/**
+ * Add a custom transport definition, to be used in addition to the built-in
+ * set of transports that come with libgit2.
+ *
+ * The caller is responsible for synchronizing calls to git_transport_register
+ * and git_transport_unregister with other calls to the library that
+ * instantiate transports.
+ *
+ * @param prefix The scheme (ending in "://") to match, i.e. "git://"
+ * @param priority The priority of this transport relative to others with
+ *             the same prefix. Built-in transports have a priority of 1.
+ * @param cb The callback used to create an instance of the transport
+ * @param param A fixed parameter to pass to cb at creation time
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_transport_register(
+       const char *prefix,
+       unsigned priority,
+       git_transport_cb cb,
+       void *param);
+
+/**
+ *
+ * Unregister a custom transport definition which was previously registered
+ * with git_transport_register.
+ *
+ * @param prefix From the previous call to git_transport_register
+ * @param priority From the previous call to git_transport_register
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_transport_unregister(
+       const char *prefix,
+       unsigned priority);
+
 /* Transports which come with libgit2 (match git_transport_cb). The expected
  * value for "param" is listed in-line below. */
 
index 354789db19c3ca1409bb515944954dcdba3d1776..ff926b1be34fe9c0728c85a90c476149112e09ac 100644 (file)
@@ -42,6 +42,8 @@ static transport_definition transports[] = {
        {NULL, 0, 0}
 };
 
+static git_vector additional_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)
@@ -61,6 +63,14 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void *
                        definition = definition_iter;
        }
 
+       git_vector_foreach(&additional_transports, i, definition_iter) {
+               if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix)))
+                       continue;
+
+               if (definition_iter->priority > priority)
+                       definition = definition_iter;
+       }
+
 #ifdef GIT_WIN32
        /* On Windows, it might not be possible to discern between absolute local
         * and ssh paths - first check if this is a valid local path that points
@@ -135,6 +145,62 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url)
        return 0;
 }
 
+int git_transport_register(
+       const char *prefix,
+       unsigned priority,
+       git_transport_cb cb,
+       void *param)
+{
+       transport_definition *d;
+
+       d = git__calloc(sizeof(transport_definition), 1);
+       GITERR_CHECK_ALLOC(d);
+
+       d->prefix = git__strdup(prefix);
+
+       if (!d->prefix)
+               goto on_error;
+
+       d->priority = priority;
+       d->fn = cb;
+       d->param = param;
+
+       if (git_vector_insert(&additional_transports, d) < 0)
+               goto on_error;
+
+       return 0;
+
+on_error:
+       git__free(d->prefix);
+       git__free(d);
+       return -1;
+}
+
+int git_transport_unregister(
+       const char *prefix,
+       unsigned priority)
+{
+       transport_definition *d;
+       unsigned i;
+
+       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;
+
+                       git__free(d->prefix);
+                       git__free(d);
+
+                       if (!additional_transports.length)
+                               git_vector_free(&additional_transports);
+
+                       return 0;
+               }
+       }
+
+       return GIT_ENOTFOUND;
+}
+
 /* from remote.h */
 int git_remote_valid_url(const char *url)
 {