rugged 1.3.2.3 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (329) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/extconf.rb +1 -1
  3. data/ext/rugged/rugged_config.c +7 -2
  4. data/ext/rugged/rugged_remote.c +17 -0
  5. data/lib/rugged/version.rb +1 -1
  6. data/vendor/libgit2/CMakeLists.txt +103 -276
  7. data/vendor/libgit2/COPYING +36 -19
  8. data/vendor/libgit2/cmake/AddCFlagIfSupported.cmake +21 -21
  9. data/vendor/libgit2/cmake/DefaultCFlags.cmake +154 -0
  10. data/vendor/libgit2/cmake/EnableWarnings.cmake +13 -13
  11. data/vendor/libgit2/cmake/FindCoreFoundation.cmake +13 -13
  12. data/vendor/libgit2/cmake/FindGSSAPI.cmake +171 -287
  13. data/vendor/libgit2/cmake/FindGSSFramework.cmake +13 -13
  14. data/vendor/libgit2/cmake/{FindHTTP_Parser.cmake → FindHTTPParser.cmake} +17 -17
  15. data/vendor/libgit2/cmake/FindIconv.cmake +27 -27
  16. data/vendor/libgit2/cmake/FindLibSSH2.cmake +5 -5
  17. data/vendor/libgit2/cmake/FindPCRE.cmake +13 -13
  18. data/vendor/libgit2/cmake/FindPCRE2.cmake +12 -12
  19. data/vendor/libgit2/cmake/FindPkgLibraries.cmake +19 -19
  20. data/vendor/libgit2/cmake/FindSecurity.cmake +14 -14
  21. data/vendor/libgit2/cmake/FindStatNsec.cmake +12 -18
  22. data/vendor/libgit2/cmake/Findfutimens.cmake +8 -8
  23. data/vendor/libgit2/cmake/FindmbedTLS.cmake +63 -70
  24. data/vendor/libgit2/cmake/IdeSplitSources.cmake +18 -18
  25. data/vendor/libgit2/cmake/PkgBuildConfig.cmake +60 -60
  26. data/vendor/libgit2/cmake/SanitizeBool.cmake +20 -20
  27. data/vendor/libgit2/cmake/SelectGSSAPI.cmake +37 -37
  28. data/vendor/libgit2/cmake/SelectHTTPParser.cmake +19 -0
  29. data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +100 -100
  30. data/vendor/libgit2/cmake/SelectHashes.cmake +39 -49
  31. data/vendor/libgit2/cmake/SelectRegex.cmake +51 -0
  32. data/vendor/libgit2/cmake/SelectSSH.cmake +41 -0
  33. data/vendor/libgit2/cmake/SelectWinHTTP.cmake +17 -0
  34. data/vendor/libgit2/cmake/SelectZlib.cmake +34 -0
  35. data/vendor/libgit2/deps/chromium-zlib/CMakeLists.txt +6 -6
  36. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +31 -31
  37. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +1 -1
  38. data/vendor/libgit2/deps/ntlmclient/ntlm.c +4 -4
  39. data/vendor/libgit2/deps/ntlmclient/ntlm.h +4 -4
  40. data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +2 -2
  41. data/vendor/libgit2/deps/pcre/CMakeLists.txt +88 -88
  42. data/vendor/libgit2/deps/winhttp/CMakeLists.txt +14 -16
  43. data/vendor/libgit2/deps/zlib/adler32.c +0 -7
  44. data/vendor/libgit2/deps/zlib/crc32.c +288 -975
  45. data/vendor/libgit2/deps/zlib/crc32.h +436 -9441
  46. data/vendor/libgit2/deps/zlib/deflate.c +31 -83
  47. data/vendor/libgit2/deps/zlib/deflate.h +15 -12
  48. data/vendor/libgit2/deps/zlib/gzguts.h +2 -3
  49. data/vendor/libgit2/deps/zlib/infback.c +1 -2
  50. data/vendor/libgit2/deps/zlib/inffast.c +14 -14
  51. data/vendor/libgit2/deps/zlib/inflate.c +8 -39
  52. data/vendor/libgit2/deps/zlib/inflate.h +2 -3
  53. data/vendor/libgit2/deps/zlib/inftrees.c +3 -3
  54. data/vendor/libgit2/deps/zlib/trees.c +48 -27
  55. data/vendor/libgit2/deps/zlib/zlib.h +100 -126
  56. data/vendor/libgit2/deps/zlib/zutil.c +2 -2
  57. data/vendor/libgit2/deps/zlib/zutil.h +9 -12
  58. data/vendor/libgit2/include/git2/apply.h +16 -2
  59. data/vendor/libgit2/include/git2/attr.h +11 -2
  60. data/vendor/libgit2/include/git2/blame.h +4 -1
  61. data/vendor/libgit2/include/git2/blob.h +14 -1
  62. data/vendor/libgit2/include/git2/branch.h +2 -0
  63. data/vendor/libgit2/include/git2/buffer.h +18 -78
  64. data/vendor/libgit2/include/git2/cert.h +2 -2
  65. data/vendor/libgit2/include/git2/checkout.h +5 -2
  66. data/vendor/libgit2/include/git2/clone.h +3 -3
  67. data/vendor/libgit2/include/git2/commit.h +2 -0
  68. data/vendor/libgit2/include/git2/common.h +5 -12
  69. data/vendor/libgit2/include/git2/config.h +19 -3
  70. data/vendor/libgit2/include/git2/credential.h +2 -1
  71. data/vendor/libgit2/include/git2/credential_helpers.h +1 -0
  72. data/vendor/libgit2/include/git2/deprecated.h +1 -1
  73. data/vendor/libgit2/include/git2/describe.h +7 -2
  74. data/vendor/libgit2/include/git2/diff.h +17 -9
  75. data/vendor/libgit2/include/git2/email.h +1 -1
  76. data/vendor/libgit2/include/git2/errors.h +1 -2
  77. data/vendor/libgit2/include/git2/filter.h +7 -2
  78. data/vendor/libgit2/include/git2/graph.h +1 -0
  79. data/vendor/libgit2/include/git2/ignore.h +1 -1
  80. data/vendor/libgit2/include/git2/index.h +11 -5
  81. data/vendor/libgit2/include/git2/indexer.h +19 -0
  82. data/vendor/libgit2/include/git2/merge.h +23 -3
  83. data/vendor/libgit2/include/git2/message.h +2 -0
  84. data/vendor/libgit2/include/git2/object.h +23 -0
  85. data/vendor/libgit2/include/git2/odb.h +37 -7
  86. data/vendor/libgit2/include/git2/odb_backend.h +1 -1
  87. data/vendor/libgit2/include/git2/pack.h +24 -8
  88. data/vendor/libgit2/include/git2/patch.h +8 -0
  89. data/vendor/libgit2/include/git2/pathspec.h +1 -1
  90. data/vendor/libgit2/include/git2/proxy.h +1 -1
  91. data/vendor/libgit2/include/git2/rebase.h +9 -1
  92. data/vendor/libgit2/include/git2/refdb.h +3 -0
  93. data/vendor/libgit2/include/git2/reflog.h +1 -1
  94. data/vendor/libgit2/include/git2/refs.h +2 -2
  95. data/vendor/libgit2/include/git2/remote.h +184 -37
  96. data/vendor/libgit2/include/git2/repository.h +14 -9
  97. data/vendor/libgit2/include/git2/reset.h +2 -2
  98. data/vendor/libgit2/include/git2/revparse.h +1 -1
  99. data/vendor/libgit2/include/git2/revwalk.h +4 -1
  100. data/vendor/libgit2/include/git2/signature.h +1 -1
  101. data/vendor/libgit2/include/git2/stash.h +3 -3
  102. data/vendor/libgit2/include/git2/status.h +9 -3
  103. data/vendor/libgit2/include/git2/submodule.h +7 -2
  104. data/vendor/libgit2/include/git2/sys/commit_graph.h +1 -1
  105. data/vendor/libgit2/include/git2/sys/odb_backend.h +2 -5
  106. data/vendor/libgit2/include/git2/sys/remote.h +31 -0
  107. data/vendor/libgit2/include/git2/sys/stream.h +1 -1
  108. data/vendor/libgit2/include/git2/sys/transport.h +25 -34
  109. data/vendor/libgit2/include/git2/tag.h +1 -0
  110. data/vendor/libgit2/include/git2/tree.h +4 -3
  111. data/vendor/libgit2/include/git2/types.h +7 -7
  112. data/vendor/libgit2/include/git2/version.h +3 -3
  113. data/vendor/libgit2/include/git2/worktree.h +12 -2
  114. data/vendor/libgit2/src/CMakeLists.txt +189 -315
  115. data/vendor/libgit2/src/annotated_commit.h +1 -1
  116. data/vendor/libgit2/src/apply.c +18 -18
  117. data/vendor/libgit2/src/apply.h +2 -2
  118. data/vendor/libgit2/src/attr.c +18 -18
  119. data/vendor/libgit2/src/attr_file.c +17 -17
  120. data/vendor/libgit2/src/attr_file.h +4 -4
  121. data/vendor/libgit2/src/attrcache.c +17 -12
  122. data/vendor/libgit2/src/blame_git.c +1 -1
  123. data/vendor/libgit2/src/blob.c +33 -26
  124. data/vendor/libgit2/src/blob.h +1 -1
  125. data/vendor/libgit2/src/branch.c +150 -109
  126. data/vendor/libgit2/src/branch.h +15 -3
  127. data/vendor/libgit2/src/buf.c +126 -0
  128. data/vendor/libgit2/src/buf.h +50 -0
  129. data/vendor/libgit2/src/cc-compat.h +1 -1
  130. data/vendor/libgit2/src/checkout.c +74 -68
  131. data/vendor/libgit2/src/cherrypick.c +10 -10
  132. data/vendor/libgit2/src/clone.c +66 -66
  133. data/vendor/libgit2/src/commit.c +128 -58
  134. data/vendor/libgit2/src/commit.h +24 -1
  135. data/vendor/libgit2/src/commit_graph.c +68 -53
  136. data/vendor/libgit2/src/commit_graph.h +10 -3
  137. data/vendor/libgit2/src/commit_list.c +2 -3
  138. data/vendor/libgit2/src/common.h +10 -3
  139. data/vendor/libgit2/src/config.c +99 -77
  140. data/vendor/libgit2/src/config.h +15 -2
  141. data/vendor/libgit2/src/config_file.c +103 -91
  142. data/vendor/libgit2/src/config_mem.c +9 -9
  143. data/vendor/libgit2/src/config_parse.c +27 -23
  144. data/vendor/libgit2/src/crlf.c +24 -21
  145. data/vendor/libgit2/src/date.c +10 -17
  146. data/vendor/libgit2/src/date.h +33 -0
  147. data/vendor/libgit2/src/describe.c +27 -19
  148. data/vendor/libgit2/src/diff.c +25 -8
  149. data/vendor/libgit2/src/diff.h +2 -4
  150. data/vendor/libgit2/src/diff_driver.c +34 -36
  151. data/vendor/libgit2/src/diff_driver.h +3 -3
  152. data/vendor/libgit2/src/diff_file.c +29 -20
  153. data/vendor/libgit2/src/diff_generate.c +30 -6
  154. data/vendor/libgit2/src/diff_generate.h +5 -3
  155. data/vendor/libgit2/src/diff_print.c +102 -95
  156. data/vendor/libgit2/src/diff_stats.c +40 -29
  157. data/vendor/libgit2/src/{message.h → diff_stats.h} +7 -6
  158. data/vendor/libgit2/src/diff_tform.c +9 -8
  159. data/vendor/libgit2/src/diff_xdiff.c +3 -8
  160. data/vendor/libgit2/src/email.c +54 -38
  161. data/vendor/libgit2/src/email.h +1 -1
  162. data/vendor/libgit2/src/errors.c +18 -18
  163. data/vendor/libgit2/src/features.h.in +6 -1
  164. data/vendor/libgit2/src/fetch.c +69 -24
  165. data/vendor/libgit2/src/fetch.h +1 -1
  166. data/vendor/libgit2/src/fetchhead.c +19 -19
  167. data/vendor/libgit2/src/filebuf.c +28 -28
  168. data/vendor/libgit2/src/filebuf.h +1 -1
  169. data/vendor/libgit2/src/filter.c +96 -52
  170. data/vendor/libgit2/src/filter.h +26 -5
  171. data/vendor/libgit2/src/fs_path.c +1912 -0
  172. data/vendor/libgit2/src/fs_path.h +752 -0
  173. data/vendor/libgit2/src/futils.c +91 -85
  174. data/vendor/libgit2/src/futils.h +26 -14
  175. data/vendor/libgit2/src/hash/sha1/collisiondetect.c +2 -2
  176. data/vendor/libgit2/src/hash/sha1/common_crypto.c +2 -2
  177. data/vendor/libgit2/src/hash/sha1/generic.c +2 -2
  178. data/vendor/libgit2/src/hash/sha1/mbedtls.c +2 -2
  179. data/vendor/libgit2/src/hash/sha1/openssl.c +2 -2
  180. data/vendor/libgit2/src/hash/sha1/sha1dc/sha1.c +1 -1
  181. data/vendor/libgit2/src/hash/sha1/win32.c +6 -6
  182. data/vendor/libgit2/src/hash/sha1.h +3 -1
  183. data/vendor/libgit2/src/hash.c +67 -35
  184. data/vendor/libgit2/src/hash.h +12 -12
  185. data/vendor/libgit2/src/ident.c +18 -18
  186. data/vendor/libgit2/src/ignore.c +35 -34
  187. data/vendor/libgit2/src/ignore.h +2 -2
  188. data/vendor/libgit2/src/index.c +79 -80
  189. data/vendor/libgit2/src/index.h +6 -3
  190. data/vendor/libgit2/src/indexer.c +75 -57
  191. data/vendor/libgit2/src/iterator.c +64 -56
  192. data/vendor/libgit2/src/iterator.h +5 -5
  193. data/vendor/libgit2/src/khash.h +1 -1
  194. data/vendor/libgit2/src/libgit2.c +22 -19
  195. data/vendor/libgit2/src/mailmap.c +38 -36
  196. data/vendor/libgit2/src/merge.c +27 -27
  197. data/vendor/libgit2/src/merge.h +1 -14
  198. data/vendor/libgit2/src/merge_driver.c +2 -2
  199. data/vendor/libgit2/src/merge_file.c +13 -3
  200. data/vendor/libgit2/src/message.c +21 -10
  201. data/vendor/libgit2/src/midx.c +83 -66
  202. data/vendor/libgit2/src/midx.h +3 -3
  203. data/vendor/libgit2/src/mwindow.c +1 -1
  204. data/vendor/libgit2/src/net.c +278 -68
  205. data/vendor/libgit2/src/net.h +10 -3
  206. data/vendor/libgit2/src/netops.c +1 -1
  207. data/vendor/libgit2/src/netops.h +1 -1
  208. data/vendor/libgit2/src/notes.c +20 -29
  209. data/vendor/libgit2/src/object.c +49 -9
  210. data/vendor/libgit2/src/object.h +1 -1
  211. data/vendor/libgit2/src/odb.c +35 -32
  212. data/vendor/libgit2/src/odb.h +1 -1
  213. data/vendor/libgit2/src/odb_loose.c +68 -68
  214. data/vendor/libgit2/src/odb_mempack.c +18 -5
  215. data/vendor/libgit2/src/odb_pack.c +43 -43
  216. data/vendor/libgit2/src/oid.c +11 -4
  217. data/vendor/libgit2/src/oid.h +15 -0
  218. data/vendor/libgit2/src/pack-objects.c +41 -26
  219. data/vendor/libgit2/src/pack-objects.h +11 -6
  220. data/vendor/libgit2/src/pack.c +10 -10
  221. data/vendor/libgit2/src/patch.c +3 -3
  222. data/vendor/libgit2/src/patch.h +1 -0
  223. data/vendor/libgit2/src/patch_generate.c +27 -11
  224. data/vendor/libgit2/src/patch_generate.h +5 -5
  225. data/vendor/libgit2/src/patch_parse.c +24 -24
  226. data/vendor/libgit2/src/path.c +76 -1951
  227. data/vendor/libgit2/src/path.h +34 -741
  228. data/vendor/libgit2/src/pathspec.c +6 -6
  229. data/vendor/libgit2/src/pathspec.h +2 -2
  230. data/vendor/libgit2/src/posix.c +3 -3
  231. data/vendor/libgit2/src/posix.h +1 -0
  232. data/vendor/libgit2/src/pqueue.h +1 -1
  233. data/vendor/libgit2/src/proxy.c +4 -1
  234. data/vendor/libgit2/src/proxy.h +1 -1
  235. data/vendor/libgit2/src/push.c +30 -35
  236. data/vendor/libgit2/src/push.h +4 -16
  237. data/vendor/libgit2/src/rand.c +226 -0
  238. data/vendor/libgit2/src/rand.h +37 -0
  239. data/vendor/libgit2/src/reader.c +8 -8
  240. data/vendor/libgit2/src/reader.h +2 -2
  241. data/vendor/libgit2/src/rebase.c +89 -88
  242. data/vendor/libgit2/src/refdb_fs.c +447 -173
  243. data/vendor/libgit2/src/refs.c +32 -32
  244. data/vendor/libgit2/src/refs.h +2 -2
  245. data/vendor/libgit2/src/refspec.c +32 -37
  246. data/vendor/libgit2/src/refspec.h +5 -2
  247. data/vendor/libgit2/src/regexp.c +1 -1
  248. data/vendor/libgit2/src/remote.c +713 -419
  249. data/vendor/libgit2/src/remote.h +15 -10
  250. data/vendor/libgit2/src/repository.c +350 -467
  251. data/vendor/libgit2/src/repository.h +11 -10
  252. data/vendor/libgit2/src/reset.c +8 -5
  253. data/vendor/libgit2/src/revert.c +10 -10
  254. data/vendor/libgit2/src/revparse.c +48 -35
  255. data/vendor/libgit2/src/revwalk.c +7 -7
  256. data/vendor/libgit2/src/signature.c +12 -6
  257. data/vendor/libgit2/src/signature.h +1 -1
  258. data/vendor/libgit2/src/sortedcache.c +1 -1
  259. data/vendor/libgit2/src/sortedcache.h +1 -1
  260. data/vendor/libgit2/src/stash.c +36 -37
  261. data/vendor/libgit2/src/status.c +4 -1
  262. data/vendor/libgit2/src/{buffer.c → str.c} +157 -151
  263. data/vendor/libgit2/src/str.h +357 -0
  264. data/vendor/libgit2/src/streams/mbedtls.c +8 -6
  265. data/vendor/libgit2/src/streams/openssl_dynamic.h +3 -3
  266. data/vendor/libgit2/src/submodule.c +171 -159
  267. data/vendor/libgit2/src/submodule.h +1 -1
  268. data/vendor/libgit2/src/sysdir.c +68 -52
  269. data/vendor/libgit2/src/sysdir.h +15 -10
  270. data/vendor/libgit2/src/tag.c +29 -27
  271. data/vendor/libgit2/src/thread.h +3 -3
  272. data/vendor/libgit2/src/threadstate.c +3 -3
  273. data/vendor/libgit2/src/threadstate.h +1 -1
  274. data/vendor/libgit2/src/trace.c +1 -14
  275. data/vendor/libgit2/src/trace.h +5 -22
  276. data/vendor/libgit2/src/trailer.c +1 -1
  277. data/vendor/libgit2/src/transaction.c +1 -1
  278. data/vendor/libgit2/src/transport.c +10 -10
  279. data/vendor/libgit2/src/transports/auth.c +7 -9
  280. data/vendor/libgit2/src/transports/auth.h +2 -3
  281. data/vendor/libgit2/src/transports/auth_negotiate.c +12 -13
  282. data/vendor/libgit2/src/transports/auth_ntlm.c +10 -10
  283. data/vendor/libgit2/src/transports/auth_ntlm.h +0 -1
  284. data/vendor/libgit2/src/transports/git.c +9 -11
  285. data/vendor/libgit2/src/transports/http.c +37 -17
  286. data/vendor/libgit2/src/transports/http.h +2 -3
  287. data/vendor/libgit2/src/transports/httpclient.c +65 -65
  288. data/vendor/libgit2/src/transports/local.c +124 -116
  289. data/vendor/libgit2/src/transports/smart.c +51 -139
  290. data/vendor/libgit2/src/transports/smart.h +25 -31
  291. data/vendor/libgit2/src/transports/smart_pkt.c +33 -33
  292. data/vendor/libgit2/src/transports/smart_protocol.c +57 -39
  293. data/vendor/libgit2/src/transports/ssh.c +47 -112
  294. data/vendor/libgit2/src/transports/winhttp.c +50 -56
  295. data/vendor/libgit2/src/tree-cache.c +5 -5
  296. data/vendor/libgit2/src/tree-cache.h +2 -2
  297. data/vendor/libgit2/src/tree.c +59 -48
  298. data/vendor/libgit2/src/tree.h +1 -1
  299. data/vendor/libgit2/src/unix/map.c +0 -2
  300. data/vendor/libgit2/src/unix/posix.h +1 -4
  301. data/vendor/libgit2/src/unix/realpath.c +0 -2
  302. data/vendor/libgit2/src/util.c +14 -14
  303. data/vendor/libgit2/src/util.h +2 -28
  304. data/vendor/libgit2/src/vector.h +1 -1
  305. data/vendor/libgit2/src/win32/findfile.c +172 -116
  306. data/vendor/libgit2/src/win32/findfile.h +7 -4
  307. data/vendor/libgit2/src/win32/path_w32.c +140 -9
  308. data/vendor/libgit2/src/win32/path_w32.h +2 -0
  309. data/vendor/libgit2/src/win32/posix.h +0 -1
  310. data/vendor/libgit2/src/win32/posix_w32.c +11 -27
  311. data/vendor/libgit2/src/win32/w32_buffer.c +2 -3
  312. data/vendor/libgit2/src/win32/w32_buffer.h +2 -3
  313. data/vendor/libgit2/src/win32/w32_leakcheck.c +1 -1
  314. data/vendor/libgit2/src/worktree.c +116 -94
  315. data/vendor/libgit2/src/worktree.h +1 -1
  316. data/vendor/libgit2/src/xdiff/git-xdiff.h +53 -0
  317. data/vendor/libgit2/src/xdiff/xdiff.h +15 -15
  318. data/vendor/libgit2/src/xdiff/xdiffi.c +134 -108
  319. data/vendor/libgit2/src/xdiff/xemit.c +23 -7
  320. data/vendor/libgit2/src/xdiff/xhistogram.c +87 -78
  321. data/vendor/libgit2/src/xdiff/xinclude.h +1 -12
  322. data/vendor/libgit2/src/xdiff/xmerge.c +104 -117
  323. data/vendor/libgit2/src/xdiff/xpatience.c +6 -17
  324. data/vendor/libgit2/src/xdiff/xprepare.c +15 -20
  325. data/vendor/libgit2/src/xdiff/xutils.c +18 -7
  326. data/vendor/libgit2/src/zstream.c +5 -5
  327. data/vendor/libgit2/src/zstream.h +4 -4
  328. metadata +25 -10
  329. data/vendor/libgit2/src/buffer.h +0 -374
@@ -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"))
@@ -99,7 +102,7 @@ static int ensure_remote_name_is_valid(const char *name)
99
102
  static int write_add_refspec(git_repository *repo, const char *name, const char *refspec, bool fetch)
100
103
  {
101
104
  git_config *cfg;
102
- git_buf var = GIT_BUF_INIT;
105
+ git_str var = GIT_STR_INIT;
103
106
  git_refspec spec;
104
107
  const char *fmt;
105
108
  int error;
@@ -117,7 +120,7 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
117
120
 
118
121
  git_refspec__dispose(&spec);
119
122
 
120
- if ((error = git_buf_printf(&var, fmt, name)) < 0)
123
+ if ((error = git_str_printf(&var, fmt, name)) < 0)
121
124
  return error;
122
125
 
123
126
  /*
@@ -130,11 +133,11 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
130
133
  }
131
134
 
132
135
  cleanup:
133
- git_buf_dispose(&var);
136
+ git_str_dispose(&var);
134
137
  return 0;
135
138
  }
136
139
 
137
- static int canonicalize_url(git_buf *out, const char *in)
140
+ static int canonicalize_url(git_str *out, const char *in)
138
141
  {
139
142
  if (in == NULL || strlen(in) == 0) {
140
143
  git_error_set(GIT_ERROR_INVALID, "cannot set empty URL");
@@ -149,18 +152,18 @@ static int canonicalize_url(git_buf *out, const char *in)
149
152
  (git__isalpha(in[2]) || git__isdigit(in[2]))) {
150
153
  const char *c;
151
154
  for (c = in; *c; c++)
152
- git_buf_putc(out, *c == '\\' ? '/' : *c);
155
+ git_str_putc(out, *c == '\\' ? '/' : *c);
153
156
 
154
- return git_buf_oom(out) ? -1 : 0;
157
+ return git_str_oom(out) ? -1 : 0;
155
158
  }
156
159
  #endif
157
160
 
158
- return git_buf_puts(out, in);
161
+ return git_str_puts(out, in);
159
162
  }
160
163
 
161
- 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)
162
165
  {
163
- 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)
164
167
  return -1;
165
168
 
166
169
  return 0;
@@ -204,9 +207,9 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
204
207
  {
205
208
  git_remote *remote = NULL;
206
209
  git_config *config_ro = NULL, *config_rw;
207
- git_buf canonical_url = GIT_BUF_INIT;
208
- git_buf var = GIT_BUF_INIT;
209
- 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;
210
213
  const git_remote_create_options dummy_opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
211
214
  int error = -1;
212
215
 
@@ -243,18 +246,20 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
243
246
  goto on_error;
244
247
 
245
248
  if (opts->repository && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
246
- 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;
247
252
  } else {
248
253
  remote->url = git__strdup(canonical_url.ptr);
254
+ GIT_ERROR_CHECK_ALLOC(remote->url);
249
255
  }
250
- GIT_ERROR_CHECK_ALLOC(remote->url);
251
256
 
252
257
  if (opts->name != NULL) {
253
258
  remote->name = git__strdup(opts->name);
254
259
  GIT_ERROR_CHECK_ALLOC(remote->name);
255
260
 
256
261
  if (opts->repository &&
257
- ((error = git_buf_printf(&var, CONFIG_URL_FMT, opts->name)) < 0 ||
262
+ ((error = git_str_printf(&var, CONFIG_URL_FMT, opts->name)) < 0 ||
258
263
  (error = git_repository_config__weakptr(&config_rw, opts->repository)) < 0 ||
259
264
  (error = git_config_set_string(config_rw, var.ptr, canonical_url.ptr)) < 0))
260
265
  goto on_error;
@@ -269,7 +274,7 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
269
274
  if ((error = default_fetchspec_for_name(&specbuf, opts->name)) < 0)
270
275
  goto on_error;
271
276
 
272
- fetch = git_buf_cstr(&specbuf);
277
+ fetch = git_str_cstr(&specbuf);
273
278
  }
274
279
 
275
280
  if ((error = add_refspec(remote, fetch, true)) < 0)
@@ -293,7 +298,7 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
293
298
  remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
294
299
 
295
300
 
296
- git_buf_dispose(&var);
301
+ git_str_dispose(&var);
297
302
 
298
303
  *out = remote;
299
304
  error = 0;
@@ -303,15 +308,15 @@ on_error:
303
308
  git_remote_free(remote);
304
309
 
305
310
  git_config_free(config_ro);
306
- git_buf_dispose(&specbuf);
307
- git_buf_dispose(&canonical_url);
308
- git_buf_dispose(&var);
311
+ git_str_dispose(&specbuf);
312
+ git_str_dispose(&canonical_url);
313
+ git_str_dispose(&var);
309
314
  return error;
310
315
  }
311
316
 
312
317
  int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
313
318
  {
314
- git_buf buf = GIT_BUF_INIT;
319
+ git_str buf = GIT_STR_INIT;
315
320
  int error;
316
321
  git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
317
322
 
@@ -322,14 +327,14 @@ int git_remote_create(git_remote **out, git_repository *repo, const char *name,
322
327
  if (canonicalize_url(&buf, url) < 0)
323
328
  return GIT_ERROR;
324
329
 
325
- git_buf_clear(&buf);
330
+ git_str_clear(&buf);
326
331
 
327
332
  opts.repository = repo;
328
333
  opts.name = name;
329
334
 
330
335
  error = git_remote_create_with_opts(out, url, &opts);
331
336
 
332
- git_buf_dispose(&buf);
337
+ git_str_dispose(&buf);
333
338
 
334
339
  return error;
335
340
  }
@@ -425,13 +430,13 @@ static int refspec_cb(const git_config_entry *entry, void *payload)
425
430
  }
426
431
 
427
432
  static int get_optional_config(
428
- bool *found, git_config *config, git_buf *buf,
433
+ bool *found, git_config *config, git_str *buf,
429
434
  git_config_foreach_cb cb, void *payload)
430
435
  {
431
436
  int error = 0;
432
- const char *key = git_buf_cstr(buf);
437
+ const char *key = git_str_cstr(buf);
433
438
 
434
- if (git_buf_oom(buf))
439
+ if (git_str_oom(buf))
435
440
  return -1;
436
441
 
437
442
  if (cb != NULL)
@@ -453,7 +458,7 @@ static int get_optional_config(
453
458
  int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
454
459
  {
455
460
  git_remote *remote = NULL;
456
- git_buf buf = GIT_BUF_INIT;
461
+ git_str buf = GIT_STR_INIT;
457
462
  const char *val;
458
463
  int error = 0;
459
464
  git_config *config;
@@ -484,7 +489,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
484
489
  goto cleanup;
485
490
  }
486
491
 
487
- if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0)
492
+ if ((error = git_str_printf(&buf, "remote.%s.url", name)) < 0)
488
493
  goto cleanup;
489
494
 
490
495
  if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
@@ -496,13 +501,14 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
496
501
  remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
497
502
 
498
503
  if (found && strlen(val) > 0) {
499
- remote->url = apply_insteadof(config, val, GIT_DIRECTION_FETCH);
500
- 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;
501
507
  }
502
508
 
503
509
  val = NULL;
504
- git_buf_clear(&buf);
505
- git_buf_printf(&buf, "remote.%s.pushurl", name);
510
+ git_str_clear(&buf);
511
+ git_str_printf(&buf, "remote.%s.pushurl", name);
506
512
 
507
513
  if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
508
514
  goto cleanup;
@@ -516,22 +522,25 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
516
522
  }
517
523
 
518
524
  if (found && strlen(val) > 0) {
519
- remote->pushurl = apply_insteadof(config, val, GIT_DIRECTION_PUSH);
520
- 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;
521
530
  }
522
531
 
523
532
  data.remote = remote;
524
533
  data.fetch = true;
525
534
 
526
- git_buf_clear(&buf);
527
- git_buf_printf(&buf, "remote.%s.fetch", name);
535
+ git_str_clear(&buf);
536
+ git_str_printf(&buf, "remote.%s.fetch", name);
528
537
 
529
538
  if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
530
539
  goto cleanup;
531
540
 
532
541
  data.fetch = false;
533
- git_buf_clear(&buf);
534
- git_buf_printf(&buf, "remote.%s.push", name);
542
+ git_str_clear(&buf);
543
+ git_str_printf(&buf, "remote.%s.push", name);
535
544
 
536
545
  if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
537
546
  goto cleanup;
@@ -550,7 +559,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
550
559
 
551
560
  cleanup:
552
561
  git_config_free(config);
553
- git_buf_dispose(&buf);
562
+ git_str_dispose(&buf);
554
563
 
555
564
  if (error < 0)
556
565
  git_remote_free(remote);
@@ -560,12 +569,12 @@ cleanup:
560
569
 
561
570
  static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name)
562
571
  {
563
- git_buf buf = GIT_BUF_INIT;
572
+ git_str buf = GIT_STR_INIT;
564
573
  int error = 0;
565
574
 
566
- git_buf_printf(&buf, "remote.%s.prune", name);
575
+ git_str_printf(&buf, "remote.%s.prune", name);
567
576
 
568
- 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) {
569
578
  if (error == GIT_ENOTFOUND) {
570
579
  git_error_clear();
571
580
 
@@ -578,7 +587,7 @@ static int lookup_remote_prune_config(git_remote *remote, git_config *config, co
578
587
  }
579
588
  }
580
589
 
581
- git_buf_dispose(&buf);
590
+ git_str_dispose(&buf);
582
591
  return error;
583
592
  }
584
593
 
@@ -619,7 +628,7 @@ int git_remote_set_instance_url(git_remote *remote, const char *url)
619
628
  static int set_url(git_repository *repo, const char *remote, const char *pattern, const char *url)
620
629
  {
621
630
  git_config *cfg;
622
- git_buf buf = GIT_BUF_INIT, canonical_url = GIT_BUF_INIT;
631
+ git_str buf = GIT_STR_INIT, canonical_url = GIT_STR_INIT;
623
632
  int error;
624
633
 
625
634
  GIT_ASSERT_ARG(repo);
@@ -631,7 +640,7 @@ static int set_url(git_repository *repo, const char *remote, const char *pattern
631
640
  if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
632
641
  return error;
633
642
 
634
- if ((error = git_buf_printf(&buf, pattern, remote)) < 0)
643
+ if ((error = git_str_printf(&buf, pattern, remote)) < 0)
635
644
  return error;
636
645
 
637
646
  if (url) {
@@ -644,8 +653,8 @@ static int set_url(git_repository *repo, const char *remote, const char *pattern
644
653
  }
645
654
 
646
655
  cleanup:
647
- git_buf_dispose(&canonical_url);
648
- git_buf_dispose(&buf);
656
+ git_str_dispose(&canonical_url);
657
+ git_str_dispose(&buf);
649
658
 
650
659
  return error;
651
660
  }
@@ -683,7 +692,7 @@ int git_remote_set_pushurl(git_repository *repo, const char *remote, const char
683
692
  }
684
693
 
685
694
  static int resolve_url(
686
- git_buf *resolved_url,
695
+ git_str *resolved_url,
687
696
  const char *url,
688
697
  int direction,
689
698
  const git_remote_callbacks *callbacks)
@@ -692,27 +701,28 @@ static int resolve_url(
692
701
  GIT_UNUSED(direction);
693
702
  GIT_UNUSED(callbacks);
694
703
  #else
695
- int status, error;
704
+ git_buf buf = GIT_BUF_INIT;
705
+ int error;
696
706
 
697
707
  if (callbacks && callbacks->resolve_url) {
698
- git_buf_clear(resolved_url);
699
- status = callbacks->resolve_url(resolved_url, url, direction, callbacks->payload);
700
- if (status != GIT_PASSTHROUGH) {
701
- git_error_set_after_callback_function(status, "git_resolve_url_cb");
708
+ error = callbacks->resolve_url(&buf, url, direction, callbacks->payload);
702
709
 
703
- if ((error = git_buf_sanitize(resolved_url)) < 0)
704
- return error;
710
+ if (error != GIT_PASSTHROUGH) {
711
+ git_error_set_after_callback_function(error, "git_resolve_url_cb");
705
712
 
706
- return status;
713
+ git_str_set(resolved_url, buf.ptr, buf.size);
714
+ git_buf_dispose(&buf);
715
+
716
+ return error;
707
717
  }
708
718
  }
709
719
  #endif
710
720
 
711
- return git_buf_sets(resolved_url, url);
721
+ return git_str_sets(resolved_url, url);
712
722
  }
713
723
 
714
724
  int git_remote__urlfordirection(
715
- git_buf *url_out,
725
+ git_str *url_out,
716
726
  struct git_remote *remote,
717
727
  int direction,
718
728
  const git_remote_callbacks *callbacks)
@@ -747,54 +757,200 @@ int git_remote__urlfordirection(
747
757
  return resolve_url(url_out, url, direction, callbacks);
748
758
  }
749
759
 
750
- 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)
763
+ {
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)
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;
803
+
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;
815
+ }
816
+
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)
751
827
  {
752
- if (!t->set_callbacks || !cbs)
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)
753
844
  return 0;
754
845
 
755
- return t->set_callbacks(t, cbs->sideband_progress, NULL,
756
- cbs->certificate_check, cbs->payload);
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;
757
859
  }
758
860
 
759
- static int set_transport_custom_headers(git_transport *t, const git_strarray *custom_headers)
861
+ static int lookup_redirect_config(
862
+ git_remote_redirect_t *out,
863
+ git_repository *repo)
760
864
  {
761
- if (!t->set_custom_headers)
865
+ git_config *config;
866
+ const char *value;
867
+ int bool_value, error = 0;
868
+
869
+ if (!repo) {
870
+ *out = GIT_REMOTE_REDIRECT_INITIAL;
762
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
+ }
763
923
 
764
- return t->set_custom_headers(t, custom_headers);
924
+ return 0;
765
925
  }
766
926
 
767
- int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn)
927
+ int git_remote_connect_ext(
928
+ git_remote *remote,
929
+ git_direction direction,
930
+ const git_remote_connect_options *given_opts)
768
931
  {
932
+ git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
933
+ git_str url = GIT_STR_INIT;
769
934
  git_transport *t;
770
- git_buf url = GIT_BUF_INIT;
771
- int flags = GIT_TRANSPORTFLAGS_NONE;
772
935
  int error;
773
- void *payload = NULL;
774
- git_credential_acquire_cb credentials = NULL;
775
- git_transport_cb transport = NULL;
776
936
 
777
937
  GIT_ASSERT_ARG(remote);
778
938
 
779
- if (callbacks) {
780
- GIT_ERROR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
781
- credentials = callbacks->credentials;
782
- transport = callbacks->transport;
783
- payload = callbacks->payload;
784
- }
939
+ if (given_opts)
940
+ memcpy(&opts, given_opts, sizeof(git_remote_connect_options));
785
941
 
786
- if (conn->proxy)
787
- 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");
788
944
 
789
945
  t = remote->transport;
790
946
 
791
- if ((error = git_remote__urlfordirection(&url, remote, direction, callbacks)) < 0)
947
+ if ((error = git_remote__urlfordirection(&url, remote, direction, &opts.callbacks)) < 0)
792
948
  goto on_error;
793
949
 
794
950
  /* If we don't have a transport object yet, and the caller specified a
795
951
  * custom transport factory, use that */
796
- if (!t && transport &&
797
- (error = transport(&t, remote, payload)) < 0)
952
+ if (!t && opts.callbacks.transport &&
953
+ (error = opts.callbacks.transport(&t, remote, opts.callbacks.payload)) < 0)
798
954
  goto on_error;
799
955
 
800
956
  /* If we still don't have a transport, then use the global
@@ -802,16 +958,12 @@ int git_remote__connect(git_remote *remote, git_direction direction, const git_r
802
958
  if (!t && (error = git_transport_new(&t, remote, url.ptr)) < 0)
803
959
  goto on_error;
804
960
 
805
- if ((error = set_transport_custom_headers(t, conn->custom_headers)) != 0)
806
- goto on_error;
807
-
808
- if ((error = remote_transport_set_callbacks(t, callbacks)) < 0 ||
809
- (error = t->connect(t, url.ptr, credentials, payload, conn->proxy, direction, flags)) != 0)
961
+ if ((error = t->connect(t, url.ptr, direction, &opts)) != 0)
810
962
  goto on_error;
811
963
 
812
964
  remote->transport = t;
813
965
 
814
- git_buf_dispose(&url);
966
+ git_str_dispose(&url);
815
967
 
816
968
  return 0;
817
969
 
@@ -819,7 +971,7 @@ on_error:
819
971
  if (t)
820
972
  t->free(t);
821
973
 
822
- git_buf_dispose(&url);
974
+ git_str_dispose(&url);
823
975
 
824
976
  if (t == remote->transport)
825
977
  remote->transport = NULL;
@@ -827,14 +979,25 @@ on_error:
827
979
  return error;
828
980
  }
829
981
 
830
- 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)
831
988
  {
832
- 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));
833
993
 
834
- conn.proxy = proxy;
835
- conn.custom_headers = custom_headers;
994
+ if (proxy)
995
+ memcpy(&opts.proxy_opts, proxy, sizeof(git_proxy_options));
836
996
 
837
- return git_remote__connect(remote, direction, callbacks, &conn);
997
+ if (custom_headers)
998
+ memcpy(&opts.custom_headers, custom_headers, sizeof(git_strarray));
999
+
1000
+ return git_remote_connect_ext(remote, direction, &opts);
838
1001
  }
839
1002
 
840
1003
  int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote)
@@ -849,6 +1012,20 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote
849
1012
  return remote->transport->ls(out, size, remote->transport);
850
1013
  }
851
1014
 
1015
+ int git_remote_capabilities(unsigned int *out, git_remote *remote)
1016
+ {
1017
+ GIT_ASSERT_ARG(remote);
1018
+
1019
+ *out = 0;
1020
+
1021
+ if (!remote->transport) {
1022
+ git_error_set(GIT_ERROR_NET, "this remote has never connected");
1023
+ return -1;
1024
+ }
1025
+
1026
+ return remote->transport->capabilities(out, remote->transport);
1027
+ }
1028
+
852
1029
  static int lookup_config(char **out, git_config *cfg, const char *name)
853
1030
  {
854
1031
  git_config_entry *ce = NULL;
@@ -885,7 +1062,7 @@ static void url_config_trim(git_net_url *url)
885
1062
  static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
886
1063
  {
887
1064
  git_config *cfg = NULL;
888
- git_buf buf = GIT_BUF_INIT;
1065
+ git_str buf = GIT_STR_INIT;
889
1066
  git_net_url lookup_url = GIT_NET_URL_INIT;
890
1067
  int error;
891
1068
 
@@ -902,19 +1079,19 @@ static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
902
1079
 
903
1080
  /* remote.<name>.proxy config setting */
904
1081
  if (remote->name && remote->name[0]) {
905
- git_buf_clear(&buf);
1082
+ git_str_clear(&buf);
906
1083
 
907
- if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0 ||
1084
+ if ((error = git_str_printf(&buf, "remote.%s.proxy", remote->name)) < 0 ||
908
1085
  (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
909
1086
  goto done;
910
1087
  }
911
1088
 
912
1089
  while (true) {
913
- git_buf_clear(&buf);
1090
+ git_str_clear(&buf);
914
1091
 
915
- if ((error = git_buf_puts(&buf, "http.")) < 0 ||
1092
+ if ((error = git_str_puts(&buf, "http.")) < 0 ||
916
1093
  (error = git_net_url_fmt(&buf, &lookup_url)) < 0 ||
917
- (error = git_buf_puts(&buf, ".proxy")) < 0 ||
1094
+ (error = git_str_puts(&buf, ".proxy")) < 0 ||
918
1095
  (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
919
1096
  goto done;
920
1097
 
@@ -924,20 +1101,20 @@ static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
924
1101
  url_config_trim(&lookup_url);
925
1102
  }
926
1103
 
927
- git_buf_clear(&buf);
1104
+ git_str_clear(&buf);
928
1105
 
929
1106
  error = lookup_config(out, cfg, "http.proxy");
930
1107
 
931
1108
  done:
932
1109
  git_config_free(cfg);
933
- git_buf_dispose(&buf);
1110
+ git_str_dispose(&buf);
934
1111
  git_net_url_dispose(&lookup_url);
935
1112
  return error;
936
1113
  }
937
1114
 
938
1115
  static int http_proxy_env(char **out, git_remote *remote, git_net_url *url)
939
1116
  {
940
- git_buf proxy_env = GIT_BUF_INIT, no_proxy_env = GIT_BUF_INIT;
1117
+ git_str proxy_env = GIT_STR_INIT, no_proxy_env = GIT_STR_INIT;
941
1118
  bool use_ssl = (strcmp(url->scheme, "https") == 0);
942
1119
  int error;
943
1120
 
@@ -963,13 +1140,13 @@ static int http_proxy_env(char **out, git_remote *remote, git_net_url *url)
963
1140
  goto done;
964
1141
 
965
1142
  if (!git_net_url_matches_pattern_list(url, no_proxy_env.ptr))
966
- *out = git_buf_detach(&proxy_env);
1143
+ *out = git_str_detach(&proxy_env);
967
1144
  else
968
1145
  error = GIT_ENOTFOUND;
969
1146
 
970
1147
  done:
971
- git_buf_dispose(&proxy_env);
972
- git_buf_dispose(&no_proxy_env);
1148
+ git_str_dispose(&proxy_env);
1149
+ git_str_dispose(&no_proxy_env);
973
1150
  return error;
974
1151
  }
975
1152
 
@@ -1048,38 +1225,50 @@ static int ls_to_vector(git_vector *out, git_remote *remote)
1048
1225
  return 0;
1049
1226
  }
1050
1227
 
1051
- int git_remote_download(git_remote *remote, const git_strarray *refspecs, const git_fetch_options *opts)
1052
- {
1053
- int error = -1;
1054
- size_t i;
1055
- git_vector *to_active, specs = GIT_VECTOR_INIT, refs = GIT_VECTOR_INIT;
1056
- const git_remote_callbacks *cbs = NULL;
1057
- const git_strarray *custom_headers = NULL;
1058
- const git_proxy_options *proxy = NULL;
1059
-
1060
- GIT_ASSERT_ARG(remote);
1061
-
1062
- if (!remote->repo) {
1063
- git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
1064
- 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; \
1065
1234
  }
1066
1235
 
1067
- if (opts) {
1068
- GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
1069
- cbs = &opts->callbacks;
1070
- custom_headers = &opts->custom_headers;
1071
- GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
1072
- 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);
1073
1255
  }
1256
+ }
1074
1257
 
1075
- if (!git_remote_connected(remote) &&
1076
- (error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs, proxy, custom_headers)) < 0)
1077
- 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;
1078
1267
 
1079
1268
  if (ls_to_vector(&refs, remote) < 0)
1080
1269
  return -1;
1081
1270
 
1082
- if ((git_vector_init(&specs, 0, NULL)) < 0)
1271
+ if ((error = git_vector_init(&specs, 0, NULL)) < 0)
1083
1272
  goto on_error;
1084
1273
 
1085
1274
  remote->passed_refspecs = 0;
@@ -1107,7 +1296,7 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
1107
1296
  git_vector_free(&specs);
1108
1297
 
1109
1298
  if (error < 0)
1110
- return error;
1299
+ goto on_error;
1111
1300
 
1112
1301
  if (remote->push) {
1113
1302
  git_push_free(remote->push);
@@ -1115,9 +1304,9 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
1115
1304
  }
1116
1305
 
1117
1306
  if ((error = git_fetch_negotiate(remote, opts)) < 0)
1118
- return error;
1307
+ goto on_error;
1119
1308
 
1120
- return git_fetch_download_pack(remote, cbs);
1309
+ error = git_fetch_download_pack(remote);
1121
1310
 
1122
1311
  on_error:
1123
1312
  git_vector_free(&refs);
@@ -1126,55 +1315,83 @@ on_error:
1126
1315
  return error;
1127
1316
  }
1128
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
+
1129
1342
  int git_remote_fetch(
1130
- git_remote *remote,
1131
- const git_strarray *refspecs,
1132
- const git_fetch_options *opts,
1133
- const char *reflog_message)
1343
+ git_remote *remote,
1344
+ const git_strarray *refspecs,
1345
+ const git_fetch_options *opts,
1346
+ const char *reflog_message)
1134
1347
  {
1135
1348
  int error, update_fetchhead = 1;
1136
1349
  git_remote_autotag_option_t tagopt = remote->download_tags;
1137
1350
  bool prune = false;
1138
- git_buf reflog_msg_buf = GIT_BUF_INIT;
1139
- const git_remote_callbacks *cbs = NULL;
1140
- 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;
1141
1366
 
1142
1367
  if (opts) {
1143
- GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
1144
- cbs = &opts->callbacks;
1145
- conn.custom_headers = &opts->custom_headers;
1146
1368
  update_fetchhead = opts->update_fetchhead;
1147
1369
  tagopt = opts->download_tags;
1148
- GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
1149
- conn.proxy = &opts->proxy_opts;
1150
1370
  }
1151
1371
 
1152
1372
  /* Connect and download everything */
1153
- if ((error = git_remote__connect(remote, GIT_DIRECTION_FETCH, cbs, &conn)) != 0)
1154
- return error;
1155
-
1156
- error = git_remote_download(remote, refspecs, opts);
1373
+ error = git_remote__download(remote, refspecs, opts);
1157
1374
 
1158
1375
  /* We don't need to be connected anymore */
1159
1376
  git_remote_disconnect(remote);
1160
1377
 
1161
1378
  /* If the download failed, return the error */
1162
1379
  if (error != 0)
1163
- return error;
1380
+ goto done;
1164
1381
 
1165
1382
  /* Default reflog message */
1166
1383
  if (reflog_message)
1167
- git_buf_sets(&reflog_msg_buf, reflog_message);
1384
+ git_str_sets(&reflog_msg_buf, reflog_message);
1168
1385
  else {
1169
- git_buf_printf(&reflog_msg_buf, "fetch %s",
1386
+ git_str_printf(&reflog_msg_buf, "fetch %s",
1170
1387
  remote->name ? remote->name : remote->url);
1171
1388
  }
1172
1389
 
1173
1390
  /* Create "remote/foo" branches for all remote branches */
1174
- error = git_remote_update_tips(remote, cbs, update_fetchhead, tagopt, git_buf_cstr(&reflog_msg_buf));
1175
- 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);
1176
1393
  if (error < 0)
1177
- return error;
1394
+ goto done;
1178
1395
 
1179
1396
  if (opts && opts->prune == GIT_FETCH_PRUNE)
1180
1397
  prune = true;
@@ -1186,8 +1403,10 @@ int git_remote_fetch(
1186
1403
  prune = remote->prune_refs;
1187
1404
 
1188
1405
  if (prune)
1189
- error = git_remote_prune(remote, cbs);
1406
+ error = git_remote_prune(remote, &connect_opts.callbacks);
1190
1407
 
1408
+ done:
1409
+ git_remote_connect_options_dispose(&connect_opts);
1191
1410
  return error;
1192
1411
  }
1193
1412
 
@@ -1211,22 +1430,22 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda
1211
1430
  return 0;
1212
1431
  }
1213
1432
 
1214
- 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)
1215
1434
  {
1216
1435
  int error = 0;
1217
1436
  git_repository *repo;
1218
- git_buf upstream_remote = GIT_BUF_INIT;
1219
- git_buf upstream_name = GIT_BUF_INIT;
1437
+ git_str upstream_remote = GIT_STR_INIT;
1438
+ git_str upstream_name = GIT_STR_INIT;
1220
1439
 
1221
1440
  repo = git_remote_owner(remote);
1222
1441
 
1223
1442
  if ((!git_reference__is_branch(ref_name)) ||
1224
1443
  !git_remote_name(remote) ||
1225
- (error = git_branch_upstream_remote(&upstream_remote, repo, ref_name) < 0) ||
1226
- git__strcmp(git_remote_name(remote), git_buf_cstr(&upstream_remote)) ||
1227
- (error = git_branch_upstream_name(&upstream_name, repo, ref_name)) < 0 ||
1228
- !git_refspec_dst_matches(spec, git_buf_cstr(&upstream_name)) ||
1229
- (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) {
1230
1449
  /* Not an error if there is no upstream */
1231
1450
  if (error == GIT_ENOTFOUND) {
1232
1451
  git_error_clear();
@@ -1238,15 +1457,15 @@ static int ref_to_update(int *update, git_buf *remote_name, git_remote *remote,
1238
1457
  *update = 1;
1239
1458
  }
1240
1459
 
1241
- git_buf_dispose(&upstream_remote);
1242
- git_buf_dispose(&upstream_name);
1460
+ git_str_dispose(&upstream_remote);
1461
+ git_str_dispose(&upstream_name);
1243
1462
  return error;
1244
1463
  }
1245
1464
 
1246
1465
  static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_refspec *spec, git_vector *update_heads, git_reference *ref)
1247
1466
  {
1248
1467
  git_reference *resolved_ref = NULL;
1249
- git_buf remote_name = GIT_BUF_INIT;
1468
+ git_str remote_name = GIT_STR_INIT;
1250
1469
  git_config *config = NULL;
1251
1470
  const char *ref_name;
1252
1471
  int error = 0, update;
@@ -1281,10 +1500,10 @@ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_re
1281
1500
  goto cleanup;
1282
1501
 
1283
1502
  if (update)
1284
- 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));
1285
1504
 
1286
1505
  cleanup:
1287
- git_buf_dispose(&remote_name);
1506
+ git_str_dispose(&remote_name);
1288
1507
  git_reference_free(resolved_ref);
1289
1508
  git_config_free(config);
1290
1509
  return error;
@@ -1422,7 +1641,7 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
1422
1641
  */
1423
1642
  git_vector_foreach(&candidates, i, refname) {
1424
1643
  git_vector_foreach(&remote->active_refspecs, j, spec) {
1425
- git_buf buf = GIT_BUF_INIT;
1644
+ git_str buf = GIT_STR_INIT;
1426
1645
  size_t pos;
1427
1646
  char *src_name;
1428
1647
  git_remote_head key = {0};
@@ -1430,12 +1649,12 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
1430
1649
  if (!git_refspec_dst_matches(spec, refname))
1431
1650
  continue;
1432
1651
 
1433
- if ((error = git_refspec_rtransform(&buf, spec, refname)) < 0)
1652
+ if ((error = git_refspec__rtransform(&buf, spec, refname)) < 0)
1434
1653
  goto cleanup;
1435
1654
 
1436
- key.name = (char *) git_buf_cstr(&buf);
1655
+ key.name = (char *) git_str_cstr(&buf);
1437
1656
  error = git_vector_bsearch(&pos, &remote_refs, &key);
1438
- git_buf_dispose(&buf);
1657
+ git_str_dispose(&buf);
1439
1658
 
1440
1659
  if (error < 0 && error != GIT_ENOTFOUND)
1441
1660
  goto cleanup;
@@ -1497,141 +1716,207 @@ cleanup:
1497
1716
  return error;
1498
1717
  }
1499
1718
 
1500
- static int update_tips_for_spec(
1501
- git_remote *remote,
1502
- const git_remote_callbacks *callbacks,
1503
- int update_fetchhead,
1504
- git_remote_autotag_option_t tagopt,
1505
- git_refspec *spec,
1506
- git_vector *refs,
1507
- 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)
1508
1725
  {
1509
- int error = 0, autotag, valid;
1510
- unsigned int i = 0;
1511
- git_buf refname = GIT_BUF_INIT;
1512
- git_oid old;
1513
- git_odb *odb;
1514
- git_remote_head *head;
1515
1726
  git_reference *ref;
1516
- git_refspec tagspec;
1517
- git_vector update_heads;
1727
+ git_oid old_id;
1728
+ int error;
1518
1729
 
1519
- GIT_ASSERT_ARG(remote);
1730
+ error = git_reference_name_to_id(&old_id, remote->repo, ref_name);
1520
1731
 
1521
- if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
1522
- 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;
1523
1736
 
1524
- if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
1525
- 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);
1526
1742
 
1527
- /* Make a copy of the transport's refs */
1528
- if (git_vector_init(&update_heads, 16, NULL) < 0)
1529
- return -1;
1743
+ git_reference_free(ref);
1530
1744
 
1531
- for (; i < refs->length; ++i) {
1532
- head = git_vector_get(refs, i);
1533
- autotag = 0;
1534
- git_buf_clear(&refname);
1745
+ if (error < 0)
1746
+ return error;
1535
1747
 
1536
- /* Ignore malformed ref names (which also saves us from tag^{} */
1537
- if (git_reference_name_is_valid(&valid, head->name) < 0)
1538
- goto on_error;
1748
+ if (callbacks && callbacks->update_tips &&
1749
+ (error = callbacks->update_tips(ref_name, &old_id, id, callbacks->payload)) < 0)
1750
+ return error;
1539
1751
 
1540
- if (!valid)
1541
- continue;
1752
+ return 0;
1753
+ }
1542
1754
 
1543
- /* If we have a tag, see if the auto-follow rules say to update it */
1544
- if (git_refspec_src_matches(&tagspec, head->name)) {
1545
- 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;
1546
1772
 
1547
- if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
1548
- autotag = 1;
1773
+ if ((error = git_repository_odb__weakptr(&odb, remote->repo)) < 0)
1774
+ goto done;
1549
1775
 
1550
- git_buf_clear(&refname);
1551
- if (git_buf_puts(&refname, head->name) < 0)
1552
- goto on_error;
1553
- }
1554
- }
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;
1555
1779
 
1556
- /* If we didn't want to auto-follow the tag, check if the refspec matches */
1557
- if (!autotag && git_refspec_src_matches(spec, head->name)) {
1558
- if (spec->dst) {
1559
- if (git_refspec_transform(&refname, spec, head->name) < 0)
1560
- goto on_error;
1561
- } else {
1562
- /*
1563
- * no rhs mans store it in FETCH_HEAD, even if we don't
1564
- update anything else.
1565
- */
1566
- if ((error = git_vector_insert(&update_heads, head)) < 0)
1567
- goto on_error;
1780
+ if (!valid)
1781
+ goto done;
1568
1782
 
1569
- continue;
1570
- }
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;
1571
1791
  }
1792
+ }
1572
1793
 
1573
- /* If we still don't have a refname, we don't want it */
1574
- if (git_buf_len(&refname) == 0) {
1575
- 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;
1576
1806
  }
1807
+ }
1577
1808
 
1578
- /* In autotag mode, only create tags for objects already in db */
1579
- if (autotag && !git_odb_exists(odb, &head->oid))
1580
- 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;
1581
1812
 
1582
- if (!autotag && git_vector_insert(&update_heads, head) < 0)
1583
- 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;
1584
1816
 
1585
- error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1586
- if (error < 0 && error != GIT_ENOTFOUND)
1587
- goto on_error;
1817
+ if (!autotag && (error = git_vector_insert(update_heads, head)) < 0)
1818
+ goto done;
1588
1819
 
1589
- if (!(error || error == GIT_ENOTFOUND)
1590
- && !spec->force
1591
- && !git_graph_descendant_of(remote->repo, &head->oid, &old))
1592
- continue;
1820
+ error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1593
1821
 
1594
- if (error == GIT_ENOTFOUND) {
1595
- memset(&old, 0, GIT_OID_RAWSZ);
1822
+ if (error < 0 && error != GIT_ENOTFOUND)
1823
+ goto done;
1596
1824
 
1597
- if (autotag && git_vector_insert(&update_heads, head) < 0)
1598
- goto on_error;
1599
- }
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
+ }
1600
1831
 
1601
- if (!git_oid__cmp(&old, &head->oid))
1602
- continue;
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
+ }
1839
+
1840
+ if (!git_oid__cmp(&old, &head->oid))
1841
+ goto done;
1603
1842
 
1604
- /* In autotag mode, don't overwrite any locally-existing tags */
1605
- error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
1606
- log_message);
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);
1607
1846
 
1847
+ if (error < 0) {
1608
1848
  if (error == GIT_EEXISTS)
1609
- continue;
1849
+ error = 0;
1610
1850
 
1611
- 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)
1612
1891
  goto on_error;
1892
+ }
1613
1893
 
1614
- git_reference_free(ref);
1894
+ /* Handle specified oid sources */
1895
+ if (git_oid__is_hexstr(spec->src)) {
1896
+ git_oid id;
1615
1897
 
1616
- if (callbacks && callbacks->update_tips != NULL) {
1617
- if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
1618
- goto on_error;
1619
- }
1898
+ if ((error = git_oid_fromstr(&id, spec->src)) < 0 ||
1899
+ (error = update_ref(remote, spec->dst, &id, log_message, callbacks)) < 0)
1900
+ goto on_error;
1901
+
1902
+ git_oid_cpy(&oid_head.oid, &id);
1903
+ oid_head.name = spec->src;
1904
+
1905
+ if ((error = git_vector_insert(&update_heads, &oid_head)) < 0)
1906
+ goto on_error;
1620
1907
  }
1621
1908
 
1622
1909
  if (update_fetchhead &&
1623
1910
  (error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0)
1624
1911
  goto on_error;
1625
1912
 
1626
- git_vector_free(&update_heads);
1627
1913
  git_refspec__dispose(&tagspec);
1628
- git_buf_dispose(&refname);
1914
+ git_vector_free(&update_heads);
1629
1915
  return 0;
1630
1916
 
1631
1917
  on_error:
1632
- git_vector_free(&update_heads);
1633
1918
  git_refspec__dispose(&tagspec);
1634
- git_buf_dispose(&refname);
1919
+ git_vector_free(&update_heads);
1635
1920
  return -1;
1636
1921
 
1637
1922
  }
@@ -1697,20 +1982,22 @@ static int next_head(const git_remote *remote, git_vector *refs,
1697
1982
  return GIT_ITEROVER;
1698
1983
  }
1699
1984
 
1700
- static int opportunistic_updates(const git_remote *remote, const git_remote_callbacks *callbacks,
1701
- git_vector *refs, const char *msg)
1985
+ static int opportunistic_updates(
1986
+ const git_remote *remote,
1987
+ const git_remote_callbacks *callbacks,
1988
+ git_vector *refs,
1989
+ const char *msg)
1702
1990
  {
1703
1991
  size_t i, j, k;
1704
1992
  git_refspec *spec;
1705
1993
  git_remote_head *head;
1706
- git_reference *ref;
1707
- git_buf refname = GIT_BUF_INIT;
1994
+ git_str refname = GIT_STR_INIT;
1708
1995
  int error = 0;
1709
1996
 
1710
1997
  i = j = k = 0;
1711
1998
 
1999
+ /* Handle refspecs matching remote heads */
1712
2000
  while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
1713
- git_oid old = {{ 0 }};
1714
2001
  /*
1715
2002
  * If we got here, there is a refspec which was used
1716
2003
  * for fetching which matches the source of one of the
@@ -1719,50 +2006,32 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call
1719
2006
  * FETCH_HEAD
1720
2007
  */
1721
2008
 
1722
- git_buf_clear(&refname);
1723
- if ((error = git_refspec_transform(&refname, spec, head->name)) < 0)
2009
+ git_str_clear(&refname);
2010
+ if ((error = git_refspec__transform(&refname, spec, head->name)) < 0 ||
2011
+ (error = update_ref(remote, refname.ptr, &head->oid, msg, callbacks)) < 0)
1724
2012
  goto cleanup;
1725
-
1726
- error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1727
- if (error < 0 && error != GIT_ENOTFOUND)
1728
- goto cleanup;
1729
-
1730
- if (!git_oid_cmp(&old, &head->oid))
1731
- continue;
1732
-
1733
- /* If we did find a current reference, make sure we haven't lost a race */
1734
- if (error)
1735
- error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, true, msg);
1736
- else
1737
- error = git_reference_create_matching(&ref, remote->repo, refname.ptr, &head->oid, true, &old, msg);
1738
- git_reference_free(ref);
1739
- if (error < 0)
1740
- goto cleanup;
1741
-
1742
- if (callbacks && callbacks->update_tips != NULL) {
1743
- if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
1744
- goto cleanup;
1745
- }
1746
2013
  }
1747
2014
 
1748
- if (error == GIT_ITEROVER)
1749
- error = 0;
2015
+ if (error != GIT_ITEROVER)
2016
+ goto cleanup;
2017
+
2018
+ error = 0;
1750
2019
 
1751
2020
  cleanup:
1752
- git_buf_dispose(&refname);
2021
+ git_str_dispose(&refname);
1753
2022
  return error;
1754
2023
  }
1755
2024
 
1756
2025
  static int truncate_fetch_head(const char *gitdir)
1757
2026
  {
1758
- git_buf path = GIT_BUF_INIT;
2027
+ git_str path = GIT_STR_INIT;
1759
2028
  int error;
1760
2029
 
1761
- if ((error = git_buf_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0)
2030
+ if ((error = git_str_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0)
1762
2031
  return error;
1763
2032
 
1764
2033
  error = git_futils_truncate(path.ptr, GIT_REFS_FILE_MODE);
1765
- git_buf_dispose(&path);
2034
+ git_str_dispose(&path);
1766
2035
 
1767
2036
  return error;
1768
2037
  }
@@ -1813,7 +2082,7 @@ int git_remote_update_tips(
1813
2082
  goto out;
1814
2083
  }
1815
2084
 
1816
- /* Only try to do opportunistic updates if the refpec lists differ. */
2085
+ /* Only try to do opportunistic updates if the refspec lists differ. */
1817
2086
  if (remote->passed_refspecs)
1818
2087
  error = opportunistic_updates(remote, callbacks, &refs, reflog_message);
1819
2088
 
@@ -1854,6 +2123,17 @@ int git_remote_disconnect(git_remote *remote)
1854
2123
  return 0;
1855
2124
  }
1856
2125
 
2126
+ static void free_heads(git_vector *heads)
2127
+ {
2128
+ git_remote_head *head;
2129
+ size_t i;
2130
+
2131
+ git_vector_foreach(heads, i, head) {
2132
+ git__free(head->name);
2133
+ git__free(head);
2134
+ }
2135
+ }
2136
+
1857
2137
  void git_remote_free(git_remote *remote)
1858
2138
  {
1859
2139
  if (remote == NULL)
@@ -1877,6 +2157,9 @@ void git_remote_free(git_remote *remote)
1877
2157
  free_refspecs(&remote->passive_refspecs);
1878
2158
  git_vector_free(&remote->passive_refspecs);
1879
2159
 
2160
+ free_heads(&remote->local_heads);
2161
+ git_vector_free(&remote->local_heads);
2162
+
1880
2163
  git_push_free(remote->push);
1881
2164
  git__free(remote->url);
1882
2165
  git__free(remote->pushurl);
@@ -1943,7 +2226,7 @@ git_remote_autotag_option_t git_remote_autotag(const git_remote *remote)
1943
2226
 
1944
2227
  int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_autotag_option_t value)
1945
2228
  {
1946
- git_buf var = GIT_BUF_INIT;
2229
+ git_str var = GIT_STR_INIT;
1947
2230
  git_config *config;
1948
2231
  int error;
1949
2232
 
@@ -1955,7 +2238,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_
1955
2238
  if ((error = git_repository_config__weakptr(&config, repo)) < 0)
1956
2239
  return error;
1957
2240
 
1958
- if ((error = git_buf_printf(&var, CONFIG_TAGOPT_FMT, remote)))
2241
+ if ((error = git_str_printf(&var, CONFIG_TAGOPT_FMT, remote)))
1959
2242
  return error;
1960
2243
 
1961
2244
  switch (value) {
@@ -1975,7 +2258,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_
1975
2258
  error = -1;
1976
2259
  }
1977
2260
 
1978
- git_buf_dispose(&var);
2261
+ git_str_dispose(&var);
1979
2262
  return error;
1980
2263
  }
1981
2264
 
@@ -1989,25 +2272,25 @@ static int rename_remote_config_section(
1989
2272
  const char *old_name,
1990
2273
  const char *new_name)
1991
2274
  {
1992
- git_buf old_section_name = GIT_BUF_INIT,
1993
- new_section_name = GIT_BUF_INIT;
2275
+ git_str old_section_name = GIT_STR_INIT,
2276
+ new_section_name = GIT_STR_INIT;
1994
2277
  int error = -1;
1995
2278
 
1996
- if (git_buf_printf(&old_section_name, "remote.%s", old_name) < 0)
2279
+ if (git_str_printf(&old_section_name, "remote.%s", old_name) < 0)
1997
2280
  goto cleanup;
1998
2281
 
1999
2282
  if (new_name &&
2000
- (git_buf_printf(&new_section_name, "remote.%s", new_name) < 0))
2283
+ (git_str_printf(&new_section_name, "remote.%s", new_name) < 0))
2001
2284
  goto cleanup;
2002
2285
 
2003
2286
  error = git_config_rename_section(
2004
2287
  repo,
2005
- git_buf_cstr(&old_section_name),
2006
- new_name ? git_buf_cstr(&new_section_name) : NULL);
2288
+ git_str_cstr(&old_section_name),
2289
+ new_name ? git_str_cstr(&new_section_name) : NULL);
2007
2290
 
2008
2291
  cleanup:
2009
- git_buf_dispose(&old_section_name);
2010
- git_buf_dispose(&new_section_name);
2292
+ git_str_dispose(&old_section_name);
2293
+ git_str_dispose(&new_section_name);
2011
2294
 
2012
2295
  return error;
2013
2296
  }
@@ -2056,27 +2339,27 @@ static int rename_one_remote_reference(
2056
2339
  {
2057
2340
  int error;
2058
2341
  git_reference *ref = NULL, *dummy = NULL;
2059
- git_buf namespace = GIT_BUF_INIT, old_namespace = GIT_BUF_INIT;
2060
- git_buf new_name = GIT_BUF_INIT;
2061
- git_buf log_message = GIT_BUF_INIT;
2342
+ git_str namespace = GIT_STR_INIT, old_namespace = GIT_STR_INIT;
2343
+ git_str new_name = GIT_STR_INIT;
2344
+ git_str log_message = GIT_STR_INIT;
2062
2345
  size_t pfx_len;
2063
2346
  const char *target;
2064
2347
 
2065
- if ((error = git_buf_printf(&namespace, GIT_REFS_REMOTES_DIR "%s/", new_remote_name)) < 0)
2348
+ if ((error = git_str_printf(&namespace, GIT_REFS_REMOTES_DIR "%s/", new_remote_name)) < 0)
2066
2349
  return error;
2067
2350
 
2068
2351
  pfx_len = strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name) + 1;
2069
- git_buf_puts(&new_name, namespace.ptr);
2070
- if ((error = git_buf_puts(&new_name, git_reference_name(reference_in) + pfx_len)) < 0)
2352
+ git_str_puts(&new_name, namespace.ptr);
2353
+ if ((error = git_str_puts(&new_name, git_reference_name(reference_in) + pfx_len)) < 0)
2071
2354
  goto cleanup;
2072
2355
 
2073
- if ((error = git_buf_printf(&log_message,
2356
+ if ((error = git_str_printf(&log_message,
2074
2357
  "renamed remote %s to %s",
2075
2358
  old_remote_name, new_remote_name)) < 0)
2076
2359
  goto cleanup;
2077
2360
 
2078
- if ((error = git_reference_rename(&ref, reference_in, git_buf_cstr(&new_name), 1,
2079
- git_buf_cstr(&log_message))) < 0)
2361
+ if ((error = git_reference_rename(&ref, reference_in, git_str_cstr(&new_name), 1,
2362
+ git_str_cstr(&log_message))) < 0)
2080
2363
  goto cleanup;
2081
2364
 
2082
2365
  if (git_reference_type(ref) != GIT_REFERENCE_SYMBOLIC)
@@ -2084,29 +2367,29 @@ static int rename_one_remote_reference(
2084
2367
 
2085
2368
  /* Handle refs like origin/HEAD -> origin/master */
2086
2369
  target = git_reference_symbolic_target(ref);
2087
- if ((error = git_buf_printf(&old_namespace, GIT_REFS_REMOTES_DIR "%s/", old_remote_name)) < 0)
2370
+ if ((error = git_str_printf(&old_namespace, GIT_REFS_REMOTES_DIR "%s/", old_remote_name)) < 0)
2088
2371
  goto cleanup;
2089
2372
 
2090
2373
  if (git__prefixcmp(target, old_namespace.ptr))
2091
2374
  goto cleanup;
2092
2375
 
2093
- git_buf_clear(&new_name);
2094
- git_buf_puts(&new_name, namespace.ptr);
2095
- if ((error = git_buf_puts(&new_name, target + pfx_len)) < 0)
2376
+ git_str_clear(&new_name);
2377
+ git_str_puts(&new_name, namespace.ptr);
2378
+ if ((error = git_str_puts(&new_name, target + pfx_len)) < 0)
2096
2379
  goto cleanup;
2097
2380
 
2098
- error = git_reference_symbolic_set_target(&dummy, ref, git_buf_cstr(&new_name),
2099
- git_buf_cstr(&log_message));
2381
+ error = git_reference_symbolic_set_target(&dummy, ref, git_str_cstr(&new_name),
2382
+ git_str_cstr(&log_message));
2100
2383
 
2101
2384
  git_reference_free(dummy);
2102
2385
 
2103
2386
  cleanup:
2104
2387
  git_reference_free(reference_in);
2105
2388
  git_reference_free(ref);
2106
- git_buf_dispose(&namespace);
2107
- git_buf_dispose(&old_namespace);
2108
- git_buf_dispose(&new_name);
2109
- git_buf_dispose(&log_message);
2389
+ git_str_dispose(&namespace);
2390
+ git_str_dispose(&old_namespace);
2391
+ git_str_dispose(&new_name);
2392
+ git_str_dispose(&log_message);
2110
2393
  return error;
2111
2394
  }
2112
2395
 
@@ -2116,15 +2399,15 @@ static int rename_remote_references(
2116
2399
  const char *new_name)
2117
2400
  {
2118
2401
  int error;
2119
- git_buf buf = GIT_BUF_INIT;
2402
+ git_str buf = GIT_STR_INIT;
2120
2403
  git_reference *ref;
2121
2404
  git_reference_iterator *iter;
2122
2405
 
2123
- if ((error = git_buf_printf(&buf, GIT_REFS_REMOTES_DIR "%s/*", old_name)) < 0)
2406
+ if ((error = git_str_printf(&buf, GIT_REFS_REMOTES_DIR "%s/*", old_name)) < 0)
2124
2407
  return error;
2125
2408
 
2126
- error = git_reference_iterator_glob_new(&iter, repo, git_buf_cstr(&buf));
2127
- git_buf_dispose(&buf);
2409
+ error = git_reference_iterator_glob_new(&iter, repo, git_str_cstr(&buf));
2410
+ git_str_dispose(&buf);
2128
2411
 
2129
2412
  if (error < 0)
2130
2413
  return error;
@@ -2142,7 +2425,7 @@ static int rename_remote_references(
2142
2425
  static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const char *new_name)
2143
2426
  {
2144
2427
  git_config *config;
2145
- git_buf base = GIT_BUF_INIT, var = GIT_BUF_INIT, val = GIT_BUF_INIT;
2428
+ git_str base = GIT_STR_INIT, var = GIT_STR_INIT, val = GIT_STR_INIT;
2146
2429
  const git_refspec *spec;
2147
2430
  size_t i;
2148
2431
  int error = 0;
@@ -2161,7 +2444,7 @@ static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const
2161
2444
  continue;
2162
2445
 
2163
2446
  /* Does the dst part of the refspec follow the expected format? */
2164
- if (strcmp(git_buf_cstr(&base), spec->string)) {
2447
+ if (strcmp(git_str_cstr(&base), spec->string)) {
2165
2448
  char *dup;
2166
2449
 
2167
2450
  dup = git__strdup(spec->string);
@@ -2175,24 +2458,24 @@ static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const
2175
2458
 
2176
2459
  /* If we do want to move it to the new section */
2177
2460
 
2178
- git_buf_clear(&val);
2179
- git_buf_clear(&var);
2461
+ git_str_clear(&val);
2462
+ git_str_clear(&var);
2180
2463
 
2181
2464
  if (default_fetchspec_for_name(&val, new_name) < 0 ||
2182
- git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
2465
+ git_str_printf(&var, "remote.%s.fetch", new_name) < 0)
2183
2466
  {
2184
2467
  error = -1;
2185
2468
  break;
2186
2469
  }
2187
2470
 
2188
2471
  if ((error = git_config_set_string(
2189
- config, git_buf_cstr(&var), git_buf_cstr(&val))) < 0)
2472
+ config, git_str_cstr(&var), git_str_cstr(&val))) < 0)
2190
2473
  break;
2191
2474
  }
2192
2475
 
2193
- git_buf_dispose(&base);
2194
- git_buf_dispose(&var);
2195
- git_buf_dispose(&val);
2476
+ git_str_dispose(&base);
2477
+ git_str_dispose(&var);
2478
+ git_str_dispose(&val);
2196
2479
 
2197
2480
  if (error < 0) {
2198
2481
  char *str;
@@ -2247,7 +2530,7 @@ cleanup:
2247
2530
 
2248
2531
  int git_remote_name_is_valid(int *valid, const char *remote_name)
2249
2532
  {
2250
- git_buf buf = GIT_BUF_INIT;
2533
+ git_str buf = GIT_STR_INIT;
2251
2534
  git_refspec refspec = {0};
2252
2535
  int error;
2253
2536
 
@@ -2258,10 +2541,10 @@ int git_remote_name_is_valid(int *valid, const char *remote_name)
2258
2541
  if (!remote_name || *remote_name == '\0')
2259
2542
  return 0;
2260
2543
 
2261
- if ((error = git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name)) < 0)
2544
+ if ((error = git_str_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name)) < 0)
2262
2545
  goto done;
2263
2546
 
2264
- error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
2547
+ error = git_refspec__parse(&refspec, git_str_cstr(&buf), true);
2265
2548
 
2266
2549
  if (!error)
2267
2550
  *valid = 1;
@@ -2269,7 +2552,7 @@ int git_remote_name_is_valid(int *valid, const char *remote_name)
2269
2552
  error = 0;
2270
2553
 
2271
2554
  done:
2272
- git_buf_dispose(&buf);
2555
+ git_str_dispose(&buf);
2273
2556
  git_refspec__dispose(&refspec);
2274
2557
 
2275
2558
  return error;
@@ -2401,7 +2684,7 @@ static int remove_branch_config_related_entries(
2401
2684
  git_config *config;
2402
2685
  git_config_entry *entry;
2403
2686
  git_config_iterator *iter;
2404
- git_buf buf = GIT_BUF_INIT;
2687
+ git_str buf = GIT_STR_INIT;
2405
2688
 
2406
2689
  if ((error = git_repository_config__weakptr(&config, repo)) < 0)
2407
2690
  return error;
@@ -2422,21 +2705,21 @@ static int remove_branch_config_related_entries(
2422
2705
  break;
2423
2706
  }
2424
2707
 
2425
- git_buf_clear(&buf);
2426
- if ((error = git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch)) < 0)
2708
+ git_str_clear(&buf);
2709
+ if ((error = git_str_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch)) < 0)
2427
2710
  break;
2428
2711
 
2429
- if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
2712
+ if ((error = git_config_delete_entry(config, git_str_cstr(&buf))) < 0) {
2430
2713
  if (error != GIT_ENOTFOUND)
2431
2714
  break;
2432
2715
  git_error_clear();
2433
2716
  }
2434
2717
 
2435
- git_buf_clear(&buf);
2436
- if ((error = git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch)) < 0)
2718
+ git_str_clear(&buf);
2719
+ if ((error = git_str_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch)) < 0)
2437
2720
  break;
2438
2721
 
2439
- if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
2722
+ if ((error = git_config_delete_entry(config, git_str_cstr(&buf))) < 0) {
2440
2723
  if (error != GIT_ENOTFOUND)
2441
2724
  break;
2442
2725
  git_error_clear();
@@ -2446,7 +2729,7 @@ static int remove_branch_config_related_entries(
2446
2729
  if (error == GIT_ITEROVER)
2447
2730
  error = 0;
2448
2731
 
2449
- git_buf_dispose(&buf);
2732
+ git_str_dispose(&buf);
2450
2733
  git_config_iterator_free(iter);
2451
2734
  return error;
2452
2735
  }
@@ -2540,12 +2823,17 @@ int git_remote_delete(git_repository *repo, const char *name)
2540
2823
  }
2541
2824
 
2542
2825
  int git_remote_default_branch(git_buf *out, git_remote *remote)
2826
+ {
2827
+ GIT_BUF_WRAP_PRIVATE(out, git_remote__default_branch, remote);
2828
+ }
2829
+
2830
+ int git_remote__default_branch(git_str *out, git_remote *remote)
2543
2831
  {
2544
2832
  const git_remote_head **heads;
2545
2833
  const git_remote_head *guess = NULL;
2546
2834
  const git_oid *head_id;
2547
2835
  size_t heads_len, i;
2548
- git_buf local_default = GIT_BUF_INIT;
2836
+ git_str local_default = GIT_STR_INIT;
2549
2837
  int error;
2550
2838
 
2551
2839
  GIT_ASSERT_ARG(out);
@@ -2558,12 +2846,9 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
2558
2846
  goto done;
2559
2847
  }
2560
2848
 
2561
- if ((error = git_buf_sanitize(out)) < 0)
2562
- return error;
2563
-
2564
2849
  /* the first one must be HEAD so if that has the symref info, we're done */
2565
2850
  if (heads[0]->symref_target) {
2566
- error = git_buf_puts(out, heads[0]->symref_target);
2851
+ error = git_str_puts(out, heads[0]->symref_target);
2567
2852
  goto done;
2568
2853
  }
2569
2854
 
@@ -2601,21 +2886,33 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
2601
2886
  goto done;
2602
2887
  }
2603
2888
 
2604
- error = git_buf_puts(out, guess->name);
2889
+ error = git_str_puts(out, guess->name);
2605
2890
 
2606
2891
  done:
2607
- git_buf_dispose(&local_default);
2892
+ git_str_dispose(&local_default);
2608
2893
  return error;
2609
2894
  }
2610
2895
 
2611
- int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
2896
+ GIT_INLINE(int) connect_opts_from_push_opts(
2897
+ git_remote_connect_options *out,
2898
+ git_remote *remote,
2899
+ const git_push_options *push_opts)
2612
2900
  {
2613
- size_t i;
2614
- int error;
2901
+ git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
2902
+ copy_opts(&tmp, push_opts);
2903
+ return git_remote_connect_options_normalize(out, remote->repo, &tmp);
2904
+ }
2905
+
2906
+ int git_remote_upload(
2907
+ git_remote *remote,
2908
+ const git_strarray *refspecs,
2909
+ const git_push_options *opts)
2910
+ {
2911
+ git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
2615
2912
  git_push *push;
2616
2913
  git_refspec *spec;
2617
- const git_remote_callbacks *cbs = NULL;
2618
- git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
2914
+ size_t i;
2915
+ int error;
2619
2916
 
2620
2917
  GIT_ASSERT_ARG(remote);
2621
2918
 
@@ -2624,14 +2921,10 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
2624
2921
  return -1;
2625
2922
  }
2626
2923
 
2627
- if (opts) {
2628
- cbs = &opts->callbacks;
2629
- conn.custom_headers = &opts->custom_headers;
2630
- conn.proxy = &opts->proxy_opts;
2631
- }
2924
+ if ((error = connect_opts_from_push_opts(&connect_opts, remote, opts)) < 0)
2925
+ goto cleanup;
2632
2926
 
2633
- if (!git_remote_connected(remote) &&
2634
- (error = git_remote__connect(remote, GIT_DIRECTION_PUSH, cbs, &conn)) < 0)
2927
+ if ((error = connect_or_reset_options(remote, GIT_DIRECTION_PUSH, &connect_opts)) < 0)
2635
2928
  goto cleanup;
2636
2929
 
2637
2930
  free_refspecs(&remote->active_refspecs);
@@ -2643,14 +2936,11 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
2643
2936
  remote->push = NULL;
2644
2937
  }
2645
2938
 
2646
- if ((error = git_push_new(&remote->push, remote)) < 0)
2647
- return error;
2939
+ if ((error = git_push_new(&remote->push, remote, opts)) < 0)
2940
+ goto cleanup;
2648
2941
 
2649
2942
  push = remote->push;
2650
2943
 
2651
- if (opts && (error = git_push_set_options(push, opts)) < 0)
2652
- goto cleanup;
2653
-
2654
2944
  if (refspecs && refspecs->count > 0) {
2655
2945
  for (i = 0; i < refspecs->count; i++) {
2656
2946
  if ((error = git_push_add_refspec(push, refspecs->strings[i])) < 0)
@@ -2665,23 +2955,25 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
2665
2955
  }
2666
2956
  }
2667
2957
 
2668
- if ((error = git_push_finish(push, cbs)) < 0)
2958
+ if ((error = git_push_finish(push)) < 0)
2669
2959
  goto cleanup;
2670
2960
 
2671
- if (cbs && cbs->push_update_reference &&
2672
- (error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
2961
+ if (connect_opts.callbacks.push_update_reference &&
2962
+ (error = git_push_status_foreach(push, connect_opts.callbacks.push_update_reference, connect_opts.callbacks.payload)) < 0)
2673
2963
  goto cleanup;
2674
2964
 
2675
2965
  cleanup:
2966
+ git_remote_connect_options_dispose(&connect_opts);
2676
2967
  return error;
2677
2968
  }
2678
2969
 
2679
- int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
2970
+ int git_remote_push(
2971
+ git_remote *remote,
2972
+ const git_strarray *refspecs,
2973
+ const git_push_options *opts)
2680
2974
  {
2975
+ git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
2681
2976
  int error;
2682
- const git_remote_callbacks *cbs = NULL;
2683
- const git_strarray *custom_headers = NULL;
2684
- const git_proxy_options *proxy = NULL;
2685
2977
 
2686
2978
  GIT_ASSERT_ARG(remote);
2687
2979
 
@@ -2690,23 +2982,17 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
2690
2982
  return -1;
2691
2983
  }
2692
2984
 
2693
- if (opts) {
2694
- GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
2695
- cbs = &opts->callbacks;
2696
- custom_headers = &opts->custom_headers;
2697
- GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
2698
- proxy = &opts->proxy_opts;
2699
- }
2700
-
2701
- if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
2702
- return error;
2985
+ if (connect_opts_from_push_opts(&connect_opts, remote, opts) < 0)
2986
+ return -1;
2703
2987
 
2704
2988
  if ((error = git_remote_upload(remote, refspecs, opts)) < 0)
2705
- return error;
2989
+ goto done;
2706
2990
 
2707
- error = git_remote_update_tips(remote, cbs, 0, 0, NULL);
2991
+ error = git_remote_update_tips(remote, &connect_opts.callbacks, 0, 0, NULL);
2708
2992
 
2993
+ done:
2709
2994
  git_remote_disconnect(remote);
2995
+ git_remote_connect_options_dispose(&connect_opts);
2710
2996
  return error;
2711
2997
  }
2712
2998
 
@@ -2714,19 +3000,20 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
2714
3000
  #define SUFFIX_FETCH "insteadof"
2715
3001
  #define SUFFIX_PUSH "pushinsteadof"
2716
3002
 
2717
- char *apply_insteadof(git_config *config, const char *url, int direction)
3003
+ static int apply_insteadof(char **out, git_config *config, const char *url, int direction, bool use_default_if_empty)
2718
3004
  {
2719
3005
  size_t match_length, prefix_length, suffix_length;
2720
3006
  char *replacement = NULL;
2721
3007
  const char *regexp;
2722
3008
 
2723
- git_buf result = GIT_BUF_INIT;
3009
+ git_str result = GIT_STR_INIT;
2724
3010
  git_config_entry *entry;
2725
3011
  git_config_iterator *iter;
2726
3012
 
2727
- GIT_ASSERT_ARG_WITH_RETVAL(config, NULL);
2728
- GIT_ASSERT_ARG_WITH_RETVAL(url, NULL);
2729
- GIT_ASSERT_ARG_WITH_RETVAL(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH, NULL);
3013
+ GIT_ASSERT_ARG(out);
3014
+ GIT_ASSERT_ARG(config);
3015
+ GIT_ASSERT_ARG(url);
3016
+ GIT_ASSERT_ARG(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
2730
3017
 
2731
3018
  /* Add 1 to prefix/suffix length due to the additional escaped dot */
2732
3019
  prefix_length = strlen(PREFIX) + 1;
@@ -2739,7 +3026,7 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
2739
3026
  }
2740
3027
 
2741
3028
  if (git_config_iterator_glob_new(&iter, config, regexp) < 0)
2742
- return NULL;
3029
+ return -1;
2743
3030
 
2744
3031
  match_length = 0;
2745
3032
  while (git_config_next(&entry, iter) == 0) {
@@ -2748,6 +3035,7 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
2748
3035
  /* Check if entry value is a prefix of URL */
2749
3036
  if (git__prefixcmp(url, entry->value))
2750
3037
  continue;
3038
+
2751
3039
  /* Check if entry value is longer than previous
2752
3040
  * prefixes */
2753
3041
  if ((n = strlen(entry->value)) <= match_length)
@@ -2765,14 +3053,20 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
2765
3053
 
2766
3054
  git_config_iterator_free(iter);
2767
3055
 
2768
- if (match_length == 0)
2769
- return git__strdup(url);
3056
+ if (match_length == 0 && use_default_if_empty) {
3057
+ *out = git__strdup(url);
3058
+ return *out ? 0 : -1;
3059
+ } else if (match_length == 0) {
3060
+ *out = NULL;
3061
+ return 0;
3062
+ }
2770
3063
 
2771
- git_buf_printf(&result, "%s%s", replacement, url + match_length);
3064
+ git_str_printf(&result, "%s%s", replacement, url + match_length);
2772
3065
 
2773
3066
  git__free(replacement);
2774
3067
 
2775
- return result.ptr;
3068
+ *out = git_str_detach(&result);
3069
+ return 0;
2776
3070
  }
2777
3071
 
2778
3072
  /* Deprecated functions */