]> git.proxmox.com Git - libgit2.git/blob - src/transport.c
Merge remote-tracking branch 'origin/development' into ssh_transport
[libgit2.git] / src / transport.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
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 */
7 #include "common.h"
8 #include "git2/types.h"
9 #include "git2/remote.h"
10 #include "git2/net.h"
11 #include "git2/transport.h"
12 #include "path.h"
13
14 typedef struct transport_definition {
15 char *prefix;
16 unsigned priority;
17 git_transport_cb fn;
18 void *param;
19 } transport_definition;
20
21 static git_smart_subtransport_definition http_subtransport_definition = { git_smart_subtransport_http, 1 };
22 static git_smart_subtransport_definition git_subtransport_definition = { git_smart_subtransport_git, 0 };
23 #ifdef GIT_SSH
24 static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0 };
25 #endif
26
27 static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL };
28 #ifdef GIT_SSH
29 static transport_definition ssh_transport_definition = { "ssh://", 1, git_transport_smart, &ssh_subtransport_definition };
30 #else
31 static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL };
32 #endif
33
34 static transport_definition transports[] = {
35 {"git://", 1, git_transport_smart, &git_subtransport_definition},
36 {"http://", 1, git_transport_smart, &http_subtransport_definition},
37 {"https://", 1, git_transport_smart, &http_subtransport_definition},
38 {"file://", 1, git_transport_local, NULL},
39 #ifdef GIT_SSH
40 {"ssh://", 1, git_transport_smart, &ssh_subtransport_definition},
41 #endif
42 {NULL, 0, 0}
43 };
44
45 #define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1
46
47 static int transport_find_fn(const char *url, git_transport_cb *callback, void **param)
48 {
49 size_t i = 0;
50 unsigned priority = 0;
51 transport_definition *definition = NULL, *definition_iter;
52
53 // First, check to see if it's an obvious URL, which a URL scheme
54 for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) {
55 definition_iter = &transports[i];
56
57 if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix)))
58 continue;
59
60 if (definition_iter->priority > priority)
61 definition = definition_iter;
62 }
63
64 #ifdef GIT_WIN32
65 /* On Windows, it might not be possible to discern between absolute local
66 * and ssh paths - first check if this is a valid local path that points
67 * to a directory and if so assume local path, else assume SSH */
68
69 /* Check to see if the path points to a file on the local file system */
70 if (!definition && git_path_exists(url) && git_path_isdir(url))
71 definition = &local_transport_definition;
72
73 /* It could be a SSH remote path. Check to see if there's a :
74 * SSH is an unsupported transport mechanism in this version of libgit2 */
75 if (!definition && strrchr(url, ':'))
76 definition = &dummy_transport_definition;
77 #else
78 /* For other systems, perform the SSH check first, to avoid going to the
79 * filesystem if it is not necessary */
80
81 /* It could be a SSH remote path. Check to see if there's a :
82 * SSH is an unsupported transport mechanism in this version of libgit2 */
83 if (!definition && strrchr(url, ':'))
84 #ifdef GIT_SSH
85 definition = &ssh_transport_definition;
86 #else
87 definition = &dummy_transport_definition;
88 #endif
89
90 /* Check to see if the path points to a file on the local file system */
91 if (!definition && git_path_exists(url) && git_path_isdir(url))
92 definition = &local_transport_definition;
93 #endif
94
95 if (!definition)
96 return -1;
97
98 *callback = definition->fn;
99 *param = definition->param;
100
101 return 0;
102 }
103
104 /**************
105 * Public API *
106 **************/
107
108 int git_transport_dummy(git_transport **transport, git_remote *owner, void *param)
109 {
110 GIT_UNUSED(transport);
111 GIT_UNUSED(owner);
112 GIT_UNUSED(param);
113 giterr_set(GITERR_NET, "This transport isn't implemented. Sorry");
114 return -1;
115 }
116
117 int git_transport_new(git_transport **out, git_remote *owner, const char *url)
118 {
119 git_transport_cb fn;
120 git_transport *transport;
121 void *param;
122 int error;
123
124 if (transport_find_fn(url, &fn, &param) < 0) {
125 giterr_set(GITERR_NET, "Unsupported URL protocol");
126 return -1;
127 }
128
129 error = fn(&transport, owner, param);
130 if (error < 0)
131 return error;
132
133 *out = transport;
134
135 return 0;
136 }
137
138 /* from remote.h */
139 int git_remote_valid_url(const char *url)
140 {
141 git_transport_cb fn;
142 void *param;
143
144 return !transport_find_fn(url, &fn, &param);
145 }
146
147 int git_remote_supported_url(const char* url)
148 {
149 git_transport_cb fn;
150 void *param;
151
152 if (transport_find_fn(url, &fn, &param) < 0)
153 return 0;
154
155 return fn != &git_transport_dummy;
156 }