rugged 1.1.1 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (407) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -0
  3. data/README.md +1 -1
  4. data/ext/rugged/extconf.rb +2 -2
  5. data/ext/rugged/rugged.c +7 -4
  6. data/ext/rugged/rugged_config.c +7 -2
  7. data/ext/rugged/rugged_object.c +1 -1
  8. data/ext/rugged/rugged_remote.c +17 -0
  9. data/ext/rugged/rugged_repo.c +3 -3
  10. data/lib/rugged/repository.rb +2 -2
  11. data/lib/rugged/version.rb +1 -1
  12. data/vendor/libgit2/CMakeLists.txt +103 -271
  13. data/vendor/libgit2/COPYING +149 -24
  14. data/vendor/libgit2/cmake/AddCFlagIfSupported.cmake +21 -21
  15. data/vendor/libgit2/cmake/DefaultCFlags.cmake +154 -0
  16. data/vendor/libgit2/cmake/EnableWarnings.cmake +13 -13
  17. data/vendor/libgit2/cmake/FindCoreFoundation.cmake +13 -13
  18. data/vendor/libgit2/cmake/FindGSSAPI.cmake +171 -287
  19. data/vendor/libgit2/cmake/FindGSSFramework.cmake +13 -13
  20. data/vendor/libgit2/cmake/{FindHTTP_Parser.cmake → FindHTTPParser.cmake} +17 -17
  21. data/vendor/libgit2/cmake/FindIconv.cmake +27 -27
  22. data/vendor/libgit2/cmake/FindLibSSH2.cmake +13 -0
  23. data/vendor/libgit2/cmake/FindPCRE.cmake +13 -13
  24. data/vendor/libgit2/cmake/FindPCRE2.cmake +12 -12
  25. data/vendor/libgit2/cmake/FindPkgLibraries.cmake +19 -19
  26. data/vendor/libgit2/cmake/FindSecurity.cmake +14 -14
  27. data/vendor/libgit2/cmake/FindStatNsec.cmake +12 -18
  28. data/vendor/libgit2/cmake/Findfutimens.cmake +14 -0
  29. data/vendor/libgit2/cmake/FindmbedTLS.cmake +63 -70
  30. data/vendor/libgit2/cmake/IdeSplitSources.cmake +18 -18
  31. data/vendor/libgit2/cmake/PkgBuildConfig.cmake +60 -60
  32. data/vendor/libgit2/cmake/SanitizeBool.cmake +20 -20
  33. data/vendor/libgit2/cmake/SelectGSSAPI.cmake +37 -37
  34. data/vendor/libgit2/cmake/SelectHTTPParser.cmake +19 -0
  35. data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +100 -96
  36. data/vendor/libgit2/cmake/SelectHashes.cmake +39 -48
  37. data/vendor/libgit2/cmake/SelectRegex.cmake +51 -0
  38. data/vendor/libgit2/cmake/SelectSSH.cmake +41 -0
  39. data/vendor/libgit2/cmake/SelectWinHTTP.cmake +17 -0
  40. data/vendor/libgit2/cmake/SelectZlib.cmake +34 -0
  41. data/vendor/libgit2/deps/chromium-zlib/CMakeLists.txt +101 -0
  42. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +32 -20
  43. data/vendor/libgit2/deps/ntlmclient/crypt.h +14 -9
  44. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +20 -20
  45. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.h +3 -3
  46. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +37 -36
  47. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.h +4 -3
  48. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +178 -51
  49. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.h +74 -5
  50. data/vendor/libgit2/deps/ntlmclient/ntlm.c +154 -122
  51. data/vendor/libgit2/deps/ntlmclient/ntlm.h +17 -13
  52. data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +17 -4
  53. data/vendor/libgit2/deps/ntlmclient/unicode.h +10 -4
  54. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +16 -27
  55. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.h +20 -0
  56. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +28 -52
  57. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.h +22 -0
  58. data/vendor/libgit2/deps/pcre/CMakeLists.txt +88 -88
  59. data/vendor/libgit2/deps/winhttp/CMakeLists.txt +14 -16
  60. data/vendor/libgit2/include/git2/apply.h +16 -2
  61. data/vendor/libgit2/include/git2/attr.h +106 -2
  62. data/vendor/libgit2/include/git2/blame.h +97 -43
  63. data/vendor/libgit2/include/git2/blob.h +33 -2
  64. data/vendor/libgit2/include/git2/branch.h +27 -0
  65. data/vendor/libgit2/include/git2/buffer.h +18 -78
  66. data/vendor/libgit2/include/git2/cert.h +43 -6
  67. data/vendor/libgit2/include/git2/checkout.h +32 -13
  68. data/vendor/libgit2/include/git2/clone.h +4 -4
  69. data/vendor/libgit2/include/git2/commit.h +37 -19
  70. data/vendor/libgit2/include/git2/common.h +46 -5
  71. data/vendor/libgit2/include/git2/config.h +19 -3
  72. data/vendor/libgit2/include/git2/credential.h +2 -1
  73. data/vendor/libgit2/include/git2/credential_helpers.h +1 -0
  74. data/vendor/libgit2/include/git2/deprecated.h +326 -6
  75. data/vendor/libgit2/include/git2/describe.h +7 -2
  76. data/vendor/libgit2/include/git2/diff.h +50 -121
  77. data/vendor/libgit2/include/git2/email.h +127 -0
  78. data/vendor/libgit2/include/git2/errors.h +7 -6
  79. data/vendor/libgit2/include/git2/filter.h +69 -18
  80. data/vendor/libgit2/include/git2/graph.h +21 -2
  81. data/vendor/libgit2/include/git2/ignore.h +1 -1
  82. data/vendor/libgit2/include/git2/index.h +13 -7
  83. data/vendor/libgit2/include/git2/indexer.h +19 -0
  84. data/vendor/libgit2/include/git2/merge.h +23 -3
  85. data/vendor/libgit2/include/git2/message.h +2 -0
  86. data/vendor/libgit2/include/git2/notes.h +2 -2
  87. data/vendor/libgit2/include/git2/object.h +23 -0
  88. data/vendor/libgit2/include/git2/odb.h +65 -6
  89. data/vendor/libgit2/include/git2/odb_backend.h +1 -1
  90. data/vendor/libgit2/include/git2/oidarray.h +5 -8
  91. data/vendor/libgit2/include/git2/pack.h +24 -8
  92. data/vendor/libgit2/include/git2/patch.h +16 -0
  93. data/vendor/libgit2/include/git2/pathspec.h +1 -1
  94. data/vendor/libgit2/include/git2/proxy.h +1 -1
  95. data/vendor/libgit2/include/git2/rebase.h +34 -2
  96. data/vendor/libgit2/include/git2/refdb.h +3 -0
  97. data/vendor/libgit2/include/git2/reflog.h +1 -1
  98. data/vendor/libgit2/include/git2/refs.h +8 -4
  99. data/vendor/libgit2/include/git2/remote.h +246 -46
  100. data/vendor/libgit2/include/git2/repository.h +25 -18
  101. data/vendor/libgit2/include/git2/reset.h +2 -2
  102. data/vendor/libgit2/include/git2/revparse.h +5 -5
  103. data/vendor/libgit2/include/git2/revwalk.h +4 -1
  104. data/vendor/libgit2/include/git2/signature.h +1 -1
  105. data/vendor/libgit2/include/git2/stash.h +4 -4
  106. data/vendor/libgit2/include/git2/status.h +124 -62
  107. data/vendor/libgit2/include/git2/stdint.h +3 -3
  108. data/vendor/libgit2/include/git2/submodule.h +16 -2
  109. data/vendor/libgit2/include/git2/sys/commit_graph.h +174 -0
  110. data/vendor/libgit2/include/git2/sys/email.h +45 -0
  111. data/vendor/libgit2/include/git2/sys/filter.h +49 -28
  112. data/vendor/libgit2/include/git2/sys/midx.h +74 -0
  113. data/vendor/libgit2/include/git2/sys/odb_backend.h +9 -5
  114. data/vendor/libgit2/include/git2/sys/remote.h +31 -0
  115. data/vendor/libgit2/include/git2/sys/stream.h +1 -1
  116. data/vendor/libgit2/include/git2/sys/transport.h +26 -34
  117. data/vendor/libgit2/include/git2/tag.h +13 -0
  118. data/vendor/libgit2/include/git2/tree.h +4 -17
  119. data/vendor/libgit2/include/git2/types.h +16 -7
  120. data/vendor/libgit2/include/git2/version.h +4 -4
  121. data/vendor/libgit2/include/git2/worktree.h +13 -2
  122. data/vendor/libgit2/include/git2.h +1 -0
  123. data/vendor/libgit2/src/CMakeLists.txt +192 -290
  124. data/vendor/libgit2/src/alloc.c +21 -8
  125. data/vendor/libgit2/src/allocators/failalloc.c +92 -0
  126. data/vendor/libgit2/src/allocators/failalloc.h +23 -0
  127. data/vendor/libgit2/src/allocators/stdalloc.c +41 -10
  128. data/vendor/libgit2/src/allocators/win32_leakcheck.c +118 -0
  129. data/vendor/libgit2/src/allocators/{win32_crtdbg.h → win32_leakcheck.h} +3 -3
  130. data/vendor/libgit2/src/annotated_commit.c +21 -9
  131. data/vendor/libgit2/src/annotated_commit.h +1 -1
  132. data/vendor/libgit2/src/apply.c +34 -25
  133. data/vendor/libgit2/src/apply.h +2 -2
  134. data/vendor/libgit2/src/array.h +11 -11
  135. data/vendor/libgit2/src/attr.c +204 -82
  136. data/vendor/libgit2/src/attr_file.c +105 -52
  137. data/vendor/libgit2/src/attr_file.h +36 -15
  138. data/vendor/libgit2/src/attrcache.c +55 -45
  139. data/vendor/libgit2/src/attrcache.h +4 -5
  140. data/vendor/libgit2/src/blame.c +15 -9
  141. data/vendor/libgit2/src/blame_git.c +2 -2
  142. data/vendor/libgit2/src/blob.c +76 -52
  143. data/vendor/libgit2/src/blob.h +1 -1
  144. data/vendor/libgit2/src/branch.c +203 -110
  145. data/vendor/libgit2/src/branch.h +15 -3
  146. data/vendor/libgit2/src/buf.c +126 -0
  147. data/vendor/libgit2/src/buf.h +50 -0
  148. data/vendor/libgit2/src/cache.c +2 -2
  149. data/vendor/libgit2/src/cache.h +7 -7
  150. data/vendor/libgit2/src/cc-compat.h +11 -9
  151. data/vendor/libgit2/src/checkout.c +118 -91
  152. data/vendor/libgit2/src/cherrypick.c +16 -12
  153. data/vendor/libgit2/src/clone.c +97 -103
  154. data/vendor/libgit2/src/commit.c +167 -84
  155. data/vendor/libgit2/src/commit.h +24 -1
  156. data/vendor/libgit2/src/commit_graph.c +1224 -0
  157. data/vendor/libgit2/src/commit_graph.h +169 -0
  158. data/vendor/libgit2/src/commit_list.c +48 -3
  159. data/vendor/libgit2/src/commit_list.h +2 -0
  160. data/vendor/libgit2/src/common.h +35 -5
  161. data/vendor/libgit2/src/config.c +119 -64
  162. data/vendor/libgit2/src/config.h +15 -2
  163. data/vendor/libgit2/src/config_cache.c +5 -3
  164. data/vendor/libgit2/src/config_file.c +120 -100
  165. data/vendor/libgit2/src/config_mem.c +9 -9
  166. data/vendor/libgit2/src/config_parse.c +29 -27
  167. data/vendor/libgit2/src/crlf.c +36 -23
  168. data/vendor/libgit2/src/date.c +13 -19
  169. data/vendor/libgit2/src/date.h +33 -0
  170. data/vendor/libgit2/src/delta.c +1 -1
  171. data/vendor/libgit2/src/describe.c +32 -21
  172. data/vendor/libgit2/src/diff.c +71 -183
  173. data/vendor/libgit2/src/diff.h +2 -4
  174. data/vendor/libgit2/src/diff_driver.c +53 -51
  175. data/vendor/libgit2/src/diff_driver.h +3 -3
  176. data/vendor/libgit2/src/diff_file.c +31 -26
  177. data/vendor/libgit2/src/diff_generate.c +76 -23
  178. data/vendor/libgit2/src/diff_generate.h +5 -3
  179. data/vendor/libgit2/src/diff_print.c +120 -95
  180. data/vendor/libgit2/src/diff_stats.c +47 -34
  181. data/vendor/libgit2/src/{message.h → diff_stats.h} +7 -6
  182. data/vendor/libgit2/src/diff_tform.c +18 -16
  183. data/vendor/libgit2/src/diff_xdiff.c +7 -10
  184. data/vendor/libgit2/src/diff_xdiff.h +1 -1
  185. data/vendor/libgit2/src/email.c +315 -0
  186. data/vendor/libgit2/src/email.h +25 -0
  187. data/vendor/libgit2/src/errors.c +37 -32
  188. data/vendor/libgit2/src/features.h.in +11 -2
  189. data/vendor/libgit2/src/fetch.c +77 -26
  190. data/vendor/libgit2/src/fetch.h +1 -1
  191. data/vendor/libgit2/src/fetchhead.c +27 -23
  192. data/vendor/libgit2/src/filebuf.c +36 -34
  193. data/vendor/libgit2/src/filebuf.h +1 -1
  194. data/vendor/libgit2/src/filter.c +278 -132
  195. data/vendor/libgit2/src/filter.h +46 -6
  196. data/vendor/libgit2/src/fs_path.c +2071 -0
  197. data/vendor/libgit2/src/fs_path.h +772 -0
  198. data/vendor/libgit2/src/futils.c +96 -90
  199. data/vendor/libgit2/src/futils.h +27 -15
  200. data/vendor/libgit2/src/graph.c +64 -9
  201. data/vendor/libgit2/src/hash/sha1/collisiondetect.c +5 -5
  202. data/vendor/libgit2/src/hash/sha1/common_crypto.c +5 -5
  203. data/vendor/libgit2/src/hash/sha1/generic.c +2 -2
  204. data/vendor/libgit2/src/hash/sha1/generic.h +1 -1
  205. data/vendor/libgit2/src/hash/sha1/mbedtls.c +13 -13
  206. data/vendor/libgit2/src/hash/sha1/openssl.c +5 -5
  207. data/vendor/libgit2/src/hash/sha1/sha1dc/sha1.c +9 -11
  208. data/vendor/libgit2/src/hash/sha1/win32.c +21 -17
  209. data/vendor/libgit2/src/hash/sha1.h +3 -1
  210. data/vendor/libgit2/src/hash.c +71 -36
  211. data/vendor/libgit2/src/hash.h +13 -13
  212. data/vendor/libgit2/src/hashsig.c +23 -10
  213. data/vendor/libgit2/src/ident.c +30 -20
  214. data/vendor/libgit2/src/ignore.c +63 -46
  215. data/vendor/libgit2/src/ignore.h +2 -2
  216. data/vendor/libgit2/src/index.c +184 -149
  217. data/vendor/libgit2/src/index.h +7 -4
  218. data/vendor/libgit2/src/indexer.c +143 -89
  219. data/vendor/libgit2/src/integer.h +64 -2
  220. data/vendor/libgit2/src/iterator.c +93 -73
  221. data/vendor/libgit2/src/iterator.h +6 -6
  222. data/vendor/libgit2/src/khash.h +3 -12
  223. data/vendor/libgit2/src/{settings.c → libgit2.c} +165 -56
  224. data/vendor/libgit2/src/libgit2.h +15 -0
  225. data/vendor/libgit2/src/mailmap.c +60 -45
  226. data/vendor/libgit2/src/map.h +3 -3
  227. data/vendor/libgit2/src/merge.c +104 -61
  228. data/vendor/libgit2/src/merge.h +3 -15
  229. data/vendor/libgit2/src/merge_driver.c +21 -15
  230. data/vendor/libgit2/src/merge_file.c +24 -6
  231. data/vendor/libgit2/src/message.c +21 -8
  232. data/vendor/libgit2/src/midx.c +501 -18
  233. data/vendor/libgit2/src/midx.h +29 -2
  234. data/vendor/libgit2/src/mwindow.c +103 -59
  235. data/vendor/libgit2/src/mwindow.h +3 -3
  236. data/vendor/libgit2/src/net.c +405 -71
  237. data/vendor/libgit2/src/net.h +26 -5
  238. data/vendor/libgit2/src/netops.c +7 -5
  239. data/vendor/libgit2/src/netops.h +3 -3
  240. data/vendor/libgit2/src/notes.c +40 -49
  241. data/vendor/libgit2/src/object.c +68 -20
  242. data/vendor/libgit2/src/object.h +1 -1
  243. data/vendor/libgit2/src/odb.c +320 -80
  244. data/vendor/libgit2/src/odb.h +17 -3
  245. data/vendor/libgit2/src/odb_loose.c +96 -86
  246. data/vendor/libgit2/src/odb_mempack.c +19 -6
  247. data/vendor/libgit2/src/odb_pack.c +402 -125
  248. data/vendor/libgit2/src/oid.c +16 -8
  249. data/vendor/libgit2/src/oid.h +15 -0
  250. data/vendor/libgit2/src/oidarray.c +10 -1
  251. data/vendor/libgit2/src/pack-objects.c +90 -69
  252. data/vendor/libgit2/src/pack-objects.h +11 -6
  253. data/vendor/libgit2/src/pack.c +337 -127
  254. data/vendor/libgit2/src/pack.h +25 -7
  255. data/vendor/libgit2/src/patch.c +17 -10
  256. data/vendor/libgit2/src/patch.h +1 -0
  257. data/vendor/libgit2/src/patch_generate.c +29 -13
  258. data/vendor/libgit2/src/patch_generate.h +5 -5
  259. data/vendor/libgit2/src/patch_parse.c +26 -25
  260. data/vendor/libgit2/src/path.c +86 -1768
  261. data/vendor/libgit2/src/path.h +39 -635
  262. data/vendor/libgit2/src/pathspec.c +12 -12
  263. data/vendor/libgit2/src/pathspec.h +2 -2
  264. data/vendor/libgit2/src/pool.c +13 -7
  265. data/vendor/libgit2/src/posix.c +14 -6
  266. data/vendor/libgit2/src/posix.h +1 -0
  267. data/vendor/libgit2/src/pqueue.h +1 -1
  268. data/vendor/libgit2/src/proxy.c +4 -1
  269. data/vendor/libgit2/src/proxy.h +1 -1
  270. data/vendor/libgit2/src/push.c +30 -35
  271. data/vendor/libgit2/src/push.h +4 -16
  272. data/vendor/libgit2/src/rand.c +226 -0
  273. data/vendor/libgit2/src/rand.h +37 -0
  274. data/vendor/libgit2/src/reader.c +18 -14
  275. data/vendor/libgit2/src/reader.h +2 -2
  276. data/vendor/libgit2/src/rebase.c +177 -132
  277. data/vendor/libgit2/src/refdb.c +30 -13
  278. data/vendor/libgit2/src/refdb_fs.c +548 -222
  279. data/vendor/libgit2/src/reflog.c +19 -14
  280. data/vendor/libgit2/src/refs.c +107 -72
  281. data/vendor/libgit2/src/refs.h +2 -2
  282. data/vendor/libgit2/src/refspec.c +53 -38
  283. data/vendor/libgit2/src/refspec.h +5 -2
  284. data/vendor/libgit2/src/regexp.c +1 -1
  285. data/vendor/libgit2/src/remote.c +960 -486
  286. data/vendor/libgit2/src/remote.h +16 -10
  287. data/vendor/libgit2/src/repository.c +702 -422
  288. data/vendor/libgit2/src/repository.h +26 -8
  289. data/vendor/libgit2/src/reset.c +16 -12
  290. data/vendor/libgit2/src/revert.c +16 -12
  291. data/vendor/libgit2/src/revparse.c +66 -48
  292. data/vendor/libgit2/src/revwalk.c +39 -22
  293. data/vendor/libgit2/src/runtime.c +162 -0
  294. data/vendor/libgit2/src/runtime.h +62 -0
  295. data/vendor/libgit2/src/settings.h +11 -0
  296. data/vendor/libgit2/src/signature.c +18 -11
  297. data/vendor/libgit2/src/signature.h +1 -1
  298. data/vendor/libgit2/src/sortedcache.c +1 -1
  299. data/vendor/libgit2/src/sortedcache.h +10 -8
  300. data/vendor/libgit2/src/stash.c +39 -38
  301. data/vendor/libgit2/src/status.c +11 -5
  302. data/vendor/libgit2/src/{buffer.c → str.c} +459 -136
  303. data/vendor/libgit2/src/str.h +357 -0
  304. data/vendor/libgit2/src/strarray.c +2 -1
  305. data/vendor/libgit2/src/streams/mbedtls.c +22 -23
  306. data/vendor/libgit2/src/streams/mbedtls.h +1 -1
  307. data/vendor/libgit2/src/streams/openssl.c +101 -201
  308. data/vendor/libgit2/src/streams/openssl.h +9 -1
  309. data/vendor/libgit2/src/streams/openssl_dynamic.c +309 -0
  310. data/vendor/libgit2/src/streams/openssl_dynamic.h +348 -0
  311. data/vendor/libgit2/src/streams/openssl_legacy.c +203 -0
  312. data/vendor/libgit2/src/streams/openssl_legacy.h +63 -0
  313. data/vendor/libgit2/src/streams/registry.c +5 -6
  314. data/vendor/libgit2/src/streams/socket.c +6 -2
  315. data/vendor/libgit2/src/streams/stransport.c +6 -3
  316. data/vendor/libgit2/src/streams/tls.c +5 -3
  317. data/vendor/libgit2/src/submodule.c +290 -212
  318. data/vendor/libgit2/src/submodule.h +10 -10
  319. data/vendor/libgit2/src/sysdir.c +70 -56
  320. data/vendor/libgit2/src/sysdir.h +15 -10
  321. data/vendor/libgit2/src/tag.c +72 -34
  322. data/vendor/libgit2/src/thread.c +140 -0
  323. data/vendor/libgit2/src/thread.h +479 -0
  324. data/vendor/libgit2/src/threadstate.c +84 -0
  325. data/vendor/libgit2/src/threadstate.h +24 -0
  326. data/vendor/libgit2/src/trace.c +3 -16
  327. data/vendor/libgit2/src/trace.h +17 -30
  328. data/vendor/libgit2/src/trailer.c +2 -2
  329. data/vendor/libgit2/src/transaction.c +20 -9
  330. data/vendor/libgit2/src/transport.c +13 -13
  331. data/vendor/libgit2/src/transports/auth.c +8 -10
  332. data/vendor/libgit2/src/transports/auth.h +2 -3
  333. data/vendor/libgit2/src/transports/auth_negotiate.c +23 -17
  334. data/vendor/libgit2/src/transports/auth_ntlm.c +20 -16
  335. data/vendor/libgit2/src/transports/auth_ntlm.h +0 -1
  336. data/vendor/libgit2/src/transports/credential.c +15 -7
  337. data/vendor/libgit2/src/transports/git.c +10 -14
  338. data/vendor/libgit2/src/transports/http.c +56 -34
  339. data/vendor/libgit2/src/transports/http.h +3 -3
  340. data/vendor/libgit2/src/transports/httpclient.c +106 -79
  341. data/vendor/libgit2/src/transports/httpclient.h +1 -1
  342. data/vendor/libgit2/src/transports/local.c +127 -119
  343. data/vendor/libgit2/src/transports/smart.c +61 -144
  344. data/vendor/libgit2/src/transports/smart.h +26 -32
  345. data/vendor/libgit2/src/transports/smart_pkt.c +33 -33
  346. data/vendor/libgit2/src/transports/smart_protocol.c +68 -44
  347. data/vendor/libgit2/src/transports/ssh.c +100 -131
  348. data/vendor/libgit2/src/transports/winhttp.c +86 -82
  349. data/vendor/libgit2/src/tree-cache.c +5 -5
  350. data/vendor/libgit2/src/tree-cache.h +2 -2
  351. data/vendor/libgit2/src/tree.c +150 -116
  352. data/vendor/libgit2/src/tree.h +1 -0
  353. data/vendor/libgit2/src/tsort.c +0 -2
  354. data/vendor/libgit2/src/unix/map.c +3 -3
  355. data/vendor/libgit2/src/unix/posix.h +1 -4
  356. data/vendor/libgit2/src/unix/pthread.h +2 -1
  357. data/vendor/libgit2/src/unix/realpath.c +0 -2
  358. data/vendor/libgit2/src/utf8.c +150 -0
  359. data/vendor/libgit2/src/utf8.h +52 -0
  360. data/vendor/libgit2/src/util.c +68 -144
  361. data/vendor/libgit2/src/util.h +36 -68
  362. data/vendor/libgit2/src/vector.c +23 -19
  363. data/vendor/libgit2/src/vector.h +5 -3
  364. data/vendor/libgit2/src/win32/findfile.c +172 -114
  365. data/vendor/libgit2/src/win32/findfile.h +7 -4
  366. data/vendor/libgit2/src/win32/map.c +1 -1
  367. data/vendor/libgit2/src/win32/msvc-compat.h +9 -1
  368. data/vendor/libgit2/src/win32/path_w32.c +162 -33
  369. data/vendor/libgit2/src/win32/path_w32.h +2 -1
  370. data/vendor/libgit2/src/win32/posix.h +6 -7
  371. data/vendor/libgit2/src/win32/posix_w32.c +26 -33
  372. data/vendor/libgit2/src/win32/precompiled.h +0 -1
  373. data/vendor/libgit2/src/win32/reparse.h +4 -4
  374. data/vendor/libgit2/src/win32/thread.c +24 -15
  375. data/vendor/libgit2/src/win32/thread.h +1 -1
  376. data/vendor/libgit2/src/win32/w32_buffer.c +5 -6
  377. data/vendor/libgit2/src/win32/w32_buffer.h +2 -3
  378. data/vendor/libgit2/src/win32/w32_common.h +18 -9
  379. data/vendor/libgit2/src/win32/{w32_crtdbg_stacktrace.c → w32_leakcheck.c} +269 -33
  380. data/vendor/libgit2/src/win32/w32_leakcheck.h +222 -0
  381. data/vendor/libgit2/src/win32/w32_util.h +6 -6
  382. data/vendor/libgit2/src/worktree.c +138 -105
  383. data/vendor/libgit2/src/worktree.h +1 -1
  384. data/vendor/libgit2/src/xdiff/git-xdiff.h +53 -0
  385. data/vendor/libgit2/src/xdiff/xdiff.h +15 -15
  386. data/vendor/libgit2/src/xdiff/xdiffi.c +134 -108
  387. data/vendor/libgit2/src/xdiff/xemit.c +23 -7
  388. data/vendor/libgit2/src/xdiff/xhistogram.c +87 -78
  389. data/vendor/libgit2/src/xdiff/xinclude.h +1 -12
  390. data/vendor/libgit2/src/xdiff/xmerge.c +104 -117
  391. data/vendor/libgit2/src/xdiff/xpatience.c +6 -17
  392. data/vendor/libgit2/src/xdiff/xprepare.c +15 -20
  393. data/vendor/libgit2/src/xdiff/xutils.c +18 -7
  394. data/vendor/libgit2/src/zstream.c +6 -6
  395. data/vendor/libgit2/src/zstream.h +4 -4
  396. metadata +60 -24
  397. data/vendor/libgit2/src/allocators/win32_crtdbg.c +0 -118
  398. data/vendor/libgit2/src/buf_text.c +0 -316
  399. data/vendor/libgit2/src/buf_text.h +0 -122
  400. data/vendor/libgit2/src/buffer.h +0 -222
  401. data/vendor/libgit2/src/global.c +0 -363
  402. data/vendor/libgit2/src/global.h +0 -41
  403. data/vendor/libgit2/src/thread-utils.c +0 -58
  404. data/vendor/libgit2/src/thread-utils.h +0 -369
  405. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +0 -127
  406. data/vendor/libgit2/src/win32/w32_stack.c +0 -188
  407. data/vendor/libgit2/src/win32/w32_stack.h +0 -140
@@ -0,0 +1,1224 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+
8
+ #include "commit_graph.h"
9
+
10
+ #include "array.h"
11
+ #include "buf.h"
12
+ #include "filebuf.h"
13
+ #include "futils.h"
14
+ #include "hash.h"
15
+ #include "oidarray.h"
16
+ #include "oidmap.h"
17
+ #include "pack.h"
18
+ #include "repository.h"
19
+ #include "revwalk.h"
20
+
21
+ #define GIT_COMMIT_GRAPH_MISSING_PARENT 0x70000000
22
+ #define GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX 0x3FFFFFFF
23
+ #define GIT_COMMIT_GRAPH_GENERATION_NUMBER_INFINITY 0xFFFFFFFF
24
+
25
+ #define COMMIT_GRAPH_SIGNATURE 0x43475048 /* "CGPH" */
26
+ #define COMMIT_GRAPH_VERSION 1
27
+ #define COMMIT_GRAPH_OBJECT_ID_VERSION 1
28
+ struct git_commit_graph_header {
29
+ uint32_t signature;
30
+ uint8_t version;
31
+ uint8_t object_id_version;
32
+ uint8_t chunks;
33
+ uint8_t base_graph_files;
34
+ };
35
+
36
+ #define COMMIT_GRAPH_OID_FANOUT_ID 0x4f494446 /* "OIDF" */
37
+ #define COMMIT_GRAPH_OID_LOOKUP_ID 0x4f49444c /* "OIDL" */
38
+ #define COMMIT_GRAPH_COMMIT_DATA_ID 0x43444154 /* "CDAT" */
39
+ #define COMMIT_GRAPH_EXTRA_EDGE_LIST_ID 0x45444745 /* "EDGE" */
40
+ #define COMMIT_GRAPH_BLOOM_FILTER_INDEX_ID 0x42494458 /* "BIDX" */
41
+ #define COMMIT_GRAPH_BLOOM_FILTER_DATA_ID 0x42444154 /* "BDAT" */
42
+
43
+ struct git_commit_graph_chunk {
44
+ off64_t offset;
45
+ size_t length;
46
+ };
47
+
48
+ typedef git_array_t(size_t) parent_index_array_t;
49
+
50
+ struct packed_commit {
51
+ size_t index;
52
+ git_oid sha1;
53
+ git_oid tree_oid;
54
+ uint32_t generation;
55
+ git_time_t commit_time;
56
+ git_array_oid_t parents;
57
+ parent_index_array_t parent_indices;
58
+ };
59
+
60
+ static void packed_commit_free(struct packed_commit *p)
61
+ {
62
+ if (!p)
63
+ return;
64
+
65
+ git_array_clear(p->parents);
66
+ git_array_clear(p->parent_indices);
67
+ git__free(p);
68
+ }
69
+
70
+ static struct packed_commit *packed_commit_new(git_commit *commit)
71
+ {
72
+ unsigned int i, parentcount = git_commit_parentcount(commit);
73
+ struct packed_commit *p = git__calloc(1, sizeof(struct packed_commit));
74
+ if (!p)
75
+ goto cleanup;
76
+
77
+ git_array_init_to_size(p->parents, parentcount);
78
+ if (parentcount && !p->parents.ptr)
79
+ goto cleanup;
80
+
81
+ if (git_oid_cpy(&p->sha1, git_commit_id(commit)) < 0)
82
+ goto cleanup;
83
+ if (git_oid_cpy(&p->tree_oid, git_commit_tree_id(commit)) < 0)
84
+ goto cleanup;
85
+ p->commit_time = git_commit_time(commit);
86
+
87
+ for (i = 0; i < parentcount; ++i) {
88
+ git_oid *parent_id = git_array_alloc(p->parents);
89
+ if (!parent_id)
90
+ goto cleanup;
91
+ if (git_oid_cpy(parent_id, git_commit_parent_id(commit, i)) < 0)
92
+ goto cleanup;
93
+ }
94
+
95
+ return p;
96
+
97
+ cleanup:
98
+ packed_commit_free(p);
99
+ return NULL;
100
+ }
101
+
102
+ typedef int (*commit_graph_write_cb)(const char *buf, size_t size, void *cb_data);
103
+
104
+ static int commit_graph_error(const char *message)
105
+ {
106
+ git_error_set(GIT_ERROR_ODB, "invalid commit-graph file - %s", message);
107
+ return -1;
108
+ }
109
+
110
+ static int commit_graph_parse_oid_fanout(
111
+ git_commit_graph_file *file,
112
+ const unsigned char *data,
113
+ struct git_commit_graph_chunk *chunk_oid_fanout)
114
+ {
115
+ uint32_t i, nr;
116
+ if (chunk_oid_fanout->offset == 0)
117
+ return commit_graph_error("missing OID Fanout chunk");
118
+ if (chunk_oid_fanout->length == 0)
119
+ return commit_graph_error("empty OID Fanout chunk");
120
+ if (chunk_oid_fanout->length != 256 * 4)
121
+ return commit_graph_error("OID Fanout chunk has wrong length");
122
+
123
+ file->oid_fanout = (const uint32_t *)(data + chunk_oid_fanout->offset);
124
+ nr = 0;
125
+ for (i = 0; i < 256; ++i) {
126
+ uint32_t n = ntohl(file->oid_fanout[i]);
127
+ if (n < nr)
128
+ return commit_graph_error("index is non-monotonic");
129
+ nr = n;
130
+ }
131
+ file->num_commits = nr;
132
+ return 0;
133
+ }
134
+
135
+ static int commit_graph_parse_oid_lookup(
136
+ git_commit_graph_file *file,
137
+ const unsigned char *data,
138
+ struct git_commit_graph_chunk *chunk_oid_lookup)
139
+ {
140
+ uint32_t i;
141
+ git_oid *oid, *prev_oid, zero_oid = {{0}};
142
+
143
+ if (chunk_oid_lookup->offset == 0)
144
+ return commit_graph_error("missing OID Lookup chunk");
145
+ if (chunk_oid_lookup->length == 0)
146
+ return commit_graph_error("empty OID Lookup chunk");
147
+ if (chunk_oid_lookup->length != file->num_commits * GIT_OID_RAWSZ)
148
+ return commit_graph_error("OID Lookup chunk has wrong length");
149
+
150
+ file->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset);
151
+ prev_oid = &zero_oid;
152
+ for (i = 0; i < file->num_commits; ++i, ++oid) {
153
+ if (git_oid_cmp(prev_oid, oid) >= 0)
154
+ return commit_graph_error("OID Lookup index is non-monotonic");
155
+ prev_oid = oid;
156
+ }
157
+
158
+ return 0;
159
+ }
160
+
161
+ static int commit_graph_parse_commit_data(
162
+ git_commit_graph_file *file,
163
+ const unsigned char *data,
164
+ struct git_commit_graph_chunk *chunk_commit_data)
165
+ {
166
+ if (chunk_commit_data->offset == 0)
167
+ return commit_graph_error("missing Commit Data chunk");
168
+ if (chunk_commit_data->length == 0)
169
+ return commit_graph_error("empty Commit Data chunk");
170
+ if (chunk_commit_data->length != file->num_commits * (GIT_OID_RAWSZ + 16))
171
+ return commit_graph_error("Commit Data chunk has wrong length");
172
+
173
+ file->commit_data = data + chunk_commit_data->offset;
174
+
175
+ return 0;
176
+ }
177
+
178
+ static int commit_graph_parse_extra_edge_list(
179
+ git_commit_graph_file *file,
180
+ const unsigned char *data,
181
+ struct git_commit_graph_chunk *chunk_extra_edge_list)
182
+ {
183
+ if (chunk_extra_edge_list->length == 0)
184
+ return 0;
185
+ if (chunk_extra_edge_list->length % 4 != 0)
186
+ return commit_graph_error("malformed Extra Edge List chunk");
187
+
188
+ file->extra_edge_list = data + chunk_extra_edge_list->offset;
189
+ file->num_extra_edge_list = chunk_extra_edge_list->length / 4;
190
+
191
+ return 0;
192
+ }
193
+
194
+ int git_commit_graph_file_parse(
195
+ git_commit_graph_file *file,
196
+ const unsigned char *data,
197
+ size_t size)
198
+ {
199
+ struct git_commit_graph_header *hdr;
200
+ const unsigned char *chunk_hdr;
201
+ struct git_commit_graph_chunk *last_chunk;
202
+ uint32_t i;
203
+ off64_t last_chunk_offset, chunk_offset, trailer_offset;
204
+ unsigned char checksum[GIT_HASH_SHA1_SIZE];
205
+ size_t checksum_size;
206
+ int error;
207
+ struct git_commit_graph_chunk chunk_oid_fanout = {0}, chunk_oid_lookup = {0},
208
+ chunk_commit_data = {0}, chunk_extra_edge_list = {0},
209
+ chunk_unsupported = {0};
210
+
211
+ GIT_ASSERT_ARG(file);
212
+
213
+ if (size < sizeof(struct git_commit_graph_header) + GIT_OID_RAWSZ)
214
+ return commit_graph_error("commit-graph is too short");
215
+
216
+ hdr = ((struct git_commit_graph_header *)data);
217
+
218
+ if (hdr->signature != htonl(COMMIT_GRAPH_SIGNATURE) || hdr->version != COMMIT_GRAPH_VERSION
219
+ || hdr->object_id_version != COMMIT_GRAPH_OBJECT_ID_VERSION) {
220
+ return commit_graph_error("unsupported commit-graph version");
221
+ }
222
+ if (hdr->chunks == 0)
223
+ return commit_graph_error("no chunks in commit-graph");
224
+
225
+ /*
226
+ * The very first chunk's offset should be after the header, all the chunk
227
+ * headers, and a special zero chunk.
228
+ */
229
+ last_chunk_offset = sizeof(struct git_commit_graph_header) + (1 + hdr->chunks) * 12;
230
+ trailer_offset = size - GIT_OID_RAWSZ;
231
+ checksum_size = GIT_HASH_SHA1_SIZE;
232
+
233
+ if (trailer_offset < last_chunk_offset)
234
+ return commit_graph_error("wrong commit-graph size");
235
+ memcpy(file->checksum, (data + trailer_offset), checksum_size);
236
+
237
+ if (git_hash_buf(checksum, data, (size_t)trailer_offset, GIT_HASH_ALGORITHM_SHA1) < 0)
238
+ return commit_graph_error("could not calculate signature");
239
+ if (memcmp(checksum, file->checksum, checksum_size) != 0)
240
+ return commit_graph_error("index signature mismatch");
241
+
242
+ chunk_hdr = data + sizeof(struct git_commit_graph_header);
243
+ last_chunk = NULL;
244
+ for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
245
+ chunk_offset = ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) << 32
246
+ | ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 8))));
247
+ if (chunk_offset < last_chunk_offset)
248
+ return commit_graph_error("chunks are non-monotonic");
249
+ if (chunk_offset >= trailer_offset)
250
+ return commit_graph_error("chunks extend beyond the trailer");
251
+ if (last_chunk != NULL)
252
+ last_chunk->length = (size_t)(chunk_offset - last_chunk_offset);
253
+ last_chunk_offset = chunk_offset;
254
+
255
+ switch (ntohl(*((uint32_t *)(chunk_hdr + 0)))) {
256
+ case COMMIT_GRAPH_OID_FANOUT_ID:
257
+ chunk_oid_fanout.offset = last_chunk_offset;
258
+ last_chunk = &chunk_oid_fanout;
259
+ break;
260
+
261
+ case COMMIT_GRAPH_OID_LOOKUP_ID:
262
+ chunk_oid_lookup.offset = last_chunk_offset;
263
+ last_chunk = &chunk_oid_lookup;
264
+ break;
265
+
266
+ case COMMIT_GRAPH_COMMIT_DATA_ID:
267
+ chunk_commit_data.offset = last_chunk_offset;
268
+ last_chunk = &chunk_commit_data;
269
+ break;
270
+
271
+ case COMMIT_GRAPH_EXTRA_EDGE_LIST_ID:
272
+ chunk_extra_edge_list.offset = last_chunk_offset;
273
+ last_chunk = &chunk_extra_edge_list;
274
+ break;
275
+
276
+ case COMMIT_GRAPH_BLOOM_FILTER_INDEX_ID:
277
+ case COMMIT_GRAPH_BLOOM_FILTER_DATA_ID:
278
+ chunk_unsupported.offset = last_chunk_offset;
279
+ last_chunk = &chunk_unsupported;
280
+ break;
281
+
282
+ default:
283
+ return commit_graph_error("unrecognized chunk ID");
284
+ }
285
+ }
286
+ last_chunk->length = (size_t)(trailer_offset - last_chunk_offset);
287
+
288
+ error = commit_graph_parse_oid_fanout(file, data, &chunk_oid_fanout);
289
+ if (error < 0)
290
+ return error;
291
+ error = commit_graph_parse_oid_lookup(file, data, &chunk_oid_lookup);
292
+ if (error < 0)
293
+ return error;
294
+ error = commit_graph_parse_commit_data(file, data, &chunk_commit_data);
295
+ if (error < 0)
296
+ return error;
297
+ error = commit_graph_parse_extra_edge_list(file, data, &chunk_extra_edge_list);
298
+ if (error < 0)
299
+ return error;
300
+
301
+ return 0;
302
+ }
303
+
304
+ int git_commit_graph_new(git_commit_graph **cgraph_out, const char *objects_dir, bool open_file)
305
+ {
306
+ git_commit_graph *cgraph = NULL;
307
+ int error = 0;
308
+
309
+ GIT_ASSERT_ARG(cgraph_out);
310
+ GIT_ASSERT_ARG(objects_dir);
311
+
312
+ cgraph = git__calloc(1, sizeof(git_commit_graph));
313
+ GIT_ERROR_CHECK_ALLOC(cgraph);
314
+
315
+ error = git_str_joinpath(&cgraph->filename, objects_dir, "info/commit-graph");
316
+ if (error < 0)
317
+ goto error;
318
+
319
+ if (open_file) {
320
+ error = git_commit_graph_file_open(&cgraph->file, git_str_cstr(&cgraph->filename));
321
+ if (error < 0)
322
+ goto error;
323
+ cgraph->checked = 1;
324
+ }
325
+
326
+ *cgraph_out = cgraph;
327
+ return 0;
328
+
329
+ error:
330
+ git_commit_graph_free(cgraph);
331
+ return error;
332
+ }
333
+
334
+ int git_commit_graph_open(git_commit_graph **cgraph_out, const char *objects_dir)
335
+ {
336
+ return git_commit_graph_new(cgraph_out, objects_dir, true);
337
+ }
338
+
339
+ int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *path)
340
+ {
341
+ git_commit_graph_file *file;
342
+ git_file fd = -1;
343
+ size_t cgraph_size;
344
+ struct stat st;
345
+ int error;
346
+
347
+ /* TODO: properly open the file without access time using O_NOATIME */
348
+ fd = git_futils_open_ro(path);
349
+ if (fd < 0)
350
+ return fd;
351
+
352
+ if (p_fstat(fd, &st) < 0) {
353
+ p_close(fd);
354
+ git_error_set(GIT_ERROR_ODB, "commit-graph file not found - '%s'", path);
355
+ return GIT_ENOTFOUND;
356
+ }
357
+
358
+ if (!S_ISREG(st.st_mode) || !git__is_sizet(st.st_size)) {
359
+ p_close(fd);
360
+ git_error_set(GIT_ERROR_ODB, "invalid pack index '%s'", path);
361
+ return GIT_ENOTFOUND;
362
+ }
363
+ cgraph_size = (size_t)st.st_size;
364
+
365
+ file = git__calloc(1, sizeof(git_commit_graph_file));
366
+ GIT_ERROR_CHECK_ALLOC(file);
367
+
368
+ error = git_futils_mmap_ro(&file->graph_map, fd, 0, cgraph_size);
369
+ p_close(fd);
370
+ if (error < 0) {
371
+ git_commit_graph_file_free(file);
372
+ return error;
373
+ }
374
+
375
+ if ((error = git_commit_graph_file_parse(file, file->graph_map.data, cgraph_size)) < 0) {
376
+ git_commit_graph_file_free(file);
377
+ return error;
378
+ }
379
+
380
+ *file_out = file;
381
+ return 0;
382
+ }
383
+
384
+ int git_commit_graph_get_file(git_commit_graph_file **file_out, git_commit_graph *cgraph)
385
+ {
386
+ if (!cgraph->checked) {
387
+ int error = 0;
388
+ git_commit_graph_file *result = NULL;
389
+
390
+ /* We only check once, no matter the result. */
391
+ cgraph->checked = 1;
392
+
393
+ /* Best effort */
394
+ error = git_commit_graph_file_open(&result, git_str_cstr(&cgraph->filename));
395
+
396
+ if (error < 0)
397
+ return error;
398
+
399
+ cgraph->file = result;
400
+ }
401
+ if (!cgraph->file)
402
+ return GIT_ENOTFOUND;
403
+
404
+ *file_out = cgraph->file;
405
+ return 0;
406
+ }
407
+
408
+ void git_commit_graph_refresh(git_commit_graph *cgraph)
409
+ {
410
+ if (!cgraph->checked)
411
+ return;
412
+
413
+ if (cgraph->file
414
+ && git_commit_graph_file_needs_refresh(cgraph->file, git_str_cstr(&cgraph->filename))) {
415
+ /* We just free the commit graph. The next time it is requested, it will be
416
+ * re-loaded. */
417
+ git_commit_graph_file_free(cgraph->file);
418
+ cgraph->file = NULL;
419
+ }
420
+ /* Force a lazy re-check next time it is needed. */
421
+ cgraph->checked = 0;
422
+ }
423
+
424
+ static int git_commit_graph_entry_get_byindex(
425
+ git_commit_graph_entry *e,
426
+ const git_commit_graph_file *file,
427
+ size_t pos)
428
+ {
429
+ const unsigned char *commit_data;
430
+
431
+ GIT_ASSERT_ARG(e);
432
+ GIT_ASSERT_ARG(file);
433
+
434
+ if (pos >= file->num_commits) {
435
+ git_error_set(GIT_ERROR_INVALID, "commit index %zu does not exist", pos);
436
+ return GIT_ENOTFOUND;
437
+ }
438
+
439
+ commit_data = file->commit_data + pos * (GIT_OID_RAWSZ + 4 * sizeof(uint32_t));
440
+ git_oid_cpy(&e->tree_oid, (const git_oid *)commit_data);
441
+ e->parent_indices[0] = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ)));
442
+ e->parent_indices[1] = ntohl(
443
+ *((uint32_t *)(commit_data + GIT_OID_RAWSZ + sizeof(uint32_t))));
444
+ e->parent_count = (e->parent_indices[0] != GIT_COMMIT_GRAPH_MISSING_PARENT)
445
+ + (e->parent_indices[1] != GIT_COMMIT_GRAPH_MISSING_PARENT);
446
+ e->generation = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ + 2 * sizeof(uint32_t))));
447
+ e->commit_time = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ + 3 * sizeof(uint32_t))));
448
+
449
+ e->commit_time |= (e->generation & UINT64_C(0x3)) << UINT64_C(32);
450
+ e->generation >>= 2u;
451
+ if (e->parent_indices[1] & 0x80000000u) {
452
+ uint32_t extra_edge_list_pos = e->parent_indices[1] & 0x7fffffff;
453
+
454
+ /* Make sure we're not being sent out of bounds */
455
+ if (extra_edge_list_pos >= file->num_extra_edge_list) {
456
+ git_error_set(GIT_ERROR_INVALID,
457
+ "commit %u does not exist",
458
+ extra_edge_list_pos);
459
+ return GIT_ENOTFOUND;
460
+ }
461
+
462
+ e->extra_parents_index = extra_edge_list_pos;
463
+ while (extra_edge_list_pos < file->num_extra_edge_list
464
+ && (ntohl(*(
465
+ (uint32_t *)(file->extra_edge_list
466
+ + extra_edge_list_pos * sizeof(uint32_t))))
467
+ & 0x80000000u)
468
+ == 0) {
469
+ extra_edge_list_pos++;
470
+ e->parent_count++;
471
+ }
472
+ }
473
+ git_oid_cpy(&e->sha1, &file->oid_lookup[pos]);
474
+ return 0;
475
+ }
476
+
477
+ bool git_commit_graph_file_needs_refresh(const git_commit_graph_file *file, const char *path)
478
+ {
479
+ git_file fd = -1;
480
+ struct stat st;
481
+ ssize_t bytes_read;
482
+ unsigned char checksum[GIT_HASH_SHA1_SIZE];
483
+ size_t checksum_size = GIT_HASH_SHA1_SIZE;
484
+
485
+ /* TODO: properly open the file without access time using O_NOATIME */
486
+ fd = git_futils_open_ro(path);
487
+ if (fd < 0)
488
+ return true;
489
+
490
+ if (p_fstat(fd, &st) < 0) {
491
+ p_close(fd);
492
+ return true;
493
+ }
494
+
495
+ if (!S_ISREG(st.st_mode) || !git__is_sizet(st.st_size)
496
+ || (size_t)st.st_size != file->graph_map.len) {
497
+ p_close(fd);
498
+ return true;
499
+ }
500
+
501
+ bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - checksum_size);
502
+ p_close(fd);
503
+ if (bytes_read != (ssize_t)checksum_size)
504
+ return true;
505
+
506
+ return (memcmp(checksum, file->checksum, checksum_size) != 0);
507
+ }
508
+
509
+ int git_commit_graph_entry_find(
510
+ git_commit_graph_entry *e,
511
+ const git_commit_graph_file *file,
512
+ const git_oid *short_oid,
513
+ size_t len)
514
+ {
515
+ int pos, found = 0;
516
+ uint32_t hi, lo;
517
+ const git_oid *current = NULL;
518
+
519
+ GIT_ASSERT_ARG(e);
520
+ GIT_ASSERT_ARG(file);
521
+ GIT_ASSERT_ARG(short_oid);
522
+
523
+ hi = ntohl(file->oid_fanout[(int)short_oid->id[0]]);
524
+ lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(file->oid_fanout[(int)short_oid->id[0] - 1]));
525
+
526
+ pos = git_pack__lookup_sha1(file->oid_lookup, GIT_OID_RAWSZ, lo, hi, short_oid->id);
527
+
528
+ if (pos >= 0) {
529
+ /* An object matching exactly the oid was found */
530
+ found = 1;
531
+ current = file->oid_lookup + pos;
532
+ } else {
533
+ /* No object was found */
534
+ /* pos refers to the object with the "closest" oid to short_oid */
535
+ pos = -1 - pos;
536
+ if (pos < (int)file->num_commits) {
537
+ current = file->oid_lookup + pos;
538
+
539
+ if (!git_oid_ncmp(short_oid, current, len))
540
+ found = 1;
541
+ }
542
+ }
543
+
544
+ if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)file->num_commits) {
545
+ /* Check for ambiguousity */
546
+ const git_oid *next = current + 1;
547
+
548
+ if (!git_oid_ncmp(short_oid, next, len)) {
549
+ found = 2;
550
+ }
551
+ }
552
+
553
+ if (!found)
554
+ return git_odb__error_notfound(
555
+ "failed to find offset for commit-graph index entry", short_oid, len);
556
+ if (found > 1)
557
+ return git_odb__error_ambiguous(
558
+ "found multiple offsets for commit-graph index entry");
559
+
560
+ return git_commit_graph_entry_get_byindex(e, file, pos);
561
+ }
562
+
563
+ int git_commit_graph_entry_parent(
564
+ git_commit_graph_entry *parent,
565
+ const git_commit_graph_file *file,
566
+ const git_commit_graph_entry *entry,
567
+ size_t n)
568
+ {
569
+ GIT_ASSERT_ARG(parent);
570
+ GIT_ASSERT_ARG(file);
571
+
572
+ if (n >= entry->parent_count) {
573
+ git_error_set(GIT_ERROR_INVALID, "parent index %zu does not exist", n);
574
+ return GIT_ENOTFOUND;
575
+ }
576
+
577
+ if (n == 0 || (n == 1 && entry->parent_count == 2))
578
+ return git_commit_graph_entry_get_byindex(parent, file, entry->parent_indices[n]);
579
+
580
+ return git_commit_graph_entry_get_byindex(
581
+ parent,
582
+ file,
583
+ ntohl(
584
+ *(uint32_t *)(file->extra_edge_list
585
+ + (entry->extra_parents_index + n - 1)
586
+ * sizeof(uint32_t)))
587
+ & 0x7fffffff);
588
+ }
589
+
590
+ int git_commit_graph_file_close(git_commit_graph_file *file)
591
+ {
592
+ GIT_ASSERT_ARG(file);
593
+
594
+ if (file->graph_map.data)
595
+ git_futils_mmap_free(&file->graph_map);
596
+
597
+ return 0;
598
+ }
599
+
600
+ void git_commit_graph_free(git_commit_graph *cgraph)
601
+ {
602
+ if (!cgraph)
603
+ return;
604
+
605
+ git_str_dispose(&cgraph->filename);
606
+ git_commit_graph_file_free(cgraph->file);
607
+ git__free(cgraph);
608
+ }
609
+
610
+ void git_commit_graph_file_free(git_commit_graph_file *file)
611
+ {
612
+ if (!file)
613
+ return;
614
+
615
+ git_commit_graph_file_close(file);
616
+ git__free(file);
617
+ }
618
+
619
+ static int packed_commit__cmp(const void *a_, const void *b_)
620
+ {
621
+ const struct packed_commit *a = a_;
622
+ const struct packed_commit *b = b_;
623
+ return git_oid_cmp(&a->sha1, &b->sha1);
624
+ }
625
+
626
+ int git_commit_graph_writer_new(git_commit_graph_writer **out, const char *objects_info_dir)
627
+ {
628
+ git_commit_graph_writer *w = git__calloc(1, sizeof(git_commit_graph_writer));
629
+ GIT_ERROR_CHECK_ALLOC(w);
630
+
631
+ if (git_str_sets(&w->objects_info_dir, objects_info_dir) < 0) {
632
+ git__free(w);
633
+ return -1;
634
+ }
635
+
636
+ if (git_vector_init(&w->commits, 0, packed_commit__cmp) < 0) {
637
+ git_str_dispose(&w->objects_info_dir);
638
+ git__free(w);
639
+ return -1;
640
+ }
641
+
642
+ *out = w;
643
+ return 0;
644
+ }
645
+
646
+ void git_commit_graph_writer_free(git_commit_graph_writer *w)
647
+ {
648
+ struct packed_commit *packed_commit;
649
+ size_t i;
650
+
651
+ if (!w)
652
+ return;
653
+
654
+ git_vector_foreach (&w->commits, i, packed_commit)
655
+ packed_commit_free(packed_commit);
656
+ git_vector_free(&w->commits);
657
+ git_str_dispose(&w->objects_info_dir);
658
+ git__free(w);
659
+ }
660
+
661
+ struct object_entry_cb_state {
662
+ git_repository *repo;
663
+ git_odb *db;
664
+ git_vector *commits;
665
+ };
666
+
667
+ static int object_entry__cb(const git_oid *id, void *data)
668
+ {
669
+ struct object_entry_cb_state *state = (struct object_entry_cb_state *)data;
670
+ git_commit *commit = NULL;
671
+ struct packed_commit *packed_commit = NULL;
672
+ size_t header_len;
673
+ git_object_t header_type;
674
+ int error = 0;
675
+
676
+ error = git_odb_read_header(&header_len, &header_type, state->db, id);
677
+ if (error < 0)
678
+ return error;
679
+
680
+ if (header_type != GIT_OBJECT_COMMIT)
681
+ return 0;
682
+
683
+ error = git_commit_lookup(&commit, state->repo, id);
684
+ if (error < 0)
685
+ return error;
686
+
687
+ packed_commit = packed_commit_new(commit);
688
+ git_commit_free(commit);
689
+ GIT_ERROR_CHECK_ALLOC(packed_commit);
690
+
691
+ error = git_vector_insert(state->commits, packed_commit);
692
+ if (error < 0) {
693
+ packed_commit_free(packed_commit);
694
+ return error;
695
+ }
696
+
697
+ return 0;
698
+ }
699
+
700
+ int git_commit_graph_writer_add_index_file(
701
+ git_commit_graph_writer *w,
702
+ git_repository *repo,
703
+ const char *idx_path)
704
+ {
705
+ int error;
706
+ struct git_pack_file *p = NULL;
707
+ struct object_entry_cb_state state = {0};
708
+ state.repo = repo;
709
+ state.commits = &w->commits;
710
+
711
+ error = git_repository_odb(&state.db, repo);
712
+ if (error < 0)
713
+ goto cleanup;
714
+
715
+ error = git_mwindow_get_pack(&p, idx_path);
716
+ if (error < 0)
717
+ goto cleanup;
718
+
719
+ error = git_pack_foreach_entry(p, object_entry__cb, &state);
720
+ if (error < 0)
721
+ goto cleanup;
722
+
723
+ cleanup:
724
+ if (p)
725
+ git_mwindow_put_pack(p);
726
+ git_odb_free(state.db);
727
+ return error;
728
+ }
729
+
730
+ int git_commit_graph_writer_add_revwalk(git_commit_graph_writer *w, git_revwalk *walk)
731
+ {
732
+ int error;
733
+ git_oid id;
734
+ git_repository *repo = git_revwalk_repository(walk);
735
+ git_commit *commit;
736
+ struct packed_commit *packed_commit;
737
+
738
+ while ((git_revwalk_next(&id, walk)) == 0) {
739
+ error = git_commit_lookup(&commit, repo, &id);
740
+ if (error < 0)
741
+ return error;
742
+
743
+ packed_commit = packed_commit_new(commit);
744
+ git_commit_free(commit);
745
+ GIT_ERROR_CHECK_ALLOC(packed_commit);
746
+
747
+ error = git_vector_insert(&w->commits, packed_commit);
748
+ if (error < 0) {
749
+ packed_commit_free(packed_commit);
750
+ return error;
751
+ }
752
+ }
753
+
754
+ return 0;
755
+ }
756
+
757
+ enum generation_number_commit_state {
758
+ GENERATION_NUMBER_COMMIT_STATE_UNVISITED = 0,
759
+ GENERATION_NUMBER_COMMIT_STATE_ADDED = 1,
760
+ GENERATION_NUMBER_COMMIT_STATE_EXPANDED = 2,
761
+ GENERATION_NUMBER_COMMIT_STATE_VISITED = 3
762
+ };
763
+
764
+ static int compute_generation_numbers(git_vector *commits)
765
+ {
766
+ git_array_t(size_t) index_stack = GIT_ARRAY_INIT;
767
+ size_t i, j;
768
+ size_t *parent_idx;
769
+ enum generation_number_commit_state *commit_states = NULL;
770
+ struct packed_commit *child_packed_commit;
771
+ git_oidmap *packed_commit_map = NULL;
772
+ int error = 0;
773
+
774
+ /* First populate the parent indices fields */
775
+ error = git_oidmap_new(&packed_commit_map);
776
+ if (error < 0)
777
+ goto cleanup;
778
+ git_vector_foreach (commits, i, child_packed_commit) {
779
+ child_packed_commit->index = i;
780
+ error = git_oidmap_set(
781
+ packed_commit_map, &child_packed_commit->sha1, child_packed_commit);
782
+ if (error < 0)
783
+ goto cleanup;
784
+ }
785
+
786
+ git_vector_foreach (commits, i, child_packed_commit) {
787
+ size_t parent_i, *parent_idx_ptr;
788
+ struct packed_commit *parent_packed_commit;
789
+ git_oid *parent_id;
790
+ git_array_init_to_size(
791
+ child_packed_commit->parent_indices,
792
+ git_array_size(child_packed_commit->parents));
793
+ if (git_array_size(child_packed_commit->parents)
794
+ && !child_packed_commit->parent_indices.ptr) {
795
+ error = -1;
796
+ goto cleanup;
797
+ }
798
+ git_array_foreach (child_packed_commit->parents, parent_i, parent_id) {
799
+ parent_packed_commit = git_oidmap_get(packed_commit_map, parent_id);
800
+ if (!parent_packed_commit) {
801
+ git_error_set(GIT_ERROR_ODB,
802
+ "parent commit %s not found in commit graph",
803
+ git_oid_tostr_s(parent_id));
804
+ error = GIT_ENOTFOUND;
805
+ goto cleanup;
806
+ }
807
+ parent_idx_ptr = git_array_alloc(child_packed_commit->parent_indices);
808
+ if (!parent_idx_ptr) {
809
+ error = -1;
810
+ goto cleanup;
811
+ }
812
+ *parent_idx_ptr = parent_packed_commit->index;
813
+ }
814
+ }
815
+
816
+ /*
817
+ * We copy all the commits to the stack and then during visitation,
818
+ * each node can be added up to two times to the stack.
819
+ */
820
+ git_array_init_to_size(index_stack, 3 * git_vector_length(commits));
821
+ if (!index_stack.ptr) {
822
+ error = -1;
823
+ goto cleanup;
824
+ }
825
+
826
+ commit_states = (enum generation_number_commit_state *)git__calloc(
827
+ git_vector_length(commits), sizeof(enum generation_number_commit_state));
828
+ if (!commit_states) {
829
+ error = -1;
830
+ goto cleanup;
831
+ }
832
+
833
+ /*
834
+ * Perform a Post-Order traversal so that all parent nodes are fully
835
+ * visited before the child node.
836
+ */
837
+ git_vector_foreach (commits, i, child_packed_commit)
838
+ *(size_t *)git_array_alloc(index_stack) = i;
839
+
840
+ while (git_array_size(index_stack)) {
841
+ size_t *index_ptr = git_array_pop(index_stack);
842
+ i = *index_ptr;
843
+ child_packed_commit = git_vector_get(commits, i);
844
+
845
+ if (commit_states[i] == GENERATION_NUMBER_COMMIT_STATE_VISITED) {
846
+ /* This commit has already been fully visited. */
847
+ continue;
848
+ }
849
+ if (commit_states[i] == GENERATION_NUMBER_COMMIT_STATE_EXPANDED) {
850
+ /* All of the commits parents have been visited. */
851
+ child_packed_commit->generation = 0;
852
+ git_array_foreach (child_packed_commit->parent_indices, j, parent_idx) {
853
+ struct packed_commit *parent = git_vector_get(commits, *parent_idx);
854
+ if (child_packed_commit->generation < parent->generation)
855
+ child_packed_commit->generation = parent->generation;
856
+ }
857
+ if (child_packed_commit->generation
858
+ < GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX) {
859
+ ++child_packed_commit->generation;
860
+ }
861
+ commit_states[i] = GENERATION_NUMBER_COMMIT_STATE_VISITED;
862
+ continue;
863
+ }
864
+
865
+ /*
866
+ * This is the first time we see this commit. We need
867
+ * to visit all its parents before we can fully visit
868
+ * it.
869
+ */
870
+ if (git_array_size(child_packed_commit->parent_indices) == 0) {
871
+ /*
872
+ * Special case: if the commit has no parents, there's
873
+ * no need to add it to the stack just to immediately
874
+ * remove it.
875
+ */
876
+ commit_states[i] = GENERATION_NUMBER_COMMIT_STATE_VISITED;
877
+ child_packed_commit->generation = 1;
878
+ continue;
879
+ }
880
+
881
+ /*
882
+ * Add this current commit again so that it is visited
883
+ * again once all its children have been visited.
884
+ */
885
+ *(size_t *)git_array_alloc(index_stack) = i;
886
+ git_array_foreach (child_packed_commit->parent_indices, j, parent_idx) {
887
+ if (commit_states[*parent_idx]
888
+ != GENERATION_NUMBER_COMMIT_STATE_UNVISITED) {
889
+ /* This commit has already been considered. */
890
+ continue;
891
+ }
892
+
893
+ commit_states[*parent_idx] = GENERATION_NUMBER_COMMIT_STATE_ADDED;
894
+ *(size_t *)git_array_alloc(index_stack) = *parent_idx;
895
+ }
896
+ commit_states[i] = GENERATION_NUMBER_COMMIT_STATE_EXPANDED;
897
+ }
898
+
899
+ cleanup:
900
+ git_oidmap_free(packed_commit_map);
901
+ git__free(commit_states);
902
+ git_array_clear(index_stack);
903
+
904
+ return error;
905
+ }
906
+
907
+ static int write_offset(off64_t offset, commit_graph_write_cb write_cb, void *cb_data)
908
+ {
909
+ int error;
910
+ uint32_t word;
911
+
912
+ word = htonl((uint32_t)((offset >> 32) & 0xffffffffu));
913
+ error = write_cb((const char *)&word, sizeof(word), cb_data);
914
+ if (error < 0)
915
+ return error;
916
+ word = htonl((uint32_t)((offset >> 0) & 0xffffffffu));
917
+ error = write_cb((const char *)&word, sizeof(word), cb_data);
918
+ if (error < 0)
919
+ return error;
920
+
921
+ return 0;
922
+ }
923
+
924
+ static int write_chunk_header(
925
+ int chunk_id,
926
+ off64_t offset,
927
+ commit_graph_write_cb write_cb,
928
+ void *cb_data)
929
+ {
930
+ uint32_t word = htonl(chunk_id);
931
+ int error = write_cb((const char *)&word, sizeof(word), cb_data);
932
+ if (error < 0)
933
+ return error;
934
+ return write_offset(offset, write_cb, cb_data);
935
+ }
936
+
937
+ static int commit_graph_write_buf(const char *buf, size_t size, void *data)
938
+ {
939
+ git_str *b = (git_str *)data;
940
+ return git_str_put(b, buf, size);
941
+ }
942
+
943
+ struct commit_graph_write_hash_context {
944
+ commit_graph_write_cb write_cb;
945
+ void *cb_data;
946
+ git_hash_ctx *ctx;
947
+ };
948
+
949
+ static int commit_graph_write_hash(const char *buf, size_t size, void *data)
950
+ {
951
+ struct commit_graph_write_hash_context *ctx = data;
952
+ int error;
953
+
954
+ error = git_hash_update(ctx->ctx, buf, size);
955
+ if (error < 0)
956
+ return error;
957
+
958
+ return ctx->write_cb(buf, size, ctx->cb_data);
959
+ }
960
+
961
+ static void packed_commit_free_dup(void *packed_commit)
962
+ {
963
+ packed_commit_free(packed_commit);
964
+ }
965
+
966
+ static int commit_graph_write(
967
+ git_commit_graph_writer *w,
968
+ commit_graph_write_cb write_cb,
969
+ void *cb_data)
970
+ {
971
+ int error = 0;
972
+ size_t i;
973
+ struct packed_commit *packed_commit;
974
+ struct git_commit_graph_header hdr = {0};
975
+ uint32_t oid_fanout_count;
976
+ uint32_t extra_edge_list_count;
977
+ uint32_t oid_fanout[256];
978
+ off64_t offset;
979
+ git_str oid_lookup = GIT_STR_INIT, commit_data = GIT_STR_INIT,
980
+ extra_edge_list = GIT_STR_INIT;
981
+ unsigned char checksum[GIT_HASH_SHA1_SIZE];
982
+ size_t checksum_size;
983
+ git_hash_ctx ctx;
984
+ struct commit_graph_write_hash_context hash_cb_data = {0};
985
+
986
+ hdr.signature = htonl(COMMIT_GRAPH_SIGNATURE);
987
+ hdr.version = COMMIT_GRAPH_VERSION;
988
+ hdr.object_id_version = COMMIT_GRAPH_OBJECT_ID_VERSION;
989
+ hdr.chunks = 0;
990
+ hdr.base_graph_files = 0;
991
+ hash_cb_data.write_cb = write_cb;
992
+ hash_cb_data.cb_data = cb_data;
993
+ hash_cb_data.ctx = &ctx;
994
+
995
+ checksum_size = GIT_HASH_SHA1_SIZE;
996
+ error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1);
997
+ if (error < 0)
998
+ return error;
999
+ cb_data = &hash_cb_data;
1000
+ write_cb = commit_graph_write_hash;
1001
+
1002
+ /* Sort the commits. */
1003
+ git_vector_sort(&w->commits);
1004
+ git_vector_uniq(&w->commits, packed_commit_free_dup);
1005
+ error = compute_generation_numbers(&w->commits);
1006
+ if (error < 0)
1007
+ goto cleanup;
1008
+
1009
+ /* Fill the OID Fanout table. */
1010
+ oid_fanout_count = 0;
1011
+ for (i = 0; i < 256; i++) {
1012
+ while (oid_fanout_count < git_vector_length(&w->commits) &&
1013
+ (packed_commit = (struct packed_commit *)git_vector_get(&w->commits, oid_fanout_count)) &&
1014
+ packed_commit->sha1.id[0] <= i)
1015
+ ++oid_fanout_count;
1016
+ oid_fanout[i] = htonl(oid_fanout_count);
1017
+ }
1018
+
1019
+ /* Fill the OID Lookup table. */
1020
+ git_vector_foreach (&w->commits, i, packed_commit) {
1021
+ error = git_str_put(&oid_lookup,
1022
+ (const char *)&packed_commit->sha1, sizeof(git_oid));
1023
+ if (error < 0)
1024
+ goto cleanup;
1025
+ }
1026
+
1027
+ /* Fill the Commit Data and Extra Edge List tables. */
1028
+ extra_edge_list_count = 0;
1029
+ git_vector_foreach (&w->commits, i, packed_commit) {
1030
+ uint64_t commit_time;
1031
+ uint32_t generation;
1032
+ uint32_t word;
1033
+ size_t *packed_index;
1034
+ unsigned int parentcount = (unsigned int)git_array_size(packed_commit->parents);
1035
+
1036
+ error = git_str_put(&commit_data,
1037
+ (const char *)&packed_commit->tree_oid,
1038
+ sizeof(git_oid));
1039
+ if (error < 0)
1040
+ goto cleanup;
1041
+
1042
+ if (parentcount == 0) {
1043
+ word = htonl(GIT_COMMIT_GRAPH_MISSING_PARENT);
1044
+ } else {
1045
+ packed_index = git_array_get(packed_commit->parent_indices, 0);
1046
+ word = htonl((uint32_t)*packed_index);
1047
+ }
1048
+ error = git_str_put(&commit_data, (const char *)&word, sizeof(word));
1049
+ if (error < 0)
1050
+ goto cleanup;
1051
+
1052
+ if (parentcount < 2) {
1053
+ word = htonl(GIT_COMMIT_GRAPH_MISSING_PARENT);
1054
+ } else if (parentcount == 2) {
1055
+ packed_index = git_array_get(packed_commit->parent_indices, 1);
1056
+ word = htonl((uint32_t)*packed_index);
1057
+ } else {
1058
+ word = htonl(0x80000000u | extra_edge_list_count);
1059
+ }
1060
+ error = git_str_put(&commit_data, (const char *)&word, sizeof(word));
1061
+ if (error < 0)
1062
+ goto cleanup;
1063
+
1064
+ if (parentcount > 2) {
1065
+ unsigned int parent_i;
1066
+ for (parent_i = 1; parent_i < parentcount; ++parent_i) {
1067
+ packed_index = git_array_get(
1068
+ packed_commit->parent_indices, parent_i);
1069
+ word = htonl((uint32_t)(*packed_index | (parent_i + 1 == parentcount ? 0x80000000u : 0)));
1070
+
1071
+ error = git_str_put(&extra_edge_list,
1072
+ (const char *)&word,
1073
+ sizeof(word));
1074
+ if (error < 0)
1075
+ goto cleanup;
1076
+ }
1077
+ extra_edge_list_count += parentcount - 1;
1078
+ }
1079
+
1080
+ generation = packed_commit->generation;
1081
+ commit_time = (uint64_t)packed_commit->commit_time;
1082
+ if (generation > GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX)
1083
+ generation = GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX;
1084
+ word = ntohl((uint32_t)((generation << 2) | (((uint32_t)(commit_time >> 32)) & 0x3) ));
1085
+ error = git_str_put(&commit_data, (const char *)&word, sizeof(word));
1086
+ if (error < 0)
1087
+ goto cleanup;
1088
+ word = ntohl((uint32_t)(commit_time & 0xfffffffful));
1089
+ error = git_str_put(&commit_data, (const char *)&word, sizeof(word));
1090
+ if (error < 0)
1091
+ goto cleanup;
1092
+ }
1093
+
1094
+ /* Write the header. */
1095
+ hdr.chunks = 3;
1096
+ if (git_str_len(&extra_edge_list) > 0)
1097
+ hdr.chunks++;
1098
+ error = write_cb((const char *)&hdr, sizeof(hdr), cb_data);
1099
+ if (error < 0)
1100
+ goto cleanup;
1101
+
1102
+ /* Write the chunk headers. */
1103
+ offset = sizeof(hdr) + (hdr.chunks + 1) * 12;
1104
+ error = write_chunk_header(COMMIT_GRAPH_OID_FANOUT_ID, offset, write_cb, cb_data);
1105
+ if (error < 0)
1106
+ goto cleanup;
1107
+ offset += sizeof(oid_fanout);
1108
+ error = write_chunk_header(COMMIT_GRAPH_OID_LOOKUP_ID, offset, write_cb, cb_data);
1109
+ if (error < 0)
1110
+ goto cleanup;
1111
+ offset += git_str_len(&oid_lookup);
1112
+ error = write_chunk_header(COMMIT_GRAPH_COMMIT_DATA_ID, offset, write_cb, cb_data);
1113
+ if (error < 0)
1114
+ goto cleanup;
1115
+ offset += git_str_len(&commit_data);
1116
+ if (git_str_len(&extra_edge_list) > 0) {
1117
+ error = write_chunk_header(
1118
+ COMMIT_GRAPH_EXTRA_EDGE_LIST_ID, offset, write_cb, cb_data);
1119
+ if (error < 0)
1120
+ goto cleanup;
1121
+ offset += git_str_len(&extra_edge_list);
1122
+ }
1123
+ error = write_chunk_header(0, offset, write_cb, cb_data);
1124
+ if (error < 0)
1125
+ goto cleanup;
1126
+
1127
+ /* Write all the chunks. */
1128
+ error = write_cb((const char *)oid_fanout, sizeof(oid_fanout), cb_data);
1129
+ if (error < 0)
1130
+ goto cleanup;
1131
+ error = write_cb(git_str_cstr(&oid_lookup), git_str_len(&oid_lookup), cb_data);
1132
+ if (error < 0)
1133
+ goto cleanup;
1134
+ error = write_cb(git_str_cstr(&commit_data), git_str_len(&commit_data), cb_data);
1135
+ if (error < 0)
1136
+ goto cleanup;
1137
+ error = write_cb(git_str_cstr(&extra_edge_list), git_str_len(&extra_edge_list), cb_data);
1138
+ if (error < 0)
1139
+ goto cleanup;
1140
+
1141
+ /* Finalize the checksum and write the trailer. */
1142
+ error = git_hash_final(checksum, &ctx);
1143
+ if (error < 0)
1144
+ goto cleanup;
1145
+ error = write_cb((char *)checksum, checksum_size, cb_data);
1146
+ if (error < 0)
1147
+ goto cleanup;
1148
+
1149
+ cleanup:
1150
+ git_str_dispose(&oid_lookup);
1151
+ git_str_dispose(&commit_data);
1152
+ git_str_dispose(&extra_edge_list);
1153
+ git_hash_ctx_cleanup(&ctx);
1154
+ return error;
1155
+ }
1156
+
1157
+ static int commit_graph_write_filebuf(const char *buf, size_t size, void *data)
1158
+ {
1159
+ git_filebuf *f = (git_filebuf *)data;
1160
+ return git_filebuf_write(f, buf, size);
1161
+ }
1162
+
1163
+ int git_commit_graph_writer_options_init(
1164
+ git_commit_graph_writer_options *opts,
1165
+ unsigned int version)
1166
+ {
1167
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1168
+ opts,
1169
+ version,
1170
+ git_commit_graph_writer_options,
1171
+ GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT);
1172
+ return 0;
1173
+ }
1174
+
1175
+ int git_commit_graph_writer_commit(
1176
+ git_commit_graph_writer *w,
1177
+ git_commit_graph_writer_options *opts)
1178
+ {
1179
+ int error;
1180
+ int filebuf_flags = GIT_FILEBUF_DO_NOT_BUFFER;
1181
+ git_str commit_graph_path = GIT_STR_INIT;
1182
+ git_filebuf output = GIT_FILEBUF_INIT;
1183
+
1184
+ /* TODO: support options and fill in defaults. */
1185
+ GIT_UNUSED(opts);
1186
+
1187
+ error = git_str_joinpath(
1188
+ &commit_graph_path, git_str_cstr(&w->objects_info_dir), "commit-graph");
1189
+ if (error < 0)
1190
+ return error;
1191
+
1192
+ if (git_repository__fsync_gitdir)
1193
+ filebuf_flags |= GIT_FILEBUF_FSYNC;
1194
+ error = git_filebuf_open(&output, git_str_cstr(&commit_graph_path), filebuf_flags, 0644);
1195
+ git_str_dispose(&commit_graph_path);
1196
+ if (error < 0)
1197
+ return error;
1198
+
1199
+ error = commit_graph_write(w, commit_graph_write_filebuf, &output);
1200
+ if (error < 0) {
1201
+ git_filebuf_cleanup(&output);
1202
+ return error;
1203
+ }
1204
+
1205
+ return git_filebuf_commit(&output);
1206
+ }
1207
+
1208
+ int git_commit_graph_writer_dump(
1209
+ git_buf *cgraph,
1210
+ git_commit_graph_writer *w,
1211
+ git_commit_graph_writer_options *opts)
1212
+ {
1213
+ GIT_BUF_WRAP_PRIVATE(cgraph, git_commit_graph__writer_dump, w, opts);
1214
+ }
1215
+
1216
+ int git_commit_graph__writer_dump(
1217
+ git_str *cgraph,
1218
+ git_commit_graph_writer *w,
1219
+ git_commit_graph_writer_options *opts)
1220
+ {
1221
+ /* TODO: support options. */
1222
+ GIT_UNUSED(opts);
1223
+ return commit_graph_write(w, commit_graph_write_buf, cgraph);
1224
+ }