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