]> git.proxmox.com Git - libgit2.git/blame - src/transport.c
Merge pull request #3097 from libgit2/cmn/submodule-config-state
[libgit2.git] / src / transport.c
CommitLineData
bb742ede 1/*
359fc2d2 2 * Copyright (C) the libgit2 contributors. All rights reserved.
bb742ede
VM
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
8f866dae
CMN
7#include "common.h"
8#include "git2/types.h"
d88d4311 9#include "git2/remote.h"
8f866dae 10#include "git2/net.h"
41fb1ca0 11#include "git2/transport.h"
c180c065 12#include "git2/sys/transport.h"
253d6df5 13#include "path.h"
8f866dae 14
41fb1ca0 15typedef struct transport_definition {
8f866dae
CMN
16 char *prefix;
17 git_transport_cb fn;
41fb1ca0
PK
18 void *param;
19} transport_definition;
20
142e5379
LY
21static git_smart_subtransport_definition http_subtransport_definition = { git_smart_subtransport_http, 1, NULL };
22static git_smart_subtransport_definition git_subtransport_definition = { git_smart_subtransport_git, 0, NULL };
bd3854a0 23#ifdef GIT_SSH
142e5379 24static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0, NULL };
bd3854a0 25#endif
41fb1ca0 26
c180c065 27static transport_definition local_transport_definition = { "file://", git_transport_local, NULL };
7261d983 28
41fb1ca0 29static transport_definition transports[] = {
c180c065
ET
30 { "git://", git_transport_smart, &git_subtransport_definition },
31 { "http://", git_transport_smart, &http_subtransport_definition },
24e53d2f 32#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT)
c180c065 33 { "https://", git_transport_smart, &http_subtransport_definition },
bd3854a0 34#endif
c180c065 35 { "file://", git_transport_local, NULL },
bd3854a0 36#ifdef GIT_SSH
c180c065 37 { "ssh://", git_transport_smart, &ssh_subtransport_definition },
bd3854a0 38#endif
c180c065 39 { NULL, 0, 0 }
8f866dae
CMN
40};
41
c180c065 42static git_vector custom_transports = GIT_VECTOR_INIT;
83786956 43
86360ffd 44#define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1
2869f404 45
34e510ce 46static transport_definition * transport_find_by_url(const char *url)
8f866dae 47{
2869f404 48 size_t i = 0;
34e510ce 49 transport_definition *d;
8f866dae 50
c180c065
ET
51 /* Find a user transport who wants to deal with this URI */
52 git_vector_foreach(&custom_transports, i, d) {
53 if (strncasecmp(url, d->prefix, strlen(d->prefix)) == 0) {
34e510ce 54 return d;
c180c065 55 }
8f866dae
CMN
56 }
57
c180c065 58 /* Find a system transport for this URI */
34e510ce
SS
59 for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) {
60 d = &transports[i];
61
62 if (strncasecmp(url, d->prefix, strlen(d->prefix)) == 0) {
63 return d;
c180c065 64 }
83786956
PK
65 }
66
34e510ce
SS
67 return NULL;
68}
69
70static int transport_find_fn(
71 git_transport_cb *out,
72 const char *url,
73 void **param)
74{
75 transport_definition *definition = transport_find_by_url(url);
76
cb2ace69
JM
77#ifdef GIT_WIN32
78 /* On Windows, it might not be possible to discern between absolute local
79 * and ssh paths - first check if this is a valid local path that points
80 * to a directory and if so assume local path, else assume SSH */
81
82 /* Check to see if the path points to a file on the local file system */
83 if (!definition && git_path_exists(url) && git_path_isdir(url))
84 definition = &local_transport_definition;
ed5b77b0 85#endif
cb2ace69 86
cb2ace69
JM
87 /* For other systems, perform the SSH check first, to avoid going to the
88 * filesystem if it is not necessary */
89
f0a2def5
JM
90 /* It could be a SSH remote path. Check to see if there's a :
91 * SSH is an unsupported transport mechanism in this version of libgit2 */
34e510ce
SS
92 if (!definition && strrchr(url, ':')) {
93 // re-search transports again with ssh:// as url so that we can find a third party ssh transport
94 definition = transport_find_by_url("ssh://");
34e510ce 95 }
cb2ace69 96
ed5b77b0 97#ifndef GIT_WIN32
cb2ace69
JM
98 /* Check to see if the path points to a file on the local file system */
99 if (!definition && git_path_exists(url) && git_path_isdir(url))
100 definition = &local_transport_definition;
101#endif
58448910 102
41fb1ca0 103 if (!definition)
c180c065 104 return GIT_ENOTFOUND;
58448910 105
c180c065 106 *out = definition->fn;
41fb1ca0 107 *param = definition->param;
a3c062db 108
41fb1ca0 109 return 0;
8f866dae
CMN
110}
111
112/**************
113 * Public API *
114 **************/
115
613d5eb9 116int git_transport_new(git_transport **out, git_remote *owner, const char *url)
8f866dae
CMN
117{
118 git_transport_cb fn;
119 git_transport *transport;
41fb1ca0 120 void *param;
8f866dae
CMN
121 int error;
122
c180c065 123 if ((error = transport_find_fn(&fn, url, &param)) == GIT_ENOTFOUND) {
3fbcac89
VM
124 giterr_set(GITERR_NET, "Unsupported URL protocol");
125 return -1;
c180c065
ET
126 } else if (error < 0)
127 return error;
8f866dae 128
1697cd6f 129 if ((error = fn(&transport, owner, param)) < 0)
4376f7f6 130 return error;
d6258deb 131
1697cd6f
PK
132 GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport");
133
8f866dae
CMN
134 *out = transport;
135
e172cf08 136 return 0;
8f866dae 137}
d88d4311 138
83786956 139int git_transport_register(
c180c065 140 const char *scheme,
83786956
PK
141 git_transport_cb cb,
142 void *param)
143{
c180c065
ET
144 git_buf prefix = GIT_BUF_INIT;
145 transport_definition *d, *definition = NULL;
146 size_t i;
147 int error = 0;
83786956 148
c180c065
ET
149 assert(scheme);
150 assert(cb);
83786956 151
c180c065 152 if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
83786956
PK
153 goto on_error;
154
c180c065
ET
155 git_vector_foreach(&custom_transports, i, d) {
156 if (strcasecmp(d->prefix, prefix.ptr) == 0) {
157 error = GIT_EEXISTS;
158 goto on_error;
159 }
160 }
161
162 definition = git__calloc(1, sizeof(transport_definition));
163 GITERR_CHECK_ALLOC(definition);
164
165 definition->prefix = git_buf_detach(&prefix);
166 definition->fn = cb;
167 definition->param = param;
83786956 168
c180c065 169 if (git_vector_insert(&custom_transports, definition) < 0)
83786956
PK
170 goto on_error;
171
172 return 0;
173
174on_error:
c180c065
ET
175 git_buf_free(&prefix);
176 git__free(definition);
177 return error;
83786956
PK
178}
179
c180c065 180int git_transport_unregister(const char *scheme)
83786956 181{
c180c065 182 git_buf prefix = GIT_BUF_INIT;
83786956 183 transport_definition *d;
c180c065
ET
184 size_t i;
185 int error = 0;
186
187 assert(scheme);
83786956 188
c180c065
ET
189 if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
190 goto done;
191
192 git_vector_foreach(&custom_transports, i, d) {
193 if (strcasecmp(d->prefix, prefix.ptr) == 0) {
194 if ((error = git_vector_remove(&custom_transports, i)) < 0)
195 goto done;
83786956
PK
196
197 git__free(d->prefix);
198 git__free(d);
199
c180c065
ET
200 if (!custom_transports.length)
201 git_vector_free(&custom_transports);
83786956 202
c180c065
ET
203 error = 0;
204 goto done;
83786956
PK
205 }
206 }
207
c180c065
ET
208 error = GIT_ENOTFOUND;
209
210done:
211 git_buf_free(&prefix);
212 return error;
83786956
PK
213}
214
bc91347b 215int git_transport_init(git_transport *opts, unsigned int version)
b9f81997 216{
bc91347b
RB
217 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
218 opts, version, git_transport, GIT_TRANSPORT_INIT);
219 return 0;
b9f81997 220}