mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-04 13:05:35 +00:00
157 lines
4.4 KiB
C
157 lines
4.4 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
#include "common.h"
|
|
#include "git2/types.h"
|
|
#include "git2/remote.h"
|
|
#include "git2/net.h"
|
|
#include "git2/transport.h"
|
|
#include "path.h"
|
|
|
|
typedef struct transport_definition {
|
|
char *prefix;
|
|
unsigned priority;
|
|
git_transport_cb fn;
|
|
void *param;
|
|
} transport_definition;
|
|
|
|
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 };
|
|
#ifdef GIT_SSH
|
|
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 };
|
|
#ifdef GIT_SSH
|
|
static transport_definition ssh_transport_definition = { "ssh://", 1, git_transport_smart, &ssh_subtransport_definition };
|
|
#else
|
|
static transport_definition dummy_transport_definition = { NULL, 1, 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},
|
|
#ifdef GIT_SSH
|
|
{"ssh://", 1, git_transport_smart, &ssh_subtransport_definition},
|
|
#endif
|
|
{NULL, 0, 0}
|
|
};
|
|
|
|
#define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1
|
|
|
|
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) {
|
|
definition_iter = &transports[i];
|
|
|
|
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
|
|
* 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, ':'))
|
|
#ifdef GIT_SSH
|
|
definition = &ssh_transport_definition;
|
|
#else
|
|
definition = &dummy_transport_definition;
|
|
#endif
|
|
|
|
/* 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;
|
|
|
|
*callback = definition->fn;
|
|
*param = definition->param;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************
|
|
* Public API *
|
|
**************/
|
|
|
|
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, git_remote *owner, const char *url)
|
|
{
|
|
git_transport_cb fn;
|
|
git_transport *transport;
|
|
void *param;
|
|
int error;
|
|
|
|
if (transport_find_fn(url, &fn, ¶m) < 0) {
|
|
giterr_set(GITERR_NET, "Unsupported URL protocol");
|
|
return -1;
|
|
}
|
|
|
|
error = fn(&transport, owner, param);
|
|
if (error < 0)
|
|
return error;
|
|
|
|
*out = transport;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* from remote.h */
|
|
int git_remote_valid_url(const char *url)
|
|
{
|
|
git_transport_cb fn;
|
|
void *param;
|
|
|
|
return !transport_find_fn(url, &fn, ¶m);
|
|
}
|
|
|
|
int git_remote_supported_url(const char* url)
|
|
{
|
|
git_transport_cb fn;
|
|
void *param;
|
|
|
|
if (transport_find_fn(url, &fn, ¶m) < 0)
|
|
return 0;
|
|
|
|
return fn != &git_transport_dummy;
|
|
}
|