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.
@@ -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