Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport.c')
-rw-r--r--src/transport.c115
1 files changed, 81 insertions, 34 deletions
diff --git a/src/transport.c b/src/transport.c
index 5b2cd7ea4..adb6d5355 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 the libgit2 contributors
+ * Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
@@ -8,76 +8,116 @@
#include "git2/types.h"
#include "git2/remote.h"
#include "git2/net.h"
-#include "transport.h"
+#include "git2/transport.h"
#include "path.h"
-static struct {
+typedef struct transport_definition {
char *prefix;
+ unsigned priority;
git_transport_cb fn;
-} transports[] = {
- {"git://", git_transport_git},
- {"http://", git_transport_http},
- {"https://", git_transport_dummy},
- {"file://", git_transport_local},
- {"git+ssh://", git_transport_dummy},
- {"ssh+git://", git_transport_dummy},
- {NULL, 0}
+ void *param;
+} transport_definition;
+
+static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL };
+static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL };
+
+static git_smart_subtransport_definition http_subtransport_definition = { git_smart_subtransport_http, 1 };
+static git_smart_subtransport_definition git_subtransport_definition = { git_smart_subtransport_git, 0 };
+
+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+ssh://", 1, git_transport_dummy, NULL},
+ {"ssh+git://", 1, git_transport_dummy, NULL},
+ {NULL, 0, 0}
};
#define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1
-static git_transport_cb transport_find_fn(const char *url)
+static int transport_find_fn(const char *url, git_transport_cb *callback, void **param)
{
size_t i = 0;
+ unsigned priority = 0;
+ transport_definition *definition = NULL, *definition_iter;
// First, check to see if it's an obvious URL, which a URL scheme
for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) {
- if (!strncasecmp(url, transports[i].prefix, strlen(transports[i].prefix)))
- return transports[i].fn;
- }
+ definition_iter = &transports[i];
+
+ if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix)))
+ continue;
- /* still here? Check to see if the path points to a file on the local file system */
- if ((git_path_exists(url) == 0) && git_path_isdir(url))
- return &git_transport_local;
+ if (definition_iter->priority > priority)
+ definition = definition_iter;
+ }
- /* It could be a SSH remote path. Check to see if there's a : */
- if (strrchr(url, ':'))
- return &git_transport_dummy; /* SSH is an unsupported transport mechanism in this version of libgit2 */
+#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
+ * to a directory and if so assume local path, else assume SSH */
+
+ /* Check to see if the path points to a file on the local file system */
+ if (!definition && git_path_exists(url) && git_path_isdir(url))
+ definition = &local_transport_definition;
+
+ /* It could be a SSH remote path. Check to see if there's a :
+ * SSH is an unsupported transport mechanism in this version of libgit2 */
+ if (!definition && strrchr(url, ':'))
+ definition = &dummy_transport_definition;
+#else
+ /* For other systems, perform the SSH check first, to avoid going to the
+ * filesystem if it is not necessary */
+
+ /* It could be a SSH remote path. Check to see if there's a :
+ * SSH is an unsupported transport mechanism in this version of libgit2 */
+ if (!definition && strrchr(url, ':'))
+ definition = &dummy_transport_definition;
+
+ /* Check to see if the path points to a file on the local file system */
+ if (!definition && git_path_exists(url) && git_path_isdir(url))
+ definition = &local_transport_definition;
+#endif
+
+ if (!definition)
+ return -1;
- return NULL;
+ *callback = definition->fn;
+ *param = definition->param;
+
+ return 0;
}
/**************
* Public API *
**************/
-int git_transport_dummy(git_transport **transport)
+int git_transport_dummy(git_transport **transport, git_remote *owner, void *param)
{
GIT_UNUSED(transport);
+ GIT_UNUSED(owner);
+ GIT_UNUSED(param);
giterr_set(GITERR_NET, "This transport isn't implemented. Sorry");
return -1;
}
-int git_transport_new(git_transport **out, const char *url)
+int git_transport_new(git_transport **out, git_remote *owner, const char *url)
{
git_transport_cb fn;
git_transport *transport;
+ void *param;
int error;
- fn = transport_find_fn(url);
-
- if (fn == NULL) {
+ if (transport_find_fn(url, &fn, &param) < 0) {
giterr_set(GITERR_NET, "Unsupported URL protocol");
return -1;
}
- error = fn(&transport);
+ error = fn(&transport, owner, param);
if (error < 0)
return error;
- transport->url = git__strdup(url);
- GITERR_CHECK_ALLOC(transport->url);
-
*out = transport;
return 0;
@@ -86,12 +126,19 @@ int git_transport_new(git_transport **out, const char *url)
/* from remote.h */
int git_remote_valid_url(const char *url)
{
- return transport_find_fn(url) != NULL;
+ git_transport_cb fn;
+ void *param;
+
+ return !transport_find_fn(url, &fn, &param);
}
int git_remote_supported_url(const char* url)
{
- git_transport_cb transport_fn = transport_find_fn(url);
+ git_transport_cb fn;
+ void *param;
+
+ if (transport_find_fn(url, &fn, &param) < 0)
+ return 0;
- return ((transport_fn != NULL) && (transport_fn != &git_transport_dummy));
+ return fn != &git_transport_dummy;
}