rugged 1.6.5 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_allocator.c +0 -54
  3. data/lib/rugged/version.rb +1 -1
  4. data/vendor/libgit2/CMakeLists.txt +3 -8
  5. data/vendor/libgit2/cmake/CheckPrototypeDefinitionSafe.cmake +16 -0
  6. data/vendor/libgit2/cmake/SelectGSSAPI.cmake +3 -3
  7. data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +21 -2
  8. data/vendor/libgit2/cmake/SelectHashes.cmake +4 -0
  9. data/vendor/libgit2/cmake/SelectXdiff.cmake +9 -0
  10. data/vendor/libgit2/deps/pcre/LICENCE +5 -5
  11. data/vendor/libgit2/deps/pcre/pcre.h +2 -2
  12. data/vendor/libgit2/deps/pcre/pcre_compile.c +6 -3
  13. data/vendor/libgit2/deps/pcre/pcre_exec.c +2 -2
  14. data/vendor/libgit2/deps/xdiff/CMakeLists.txt +28 -0
  15. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/git-xdiff.h +4 -1
  16. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.c +19 -18
  17. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.h +2 -4
  18. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.c +3 -3
  19. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xhistogram.c +7 -18
  20. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmacros.h +18 -1
  21. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmerge.c +24 -22
  22. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xpatience.c +21 -30
  23. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.c +13 -30
  24. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.c +18 -1
  25. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.h +2 -1
  26. data/vendor/libgit2/include/git2/common.h +26 -1
  27. data/vendor/libgit2/include/git2/diff.h +41 -3
  28. data/vendor/libgit2/include/git2/errors.h +4 -2
  29. data/vendor/libgit2/include/git2/index.h +9 -0
  30. data/vendor/libgit2/include/git2/oid.h +1 -1
  31. data/vendor/libgit2/include/git2/remote.h +18 -0
  32. data/vendor/libgit2/include/git2/repository.h +12 -2
  33. data/vendor/libgit2/include/git2/sys/alloc.h +0 -34
  34. data/vendor/libgit2/include/git2/sys/commit_graph.h +12 -2
  35. data/vendor/libgit2/include/git2/sys/midx.h +5 -1
  36. data/vendor/libgit2/include/git2/sys/stream.h +16 -2
  37. data/vendor/libgit2/include/git2/sys/transport.h +20 -2
  38. data/vendor/libgit2/include/git2/version.h +4 -4
  39. data/vendor/libgit2/include/git2/worktree.h +3 -1
  40. data/vendor/libgit2/src/CMakeLists.txt +34 -11
  41. data/vendor/libgit2/src/cli/cmd_clone.c +22 -6
  42. data/vendor/libgit2/src/cli/progress.c +9 -8
  43. data/vendor/libgit2/src/cli/progress.h +4 -4
  44. data/vendor/libgit2/src/libgit2/CMakeLists.txt +1 -19
  45. data/vendor/libgit2/src/libgit2/annotated_commit.c +2 -2
  46. data/vendor/libgit2/src/libgit2/annotated_commit.h +1 -1
  47. data/vendor/libgit2/src/libgit2/apply.c +4 -3
  48. data/vendor/libgit2/src/libgit2/blame.c +23 -16
  49. data/vendor/libgit2/src/libgit2/blame_git.c +0 -1
  50. data/vendor/libgit2/src/libgit2/branch.c +2 -2
  51. data/vendor/libgit2/src/libgit2/cherrypick.c +3 -3
  52. data/vendor/libgit2/src/libgit2/clone.c +3 -1
  53. data/vendor/libgit2/src/libgit2/commit.c +31 -9
  54. data/vendor/libgit2/src/libgit2/commit_graph.c +110 -43
  55. data/vendor/libgit2/src/libgit2/commit_graph.h +20 -4
  56. data/vendor/libgit2/src/libgit2/commit_list.c +12 -5
  57. data/vendor/libgit2/src/libgit2/commit_list.h +1 -0
  58. data/vendor/libgit2/src/libgit2/config_file.c +14 -8
  59. data/vendor/libgit2/src/libgit2/describe.c +10 -7
  60. data/vendor/libgit2/src/libgit2/diff.c +16 -7
  61. data/vendor/libgit2/src/libgit2/diff.h +6 -6
  62. data/vendor/libgit2/src/libgit2/diff_file.c +7 -7
  63. data/vendor/libgit2/src/libgit2/diff_generate.c +36 -15
  64. data/vendor/libgit2/src/libgit2/diff_parse.c +20 -4
  65. data/vendor/libgit2/src/libgit2/diff_print.c +26 -7
  66. data/vendor/libgit2/src/libgit2/diff_tform.c +4 -4
  67. data/vendor/libgit2/src/libgit2/diff_xdiff.h +1 -1
  68. data/vendor/libgit2/src/libgit2/email.c +4 -3
  69. data/vendor/libgit2/src/libgit2/errors.c +73 -18
  70. data/vendor/libgit2/src/libgit2/fetch.c +37 -9
  71. data/vendor/libgit2/src/libgit2/fetch.h +0 -2
  72. data/vendor/libgit2/src/libgit2/fetchhead.c +11 -9
  73. data/vendor/libgit2/src/libgit2/grafts.c +272 -0
  74. data/vendor/libgit2/src/libgit2/grafts.h +36 -0
  75. data/vendor/libgit2/src/libgit2/ident.c +3 -3
  76. data/vendor/libgit2/src/libgit2/index.c +325 -125
  77. data/vendor/libgit2/src/libgit2/index.h +14 -1
  78. data/vendor/libgit2/src/libgit2/indexer.c +10 -3
  79. data/vendor/libgit2/src/libgit2/iterator.c +20 -5
  80. data/vendor/libgit2/src/libgit2/iterator.h +3 -0
  81. data/vendor/libgit2/src/libgit2/libgit2.c +39 -0
  82. data/vendor/libgit2/src/libgit2/merge.c +14 -9
  83. data/vendor/libgit2/src/libgit2/merge_file.c +0 -2
  84. data/vendor/libgit2/src/libgit2/midx.c +66 -37
  85. data/vendor/libgit2/src/libgit2/midx.h +13 -3
  86. data/vendor/libgit2/src/libgit2/notes.c +9 -8
  87. data/vendor/libgit2/src/libgit2/object.c +40 -15
  88. data/vendor/libgit2/src/libgit2/object.h +6 -0
  89. data/vendor/libgit2/src/libgit2/odb.c +11 -5
  90. data/vendor/libgit2/src/libgit2/odb_pack.c +16 -3
  91. data/vendor/libgit2/src/libgit2/oid.c +7 -1
  92. data/vendor/libgit2/src/libgit2/oidarray.c +49 -3
  93. data/vendor/libgit2/src/libgit2/oidarray.h +5 -1
  94. data/vendor/libgit2/src/libgit2/pack-objects.c +19 -12
  95. data/vendor/libgit2/src/libgit2/pack-objects.h +5 -2
  96. data/vendor/libgit2/src/libgit2/pack.c +3 -3
  97. data/vendor/libgit2/src/libgit2/parse.c +7 -4
  98. data/vendor/libgit2/src/libgit2/parse.h +1 -1
  99. data/vendor/libgit2/src/libgit2/patch.h +7 -1
  100. data/vendor/libgit2/src/libgit2/patch_generate.c +24 -5
  101. data/vendor/libgit2/src/libgit2/patch_parse.c +16 -8
  102. data/vendor/libgit2/src/libgit2/push.c +2 -2
  103. data/vendor/libgit2/src/libgit2/reader.c +1 -1
  104. data/vendor/libgit2/src/libgit2/rebase.c +72 -84
  105. data/vendor/libgit2/src/libgit2/refdb_fs.c +22 -13
  106. data/vendor/libgit2/src/libgit2/refs.c +8 -1
  107. data/vendor/libgit2/src/libgit2/remote.c +15 -6
  108. data/vendor/libgit2/src/libgit2/remote.h +1 -0
  109. data/vendor/libgit2/src/libgit2/repository.c +580 -301
  110. data/vendor/libgit2/src/libgit2/repository.h +17 -2
  111. data/vendor/libgit2/src/libgit2/reset.c +2 -2
  112. data/vendor/libgit2/src/libgit2/revert.c +8 -11
  113. data/vendor/libgit2/src/libgit2/revparse.c +1 -4
  114. data/vendor/libgit2/src/libgit2/revwalk.c +26 -4
  115. data/vendor/libgit2/src/libgit2/stash.c +9 -8
  116. data/vendor/libgit2/src/libgit2/streams/mbedtls.c +0 -1
  117. data/vendor/libgit2/src/libgit2/streams/openssl.c +8 -16
  118. data/vendor/libgit2/src/libgit2/streams/schannel.c +715 -0
  119. data/vendor/libgit2/src/libgit2/streams/schannel.h +28 -0
  120. data/vendor/libgit2/src/libgit2/streams/socket.c +237 -51
  121. data/vendor/libgit2/src/libgit2/streams/socket.h +3 -1
  122. data/vendor/libgit2/src/libgit2/streams/stransport.c +40 -12
  123. data/vendor/libgit2/src/libgit2/streams/tls.c +5 -0
  124. data/vendor/libgit2/src/libgit2/submodule.h +3 -3
  125. data/vendor/libgit2/src/libgit2/threadstate.c +15 -2
  126. data/vendor/libgit2/src/libgit2/threadstate.h +1 -3
  127. data/vendor/libgit2/src/libgit2/transports/auth.h +1 -2
  128. data/vendor/libgit2/src/libgit2/transports/{auth_negotiate.c → auth_gssapi.c} +32 -32
  129. data/vendor/libgit2/src/libgit2/transports/auth_negotiate.h +1 -1
  130. data/vendor/libgit2/src/libgit2/transports/auth_ntlm.h +1 -1
  131. data/vendor/libgit2/src/libgit2/transports/{auth_ntlm.c → auth_ntlmclient.c} +12 -12
  132. data/vendor/libgit2/src/libgit2/transports/auth_sspi.c +341 -0
  133. data/vendor/libgit2/src/libgit2/transports/git.c +7 -8
  134. data/vendor/libgit2/src/libgit2/transports/http.c +7 -2
  135. data/vendor/libgit2/src/libgit2/transports/httpclient.c +5 -0
  136. data/vendor/libgit2/src/libgit2/transports/local.c +13 -4
  137. data/vendor/libgit2/src/libgit2/transports/smart.c +33 -27
  138. data/vendor/libgit2/src/libgit2/transports/smart.h +23 -8
  139. data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +136 -17
  140. data/vendor/libgit2/src/libgit2/transports/smart_protocol.c +154 -47
  141. data/vendor/libgit2/src/libgit2/transports/ssh.c +3 -3
  142. data/vendor/libgit2/src/libgit2/transports/winhttp.c +14 -15
  143. data/vendor/libgit2/src/libgit2/tree-cache.c +26 -16
  144. data/vendor/libgit2/src/libgit2/tree-cache.h +5 -3
  145. data/vendor/libgit2/src/libgit2/tree.c +1 -1
  146. data/vendor/libgit2/src/libgit2/worktree.c +25 -10
  147. data/vendor/libgit2/src/util/alloc.c +65 -6
  148. data/vendor/libgit2/src/util/alloc.h +34 -9
  149. data/vendor/libgit2/src/util/allocators/failalloc.c +0 -60
  150. data/vendor/libgit2/src/util/allocators/failalloc.h +0 -6
  151. data/vendor/libgit2/src/util/allocators/stdalloc.c +2 -105
  152. data/vendor/libgit2/src/util/allocators/win32_leakcheck.c +0 -68
  153. data/vendor/libgit2/src/util/array.h +6 -1
  154. data/vendor/libgit2/src/util/cc-compat.h +2 -0
  155. data/vendor/libgit2/src/util/filebuf.c +6 -1
  156. data/vendor/libgit2/src/util/filebuf.h +19 -6
  157. data/vendor/libgit2/src/util/fs_path.c +1 -1
  158. data/vendor/libgit2/src/util/futils.c +8 -5
  159. data/vendor/libgit2/src/util/git2_features.h.in +9 -3
  160. data/vendor/libgit2/src/util/net.c +308 -157
  161. data/vendor/libgit2/src/util/net.h +25 -0
  162. data/vendor/libgit2/src/util/posix.c +54 -0
  163. data/vendor/libgit2/src/util/posix.h +22 -0
  164. data/vendor/libgit2/src/util/rand.c +6 -4
  165. data/vendor/libgit2/src/util/staticstr.h +66 -0
  166. data/vendor/libgit2/src/util/util.c +15 -10
  167. data/vendor/libgit2/src/util/util.h +24 -16
  168. data/vendor/libgit2/src/util/win32/error.c +1 -1
  169. data/vendor/libgit2/src/util/win32/path_w32.c +8 -8
  170. data/vendor/libgit2/src/util/win32/posix_w32.c +1 -1
  171. data/vendor/libgit2/src/util/win32/utf-conv.c +73 -75
  172. data/vendor/libgit2/src/util/win32/utf-conv.h +81 -14
  173. data/vendor/libgit2/src/util/win32/w32_util.c +1 -1
  174. metadata +29 -23
  175. data/vendor/libgit2/cmake/SelectWinHTTP.cmake +0 -17
  176. data/vendor/libgit2/src/libgit2/netops.c +0 -124
  177. data/vendor/libgit2/src/libgit2/netops.h +0 -68
  178. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiff.h +0 -0
  179. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.h +0 -0
  180. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xinclude.h +0 -0
  181. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.h +0 -0
  182. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xtypes.h +0 -0
@@ -24,9 +24,10 @@
24
24
  #cmakedefine GIT_REGEX_PCRE2
25
25
  #cmakedefine GIT_REGEX_BUILTIN 1
26
26
 
27
- #cmakedefine GIT_QSORT_R_BSD
28
- #cmakedefine GIT_QSORT_R_GNU
29
- #cmakedefine GIT_QSORT_S
27
+ #cmakedefine GIT_QSORT_BSD
28
+ #cmakedefine GIT_QSORT_GNU
29
+ #cmakedefine GIT_QSORT_C11
30
+ #cmakedefine GIT_QSORT_MSC
30
31
 
31
32
  #cmakedefine GIT_SSH 1
32
33
  #cmakedefine GIT_SSH_MEMORY_CREDENTIALS 1
@@ -41,6 +42,7 @@
41
42
  #cmakedefine GIT_OPENSSL_DYNAMIC 1
42
43
  #cmakedefine GIT_SECURE_TRANSPORT 1
43
44
  #cmakedefine GIT_MBEDTLS 1
45
+ #cmakedefine GIT_SCHANNEL 1
44
46
 
45
47
  #cmakedefine GIT_SHA1_COLLISIONDETECT 1
46
48
  #cmakedefine GIT_SHA1_WIN32 1
@@ -59,4 +61,8 @@
59
61
  #cmakedefine GIT_RAND_GETENTROPY 1
60
62
  #cmakedefine GIT_RAND_GETLOADAVG 1
61
63
 
64
+ #cmakedefine GIT_IO_POLL 1
65
+ #cmakedefine GIT_IO_WSAPOLL 1
66
+ #cmakedefine GIT_IO_SELECT 1
67
+
62
68
  #endif
@@ -19,6 +19,80 @@
19
19
  #define DEFAULT_PORT_GIT "9418"
20
20
  #define DEFAULT_PORT_SSH "22"
21
21
 
22
+ #define GIT_NET_URL_PARSER_INIT { 0 }
23
+
24
+ typedef struct {
25
+ int hierarchical : 1;
26
+
27
+ const char *scheme;
28
+ const char *user;
29
+ const char *password;
30
+ const char *host;
31
+ const char *port;
32
+ const char *path;
33
+ const char *query;
34
+ const char *fragment;
35
+
36
+ size_t scheme_len;
37
+ size_t user_len;
38
+ size_t password_len;
39
+ size_t host_len;
40
+ size_t port_len;
41
+ size_t path_len;
42
+ size_t query_len;
43
+ size_t fragment_len;
44
+ } git_net_url_parser;
45
+
46
+ bool git_net_hostname_matches_cert(
47
+ const char *hostname,
48
+ const char *pattern)
49
+ {
50
+ for (;;) {
51
+ char c = git__tolower(*pattern++);
52
+
53
+ if (c == '\0')
54
+ return *hostname ? false : true;
55
+
56
+ if (c == '*') {
57
+ c = *pattern;
58
+
59
+ /* '*' at the end matches everything left */
60
+ if (c == '\0')
61
+ return true;
62
+
63
+ /*
64
+ * We've found a pattern, so move towards the
65
+ * next matching char. The '.' is handled
66
+ * specially because wildcards aren't allowed
67
+ * to cross subdomains.
68
+ */
69
+ while(*hostname) {
70
+ char h = git__tolower(*hostname);
71
+
72
+ if (h == c)
73
+ return git_net_hostname_matches_cert(hostname++, pattern);
74
+ else if (h == '.')
75
+ return git_net_hostname_matches_cert(hostname, pattern);
76
+
77
+ hostname++;
78
+ }
79
+
80
+ return false;
81
+ }
82
+
83
+ if (c != git__tolower(*hostname++))
84
+ return false;
85
+ }
86
+
87
+ return false;
88
+ }
89
+
90
+ #define is_valid_scheme_char(c) \
91
+ (((c) >= 'a' && (c) <= 'z') || \
92
+ ((c) >= 'A' && (c) <= 'Z') || \
93
+ ((c) >= '0' && (c) <= '9') || \
94
+ (c) == '+' || (c) == '-' || (c) == '.')
95
+
22
96
  bool git_net_str_is_url(const char *str)
23
97
  {
24
98
  const char *c;
@@ -27,10 +101,7 @@ bool git_net_str_is_url(const char *str)
27
101
  if (*c == ':' && *(c+1) == '/' && *(c+2) == '/')
28
102
  return true;
29
103
 
30
- if ((*c < 'a' || *c > 'z') &&
31
- (*c < 'A' || *c > 'Z') &&
32
- (*c < '0' || *c > '9') &&
33
- (*c != '+' && *c != '-' && *c != '.'))
104
+ if (!is_valid_scheme_char(*c))
34
105
  break;
35
106
  }
36
107
 
@@ -53,6 +124,16 @@ static const char *default_port_for_scheme(const char *scheme)
53
124
  return NULL;
54
125
  }
55
126
 
127
+ static bool is_ssh_scheme(const char *scheme, size_t scheme_len)
128
+ {
129
+ if (!scheme_len)
130
+ return false;
131
+
132
+ return strncasecmp(scheme, "ssh", scheme_len) == 0 ||
133
+ strncasecmp(scheme, "ssh+git", scheme_len) == 0 ||
134
+ strncasecmp(scheme, "git+ssh", scheme_len) == 0;
135
+ }
136
+
56
137
  int git_net_url_dup(git_net_url *out, git_net_url *in)
57
138
  {
58
139
  if (in->scheme) {
@@ -100,12 +181,9 @@ static int url_invalid(const char *message)
100
181
  }
101
182
 
102
183
  static int url_parse_authority(
103
- const char **user_start, size_t *user_len,
104
- const char **password_start, size_t *password_len,
105
- const char **host_start, size_t *host_len,
106
- const char **port_start, size_t *port_len,
107
- const char *authority_start, size_t len,
108
- const char *scheme_start, size_t scheme_len)
184
+ git_net_url_parser *parser,
185
+ const char *authority,
186
+ size_t len)
109
187
  {
110
188
  const char *c, *hostport_end, *host_end = NULL,
111
189
  *userpass_end, *user_end = NULL;
@@ -121,14 +199,14 @@ static int url_parse_authority(
121
199
  * walk the authority backwards so that we can parse google code's
122
200
  * ssh urls that are not rfc compliant and allow @ in the username
123
201
  */
124
- for (hostport_end = authority_start + len, c = hostport_end - 1;
125
- c >= authority_start && !user_end;
202
+ for (hostport_end = authority + len, c = hostport_end - 1;
203
+ c >= authority && !user_end;
126
204
  c--) {
127
205
  switch (state) {
128
206
  case HOSTPORT:
129
207
  if (*c == ':') {
130
- *port_start = c + 1;
131
- *port_len = hostport_end - *port_start;
208
+ parser->port = c + 1;
209
+ parser->port_len = hostport_end - parser->port;
132
210
  host_end = c;
133
211
  state = HOST;
134
212
  break;
@@ -156,9 +234,10 @@ static int url_parse_authority(
156
234
  }
157
235
 
158
236
  else if (*c == '@') {
159
- *host_start = c + 1;
160
- *host_len = host_end ? host_end - *host_start :
161
- hostport_end - *host_start;
237
+ parser->host = c + 1;
238
+ parser->host_len = host_end ?
239
+ host_end - parser->host :
240
+ hostport_end - parser->host;
162
241
  userpass_end = c;
163
242
  state = USERPASS;
164
243
  }
@@ -171,8 +250,8 @@ static int url_parse_authority(
171
250
 
172
251
  case IPV6:
173
252
  if (*c == '[') {
174
- *host_start = c + 1;
175
- *host_len = host_end - *host_start;
253
+ parser->host = c + 1;
254
+ parser->host_len = host_end - parser->host;
176
255
  state = HOST_END;
177
256
  }
178
257
 
@@ -196,12 +275,12 @@ static int url_parse_authority(
196
275
 
197
276
  case USERPASS:
198
277
  if (*c == '@' &&
199
- strncasecmp(scheme_start, "ssh", scheme_len))
278
+ !is_ssh_scheme(parser->scheme, parser->scheme_len))
200
279
  return url_invalid("malformed hostname");
201
280
 
202
281
  if (*c == ':') {
203
- *password_start = c + 1;
204
- *password_len = userpass_end - *password_start;
282
+ parser->password = c + 1;
283
+ parser->password_len = userpass_end - parser->password;
205
284
  user_end = c;
206
285
  state = USER;
207
286
  break;
@@ -216,24 +295,24 @@ static int url_parse_authority(
216
295
 
217
296
  switch (state) {
218
297
  case HOSTPORT:
219
- *host_start = authority_start;
220
- *host_len = (hostport_end - *host_start);
298
+ parser->host = authority;
299
+ parser->host_len = (hostport_end - parser->host);
221
300
  break;
222
301
  case HOST:
223
- *host_start = authority_start;
224
- *host_len = (host_end - *host_start);
302
+ parser->host = authority;
303
+ parser->host_len = (host_end - parser->host);
225
304
  break;
226
305
  case IPV6:
227
306
  return url_invalid("malformed hostname");
228
307
  case HOST_END:
229
308
  break;
230
309
  case USERPASS:
231
- *user_start = authority_start;
232
- *user_len = (userpass_end - *user_start);
310
+ parser->user = authority;
311
+ parser->user_len = (userpass_end - parser->user);
233
312
  break;
234
313
  case USER:
235
- *user_start = authority_start;
236
- *user_len = (user_end - *user_start);
314
+ parser->user = authority;
315
+ parser->user_len = (user_end - parser->user);
237
316
  break;
238
317
  default:
239
318
  GIT_ASSERT(!"unhandled state");
@@ -242,97 +321,30 @@ static int url_parse_authority(
242
321
  return 0;
243
322
  }
244
323
 
245
- int git_net_url_parse(git_net_url *url, const char *given)
324
+ static int url_parse_path(
325
+ git_net_url_parser *parser,
326
+ const char *path,
327
+ size_t len)
246
328
  {
247
- const char *c, *scheme_start, *authority_start, *user_start,
248
- *password_start, *host_start, *port_start, *path_start,
249
- *query_start, *fragment_start, *default_port;
250
- git_str scheme = GIT_STR_INIT, user = GIT_STR_INIT,
251
- password = GIT_STR_INIT, host = GIT_STR_INIT,
252
- port = GIT_STR_INIT, path = GIT_STR_INIT,
253
- query = GIT_STR_INIT, fragment = GIT_STR_INIT;
254
- size_t scheme_len = 0, user_len = 0, password_len = 0, host_len = 0,
255
- port_len = 0, path_len = 0, query_len = 0, fragment_len = 0;
256
- bool hierarchical = false;
257
- int error = 0;
329
+ const char *c, *end;
258
330
 
259
- enum {
260
- SCHEME,
261
- AUTHORITY_START, AUTHORITY,
262
- PATH_START, PATH,
263
- QUERY,
264
- FRAGMENT
265
- } state = SCHEME;
331
+ enum { PATH, QUERY, FRAGMENT } state = PATH;
266
332
 
267
- memset(url, 0, sizeof(git_net_url));
333
+ parser->path = path;
334
+ end = path + len;
268
335
 
269
- for (c = scheme_start = given; *c; c++) {
336
+ for (c = path; c < end; c++) {
270
337
  switch (state) {
271
- case SCHEME:
272
- if (*c == ':') {
273
- scheme_len = (c - scheme_start);
274
-
275
- if (*(c+1) == '/' && *(c+2) == '/') {
276
- c += 2;
277
- hierarchical = true;
278
- state = AUTHORITY_START;
279
- } else {
280
- state = PATH_START;
281
- }
282
- } else if ((*c < 'A' || *c > 'Z') &&
283
- (*c < 'a' || *c > 'z') &&
284
- (*c < '0' || *c > '9') &&
285
- (*c != '+' && *c != '-' && *c != '.')) {
286
- /*
287
- * an illegal scheme character means that we
288
- * were just given a relative path
289
- */
290
- path_start = given;
291
- state = PATH;
292
- break;
293
- }
294
- break;
295
-
296
- case AUTHORITY_START:
297
- authority_start = c;
298
- state = AUTHORITY;
299
-
300
- /* fall through */
301
-
302
- case AUTHORITY:
303
- if (*c != '/')
304
- break;
305
-
306
- /*
307
- * authority is sufficiently complex that we parse
308
- * it separately
309
- */
310
- if ((error = url_parse_authority(
311
- &user_start, &user_len,
312
- &password_start,&password_len,
313
- &host_start, &host_len,
314
- &port_start, &port_len,
315
- authority_start, (c - authority_start),
316
- scheme_start, scheme_len)) < 0)
317
- goto done;
318
-
319
- /* fall through */
320
-
321
- case PATH_START:
322
- path_start = c;
323
- state = PATH;
324
- /* fall through */
325
-
326
338
  case PATH:
327
339
  switch (*c) {
328
340
  case '?':
329
- path_len = (c - path_start);
330
- query_start = c + 1;
341
+ parser->path_len = (c - parser->path);
342
+ parser->query = c + 1;
331
343
  state = QUERY;
332
344
  break;
333
345
  case '#':
334
- path_len = (c - path_start);
335
- fragment_start = c + 1;
346
+ parser->path_len = (c - parser->path);
347
+ parser->fragment = c + 1;
336
348
  state = FRAGMENT;
337
349
  break;
338
350
  }
@@ -340,8 +352,8 @@ int git_net_url_parse(git_net_url *url, const char *given)
340
352
 
341
353
  case QUERY:
342
354
  if (*c == '#') {
343
- query_len = (c - query_start);
344
- fragment_start = c + 1;
355
+ parser->query_len = (c - parser->query);
356
+ parser->fragment = c + 1;
345
357
  state = FRAGMENT;
346
358
  }
347
359
  break;
@@ -355,82 +367,70 @@ int git_net_url_parse(git_net_url *url, const char *given)
355
367
  }
356
368
 
357
369
  switch (state) {
358
- case SCHEME:
359
- /*
360
- * if we never saw a ':' then we were given a relative
361
- * path, not a bare scheme
362
- */
363
- path_start = given;
364
- path_len = (c - scheme_start);
365
- break;
366
- case AUTHORITY_START:
367
- break;
368
- case AUTHORITY:
369
- if ((error = url_parse_authority(
370
- &user_start, &user_len,
371
- &password_start,&password_len,
372
- &host_start, &host_len,
373
- &port_start, &port_len,
374
- authority_start, (c - authority_start),
375
- scheme_start, scheme_len)) < 0)
376
- goto done;
377
- break;
378
- case PATH_START:
379
- break;
380
370
  case PATH:
381
- path_len = (c - path_start);
371
+ parser->path_len = (c - parser->path);
382
372
  break;
383
373
  case QUERY:
384
- query_len = (c - query_start);
374
+ parser->query_len = (c - parser->query);
385
375
  break;
386
376
  case FRAGMENT:
387
- fragment_len = (c - fragment_start);
377
+ parser->fragment_len = (c - parser->fragment);
388
378
  break;
389
- default:
390
- GIT_ASSERT(!"unhandled state");
391
379
  }
392
380
 
393
- if (scheme_len) {
394
- if ((error = git_str_put(&scheme, scheme_start, scheme_len)) < 0)
381
+ return 0;
382
+ }
383
+
384
+ static int url_parse_finalize(git_net_url *url, git_net_url_parser *parser)
385
+ {
386
+ git_str scheme = GIT_STR_INIT, user = GIT_STR_INIT,
387
+ password = GIT_STR_INIT, host = GIT_STR_INIT,
388
+ port = GIT_STR_INIT, path = GIT_STR_INIT,
389
+ query = GIT_STR_INIT, fragment = GIT_STR_INIT;
390
+ const char *default_port;
391
+ int error = 0;
392
+
393
+ if (parser->scheme_len) {
394
+ if ((error = git_str_put(&scheme, parser->scheme, parser->scheme_len)) < 0)
395
395
  goto done;
396
396
 
397
397
  git__strntolower(scheme.ptr, scheme.size);
398
398
  }
399
399
 
400
- if (user_len &&
401
- (error = git_str_decode_percent(&user, user_start, user_len)) < 0)
400
+ if (parser->user_len &&
401
+ (error = git_str_decode_percent(&user, parser->user, parser->user_len)) < 0)
402
402
  goto done;
403
403
 
404
- if (password_len &&
405
- (error = git_str_decode_percent(&password, password_start, password_len)) < 0)
404
+ if (parser->password_len &&
405
+ (error = git_str_decode_percent(&password, parser->password, parser->password_len)) < 0)
406
406
  goto done;
407
407
 
408
- if (host_len &&
409
- (error = git_str_decode_percent(&host, host_start, host_len)) < 0)
408
+ if (parser->host_len &&
409
+ (error = git_str_decode_percent(&host, parser->host, parser->host_len)) < 0)
410
410
  goto done;
411
411
 
412
- if (port_len)
413
- error = git_str_put(&port, port_start, port_len);
414
- else if (scheme_len && (default_port = default_port_for_scheme(scheme.ptr)) != NULL)
412
+ if (parser->port_len)
413
+ error = git_str_put(&port, parser->port, parser->port_len);
414
+ else if (parser->scheme_len && (default_port = default_port_for_scheme(scheme.ptr)) != NULL)
415
415
  error = git_str_puts(&port, default_port);
416
416
 
417
417
  if (error < 0)
418
418
  goto done;
419
419
 
420
- if (path_len)
421
- error = git_str_put(&path, path_start, path_len);
422
- else if (hierarchical)
420
+ if (parser->path_len)
421
+ error = git_str_put(&path, parser->path, parser->path_len);
422
+ else if (parser->hierarchical)
423
423
  error = git_str_puts(&path, "/");
424
424
 
425
425
  if (error < 0)
426
426
  goto done;
427
427
 
428
- if (query_len &&
429
- (error = git_str_decode_percent(&query, query_start, query_len)) < 0)
428
+ if (parser->query_len &&
429
+ (error = git_str_decode_percent(&query, parser->query, parser->query_len)) < 0)
430
430
  goto done;
431
431
 
432
- if (fragment_len &&
433
- (error = git_str_decode_percent(&fragment, fragment_start, fragment_len)) < 0)
432
+ if (parser->fragment_len &&
433
+ (error = git_str_decode_percent(&fragment, parser->fragment, parser->fragment_len)) < 0)
434
434
  goto done;
435
435
 
436
436
  url->scheme = git_str_detach(&scheme);
@@ -457,6 +457,157 @@ done:
457
457
  return error;
458
458
  }
459
459
 
460
+ int git_net_url_parse(git_net_url *url, const char *given)
461
+ {
462
+ git_net_url_parser parser = GIT_NET_URL_PARSER_INIT;
463
+ const char *c, *authority, *path;
464
+ size_t authority_len = 0, path_len = 0;
465
+ int error = 0;
466
+
467
+ enum {
468
+ SCHEME_START, SCHEME,
469
+ AUTHORITY_START, AUTHORITY,
470
+ PATH_START, PATH
471
+ } state = SCHEME_START;
472
+
473
+ memset(url, 0, sizeof(git_net_url));
474
+
475
+ for (c = given; *c; c++) {
476
+ switch (state) {
477
+ case SCHEME_START:
478
+ parser.scheme = c;
479
+ state = SCHEME;
480
+
481
+ /* fall through */
482
+
483
+ case SCHEME:
484
+ if (*c == ':') {
485
+ parser.scheme_len = (c - parser.scheme);
486
+
487
+ if (parser.scheme_len &&
488
+ *(c+1) == '/' && *(c+2) == '/') {
489
+ c += 2;
490
+ parser.hierarchical = 1;
491
+ state = AUTHORITY_START;
492
+ } else {
493
+ state = PATH_START;
494
+ }
495
+ } else if (!is_valid_scheme_char(*c)) {
496
+ /*
497
+ * an illegal scheme character means that we
498
+ * were just given a relative path
499
+ */
500
+ path = given;
501
+ state = PATH;
502
+ break;
503
+ }
504
+ break;
505
+
506
+ case AUTHORITY_START:
507
+ authority = c;
508
+ state = AUTHORITY;
509
+
510
+ /* fall through */
511
+ case AUTHORITY:
512
+ if (*c != '/')
513
+ break;
514
+
515
+ authority_len = (c - authority);
516
+
517
+ /* fall through */
518
+ case PATH_START:
519
+ path = c;
520
+ state = PATH;
521
+ break;
522
+
523
+ case PATH:
524
+ break;
525
+
526
+ default:
527
+ GIT_ASSERT(!"unhandled state");
528
+ }
529
+ }
530
+
531
+ switch (state) {
532
+ case SCHEME:
533
+ /*
534
+ * if we never saw a ':' then we were given a relative
535
+ * path, not a bare scheme
536
+ */
537
+ path = given;
538
+ path_len = (c - path);
539
+ break;
540
+ case AUTHORITY_START:
541
+ break;
542
+ case AUTHORITY:
543
+ authority_len = (c - authority);
544
+ break;
545
+ case PATH_START:
546
+ break;
547
+ case PATH:
548
+ path_len = (c - path);
549
+ break;
550
+ default:
551
+ GIT_ASSERT(!"unhandled state");
552
+ }
553
+
554
+ if (authority_len &&
555
+ (error = url_parse_authority(&parser, authority, authority_len)) < 0)
556
+ goto done;
557
+
558
+ if (path_len &&
559
+ (error = url_parse_path(&parser, path, path_len)) < 0)
560
+ goto done;
561
+
562
+ error = url_parse_finalize(url, &parser);
563
+
564
+ done:
565
+ return error;
566
+ }
567
+
568
+ int git_net_url_parse_http(
569
+ git_net_url *url,
570
+ const char *given)
571
+ {
572
+ git_net_url_parser parser = GIT_NET_URL_PARSER_INIT;
573
+ const char *c, *authority, *path = NULL;
574
+ size_t authority_len = 0, path_len = 0;
575
+ int error;
576
+
577
+ /* Hopefully this is a proper URL with a scheme. */
578
+ if (git_net_str_is_url(given))
579
+ return git_net_url_parse(url, given);
580
+
581
+ memset(url, 0, sizeof(git_net_url));
582
+
583
+ /* Without a scheme, we are in the host (authority) section. */
584
+ for (c = authority = given; *c; c++) {
585
+ if (!path && *c == '/') {
586
+ authority_len = (c - authority);
587
+ path = c;
588
+ }
589
+ }
590
+
591
+ if (path)
592
+ path_len = (c - path);
593
+ else
594
+ authority_len = (c - authority);
595
+
596
+ parser.scheme = "http";
597
+ parser.scheme_len = 4;
598
+ parser.hierarchical = 1;
599
+
600
+ if (authority_len &&
601
+ (error = url_parse_authority(&parser, authority, authority_len)) < 0)
602
+ return error;
603
+
604
+ if (path_len &&
605
+ (error = url_parse_path(&parser, path, path_len)) < 0)
606
+ return error;
607
+
608
+ return url_parse_finalize(url, &parser);
609
+ }
610
+
460
611
  static int scp_invalid(const char *message)
461
612
  {
462
613
  git_error_set(GIT_ERROR_NET, "invalid scp-style path: %s", message);
@@ -9,6 +9,23 @@
9
9
 
10
10
  #include "git2_util.h"
11
11
 
12
+ /*
13
+ * Hostname handling
14
+ */
15
+
16
+ /*
17
+ * See if a given hostname matches a certificate name pattern, according
18
+ * to RFC2818 rules (which specifies HTTP over TLS). Mainly, an asterisk
19
+ * matches anything, but is limited to a single url component.
20
+ */
21
+ extern bool git_net_hostname_matches_cert(
22
+ const char *hostname,
23
+ const char *pattern);
24
+
25
+ /*
26
+ * URL handling
27
+ */
28
+
12
29
  typedef struct git_net_url {
13
30
  char *scheme;
14
31
  char *host;
@@ -40,6 +57,14 @@ extern int git_net_url_parse_scp(git_net_url *url, const char *str);
40
57
  */
41
58
  extern int git_net_url_parse_standard_or_scp(git_net_url *url, const char *str);
42
59
 
60
+ /**
61
+ * Parses a string containing an HTTP endpoint that may not be a
62
+ * well-formed URL. For example, "localhost" or "localhost:port".
63
+ */
64
+ extern int git_net_url_parse_http(
65
+ git_net_url *url,
66
+ const char *str);
67
+
43
68
  /** Appends a path and/or query string to the given URL */
44
69
  extern int git_net_url_joinpath(
45
70
  git_net_url *out,