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.
@@ -22,7 +22,7 @@ struct git_index {
22
22
 
23
23
  char *index_file_path;
24
24
 
25
- time_t last_modified;
25
+ git_futils_filestamp stamp;
26
26
  git_vector entries;
27
27
 
28
28
  unsigned int on_disk:1;
@@ -33,13 +33,21 @@ struct git_index {
33
33
 
34
34
  git_tree_cache *tree;
35
35
 
36
- git_vector unmerged;
36
+ git_vector reuc;
37
37
 
38
+ git_vector_cmp entries_cmp_path;
38
39
  git_vector_cmp entries_search;
40
+ git_vector_cmp entries_search_path;
41
+ git_vector_cmp reuc_search;
39
42
  };
40
43
 
41
- extern void git_index__init_entry_from_stat(struct stat *st, git_index_entry *entry);
44
+ extern void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st);
42
45
 
43
- extern unsigned int git_index__prefix_position(git_index *index, const char *path);
46
+ extern size_t git_index__prefix_position(git_index *index, const char *path);
47
+
48
+ extern int git_index_entry__cmp(const void *a, const void *b);
49
+ extern int git_index_entry__cmp_icase(const void *a, const void *b);
50
+
51
+ extern void git_index__set_ignore_case(git_index *index, bool ignore_case);
44
52
 
45
53
  #endif
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -17,7 +17,7 @@
17
17
  #include "posix.h"
18
18
  #include "pack.h"
19
19
  #include "filebuf.h"
20
- #include "sha1.h"
20
+ #include "oidmap.h"
21
21
 
22
22
  #define UINT31_MAX (0x7FFFFFFF)
23
23
 
@@ -28,39 +28,32 @@ struct entry {
28
28
  uint64_t offset_long;
29
29
  };
30
30
 
31
- struct git_indexer {
32
- struct git_pack_file *pack;
33
- size_t nr_objects;
34
- git_vector objects;
35
- git_filebuf file;
36
- unsigned int fanout[256];
37
- git_oid hash;
38
- };
39
-
40
31
  struct git_indexer_stream {
41
32
  unsigned int parsed_header :1,
42
- opened_pack;
33
+ opened_pack :1,
34
+ have_stream :1,
35
+ have_delta :1;
43
36
  struct git_pack_file *pack;
44
37
  git_filebuf pack_file;
45
- git_filebuf index_file;
46
38
  git_off_t off;
39
+ git_off_t entry_start;
40
+ git_packfile_stream stream;
47
41
  size_t nr_objects;
48
42
  git_vector objects;
49
43
  git_vector deltas;
50
44
  unsigned int fanout[256];
45
+ git_hash_ctx hash_ctx;
51
46
  git_oid hash;
47
+ git_transfer_progress_callback progress_cb;
48
+ void *progress_payload;
49
+ char objbuf[8*1024];
52
50
  };
53
51
 
54
52
  struct delta_info {
55
53
  git_off_t delta_off;
56
54
  };
57
55
 
58
- const git_oid *git_indexer_hash(git_indexer *idx)
59
- {
60
- return &idx->hash;
61
- }
62
-
63
- const git_oid *git_indexer_stream_hash(git_indexer_stream *idx)
56
+ const git_oid *git_indexer_stream_hash(const git_indexer_stream *idx)
64
57
  {
65
58
  return &idx->hash;
66
59
  }
@@ -130,15 +123,11 @@ static int objects_cmp(const void *a, const void *b)
130
123
  return git_oid_cmp(&entrya->oid, &entryb->oid);
131
124
  }
132
125
 
133
- static int cache_cmp(const void *a, const void *b)
134
- {
135
- const struct git_pack_entry *ea = a;
136
- const struct git_pack_entry *eb = b;
137
-
138
- return git_oid_cmp(&ea->sha1, &eb->sha1);
139
- }
140
-
141
- int git_indexer_stream_new(git_indexer_stream **out, const char *prefix)
126
+ int git_indexer_stream_new(
127
+ git_indexer_stream **out,
128
+ const char *prefix,
129
+ git_transfer_progress_callback progress_cb,
130
+ void *progress_payload)
142
131
  {
143
132
  git_indexer_stream *idx;
144
133
  git_buf path = GIT_BUF_INIT;
@@ -147,6 +136,8 @@ int git_indexer_stream_new(git_indexer_stream **out, const char *prefix)
147
136
 
148
137
  idx = git__calloc(1, sizeof(git_indexer_stream));
149
138
  GITERR_CHECK_ALLOC(idx);
139
+ idx->progress_cb = progress_cb;
140
+ idx->progress_payload = progress_payload;
150
141
 
151
142
  error = git_buf_joinpath(&path, prefix, suff);
152
143
  if (error < 0)
@@ -169,56 +160,173 @@ cleanup:
169
160
  }
170
161
 
171
162
  /* Try to store the delta so we can try to resolve it later */
172
- static int store_delta(git_indexer_stream *idx, git_off_t entry_start, size_t entry_size, git_otype type)
163
+ static int store_delta(git_indexer_stream *idx)
173
164
  {
174
- git_mwindow *w = NULL;
175
165
  struct delta_info *delta;
176
- git_rawobj obj;
177
- int error;
166
+
167
+ delta = git__calloc(1, sizeof(struct delta_info));
168
+ GITERR_CHECK_ALLOC(delta);
169
+ delta->delta_off = idx->entry_start;
170
+
171
+ if (git_vector_insert(&idx->deltas, delta) < 0)
172
+ return -1;
173
+
174
+ return 0;
175
+ }
176
+
177
+ static void hash_header(git_hash_ctx *ctx, git_off_t len, git_otype type)
178
+ {
179
+ char buffer[64];
180
+ size_t hdrlen;
181
+
182
+ hdrlen = git_odb__format_object_header(buffer, sizeof(buffer), (size_t)len, type);
183
+ git_hash_update(ctx, buffer, hdrlen);
184
+ }
185
+
186
+ static int hash_object_stream(git_indexer_stream *idx, git_packfile_stream *stream)
187
+ {
188
+ ssize_t read;
189
+
190
+ assert(idx && stream);
191
+
192
+ do {
193
+ if ((read = git_packfile_stream_read(stream, idx->objbuf, sizeof(idx->objbuf))) < 0)
194
+ break;
195
+
196
+ git_hash_update(&idx->hash_ctx, idx->objbuf, read);
197
+ } while (read > 0);
198
+
199
+ if (read < 0)
200
+ return (int)read;
201
+
202
+ return 0;
203
+ }
204
+
205
+ /* In order to create the packfile stream, we need to skip over the delta base description */
206
+ static int advance_delta_offset(git_indexer_stream *idx, git_otype type)
207
+ {
208
+ git_mwindow *w = NULL;
178
209
 
179
210
  assert(type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA);
180
211
 
181
212
  if (type == GIT_OBJ_REF_DELTA) {
182
213
  idx->off += GIT_OID_RAWSZ;
183
214
  } else {
184
- git_off_t base_off;
185
-
186
- base_off = get_delta_base(idx->pack, &w, &idx->off, type, entry_start);
215
+ git_off_t base_off = get_delta_base(idx->pack, &w, &idx->off, type, idx->entry_start);
187
216
  git_mwindow_close(&w);
188
217
  if (base_off < 0)
189
218
  return (int)base_off;
190
219
  }
191
220
 
192
- error = packfile_unpack_compressed(&obj, idx->pack, &w, &idx->off, entry_size, type);
193
- if (error == GIT_EBUFS) {
194
- idx->off = entry_start;
195
- return GIT_EBUFS;
196
- } else if (error < 0){
197
- return -1;
221
+ return 0;
222
+ }
223
+
224
+ /* Read from the stream and discard any output */
225
+ static int read_object_stream(git_indexer_stream *idx, git_packfile_stream *stream)
226
+ {
227
+ ssize_t read;
228
+
229
+ assert(stream);
230
+
231
+ do {
232
+ read = git_packfile_stream_read(stream, idx->objbuf, sizeof(idx->objbuf));
233
+ } while (read > 0);
234
+
235
+ if (read < 0)
236
+ return (int)read;
237
+
238
+ return 0;
239
+ }
240
+
241
+ static int crc_object(uint32_t *crc_out, git_mwindow_file *mwf, git_off_t start, git_off_t size)
242
+ {
243
+ void *ptr;
244
+ uint32_t crc;
245
+ unsigned int left, len;
246
+ git_mwindow *w = NULL;
247
+
248
+ crc = crc32(0L, Z_NULL, 0);
249
+ while (size) {
250
+ ptr = git_mwindow_open(mwf, &w, start, (size_t)size, &left);
251
+ if (ptr == NULL)
252
+ return -1;
253
+
254
+ len = min(left, (unsigned int)size);
255
+ crc = crc32(crc, ptr, len);
256
+ size -= len;
257
+ start += len;
258
+ git_mwindow_close(&w);
198
259
  }
199
260
 
200
- delta = git__calloc(1, sizeof(struct delta_info));
201
- GITERR_CHECK_ALLOC(delta);
202
- delta->delta_off = entry_start;
261
+ *crc_out = htonl(crc);
262
+ return 0;
263
+ }
264
+
265
+ static int store_object(git_indexer_stream *idx)
266
+ {
267
+ int i, error;
268
+ khiter_t k;
269
+ git_oid oid;
270
+ struct entry *entry;
271
+ git_off_t entry_size;
272
+ struct git_pack_entry *pentry;
273
+ git_hash_ctx *ctx = &idx->hash_ctx;
274
+ git_off_t entry_start = idx->entry_start;
203
275
 
204
- git__free(obj.data);
276
+ entry = git__calloc(1, sizeof(*entry));
277
+ GITERR_CHECK_ALLOC(entry);
205
278
 
206
- if (git_vector_insert(&idx->deltas, delta) < 0)
207
- return -1;
279
+ pentry = git__malloc(sizeof(struct git_pack_entry));
280
+ GITERR_CHECK_ALLOC(pentry);
281
+
282
+ git_hash_final(&oid, ctx);
283
+ entry_size = idx->off - entry_start;
284
+ if (entry_start > UINT31_MAX) {
285
+ entry->offset = UINT32_MAX;
286
+ entry->offset_long = entry_start;
287
+ } else {
288
+ entry->offset = (uint32_t)entry_start;
289
+ }
290
+
291
+ git_oid_cpy(&pentry->sha1, &oid);
292
+ pentry->offset = entry_start;
293
+
294
+ k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error);
295
+ if (!error) {
296
+ git__free(pentry);
297
+ goto on_error;
298
+ }
299
+
300
+ kh_value(idx->pack->idx_cache, k) = pentry;
301
+
302
+ git_oid_cpy(&entry->oid, &oid);
303
+
304
+ if (crc_object(&entry->crc, &idx->pack->mwf, entry_start, entry_size) < 0)
305
+ goto on_error;
306
+
307
+ /* Add the object to the list */
308
+ if (git_vector_insert(&idx->objects, entry) < 0)
309
+ goto on_error;
310
+
311
+ for (i = oid.id[0]; i < 256; ++i) {
312
+ idx->fanout[i]++;
313
+ }
208
314
 
209
315
  return 0;
316
+
317
+ on_error:
318
+ git__free(entry);
319
+
320
+ return -1;
210
321
  }
211
322
 
212
323
  static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t entry_start)
213
324
  {
214
- int i;
325
+ int i, error;
326
+ khiter_t k;
215
327
  git_oid oid;
216
- void *packed;
217
328
  size_t entry_size;
218
- unsigned int left;
219
329
  struct entry *entry;
220
- git_mwindow *w = NULL;
221
- git_mwindow_file *mwf = &idx->pack->mwf;
222
330
  struct git_pack_entry *pentry;
223
331
 
224
332
  entry = git__calloc(1, sizeof(*entry));
@@ -242,20 +350,21 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent
242
350
 
243
351
  git_oid_cpy(&pentry->sha1, &oid);
244
352
  pentry->offset = entry_start;
245
- if (git_vector_insert(&idx->pack->cache, pentry) < 0)
353
+ k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error);
354
+ if (!error) {
355
+ git__free(pentry);
246
356
  goto on_error;
357
+ }
358
+
359
+ kh_value(idx->pack->idx_cache, k) = pentry;
247
360
 
248
361
  git_oid_cpy(&entry->oid, &oid);
249
362
  entry->crc = crc32(0L, Z_NULL, 0);
250
363
 
251
364
  entry_size = (size_t)(idx->off - entry_start);
252
- packed = git_mwindow_open(mwf, &w, entry_start, entry_size, &left);
253
- if (packed == NULL)
365
+ if (crc_object(&entry->crc, &idx->pack->mwf, entry_start, entry_size) < 0)
254
366
  goto on_error;
255
367
 
256
- entry->crc = htonl(crc32(entry->crc, packed, (uInt)entry_size));
257
- git_mwindow_close(&w);
258
-
259
368
  /* Add the object to the list */
260
369
  if (git_vector_insert(&idx->objects, entry) < 0)
261
370
  goto on_error;
@@ -268,21 +377,26 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent
268
377
 
269
378
  on_error:
270
379
  git__free(entry);
271
- git__free(pentry);
272
380
  git__free(obj->data);
273
381
  return -1;
274
382
  }
275
383
 
276
- int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_indexer_stats *stats)
384
+ static int do_progress_callback(git_indexer_stream *idx, git_transfer_progress *stats)
277
385
  {
278
- int error;
386
+ if (!idx->progress_cb) return 0;
387
+ return idx->progress_cb(stats, idx->progress_payload);
388
+ }
389
+
390
+ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats)
391
+ {
392
+ int error = -1;
279
393
  struct git_pack_header hdr;
280
394
  size_t processed;
281
395
  git_mwindow_file *mwf = &idx->pack->mwf;
282
396
 
283
397
  assert(idx && data && stats);
284
398
 
285
- processed = stats->processed;
399
+ processed = stats->indexed_objects;
286
400
 
287
401
  if (git_filebuf_write(&idx->pack_file, data, size) < 0)
288
402
  return -1;
@@ -301,6 +415,8 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
301
415
  }
302
416
 
303
417
  if (!idx->parsed_header) {
418
+ unsigned int total_objects;
419
+
304
420
  if ((unsigned)idx->pack->mwf.size < sizeof(hdr))
305
421
  return 0;
306
422
 
@@ -313,19 +429,25 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
313
429
 
314
430
  /* for now, limit to 2^32 objects */
315
431
  assert(idx->nr_objects == (size_t)((unsigned int)idx->nr_objects));
432
+ if (idx->nr_objects == (size_t)((unsigned int)idx->nr_objects))
433
+ total_objects = (unsigned int)idx->nr_objects;
434
+ else
435
+ total_objects = UINT_MAX;
316
436
 
317
- if (git_vector_init(&idx->pack->cache, (unsigned int)idx->nr_objects, cache_cmp) < 0)
318
- return -1;
437
+ idx->pack->idx_cache = git_oidmap_alloc();
438
+ GITERR_CHECK_ALLOC(idx->pack->idx_cache);
319
439
 
320
440
  idx->pack->has_cache = 1;
321
- if (git_vector_init(&idx->objects, (unsigned int)idx->nr_objects, objects_cmp) < 0)
441
+ if (git_vector_init(&idx->objects, total_objects, objects_cmp) < 0)
322
442
  return -1;
323
443
 
324
- if (git_vector_init(&idx->deltas, (unsigned int)(idx->nr_objects / 2), NULL) < 0)
444
+ if (git_vector_init(&idx->deltas, total_objects / 2, NULL) < 0)
325
445
  return -1;
326
446
 
327
- memset(stats, 0, sizeof(git_indexer_stats));
328
- stats->total = (unsigned int)idx->nr_objects;
447
+ stats->received_objects = 0;
448
+ processed = stats->indexed_objects = 0;
449
+ stats->total_objects = total_objects;
450
+ do_progress_callback(idx, stats);
329
451
  }
330
452
 
331
453
  /* Now that we have data in the pack, let's try to parse it */
@@ -333,7 +455,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
333
455
  /* As the file grows any windows we try to use will be out of date */
334
456
  git_mwindow_free_all(mwf);
335
457
  while (processed < idx->nr_objects) {
336
- git_rawobj obj;
458
+ git_packfile_stream *stream = &idx->stream;
337
459
  git_off_t entry_start = idx->off;
338
460
  size_t entry_size;
339
461
  git_otype type;
@@ -342,52 +464,82 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
342
464
  if (idx->pack->mwf.size <= idx->off + 20)
343
465
  return 0;
344
466
 
345
- error = git_packfile_unpack_header(&entry_size, &type, mwf, &w, &idx->off);
346
- if (error == GIT_EBUFS) {
347
- idx->off = entry_start;
348
- return 0;
349
- }
350
- if (error < 0)
351
- return -1;
352
-
353
- git_mwindow_close(&w);
354
-
355
- if (type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA) {
356
- error = store_delta(idx, entry_start, entry_size, type);
467
+ if (!idx->have_stream) {
468
+ error = git_packfile_unpack_header(&entry_size, &type, mwf, &w, &idx->off);
357
469
  if (error == GIT_EBUFS) {
358
470
  idx->off = entry_start;
359
471
  return 0;
360
472
  }
361
473
  if (error < 0)
362
- return error;
474
+ return -1;
475
+
476
+ git_mwindow_close(&w);
477
+ idx->entry_start = entry_start;
478
+ git_hash_ctx_init(&idx->hash_ctx);
479
+
480
+ if (type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA) {
481
+ error = advance_delta_offset(idx, type);
482
+ if (error == GIT_EBUFS) {
483
+ idx->off = entry_start;
484
+ return 0;
485
+ }
486
+ if (error < 0)
487
+ return -1;
488
+
489
+ idx->have_delta = 1;
490
+ } else {
491
+ idx->have_delta = 0;
492
+ hash_header(&idx->hash_ctx, entry_size, type);
493
+ }
494
+
495
+ idx->have_stream = 1;
496
+ if (git_packfile_stream_open(stream, idx->pack, idx->off) < 0)
497
+ goto on_error;
363
498
 
364
- stats->received++;
365
- continue;
366
499
  }
367
500
 
368
- idx->off = entry_start;
369
- error = git_packfile_unpack(&obj, idx->pack, &idx->off);
370
- if (error == GIT_EBUFS) {
371
- idx->off = entry_start;
372
- return 0;
501
+ if (idx->have_delta) {
502
+ error = read_object_stream(idx, stream);
503
+ } else {
504
+ error = hash_object_stream(idx, stream);
373
505
  }
506
+
507
+ idx->off = stream->curpos;
508
+ if (error == GIT_EBUFS)
509
+ return 0;
510
+
511
+ /* We want to free the stream reasorces no matter what here */
512
+ idx->have_stream = 0;
513
+ git_packfile_stream_free(stream);
514
+
374
515
  if (error < 0)
375
- return -1;
516
+ goto on_error;
517
+
518
+ if (idx->have_delta) {
519
+ error = store_delta(idx);
520
+ } else {
521
+ error = store_object(idx);
522
+ }
376
523
 
377
- if (hash_and_save(idx, &obj, entry_start) < 0)
524
+ if (error < 0)
378
525
  goto on_error;
379
526
 
380
- git__free(obj.data);
527
+ if (!idx->have_delta) {
528
+ stats->indexed_objects = (unsigned int)++processed;
529
+ }
530
+ stats->received_objects++;
381
531
 
382
- stats->processed = (unsigned int)++processed;
383
- stats->received++;
532
+ if (do_progress_callback(idx, stats) != 0) {
533
+ error = GIT_EUSER;
534
+ goto on_error;
535
+ }
384
536
  }
385
537
 
386
538
  return 0;
387
539
 
388
540
  on_error:
389
541
  git_mwindow_free_all(mwf);
390
- return -1;
542
+ return error;
391
543
  }
392
544
 
393
545
  static int index_path_stream(git_buf *path, git_indexer_stream *idx, const char *suffix)
@@ -412,7 +564,7 @@ static int index_path_stream(git_buf *path, git_indexer_stream *idx, const char
412
564
  return git_buf_oom(path) ? -1 : 0;
413
565
  }
414
566
 
415
- static int resolve_deltas(git_indexer_stream *idx, git_indexer_stats *stats)
567
+ static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats)
416
568
  {
417
569
  unsigned int i;
418
570
  struct delta_info *delta;
@@ -428,13 +580,14 @@ static int resolve_deltas(git_indexer_stream *idx, git_indexer_stats *stats)
428
580
  return -1;
429
581
 
430
582
  git__free(obj.data);
431
- stats->processed++;
583
+ stats->indexed_objects++;
584
+ do_progress_callback(idx, stats);
432
585
  }
433
586
 
434
587
  return 0;
435
588
  }
436
589
 
437
- int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stats)
590
+ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *stats)
438
591
  {
439
592
  git_mwindow *w = NULL;
440
593
  unsigned int i, long_offsets = 0, left;
@@ -443,11 +596,15 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stat
443
596
  struct entry *entry;
444
597
  void *packfile_hash;
445
598
  git_oid file_hash;
446
- SHA_CTX ctx;
599
+ git_hash_ctx ctx;
600
+ git_filebuf index_file = {0};
601
+
602
+ if (git_hash_ctx_init(&ctx) < 0)
603
+ return -1;
447
604
 
448
605
  /* Test for this before resolve_deltas(), as it plays with idx->off */
449
606
  if (idx->off < idx->pack->mwf.size - GIT_OID_RAWSZ) {
450
- giterr_set(GITERR_INDEXER, "Indexing error: junk at the end of the pack");
607
+ giterr_set(GITERR_INDEXER, "Indexing error: unexpected data at the end of the pack");
451
608
  return -1;
452
609
  }
453
610
 
@@ -455,7 +612,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stat
455
612
  if (resolve_deltas(idx, stats) < 0)
456
613
  return -1;
457
614
 
458
- if (stats->processed != stats->total) {
615
+ if (stats->indexed_objects != stats->total_objects) {
459
616
  giterr_set(GITERR_INDEXER, "Indexing error: early EOF");
460
617
  return -1;
461
618
  }
@@ -468,31 +625,30 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stat
468
625
  if (git_buf_oom(&filename))
469
626
  return -1;
470
627
 
471
- if (git_filebuf_open(&idx->index_file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS) < 0)
628
+ if (git_filebuf_open(&index_file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS) < 0)
472
629
  goto on_error;
473
630
 
474
631
  /* Write out the header */
475
632
  hdr.idx_signature = htonl(PACK_IDX_SIGNATURE);
476
633
  hdr.idx_version = htonl(2);
477
- git_filebuf_write(&idx->index_file, &hdr, sizeof(hdr));
634
+ git_filebuf_write(&index_file, &hdr, sizeof(hdr));
478
635
 
479
636
  /* Write out the fanout table */
480
637
  for (i = 0; i < 256; ++i) {
481
638
  uint32_t n = htonl(idx->fanout[i]);
482
- git_filebuf_write(&idx->index_file, &n, sizeof(n));
639
+ git_filebuf_write(&index_file, &n, sizeof(n));
483
640
  }
484
641
 
485
642
  /* Write out the object names (SHA-1 hashes) */
486
- SHA1_Init(&ctx);
487
643
  git_vector_foreach(&idx->objects, i, entry) {
488
- git_filebuf_write(&idx->index_file, &entry->oid, sizeof(git_oid));
489
- SHA1_Update(&ctx, &entry->oid, GIT_OID_RAWSZ);
644
+ git_filebuf_write(&index_file, &entry->oid, sizeof(git_oid));
645
+ git_hash_update(&ctx, &entry->oid, GIT_OID_RAWSZ);
490
646
  }
491
- SHA1_Final(idx->hash.id, &ctx);
647
+ git_hash_final(&idx->hash, &ctx);
492
648
 
493
649
  /* Write out the CRC32 values */
494
650
  git_vector_foreach(&idx->objects, i, entry) {
495
- git_filebuf_write(&idx->index_file, &entry->crc, sizeof(uint32_t));
651
+ git_filebuf_write(&index_file, &entry->crc, sizeof(uint32_t));
496
652
  }
497
653
 
498
654
  /* Write out the offsets */
@@ -504,7 +660,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stat
504
660
  else
505
661
  n = htonl(entry->offset);
506
662
 
507
- git_filebuf_write(&idx->index_file, &n, sizeof(uint32_t));
663
+ git_filebuf_write(&index_file, &n, sizeof(uint32_t));
508
664
  }
509
665
 
510
666
  /* Write out the long offsets */
@@ -517,7 +673,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stat
517
673
  split[0] = htonl(entry->offset_long >> 32);
518
674
  split[1] = htonl(entry->offset_long & 0xffffffff);
519
675
 
520
- git_filebuf_write(&idx->index_file, &split, sizeof(uint32_t) * 2);
676
+ git_filebuf_write(&index_file, &split, sizeof(uint32_t) * 2);
521
677
  }
522
678
 
523
679
  /* Write out the packfile trailer */
@@ -530,24 +686,26 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stat
530
686
  memcpy(&file_hash, packfile_hash, GIT_OID_RAWSZ);
531
687
  git_mwindow_close(&w);
532
688
 
533
- git_filebuf_write(&idx->index_file, &file_hash, sizeof(git_oid));
689
+ git_filebuf_write(&index_file, &file_hash, sizeof(git_oid));
534
690
 
535
691
  /* Write out the packfile trailer to the idx file as well */
536
- if (git_filebuf_hash(&file_hash, &idx->index_file) < 0)
692
+ if (git_filebuf_hash(&file_hash, &index_file) < 0)
537
693
  goto on_error;
538
694
 
539
- git_filebuf_write(&idx->index_file, &file_hash, sizeof(git_oid));
695
+ git_filebuf_write(&index_file, &file_hash, sizeof(git_oid));
540
696
 
541
697
  /* Figure out what the final name should be */
542
698
  if (index_path_stream(&filename, idx, ".idx") < 0)
543
699
  goto on_error;
544
700
 
545
701
  /* Commit file */
546
- if (git_filebuf_commit_at(&idx->index_file, filename.ptr, GIT_PACK_FILE_MODE) < 0)
702
+ if (git_filebuf_commit_at(&index_file, filename.ptr, GIT_PACK_FILE_MODE) < 0)
547
703
  goto on_error;
548
704
 
549
705
  git_mwindow_free_all(&idx->pack->mwf);
706
+ /* We need to close the descriptor here so Windows doesn't choke on commit_at */
550
707
  p_close(idx->pack->mwf.fd);
708
+ idx->pack->mwf.fd = -1;
551
709
 
552
710
  if (index_path_stream(&filename, idx, ".pack") < 0)
553
711
  goto on_error;
@@ -560,17 +718,17 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stat
560
718
 
561
719
  on_error:
562
720
  git_mwindow_free_all(&idx->pack->mwf);
563
- p_close(idx->pack->mwf.fd);
564
- git_filebuf_cleanup(&idx->index_file);
721
+ git_filebuf_cleanup(&index_file);
565
722
  git_buf_free(&filename);
723
+ git_hash_ctx_cleanup(&ctx);
566
724
  return -1;
567
725
  }
568
726
 
569
727
  void git_indexer_stream_free(git_indexer_stream *idx)
570
728
  {
729
+ khiter_t k;
571
730
  unsigned int i;
572
731
  struct entry *e;
573
- struct git_pack_entry *pe;
574
732
  struct delta_info *delta;
575
733
 
576
734
  if (idx == NULL)
@@ -579,323 +737,20 @@ void git_indexer_stream_free(git_indexer_stream *idx)
579
737
  git_vector_foreach(&idx->objects, i, e)
580
738
  git__free(e);
581
739
  git_vector_free(&idx->objects);
582
- if (idx->pack) {
583
- git_vector_foreach(&idx->pack->cache, i, pe)
584
- git__free(pe);
585
- git_vector_free(&idx->pack->cache);
586
- }
587
- git_vector_foreach(&idx->deltas, i, delta)
588
- git__free(delta);
589
- git_vector_free(&idx->deltas);
590
- git__free(idx->pack);
591
- git__free(idx);
592
- }
593
-
594
- int git_indexer_new(git_indexer **out, const char *packname)
595
- {
596
- git_indexer *idx;
597
- struct git_pack_header hdr;
598
- int error;
599
-
600
- assert(out && packname);
601
-
602
- idx = git__calloc(1, sizeof(git_indexer));
603
- GITERR_CHECK_ALLOC(idx);
604
-
605
- open_pack(&idx->pack, packname);
606
-
607
- if ((error = parse_header(&hdr, idx->pack)) < 0)
608
- goto cleanup;
609
-
610
- idx->nr_objects = ntohl(hdr.hdr_entries);
611
-
612
- /* for now, limit to 2^32 objects */
613
- assert(idx->nr_objects == (size_t)((unsigned int)idx->nr_objects));
614
-
615
- error = git_vector_init(&idx->pack->cache, (unsigned int)idx->nr_objects, cache_cmp);
616
- if (error < 0)
617
- goto cleanup;
618
-
619
- idx->pack->has_cache = 1;
620
- error = git_vector_init(&idx->objects, (unsigned int)idx->nr_objects, objects_cmp);
621
- if (error < 0)
622
- goto cleanup;
623
-
624
- *out = idx;
625
-
626
- return 0;
627
-
628
- cleanup:
629
- git_indexer_free(idx);
630
740
 
631
- return -1;
632
- }
633
-
634
- static int index_path(git_buf *path, git_indexer *idx)
635
- {
636
- const char prefix[] = "pack-", suffix[] = ".idx";
637
- size_t slash = (size_t)path->size;
638
-
639
- /* search backwards for '/' */
640
- while (slash > 0 && path->ptr[slash - 1] != '/')
641
- slash--;
642
-
643
- if (git_buf_grow(path, slash + 1 + strlen(prefix) +
644
- GIT_OID_HEXSZ + strlen(suffix) + 1) < 0)
645
- return -1;
646
-
647
- git_buf_truncate(path, slash);
648
- git_buf_puts(path, prefix);
649
- git_oid_fmt(path->ptr + git_buf_len(path), &idx->hash);
650
- path->size += GIT_OID_HEXSZ;
651
- git_buf_puts(path, suffix);
652
-
653
- return git_buf_oom(path) ? -1 : 0;
654
- }
655
-
656
- int git_indexer_write(git_indexer *idx)
657
- {
658
- git_mwindow *w = NULL;
659
- int error;
660
- unsigned int i, long_offsets = 0, left;
661
- struct git_pack_idx_header hdr;
662
- git_buf filename = GIT_BUF_INIT;
663
- struct entry *entry;
664
- void *packfile_hash;
665
- git_oid file_hash;
666
- SHA_CTX ctx;
667
-
668
- git_vector_sort(&idx->objects);
669
-
670
- git_buf_sets(&filename, idx->pack->pack_name);
671
- git_buf_truncate(&filename, filename.size - strlen("pack"));
672
- git_buf_puts(&filename, "idx");
673
- if (git_buf_oom(&filename))
674
- return -1;
675
-
676
- error = git_filebuf_open(&idx->file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS);
677
- if (error < 0)
678
- goto cleanup;
679
-
680
- /* Write out the header */
681
- hdr.idx_signature = htonl(PACK_IDX_SIGNATURE);
682
- hdr.idx_version = htonl(2);
683
- error = git_filebuf_write(&idx->file, &hdr, sizeof(hdr));
684
- if (error < 0)
685
- goto cleanup;
686
-
687
- /* Write out the fanout table */
688
- for (i = 0; i < 256; ++i) {
689
- uint32_t n = htonl(idx->fanout[i]);
690
- error = git_filebuf_write(&idx->file, &n, sizeof(n));
691
- if (error < 0)
692
- goto cleanup;
693
- }
694
-
695
- /* Write out the object names (SHA-1 hashes) */
696
- SHA1_Init(&ctx);
697
- git_vector_foreach(&idx->objects, i, entry) {
698
- error = git_filebuf_write(&idx->file, &entry->oid, sizeof(git_oid));
699
- SHA1_Update(&ctx, &entry->oid, GIT_OID_RAWSZ);
700
- if (error < 0)
701
- goto cleanup;
702
- }
703
- SHA1_Final(idx->hash.id, &ctx);
704
-
705
- /* Write out the CRC32 values */
706
- git_vector_foreach(&idx->objects, i, entry) {
707
- error = git_filebuf_write(&idx->file, &entry->crc, sizeof(uint32_t));
708
- if (error < 0)
709
- goto cleanup;
710
- }
711
-
712
- /* Write out the offsets */
713
- git_vector_foreach(&idx->objects, i, entry) {
714
- uint32_t n;
715
-
716
- if (entry->offset == UINT32_MAX)
717
- n = htonl(0x80000000 | long_offsets++);
718
- else
719
- n = htonl(entry->offset);
720
-
721
- error = git_filebuf_write(&idx->file, &n, sizeof(uint32_t));
722
- if (error < 0)
723
- goto cleanup;
724
- }
725
-
726
- /* Write out the long offsets */
727
- git_vector_foreach(&idx->objects, i, entry) {
728
- uint32_t split[2];
729
-
730
- if (entry->offset != UINT32_MAX)
731
- continue;
732
-
733
- split[0] = htonl(entry->offset_long >> 32);
734
- split[1] = htonl(entry->offset_long & 0xffffffff);
735
-
736
- error = git_filebuf_write(&idx->file, &split, sizeof(uint32_t) * 2);
737
- if (error < 0)
738
- goto cleanup;
739
- }
740
-
741
- /* Write out the packfile trailer */
742
-
743
- packfile_hash = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left);
744
- git_mwindow_close(&w);
745
- if (packfile_hash == NULL) {
746
- error = -1;
747
- goto cleanup;
748
- }
749
-
750
- memcpy(&file_hash, packfile_hash, GIT_OID_RAWSZ);
751
-
752
- git_mwindow_close(&w);
753
-
754
- error = git_filebuf_write(&idx->file, &file_hash, sizeof(git_oid));
755
- if (error < 0)
756
- goto cleanup;
757
-
758
- /* Write out the index sha */
759
- error = git_filebuf_hash(&file_hash, &idx->file);
760
- if (error < 0)
761
- goto cleanup;
762
-
763
- error = git_filebuf_write(&idx->file, &file_hash, sizeof(git_oid));
764
- if (error < 0)
765
- goto cleanup;
766
-
767
- /* Figure out what the final name should be */
768
- error = index_path(&filename, idx);
769
- if (error < 0)
770
- goto cleanup;
771
-
772
- /* Commit file */
773
- error = git_filebuf_commit_at(&idx->file, filename.ptr, GIT_PACK_FILE_MODE);
774
-
775
- cleanup:
776
- git_mwindow_free_all(&idx->pack->mwf);
777
- git_mwindow_file_deregister(&idx->pack->mwf);
778
- if (error < 0)
779
- git_filebuf_cleanup(&idx->file);
780
- git_buf_free(&filename);
781
-
782
- return error;
783
- }
784
-
785
- int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
786
- {
787
- git_mwindow_file *mwf;
788
- git_off_t off = sizeof(struct git_pack_header);
789
- int error;
790
- struct entry *entry;
791
- unsigned int left, processed;
792
-
793
- assert(idx && stats);
794
-
795
- mwf = &idx->pack->mwf;
796
- error = git_mwindow_file_register(mwf);
797
- if (error < 0)
798
- return error;
799
-
800
- stats->total = (unsigned int)idx->nr_objects;
801
- stats->processed = processed = 0;
802
-
803
- while (processed < idx->nr_objects) {
804
- git_rawobj obj;
805
- git_oid oid;
806
- struct git_pack_entry *pentry;
807
- git_mwindow *w = NULL;
808
- int i;
809
- git_off_t entry_start = off;
810
- void *packed;
811
- size_t entry_size;
812
- char fmt[GIT_OID_HEXSZ] = {0};
813
-
814
- entry = git__calloc(1, sizeof(*entry));
815
- GITERR_CHECK_ALLOC(entry);
816
-
817
- if (off > UINT31_MAX) {
818
- entry->offset = UINT32_MAX;
819
- entry->offset_long = off;
820
- } else {
821
- entry->offset = (uint32_t)off;
822
- }
823
-
824
- error = git_packfile_unpack(&obj, idx->pack, &off);
825
- if (error < 0)
826
- goto cleanup;
827
-
828
- /* FIXME: Parse the object instead of hashing it */
829
- error = git_odb__hashobj(&oid, &obj);
830
- if (error < 0) {
831
- giterr_set(GITERR_INDEXER, "Failed to hash object");
832
- goto cleanup;
833
- }
834
-
835
- pentry = git__malloc(sizeof(struct git_pack_entry));
836
- if (pentry == NULL) {
837
- error = -1;
838
- goto cleanup;
839
- }
840
-
841
- git_oid_cpy(&pentry->sha1, &oid);
842
- pentry->offset = entry_start;
843
- git_oid_fmt(fmt, &oid);
844
- error = git_vector_insert(&idx->pack->cache, pentry);
845
- if (error < 0)
846
- goto cleanup;
847
-
848
- git_oid_cpy(&entry->oid, &oid);
849
- entry->crc = crc32(0L, Z_NULL, 0);
850
-
851
- entry_size = (size_t)(off - entry_start);
852
- packed = git_mwindow_open(mwf, &w, entry_start, entry_size, &left);
853
- if (packed == NULL) {
854
- error = -1;
855
- goto cleanup;
856
- }
857
- entry->crc = htonl(crc32(entry->crc, packed, (uInt)entry_size));
858
- git_mwindow_close(&w);
859
-
860
- /* Add the object to the list */
861
- error = git_vector_insert(&idx->objects, entry);
862
- if (error < 0)
863
- goto cleanup;
864
-
865
- for (i = oid.id[0]; i < 256; ++i) {
866
- idx->fanout[i]++;
741
+ if (idx->pack) {
742
+ for (k = kh_begin(idx->pack->idx_cache); k != kh_end(idx->pack->idx_cache); k++) {
743
+ if (kh_exist(idx->pack->idx_cache, k))
744
+ git__free(kh_value(idx->pack->idx_cache, k));
867
745
  }
868
746
 
869
- git__free(obj.data);
870
-
871
- stats->processed = ++processed;
747
+ git_oidmap_free(idx->pack->idx_cache);
872
748
  }
873
749
 
874
- cleanup:
875
- git_mwindow_free_all(mwf);
876
-
877
- return error;
878
-
879
- }
880
-
881
- void git_indexer_free(git_indexer *idx)
882
- {
883
- unsigned int i;
884
- struct entry *e;
885
- struct git_pack_entry *pe;
886
-
887
- if (idx == NULL)
888
- return;
889
-
890
- p_close(idx->pack->mwf.fd);
891
- git_mwindow_file_deregister(&idx->pack->mwf);
892
- git_vector_foreach(&idx->objects, i, e)
893
- git__free(e);
894
- git_vector_free(&idx->objects);
895
- git_vector_foreach(&idx->pack->cache, i, pe)
896
- git__free(pe);
897
- git_vector_free(&idx->pack->cache);
898
- git__free(idx->pack);
750
+ git_vector_foreach(&idx->deltas, i, delta)
751
+ git__free(delta);
752
+ git_vector_free(&idx->deltas);
753
+ git_packfile_free(idx->pack);
754
+ git_filebuf_cleanup(&idx->pack_file);
899
755
  git__free(idx);
900
756
  }
901
-