rugged 0.17.0.b7 → 0.18.0.b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (310) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +88 -32
  3. data/ext/rugged/extconf.rb +4 -2
  4. data/ext/rugged/rugged.c +72 -10
  5. data/ext/rugged/rugged.h +14 -10
  6. data/ext/rugged/rugged_blob.c +8 -10
  7. data/ext/rugged/rugged_branch.c +11 -14
  8. data/ext/rugged/rugged_commit.c +31 -24
  9. data/ext/rugged/rugged_config.c +2 -2
  10. data/ext/rugged/rugged_index.c +133 -198
  11. data/ext/rugged/rugged_note.c +372 -0
  12. data/ext/rugged/rugged_object.c +50 -22
  13. data/ext/rugged/rugged_reference.c +122 -130
  14. data/ext/rugged/rugged_remote.c +72 -29
  15. data/ext/rugged/rugged_repo.c +402 -20
  16. data/ext/rugged/rugged_revwalk.c +7 -3
  17. data/ext/rugged/rugged_settings.c +110 -0
  18. data/ext/rugged/rugged_signature.c +23 -7
  19. data/ext/rugged/rugged_tag.c +32 -16
  20. data/ext/rugged/rugged_tree.c +44 -15
  21. data/lib/rugged.rb +1 -0
  22. data/lib/rugged/index.rb +8 -0
  23. data/lib/rugged/remote.rb +13 -0
  24. data/lib/rugged/repository.rb +3 -3
  25. data/lib/rugged/version.rb +1 -1
  26. data/test/blob_test.rb +13 -15
  27. data/test/branch_test.rb +32 -67
  28. data/test/commit_test.rb +50 -12
  29. data/test/config_test.rb +12 -11
  30. data/test/coverage/HEAD.json +1 -1
  31. data/test/coverage/cover.rb +40 -21
  32. data/test/errors_test.rb +34 -0
  33. data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
  34. data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
  35. data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
  36. data/test/fixtures/testrepo.git/logs/refs/notes/commits +1 -0
  37. data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +1 -0
  38. data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
  39. data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +1 -0
  40. data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
  41. data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
  42. data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +3 -0
  43. data/test/fixtures/testrepo.git/refs/notes/commits +1 -0
  44. data/test/index_test.rb +65 -69
  45. data/test/lib_test.rb +76 -11
  46. data/test/note_test.rb +158 -0
  47. data/test/object_test.rb +8 -11
  48. data/test/reference_test.rb +77 -85
  49. data/test/remote_test.rb +86 -8
  50. data/test/repo_pack_test.rb +9 -7
  51. data/test/repo_reset_test.rb +80 -0
  52. data/test/repo_test.rb +176 -53
  53. data/test/tag_test.rb +44 -7
  54. data/test/test_helper.rb +63 -35
  55. data/test/tree_test.rb +34 -13
  56. data/test/walker_test.rb +14 -14
  57. data/vendor/libgit2/Makefile.embed +1 -1
  58. data/vendor/libgit2/deps/http-parser/http_parser.c +974 -578
  59. data/vendor/libgit2/deps/http-parser/http_parser.h +106 -70
  60. data/vendor/libgit2/deps/regex/regcomp.c +7 -6
  61. data/vendor/libgit2/deps/regex/regex_internal.c +1 -1
  62. data/vendor/libgit2/deps/regex/regex_internal.h +12 -3
  63. data/vendor/libgit2/deps/regex/regexec.c +5 -5
  64. data/vendor/libgit2/include/git2.h +5 -1
  65. data/vendor/libgit2/include/git2/attr.h +4 -2
  66. data/vendor/libgit2/include/git2/blob.h +39 -12
  67. data/vendor/libgit2/include/git2/branch.h +123 -35
  68. data/vendor/libgit2/include/git2/checkout.h +206 -48
  69. data/vendor/libgit2/include/git2/clone.h +72 -27
  70. data/vendor/libgit2/include/git2/commit.h +20 -17
  71. data/vendor/libgit2/include/git2/common.h +67 -1
  72. data/vendor/libgit2/include/git2/config.h +81 -60
  73. data/vendor/libgit2/include/git2/cred_helpers.h +53 -0
  74. data/vendor/libgit2/include/git2/diff.h +459 -150
  75. data/vendor/libgit2/include/git2/errors.h +9 -1
  76. data/vendor/libgit2/include/git2/graph.h +41 -0
  77. data/vendor/libgit2/include/git2/ignore.h +7 -6
  78. data/vendor/libgit2/include/git2/index.h +323 -97
  79. data/vendor/libgit2/include/git2/indexer.h +27 -59
  80. data/vendor/libgit2/include/git2/inttypes.h +4 -0
  81. data/vendor/libgit2/include/git2/merge.h +13 -3
  82. data/vendor/libgit2/include/git2/message.h +14 -8
  83. data/vendor/libgit2/include/git2/net.h +9 -7
  84. data/vendor/libgit2/include/git2/notes.h +88 -29
  85. data/vendor/libgit2/include/git2/object.h +16 -6
  86. data/vendor/libgit2/include/git2/odb.h +80 -17
  87. data/vendor/libgit2/include/git2/odb_backend.h +47 -11
  88. data/vendor/libgit2/include/git2/oid.h +26 -17
  89. data/vendor/libgit2/include/git2/pack.h +62 -8
  90. data/vendor/libgit2/include/git2/push.h +131 -0
  91. data/vendor/libgit2/include/git2/refdb.h +103 -0
  92. data/vendor/libgit2/include/git2/refdb_backend.h +109 -0
  93. data/vendor/libgit2/include/git2/reflog.h +30 -21
  94. data/vendor/libgit2/include/git2/refs.h +215 -193
  95. data/vendor/libgit2/include/git2/refspec.h +22 -2
  96. data/vendor/libgit2/include/git2/remote.h +158 -37
  97. data/vendor/libgit2/include/git2/repository.h +150 -31
  98. data/vendor/libgit2/include/git2/reset.h +43 -9
  99. data/vendor/libgit2/include/git2/revparse.h +48 -4
  100. data/vendor/libgit2/include/git2/revwalk.h +25 -10
  101. data/vendor/libgit2/include/git2/signature.h +20 -12
  102. data/vendor/libgit2/include/git2/stash.h +121 -0
  103. data/vendor/libgit2/include/git2/status.h +122 -53
  104. data/vendor/libgit2/include/git2/strarray.h +17 -11
  105. data/vendor/libgit2/include/git2/submodule.h +42 -7
  106. data/vendor/libgit2/include/git2/tag.h +72 -59
  107. data/vendor/libgit2/include/git2/threads.h +4 -2
  108. data/vendor/libgit2/include/git2/trace.h +68 -0
  109. data/vendor/libgit2/include/git2/transport.h +328 -0
  110. data/vendor/libgit2/include/git2/tree.h +149 -120
  111. data/vendor/libgit2/include/git2/types.h +13 -12
  112. data/vendor/libgit2/include/git2/version.h +3 -3
  113. data/vendor/libgit2/src/amiga/map.c +2 -2
  114. data/vendor/libgit2/src/attr.c +58 -48
  115. data/vendor/libgit2/src/attr.h +4 -18
  116. data/vendor/libgit2/src/attr_file.c +30 -6
  117. data/vendor/libgit2/src/attr_file.h +6 -8
  118. data/vendor/libgit2/src/attrcache.h +24 -0
  119. data/vendor/libgit2/src/blob.c +30 -7
  120. data/vendor/libgit2/src/blob.h +1 -1
  121. data/vendor/libgit2/src/branch.c +361 -68
  122. data/vendor/libgit2/src/branch.h +17 -0
  123. data/vendor/libgit2/src/bswap.h +1 -1
  124. data/vendor/libgit2/src/buf_text.c +291 -0
  125. data/vendor/libgit2/src/buf_text.h +122 -0
  126. data/vendor/libgit2/src/buffer.c +27 -101
  127. data/vendor/libgit2/src/buffer.h +54 -39
  128. data/vendor/libgit2/src/cache.c +15 -6
  129. data/vendor/libgit2/src/cache.h +1 -1
  130. data/vendor/libgit2/src/cc-compat.h +3 -1
  131. data/vendor/libgit2/src/checkout.c +1165 -222
  132. data/vendor/libgit2/src/checkout.h +24 -0
  133. data/vendor/libgit2/src/clone.c +171 -86
  134. data/vendor/libgit2/src/commit.c +44 -45
  135. data/vendor/libgit2/src/commit.h +3 -3
  136. data/vendor/libgit2/src/commit_list.c +194 -0
  137. data/vendor/libgit2/src/commit_list.h +49 -0
  138. data/vendor/libgit2/src/common.h +44 -10
  139. data/vendor/libgit2/src/compress.c +1 -1
  140. data/vendor/libgit2/src/compress.h +1 -1
  141. data/vendor/libgit2/src/config.c +211 -124
  142. data/vendor/libgit2/src/config.h +23 -4
  143. data/vendor/libgit2/src/config_cache.c +2 -2
  144. data/vendor/libgit2/src/config_file.c +129 -53
  145. data/vendor/libgit2/src/config_file.h +10 -8
  146. data/vendor/libgit2/src/crlf.c +66 -67
  147. data/vendor/libgit2/src/date.c +12 -12
  148. data/vendor/libgit2/src/delta-apply.c +14 -1
  149. data/vendor/libgit2/src/delta-apply.h +18 -1
  150. data/vendor/libgit2/src/delta.c +40 -107
  151. data/vendor/libgit2/src/delta.h +19 -17
  152. data/vendor/libgit2/src/diff.c +347 -496
  153. data/vendor/libgit2/src/diff.h +27 -1
  154. data/vendor/libgit2/src/diff_output.c +564 -249
  155. data/vendor/libgit2/src/diff_output.h +15 -8
  156. data/vendor/libgit2/src/diff_tform.c +687 -0
  157. data/vendor/libgit2/src/errors.c +27 -36
  158. data/vendor/libgit2/src/fetch.c +13 -351
  159. data/vendor/libgit2/src/fetch.h +13 -3
  160. data/vendor/libgit2/src/fetchhead.c +295 -0
  161. data/vendor/libgit2/src/fetchhead.h +34 -0
  162. data/vendor/libgit2/src/filebuf.c +42 -15
  163. data/vendor/libgit2/src/filebuf.h +4 -2
  164. data/vendor/libgit2/src/fileops.c +466 -113
  165. data/vendor/libgit2/src/fileops.h +154 -28
  166. data/vendor/libgit2/src/filter.c +3 -75
  167. data/vendor/libgit2/src/filter.h +1 -29
  168. data/vendor/libgit2/src/fnmatch.c +1 -1
  169. data/vendor/libgit2/src/fnmatch.h +1 -1
  170. data/vendor/libgit2/src/global.c +54 -10
  171. data/vendor/libgit2/src/global.h +10 -1
  172. data/vendor/libgit2/src/graph.c +178 -0
  173. data/vendor/libgit2/src/hash.c +25 -52
  174. data/vendor/libgit2/src/hash.h +21 -9
  175. data/vendor/libgit2/src/{sha1/sha1.c → hash/hash_generic.c} +20 -12
  176. data/vendor/libgit2/src/hash/hash_generic.h +24 -0
  177. data/vendor/libgit2/src/hash/hash_openssl.h +45 -0
  178. data/vendor/libgit2/src/hash/hash_win32.c +291 -0
  179. data/vendor/libgit2/src/hash/hash_win32.h +140 -0
  180. data/vendor/libgit2/src/hashsig.c +368 -0
  181. data/vendor/libgit2/src/hashsig.h +72 -0
  182. data/vendor/libgit2/src/ignore.c +22 -15
  183. data/vendor/libgit2/src/ignore.h +6 -1
  184. data/vendor/libgit2/src/index.c +770 -171
  185. data/vendor/libgit2/src/index.h +13 -5
  186. data/vendor/libgit2/src/indexer.c +286 -431
  187. data/vendor/libgit2/src/iterator.c +854 -466
  188. data/vendor/libgit2/src/iterator.h +134 -109
  189. data/vendor/libgit2/src/map.h +1 -1
  190. data/vendor/libgit2/src/merge.c +296 -0
  191. data/vendor/libgit2/src/merge.h +22 -0
  192. data/vendor/libgit2/src/message.c +1 -1
  193. data/vendor/libgit2/src/message.h +1 -1
  194. data/vendor/libgit2/src/mwindow.c +35 -30
  195. data/vendor/libgit2/src/mwindow.h +2 -2
  196. data/vendor/libgit2/src/netops.c +162 -98
  197. data/vendor/libgit2/src/netops.h +50 -15
  198. data/vendor/libgit2/src/notes.c +109 -58
  199. data/vendor/libgit2/src/notes.h +2 -1
  200. data/vendor/libgit2/src/object.c +46 -57
  201. data/vendor/libgit2/src/object.h +1 -8
  202. data/vendor/libgit2/src/odb.c +151 -40
  203. data/vendor/libgit2/src/odb.h +5 -1
  204. data/vendor/libgit2/src/odb_loose.c +4 -5
  205. data/vendor/libgit2/src/odb_pack.c +122 -80
  206. data/vendor/libgit2/src/offmap.h +65 -0
  207. data/vendor/libgit2/src/oid.c +12 -4
  208. data/vendor/libgit2/src/oidmap.h +1 -1
  209. data/vendor/libgit2/src/pack-objects.c +88 -61
  210. data/vendor/libgit2/src/pack-objects.h +8 -8
  211. data/vendor/libgit2/src/pack.c +293 -28
  212. data/vendor/libgit2/src/pack.h +49 -4
  213. data/vendor/libgit2/src/path.c +103 -14
  214. data/vendor/libgit2/src/path.h +23 -7
  215. data/vendor/libgit2/src/pathspec.c +168 -0
  216. data/vendor/libgit2/src/pathspec.h +40 -0
  217. data/vendor/libgit2/src/pool.c +29 -4
  218. data/vendor/libgit2/src/pool.h +8 -1
  219. data/vendor/libgit2/src/posix.c +26 -27
  220. data/vendor/libgit2/src/posix.h +2 -3
  221. data/vendor/libgit2/src/pqueue.c +23 -1
  222. data/vendor/libgit2/src/pqueue.h +23 -1
  223. data/vendor/libgit2/src/push.c +653 -0
  224. data/vendor/libgit2/src/push.h +51 -0
  225. data/vendor/libgit2/src/refdb.c +185 -0
  226. data/vendor/libgit2/src/refdb.h +46 -0
  227. data/vendor/libgit2/src/refdb_fs.c +1024 -0
  228. data/vendor/libgit2/src/refdb_fs.h +15 -0
  229. data/vendor/libgit2/src/reflog.c +77 -45
  230. data/vendor/libgit2/src/reflog.h +1 -3
  231. data/vendor/libgit2/src/refs.c +366 -1326
  232. data/vendor/libgit2/src/refs.h +22 -13
  233. data/vendor/libgit2/src/refspec.c +46 -7
  234. data/vendor/libgit2/src/refspec.h +11 -1
  235. data/vendor/libgit2/src/remote.c +758 -120
  236. data/vendor/libgit2/src/remote.h +10 -5
  237. data/vendor/libgit2/src/repo_template.h +6 -6
  238. data/vendor/libgit2/src/repository.c +315 -96
  239. data/vendor/libgit2/src/repository.h +5 -3
  240. data/vendor/libgit2/src/reset.c +99 -81
  241. data/vendor/libgit2/src/revparse.c +157 -84
  242. data/vendor/libgit2/src/revwalk.c +68 -470
  243. data/vendor/libgit2/src/revwalk.h +44 -0
  244. data/vendor/libgit2/src/sha1_lookup.c +1 -1
  245. data/vendor/libgit2/src/sha1_lookup.h +1 -1
  246. data/vendor/libgit2/src/signature.c +68 -200
  247. data/vendor/libgit2/src/signature.h +1 -1
  248. data/vendor/libgit2/src/stash.c +663 -0
  249. data/vendor/libgit2/src/status.c +101 -79
  250. data/vendor/libgit2/src/strmap.h +1 -1
  251. data/vendor/libgit2/src/submodule.c +67 -51
  252. data/vendor/libgit2/src/submodule.h +1 -1
  253. data/vendor/libgit2/src/tag.c +35 -29
  254. data/vendor/libgit2/src/tag.h +1 -1
  255. data/vendor/libgit2/src/thread-utils.c +1 -1
  256. data/vendor/libgit2/src/thread-utils.h +2 -2
  257. data/vendor/libgit2/src/trace.c +39 -0
  258. data/vendor/libgit2/src/trace.h +56 -0
  259. data/vendor/libgit2/src/transport.c +81 -34
  260. data/vendor/libgit2/src/transports/cred.c +60 -0
  261. data/vendor/libgit2/src/transports/cred_helpers.c +49 -0
  262. data/vendor/libgit2/src/transports/git.c +234 -127
  263. data/vendor/libgit2/src/transports/http.c +761 -433
  264. data/vendor/libgit2/src/transports/local.c +460 -64
  265. data/vendor/libgit2/src/transports/smart.c +345 -0
  266. data/vendor/libgit2/src/transports/smart.h +179 -0
  267. data/vendor/libgit2/src/{pkt.c → transports/smart_pkt.c} +131 -12
  268. data/vendor/libgit2/src/transports/smart_protocol.c +856 -0
  269. data/vendor/libgit2/src/transports/winhttp.c +1136 -0
  270. data/vendor/libgit2/src/tree-cache.c +2 -2
  271. data/vendor/libgit2/src/tree-cache.h +1 -1
  272. data/vendor/libgit2/src/tree.c +239 -166
  273. data/vendor/libgit2/src/tree.h +11 -2
  274. data/vendor/libgit2/src/tsort.c +39 -23
  275. data/vendor/libgit2/src/unix/map.c +1 -1
  276. data/vendor/libgit2/src/unix/posix.h +12 -2
  277. data/vendor/libgit2/src/unix/realpath.c +30 -0
  278. data/vendor/libgit2/src/util.c +250 -13
  279. data/vendor/libgit2/src/util.h +71 -14
  280. data/vendor/libgit2/src/vector.c +123 -60
  281. data/vendor/libgit2/src/vector.h +24 -22
  282. data/vendor/libgit2/src/win32/dir.c +1 -1
  283. data/vendor/libgit2/src/win32/dir.h +1 -1
  284. data/vendor/libgit2/src/win32/error.c +77 -0
  285. data/vendor/libgit2/src/win32/error.h +13 -0
  286. data/vendor/libgit2/src/win32/findfile.c +143 -54
  287. data/vendor/libgit2/src/win32/findfile.h +10 -6
  288. data/vendor/libgit2/src/win32/map.c +1 -1
  289. data/vendor/libgit2/src/win32/mingw-compat.h +1 -1
  290. data/vendor/libgit2/src/win32/msvc-compat.h +10 -1
  291. data/vendor/libgit2/src/win32/posix.h +10 -1
  292. data/vendor/libgit2/src/win32/posix_w32.c +132 -63
  293. data/vendor/libgit2/src/win32/precompiled.c +1 -1
  294. data/vendor/libgit2/src/win32/pthread.c +1 -1
  295. data/vendor/libgit2/src/win32/pthread.h +1 -1
  296. data/vendor/libgit2/src/win32/utf-conv.c +5 -5
  297. data/vendor/libgit2/src/win32/utf-conv.h +3 -3
  298. data/vendor/libgit2/src/win32/version.h +20 -0
  299. metadata +308 -252
  300. data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
  301. data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
  302. data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
  303. data/test/index_test.rb~ +0 -218
  304. data/vendor/libgit2/src/pkt.h +0 -91
  305. data/vendor/libgit2/src/ppc/sha1.c +0 -70
  306. data/vendor/libgit2/src/ppc/sha1.h +0 -26
  307. data/vendor/libgit2/src/protocol.c +0 -110
  308. data/vendor/libgit2/src/protocol.h +0 -21
  309. data/vendor/libgit2/src/sha1.h +0 -33
  310. data/vendor/libgit2/src/transport.h +0 -148
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -10,6 +10,7 @@
10
10
  #include "common.h"
11
11
  #include "git2/oid.h"
12
12
  #include "git2/refs.h"
13
+ #include "git2/refdb.h"
13
14
  #include "strmap.h"
14
15
  #include "buffer.h"
15
16
 
@@ -28,35 +29,43 @@
28
29
  #define GIT_PACKEDREFS_FILE_MODE 0666
29
30
 
30
31
  #define GIT_HEAD_FILE "HEAD"
32
+ #define GIT_ORIG_HEAD_FILE "ORIG_HEAD"
31
33
  #define GIT_FETCH_HEAD_FILE "FETCH_HEAD"
32
34
  #define GIT_MERGE_HEAD_FILE "MERGE_HEAD"
35
+ #define GIT_REVERT_HEAD_FILE "REVERT_HEAD"
36
+ #define GIT_CHERRY_PICK_HEAD_FILE "CHERRY_PICK_HEAD"
37
+ #define GIT_BISECT_LOG_FILE "BISECT_LOG"
38
+ #define GIT_REBASE_MERGE_DIR "rebase-merge/"
39
+ #define GIT_REBASE_MERGE_INTERACTIVE_FILE GIT_REBASE_MERGE_DIR "interactive"
40
+ #define GIT_REBASE_APPLY_DIR "rebase-apply/"
41
+ #define GIT_REBASE_APPLY_REBASING_FILE GIT_REBASE_APPLY_DIR "rebasing"
42
+ #define GIT_REBASE_APPLY_APPLYING_FILE GIT_REBASE_APPLY_DIR "applying"
33
43
  #define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master"
34
44
 
45
+ #define GIT_STASH_FILE "stash"
46
+ #define GIT_REFS_STASH_FILE GIT_REFS_DIR GIT_STASH_FILE
47
+
35
48
  #define GIT_REFNAME_MAX 1024
36
49
 
37
50
  struct git_reference {
38
- unsigned int flags;
39
- git_repository *owner;
40
- char *name;
41
- time_t mtime;
51
+ git_refdb *db;
52
+ git_ref_t type;
42
53
 
43
54
  union {
44
55
  git_oid oid;
45
56
  char *symbolic;
46
57
  } target;
47
- };
48
58
 
49
- typedef struct {
50
- git_strmap *packfile;
51
- time_t packfile_time;
52
- } git_refcache;
53
-
54
- void git_repository__refcache_free(git_refcache *refs);
59
+ git_oid peel;
60
+ char name[0];
61
+ };
55
62
 
56
63
  int git_reference__normalize_name_lax(char *buffer_out, size_t out_size, const char *name);
57
64
  int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags);
65
+ int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid);
58
66
  int git_reference__is_valid_name(const char *refname, unsigned int flags);
59
- int git_reference__update(git_repository *repo, const git_oid *oid, const char *ref_name);
67
+ int git_reference__is_branch(const char *ref_name);
68
+ int git_reference__is_remote(const char *ref_name);
60
69
 
61
70
  /**
62
71
  * Lookup a reference by name and try to resolve to an OID.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -127,6 +127,9 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
127
127
 
128
128
  void git_refspec__free(git_refspec *refspec)
129
129
  {
130
+ if (refspec == NULL)
131
+ return;
132
+
130
133
  git__free(refspec->src);
131
134
  git__free(refspec->dst);
132
135
  }
@@ -156,11 +159,19 @@ int git_refspec_src_matches(const git_refspec *refspec, const char *refname)
156
159
  return (p_fnmatch(refspec->src, refname, 0) == 0);
157
160
  }
158
161
 
159
- int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name)
162
+ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname)
163
+ {
164
+ if (refspec == NULL || refspec->dst == NULL)
165
+ return false;
166
+
167
+ return (p_fnmatch(refspec->dst, refname, 0) == 0);
168
+ }
169
+
170
+ static int refspec_transform_internal(char *out, size_t outlen, const char *from, const char *to, const char *name)
160
171
  {
161
172
  size_t baselen, namelen;
162
173
 
163
- baselen = strlen(spec->dst);
174
+ baselen = strlen(to);
164
175
  if (outlen <= baselen) {
165
176
  giterr_set(GITERR_INVALID, "Reference name too long");
166
177
  return GIT_EBUFS;
@@ -170,8 +181,8 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
170
181
  * No '*' at the end means that it's mapped to one specific local
171
182
  * branch, so no actual transformation is needed.
172
183
  */
173
- if (spec->dst[baselen - 1] != '*') {
174
- memcpy(out, spec->dst, baselen + 1); /* include '\0' */
184
+ if (to[baselen - 1] != '*') {
185
+ memcpy(out, to, baselen + 1); /* include '\0' */
175
186
  return 0;
176
187
  }
177
188
 
@@ -179,7 +190,7 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
179
190
  baselen--;
180
191
 
181
192
  /* skip the prefix, -1 is for the '*' */
182
- name += strlen(spec->src) - 1;
193
+ name += strlen(from) - 1;
183
194
 
184
195
  namelen = strlen(name);
185
196
 
@@ -188,12 +199,22 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
188
199
  return GIT_EBUFS;
189
200
  }
190
201
 
191
- memcpy(out, spec->dst, baselen);
202
+ memcpy(out, to, baselen);
192
203
  memcpy(out + baselen, name, namelen + 1);
193
204
 
194
205
  return 0;
195
206
  }
196
207
 
208
+ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name)
209
+ {
210
+ return refspec_transform_internal(out, outlen, spec->src, spec->dst, name);
211
+ }
212
+
213
+ int git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, const char *name)
214
+ {
215
+ return refspec_transform_internal(out, outlen, spec->dst, spec->src, name);
216
+ }
217
+
197
218
  static int refspec_transform(git_buf *out, const char *from, const char *to, const char *name)
198
219
  {
199
220
  if (git_buf_sets(out, to) < 0)
@@ -225,3 +246,21 @@ int git_refspec_transform_l(git_buf *out, const git_refspec *spec, const char *n
225
246
  return refspec_transform(out, spec->dst, spec->src, name);
226
247
  }
227
248
 
249
+ int git_refspec__serialize(git_buf *out, const git_refspec *refspec)
250
+ {
251
+ if (refspec->force)
252
+ git_buf_putc(out, '+');
253
+
254
+ git_buf_printf(out, "%s:%s",
255
+ refspec->src != NULL ? refspec->src : "",
256
+ refspec->dst != NULL ? refspec->dst : "");
257
+
258
+ return git_buf_oom(out) == false;
259
+ }
260
+
261
+ int git_refspec_is_wildcard(const git_refspec *spec)
262
+ {
263
+ assert(spec && spec->src);
264
+
265
+ return (spec->src[strlen(spec->src) - 1] == '*');
266
+ }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -51,4 +51,14 @@ int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *n
51
51
  */
52
52
  int git_refspec_transform_l(git_buf *out, const git_refspec *spec, const char *name);
53
53
 
54
+ int git_refspec__serialize(git_buf *out, const git_refspec *refspec);
55
+
56
+ /**
57
+ * Determines if a refspec is a wildcard refspec.
58
+ *
59
+ * @param spec the refspec
60
+ * @return 1 if the refspec is a wildcard, 0 otherwise
61
+ */
62
+ int git_refspec_is_wildcard(const git_refspec *spec);
63
+
54
64
  #endif
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -14,7 +14,8 @@
14
14
  #include "remote.h"
15
15
  #include "fetch.h"
16
16
  #include "refs.h"
17
- #include "pkt.h"
17
+ #include "refspec.h"
18
+ #include "fetchhead.h"
18
19
 
19
20
  #include <regex.h>
20
21
 
@@ -56,22 +57,38 @@ static int download_tags_value(git_remote *remote, git_config *cfg)
56
57
  return error;
57
58
  }
58
59
 
59
- int git_remote_new(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
60
+ static int ensure_remote_name_is_valid(const char *name)
61
+ {
62
+ int error = 0;
63
+
64
+ if (!git_remote_is_valid_name(name)) {
65
+ giterr_set(
66
+ GITERR_CONFIG,
67
+ "'%s' is not a valid remote name.", name);
68
+ error = GIT_EINVALIDSPEC;
69
+ }
70
+
71
+ return error;
72
+ }
73
+
74
+ static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
60
75
  {
61
76
  git_remote *remote;
77
+ git_buf fetchbuf = GIT_BUF_INIT;
78
+ int error = -1;
62
79
 
63
80
  /* name is optional */
64
81
  assert(out && repo && url);
65
82
 
66
- remote = git__malloc(sizeof(git_remote));
83
+ remote = git__calloc(1, sizeof(git_remote));
67
84
  GITERR_CHECK_ALLOC(remote);
68
85
 
69
- memset(remote, 0x0, sizeof(git_remote));
70
86
  remote->repo = repo;
71
87
  remote->check_cert = 1;
88
+ remote->update_fetchhead = 1;
72
89
 
73
90
  if (git_vector_init(&remote->refs, 32, NULL) < 0)
74
- return -1;
91
+ goto on_error;
75
92
 
76
93
  remote->url = git__strdup(url);
77
94
  GITERR_CHECK_ALLOC(remote->url);
@@ -92,13 +109,83 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *name, con
92
109
  }
93
110
 
94
111
  *out = remote;
112
+ git_buf_free(&fetchbuf);
113
+ return 0;
114
+
115
+ on_error:
116
+ git_remote_free(remote);
117
+ git_buf_free(&fetchbuf);
118
+ return error;
119
+ }
120
+
121
+ static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
122
+ {
123
+ int error;
124
+ git_remote *remote;
125
+
126
+ error = git_remote_load(&remote, repo, name);
127
+
128
+ if (error == GIT_ENOTFOUND)
129
+ return 0;
130
+
131
+ if (error < 0)
132
+ return error;
133
+
134
+ git_remote_free(remote);
135
+
136
+ giterr_set(
137
+ GITERR_CONFIG,
138
+ "Remote '%s' already exists.", name);
139
+
140
+ return GIT_EEXISTS;
141
+ }
142
+
143
+
144
+ int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
145
+ {
146
+ git_buf buf = GIT_BUF_INIT;
147
+ git_remote *remote = NULL;
148
+ int error;
149
+
150
+ if ((error = ensure_remote_name_is_valid(name)) < 0)
151
+ return error;
152
+
153
+ if ((error = ensure_remote_doesnot_exist(repo, name)) < 0)
154
+ return error;
155
+
156
+ if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
157
+ return -1;
158
+
159
+ if (create_internal(&remote, repo, name, url, git_buf_cstr(&buf)) < 0)
160
+ goto on_error;
161
+
162
+ git_buf_free(&buf);
163
+
164
+ if (git_remote_save(remote) < 0)
165
+ goto on_error;
166
+
167
+ *out = remote;
168
+
95
169
  return 0;
96
170
 
97
171
  on_error:
172
+ git_buf_free(&buf);
98
173
  git_remote_free(remote);
99
174
  return -1;
100
175
  }
101
176
 
177
+ int git_remote_create_inmemory(git_remote **out, git_repository *repo, const char *fetch, const char *url)
178
+ {
179
+ int error;
180
+ git_remote *remote;
181
+
182
+ if ((error = create_internal(&remote, repo, NULL, url, fetch)) < 0)
183
+ return error;
184
+
185
+ *out = remote;
186
+ return 0;
187
+ }
188
+
102
189
  int git_remote_load(git_remote **out, git_repository *repo, const char *name)
103
190
  {
104
191
  git_remote *remote;
@@ -109,6 +196,9 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
109
196
 
110
197
  assert(out && repo && name);
111
198
 
199
+ if ((error = ensure_remote_name_is_valid(name)) < 0)
200
+ return error;
201
+
112
202
  if (git_repository_config__weakptr(&config, repo) < 0)
113
203
  return -1;
114
204
 
@@ -117,6 +207,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
117
207
 
118
208
  memset(remote, 0x0, sizeof(git_remote));
119
209
  remote->check_cert = 1;
210
+ remote->update_fetchhead = 1;
120
211
  remote->name = git__strdup(name);
121
212
  GITERR_CHECK_ALLOC(remote->name);
122
213
 
@@ -132,6 +223,12 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
132
223
 
133
224
  if ((error = git_config_get_string(&val, config, git_buf_cstr(&buf))) < 0)
134
225
  goto cleanup;
226
+
227
+ if (strlen(val) == 0) {
228
+ giterr_set(GITERR_INVALID, "Malformed remote '%s' - missing URL", name);
229
+ error = -1;
230
+ goto cleanup;
231
+ }
135
232
 
136
233
  remote->repo = repo;
137
234
  remote->url = git__strdup(val);
@@ -144,8 +241,10 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
144
241
  }
145
242
 
146
243
  error = git_config_get_string(&val, config, git_buf_cstr(&buf));
147
- if (error == GIT_ENOTFOUND)
244
+ if (error == GIT_ENOTFOUND) {
245
+ val = NULL;
148
246
  error = 0;
247
+ }
149
248
 
150
249
  if (error < 0) {
151
250
  error = -1;
@@ -201,12 +300,56 @@ cleanup:
201
300
  return error;
202
301
  }
203
302
 
303
+ static int update_config_refspec(
304
+ git_config *config,
305
+ const char *remote_name,
306
+ const git_refspec *refspec,
307
+ int git_direction)
308
+ {
309
+ git_buf name = GIT_BUF_INIT, value = GIT_BUF_INIT;
310
+ int error = -1;
311
+
312
+ if (refspec->src == NULL || refspec->dst == NULL)
313
+ return 0;
314
+
315
+ if (git_buf_printf(
316
+ &name,
317
+ "remote.%s.%s",
318
+ remote_name,
319
+ git_direction == GIT_DIRECTION_FETCH ? "fetch" : "push") < 0)
320
+ goto cleanup;
321
+
322
+ if (git_refspec__serialize(&value, refspec) < 0)
323
+ goto cleanup;
324
+
325
+ error = git_config_set_string(
326
+ config,
327
+ git_buf_cstr(&name),
328
+ git_buf_cstr(&value));
329
+
330
+ cleanup:
331
+ git_buf_free(&name);
332
+ git_buf_free(&value);
333
+
334
+ return error;
335
+ }
336
+
204
337
  int git_remote_save(const git_remote *remote)
205
338
  {
206
339
  int error;
207
340
  git_config *config;
208
341
  const char *tagopt = NULL;
209
- git_buf buf = GIT_BUF_INIT, value = GIT_BUF_INIT;
342
+ git_buf buf = GIT_BUF_INIT;
343
+
344
+ assert(remote);
345
+
346
+ if (!remote->name) {
347
+ giterr_set(GITERR_INVALID, "Can't save an in-memory remote.");
348
+ return GIT_EINVALIDSPEC;
349
+ }
350
+
351
+ if ((error = ensure_remote_name_is_valid(remote->name)) < 0)
352
+ return error;
210
353
 
211
354
  if (git_repository_config__weakptr(&config, remote->repo) < 0)
212
355
  return -1;
@@ -229,9 +372,10 @@ int git_remote_save(const git_remote *remote)
229
372
  return -1;
230
373
  }
231
374
  } else {
232
- int error = git_config_delete(config, git_buf_cstr(&buf));
375
+ int error = git_config_delete_entry(config, git_buf_cstr(&buf));
233
376
  if (error == GIT_ENOTFOUND) {
234
377
  error = 0;
378
+ giterr_clear();
235
379
  }
236
380
  if (error < 0) {
237
381
  git_buf_free(&buf);
@@ -239,33 +383,19 @@ int git_remote_save(const git_remote *remote)
239
383
  }
240
384
  }
241
385
 
242
- if (remote->fetch.src != NULL && remote->fetch.dst != NULL) {
243
- git_buf_clear(&buf);
244
- git_buf_clear(&value);
245
- git_buf_printf(&buf, "remote.%s.fetch", remote->name);
246
- if (remote->fetch.force)
247
- git_buf_putc(&value, '+');
248
- git_buf_printf(&value, "%s:%s", remote->fetch.src, remote->fetch.dst);
249
- if (git_buf_oom(&buf) || git_buf_oom(&value))
250
- return -1;
251
-
252
- if (git_config_set_string(config, git_buf_cstr(&buf), git_buf_cstr(&value)) < 0)
386
+ if (update_config_refspec(
387
+ config,
388
+ remote->name,
389
+ &remote->fetch,
390
+ GIT_DIRECTION_FETCH) < 0)
253
391
  goto on_error;
254
- }
255
392
 
256
- if (remote->push.src != NULL && remote->push.dst != NULL) {
257
- git_buf_clear(&buf);
258
- git_buf_clear(&value);
259
- git_buf_printf(&buf, "remote.%s.push", remote->name);
260
- if (remote->push.force)
261
- git_buf_putc(&value, '+');
262
- git_buf_printf(&value, "%s:%s", remote->push.src, remote->push.dst);
263
- if (git_buf_oom(&buf) || git_buf_oom(&value))
264
- return -1;
265
-
266
- if (git_config_set_string(config, git_buf_cstr(&buf), git_buf_cstr(&value)) < 0)
393
+ if (update_config_refspec(
394
+ config,
395
+ remote->name,
396
+ &remote->push,
397
+ GIT_DIRECTION_PUSH) < 0)
267
398
  goto on_error;
268
- }
269
399
 
270
400
  /*
271
401
  * What action to take depends on the old and new values. This
@@ -295,28 +425,26 @@ int git_remote_save(const git_remote *remote)
295
425
  if (git_config_set_string(config, git_buf_cstr(&buf), "--no-tags") < 0)
296
426
  goto on_error;
297
427
  } else if (tagopt) {
298
- if (git_config_delete(config, git_buf_cstr(&buf)) < 0)
428
+ if (git_config_delete_entry(config, git_buf_cstr(&buf)) < 0)
299
429
  goto on_error;
300
430
  }
301
431
 
302
432
  git_buf_free(&buf);
303
- git_buf_free(&value);
304
433
 
305
434
  return 0;
306
435
 
307
436
  on_error:
308
437
  git_buf_free(&buf);
309
- git_buf_free(&value);
310
438
  return -1;
311
439
  }
312
440
 
313
- const char *git_remote_name(git_remote *remote)
441
+ const char *git_remote_name(const git_remote *remote)
314
442
  {
315
443
  assert(remote);
316
444
  return remote->name;
317
445
  }
318
446
 
319
- const char *git_remote_url(git_remote *remote)
447
+ const char *git_remote_url(const git_remote *remote)
320
448
  {
321
449
  assert(remote);
322
450
  return remote->url;
@@ -334,7 +462,7 @@ int git_remote_set_url(git_remote *remote, const char* url)
334
462
  return 0;
335
463
  }
336
464
 
337
- const char *git_remote_pushurl(git_remote *remote)
465
+ const char *git_remote_pushurl(const git_remote *remote)
338
466
  {
339
467
  assert(remote);
340
468
  return remote->pushurl;
@@ -364,13 +492,12 @@ int git_remote_set_fetchspec(git_remote *remote, const char *spec)
364
492
  return -1;
365
493
 
366
494
  git_refspec__free(&remote->fetch);
367
- remote->fetch.src = refspec.src;
368
- remote->fetch.dst = refspec.dst;
495
+ memcpy(&remote->fetch, &refspec, sizeof(git_refspec));
369
496
 
370
497
  return 0;
371
498
  }
372
499
 
373
- const git_refspec *git_remote_fetchspec(git_remote *remote)
500
+ const git_refspec *git_remote_fetchspec(const git_remote *remote)
374
501
  {
375
502
  assert(remote);
376
503
  return &remote->fetch;
@@ -392,7 +519,7 @@ int git_remote_set_pushspec(git_remote *remote, const char *spec)
392
519
  return 0;
393
520
  }
394
521
 
395
- const git_refspec *git_remote_pushspec(git_remote *remote)
522
+ const git_refspec *git_remote_pushspec(const git_remote *remote)
396
523
  {
397
524
  assert(remote);
398
525
  return &remote->push;
@@ -402,38 +529,45 @@ const char* git_remote__urlfordirection(git_remote *remote, int direction)
402
529
  {
403
530
  assert(remote);
404
531
 
405
- if (direction == GIT_DIR_FETCH) {
532
+ if (direction == GIT_DIRECTION_FETCH) {
406
533
  return remote->url;
407
534
  }
408
535
 
409
- if (direction == GIT_DIR_PUSH) {
536
+ if (direction == GIT_DIRECTION_PUSH) {
410
537
  return remote->pushurl ? remote->pushurl : remote->url;
411
538
  }
412
539
 
413
540
  return NULL;
414
541
  }
415
542
 
416
- int git_remote_connect(git_remote *remote, int direction)
543
+ int git_remote_connect(git_remote *remote, git_direction direction)
417
544
  {
418
545
  git_transport *t;
419
546
  const char *url;
547
+ int flags = GIT_TRANSPORTFLAGS_NONE;
420
548
 
421
549
  assert(remote);
422
550
 
551
+ t = remote->transport;
552
+
423
553
  url = git_remote__urlfordirection(remote, direction);
424
554
  if (url == NULL )
425
555
  return -1;
426
556
 
427
- if (git_transport_new(&t, url) < 0)
557
+ /* A transport could have been supplied in advance with
558
+ * git_remote_set_transport */
559
+ if (!t && git_transport_new(&t, remote, url) < 0)
428
560
  return -1;
429
561
 
430
- t->progress_cb = remote->callbacks.progress;
431
- t->cb_data = remote->callbacks.data;
562
+ if (t->set_callbacks &&
563
+ t->set_callbacks(t, remote->callbacks.progress, NULL, remote->callbacks.payload) < 0)
564
+ goto on_error;
565
+
566
+ if (!remote->check_cert)
567
+ flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT;
432
568
 
433
- t->check_cert = remote->check_cert;
434
- if (t->connect(t, direction) < 0) {
569
+ if (t->connect(t, url, remote->cred_acquire_cb, remote->cred_acquire_payload, direction, flags) < 0)
435
570
  goto on_error;
436
- }
437
571
 
438
572
  remote->transport = t;
439
573
 
@@ -441,47 +575,215 @@ int git_remote_connect(git_remote *remote, int direction)
441
575
 
442
576
  on_error:
443
577
  t->free(t);
578
+
579
+ if (t == remote->transport)
580
+ remote->transport = NULL;
581
+
444
582
  return -1;
445
583
  }
446
584
 
447
585
  int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload)
448
586
  {
449
- git_vector *refs = &remote->transport->refs;
450
- unsigned int i;
451
- git_pkt *p = NULL;
587
+ assert(remote);
588
+
589
+ return remote->transport->ls(remote->transport, list_cb, payload);
590
+ }
591
+
592
+ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
593
+ {
594
+ git_config *cfg;
595
+ const char *val;
452
596
 
453
597
  assert(remote);
454
598
 
455
- if (!remote->transport || !remote->transport->connected) {
456
- giterr_set(GITERR_NET, "The remote is not connected");
599
+ if (!proxy_url || !remote->repo)
457
600
  return -1;
458
- }
459
601
 
460
- git_vector_foreach(refs, i, p) {
461
- git_pkt_ref *pkt = NULL;
602
+ *proxy_url = NULL;
462
603
 
463
- if (p->type != GIT_PKT_REF)
464
- continue;
604
+ if (git_repository_config__weakptr(&cfg, remote->repo) < 0)
605
+ return -1;
606
+
607
+ /* Go through the possible sources for proxy configuration, from most specific
608
+ * to least specific. */
609
+
610
+ /* remote.<name>.proxy config setting */
611
+ if (remote->name && 0 != *(remote->name)) {
612
+ git_buf buf = GIT_BUF_INIT;
613
+
614
+ if (git_buf_printf(&buf, "remote.%s.proxy", remote->name) < 0)
615
+ return -1;
465
616
 
466
- pkt = (git_pkt_ref *)p;
617
+ if (!git_config_get_string(&val, cfg, git_buf_cstr(&buf)) &&
618
+ val && ('\0' != *val)) {
619
+ git_buf_free(&buf);
620
+
621
+ *proxy_url = git__strdup(val);
622
+ GITERR_CHECK_ALLOC(*proxy_url);
623
+ return 0;
624
+ }
467
625
 
468
- if (list_cb(&pkt->head, payload))
469
- return GIT_EUSER;
626
+ git_buf_free(&buf);
627
+ }
628
+
629
+ /* http.proxy config setting */
630
+ if (!git_config_get_string(&val, cfg, "http.proxy") &&
631
+ val && ('\0' != *val)) {
632
+ *proxy_url = git__strdup(val);
633
+ GITERR_CHECK_ALLOC(*proxy_url);
634
+ return 0;
635
+ }
636
+
637
+ /* HTTP_PROXY / HTTPS_PROXY environment variables */
638
+ val = use_ssl ? getenv("HTTPS_PROXY") : getenv("HTTP_PROXY");
639
+
640
+ if (val && ('\0' != *val)) {
641
+ *proxy_url = git__strdup(val);
642
+ GITERR_CHECK_ALLOC(*proxy_url);
643
+ return 0;
470
644
  }
471
645
 
472
646
  return 0;
473
647
  }
474
648
 
475
- int git_remote_download(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats)
649
+ int git_remote_download(
650
+ git_remote *remote,
651
+ git_transfer_progress_callback progress_cb,
652
+ void *progress_payload)
476
653
  {
477
654
  int error;
478
655
 
479
- assert(remote && bytes && stats);
656
+ assert(remote);
480
657
 
481
658
  if ((error = git_fetch_negotiate(remote)) < 0)
482
659
  return error;
483
660
 
484
- return git_fetch_download_pack(remote, bytes, stats);
661
+ return git_fetch_download_pack(remote, progress_cb, progress_payload);
662
+ }
663
+
664
+ static int update_tips_callback(git_remote_head *head, void *payload)
665
+ {
666
+ git_vector *refs = (git_vector *)payload;
667
+
668
+ return git_vector_insert(refs, head);
669
+ }
670
+
671
+ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src)
672
+ {
673
+ unsigned int i;
674
+ git_remote_head *remote_ref;
675
+
676
+ assert(update_heads && fetchspec_src);
677
+
678
+ *out = NULL;
679
+
680
+ git_vector_foreach(update_heads, i, remote_ref) {
681
+ if (strcmp(remote_ref->name, fetchspec_src) == 0) {
682
+ *out = remote_ref;
683
+ break;
684
+ }
685
+ }
686
+
687
+ return 0;
688
+ }
689
+
690
+ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_vector *update_heads, git_reference *ref)
691
+ {
692
+ git_reference *resolved_ref = NULL;
693
+ git_reference *tracking_ref = NULL;
694
+ git_buf remote_name = GIT_BUF_INIT;
695
+ int error = 0;
696
+
697
+ assert(out && remote && ref);
698
+
699
+ *out = NULL;
700
+
701
+ if ((error = git_reference_resolve(&resolved_ref, ref)) < 0 ||
702
+ (!git_reference_is_branch(resolved_ref)) ||
703
+ (error = git_branch_upstream(&tracking_ref, resolved_ref)) < 0 ||
704
+ (error = git_refspec_transform_l(&remote_name, &remote->fetch, git_reference_name(tracking_ref))) < 0) {
705
+ /* Not an error if HEAD is orphaned or no tracking branch */
706
+ if (error == GIT_ENOTFOUND)
707
+ error = 0;
708
+
709
+ goto cleanup;
710
+ }
711
+
712
+ error = remote_head_for_fetchspec_src(out, update_heads, git_buf_cstr(&remote_name));
713
+
714
+ cleanup:
715
+ git_reference_free(tracking_ref);
716
+ git_reference_free(resolved_ref);
717
+ git_buf_free(&remote_name);
718
+ return error;
719
+ }
720
+
721
+ static int git_remote_write_fetchhead(git_remote *remote, git_vector *update_heads)
722
+ {
723
+ struct git_refspec *spec;
724
+ git_reference *head_ref = NULL;
725
+ git_fetchhead_ref *fetchhead_ref;
726
+ git_remote_head *remote_ref, *merge_remote_ref;
727
+ git_vector fetchhead_refs;
728
+ bool include_all_fetchheads;
729
+ unsigned int i = 0;
730
+ int error = 0;
731
+
732
+ assert(remote);
733
+
734
+ /* no heads, nothing to do */
735
+ if (update_heads->length == 0)
736
+ return 0;
737
+
738
+ spec = &remote->fetch;
739
+
740
+ if (git_vector_init(&fetchhead_refs, update_heads->length, git_fetchhead_ref_cmp) < 0)
741
+ return -1;
742
+
743
+ /* Iff refspec is * (but not subdir slash star), include tags */
744
+ include_all_fetchheads = (strcmp(GIT_REFS_HEADS_DIR "*", git_refspec_src(spec)) == 0);
745
+
746
+ /* Determine what to merge: if refspec was a wildcard, just use HEAD */
747
+ if (git_refspec_is_wildcard(spec)) {
748
+ if ((error = git_reference_lookup(&head_ref, remote->repo, GIT_HEAD_FILE)) < 0 ||
749
+ (error = remote_head_for_ref(&merge_remote_ref, remote, update_heads, head_ref)) < 0)
750
+ goto cleanup;
751
+ } else {
752
+ /* If we're fetching a single refspec, that's the only thing that should be in FETCH_HEAD. */
753
+ if ((error = remote_head_for_fetchspec_src(&merge_remote_ref, update_heads, git_refspec_src(spec))) < 0)
754
+ goto cleanup;
755
+ }
756
+
757
+ /* Create the FETCH_HEAD file */
758
+ git_vector_foreach(update_heads, i, remote_ref) {
759
+ int merge_this_fetchhead = (merge_remote_ref == remote_ref);
760
+
761
+ if (!include_all_fetchheads &&
762
+ !git_refspec_src_matches(spec, remote_ref->name) &&
763
+ !merge_this_fetchhead)
764
+ continue;
765
+
766
+ if (git_fetchhead_ref_create(&fetchhead_ref,
767
+ &remote_ref->oid,
768
+ merge_this_fetchhead,
769
+ remote_ref->name,
770
+ git_remote_url(remote)) < 0)
771
+ goto cleanup;
772
+
773
+ if (git_vector_insert(&fetchhead_refs, fetchhead_ref) < 0)
774
+ goto cleanup;
775
+ }
776
+
777
+ git_fetchhead_write(remote->repo, &fetchhead_refs);
778
+
779
+ cleanup:
780
+ for (i = 0; i < fetchhead_refs.length; ++i)
781
+ git_fetchhead_ref_free(fetchhead_refs.contents[i]);
782
+
783
+ git_vector_free(&fetchhead_refs);
784
+ git_reference_free(head_ref);
785
+
786
+ return error;
485
787
  }
486
788
 
487
789
  int git_remote_update_tips(git_remote *remote)
@@ -490,48 +792,48 @@ int git_remote_update_tips(git_remote *remote)
490
792
  unsigned int i = 0;
491
793
  git_buf refname = GIT_BUF_INIT;
492
794
  git_oid old;
493
- git_pkt *pkt;
494
795
  git_odb *odb;
495
- git_vector *refs;
496
796
  git_remote_head *head;
497
797
  git_reference *ref;
498
798
  struct git_refspec *spec;
499
799
  git_refspec tagspec;
800
+ git_vector refs, update_heads;
500
801
 
501
802
  assert(remote);
502
803
 
503
- refs = &remote->transport->refs;
504
804
  spec = &remote->fetch;
505
-
506
- if (refs->length == 0)
507
- return 0;
508
-
805
+
509
806
  if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
510
807
  return -1;
511
808
 
512
809
  if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
513
810
  return -1;
514
811
 
515
- /* HEAD is only allowed to be the first in the list */
516
- pkt = refs->contents[0];
517
- head = &((git_pkt_ref *)pkt)->head;
518
- if (!strcmp(head->name, GIT_HEAD_FILE)) {
519
- if (git_reference_create_oid(&ref, remote->repo, GIT_FETCH_HEAD_FILE, &head->oid, 1) < 0)
520
- return -1;
812
+ /* Make a copy of the transport's refs */
813
+ if (git_vector_init(&refs, 16, NULL) < 0 ||
814
+ git_vector_init(&update_heads, 16, NULL) < 0)
815
+ return -1;
521
816
 
522
- i = 1;
523
- git_reference_free(ref);
817
+ if (git_remote_ls(remote, update_tips_callback, &refs) < 0)
818
+ goto on_error;
819
+
820
+ /* Let's go find HEAD, if it exists. Check only the first ref in the vector. */
821
+ if (refs.length > 0) {
822
+ head = (git_remote_head *)refs.contents[0];
823
+
824
+ if (!strcmp(head->name, GIT_HEAD_FILE)) {
825
+ if (git_reference_create(&ref, remote->repo, GIT_FETCH_HEAD_FILE, &head->oid, 1) < 0)
826
+ goto on_error;
827
+
828
+ i = 1;
829
+ git_reference_free(ref);
830
+ }
524
831
  }
525
832
 
526
- for (; i < refs->length; ++i) {
527
- git_pkt *pkt = refs->contents[i];
833
+ for (; i < refs.length; ++i) {
834
+ head = (git_remote_head *)refs.contents[i];
528
835
  autotag = 0;
529
836
 
530
- if (pkt->type == GIT_PKT_REF)
531
- head = &((git_pkt_ref *)pkt)->head;
532
- else
533
- continue;
534
-
535
837
  /* Ignore malformed ref names (which also saves us from tag^{} */
536
838
  if (!git_reference_is_valid_name(head->name))
537
839
  continue;
@@ -557,7 +859,10 @@ int git_remote_update_tips(git_remote *remote)
557
859
  if (autotag && !git_odb_exists(odb, &head->oid))
558
860
  continue;
559
861
 
560
- error = git_reference_name_to_oid(&old, remote->repo, refname.ptr);
862
+ if (git_vector_insert(&update_heads, head) < 0)
863
+ goto on_error;
864
+
865
+ error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
561
866
  if (error < 0 && error != GIT_ENOTFOUND)
562
867
  goto on_error;
563
868
 
@@ -568,23 +873,31 @@ int git_remote_update_tips(git_remote *remote)
568
873
  continue;
569
874
 
570
875
  /* In autotag mode, don't overwrite any locally-existing tags */
571
- error = git_reference_create_oid(&ref, remote->repo, refname.ptr, &head->oid, !autotag);
876
+ error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag);
572
877
  if (error < 0 && error != GIT_EEXISTS)
573
878
  goto on_error;
574
879
 
575
880
  git_reference_free(ref);
576
881
 
577
882
  if (remote->callbacks.update_tips != NULL) {
578
- if (remote->callbacks.update_tips(refname.ptr, &old, &head->oid, remote->callbacks.data) < 0)
883
+ if (remote->callbacks.update_tips(refname.ptr, &old, &head->oid, remote->callbacks.payload) < 0)
579
884
  goto on_error;
580
885
  }
581
886
  }
582
887
 
888
+ if (git_remote_update_fetchhead(remote) &&
889
+ (error = git_remote_write_fetchhead(remote, &update_heads)) < 0)
890
+ goto on_error;
891
+
892
+ git_vector_free(&refs);
893
+ git_vector_free(&update_heads);
583
894
  git_refspec__free(&tagspec);
584
895
  git_buf_free(&refname);
585
896
  return 0;
586
897
 
587
898
  on_error:
899
+ git_vector_free(&refs);
900
+ git_vector_free(&update_heads);
588
901
  git_refspec__free(&tagspec);
589
902
  git_buf_free(&refname);
590
903
  return -1;
@@ -594,20 +907,28 @@ on_error:
594
907
  int git_remote_connected(git_remote *remote)
595
908
  {
596
909
  assert(remote);
597
- return remote->transport == NULL ? 0 : remote->transport->connected;
910
+
911
+ if (!remote->transport || !remote->transport->is_connected)
912
+ return 0;
913
+
914
+ /* Ask the transport if it's connected. */
915
+ return remote->transport->is_connected(remote->transport);
598
916
  }
599
917
 
600
918
  void git_remote_stop(git_remote *remote)
601
919
  {
602
- git_atomic_set(&remote->transport->cancel, 1);
920
+ assert(remote);
921
+
922
+ if (remote->transport && remote->transport->cancel)
923
+ remote->transport->cancel(remote->transport);
603
924
  }
604
925
 
605
926
  void git_remote_disconnect(git_remote *remote)
606
927
  {
607
928
  assert(remote);
608
929
 
609
- if (remote->transport != NULL && remote->transport->connected)
610
- remote->transport->close(remote->transport);
930
+ if (git_remote_connected(remote))
931
+ remote->transport->close(remote->transport);
611
932
  }
612
933
 
613
934
  void git_remote_free(git_remote *remote)
@@ -700,54 +1021,371 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
700
1021
  return 0;
701
1022
  }
702
1023
 
703
- int git_remote_add(git_remote **out, git_repository *repo, const char *name, const char *url)
1024
+ void git_remote_check_cert(git_remote *remote, int check)
704
1025
  {
705
- git_buf buf = GIT_BUF_INIT;
1026
+ assert(remote);
706
1027
 
707
- if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
708
- return -1;
1028
+ remote->check_cert = check;
1029
+ }
709
1030
 
710
- if (git_remote_new(out, repo, name, url, git_buf_cstr(&buf)) < 0)
711
- goto on_error;
1031
+ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks)
1032
+ {
1033
+ assert(remote && callbacks);
712
1034
 
713
- git_buf_free(&buf);
1035
+ GITERR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
714
1036
 
715
- if (git_remote_save(*out) < 0)
716
- goto on_error;
1037
+ memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks));
717
1038
 
718
- return 0;
1039
+ if (remote->transport && remote->transport->set_callbacks)
1040
+ remote->transport->set_callbacks(remote->transport,
1041
+ remote->callbacks.progress,
1042
+ NULL,
1043
+ remote->callbacks.payload);
719
1044
 
720
- on_error:
721
- git_buf_free(&buf);
722
- git_remote_free(*out);
723
- return -1;
1045
+ return 0;
724
1046
  }
725
1047
 
726
- void git_remote_check_cert(git_remote *remote, int check)
1048
+ void git_remote_set_cred_acquire_cb(
1049
+ git_remote *remote,
1050
+ git_cred_acquire_cb cred_acquire_cb,
1051
+ void *payload)
727
1052
  {
728
1053
  assert(remote);
729
1054
 
730
- remote->check_cert = check;
1055
+ remote->cred_acquire_cb = cred_acquire_cb;
1056
+ remote->cred_acquire_payload = payload;
731
1057
  }
732
1058
 
733
- void git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks)
1059
+ int git_remote_set_transport(git_remote *remote, git_transport *transport)
734
1060
  {
735
- assert(remote && callbacks);
1061
+ assert(remote && transport);
736
1062
 
737
- memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks));
1063
+ GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport");
738
1064
 
739
1065
  if (remote->transport) {
740
- remote->transport->progress_cb = remote->callbacks.progress;
741
- remote->transport->cb_data = remote->callbacks.data;
1066
+ giterr_set(GITERR_NET, "A transport is already bound to this remote");
1067
+ return -1;
742
1068
  }
1069
+
1070
+ remote->transport = transport;
1071
+ return 0;
1072
+ }
1073
+
1074
+ const git_transfer_progress* git_remote_stats(git_remote *remote)
1075
+ {
1076
+ assert(remote);
1077
+ return &remote->stats;
743
1078
  }
744
1079
 
745
- int git_remote_autotag(git_remote *remote)
1080
+ git_remote_autotag_option_t git_remote_autotag(git_remote *remote)
746
1081
  {
747
1082
  return remote->download_tags;
748
1083
  }
749
1084
 
750
- void git_remote_set_autotag(git_remote *remote, int value)
1085
+ void git_remote_set_autotag(git_remote *remote, git_remote_autotag_option_t value)
751
1086
  {
752
1087
  remote->download_tags = value;
753
1088
  }
1089
+
1090
+ static int rename_remote_config_section(
1091
+ git_repository *repo,
1092
+ const char *old_name,
1093
+ const char *new_name)
1094
+ {
1095
+ git_buf old_section_name = GIT_BUF_INIT,
1096
+ new_section_name = GIT_BUF_INIT;
1097
+ int error = -1;
1098
+
1099
+ if (git_buf_printf(&old_section_name, "remote.%s", old_name) < 0)
1100
+ goto cleanup;
1101
+
1102
+ if (git_buf_printf(&new_section_name, "remote.%s", new_name) < 0)
1103
+ goto cleanup;
1104
+
1105
+ error = git_config_rename_section(
1106
+ repo,
1107
+ git_buf_cstr(&old_section_name),
1108
+ git_buf_cstr(&new_section_name));
1109
+
1110
+ cleanup:
1111
+ git_buf_free(&old_section_name);
1112
+ git_buf_free(&new_section_name);
1113
+
1114
+ return error;
1115
+ }
1116
+
1117
+ struct update_data
1118
+ {
1119
+ git_config *config;
1120
+ const char *old_remote_name;
1121
+ const char *new_remote_name;
1122
+ };
1123
+
1124
+ static int update_config_entries_cb(
1125
+ const git_config_entry *entry,
1126
+ void *payload)
1127
+ {
1128
+ struct update_data *data = (struct update_data *)payload;
1129
+
1130
+ if (strcmp(entry->value, data->old_remote_name))
1131
+ return 0;
1132
+
1133
+ return git_config_set_string(
1134
+ data->config,
1135
+ entry->name,
1136
+ data->new_remote_name);
1137
+ }
1138
+
1139
+ static int update_branch_remote_config_entry(
1140
+ git_repository *repo,
1141
+ const char *old_name,
1142
+ const char *new_name)
1143
+ {
1144
+ git_config *config;
1145
+ struct update_data data;
1146
+
1147
+ if (git_repository_config__weakptr(&config, repo) < 0)
1148
+ return -1;
1149
+
1150
+ data.config = config;
1151
+ data.old_remote_name = old_name;
1152
+ data.new_remote_name = new_name;
1153
+
1154
+ return git_config_foreach_match(
1155
+ config,
1156
+ "branch\\..+\\.remote",
1157
+ update_config_entries_cb, &data);
1158
+ }
1159
+
1160
+ static int rename_cb(const char *ref, void *data)
1161
+ {
1162
+ if (git__prefixcmp(ref, GIT_REFS_REMOTES_DIR))
1163
+ return 0;
1164
+
1165
+ return git_vector_insert((git_vector *)data, git__strdup(ref));
1166
+ }
1167
+
1168
+ static int rename_one_remote_reference(
1169
+ git_repository *repo,
1170
+ const char *reference_name,
1171
+ const char *old_remote_name,
1172
+ const char *new_remote_name)
1173
+ {
1174
+ int error = -1;
1175
+ git_buf new_name = GIT_BUF_INIT;
1176
+ git_reference *reference = NULL;
1177
+ git_reference *newref = NULL;
1178
+
1179
+ if (git_buf_printf(
1180
+ &new_name,
1181
+ GIT_REFS_REMOTES_DIR "%s%s",
1182
+ new_remote_name,
1183
+ reference_name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name)) < 0)
1184
+ return -1;
1185
+
1186
+ if (git_reference_lookup(&reference, repo, reference_name) < 0)
1187
+ goto cleanup;
1188
+
1189
+ error = git_reference_rename(&newref, reference, git_buf_cstr(&new_name), 0);
1190
+ git_reference_free(reference);
1191
+
1192
+ cleanup:
1193
+ git_reference_free(newref);
1194
+ git_buf_free(&new_name);
1195
+ return error;
1196
+ }
1197
+
1198
+ static int rename_remote_references(
1199
+ git_repository *repo,
1200
+ const char *old_name,
1201
+ const char *new_name)
1202
+ {
1203
+ git_vector refnames;
1204
+ int error = -1;
1205
+ unsigned int i;
1206
+ char *name;
1207
+
1208
+ if (git_vector_init(&refnames, 8, NULL) < 0)
1209
+ goto cleanup;
1210
+
1211
+ if (git_reference_foreach(
1212
+ repo,
1213
+ GIT_REF_LISTALL,
1214
+ rename_cb,
1215
+ &refnames) < 0)
1216
+ goto cleanup;
1217
+
1218
+ git_vector_foreach(&refnames, i, name) {
1219
+ if ((error = rename_one_remote_reference(repo, name, old_name, new_name)) < 0)
1220
+ goto cleanup;
1221
+ }
1222
+
1223
+ error = 0;
1224
+ cleanup:
1225
+ git_vector_foreach(&refnames, i, name) {
1226
+ git__free(name);
1227
+ }
1228
+
1229
+ git_vector_free(&refnames);
1230
+ return error;
1231
+ }
1232
+
1233
+ static int rename_fetch_refspecs(
1234
+ git_remote *remote,
1235
+ const char *new_name,
1236
+ int (*callback)(const char *problematic_refspec, void *payload),
1237
+ void *payload)
1238
+ {
1239
+ git_config *config;
1240
+ const git_refspec *fetch_refspec;
1241
+ git_buf dst_prefix = GIT_BUF_INIT, serialized = GIT_BUF_INIT;
1242
+ const char* pos;
1243
+ int error = -1;
1244
+
1245
+ fetch_refspec = git_remote_fetchspec(remote);
1246
+
1247
+ /* Is there a refspec to deal with? */
1248
+ if (fetch_refspec->src == NULL &&
1249
+ fetch_refspec->dst == NULL)
1250
+ return 0;
1251
+
1252
+ if (git_refspec__serialize(&serialized, fetch_refspec) < 0)
1253
+ goto cleanup;
1254
+
1255
+ /* Is it an in-memory remote? */
1256
+ if (!remote->name) {
1257
+ error = (callback(git_buf_cstr(&serialized), payload) < 0) ? GIT_EUSER : 0;
1258
+ goto cleanup;
1259
+ }
1260
+
1261
+ if (git_buf_printf(&dst_prefix, ":refs/remotes/%s/", remote->name) < 0)
1262
+ goto cleanup;
1263
+
1264
+ pos = strstr(git_buf_cstr(&serialized), git_buf_cstr(&dst_prefix));
1265
+
1266
+ /* Does the dst part of the refspec follow the extected standard format? */
1267
+ if (!pos) {
1268
+ error = (callback(git_buf_cstr(&serialized), payload) < 0) ? GIT_EUSER : 0;
1269
+ goto cleanup;
1270
+ }
1271
+
1272
+ if (git_buf_splice(
1273
+ &serialized,
1274
+ pos - git_buf_cstr(&serialized) + strlen(":refs/remotes/"),
1275
+ strlen(remote->name), new_name,
1276
+ strlen(new_name)) < 0)
1277
+ goto cleanup;
1278
+
1279
+ git_refspec__free(&remote->fetch);
1280
+
1281
+ if (git_refspec__parse(&remote->fetch, git_buf_cstr(&serialized), true) < 0)
1282
+ goto cleanup;
1283
+
1284
+ if (git_repository_config__weakptr(&config, remote->repo) < 0)
1285
+ goto cleanup;
1286
+
1287
+ error = update_config_refspec(config, new_name, &remote->fetch, GIT_DIRECTION_FETCH);
1288
+
1289
+ cleanup:
1290
+ git_buf_free(&serialized);
1291
+ git_buf_free(&dst_prefix);
1292
+ return error;
1293
+ }
1294
+
1295
+ int git_remote_rename(
1296
+ git_remote *remote,
1297
+ const char *new_name,
1298
+ git_remote_rename_problem_cb callback,
1299
+ void *payload)
1300
+ {
1301
+ int error;
1302
+
1303
+ assert(remote && new_name);
1304
+
1305
+ if (!remote->name) {
1306
+ giterr_set(GITERR_INVALID, "Can't rename an in-memory remote.");
1307
+ return GIT_EINVALIDSPEC;
1308
+ }
1309
+
1310
+ if ((error = ensure_remote_name_is_valid(new_name)) < 0)
1311
+ return error;
1312
+
1313
+ if (remote->repo) {
1314
+ if ((error = ensure_remote_doesnot_exist(remote->repo, new_name)) < 0)
1315
+ return error;
1316
+
1317
+ if (!remote->name) {
1318
+ if ((error = rename_fetch_refspecs(
1319
+ remote,
1320
+ new_name,
1321
+ callback,
1322
+ payload)) < 0)
1323
+ return error;
1324
+
1325
+ remote->name = git__strdup(new_name);
1326
+
1327
+ if (!remote->name) return 0;
1328
+ return git_remote_save(remote);
1329
+ }
1330
+
1331
+ if ((error = rename_remote_config_section(
1332
+ remote->repo,
1333
+ remote->name,
1334
+ new_name)) < 0)
1335
+ return error;
1336
+
1337
+ if ((error = update_branch_remote_config_entry(
1338
+ remote->repo,
1339
+ remote->name,
1340
+ new_name)) < 0)
1341
+ return error;
1342
+
1343
+ if ((error = rename_remote_references(
1344
+ remote->repo,
1345
+ remote->name,
1346
+ new_name)) < 0)
1347
+ return error;
1348
+
1349
+ if ((error = rename_fetch_refspecs(
1350
+ remote,
1351
+ new_name,
1352
+ callback,
1353
+ payload)) < 0)
1354
+ return error;
1355
+ }
1356
+
1357
+ git__free(remote->name);
1358
+ remote->name = git__strdup(new_name);
1359
+
1360
+ return 0;
1361
+ }
1362
+
1363
+ int git_remote_update_fetchhead(git_remote *remote)
1364
+ {
1365
+ return remote->update_fetchhead;
1366
+ }
1367
+
1368
+ void git_remote_set_update_fetchhead(git_remote *remote, int value)
1369
+ {
1370
+ remote->update_fetchhead = value;
1371
+ }
1372
+
1373
+ int git_remote_is_valid_name(
1374
+ const char *remote_name)
1375
+ {
1376
+ git_buf buf = GIT_BUF_INIT;
1377
+ git_refspec refspec;
1378
+ int error = -1;
1379
+
1380
+ if (!remote_name || *remote_name == '\0')
1381
+ return 0;
1382
+
1383
+ git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name);
1384
+ error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
1385
+
1386
+ git_buf_free(&buf);
1387
+ git_refspec__free(&refspec);
1388
+
1389
+ giterr_clear();
1390
+ return error == 0;
1391
+ }