rugged 0.17.0.b7 → 0.18.0.b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (310) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +88 -32
  3. data/ext/rugged/extconf.rb +4 -2
  4. data/ext/rugged/rugged.c +72 -10
  5. data/ext/rugged/rugged.h +14 -10
  6. data/ext/rugged/rugged_blob.c +8 -10
  7. data/ext/rugged/rugged_branch.c +11 -14
  8. data/ext/rugged/rugged_commit.c +31 -24
  9. data/ext/rugged/rugged_config.c +2 -2
  10. data/ext/rugged/rugged_index.c +133 -198
  11. data/ext/rugged/rugged_note.c +372 -0
  12. data/ext/rugged/rugged_object.c +50 -22
  13. data/ext/rugged/rugged_reference.c +122 -130
  14. data/ext/rugged/rugged_remote.c +72 -29
  15. data/ext/rugged/rugged_repo.c +402 -20
  16. data/ext/rugged/rugged_revwalk.c +7 -3
  17. data/ext/rugged/rugged_settings.c +110 -0
  18. data/ext/rugged/rugged_signature.c +23 -7
  19. data/ext/rugged/rugged_tag.c +32 -16
  20. data/ext/rugged/rugged_tree.c +44 -15
  21. data/lib/rugged.rb +1 -0
  22. data/lib/rugged/index.rb +8 -0
  23. data/lib/rugged/remote.rb +13 -0
  24. data/lib/rugged/repository.rb +3 -3
  25. data/lib/rugged/version.rb +1 -1
  26. data/test/blob_test.rb +13 -15
  27. data/test/branch_test.rb +32 -67
  28. data/test/commit_test.rb +50 -12
  29. data/test/config_test.rb +12 -11
  30. data/test/coverage/HEAD.json +1 -1
  31. data/test/coverage/cover.rb +40 -21
  32. data/test/errors_test.rb +34 -0
  33. data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
  34. data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
  35. data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
  36. data/test/fixtures/testrepo.git/logs/refs/notes/commits +1 -0
  37. data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +1 -0
  38. data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
  39. data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +1 -0
  40. data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
  41. data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
  42. data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +3 -0
  43. data/test/fixtures/testrepo.git/refs/notes/commits +1 -0
  44. data/test/index_test.rb +65 -69
  45. data/test/lib_test.rb +76 -11
  46. data/test/note_test.rb +158 -0
  47. data/test/object_test.rb +8 -11
  48. data/test/reference_test.rb +77 -85
  49. data/test/remote_test.rb +86 -8
  50. data/test/repo_pack_test.rb +9 -7
  51. data/test/repo_reset_test.rb +80 -0
  52. data/test/repo_test.rb +176 -53
  53. data/test/tag_test.rb +44 -7
  54. data/test/test_helper.rb +63 -35
  55. data/test/tree_test.rb +34 -13
  56. data/test/walker_test.rb +14 -14
  57. data/vendor/libgit2/Makefile.embed +1 -1
  58. data/vendor/libgit2/deps/http-parser/http_parser.c +974 -578
  59. data/vendor/libgit2/deps/http-parser/http_parser.h +106 -70
  60. data/vendor/libgit2/deps/regex/regcomp.c +7 -6
  61. data/vendor/libgit2/deps/regex/regex_internal.c +1 -1
  62. data/vendor/libgit2/deps/regex/regex_internal.h +12 -3
  63. data/vendor/libgit2/deps/regex/regexec.c +5 -5
  64. data/vendor/libgit2/include/git2.h +5 -1
  65. data/vendor/libgit2/include/git2/attr.h +4 -2
  66. data/vendor/libgit2/include/git2/blob.h +39 -12
  67. data/vendor/libgit2/include/git2/branch.h +123 -35
  68. data/vendor/libgit2/include/git2/checkout.h +206 -48
  69. data/vendor/libgit2/include/git2/clone.h +72 -27
  70. data/vendor/libgit2/include/git2/commit.h +20 -17
  71. data/vendor/libgit2/include/git2/common.h +67 -1
  72. data/vendor/libgit2/include/git2/config.h +81 -60
  73. data/vendor/libgit2/include/git2/cred_helpers.h +53 -0
  74. data/vendor/libgit2/include/git2/diff.h +459 -150
  75. data/vendor/libgit2/include/git2/errors.h +9 -1
  76. data/vendor/libgit2/include/git2/graph.h +41 -0
  77. data/vendor/libgit2/include/git2/ignore.h +7 -6
  78. data/vendor/libgit2/include/git2/index.h +323 -97
  79. data/vendor/libgit2/include/git2/indexer.h +27 -59
  80. data/vendor/libgit2/include/git2/inttypes.h +4 -0
  81. data/vendor/libgit2/include/git2/merge.h +13 -3
  82. data/vendor/libgit2/include/git2/message.h +14 -8
  83. data/vendor/libgit2/include/git2/net.h +9 -7
  84. data/vendor/libgit2/include/git2/notes.h +88 -29
  85. data/vendor/libgit2/include/git2/object.h +16 -6
  86. data/vendor/libgit2/include/git2/odb.h +80 -17
  87. data/vendor/libgit2/include/git2/odb_backend.h +47 -11
  88. data/vendor/libgit2/include/git2/oid.h +26 -17
  89. data/vendor/libgit2/include/git2/pack.h +62 -8
  90. data/vendor/libgit2/include/git2/push.h +131 -0
  91. data/vendor/libgit2/include/git2/refdb.h +103 -0
  92. data/vendor/libgit2/include/git2/refdb_backend.h +109 -0
  93. data/vendor/libgit2/include/git2/reflog.h +30 -21
  94. data/vendor/libgit2/include/git2/refs.h +215 -193
  95. data/vendor/libgit2/include/git2/refspec.h +22 -2
  96. data/vendor/libgit2/include/git2/remote.h +158 -37
  97. data/vendor/libgit2/include/git2/repository.h +150 -31
  98. data/vendor/libgit2/include/git2/reset.h +43 -9
  99. data/vendor/libgit2/include/git2/revparse.h +48 -4
  100. data/vendor/libgit2/include/git2/revwalk.h +25 -10
  101. data/vendor/libgit2/include/git2/signature.h +20 -12
  102. data/vendor/libgit2/include/git2/stash.h +121 -0
  103. data/vendor/libgit2/include/git2/status.h +122 -53
  104. data/vendor/libgit2/include/git2/strarray.h +17 -11
  105. data/vendor/libgit2/include/git2/submodule.h +42 -7
  106. data/vendor/libgit2/include/git2/tag.h +72 -59
  107. data/vendor/libgit2/include/git2/threads.h +4 -2
  108. data/vendor/libgit2/include/git2/trace.h +68 -0
  109. data/vendor/libgit2/include/git2/transport.h +328 -0
  110. data/vendor/libgit2/include/git2/tree.h +149 -120
  111. data/vendor/libgit2/include/git2/types.h +13 -12
  112. data/vendor/libgit2/include/git2/version.h +3 -3
  113. data/vendor/libgit2/src/amiga/map.c +2 -2
  114. data/vendor/libgit2/src/attr.c +58 -48
  115. data/vendor/libgit2/src/attr.h +4 -18
  116. data/vendor/libgit2/src/attr_file.c +30 -6
  117. data/vendor/libgit2/src/attr_file.h +6 -8
  118. data/vendor/libgit2/src/attrcache.h +24 -0
  119. data/vendor/libgit2/src/blob.c +30 -7
  120. data/vendor/libgit2/src/blob.h +1 -1
  121. data/vendor/libgit2/src/branch.c +361 -68
  122. data/vendor/libgit2/src/branch.h +17 -0
  123. data/vendor/libgit2/src/bswap.h +1 -1
  124. data/vendor/libgit2/src/buf_text.c +291 -0
  125. data/vendor/libgit2/src/buf_text.h +122 -0
  126. data/vendor/libgit2/src/buffer.c +27 -101
  127. data/vendor/libgit2/src/buffer.h +54 -39
  128. data/vendor/libgit2/src/cache.c +15 -6
  129. data/vendor/libgit2/src/cache.h +1 -1
  130. data/vendor/libgit2/src/cc-compat.h +3 -1
  131. data/vendor/libgit2/src/checkout.c +1165 -222
  132. data/vendor/libgit2/src/checkout.h +24 -0
  133. data/vendor/libgit2/src/clone.c +171 -86
  134. data/vendor/libgit2/src/commit.c +44 -45
  135. data/vendor/libgit2/src/commit.h +3 -3
  136. data/vendor/libgit2/src/commit_list.c +194 -0
  137. data/vendor/libgit2/src/commit_list.h +49 -0
  138. data/vendor/libgit2/src/common.h +44 -10
  139. data/vendor/libgit2/src/compress.c +1 -1
  140. data/vendor/libgit2/src/compress.h +1 -1
  141. data/vendor/libgit2/src/config.c +211 -124
  142. data/vendor/libgit2/src/config.h +23 -4
  143. data/vendor/libgit2/src/config_cache.c +2 -2
  144. data/vendor/libgit2/src/config_file.c +129 -53
  145. data/vendor/libgit2/src/config_file.h +10 -8
  146. data/vendor/libgit2/src/crlf.c +66 -67
  147. data/vendor/libgit2/src/date.c +12 -12
  148. data/vendor/libgit2/src/delta-apply.c +14 -1
  149. data/vendor/libgit2/src/delta-apply.h +18 -1
  150. data/vendor/libgit2/src/delta.c +40 -107
  151. data/vendor/libgit2/src/delta.h +19 -17
  152. data/vendor/libgit2/src/diff.c +347 -496
  153. data/vendor/libgit2/src/diff.h +27 -1
  154. data/vendor/libgit2/src/diff_output.c +564 -249
  155. data/vendor/libgit2/src/diff_output.h +15 -8
  156. data/vendor/libgit2/src/diff_tform.c +687 -0
  157. data/vendor/libgit2/src/errors.c +27 -36
  158. data/vendor/libgit2/src/fetch.c +13 -351
  159. data/vendor/libgit2/src/fetch.h +13 -3
  160. data/vendor/libgit2/src/fetchhead.c +295 -0
  161. data/vendor/libgit2/src/fetchhead.h +34 -0
  162. data/vendor/libgit2/src/filebuf.c +42 -15
  163. data/vendor/libgit2/src/filebuf.h +4 -2
  164. data/vendor/libgit2/src/fileops.c +466 -113
  165. data/vendor/libgit2/src/fileops.h +154 -28
  166. data/vendor/libgit2/src/filter.c +3 -75
  167. data/vendor/libgit2/src/filter.h +1 -29
  168. data/vendor/libgit2/src/fnmatch.c +1 -1
  169. data/vendor/libgit2/src/fnmatch.h +1 -1
  170. data/vendor/libgit2/src/global.c +54 -10
  171. data/vendor/libgit2/src/global.h +10 -1
  172. data/vendor/libgit2/src/graph.c +178 -0
  173. data/vendor/libgit2/src/hash.c +25 -52
  174. data/vendor/libgit2/src/hash.h +21 -9
  175. data/vendor/libgit2/src/{sha1/sha1.c → hash/hash_generic.c} +20 -12
  176. data/vendor/libgit2/src/hash/hash_generic.h +24 -0
  177. data/vendor/libgit2/src/hash/hash_openssl.h +45 -0
  178. data/vendor/libgit2/src/hash/hash_win32.c +291 -0
  179. data/vendor/libgit2/src/hash/hash_win32.h +140 -0
  180. data/vendor/libgit2/src/hashsig.c +368 -0
  181. data/vendor/libgit2/src/hashsig.h +72 -0
  182. data/vendor/libgit2/src/ignore.c +22 -15
  183. data/vendor/libgit2/src/ignore.h +6 -1
  184. data/vendor/libgit2/src/index.c +770 -171
  185. data/vendor/libgit2/src/index.h +13 -5
  186. data/vendor/libgit2/src/indexer.c +286 -431
  187. data/vendor/libgit2/src/iterator.c +854 -466
  188. data/vendor/libgit2/src/iterator.h +134 -109
  189. data/vendor/libgit2/src/map.h +1 -1
  190. data/vendor/libgit2/src/merge.c +296 -0
  191. data/vendor/libgit2/src/merge.h +22 -0
  192. data/vendor/libgit2/src/message.c +1 -1
  193. data/vendor/libgit2/src/message.h +1 -1
  194. data/vendor/libgit2/src/mwindow.c +35 -30
  195. data/vendor/libgit2/src/mwindow.h +2 -2
  196. data/vendor/libgit2/src/netops.c +162 -98
  197. data/vendor/libgit2/src/netops.h +50 -15
  198. data/vendor/libgit2/src/notes.c +109 -58
  199. data/vendor/libgit2/src/notes.h +2 -1
  200. data/vendor/libgit2/src/object.c +46 -57
  201. data/vendor/libgit2/src/object.h +1 -8
  202. data/vendor/libgit2/src/odb.c +151 -40
  203. data/vendor/libgit2/src/odb.h +5 -1
  204. data/vendor/libgit2/src/odb_loose.c +4 -5
  205. data/vendor/libgit2/src/odb_pack.c +122 -80
  206. data/vendor/libgit2/src/offmap.h +65 -0
  207. data/vendor/libgit2/src/oid.c +12 -4
  208. data/vendor/libgit2/src/oidmap.h +1 -1
  209. data/vendor/libgit2/src/pack-objects.c +88 -61
  210. data/vendor/libgit2/src/pack-objects.h +8 -8
  211. data/vendor/libgit2/src/pack.c +293 -28
  212. data/vendor/libgit2/src/pack.h +49 -4
  213. data/vendor/libgit2/src/path.c +103 -14
  214. data/vendor/libgit2/src/path.h +23 -7
  215. data/vendor/libgit2/src/pathspec.c +168 -0
  216. data/vendor/libgit2/src/pathspec.h +40 -0
  217. data/vendor/libgit2/src/pool.c +29 -4
  218. data/vendor/libgit2/src/pool.h +8 -1
  219. data/vendor/libgit2/src/posix.c +26 -27
  220. data/vendor/libgit2/src/posix.h +2 -3
  221. data/vendor/libgit2/src/pqueue.c +23 -1
  222. data/vendor/libgit2/src/pqueue.h +23 -1
  223. data/vendor/libgit2/src/push.c +653 -0
  224. data/vendor/libgit2/src/push.h +51 -0
  225. data/vendor/libgit2/src/refdb.c +185 -0
  226. data/vendor/libgit2/src/refdb.h +46 -0
  227. data/vendor/libgit2/src/refdb_fs.c +1024 -0
  228. data/vendor/libgit2/src/refdb_fs.h +15 -0
  229. data/vendor/libgit2/src/reflog.c +77 -45
  230. data/vendor/libgit2/src/reflog.h +1 -3
  231. data/vendor/libgit2/src/refs.c +366 -1326
  232. data/vendor/libgit2/src/refs.h +22 -13
  233. data/vendor/libgit2/src/refspec.c +46 -7
  234. data/vendor/libgit2/src/refspec.h +11 -1
  235. data/vendor/libgit2/src/remote.c +758 -120
  236. data/vendor/libgit2/src/remote.h +10 -5
  237. data/vendor/libgit2/src/repo_template.h +6 -6
  238. data/vendor/libgit2/src/repository.c +315 -96
  239. data/vendor/libgit2/src/repository.h +5 -3
  240. data/vendor/libgit2/src/reset.c +99 -81
  241. data/vendor/libgit2/src/revparse.c +157 -84
  242. data/vendor/libgit2/src/revwalk.c +68 -470
  243. data/vendor/libgit2/src/revwalk.h +44 -0
  244. data/vendor/libgit2/src/sha1_lookup.c +1 -1
  245. data/vendor/libgit2/src/sha1_lookup.h +1 -1
  246. data/vendor/libgit2/src/signature.c +68 -200
  247. data/vendor/libgit2/src/signature.h +1 -1
  248. data/vendor/libgit2/src/stash.c +663 -0
  249. data/vendor/libgit2/src/status.c +101 -79
  250. data/vendor/libgit2/src/strmap.h +1 -1
  251. data/vendor/libgit2/src/submodule.c +67 -51
  252. data/vendor/libgit2/src/submodule.h +1 -1
  253. data/vendor/libgit2/src/tag.c +35 -29
  254. data/vendor/libgit2/src/tag.h +1 -1
  255. data/vendor/libgit2/src/thread-utils.c +1 -1
  256. data/vendor/libgit2/src/thread-utils.h +2 -2
  257. data/vendor/libgit2/src/trace.c +39 -0
  258. data/vendor/libgit2/src/trace.h +56 -0
  259. data/vendor/libgit2/src/transport.c +81 -34
  260. data/vendor/libgit2/src/transports/cred.c +60 -0
  261. data/vendor/libgit2/src/transports/cred_helpers.c +49 -0
  262. data/vendor/libgit2/src/transports/git.c +234 -127
  263. data/vendor/libgit2/src/transports/http.c +761 -433
  264. data/vendor/libgit2/src/transports/local.c +460 -64
  265. data/vendor/libgit2/src/transports/smart.c +345 -0
  266. data/vendor/libgit2/src/transports/smart.h +179 -0
  267. data/vendor/libgit2/src/{pkt.c → transports/smart_pkt.c} +131 -12
  268. data/vendor/libgit2/src/transports/smart_protocol.c +856 -0
  269. data/vendor/libgit2/src/transports/winhttp.c +1136 -0
  270. data/vendor/libgit2/src/tree-cache.c +2 -2
  271. data/vendor/libgit2/src/tree-cache.h +1 -1
  272. data/vendor/libgit2/src/tree.c +239 -166
  273. data/vendor/libgit2/src/tree.h +11 -2
  274. data/vendor/libgit2/src/tsort.c +39 -23
  275. data/vendor/libgit2/src/unix/map.c +1 -1
  276. data/vendor/libgit2/src/unix/posix.h +12 -2
  277. data/vendor/libgit2/src/unix/realpath.c +30 -0
  278. data/vendor/libgit2/src/util.c +250 -13
  279. data/vendor/libgit2/src/util.h +71 -14
  280. data/vendor/libgit2/src/vector.c +123 -60
  281. data/vendor/libgit2/src/vector.h +24 -22
  282. data/vendor/libgit2/src/win32/dir.c +1 -1
  283. data/vendor/libgit2/src/win32/dir.h +1 -1
  284. data/vendor/libgit2/src/win32/error.c +77 -0
  285. data/vendor/libgit2/src/win32/error.h +13 -0
  286. data/vendor/libgit2/src/win32/findfile.c +143 -54
  287. data/vendor/libgit2/src/win32/findfile.h +10 -6
  288. data/vendor/libgit2/src/win32/map.c +1 -1
  289. data/vendor/libgit2/src/win32/mingw-compat.h +1 -1
  290. data/vendor/libgit2/src/win32/msvc-compat.h +10 -1
  291. data/vendor/libgit2/src/win32/posix.h +10 -1
  292. data/vendor/libgit2/src/win32/posix_w32.c +132 -63
  293. data/vendor/libgit2/src/win32/precompiled.c +1 -1
  294. data/vendor/libgit2/src/win32/pthread.c +1 -1
  295. data/vendor/libgit2/src/win32/pthread.h +1 -1
  296. data/vendor/libgit2/src/win32/utf-conv.c +5 -5
  297. data/vendor/libgit2/src/win32/utf-conv.h +3 -3
  298. data/vendor/libgit2/src/win32/version.h +20 -0
  299. metadata +308 -252
  300. data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
  301. data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
  302. data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
  303. data/test/index_test.rb~ +0 -218
  304. data/vendor/libgit2/src/pkt.h +0 -91
  305. data/vendor/libgit2/src/ppc/sha1.c +0 -70
  306. data/vendor/libgit2/src/ppc/sha1.h +0 -26
  307. data/vendor/libgit2/src/protocol.c +0 -110
  308. data/vendor/libgit2/src/protocol.h +0 -21
  309. data/vendor/libgit2/src/sha1.h +0 -33
  310. data/vendor/libgit2/src/transport.h +0 -148
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -17,13 +17,6 @@ struct git_object {
17
17
  /* fully free the object; internal method, DO NOT EXPORT */
18
18
  void git_object__free(void *object);
19
19
 
20
- GIT_INLINE(int) git_object__dup(git_object **dest, git_object *source)
21
- {
22
- git_cached_obj_incref(source);
23
- *dest = source;
24
- return 0;
25
- }
26
-
27
20
  int git_object__from_odb_object(
28
21
  git_object **object_out,
29
22
  git_repository *repo,
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -23,6 +23,8 @@
23
23
  #define GIT_LOOSE_PRIORITY 2
24
24
  #define GIT_PACKED_PRIORITY 1
25
25
 
26
+ #define GIT_ALTERNATES_MAX_DEPTH 5
27
+
26
28
  typedef struct
27
29
  {
28
30
  git_odb_backend *backend;
@@ -30,7 +32,11 @@ typedef struct
30
32
  int is_alternate;
31
33
  } backend_internal;
32
34
 
33
- static int format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type)
35
+ size_t git_odb__cache_size = GIT_DEFAULT_CACHE_SIZE;
36
+
37
+ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth);
38
+
39
+ int git_odb__format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type)
34
40
  {
35
41
  const char *type_str = git_object_type2string(obj_type);
36
42
  int len = p_snprintf(hdr, n, "%s %"PRIuZ, type_str, obj_len);
@@ -51,7 +57,7 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj)
51
57
  if (!obj->data && obj->len != 0)
52
58
  return -1;
53
59
 
54
- hdrlen = format_object_header(header, sizeof(header), obj->len, obj->type);
60
+ hdrlen = git_odb__format_object_header(header, sizeof(header), obj->len, obj->type);
55
61
 
56
62
  vec[0].data = header;
57
63
  vec[0].len = hdrlen;
@@ -117,23 +123,27 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
117
123
  {
118
124
  int hdr_len;
119
125
  char hdr[64], buffer[2048];
120
- git_hash_ctx *ctx;
126
+ git_hash_ctx ctx;
121
127
  ssize_t read_len = 0;
128
+ int error = 0;
122
129
 
123
130
  if (!git_object_typeisloose(type)) {
124
131
  giterr_set(GITERR_INVALID, "Invalid object type for hash");
125
132
  return -1;
126
133
  }
127
134
 
128
- hdr_len = format_object_header(hdr, sizeof(hdr), size, type);
135
+ if ((error = git_hash_ctx_init(&ctx)) < 0)
136
+ return -1;
129
137
 
130
- ctx = git_hash_new_ctx();
131
- GITERR_CHECK_ALLOC(ctx);
138
+ hdr_len = git_odb__format_object_header(hdr, sizeof(hdr), size, type);
132
139
 
133
- git_hash_update(ctx, hdr, hdr_len);
140
+ if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0)
141
+ goto done;
134
142
 
135
143
  while (size > 0 && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) {
136
- git_hash_update(ctx, buffer, read_len);
144
+ if ((error = git_hash_update(&ctx, buffer, read_len)) < 0)
145
+ goto done;
146
+
137
147
  size -= read_len;
138
148
  }
139
149
 
@@ -141,15 +151,18 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
141
151
  * If size is not zero, the file was truncated after we originally
142
152
  * stat'd it, so we consider this a read failure too */
143
153
  if (read_len < 0 || size > 0) {
144
- git_hash_free_ctx(ctx);
145
154
  giterr_set(GITERR_OS, "Error reading file for hashing");
155
+ error = -1;
156
+
157
+ goto done;
146
158
  return -1;
147
159
  }
148
160
 
149
- git_hash_final(out, ctx);
150
- git_hash_free_ctx(ctx);
161
+ error = git_hash_final(out, &ctx);
151
162
 
152
- return 0;
163
+ done:
164
+ git_hash_ctx_cleanup(&ctx);
165
+ return error;
153
166
  }
154
167
 
155
168
  int git_odb__hashfd_filtered(
@@ -340,7 +353,7 @@ int git_odb_new(git_odb **out)
340
353
  git_odb *db = git__calloc(1, sizeof(*db));
341
354
  GITERR_CHECK_ALLOC(db);
342
355
 
343
- if (git_cache_init(&db->cache, GIT_DEFAULT_CACHE_SIZE, &free_odb_object) < 0 ||
356
+ if (git_cache_init(&db->cache, git_odb__cache_size, &free_odb_object) < 0 ||
344
357
  git_vector_init(&db->backends, 4, backend_sort_cmp) < 0)
345
358
  {
346
359
  git__free(db);
@@ -358,6 +371,8 @@ static int add_backend_internal(git_odb *odb, git_odb_backend *backend, int prio
358
371
 
359
372
  assert(odb && backend);
360
373
 
374
+ GITERR_CHECK_VERSION(backend, GIT_ODB_BACKEND_VERSION, "git_odb_backend");
375
+
361
376
  /* Check if the backend is already owned by another ODB */
362
377
  assert(!backend->odb || backend->odb == odb);
363
378
 
@@ -388,7 +403,7 @@ int git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority)
388
403
  return add_backend_internal(odb, backend, priority, 1);
389
404
  }
390
405
 
391
- static int add_default_backends(git_odb *db, const char *objects_dir, int as_alternates)
406
+ static int add_default_backends(git_odb *db, const char *objects_dir, int as_alternates, int alternate_depth)
392
407
  {
393
408
  git_odb_backend *loose, *packed;
394
409
 
@@ -402,10 +417,10 @@ static int add_default_backends(git_odb *db, const char *objects_dir, int as_alt
402
417
  add_backend_internal(db, packed, GIT_PACKED_PRIORITY, as_alternates) < 0)
403
418
  return -1;
404
419
 
405
- return 0;
420
+ return load_alternates(db, objects_dir, alternate_depth);
406
421
  }
407
422
 
408
- static int load_alternates(git_odb *odb, const char *objects_dir)
423
+ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth)
409
424
  {
410
425
  git_buf alternates_path = GIT_BUF_INIT;
411
426
  git_buf alternates_buf = GIT_BUF_INIT;
@@ -413,6 +428,11 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
413
428
  const char *alternate;
414
429
  int result = 0;
415
430
 
431
+ /* Git reports an error, we just ignore anything deeper */
432
+ if (alternate_depth > GIT_ALTERNATES_MAX_DEPTH) {
433
+ return 0;
434
+ }
435
+
416
436
  if (git_buf_joinpath(&alternates_path, objects_dir, GIT_ALTERNATES_FILE) < 0)
417
437
  return -1;
418
438
 
@@ -433,14 +453,18 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
433
453
  if (*alternate == '\0' || *alternate == '#')
434
454
  continue;
435
455
 
436
- /* relative path: build based on the current `objects` folder */
437
- if (*alternate == '.') {
456
+ /*
457
+ * Relative path: build based on the current `objects`
458
+ * folder. However, relative paths are only allowed in
459
+ * the current repository.
460
+ */
461
+ if (*alternate == '.' && !alternate_depth) {
438
462
  if ((result = git_buf_joinpath(&alternates_path, objects_dir, alternate)) < 0)
439
463
  break;
440
464
  alternate = git_buf_cstr(&alternates_path);
441
465
  }
442
466
 
443
- if ((result = add_default_backends(odb, alternate, 1)) < 0)
467
+ if ((result = add_default_backends(odb, alternate, 1, alternate_depth + 1)) < 0)
444
468
  break;
445
469
  }
446
470
 
@@ -450,6 +474,11 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
450
474
  return result;
451
475
  }
452
476
 
477
+ int git_odb_add_disk_alternate(git_odb *odb, const char *path)
478
+ {
479
+ return add_default_backends(odb, path, 1, 0);
480
+ }
481
+
453
482
  int git_odb_open(git_odb **out, const char *objects_dir)
454
483
  {
455
484
  git_odb *db;
@@ -461,9 +490,7 @@ int git_odb_open(git_odb **out, const char *objects_dir)
461
490
  if (git_odb_new(&db) < 0)
462
491
  return -1;
463
492
 
464
- if (add_default_backends(db, objects_dir, 0) < 0 ||
465
- load_alternates(db, objects_dir) < 0)
466
- {
493
+ if (add_default_backends(db, objects_dir, 0, 0) < 0) {
467
494
  git_odb_free(db);
468
495
  return -1;
469
496
  }
@@ -474,7 +501,7 @@ int git_odb_open(git_odb **out, const char *objects_dir)
474
501
 
475
502
  static void odb_free(git_odb *db)
476
503
  {
477
- unsigned int i;
504
+ size_t i;
478
505
 
479
506
  for (i = 0; i < db->backends.length; ++i) {
480
507
  backend_internal *internal = git_vector_get(&db->backends, i);
@@ -502,8 +529,9 @@ void git_odb_free(git_odb *db)
502
529
  int git_odb_exists(git_odb *db, const git_oid *id)
503
530
  {
504
531
  git_odb_object *object;
505
- unsigned int i;
532
+ size_t i;
506
533
  bool found = false;
534
+ bool refreshed = false;
507
535
 
508
536
  assert(db && id);
509
537
 
@@ -512,6 +540,7 @@ int git_odb_exists(git_odb *db, const git_oid *id)
512
540
  return (int)true;
513
541
  }
514
542
 
543
+ attempt_lookup:
515
544
  for (i = 0; i < db->backends.length && !found; ++i) {
516
545
  backend_internal *internal = git_vector_get(&db->backends, i);
517
546
  git_odb_backend *b = internal->backend;
@@ -520,6 +549,16 @@ int git_odb_exists(git_odb *db, const git_oid *id)
520
549
  found = b->exists(b, id);
521
550
  }
522
551
 
552
+ if (!found && !refreshed) {
553
+ if (git_odb_refresh(db) < 0) {
554
+ giterr_clear();
555
+ return (int)false;
556
+ }
557
+
558
+ refreshed = true;
559
+ goto attempt_lookup;
560
+ }
561
+
523
562
  return (int)found;
524
563
  }
525
564
 
@@ -540,7 +579,7 @@ int git_odb__read_header_or_object(
540
579
  git_odb_object **out, size_t *len_p, git_otype *type_p,
541
580
  git_odb *db, const git_oid *id)
542
581
  {
543
- unsigned int i;
582
+ size_t i;
544
583
  int error = GIT_ENOTFOUND;
545
584
  git_odb_object *object;
546
585
 
@@ -582,16 +621,25 @@ int git_odb__read_header_or_object(
582
621
 
583
622
  int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
584
623
  {
585
- unsigned int i;
586
- int error = GIT_ENOTFOUND;
624
+ size_t i;
625
+ int error;
626
+ bool refreshed = false;
587
627
  git_rawobj raw;
588
628
 
589
629
  assert(out && db && id);
590
630
 
631
+ if (db->backends.length == 0) {
632
+ giterr_set(GITERR_ODB, "Failed to lookup object: no backends loaded");
633
+ return GIT_ENOTFOUND;
634
+ }
635
+
591
636
  *out = git_cache_get(&db->cache, id);
592
637
  if (*out != NULL)
593
638
  return 0;
594
639
 
640
+ attempt_lookup:
641
+ error = GIT_ENOTFOUND;
642
+
595
643
  for (i = 0; i < db->backends.length && error < 0; ++i) {
596
644
  backend_internal *internal = git_vector_get(&db->backends, i);
597
645
  git_odb_backend *b = internal->backend;
@@ -600,9 +648,13 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
600
648
  error = b->read(&raw.data, &raw.len, &raw.type, b, id);
601
649
  }
602
650
 
603
- /* TODO: If no backends are configured, this returns GIT_ENOTFOUND but
604
- * will never have called giterr_set().
605
- */
651
+ if (error == GIT_ENOTFOUND && !refreshed) {
652
+ if ((error = git_odb_refresh(db)) < 0)
653
+ return error;
654
+
655
+ refreshed = true;
656
+ goto attempt_lookup;
657
+ }
606
658
 
607
659
  if (error && error != GIT_PASSTHROUGH)
608
660
  return error;
@@ -614,12 +666,12 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
614
666
  int git_odb_read_prefix(
615
667
  git_odb_object **out, git_odb *db, const git_oid *short_id, size_t len)
616
668
  {
617
- unsigned int i;
669
+ size_t i;
618
670
  int error = GIT_ENOTFOUND;
619
671
  git_oid found_full_oid = {{0}};
620
672
  git_rawobj raw;
621
673
  void *data = NULL;
622
- bool found = false;
674
+ bool found = false, refreshed = false;
623
675
 
624
676
  assert(out && db);
625
677
 
@@ -635,11 +687,12 @@ int git_odb_read_prefix(
635
687
  return 0;
636
688
  }
637
689
 
690
+ attempt_lookup:
638
691
  for (i = 0; i < db->backends.length; ++i) {
639
692
  backend_internal *internal = git_vector_get(&db->backends, i);
640
693
  git_odb_backend *b = internal->backend;
641
694
 
642
- if (b->read != NULL) {
695
+ if (b->read_prefix != NULL) {
643
696
  git_oid full_oid;
644
697
  error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, short_id, len);
645
698
  if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
@@ -650,13 +703,23 @@ int git_odb_read_prefix(
650
703
 
651
704
  git__free(data);
652
705
  data = raw.data;
706
+
653
707
  if (found && git_oid_cmp(&full_oid, &found_full_oid))
654
708
  return git_odb__error_ambiguous("multiple matches for prefix");
709
+
655
710
  found_full_oid = full_oid;
656
711
  found = true;
657
712
  }
658
713
  }
659
714
 
715
+ if (!found && !refreshed) {
716
+ if ((error = git_odb_refresh(db)) < 0)
717
+ return error;
718
+
719
+ refreshed = true;
720
+ goto attempt_lookup;
721
+ }
722
+
660
723
  if (!found)
661
724
  return git_odb__error_notfound("no match for prefix", short_id);
662
725
 
@@ -664,14 +727,14 @@ int git_odb_read_prefix(
664
727
  return 0;
665
728
  }
666
729
 
667
- int git_odb_foreach(git_odb *db, int (*cb)(git_oid *oid, void *data), void *data)
730
+ int git_odb_foreach(git_odb *db, git_odb_foreach_cb cb, void *payload)
668
731
  {
669
732
  unsigned int i;
670
733
  backend_internal *internal;
671
734
 
672
735
  git_vector_foreach(&db->backends, i, internal) {
673
736
  git_odb_backend *b = internal->backend;
674
- int error = b->foreach(b, cb, data);
737
+ int error = b->foreach(b, cb, payload);
675
738
  if (error < 0)
676
739
  return error;
677
740
  }
@@ -682,12 +745,16 @@ int git_odb_foreach(git_odb *db, int (*cb)(git_oid *oid, void *data), void *data
682
745
  int git_odb_write(
683
746
  git_oid *oid, git_odb *db, const void *data, size_t len, git_otype type)
684
747
  {
685
- unsigned int i;
748
+ size_t i;
686
749
  int error = GIT_ERROR;
687
750
  git_odb_stream *stream;
688
751
 
689
752
  assert(oid && db);
690
753
 
754
+ git_odb_hash(oid, data, len, type);
755
+ if (git_odb_exists(db, oid))
756
+ return 0;
757
+
691
758
  for (i = 0; i < db->backends.length && error < 0; ++i) {
692
759
  backend_internal *internal = git_vector_get(&db->backends, i);
693
760
  git_odb_backend *b = internal->backend;
@@ -720,7 +787,7 @@ int git_odb_write(
720
787
  int git_odb_open_wstream(
721
788
  git_odb_stream **stream, git_odb *db, size_t size, git_otype type)
722
789
  {
723
- unsigned int i;
790
+ size_t i;
724
791
  int error = GIT_ERROR;
725
792
 
726
793
  assert(stream && db);
@@ -747,7 +814,7 @@ int git_odb_open_wstream(
747
814
 
748
815
  int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oid)
749
816
  {
750
- unsigned int i;
817
+ size_t i;
751
818
  int error = GIT_ERROR;
752
819
 
753
820
  assert(stream && db);
@@ -766,12 +833,56 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi
766
833
  return error;
767
834
  }
768
835
 
769
- void * git_odb_backend_malloc(git_odb_backend *backend, size_t len)
836
+ int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer_progress_callback progress_cb, void *progress_payload)
837
+ {
838
+ size_t i;
839
+ int error = GIT_ERROR;
840
+
841
+ assert(out && db);
842
+
843
+ for (i = 0; i < db->backends.length && error < 0; ++i) {
844
+ backend_internal *internal = git_vector_get(&db->backends, i);
845
+ git_odb_backend *b = internal->backend;
846
+
847
+ /* we don't write in alternates! */
848
+ if (internal->is_alternate)
849
+ continue;
850
+
851
+ if (b->writepack != NULL)
852
+ error = b->writepack(out, b, progress_cb, progress_payload);
853
+ }
854
+
855
+ if (error == GIT_PASSTHROUGH)
856
+ error = 0;
857
+
858
+ return error;
859
+ }
860
+
861
+ void *git_odb_backend_malloc(git_odb_backend *backend, size_t len)
770
862
  {
771
863
  GIT_UNUSED(backend);
772
864
  return git__malloc(len);
773
865
  }
774
866
 
867
+ int git_odb_refresh(struct git_odb *db)
868
+ {
869
+ size_t i;
870
+ assert(db);
871
+
872
+ for (i = 0; i < db->backends.length; ++i) {
873
+ backend_internal *internal = git_vector_get(&db->backends, i);
874
+ git_odb_backend *b = internal->backend;
875
+
876
+ if (b->refresh != NULL) {
877
+ int error = b->refresh(b);
878
+ if (error < 0)
879
+ return error;
880
+ }
881
+ }
882
+
883
+ return 0;
884
+ }
885
+
775
886
  int git_odb__error_notfound(const char *message, const git_oid *oid)
776
887
  {
777
888
  if (oid != NULL) {