rugged 0.19.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (668) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -1
  3. data/README.md +184 -33
  4. data/ext/rugged/extconf.rb +111 -28
  5. data/ext/rugged/rugged.c +327 -89
  6. data/ext/rugged/rugged.h +64 -28
  7. data/ext/rugged/rugged_allocator.c +89 -0
  8. data/ext/rugged/rugged_backend.c +17 -0
  9. data/ext/rugged/rugged_blame.c +278 -0
  10. data/ext/rugged/rugged_blob.c +301 -75
  11. data/ext/rugged/rugged_branch.c +92 -242
  12. data/ext/rugged/rugged_branch_collection.c +388 -0
  13. data/ext/rugged/rugged_commit.c +575 -79
  14. data/ext/rugged/rugged_config.c +129 -36
  15. data/ext/rugged/rugged_cred.c +131 -0
  16. data/ext/rugged/rugged_diff.c +291 -122
  17. data/ext/rugged/rugged_diff_delta.c +16 -22
  18. data/ext/rugged/rugged_diff_hunk.c +35 -51
  19. data/ext/rugged/rugged_diff_line.c +23 -36
  20. data/ext/rugged/rugged_index.c +289 -152
  21. data/ext/rugged/rugged_note.c +50 -60
  22. data/ext/rugged/rugged_object.c +13 -30
  23. data/ext/rugged/rugged_patch.c +400 -0
  24. data/ext/rugged/rugged_rebase.c +397 -0
  25. data/ext/rugged/rugged_reference.c +76 -346
  26. data/ext/rugged/rugged_reference_collection.c +423 -0
  27. data/ext/rugged/rugged_remote.c +438 -461
  28. data/ext/rugged/rugged_remote_collection.c +435 -0
  29. data/ext/rugged/rugged_repo.c +1548 -365
  30. data/ext/rugged/rugged_revwalk.c +378 -99
  31. data/ext/rugged/rugged_settings.c +86 -23
  32. data/ext/rugged/rugged_signature.c +47 -37
  33. data/ext/rugged/rugged_submodule.c +835 -0
  34. data/ext/rugged/rugged_submodule_collection.c +366 -0
  35. data/ext/rugged/rugged_tag.c +88 -210
  36. data/ext/rugged/rugged_tag_collection.c +326 -0
  37. data/ext/rugged/rugged_tree.c +460 -217
  38. data/lib/rugged/attributes.rb +46 -0
  39. data/lib/rugged/blob.rb +33 -0
  40. data/lib/rugged/branch.rb +12 -16
  41. data/lib/rugged/commit.rb +9 -0
  42. data/lib/rugged/console.rb +5 -0
  43. data/lib/rugged/credentials.rb +48 -0
  44. data/lib/rugged/diff/delta.rb +6 -2
  45. data/lib/rugged/diff/hunk.rb +9 -9
  46. data/lib/rugged/diff/line.rb +28 -5
  47. data/lib/rugged/diff.rb +7 -1
  48. data/lib/rugged/index.rb +120 -0
  49. data/lib/rugged/object.rb +5 -0
  50. data/lib/rugged/patch.rb +41 -0
  51. data/lib/rugged/reference.rb +6 -3
  52. data/lib/rugged/remote.rb +5 -9
  53. data/lib/rugged/repository.rb +126 -14
  54. data/lib/rugged/submodule_collection.rb +53 -0
  55. data/lib/rugged/tag.rb +45 -16
  56. data/lib/rugged/tree.rb +163 -1
  57. data/lib/rugged/version.rb +6 -1
  58. data/lib/rugged/walker.rb +5 -0
  59. data/lib/rugged.rb +16 -1
  60. data/vendor/libgit2/AUTHORS +77 -0
  61. data/vendor/libgit2/CMakeLists.txt +317 -0
  62. data/vendor/libgit2/COPYING +993 -0
  63. data/vendor/libgit2/cmake/Modules/AddCFlagIfSupported.cmake +30 -0
  64. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.c.in +29 -0
  65. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.cmake +96 -0
  66. data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +11 -0
  67. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +26 -0
  68. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +324 -0
  69. data/vendor/libgit2/cmake/Modules/FindHTTP_Parser.cmake +39 -0
  70. data/vendor/libgit2/cmake/Modules/FindIconv.cmake +45 -0
  71. data/vendor/libgit2/cmake/Modules/FindPkgLibraries.cmake +28 -0
  72. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +28 -0
  73. data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +20 -0
  74. data/vendor/libgit2/cmake/Modules/FindmbedTLS.cmake +93 -0
  75. data/vendor/libgit2/cmake/Modules/IdeSplitSources.cmake +22 -0
  76. data/vendor/libgit2/deps/http-parser/CMakeLists.txt +5 -0
  77. data/vendor/libgit2/deps/http-parser/COPYING +23 -0
  78. data/vendor/libgit2/deps/http-parser/http_parser.c +5 -2
  79. data/vendor/libgit2/deps/http-parser/http_parser.h +2 -0
  80. data/vendor/libgit2/deps/regex/CMakeLists.txt +2 -0
  81. data/vendor/libgit2/deps/regex/COPYING +502 -0
  82. data/vendor/libgit2/deps/regex/regex.c +10 -3
  83. data/vendor/libgit2/deps/winhttp/CMakeLists.txt +26 -0
  84. data/vendor/libgit2/deps/winhttp/COPYING.GPL +993 -0
  85. data/vendor/libgit2/deps/winhttp/COPYING.LGPL +502 -0
  86. data/vendor/libgit2/deps/winhttp/urlmon.h +45 -0
  87. data/vendor/libgit2/deps/winhttp/winhttp.def +29 -0
  88. data/vendor/libgit2/deps/winhttp/winhttp.h +594 -0
  89. data/vendor/libgit2/deps/winhttp/winhttp64.def +29 -0
  90. data/vendor/libgit2/deps/zlib/CMakeLists.txt +5 -0
  91. data/vendor/libgit2/deps/zlib/COPYING +27 -0
  92. data/vendor/libgit2/deps/zlib/adler32.c +51 -34
  93. data/vendor/libgit2/deps/zlib/crc32.c +61 -61
  94. data/vendor/libgit2/deps/zlib/crc32.h +1 -1
  95. data/vendor/libgit2/deps/zlib/deflate.c +681 -352
  96. data/vendor/libgit2/deps/zlib/deflate.h +25 -18
  97. data/vendor/libgit2/deps/zlib/gzguts.h +218 -0
  98. data/vendor/libgit2/deps/zlib/infback.c +640 -0
  99. data/vendor/libgit2/deps/zlib/inffast.c +36 -53
  100. data/vendor/libgit2/deps/zlib/inffixed.h +3 -3
  101. data/vendor/libgit2/deps/zlib/inflate.c +167 -86
  102. data/vendor/libgit2/deps/zlib/inflate.h +7 -4
  103. data/vendor/libgit2/deps/zlib/inftrees.c +24 -50
  104. data/vendor/libgit2/deps/zlib/trees.c +55 -96
  105. data/vendor/libgit2/deps/zlib/zconf.h +499 -19
  106. data/vendor/libgit2/deps/zlib/zlib.h +526 -227
  107. data/vendor/libgit2/deps/zlib/zutil.c +39 -32
  108. data/vendor/libgit2/deps/zlib/zutil.h +75 -78
  109. data/vendor/libgit2/include/git2/annotated_commit.h +125 -0
  110. data/vendor/libgit2/include/git2/apply.h +129 -0
  111. data/vendor/libgit2/include/git2/attr.h +36 -21
  112. data/vendor/libgit2/include/git2/blame.h +229 -0
  113. data/vendor/libgit2/include/git2/blob.h +81 -44
  114. data/vendor/libgit2/include/git2/branch.h +81 -42
  115. data/vendor/libgit2/include/git2/buffer.h +128 -0
  116. data/vendor/libgit2/include/git2/checkout.h +141 -67
  117. data/vendor/libgit2/include/git2/cherrypick.h +92 -0
  118. data/vendor/libgit2/include/git2/clone.h +157 -58
  119. data/vendor/libgit2/include/git2/commit.h +231 -12
  120. data/vendor/libgit2/include/git2/common.h +216 -30
  121. data/vendor/libgit2/include/git2/config.h +274 -48
  122. data/vendor/libgit2/include/git2/cred_helpers.h +4 -4
  123. data/vendor/libgit2/include/git2/deprecated.h +253 -0
  124. data/vendor/libgit2/include/git2/describe.h +189 -0
  125. data/vendor/libgit2/include/git2/diff.h +985 -575
  126. data/vendor/libgit2/include/git2/errors.h +93 -52
  127. data/vendor/libgit2/include/git2/filter.h +217 -0
  128. data/vendor/libgit2/include/git2/global.h +44 -0
  129. data/vendor/libgit2/include/git2/graph.h +17 -0
  130. data/vendor/libgit2/include/git2/ignore.h +2 -2
  131. data/vendor/libgit2/include/git2/index.h +269 -94
  132. data/vendor/libgit2/include/git2/indexer.h +44 -12
  133. data/vendor/libgit2/include/git2/mailmap.h +115 -0
  134. data/vendor/libgit2/include/git2/merge.h +501 -64
  135. data/vendor/libgit2/include/git2/message.h +52 -17
  136. data/vendor/libgit2/include/git2/net.h +11 -5
  137. data/vendor/libgit2/include/git2/notes.h +120 -16
  138. data/vendor/libgit2/include/git2/object.h +62 -23
  139. data/vendor/libgit2/include/git2/odb.h +140 -24
  140. data/vendor/libgit2/include/git2/odb_backend.h +56 -12
  141. data/vendor/libgit2/include/git2/oid.h +17 -18
  142. data/vendor/libgit2/include/git2/oidarray.h +40 -0
  143. data/vendor/libgit2/include/git2/pack.h +86 -7
  144. data/vendor/libgit2/include/git2/patch.h +274 -0
  145. data/vendor/libgit2/include/git2/pathspec.h +280 -0
  146. data/vendor/libgit2/include/git2/proxy.h +96 -0
  147. data/vendor/libgit2/include/git2/rebase.h +323 -0
  148. data/vendor/libgit2/include/git2/reflog.h +12 -9
  149. data/vendor/libgit2/include/git2/refs.h +241 -46
  150. data/vendor/libgit2/include/git2/refspec.h +20 -4
  151. data/vendor/libgit2/include/git2/remote.h +636 -209
  152. data/vendor/libgit2/include/git2/repository.h +267 -57
  153. data/vendor/libgit2/include/git2/reset.h +36 -6
  154. data/vendor/libgit2/include/git2/revert.h +91 -0
  155. data/vendor/libgit2/include/git2/revparse.h +27 -16
  156. data/vendor/libgit2/include/git2/revwalk.h +78 -35
  157. data/vendor/libgit2/include/git2/signature.h +32 -5
  158. data/vendor/libgit2/include/git2/stash.h +160 -21
  159. data/vendor/libgit2/include/git2/status.h +92 -30
  160. data/vendor/libgit2/include/git2/submodule.h +226 -133
  161. data/vendor/libgit2/include/git2/sys/alloc.h +101 -0
  162. data/vendor/libgit2/include/git2/sys/commit.h +38 -4
  163. data/vendor/libgit2/include/git2/sys/config.h +68 -9
  164. data/vendor/libgit2/include/git2/sys/diff.h +94 -0
  165. data/vendor/libgit2/include/git2/sys/filter.h +332 -0
  166. data/vendor/libgit2/include/git2/sys/hashsig.h +106 -0
  167. data/vendor/libgit2/include/git2/sys/index.h +6 -5
  168. data/vendor/libgit2/include/git2/sys/mempack.h +86 -0
  169. data/vendor/libgit2/include/git2/sys/merge.h +182 -0
  170. data/vendor/libgit2/include/git2/sys/odb_backend.h +66 -28
  171. data/vendor/libgit2/include/git2/sys/openssl.h +38 -0
  172. data/vendor/libgit2/include/git2/sys/path.h +64 -0
  173. data/vendor/libgit2/include/git2/sys/refdb_backend.h +79 -19
  174. data/vendor/libgit2/include/git2/sys/reflog.h +21 -0
  175. data/vendor/libgit2/include/git2/sys/refs.h +13 -2
  176. data/vendor/libgit2/include/git2/sys/repository.h +64 -1
  177. data/vendor/libgit2/include/git2/sys/stream.h +138 -0
  178. data/vendor/libgit2/include/git2/sys/time.h +31 -0
  179. data/vendor/libgit2/include/git2/sys/transport.h +439 -0
  180. data/vendor/libgit2/include/git2/tag.h +11 -2
  181. data/vendor/libgit2/include/git2/trace.h +1 -1
  182. data/vendor/libgit2/include/git2/transaction.h +121 -0
  183. data/vendor/libgit2/include/git2/transport.h +261 -292
  184. data/vendor/libgit2/include/git2/tree.h +111 -21
  185. data/vendor/libgit2/include/git2/types.h +244 -32
  186. data/vendor/libgit2/include/git2/version.h +5 -2
  187. data/vendor/libgit2/include/git2/worktree.h +255 -0
  188. data/vendor/libgit2/include/git2.h +50 -40
  189. data/vendor/libgit2/libgit2.pc.in +13 -0
  190. data/vendor/libgit2/src/CMakeLists.txt +525 -0
  191. data/vendor/libgit2/src/alloc.c +55 -0
  192. data/vendor/libgit2/src/alloc.h +40 -0
  193. data/vendor/libgit2/src/annotated_commit.c +228 -0
  194. data/vendor/libgit2/src/annotated_commit.h +52 -0
  195. data/vendor/libgit2/src/apply.c +855 -0
  196. data/vendor/libgit2/src/apply.h +25 -0
  197. data/vendor/libgit2/src/array.h +74 -16
  198. data/vendor/libgit2/src/attr.c +239 -408
  199. data/vendor/libgit2/src/attr.h +3 -33
  200. data/vendor/libgit2/src/attr_file.c +424 -156
  201. data/vendor/libgit2/src/attr_file.h +95 -23
  202. data/vendor/libgit2/src/attrcache.c +469 -0
  203. data/vendor/libgit2/src/attrcache.h +37 -5
  204. data/vendor/libgit2/src/bitvec.h +75 -0
  205. data/vendor/libgit2/src/blame.c +532 -0
  206. data/vendor/libgit2/src/blame.h +95 -0
  207. data/vendor/libgit2/src/blame_git.c +668 -0
  208. data/vendor/libgit2/src/blame_git.h +22 -0
  209. data/vendor/libgit2/src/blob.c +233 -129
  210. data/vendor/libgit2/src/blob.h +29 -1
  211. data/vendor/libgit2/src/branch.c +295 -197
  212. data/vendor/libgit2/src/branch.h +2 -0
  213. data/vendor/libgit2/src/buf_text.c +52 -27
  214. data/vendor/libgit2/src/buf_text.h +7 -7
  215. data/vendor/libgit2/src/buffer.c +609 -52
  216. data/vendor/libgit2/src/buffer.h +68 -23
  217. data/vendor/libgit2/src/cache.c +48 -51
  218. data/vendor/libgit2/src/cache.h +6 -4
  219. data/vendor/libgit2/src/cc-compat.h +35 -7
  220. data/vendor/libgit2/src/checkout.c +1827 -483
  221. data/vendor/libgit2/src/checkout.h +4 -1
  222. data/vendor/libgit2/src/cherrypick.c +230 -0
  223. data/vendor/libgit2/src/clone.c +338 -258
  224. data/vendor/libgit2/src/{compress.h → clone.h} +5 -5
  225. data/vendor/libgit2/src/commit.c +711 -124
  226. data/vendor/libgit2/src/commit.h +10 -3
  227. data/vendor/libgit2/src/commit_list.c +21 -14
  228. data/vendor/libgit2/src/commit_list.h +9 -3
  229. data/vendor/libgit2/src/common.h +153 -13
  230. data/vendor/libgit2/src/config.c +871 -242
  231. data/vendor/libgit2/src/config.h +58 -14
  232. data/vendor/libgit2/src/config_backend.h +84 -0
  233. data/vendor/libgit2/src/config_cache.c +44 -18
  234. data/vendor/libgit2/src/config_entries.c +259 -0
  235. data/vendor/libgit2/src/config_entries.h +23 -0
  236. data/vendor/libgit2/src/config_file.c +837 -1113
  237. data/vendor/libgit2/src/config_mem.c +224 -0
  238. data/vendor/libgit2/src/config_parse.c +558 -0
  239. data/vendor/libgit2/src/config_parse.h +64 -0
  240. data/vendor/libgit2/src/crlf.c +290 -195
  241. data/vendor/libgit2/src/date.c +35 -7
  242. data/vendor/libgit2/src/delta.c +275 -71
  243. data/vendor/libgit2/src/delta.h +80 -58
  244. data/vendor/libgit2/src/describe.c +893 -0
  245. data/vendor/libgit2/src/diff.c +330 -1128
  246. data/vendor/libgit2/src/diff.h +25 -67
  247. data/vendor/libgit2/src/diff_driver.c +225 -109
  248. data/vendor/libgit2/src/diff_driver.h +5 -2
  249. data/vendor/libgit2/src/diff_file.c +128 -103
  250. data/vendor/libgit2/src/diff_file.h +17 -12
  251. data/vendor/libgit2/src/diff_generate.c +1622 -0
  252. data/vendor/libgit2/src/diff_generate.h +128 -0
  253. data/vendor/libgit2/src/diff_parse.c +108 -0
  254. data/vendor/libgit2/src/diff_parse.h +20 -0
  255. data/vendor/libgit2/src/diff_print.c +578 -218
  256. data/vendor/libgit2/src/diff_stats.c +362 -0
  257. data/vendor/libgit2/src/diff_tform.c +429 -257
  258. data/vendor/libgit2/src/diff_tform.h +25 -0
  259. data/vendor/libgit2/src/diff_xdiff.c +143 -46
  260. data/vendor/libgit2/src/diff_xdiff.h +12 -5
  261. data/vendor/libgit2/src/errors.c +150 -34
  262. data/vendor/libgit2/src/features.h.in +37 -0
  263. data/vendor/libgit2/src/fetch.c +69 -46
  264. data/vendor/libgit2/src/fetch.h +6 -12
  265. data/vendor/libgit2/src/fetchhead.c +40 -33
  266. data/vendor/libgit2/src/fetchhead.h +5 -4
  267. data/vendor/libgit2/src/filebuf.c +163 -61
  268. data/vendor/libgit2/src/filebuf.h +13 -7
  269. data/vendor/libgit2/src/fileops.c +549 -407
  270. data/vendor/libgit2/src/fileops.h +97 -106
  271. data/vendor/libgit2/src/filter.c +989 -46
  272. data/vendor/libgit2/src/filter.h +21 -70
  273. data/vendor/libgit2/src/fnmatch.c +67 -11
  274. data/vendor/libgit2/src/fnmatch.h +27 -7
  275. data/vendor/libgit2/src/global.c +257 -63
  276. data/vendor/libgit2/src/global.h +19 -0
  277. data/vendor/libgit2/src/graph.c +39 -23
  278. data/vendor/libgit2/src/hash/hash_collisiondetect.h +51 -0
  279. data/vendor/libgit2/src/hash/hash_common_crypto.h +61 -0
  280. data/vendor/libgit2/src/hash/hash_generic.c +3 -3
  281. data/vendor/libgit2/src/hash/hash_generic.h +10 -5
  282. data/vendor/libgit2/src/hash/hash_mbedtls.c +38 -0
  283. data/vendor/libgit2/src/hash/hash_mbedtls.h +24 -0
  284. data/vendor/libgit2/src/hash/hash_openssl.h +26 -8
  285. data/vendor/libgit2/src/hash/hash_win32.c +71 -43
  286. data/vendor/libgit2/src/hash/hash_win32.h +4 -3
  287. data/vendor/libgit2/src/hash/sha1dc/sha1.c +1900 -0
  288. data/vendor/libgit2/src/hash/sha1dc/sha1.h +110 -0
  289. data/vendor/libgit2/src/hash/sha1dc/ubc_check.c +372 -0
  290. data/vendor/libgit2/src/hash/sha1dc/ubc_check.h +52 -0
  291. data/vendor/libgit2/src/hash.c +0 -1
  292. data/vendor/libgit2/src/hash.h +13 -6
  293. data/vendor/libgit2/src/hashsig.c +121 -126
  294. data/vendor/libgit2/src/ident.c +129 -0
  295. data/vendor/libgit2/src/idxmap.c +153 -0
  296. data/vendor/libgit2/src/idxmap.h +41 -0
  297. data/vendor/libgit2/src/ignore.c +362 -123
  298. data/vendor/libgit2/src/ignore.h +16 -4
  299. data/vendor/libgit2/src/index.c +2131 -692
  300. data/vendor/libgit2/src/index.h +138 -6
  301. data/vendor/libgit2/src/indexer.c +866 -266
  302. data/vendor/libgit2/src/indexer.h +16 -0
  303. data/vendor/libgit2/src/integer.h +106 -0
  304. data/vendor/libgit2/src/iterator.c +1888 -967
  305. data/vendor/libgit2/src/iterator.h +130 -67
  306. data/vendor/libgit2/src/khash.h +43 -29
  307. data/vendor/libgit2/src/mailmap.c +485 -0
  308. data/vendor/libgit2/src/mailmap.h +35 -0
  309. data/vendor/libgit2/src/map.h +1 -1
  310. data/vendor/libgit2/src/merge.c +1679 -479
  311. data/vendor/libgit2/src/merge.h +89 -22
  312. data/vendor/libgit2/src/merge_driver.c +426 -0
  313. data/vendor/libgit2/src/merge_driver.h +62 -0
  314. data/vendor/libgit2/src/merge_file.c +238 -101
  315. data/vendor/libgit2/src/message.c +4 -28
  316. data/vendor/libgit2/src/message.h +3 -1
  317. data/vendor/libgit2/src/mwindow.c +123 -15
  318. data/vendor/libgit2/src/mwindow.h +10 -1
  319. data/vendor/libgit2/src/netops.c +178 -499
  320. data/vendor/libgit2/src/netops.h +51 -27
  321. data/vendor/libgit2/src/notes.c +251 -94
  322. data/vendor/libgit2/src/notes.h +5 -2
  323. data/vendor/libgit2/src/object.c +253 -67
  324. data/vendor/libgit2/src/object.h +40 -2
  325. data/vendor/libgit2/src/object_api.c +30 -11
  326. data/vendor/libgit2/src/odb.c +765 -201
  327. data/vendor/libgit2/src/odb.h +40 -8
  328. data/vendor/libgit2/src/odb_loose.c +560 -346
  329. data/vendor/libgit2/src/odb_mempack.c +185 -0
  330. data/vendor/libgit2/src/odb_pack.c +117 -73
  331. data/vendor/libgit2/src/offmap.c +113 -0
  332. data/vendor/libgit2/src/offmap.h +32 -42
  333. data/vendor/libgit2/src/oid.c +45 -25
  334. data/vendor/libgit2/src/oid.h +26 -8
  335. data/vendor/libgit2/src/oidarray.c +34 -0
  336. data/vendor/libgit2/src/oidarray.h +20 -0
  337. data/vendor/libgit2/src/oidmap.c +125 -0
  338. data/vendor/libgit2/src/oidmap.h +30 -17
  339. data/vendor/libgit2/src/pack-objects.c +688 -265
  340. data/vendor/libgit2/src/pack-objects.h +27 -13
  341. data/vendor/libgit2/src/pack.c +418 -202
  342. data/vendor/libgit2/src/pack.h +25 -16
  343. data/vendor/libgit2/src/parse.c +124 -0
  344. data/vendor/libgit2/src/parse.h +61 -0
  345. data/vendor/libgit2/src/patch.c +223 -0
  346. data/vendor/libgit2/src/patch.h +68 -0
  347. data/vendor/libgit2/src/patch_generate.c +901 -0
  348. data/vendor/libgit2/src/patch_generate.h +69 -0
  349. data/vendor/libgit2/src/patch_parse.c +1136 -0
  350. data/vendor/libgit2/src/patch_parse.h +51 -0
  351. data/vendor/libgit2/src/path.c +1247 -241
  352. data/vendor/libgit2/src/path.h +353 -57
  353. data/vendor/libgit2/src/pathspec.c +586 -58
  354. data/vendor/libgit2/src/pathspec.h +37 -15
  355. data/vendor/libgit2/src/pool.c +134 -221
  356. data/vendor/libgit2/src/pool.h +38 -50
  357. data/vendor/libgit2/src/posix.c +76 -10
  358. data/vendor/libgit2/src/posix.h +74 -32
  359. data/vendor/libgit2/src/pqueue.c +79 -117
  360. data/vendor/libgit2/src/pqueue.h +38 -82
  361. data/vendor/libgit2/src/proxy.c +39 -0
  362. data/vendor/libgit2/src/proxy.h +17 -0
  363. data/vendor/libgit2/src/push.c +178 -279
  364. data/vendor/libgit2/src/push.h +93 -4
  365. data/vendor/libgit2/src/reader.c +265 -0
  366. data/vendor/libgit2/src/reader.h +107 -0
  367. data/vendor/libgit2/src/rebase.c +1364 -0
  368. data/vendor/libgit2/src/refdb.c +74 -19
  369. data/vendor/libgit2/src/refdb.h +16 -3
  370. data/vendor/libgit2/src/refdb_fs.c +1472 -603
  371. data/vendor/libgit2/src/refdb_fs.h +4 -0
  372. data/vendor/libgit2/src/reflog.c +40 -330
  373. data/vendor/libgit2/src/reflog.h +8 -2
  374. data/vendor/libgit2/src/refs.c +641 -225
  375. data/vendor/libgit2/src/refs.h +53 -6
  376. data/vendor/libgit2/src/refspec.c +175 -62
  377. data/vendor/libgit2/src/refspec.h +10 -25
  378. data/vendor/libgit2/src/remote.c +1741 -723
  379. data/vendor/libgit2/src/remote.h +17 -5
  380. data/vendor/libgit2/src/repository.c +1505 -421
  381. data/vendor/libgit2/src/repository.h +95 -15
  382. data/vendor/libgit2/src/reset.c +63 -26
  383. data/vendor/libgit2/src/revert.c +232 -0
  384. data/vendor/libgit2/src/revparse.c +94 -80
  385. data/vendor/libgit2/src/revwalk.c +427 -194
  386. data/vendor/libgit2/src/revwalk.h +14 -5
  387. data/vendor/libgit2/src/settings.c +290 -0
  388. data/vendor/libgit2/src/sha1_lookup.c +16 -159
  389. data/vendor/libgit2/src/sha1_lookup.h +5 -4
  390. data/vendor/libgit2/src/signature.c +138 -26
  391. data/vendor/libgit2/src/signature.h +5 -0
  392. data/vendor/libgit2/src/sortedcache.c +395 -0
  393. data/vendor/libgit2/src/sortedcache.h +180 -0
  394. data/vendor/libgit2/src/stash.c +629 -168
  395. data/vendor/libgit2/src/status.c +125 -75
  396. data/vendor/libgit2/src/status.h +4 -2
  397. data/vendor/libgit2/src/stdalloc.c +120 -0
  398. data/vendor/libgit2/src/stdalloc.h +17 -0
  399. data/vendor/libgit2/src/stream.h +86 -0
  400. data/vendor/libgit2/src/streams/mbedtls.c +483 -0
  401. data/vendor/libgit2/src/streams/mbedtls.h +23 -0
  402. data/vendor/libgit2/src/streams/openssl.c +789 -0
  403. data/vendor/libgit2/src/streams/openssl.h +23 -0
  404. data/vendor/libgit2/src/streams/registry.c +118 -0
  405. data/vendor/libgit2/src/streams/registry.h +19 -0
  406. data/vendor/libgit2/src/streams/socket.c +235 -0
  407. data/vendor/libgit2/src/streams/socket.h +23 -0
  408. data/vendor/libgit2/src/streams/stransport.c +323 -0
  409. data/vendor/libgit2/src/streams/stransport.h +21 -0
  410. data/vendor/libgit2/src/streams/tls.c +73 -0
  411. data/vendor/libgit2/src/streams/tls.h +31 -0
  412. data/vendor/libgit2/src/strmap.c +147 -0
  413. data/vendor/libgit2/src/strmap.h +46 -51
  414. data/vendor/libgit2/src/strnlen.h +24 -0
  415. data/vendor/libgit2/src/submodule.c +1633 -877
  416. data/vendor/libgit2/src/submodule.h +83 -21
  417. data/vendor/libgit2/src/sysdir.c +355 -0
  418. data/vendor/libgit2/src/sysdir.h +119 -0
  419. data/vendor/libgit2/src/tag.c +87 -62
  420. data/vendor/libgit2/src/tag.h +4 -1
  421. data/vendor/libgit2/src/thread-utils.c +3 -0
  422. data/vendor/libgit2/src/thread-utils.h +71 -35
  423. data/vendor/libgit2/src/trace.c +4 -4
  424. data/vendor/libgit2/src/trace.h +11 -3
  425. data/vendor/libgit2/src/trailer.c +416 -0
  426. data/vendor/libgit2/src/transaction.c +382 -0
  427. data/vendor/libgit2/src/transaction.h +14 -0
  428. data/vendor/libgit2/src/transport.c +133 -67
  429. data/vendor/libgit2/src/transports/auth.c +75 -0
  430. data/vendor/libgit2/src/transports/auth.h +64 -0
  431. data/vendor/libgit2/src/transports/auth_negotiate.c +277 -0
  432. data/vendor/libgit2/src/transports/auth_negotiate.h +27 -0
  433. data/vendor/libgit2/src/transports/cred.c +296 -68
  434. data/vendor/libgit2/src/transports/cred.h +16 -0
  435. data/vendor/libgit2/src/transports/cred_helpers.c +4 -0
  436. data/vendor/libgit2/src/transports/git.c +108 -90
  437. data/vendor/libgit2/src/transports/http.c +803 -258
  438. data/vendor/libgit2/src/transports/http.h +25 -0
  439. data/vendor/libgit2/src/transports/local.c +265 -169
  440. data/vendor/libgit2/src/transports/smart.c +255 -45
  441. data/vendor/libgit2/src/transports/smart.h +42 -22
  442. data/vendor/libgit2/src/transports/smart_pkt.c +250 -159
  443. data/vendor/libgit2/src/transports/smart_protocol.c +414 -196
  444. data/vendor/libgit2/src/transports/ssh.c +645 -236
  445. data/vendor/libgit2/src/transports/ssh.h +14 -0
  446. data/vendor/libgit2/src/transports/winhttp.c +809 -353
  447. data/vendor/libgit2/src/tree-cache.c +138 -52
  448. data/vendor/libgit2/src/tree-cache.h +14 -7
  449. data/vendor/libgit2/src/tree.c +620 -259
  450. data/vendor/libgit2/src/tree.h +12 -19
  451. data/vendor/libgit2/src/tsort.c +3 -2
  452. data/vendor/libgit2/src/unix/map.c +25 -7
  453. data/vendor/libgit2/src/unix/posix.h +77 -12
  454. data/vendor/libgit2/src/unix/pthread.h +56 -0
  455. data/vendor/libgit2/src/unix/realpath.c +12 -8
  456. data/vendor/libgit2/src/userdiff.h +208 -0
  457. data/vendor/libgit2/src/util.c +349 -165
  458. data/vendor/libgit2/src/util.h +167 -85
  459. data/vendor/libgit2/src/varint.c +43 -0
  460. data/vendor/libgit2/src/varint.h +17 -0
  461. data/vendor/libgit2/src/vector.c +156 -33
  462. data/vendor/libgit2/src/vector.h +41 -5
  463. data/vendor/libgit2/src/win32/dir.c +22 -42
  464. data/vendor/libgit2/src/win32/dir.h +7 -5
  465. data/vendor/libgit2/src/win32/error.c +6 -32
  466. data/vendor/libgit2/src/win32/error.h +4 -2
  467. data/vendor/libgit2/src/win32/findfile.c +62 -69
  468. data/vendor/libgit2/src/win32/findfile.h +5 -13
  469. data/vendor/libgit2/src/win32/git2.rc +44 -0
  470. data/vendor/libgit2/src/win32/map.c +39 -11
  471. data/vendor/libgit2/src/win32/mingw-compat.h +10 -11
  472. data/vendor/libgit2/src/win32/msvc-compat.h +10 -33
  473. data/vendor/libgit2/src/win32/path_w32.c +476 -0
  474. data/vendor/libgit2/src/win32/path_w32.h +104 -0
  475. data/vendor/libgit2/src/win32/posix.h +35 -30
  476. data/vendor/libgit2/src/win32/posix_w32.c +659 -327
  477. data/vendor/libgit2/src/win32/precompiled.h +7 -2
  478. data/vendor/libgit2/src/win32/reparse.h +57 -0
  479. data/vendor/libgit2/src/win32/thread.c +258 -0
  480. data/vendor/libgit2/src/win32/thread.h +64 -0
  481. data/vendor/libgit2/src/win32/utf-conv.c +127 -62
  482. data/vendor/libgit2/src/win32/utf-conv.h +47 -6
  483. data/vendor/libgit2/src/win32/version.h +21 -4
  484. data/vendor/libgit2/src/win32/w32_buffer.c +54 -0
  485. data/vendor/libgit2/src/win32/w32_buffer.h +20 -0
  486. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +438 -0
  487. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +129 -0
  488. data/vendor/libgit2/src/win32/w32_stack.c +193 -0
  489. data/vendor/libgit2/src/win32/w32_stack.h +140 -0
  490. data/vendor/libgit2/src/win32/w32_util.c +95 -0
  491. data/vendor/libgit2/src/win32/w32_util.h +170 -0
  492. data/vendor/libgit2/src/win32/win32-compat.h +52 -0
  493. data/vendor/libgit2/src/worktree.c +578 -0
  494. data/vendor/libgit2/src/worktree.h +39 -0
  495. data/vendor/libgit2/src/xdiff/xdiff.h +33 -18
  496. data/vendor/libgit2/src/xdiff/xdiffi.c +578 -88
  497. data/vendor/libgit2/src/xdiff/xdiffi.h +3 -2
  498. data/vendor/libgit2/src/xdiff/xemit.c +106 -45
  499. data/vendor/libgit2/src/xdiff/xemit.h +3 -3
  500. data/vendor/libgit2/src/xdiff/xhistogram.c +5 -4
  501. data/vendor/libgit2/src/xdiff/xinclude.h +3 -2
  502. data/vendor/libgit2/src/xdiff/xmacros.h +2 -2
  503. data/vendor/libgit2/src/xdiff/xmerge.c +167 -48
  504. data/vendor/libgit2/src/xdiff/xpatience.c +42 -10
  505. data/vendor/libgit2/src/xdiff/xprepare.c +14 -14
  506. data/vendor/libgit2/src/xdiff/xprepare.h +2 -2
  507. data/vendor/libgit2/src/xdiff/xtypes.h +2 -2
  508. data/vendor/libgit2/src/xdiff/xutils.c +60 -56
  509. data/vendor/libgit2/src/xdiff/xutils.h +3 -5
  510. data/vendor/libgit2/src/zstream.c +205 -0
  511. data/vendor/libgit2/src/zstream.h +53 -0
  512. metadata +281 -233
  513. data/Rakefile +0 -61
  514. data/ext/rugged/rugged_diff_patch.c +0 -169
  515. data/lib/rugged/diff/patch.rb +0 -28
  516. data/test/blob_test.rb +0 -341
  517. data/test/branch_test.rb +0 -199
  518. data/test/commit_test.rb +0 -104
  519. data/test/config_test.rb +0 -45
  520. data/test/coverage/cover.rb +0 -133
  521. data/test/diff_test.rb +0 -777
  522. data/test/errors_test.rb +0 -34
  523. data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
  524. data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
  525. data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
  526. data/test/fixtures/archive.tar.gz +0 -0
  527. data/test/fixtures/attr/attr0 +0 -1
  528. data/test/fixtures/attr/attr1 +0 -29
  529. data/test/fixtures/attr/attr2 +0 -21
  530. data/test/fixtures/attr/attr3 +0 -4
  531. data/test/fixtures/attr/binfile +0 -1
  532. data/test/fixtures/attr/dir/file +0 -0
  533. data/test/fixtures/attr/file +0 -1
  534. data/test/fixtures/attr/gitattributes +0 -29
  535. data/test/fixtures/attr/gitignore +0 -2
  536. data/test/fixtures/attr/ign +0 -1
  537. data/test/fixtures/attr/macro_bad +0 -1
  538. data/test/fixtures/attr/macro_test +0 -1
  539. data/test/fixtures/attr/root_test1 +0 -1
  540. data/test/fixtures/attr/root_test2 +0 -6
  541. data/test/fixtures/attr/root_test3 +0 -19
  542. data/test/fixtures/attr/root_test4.txt +0 -14
  543. data/test/fixtures/attr/sub/abc +0 -37
  544. data/test/fixtures/attr/sub/dir/file +0 -0
  545. data/test/fixtures/attr/sub/file +0 -1
  546. data/test/fixtures/attr/sub/ign/file +0 -1
  547. data/test/fixtures/attr/sub/ign/sub/file +0 -1
  548. data/test/fixtures/attr/sub/sub/dir +0 -0
  549. data/test/fixtures/attr/sub/sub/file +0 -1
  550. data/test/fixtures/attr/sub/sub/subsub.txt +0 -1
  551. data/test/fixtures/attr/sub/subdir_test1 +0 -2
  552. data/test/fixtures/attr/sub/subdir_test2.txt +0 -1
  553. data/test/fixtures/diff/another.txt +0 -38
  554. data/test/fixtures/diff/readme.txt +0 -36
  555. data/test/fixtures/mergedrepo/conflicts-one.txt +0 -5
  556. data/test/fixtures/mergedrepo/conflicts-two.txt +0 -5
  557. data/test/fixtures/mergedrepo/one.txt +0 -10
  558. data/test/fixtures/mergedrepo/two.txt +0 -12
  559. data/test/fixtures/status/current_file +0 -1
  560. data/test/fixtures/status/ignored_file +0 -1
  561. data/test/fixtures/status/modified_file +0 -2
  562. data/test/fixtures/status/new_file +0 -1
  563. data/test/fixtures/status/staged_changes +0 -2
  564. data/test/fixtures/status/staged_changes_modified_file +0 -3
  565. data/test/fixtures/status/staged_delete_modified_file +0 -1
  566. data/test/fixtures/status/staged_new_file +0 -1
  567. data/test/fixtures/status/staged_new_file_modified_file +0 -2
  568. data/test/fixtures/status/subdir/current_file +0 -1
  569. data/test/fixtures/status/subdir/modified_file +0 -2
  570. data/test/fixtures/status/subdir/new_file +0 -1
  571. data/test/fixtures/status/subdir.txt +0 -2
  572. data/test/fixtures/status//350/277/231 +0 -1
  573. data/test/fixtures/testrepo.git/HEAD +0 -1
  574. data/test/fixtures/testrepo.git/config +0 -13
  575. data/test/fixtures/testrepo.git/description +0 -1
  576. data/test/fixtures/testrepo.git/index +0 -0
  577. data/test/fixtures/testrepo.git/info/exclude +0 -6
  578. data/test/fixtures/testrepo.git/logs/HEAD +0 -3
  579. data/test/fixtures/testrepo.git/logs/refs/heads/master +0 -3
  580. data/test/fixtures/testrepo.git/logs/refs/notes/commits +0 -1
  581. data/test/fixtures/testrepo.git/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d +0 -0
  582. data/test/fixtures/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 +0 -0
  583. data/test/fixtures/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 +0 -0
  584. data/test/fixtures/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd +0 -0
  585. data/test/fixtures/testrepo.git/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 +0 -0
  586. data/test/fixtures/testrepo.git/objects/36/060c58702ed4c2a40832c51758d5344201d89a +0 -2
  587. data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +0 -1
  588. data/test/fixtures/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 +0 -0
  589. data/test/fixtures/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +0 -2
  590. data/test/fixtures/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +0 -2
  591. data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
  592. data/test/fixtures/testrepo.git/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 +0 -0
  593. data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +0 -1
  594. data/test/fixtures/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a +0 -0
  595. data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
  596. data/test/fixtures/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d +0 -0
  597. data/test/fixtures/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 +0 -0
  598. data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
  599. data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
  600. data/test/fixtures/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +0 -3
  601. data/test/fixtures/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +0 -2
  602. data/test/fixtures/testrepo.git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd +0 -0
  603. data/test/fixtures/testrepo.git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 +0 -0
  604. data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +0 -3
  605. data/test/fixtures/testrepo.git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 +0 -3
  606. data/test/fixtures/testrepo.git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd +0 -3
  607. data/test/fixtures/testrepo.git/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b +0 -0
  608. data/test/fixtures/testrepo.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  609. data/test/fixtures/testrepo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 +0 -0
  610. data/test/fixtures/testrepo.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 +0 -0
  611. data/test/fixtures/testrepo.git/objects/fd/093bff70906175335656e6ce6ae05783708765 +0 -0
  612. data/test/fixtures/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx +0 -0
  613. data/test/fixtures/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack +0 -0
  614. data/test/fixtures/testrepo.git/packed-refs +0 -2
  615. data/test/fixtures/testrepo.git/refs/heads/master +0 -1
  616. data/test/fixtures/testrepo.git/refs/notes/commits +0 -1
  617. data/test/fixtures/testrepo.git/refs/tags/v0.9 +0 -1
  618. data/test/fixtures/testrepo.git/refs/tags/v1.0 +0 -1
  619. data/test/fixtures/text_file.md +0 -464
  620. data/test/fixtures/unsymlinked.git/HEAD +0 -1
  621. data/test/fixtures/unsymlinked.git/config +0 -6
  622. data/test/fixtures/unsymlinked.git/description +0 -1
  623. data/test/fixtures/unsymlinked.git/info/exclude +0 -2
  624. data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
  625. data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
  626. data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
  627. data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
  628. data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
  629. data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
  630. data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
  631. data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
  632. data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
  633. data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +0 -2
  634. data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
  635. data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
  636. data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
  637. data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
  638. data/test/fixtures/unsymlinked.git/refs/heads/exe-file +0 -1
  639. data/test/fixtures/unsymlinked.git/refs/heads/master +0 -1
  640. data/test/fixtures/unsymlinked.git/refs/heads/reg-file +0 -1
  641. data/test/index_test.rb +0 -333
  642. data/test/lib_test.rb +0 -127
  643. data/test/note_test.rb +0 -158
  644. data/test/object_test.rb +0 -43
  645. data/test/reference_test.rb +0 -207
  646. data/test/remote_test.rb +0 -324
  647. data/test/repo_pack_test.rb +0 -24
  648. data/test/repo_reset_test.rb +0 -82
  649. data/test/repo_test.rb +0 -402
  650. data/test/tag_test.rb +0 -68
  651. data/test/test_helper.rb +0 -92
  652. data/test/tree_test.rb +0 -91
  653. data/test/walker_test.rb +0 -88
  654. data/vendor/libgit2/Makefile.embed +0 -42
  655. data/vendor/libgit2/include/git2/push.h +0 -131
  656. data/vendor/libgit2/include/git2/threads.h +0 -50
  657. data/vendor/libgit2/src/amiga/map.c +0 -48
  658. data/vendor/libgit2/src/bswap.h +0 -97
  659. data/vendor/libgit2/src/compress.c +0 -53
  660. data/vendor/libgit2/src/config_file.h +0 -60
  661. data/vendor/libgit2/src/delta-apply.c +0 -134
  662. data/vendor/libgit2/src/delta-apply.h +0 -50
  663. data/vendor/libgit2/src/diff_patch.c +0 -995
  664. data/vendor/libgit2/src/diff_patch.h +0 -46
  665. data/vendor/libgit2/src/hashsig.h +0 -72
  666. data/vendor/libgit2/src/merge_file.h +0 -71
  667. data/vendor/libgit2/src/win32/pthread.c +0 -144
  668. data/vendor/libgit2/src/win32/pthread.h +0 -50
@@ -5,12 +5,14 @@
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
7
 
8
- #include <zlib.h>
8
+ #include "indexer.h"
9
9
 
10
10
  #include "git2/indexer.h"
11
11
  #include "git2/object.h"
12
12
 
13
- #include "common.h"
13
+ #include "commit.h"
14
+ #include "tree.h"
15
+ #include "tag.h"
14
16
  #include "pack.h"
15
17
  #include "mwindow.h"
16
18
  #include "posix.h"
@@ -18,6 +20,12 @@
18
20
  #include "filebuf.h"
19
21
  #include "oid.h"
20
22
  #include "oidmap.h"
23
+ #include "zstream.h"
24
+ #include "object.h"
25
+
26
+ extern git_mutex git__mwindow_mutex;
27
+
28
+ size_t git_indexer__max_objects = UINT32_MAX;
21
29
 
22
30
  #define UINT31_MAX (0x7FFFFFFF)
23
31
 
@@ -28,15 +36,20 @@ struct entry {
28
36
  uint64_t offset_long;
29
37
  };
30
38
 
31
- struct git_indexer_stream {
39
+ struct git_indexer {
32
40
  unsigned int parsed_header :1,
33
- opened_pack :1,
41
+ pack_committed :1,
34
42
  have_stream :1,
35
- have_delta :1;
43
+ have_delta :1,
44
+ do_fsync :1,
45
+ do_verify :1;
46
+ struct git_pack_header hdr;
36
47
  struct git_pack_file *pack;
37
- git_filebuf pack_file;
48
+ unsigned int mode;
38
49
  git_off_t off;
39
50
  git_off_t entry_start;
51
+ git_object_t entry_type;
52
+ git_buf entry_data;
40
53
  git_packfile_stream stream;
41
54
  size_t nr_objects;
42
55
  git_vector objects;
@@ -44,54 +57,50 @@ struct git_indexer_stream {
44
57
  unsigned int fanout[256];
45
58
  git_hash_ctx hash_ctx;
46
59
  git_oid hash;
47
- git_transfer_progress_callback progress_cb;
60
+ git_transfer_progress_cb progress_cb;
48
61
  void *progress_payload;
49
62
  char objbuf[8*1024];
63
+
64
+ /* OIDs referenced from pack objects. Used for verification. */
65
+ git_oidmap *expected_oids;
66
+
67
+ /* Needed to look up objects which we want to inject to fix a thin pack */
68
+ git_odb *odb;
69
+
70
+ /* Fields for calculating the packfile trailer (hash of everything before it) */
71
+ char inbuf[GIT_OID_RAWSZ];
72
+ size_t inbuf_len;
73
+ git_hash_ctx trailer;
50
74
  };
51
75
 
52
76
  struct delta_info {
53
77
  git_off_t delta_off;
54
78
  };
55
79
 
56
- const git_oid *git_indexer_stream_hash(const git_indexer_stream *idx)
80
+ const git_oid *git_indexer_hash(const git_indexer *idx)
57
81
  {
58
82
  return &idx->hash;
59
83
  }
60
84
 
61
- static int open_pack(struct git_pack_file **out, const char *filename)
62
- {
63
- struct git_pack_file *pack;
64
-
65
- if (git_packfile_alloc(&pack, filename) < 0)
66
- return -1;
67
-
68
- if ((pack->mwf.fd = p_open(pack->pack_name, O_RDONLY)) < 0) {
69
- giterr_set(GITERR_OS, "Failed to open packfile.");
70
- git_packfile_free(pack);
71
- return -1;
72
- }
73
-
74
- *out = pack;
75
- return 0;
76
- }
77
-
78
85
  static int parse_header(struct git_pack_header *hdr, struct git_pack_file *pack)
79
86
  {
80
87
  int error;
88
+ git_map map;
81
89
 
82
- /* Verify we recognize this pack file format. */
83
- if ((error = p_read(pack->mwf.fd, hdr, sizeof(*hdr))) < 0) {
84
- giterr_set(GITERR_OS, "Failed to read in pack header");
90
+ if ((error = p_mmap(&map, sizeof(*hdr), GIT_PROT_READ, GIT_MAP_SHARED, pack->mwf.fd, 0)) < 0)
85
91
  return error;
86
- }
87
92
 
93
+ memcpy(hdr, map.data, sizeof(*hdr));
94
+ p_munmap(&map);
95
+
96
+ /* Verify we recognize this pack file format. */
88
97
  if (hdr->hdr_signature != ntohl(PACK_SIGNATURE)) {
89
- giterr_set(GITERR_INDEXER, "Wrong pack signature");
98
+ git_error_set(GIT_ERROR_INDEXER, "wrong pack signature");
90
99
  return -1;
91
100
  }
92
101
 
93
102
  if (!pack_version_ok(hdr->hdr_version)) {
94
- giterr_set(GITERR_INDEXER, "Wrong pack version");
103
+ git_error_set(GIT_ERROR_INDEXER, "wrong pack version");
95
104
  return -1;
96
105
  }
97
106
 
@@ -106,49 +115,96 @@ static int objects_cmp(const void *a, const void *b)
106
115
  return git_oid__cmp(&entrya->oid, &entryb->oid);
107
116
  }
108
117
 
109
- int git_indexer_stream_new(
110
- git_indexer_stream **out,
118
+ int git_indexer_init_options(git_indexer_options *opts, unsigned int version)
119
+ {
120
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
121
+ opts, version, git_indexer_options, GIT_INDEXER_OPTIONS_INIT);
122
+ return 0;
123
+ }
124
+
125
+ int git_indexer_new(
126
+ git_indexer **out,
111
127
  const char *prefix,
112
- git_transfer_progress_callback progress_cb,
113
- void *progress_payload)
128
+ unsigned int mode,
129
+ git_odb *odb,
130
+ git_indexer_options *in_opts)
114
131
  {
115
- git_indexer_stream *idx;
116
- git_buf path = GIT_BUF_INIT;
132
+ git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT;
133
+ git_indexer *idx;
134
+ git_buf path = GIT_BUF_INIT, tmp_path = GIT_BUF_INIT;
117
135
  static const char suff[] = "/pack";
118
- int error;
136
+ int error, fd = -1;
137
+
138
+ if (in_opts)
139
+ memcpy(&opts, in_opts, sizeof(opts));
119
140
 
120
- idx = git__calloc(1, sizeof(git_indexer_stream));
121
- GITERR_CHECK_ALLOC(idx);
122
- idx->progress_cb = progress_cb;
123
- idx->progress_payload = progress_payload;
141
+ idx = git__calloc(1, sizeof(git_indexer));
142
+ GIT_ERROR_CHECK_ALLOC(idx);
143
+ idx->odb = odb;
144
+ idx->progress_cb = opts.progress_cb;
145
+ idx->progress_payload = opts.progress_cb_payload;
146
+ idx->mode = mode ? mode : GIT_PACK_FILE_MODE;
147
+ git_hash_ctx_init(&idx->hash_ctx);
148
+ git_hash_ctx_init(&idx->trailer);
149
+ git_buf_init(&idx->entry_data, 0);
150
+ idx->expected_oids = git_oidmap_alloc();
151
+ GIT_ERROR_CHECK_ALLOC(idx->expected_oids);
152
+
153
+ idx->do_verify = opts.verify;
154
+
155
+ if (git_repository__fsync_gitdir)
156
+ idx->do_fsync = 1;
124
157
 
125
158
  error = git_buf_joinpath(&path, prefix, suff);
126
159
  if (error < 0)
127
160
  goto cleanup;
128
161
 
129
- error = git_filebuf_open(&idx->pack_file, path.ptr,
130
- GIT_FILEBUF_TEMPORARY | GIT_FILEBUF_DO_NOT_BUFFER);
131
- git_buf_free(&path);
162
+ fd = git_futils_mktmp(&tmp_path, git_buf_cstr(&path), idx->mode);
163
+ git_buf_dispose(&path);
164
+ if (fd < 0)
165
+ goto cleanup;
166
+
167
+ error = git_packfile_alloc(&idx->pack, git_buf_cstr(&tmp_path));
168
+ git_buf_dispose(&tmp_path);
169
+
132
170
  if (error < 0)
133
171
  goto cleanup;
134
172
 
173
+ idx->pack->mwf.fd = fd;
174
+ if ((error = git_mwindow_file_register(&idx->pack->mwf)) < 0)
175
+ goto cleanup;
176
+
135
177
  *out = idx;
136
178
  return 0;
137
179
 
138
180
  cleanup:
139
- git_buf_free(&path);
140
- git_filebuf_cleanup(&idx->pack_file);
181
+ if (fd != -1)
182
+ p_close(fd);
183
+
184
+ if (git_buf_len(&tmp_path) > 0)
185
+ p_unlink(git_buf_cstr(&tmp_path));
186
+
187
+ if (idx->pack != NULL)
188
+ p_unlink(idx->pack->pack_name);
189
+
190
+ git_buf_dispose(&path);
191
+ git_buf_dispose(&tmp_path);
141
192
  git__free(idx);
142
193
  return -1;
143
194
  }
144
195
 
196
+ void git_indexer__set_fsync(git_indexer *idx, int do_fsync)
197
+ {
198
+ idx->do_fsync = !!do_fsync;
199
+ }
200
+
145
201
  /* Try to store the delta so we can try to resolve it later */
146
- static int store_delta(git_indexer_stream *idx)
202
+ static int store_delta(git_indexer *idx)
147
203
  {
148
204
  struct delta_info *delta;
149
205
 
150
206
  delta = git__calloc(1, sizeof(struct delta_info));
151
- GITERR_CHECK_ALLOC(delta);
207
+ GIT_ERROR_CHECK_ALLOC(delta);
152
208
  delta->delta_off = idx->entry_start;
153
209
 
154
210
  if (git_vector_insert(&idx->deltas, delta) < 0)
@@ -157,16 +213,20 @@ static int store_delta(git_indexer_stream *idx)
157
213
  return 0;
158
214
  }
159
215
 
160
- static void hash_header(git_hash_ctx *ctx, git_off_t len, git_otype type)
216
+ static int hash_header(git_hash_ctx *ctx, git_off_t len, git_object_t type)
161
217
  {
162
218
  char buffer[64];
163
219
  size_t hdrlen;
220
+ int error;
221
+
222
+ if ((error = git_odb__format_object_header(&hdrlen,
223
+ buffer, sizeof(buffer), (size_t)len, type)) < 0)
224
+ return error;
164
225
 
165
- hdrlen = git_odb__format_object_header(buffer, sizeof(buffer), (size_t)len, type);
166
- git_hash_update(ctx, buffer, hdrlen);
226
+ return git_hash_update(ctx, buffer, hdrlen);
167
227
  }
168
228
 
169
- static int hash_object_stream(git_indexer_stream *idx, git_packfile_stream *stream)
229
+ static int hash_object_stream(git_indexer*idx, git_packfile_stream *stream)
170
230
  {
171
231
  ssize_t read;
172
232
 
@@ -176,6 +236,9 @@ static int hash_object_stream(git_indexer_stream *idx, git_packfile_stream *stre
176
236
  if ((read = git_packfile_stream_read(stream, idx->objbuf, sizeof(idx->objbuf))) < 0)
177
237
  break;
178
238
 
239
+ if (idx->do_verify)
240
+ git_buf_put(&idx->entry_data, idx->objbuf, read);
241
+
179
242
  git_hash_update(&idx->hash_ctx, idx->objbuf, read);
180
243
  } while (read > 0);
181
244
 
@@ -186,13 +249,13 @@ static int hash_object_stream(git_indexer_stream *idx, git_packfile_stream *stre
186
249
  }
187
250
 
188
251
  /* In order to create the packfile stream, we need to skip over the delta base description */
189
- static int advance_delta_offset(git_indexer_stream *idx, git_otype type)
252
+ static int advance_delta_offset(git_indexer *idx, git_object_t type)
190
253
  {
191
254
  git_mwindow *w = NULL;
192
255
 
193
- assert(type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA);
256
+ assert(type == GIT_OBJECT_REF_DELTA || type == GIT_OBJECT_OFS_DELTA);
194
257
 
195
- if (type == GIT_OBJ_REF_DELTA) {
258
+ if (type == GIT_OBJECT_REF_DELTA) {
196
259
  idx->off += GIT_OID_RAWSZ;
197
260
  } else {
198
261
  git_off_t base_off = get_delta_base(idx->pack, &w, &idx->off, type, idx->entry_start);
@@ -205,7 +268,7 @@ static int advance_delta_offset(git_indexer_stream *idx, git_otype type)
205
268
  }
206
269
 
207
270
  /* Read from the stream and discard any output */
208
- static int read_object_stream(git_indexer_stream *idx, git_packfile_stream *stream)
271
+ static int read_object_stream(git_indexer *idx, git_packfile_stream *stream)
209
272
  {
210
273
  ssize_t read;
211
274
 
@@ -245,24 +308,114 @@ static int crc_object(uint32_t *crc_out, git_mwindow_file *mwf, git_off_t start,
245
308
  return 0;
246
309
  }
247
310
 
248
- static int store_object(git_indexer_stream *idx)
311
+ static void add_expected_oid(git_indexer *idx, const git_oid *oid)
312
+ {
313
+ int ret;
314
+
315
+ /*
316
+ * If we know about that object because it is stored in our ODB or
317
+ * because we have already processed it as part of our pack file, we do
318
+ * not have to expect it.
319
+ */
320
+ if ((!idx->odb || !git_odb_exists(idx->odb, oid)) &&
321
+ !git_oidmap_exists(idx->pack->idx_cache, oid) &&
322
+ !git_oidmap_exists(idx->expected_oids, oid)) {
323
+ git_oid *dup = git__malloc(sizeof(*oid));
324
+ git_oid_cpy(dup, oid);
325
+ git_oidmap_put(idx->expected_oids, dup, &ret);
326
+ }
327
+ }
328
+
329
+ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
330
+ {
331
+ git_object *object;
332
+ size_t keyidx;
333
+ int error;
334
+
335
+ if (obj->type != GIT_OBJECT_BLOB &&
336
+ obj->type != GIT_OBJECT_TREE &&
337
+ obj->type != GIT_OBJECT_COMMIT &&
338
+ obj->type != GIT_OBJECT_TAG)
339
+ return 0;
340
+
341
+ if ((error = git_object__from_raw(&object, obj->data, obj->len, obj->type)) < 0)
342
+ goto out;
343
+
344
+ keyidx = git_oidmap_lookup_index(idx->expected_oids, &object->cached.oid);
345
+ if (git_oidmap_valid_index(idx->expected_oids, keyidx)) {
346
+ const git_oid *key = git_oidmap_key(idx->expected_oids, keyidx);
347
+ git__free((git_oid *) key);
348
+ git_oidmap_delete_at(idx->expected_oids, keyidx);
349
+ }
350
+
351
+ /*
352
+ * Check whether this is a known object. If so, we can just continue as
353
+ * we assume that the ODB has a complete graph.
354
+ */
355
+ if (idx->odb && git_odb_exists(idx->odb, &object->cached.oid))
356
+ return 0;
357
+
358
+ switch (obj->type) {
359
+ case GIT_OBJECT_TREE:
360
+ {
361
+ git_tree *tree = (git_tree *) object;
362
+ git_tree_entry *entry;
363
+ size_t i;
364
+
365
+ git_array_foreach(tree->entries, i, entry)
366
+ add_expected_oid(idx, entry->oid);
367
+
368
+ break;
369
+ }
370
+ case GIT_OBJECT_COMMIT:
371
+ {
372
+ git_commit *commit = (git_commit *) object;
373
+ git_oid *parent_oid;
374
+ size_t i;
375
+
376
+ git_array_foreach(commit->parent_ids, i, parent_oid)
377
+ add_expected_oid(idx, parent_oid);
378
+
379
+ add_expected_oid(idx, &commit->tree_id);
380
+
381
+ break;
382
+ }
383
+ case GIT_OBJECT_TAG:
384
+ {
385
+ git_tag *tag = (git_tag *) object;
386
+
387
+ add_expected_oid(idx, &tag->target);
388
+
389
+ break;
390
+ }
391
+ case GIT_OBJECT_BLOB:
392
+ default:
393
+ break;
394
+ }
395
+
396
+ out:
397
+ git_object_free(object);
398
+
399
+ return error;
400
+ }
401
+
402
+ static int store_object(git_indexer *idx)
249
403
  {
250
404
  int i, error;
251
- khiter_t k;
405
+ size_t k;
252
406
  git_oid oid;
253
407
  struct entry *entry;
254
408
  git_off_t entry_size;
255
409
  struct git_pack_entry *pentry;
256
- git_hash_ctx *ctx = &idx->hash_ctx;
257
410
  git_off_t entry_start = idx->entry_start;
258
411
 
259
412
  entry = git__calloc(1, sizeof(*entry));
260
- GITERR_CHECK_ALLOC(entry);
413
+ GIT_ERROR_CHECK_ALLOC(entry);
261
414
 
262
415
  pentry = git__calloc(1, sizeof(struct git_pack_entry));
263
- GITERR_CHECK_ALLOC(pentry);
416
+ GIT_ERROR_CHECK_ALLOC(pentry);
264
417
 
265
- git_hash_final(&oid, ctx);
418
+ git_hash_final(&oid, &idx->hash_ctx);
266
419
  entry_size = idx->off - entry_start;
267
420
  if (entry_start > UINT31_MAX) {
268
421
  entry->offset = UINT32_MAX;
@@ -271,16 +424,35 @@ static int store_object(git_indexer_stream *idx)
271
424
  entry->offset = (uint32_t)entry_start;
272
425
  }
273
426
 
427
+ if (idx->do_verify) {
428
+ git_rawobj rawobj = {
429
+ idx->entry_data.ptr,
430
+ idx->entry_data.size,
431
+ idx->entry_type
432
+ };
433
+
434
+ if ((error = check_object_connectivity(idx, &rawobj)) < 0)
435
+ goto on_error;
436
+ }
437
+
274
438
  git_oid_cpy(&pentry->sha1, &oid);
275
439
  pentry->offset = entry_start;
276
440
 
277
- k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error);
278
- if (!error) {
441
+ k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error);
442
+ if (error == -1) {
443
+ git__free(pentry);
444
+ git_error_set_oom();
445
+ goto on_error;
446
+ }
447
+
448
+ if (error == 0) {
449
+ git_error_set(GIT_ERROR_INDEXER, "duplicate object %s found in pack", git_oid_tostr_s(&pentry->sha1));
279
450
  git__free(pentry);
280
451
  goto on_error;
281
452
  }
282
453
 
283
- kh_value(idx->pack->idx_cache, k) = pentry;
454
+
455
+ git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry);
284
456
 
285
457
  git_oid_cpy(&entry->oid, &oid);
286
458
 
@@ -303,17 +475,15 @@ on_error:
303
475
  return -1;
304
476
  }
305
477
 
306
- static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t entry_start)
478
+ GIT_INLINE(bool) has_entry(git_indexer *idx, git_oid *id)
307
479
  {
308
- int i, error;
309
- khiter_t k;
310
- git_oid oid;
311
- size_t entry_size;
312
- struct entry *entry;
313
- struct git_pack_entry *pentry;
480
+ return git_oidmap_exists(idx->pack->idx_cache, id);
481
+ }
314
482
 
315
- entry = git__calloc(1, sizeof(*entry));
316
- GITERR_CHECK_ALLOC(entry);
483
+ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start)
484
+ {
485
+ int i, error;
486
+ size_t k;
317
487
 
318
488
  if (entry_start > UINT31_MAX) {
319
489
  entry->offset = UINT32_MAX;
@@ -322,25 +492,46 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent
322
492
  entry->offset = (uint32_t)entry_start;
323
493
  }
324
494
 
325
- /* FIXME: Parse the object instead of hashing it */
326
- if (git_odb__hashobj(&oid, obj) < 0) {
327
- giterr_set(GITERR_INDEXER, "Failed to hash object");
495
+ pentry->offset = entry_start;
496
+ k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error);
497
+
498
+ if (error <= 0) {
499
+ git_error_set(GIT_ERROR_INDEXER, "cannot insert object into pack");
328
500
  return -1;
329
501
  }
330
502
 
331
- pentry = git__calloc(1, sizeof(struct git_pack_entry));
332
- GITERR_CHECK_ALLOC(pentry);
503
+ git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry);
333
504
 
334
- git_oid_cpy(&pentry->sha1, &oid);
335
- pentry->offset = entry_start;
336
- k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error);
337
- if (!error) {
338
- git__free(pentry);
505
+ /* Add the object to the list */
506
+ if (git_vector_insert(&idx->objects, entry) < 0)
507
+ return -1;
508
+
509
+ for (i = entry->oid.id[0]; i < 256; ++i) {
510
+ idx->fanout[i]++;
511
+ }
512
+
513
+ return 0;
514
+ }
515
+
516
+ static int hash_and_save(git_indexer *idx, git_rawobj *obj, git_off_t entry_start)
517
+ {
518
+ git_oid oid;
519
+ size_t entry_size;
520
+ struct entry *entry;
521
+ struct git_pack_entry *pentry = NULL;
522
+
523
+ entry = git__calloc(1, sizeof(*entry));
524
+ GIT_ERROR_CHECK_ALLOC(entry);
525
+
526
+ if (git_odb__hashobj(&oid, obj) < 0) {
527
+ git_error_set(GIT_ERROR_INDEXER, "failed to hash object");
339
528
  goto on_error;
340
529
  }
341
530
 
342
- kh_value(idx->pack->idx_cache, k) = pentry;
531
+ pentry = git__calloc(1, sizeof(struct git_pack_entry));
532
+ GIT_ERROR_CHECK_ALLOC(pentry);
343
533
 
534
+ git_oid_cpy(&pentry->sha1, &oid);
344
535
  git_oid_cpy(&entry->oid, &oid);
345
536
  entry->crc = crc32(0L, Z_NULL, 0);
346
537
 
@@ -348,76 +539,250 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent
348
539
  if (crc_object(&entry->crc, &idx->pack->mwf, entry_start, entry_size) < 0)
349
540
  goto on_error;
350
541
 
351
- /* Add the object to the list */
352
- if (git_vector_insert(&idx->objects, entry) < 0)
353
- goto on_error;
354
-
355
- for (i = oid.id[0]; i < 256; ++i) {
356
- idx->fanout[i]++;
357
- }
358
-
359
- return 0;
542
+ return save_entry(idx, entry, pentry, entry_start);
360
543
 
361
544
  on_error:
545
+ git__free(pentry);
362
546
  git__free(entry);
363
547
  git__free(obj->data);
364
548
  return -1;
365
549
  }
366
550
 
367
- static int do_progress_callback(git_indexer_stream *idx, git_transfer_progress *stats)
551
+ static int do_progress_callback(git_indexer *idx, git_transfer_progress *stats)
552
+ {
553
+ if (idx->progress_cb)
554
+ return git_error_set_after_callback_function(
555
+ idx->progress_cb(stats, idx->progress_payload),
556
+ "indexer progress");
557
+ return 0;
558
+ }
559
+
560
+ /* Hash everything but the last 20B of input */
561
+ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
562
+ {
563
+ size_t to_expell, to_keep;
564
+
565
+ if (size == 0)
566
+ return;
567
+
568
+ /* Easy case, dump the buffer and the data minus the last 20 bytes */
569
+ if (size >= GIT_OID_RAWSZ) {
570
+ git_hash_update(&idx->trailer, idx->inbuf, idx->inbuf_len);
571
+ git_hash_update(&idx->trailer, data, size - GIT_OID_RAWSZ);
572
+
573
+ data += size - GIT_OID_RAWSZ;
574
+ memcpy(idx->inbuf, data, GIT_OID_RAWSZ);
575
+ idx->inbuf_len = GIT_OID_RAWSZ;
576
+ return;
577
+ }
578
+
579
+ /* We can just append */
580
+ if (idx->inbuf_len + size <= GIT_OID_RAWSZ) {
581
+ memcpy(idx->inbuf + idx->inbuf_len, data, size);
582
+ idx->inbuf_len += size;
583
+ return;
584
+ }
585
+
586
+ /* We need to partially drain the buffer and then append */
587
+ to_keep = GIT_OID_RAWSZ - size;
588
+ to_expell = idx->inbuf_len - to_keep;
589
+
590
+ git_hash_update(&idx->trailer, idx->inbuf, to_expell);
591
+
592
+ memmove(idx->inbuf, idx->inbuf + to_expell, to_keep);
593
+ memcpy(idx->inbuf + to_keep, data, size);
594
+ idx->inbuf_len += size - to_expell;
595
+ }
596
+
597
+ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t size)
598
+ {
599
+ git_file fd = idx->pack->mwf.fd;
600
+ size_t mmap_alignment;
601
+ size_t page_offset;
602
+ git_off_t page_start;
603
+ unsigned char *map_data;
604
+ git_map map;
605
+ int error;
606
+
607
+ assert(data && size);
608
+
609
+ if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
610
+ return error;
611
+
612
+ /* the offset needs to be at the mmap boundary for the platform */
613
+ page_offset = offset % mmap_alignment;
614
+ page_start = offset - page_offset;
615
+
616
+ if ((error = p_mmap(&map, page_offset + size, GIT_PROT_WRITE, GIT_MAP_SHARED, fd, page_start)) < 0)
617
+ return error;
618
+
619
+ map_data = (unsigned char *)map.data;
620
+ memcpy(map_data + page_offset, data, size);
621
+ p_munmap(&map);
622
+
623
+ return 0;
624
+ }
625
+
626
+ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
627
+ {
628
+ git_off_t new_size;
629
+ size_t mmap_alignment;
630
+ size_t page_offset;
631
+ git_off_t page_start;
632
+ git_off_t current_size = idx->pack->mwf.size;
633
+ int fd = idx->pack->mwf.fd;
634
+ int error;
635
+
636
+ if (!size)
637
+ return 0;
638
+
639
+ if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
640
+ return error;
641
+
642
+ /* Write a single byte to force the file system to allocate space now or
643
+ * report an error, since we can't report errors when writing using mmap.
644
+ * Round the size up to the nearest page so that we only need to perform file
645
+ * I/O when we add a page, instead of whenever we write even a single byte. */
646
+ new_size = current_size + size;
647
+ page_offset = new_size % mmap_alignment;
648
+ page_start = new_size - page_offset;
649
+
650
+ if (p_lseek(fd, page_start + mmap_alignment - 1, SEEK_SET) < 0 ||
651
+ p_write(idx->pack->mwf.fd, data, 1) < 0) {
652
+ git_error_set(GIT_ERROR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
653
+ return -1;
654
+ }
655
+
656
+ return write_at(idx, data, idx->pack->mwf.size, size);
657
+ }
658
+
659
+ static int read_stream_object(git_indexer *idx, git_transfer_progress *stats)
368
660
  {
369
- if (!idx->progress_cb) return 0;
370
- return idx->progress_cb(stats, idx->progress_payload);
661
+ git_packfile_stream *stream = &idx->stream;
662
+ git_off_t entry_start = idx->off;
663
+ size_t entry_size;
664
+ git_object_t type;
665
+ git_mwindow *w = NULL;
666
+ int error;
667
+
668
+ if (idx->pack->mwf.size <= idx->off + 20)
669
+ return GIT_EBUFS;
670
+
671
+ if (!idx->have_stream) {
672
+ error = git_packfile_unpack_header(&entry_size, &type, &idx->pack->mwf, &w, &idx->off);
673
+ if (error == GIT_EBUFS) {
674
+ idx->off = entry_start;
675
+ return error;
676
+ }
677
+ if (error < 0)
678
+ return error;
679
+
680
+ git_mwindow_close(&w);
681
+ idx->entry_start = entry_start;
682
+ git_hash_init(&idx->hash_ctx);
683
+ git_buf_clear(&idx->entry_data);
684
+
685
+ if (type == GIT_OBJECT_REF_DELTA || type == GIT_OBJECT_OFS_DELTA) {
686
+ error = advance_delta_offset(idx, type);
687
+ if (error == GIT_EBUFS) {
688
+ idx->off = entry_start;
689
+ return error;
690
+ }
691
+ if (error < 0)
692
+ return error;
693
+
694
+ idx->have_delta = 1;
695
+ } else {
696
+ idx->have_delta = 0;
697
+
698
+ error = hash_header(&idx->hash_ctx, entry_size, type);
699
+ if (error < 0)
700
+ return error;
701
+ }
702
+
703
+ idx->have_stream = 1;
704
+ idx->entry_type = type;
705
+
706
+ error = git_packfile_stream_open(stream, idx->pack, idx->off);
707
+ if (error < 0)
708
+ return error;
709
+ }
710
+
711
+ if (idx->have_delta) {
712
+ error = read_object_stream(idx, stream);
713
+ } else {
714
+ error = hash_object_stream(idx, stream);
715
+ }
716
+
717
+ idx->off = stream->curpos;
718
+ if (error == GIT_EBUFS)
719
+ return error;
720
+
721
+ /* We want to free the stream reasorces no matter what here */
722
+ idx->have_stream = 0;
723
+ git_packfile_stream_dispose(stream);
724
+
725
+ if (error < 0)
726
+ return error;
727
+
728
+ if (idx->have_delta) {
729
+ error = store_delta(idx);
730
+ } else {
731
+ error = store_object(idx);
732
+ }
733
+
734
+ if (error < 0)
735
+ return error;
736
+
737
+ if (!idx->have_delta) {
738
+ stats->indexed_objects++;
739
+ }
740
+ stats->received_objects++;
741
+
742
+ if ((error = do_progress_callback(idx, stats)) != 0)
743
+ return error;
744
+
745
+ return 0;
371
746
  }
372
747
 
373
- int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats)
748
+ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_transfer_progress *stats)
374
749
  {
375
750
  int error = -1;
376
- struct git_pack_header hdr;
377
- size_t processed;
751
+ struct git_pack_header *hdr = &idx->hdr;
378
752
  git_mwindow_file *mwf = &idx->pack->mwf;
379
753
 
380
754
  assert(idx && data && stats);
381
755
 
382
- processed = stats->indexed_objects;
756
+ if ((error = append_to_pack(idx, data, size)) < 0)
757
+ return error;
383
758
 
384
- if (git_filebuf_write(&idx->pack_file, data, size) < 0)
385
- return -1;
759
+ hash_partially(idx, data, (int)size);
386
760
 
387
761
  /* Make sure we set the new size of the pack */
388
- if (idx->opened_pack) {
389
- idx->pack->mwf.size += size;
390
- } else {
391
- if (open_pack(&idx->pack, idx->pack_file.path_lock) < 0)
392
- return -1;
393
- idx->opened_pack = 1;
394
- mwf = &idx->pack->mwf;
395
- if (git_mwindow_file_register(&idx->pack->mwf) < 0)
396
- return -1;
397
- }
762
+ idx->pack->mwf.size += size;
398
763
 
399
764
  if (!idx->parsed_header) {
400
765
  unsigned int total_objects;
401
766
 
402
- if ((unsigned)idx->pack->mwf.size < sizeof(hdr))
767
+ if ((unsigned)idx->pack->mwf.size < sizeof(struct git_pack_header))
403
768
  return 0;
404
769
 
405
- if (parse_header(&hdr, idx->pack) < 0)
406
- return -1;
770
+ if ((error = parse_header(&idx->hdr, idx->pack)) < 0)
771
+ return error;
407
772
 
408
773
  idx->parsed_header = 1;
409
- idx->nr_objects = ntohl(hdr.hdr_entries);
774
+ idx->nr_objects = ntohl(hdr->hdr_entries);
410
775
  idx->off = sizeof(struct git_pack_header);
411
776
 
412
- /* for now, limit to 2^32 objects */
413
- assert(idx->nr_objects == (size_t)((unsigned int)idx->nr_objects));
414
- if (idx->nr_objects == (size_t)((unsigned int)idx->nr_objects))
777
+ if (idx->nr_objects <= git_indexer__max_objects) {
415
778
  total_objects = (unsigned int)idx->nr_objects;
416
- else
417
- total_objects = UINT_MAX;
779
+ } else {
780
+ git_error_set(GIT_ERROR_INDEXER, "too many objects");
781
+ return -1;
782
+ }
418
783
 
419
784
  idx->pack->idx_cache = git_oidmap_alloc();
420
- GITERR_CHECK_ALLOC(idx->pack->idx_cache);
785
+ GIT_ERROR_CHECK_ALLOC(idx->pack->idx_cache);
421
786
 
422
787
  idx->pack->has_cache = 1;
423
788
  if (git_vector_init(&idx->objects, total_objects, objects_cmp) < 0)
@@ -427,93 +792,27 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
427
792
  return -1;
428
793
 
429
794
  stats->received_objects = 0;
430
- processed = stats->indexed_objects = 0;
795
+ stats->local_objects = 0;
796
+ stats->total_deltas = 0;
797
+ stats->indexed_deltas = 0;
798
+ stats->indexed_objects = 0;
431
799
  stats->total_objects = total_objects;
432
- do_progress_callback(idx, stats);
800
+
801
+ if ((error = do_progress_callback(idx, stats)) != 0)
802
+ return error;
433
803
  }
434
804
 
435
805
  /* Now that we have data in the pack, let's try to parse it */
436
806
 
437
807
  /* As the file grows any windows we try to use will be out of date */
438
808
  git_mwindow_free_all(mwf);
439
- while (processed < idx->nr_objects) {
440
- git_packfile_stream *stream = &idx->stream;
441
- git_off_t entry_start = idx->off;
442
- size_t entry_size;
443
- git_otype type;
444
- git_mwindow *w = NULL;
445
-
446
- if (idx->pack->mwf.size <= idx->off + 20)
447
- return 0;
448
-
449
- if (!idx->have_stream) {
450
- error = git_packfile_unpack_header(&entry_size, &type, mwf, &w, &idx->off);
451
- if (error == GIT_EBUFS) {
452
- idx->off = entry_start;
453
- return 0;
454
- }
455
- if (error < 0)
456
- return -1;
457
-
458
- git_mwindow_close(&w);
459
- idx->entry_start = entry_start;
460
- git_hash_ctx_init(&idx->hash_ctx);
461
809
 
462
- if (type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA) {
463
- error = advance_delta_offset(idx, type);
464
- if (error == GIT_EBUFS) {
465
- idx->off = entry_start;
466
- return 0;
467
- }
468
- if (error < 0)
469
- return -1;
470
-
471
- idx->have_delta = 1;
472
- } else {
473
- idx->have_delta = 0;
474
- hash_header(&idx->hash_ctx, entry_size, type);
475
- }
476
-
477
- idx->have_stream = 1;
478
- if (git_packfile_stream_open(stream, idx->pack, idx->off) < 0)
810
+ while (stats->indexed_objects < idx->nr_objects) {
811
+ if ((error = read_stream_object(idx, stats)) != 0) {
812
+ if (error == GIT_EBUFS)
813
+ break;
814
+ else
479
815
  goto on_error;
480
-
481
- }
482
-
483
- if (idx->have_delta) {
484
- error = read_object_stream(idx, stream);
485
- } else {
486
- error = hash_object_stream(idx, stream);
487
- }
488
-
489
- idx->off = stream->curpos;
490
- if (error == GIT_EBUFS)
491
- return 0;
492
-
493
- /* We want to free the stream reasorces no matter what here */
494
- idx->have_stream = 0;
495
- git_packfile_stream_free(stream);
496
-
497
- if (error < 0)
498
- goto on_error;
499
-
500
- if (idx->have_delta) {
501
- error = store_delta(idx);
502
- } else {
503
- error = store_object(idx);
504
- }
505
-
506
- if (error < 0)
507
- goto on_error;
508
-
509
- if (!idx->have_delta) {
510
- stats->indexed_objects = (unsigned int)++processed;
511
- }
512
- stats->received_objects++;
513
-
514
- if (do_progress_callback(idx, stats) != 0) {
515
- error = GIT_EUSER;
516
- goto on_error;
517
816
  }
518
817
  }
519
818
 
@@ -524,7 +823,7 @@ on_error:
524
823
  return error;
525
824
  }
526
825
 
527
- static int index_path_stream(git_buf *path, git_indexer_stream *idx, const char *suffix)
826
+ static int index_path(git_buf *path, git_indexer *idx, const char *suffix)
528
827
  {
529
828
  const char prefix[] = "pack-";
530
829
  size_t slash = (size_t)path->size;
@@ -546,68 +845,340 @@ static int index_path_stream(git_buf *path, git_indexer_stream *idx, const char
546
845
  return git_buf_oom(path) ? -1 : 0;
547
846
  }
548
847
 
549
- static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats)
848
+ /**
849
+ * Rewind the packfile by the trailer, as we might need to fix the
850
+ * packfile by injecting objects at the tail and must overwrite it.
851
+ */
852
+ static void seek_back_trailer(git_indexer *idx)
853
+ {
854
+ idx->pack->mwf.size -= GIT_OID_RAWSZ;
855
+ git_mwindow_free_all(&idx->pack->mwf);
856
+ }
857
+
858
+ static int inject_object(git_indexer *idx, git_oid *id)
550
859
  {
860
+ git_odb_object *obj;
861
+ struct entry *entry;
862
+ struct git_pack_entry *pentry = NULL;
863
+ git_oid foo = {{0}};
864
+ unsigned char hdr[64];
865
+ git_buf buf = GIT_BUF_INIT;
866
+ git_off_t entry_start;
867
+ const void *data;
868
+ size_t len, hdr_len;
869
+ int error;
870
+
871
+ seek_back_trailer(idx);
872
+ entry_start = idx->pack->mwf.size;
873
+
874
+ if (git_odb_read(&obj, idx->odb, id) < 0) {
875
+ git_error_set(GIT_ERROR_INDEXER, "missing delta bases");
876
+ return -1;
877
+ }
878
+
879
+ data = git_odb_object_data(obj);
880
+ len = git_odb_object_size(obj);
881
+
882
+ entry = git__calloc(1, sizeof(*entry));
883
+ GIT_ERROR_CHECK_ALLOC(entry);
884
+
885
+ entry->crc = crc32(0L, Z_NULL, 0);
886
+
887
+ /* Write out the object header */
888
+ hdr_len = git_packfile__object_header(hdr, len, git_odb_object_type(obj));
889
+ if ((error = append_to_pack(idx, hdr, hdr_len)) < 0)
890
+ goto cleanup;
891
+
892
+ idx->pack->mwf.size += hdr_len;
893
+ entry->crc = crc32(entry->crc, hdr, (uInt)hdr_len);
894
+
895
+ if ((error = git_zstream_deflatebuf(&buf, data, len)) < 0)
896
+ goto cleanup;
897
+
898
+ /* And then the compressed object */
899
+ if ((error = append_to_pack(idx, buf.ptr, buf.size)) < 0)
900
+ goto cleanup;
901
+
902
+ idx->pack->mwf.size += buf.size;
903
+ entry->crc = htonl(crc32(entry->crc, (unsigned char *)buf.ptr, (uInt)buf.size));
904
+ git_buf_dispose(&buf);
905
+
906
+ /* Write a fake trailer so the pack functions play ball */
907
+
908
+ if ((error = append_to_pack(idx, &foo, GIT_OID_RAWSZ)) < 0)
909
+ goto cleanup;
910
+
911
+ idx->pack->mwf.size += GIT_OID_RAWSZ;
912
+
913
+ pentry = git__calloc(1, sizeof(struct git_pack_entry));
914
+ GIT_ERROR_CHECK_ALLOC(pentry);
915
+
916
+ git_oid_cpy(&pentry->sha1, id);
917
+ git_oid_cpy(&entry->oid, id);
918
+ idx->off = entry_start + hdr_len + len;
919
+
920
+ error = save_entry(idx, entry, pentry, entry_start);
921
+
922
+ cleanup:
923
+ if (error) {
924
+ git__free(entry);
925
+ git__free(pentry);
926
+ }
927
+
928
+ git_odb_object_free(obj);
929
+ return error;
930
+ }
931
+
932
+ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats)
933
+ {
934
+ int error, found_ref_delta = 0;
551
935
  unsigned int i;
552
936
  struct delta_info *delta;
937
+ size_t size;
938
+ git_object_t type;
939
+ git_mwindow *w = NULL;
940
+ git_off_t curpos = 0;
941
+ unsigned char *base_info;
942
+ unsigned int left = 0;
943
+ git_oid base;
553
944
 
945
+ assert(git_vector_length(&idx->deltas) > 0);
946
+
947
+ if (idx->odb == NULL) {
948
+ git_error_set(GIT_ERROR_INDEXER, "cannot fix a thin pack without an ODB");
949
+ return -1;
950
+ }
951
+
952
+ /* Loop until we find the first REF delta */
554
953
  git_vector_foreach(&idx->deltas, i, delta) {
555
- git_rawobj obj;
954
+ if (!delta)
955
+ continue;
956
+
957
+ curpos = delta->delta_off;
958
+ error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos);
959
+ if (error < 0)
960
+ return error;
961
+
962
+ if (type == GIT_OBJECT_REF_DELTA) {
963
+ found_ref_delta = 1;
964
+ break;
965
+ }
966
+ }
556
967
 
557
- idx->off = delta->delta_off;
558
- if (git_packfile_unpack(&obj, idx->pack, &idx->off) < 0)
968
+ if (!found_ref_delta) {
969
+ git_error_set(GIT_ERROR_INDEXER, "no REF_DELTA found, cannot inject object");
970
+ return -1;
971
+ }
972
+
973
+ /* curpos now points to the base information, which is an OID */
974
+ base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, GIT_OID_RAWSZ, &left);
975
+ if (base_info == NULL) {
976
+ git_error_set(GIT_ERROR_INDEXER, "failed to map delta information");
977
+ return -1;
978
+ }
979
+
980
+ git_oid_fromraw(&base, base_info);
981
+ git_mwindow_close(&w);
982
+
983
+ if (has_entry(idx, &base))
984
+ return 0;
985
+
986
+ if (inject_object(idx, &base) < 0)
987
+ return -1;
988
+
989
+ stats->local_objects++;
990
+
991
+ return 0;
992
+ }
993
+
994
+ static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats)
995
+ {
996
+ unsigned int i;
997
+ int error;
998
+ struct delta_info *delta;
999
+ int progressed = 0, non_null = 0, progress_cb_result;
1000
+
1001
+ while (idx->deltas.length > 0) {
1002
+ progressed = 0;
1003
+ non_null = 0;
1004
+ git_vector_foreach(&idx->deltas, i, delta) {
1005
+ git_rawobj obj = {0};
1006
+
1007
+ if (!delta)
1008
+ continue;
1009
+
1010
+ non_null = 1;
1011
+ idx->off = delta->delta_off;
1012
+ if ((error = git_packfile_unpack(&obj, idx->pack, &idx->off)) < 0) {
1013
+ if (error == GIT_PASSTHROUGH) {
1014
+ /* We have not seen the base object, we'll try again later. */
1015
+ continue;
1016
+ }
1017
+ return -1;
1018
+ }
1019
+
1020
+ if (idx->do_verify && check_object_connectivity(idx, &obj) < 0)
1021
+ /* TODO: error? continue? */
1022
+ continue;
1023
+
1024
+ if (hash_and_save(idx, &obj, delta->delta_off) < 0)
1025
+ continue;
1026
+
1027
+ git__free(obj.data);
1028
+ stats->indexed_objects++;
1029
+ stats->indexed_deltas++;
1030
+ progressed = 1;
1031
+ if ((progress_cb_result = do_progress_callback(idx, stats)) < 0)
1032
+ return progress_cb_result;
1033
+
1034
+ /* remove from the list */
1035
+ git_vector_set(NULL, &idx->deltas, i, NULL);
1036
+ git__free(delta);
1037
+ }
1038
+
1039
+ /* if none were actually set, we're done */
1040
+ if (!non_null)
1041
+ break;
1042
+
1043
+ if (!progressed && (fix_thin_pack(idx, stats) < 0)) {
559
1044
  return -1;
1045
+ }
1046
+ }
1047
+
1048
+ return 0;
1049
+ }
1050
+
1051
+ static int update_header_and_rehash(git_indexer *idx, git_transfer_progress *stats)
1052
+ {
1053
+ void *ptr;
1054
+ size_t chunk = 1024*1024;
1055
+ git_off_t hashed = 0;
1056
+ git_mwindow *w = NULL;
1057
+ git_mwindow_file *mwf;
1058
+ unsigned int left;
1059
+
1060
+ mwf = &idx->pack->mwf;
560
1061
 
561
- if (hash_and_save(idx, &obj, delta->delta_off) < 0)
1062
+ git_hash_init(&idx->trailer);
1063
+
1064
+
1065
+ /* Update the header to include the numer of local objects we injected */
1066
+ idx->hdr.hdr_entries = htonl(stats->total_objects + stats->local_objects);
1067
+ if (write_at(idx, &idx->hdr, 0, sizeof(struct git_pack_header)) < 0)
1068
+ return -1;
1069
+
1070
+ /*
1071
+ * We now use the same technique as before to determine the
1072
+ * hash. We keep reading up to the end and let
1073
+ * hash_partially() keep the existing trailer out of the
1074
+ * calculation.
1075
+ */
1076
+ git_mwindow_free_all(mwf);
1077
+ idx->inbuf_len = 0;
1078
+ while (hashed < mwf->size) {
1079
+ ptr = git_mwindow_open(mwf, &w, hashed, chunk, &left);
1080
+ if (ptr == NULL)
562
1081
  return -1;
563
1082
 
564
- git__free(obj.data);
565
- stats->indexed_objects++;
566
- do_progress_callback(idx, stats);
1083
+ hash_partially(idx, ptr, left);
1084
+ hashed += left;
1085
+
1086
+ git_mwindow_close(&w);
567
1087
  }
568
1088
 
569
1089
  return 0;
570
1090
  }
571
1091
 
572
- int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *stats)
1092
+ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
573
1093
  {
574
1094
  git_mwindow *w = NULL;
575
1095
  unsigned int i, long_offsets = 0, left;
1096
+ int error;
576
1097
  struct git_pack_idx_header hdr;
577
1098
  git_buf filename = GIT_BUF_INIT;
578
1099
  struct entry *entry;
579
- void *packfile_hash;
580
- git_oid file_hash;
581
- git_hash_ctx ctx;
1100
+ git_oid trailer_hash, file_hash;
582
1101
  git_filebuf index_file = {0};
1102
+ void *packfile_trailer;
583
1103
 
584
- if (git_hash_ctx_init(&ctx) < 0)
1104
+ if (!idx->parsed_header) {
1105
+ git_error_set(GIT_ERROR_INDEXER, "incomplete pack header");
585
1106
  return -1;
1107
+ }
586
1108
 
587
1109
  /* Test for this before resolve_deltas(), as it plays with idx->off */
588
- if (idx->off < idx->pack->mwf.size - GIT_OID_RAWSZ) {
589
- giterr_set(GITERR_INDEXER, "Indexing error: unexpected data at the end of the pack");
1110
+ if (idx->off + 20 < idx->pack->mwf.size) {
1111
+ git_error_set(GIT_ERROR_INDEXER, "unexpected data at the end of the pack");
1112
+ return -1;
1113
+ }
1114
+ if (idx->off + 20 > idx->pack->mwf.size) {
1115
+ git_error_set(GIT_ERROR_INDEXER, "missing trailer at the end of the pack");
590
1116
  return -1;
591
1117
  }
592
1118
 
593
- if (idx->deltas.length > 0)
594
- if (resolve_deltas(idx, stats) < 0)
595
- return -1;
1119
+ packfile_trailer = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left);
1120
+ if (packfile_trailer == NULL) {
1121
+ git_mwindow_close(&w);
1122
+ goto on_error;
1123
+ }
1124
+
1125
+ /* Compare the packfile trailer as it was sent to us and what we calculated */
1126
+ git_oid_fromraw(&file_hash, packfile_trailer);
1127
+ git_mwindow_close(&w);
1128
+
1129
+ git_hash_final(&trailer_hash, &idx->trailer);
1130
+ if (git_oid_cmp(&file_hash, &trailer_hash)) {
1131
+ git_error_set(GIT_ERROR_INDEXER, "packfile trailer mismatch");
1132
+ return -1;
1133
+ }
1134
+
1135
+ /* Freeze the number of deltas */
1136
+ stats->total_deltas = stats->total_objects - stats->indexed_objects;
1137
+
1138
+ if ((error = resolve_deltas(idx, stats)) < 0)
1139
+ return error;
596
1140
 
597
1141
  if (stats->indexed_objects != stats->total_objects) {
598
- giterr_set(GITERR_INDEXER, "Indexing error: early EOF");
1142
+ git_error_set(GIT_ERROR_INDEXER, "early EOF");
1143
+ return -1;
1144
+ }
1145
+
1146
+ if (stats->local_objects > 0) {
1147
+ if (update_header_and_rehash(idx, stats) < 0)
1148
+ return -1;
1149
+
1150
+ git_hash_final(&trailer_hash, &idx->trailer);
1151
+ write_at(idx, &trailer_hash, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ);
1152
+ }
1153
+
1154
+ /*
1155
+ * Is the resulting graph fully connected or are we still
1156
+ * missing some objects? In the second case, we can
1157
+ * bail out due to an incomplete and thus corrupt
1158
+ * packfile.
1159
+ */
1160
+ if (git_oidmap_size(idx->expected_oids) > 0) {
1161
+ git_error_set(GIT_ERROR_INDEXER, "packfile is missing %"PRIuZ" objects",
1162
+ git_oidmap_size(idx->expected_oids));
599
1163
  return -1;
600
1164
  }
601
1165
 
602
1166
  git_vector_sort(&idx->objects);
603
1167
 
1168
+ /* Use the trailer hash as the pack file name to ensure
1169
+ * files with different contents have different names */
1170
+ git_oid_cpy(&idx->hash, &trailer_hash);
1171
+
604
1172
  git_buf_sets(&filename, idx->pack->pack_name);
605
- git_buf_truncate(&filename, filename.size - strlen("pack"));
1173
+ git_buf_shorten(&filename, strlen("pack"));
606
1174
  git_buf_puts(&filename, "idx");
607
1175
  if (git_buf_oom(&filename))
608
1176
  return -1;
609
1177
 
610
- if (git_filebuf_open(&index_file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS) < 0)
1178
+ if (git_filebuf_open(&index_file, filename.ptr,
1179
+ GIT_FILEBUF_HASH_CONTENTS |
1180
+ (idx->do_fsync ? GIT_FILEBUF_FSYNC : 0),
1181
+ idx->mode) < 0)
611
1182
  goto on_error;
612
1183
 
613
1184
  /* Write out the header */
@@ -624,9 +1195,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *
624
1195
  /* Write out the object names (SHA-1 hashes) */
625
1196
  git_vector_foreach(&idx->objects, i, entry) {
626
1197
  git_filebuf_write(&index_file, &entry->oid, sizeof(git_oid));
627
- git_hash_update(&ctx, &entry->oid, GIT_OID_RAWSZ);
628
1198
  }
629
- git_hash_final(&idx->hash, &ctx);
630
1199
 
631
1200
  /* Write out the CRC32 values */
632
1201
  git_vector_foreach(&idx->objects, i, entry) {
@@ -658,81 +1227,112 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *
658
1227
  git_filebuf_write(&index_file, &split, sizeof(uint32_t) * 2);
659
1228
  }
660
1229
 
661
- /* Write out the packfile trailer */
662
- packfile_hash = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left);
663
- if (packfile_hash == NULL) {
664
- git_mwindow_close(&w);
1230
+ /* Write out the packfile trailer to the index */
1231
+ if (git_filebuf_write(&index_file, &trailer_hash, GIT_OID_RAWSZ) < 0)
665
1232
  goto on_error;
666
- }
667
-
668
- memcpy(&file_hash, packfile_hash, GIT_OID_RAWSZ);
669
- git_mwindow_close(&w);
670
-
671
- git_filebuf_write(&index_file, &file_hash, sizeof(git_oid));
672
1233
 
673
- /* Write out the packfile trailer to the idx file as well */
674
- if (git_filebuf_hash(&file_hash, &index_file) < 0)
1234
+ /* Write out the hash of the idx */
1235
+ if (git_filebuf_hash(&trailer_hash, &index_file) < 0)
675
1236
  goto on_error;
676
1237
 
677
- git_filebuf_write(&index_file, &file_hash, sizeof(git_oid));
1238
+ git_filebuf_write(&index_file, &trailer_hash, sizeof(git_oid));
678
1239
 
679
1240
  /* Figure out what the final name should be */
680
- if (index_path_stream(&filename, idx, ".idx") < 0)
1241
+ if (index_path(&filename, idx, ".idx") < 0)
681
1242
  goto on_error;
682
1243
 
683
1244
  /* Commit file */
684
- if (git_filebuf_commit_at(&index_file, filename.ptr, GIT_PACK_FILE_MODE) < 0)
1245
+ if (git_filebuf_commit_at(&index_file, filename.ptr) < 0)
685
1246
  goto on_error;
686
1247
 
687
1248
  git_mwindow_free_all(&idx->pack->mwf);
1249
+
1250
+ /* Truncate file to undo rounding up to next page_size in append_to_pack */
1251
+ if (p_ftruncate(idx->pack->mwf.fd, idx->pack->mwf.size) < 0) {
1252
+ git_error_set(GIT_ERROR_OS, "failed to truncate pack file '%s'", idx->pack->pack_name);
1253
+ return -1;
1254
+ }
1255
+
1256
+ if (idx->do_fsync && p_fsync(idx->pack->mwf.fd) < 0) {
1257
+ git_error_set(GIT_ERROR_OS, "failed to fsync packfile");
1258
+ goto on_error;
1259
+ }
1260
+
688
1261
  /* We need to close the descriptor here so Windows doesn't choke on commit_at */
689
- p_close(idx->pack->mwf.fd);
1262
+ if (p_close(idx->pack->mwf.fd) < 0) {
1263
+ git_error_set(GIT_ERROR_OS, "failed to close packfile");
1264
+ goto on_error;
1265
+ }
1266
+
690
1267
  idx->pack->mwf.fd = -1;
691
1268
 
692
- if (index_path_stream(&filename, idx, ".pack") < 0)
1269
+ if (index_path(&filename, idx, ".pack") < 0)
693
1270
  goto on_error;
1271
+
694
1272
  /* And don't forget to rename the packfile to its new place. */
695
- if (git_filebuf_commit_at(&idx->pack_file, filename.ptr, GIT_PACK_FILE_MODE) < 0)
696
- return -1;
1273
+ if (p_rename(idx->pack->pack_name, git_buf_cstr(&filename)) < 0)
1274
+ goto on_error;
1275
+
1276
+ /* And fsync the parent directory if we're asked to. */
1277
+ if (idx->do_fsync &&
1278
+ git_futils_fsync_parent(git_buf_cstr(&filename)) < 0)
1279
+ goto on_error;
1280
+
1281
+ idx->pack_committed = 1;
697
1282
 
698
- git_buf_free(&filename);
1283
+ git_buf_dispose(&filename);
699
1284
  return 0;
700
1285
 
701
1286
  on_error:
702
1287
  git_mwindow_free_all(&idx->pack->mwf);
703
1288
  git_filebuf_cleanup(&index_file);
704
- git_buf_free(&filename);
705
- git_hash_ctx_cleanup(&ctx);
1289
+ git_buf_dispose(&filename);
706
1290
  return -1;
707
1291
  }
708
1292
 
709
- void git_indexer_stream_free(git_indexer_stream *idx)
1293
+ void git_indexer_free(git_indexer *idx)
710
1294
  {
711
- khiter_t k;
712
- unsigned int i;
713
- struct entry *e;
714
- struct delta_info *delta;
1295
+ size_t pos;
715
1296
 
716
1297
  if (idx == NULL)
717
1298
  return;
718
1299
 
719
- git_vector_foreach(&idx->objects, i, e)
720
- git__free(e);
721
- git_vector_free(&idx->objects);
1300
+ if (idx->have_stream)
1301
+ git_packfile_stream_dispose(&idx->stream);
722
1302
 
723
- if (idx->pack) {
724
- for (k = kh_begin(idx->pack->idx_cache); k != kh_end(idx->pack->idx_cache); k++) {
725
- if (kh_exist(idx->pack->idx_cache, k))
726
- git__free(kh_value(idx->pack->idx_cache, k));
727
- }
1303
+ git_vector_free_deep(&idx->objects);
1304
+
1305
+ if (idx->pack->idx_cache) {
1306
+ struct git_pack_entry *pentry;
1307
+ git_oidmap_foreach_value(idx->pack->idx_cache, pentry, {
1308
+ git__free(pentry);
1309
+ });
728
1310
 
729
1311
  git_oidmap_free(idx->pack->idx_cache);
730
1312
  }
731
1313
 
732
- git_vector_foreach(&idx->deltas, i, delta)
733
- git__free(delta);
734
- git_vector_free(&idx->deltas);
735
- git_packfile_free(idx->pack);
736
- git_filebuf_cleanup(&idx->pack_file);
1314
+ git_vector_free_deep(&idx->deltas);
1315
+
1316
+ if (!git_mutex_lock(&git__mwindow_mutex)) {
1317
+ if (!idx->pack_committed)
1318
+ git_packfile_close(idx->pack, true);
1319
+
1320
+ git_packfile_free(idx->pack);
1321
+ git_mutex_unlock(&git__mwindow_mutex);
1322
+ }
1323
+
1324
+ for (pos = git_oidmap_begin(idx->expected_oids);
1325
+ pos != git_oidmap_end(idx->expected_oids); pos++)
1326
+ {
1327
+ if (git_oidmap_has_data(idx->expected_oids, pos)) {
1328
+ git__free((git_oid *) git_oidmap_key(idx->expected_oids, pos));
1329
+ git_oidmap_delete_at(idx->expected_oids, pos);
1330
+ }
1331
+ }
1332
+
1333
+ git_hash_ctx_cleanup(&idx->trailer);
1334
+ git_hash_ctx_cleanup(&idx->hash_ctx);
1335
+ git_buf_dispose(&idx->entry_data);
1336
+ git_oidmap_free(idx->expected_oids);
737
1337
  git__free(idx);
738
1338
  }