rugged 1.5.0.1 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (250) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/extconf.rb +2 -2
  3. data/ext/rugged/rugged_allocator.c +0 -54
  4. data/ext/rugged/rugged_blame.c +2 -0
  5. data/ext/rugged/rugged_blob.c +3 -0
  6. data/ext/rugged/rugged_commit.c +1 -0
  7. data/ext/rugged/rugged_config.c +2 -0
  8. data/ext/rugged/rugged_diff.c +1 -0
  9. data/ext/rugged/rugged_index.c +2 -0
  10. data/ext/rugged/rugged_patch.c +1 -0
  11. data/ext/rugged/rugged_rebase.c +1 -0
  12. data/ext/rugged/rugged_reference.c +1 -0
  13. data/ext/rugged/rugged_remote.c +1 -0
  14. data/ext/rugged/rugged_repo.c +5 -2
  15. data/ext/rugged/rugged_revwalk.c +5 -1
  16. data/ext/rugged/rugged_submodule.c +1 -0
  17. data/ext/rugged/rugged_tag.c +1 -0
  18. data/ext/rugged/rugged_tree.c +4 -0
  19. data/lib/rugged/index.rb +1 -1
  20. data/lib/rugged/tree.rb +1 -1
  21. data/lib/rugged/version.rb +1 -1
  22. data/vendor/libgit2/CMakeLists.txt +7 -8
  23. data/vendor/libgit2/COPYING +30 -0
  24. data/vendor/libgit2/cmake/CheckPrototypeDefinitionSafe.cmake +16 -0
  25. data/vendor/libgit2/cmake/ExperimentalFeatures.cmake +23 -0
  26. data/vendor/libgit2/cmake/SelectGSSAPI.cmake +3 -3
  27. data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +21 -2
  28. data/vendor/libgit2/cmake/SelectHashes.cmake +4 -0
  29. data/vendor/libgit2/cmake/SelectXdiff.cmake +9 -0
  30. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +2 -0
  31. data/vendor/libgit2/deps/pcre/LICENCE +5 -5
  32. data/vendor/libgit2/deps/pcre/pcre.h +2 -2
  33. data/vendor/libgit2/deps/pcre/pcre_compile.c +6 -3
  34. data/vendor/libgit2/deps/pcre/pcre_exec.c +2 -2
  35. data/vendor/libgit2/deps/xdiff/CMakeLists.txt +28 -0
  36. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/git-xdiff.h +4 -1
  37. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.c +19 -18
  38. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.h +2 -4
  39. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.c +3 -3
  40. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xhistogram.c +7 -18
  41. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmacros.h +18 -1
  42. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmerge.c +24 -22
  43. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xpatience.c +21 -30
  44. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.c +13 -30
  45. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.c +18 -1
  46. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.h +2 -1
  47. data/vendor/libgit2/include/git2/common.h +38 -6
  48. data/vendor/libgit2/include/git2/deprecated.h +6 -0
  49. data/vendor/libgit2/include/git2/diff.h +42 -4
  50. data/vendor/libgit2/include/git2/errors.h +4 -2
  51. data/vendor/libgit2/include/git2/experimental.h +20 -0
  52. data/vendor/libgit2/include/git2/index.h +9 -0
  53. data/vendor/libgit2/include/git2/indexer.h +29 -0
  54. data/vendor/libgit2/include/git2/object.h +28 -2
  55. data/vendor/libgit2/include/git2/odb.h +58 -7
  56. data/vendor/libgit2/include/git2/odb_backend.h +106 -18
  57. data/vendor/libgit2/include/git2/oid.h +116 -16
  58. data/vendor/libgit2/include/git2/remote.h +18 -0
  59. data/vendor/libgit2/include/git2/repository.h +32 -3
  60. data/vendor/libgit2/include/git2/stash.h +60 -6
  61. data/vendor/libgit2/include/git2/strarray.h +0 -13
  62. data/vendor/libgit2/include/git2/sys/alloc.h +0 -34
  63. data/vendor/libgit2/include/git2/sys/commit_graph.h +12 -2
  64. data/vendor/libgit2/include/git2/sys/midx.h +5 -1
  65. data/vendor/libgit2/include/git2/sys/odb_backend.h +1 -1
  66. data/vendor/libgit2/include/git2/sys/stream.h +16 -2
  67. data/vendor/libgit2/include/git2/sys/transport.h +32 -2
  68. data/vendor/libgit2/include/git2/version.h +4 -4
  69. data/vendor/libgit2/include/git2/worktree.h +3 -1
  70. data/vendor/libgit2/include/git2.h +1 -0
  71. data/vendor/libgit2/src/CMakeLists.txt +34 -17
  72. data/vendor/libgit2/src/cli/CMakeLists.txt +5 -2
  73. data/vendor/libgit2/src/cli/cmd_clone.c +22 -6
  74. data/vendor/libgit2/src/cli/cmd_hash_object.c +27 -8
  75. data/vendor/libgit2/src/cli/opt.c +1 -1
  76. data/vendor/libgit2/src/cli/progress.c +9 -8
  77. data/vendor/libgit2/src/cli/progress.h +4 -4
  78. data/vendor/libgit2/src/libgit2/CMakeLists.txt +25 -34
  79. data/vendor/libgit2/src/libgit2/annotated_commit.c +2 -2
  80. data/vendor/libgit2/src/libgit2/annotated_commit.h +1 -1
  81. data/vendor/libgit2/src/libgit2/apply.c +4 -3
  82. data/vendor/libgit2/src/libgit2/attr_file.c +1 -1
  83. data/vendor/libgit2/src/libgit2/attrcache.c +1 -1
  84. data/vendor/libgit2/src/libgit2/blame.c +23 -14
  85. data/vendor/libgit2/src/libgit2/blame_git.c +0 -1
  86. data/vendor/libgit2/src/libgit2/blob.c +4 -2
  87. data/vendor/libgit2/src/libgit2/blob.h +2 -2
  88. data/vendor/libgit2/src/libgit2/branch.c +2 -2
  89. data/vendor/libgit2/src/libgit2/cherrypick.c +3 -3
  90. data/vendor/libgit2/src/libgit2/clone.c +34 -3
  91. data/vendor/libgit2/src/libgit2/commit.c +78 -21
  92. data/vendor/libgit2/src/libgit2/commit.h +25 -7
  93. data/vendor/libgit2/src/libgit2/commit_graph.c +129 -47
  94. data/vendor/libgit2/src/libgit2/commit_graph.h +23 -4
  95. data/vendor/libgit2/src/libgit2/commit_list.c +16 -5
  96. data/vendor/libgit2/src/libgit2/commit_list.h +1 -0
  97. data/vendor/libgit2/src/libgit2/config.c +6 -3
  98. data/vendor/libgit2/src/libgit2/config_file.c +16 -10
  99. data/vendor/libgit2/src/libgit2/describe.c +11 -8
  100. data/vendor/libgit2/src/libgit2/diff.c +19 -6
  101. data/vendor/libgit2/src/libgit2/diff.h +6 -6
  102. data/vendor/libgit2/src/libgit2/diff_file.c +16 -7
  103. data/vendor/libgit2/src/libgit2/diff_generate.c +37 -11
  104. data/vendor/libgit2/src/libgit2/diff_parse.c +20 -4
  105. data/vendor/libgit2/src/libgit2/diff_print.c +26 -7
  106. data/vendor/libgit2/src/libgit2/diff_tform.c +4 -0
  107. data/vendor/libgit2/src/libgit2/diff_xdiff.h +1 -1
  108. data/vendor/libgit2/src/libgit2/email.c +4 -3
  109. data/vendor/libgit2/src/libgit2/errors.c +73 -18
  110. data/vendor/libgit2/src/libgit2/experimental.h.in +13 -0
  111. data/vendor/libgit2/src/libgit2/fetch.c +38 -13
  112. data/vendor/libgit2/src/libgit2/fetch.h +0 -2
  113. data/vendor/libgit2/src/libgit2/fetchhead.c +11 -9
  114. data/vendor/libgit2/src/libgit2/grafts.c +272 -0
  115. data/vendor/libgit2/src/libgit2/grafts.h +36 -0
  116. data/vendor/libgit2/src/libgit2/ident.c +3 -3
  117. data/vendor/libgit2/src/libgit2/index.c +327 -123
  118. data/vendor/libgit2/src/libgit2/index.h +14 -1
  119. data/vendor/libgit2/src/libgit2/indexer.c +116 -46
  120. data/vendor/libgit2/src/libgit2/iterator.c +21 -4
  121. data/vendor/libgit2/src/libgit2/iterator.h +3 -0
  122. data/vendor/libgit2/src/libgit2/libgit2.c +58 -0
  123. data/vendor/libgit2/src/libgit2/merge.c +14 -9
  124. data/vendor/libgit2/src/libgit2/merge_file.c +0 -2
  125. data/vendor/libgit2/src/libgit2/midx.c +68 -38
  126. data/vendor/libgit2/src/libgit2/midx.h +13 -3
  127. data/vendor/libgit2/src/libgit2/mwindow.c +5 -2
  128. data/vendor/libgit2/src/libgit2/mwindow.h +4 -1
  129. data/vendor/libgit2/src/libgit2/notes.c +9 -8
  130. data/vendor/libgit2/src/libgit2/object.c +118 -29
  131. data/vendor/libgit2/src/libgit2/object.h +17 -2
  132. data/vendor/libgit2/src/libgit2/odb.c +224 -55
  133. data/vendor/libgit2/src/libgit2/odb.h +43 -4
  134. data/vendor/libgit2/src/libgit2/odb_loose.c +128 -70
  135. data/vendor/libgit2/src/libgit2/odb_pack.c +111 -46
  136. data/vendor/libgit2/src/libgit2/oid.c +141 -77
  137. data/vendor/libgit2/src/libgit2/oid.h +183 -9
  138. data/vendor/libgit2/src/libgit2/oidarray.c +49 -3
  139. data/vendor/libgit2/src/libgit2/oidarray.h +5 -1
  140. data/vendor/libgit2/src/libgit2/pack-objects.c +31 -13
  141. data/vendor/libgit2/src/libgit2/pack-objects.h +5 -2
  142. data/vendor/libgit2/src/libgit2/pack.c +93 -70
  143. data/vendor/libgit2/src/libgit2/pack.h +29 -15
  144. data/vendor/libgit2/src/libgit2/parse.c +8 -4
  145. data/vendor/libgit2/src/libgit2/parse.h +1 -1
  146. data/vendor/libgit2/src/libgit2/patch.h +7 -1
  147. data/vendor/libgit2/src/libgit2/patch_generate.c +24 -5
  148. data/vendor/libgit2/src/libgit2/patch_parse.c +16 -8
  149. data/vendor/libgit2/src/libgit2/push.c +13 -3
  150. data/vendor/libgit2/src/libgit2/reader.c +1 -1
  151. data/vendor/libgit2/src/libgit2/rebase.c +72 -83
  152. data/vendor/libgit2/src/libgit2/refdb_fs.c +92 -52
  153. data/vendor/libgit2/src/libgit2/reflog.c +7 -5
  154. data/vendor/libgit2/src/libgit2/reflog.h +1 -2
  155. data/vendor/libgit2/src/libgit2/refs.c +9 -0
  156. data/vendor/libgit2/src/libgit2/remote.c +47 -37
  157. data/vendor/libgit2/src/libgit2/remote.h +41 -0
  158. data/vendor/libgit2/src/libgit2/repository.c +784 -329
  159. data/vendor/libgit2/src/libgit2/repository.h +26 -2
  160. data/vendor/libgit2/src/libgit2/reset.c +2 -2
  161. data/vendor/libgit2/src/libgit2/revert.c +8 -11
  162. data/vendor/libgit2/src/libgit2/revparse.c +23 -7
  163. data/vendor/libgit2/src/libgit2/revwalk.c +31 -5
  164. data/vendor/libgit2/src/libgit2/stash.c +209 -33
  165. data/vendor/libgit2/src/libgit2/strarray.c +1 -0
  166. data/vendor/libgit2/src/libgit2/strarray.h +25 -0
  167. data/vendor/libgit2/src/libgit2/streams/mbedtls.c +0 -1
  168. data/vendor/libgit2/src/libgit2/streams/openssl.c +9 -17
  169. data/vendor/libgit2/src/libgit2/streams/openssl_dynamic.c +7 -3
  170. data/vendor/libgit2/src/libgit2/streams/schannel.c +715 -0
  171. data/vendor/libgit2/src/libgit2/streams/schannel.h +28 -0
  172. data/vendor/libgit2/src/libgit2/streams/socket.c +240 -51
  173. data/vendor/libgit2/src/libgit2/streams/socket.h +3 -1
  174. data/vendor/libgit2/src/libgit2/streams/stransport.c +40 -12
  175. data/vendor/libgit2/src/libgit2/streams/tls.c +5 -0
  176. data/vendor/libgit2/src/libgit2/submodule.c +6 -2
  177. data/vendor/libgit2/src/libgit2/submodule.h +3 -3
  178. data/vendor/libgit2/src/libgit2/sysdir.c +294 -7
  179. data/vendor/libgit2/src/libgit2/sysdir.h +41 -9
  180. data/vendor/libgit2/src/libgit2/tag.c +29 -10
  181. data/vendor/libgit2/src/libgit2/tag.h +2 -2
  182. data/vendor/libgit2/src/libgit2/threadstate.c +15 -2
  183. data/vendor/libgit2/src/libgit2/threadstate.h +1 -3
  184. data/vendor/libgit2/src/libgit2/transports/auth.h +1 -2
  185. data/vendor/libgit2/src/libgit2/transports/{auth_negotiate.c → auth_gssapi.c} +32 -32
  186. data/vendor/libgit2/src/libgit2/transports/auth_negotiate.h +1 -1
  187. data/vendor/libgit2/src/libgit2/transports/auth_ntlm.h +1 -1
  188. data/vendor/libgit2/src/libgit2/transports/{auth_ntlm.c → auth_ntlmclient.c} +12 -12
  189. data/vendor/libgit2/src/libgit2/transports/auth_sspi.c +341 -0
  190. data/vendor/libgit2/src/libgit2/transports/git.c +7 -8
  191. data/vendor/libgit2/src/libgit2/transports/http.c +15 -9
  192. data/vendor/libgit2/src/libgit2/transports/httpclient.c +14 -0
  193. data/vendor/libgit2/src/libgit2/transports/httpclient.h +10 -0
  194. data/vendor/libgit2/src/libgit2/transports/local.c +27 -4
  195. data/vendor/libgit2/src/libgit2/transports/smart.c +68 -27
  196. data/vendor/libgit2/src/libgit2/transports/smart.h +33 -9
  197. data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +281 -49
  198. data/vendor/libgit2/src/libgit2/transports/smart_protocol.c +192 -55
  199. data/vendor/libgit2/src/libgit2/transports/ssh.c +334 -102
  200. data/vendor/libgit2/src/libgit2/transports/winhttp.c +22 -18
  201. data/vendor/libgit2/src/libgit2/tree-cache.c +26 -16
  202. data/vendor/libgit2/src/libgit2/tree-cache.h +5 -3
  203. data/vendor/libgit2/src/libgit2/tree.c +23 -17
  204. data/vendor/libgit2/src/libgit2/tree.h +2 -2
  205. data/vendor/libgit2/src/libgit2/worktree.c +30 -10
  206. data/vendor/libgit2/src/util/CMakeLists.txt +6 -1
  207. data/vendor/libgit2/src/util/alloc.c +65 -6
  208. data/vendor/libgit2/src/util/alloc.h +34 -9
  209. data/vendor/libgit2/src/util/allocators/failalloc.c +0 -60
  210. data/vendor/libgit2/src/util/allocators/failalloc.h +0 -6
  211. data/vendor/libgit2/src/util/allocators/stdalloc.c +2 -105
  212. data/vendor/libgit2/src/util/allocators/win32_leakcheck.c +0 -68
  213. data/vendor/libgit2/src/util/array.h +6 -1
  214. data/vendor/libgit2/src/util/cc-compat.h +2 -0
  215. data/vendor/libgit2/src/util/filebuf.c +6 -1
  216. data/vendor/libgit2/src/util/filebuf.h +19 -6
  217. data/vendor/libgit2/src/util/fs_path.c +2 -2
  218. data/vendor/libgit2/src/util/futils.c +8 -8
  219. data/vendor/libgit2/src/{features.h.in → util/git2_features.h.in} +9 -3
  220. data/vendor/libgit2/src/util/git2_util.h +2 -2
  221. data/vendor/libgit2/src/util/hash/openssl.c +4 -3
  222. data/vendor/libgit2/src/util/hash/rfc6234/sha.h +0 -112
  223. data/vendor/libgit2/src/util/hash.h +13 -0
  224. data/vendor/libgit2/src/util/net.c +492 -87
  225. data/vendor/libgit2/src/util/net.h +32 -0
  226. data/vendor/libgit2/src/util/posix.c +54 -0
  227. data/vendor/libgit2/src/util/posix.h +24 -0
  228. data/vendor/libgit2/src/util/rand.c +10 -4
  229. data/vendor/libgit2/src/util/regexp.c +3 -3
  230. data/vendor/libgit2/src/util/staticstr.h +66 -0
  231. data/vendor/libgit2/src/util/thread.h +20 -19
  232. data/vendor/libgit2/src/util/util.c +15 -10
  233. data/vendor/libgit2/src/util/util.h +25 -16
  234. data/vendor/libgit2/src/util/win32/error.c +1 -1
  235. data/vendor/libgit2/src/util/win32/path_w32.c +8 -8
  236. data/vendor/libgit2/src/util/win32/posix_w32.c +1 -1
  237. data/vendor/libgit2/src/util/win32/utf-conv.c +73 -75
  238. data/vendor/libgit2/src/util/win32/utf-conv.h +81 -14
  239. data/vendor/libgit2/src/util/win32/w32_util.c +1 -1
  240. metadata +34 -26
  241. data/vendor/libgit2/cmake/SelectWinHTTP.cmake +0 -17
  242. data/vendor/libgit2/src/libgit2/netops.c +0 -124
  243. data/vendor/libgit2/src/libgit2/netops.h +0 -68
  244. data/vendor/libgit2/src/util/win32/findfile.c +0 -286
  245. data/vendor/libgit2/src/util/win32/findfile.h +0 -22
  246. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiff.h +0 -0
  247. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.h +0 -0
  248. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xinclude.h +0 -0
  249. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.h +0 -0
  250. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xtypes.h +0 -0
@@ -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) {
@@ -93,124 +174,440 @@ int git_net_url_dup(git_net_url *out, git_net_url *in)
93
174
  return 0;
94
175
  }
95
176
 
96
- int git_net_url_parse(git_net_url *url, const char *given)
177
+ static int url_invalid(const char *message)
97
178
  {
98
- struct http_parser_url u = {0};
99
- bool has_scheme, has_host, has_port, has_path, has_query, has_userinfo;
100
- git_str scheme = GIT_STR_INIT,
101
- host = GIT_STR_INIT,
102
- port = GIT_STR_INIT,
103
- path = GIT_STR_INIT,
104
- username = GIT_STR_INIT,
105
- password = GIT_STR_INIT,
106
- query = GIT_STR_INIT;
107
- int error = GIT_EINVALIDSPEC;
108
-
109
- if (http_parser_parse_url(given, strlen(given), false, &u)) {
110
- git_error_set(GIT_ERROR_NET, "malformed URL '%s'", given);
111
- goto done;
112
- }
179
+ git_error_set(GIT_ERROR_NET, "invalid url: %s", message);
180
+ return GIT_EINVALIDSPEC;
181
+ }
113
182
 
114
- has_scheme = !!(u.field_set & (1 << UF_SCHEMA));
115
- has_host = !!(u.field_set & (1 << UF_HOST));
116
- has_port = !!(u.field_set & (1 << UF_PORT));
117
- has_path = !!(u.field_set & (1 << UF_PATH));
118
- has_query = !!(u.field_set & (1 << UF_QUERY));
119
- has_userinfo = !!(u.field_set & (1 << UF_USERINFO));
183
+ static int url_parse_authority(
184
+ git_net_url_parser *parser,
185
+ const char *authority,
186
+ size_t len)
187
+ {
188
+ const char *c, *hostport_end, *host_end = NULL,
189
+ *userpass_end, *user_end = NULL;
120
190
 
121
- if (has_scheme) {
122
- const char *url_scheme = given + u.field_data[UF_SCHEMA].off;
123
- size_t url_scheme_len = u.field_data[UF_SCHEMA].len;
124
- git_str_put(&scheme, url_scheme, url_scheme_len);
125
- git__strntolower(scheme.ptr, scheme.size);
126
- } else {
127
- git_error_set(GIT_ERROR_NET, "malformed URL '%s'", given);
128
- goto done;
129
- }
191
+ enum {
192
+ HOSTPORT, HOST, IPV6, HOST_END, USERPASS, USER
193
+ } state = HOSTPORT;
130
194
 
131
- if (has_host) {
132
- const char *url_host = given + u.field_data[UF_HOST].off;
133
- size_t url_host_len = u.field_data[UF_HOST].len;
134
- git_str_decode_percent(&host, url_host, url_host_len);
135
- }
195
+ if (len == 0)
196
+ return 0;
136
197
 
137
- if (has_port) {
138
- const char *url_port = given + u.field_data[UF_PORT].off;
139
- size_t url_port_len = u.field_data[UF_PORT].len;
140
- git_str_put(&port, url_port, url_port_len);
141
- } else {
142
- const char *default_port = default_port_for_scheme(scheme.ptr);
198
+ /*
199
+ * walk the authority backwards so that we can parse google code's
200
+ * ssh urls that are not rfc compliant and allow @ in the username
201
+ */
202
+ for (hostport_end = authority + len, c = hostport_end - 1;
203
+ c >= authority && !user_end;
204
+ c--) {
205
+ switch (state) {
206
+ case HOSTPORT:
207
+ if (*c == ':') {
208
+ parser->port = c + 1;
209
+ parser->port_len = hostport_end - parser->port;
210
+ host_end = c;
211
+ state = HOST;
212
+ break;
213
+ }
143
214
 
144
- if (default_port == NULL) {
145
- git_error_set(GIT_ERROR_NET, "unknown scheme for URL '%s'", given);
146
- goto done;
215
+ /*
216
+ * if we've only seen digits then we don't know
217
+ * if we're parsing just a host or a host and port.
218
+ * if we see a non-digit, then we're in a host,
219
+ * otherwise, fall through to possibly match the
220
+ * "@" (user/host separator).
221
+ */
222
+
223
+ if (*c < '0' || *c > '9') {
224
+ host_end = hostport_end;
225
+ state = HOST;
226
+ }
227
+
228
+ /* fall through */
229
+
230
+ case HOST:
231
+ if (*c == ']' && host_end == c + 1) {
232
+ host_end = c;
233
+ state = IPV6;
234
+ }
235
+
236
+ else if (*c == '@') {
237
+ parser->host = c + 1;
238
+ parser->host_len = host_end ?
239
+ host_end - parser->host :
240
+ hostport_end - parser->host;
241
+ userpass_end = c;
242
+ state = USERPASS;
243
+ }
244
+
245
+ else if (*c == '[' || *c == ']' || *c == ':') {
246
+ return url_invalid("malformed hostname");
247
+ }
248
+
249
+ break;
250
+
251
+ case IPV6:
252
+ if (*c == '[') {
253
+ parser->host = c + 1;
254
+ parser->host_len = host_end - parser->host;
255
+ state = HOST_END;
256
+ }
257
+
258
+ else if ((*c < '0' || *c > '9') &&
259
+ (*c < 'a' || *c > 'f') &&
260
+ (*c < 'A' || *c > 'F') &&
261
+ (*c != ':')) {
262
+ return url_invalid("malformed hostname");
263
+ }
264
+
265
+ break;
266
+
267
+ case HOST_END:
268
+ if (*c == '@') {
269
+ userpass_end = c;
270
+ state = USERPASS;
271
+ break;
272
+ }
273
+
274
+ return url_invalid("malformed hostname");
275
+
276
+ case USERPASS:
277
+ if (*c == '@' &&
278
+ !is_ssh_scheme(parser->scheme, parser->scheme_len))
279
+ return url_invalid("malformed hostname");
280
+
281
+ if (*c == ':') {
282
+ parser->password = c + 1;
283
+ parser->password_len = userpass_end - parser->password;
284
+ user_end = c;
285
+ state = USER;
286
+ break;
287
+ }
288
+
289
+ break;
290
+
291
+ default:
292
+ GIT_ASSERT(!"unhandled state");
147
293
  }
294
+ }
148
295
 
149
- git_str_puts(&port, default_port);
296
+ switch (state) {
297
+ case HOSTPORT:
298
+ parser->host = authority;
299
+ parser->host_len = (hostport_end - parser->host);
300
+ break;
301
+ case HOST:
302
+ parser->host = authority;
303
+ parser->host_len = (host_end - parser->host);
304
+ break;
305
+ case IPV6:
306
+ return url_invalid("malformed hostname");
307
+ case HOST_END:
308
+ break;
309
+ case USERPASS:
310
+ parser->user = authority;
311
+ parser->user_len = (userpass_end - parser->user);
312
+ break;
313
+ case USER:
314
+ parser->user = authority;
315
+ parser->user_len = (user_end - parser->user);
316
+ break;
317
+ default:
318
+ GIT_ASSERT(!"unhandled state");
150
319
  }
151
320
 
152
- if (has_path) {
153
- const char *url_path = given + u.field_data[UF_PATH].off;
154
- size_t url_path_len = u.field_data[UF_PATH].len;
155
- git_str_put(&path, url_path, url_path_len);
156
- } else {
157
- git_str_puts(&path, "/");
321
+ return 0;
322
+ }
323
+
324
+ static int url_parse_path(
325
+ git_net_url_parser *parser,
326
+ const char *path,
327
+ size_t len)
328
+ {
329
+ const char *c, *end;
330
+
331
+ enum { PATH, QUERY, FRAGMENT } state = PATH;
332
+
333
+ parser->path = path;
334
+ end = path + len;
335
+
336
+ for (c = path; c < end; c++) {
337
+ switch (state) {
338
+ case PATH:
339
+ switch (*c) {
340
+ case '?':
341
+ parser->path_len = (c - parser->path);
342
+ parser->query = c + 1;
343
+ state = QUERY;
344
+ break;
345
+ case '#':
346
+ parser->path_len = (c - parser->path);
347
+ parser->fragment = c + 1;
348
+ state = FRAGMENT;
349
+ break;
350
+ }
351
+ break;
352
+
353
+ case QUERY:
354
+ if (*c == '#') {
355
+ parser->query_len = (c - parser->query);
356
+ parser->fragment = c + 1;
357
+ state = FRAGMENT;
358
+ }
359
+ break;
360
+
361
+ case FRAGMENT:
362
+ break;
363
+
364
+ default:
365
+ GIT_ASSERT(!"unhandled state");
366
+ }
158
367
  }
159
368
 
160
- if (has_query) {
161
- const char *url_query = given + u.field_data[UF_QUERY].off;
162
- size_t url_query_len = u.field_data[UF_QUERY].len;
163
- git_str_decode_percent(&query, url_query, url_query_len);
369
+ switch (state) {
370
+ case PATH:
371
+ parser->path_len = (c - parser->path);
372
+ break;
373
+ case QUERY:
374
+ parser->query_len = (c - parser->query);
375
+ break;
376
+ case FRAGMENT:
377
+ parser->fragment_len = (c - parser->fragment);
378
+ break;
164
379
  }
165
380
 
166
- if (has_userinfo) {
167
- const char *url_userinfo = given + u.field_data[UF_USERINFO].off;
168
- size_t url_userinfo_len = u.field_data[UF_USERINFO].len;
169
- const char *colon = memchr(url_userinfo, ':', url_userinfo_len);
381
+ return 0;
382
+ }
170
383
 
171
- if (colon) {
172
- const char *url_username = url_userinfo;
173
- size_t url_username_len = colon - url_userinfo;
174
- const char *url_password = colon + 1;
175
- size_t url_password_len = url_userinfo_len - (url_username_len + 1);
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;
176
392
 
177
- git_str_decode_percent(&username, url_username, url_username_len);
178
- git_str_decode_percent(&password, url_password, url_password_len);
179
- } else {
180
- git_str_decode_percent(&username, url_userinfo, url_userinfo_len);
181
- }
393
+ if (parser->scheme_len) {
394
+ if ((error = git_str_put(&scheme, parser->scheme, parser->scheme_len)) < 0)
395
+ goto done;
396
+
397
+ git__strntolower(scheme.ptr, scheme.size);
182
398
  }
183
399
 
184
- if (git_str_oom(&scheme) ||
185
- git_str_oom(&host) ||
186
- git_str_oom(&port) ||
187
- git_str_oom(&path) ||
188
- git_str_oom(&query) ||
189
- git_str_oom(&username) ||
190
- git_str_oom(&password))
191
- return -1;
400
+ if (parser->user_len &&
401
+ (error = git_str_decode_percent(&user, parser->user, parser->user_len)) < 0)
402
+ goto done;
403
+
404
+ if (parser->password_len &&
405
+ (error = git_str_decode_percent(&password, parser->password, parser->password_len)) < 0)
406
+ goto done;
407
+
408
+ if (parser->host_len &&
409
+ (error = git_str_decode_percent(&host, parser->host, parser->host_len)) < 0)
410
+ goto done;
411
+
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
+ error = git_str_puts(&port, default_port);
416
+
417
+ if (error < 0)
418
+ goto done;
419
+
420
+ if (parser->path_len)
421
+ error = git_str_put(&path, parser->path, parser->path_len);
422
+ else if (parser->hierarchical)
423
+ error = git_str_puts(&path, "/");
424
+
425
+ if (error < 0)
426
+ goto done;
427
+
428
+ if (parser->query_len &&
429
+ (error = git_str_decode_percent(&query, parser->query, parser->query_len)) < 0)
430
+ goto done;
431
+
432
+ if (parser->fragment_len &&
433
+ (error = git_str_decode_percent(&fragment, parser->fragment, parser->fragment_len)) < 0)
434
+ goto done;
192
435
 
193
436
  url->scheme = git_str_detach(&scheme);
194
437
  url->host = git_str_detach(&host);
195
438
  url->port = git_str_detach(&port);
196
439
  url->path = git_str_detach(&path);
197
440
  url->query = git_str_detach(&query);
198
- url->username = git_str_detach(&username);
441
+ url->fragment = git_str_detach(&fragment);
442
+ url->username = git_str_detach(&user);
199
443
  url->password = git_str_detach(&password);
200
444
 
201
445
  error = 0;
202
446
 
203
447
  done:
204
448
  git_str_dispose(&scheme);
449
+ git_str_dispose(&user);
450
+ git_str_dispose(&password);
205
451
  git_str_dispose(&host);
206
452
  git_str_dispose(&port);
207
453
  git_str_dispose(&path);
208
454
  git_str_dispose(&query);
209
- git_str_dispose(&username);
210
- git_str_dispose(&password);
455
+ git_str_dispose(&fragment);
456
+
457
+ return error;
458
+ }
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:
211
565
  return error;
212
566
  }
213
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
+
214
611
  static int scp_invalid(const char *message)
215
612
  {
216
613
  git_error_set(GIT_ERROR_NET, "invalid scp-style path: %s", message);
@@ -374,7 +771,7 @@ int git_net_url_parse_scp(git_net_url *url, const char *given)
374
771
  break;
375
772
 
376
773
  default:
377
- GIT_ASSERT("unhandled state");
774
+ GIT_ASSERT(!"unhandled state");
378
775
  }
379
776
  }
380
777
 
@@ -400,6 +797,13 @@ int git_net_url_parse_scp(git_net_url *url, const char *given)
400
797
  return 0;
401
798
  }
402
799
 
800
+ int git_net_url_parse_standard_or_scp(git_net_url *url, const char *given)
801
+ {
802
+ return git_net_str_is_url(given) ?
803
+ git_net_url_parse(url, given) :
804
+ git_net_url_parse_scp(url, given);
805
+ }
806
+
403
807
  int git_net_url_joinpath(
404
808
  git_net_url *out,
405
809
  git_net_url *one,
@@ -588,7 +992,7 @@ bool git_net_url_is_default_port(git_net_url *url)
588
992
  {
589
993
  const char *default_port;
590
994
 
591
- if ((default_port = default_port_for_scheme(url->scheme)) != NULL)
995
+ if (url->scheme && (default_port = default_port_for_scheme(url->scheme)) != NULL)
592
996
  return (strcmp(url->port, default_port) == 0);
593
997
  else
594
998
  return false;
@@ -744,6 +1148,7 @@ void git_net_url_dispose(git_net_url *url)
744
1148
  git__free(url->port); url->port = NULL;
745
1149
  git__free(url->path); url->path = NULL;
746
1150
  git__free(url->query); url->query = NULL;
1151
+ git__free(url->fragment); url->fragment = NULL;
747
1152
  git__free(url->username); url->username = NULL;
748
1153
  git__free(url->password); url->password = NULL;
749
1154
  }