rugged 1.1.1 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (407) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -0
  3. data/README.md +1 -1
  4. data/ext/rugged/extconf.rb +2 -2
  5. data/ext/rugged/rugged.c +7 -4
  6. data/ext/rugged/rugged_config.c +7 -2
  7. data/ext/rugged/rugged_object.c +1 -1
  8. data/ext/rugged/rugged_remote.c +17 -0
  9. data/ext/rugged/rugged_repo.c +3 -3
  10. data/lib/rugged/repository.rb +2 -2
  11. data/lib/rugged/version.rb +1 -1
  12. data/vendor/libgit2/CMakeLists.txt +103 -271
  13. data/vendor/libgit2/COPYING +149 -24
  14. data/vendor/libgit2/cmake/AddCFlagIfSupported.cmake +21 -21
  15. data/vendor/libgit2/cmake/DefaultCFlags.cmake +154 -0
  16. data/vendor/libgit2/cmake/EnableWarnings.cmake +13 -13
  17. data/vendor/libgit2/cmake/FindCoreFoundation.cmake +13 -13
  18. data/vendor/libgit2/cmake/FindGSSAPI.cmake +171 -287
  19. data/vendor/libgit2/cmake/FindGSSFramework.cmake +13 -13
  20. data/vendor/libgit2/cmake/{FindHTTP_Parser.cmake → FindHTTPParser.cmake} +17 -17
  21. data/vendor/libgit2/cmake/FindIconv.cmake +27 -27
  22. data/vendor/libgit2/cmake/FindLibSSH2.cmake +13 -0
  23. data/vendor/libgit2/cmake/FindPCRE.cmake +13 -13
  24. data/vendor/libgit2/cmake/FindPCRE2.cmake +12 -12
  25. data/vendor/libgit2/cmake/FindPkgLibraries.cmake +19 -19
  26. data/vendor/libgit2/cmake/FindSecurity.cmake +14 -14
  27. data/vendor/libgit2/cmake/FindStatNsec.cmake +12 -18
  28. data/vendor/libgit2/cmake/Findfutimens.cmake +14 -0
  29. data/vendor/libgit2/cmake/FindmbedTLS.cmake +63 -70
  30. data/vendor/libgit2/cmake/IdeSplitSources.cmake +18 -18
  31. data/vendor/libgit2/cmake/PkgBuildConfig.cmake +60 -60
  32. data/vendor/libgit2/cmake/SanitizeBool.cmake +20 -20
  33. data/vendor/libgit2/cmake/SelectGSSAPI.cmake +37 -37
  34. data/vendor/libgit2/cmake/SelectHTTPParser.cmake +19 -0
  35. data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +100 -96
  36. data/vendor/libgit2/cmake/SelectHashes.cmake +39 -48
  37. data/vendor/libgit2/cmake/SelectRegex.cmake +51 -0
  38. data/vendor/libgit2/cmake/SelectSSH.cmake +41 -0
  39. data/vendor/libgit2/cmake/SelectWinHTTP.cmake +17 -0
  40. data/vendor/libgit2/cmake/SelectZlib.cmake +34 -0
  41. data/vendor/libgit2/deps/chromium-zlib/CMakeLists.txt +101 -0
  42. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +32 -20
  43. data/vendor/libgit2/deps/ntlmclient/crypt.h +14 -9
  44. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +20 -20
  45. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.h +3 -3
  46. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +37 -36
  47. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.h +4 -3
  48. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +178 -51
  49. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.h +74 -5
  50. data/vendor/libgit2/deps/ntlmclient/ntlm.c +154 -122
  51. data/vendor/libgit2/deps/ntlmclient/ntlm.h +17 -13
  52. data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +17 -4
  53. data/vendor/libgit2/deps/ntlmclient/unicode.h +10 -4
  54. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +16 -27
  55. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.h +20 -0
  56. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +28 -52
  57. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.h +22 -0
  58. data/vendor/libgit2/deps/pcre/CMakeLists.txt +88 -88
  59. data/vendor/libgit2/deps/winhttp/CMakeLists.txt +14 -16
  60. data/vendor/libgit2/include/git2/apply.h +16 -2
  61. data/vendor/libgit2/include/git2/attr.h +106 -2
  62. data/vendor/libgit2/include/git2/blame.h +97 -43
  63. data/vendor/libgit2/include/git2/blob.h +33 -2
  64. data/vendor/libgit2/include/git2/branch.h +27 -0
  65. data/vendor/libgit2/include/git2/buffer.h +18 -78
  66. data/vendor/libgit2/include/git2/cert.h +43 -6
  67. data/vendor/libgit2/include/git2/checkout.h +32 -13
  68. data/vendor/libgit2/include/git2/clone.h +4 -4
  69. data/vendor/libgit2/include/git2/commit.h +37 -19
  70. data/vendor/libgit2/include/git2/common.h +46 -5
  71. data/vendor/libgit2/include/git2/config.h +19 -3
  72. data/vendor/libgit2/include/git2/credential.h +2 -1
  73. data/vendor/libgit2/include/git2/credential_helpers.h +1 -0
  74. data/vendor/libgit2/include/git2/deprecated.h +326 -6
  75. data/vendor/libgit2/include/git2/describe.h +7 -2
  76. data/vendor/libgit2/include/git2/diff.h +50 -121
  77. data/vendor/libgit2/include/git2/email.h +127 -0
  78. data/vendor/libgit2/include/git2/errors.h +7 -6
  79. data/vendor/libgit2/include/git2/filter.h +69 -18
  80. data/vendor/libgit2/include/git2/graph.h +21 -2
  81. data/vendor/libgit2/include/git2/ignore.h +1 -1
  82. data/vendor/libgit2/include/git2/index.h +13 -7
  83. data/vendor/libgit2/include/git2/indexer.h +19 -0
  84. data/vendor/libgit2/include/git2/merge.h +23 -3
  85. data/vendor/libgit2/include/git2/message.h +2 -0
  86. data/vendor/libgit2/include/git2/notes.h +2 -2
  87. data/vendor/libgit2/include/git2/object.h +23 -0
  88. data/vendor/libgit2/include/git2/odb.h +65 -6
  89. data/vendor/libgit2/include/git2/odb_backend.h +1 -1
  90. data/vendor/libgit2/include/git2/oidarray.h +5 -8
  91. data/vendor/libgit2/include/git2/pack.h +24 -8
  92. data/vendor/libgit2/include/git2/patch.h +16 -0
  93. data/vendor/libgit2/include/git2/pathspec.h +1 -1
  94. data/vendor/libgit2/include/git2/proxy.h +1 -1
  95. data/vendor/libgit2/include/git2/rebase.h +34 -2
  96. data/vendor/libgit2/include/git2/refdb.h +3 -0
  97. data/vendor/libgit2/include/git2/reflog.h +1 -1
  98. data/vendor/libgit2/include/git2/refs.h +8 -4
  99. data/vendor/libgit2/include/git2/remote.h +246 -46
  100. data/vendor/libgit2/include/git2/repository.h +25 -18
  101. data/vendor/libgit2/include/git2/reset.h +2 -2
  102. data/vendor/libgit2/include/git2/revparse.h +5 -5
  103. data/vendor/libgit2/include/git2/revwalk.h +4 -1
  104. data/vendor/libgit2/include/git2/signature.h +1 -1
  105. data/vendor/libgit2/include/git2/stash.h +4 -4
  106. data/vendor/libgit2/include/git2/status.h +124 -62
  107. data/vendor/libgit2/include/git2/stdint.h +3 -3
  108. data/vendor/libgit2/include/git2/submodule.h +16 -2
  109. data/vendor/libgit2/include/git2/sys/commit_graph.h +174 -0
  110. data/vendor/libgit2/include/git2/sys/email.h +45 -0
  111. data/vendor/libgit2/include/git2/sys/filter.h +49 -28
  112. data/vendor/libgit2/include/git2/sys/midx.h +74 -0
  113. data/vendor/libgit2/include/git2/sys/odb_backend.h +9 -5
  114. data/vendor/libgit2/include/git2/sys/remote.h +31 -0
  115. data/vendor/libgit2/include/git2/sys/stream.h +1 -1
  116. data/vendor/libgit2/include/git2/sys/transport.h +26 -34
  117. data/vendor/libgit2/include/git2/tag.h +13 -0
  118. data/vendor/libgit2/include/git2/tree.h +4 -17
  119. data/vendor/libgit2/include/git2/types.h +16 -7
  120. data/vendor/libgit2/include/git2/version.h +4 -4
  121. data/vendor/libgit2/include/git2/worktree.h +13 -2
  122. data/vendor/libgit2/include/git2.h +1 -0
  123. data/vendor/libgit2/src/CMakeLists.txt +192 -290
  124. data/vendor/libgit2/src/alloc.c +21 -8
  125. data/vendor/libgit2/src/allocators/failalloc.c +92 -0
  126. data/vendor/libgit2/src/allocators/failalloc.h +23 -0
  127. data/vendor/libgit2/src/allocators/stdalloc.c +41 -10
  128. data/vendor/libgit2/src/allocators/win32_leakcheck.c +118 -0
  129. data/vendor/libgit2/src/allocators/{win32_crtdbg.h → win32_leakcheck.h} +3 -3
  130. data/vendor/libgit2/src/annotated_commit.c +21 -9
  131. data/vendor/libgit2/src/annotated_commit.h +1 -1
  132. data/vendor/libgit2/src/apply.c +34 -25
  133. data/vendor/libgit2/src/apply.h +2 -2
  134. data/vendor/libgit2/src/array.h +11 -11
  135. data/vendor/libgit2/src/attr.c +204 -82
  136. data/vendor/libgit2/src/attr_file.c +105 -52
  137. data/vendor/libgit2/src/attr_file.h +36 -15
  138. data/vendor/libgit2/src/attrcache.c +55 -45
  139. data/vendor/libgit2/src/attrcache.h +4 -5
  140. data/vendor/libgit2/src/blame.c +15 -9
  141. data/vendor/libgit2/src/blame_git.c +2 -2
  142. data/vendor/libgit2/src/blob.c +76 -52
  143. data/vendor/libgit2/src/blob.h +1 -1
  144. data/vendor/libgit2/src/branch.c +203 -110
  145. data/vendor/libgit2/src/branch.h +15 -3
  146. data/vendor/libgit2/src/buf.c +126 -0
  147. data/vendor/libgit2/src/buf.h +50 -0
  148. data/vendor/libgit2/src/cache.c +2 -2
  149. data/vendor/libgit2/src/cache.h +7 -7
  150. data/vendor/libgit2/src/cc-compat.h +11 -9
  151. data/vendor/libgit2/src/checkout.c +118 -91
  152. data/vendor/libgit2/src/cherrypick.c +16 -12
  153. data/vendor/libgit2/src/clone.c +97 -103
  154. data/vendor/libgit2/src/commit.c +167 -84
  155. data/vendor/libgit2/src/commit.h +24 -1
  156. data/vendor/libgit2/src/commit_graph.c +1224 -0
  157. data/vendor/libgit2/src/commit_graph.h +169 -0
  158. data/vendor/libgit2/src/commit_list.c +48 -3
  159. data/vendor/libgit2/src/commit_list.h +2 -0
  160. data/vendor/libgit2/src/common.h +35 -5
  161. data/vendor/libgit2/src/config.c +119 -64
  162. data/vendor/libgit2/src/config.h +15 -2
  163. data/vendor/libgit2/src/config_cache.c +5 -3
  164. data/vendor/libgit2/src/config_file.c +120 -100
  165. data/vendor/libgit2/src/config_mem.c +9 -9
  166. data/vendor/libgit2/src/config_parse.c +29 -27
  167. data/vendor/libgit2/src/crlf.c +36 -23
  168. data/vendor/libgit2/src/date.c +13 -19
  169. data/vendor/libgit2/src/date.h +33 -0
  170. data/vendor/libgit2/src/delta.c +1 -1
  171. data/vendor/libgit2/src/describe.c +32 -21
  172. data/vendor/libgit2/src/diff.c +71 -183
  173. data/vendor/libgit2/src/diff.h +2 -4
  174. data/vendor/libgit2/src/diff_driver.c +53 -51
  175. data/vendor/libgit2/src/diff_driver.h +3 -3
  176. data/vendor/libgit2/src/diff_file.c +31 -26
  177. data/vendor/libgit2/src/diff_generate.c +76 -23
  178. data/vendor/libgit2/src/diff_generate.h +5 -3
  179. data/vendor/libgit2/src/diff_print.c +120 -95
  180. data/vendor/libgit2/src/diff_stats.c +47 -34
  181. data/vendor/libgit2/src/{message.h → diff_stats.h} +7 -6
  182. data/vendor/libgit2/src/diff_tform.c +18 -16
  183. data/vendor/libgit2/src/diff_xdiff.c +7 -10
  184. data/vendor/libgit2/src/diff_xdiff.h +1 -1
  185. data/vendor/libgit2/src/email.c +315 -0
  186. data/vendor/libgit2/src/email.h +25 -0
  187. data/vendor/libgit2/src/errors.c +37 -32
  188. data/vendor/libgit2/src/features.h.in +11 -2
  189. data/vendor/libgit2/src/fetch.c +77 -26
  190. data/vendor/libgit2/src/fetch.h +1 -1
  191. data/vendor/libgit2/src/fetchhead.c +27 -23
  192. data/vendor/libgit2/src/filebuf.c +36 -34
  193. data/vendor/libgit2/src/filebuf.h +1 -1
  194. data/vendor/libgit2/src/filter.c +278 -132
  195. data/vendor/libgit2/src/filter.h +46 -6
  196. data/vendor/libgit2/src/fs_path.c +2071 -0
  197. data/vendor/libgit2/src/fs_path.h +772 -0
  198. data/vendor/libgit2/src/futils.c +96 -90
  199. data/vendor/libgit2/src/futils.h +27 -15
  200. data/vendor/libgit2/src/graph.c +64 -9
  201. data/vendor/libgit2/src/hash/sha1/collisiondetect.c +5 -5
  202. data/vendor/libgit2/src/hash/sha1/common_crypto.c +5 -5
  203. data/vendor/libgit2/src/hash/sha1/generic.c +2 -2
  204. data/vendor/libgit2/src/hash/sha1/generic.h +1 -1
  205. data/vendor/libgit2/src/hash/sha1/mbedtls.c +13 -13
  206. data/vendor/libgit2/src/hash/sha1/openssl.c +5 -5
  207. data/vendor/libgit2/src/hash/sha1/sha1dc/sha1.c +9 -11
  208. data/vendor/libgit2/src/hash/sha1/win32.c +21 -17
  209. data/vendor/libgit2/src/hash/sha1.h +3 -1
  210. data/vendor/libgit2/src/hash.c +71 -36
  211. data/vendor/libgit2/src/hash.h +13 -13
  212. data/vendor/libgit2/src/hashsig.c +23 -10
  213. data/vendor/libgit2/src/ident.c +30 -20
  214. data/vendor/libgit2/src/ignore.c +63 -46
  215. data/vendor/libgit2/src/ignore.h +2 -2
  216. data/vendor/libgit2/src/index.c +184 -149
  217. data/vendor/libgit2/src/index.h +7 -4
  218. data/vendor/libgit2/src/indexer.c +143 -89
  219. data/vendor/libgit2/src/integer.h +64 -2
  220. data/vendor/libgit2/src/iterator.c +93 -73
  221. data/vendor/libgit2/src/iterator.h +6 -6
  222. data/vendor/libgit2/src/khash.h +3 -12
  223. data/vendor/libgit2/src/{settings.c → libgit2.c} +165 -56
  224. data/vendor/libgit2/src/libgit2.h +15 -0
  225. data/vendor/libgit2/src/mailmap.c +60 -45
  226. data/vendor/libgit2/src/map.h +3 -3
  227. data/vendor/libgit2/src/merge.c +104 -61
  228. data/vendor/libgit2/src/merge.h +3 -15
  229. data/vendor/libgit2/src/merge_driver.c +21 -15
  230. data/vendor/libgit2/src/merge_file.c +24 -6
  231. data/vendor/libgit2/src/message.c +21 -8
  232. data/vendor/libgit2/src/midx.c +501 -18
  233. data/vendor/libgit2/src/midx.h +29 -2
  234. data/vendor/libgit2/src/mwindow.c +103 -59
  235. data/vendor/libgit2/src/mwindow.h +3 -3
  236. data/vendor/libgit2/src/net.c +405 -71
  237. data/vendor/libgit2/src/net.h +26 -5
  238. data/vendor/libgit2/src/netops.c +7 -5
  239. data/vendor/libgit2/src/netops.h +3 -3
  240. data/vendor/libgit2/src/notes.c +40 -49
  241. data/vendor/libgit2/src/object.c +68 -20
  242. data/vendor/libgit2/src/object.h +1 -1
  243. data/vendor/libgit2/src/odb.c +320 -80
  244. data/vendor/libgit2/src/odb.h +17 -3
  245. data/vendor/libgit2/src/odb_loose.c +96 -86
  246. data/vendor/libgit2/src/odb_mempack.c +19 -6
  247. data/vendor/libgit2/src/odb_pack.c +402 -125
  248. data/vendor/libgit2/src/oid.c +16 -8
  249. data/vendor/libgit2/src/oid.h +15 -0
  250. data/vendor/libgit2/src/oidarray.c +10 -1
  251. data/vendor/libgit2/src/pack-objects.c +90 -69
  252. data/vendor/libgit2/src/pack-objects.h +11 -6
  253. data/vendor/libgit2/src/pack.c +337 -127
  254. data/vendor/libgit2/src/pack.h +25 -7
  255. data/vendor/libgit2/src/patch.c +17 -10
  256. data/vendor/libgit2/src/patch.h +1 -0
  257. data/vendor/libgit2/src/patch_generate.c +29 -13
  258. data/vendor/libgit2/src/patch_generate.h +5 -5
  259. data/vendor/libgit2/src/patch_parse.c +26 -25
  260. data/vendor/libgit2/src/path.c +86 -1768
  261. data/vendor/libgit2/src/path.h +39 -635
  262. data/vendor/libgit2/src/pathspec.c +12 -12
  263. data/vendor/libgit2/src/pathspec.h +2 -2
  264. data/vendor/libgit2/src/pool.c +13 -7
  265. data/vendor/libgit2/src/posix.c +14 -6
  266. data/vendor/libgit2/src/posix.h +1 -0
  267. data/vendor/libgit2/src/pqueue.h +1 -1
  268. data/vendor/libgit2/src/proxy.c +4 -1
  269. data/vendor/libgit2/src/proxy.h +1 -1
  270. data/vendor/libgit2/src/push.c +30 -35
  271. data/vendor/libgit2/src/push.h +4 -16
  272. data/vendor/libgit2/src/rand.c +226 -0
  273. data/vendor/libgit2/src/rand.h +37 -0
  274. data/vendor/libgit2/src/reader.c +18 -14
  275. data/vendor/libgit2/src/reader.h +2 -2
  276. data/vendor/libgit2/src/rebase.c +177 -132
  277. data/vendor/libgit2/src/refdb.c +30 -13
  278. data/vendor/libgit2/src/refdb_fs.c +548 -222
  279. data/vendor/libgit2/src/reflog.c +19 -14
  280. data/vendor/libgit2/src/refs.c +107 -72
  281. data/vendor/libgit2/src/refs.h +2 -2
  282. data/vendor/libgit2/src/refspec.c +53 -38
  283. data/vendor/libgit2/src/refspec.h +5 -2
  284. data/vendor/libgit2/src/regexp.c +1 -1
  285. data/vendor/libgit2/src/remote.c +960 -486
  286. data/vendor/libgit2/src/remote.h +16 -10
  287. data/vendor/libgit2/src/repository.c +702 -422
  288. data/vendor/libgit2/src/repository.h +26 -8
  289. data/vendor/libgit2/src/reset.c +16 -12
  290. data/vendor/libgit2/src/revert.c +16 -12
  291. data/vendor/libgit2/src/revparse.c +66 -48
  292. data/vendor/libgit2/src/revwalk.c +39 -22
  293. data/vendor/libgit2/src/runtime.c +162 -0
  294. data/vendor/libgit2/src/runtime.h +62 -0
  295. data/vendor/libgit2/src/settings.h +11 -0
  296. data/vendor/libgit2/src/signature.c +18 -11
  297. data/vendor/libgit2/src/signature.h +1 -1
  298. data/vendor/libgit2/src/sortedcache.c +1 -1
  299. data/vendor/libgit2/src/sortedcache.h +10 -8
  300. data/vendor/libgit2/src/stash.c +39 -38
  301. data/vendor/libgit2/src/status.c +11 -5
  302. data/vendor/libgit2/src/{buffer.c → str.c} +459 -136
  303. data/vendor/libgit2/src/str.h +357 -0
  304. data/vendor/libgit2/src/strarray.c +2 -1
  305. data/vendor/libgit2/src/streams/mbedtls.c +22 -23
  306. data/vendor/libgit2/src/streams/mbedtls.h +1 -1
  307. data/vendor/libgit2/src/streams/openssl.c +101 -201
  308. data/vendor/libgit2/src/streams/openssl.h +9 -1
  309. data/vendor/libgit2/src/streams/openssl_dynamic.c +309 -0
  310. data/vendor/libgit2/src/streams/openssl_dynamic.h +348 -0
  311. data/vendor/libgit2/src/streams/openssl_legacy.c +203 -0
  312. data/vendor/libgit2/src/streams/openssl_legacy.h +63 -0
  313. data/vendor/libgit2/src/streams/registry.c +5 -6
  314. data/vendor/libgit2/src/streams/socket.c +6 -2
  315. data/vendor/libgit2/src/streams/stransport.c +6 -3
  316. data/vendor/libgit2/src/streams/tls.c +5 -3
  317. data/vendor/libgit2/src/submodule.c +290 -212
  318. data/vendor/libgit2/src/submodule.h +10 -10
  319. data/vendor/libgit2/src/sysdir.c +70 -56
  320. data/vendor/libgit2/src/sysdir.h +15 -10
  321. data/vendor/libgit2/src/tag.c +72 -34
  322. data/vendor/libgit2/src/thread.c +140 -0
  323. data/vendor/libgit2/src/thread.h +479 -0
  324. data/vendor/libgit2/src/threadstate.c +84 -0
  325. data/vendor/libgit2/src/threadstate.h +24 -0
  326. data/vendor/libgit2/src/trace.c +3 -16
  327. data/vendor/libgit2/src/trace.h +17 -30
  328. data/vendor/libgit2/src/trailer.c +2 -2
  329. data/vendor/libgit2/src/transaction.c +20 -9
  330. data/vendor/libgit2/src/transport.c +13 -13
  331. data/vendor/libgit2/src/transports/auth.c +8 -10
  332. data/vendor/libgit2/src/transports/auth.h +2 -3
  333. data/vendor/libgit2/src/transports/auth_negotiate.c +23 -17
  334. data/vendor/libgit2/src/transports/auth_ntlm.c +20 -16
  335. data/vendor/libgit2/src/transports/auth_ntlm.h +0 -1
  336. data/vendor/libgit2/src/transports/credential.c +15 -7
  337. data/vendor/libgit2/src/transports/git.c +10 -14
  338. data/vendor/libgit2/src/transports/http.c +56 -34
  339. data/vendor/libgit2/src/transports/http.h +3 -3
  340. data/vendor/libgit2/src/transports/httpclient.c +106 -79
  341. data/vendor/libgit2/src/transports/httpclient.h +1 -1
  342. data/vendor/libgit2/src/transports/local.c +127 -119
  343. data/vendor/libgit2/src/transports/smart.c +61 -144
  344. data/vendor/libgit2/src/transports/smart.h +26 -32
  345. data/vendor/libgit2/src/transports/smart_pkt.c +33 -33
  346. data/vendor/libgit2/src/transports/smart_protocol.c +68 -44
  347. data/vendor/libgit2/src/transports/ssh.c +100 -131
  348. data/vendor/libgit2/src/transports/winhttp.c +86 -82
  349. data/vendor/libgit2/src/tree-cache.c +5 -5
  350. data/vendor/libgit2/src/tree-cache.h +2 -2
  351. data/vendor/libgit2/src/tree.c +150 -116
  352. data/vendor/libgit2/src/tree.h +1 -0
  353. data/vendor/libgit2/src/tsort.c +0 -2
  354. data/vendor/libgit2/src/unix/map.c +3 -3
  355. data/vendor/libgit2/src/unix/posix.h +1 -4
  356. data/vendor/libgit2/src/unix/pthread.h +2 -1
  357. data/vendor/libgit2/src/unix/realpath.c +0 -2
  358. data/vendor/libgit2/src/utf8.c +150 -0
  359. data/vendor/libgit2/src/utf8.h +52 -0
  360. data/vendor/libgit2/src/util.c +68 -144
  361. data/vendor/libgit2/src/util.h +36 -68
  362. data/vendor/libgit2/src/vector.c +23 -19
  363. data/vendor/libgit2/src/vector.h +5 -3
  364. data/vendor/libgit2/src/win32/findfile.c +172 -114
  365. data/vendor/libgit2/src/win32/findfile.h +7 -4
  366. data/vendor/libgit2/src/win32/map.c +1 -1
  367. data/vendor/libgit2/src/win32/msvc-compat.h +9 -1
  368. data/vendor/libgit2/src/win32/path_w32.c +162 -33
  369. data/vendor/libgit2/src/win32/path_w32.h +2 -1
  370. data/vendor/libgit2/src/win32/posix.h +6 -7
  371. data/vendor/libgit2/src/win32/posix_w32.c +26 -33
  372. data/vendor/libgit2/src/win32/precompiled.h +0 -1
  373. data/vendor/libgit2/src/win32/reparse.h +4 -4
  374. data/vendor/libgit2/src/win32/thread.c +24 -15
  375. data/vendor/libgit2/src/win32/thread.h +1 -1
  376. data/vendor/libgit2/src/win32/w32_buffer.c +5 -6
  377. data/vendor/libgit2/src/win32/w32_buffer.h +2 -3
  378. data/vendor/libgit2/src/win32/w32_common.h +18 -9
  379. data/vendor/libgit2/src/win32/{w32_crtdbg_stacktrace.c → w32_leakcheck.c} +269 -33
  380. data/vendor/libgit2/src/win32/w32_leakcheck.h +222 -0
  381. data/vendor/libgit2/src/win32/w32_util.h +6 -6
  382. data/vendor/libgit2/src/worktree.c +138 -105
  383. data/vendor/libgit2/src/worktree.h +1 -1
  384. data/vendor/libgit2/src/xdiff/git-xdiff.h +53 -0
  385. data/vendor/libgit2/src/xdiff/xdiff.h +15 -15
  386. data/vendor/libgit2/src/xdiff/xdiffi.c +134 -108
  387. data/vendor/libgit2/src/xdiff/xemit.c +23 -7
  388. data/vendor/libgit2/src/xdiff/xhistogram.c +87 -78
  389. data/vendor/libgit2/src/xdiff/xinclude.h +1 -12
  390. data/vendor/libgit2/src/xdiff/xmerge.c +104 -117
  391. data/vendor/libgit2/src/xdiff/xpatience.c +6 -17
  392. data/vendor/libgit2/src/xdiff/xprepare.c +15 -20
  393. data/vendor/libgit2/src/xdiff/xutils.c +18 -7
  394. data/vendor/libgit2/src/zstream.c +6 -6
  395. data/vendor/libgit2/src/zstream.h +4 -4
  396. metadata +60 -24
  397. data/vendor/libgit2/src/allocators/win32_crtdbg.c +0 -118
  398. data/vendor/libgit2/src/buf_text.c +0 -316
  399. data/vendor/libgit2/src/buf_text.h +0 -122
  400. data/vendor/libgit2/src/buffer.h +0 -222
  401. data/vendor/libgit2/src/global.c +0 -363
  402. data/vendor/libgit2/src/global.h +0 -41
  403. data/vendor/libgit2/src/thread-utils.c +0 -58
  404. data/vendor/libgit2/src/thread-utils.h +0 -369
  405. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +0 -127
  406. data/vendor/libgit2/src/win32/w32_stack.c +0 -188
  407. data/vendor/libgit2/src/win32/w32_stack.h +0 -140
@@ -7,11 +7,8 @@
7
7
 
8
8
  #include "remote.h"
9
9
 
10
- #include "git2/config.h"
11
- #include "git2/types.h"
12
- #include "git2/oid.h"
13
- #include "git2/net.h"
14
-
10
+ #include "buf.h"
11
+ #include "branch.h"
15
12
  #include "config.h"
16
13
  #include "repository.h"
17
14
  #include "fetch.h"
@@ -19,6 +16,12 @@
19
16
  #include "refspec.h"
20
17
  #include "fetchhead.h"
21
18
  #include "push.h"
19
+ #include "proxy.h"
20
+
21
+ #include "git2/config.h"
22
+ #include "git2/types.h"
23
+ #include "git2/oid.h"
24
+ #include "git2/net.h"
22
25
 
23
26
  #define CONFIG_URL_FMT "remote.%s.url"
24
27
  #define CONFIG_PUSHURL_FMT "remote.%s.pushurl"
@@ -28,7 +31,7 @@
28
31
 
29
32
  static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs);
30
33
  static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name);
31
- char *apply_insteadof(git_config *config, const char *url, int direction);
34
+ static int apply_insteadof(char **out, git_config *config, const char *url, int direction, bool use_default_if_empty);
32
35
 
33
36
  static int add_refspec_to(git_vector *vector, const char *string, bool is_fetch)
34
37
  {
@@ -60,14 +63,14 @@ static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
60
63
  static int download_tags_value(git_remote *remote, git_config *cfg)
61
64
  {
62
65
  git_config_entry *ce;
63
- git_buf buf = GIT_BUF_INIT;
66
+ git_str buf = GIT_STR_INIT;
64
67
  int error;
65
68
 
66
- if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
69
+ if (git_str_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
67
70
  return -1;
68
71
 
69
- error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
70
- git_buf_dispose(&buf);
72
+ error = git_config__lookup_entry(&ce, cfg, git_str_cstr(&buf), false);
73
+ git_str_dispose(&buf);
71
74
 
72
75
  if (!error && ce && ce->value) {
73
76
  if (!strcmp(ce->value, "--no-tags"))
@@ -82,9 +85,11 @@ static int download_tags_value(git_remote *remote, git_config *cfg)
82
85
 
83
86
  static int ensure_remote_name_is_valid(const char *name)
84
87
  {
85
- int error = 0;
88
+ int valid, error;
86
89
 
87
- if (!git_remote_is_valid_name(name)) {
90
+ error = git_remote_name_is_valid(&valid, name);
91
+
92
+ if (!error && !valid) {
88
93
  git_error_set(
89
94
  GIT_ERROR_CONFIG,
90
95
  "'%s' is not a valid remote name.", name ? name : "(null)");
@@ -97,7 +102,7 @@ static int ensure_remote_name_is_valid(const char *name)
97
102
  static int write_add_refspec(git_repository *repo, const char *name, const char *refspec, bool fetch)
98
103
  {
99
104
  git_config *cfg;
100
- git_buf var = GIT_BUF_INIT;
105
+ git_str var = GIT_STR_INIT;
101
106
  git_refspec spec;
102
107
  const char *fmt;
103
108
  int error;
@@ -115,11 +120,11 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
115
120
 
116
121
  git_refspec__dispose(&spec);
117
122
 
118
- if ((error = git_buf_printf(&var, fmt, name)) < 0)
123
+ if ((error = git_str_printf(&var, fmt, name)) < 0)
119
124
  return error;
120
125
 
121
126
  /*
122
- * "$^" is a unmatcheable regexp: it will not match anything at all, so
127
+ * "$^" is an unmatchable regexp: it will not match anything at all, so
123
128
  * all values will be considered new and we will not replace any
124
129
  * present value.
125
130
  */
@@ -128,11 +133,11 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
128
133
  }
129
134
 
130
135
  cleanup:
131
- git_buf_dispose(&var);
136
+ git_str_dispose(&var);
132
137
  return 0;
133
138
  }
134
139
 
135
- static int canonicalize_url(git_buf *out, const char *in)
140
+ static int canonicalize_url(git_str *out, const char *in)
136
141
  {
137
142
  if (in == NULL || strlen(in) == 0) {
138
143
  git_error_set(GIT_ERROR_INVALID, "cannot set empty URL");
@@ -147,18 +152,18 @@ static int canonicalize_url(git_buf *out, const char *in)
147
152
  (git__isalpha(in[2]) || git__isdigit(in[2]))) {
148
153
  const char *c;
149
154
  for (c = in; *c; c++)
150
- git_buf_putc(out, *c == '\\' ? '/' : *c);
155
+ git_str_putc(out, *c == '\\' ? '/' : *c);
151
156
 
152
- return git_buf_oom(out) ? -1 : 0;
157
+ return git_str_oom(out) ? -1 : 0;
153
158
  }
154
159
  #endif
155
160
 
156
- return git_buf_puts(out, in);
161
+ return git_str_puts(out, in);
157
162
  }
158
163
 
159
- static int default_fetchspec_for_name(git_buf *buf, const char *name)
164
+ static int default_fetchspec_for_name(git_str *buf, const char *name)
160
165
  {
161
- if (git_buf_printf(buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
166
+ if (git_str_printf(buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
162
167
  return -1;
163
168
 
164
169
  return 0;
@@ -202,13 +207,14 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
202
207
  {
203
208
  git_remote *remote = NULL;
204
209
  git_config *config_ro = NULL, *config_rw;
205
- git_buf canonical_url = GIT_BUF_INIT;
206
- git_buf var = GIT_BUF_INIT;
207
- git_buf specbuf = GIT_BUF_INIT;
210
+ git_str canonical_url = GIT_STR_INIT;
211
+ git_str var = GIT_STR_INIT;
212
+ git_str specbuf = GIT_STR_INIT;
208
213
  const git_remote_create_options dummy_opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
209
214
  int error = -1;
210
215
 
211
- assert(out && url);
216
+ GIT_ASSERT_ARG(out);
217
+ GIT_ASSERT_ARG(url);
212
218
 
213
219
  if (!opts) {
214
220
  opts = &dummy_opts;
@@ -240,18 +246,20 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
240
246
  goto on_error;
241
247
 
242
248
  if (opts->repository && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
243
- remote->url = apply_insteadof(config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH);
249
+ if ((error = apply_insteadof(&remote->url, config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH, true)) < 0 ||
250
+ (error = apply_insteadof(&remote->pushurl, config_ro, canonical_url.ptr, GIT_DIRECTION_PUSH, false)) < 0)
251
+ goto on_error;
244
252
  } else {
245
253
  remote->url = git__strdup(canonical_url.ptr);
254
+ GIT_ERROR_CHECK_ALLOC(remote->url);
246
255
  }
247
- GIT_ERROR_CHECK_ALLOC(remote->url);
248
256
 
249
257
  if (opts->name != NULL) {
250
258
  remote->name = git__strdup(opts->name);
251
259
  GIT_ERROR_CHECK_ALLOC(remote->name);
252
260
 
253
261
  if (opts->repository &&
254
- ((error = git_buf_printf(&var, CONFIG_URL_FMT, opts->name)) < 0 ||
262
+ ((error = git_str_printf(&var, CONFIG_URL_FMT, opts->name)) < 0 ||
255
263
  (error = git_repository_config__weakptr(&config_rw, opts->repository)) < 0 ||
256
264
  (error = git_config_set_string(config_rw, var.ptr, canonical_url.ptr)) < 0))
257
265
  goto on_error;
@@ -266,7 +274,7 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
266
274
  if ((error = default_fetchspec_for_name(&specbuf, opts->name)) < 0)
267
275
  goto on_error;
268
276
 
269
- fetch = git_buf_cstr(&specbuf);
277
+ fetch = git_str_cstr(&specbuf);
270
278
  }
271
279
 
272
280
  if ((error = add_refspec(remote, fetch, true)) < 0)
@@ -290,7 +298,7 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
290
298
  remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
291
299
 
292
300
 
293
- git_buf_dispose(&var);
301
+ git_str_dispose(&var);
294
302
 
295
303
  *out = remote;
296
304
  error = 0;
@@ -300,15 +308,15 @@ on_error:
300
308
  git_remote_free(remote);
301
309
 
302
310
  git_config_free(config_ro);
303
- git_buf_dispose(&specbuf);
304
- git_buf_dispose(&canonical_url);
305
- git_buf_dispose(&var);
311
+ git_str_dispose(&specbuf);
312
+ git_str_dispose(&canonical_url);
313
+ git_str_dispose(&var);
306
314
  return error;
307
315
  }
308
316
 
309
317
  int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
310
318
  {
311
- git_buf buf = GIT_BUF_INIT;
319
+ git_str buf = GIT_STR_INIT;
312
320
  int error;
313
321
  git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
314
322
 
@@ -319,14 +327,14 @@ int git_remote_create(git_remote **out, git_repository *repo, const char *name,
319
327
  if (canonicalize_url(&buf, url) < 0)
320
328
  return GIT_ERROR;
321
329
 
322
- git_buf_clear(&buf);
330
+ git_str_clear(&buf);
323
331
 
324
332
  opts.repository = repo;
325
333
  opts.name = name;
326
334
 
327
335
  error = git_remote_create_with_opts(out, url, &opts);
328
336
 
329
- git_buf_dispose(&buf);
337
+ git_str_dispose(&buf);
330
338
 
331
339
  return error;
332
340
  }
@@ -422,13 +430,13 @@ static int refspec_cb(const git_config_entry *entry, void *payload)
422
430
  }
423
431
 
424
432
  static int get_optional_config(
425
- bool *found, git_config *config, git_buf *buf,
433
+ bool *found, git_config *config, git_str *buf,
426
434
  git_config_foreach_cb cb, void *payload)
427
435
  {
428
436
  int error = 0;
429
- const char *key = git_buf_cstr(buf);
437
+ const char *key = git_str_cstr(buf);
430
438
 
431
- if (git_buf_oom(buf))
439
+ if (git_str_oom(buf))
432
440
  return -1;
433
441
 
434
442
  if (cb != NULL)
@@ -450,14 +458,16 @@ static int get_optional_config(
450
458
  int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
451
459
  {
452
460
  git_remote *remote = NULL;
453
- git_buf buf = GIT_BUF_INIT;
461
+ git_str buf = GIT_STR_INIT;
454
462
  const char *val;
455
463
  int error = 0;
456
464
  git_config *config;
457
465
  struct refspec_cb_data data = { NULL };
458
466
  bool optional_setting_found = false, found;
459
467
 
460
- assert(out && repo && name);
468
+ GIT_ASSERT_ARG(out);
469
+ GIT_ASSERT_ARG(repo);
470
+ GIT_ASSERT_ARG(name);
461
471
 
462
472
  if ((error = ensure_remote_name_is_valid(name)) < 0)
463
473
  return error;
@@ -479,7 +489,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
479
489
  goto cleanup;
480
490
  }
481
491
 
482
- if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0)
492
+ if ((error = git_str_printf(&buf, "remote.%s.url", name)) < 0)
483
493
  goto cleanup;
484
494
 
485
495
  if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
@@ -491,13 +501,14 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
491
501
  remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
492
502
 
493
503
  if (found && strlen(val) > 0) {
494
- remote->url = apply_insteadof(config, val, GIT_DIRECTION_FETCH);
495
- GIT_ERROR_CHECK_ALLOC(remote->url);
504
+ if ((error = apply_insteadof(&remote->url, config, val, GIT_DIRECTION_FETCH, true)) < 0 ||
505
+ (error = apply_insteadof(&remote->pushurl, config, val, GIT_DIRECTION_PUSH, false)) < 0)
506
+ goto cleanup;
496
507
  }
497
508
 
498
509
  val = NULL;
499
- git_buf_clear(&buf);
500
- git_buf_printf(&buf, "remote.%s.pushurl", name);
510
+ git_str_clear(&buf);
511
+ git_str_printf(&buf, "remote.%s.pushurl", name);
501
512
 
502
513
  if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
503
514
  goto cleanup;
@@ -511,22 +522,25 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
511
522
  }
512
523
 
513
524
  if (found && strlen(val) > 0) {
514
- remote->pushurl = apply_insteadof(config, val, GIT_DIRECTION_PUSH);
515
- GIT_ERROR_CHECK_ALLOC(remote->pushurl);
525
+ if (remote->pushurl)
526
+ git__free(remote->pushurl);
527
+
528
+ if ((error = apply_insteadof(&remote->pushurl, config, val, GIT_DIRECTION_FETCH, true)) < 0)
529
+ goto cleanup;
516
530
  }
517
531
 
518
532
  data.remote = remote;
519
533
  data.fetch = true;
520
534
 
521
- git_buf_clear(&buf);
522
- git_buf_printf(&buf, "remote.%s.fetch", name);
535
+ git_str_clear(&buf);
536
+ git_str_printf(&buf, "remote.%s.fetch", name);
523
537
 
524
538
  if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
525
539
  goto cleanup;
526
540
 
527
541
  data.fetch = false;
528
- git_buf_clear(&buf);
529
- git_buf_printf(&buf, "remote.%s.push", name);
542
+ git_str_clear(&buf);
543
+ git_str_printf(&buf, "remote.%s.push", name);
530
544
 
531
545
  if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
532
546
  goto cleanup;
@@ -545,7 +559,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
545
559
 
546
560
  cleanup:
547
561
  git_config_free(config);
548
- git_buf_dispose(&buf);
562
+ git_str_dispose(&buf);
549
563
 
550
564
  if (error < 0)
551
565
  git_remote_free(remote);
@@ -555,12 +569,12 @@ cleanup:
555
569
 
556
570
  static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name)
557
571
  {
558
- git_buf buf = GIT_BUF_INIT;
572
+ git_str buf = GIT_STR_INIT;
559
573
  int error = 0;
560
574
 
561
- git_buf_printf(&buf, "remote.%s.prune", name);
575
+ git_str_printf(&buf, "remote.%s.prune", name);
562
576
 
563
- if ((error = git_config_get_bool(&remote->prune_refs, config, git_buf_cstr(&buf))) < 0) {
577
+ if ((error = git_config_get_bool(&remote->prune_refs, config, git_str_cstr(&buf))) < 0) {
564
578
  if (error == GIT_ENOTFOUND) {
565
579
  git_error_clear();
566
580
 
@@ -573,35 +587,52 @@ static int lookup_remote_prune_config(git_remote *remote, git_config *config, co
573
587
  }
574
588
  }
575
589
 
576
- git_buf_dispose(&buf);
590
+ git_str_dispose(&buf);
577
591
  return error;
578
592
  }
579
593
 
580
594
  const char *git_remote_name(const git_remote *remote)
581
595
  {
582
- assert(remote);
596
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
583
597
  return remote->name;
584
598
  }
585
599
 
586
600
  git_repository *git_remote_owner(const git_remote *remote)
587
601
  {
588
- assert(remote);
602
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
589
603
  return remote->repo;
590
604
  }
591
605
 
592
606
  const char *git_remote_url(const git_remote *remote)
593
607
  {
594
- assert(remote);
608
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
595
609
  return remote->url;
596
610
  }
597
611
 
612
+ int git_remote_set_instance_url(git_remote *remote, const char *url)
613
+ {
614
+ char *tmp;
615
+
616
+ GIT_ASSERT_ARG(remote);
617
+ GIT_ASSERT_ARG(url);
618
+
619
+ if ((tmp = git__strdup(url)) == NULL)
620
+ return -1;
621
+
622
+ git__free(remote->url);
623
+ remote->url = tmp;
624
+
625
+ return 0;
626
+ }
627
+
598
628
  static int set_url(git_repository *repo, const char *remote, const char *pattern, const char *url)
599
629
  {
600
630
  git_config *cfg;
601
- git_buf buf = GIT_BUF_INIT, canonical_url = GIT_BUF_INIT;
631
+ git_str buf = GIT_STR_INIT, canonical_url = GIT_STR_INIT;
602
632
  int error;
603
633
 
604
- assert(repo && remote);
634
+ GIT_ASSERT_ARG(repo);
635
+ GIT_ASSERT_ARG(remote);
605
636
 
606
637
  if ((error = ensure_remote_name_is_valid(remote)) < 0)
607
638
  return error;
@@ -609,7 +640,7 @@ static int set_url(git_repository *repo, const char *remote, const char *pattern
609
640
  if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
610
641
  return error;
611
642
 
612
- if ((error = git_buf_printf(&buf, pattern, remote)) < 0)
643
+ if ((error = git_str_printf(&buf, pattern, remote)) < 0)
613
644
  return error;
614
645
 
615
646
  if (url) {
@@ -622,8 +653,8 @@ static int set_url(git_repository *repo, const char *remote, const char *pattern
622
653
  }
623
654
 
624
655
  cleanup:
625
- git_buf_dispose(&canonical_url);
626
- git_buf_dispose(&buf);
656
+ git_str_dispose(&canonical_url);
657
+ git_str_dispose(&buf);
627
658
 
628
659
  return error;
629
660
  }
@@ -635,44 +666,85 @@ int git_remote_set_url(git_repository *repo, const char *remote, const char *url
635
666
 
636
667
  const char *git_remote_pushurl(const git_remote *remote)
637
668
  {
638
- assert(remote);
669
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
639
670
  return remote->pushurl;
640
671
  }
641
672
 
642
- int git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url)
673
+ int git_remote_set_instance_pushurl(git_remote *remote, const char *url)
674
+ {
675
+ char *tmp;
676
+
677
+ GIT_ASSERT_ARG(remote);
678
+ GIT_ASSERT_ARG(url);
679
+
680
+ if ((tmp = git__strdup(url)) == NULL)
681
+ return -1;
682
+
683
+ git__free(remote->pushurl);
684
+ remote->pushurl = tmp;
685
+
686
+ return 0;
687
+ }
688
+
689
+ int git_remote_set_pushurl(git_repository *repo, const char *remote, const char *url)
643
690
  {
644
691
  return set_url(repo, remote, CONFIG_PUSHURL_FMT, url);
645
692
  }
646
693
 
647
- static int resolve_url(git_buf *resolved_url, const char *url, int direction, const git_remote_callbacks *callbacks)
694
+ static int resolve_url(
695
+ git_str *resolved_url,
696
+ const char *url,
697
+ int direction,
698
+ const git_remote_callbacks *callbacks)
648
699
  {
649
- int status;
700
+ #ifdef GIT_DEPRECATE_HARD
701
+ GIT_UNUSED(direction);
702
+ GIT_UNUSED(callbacks);
703
+ #else
704
+ git_buf buf = GIT_BUF_INIT;
705
+ int error;
650
706
 
651
707
  if (callbacks && callbacks->resolve_url) {
652
- git_buf_clear(resolved_url);
653
- status = callbacks->resolve_url(resolved_url, url, direction, callbacks->payload);
654
- if (status != GIT_PASSTHROUGH) {
655
- git_error_set_after_callback_function(status, "git_resolve_url_cb");
656
- git_buf_sanitize(resolved_url);
657
- return status;
708
+ error = callbacks->resolve_url(&buf, url, direction, callbacks->payload);
709
+
710
+ if (error != GIT_PASSTHROUGH) {
711
+ git_error_set_after_callback_function(error, "git_resolve_url_cb");
712
+
713
+ git_str_set(resolved_url, buf.ptr, buf.size);
714
+ git_buf_dispose(&buf);
715
+
716
+ return error;
658
717
  }
659
718
  }
719
+ #endif
660
720
 
661
- return git_buf_sets(resolved_url, url);
721
+ return git_str_sets(resolved_url, url);
662
722
  }
663
723
 
664
- int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks)
724
+ int git_remote__urlfordirection(
725
+ git_str *url_out,
726
+ struct git_remote *remote,
727
+ int direction,
728
+ const git_remote_callbacks *callbacks)
665
729
  {
666
730
  const char *url = NULL;
667
731
 
668
- assert(remote);
669
- assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
732
+ GIT_ASSERT_ARG(remote);
733
+ GIT_ASSERT_ARG(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
670
734
 
671
- if (direction == GIT_DIRECTION_FETCH) {
735
+ if (callbacks && callbacks->remote_ready) {
736
+ int status = callbacks->remote_ready(remote, direction, callbacks->payload);
737
+
738
+ if (status != 0 && status != GIT_PASSTHROUGH) {
739
+ git_error_set_after_callback_function(status, "git_remote_ready_cb");
740
+ return status;
741
+ }
742
+ }
743
+
744
+ if (direction == GIT_DIRECTION_FETCH)
672
745
  url = remote->url;
673
- } else if (direction == GIT_DIRECTION_PUSH) {
746
+ else if (direction == GIT_DIRECTION_PUSH)
674
747
  url = remote->pushurl ? remote->pushurl : remote->url;
675
- }
676
748
 
677
749
  if (!url) {
678
750
  git_error_set(GIT_ERROR_INVALID,
@@ -681,57 +753,204 @@ int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int
681
753
  direction == GIT_DIRECTION_FETCH ? "fetch" : "push");
682
754
  return GIT_EINVALID;
683
755
  }
756
+
684
757
  return resolve_url(url_out, url, direction, callbacks);
685
758
  }
686
759
 
687
- static int remote_transport_set_callbacks(git_transport *t, const git_remote_callbacks *cbs)
760
+ int git_remote_connect_options_init(
761
+ git_remote_connect_options *opts,
762
+ unsigned int version)
688
763
  {
689
- if (!t->set_callbacks || !cbs)
764
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
765
+ opts, version, git_remote_connect_options, GIT_REMOTE_CONNECT_OPTIONS_INIT);
766
+ return 0;
767
+ }
768
+
769
+ int git_remote_connect_options_dup(
770
+ git_remote_connect_options *dst,
771
+ const git_remote_connect_options *src)
772
+ {
773
+ memcpy(dst, src, sizeof(git_remote_connect_options));
774
+
775
+ if (git_proxy_options_dup(&dst->proxy_opts, &src->proxy_opts) < 0 ||
776
+ git_strarray_copy(&dst->custom_headers, &src->custom_headers) < 0)
777
+ return -1;
778
+
779
+ return 0;
780
+ }
781
+
782
+ void git_remote_connect_options_dispose(git_remote_connect_options *opts)
783
+ {
784
+ if (!opts)
785
+ return;
786
+
787
+ git_strarray_dispose(&opts->custom_headers);
788
+ git_proxy_options_dispose(&opts->proxy_opts);
789
+ }
790
+
791
+ static size_t http_header_name_length(const char *http_header)
792
+ {
793
+ const char *colon = strchr(http_header, ':');
794
+ if (!colon)
690
795
  return 0;
796
+ return colon - http_header;
797
+ }
798
+
799
+ static bool is_malformed_http_header(const char *http_header)
800
+ {
801
+ const char *c;
802
+ size_t name_len;
691
803
 
692
- return t->set_callbacks(t, cbs->sideband_progress, NULL,
693
- cbs->certificate_check, cbs->payload);
804
+ /* Disallow \r and \n */
805
+ if ((c = strchr(http_header, '\r')) != NULL)
806
+ return true;
807
+ if ((c = strchr(http_header, '\n')) != NULL)
808
+ return true;
809
+
810
+ /* Require a header name followed by : */
811
+ if ((name_len = http_header_name_length(http_header)) < 1)
812
+ return true;
813
+
814
+ return false;
694
815
  }
695
816
 
696
- static int set_transport_custom_headers(git_transport *t, const git_strarray *custom_headers)
817
+ static char *forbidden_custom_headers[] = {
818
+ "User-Agent",
819
+ "Host",
820
+ "Accept",
821
+ "Content-Type",
822
+ "Transfer-Encoding",
823
+ "Content-Length",
824
+ };
825
+
826
+ static bool is_forbidden_custom_header(const char *custom_header)
697
827
  {
698
- if (!t->set_custom_headers)
828
+ unsigned long i;
829
+ size_t name_len = http_header_name_length(custom_header);
830
+
831
+ /* Disallow headers that we set */
832
+ for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++)
833
+ if (strncmp(forbidden_custom_headers[i], custom_header, name_len) == 0)
834
+ return true;
835
+
836
+ return false;
837
+ }
838
+
839
+ static int validate_custom_headers(const git_strarray *custom_headers)
840
+ {
841
+ size_t i;
842
+
843
+ if (!custom_headers)
699
844
  return 0;
700
845
 
701
- return t->set_custom_headers(t, custom_headers);
846
+ for (i = 0; i < custom_headers->count; i++) {
847
+ if (is_malformed_http_header(custom_headers->strings[i])) {
848
+ git_error_set(GIT_ERROR_INVALID, "custom HTTP header '%s' is malformed", custom_headers->strings[i]);
849
+ return -1;
850
+ }
851
+
852
+ if (is_forbidden_custom_header(custom_headers->strings[i])) {
853
+ git_error_set(GIT_ERROR_INVALID, "custom HTTP header '%s' is already set by libgit2", custom_headers->strings[i]);
854
+ return -1;
855
+ }
856
+ }
857
+
858
+ return 0;
702
859
  }
703
860
 
704
- int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn)
861
+ static int lookup_redirect_config(
862
+ git_remote_redirect_t *out,
863
+ git_repository *repo)
705
864
  {
865
+ git_config *config;
866
+ const char *value;
867
+ int bool_value, error = 0;
868
+
869
+ if (!repo) {
870
+ *out = GIT_REMOTE_REDIRECT_INITIAL;
871
+ return 0;
872
+ }
873
+
874
+ if ((error = git_repository_config_snapshot(&config, repo)) < 0)
875
+ goto done;
876
+
877
+ if ((error = git_config_get_string(&value, config, "http.followRedirects")) < 0) {
878
+ if (error == GIT_ENOTFOUND) {
879
+ *out = GIT_REMOTE_REDIRECT_INITIAL;
880
+ error = 0;
881
+ }
882
+
883
+ goto done;
884
+ }
885
+
886
+ if (git_config_parse_bool(&bool_value, value) == 0) {
887
+ *out = bool_value ? GIT_REMOTE_REDIRECT_ALL :
888
+ GIT_REMOTE_REDIRECT_NONE;
889
+ } else if (strcasecmp(value, "initial") == 0) {
890
+ *out = GIT_REMOTE_REDIRECT_INITIAL;
891
+ } else {
892
+ git_error_set(GIT_ERROR_CONFIG, "invalid configuration setting '%s' for 'http.followRedirects'", value);
893
+ error = -1;
894
+ }
895
+
896
+ done:
897
+ git_config_free(config);
898
+ return error;
899
+ }
900
+
901
+ int git_remote_connect_options_normalize(
902
+ git_remote_connect_options *dst,
903
+ git_repository *repo,
904
+ const git_remote_connect_options *src)
905
+ {
906
+ git_remote_connect_options_dispose(dst);
907
+ git_remote_connect_options_init(dst, GIT_REMOTE_CONNECT_OPTIONS_VERSION);
908
+
909
+ if (src) {
910
+ GIT_ERROR_CHECK_VERSION(src, GIT_REMOTE_CONNECT_OPTIONS_VERSION, "git_remote_connect_options");
911
+ GIT_ERROR_CHECK_VERSION(&src->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
912
+ GIT_ERROR_CHECK_VERSION(&src->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
913
+
914
+ if (validate_custom_headers(&src->custom_headers) < 0 ||
915
+ git_remote_connect_options_dup(dst, src) < 0)
916
+ return -1;
917
+ }
918
+
919
+ if (dst->follow_redirects == 0) {
920
+ if (lookup_redirect_config(&dst->follow_redirects, repo) < 0)
921
+ return -1;
922
+ }
923
+
924
+ return 0;
925
+ }
926
+
927
+ int git_remote_connect_ext(
928
+ git_remote *remote,
929
+ git_direction direction,
930
+ const git_remote_connect_options *given_opts)
931
+ {
932
+ git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
933
+ git_str url = GIT_STR_INIT;
706
934
  git_transport *t;
707
- git_buf url = GIT_BUF_INIT;
708
- int flags = GIT_TRANSPORTFLAGS_NONE;
709
935
  int error;
710
- void *payload = NULL;
711
- git_credential_acquire_cb credentials = NULL;
712
- git_transport_cb transport = NULL;
713
936
 
714
- assert(remote);
937
+ GIT_ASSERT_ARG(remote);
715
938
 
716
- if (callbacks) {
717
- GIT_ERROR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
718
- credentials = callbacks->credentials;
719
- transport = callbacks->transport;
720
- payload = callbacks->payload;
721
- }
939
+ if (given_opts)
940
+ memcpy(&opts, given_opts, sizeof(git_remote_connect_options));
722
941
 
723
- if (conn->proxy)
724
- GIT_ERROR_CHECK_VERSION(conn->proxy, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
942
+ GIT_ERROR_CHECK_VERSION(&opts.callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
943
+ GIT_ERROR_CHECK_VERSION(&opts.proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
725
944
 
726
945
  t = remote->transport;
727
946
 
728
- if ((error = git_remote__urlfordirection(&url, remote, direction, callbacks)) < 0)
947
+ if ((error = git_remote__urlfordirection(&url, remote, direction, &opts.callbacks)) < 0)
729
948
  goto on_error;
730
949
 
731
950
  /* If we don't have a transport object yet, and the caller specified a
732
951
  * custom transport factory, use that */
733
- if (!t && transport &&
734
- (error = transport(&t, remote, payload)) < 0)
952
+ if (!t && opts.callbacks.transport &&
953
+ (error = opts.callbacks.transport(&t, remote, opts.callbacks.payload)) < 0)
735
954
  goto on_error;
736
955
 
737
956
  /* If we still don't have a transport, then use the global
@@ -739,16 +958,12 @@ int git_remote__connect(git_remote *remote, git_direction direction, const git_r
739
958
  if (!t && (error = git_transport_new(&t, remote, url.ptr)) < 0)
740
959
  goto on_error;
741
960
 
742
- if ((error = set_transport_custom_headers(t, conn->custom_headers)) != 0)
743
- goto on_error;
744
-
745
- if ((error = remote_transport_set_callbacks(t, callbacks)) < 0 ||
746
- (error = t->connect(t, url.ptr, credentials, payload, conn->proxy, direction, flags)) != 0)
961
+ if ((error = t->connect(t, url.ptr, direction, &opts)) != 0)
747
962
  goto on_error;
748
963
 
749
964
  remote->transport = t;
750
965
 
751
- git_buf_dispose(&url);
966
+ git_str_dispose(&url);
752
967
 
753
968
  return 0;
754
969
 
@@ -756,7 +971,7 @@ on_error:
756
971
  if (t)
757
972
  t->free(t);
758
973
 
759
- git_buf_dispose(&url);
974
+ git_str_dispose(&url);
760
975
 
761
976
  if (t == remote->transport)
762
977
  remote->transport = NULL;
@@ -764,19 +979,30 @@ on_error:
764
979
  return error;
765
980
  }
766
981
 
767
- int git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_proxy_options *proxy, const git_strarray *custom_headers)
982
+ int git_remote_connect(
983
+ git_remote *remote,
984
+ git_direction direction,
985
+ const git_remote_callbacks *callbacks,
986
+ const git_proxy_options *proxy,
987
+ const git_strarray *custom_headers)
768
988
  {
769
- git_remote_connection_opts conn;
989
+ git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
990
+
991
+ if (callbacks)
992
+ memcpy(&opts.callbacks, callbacks, sizeof(git_remote_callbacks));
993
+
994
+ if (proxy)
995
+ memcpy(&opts.proxy_opts, proxy, sizeof(git_proxy_options));
770
996
 
771
- conn.proxy = proxy;
772
- conn.custom_headers = custom_headers;
997
+ if (custom_headers)
998
+ memcpy(&opts.custom_headers, custom_headers, sizeof(git_strarray));
773
999
 
774
- return git_remote__connect(remote, direction, callbacks, &conn);
1000
+ return git_remote_connect_ext(remote, direction, &opts);
775
1001
  }
776
1002
 
777
1003
  int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote)
778
1004
  {
779
- assert(remote);
1005
+ GIT_ASSERT_ARG(remote);
780
1006
 
781
1007
  if (!remote->transport) {
782
1008
  git_error_set(GIT_ERROR_NET, "this remote has never connected");
@@ -786,75 +1012,161 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote
786
1012
  return remote->transport->ls(out, size, remote->transport);
787
1013
  }
788
1014
 
789
- int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
1015
+ int git_remote_capabilities(unsigned int *out, git_remote *remote)
790
1016
  {
791
- git_config *cfg;
792
- git_config_entry *ce = NULL;
793
- git_buf val = GIT_BUF_INIT;
794
- int error;
1017
+ GIT_ASSERT_ARG(remote);
795
1018
 
796
- assert(remote);
1019
+ *out = 0;
797
1020
 
798
- if (!proxy_url || !remote->repo)
1021
+ if (!remote->transport) {
1022
+ git_error_set(GIT_ERROR_NET, "this remote has never connected");
799
1023
  return -1;
1024
+ }
1025
+
1026
+ return remote->transport->capabilities(out, remote->transport);
1027
+ }
800
1028
 
801
- *proxy_url = NULL;
1029
+ static int lookup_config(char **out, git_config *cfg, const char *name)
1030
+ {
1031
+ git_config_entry *ce = NULL;
1032
+ int error;
802
1033
 
803
- if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
1034
+ if ((error = git_config__lookup_entry(&ce, cfg, name, false)) < 0)
804
1035
  return error;
805
1036
 
806
- /* Go through the possible sources for proxy configuration, from most specific
807
- * to least specific. */
1037
+ if (ce && ce->value) {
1038
+ *out = git__strdup(ce->value);
1039
+ GIT_ERROR_CHECK_ALLOC(*out);
1040
+ } else {
1041
+ error = GIT_ENOTFOUND;
1042
+ }
1043
+
1044
+ git_config_entry_free(ce);
1045
+ return error;
1046
+ }
1047
+
1048
+ static void url_config_trim(git_net_url *url)
1049
+ {
1050
+ size_t len = strlen(url->path);
1051
+
1052
+ if (url->path[len - 1] == '/') {
1053
+ len--;
1054
+ } else {
1055
+ while (len && url->path[len - 1] != '/')
1056
+ len--;
1057
+ }
1058
+
1059
+ url->path[len] = '\0';
1060
+ }
1061
+
1062
+ static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
1063
+ {
1064
+ git_config *cfg = NULL;
1065
+ git_str buf = GIT_STR_INIT;
1066
+ git_net_url lookup_url = GIT_NET_URL_INIT;
1067
+ int error;
1068
+
1069
+ if ((error = git_net_url_dup(&lookup_url, url)) < 0)
1070
+ goto done;
1071
+
1072
+ if (remote->repo) {
1073
+ if ((error = git_repository_config(&cfg, remote->repo)) < 0)
1074
+ goto done;
1075
+ } else {
1076
+ if ((error = git_config_open_default(&cfg)) < 0)
1077
+ goto done;
1078
+ }
808
1079
 
809
1080
  /* remote.<name>.proxy config setting */
810
1081
  if (remote->name && remote->name[0]) {
811
- git_buf buf = GIT_BUF_INIT;
1082
+ git_str_clear(&buf);
812
1083
 
813
- if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0)
814
- return error;
1084
+ if ((error = git_str_printf(&buf, "remote.%s.proxy", remote->name)) < 0 ||
1085
+ (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
1086
+ goto done;
1087
+ }
815
1088
 
816
- error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
817
- git_buf_dispose(&buf);
1089
+ while (true) {
1090
+ git_str_clear(&buf);
818
1091
 
819
- if (error < 0)
820
- return error;
1092
+ if ((error = git_str_puts(&buf, "http.")) < 0 ||
1093
+ (error = git_net_url_fmt(&buf, &lookup_url)) < 0 ||
1094
+ (error = git_str_puts(&buf, ".proxy")) < 0 ||
1095
+ (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
1096
+ goto done;
821
1097
 
822
- if (ce && ce->value) {
823
- *proxy_url = git__strdup(ce->value);
824
- goto found;
825
- }
1098
+ if (! lookup_url.path[0])
1099
+ break;
1100
+
1101
+ url_config_trim(&lookup_url);
826
1102
  }
827
1103
 
828
- /* http.proxy config setting */
829
- if ((error = git_config__lookup_entry(&ce, cfg, "http.proxy", false)) < 0)
830
- return error;
1104
+ git_str_clear(&buf);
831
1105
 
832
- if (ce && ce->value) {
833
- *proxy_url = git__strdup(ce->value);
834
- goto found;
835
- }
1106
+ error = lookup_config(out, cfg, "http.proxy");
1107
+
1108
+ done:
1109
+ git_config_free(cfg);
1110
+ git_str_dispose(&buf);
1111
+ git_net_url_dispose(&lookup_url);
1112
+ return error;
1113
+ }
1114
+
1115
+ static int http_proxy_env(char **out, git_remote *remote, git_net_url *url)
1116
+ {
1117
+ git_str proxy_env = GIT_STR_INIT, no_proxy_env = GIT_STR_INIT;
1118
+ bool use_ssl = (strcmp(url->scheme, "https") == 0);
1119
+ int error;
1120
+
1121
+ GIT_UNUSED(remote);
836
1122
 
837
1123
  /* http_proxy / https_proxy environment variables */
838
- error = git__getenv(&val, use_ssl ? "https_proxy" : "http_proxy");
1124
+ error = git__getenv(&proxy_env, use_ssl ? "https_proxy" : "http_proxy");
839
1125
 
840
1126
  /* try uppercase environment variables */
841
1127
  if (error == GIT_ENOTFOUND)
842
- error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
1128
+ error = git__getenv(&proxy_env, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
843
1129
 
844
- if (error < 0) {
845
- if (error == GIT_ENOTFOUND) {
846
- git_error_clear();
847
- error = 0;
848
- }
1130
+ if (error)
1131
+ goto done;
849
1132
 
850
- return error;
851
- }
1133
+ /* no_proxy/NO_PROXY environment variables */
1134
+ error = git__getenv(&no_proxy_env, "no_proxy");
852
1135
 
853
- *proxy_url = git_buf_detach(&val);
1136
+ if (error == GIT_ENOTFOUND)
1137
+ error = git__getenv(&no_proxy_env, "NO_PROXY");
854
1138
 
855
- found:
856
- GIT_ERROR_CHECK_ALLOC(*proxy_url);
857
- git_config_entry_free(ce);
1139
+ if (error && error != GIT_ENOTFOUND)
1140
+ goto done;
1141
+
1142
+ if (!git_net_url_matches_pattern_list(url, no_proxy_env.ptr))
1143
+ *out = git_str_detach(&proxy_env);
1144
+ else
1145
+ error = GIT_ENOTFOUND;
1146
+
1147
+ done:
1148
+ git_str_dispose(&proxy_env);
1149
+ git_str_dispose(&no_proxy_env);
1150
+ return error;
1151
+ }
1152
+
1153
+ int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url)
1154
+ {
1155
+ int error;
1156
+
1157
+ GIT_ASSERT_ARG(out);
1158
+ GIT_ASSERT_ARG(remote);
1159
+
1160
+ *out = NULL;
1161
+
1162
+ /*
1163
+ * Go through the possible sources for proxy configuration,
1164
+ * Examine the various git config options first, then
1165
+ * consult environment variables.
1166
+ */
1167
+ if ((error = http_proxy_config(out, remote, url)) != GIT_ENOTFOUND ||
1168
+ (error = http_proxy_env(out, remote, url)) != GIT_ENOTFOUND)
1169
+ return error;
858
1170
 
859
1171
  return 0;
860
1172
  }
@@ -913,38 +1225,50 @@ static int ls_to_vector(git_vector *out, git_remote *remote)
913
1225
  return 0;
914
1226
  }
915
1227
 
916
- int git_remote_download(git_remote *remote, const git_strarray *refspecs, const git_fetch_options *opts)
917
- {
918
- int error = -1;
919
- size_t i;
920
- git_vector *to_active, specs = GIT_VECTOR_INIT, refs = GIT_VECTOR_INIT;
921
- const git_remote_callbacks *cbs = NULL;
922
- const git_strarray *custom_headers = NULL;
923
- const git_proxy_options *proxy = NULL;
924
-
925
- assert(remote);
926
-
927
- if (!remote->repo) {
928
- git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
929
- return -1;
1228
+ #define copy_opts(out, in) \
1229
+ if (in) { \
1230
+ (out)->callbacks = (in)->callbacks; \
1231
+ (out)->proxy_opts = (in)->proxy_opts; \
1232
+ (out)->custom_headers = (in)->custom_headers; \
1233
+ (out)->follow_redirects = (in)->follow_redirects; \
930
1234
  }
931
1235
 
932
- if (opts) {
933
- GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
934
- cbs = &opts->callbacks;
935
- custom_headers = &opts->custom_headers;
936
- GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
937
- proxy = &opts->proxy_opts;
1236
+ GIT_INLINE(int) connect_opts_from_fetch_opts(
1237
+ git_remote_connect_options *out,
1238
+ git_remote *remote,
1239
+ const git_fetch_options *fetch_opts)
1240
+ {
1241
+ git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
1242
+ copy_opts(&tmp, fetch_opts);
1243
+ return git_remote_connect_options_normalize(out, remote->repo, &tmp);
1244
+ }
1245
+
1246
+ static int connect_or_reset_options(
1247
+ git_remote *remote,
1248
+ int direction,
1249
+ git_remote_connect_options *opts)
1250
+ {
1251
+ if (!git_remote_connected(remote)) {
1252
+ return git_remote_connect_ext(remote, direction, opts);
1253
+ } else {
1254
+ return remote->transport->set_connect_opts(remote->transport, opts);
938
1255
  }
1256
+ }
939
1257
 
940
- if (!git_remote_connected(remote) &&
941
- (error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs, proxy, custom_headers)) < 0)
942
- goto on_error;
1258
+ /* Download from an already connected remote. */
1259
+ static int git_remote__download(
1260
+ git_remote *remote,
1261
+ const git_strarray *refspecs,
1262
+ const git_fetch_options *opts)
1263
+ {
1264
+ git_vector *to_active, specs = GIT_VECTOR_INIT, refs = GIT_VECTOR_INIT;
1265
+ size_t i;
1266
+ int error;
943
1267
 
944
1268
  if (ls_to_vector(&refs, remote) < 0)
945
1269
  return -1;
946
1270
 
947
- if ((git_vector_init(&specs, 0, NULL)) < 0)
1271
+ if ((error = git_vector_init(&specs, 0, NULL)) < 0)
948
1272
  goto on_error;
949
1273
 
950
1274
  remote->passed_refspecs = 0;
@@ -972,7 +1296,7 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
972
1296
  git_vector_free(&specs);
973
1297
 
974
1298
  if (error < 0)
975
- return error;
1299
+ goto on_error;
976
1300
 
977
1301
  if (remote->push) {
978
1302
  git_push_free(remote->push);
@@ -980,9 +1304,9 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
980
1304
  }
981
1305
 
982
1306
  if ((error = git_fetch_negotiate(remote, opts)) < 0)
983
- return error;
1307
+ goto on_error;
984
1308
 
985
- return git_fetch_download_pack(remote, cbs);
1309
+ error = git_fetch_download_pack(remote);
986
1310
 
987
1311
  on_error:
988
1312
  git_vector_free(&refs);
@@ -991,55 +1315,83 @@ on_error:
991
1315
  return error;
992
1316
  }
993
1317
 
1318
+ int git_remote_download(
1319
+ git_remote *remote,
1320
+ const git_strarray *refspecs,
1321
+ const git_fetch_options *opts)
1322
+ {
1323
+ git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
1324
+ int error;
1325
+
1326
+ GIT_ASSERT_ARG(remote);
1327
+
1328
+ if (!remote->repo) {
1329
+ git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
1330
+ return -1;
1331
+ }
1332
+
1333
+ if (connect_opts_from_fetch_opts(&connect_opts, remote, opts) < 0)
1334
+ return -1;
1335
+
1336
+ if ((error = connect_or_reset_options(remote, GIT_DIRECTION_FETCH, &connect_opts)) < 0)
1337
+ return error;
1338
+
1339
+ return git_remote__download(remote, refspecs, opts);
1340
+ }
1341
+
994
1342
  int git_remote_fetch(
995
- git_remote *remote,
996
- const git_strarray *refspecs,
997
- const git_fetch_options *opts,
998
- const char *reflog_message)
1343
+ git_remote *remote,
1344
+ const git_strarray *refspecs,
1345
+ const git_fetch_options *opts,
1346
+ const char *reflog_message)
999
1347
  {
1000
1348
  int error, update_fetchhead = 1;
1001
1349
  git_remote_autotag_option_t tagopt = remote->download_tags;
1002
1350
  bool prune = false;
1003
- git_buf reflog_msg_buf = GIT_BUF_INIT;
1004
- const git_remote_callbacks *cbs = NULL;
1005
- git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
1351
+ git_str reflog_msg_buf = GIT_STR_INIT;
1352
+ git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
1353
+
1354
+ GIT_ASSERT_ARG(remote);
1355
+
1356
+ if (!remote->repo) {
1357
+ git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
1358
+ return -1;
1359
+ }
1360
+
1361
+ if (connect_opts_from_fetch_opts(&connect_opts, remote, opts) < 0)
1362
+ return -1;
1363
+
1364
+ if ((error = connect_or_reset_options(remote, GIT_DIRECTION_FETCH, &connect_opts)) < 0)
1365
+ return error;
1006
1366
 
1007
1367
  if (opts) {
1008
- GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
1009
- cbs = &opts->callbacks;
1010
- conn.custom_headers = &opts->custom_headers;
1011
1368
  update_fetchhead = opts->update_fetchhead;
1012
1369
  tagopt = opts->download_tags;
1013
- GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
1014
- conn.proxy = &opts->proxy_opts;
1015
1370
  }
1016
1371
 
1017
1372
  /* Connect and download everything */
1018
- if ((error = git_remote__connect(remote, GIT_DIRECTION_FETCH, cbs, &conn)) != 0)
1019
- return error;
1020
-
1021
- error = git_remote_download(remote, refspecs, opts);
1373
+ error = git_remote__download(remote, refspecs, opts);
1022
1374
 
1023
1375
  /* We don't need to be connected anymore */
1024
1376
  git_remote_disconnect(remote);
1025
1377
 
1026
1378
  /* If the download failed, return the error */
1027
1379
  if (error != 0)
1028
- return error;
1380
+ goto done;
1029
1381
 
1030
1382
  /* Default reflog message */
1031
1383
  if (reflog_message)
1032
- git_buf_sets(&reflog_msg_buf, reflog_message);
1384
+ git_str_sets(&reflog_msg_buf, reflog_message);
1033
1385
  else {
1034
- git_buf_printf(&reflog_msg_buf, "fetch %s",
1386
+ git_str_printf(&reflog_msg_buf, "fetch %s",
1035
1387
  remote->name ? remote->name : remote->url);
1036
1388
  }
1037
1389
 
1038
1390
  /* Create "remote/foo" branches for all remote branches */
1039
- error = git_remote_update_tips(remote, cbs, update_fetchhead, tagopt, git_buf_cstr(&reflog_msg_buf));
1040
- git_buf_dispose(&reflog_msg_buf);
1391
+ error = git_remote_update_tips(remote, &connect_opts.callbacks, update_fetchhead, tagopt, git_str_cstr(&reflog_msg_buf));
1392
+ git_str_dispose(&reflog_msg_buf);
1041
1393
  if (error < 0)
1042
- return error;
1394
+ goto done;
1043
1395
 
1044
1396
  if (opts && opts->prune == GIT_FETCH_PRUNE)
1045
1397
  prune = true;
@@ -1051,8 +1403,10 @@ int git_remote_fetch(
1051
1403
  prune = remote->prune_refs;
1052
1404
 
1053
1405
  if (prune)
1054
- error = git_remote_prune(remote, cbs);
1406
+ error = git_remote_prune(remote, &connect_opts.callbacks);
1055
1407
 
1408
+ done:
1409
+ git_remote_connect_options_dispose(&connect_opts);
1056
1410
  return error;
1057
1411
  }
1058
1412
 
@@ -1061,7 +1415,8 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda
1061
1415
  unsigned int i;
1062
1416
  git_remote_head *remote_ref;
1063
1417
 
1064
- assert(update_heads && fetchspec_src);
1418
+ GIT_ASSERT_ARG(update_heads);
1419
+ GIT_ASSERT_ARG(fetchspec_src);
1065
1420
 
1066
1421
  *out = NULL;
1067
1422
 
@@ -1075,22 +1430,22 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda
1075
1430
  return 0;
1076
1431
  }
1077
1432
 
1078
- static int ref_to_update(int *update, git_buf *remote_name, git_remote *remote, git_refspec *spec, const char *ref_name)
1433
+ static int ref_to_update(int *update, git_str *remote_name, git_remote *remote, git_refspec *spec, const char *ref_name)
1079
1434
  {
1080
1435
  int error = 0;
1081
1436
  git_repository *repo;
1082
- git_buf upstream_remote = GIT_BUF_INIT;
1083
- git_buf upstream_name = GIT_BUF_INIT;
1437
+ git_str upstream_remote = GIT_STR_INIT;
1438
+ git_str upstream_name = GIT_STR_INIT;
1084
1439
 
1085
1440
  repo = git_remote_owner(remote);
1086
1441
 
1087
1442
  if ((!git_reference__is_branch(ref_name)) ||
1088
1443
  !git_remote_name(remote) ||
1089
- (error = git_branch_upstream_remote(&upstream_remote, repo, ref_name) < 0) ||
1090
- git__strcmp(git_remote_name(remote), git_buf_cstr(&upstream_remote)) ||
1091
- (error = git_branch_upstream_name(&upstream_name, repo, ref_name)) < 0 ||
1092
- !git_refspec_dst_matches(spec, git_buf_cstr(&upstream_name)) ||
1093
- (error = git_refspec_rtransform(remote_name, spec, upstream_name.ptr)) < 0) {
1444
+ (error = git_branch__upstream_remote(&upstream_remote, repo, ref_name) < 0) ||
1445
+ git__strcmp(git_remote_name(remote), git_str_cstr(&upstream_remote)) ||
1446
+ (error = git_branch__upstream_name(&upstream_name, repo, ref_name)) < 0 ||
1447
+ !git_refspec_dst_matches(spec, git_str_cstr(&upstream_name)) ||
1448
+ (error = git_refspec__rtransform(remote_name, spec, upstream_name.ptr)) < 0) {
1094
1449
  /* Not an error if there is no upstream */
1095
1450
  if (error == GIT_ENOTFOUND) {
1096
1451
  git_error_clear();
@@ -1102,20 +1457,22 @@ static int ref_to_update(int *update, git_buf *remote_name, git_remote *remote,
1102
1457
  *update = 1;
1103
1458
  }
1104
1459
 
1105
- git_buf_dispose(&upstream_remote);
1106
- git_buf_dispose(&upstream_name);
1460
+ git_str_dispose(&upstream_remote);
1461
+ git_str_dispose(&upstream_name);
1107
1462
  return error;
1108
1463
  }
1109
1464
 
1110
1465
  static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_refspec *spec, git_vector *update_heads, git_reference *ref)
1111
1466
  {
1112
1467
  git_reference *resolved_ref = NULL;
1113
- git_buf remote_name = GIT_BUF_INIT;
1468
+ git_str remote_name = GIT_STR_INIT;
1114
1469
  git_config *config = NULL;
1115
- const char *ref_name = NULL;
1470
+ const char *ref_name;
1116
1471
  int error = 0, update;
1117
1472
 
1118
- assert(out && spec && ref);
1473
+ GIT_ASSERT_ARG(out);
1474
+ GIT_ASSERT_ARG(spec);
1475
+ GIT_ASSERT_ARG(ref);
1119
1476
 
1120
1477
  *out = NULL;
1121
1478
 
@@ -1125,7 +1482,7 @@ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_re
1125
1482
  if (error == GIT_ENOTFOUND && git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) {
1126
1483
  ref_name = git_reference_symbolic_target(ref);
1127
1484
  error = 0;
1128
- } else if (resolved_ref) {
1485
+ } else {
1129
1486
  ref_name = git_reference_name(resolved_ref);
1130
1487
  }
1131
1488
 
@@ -1143,10 +1500,10 @@ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_re
1143
1500
  goto cleanup;
1144
1501
 
1145
1502
  if (update)
1146
- error = remote_head_for_fetchspec_src(out, update_heads, git_buf_cstr(&remote_name));
1503
+ error = remote_head_for_fetchspec_src(out, update_heads, git_str_cstr(&remote_name));
1147
1504
 
1148
1505
  cleanup:
1149
- git_buf_dispose(&remote_name);
1506
+ git_str_dispose(&remote_name);
1150
1507
  git_reference_free(resolved_ref);
1151
1508
  git_config_free(config);
1152
1509
  return error;
@@ -1162,7 +1519,7 @@ static int git_remote_write_fetchhead(git_remote *remote, git_refspec *spec, git
1162
1519
  unsigned int i = 0;
1163
1520
  int error = 0;
1164
1521
 
1165
- assert(remote);
1522
+ GIT_ASSERT_ARG(remote);
1166
1523
 
1167
1524
  /* no heads, nothing to do */
1168
1525
  if (update_heads->length == 0)
@@ -1284,7 +1641,7 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
1284
1641
  */
1285
1642
  git_vector_foreach(&candidates, i, refname) {
1286
1643
  git_vector_foreach(&remote->active_refspecs, j, spec) {
1287
- git_buf buf = GIT_BUF_INIT;
1644
+ git_str buf = GIT_STR_INIT;
1288
1645
  size_t pos;
1289
1646
  char *src_name;
1290
1647
  git_remote_head key = {0};
@@ -1292,12 +1649,12 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
1292
1649
  if (!git_refspec_dst_matches(spec, refname))
1293
1650
  continue;
1294
1651
 
1295
- if ((error = git_refspec_rtransform(&buf, spec, refname)) < 0)
1652
+ if ((error = git_refspec__rtransform(&buf, spec, refname)) < 0)
1296
1653
  goto cleanup;
1297
1654
 
1298
- key.name = (char *) git_buf_cstr(&buf);
1655
+ key.name = (char *) git_str_cstr(&buf);
1299
1656
  error = git_vector_bsearch(&pos, &remote_refs, &key);
1300
- git_buf_dispose(&buf);
1657
+ git_str_dispose(&buf);
1301
1658
 
1302
1659
  if (error < 0 && error != GIT_ENOTFOUND)
1303
1660
  goto cleanup;
@@ -1305,7 +1662,7 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
1305
1662
  if (error == GIT_ENOTFOUND)
1306
1663
  continue;
1307
1664
 
1308
- /* if we did find a source, remove it from the candiates */
1665
+ /* If we did find a source, remove it from the candidates. */
1309
1666
  if ((error = git_vector_set((void **) &src_name, &candidates, i, NULL)) < 0)
1310
1667
  goto cleanup;
1311
1668
 
@@ -1359,133 +1716,210 @@ cleanup:
1359
1716
  return error;
1360
1717
  }
1361
1718
 
1362
- static int update_tips_for_spec(
1363
- git_remote *remote,
1364
- const git_remote_callbacks *callbacks,
1365
- int update_fetchhead,
1366
- git_remote_autotag_option_t tagopt,
1367
- git_refspec *spec,
1368
- git_vector *refs,
1369
- const char *log_message)
1719
+ static int update_ref(
1720
+ const git_remote *remote,
1721
+ const char *ref_name,
1722
+ git_oid *id,
1723
+ const char *msg,
1724
+ const git_remote_callbacks *callbacks)
1370
1725
  {
1371
- int error = 0, autotag;
1372
- unsigned int i = 0;
1373
- git_buf refname = GIT_BUF_INIT;
1374
- git_oid old;
1375
- git_odb *odb;
1376
- git_remote_head *head;
1377
1726
  git_reference *ref;
1378
- git_refspec tagspec;
1379
- git_vector update_heads;
1727
+ git_oid old_id;
1728
+ int error;
1380
1729
 
1381
- assert(remote);
1730
+ error = git_reference_name_to_id(&old_id, remote->repo, ref_name);
1382
1731
 
1383
- if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
1384
- return -1;
1732
+ if (error < 0 && error != GIT_ENOTFOUND)
1733
+ return error;
1734
+ else if (error == 0 && git_oid_equal(&old_id, id))
1735
+ return 0;
1385
1736
 
1386
- if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
1387
- return -1;
1737
+ /* If we did find a current reference, make sure we haven't lost a race */
1738
+ if (error)
1739
+ error = git_reference_create(&ref, remote->repo, ref_name, id, true, msg);
1740
+ else
1741
+ error = git_reference_create_matching(&ref, remote->repo, ref_name, id, true, &old_id, msg);
1388
1742
 
1389
- /* Make a copy of the transport's refs */
1390
- if (git_vector_init(&update_heads, 16, NULL) < 0)
1391
- return -1;
1743
+ git_reference_free(ref);
1392
1744
 
1393
- for (; i < refs->length; ++i) {
1394
- head = git_vector_get(refs, i);
1395
- autotag = 0;
1396
- git_buf_clear(&refname);
1745
+ if (error < 0)
1746
+ return error;
1397
1747
 
1398
- /* Ignore malformed ref names (which also saves us from tag^{} */
1399
- if (!git_reference_is_valid_name(head->name))
1400
- continue;
1748
+ if (callbacks && callbacks->update_tips &&
1749
+ (error = callbacks->update_tips(ref_name, &old_id, id, callbacks->payload)) < 0)
1750
+ return error;
1751
+
1752
+ return 0;
1753
+ }
1401
1754
 
1402
- /* If we have a tag, see if the auto-follow rules say to update it */
1403
- if (git_refspec_src_matches(&tagspec, head->name)) {
1404
- if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
1755
+ static int update_one_tip(
1756
+ git_vector *update_heads,
1757
+ git_remote *remote,
1758
+ git_refspec *spec,
1759
+ git_remote_head *head,
1760
+ git_refspec *tagspec,
1761
+ git_remote_autotag_option_t tagopt,
1762
+ const char *log_message,
1763
+ const git_remote_callbacks *callbacks)
1764
+ {
1765
+ git_odb *odb;
1766
+ git_str refname = GIT_STR_INIT;
1767
+ git_reference *ref = NULL;
1768
+ bool autotag = false;
1769
+ git_oid old;
1770
+ int valid;
1771
+ int error;
1405
1772
 
1406
- if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
1407
- autotag = 1;
1773
+ if ((error = git_repository_odb__weakptr(&odb, remote->repo)) < 0)
1774
+ goto done;
1408
1775
 
1409
- git_buf_clear(&refname);
1410
- if (git_buf_puts(&refname, head->name) < 0)
1411
- goto on_error;
1412
- }
1413
- }
1776
+ /* Ignore malformed ref names (which also saves us from tag^{} */
1777
+ if ((error = git_reference_name_is_valid(&valid, head->name)) < 0)
1778
+ goto done;
1414
1779
 
1415
- /* If we didn't want to auto-follow the tag, check if the refspec matches */
1416
- if (!autotag && git_refspec_src_matches(spec, head->name)) {
1417
- if (spec->dst) {
1418
- if (git_refspec_transform(&refname, spec, head->name) < 0)
1419
- goto on_error;
1420
- } else {
1421
- /*
1422
- * no rhs mans store it in FETCH_HEAD, even if we don't
1423
- update anything else.
1424
- */
1425
- if ((error = git_vector_insert(&update_heads, head)) < 0)
1426
- goto on_error;
1780
+ if (!valid)
1781
+ goto done;
1427
1782
 
1428
- continue;
1429
- }
1783
+ /* If we have a tag, see if the auto-follow rules say to update it */
1784
+ if (git_refspec_src_matches(tagspec, head->name)) {
1785
+ if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
1786
+ autotag = true;
1787
+
1788
+ if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
1789
+ if (git_str_puts(&refname, head->name) < 0)
1790
+ goto done;
1430
1791
  }
1792
+ }
1431
1793
 
1432
- /* If we still don't have a refname, we don't want it */
1433
- if (git_buf_len(&refname) == 0) {
1434
- continue;
1794
+ /* If we didn't want to auto-follow the tag, check if the refspec matches */
1795
+ if (!autotag && git_refspec_src_matches(spec, head->name)) {
1796
+ if (spec->dst) {
1797
+ if ((error = git_refspec__transform(&refname, spec, head->name)) < 0)
1798
+ goto done;
1799
+ } else {
1800
+ /*
1801
+ * no rhs means store it in FETCH_HEAD, even if we don't
1802
+ * update anything else.
1803
+ */
1804
+ error = git_vector_insert(update_heads, head);
1805
+ goto done;
1435
1806
  }
1807
+ }
1436
1808
 
1437
- /* In autotag mode, only create tags for objects already in db */
1438
- if (autotag && !git_odb_exists(odb, &head->oid))
1439
- continue;
1809
+ /* If we still don't have a refname, we don't want it */
1810
+ if (git_str_len(&refname) == 0)
1811
+ goto done;
1440
1812
 
1441
- if (!autotag && git_vector_insert(&update_heads, head) < 0)
1442
- goto on_error;
1813
+ /* In autotag mode, only create tags for objects already in db */
1814
+ if (autotag && !git_odb_exists(odb, &head->oid))
1815
+ goto done;
1443
1816
 
1444
- error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1445
- if (error < 0 && error != GIT_ENOTFOUND)
1446
- goto on_error;
1817
+ if (!autotag && (error = git_vector_insert(update_heads, head)) < 0)
1818
+ goto done;
1447
1819
 
1448
- if (error == GIT_ENOTFOUND) {
1449
- memset(&old, 0, GIT_OID_RAWSZ);
1820
+ error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1450
1821
 
1451
- if (autotag && git_vector_insert(&update_heads, head) < 0)
1452
- goto on_error;
1453
- }
1822
+ if (error < 0 && error != GIT_ENOTFOUND)
1823
+ goto done;
1454
1824
 
1455
- if (!git_oid__cmp(&old, &head->oid))
1456
- continue;
1825
+ if (!(error || error == GIT_ENOTFOUND) &&
1826
+ !spec->force &&
1827
+ !git_graph_descendant_of(remote->repo, &head->oid, &old)) {
1828
+ error = 0;
1829
+ goto done;
1830
+ }
1457
1831
 
1458
- /* In autotag mode, don't overwrite any locally-existing tags */
1459
- error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
1460
- log_message);
1832
+ if (error == GIT_ENOTFOUND) {
1833
+ memset(&old, 0, GIT_OID_RAWSZ);
1834
+ error = 0;
1835
+
1836
+ if (autotag && (error = git_vector_insert(update_heads, head)) < 0)
1837
+ goto done;
1838
+ }
1461
1839
 
1840
+ if (!git_oid__cmp(&old, &head->oid))
1841
+ goto done;
1842
+
1843
+ /* In autotag mode, don't overwrite any locally-existing tags */
1844
+ error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
1845
+ log_message);
1846
+
1847
+ if (error < 0) {
1462
1848
  if (error == GIT_EEXISTS)
1463
- continue;
1849
+ error = 0;
1464
1850
 
1465
- if (error < 0)
1851
+ goto done;
1852
+ }
1853
+
1854
+ if (callbacks && callbacks->update_tips != NULL &&
1855
+ (error = callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload)) < 0)
1856
+ git_error_set_after_callback_function(error, "git_remote_fetch");
1857
+
1858
+ done:
1859
+ git_reference_free(ref);
1860
+ git_str_dispose(&refname);
1861
+ return error;
1862
+ }
1863
+
1864
+ static int update_tips_for_spec(
1865
+ git_remote *remote,
1866
+ const git_remote_callbacks *callbacks,
1867
+ int update_fetchhead,
1868
+ git_remote_autotag_option_t tagopt,
1869
+ git_refspec *spec,
1870
+ git_vector *refs,
1871
+ const char *log_message)
1872
+ {
1873
+ git_refspec tagspec;
1874
+ git_remote_head *head, oid_head;
1875
+ git_vector update_heads;
1876
+ int error = 0;
1877
+ size_t i;
1878
+
1879
+ GIT_ASSERT_ARG(remote);
1880
+
1881
+ if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
1882
+ return -1;
1883
+
1884
+ /* Make a copy of the transport's refs */
1885
+ if (git_vector_init(&update_heads, 16, NULL) < 0)
1886
+ return -1;
1887
+
1888
+ /* Update tips based on the remote heads */
1889
+ git_vector_foreach(refs, i, head) {
1890
+ if (update_one_tip(&update_heads, remote, spec, head, &tagspec, tagopt, log_message, callbacks) < 0)
1466
1891
  goto on_error;
1892
+ }
1467
1893
 
1468
- git_reference_free(ref);
1894
+ /* Handle specified oid sources */
1895
+ if (git_oid__is_hexstr(spec->src)) {
1896
+ git_oid id;
1469
1897
 
1470
- if (callbacks && callbacks->update_tips != NULL) {
1471
- if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
1472
- goto on_error;
1473
- }
1898
+ if ((error = git_oid_fromstr(&id, spec->src)) < 0)
1899
+ goto on_error;
1900
+
1901
+ if (spec->dst &&
1902
+ (error = update_ref(remote, spec->dst, &id, log_message, callbacks)) < 0)
1903
+ goto on_error;
1904
+
1905
+ git_oid_cpy(&oid_head.oid, &id);
1906
+ oid_head.name = spec->src;
1907
+
1908
+ if ((error = git_vector_insert(&update_heads, &oid_head)) < 0)
1909
+ goto on_error;
1474
1910
  }
1475
1911
 
1476
1912
  if (update_fetchhead &&
1477
1913
  (error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0)
1478
1914
  goto on_error;
1479
1915
 
1480
- git_vector_free(&update_heads);
1481
1916
  git_refspec__dispose(&tagspec);
1482
- git_buf_dispose(&refname);
1917
+ git_vector_free(&update_heads);
1483
1918
  return 0;
1484
1919
 
1485
1920
  on_error:
1486
- git_vector_free(&update_heads);
1487
1921
  git_refspec__dispose(&tagspec);
1488
- git_buf_dispose(&refname);
1922
+ git_vector_free(&update_heads);
1489
1923
  return -1;
1490
1924
 
1491
1925
  }
@@ -1505,6 +1939,7 @@ static int next_head(const git_remote *remote, git_vector *refs,
1505
1939
  git_remote_head *head;
1506
1940
  git_refspec *spec, *passive_spec;
1507
1941
  size_t i, j, k;
1942
+ int valid;
1508
1943
 
1509
1944
  active = &remote->active_refspecs;
1510
1945
  passive = &remote->passive_refspecs;
@@ -1516,7 +1951,10 @@ static int next_head(const git_remote *remote, git_vector *refs,
1516
1951
  for (; i < refs->length; i++) {
1517
1952
  head = git_vector_get(refs, i);
1518
1953
 
1519
- if (!git_reference_is_valid_name(head->name))
1954
+ if (git_reference_name_is_valid(&valid, head->name) < 0)
1955
+ return -1;
1956
+
1957
+ if (!valid)
1520
1958
  continue;
1521
1959
 
1522
1960
  for (; j < active->length; j++) {
@@ -1547,20 +1985,22 @@ static int next_head(const git_remote *remote, git_vector *refs,
1547
1985
  return GIT_ITEROVER;
1548
1986
  }
1549
1987
 
1550
- static int opportunistic_updates(const git_remote *remote, const git_remote_callbacks *callbacks,
1551
- git_vector *refs, const char *msg)
1988
+ static int opportunistic_updates(
1989
+ const git_remote *remote,
1990
+ const git_remote_callbacks *callbacks,
1991
+ git_vector *refs,
1992
+ const char *msg)
1552
1993
  {
1553
1994
  size_t i, j, k;
1554
1995
  git_refspec *spec;
1555
1996
  git_remote_head *head;
1556
- git_reference *ref;
1557
- git_buf refname = GIT_BUF_INIT;
1997
+ git_str refname = GIT_STR_INIT;
1558
1998
  int error = 0;
1559
1999
 
1560
2000
  i = j = k = 0;
1561
2001
 
2002
+ /* Handle refspecs matching remote heads */
1562
2003
  while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
1563
- git_oid old = {{ 0 }};
1564
2004
  /*
1565
2005
  * If we got here, there is a refspec which was used
1566
2006
  * for fetching which matches the source of one of the
@@ -1569,50 +2009,32 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call
1569
2009
  * FETCH_HEAD
1570
2010
  */
1571
2011
 
1572
- git_buf_clear(&refname);
1573
- if ((error = git_refspec_transform(&refname, spec, head->name)) < 0)
1574
- goto cleanup;
1575
-
1576
- error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1577
- if (error < 0 && error != GIT_ENOTFOUND)
1578
- goto cleanup;
1579
-
1580
- if (!git_oid_cmp(&old, &head->oid))
1581
- continue;
1582
-
1583
- /* If we did find a current reference, make sure we haven't lost a race */
1584
- if (error)
1585
- error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, true, msg);
1586
- else
1587
- error = git_reference_create_matching(&ref, remote->repo, refname.ptr, &head->oid, true, &old, msg);
1588
- git_reference_free(ref);
1589
- if (error < 0)
2012
+ git_str_clear(&refname);
2013
+ if ((error = git_refspec__transform(&refname, spec, head->name)) < 0 ||
2014
+ (error = update_ref(remote, refname.ptr, &head->oid, msg, callbacks)) < 0)
1590
2015
  goto cleanup;
1591
-
1592
- if (callbacks && callbacks->update_tips != NULL) {
1593
- if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
1594
- goto cleanup;
1595
- }
1596
2016
  }
1597
2017
 
1598
- if (error == GIT_ITEROVER)
1599
- error = 0;
2018
+ if (error != GIT_ITEROVER)
2019
+ goto cleanup;
2020
+
2021
+ error = 0;
1600
2022
 
1601
2023
  cleanup:
1602
- git_buf_dispose(&refname);
2024
+ git_str_dispose(&refname);
1603
2025
  return error;
1604
2026
  }
1605
2027
 
1606
2028
  static int truncate_fetch_head(const char *gitdir)
1607
2029
  {
1608
- git_buf path = GIT_BUF_INIT;
2030
+ git_str path = GIT_STR_INIT;
1609
2031
  int error;
1610
2032
 
1611
- if ((error = git_buf_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0)
2033
+ if ((error = git_str_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0)
1612
2034
  return error;
1613
2035
 
1614
2036
  error = git_futils_truncate(path.ptr, GIT_REFS_FILE_MODE);
1615
- git_buf_dispose(&path);
2037
+ git_str_dispose(&path);
1616
2038
 
1617
2039
  return error;
1618
2040
  }
@@ -1663,7 +2085,7 @@ int git_remote_update_tips(
1663
2085
  goto out;
1664
2086
  }
1665
2087
 
1666
- /* only try to do opportunisitic updates if the refpec lists differ */
2088
+ /* Only try to do opportunistic updates if the refspec lists differ. */
1667
2089
  if (remote->passed_refspecs)
1668
2090
  error = opportunistic_updates(remote, callbacks, &refs, reflog_message);
1669
2091
 
@@ -1675,7 +2097,7 @@ out:
1675
2097
 
1676
2098
  int git_remote_connected(const git_remote *remote)
1677
2099
  {
1678
- assert(remote);
2100
+ GIT_ASSERT_ARG(remote);
1679
2101
 
1680
2102
  if (!remote->transport || !remote->transport->is_connected)
1681
2103
  return 0;
@@ -1686,7 +2108,7 @@ int git_remote_connected(const git_remote *remote)
1686
2108
 
1687
2109
  int git_remote_stop(git_remote *remote)
1688
2110
  {
1689
- assert(remote);
2111
+ GIT_ASSERT_ARG(remote);
1690
2112
 
1691
2113
  if (remote->transport && remote->transport->cancel)
1692
2114
  remote->transport->cancel(remote->transport);
@@ -1696,7 +2118,7 @@ int git_remote_stop(git_remote *remote)
1696
2118
 
1697
2119
  int git_remote_disconnect(git_remote *remote)
1698
2120
  {
1699
- assert(remote);
2121
+ GIT_ASSERT_ARG(remote);
1700
2122
 
1701
2123
  if (git_remote_connected(remote))
1702
2124
  remote->transport->close(remote->transport);
@@ -1704,6 +2126,17 @@ int git_remote_disconnect(git_remote *remote)
1704
2126
  return 0;
1705
2127
  }
1706
2128
 
2129
+ static void free_heads(git_vector *heads)
2130
+ {
2131
+ git_remote_head *head;
2132
+ size_t i;
2133
+
2134
+ git_vector_foreach(heads, i, head) {
2135
+ git__free(head->name);
2136
+ git__free(head);
2137
+ }
2138
+ }
2139
+
1707
2140
  void git_remote_free(git_remote *remote)
1708
2141
  {
1709
2142
  if (remote == NULL)
@@ -1727,6 +2160,9 @@ void git_remote_free(git_remote *remote)
1727
2160
  free_refspecs(&remote->passive_refspecs);
1728
2161
  git_vector_free(&remote->passive_refspecs);
1729
2162
 
2163
+ free_heads(&remote->local_heads);
2164
+ git_vector_free(&remote->local_heads);
2165
+
1730
2166
  git_push_free(remote->push);
1731
2167
  git__free(remote->url);
1732
2168
  git__free(remote->pushurl);
@@ -1782,7 +2218,7 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
1782
2218
 
1783
2219
  const git_indexer_progress *git_remote_stats(git_remote *remote)
1784
2220
  {
1785
- assert(remote);
2221
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
1786
2222
  return &remote->stats;
1787
2223
  }
1788
2224
 
@@ -1793,11 +2229,11 @@ git_remote_autotag_option_t git_remote_autotag(const git_remote *remote)
1793
2229
 
1794
2230
  int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_autotag_option_t value)
1795
2231
  {
1796
- git_buf var = GIT_BUF_INIT;
2232
+ git_str var = GIT_STR_INIT;
1797
2233
  git_config *config;
1798
2234
  int error;
1799
2235
 
1800
- assert(repo && remote);
2236
+ GIT_ASSERT_ARG(repo && remote);
1801
2237
 
1802
2238
  if ((error = ensure_remote_name_is_valid(remote)) < 0)
1803
2239
  return error;
@@ -1805,7 +2241,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_
1805
2241
  if ((error = git_repository_config__weakptr(&config, repo)) < 0)
1806
2242
  return error;
1807
2243
 
1808
- if ((error = git_buf_printf(&var, CONFIG_TAGOPT_FMT, remote)))
2244
+ if ((error = git_str_printf(&var, CONFIG_TAGOPT_FMT, remote)))
1809
2245
  return error;
1810
2246
 
1811
2247
  switch (value) {
@@ -1825,7 +2261,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_
1825
2261
  error = -1;
1826
2262
  }
1827
2263
 
1828
- git_buf_dispose(&var);
2264
+ git_str_dispose(&var);
1829
2265
  return error;
1830
2266
  }
1831
2267
 
@@ -1839,25 +2275,25 @@ static int rename_remote_config_section(
1839
2275
  const char *old_name,
1840
2276
  const char *new_name)
1841
2277
  {
1842
- git_buf old_section_name = GIT_BUF_INIT,
1843
- new_section_name = GIT_BUF_INIT;
2278
+ git_str old_section_name = GIT_STR_INIT,
2279
+ new_section_name = GIT_STR_INIT;
1844
2280
  int error = -1;
1845
2281
 
1846
- if (git_buf_printf(&old_section_name, "remote.%s", old_name) < 0)
2282
+ if (git_str_printf(&old_section_name, "remote.%s", old_name) < 0)
1847
2283
  goto cleanup;
1848
2284
 
1849
2285
  if (new_name &&
1850
- (git_buf_printf(&new_section_name, "remote.%s", new_name) < 0))
2286
+ (git_str_printf(&new_section_name, "remote.%s", new_name) < 0))
1851
2287
  goto cleanup;
1852
2288
 
1853
2289
  error = git_config_rename_section(
1854
2290
  repo,
1855
- git_buf_cstr(&old_section_name),
1856
- new_name ? git_buf_cstr(&new_section_name) : NULL);
2291
+ git_str_cstr(&old_section_name),
2292
+ new_name ? git_str_cstr(&new_section_name) : NULL);
1857
2293
 
1858
2294
  cleanup:
1859
- git_buf_dispose(&old_section_name);
1860
- git_buf_dispose(&new_section_name);
2295
+ git_str_dispose(&old_section_name);
2296
+ git_str_dispose(&new_section_name);
1861
2297
 
1862
2298
  return error;
1863
2299
  }
@@ -1906,27 +2342,27 @@ static int rename_one_remote_reference(
1906
2342
  {
1907
2343
  int error;
1908
2344
  git_reference *ref = NULL, *dummy = NULL;
1909
- git_buf namespace = GIT_BUF_INIT, old_namespace = GIT_BUF_INIT;
1910
- git_buf new_name = GIT_BUF_INIT;
1911
- git_buf log_message = GIT_BUF_INIT;
2345
+ git_str namespace = GIT_STR_INIT, old_namespace = GIT_STR_INIT;
2346
+ git_str new_name = GIT_STR_INIT;
2347
+ git_str log_message = GIT_STR_INIT;
1912
2348
  size_t pfx_len;
1913
2349
  const char *target;
1914
2350
 
1915
- if ((error = git_buf_printf(&namespace, GIT_REFS_REMOTES_DIR "%s/", new_remote_name)) < 0)
2351
+ if ((error = git_str_printf(&namespace, GIT_REFS_REMOTES_DIR "%s/", new_remote_name)) < 0)
1916
2352
  return error;
1917
2353
 
1918
2354
  pfx_len = strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name) + 1;
1919
- git_buf_puts(&new_name, namespace.ptr);
1920
- if ((error = git_buf_puts(&new_name, git_reference_name(reference_in) + pfx_len)) < 0)
2355
+ git_str_puts(&new_name, namespace.ptr);
2356
+ if ((error = git_str_puts(&new_name, git_reference_name(reference_in) + pfx_len)) < 0)
1921
2357
  goto cleanup;
1922
2358
 
1923
- if ((error = git_buf_printf(&log_message,
2359
+ if ((error = git_str_printf(&log_message,
1924
2360
  "renamed remote %s to %s",
1925
2361
  old_remote_name, new_remote_name)) < 0)
1926
2362
  goto cleanup;
1927
2363
 
1928
- if ((error = git_reference_rename(&ref, reference_in, git_buf_cstr(&new_name), 1,
1929
- git_buf_cstr(&log_message))) < 0)
2364
+ if ((error = git_reference_rename(&ref, reference_in, git_str_cstr(&new_name), 1,
2365
+ git_str_cstr(&log_message))) < 0)
1930
2366
  goto cleanup;
1931
2367
 
1932
2368
  if (git_reference_type(ref) != GIT_REFERENCE_SYMBOLIC)
@@ -1934,29 +2370,29 @@ static int rename_one_remote_reference(
1934
2370
 
1935
2371
  /* Handle refs like origin/HEAD -> origin/master */
1936
2372
  target = git_reference_symbolic_target(ref);
1937
- if ((error = git_buf_printf(&old_namespace, GIT_REFS_REMOTES_DIR "%s/", old_remote_name)) < 0)
2373
+ if ((error = git_str_printf(&old_namespace, GIT_REFS_REMOTES_DIR "%s/", old_remote_name)) < 0)
1938
2374
  goto cleanup;
1939
2375
 
1940
2376
  if (git__prefixcmp(target, old_namespace.ptr))
1941
2377
  goto cleanup;
1942
2378
 
1943
- git_buf_clear(&new_name);
1944
- git_buf_puts(&new_name, namespace.ptr);
1945
- if ((error = git_buf_puts(&new_name, target + pfx_len)) < 0)
2379
+ git_str_clear(&new_name);
2380
+ git_str_puts(&new_name, namespace.ptr);
2381
+ if ((error = git_str_puts(&new_name, target + pfx_len)) < 0)
1946
2382
  goto cleanup;
1947
2383
 
1948
- error = git_reference_symbolic_set_target(&dummy, ref, git_buf_cstr(&new_name),
1949
- git_buf_cstr(&log_message));
2384
+ error = git_reference_symbolic_set_target(&dummy, ref, git_str_cstr(&new_name),
2385
+ git_str_cstr(&log_message));
1950
2386
 
1951
2387
  git_reference_free(dummy);
1952
2388
 
1953
2389
  cleanup:
1954
2390
  git_reference_free(reference_in);
1955
2391
  git_reference_free(ref);
1956
- git_buf_dispose(&namespace);
1957
- git_buf_dispose(&old_namespace);
1958
- git_buf_dispose(&new_name);
1959
- git_buf_dispose(&log_message);
2392
+ git_str_dispose(&namespace);
2393
+ git_str_dispose(&old_namespace);
2394
+ git_str_dispose(&new_name);
2395
+ git_str_dispose(&log_message);
1960
2396
  return error;
1961
2397
  }
1962
2398
 
@@ -1966,15 +2402,15 @@ static int rename_remote_references(
1966
2402
  const char *new_name)
1967
2403
  {
1968
2404
  int error;
1969
- git_buf buf = GIT_BUF_INIT;
2405
+ git_str buf = GIT_STR_INIT;
1970
2406
  git_reference *ref;
1971
2407
  git_reference_iterator *iter;
1972
2408
 
1973
- if ((error = git_buf_printf(&buf, GIT_REFS_REMOTES_DIR "%s/*", old_name)) < 0)
2409
+ if ((error = git_str_printf(&buf, GIT_REFS_REMOTES_DIR "%s/*", old_name)) < 0)
1974
2410
  return error;
1975
2411
 
1976
- error = git_reference_iterator_glob_new(&iter, repo, git_buf_cstr(&buf));
1977
- git_buf_dispose(&buf);
2412
+ error = git_reference_iterator_glob_new(&iter, repo, git_str_cstr(&buf));
2413
+ git_str_dispose(&buf);
1978
2414
 
1979
2415
  if (error < 0)
1980
2416
  return error;
@@ -1992,7 +2428,7 @@ static int rename_remote_references(
1992
2428
  static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const char *new_name)
1993
2429
  {
1994
2430
  git_config *config;
1995
- git_buf base = GIT_BUF_INIT, var = GIT_BUF_INIT, val = GIT_BUF_INIT;
2431
+ git_str base = GIT_STR_INIT, var = GIT_STR_INIT, val = GIT_STR_INIT;
1996
2432
  const git_refspec *spec;
1997
2433
  size_t i;
1998
2434
  int error = 0;
@@ -2011,7 +2447,7 @@ static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const
2011
2447
  continue;
2012
2448
 
2013
2449
  /* Does the dst part of the refspec follow the expected format? */
2014
- if (strcmp(git_buf_cstr(&base), spec->string)) {
2450
+ if (strcmp(git_str_cstr(&base), spec->string)) {
2015
2451
  char *dup;
2016
2452
 
2017
2453
  dup = git__strdup(spec->string);
@@ -2025,24 +2461,24 @@ static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const
2025
2461
 
2026
2462
  /* If we do want to move it to the new section */
2027
2463
 
2028
- git_buf_clear(&val);
2029
- git_buf_clear(&var);
2464
+ git_str_clear(&val);
2465
+ git_str_clear(&var);
2030
2466
 
2031
2467
  if (default_fetchspec_for_name(&val, new_name) < 0 ||
2032
- git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
2468
+ git_str_printf(&var, "remote.%s.fetch", new_name) < 0)
2033
2469
  {
2034
2470
  error = -1;
2035
2471
  break;
2036
2472
  }
2037
2473
 
2038
2474
  if ((error = git_config_set_string(
2039
- config, git_buf_cstr(&var), git_buf_cstr(&val))) < 0)
2475
+ config, git_str_cstr(&var), git_str_cstr(&val))) < 0)
2040
2476
  break;
2041
2477
  }
2042
2478
 
2043
- git_buf_dispose(&base);
2044
- git_buf_dispose(&var);
2045
- git_buf_dispose(&val);
2479
+ git_str_dispose(&base);
2480
+ git_str_dispose(&var);
2481
+ git_str_dispose(&val);
2046
2482
 
2047
2483
  if (error < 0) {
2048
2484
  char *str;
@@ -2061,7 +2497,7 @@ int git_remote_rename(git_strarray *out, git_repository *repo, const char *name,
2061
2497
  git_vector problem_refspecs = GIT_VECTOR_INIT;
2062
2498
  git_remote *remote = NULL;
2063
2499
 
2064
- assert(out && repo && name && new_name);
2500
+ GIT_ASSERT_ARG(out && repo && name && new_name);
2065
2501
 
2066
2502
  if ((error = git_remote_lookup(&remote, repo, name)) < 0)
2067
2503
  return error;
@@ -2095,24 +2531,34 @@ cleanup:
2095
2531
  return error;
2096
2532
  }
2097
2533
 
2098
- int git_remote_is_valid_name(
2099
- const char *remote_name)
2534
+ int git_remote_name_is_valid(int *valid, const char *remote_name)
2100
2535
  {
2101
- git_buf buf = GIT_BUF_INIT;
2102
- git_refspec refspec;
2103
- int error = -1;
2536
+ git_str buf = GIT_STR_INIT;
2537
+ git_refspec refspec = {0};
2538
+ int error;
2539
+
2540
+ GIT_ASSERT(valid);
2541
+
2542
+ *valid = 0;
2104
2543
 
2105
2544
  if (!remote_name || *remote_name == '\0')
2106
2545
  return 0;
2107
2546
 
2108
- git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name);
2109
- error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
2547
+ if ((error = git_str_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name)) < 0)
2548
+ goto done;
2549
+
2550
+ error = git_refspec__parse(&refspec, git_str_cstr(&buf), true);
2110
2551
 
2111
- git_buf_dispose(&buf);
2552
+ if (!error)
2553
+ *valid = 1;
2554
+ else if (error == GIT_EINVALIDSPEC)
2555
+ error = 0;
2556
+
2557
+ done:
2558
+ git_str_dispose(&buf);
2112
2559
  git_refspec__dispose(&refspec);
2113
2560
 
2114
- git_error_clear();
2115
- return error == 0;
2561
+ return error;
2116
2562
  }
2117
2563
 
2118
2564
  git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refname)
@@ -2227,7 +2673,7 @@ static const char *name_offset(size_t *len_out, const char *name)
2227
2673
  prefix_len = strlen("remote.");
2228
2674
  dot = strchr(name + prefix_len, '.');
2229
2675
 
2230
- assert(dot);
2676
+ GIT_ASSERT_ARG_WITH_RETVAL(dot, NULL);
2231
2677
 
2232
2678
  *len_out = dot - name - prefix_len;
2233
2679
  return name + prefix_len;
@@ -2241,7 +2687,7 @@ static int remove_branch_config_related_entries(
2241
2687
  git_config *config;
2242
2688
  git_config_entry *entry;
2243
2689
  git_config_iterator *iter;
2244
- git_buf buf = GIT_BUF_INIT;
2690
+ git_str buf = GIT_STR_INIT;
2245
2691
 
2246
2692
  if ((error = git_repository_config__weakptr(&config, repo)) < 0)
2247
2693
  return error;
@@ -2257,23 +2703,26 @@ static int remove_branch_config_related_entries(
2257
2703
  if (strcmp(remote_name, entry->value))
2258
2704
  continue;
2259
2705
 
2260
- branch = name_offset(&branch_len, entry->name);
2706
+ if ((branch = name_offset(&branch_len, entry->name)) == NULL) {
2707
+ error = -1;
2708
+ break;
2709
+ }
2261
2710
 
2262
- git_buf_clear(&buf);
2263
- if (git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch) < 0)
2711
+ git_str_clear(&buf);
2712
+ if ((error = git_str_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch)) < 0)
2264
2713
  break;
2265
2714
 
2266
- if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
2715
+ if ((error = git_config_delete_entry(config, git_str_cstr(&buf))) < 0) {
2267
2716
  if (error != GIT_ENOTFOUND)
2268
2717
  break;
2269
2718
  git_error_clear();
2270
2719
  }
2271
2720
 
2272
- git_buf_clear(&buf);
2273
- if (git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch) < 0)
2721
+ git_str_clear(&buf);
2722
+ if ((error = git_str_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch)) < 0)
2274
2723
  break;
2275
2724
 
2276
- if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
2725
+ if ((error = git_config_delete_entry(config, git_str_cstr(&buf))) < 0) {
2277
2726
  if (error != GIT_ENOTFOUND)
2278
2727
  break;
2279
2728
  git_error_clear();
@@ -2283,7 +2732,7 @@ static int remove_branch_config_related_entries(
2283
2732
  if (error == GIT_ITEROVER)
2284
2733
  error = 0;
2285
2734
 
2286
- git_buf_dispose(&buf);
2735
+ git_str_dispose(&buf);
2287
2736
  git_config_iterator_free(iter);
2288
2737
  return error;
2289
2738
  }
@@ -2365,7 +2814,8 @@ int git_remote_delete(git_repository *repo, const char *name)
2365
2814
  {
2366
2815
  int error;
2367
2816
 
2368
- assert(repo && name);
2817
+ GIT_ASSERT_ARG(repo);
2818
+ GIT_ASSERT_ARG(name);
2369
2819
 
2370
2820
  if ((error = remove_branch_config_related_entries(repo, name)) < 0 ||
2371
2821
  (error = remove_remote_tracking(repo, name)) < 0 ||
@@ -2376,15 +2826,20 @@ int git_remote_delete(git_repository *repo, const char *name)
2376
2826
  }
2377
2827
 
2378
2828
  int git_remote_default_branch(git_buf *out, git_remote *remote)
2829
+ {
2830
+ GIT_BUF_WRAP_PRIVATE(out, git_remote__default_branch, remote);
2831
+ }
2832
+
2833
+ int git_remote__default_branch(git_str *out, git_remote *remote)
2379
2834
  {
2380
2835
  const git_remote_head **heads;
2381
2836
  const git_remote_head *guess = NULL;
2382
2837
  const git_oid *head_id;
2383
2838
  size_t heads_len, i;
2384
- git_buf local_default = GIT_BUF_INIT;
2839
+ git_str local_default = GIT_STR_INIT;
2385
2840
  int error;
2386
2841
 
2387
- assert(out);
2842
+ GIT_ASSERT_ARG(out);
2388
2843
 
2389
2844
  if ((error = git_remote_ls(&heads, &heads_len, remote)) < 0)
2390
2845
  goto done;
@@ -2394,11 +2849,9 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
2394
2849
  goto done;
2395
2850
  }
2396
2851
 
2397
- git_buf_sanitize(out);
2398
-
2399
2852
  /* the first one must be HEAD so if that has the symref info, we're done */
2400
2853
  if (heads[0]->symref_target) {
2401
- error = git_buf_puts(out, heads[0]->symref_target);
2854
+ error = git_str_puts(out, heads[0]->symref_target);
2402
2855
  goto done;
2403
2856
  }
2404
2857
 
@@ -2436,37 +2889,45 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
2436
2889
  goto done;
2437
2890
  }
2438
2891
 
2439
- error = git_buf_puts(out, guess->name);
2892
+ error = git_str_puts(out, guess->name);
2440
2893
 
2441
2894
  done:
2442
- git_buf_dispose(&local_default);
2895
+ git_str_dispose(&local_default);
2443
2896
  return error;
2444
2897
  }
2445
2898
 
2446
- int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
2899
+ GIT_INLINE(int) connect_opts_from_push_opts(
2900
+ git_remote_connect_options *out,
2901
+ git_remote *remote,
2902
+ const git_push_options *push_opts)
2447
2903
  {
2448
- size_t i;
2449
- int error;
2904
+ git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
2905
+ copy_opts(&tmp, push_opts);
2906
+ return git_remote_connect_options_normalize(out, remote->repo, &tmp);
2907
+ }
2908
+
2909
+ int git_remote_upload(
2910
+ git_remote *remote,
2911
+ const git_strarray *refspecs,
2912
+ const git_push_options *opts)
2913
+ {
2914
+ git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
2450
2915
  git_push *push;
2451
2916
  git_refspec *spec;
2452
- const git_remote_callbacks *cbs = NULL;
2453
- git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
2917
+ size_t i;
2918
+ int error;
2454
2919
 
2455
- assert(remote);
2920
+ GIT_ASSERT_ARG(remote);
2456
2921
 
2457
2922
  if (!remote->repo) {
2458
2923
  git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
2459
2924
  return -1;
2460
2925
  }
2461
2926
 
2462
- if (opts) {
2463
- cbs = &opts->callbacks;
2464
- conn.custom_headers = &opts->custom_headers;
2465
- conn.proxy = &opts->proxy_opts;
2466
- }
2927
+ if ((error = connect_opts_from_push_opts(&connect_opts, remote, opts)) < 0)
2928
+ goto cleanup;
2467
2929
 
2468
- if (!git_remote_connected(remote) &&
2469
- (error = git_remote__connect(remote, GIT_DIRECTION_PUSH, cbs, &conn)) < 0)
2930
+ if ((error = connect_or_reset_options(remote, GIT_DIRECTION_PUSH, &connect_opts)) < 0)
2470
2931
  goto cleanup;
2471
2932
 
2472
2933
  free_refspecs(&remote->active_refspecs);
@@ -2478,14 +2939,11 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
2478
2939
  remote->push = NULL;
2479
2940
  }
2480
2941
 
2481
- if ((error = git_push_new(&remote->push, remote)) < 0)
2482
- return error;
2942
+ if ((error = git_push_new(&remote->push, remote, opts)) < 0)
2943
+ goto cleanup;
2483
2944
 
2484
2945
  push = remote->push;
2485
2946
 
2486
- if (opts && (error = git_push_set_options(push, opts)) < 0)
2487
- goto cleanup;
2488
-
2489
2947
  if (refspecs && refspecs->count > 0) {
2490
2948
  for (i = 0; i < refspecs->count; i++) {
2491
2949
  if ((error = git_push_add_refspec(push, refspecs->strings[i])) < 0)
@@ -2500,50 +2958,44 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
2500
2958
  }
2501
2959
  }
2502
2960
 
2503
- if ((error = git_push_finish(push, cbs)) < 0)
2961
+ if ((error = git_push_finish(push)) < 0)
2504
2962
  goto cleanup;
2505
2963
 
2506
- if (cbs && cbs->push_update_reference &&
2507
- (error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
2964
+ if (connect_opts.callbacks.push_update_reference &&
2965
+ (error = git_push_status_foreach(push, connect_opts.callbacks.push_update_reference, connect_opts.callbacks.payload)) < 0)
2508
2966
  goto cleanup;
2509
2967
 
2510
2968
  cleanup:
2969
+ git_remote_connect_options_dispose(&connect_opts);
2511
2970
  return error;
2512
2971
  }
2513
2972
 
2514
- int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
2973
+ int git_remote_push(
2974
+ git_remote *remote,
2975
+ const git_strarray *refspecs,
2976
+ const git_push_options *opts)
2515
2977
  {
2978
+ git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
2516
2979
  int error;
2517
- const git_remote_callbacks *cbs = NULL;
2518
- const git_strarray *custom_headers = NULL;
2519
- const git_proxy_options *proxy = NULL;
2520
2980
 
2521
- assert(remote);
2981
+ GIT_ASSERT_ARG(remote);
2522
2982
 
2523
2983
  if (!remote->repo) {
2524
2984
  git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
2525
2985
  return -1;
2526
2986
  }
2527
2987
 
2528
- if (opts) {
2529
- GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
2530
- cbs = &opts->callbacks;
2531
- custom_headers = &opts->custom_headers;
2532
- GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
2533
- proxy = &opts->proxy_opts;
2534
- }
2535
-
2536
- assert(remote);
2537
-
2538
- if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
2539
- return error;
2988
+ if (connect_opts_from_push_opts(&connect_opts, remote, opts) < 0)
2989
+ return -1;
2540
2990
 
2541
2991
  if ((error = git_remote_upload(remote, refspecs, opts)) < 0)
2542
- return error;
2992
+ goto done;
2543
2993
 
2544
- error = git_remote_update_tips(remote, cbs, 0, 0, NULL);
2994
+ error = git_remote_update_tips(remote, &connect_opts.callbacks, 0, 0, NULL);
2545
2995
 
2996
+ done:
2546
2997
  git_remote_disconnect(remote);
2998
+ git_remote_connect_options_dispose(&connect_opts);
2547
2999
  return error;
2548
3000
  }
2549
3001
 
@@ -2551,19 +3003,20 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
2551
3003
  #define SUFFIX_FETCH "insteadof"
2552
3004
  #define SUFFIX_PUSH "pushinsteadof"
2553
3005
 
2554
- char *apply_insteadof(git_config *config, const char *url, int direction)
3006
+ static int apply_insteadof(char **out, git_config *config, const char *url, int direction, bool use_default_if_empty)
2555
3007
  {
2556
3008
  size_t match_length, prefix_length, suffix_length;
2557
3009
  char *replacement = NULL;
2558
3010
  const char *regexp;
2559
3011
 
2560
- git_buf result = GIT_BUF_INIT;
3012
+ git_str result = GIT_STR_INIT;
2561
3013
  git_config_entry *entry;
2562
3014
  git_config_iterator *iter;
2563
3015
 
2564
- assert(config);
2565
- assert(url);
2566
- assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
3016
+ GIT_ASSERT_ARG(out);
3017
+ GIT_ASSERT_ARG(config);
3018
+ GIT_ASSERT_ARG(url);
3019
+ GIT_ASSERT_ARG(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
2567
3020
 
2568
3021
  /* Add 1 to prefix/suffix length due to the additional escaped dot */
2569
3022
  prefix_length = strlen(PREFIX) + 1;
@@ -2576,7 +3029,7 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
2576
3029
  }
2577
3030
 
2578
3031
  if (git_config_iterator_glob_new(&iter, config, regexp) < 0)
2579
- return NULL;
3032
+ return -1;
2580
3033
 
2581
3034
  match_length = 0;
2582
3035
  while (git_config_next(&entry, iter) == 0) {
@@ -2585,6 +3038,7 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
2585
3038
  /* Check if entry value is a prefix of URL */
2586
3039
  if (git__prefixcmp(url, entry->value))
2587
3040
  continue;
3041
+
2588
3042
  /* Check if entry value is longer than previous
2589
3043
  * prefixes */
2590
3044
  if ((n = strlen(entry->value)) <= match_length)
@@ -2602,12 +3056,32 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
2602
3056
 
2603
3057
  git_config_iterator_free(iter);
2604
3058
 
2605
- if (match_length == 0)
2606
- return git__strdup(url);
3059
+ if (match_length == 0 && use_default_if_empty) {
3060
+ *out = git__strdup(url);
3061
+ return *out ? 0 : -1;
3062
+ } else if (match_length == 0) {
3063
+ *out = NULL;
3064
+ return 0;
3065
+ }
2607
3066
 
2608
- git_buf_printf(&result, "%s%s", replacement, url + match_length);
3067
+ git_str_printf(&result, "%s%s", replacement, url + match_length);
2609
3068
 
2610
3069
  git__free(replacement);
2611
3070
 
2612
- return result.ptr;
3071
+ *out = git_str_detach(&result);
3072
+ return 0;
2613
3073
  }
3074
+
3075
+ /* Deprecated functions */
3076
+
3077
+ #ifndef GIT_DEPRECATE_HARD
3078
+
3079
+ int git_remote_is_valid_name(const char *remote_name)
3080
+ {
3081
+ int valid = 0;
3082
+
3083
+ git_remote_name_is_valid(&valid, remote_name);
3084
+ return valid;
3085
+ }
3086
+
3087
+ #endif