rugged 0.16.0 → 0.17.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (392) hide show
  1. data/README.md +373 -243
  2. data/Rakefile +22 -0
  3. data/ext/rugged/extconf.rb +9 -6
  4. data/ext/rugged/rugged.c +123 -31
  5. data/ext/rugged/rugged.h +11 -10
  6. data/ext/rugged/rugged_blob.c +181 -18
  7. data/ext/rugged/rugged_commit.c +196 -18
  8. data/ext/rugged/rugged_config.c +94 -5
  9. data/ext/rugged/rugged_object.c +54 -1
  10. data/ext/rugged/rugged_reference.c +203 -15
  11. data/ext/rugged/{remote.c → rugged_remote.c} +35 -10
  12. data/ext/rugged/rugged_repo.c +323 -81
  13. data/ext/rugged/rugged_revwalk.c +57 -4
  14. data/ext/rugged/rugged_signature.c +3 -3
  15. data/ext/rugged/rugged_tag.c +72 -1
  16. data/ext/rugged/rugged_tree.c +70 -2
  17. data/ext/rugged/vendor/libgit2-dist/deps/regex/config.h +7 -0
  18. data/ext/rugged/vendor/libgit2-dist/deps/regex/regcomp.c +3856 -0
  19. data/ext/rugged/vendor/libgit2-dist/deps/regex/regex.c +85 -0
  20. data/ext/rugged/vendor/libgit2-dist/deps/regex/regex.h +582 -0
  21. data/ext/rugged/vendor/libgit2-dist/deps/regex/regex_internal.c +1744 -0
  22. data/ext/rugged/vendor/libgit2-dist/deps/regex/regex_internal.h +810 -0
  23. data/ext/rugged/vendor/libgit2-dist/deps/regex/regexec.c +4369 -0
  24. data/ext/rugged/vendor/libgit2-dist/examples/diff.c +238 -0
  25. data/ext/rugged/vendor/libgit2-dist/examples/general.c +4 -4
  26. data/ext/rugged/vendor/libgit2-dist/examples/network/fetch.c +101 -85
  27. data/ext/rugged/vendor/libgit2-dist/examples/network/git2.c +7 -3
  28. data/ext/rugged/vendor/libgit2-dist/examples/network/index-pack.c +80 -25
  29. data/ext/rugged/vendor/libgit2-dist/examples/network/ls-remote.c +6 -6
  30. data/ext/rugged/vendor/libgit2-dist/include/git2/attr.h +224 -0
  31. data/ext/rugged/vendor/libgit2-dist/include/git2/blob.h +59 -5
  32. data/ext/rugged/vendor/libgit2-dist/include/git2/branch.h +114 -7
  33. data/ext/rugged/vendor/libgit2-dist/include/git2/commit.h +14 -7
  34. data/ext/rugged/vendor/libgit2-dist/include/git2/common.h +4 -3
  35. data/ext/rugged/vendor/libgit2-dist/include/git2/config.h +105 -27
  36. data/ext/rugged/vendor/libgit2-dist/include/git2/diff.h +409 -0
  37. data/ext/rugged/vendor/libgit2-dist/include/git2/errors.h +47 -82
  38. data/ext/rugged/vendor/libgit2-dist/include/git2/index.h +25 -10
  39. data/ext/rugged/vendor/libgit2-dist/include/git2/indexer.h +46 -1
  40. data/ext/rugged/vendor/libgit2-dist/include/git2/merge.h +35 -0
  41. data/ext/rugged/vendor/libgit2-dist/include/git2/net.h +1 -1
  42. data/ext/rugged/vendor/libgit2-dist/include/git2/notes.h +139 -0
  43. data/ext/rugged/vendor/libgit2-dist/include/git2/object.h +5 -5
  44. data/ext/rugged/vendor/libgit2-dist/include/git2/odb.h +13 -13
  45. data/ext/rugged/vendor/libgit2-dist/include/git2/odb_backend.h +8 -8
  46. data/ext/rugged/vendor/libgit2-dist/include/git2/oid.h +14 -9
  47. data/ext/rugged/vendor/libgit2-dist/include/git2/reflog.h +5 -5
  48. data/ext/rugged/vendor/libgit2-dist/include/git2/refs.h +37 -17
  49. data/ext/rugged/vendor/libgit2-dist/include/git2/refspec.h +17 -9
  50. data/ext/rugged/vendor/libgit2-dist/include/git2/remote.h +83 -16
  51. data/ext/rugged/vendor/libgit2-dist/include/git2/repository.h +24 -10
  52. data/ext/rugged/vendor/libgit2-dist/include/git2/reset.h +44 -0
  53. data/ext/rugged/vendor/libgit2-dist/include/git2/revparse.h +36 -0
  54. data/ext/rugged/vendor/libgit2-dist/include/git2/revwalk.h +74 -6
  55. data/ext/rugged/vendor/libgit2-dist/include/git2/signature.h +3 -3
  56. data/ext/rugged/vendor/libgit2-dist/include/git2/status.h +120 -19
  57. data/ext/rugged/vendor/libgit2-dist/include/git2/submodule.h +103 -0
  58. data/ext/rugged/vendor/libgit2-dist/include/git2/tag.h +28 -10
  59. data/ext/rugged/vendor/libgit2-dist/include/git2/threads.h +1 -1
  60. data/ext/rugged/vendor/libgit2-dist/include/git2/tree.h +13 -13
  61. data/ext/rugged/vendor/libgit2-dist/include/git2/types.h +16 -2
  62. data/ext/rugged/vendor/libgit2-dist/include/git2/version.h +3 -3
  63. data/ext/rugged/vendor/libgit2-dist/include/git2/windows.h +1 -1
  64. data/ext/rugged/vendor/libgit2-dist/include/git2.h +7 -2
  65. data/ext/rugged/vendor/libgit2-dist/src/attr.c +677 -0
  66. data/ext/rugged/vendor/libgit2-dist/src/attr.h +56 -0
  67. data/ext/rugged/vendor/libgit2-dist/src/attr_file.c +609 -0
  68. data/ext/rugged/vendor/libgit2-dist/src/attr_file.h +145 -0
  69. data/ext/rugged/vendor/libgit2-dist/src/blob.c +213 -60
  70. data/ext/rugged/vendor/libgit2-dist/src/blob.h +2 -1
  71. data/ext/rugged/vendor/libgit2-dist/src/branch.c +208 -0
  72. data/ext/rugged/vendor/libgit2-dist/src/branch.h +17 -0
  73. data/ext/rugged/vendor/libgit2-dist/src/bswap.h +1 -1
  74. data/ext/rugged/vendor/libgit2-dist/src/buffer.c +395 -46
  75. data/ext/rugged/vendor/libgit2-dist/src/buffer.h +112 -9
  76. data/ext/rugged/vendor/libgit2-dist/src/cache.c +37 -49
  77. data/ext/rugged/vendor/libgit2-dist/src/cache.h +7 -17
  78. data/ext/rugged/vendor/libgit2-dist/src/cc-compat.h +18 -16
  79. data/ext/rugged/vendor/libgit2-dist/src/commit.c +56 -90
  80. data/ext/rugged/vendor/libgit2-dist/src/commit.h +1 -1
  81. data/ext/rugged/vendor/libgit2-dist/src/common.h +12 -5
  82. data/ext/rugged/vendor/libgit2-dist/src/{win32 → compat}/fnmatch.c +1 -1
  83. data/ext/rugged/vendor/libgit2-dist/src/{win32 → compat}/fnmatch.h +3 -3
  84. data/ext/rugged/vendor/libgit2-dist/src/config.c +247 -158
  85. data/ext/rugged/vendor/libgit2-dist/src/config.h +10 -1
  86. data/ext/rugged/vendor/libgit2-dist/src/config_cache.c +94 -0
  87. data/ext/rugged/vendor/libgit2-dist/src/config_file.c +606 -496
  88. data/ext/rugged/vendor/libgit2-dist/src/config_file.h +31 -0
  89. data/ext/rugged/vendor/libgit2-dist/src/crlf.c +228 -0
  90. data/ext/rugged/vendor/libgit2-dist/src/date.c +876 -0
  91. data/ext/rugged/vendor/libgit2-dist/src/delta-apply.c +15 -9
  92. data/ext/rugged/vendor/libgit2-dist/src/delta-apply.h +2 -2
  93. data/ext/rugged/vendor/libgit2-dist/src/diff.c +814 -0
  94. data/ext/rugged/vendor/libgit2-dist/src/diff.h +43 -0
  95. data/ext/rugged/vendor/libgit2-dist/src/diff_output.c +794 -0
  96. data/ext/rugged/vendor/libgit2-dist/src/errors.c +89 -74
  97. data/ext/rugged/vendor/libgit2-dist/src/fetch.c +94 -66
  98. data/ext/rugged/vendor/libgit2-dist/src/fetch.h +5 -4
  99. data/ext/rugged/vendor/libgit2-dist/src/filebuf.c +157 -100
  100. data/ext/rugged/vendor/libgit2-dist/src/filebuf.h +22 -8
  101. data/ext/rugged/vendor/libgit2-dist/src/fileops.c +330 -206
  102. data/ext/rugged/vendor/libgit2-dist/src/fileops.h +82 -51
  103. data/ext/rugged/vendor/libgit2-dist/src/filter.c +165 -0
  104. data/ext/rugged/vendor/libgit2-dist/src/filter.h +119 -0
  105. data/ext/rugged/vendor/libgit2-dist/src/global.c +4 -4
  106. data/ext/rugged/vendor/libgit2-dist/src/global.h +4 -1
  107. data/ext/rugged/vendor/libgit2-dist/src/hash.c +1 -1
  108. data/ext/rugged/vendor/libgit2-dist/src/hash.h +1 -1
  109. data/ext/rugged/vendor/libgit2-dist/src/ignore.c +203 -0
  110. data/ext/rugged/vendor/libgit2-dist/src/ignore.h +38 -0
  111. data/ext/rugged/vendor/libgit2-dist/src/index.c +220 -169
  112. data/ext/rugged/vendor/libgit2-dist/src/index.h +5 -1
  113. data/ext/rugged/vendor/libgit2-dist/src/indexer.c +601 -102
  114. data/ext/rugged/vendor/libgit2-dist/src/iterator.c +748 -0
  115. data/ext/rugged/vendor/libgit2-dist/src/iterator.h +151 -0
  116. data/ext/rugged/vendor/libgit2-dist/src/khash.h +608 -0
  117. data/ext/rugged/vendor/libgit2-dist/src/map.h +6 -1
  118. data/ext/rugged/vendor/libgit2-dist/src/message.c +61 -0
  119. data/ext/rugged/vendor/libgit2-dist/src/message.h +14 -0
  120. data/ext/rugged/vendor/libgit2-dist/src/mwindow.c +27 -29
  121. data/ext/rugged/vendor/libgit2-dist/src/mwindow.h +4 -4
  122. data/ext/rugged/vendor/libgit2-dist/src/netops.c +375 -56
  123. data/ext/rugged/vendor/libgit2-dist/src/netops.h +12 -9
  124. data/ext/rugged/vendor/libgit2-dist/src/notes.c +548 -0
  125. data/ext/rugged/vendor/libgit2-dist/src/notes.h +28 -0
  126. data/ext/rugged/vendor/libgit2-dist/src/object.c +59 -21
  127. data/ext/rugged/vendor/libgit2-dist/src/odb.c +212 -175
  128. data/ext/rugged/vendor/libgit2-dist/src/odb.h +39 -2
  129. data/ext/rugged/vendor/libgit2-dist/src/odb_loose.c +238 -241
  130. data/ext/rugged/vendor/libgit2-dist/src/odb_pack.c +94 -106
  131. data/ext/rugged/vendor/libgit2-dist/src/oid.c +59 -60
  132. data/ext/rugged/vendor/libgit2-dist/src/oidmap.h +42 -0
  133. data/ext/rugged/vendor/libgit2-dist/src/pack.c +198 -170
  134. data/ext/rugged/vendor/libgit2-dist/src/pack.h +16 -9
  135. data/ext/rugged/vendor/libgit2-dist/src/path.c +496 -106
  136. data/ext/rugged/vendor/libgit2-dist/src/path.h +214 -20
  137. data/ext/rugged/vendor/libgit2-dist/src/pkt.c +88 -159
  138. data/ext/rugged/vendor/libgit2-dist/src/pkt.h +9 -5
  139. data/ext/rugged/vendor/libgit2-dist/src/pool.c +294 -0
  140. data/ext/rugged/vendor/libgit2-dist/src/pool.h +125 -0
  141. data/ext/rugged/vendor/libgit2-dist/src/posix.c +38 -16
  142. data/ext/rugged/vendor/libgit2-dist/src/posix.h +20 -2
  143. data/ext/rugged/vendor/libgit2-dist/src/ppc/sha1.c +1 -1
  144. data/ext/rugged/vendor/libgit2-dist/src/ppc/sha1.h +1 -1
  145. data/ext/rugged/vendor/libgit2-dist/src/pqueue.c +7 -7
  146. data/ext/rugged/vendor/libgit2-dist/src/pqueue.h +1 -1
  147. data/ext/rugged/vendor/libgit2-dist/src/protocol.c +21 -13
  148. data/ext/rugged/vendor/libgit2-dist/src/protocol.h +1 -1
  149. data/ext/rugged/vendor/libgit2-dist/src/reflog.c +125 -103
  150. data/ext/rugged/vendor/libgit2-dist/src/reflog.h +1 -1
  151. data/ext/rugged/vendor/libgit2-dist/src/refs.c +713 -640
  152. data/ext/rugged/vendor/libgit2-dist/src/refs.h +27 -3
  153. data/ext/rugged/vendor/libgit2-dist/src/refspec.c +51 -17
  154. data/ext/rugged/vendor/libgit2-dist/src/refspec.h +13 -1
  155. data/ext/rugged/vendor/libgit2-dist/src/remote.c +307 -119
  156. data/ext/rugged/vendor/libgit2-dist/src/remote.h +3 -2
  157. data/ext/rugged/vendor/libgit2-dist/src/repository.c +593 -442
  158. data/ext/rugged/vendor/libgit2-dist/src/repository.h +80 -2
  159. data/ext/rugged/vendor/libgit2-dist/src/reset.c +103 -0
  160. data/ext/rugged/vendor/libgit2-dist/src/revparse.c +753 -0
  161. data/ext/rugged/vendor/libgit2-dist/src/revwalk.c +434 -158
  162. data/ext/rugged/vendor/libgit2-dist/src/sha1.c +3 -3
  163. data/ext/rugged/vendor/libgit2-dist/src/sha1.h +2 -2
  164. data/ext/rugged/vendor/libgit2-dist/src/sha1_lookup.c +3 -2
  165. data/ext/rugged/vendor/libgit2-dist/src/sha1_lookup.h +1 -1
  166. data/ext/rugged/vendor/libgit2-dist/src/signature.c +69 -80
  167. data/ext/rugged/vendor/libgit2-dist/src/signature.h +1 -1
  168. data/ext/rugged/vendor/libgit2-dist/src/status.c +184 -638
  169. data/ext/rugged/vendor/libgit2-dist/src/strmap.h +64 -0
  170. data/ext/rugged/vendor/libgit2-dist/src/submodule.c +387 -0
  171. data/ext/rugged/vendor/libgit2-dist/src/tag.c +162 -137
  172. data/ext/rugged/vendor/libgit2-dist/src/tag.h +2 -1
  173. data/ext/rugged/vendor/libgit2-dist/src/thread-utils.c +1 -1
  174. data/ext/rugged/vendor/libgit2-dist/src/thread-utils.h +8 -8
  175. data/ext/rugged/vendor/libgit2-dist/src/transport.c +31 -19
  176. data/ext/rugged/vendor/libgit2-dist/src/transport.h +31 -11
  177. data/ext/rugged/vendor/libgit2-dist/src/transports/git.c +168 -193
  178. data/ext/rugged/vendor/libgit2-dist/src/transports/http.c +192 -241
  179. data/ext/rugged/vendor/libgit2-dist/src/transports/local.c +92 -86
  180. data/ext/rugged/vendor/libgit2-dist/src/tree-cache.c +32 -49
  181. data/ext/rugged/vendor/libgit2-dist/src/tree-cache.h +1 -1
  182. data/ext/rugged/vendor/libgit2-dist/src/tree.c +172 -145
  183. data/ext/rugged/vendor/libgit2-dist/src/tree.h +16 -2
  184. data/ext/rugged/vendor/libgit2-dist/src/tsort.c +16 -14
  185. data/ext/rugged/vendor/libgit2-dist/src/unix/map.c +8 -24
  186. data/ext/rugged/vendor/libgit2-dist/src/unix/posix.h +9 -3
  187. data/ext/rugged/vendor/libgit2-dist/src/util.c +94 -38
  188. data/ext/rugged/vendor/libgit2-dist/src/util.h +119 -13
  189. data/ext/rugged/vendor/libgit2-dist/src/vector.c +84 -31
  190. data/ext/rugged/vendor/libgit2-dist/src/vector.h +37 -4
  191. data/ext/rugged/vendor/libgit2-dist/src/win32/dir.c +81 -41
  192. data/ext/rugged/vendor/libgit2-dist/src/{dir.h → win32/dir.h} +4 -9
  193. data/ext/rugged/vendor/libgit2-dist/src/win32/map.c +19 -35
  194. data/ext/rugged/vendor/libgit2-dist/src/win32/mingw-compat.h +1 -1
  195. data/ext/rugged/vendor/libgit2-dist/src/win32/msvc-compat.h +5 -1
  196. data/ext/rugged/vendor/libgit2-dist/src/win32/posix.h +10 -8
  197. data/ext/rugged/vendor/libgit2-dist/src/win32/posix_w32.c +262 -118
  198. data/ext/rugged/vendor/libgit2-dist/src/win32/pthread.c +12 -9
  199. data/ext/rugged/vendor/libgit2-dist/src/win32/pthread.h +1 -1
  200. data/ext/rugged/vendor/libgit2-dist/src/win32/utf-conv.c +30 -26
  201. data/ext/rugged/vendor/libgit2-dist/src/win32/utf-conv.h +2 -1
  202. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xdiff.h +135 -0
  203. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xdiffi.c +572 -0
  204. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xdiffi.h +63 -0
  205. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xemit.c +253 -0
  206. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xemit.h +36 -0
  207. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xhistogram.c +371 -0
  208. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xinclude.h +46 -0
  209. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xmacros.h +54 -0
  210. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xmerge.c +619 -0
  211. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xpatience.c +358 -0
  212. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xprepare.c +483 -0
  213. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xprepare.h +34 -0
  214. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xtypes.h +67 -0
  215. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xutils.c +419 -0
  216. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xutils.h +49 -0
  217. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/attr_expect.h +43 -0
  218. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/file.c +226 -0
  219. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/flags.c +108 -0
  220. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/lookup.c +262 -0
  221. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/repo.c +273 -0
  222. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/buf/basic.c +5 -5
  223. data/ext/rugged/vendor/libgit2-dist/tests-clar/clar_helpers.c +181 -0
  224. data/ext/rugged/vendor/libgit2-dist/tests-clar/clar_libgit2.h +55 -0
  225. data/ext/rugged/vendor/libgit2-dist/tests-clar/commit/commit.c +44 -0
  226. data/ext/rugged/vendor/libgit2-dist/tests-clar/commit/parse.c +350 -0
  227. data/ext/rugged/vendor/libgit2-dist/tests-clar/commit/signature.c +65 -0
  228. data/ext/rugged/vendor/libgit2-dist/tests-clar/commit/write.c +140 -0
  229. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/config/add.c +3 -3
  230. data/ext/rugged/vendor/libgit2-dist/tests-clar/config/multivar.c +151 -0
  231. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/config/new.c +5 -5
  232. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/config/read.c +44 -32
  233. data/ext/rugged/vendor/libgit2-dist/tests-clar/config/stress.c +61 -0
  234. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/config/write.c +20 -5
  235. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/buffer.c +613 -0
  236. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/dirent.c +39 -26
  237. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/env.c +115 -0
  238. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/errors.c +60 -0
  239. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/filebuf.c +4 -18
  240. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/hex.c +22 -0
  241. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/oid.c +6 -6
  242. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/path.c +420 -0
  243. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/pool.c +85 -0
  244. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/rmdir.c +68 -0
  245. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/string.c +1 -1
  246. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/strmap.c +102 -0
  247. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/strtol.c +1 -1
  248. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/vector.c +191 -0
  249. data/ext/rugged/vendor/libgit2-dist/tests-clar/date/date.c +15 -0
  250. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/blob.c +254 -0
  251. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/diff_helpers.c +104 -0
  252. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/diff_helpers.h +47 -0
  253. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/index.c +92 -0
  254. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/iterator.c +572 -0
  255. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/patch.c +99 -0
  256. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/tree.c +210 -0
  257. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/workdir.c +543 -0
  258. data/ext/rugged/vendor/libgit2-dist/tests-clar/index/read_tree.c +46 -0
  259. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/index/rename.c +2 -12
  260. data/ext/rugged/vendor/libgit2-dist/tests-clar/index/tests.c +246 -0
  261. data/ext/rugged/vendor/libgit2-dist/tests-clar/network/createremotethenload.c +33 -0
  262. data/ext/rugged/vendor/libgit2-dist/tests-clar/network/remotelocal.c +137 -0
  263. data/ext/rugged/vendor/libgit2-dist/tests-clar/network/remotes.c +183 -0
  264. data/ext/rugged/vendor/libgit2-dist/tests-clar/notes/notes.c +133 -0
  265. data/ext/rugged/vendor/libgit2-dist/tests-clar/notes/notesref.c +57 -0
  266. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/blob/filter.c +125 -0
  267. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/blob/fromchunks.c +87 -0
  268. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/blob/write.c +69 -0
  269. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/commit/commitstagedfile.c +126 -0
  270. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/lookup.c +63 -0
  271. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/message.c +171 -0
  272. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/chars.c +3 -14
  273. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/compare.c +4 -4
  274. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/convert.c +10 -10
  275. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/data.h +0 -0
  276. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/fromstr.c +1 -1
  277. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/hash.c +21 -17
  278. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/short.c +1 -1
  279. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/size.c +1 -1
  280. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/type2string.c +14 -14
  281. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/raw/write.c +455 -0
  282. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tag/peel.c +56 -0
  283. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tag/read.c +130 -0
  284. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tag/write.c +192 -0
  285. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/tree/frompath.c +22 -16
  286. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tree/read.c +75 -0
  287. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tree/write.c +84 -0
  288. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/loose.c +1 -1
  289. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/loose_data.h +0 -0
  290. data/ext/rugged/vendor/libgit2-dist/tests-clar/odb/mixed.c +24 -0
  291. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/pack_data.h +0 -0
  292. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/packed.c +1 -1
  293. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/sorting.c +1 -1
  294. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/branches/create.c +113 -0
  295. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/branches/delete.c +91 -0
  296. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/branches/listall.c +78 -0
  297. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/branches/move.c +72 -0
  298. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/crashes.c +17 -0
  299. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/create.c +149 -0
  300. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/delete.c +85 -0
  301. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/list.c +53 -0
  302. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/listall.c +36 -0
  303. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/lookup.c +42 -0
  304. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/normalize.c +200 -0
  305. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/overwrite.c +136 -0
  306. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/pack.c +67 -0
  307. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/read.c +194 -0
  308. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/reflog.c +123 -0
  309. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/rename.c +339 -0
  310. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/revparse.c +174 -0
  311. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/unicode.c +42 -0
  312. data/ext/rugged/vendor/libgit2-dist/tests-clar/repo/discover.c +142 -0
  313. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/repo/getters.c +19 -1
  314. data/ext/rugged/vendor/libgit2-dist/tests-clar/repo/init.c +235 -0
  315. data/ext/rugged/vendor/libgit2-dist/tests-clar/repo/open.c +282 -0
  316. data/ext/rugged/vendor/libgit2-dist/tests-clar/repo/setters.c +80 -0
  317. data/ext/rugged/vendor/libgit2-dist/tests-clar/reset/mixed.c +47 -0
  318. data/ext/rugged/vendor/libgit2-dist/tests-clar/reset/reset_helpers.c +10 -0
  319. data/ext/rugged/vendor/libgit2-dist/tests-clar/reset/reset_helpers.h +6 -0
  320. data/ext/rugged/vendor/libgit2-dist/tests-clar/reset/soft.c +102 -0
  321. data/ext/rugged/vendor/libgit2-dist/{tests/t05-revwalk.c → tests-clar/revwalk/basic.c} +85 -44
  322. data/ext/rugged/vendor/libgit2-dist/tests-clar/revwalk/mergebase.c +148 -0
  323. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/ignore.c +133 -0
  324. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/status/single.c +2 -11
  325. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/status_data.h +202 -0
  326. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/status_helpers.c +49 -0
  327. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/status_helpers.h +33 -0
  328. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/submodules.c +112 -0
  329. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/worktree.c +649 -0
  330. data/ext/rugged/vendor/libgit2-dist/tests-clar/threads/basic.c +20 -0
  331. data/ext/rugged/vendor/libgit2-dist.tar.gz +0 -0
  332. data/lib/rugged/commit.rb +35 -0
  333. data/lib/rugged/object.rb +7 -0
  334. data/lib/rugged/reference.rb +9 -0
  335. data/lib/rugged/repository.rb +99 -3
  336. data/lib/rugged/tag.rb +22 -0
  337. data/lib/rugged/tree.rb +8 -0
  338. data/lib/rugged/version.rb +1 -1
  339. data/lib/rugged.rb +4 -1
  340. data/test/blob_test.rb +2 -2
  341. data/test/commit_test.rb +27 -13
  342. data/test/config_test.rb +44 -0
  343. data/test/coverage/HEAD.json +1 -1
  344. data/test/fixtures/testrepo.git/config +2 -0
  345. data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
  346. data/test/lib_test.rb +7 -0
  347. data/test/object_test.rb +3 -3
  348. data/test/reference_test.rb +46 -8
  349. data/test/remote_test.rb +8 -2
  350. data/test/repo_pack_test.rb +3 -3
  351. data/test/repo_test.rb +79 -11
  352. data/test/tag_test.rb +9 -2
  353. data/test/test_helper.rb +21 -0
  354. data/test/tree_test.rb +18 -6
  355. metadata +205 -81
  356. data/ext/rugged/vendor/libgit2-dist/include/git2/zlib.h +0 -40
  357. data/ext/rugged/vendor/libgit2-dist/src/hashtable.c +0 -243
  358. data/ext/rugged/vendor/libgit2-dist/src/hashtable.h +0 -80
  359. data/ext/rugged/vendor/libgit2-dist/tests/t00-core.c +0 -628
  360. data/ext/rugged/vendor/libgit2-dist/tests/t01-data.h +0 -322
  361. data/ext/rugged/vendor/libgit2-dist/tests/t01-rawobj.c +0 -638
  362. data/ext/rugged/vendor/libgit2-dist/tests/t03-data.h +0 -344
  363. data/ext/rugged/vendor/libgit2-dist/tests/t03-objwrite.c +0 -255
  364. data/ext/rugged/vendor/libgit2-dist/tests/t04-commit.c +0 -788
  365. data/ext/rugged/vendor/libgit2-dist/tests/t06-index.c +0 -219
  366. data/ext/rugged/vendor/libgit2-dist/tests/t07-hashtable.c +0 -192
  367. data/ext/rugged/vendor/libgit2-dist/tests/t08-tag.c +0 -357
  368. data/ext/rugged/vendor/libgit2-dist/tests/t09-tree.c +0 -221
  369. data/ext/rugged/vendor/libgit2-dist/tests/t10-refs.c +0 -1294
  370. data/ext/rugged/vendor/libgit2-dist/tests/t12-repo.c +0 -174
  371. data/ext/rugged/vendor/libgit2-dist/tests/t13-threads.c +0 -41
  372. data/ext/rugged/vendor/libgit2-dist/tests/t17-bufs.c +0 -61
  373. data/ext/rugged/vendor/libgit2-dist/tests/t18-status.c +0 -448
  374. data/ext/rugged/vendor/libgit2-dist/tests/test_helpers.c +0 -310
  375. data/ext/rugged/vendor/libgit2-dist/tests/test_helpers.h +0 -83
  376. data/ext/rugged/vendor/libgit2-dist/tests/test_lib.c +0 -198
  377. data/ext/rugged/vendor/libgit2-dist/tests/test_lib.h +0 -54
  378. data/ext/rugged/vendor/libgit2-dist/tests/test_main.c +0 -89
  379. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay.h +0 -187
  380. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay_libgit2.h +0 -28
  381. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay_main.c +0 -1073
  382. data/ext/rugged/vendor/libgit2-dist/tests-clay/config/stress.c +0 -39
  383. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/path.c +0 -139
  384. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/rmdir.c +0 -50
  385. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/vector.c +0 -66
  386. data/ext/rugged/vendor/libgit2-dist/tests-clay/network/remotes.c +0 -50
  387. data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/init.c +0 -104
  388. data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/open.c +0 -54
  389. data/ext/rugged/vendor/libgit2-dist/tests-clay/status/status_data.h +0 -48
  390. data/ext/rugged/vendor/libgit2-dist/tests-clay/status/worktree.c +0 -124
  391. data/lib/rugged/objects.rb +0 -45
  392. data/test/fixtures/testrepo.git/refs/heads/new_name +0 -1
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2011 the libgit2 contributors
2
+ * Copyright (C) 2009-2012 the libgit2 contributors
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.
@@ -15,7 +15,10 @@
15
15
  #include <git2/tag.h>
16
16
  #include <git2/object.h>
17
17
 
18
- #define MAX_NESTING_LEVEL 5
18
+ GIT__USE_STRMAP;
19
+
20
+ #define DEFAULT_NESTING_LEVEL 5
21
+ #define MAX_NESTING_LEVEL 10
19
22
 
20
23
  enum {
21
24
  GIT_PACKREF_HAS_PEEL = 1,
@@ -29,29 +32,16 @@ struct packref {
29
32
  char name[GIT_FLEX_ARRAY];
30
33
  };
31
34
 
32
- static const int default_table_size = 32;
33
-
34
- static uint32_t reftable_hash(const void *key, int hash_id)
35
- {
36
- static uint32_t hash_seeds[GIT_HASHTABLE_HASHES] = {
37
- 2147483647,
38
- 0x5d20bb23,
39
- 0x7daaab3c
40
- };
41
-
42
- return git__hash(key, strlen((const char *)key), hash_seeds[hash_id]);
43
- }
44
-
45
35
  static int reference_read(
46
- git_fbuffer *file_content,
36
+ git_buf *file_content,
47
37
  time_t *mtime,
48
38
  const char *repo_path,
49
39
  const char *ref_name,
50
40
  int *updated);
51
41
 
52
42
  /* loose refs */
53
- static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content);
54
- static int loose_parse_oid(git_oid *ref, git_fbuffer *file_content);
43
+ static int loose_parse_symbolic(git_reference *ref, git_buf *file_content);
44
+ static int loose_parse_oid(git_oid *ref, git_buf *file_content);
55
45
  static int loose_lookup(git_reference *ref);
56
46
  static int loose_lookup_to_packfile(struct packref **ref_out,
57
47
  git_repository *repo, const char *name);
@@ -72,7 +62,7 @@ static int packed_lookup(git_reference *ref);
72
62
  static int packed_write(git_repository *repo);
73
63
 
74
64
  /* internal helpers */
75
- static int reference_available(git_repository *repo,
65
+ static int reference_path_available(git_repository *repo,
76
66
  const char *ref, const char *old_ref);
77
67
  static int reference_delete(git_reference *ref);
78
68
  static int reference_lookup(git_reference *ref);
@@ -88,14 +78,17 @@ void git_reference_free(git_reference *reference)
88
78
  return;
89
79
 
90
80
  git__free(reference->name);
81
+ reference->name = NULL;
91
82
 
92
- if (reference->flags & GIT_REF_SYMBOLIC)
83
+ if (reference->flags & GIT_REF_SYMBOLIC) {
93
84
  git__free(reference->target.symbolic);
85
+ reference->target.symbolic = NULL;
86
+ }
94
87
 
95
88
  git__free(reference);
96
89
  }
97
90
 
98
- static int reference_create(
91
+ static int reference_alloc(
99
92
  git_reference **ref_out,
100
93
  git_repository *repo,
101
94
  const char *name)
@@ -105,145 +98,151 @@ static int reference_create(
105
98
  assert(ref_out && repo && name);
106
99
 
107
100
  reference = git__malloc(sizeof(git_reference));
108
- if (reference == NULL)
109
- return GIT_ENOMEM;
101
+ GITERR_CHECK_ALLOC(reference);
110
102
 
111
103
  memset(reference, 0x0, sizeof(git_reference));
112
104
  reference->owner = repo;
113
105
 
114
106
  reference->name = git__strdup(name);
115
- if (reference->name == NULL) {
116
- free(reference);
117
- return GIT_ENOMEM;
118
- }
107
+ GITERR_CHECK_ALLOC(reference->name);
119
108
 
120
109
  *ref_out = reference;
121
- return GIT_SUCCESS;
110
+ return 0;
122
111
  }
123
112
 
124
- static int reference_read(git_fbuffer *file_content, time_t *mtime, const char *repo_path, const char *ref_name, int *updated)
113
+ static int reference_read(
114
+ git_buf *file_content,
115
+ time_t *mtime,
116
+ const char *repo_path,
117
+ const char *ref_name,
118
+ int *updated)
125
119
  {
126
- char path[GIT_PATH_MAX];
120
+ git_buf path = GIT_BUF_INIT;
121
+ int result;
127
122
 
128
123
  assert(file_content && repo_path && ref_name);
129
124
 
130
125
  /* Determine the full path of the file */
131
- git_path_join(path, repo_path, ref_name);
126
+ if (git_buf_joinpath(&path, repo_path, ref_name) < 0)
127
+ return -1;
132
128
 
133
- return git_futils_readbuffer_updated(file_content, path, mtime, updated);
129
+ result = git_futils_readbuffer_updated(file_content, path.ptr, mtime, updated);
130
+ git_buf_free(&path);
131
+ return result;
134
132
  }
135
133
 
136
- static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content)
134
+ static int loose_parse_symbolic(git_reference *ref, git_buf *file_content)
137
135
  {
138
- const unsigned int header_len = strlen(GIT_SYMREF);
136
+ const unsigned int header_len = (unsigned int)strlen(GIT_SYMREF);
139
137
  const char *refname_start;
140
138
  char *eol;
141
139
 
142
- refname_start = (const char *)file_content->data;
140
+ refname_start = (const char *)file_content->ptr;
143
141
 
144
- if (file_content->len < (header_len + 1))
145
- return git__throw(GIT_EOBJCORRUPTED,
146
- "Failed to parse loose reference. Object too short");
142
+ if (git_buf_len(file_content) < header_len + 1)
143
+ goto corrupt;
147
144
 
148
145
  /*
149
146
  * Assume we have already checked for the header
150
147
  * before calling this function
151
148
  */
152
-
153
149
  refname_start += header_len;
154
150
 
155
151
  ref->target.symbolic = git__strdup(refname_start);
156
- if (ref->target.symbolic == NULL)
157
- return GIT_ENOMEM;
152
+ GITERR_CHECK_ALLOC(ref->target.symbolic);
158
153
 
159
154
  /* remove newline at the end of file */
160
155
  eol = strchr(ref->target.symbolic, '\n');
161
156
  if (eol == NULL)
162
- return git__throw(GIT_EOBJCORRUPTED,
163
- "Failed to parse loose reference. Missing EOL");
157
+ goto corrupt;
164
158
 
165
159
  *eol = '\0';
166
160
  if (eol[-1] == '\r')
167
161
  eol[-1] = '\0';
168
162
 
169
- return GIT_SUCCESS;
163
+ return 0;
164
+
165
+ corrupt:
166
+ giterr_set(GITERR_REFERENCE, "Corrupted loose reference file");
167
+ return -1;
170
168
  }
171
169
 
172
- static int loose_parse_oid(git_oid *oid, git_fbuffer *file_content)
170
+ static int loose_parse_oid(git_oid *oid, git_buf *file_content)
173
171
  {
174
- int error;
175
172
  char *buffer;
176
173
 
177
- buffer = (char *)file_content->data;
174
+ buffer = (char *)file_content->ptr;
178
175
 
179
176
  /* File format: 40 chars (OID) + newline */
180
- if (file_content->len < GIT_OID_HEXSZ + 1)
181
- return git__throw(GIT_EOBJCORRUPTED,
182
- "Failed to parse loose reference. Reference too short");
177
+ if (git_buf_len(file_content) < GIT_OID_HEXSZ + 1)
178
+ goto corrupt;
183
179
 
184
- if ((error = git_oid_fromstr(oid, buffer)) < GIT_SUCCESS)
185
- return git__rethrow(GIT_EOBJCORRUPTED, "Failed to parse loose reference.");
180
+ if (git_oid_fromstr(oid, buffer) < 0)
181
+ goto corrupt;
186
182
 
187
183
  buffer = buffer + GIT_OID_HEXSZ;
188
184
  if (*buffer == '\r')
189
185
  buffer++;
190
186
 
191
187
  if (*buffer != '\n')
192
- return git__throw(GIT_EOBJCORRUPTED,
193
- "Failed to parse loose reference. Missing EOL");
188
+ goto corrupt;
194
189
 
195
- return GIT_SUCCESS;
190
+ return 0;
191
+
192
+ corrupt:
193
+ giterr_set(GITERR_REFERENCE, "Corrupted loose reference file");
194
+ return -1;
196
195
  }
197
196
 
198
- static git_rtype loose_guess_rtype(const char *full_path)
197
+ static git_ref_t loose_guess_rtype(const git_buf *full_path)
199
198
  {
200
- git_fbuffer ref_file = GIT_FBUFFER_INIT;
201
- git_rtype type;
199
+ git_buf ref_file = GIT_BUF_INIT;
200
+ git_ref_t type;
202
201
 
203
202
  type = GIT_REF_INVALID;
204
203
 
205
- if (git_futils_readbuffer(&ref_file, full_path) == GIT_SUCCESS) {
206
- if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0)
204
+ if (git_futils_readbuffer(&ref_file, full_path->ptr) == 0) {
205
+ if (git__prefixcmp((const char *)(ref_file.ptr), GIT_SYMREF) == 0)
207
206
  type = GIT_REF_SYMBOLIC;
208
207
  else
209
208
  type = GIT_REF_OID;
210
209
  }
211
210
 
212
- git_futils_freebuffer(&ref_file);
211
+ git_buf_free(&ref_file);
213
212
  return type;
214
213
  }
215
214
 
216
215
  static int loose_lookup(git_reference *ref)
217
216
  {
218
- int error = GIT_SUCCESS, updated;
219
- git_fbuffer ref_file = GIT_FBUFFER_INIT;
217
+ int result, updated;
218
+ git_buf ref_file = GIT_BUF_INIT;
219
+
220
+ result = reference_read(&ref_file, &ref->mtime,
221
+ ref->owner->path_repository, ref->name, &updated);
220
222
 
221
- if (reference_read(&ref_file, &ref->mtime,
222
- ref->owner->path_repository, ref->name, &updated) < GIT_SUCCESS)
223
- return git__throw(GIT_ENOTFOUND, "Failed to lookup loose reference");
223
+ if (result < 0)
224
+ return result;
224
225
 
225
226
  if (!updated)
226
- return GIT_SUCCESS;
227
+ return 0;
227
228
 
228
- if (ref->flags & GIT_REF_SYMBOLIC)
229
- free(ref->target.symbolic);
229
+ if (ref->flags & GIT_REF_SYMBOLIC) {
230
+ git__free(ref->target.symbolic);
231
+ ref->target.symbolic = NULL;
232
+ }
230
233
 
231
234
  ref->flags = 0;
232
235
 
233
- if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0) {
236
+ if (git__prefixcmp((const char *)(ref_file.ptr), GIT_SYMREF) == 0) {
234
237
  ref->flags |= GIT_REF_SYMBOLIC;
235
- error = loose_parse_symbolic(ref, &ref_file);
238
+ result = loose_parse_symbolic(ref, &ref_file);
236
239
  } else {
237
240
  ref->flags |= GIT_REF_OID;
238
- error = loose_parse_oid(&ref->target.oid, &ref_file);
241
+ result = loose_parse_oid(&ref->target.oid, &ref_file);
239
242
  }
240
243
 
241
- git_futils_freebuffer(&ref_file);
242
-
243
- if (error < GIT_SUCCESS)
244
- return git__rethrow(error, "Failed to lookup loose reference");
245
-
246
- return GIT_SUCCESS;
244
+ git_buf_free(&ref_file);
245
+ return result;
247
246
  }
248
247
 
249
248
  static int loose_lookup_to_packfile(
@@ -251,50 +250,59 @@ static int loose_lookup_to_packfile(
251
250
  git_repository *repo,
252
251
  const char *name)
253
252
  {
254
- int error = GIT_SUCCESS;
255
- git_fbuffer ref_file = GIT_FBUFFER_INIT;
253
+ git_buf ref_file = GIT_BUF_INIT;
256
254
  struct packref *ref = NULL;
257
255
  size_t name_len;
258
256
 
259
257
  *ref_out = NULL;
260
258
 
261
- error = reference_read(&ref_file, NULL, repo->path_repository, name, NULL);
262
- if (error < GIT_SUCCESS)
263
- goto cleanup;
259
+ if (reference_read(&ref_file, NULL, repo->path_repository, name, NULL) < 0)
260
+ return -1;
264
261
 
265
262
  name_len = strlen(name);
266
263
  ref = git__malloc(sizeof(struct packref) + name_len + 1);
264
+ GITERR_CHECK_ALLOC(ref);
267
265
 
268
266
  memcpy(ref->name, name, name_len);
269
267
  ref->name[name_len] = 0;
270
268
 
271
- error = loose_parse_oid(&ref->oid, &ref_file);
272
- if (error < GIT_SUCCESS)
273
- goto cleanup;
269
+ if (loose_parse_oid(&ref->oid, &ref_file) < 0) {
270
+ git_buf_free(&ref_file);
271
+ git__free(ref);
272
+ return -1;
273
+ }
274
274
 
275
275
  ref->flags = GIT_PACKREF_WAS_LOOSE;
276
276
 
277
277
  *ref_out = ref;
278
- git_futils_freebuffer(&ref_file);
279
- return GIT_SUCCESS;
280
-
281
- cleanup:
282
- git_futils_freebuffer(&ref_file);
283
- free(ref);
284
- return git__rethrow(error, "Failed to lookup loose reference");
278
+ git_buf_free(&ref_file);
279
+ return 0;
285
280
  }
286
281
 
287
282
  static int loose_write(git_reference *ref)
288
283
  {
289
284
  git_filebuf file = GIT_FILEBUF_INIT;
290
- char ref_path[GIT_PATH_MAX];
291
- int error;
285
+ git_buf ref_path = GIT_BUF_INIT;
292
286
  struct stat st;
293
287
 
294
- git_path_join(ref_path, ref->owner->path_repository, ref->name);
288
+ if (git_buf_joinpath(&ref_path, ref->owner->path_repository, ref->name) < 0)
289
+ return -1;
295
290
 
296
- if ((error = git_filebuf_open(&file, ref_path, GIT_FILEBUF_FORCE)) < GIT_SUCCESS)
297
- return git__rethrow(error, "Failed to write loose reference");
291
+ /* Remove a possibly existing empty directory hierarchy
292
+ * which name would collide with the reference name
293
+ */
294
+ if (git_path_isdir(git_buf_cstr(&ref_path)) &&
295
+ (git_futils_rmdir_r(git_buf_cstr(&ref_path), GIT_DIRREMOVAL_ONLY_EMPTY_DIRS) < 0)) {
296
+ git_buf_free(&ref_path);
297
+ return -1;
298
+ }
299
+
300
+ if (git_filebuf_open(&file, ref_path.ptr, GIT_FILEBUF_FORCE) < 0) {
301
+ git_buf_free(&ref_path);
302
+ return -1;
303
+ }
304
+
305
+ git_buf_free(&ref_path);
298
306
 
299
307
  if (ref->flags & GIT_REF_OID) {
300
308
  char oid[GIT_OID_HEXSZ + 1];
@@ -302,26 +310,18 @@ static int loose_write(git_reference *ref)
302
310
  git_oid_fmt(oid, &ref->target.oid);
303
311
  oid[GIT_OID_HEXSZ] = '\0';
304
312
 
305
- error = git_filebuf_printf(&file, "%s\n", oid);
306
- if (error < GIT_SUCCESS)
307
- goto unlock;
313
+ git_filebuf_printf(&file, "%s\n", oid);
308
314
 
309
- } else if (ref->flags & GIT_REF_SYMBOLIC) { /* GIT_REF_SYMBOLIC */
310
- error = git_filebuf_printf(&file, GIT_SYMREF "%s\n", ref->target.symbolic);
315
+ } else if (ref->flags & GIT_REF_SYMBOLIC) {
316
+ git_filebuf_printf(&file, GIT_SYMREF "%s\n", ref->target.symbolic);
311
317
  } else {
312
- error = git__throw(GIT_EOBJCORRUPTED,
313
- "Failed to write reference. Invalid reference type");
314
- goto unlock;
318
+ assert(0); /* don't let this happen */
315
319
  }
316
320
 
317
- if (p_stat(ref_path, &st) == GIT_SUCCESS)
321
+ if (p_stat(ref_path.ptr, &st) == 0)
318
322
  ref->mtime = st.st_mtime;
319
323
 
320
324
  return git_filebuf_commit(&file, GIT_REFS_FILE_MODE);
321
-
322
- unlock:
323
- git_filebuf_cleanup(&file);
324
- return git__rethrow(error, "Failed to write loose reference");
325
325
  }
326
326
 
327
327
  static int packed_parse_peel(
@@ -335,34 +335,32 @@ static int packed_parse_peel(
335
335
 
336
336
  /* Ensure it's not the first entry of the file */
337
337
  if (tag_ref == NULL)
338
- return git__throw(GIT_EPACKEDREFSCORRUPTED,
339
- "Failed to parse packed reference. "
340
- "Reference is the first entry of the file");
338
+ goto corrupt;
341
339
 
342
340
  /* Ensure reference is a tag */
343
341
  if (git__prefixcmp(tag_ref->name, GIT_REFS_TAGS_DIR) != 0)
344
- return git__throw(GIT_EPACKEDREFSCORRUPTED,
345
- "Failed to parse packed reference. Reference is not a tag");
342
+ goto corrupt;
346
343
 
347
344
  if (buffer + GIT_OID_HEXSZ >= buffer_end)
348
- return git__throw(GIT_EPACKEDREFSCORRUPTED,
349
- "Failed to parse packed reference. Buffer too small");
345
+ goto corrupt;
350
346
 
351
347
  /* Is this a valid object id? */
352
- if (git_oid_fromstr(&tag_ref->peel, buffer) < GIT_SUCCESS)
353
- return git__throw(GIT_EPACKEDREFSCORRUPTED,
354
- "Failed to parse packed reference. Not a valid object ID");
348
+ if (git_oid_fromstr(&tag_ref->peel, buffer) < 0)
349
+ goto corrupt;
355
350
 
356
351
  buffer = buffer + GIT_OID_HEXSZ;
357
352
  if (*buffer == '\r')
358
353
  buffer++;
359
354
 
360
355
  if (*buffer != '\n')
361
- return git__throw(GIT_EPACKEDREFSCORRUPTED,
362
- "Failed to parse packed reference. Buffer not terminated correctly");
356
+ goto corrupt;
363
357
 
364
358
  *buffer_out = buffer + 1;
365
- return GIT_SUCCESS;
359
+ return 0;
360
+
361
+ corrupt:
362
+ giterr_set(GITERR_REFERENCE, "The packed references file is corrupted");
363
+ return -1;
366
364
  }
367
365
 
368
366
  static int packed_parse_oid(
@@ -375,26 +373,20 @@ static int packed_parse_oid(
375
373
  const char *buffer = *buffer_out;
376
374
  const char *refname_begin, *refname_end;
377
375
 
378
- int error = GIT_SUCCESS;
379
376
  size_t refname_len;
380
377
  git_oid id;
381
378
 
382
379
  refname_begin = (buffer + GIT_OID_HEXSZ + 1);
383
- if (refname_begin >= buffer_end ||
384
- refname_begin[-1] != ' ') {
385
- error = GIT_EPACKEDREFSCORRUPTED;
386
- goto cleanup;
387
- }
380
+ if (refname_begin >= buffer_end || refname_begin[-1] != ' ')
381
+ goto corrupt;
388
382
 
389
383
  /* Is this a valid object id? */
390
- if ((error = git_oid_fromstr(&id, buffer)) < GIT_SUCCESS)
391
- goto cleanup;
384
+ if (git_oid_fromstr(&id, buffer) < 0)
385
+ goto corrupt;
392
386
 
393
387
  refname_end = memchr(refname_begin, '\n', buffer_end - refname_begin);
394
- if (refname_end == NULL) {
395
- error = GIT_EPACKEDREFSCORRUPTED;
396
- goto cleanup;
397
- }
388
+ if (refname_end == NULL)
389
+ goto corrupt;
398
390
 
399
391
  if (refname_end[-1] == '\r')
400
392
  refname_end--;
@@ -402,6 +394,7 @@ static int packed_parse_oid(
402
394
  refname_len = refname_end - refname_begin;
403
395
 
404
396
  ref = git__malloc(sizeof(struct packref) + refname_len + 1);
397
+ GITERR_CHECK_ALLOC(ref);
405
398
 
406
399
  memcpy(ref->name, refname_begin, refname_len);
407
400
  ref->name[refname_len] = 0;
@@ -413,34 +406,28 @@ static int packed_parse_oid(
413
406
  *ref_out = ref;
414
407
  *buffer_out = refname_end + 1;
415
408
 
416
- return GIT_SUCCESS;
409
+ return 0;
417
410
 
418
- cleanup:
419
- free(ref);
420
- return git__rethrow(error, "Failed to parse OID of packed reference");
411
+ corrupt:
412
+ git__free(ref);
413
+ giterr_set(GITERR_REFERENCE, "The packed references file is corrupted");
414
+ return -1;
421
415
  }
422
416
 
423
417
  static int packed_load(git_repository *repo)
424
418
  {
425
- int error = GIT_SUCCESS, updated;
426
- git_fbuffer packfile = GIT_FBUFFER_INIT;
419
+ int result, updated;
420
+ git_buf packfile = GIT_BUF_INIT;
427
421
  const char *buffer_start, *buffer_end;
428
422
  git_refcache *ref_cache = &repo->references;
429
423
 
430
424
  /* First we make sure we have allocated the hash table */
431
425
  if (ref_cache->packfile == NULL) {
432
- ref_cache->packfile = git_hashtable_alloc(
433
- default_table_size,
434
- reftable_hash,
435
- (git_hash_keyeq_ptr)&git__strcmp_cb);
436
-
437
- if (ref_cache->packfile == NULL) {
438
- error = GIT_ENOMEM;
439
- goto cleanup;
440
- }
426
+ ref_cache->packfile = git_strmap_alloc();
427
+ GITERR_CHECK_ALLOC(ref_cache->packfile);
441
428
  }
442
429
 
443
- error = reference_read(&packfile, &ref_cache->packfile_time,
430
+ result = reference_read(&packfile, &ref_cache->packfile_time,
444
431
  repo->path_repository, GIT_PACKEDREFS_FILE, &updated);
445
432
 
446
433
  /*
@@ -450,62 +437,59 @@ static int packed_load(git_repository *repo)
450
437
  * for us here, so just return. Anything else means we need to
451
438
  * refresh the packed refs.
452
439
  */
453
- if (error == GIT_ENOTFOUND) {
454
- git_hashtable_clear(ref_cache->packfile);
455
- return GIT_SUCCESS;
456
- } else if (error < GIT_SUCCESS) {
457
- return git__rethrow(error, "Failed to read packed refs");
458
- } else if (!updated) {
459
- return GIT_SUCCESS;
440
+ if (result == GIT_ENOTFOUND) {
441
+ git_strmap_clear(ref_cache->packfile);
442
+ return 0;
460
443
  }
461
444
 
445
+ if (result < 0)
446
+ return -1;
447
+
448
+ if (!updated)
449
+ return 0;
450
+
462
451
  /*
463
452
  * At this point, we want to refresh the packed refs. We already
464
453
  * have the contents in our buffer.
465
454
  */
455
+ git_strmap_clear(ref_cache->packfile);
466
456
 
467
- git_hashtable_clear(ref_cache->packfile);
468
-
469
- buffer_start = (const char *)packfile.data;
470
- buffer_end = (const char *)(buffer_start) + packfile.len;
457
+ buffer_start = (const char *)packfile.ptr;
458
+ buffer_end = (const char *)(buffer_start) + packfile.size;
471
459
 
472
460
  while (buffer_start < buffer_end && buffer_start[0] == '#') {
473
461
  buffer_start = strchr(buffer_start, '\n');
474
- if (buffer_start == NULL) {
475
- error = GIT_EPACKEDREFSCORRUPTED;
476
- goto cleanup;
477
- }
462
+ if (buffer_start == NULL)
463
+ goto parse_failed;
464
+
478
465
  buffer_start++;
479
466
  }
480
467
 
481
468
  while (buffer_start < buffer_end) {
469
+ int err;
482
470
  struct packref *ref = NULL;
483
471
 
484
- error = packed_parse_oid(&ref, &buffer_start, buffer_end);
485
- if (error < GIT_SUCCESS)
486
- goto cleanup;
472
+ if (packed_parse_oid(&ref, &buffer_start, buffer_end) < 0)
473
+ goto parse_failed;
487
474
 
488
475
  if (buffer_start[0] == '^') {
489
- error = packed_parse_peel(ref, &buffer_start, buffer_end);
490
- if (error < GIT_SUCCESS)
491
- goto cleanup;
476
+ if (packed_parse_peel(ref, &buffer_start, buffer_end) < 0)
477
+ goto parse_failed;
492
478
  }
493
479
 
494
- error = git_hashtable_insert(ref_cache->packfile, ref->name, ref);
495
- if (error < GIT_SUCCESS) {
496
- free(ref);
497
- goto cleanup;
498
- }
480
+ git_strmap_insert(ref_cache->packfile, ref->name, ref, err);
481
+ if (err < 0)
482
+ goto parse_failed;
499
483
  }
500
484
 
501
- git_futils_freebuffer(&packfile);
502
- return GIT_SUCCESS;
485
+ git_buf_free(&packfile);
486
+ return 0;
503
487
 
504
- cleanup:
505
- git_hashtable_free(ref_cache->packfile);
488
+ parse_failed:
489
+ git_strmap_free(ref_cache->packfile);
506
490
  ref_cache->packfile = NULL;
507
- git_futils_freebuffer(&packfile);
508
- return git__rethrow(error, "Failed to load packed references");
491
+ git_buf_free(&packfile);
492
+ return -1;
509
493
  }
510
494
 
511
495
 
@@ -518,60 +502,52 @@ struct dirent_list_data {
518
502
  void *callback_payload;
519
503
  };
520
504
 
521
- static int _dirent_loose_listall(void *_data, char *full_path)
505
+ static int _dirent_loose_listall(void *_data, git_buf *full_path)
522
506
  {
523
507
  struct dirent_list_data *data = (struct dirent_list_data *)_data;
524
- char *file_path = full_path + data->repo_path_len;
508
+ const char *file_path = full_path->ptr + data->repo_path_len;
525
509
 
526
- if (git_futils_isdir(full_path) == GIT_SUCCESS)
527
- return git_futils_direach(full_path, GIT_PATH_MAX,
528
- _dirent_loose_listall, _data);
510
+ if (git_path_isdir(full_path->ptr) == true)
511
+ return git_path_direach(full_path, _dirent_loose_listall, _data);
529
512
 
530
513
  /* do not add twice a reference that exists already in the packfile */
531
514
  if ((data->list_flags & GIT_REF_PACKED) != 0 &&
532
- git_hashtable_lookup(data->repo->references.packfile, file_path) != NULL)
533
- return GIT_SUCCESS;
515
+ git_strmap_exists(data->repo->references.packfile, file_path))
516
+ return 0;
534
517
 
535
518
  if (data->list_flags != GIT_REF_LISTALL) {
536
519
  if ((data->list_flags & loose_guess_rtype(full_path)) == 0)
537
- return GIT_SUCCESS; /* we are filtering out this reference */
520
+ return 0; /* we are filtering out this reference */
538
521
  }
539
522
 
540
523
  return data->callback(file_path, data->callback_payload);
541
524
  }
542
525
 
543
- static int _dirent_loose_load(void *data, char *full_path)
526
+ static int _dirent_loose_load(void *data, git_buf *full_path)
544
527
  {
545
528
  git_repository *repository = (git_repository *)data;
546
529
  void *old_ref = NULL;
547
530
  struct packref *ref;
548
- char *file_path;
549
- int error;
531
+ const char *file_path;
532
+ int err;
550
533
 
551
- if (git_futils_isdir(full_path) == GIT_SUCCESS)
552
- return git_futils_direach(
553
- full_path, GIT_PATH_MAX,
554
- _dirent_loose_load, repository);
534
+ if (git_path_isdir(full_path->ptr) == true)
535
+ return git_path_direach(full_path, _dirent_loose_load, repository);
555
536
 
556
- file_path = full_path + strlen(repository->path_repository);
557
- error = loose_lookup_to_packfile(&ref, repository, file_path);
537
+ file_path = full_path->ptr + strlen(repository->path_repository);
558
538
 
559
- if (error == GIT_SUCCESS) {
560
-
561
- if (git_hashtable_insert2(
562
- repository->references.packfile,
563
- ref->name, ref, &old_ref) < GIT_SUCCESS) {
564
- free(ref);
565
- return GIT_ENOMEM;
566
- }
539
+ if (loose_lookup_to_packfile(&ref, repository, file_path) < 0)
540
+ return -1;
567
541
 
568
- if (old_ref != NULL)
569
- free(old_ref);
542
+ git_strmap_insert2(
543
+ repository->references.packfile, ref->name, ref, old_ref, err);
544
+ if (err < 0) {
545
+ git__free(ref);
546
+ return -1;
570
547
  }
571
548
 
572
- return error == GIT_SUCCESS ?
573
- GIT_SUCCESS :
574
- git__rethrow(error, "Failed to load loose references into packfile");
549
+ git__free(old_ref);
550
+ return 0;
575
551
  }
576
552
 
577
553
  /*
@@ -582,21 +558,24 @@ static int _dirent_loose_load(void *data, char *full_path)
582
558
  */
583
559
  static int packed_loadloose(git_repository *repository)
584
560
  {
585
- char refs_path[GIT_PATH_MAX];
561
+ git_buf refs_path = GIT_BUF_INIT;
562
+ int result;
586
563
 
587
564
  /* the packfile must have been previously loaded! */
588
565
  assert(repository->references.packfile);
589
566
 
590
- git_path_join(refs_path, repository->path_repository, GIT_REFS_DIR);
567
+ if (git_buf_joinpath(&refs_path, repository->path_repository, GIT_REFS_DIR) < 0)
568
+ return -1;
591
569
 
592
570
  /*
593
571
  * Load all the loose files from disk into the Packfile table.
594
572
  * This will overwrite any old packed entries with their
595
573
  * updated loose versions
596
574
  */
597
- return git_futils_direach(
598
- refs_path, GIT_PATH_MAX,
599
- _dirent_loose_load, repository);
575
+ result = git_path_direach(&refs_path, _dirent_loose_load, repository);
576
+ git_buf_free(&refs_path);
577
+
578
+ return result;
600
579
  }
601
580
 
602
581
  /*
@@ -604,7 +583,6 @@ static int packed_loadloose(git_repository *repository)
604
583
  */
605
584
  static int packed_write_ref(struct packref *ref, git_filebuf *file)
606
585
  {
607
- int error;
608
586
  char oid[GIT_OID_HEXSZ + 1];
609
587
 
610
588
  git_oid_fmt(oid, &ref->oid);
@@ -625,14 +603,14 @@ static int packed_write_ref(struct packref *ref, git_filebuf *file)
625
603
  git_oid_fmt(peel, &ref->peel);
626
604
  peel[GIT_OID_HEXSZ] = 0;
627
605
 
628
- error = git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->name, peel);
606
+ if (git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->name, peel) < 0)
607
+ return -1;
629
608
  } else {
630
- error = git_filebuf_printf(file, "%s %s\n", oid, ref->name);
609
+ if (git_filebuf_printf(file, "%s %s\n", oid, ref->name) < 0)
610
+ return -1;
631
611
  }
632
612
 
633
- return error == GIT_SUCCESS ?
634
- GIT_SUCCESS :
635
- git__rethrow(error, "Failed to write packed reference");
613
+ return 0;
636
614
  }
637
615
 
638
616
  /*
@@ -646,24 +624,22 @@ static int packed_write_ref(struct packref *ref, git_filebuf *file)
646
624
  static int packed_find_peel(git_repository *repo, struct packref *ref)
647
625
  {
648
626
  git_object *object;
649
- int error;
650
627
 
651
628
  if (ref->flags & GIT_PACKREF_HAS_PEEL)
652
- return GIT_SUCCESS;
629
+ return 0;
653
630
 
654
631
  /*
655
632
  * Only applies to tags, i.e. references
656
633
  * in the /refs/tags folder
657
634
  */
658
635
  if (git__prefixcmp(ref->name, GIT_REFS_TAGS_DIR) != 0)
659
- return GIT_SUCCESS;
636
+ return 0;
660
637
 
661
638
  /*
662
639
  * Find the tagged object in the repository
663
640
  */
664
- error = git_object_lookup(&object, repo, &ref->oid, GIT_OBJ_ANY);
665
- if (error < GIT_SUCCESS)
666
- return git__throw(GIT_EOBJCORRUPTED, "Failed to find packed reference");
641
+ if (git_object_lookup(&object, repo, &ref->oid, GIT_OBJ_ANY) < 0)
642
+ return -1;
667
643
 
668
644
  /*
669
645
  * If the tagged object is a Tag object, we need to resolve it;
@@ -687,7 +663,7 @@ static int packed_find_peel(git_repository *repo, struct packref *ref)
687
663
  }
688
664
 
689
665
  git_object_free(object);
690
- return GIT_SUCCESS;
666
+ return 0;
691
667
  }
692
668
 
693
669
  /*
@@ -704,8 +680,8 @@ static int packed_find_peel(git_repository *repo, struct packref *ref)
704
680
  static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
705
681
  {
706
682
  unsigned int i;
707
- char full_path[GIT_PATH_MAX];
708
- int error = GIT_SUCCESS;
683
+ git_buf full_path = GIT_BUF_INIT;
684
+ int failed = 0;
709
685
 
710
686
  for (i = 0; i < packing_list->length; ++i) {
711
687
  struct packref *ref = git_vector_get(packing_list, i);
@@ -713,11 +689,19 @@ static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
713
689
  if ((ref->flags & GIT_PACKREF_WAS_LOOSE) == 0)
714
690
  continue;
715
691
 
716
- git_path_join(full_path, repo->path_repository, ref->name);
692
+ if (git_buf_joinpath(&full_path, repo->path_repository, ref->name) < 0)
693
+ return -1; /* critical; do not try to recover on oom */
694
+
695
+ if (git_path_exists(full_path.ptr) == true && p_unlink(full_path.ptr) < 0) {
696
+ if (failed)
697
+ continue;
717
698
 
718
- if (git_futils_exists(full_path) == GIT_SUCCESS &&
719
- p_unlink(full_path) < GIT_SUCCESS)
720
- error = GIT_EOSERR;
699
+ giterr_set(GITERR_REFERENCE,
700
+ "Failed to remove loose reference '%s' after packing: %s",
701
+ full_path.ptr, strerror(errno));
702
+
703
+ failed = 1;
704
+ }
721
705
 
722
706
  /*
723
707
  * if we fail to remove a single file, this is *not* good,
@@ -727,9 +711,8 @@ static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
727
711
  */
728
712
  }
729
713
 
730
- return error == GIT_SUCCESS ?
731
- GIT_SUCCESS :
732
- git__rethrow(error, "Failed to remove loose packed reference");
714
+ git_buf_free(&full_path);
715
+ return failed ? -1 : 0;
733
716
  }
734
717
 
735
718
  static int packed_sort(const void *a, const void *b)
@@ -746,202 +729,271 @@ static int packed_sort(const void *a, const void *b)
746
729
  static int packed_write(git_repository *repo)
747
730
  {
748
731
  git_filebuf pack_file = GIT_FILEBUF_INIT;
749
- int error;
750
732
  unsigned int i;
751
- char pack_file_path[GIT_PATH_MAX];
752
-
733
+ git_buf pack_file_path = GIT_BUF_INIT;
753
734
  git_vector packing_list;
754
- size_t total_refs;
735
+ unsigned int total_refs;
755
736
 
756
737
  assert(repo && repo->references.packfile);
757
738
 
758
- total_refs = repo->references.packfile->key_count;
759
- if ((error =
760
- git_vector_init(&packing_list, total_refs, packed_sort)) < GIT_SUCCESS)
761
- return git__rethrow(error, "Failed to init packed refernces list");
739
+ total_refs =
740
+ (unsigned int)git_strmap_num_entries(repo->references.packfile);
741
+
742
+ if (git_vector_init(&packing_list, total_refs, packed_sort) < 0)
743
+ return -1;
762
744
 
763
745
  /* Load all the packfile into a vector */
764
746
  {
765
747
  struct packref *reference;
766
- const void *GIT_UNUSED(_unused);
767
748
 
768
- GIT_HASHTABLE_FOREACH(repo->references.packfile, _unused, reference,
769
- /* cannot fail: vector already has the right size */
749
+ /* cannot fail: vector already has the right size */
750
+ git_strmap_foreach_value(repo->references.packfile, reference, {
770
751
  git_vector_insert(&packing_list, reference);
771
- );
752
+ });
772
753
  }
773
754
 
774
755
  /* sort the vector so the entries appear sorted on the packfile */
775
756
  git_vector_sort(&packing_list);
776
757
 
777
758
  /* Now we can open the file! */
778
- git_path_join(pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE);
779
- if ((error = git_filebuf_open(&pack_file, pack_file_path, 0)) < GIT_SUCCESS)
780
- return git__rethrow(error, "Failed to write open packed references file");
759
+ if (git_buf_joinpath(&pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE) < 0)
760
+ goto cleanup_memory;
761
+
762
+ if (git_filebuf_open(&pack_file, pack_file_path.ptr, 0) < 0)
763
+ goto cleanup_packfile;
781
764
 
782
765
  /* Packfiles have a header... apparently
783
766
  * This is in fact not required, but we might as well print it
784
767
  * just for kicks */
785
- if ((error =
786
- git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER)) < GIT_SUCCESS)
787
- return git__rethrow(error, "Failed to write packed references file header");
768
+ if (git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER) < 0)
769
+ goto cleanup_packfile;
788
770
 
789
771
  for (i = 0; i < packing_list.length; ++i) {
790
772
  struct packref *ref = (struct packref *)git_vector_get(&packing_list, i);
791
773
 
792
- if ((error = packed_find_peel(repo, ref)) < GIT_SUCCESS) {
793
- error = git__throw(GIT_EOBJCORRUPTED,
794
- "A reference cannot be peeled");
795
- goto cleanup;
796
- }
774
+ if (packed_find_peel(repo, ref) < 0)
775
+ goto cleanup_packfile;
797
776
 
798
- if ((error = packed_write_ref(ref, &pack_file)) < GIT_SUCCESS)
799
- goto cleanup;
777
+ if (packed_write_ref(ref, &pack_file) < 0)
778
+ goto cleanup_packfile;
800
779
  }
801
780
 
802
- cleanup:
803
781
  /* if we've written all the references properly, we can commit
804
782
  * the packfile to make the changes effective */
805
- if (error == GIT_SUCCESS) {
806
- error = git_filebuf_commit(&pack_file, GIT_PACKEDREFS_FILE_MODE);
783
+ if (git_filebuf_commit(&pack_file, GIT_PACKEDREFS_FILE_MODE) < 0)
784
+ goto cleanup_memory;
807
785
 
808
- /* when and only when the packfile has been properly written,
809
- * we can go ahead and remove the loose refs */
810
- if (error == GIT_SUCCESS) {
811
- struct stat st;
786
+ /* when and only when the packfile has been properly written,
787
+ * we can go ahead and remove the loose refs */
788
+ if (packed_remove_loose(repo, &packing_list) < 0)
789
+ goto cleanup_memory;
812
790
 
813
- error = packed_remove_loose(repo, &packing_list);
791
+ {
792
+ struct stat st;
793
+ if (p_stat(pack_file_path.ptr, &st) == 0)
794
+ repo->references.packfile_time = st.st_mtime;
795
+ }
814
796
 
815
- if (p_stat(pack_file_path, &st) == GIT_SUCCESS)
816
- repo->references.packfile_time = st.st_mtime;
817
- }
818
- }
819
- else git_filebuf_cleanup(&pack_file);
797
+ git_vector_free(&packing_list);
798
+ git_buf_free(&pack_file_path);
799
+
800
+ /* we're good now */
801
+ return 0;
802
+
803
+ cleanup_packfile:
804
+ git_filebuf_cleanup(&pack_file);
820
805
 
806
+ cleanup_memory:
821
807
  git_vector_free(&packing_list);
808
+ git_buf_free(&pack_file_path);
822
809
 
823
- return error == GIT_SUCCESS ?
824
- GIT_SUCCESS :
825
- git__rethrow(error, "Failed to write packed references file");
810
+ return -1;
826
811
  }
827
812
 
813
+ struct reference_available_t {
814
+ const char *new_ref;
815
+ const char *old_ref;
816
+ int available;
817
+ };
818
+
828
819
  static int _reference_available_cb(const char *ref, void *data)
829
820
  {
830
- const char *new, *old;
831
- const char **refs;
821
+ struct reference_available_t *d;
832
822
 
833
823
  assert(ref && data);
824
+ d = (struct reference_available_t *)data;
834
825
 
835
- refs = (const char **)data;
836
-
837
- new = (const char *)refs[0];
838
- old = (const char *)refs[1];
839
-
840
- if (!old || strcmp(old, ref)) {
841
- int reflen = strlen(ref);
842
- int newlen = strlen(new);
843
- int cmplen = reflen < newlen ? reflen : newlen;
844
- const char *lead = reflen < newlen ? new : ref;
826
+ if (!d->old_ref || strcmp(d->old_ref, ref)) {
827
+ size_t reflen = strlen(ref);
828
+ size_t newlen = strlen(d->new_ref);
829
+ size_t cmplen = reflen < newlen ? reflen : newlen;
830
+ const char *lead = reflen < newlen ? d->new_ref : ref;
845
831
 
846
- if (!strncmp(new, ref, cmplen) &&
847
- lead[cmplen] == '/')
848
- return GIT_EEXISTS;
832
+ if (!strncmp(d->new_ref, ref, cmplen) && lead[cmplen] == '/') {
833
+ d->available = 0;
834
+ return -1;
835
+ }
849
836
  }
850
837
 
851
- return GIT_SUCCESS;
838
+ return 0;
852
839
  }
853
840
 
854
- static int reference_available(
841
+ static int reference_path_available(
855
842
  git_repository *repo,
856
843
  const char *ref,
857
844
  const char* old_ref)
858
845
  {
859
- const char *refs[2];
846
+ struct reference_available_t data;
860
847
 
861
- refs[0] = ref;
862
- refs[1] = old_ref;
848
+ data.new_ref = ref;
849
+ data.old_ref = old_ref;
850
+ data.available = 1;
863
851
 
864
852
  if (git_reference_foreach(repo, GIT_REF_LISTALL,
865
- _reference_available_cb, (void *)refs) < 0) {
866
- return git__throw(GIT_EEXISTS,
867
- "Reference name `%s` conflicts with existing reference", ref);
853
+ _reference_available_cb, (void *)&data) < 0)
854
+ return -1;
855
+
856
+ if (!data.available) {
857
+ giterr_set(GITERR_REFERENCE,
858
+ "The path to reference '%s' collides with an existing one", ref);
859
+ return -1;
868
860
  }
869
861
 
870
- return GIT_SUCCESS;
862
+ return 0;
871
863
  }
872
864
 
873
865
  static int reference_exists(int *exists, git_repository *repo, const char *ref_name)
874
866
  {
875
- int error;
876
- char ref_path[GIT_PATH_MAX];
867
+ git_buf ref_path = GIT_BUF_INIT;
877
868
 
878
- error = packed_load(repo);
879
- if (error < GIT_SUCCESS)
880
- return git__rethrow(error, "Cannot resolve if a reference exists");
869
+ if (packed_load(repo) < 0)
870
+ return -1;
881
871
 
882
- git_path_join(ref_path, repo->path_repository, ref_name);
872
+ if (git_buf_joinpath(&ref_path, repo->path_repository, ref_name) < 0)
873
+ return -1;
883
874
 
884
- if (git_futils_isfile(ref_path) == GIT_SUCCESS ||
885
- git_hashtable_lookup(repo->references.packfile, ref_path) != NULL) {
875
+ if (git_path_isfile(ref_path.ptr) == true ||
876
+ git_strmap_exists(repo->references.packfile, ref_path.ptr))
877
+ {
886
878
  *exists = 1;
887
879
  } else {
888
880
  *exists = 0;
889
881
  }
890
882
 
891
- return GIT_SUCCESS;
883
+ git_buf_free(&ref_path);
884
+ return 0;
885
+ }
886
+
887
+ /*
888
+ * Check if a reference could be written to disk, based on:
889
+ *
890
+ * - Whether a reference with the same name already exists,
891
+ * and we are allowing or disallowing overwrites
892
+ *
893
+ * - Whether the name of the reference would collide with
894
+ * an existing path
895
+ */
896
+ static int reference_can_write(
897
+ git_repository *repo,
898
+ const char *refname,
899
+ const char *previous_name,
900
+ int force)
901
+ {
902
+ /* see if the reference shares a path with an existing reference;
903
+ * if a path is shared, we cannot create the reference, even when forcing */
904
+ if (reference_path_available(repo, refname, previous_name) < 0)
905
+ return -1;
906
+
907
+ /* check if the reference actually exists, but only if we are not forcing
908
+ * the rename. If we are forcing, it's OK to overwrite */
909
+ if (!force) {
910
+ int exists;
911
+
912
+ if (reference_exists(&exists, repo, refname) < 0)
913
+ return -1;
914
+
915
+ /* We cannot proceed if the reference already exists and we're not forcing
916
+ * the rename; the existing one would be overwritten */
917
+ if (exists) {
918
+ giterr_set(GITERR_REFERENCE,
919
+ "A reference with that name (%s) already exists", refname);
920
+ return GIT_EEXISTS;
921
+ }
922
+ }
923
+
924
+ /* FIXME: if the reference exists and we are forcing, do we really need to
925
+ * remove the reference first?
926
+ *
927
+ * Two cases:
928
+ *
929
+ * - the reference already exists and is loose: not a problem, the file
930
+ * gets overwritten on disk
931
+ *
932
+ * - the reference already exists and is packed: we write a new one as
933
+ * loose, which by all means renders the packed one useless
934
+ */
935
+
936
+ return 0;
892
937
  }
893
938
 
939
+
894
940
  static int packed_lookup(git_reference *ref)
895
941
  {
896
- int error;
897
942
  struct packref *pack_ref = NULL;
943
+ git_strmap *packfile_refs;
944
+ khiter_t pos;
898
945
 
899
- error = packed_load(ref->owner);
900
- if (error < GIT_SUCCESS)
901
- return git__rethrow(error,
902
- "Failed to lookup reference from packfile");
946
+ if (packed_load(ref->owner) < 0)
947
+ return -1;
903
948
 
904
- if (ref->flags & GIT_REF_PACKED &&
949
+ /* maybe the packfile hasn't changed at all, so we don't
950
+ * have to re-lookup the reference */
951
+ if ((ref->flags & GIT_REF_PACKED) &&
905
952
  ref->mtime == ref->owner->references.packfile_time)
906
- return GIT_SUCCESS;
953
+ return 0;
907
954
 
908
- if (ref->flags & GIT_REF_SYMBOLIC)
909
- free(ref->target.symbolic);
955
+ if (ref->flags & GIT_REF_SYMBOLIC) {
956
+ git__free(ref->target.symbolic);
957
+ ref->target.symbolic = NULL;
958
+ }
910
959
 
911
960
  /* Look up on the packfile */
912
- pack_ref = git_hashtable_lookup(ref->owner->references.packfile, ref->name);
913
- if (pack_ref == NULL)
914
- return git__throw(GIT_ENOTFOUND,
915
- "Failed to lookup reference from packfile");
961
+ packfile_refs = ref->owner->references.packfile;
962
+ pos = git_strmap_lookup_index(packfile_refs, ref->name);
963
+ if (!git_strmap_valid_index(packfile_refs, pos)) {
964
+ giterr_set(GITERR_REFERENCE, "Reference '%s' not found", ref->name);
965
+ return GIT_ENOTFOUND;
966
+ }
967
+
968
+ pack_ref = git_strmap_value_at(packfile_refs, pos);
916
969
 
917
970
  ref->flags = GIT_REF_OID | GIT_REF_PACKED;
918
971
  ref->mtime = ref->owner->references.packfile_time;
919
972
  git_oid_cpy(&ref->target.oid, &pack_ref->oid);
920
973
 
921
- return GIT_SUCCESS;
974
+ return 0;
922
975
  }
923
976
 
924
977
  static int reference_lookup(git_reference *ref)
925
978
  {
926
- int error_loose, error_packed;
979
+ int result;
927
980
 
928
- error_loose = loose_lookup(ref);
929
- if (error_loose == GIT_SUCCESS)
930
- return GIT_SUCCESS;
981
+ result = loose_lookup(ref);
982
+ if (result == 0)
983
+ return 0;
931
984
 
932
- error_packed = packed_lookup(ref);
933
- if (error_packed == GIT_SUCCESS)
934
- return GIT_SUCCESS;
985
+ /* only try to lookup this reference on the packfile if it
986
+ * wasn't found on the loose refs; not if there was a critical error */
987
+ if (result == GIT_ENOTFOUND) {
988
+ giterr_clear();
989
+ result = packed_lookup(ref);
990
+ if (result == 0)
991
+ return 0;
992
+ }
935
993
 
994
+ /* unexpected error; free the reference */
936
995
  git_reference_free(ref);
937
-
938
- if (error_loose != GIT_ENOTFOUND)
939
- return git__rethrow(error_loose, "Failed to lookup reference");
940
-
941
- if (error_packed != GIT_ENOTFOUND)
942
- return git__rethrow(error_packed, "Failed to lookup reference");
943
-
944
- return git__throw(GIT_ENOTFOUND, "Reference not found");
996
+ return result;
945
997
  }
946
998
 
947
999
  /*
@@ -951,7 +1003,7 @@ static int reference_lookup(git_reference *ref)
951
1003
  */
952
1004
  static int reference_delete(git_reference *ref)
953
1005
  {
954
- int error;
1006
+ int result;
955
1007
 
956
1008
  assert(ref);
957
1009
 
@@ -959,85 +1011,149 @@ static int reference_delete(git_reference *ref)
959
1011
  * We need to reload the packfile, remove the reference from the
960
1012
  * packing list, and repack */
961
1013
  if (ref->flags & GIT_REF_PACKED) {
1014
+ git_strmap *packfile_refs;
1015
+ struct packref *packref;
1016
+ khiter_t pos;
1017
+
962
1018
  /* load the existing packfile */
963
- if ((error = packed_load(ref->owner)) < GIT_SUCCESS)
964
- return git__rethrow(error, "Failed to delete reference");
1019
+ if (packed_load(ref->owner) < 0)
1020
+ return -1;
1021
+
1022
+ packfile_refs = ref->owner->references.packfile;
1023
+ pos = git_strmap_lookup_index(packfile_refs, ref->name);
1024
+ if (!git_strmap_valid_index(packfile_refs, pos)) {
1025
+ giterr_set(GITERR_REFERENCE,
1026
+ "Reference %s stopped existing in the packfile", ref->name);
1027
+ return -1;
1028
+ }
965
1029
 
966
- if (git_hashtable_remove(ref->owner->references.packfile,
967
- ref->name) < GIT_SUCCESS)
968
- return git__throw(GIT_ENOTFOUND, "Reference not found");
1030
+ packref = git_strmap_value_at(packfile_refs, pos);
1031
+ git_strmap_delete_at(packfile_refs, pos);
969
1032
 
970
- error = packed_write(ref->owner);
1033
+ git__free(packref);
1034
+ if (packed_write(ref->owner) < 0)
1035
+ return -1;
971
1036
 
972
1037
  /* If the reference is loose, we can just remove the reference
973
1038
  * from the filesystem */
974
1039
  } else {
975
- char full_path[GIT_PATH_MAX];
976
1040
  git_reference *ref_in_pack;
1041
+ git_buf full_path = GIT_BUF_INIT;
977
1042
 
978
- git_path_join(full_path, ref->owner->path_repository, ref->name);
1043
+ if (git_buf_joinpath(&full_path, ref->owner->path_repository, ref->name) < 0)
1044
+ return -1;
979
1045
 
980
- error = p_unlink(full_path);
981
- if (error < GIT_SUCCESS)
982
- goto cleanup;
1046
+ result = p_unlink(full_path.ptr);
1047
+ git_buf_free(&full_path); /* done with path at this point */
1048
+
1049
+ if (result < 0) {
1050
+ giterr_set(GITERR_OS, "Failed to unlink '%s'", full_path.ptr);
1051
+ return -1;
1052
+ }
983
1053
 
984
1054
  /* When deleting a loose reference, we have to ensure that an older
985
1055
  * packed version of it doesn't exist */
986
- if (git_reference_lookup(&ref_in_pack, ref->owner,
987
- ref->name) == GIT_SUCCESS) {
1056
+ if (git_reference_lookup(&ref_in_pack, ref->owner, ref->name) == 0) {
988
1057
  assert((ref_in_pack->flags & GIT_REF_PACKED) != 0);
989
- error = git_reference_delete(ref_in_pack);
1058
+ return git_reference_delete(ref_in_pack);
990
1059
  }
1060
+
1061
+ giterr_clear();
991
1062
  }
992
1063
 
993
- cleanup:
994
- return error == GIT_SUCCESS ?
995
- GIT_SUCCESS :
996
- git__rethrow(error, "Failed to delete reference");
1064
+ return 0;
997
1065
  }
998
1066
 
999
1067
  int git_reference_delete(git_reference *ref)
1000
1068
  {
1001
- int error = reference_delete(ref);
1002
- if (error < GIT_SUCCESS)
1003
- return error;
1004
-
1069
+ int result = reference_delete(ref);
1005
1070
  git_reference_free(ref);
1006
- return GIT_SUCCESS;
1071
+ return result;
1007
1072
  }
1008
1073
 
1009
-
1010
1074
  int git_reference_lookup(git_reference **ref_out,
1011
1075
  git_repository *repo, const char *name)
1076
+ {
1077
+ return git_reference_lookup_resolved(ref_out, repo, name, 0);
1078
+ }
1079
+
1080
+ int git_reference_name_to_oid(
1081
+ git_oid *out, git_repository *repo, const char *name)
1012
1082
  {
1013
1083
  int error;
1014
- char normalized_name[GIT_REFNAME_MAX];
1015
- git_reference *ref = NULL;
1084
+ git_reference *ref;
1085
+
1086
+ if ((error = git_reference_lookup_resolved(&ref, repo, name, -1)) < 0)
1087
+ return error;
1088
+
1089
+ git_oid_cpy(out, git_reference_oid(ref));
1090
+ git_reference_free(ref);
1091
+ return 0;
1092
+ }
1093
+
1094
+ int git_reference_lookup_resolved(
1095
+ git_reference **ref_out,
1096
+ git_repository *repo,
1097
+ const char *name,
1098
+ int max_nesting)
1099
+ {
1100
+ git_reference *scan;
1101
+ int result, nesting;
1016
1102
 
1017
1103
  assert(ref_out && repo && name);
1018
1104
 
1019
1105
  *ref_out = NULL;
1020
1106
 
1021
- error = normalize_name(normalized_name, sizeof(normalized_name), name, 0);
1022
- if (error < GIT_SUCCESS)
1023
- return git__rethrow(error, "Failed to lookup reference");
1107
+ if (max_nesting > MAX_NESTING_LEVEL)
1108
+ max_nesting = MAX_NESTING_LEVEL;
1109
+ else if (max_nesting < 0)
1110
+ max_nesting = DEFAULT_NESTING_LEVEL;
1024
1111
 
1025
- error = reference_create(&ref, repo, normalized_name);
1026
- if (error < GIT_SUCCESS)
1027
- return git__rethrow(error, "Failed to lookup reference");
1112
+ scan = git__calloc(1, sizeof(git_reference));
1113
+ GITERR_CHECK_ALLOC(scan);
1028
1114
 
1029
- error = reference_lookup(ref);
1030
- if (error < GIT_SUCCESS)
1031
- return git__rethrow(error, "Failed to lookup reference");
1115
+ scan->name = git__calloc(GIT_REFNAME_MAX + 1, sizeof(char));
1116
+ GITERR_CHECK_ALLOC(scan->name);
1032
1117
 
1033
- *ref_out = ref;
1034
- return GIT_SUCCESS;
1118
+ if ((result = normalize_name(scan->name, GIT_REFNAME_MAX, name, 0)) < 0) {
1119
+ git_reference_free(scan);
1120
+ return result;
1121
+ }
1122
+
1123
+ scan->target.symbolic = git__strdup(scan->name);
1124
+ GITERR_CHECK_ALLOC(scan->target.symbolic);
1125
+
1126
+ scan->owner = repo;
1127
+ scan->flags = GIT_REF_SYMBOLIC;
1128
+
1129
+ for (nesting = max_nesting;
1130
+ nesting >= 0 && (scan->flags & GIT_REF_SYMBOLIC) != 0;
1131
+ nesting--)
1132
+ {
1133
+ if (nesting != max_nesting)
1134
+ strncpy(scan->name, scan->target.symbolic, GIT_REFNAME_MAX);
1135
+
1136
+ scan->mtime = 0;
1137
+
1138
+ if ((result = reference_lookup(scan)) < 0)
1139
+ return result; /* lookup git_reference_free on scan already */
1140
+ }
1141
+
1142
+ if ((scan->flags & GIT_REF_OID) == 0 && max_nesting != 0) {
1143
+ giterr_set(GITERR_REFERENCE,
1144
+ "Cannot resolve reference (>%u levels deep)", max_nesting);
1145
+ git_reference_free(scan);
1146
+ return -1;
1147
+ }
1148
+
1149
+ *ref_out = scan;
1150
+ return 0;
1035
1151
  }
1036
1152
 
1037
1153
  /**
1038
1154
  * Getters
1039
1155
  */
1040
- git_rtype git_reference_type(git_reference *ref)
1156
+ git_ref_t git_reference_type(git_reference *ref)
1041
1157
  {
1042
1158
  assert(ref);
1043
1159
 
@@ -1096,43 +1212,32 @@ int git_reference_create_symbolic(
1096
1212
  int force)
1097
1213
  {
1098
1214
  char normalized[GIT_REFNAME_MAX];
1099
- int ref_exists, error = GIT_SUCCESS;
1100
1215
  git_reference *ref = NULL;
1101
1216
 
1102
- error = normalize_name(normalized, sizeof(normalized), name, 0);
1103
- if (error < GIT_SUCCESS)
1104
- goto cleanup;
1105
-
1106
- if ((error = reference_exists(&ref_exists, repo, normalized) < GIT_SUCCESS))
1107
- return git__rethrow(error, "Failed to create symbolic reference");
1217
+ if (normalize_name(normalized, sizeof(normalized), name, 0) < 0)
1218
+ return -1;
1108
1219
 
1109
- if (ref_exists && !force)
1110
- return git__throw(GIT_EEXISTS,
1111
- "Failed to create symbolic reference. Reference already exists");
1220
+ if (reference_can_write(repo, normalized, NULL, force) < 0)
1221
+ return -1;
1112
1222
 
1113
- error = reference_create(&ref, repo, normalized);
1114
- if (error < GIT_SUCCESS)
1115
- goto cleanup;
1223
+ if (reference_alloc(&ref, repo, normalized) < 0)
1224
+ return -1;
1116
1225
 
1117
1226
  ref->flags |= GIT_REF_SYMBOLIC;
1118
1227
 
1119
1228
  /* set the target; this will normalize the name automatically
1120
1229
  * and write the reference on disk */
1121
- error = git_reference_set_target(ref, target);
1122
- if (error < GIT_SUCCESS)
1123
- goto cleanup;
1124
-
1230
+ if (git_reference_set_target(ref, target) < 0) {
1231
+ git_reference_free(ref);
1232
+ return -1;
1233
+ }
1125
1234
  if (ref_out == NULL) {
1126
1235
  git_reference_free(ref);
1127
1236
  } else {
1128
1237
  *ref_out = ref;
1129
1238
  }
1130
1239
 
1131
- return GIT_SUCCESS;
1132
-
1133
- cleanup:
1134
- git_reference_free(ref);
1135
- return git__rethrow(error, "Failed to create symbolic reference");
1240
+ return 0;
1136
1241
  }
1137
1242
 
1138
1243
  int git_reference_create_oid(
@@ -1142,34 +1247,25 @@ int git_reference_create_oid(
1142
1247
  const git_oid *id,
1143
1248
  int force)
1144
1249
  {
1145
- int error = GIT_SUCCESS, ref_exists;
1146
1250
  git_reference *ref = NULL;
1147
1251
  char normalized[GIT_REFNAME_MAX];
1148
1252
 
1149
- error = normalize_name(normalized, sizeof(normalized), name, 1);
1150
- if (error < GIT_SUCCESS)
1151
- goto cleanup;
1152
-
1153
- if ((error = reference_exists(&ref_exists, repo, normalized) < GIT_SUCCESS))
1154
- return git__rethrow(error, "Failed to create OID reference");
1253
+ if (normalize_name(normalized, sizeof(normalized), name, 1) < 0)
1254
+ return -1;
1155
1255
 
1156
- if (ref_exists && !force)
1157
- return git__throw(GIT_EEXISTS,
1158
- "Failed to create OID reference. Reference already exists");
1256
+ if (reference_can_write(repo, normalized, NULL, force) < 0)
1257
+ return -1;
1159
1258
 
1160
- if ((error = reference_available(repo, name, NULL)) < GIT_SUCCESS)
1161
- return git__rethrow(error, "Failed to create reference");
1162
-
1163
- error = reference_create(&ref, repo, name);
1164
- if (error < GIT_SUCCESS)
1165
- goto cleanup;
1259
+ if (reference_alloc(&ref, repo, name) < 0)
1260
+ return -1;
1166
1261
 
1167
1262
  ref->flags |= GIT_REF_OID;
1168
1263
 
1169
1264
  /* set the oid; this will write the reference on disk */
1170
- error = git_reference_set_oid(ref, id);
1171
- if (error < GIT_SUCCESS)
1172
- goto cleanup;
1265
+ if (git_reference_set_oid(ref, id) < 0) {
1266
+ git_reference_free(ref);
1267
+ return -1;
1268
+ }
1173
1269
 
1174
1270
  if (ref_out == NULL) {
1175
1271
  git_reference_free(ref);
@@ -1177,13 +1273,8 @@ int git_reference_create_oid(
1177
1273
  *ref_out = ref;
1178
1274
  }
1179
1275
 
1180
- return GIT_SUCCESS;
1181
-
1182
- cleanup:
1183
- git_reference_free(ref);
1184
- return git__rethrow(error, "Failed to create reference OID");
1276
+ return 0;
1185
1277
  }
1186
-
1187
1278
  /*
1188
1279
  * Change the OID target of a reference.
1189
1280
  *
@@ -1195,38 +1286,31 @@ cleanup:
1195
1286
  */
1196
1287
  int git_reference_set_oid(git_reference *ref, const git_oid *id)
1197
1288
  {
1198
- int error = GIT_SUCCESS, exists;
1199
1289
  git_odb *odb = NULL;
1200
1290
 
1201
- if ((ref->flags & GIT_REF_OID) == 0)
1202
- return git__throw(GIT_EINVALIDREFSTATE,
1203
- "Failed to set OID target of reference. Not an OID reference");
1291
+ if ((ref->flags & GIT_REF_OID) == 0) {
1292
+ giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference");
1293
+ return -1;
1294
+ }
1204
1295
 
1205
1296
  assert(ref->owner);
1206
1297
 
1207
- error = git_repository_odb__weakptr(&odb, ref->owner);
1208
- if (error < GIT_SUCCESS)
1209
- return error;
1210
-
1211
- exists = git_odb_exists(odb, id);
1212
-
1213
- git_odb_free(odb);
1298
+ if (git_repository_odb__weakptr(&odb, ref->owner) < 0)
1299
+ return -1;
1214
1300
 
1215
1301
  /* Don't let the user create references to OIDs that
1216
1302
  * don't exist in the ODB */
1217
- if (!exists)
1218
- return git__throw(GIT_ENOTFOUND,
1219
- "Failed to set OID target of reference. OID doesn't exist in ODB");
1303
+ if (!git_odb_exists(odb, id)) {
1304
+ giterr_set(GITERR_REFERENCE,
1305
+ "Target OID for the reference doesn't exist on the repository");
1306
+ return -1;
1307
+ }
1220
1308
 
1221
1309
  /* Update the OID value on `ref` */
1222
1310
  git_oid_cpy(&ref->target.oid, id);
1223
1311
 
1224
1312
  /* Write back to disk */
1225
- error = loose_write(ref);
1226
- if (error < GIT_SUCCESS)
1227
- return git__rethrow(error, "Failed to set OID target of reference");
1228
-
1229
- return GIT_SUCCESS;
1313
+ return loose_write(ref);
1230
1314
  }
1231
1315
 
1232
1316
  /*
@@ -1238,76 +1322,44 @@ int git_reference_set_oid(git_reference *ref, const git_oid *id)
1238
1322
  */
1239
1323
  int git_reference_set_target(git_reference *ref, const char *target)
1240
1324
  {
1241
- int error;
1242
1325
  char normalized[GIT_REFNAME_MAX];
1243
1326
 
1244
- if ((ref->flags & GIT_REF_SYMBOLIC) == 0)
1245
- return git__throw(GIT_EINVALIDREFSTATE,
1246
- "Failed to set reference target. Not a symbolic reference");
1327
+ if ((ref->flags & GIT_REF_SYMBOLIC) == 0) {
1328
+ giterr_set(GITERR_REFERENCE,
1329
+ "Cannot set symbolic target on a direct reference");
1330
+ return -1;
1331
+ }
1247
1332
 
1248
- error = normalize_name(normalized, sizeof(normalized), target, 0);
1249
- if (error < GIT_SUCCESS)
1250
- return git__rethrow(error,
1251
- "Failed to set reference target. Invalid target name");
1333
+ if (normalize_name(normalized, sizeof(normalized), target, 0))
1334
+ return -1;
1252
1335
 
1253
1336
  git__free(ref->target.symbolic);
1254
1337
  ref->target.symbolic = git__strdup(normalized);
1255
- if (ref->target.symbolic == NULL)
1256
- return GIT_ENOMEM;
1338
+ GITERR_CHECK_ALLOC(ref->target.symbolic);
1257
1339
 
1258
1340
  return loose_write(ref);
1259
1341
  }
1260
1342
 
1261
1343
  int git_reference_rename(git_reference *ref, const char *new_name, int force)
1262
1344
  {
1263
- int error;
1264
-
1265
- char aux_path[GIT_PATH_MAX];
1345
+ int result;
1346
+ git_buf aux_path = GIT_BUF_INIT;
1266
1347
  char normalized[GIT_REFNAME_MAX];
1267
1348
 
1268
1349
  const char *head_target = NULL;
1269
- git_reference *existing_ref = NULL, *head = NULL;
1270
-
1271
- error = normalize_name(normalized, sizeof(normalized),
1272
- new_name, ref->flags & GIT_REF_OID);
1350
+ git_reference *head = NULL;
1273
1351
 
1274
- if (error < GIT_SUCCESS)
1275
- return git__rethrow(error, "Failed to rename reference. Invalid name");
1352
+ if (normalize_name(normalized, sizeof(normalized),
1353
+ new_name, ref->flags & GIT_REF_OID) < 0)
1354
+ return -1;
1276
1355
 
1277
- new_name = normalized;
1356
+ if (reference_can_write(ref->owner, normalized, ref->name, force) < 0)
1357
+ return -1;
1278
1358
 
1279
- /* If we are forcing the rename, try to lookup a reference with the
1280
- * new one. If the lookup succeeds, we need to delete that ref
1281
- * before the renaming can proceed */
1282
- if (force) {
1283
- error = git_reference_lookup(&existing_ref, ref->owner, new_name);
1284
-
1285
- if (error == GIT_SUCCESS) {
1286
- error = git_reference_delete(existing_ref);
1287
- if (error < GIT_SUCCESS)
1288
- return git__rethrow(error,
1289
- "Failed to rename reference. "
1290
- "The existing reference cannot be deleted");
1291
- } else if (error != GIT_ENOTFOUND)
1292
- goto cleanup;
1293
-
1294
- /* If we're not forcing the rename, check if the reference exists.
1295
- * If it does, renaming cannot continue */
1296
- } else {
1297
- int exists;
1298
-
1299
- error = reference_exists(&exists, ref->owner, normalized);
1300
- if (error < GIT_SUCCESS)
1301
- goto cleanup;
1302
-
1303
- if (exists)
1304
- return git__throw(GIT_EEXISTS,
1305
- "Failed to rename reference. Reference already exists");
1306
- }
1307
-
1308
- if ((error = reference_available(ref->owner, new_name, ref->name)) < GIT_SUCCESS)
1309
- return git__rethrow(error,
1310
- "Failed to rename reference. Reference already exists");
1359
+ /* Initialize path now so we won't get an allocation failure once
1360
+ * we actually start removing things. */
1361
+ if (git_buf_joinpath(&aux_path, ref->owner->path_repository, new_name) < 0)
1362
+ return -1;
1311
1363
 
1312
1364
  /*
1313
1365
  * Now delete the old ref and remove an possibly existing directory
@@ -1315,55 +1367,54 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
1315
1367
  * method deletes the ref from disk but doesn't free the pointer, so
1316
1368
  * we can still access the ref's attributes for creating the new one
1317
1369
  */
1318
- if ((error = reference_delete(ref)) < GIT_SUCCESS)
1370
+ if (reference_delete(ref) < 0)
1319
1371
  goto cleanup;
1320
1372
 
1321
- git_path_join(aux_path, ref->owner->path_repository, new_name);
1322
- if (git_futils_exists(aux_path) == GIT_SUCCESS) {
1323
- if (git_futils_isdir(aux_path) == GIT_SUCCESS) {
1324
- if ((error = git_futils_rmdir_r(aux_path, 0)) < GIT_SUCCESS)
1325
- goto rollback;
1326
- } else goto rollback;
1327
- }
1328
-
1329
1373
  /*
1330
1374
  * Finally we can create the new reference.
1331
1375
  */
1332
1376
  if (ref->flags & GIT_REF_SYMBOLIC) {
1333
- error = git_reference_create_symbolic(
1334
- NULL, ref->owner, new_name, ref->target.symbolic, 0);
1377
+ result = git_reference_create_symbolic(
1378
+ NULL, ref->owner, new_name, ref->target.symbolic, force);
1335
1379
  } else {
1336
- error = git_reference_create_oid(
1337
- NULL, ref->owner, new_name, &ref->target.oid, 0);
1380
+ result = git_reference_create_oid(
1381
+ NULL, ref->owner, new_name, &ref->target.oid, force);
1338
1382
  }
1339
1383
 
1340
- if (error < GIT_SUCCESS)
1384
+ if (result < 0)
1341
1385
  goto rollback;
1342
1386
 
1343
1387
  /*
1344
1388
  * Check if we have to update HEAD.
1345
1389
  */
1346
- error = git_reference_lookup(&head, ref->owner, GIT_HEAD_FILE);
1347
- if (error < GIT_SUCCESS)
1390
+ if (git_reference_lookup(&head, ref->owner, GIT_HEAD_FILE) < 0) {
1391
+ giterr_set(GITERR_REFERENCE,
1392
+ "Failed to update HEAD after renaming reference");
1348
1393
  goto cleanup;
1394
+ }
1349
1395
 
1350
1396
  head_target = git_reference_target(head);
1351
1397
 
1352
1398
  if (head_target && !strcmp(head_target, ref->name)) {
1353
- error = git_reference_create_symbolic(
1354
- &head, ref->owner, "HEAD", new_name, 1);
1355
-
1356
- if (error < GIT_SUCCESS)
1399
+ if (git_reference_create_symbolic(&head, ref->owner, "HEAD", new_name, 1) < 0) {
1400
+ giterr_set(GITERR_REFERENCE,
1401
+ "Failed to update HEAD after renaming reference");
1357
1402
  goto cleanup;
1403
+ }
1358
1404
  }
1359
1405
 
1360
1406
  /*
1361
1407
  * Rename the reflog file.
1362
1408
  */
1363
- git_path_join_n(aux_path, 3, ref->owner->path_repository,
1364
- GIT_REFLOG_DIR, ref->name);
1365
- if (git_futils_exists(aux_path) == GIT_SUCCESS)
1366
- error = git_reflog_rename(ref, new_name);
1409
+ if (git_buf_join_n(&aux_path, '/', 3, ref->owner->path_repository, GIT_REFLOG_DIR, ref->name) < 0)
1410
+ goto cleanup;
1411
+
1412
+ if (git_path_exists(aux_path.ptr) == true) {
1413
+ if (git_reflog_rename(ref, new_name) < 0)
1414
+ goto cleanup;
1415
+ } else {
1416
+ giterr_clear();
1417
+ }
1367
1418
 
1368
1419
  /*
1369
1420
  * Change the name of the reference given by the user.
@@ -1374,89 +1425,49 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
1374
1425
  /* The reference is no longer packed */
1375
1426
  ref->flags &= ~GIT_REF_PACKED;
1376
1427
 
1428
+ git_reference_free(head);
1429
+ git_buf_free(&aux_path);
1430
+ return 0;
1431
+
1377
1432
  cleanup:
1378
- /* We no longer need the newly created reference nor the head */
1379
1433
  git_reference_free(head);
1380
- return error == GIT_SUCCESS ?
1381
- GIT_SUCCESS :
1382
- git__rethrow(error, "Failed to rename reference");
1434
+ git_buf_free(&aux_path);
1435
+ return -1;
1383
1436
 
1384
1437
  rollback:
1385
1438
  /*
1386
- * Try to create the old reference again.
1439
+ * Try to create the old reference again, ignore failures
1387
1440
  */
1388
1441
  if (ref->flags & GIT_REF_SYMBOLIC)
1389
- error = git_reference_create_symbolic(
1442
+ git_reference_create_symbolic(
1390
1443
  NULL, ref->owner, ref->name, ref->target.symbolic, 0);
1391
1444
  else
1392
- error = git_reference_create_oid(
1445
+ git_reference_create_oid(
1393
1446
  NULL, ref->owner, ref->name, &ref->target.oid, 0);
1394
1447
 
1395
1448
  /* The reference is no longer packed */
1396
1449
  ref->flags &= ~GIT_REF_PACKED;
1397
1450
 
1398
- return error == GIT_SUCCESS ?
1399
- git__rethrow(GIT_ERROR, "Failed to rename reference. Did rollback") :
1400
- git__rethrow(error, "Failed to rename reference. Failed to rollback");
1451
+ git_buf_free(&aux_path);
1452
+ return -1;
1401
1453
  }
1402
1454
 
1403
1455
  int git_reference_resolve(git_reference **ref_out, git_reference *ref)
1404
1456
  {
1405
- int error, i = 0;
1406
- git_repository *repo;
1407
-
1408
- assert(ref);
1409
-
1410
- *ref_out = NULL;
1411
- repo = ref->owner;
1412
-
1413
- /* If the reference is already resolved, we need to return a
1414
- * copy. Instead of duplicating `ref`, we look it up again to
1415
- * ensure the copy is out to date */
1416
1457
  if (ref->flags & GIT_REF_OID)
1417
1458
  return git_reference_lookup(ref_out, ref->owner, ref->name);
1418
-
1419
- /* Otherwise, keep iterating until the reference is resolved */
1420
- for (i = 0; i < MAX_NESTING_LEVEL; ++i) {
1421
- git_reference *new_ref;
1422
-
1423
- error = git_reference_lookup(&new_ref, repo, ref->target.symbolic);
1424
- if (error < GIT_SUCCESS)
1425
- return git__rethrow(error, "Failed to resolve reference");
1426
-
1427
- /* Free intermediate references, except for the original one
1428
- * we've received */
1429
- if (i > 0)
1430
- git_reference_free(ref);
1431
-
1432
- ref = new_ref;
1433
-
1434
- /* When the reference we've just looked up is an OID, we've
1435
- * successfully resolved the symbolic ref */
1436
- if (ref->flags & GIT_REF_OID) {
1437
- *ref_out = ref;
1438
- return GIT_SUCCESS;
1439
- }
1440
- }
1441
-
1442
- return git__throw(GIT_ENOMEM,
1443
- "Failed to resolve reference. Reference is too nested");
1459
+ else
1460
+ return git_reference_lookup_resolved(ref_out, ref->owner, ref->target.symbolic, -1);
1444
1461
  }
1445
1462
 
1446
1463
  int git_reference_packall(git_repository *repo)
1447
1464
  {
1448
- int error;
1465
+ if (packed_load(repo) < 0 || /* load the existing packfile */
1466
+ packed_loadloose(repo) < 0 || /* add all the loose refs */
1467
+ packed_write(repo) < 0) /* write back to disk */
1468
+ return -1;
1449
1469
 
1450
- /* load the existing packfile */
1451
- if ((error = packed_load(repo)) < GIT_SUCCESS)
1452
- return git__rethrow(error, "Failed to pack references");
1453
-
1454
- /* update it in-memory with all the loose references */
1455
- if ((error = packed_loadloose(repo)) < GIT_SUCCESS)
1456
- return git__rethrow(error, "Failed to pack references");
1457
-
1458
- /* write it back to disk */
1459
- return packed_write(repo);
1470
+ return 0;
1460
1471
  }
1461
1472
 
1462
1473
  int git_reference_foreach(
@@ -1465,23 +1476,23 @@ int git_reference_foreach(
1465
1476
  int (*callback)(const char *, void *),
1466
1477
  void *payload)
1467
1478
  {
1468
- int error;
1479
+ int result;
1469
1480
  struct dirent_list_data data;
1470
- char refs_path[GIT_PATH_MAX];
1481
+ git_buf refs_path = GIT_BUF_INIT;
1471
1482
 
1472
1483
  /* list all the packed references first */
1473
1484
  if (list_flags & GIT_REF_PACKED) {
1474
1485
  const char *ref_name;
1475
- void *GIT_UNUSED(_unused);
1486
+ void *ref;
1487
+ GIT_UNUSED(ref);
1476
1488
 
1477
- if ((error = packed_load(repo)) < GIT_SUCCESS)
1478
- return git__rethrow(error, "Failed to list references");
1489
+ if (packed_load(repo) < 0)
1490
+ return -1;
1479
1491
 
1480
- GIT_HASHTABLE_FOREACH(repo->references.packfile, ref_name, _unused,
1481
- if ((error = callback(ref_name, payload)) < GIT_SUCCESS)
1482
- return git__throw(error,
1483
- "Failed to list references. User callback failed");
1484
- );
1492
+ git_strmap_foreach(repo->references.packfile, ref_name, ref, {
1493
+ if (callback(ref_name, payload) < 0)
1494
+ return 0;
1495
+ });
1485
1496
  }
1486
1497
 
1487
1498
  /* now list the loose references, trying not to
@@ -1493,8 +1504,13 @@ int git_reference_foreach(
1493
1504
  data.callback = callback;
1494
1505
  data.callback_payload = payload;
1495
1506
 
1496
- git_path_join(refs_path, repo->path_repository, GIT_REFS_DIR);
1497
- return git_futils_direach(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
1507
+ if (git_buf_joinpath(&refs_path, repo->path_repository, GIT_REFS_DIR) < 0)
1508
+ return -1;
1509
+
1510
+ result = git_path_direach(&refs_path, _dirent_loose_listall, &data);
1511
+ git_buf_free(&refs_path);
1512
+
1513
+ return result;
1498
1514
  }
1499
1515
 
1500
1516
  static int cb__reflist_add(const char *ref, void *data)
@@ -1502,12 +1518,11 @@ static int cb__reflist_add(const char *ref, void *data)
1502
1518
  return git_vector_insert((git_vector *)data, git__strdup(ref));
1503
1519
  }
1504
1520
 
1505
- int git_reference_listall(
1521
+ int git_reference_list(
1506
1522
  git_strarray *array,
1507
1523
  git_repository *repo,
1508
1524
  unsigned int list_flags)
1509
1525
  {
1510
- int error;
1511
1526
  git_vector ref_list;
1512
1527
 
1513
1528
  assert(array && repo);
@@ -1515,48 +1530,37 @@ int git_reference_listall(
1515
1530
  array->strings = NULL;
1516
1531
  array->count = 0;
1517
1532
 
1518
- if (git_vector_init(&ref_list, 8, NULL) < GIT_SUCCESS)
1519
- return GIT_ENOMEM;
1533
+ if (git_vector_init(&ref_list, 8, NULL) < 0)
1534
+ return -1;
1520
1535
 
1521
- error = git_reference_foreach(
1522
- repo, list_flags, &cb__reflist_add, (void *)&ref_list);
1523
-
1524
- if (error < GIT_SUCCESS) {
1536
+ if (git_reference_foreach(
1537
+ repo, list_flags, &cb__reflist_add, (void *)&ref_list) < 0) {
1525
1538
  git_vector_free(&ref_list);
1526
- return error;
1539
+ return -1;
1527
1540
  }
1528
1541
 
1529
1542
  array->strings = (char **)ref_list.contents;
1530
1543
  array->count = ref_list.length;
1531
- return GIT_SUCCESS;
1544
+ return 0;
1532
1545
  }
1533
1546
 
1534
1547
  int git_reference_reload(git_reference *ref)
1535
1548
  {
1536
- int error = reference_lookup(ref);
1537
-
1538
- if (error < GIT_SUCCESS) {
1539
- git_reference_free(ref);
1540
- return git__rethrow(error, "Failed to reload reference");
1541
- }
1542
-
1543
- return GIT_SUCCESS;
1549
+ return reference_lookup(ref);
1544
1550
  }
1545
1551
 
1546
-
1547
1552
  void git_repository__refcache_free(git_refcache *refs)
1548
1553
  {
1549
1554
  assert(refs);
1550
1555
 
1551
1556
  if (refs->packfile) {
1552
- const void *GIT_UNUSED(_unused);
1553
1557
  struct packref *reference;
1554
1558
 
1555
- GIT_HASHTABLE_FOREACH(refs->packfile, _unused, reference,
1556
- free(reference);
1557
- );
1559
+ git_strmap_foreach_value(refs->packfile, reference, {
1560
+ git__free(reference);
1561
+ });
1558
1562
 
1559
- git_hashtable_free(refs->packfile);
1563
+ git_strmap_free(refs->packfile);
1560
1564
  }
1561
1565
  }
1562
1566
 
@@ -1600,33 +1604,26 @@ static int normalize_name(
1600
1604
 
1601
1605
  /* A refname can not be empty */
1602
1606
  if (name_end == name)
1603
- return git__throw(GIT_EINVALIDREFNAME,
1604
- "Failed to normalize name. Reference name is empty");
1607
+ goto invalid_name;
1605
1608
 
1606
1609
  /* A refname can not end with a dot or a slash */
1607
1610
  if (*(name_end - 1) == '.' || *(name_end - 1) == '/')
1608
- return git__throw(GIT_EINVALIDREFNAME,
1609
- "Failed to normalize name. Reference name ends with dot or slash");
1611
+ goto invalid_name;
1610
1612
 
1611
1613
  while (current < name_end && out_size) {
1612
1614
  if (!is_valid_ref_char(*current))
1613
- return git__throw(GIT_EINVALIDREFNAME,
1614
- "Failed to normalize name. "
1615
- "Reference name contains invalid characters");
1615
+ goto invalid_name;
1616
1616
 
1617
1617
  if (buffer_out > buffer_out_start) {
1618
1618
  char prev = *(buffer_out - 1);
1619
1619
 
1620
1620
  /* A refname can not start with a dot nor contain a double dot */
1621
1621
  if (*current == '.' && ((prev == '.') || (prev == '/')))
1622
- return git__throw(GIT_EINVALIDREFNAME,
1623
- "Failed to normalize name. "
1624
- "Reference name starts with a dot or contains a double dot");
1622
+ goto invalid_name;
1625
1623
 
1626
1624
  /* '@{' is forbidden within a refname */
1627
1625
  if (*current == '{' && prev == '@')
1628
- return git__throw(GIT_EINVALIDREFNAME,
1629
- "Failed to normalize name. Reference name contains '@{'");
1626
+ goto invalid_name;
1630
1627
 
1631
1628
  /* Prevent multiple slashes from being added to the output */
1632
1629
  if (*current == '/' && prev == '/') {
@@ -1643,7 +1640,7 @@ static int normalize_name(
1643
1640
  }
1644
1641
 
1645
1642
  if (!out_size)
1646
- return git__throw(GIT_EINVALIDREFNAME, "Reference name is too long");
1643
+ goto invalid_name;
1647
1644
 
1648
1645
  /* Object id refname have to contain at least one slash, except
1649
1646
  * for HEAD in a detached state or MERGE_HEAD if we're in the
@@ -1653,13 +1650,11 @@ static int normalize_name(
1653
1650
  strcmp(name, GIT_HEAD_FILE) != 0 &&
1654
1651
  strcmp(name, GIT_MERGE_HEAD_FILE) != 0 &&
1655
1652
  strcmp(name, GIT_FETCH_HEAD_FILE) != 0)
1656
- return git__throw(GIT_EINVALIDREFNAME,
1657
- "Failed to normalize name. Reference name contains no slashes");
1653
+ goto invalid_name;
1658
1654
 
1659
1655
  /* A refname can not end with ".lock" */
1660
1656
  if (!git__suffixcmp(name, GIT_FILELOCK_EXTENSION))
1661
- return git__throw(GIT_EINVALIDREFNAME,
1662
- "Failed to normalize name. Reference name ends with '.lock'");
1657
+ goto invalid_name;
1663
1658
 
1664
1659
  *buffer_out = '\0';
1665
1660
 
@@ -1669,11 +1664,13 @@ static int normalize_name(
1669
1664
  */
1670
1665
  if (is_oid_ref && !(git__prefixcmp(buffer_out_start, GIT_REFS_DIR) ||
1671
1666
  strcmp(buffer_out_start, GIT_HEAD_FILE)))
1672
- return git__throw(GIT_EINVALIDREFNAME,
1673
- "Failed to normalize name. "
1674
- "Reference name does not start with 'refs/'");
1667
+ goto invalid_name;
1675
1668
 
1676
- return GIT_SUCCESS;
1669
+ return 0;
1670
+
1671
+ invalid_name:
1672
+ giterr_set(GITERR_REFERENCE, "The given reference name is not valid");
1673
+ return -1;
1677
1674
  }
1678
1675
 
1679
1676
  int git_reference__normalize_name(
@@ -1691,3 +1688,79 @@ int git_reference__normalize_name_oid(
1691
1688
  {
1692
1689
  return normalize_name(buffer_out, out_size, name, 1);
1693
1690
  }
1691
+
1692
+ #define GIT_REF_TYPEMASK (GIT_REF_OID | GIT_REF_SYMBOLIC)
1693
+
1694
+ int git_reference_cmp(git_reference *ref1, git_reference *ref2)
1695
+ {
1696
+ assert(ref1 && ref2);
1697
+
1698
+ /* let's put symbolic refs before OIDs */
1699
+ if ((ref1->flags & GIT_REF_TYPEMASK) != (ref2->flags & GIT_REF_TYPEMASK))
1700
+ return (ref1->flags & GIT_REF_SYMBOLIC) ? -1 : 1;
1701
+
1702
+ if (ref1->flags & GIT_REF_SYMBOLIC)
1703
+ return strcmp(ref1->target.symbolic, ref2->target.symbolic);
1704
+
1705
+ return git_oid_cmp(&ref1->target.oid, &ref2->target.oid);
1706
+ }
1707
+
1708
+ /* Update the reference named `ref_name` so it points to `oid` */
1709
+ int git_reference__update(git_repository *repo, const git_oid *oid, const char *ref_name)
1710
+ {
1711
+ git_reference *ref;
1712
+ int res;
1713
+
1714
+ res = git_reference_lookup(&ref, repo, ref_name);
1715
+
1716
+ /* If we haven't found the reference at all, we assume we need to create
1717
+ * a new reference and that's it */
1718
+ if (res == GIT_ENOTFOUND) {
1719
+ giterr_clear();
1720
+ return git_reference_create_oid(NULL, repo, ref_name, oid, 1);
1721
+ }
1722
+
1723
+ if (res < 0)
1724
+ return -1;
1725
+
1726
+ /* If we have found a reference, but it's symbolic, we need to update
1727
+ * the direct reference it points to */
1728
+ if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
1729
+ git_reference *aux;
1730
+ const char *sym_target;
1731
+
1732
+ /* The target pointed at by this reference */
1733
+ sym_target = git_reference_target(ref);
1734
+
1735
+ /* resolve the reference to the target it points to */
1736
+ res = git_reference_resolve(&aux, ref);
1737
+
1738
+ /*
1739
+ * if the symbolic reference pointed to an inexisting ref,
1740
+ * this is means we're creating a new branch, for example.
1741
+ * We need to create a new direct reference with that name
1742
+ */
1743
+ if (res == GIT_ENOTFOUND) {
1744
+ giterr_clear();
1745
+ res = git_reference_create_oid(NULL, repo, sym_target, oid, 1);
1746
+ git_reference_free(ref);
1747
+ return res;
1748
+ }
1749
+
1750
+ /* free the original symbolic reference now; not before because
1751
+ * we're using the `sym_target` pointer */
1752
+ git_reference_free(ref);
1753
+
1754
+ if (res < 0)
1755
+ return -1;
1756
+
1757
+ /* store the newly found direct reference in its place */
1758
+ ref = aux;
1759
+ }
1760
+
1761
+ /* ref is made to point to `oid`: ref is either the original reference,
1762
+ * or the target of the symbolic reference we've looked up */
1763
+ res = git_reference_set_oid(ref, oid);
1764
+ git_reference_free(ref);
1765
+ return res;
1766
+ }