rugged 1.3.2.3 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 */