rugged 0.17.0.b7 → 0.18.0.b1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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.
@@ -46,6 +46,134 @@ static int packfile_error(const char *message)
46
46
  return -1;
47
47
  }
48
48
 
49
+ /********************
50
+ * Delta base cache
51
+ ********************/
52
+
53
+ static git_pack_cache_entry *new_cache_object(git_rawobj *source)
54
+ {
55
+ git_pack_cache_entry *e = git__calloc(1, sizeof(git_pack_cache_entry));
56
+ if (!e)
57
+ return NULL;
58
+
59
+ memcpy(&e->raw, source, sizeof(git_rawobj));
60
+
61
+ return e;
62
+ }
63
+
64
+ static void free_cache_object(void *o)
65
+ {
66
+ git_pack_cache_entry *e = (git_pack_cache_entry *)o;
67
+
68
+ if (e != NULL) {
69
+ assert(e->refcount.val == 0);
70
+ git__free(e->raw.data);
71
+ git__free(e);
72
+ }
73
+ }
74
+
75
+ static void cache_free(git_pack_cache *cache)
76
+ {
77
+ khiter_t k;
78
+
79
+ if (cache->entries) {
80
+ for (k = kh_begin(cache->entries); k != kh_end(cache->entries); k++) {
81
+ if (kh_exist(cache->entries, k))
82
+ free_cache_object(kh_value(cache->entries, k));
83
+ }
84
+
85
+ git_offmap_free(cache->entries);
86
+ git_mutex_free(&cache->lock);
87
+ }
88
+ }
89
+
90
+ static int cache_init(git_pack_cache *cache)
91
+ {
92
+ memset(cache, 0, sizeof(git_pack_cache));
93
+ cache->entries = git_offmap_alloc();
94
+ GITERR_CHECK_ALLOC(cache->entries);
95
+ cache->memory_limit = GIT_PACK_CACHE_MEMORY_LIMIT;
96
+ git_mutex_init(&cache->lock);
97
+
98
+ return 0;
99
+ }
100
+
101
+ static git_pack_cache_entry *cache_get(git_pack_cache *cache, git_off_t offset)
102
+ {
103
+ khiter_t k;
104
+ git_pack_cache_entry *entry = NULL;
105
+
106
+ if (git_mutex_lock(&cache->lock) < 0)
107
+ return NULL;
108
+
109
+ k = kh_get(off, cache->entries, offset);
110
+ if (k != kh_end(cache->entries)) { /* found it */
111
+ entry = kh_value(cache->entries, k);
112
+ git_atomic_inc(&entry->refcount);
113
+ entry->last_usage = cache->use_ctr++;
114
+ }
115
+ git_mutex_unlock(&cache->lock);
116
+
117
+ return entry;
118
+ }
119
+
120
+ /* Run with the cache lock held */
121
+ static void free_lowest_entry(git_pack_cache *cache)
122
+ {
123
+ git_pack_cache_entry *entry;
124
+ khiter_t k;
125
+
126
+ for (k = kh_begin(cache->entries); k != kh_end(cache->entries); k++) {
127
+ if (!kh_exist(cache->entries, k))
128
+ continue;
129
+
130
+ entry = kh_value(cache->entries, k);
131
+
132
+ if (entry && entry->refcount.val == 0) {
133
+ cache->memory_used -= entry->raw.len;
134
+ kh_del(off, cache->entries, k);
135
+ free_cache_object(entry);
136
+ }
137
+ }
138
+ }
139
+
140
+ static int cache_add(git_pack_cache *cache, git_rawobj *base, git_off_t offset)
141
+ {
142
+ git_pack_cache_entry *entry;
143
+ int error, exists = 0;
144
+ khiter_t k;
145
+
146
+ if (base->len > GIT_PACK_CACHE_SIZE_LIMIT)
147
+ return -1;
148
+
149
+ entry = new_cache_object(base);
150
+ if (entry) {
151
+ if (git_mutex_lock(&cache->lock) < 0) {
152
+ giterr_set(GITERR_OS, "failed to lock cache");
153
+ return -1;
154
+ }
155
+ /* Add it to the cache if nobody else has */
156
+ exists = kh_get(off, cache->entries, offset) != kh_end(cache->entries);
157
+ if (!exists) {
158
+ while (cache->memory_used + base->len > cache->memory_limit)
159
+ free_lowest_entry(cache);
160
+
161
+ k = kh_put(off, cache->entries, offset, &error);
162
+ assert(error != 0);
163
+ kh_value(cache->entries, k) = entry;
164
+ cache->memory_used += entry->raw.len;
165
+ }
166
+ git_mutex_unlock(&cache->lock);
167
+ /* Somebody beat us to adding it into the cache */
168
+ if (exists) {
169
+ git__free(entry);
170
+ return -1;
171
+ }
172
+ }
173
+
174
+ return 0;
175
+ }
176
+
49
177
  /***********************************************************
50
178
  *
51
179
  * PACK INDEX METHODS
@@ -277,6 +405,56 @@ int git_packfile_unpack_header(
277
405
  return 0;
278
406
  }
279
407
 
408
+ int git_packfile_resolve_header(
409
+ size_t *size_p,
410
+ git_otype *type_p,
411
+ struct git_pack_file *p,
412
+ git_off_t offset)
413
+ {
414
+ git_mwindow *w_curs = NULL;
415
+ git_off_t curpos = offset;
416
+ size_t size;
417
+ git_otype type;
418
+ git_off_t base_offset;
419
+ int error;
420
+
421
+ error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
422
+ git_mwindow_close(&w_curs);
423
+ if (error < 0)
424
+ return error;
425
+
426
+ if (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
427
+ size_t base_size;
428
+ git_rawobj delta;
429
+ base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
430
+ git_mwindow_close(&w_curs);
431
+ error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, size, type);
432
+ git_mwindow_close(&w_curs);
433
+ if (error < 0)
434
+ return error;
435
+ error = git__delta_read_header(delta.data, delta.len, &base_size, size_p);
436
+ git__free(delta.data);
437
+ if (error < 0)
438
+ return error;
439
+ } else
440
+ *size_p = size;
441
+
442
+ while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
443
+ curpos = base_offset;
444
+ error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
445
+ git_mwindow_close(&w_curs);
446
+ if (error < 0)
447
+ return error;
448
+ if (type != GIT_OBJ_OFS_DELTA && type != GIT_OBJ_REF_DELTA)
449
+ break;
450
+ base_offset = get_delta_base(p, &w_curs, &curpos, type, base_offset);
451
+ git_mwindow_close(&w_curs);
452
+ }
453
+ *type_p = type;
454
+
455
+ return error;
456
+ }
457
+
280
458
  static int packfile_unpack_delta(
281
459
  git_rawobj *obj,
282
460
  struct git_pack_file *p,
@@ -286,9 +464,10 @@ static int packfile_unpack_delta(
286
464
  git_otype delta_type,
287
465
  git_off_t obj_offset)
288
466
  {
289
- git_off_t base_offset;
467
+ git_off_t base_offset, base_key;
290
468
  git_rawobj base, delta;
291
- int error;
469
+ git_pack_cache_entry *cached = NULL;
470
+ int error, found_base = 0;
292
471
 
293
472
  base_offset = get_delta_base(p, w_curs, curpos, delta_type, obj_offset);
294
473
  git_mwindow_close(w_curs);
@@ -297,32 +476,49 @@ static int packfile_unpack_delta(
297
476
  if (base_offset < 0) /* must actually be an error code */
298
477
  return (int)base_offset;
299
478
 
300
- error = git_packfile_unpack(&base, p, &base_offset);
479
+ if (!p->bases.entries && (cache_init(&p->bases) < 0))
480
+ return -1;
301
481
 
302
- /*
303
- * TODO: git.git tries to load the base from other packfiles
304
- * or loose objects.
305
- *
306
- * We'll need to do this in order to support thin packs.
307
- */
308
- if (error < 0)
309
- return error;
482
+ base_key = base_offset; /* git_packfile_unpack modifies base_offset */
483
+ if ((cached = cache_get(&p->bases, base_offset)) != NULL) {
484
+ memcpy(&base, &cached->raw, sizeof(git_rawobj));
485
+ found_base = 1;
486
+ }
487
+
488
+ if (!cached) { /* have to inflate it */
489
+ error = git_packfile_unpack(&base, p, &base_offset);
490
+
491
+ /*
492
+ * TODO: git.git tries to load the base from other packfiles
493
+ * or loose objects.
494
+ *
495
+ * We'll need to do this in order to support thin packs.
496
+ */
497
+ if (error < 0)
498
+ return error;
499
+ }
310
500
 
311
501
  error = packfile_unpack_compressed(&delta, p, w_curs, curpos, delta_size, delta_type);
312
502
  git_mwindow_close(w_curs);
503
+
313
504
  if (error < 0) {
314
- git__free(base.data);
505
+ if (!found_base)
506
+ git__free(base.data);
315
507
  return error;
316
508
  }
317
509
 
318
510
  obj->type = base.type;
319
511
  error = git__delta_apply(obj, base.data, base.len, delta.data, delta.len);
512
+ if (error < 0)
513
+ goto on_error;
320
514
 
321
- git__free(base.data);
322
- git__free(delta.data);
515
+ if (found_base)
516
+ git_atomic_dec(&cached->refcount);
517
+ else if (cache_add(&p->bases, &base, base_key) < 0)
518
+ git__free(base.data);
323
519
 
324
- /* TODO: we might want to cache this shit. eventually */
325
- //add_delta_base_cache(p, base_offset, base, base_size, *type);
520
+ on_error:
521
+ git__free(delta.data);
326
522
 
327
523
  return error; /* error set by git__delta_apply */
328
524
  }
@@ -391,6 +587,72 @@ static void use_git_free(void *opaq, void *ptr)
391
587
  git__free(ptr);
392
588
  }
393
589
 
590
+ int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, git_off_t curpos)
591
+ {
592
+ int st;
593
+
594
+ memset(obj, 0, sizeof(git_packfile_stream));
595
+ obj->curpos = curpos;
596
+ obj->p = p;
597
+ obj->zstream.zalloc = use_git_alloc;
598
+ obj->zstream.zfree = use_git_free;
599
+ obj->zstream.next_in = Z_NULL;
600
+ obj->zstream.next_out = Z_NULL;
601
+ st = inflateInit(&obj->zstream);
602
+ if (st != Z_OK) {
603
+ git__free(obj);
604
+ giterr_set(GITERR_ZLIB, "Failed to inflate packfile");
605
+ return -1;
606
+ }
607
+
608
+ return 0;
609
+ }
610
+
611
+ ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t len)
612
+ {
613
+ unsigned char *in;
614
+ size_t written;
615
+ int st;
616
+
617
+ if (obj->done)
618
+ return 0;
619
+
620
+ in = pack_window_open(obj->p, &obj->mw, obj->curpos, &obj->zstream.avail_in);
621
+ if (in == NULL)
622
+ return GIT_EBUFS;
623
+
624
+ obj->zstream.next_out = buffer;
625
+ obj->zstream.avail_out = (unsigned int)len;
626
+ obj->zstream.next_in = in;
627
+
628
+ st = inflate(&obj->zstream, Z_SYNC_FLUSH);
629
+ git_mwindow_close(&obj->mw);
630
+
631
+ obj->curpos += obj->zstream.next_in - in;
632
+ written = len - obj->zstream.avail_out;
633
+
634
+ if (st != Z_OK && st != Z_STREAM_END) {
635
+ giterr_set(GITERR_ZLIB, "Failed to inflate packfile");
636
+ return -1;
637
+ }
638
+
639
+ if (st == Z_STREAM_END)
640
+ obj->done = 1;
641
+
642
+
643
+ /* If we didn't write anything out but we're not done, we need more data */
644
+ if (!written && st != Z_STREAM_END)
645
+ return GIT_EBUFS;
646
+
647
+ return written;
648
+
649
+ }
650
+
651
+ void git_packfile_stream_free(git_packfile_stream *obj)
652
+ {
653
+ inflateEnd(&obj->zstream);
654
+ }
655
+
394
656
  int packfile_unpack_compressed(
395
657
  git_rawobj *obj,
396
658
  struct git_pack_file *p,
@@ -498,14 +760,14 @@ git_off_t get_delta_base(
498
760
  } else if (type == GIT_OBJ_REF_DELTA) {
499
761
  /* If we have the cooperative cache, search in it first */
500
762
  if (p->has_cache) {
501
- int pos;
502
- struct git_pack_entry key;
763
+ khiter_t k;
764
+ git_oid oid;
503
765
 
504
- git_oid_fromraw(&key.sha1, base_info);
505
- pos = git_vector_bsearch(&p->cache, &key);
506
- if (pos >= 0) {
766
+ git_oid_fromraw(&oid, base_info);
767
+ k = kh_get(oid, p->idx_cache, &oid);
768
+ if (k != kh_end(p->idx_cache)) {
507
769
  *curpos += 20;
508
- return ((struct git_pack_entry *)git_vector_get(&p->cache, pos))->offset;
770
+ return ((struct git_pack_entry *)kh_value(p->idx_cache, k))->offset;
509
771
  }
510
772
  }
511
773
  /* The base entry _must_ be in the same pack */
@@ -533,11 +795,12 @@ static struct git_pack_file *packfile_alloc(size_t extra)
533
795
  }
534
796
 
535
797
 
536
- void packfile_free(struct git_pack_file *p)
798
+ void git_packfile_free(struct git_pack_file *p)
537
799
  {
538
800
  assert(p);
539
801
 
540
- /* clear_delta_base_cache(); */
802
+ cache_free(&p->bases);
803
+
541
804
  git_mwindow_free_all(&p->mwf);
542
805
  git_mwindow_file_deregister(&p->mwf);
543
806
 
@@ -564,8 +827,10 @@ static int packfile_open(struct git_pack_file *p)
564
827
 
565
828
  /* TODO: open with noatime */
566
829
  p->mwf.fd = git_futils_open_ro(p->pack_name);
567
- if (p->mwf.fd < 0)
568
- return p->mwf.fd;
830
+ if (p->mwf.fd < 0) {
831
+ p->mwf.fd = -1;
832
+ return -1;
833
+ }
569
834
 
570
835
  if (p_fstat(p->mwf.fd, &st) < 0 ||
571
836
  git_mwindow_file_register(&p->mwf) < 0)
@@ -696,7 +961,7 @@ static int git__memcmp4(const void *a, const void *b) {
696
961
 
697
962
  int git_pack_foreach_entry(
698
963
  struct git_pack_file *p,
699
- int (*cb)(git_oid *oid, void *data),
964
+ git_odb_foreach_cb cb,
700
965
  void *data)
701
966
  {
702
967
  const unsigned char *index = p->index_map.data, *current;
@@ -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.
@@ -8,12 +8,15 @@
8
8
  #ifndef INCLUDE_pack_h__
9
9
  #define INCLUDE_pack_h__
10
10
 
11
+ #include <zlib.h>
12
+
11
13
  #include "git2/oid.h"
12
14
 
13
15
  #include "common.h"
14
16
  #include "map.h"
15
17
  #include "mwindow.h"
16
18
  #include "odb.h"
19
+ #include "oidmap.h"
17
20
 
18
21
  #define GIT_PACK_FILE_MODE 0444
19
22
 
@@ -51,6 +54,28 @@ struct git_pack_idx_header {
51
54
  uint32_t idx_version;
52
55
  };
53
56
 
57
+ typedef struct git_pack_cache_entry {
58
+ size_t last_usage; /* enough? */
59
+ git_atomic refcount;
60
+ git_rawobj raw;
61
+ } git_pack_cache_entry;
62
+
63
+ #include "offmap.h"
64
+
65
+ GIT__USE_OFFMAP;
66
+ GIT__USE_OIDMAP;
67
+
68
+ #define GIT_PACK_CACHE_MEMORY_LIMIT 16 * 1024 * 1024
69
+ #define GIT_PACK_CACHE_SIZE_LIMIT 1024 * 1024 /* don't bother caching anything over 1MB */
70
+
71
+ typedef struct {
72
+ size_t memory_used;
73
+ size_t memory_limit;
74
+ size_t use_ctr;
75
+ git_mutex lock;
76
+ git_offmap *entries;
77
+ } git_pack_cache;
78
+
54
79
  struct git_pack_file {
55
80
  git_mwindow_file mwf;
56
81
  git_map index_map;
@@ -63,9 +88,11 @@ struct git_pack_file {
63
88
  git_time_t mtime;
64
89
  unsigned pack_local:1, pack_keep:1, has_cache:1;
65
90
  git_oid sha1;
66
- git_vector cache;
91
+ git_oidmap *idx_cache;
67
92
  git_oid **oids;
68
93
 
94
+ git_pack_cache bases; /* delta base cache */
95
+
69
96
  /* something like ".git/objects/pack/xxxxx.pack" */
70
97
  char pack_name[GIT_FLEX_ARRAY]; /* more */
71
98
  };
@@ -76,6 +103,14 @@ struct git_pack_entry {
76
103
  struct git_pack_file *p;
77
104
  };
78
105
 
106
+ typedef struct git_packfile_stream {
107
+ git_off_t curpos;
108
+ int done;
109
+ z_stream zstream;
110
+ struct git_pack_file *p;
111
+ git_mwindow *mw;
112
+ } git_packfile_stream;
113
+
79
114
  int git_packfile_unpack_header(
80
115
  size_t *size_p,
81
116
  git_otype *type_p,
@@ -83,6 +118,12 @@ int git_packfile_unpack_header(
83
118
  git_mwindow **w_curs,
84
119
  git_off_t *curpos);
85
120
 
121
+ int git_packfile_resolve_header(
122
+ size_t *size_p,
123
+ git_otype *type_p,
124
+ struct git_pack_file *p,
125
+ git_off_t offset);
126
+
86
127
  int git_packfile_unpack(git_rawobj *obj, struct git_pack_file *p, git_off_t *obj_offset);
87
128
  int packfile_unpack_compressed(
88
129
  git_rawobj *obj,
@@ -92,11 +133,15 @@ int packfile_unpack_compressed(
92
133
  size_t size,
93
134
  git_otype type);
94
135
 
136
+ int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, git_off_t curpos);
137
+ ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t len);
138
+ void git_packfile_stream_free(git_packfile_stream *obj);
139
+
95
140
  git_off_t get_delta_base(struct git_pack_file *p, git_mwindow **w_curs,
96
141
  git_off_t *curpos, git_otype type,
97
142
  git_off_t delta_obj_offset);
98
143
 
99
- void packfile_free(struct git_pack_file *p);
144
+ void git_packfile_free(struct git_pack_file *p);
100
145
  int git_packfile_check(struct git_pack_file **pack_out, const char *path);
101
146
  int git_pack_entry_find(
102
147
  struct git_pack_entry *e,
@@ -105,7 +150,7 @@ int git_pack_entry_find(
105
150
  size_t len);
106
151
  int git_pack_foreach_entry(
107
152
  struct git_pack_file *p,
108
- int (*cb)(git_oid *oid, void *data),
153
+ git_odb_foreach_cb cb,
109
154
  void *data);
110
155
 
111
156
  #endif