]>
Commit | Line | Data |
---|---|---|
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 | 15 | typedef struct transport_definition { |
8f866dae CMN |
16 | char *prefix; |
17 | git_transport_cb fn; | |
41fb1ca0 PK |
18 | void *param; |
19 | } transport_definition; | |
20 | ||
142e5379 LY |
21 | static git_smart_subtransport_definition http_subtransport_definition = { git_smart_subtransport_http, 1, NULL }; |
22 | static git_smart_subtransport_definition git_subtransport_definition = { git_smart_subtransport_git, 0, NULL }; | |
bd3854a0 | 23 | #ifdef GIT_SSH |
142e5379 | 24 | static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0, NULL }; |
bd3854a0 | 25 | #endif |
41fb1ca0 | 26 | |
c180c065 | 27 | static transport_definition local_transport_definition = { "file://", git_transport_local, NULL }; |
7261d983 | 28 | |
41fb1ca0 | 29 | static 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 | 42 | static git_vector custom_transports = GIT_VECTOR_INIT; |
83786956 | 43 | |
86360ffd | 44 | #define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1 |
2869f404 | 45 | |
34e510ce | 46 | static 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 | ||
70 | static 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 | 116 | int 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, ¶m)) == 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 | 139 | int 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 | ||
174 | on_error: | |
c180c065 ET |
175 | git_buf_free(&prefix); |
176 | git__free(definition); | |
177 | return error; | |
83786956 PK |
178 | } |
179 | ||
c180c065 | 180 | int 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 | ||
210 | done: | |
211 | git_buf_free(&prefix); | |
212 | return error; | |
83786956 PK |
213 | } |
214 | ||
bc91347b | 215 | int 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 | } |