rugged 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (338) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -0
  3. data/README.md +3 -3
  4. data/ext/rugged/rugged.c +7 -4
  5. data/ext/rugged/rugged_commit.c +1 -1
  6. data/ext/rugged/rugged_config.c +1 -1
  7. data/ext/rugged/rugged_object.c +1 -1
  8. data/ext/rugged/rugged_remote.c +32 -2
  9. data/ext/rugged/rugged_repo.c +13 -3
  10. data/lib/rugged/commit.rb +17 -4
  11. data/lib/rugged/repository.rb +7 -8
  12. data/lib/rugged/submodule_collection.rb +4 -4
  13. data/lib/rugged/version.rb +1 -1
  14. data/vendor/libgit2/CMakeLists.txt +41 -74
  15. data/vendor/libgit2/COPYING +109 -1
  16. data/vendor/libgit2/cmake/{Modules/AddCFlagIfSupported.cmake → AddCFlagIfSupported.cmake} +0 -0
  17. data/vendor/libgit2/cmake/{Modules/EnableWarnings.cmake → EnableWarnings.cmake} +0 -0
  18. data/vendor/libgit2/cmake/{Modules/FindCoreFoundation.cmake → FindCoreFoundation.cmake} +0 -0
  19. data/vendor/libgit2/cmake/{Modules/FindGSSAPI.cmake → FindGSSAPI.cmake} +0 -0
  20. data/vendor/libgit2/cmake/{Modules/FindGSSFramework.cmake → FindGSSFramework.cmake} +0 -0
  21. data/vendor/libgit2/cmake/{Modules/FindHTTP_Parser.cmake → FindHTTP_Parser.cmake} +0 -0
  22. data/vendor/libgit2/cmake/{Modules/FindIconv.cmake → FindIconv.cmake} +0 -0
  23. data/vendor/libgit2/cmake/{Modules/FindPCRE.cmake → FindPCRE.cmake} +0 -0
  24. data/vendor/libgit2/cmake/{Modules/FindPCRE2.cmake → FindPCRE2.cmake} +0 -0
  25. data/vendor/libgit2/cmake/{Modules/FindPkgLibraries.cmake → FindPkgLibraries.cmake} +0 -0
  26. data/vendor/libgit2/cmake/{Modules/FindSecurity.cmake → FindSecurity.cmake} +0 -0
  27. data/vendor/libgit2/cmake/{Modules/FindStatNsec.cmake → FindStatNsec.cmake} +0 -0
  28. data/vendor/libgit2/cmake/Findfutimens.cmake +14 -0
  29. data/vendor/libgit2/cmake/{Modules/FindmbedTLS.cmake → FindmbedTLS.cmake} +0 -0
  30. data/vendor/libgit2/cmake/{Modules/IdeSplitSources.cmake → IdeSplitSources.cmake} +0 -0
  31. data/vendor/libgit2/cmake/{Modules/PkgBuildConfig.cmake → PkgBuildConfig.cmake} +0 -0
  32. data/vendor/libgit2/cmake/{Modules/SanitizeBool.cmake → SanitizeBool.cmake} +0 -0
  33. data/vendor/libgit2/cmake/{Modules/SelectGSSAPI.cmake → SelectGSSAPI.cmake} +18 -26
  34. data/vendor/libgit2/cmake/{Modules/SelectHTTPSBackend.cmake → SelectHTTPSBackend.cmake} +29 -32
  35. data/vendor/libgit2/cmake/{Modules/SelectHashes.cmake → SelectHashes.cmake} +21 -28
  36. data/vendor/libgit2/deps/chromium-zlib/CMakeLists.txt +101 -0
  37. data/vendor/libgit2/deps/http-parser/CMakeLists.txt +4 -3
  38. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +24 -10
  39. data/vendor/libgit2/deps/ntlmclient/compat.h +0 -27
  40. data/vendor/libgit2/deps/ntlmclient/crypt.h +14 -9
  41. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +20 -20
  42. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.h +3 -3
  43. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +37 -36
  44. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.h +4 -3
  45. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +178 -51
  46. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.h +74 -5
  47. data/vendor/libgit2/deps/ntlmclient/ntlm.c +164 -135
  48. data/vendor/libgit2/deps/ntlmclient/ntlm.h +13 -9
  49. data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +16 -3
  50. data/vendor/libgit2/deps/ntlmclient/unicode.h +10 -4
  51. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +16 -27
  52. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.h +20 -0
  53. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +28 -52
  54. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.h +22 -0
  55. data/vendor/libgit2/deps/ntlmclient/util.c +15 -1
  56. data/vendor/libgit2/deps/ntlmclient/util.h +2 -1
  57. data/vendor/libgit2/deps/pcre/LICENCE +93 -0
  58. data/vendor/libgit2/deps/pcre/pcre.h +2 -2
  59. data/vendor/libgit2/deps/pcre/pcre_compile.c +29 -17
  60. data/vendor/libgit2/deps/pcre/pcre_jit_compile.c +4 -4
  61. data/vendor/libgit2/deps/pcre/pcreposix.c +2 -3
  62. data/vendor/libgit2/deps/zlib/CMakeLists.txt +6 -5
  63. data/vendor/libgit2/deps/zlib/deflate.c +1 -0
  64. data/vendor/libgit2/include/git2/annotated_commit.h +1 -1
  65. data/vendor/libgit2/include/git2/apply.h +2 -0
  66. data/vendor/libgit2/include/git2/attr.h +89 -0
  67. data/vendor/libgit2/include/git2/blame.h +95 -42
  68. data/vendor/libgit2/include/git2/blob.h +31 -3
  69. data/vendor/libgit2/include/git2/branch.h +25 -0
  70. data/vendor/libgit2/include/git2/cert.h +42 -5
  71. data/vendor/libgit2/include/git2/checkout.h +28 -12
  72. data/vendor/libgit2/include/git2/commit.h +35 -19
  73. data/vendor/libgit2/include/git2/common.h +33 -6
  74. data/vendor/libgit2/include/git2/config.h +1 -1
  75. data/vendor/libgit2/include/git2/deprecated.h +248 -8
  76. data/vendor/libgit2/include/git2/diff.h +35 -20
  77. data/vendor/libgit2/include/git2/errors.h +8 -7
  78. data/vendor/libgit2/include/git2/filter.h +57 -17
  79. data/vendor/libgit2/include/git2/graph.h +20 -2
  80. data/vendor/libgit2/include/git2/index.h +4 -5
  81. data/vendor/libgit2/include/git2/indexer.h +2 -1
  82. data/vendor/libgit2/include/git2/odb.h +44 -20
  83. data/vendor/libgit2/include/git2/pack.h +1 -1
  84. data/vendor/libgit2/include/git2/patch.h +8 -0
  85. data/vendor/libgit2/include/git2/rebase.h +25 -1
  86. data/vendor/libgit2/include/git2/refs.h +9 -5
  87. data/vendor/libgit2/include/git2/remote.h +59 -6
  88. data/vendor/libgit2/include/git2/repository.h +95 -52
  89. data/vendor/libgit2/include/git2/revparse.h +5 -5
  90. data/vendor/libgit2/include/git2/status.h +115 -59
  91. data/vendor/libgit2/include/git2/strarray.h +6 -10
  92. data/vendor/libgit2/include/git2/submodule.h +9 -0
  93. data/vendor/libgit2/include/git2/sys/commit_graph.h +174 -0
  94. data/vendor/libgit2/include/git2/sys/filter.h +49 -28
  95. data/vendor/libgit2/include/git2/sys/midx.h +74 -0
  96. data/vendor/libgit2/include/git2/sys/odb_backend.h +7 -0
  97. data/vendor/libgit2/include/git2/sys/transport.h +1 -0
  98. data/vendor/libgit2/include/git2/tag.h +12 -0
  99. data/vendor/libgit2/include/git2/transport.h +1 -1
  100. data/vendor/libgit2/include/git2/tree.h +2 -14
  101. data/vendor/libgit2/include/git2/types.h +9 -0
  102. data/vendor/libgit2/include/git2/version.h +3 -3
  103. data/vendor/libgit2/include/git2/worktree.h +1 -0
  104. data/vendor/libgit2/src/CMakeLists.txt +77 -44
  105. data/vendor/libgit2/src/alloc.c +21 -8
  106. data/vendor/libgit2/src/allocators/failalloc.c +92 -0
  107. data/vendor/libgit2/src/allocators/failalloc.h +23 -0
  108. data/vendor/libgit2/src/allocators/stdalloc.c +41 -10
  109. data/vendor/libgit2/src/allocators/win32_leakcheck.c +118 -0
  110. data/vendor/libgit2/src/allocators/{win32_crtdbg.h → win32_leakcheck.h} +3 -3
  111. data/vendor/libgit2/src/annotated_commit.c +21 -9
  112. data/vendor/libgit2/src/apply.c +21 -8
  113. data/vendor/libgit2/src/array.h +11 -11
  114. data/vendor/libgit2/src/assert_safe.h +58 -0
  115. data/vendor/libgit2/src/attr.c +181 -74
  116. data/vendor/libgit2/src/attr_file.c +92 -42
  117. data/vendor/libgit2/src/attr_file.h +32 -11
  118. data/vendor/libgit2/src/attrcache.c +44 -40
  119. data/vendor/libgit2/src/attrcache.h +4 -5
  120. data/vendor/libgit2/src/blame.c +28 -15
  121. data/vendor/libgit2/src/blame_git.c +6 -3
  122. data/vendor/libgit2/src/blob.c +46 -24
  123. data/vendor/libgit2/src/branch.c +87 -37
  124. data/vendor/libgit2/src/buffer.c +339 -27
  125. data/vendor/libgit2/src/buffer.h +153 -2
  126. data/vendor/libgit2/src/cache.c +3 -24
  127. data/vendor/libgit2/src/cache.h +7 -7
  128. data/vendor/libgit2/src/cc-compat.h +10 -2
  129. data/vendor/libgit2/src/checkout.c +97 -98
  130. data/vendor/libgit2/src/cherrypick.c +8 -2
  131. data/vendor/libgit2/src/clone.c +104 -29
  132. data/vendor/libgit2/src/commit.c +41 -28
  133. data/vendor/libgit2/src/commit_graph.c +1209 -0
  134. data/vendor/libgit2/src/commit_graph.h +162 -0
  135. data/vendor/libgit2/src/commit_list.c +46 -0
  136. data/vendor/libgit2/src/commit_list.h +2 -0
  137. data/vendor/libgit2/src/common.h +26 -2
  138. data/vendor/libgit2/src/config.c +40 -22
  139. data/vendor/libgit2/src/config_cache.c +9 -4
  140. data/vendor/libgit2/src/config_entries.c +35 -27
  141. data/vendor/libgit2/src/config_file.c +25 -8
  142. data/vendor/libgit2/src/config_parse.c +5 -7
  143. data/vendor/libgit2/src/config_snapshot.c +2 -1
  144. data/vendor/libgit2/src/crlf.c +16 -6
  145. data/vendor/libgit2/src/date.c +4 -3
  146. data/vendor/libgit2/src/delta.c +1 -1
  147. data/vendor/libgit2/src/describe.c +11 -4
  148. data/vendor/libgit2/src/diff.c +23 -19
  149. data/vendor/libgit2/src/diff_driver.c +21 -17
  150. data/vendor/libgit2/src/diff_file.c +5 -7
  151. data/vendor/libgit2/src/diff_generate.c +56 -28
  152. data/vendor/libgit2/src/diff_parse.c +2 -3
  153. data/vendor/libgit2/src/diff_print.c +81 -65
  154. data/vendor/libgit2/src/diff_stats.c +19 -16
  155. data/vendor/libgit2/src/diff_tform.c +13 -13
  156. data/vendor/libgit2/src/diff_xdiff.c +4 -2
  157. data/vendor/libgit2/src/diff_xdiff.h +1 -1
  158. data/vendor/libgit2/src/errors.c +26 -19
  159. data/vendor/libgit2/src/features.h.in +5 -1
  160. data/vendor/libgit2/src/fetch.c +7 -2
  161. data/vendor/libgit2/src/fetchhead.c +8 -4
  162. data/vendor/libgit2/src/filebuf.c +9 -7
  163. data/vendor/libgit2/src/filter.c +209 -113
  164. data/vendor/libgit2/src/filter.h +24 -5
  165. data/vendor/libgit2/src/futils.c +8 -8
  166. data/vendor/libgit2/src/futils.h +4 -4
  167. data/vendor/libgit2/src/graph.c +64 -9
  168. data/vendor/libgit2/src/hash/sha1/collisiondetect.c +3 -3
  169. data/vendor/libgit2/src/hash/sha1/common_crypto.c +3 -3
  170. data/vendor/libgit2/src/hash/sha1/generic.h +1 -1
  171. data/vendor/libgit2/src/hash/sha1/mbedtls.c +12 -12
  172. data/vendor/libgit2/src/hash/sha1/openssl.c +3 -3
  173. data/vendor/libgit2/src/hash/sha1/sha1dc/sha1.c +0 -2
  174. data/vendor/libgit2/src/hash/sha1/win32.c +15 -11
  175. data/vendor/libgit2/src/hash.c +16 -13
  176. data/vendor/libgit2/src/hash.h +1 -1
  177. data/vendor/libgit2/src/hashsig.c +23 -10
  178. data/vendor/libgit2/src/ident.c +13 -3
  179. data/vendor/libgit2/src/idxmap.c +0 -22
  180. data/vendor/libgit2/src/ignore.c +35 -19
  181. data/vendor/libgit2/src/index.c +126 -84
  182. data/vendor/libgit2/src/index.h +1 -1
  183. data/vendor/libgit2/src/indexer.c +60 -36
  184. data/vendor/libgit2/src/integer.h +79 -2
  185. data/vendor/libgit2/src/iterator.c +40 -28
  186. data/vendor/libgit2/src/iterator.h +1 -1
  187. data/vendor/libgit2/src/khash.h +2 -11
  188. data/vendor/libgit2/src/{settings.c → libgit2.c} +125 -49
  189. data/vendor/libgit2/src/libgit2.h +15 -0
  190. data/vendor/libgit2/src/mailmap.c +23 -10
  191. data/vendor/libgit2/src/map.h +3 -3
  192. data/vendor/libgit2/src/merge.c +108 -46
  193. data/vendor/libgit2/src/merge.h +2 -1
  194. data/vendor/libgit2/src/merge_driver.c +19 -13
  195. data/vendor/libgit2/src/merge_file.c +15 -9
  196. data/vendor/libgit2/src/message.c +3 -1
  197. data/vendor/libgit2/src/midx.c +879 -0
  198. data/vendor/libgit2/src/midx.h +110 -0
  199. data/vendor/libgit2/src/mwindow.c +214 -95
  200. data/vendor/libgit2/src/mwindow.h +3 -3
  201. data/vendor/libgit2/src/net.c +133 -4
  202. data/vendor/libgit2/src/net.h +16 -2
  203. data/vendor/libgit2/src/netops.c +6 -4
  204. data/vendor/libgit2/src/netops.h +2 -2
  205. data/vendor/libgit2/src/notes.c +10 -10
  206. data/vendor/libgit2/src/object.c +24 -15
  207. data/vendor/libgit2/src/odb.c +298 -57
  208. data/vendor/libgit2/src/odb.h +16 -2
  209. data/vendor/libgit2/src/odb_loose.c +31 -21
  210. data/vendor/libgit2/src/odb_mempack.c +3 -1
  211. data/vendor/libgit2/src/odb_pack.c +391 -114
  212. data/vendor/libgit2/src/oid.c +7 -4
  213. data/vendor/libgit2/src/pack-objects.c +83 -69
  214. data/vendor/libgit2/src/pack.c +383 -150
  215. data/vendor/libgit2/src/pack.h +44 -9
  216. data/vendor/libgit2/src/patch.c +14 -7
  217. data/vendor/libgit2/src/patch_generate.c +3 -5
  218. data/vendor/libgit2/src/patch_parse.c +6 -3
  219. data/vendor/libgit2/src/path.c +102 -57
  220. data/vendor/libgit2/src/path.h +79 -6
  221. data/vendor/libgit2/src/pathspec.c +12 -11
  222. data/vendor/libgit2/src/pool.c +34 -22
  223. data/vendor/libgit2/src/pool.h +9 -1
  224. data/vendor/libgit2/src/posix.c +43 -12
  225. data/vendor/libgit2/src/posix.h +9 -0
  226. data/vendor/libgit2/src/proxy.c +2 -0
  227. data/vendor/libgit2/src/push.c +2 -0
  228. data/vendor/libgit2/src/reader.c +10 -6
  229. data/vendor/libgit2/src/rebase.c +95 -49
  230. data/vendor/libgit2/src/refdb.c +165 -13
  231. data/vendor/libgit2/src/refdb.h +69 -0
  232. data/vendor/libgit2/src/refdb_fs.c +144 -152
  233. data/vendor/libgit2/src/reflog.c +21 -20
  234. data/vendor/libgit2/src/refs.c +151 -231
  235. data/vendor/libgit2/src/refs.h +2 -20
  236. data/vendor/libgit2/src/refspec.c +80 -44
  237. data/vendor/libgit2/src/regexp.c +2 -2
  238. data/vendor/libgit2/src/remote.c +312 -121
  239. data/vendor/libgit2/src/remote.h +2 -1
  240. data/vendor/libgit2/src/repository.c +351 -189
  241. data/vendor/libgit2/src/repository.h +23 -29
  242. data/vendor/libgit2/src/reset.c +7 -6
  243. data/vendor/libgit2/src/revert.c +8 -2
  244. data/vendor/libgit2/src/revparse.c +19 -13
  245. data/vendor/libgit2/src/revwalk.c +35 -20
  246. data/vendor/libgit2/src/runtime.c +162 -0
  247. data/vendor/libgit2/src/runtime.h +62 -0
  248. data/vendor/libgit2/src/{refdb_fs.h → settings.h} +3 -11
  249. data/vendor/libgit2/src/signature.c +6 -5
  250. data/vendor/libgit2/src/sortedcache.c +2 -3
  251. data/vendor/libgit2/src/sortedcache.h +10 -8
  252. data/vendor/libgit2/src/stash.c +7 -3
  253. data/vendor/libgit2/src/status.c +9 -4
  254. data/vendor/libgit2/src/strarray.c +64 -0
  255. data/vendor/libgit2/src/streams/mbedtls.c +14 -17
  256. data/vendor/libgit2/src/streams/mbedtls.h +1 -1
  257. data/vendor/libgit2/src/streams/openssl.c +113 -207
  258. data/vendor/libgit2/src/streams/openssl.h +9 -1
  259. data/vendor/libgit2/src/streams/openssl_dynamic.c +309 -0
  260. data/vendor/libgit2/src/streams/openssl_dynamic.h +348 -0
  261. data/vendor/libgit2/src/streams/openssl_legacy.c +203 -0
  262. data/vendor/libgit2/src/streams/openssl_legacy.h +63 -0
  263. data/vendor/libgit2/src/streams/registry.c +10 -9
  264. data/vendor/libgit2/src/streams/socket.c +6 -2
  265. data/vendor/libgit2/src/streams/stransport.c +6 -3
  266. data/vendor/libgit2/src/streams/tls.c +5 -3
  267. data/vendor/libgit2/src/submodule.c +134 -66
  268. data/vendor/libgit2/src/submodule.h +9 -9
  269. data/vendor/libgit2/src/sysdir.c +8 -26
  270. data/vendor/libgit2/src/sysdir.h +0 -11
  271. data/vendor/libgit2/src/tag.c +49 -11
  272. data/vendor/libgit2/src/thread.c +140 -0
  273. data/vendor/libgit2/src/thread.h +479 -0
  274. data/vendor/libgit2/src/threadstate.c +83 -0
  275. data/vendor/libgit2/src/threadstate.h +24 -0
  276. data/vendor/libgit2/src/trace.c +2 -2
  277. data/vendor/libgit2/src/trace.h +17 -13
  278. data/vendor/libgit2/src/transaction.c +21 -9
  279. data/vendor/libgit2/src/transport.c +3 -3
  280. data/vendor/libgit2/src/transports/auth.c +1 -1
  281. data/vendor/libgit2/src/transports/auth_negotiate.c +11 -4
  282. data/vendor/libgit2/src/transports/auth_ntlm.c +10 -6
  283. data/vendor/libgit2/src/transports/credential.c +17 -7
  284. data/vendor/libgit2/src/transports/credential_helpers.c +2 -0
  285. data/vendor/libgit2/src/transports/git.c +1 -3
  286. data/vendor/libgit2/src/transports/http.c +19 -17
  287. data/vendor/libgit2/src/transports/http.h +1 -0
  288. data/vendor/libgit2/src/transports/httpclient.c +84 -42
  289. data/vendor/libgit2/src/transports/httpclient.h +1 -1
  290. data/vendor/libgit2/src/transports/local.c +5 -5
  291. data/vendor/libgit2/src/transports/smart.c +14 -9
  292. data/vendor/libgit2/src/transports/smart.h +1 -1
  293. data/vendor/libgit2/src/transports/smart_protocol.c +11 -5
  294. data/vendor/libgit2/src/transports/ssh.c +51 -17
  295. data/vendor/libgit2/src/transports/winhttp.c +156 -88
  296. data/vendor/libgit2/src/tree.c +100 -77
  297. data/vendor/libgit2/src/tree.h +1 -0
  298. data/vendor/libgit2/src/tsort.c +0 -2
  299. data/vendor/libgit2/src/unix/map.c +3 -1
  300. data/vendor/libgit2/src/unix/posix.h +16 -1
  301. data/vendor/libgit2/src/unix/pthread.h +2 -1
  302. data/vendor/libgit2/src/utf8.c +150 -0
  303. data/vendor/libgit2/src/utf8.h +52 -0
  304. data/vendor/libgit2/src/util.c +74 -183
  305. data/vendor/libgit2/src/util.h +33 -39
  306. data/vendor/libgit2/src/vector.c +23 -19
  307. data/vendor/libgit2/src/vector.h +4 -2
  308. data/vendor/libgit2/src/win32/findfile.c +4 -2
  309. data/vendor/libgit2/src/win32/git2.rc +18 -3
  310. data/vendor/libgit2/src/win32/map.c +1 -1
  311. data/vendor/libgit2/src/win32/msvc-compat.h +9 -1
  312. data/vendor/libgit2/src/win32/path_w32.c +23 -25
  313. data/vendor/libgit2/src/win32/path_w32.h +0 -1
  314. data/vendor/libgit2/src/win32/posix_w32.c +77 -1
  315. data/vendor/libgit2/src/win32/precompiled.h +0 -1
  316. data/vendor/libgit2/src/win32/reparse.h +4 -4
  317. data/vendor/libgit2/src/win32/thread.c +24 -15
  318. data/vendor/libgit2/src/win32/thread.h +1 -1
  319. data/vendor/libgit2/src/win32/w32_buffer.c +3 -3
  320. data/vendor/libgit2/src/win32/w32_common.h +18 -9
  321. data/vendor/libgit2/src/win32/{w32_crtdbg_stacktrace.c → w32_leakcheck.c} +269 -33
  322. data/vendor/libgit2/src/win32/w32_leakcheck.h +222 -0
  323. data/vendor/libgit2/src/win32/w32_util.h +6 -6
  324. data/vendor/libgit2/src/worktree.c +37 -15
  325. data/vendor/libgit2/src/zstream.c +1 -1
  326. metadata +56 -38
  327. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.c.in +0 -29
  328. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.cmake +0 -96
  329. data/vendor/libgit2/src/allocators/win32_crtdbg.c +0 -118
  330. data/vendor/libgit2/src/buf_text.c +0 -316
  331. data/vendor/libgit2/src/buf_text.h +0 -122
  332. data/vendor/libgit2/src/global.c +0 -361
  333. data/vendor/libgit2/src/global.h +0 -41
  334. data/vendor/libgit2/src/thread-utils.c +0 -58
  335. data/vendor/libgit2/src/thread-utils.h +0 -246
  336. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +0 -127
  337. data/vendor/libgit2/src/win32/w32_stack.c +0 -188
  338. data/vendor/libgit2/src/win32/w32_stack.h +0 -140
@@ -9,7 +9,7 @@
9
9
 
10
10
  #include "git2/oid.h"
11
11
  #include "repository.h"
12
- #include "global.h"
12
+ #include "threadstate.h"
13
13
  #include <string.h>
14
14
  #include <limits.h>
15
15
 
@@ -26,7 +26,8 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
26
26
  size_t p;
27
27
  int v;
28
28
 
29
- assert(out && str);
29
+ GIT_ASSERT_ARG(out);
30
+ GIT_ASSERT_ARG(str);
30
31
 
31
32
  if (!length)
32
33
  return oid_error_invalid("too short");
@@ -107,7 +108,7 @@ int git_oid_pathfmt(char *str, const git_oid *oid)
107
108
 
108
109
  char *git_oid_tostr_s(const git_oid *oid)
109
110
  {
110
- char *str = GIT_GLOBAL->oid_fmt;
111
+ char *str = GIT_THREADSTATE->oid_fmt;
111
112
  git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
112
113
  return str;
113
114
  }
@@ -253,10 +254,12 @@ int git_oid_is_zero(const git_oid *oid_a)
253
254
  return 1;
254
255
  }
255
256
 
257
+ #ifndef GIT_DEPRECATE_HARD
256
258
  int git_oid_iszero(const git_oid *oid_a)
257
259
  {
258
260
  return git_oid_is_zero(oid_a);
259
261
  }
262
+ #endif
260
263
 
261
264
  typedef short node_index;
262
265
 
@@ -314,7 +317,7 @@ git_oid_shorten *git_oid_shorten_new(size_t min_length)
314
317
  {
315
318
  git_oid_shorten *os;
316
319
 
317
- assert((size_t)((int)min_length) == min_length);
320
+ GIT_ASSERT_ARG_WITH_RETVAL((size_t)((int)min_length) == min_length, NULL);
318
321
 
319
322
  os = git__calloc(1, sizeof(git_oid_shorten));
320
323
  if (os == NULL)
@@ -12,7 +12,7 @@
12
12
  #include "iterator.h"
13
13
  #include "netops.h"
14
14
  #include "pack.h"
15
- #include "thread-utils.h"
15
+ #include "thread.h"
16
16
  #include "tree.h"
17
17
  #include "util.h"
18
18
  #include "revwalk.h"
@@ -48,18 +48,10 @@ struct walk_object {
48
48
  };
49
49
 
50
50
  #ifdef GIT_THREADS
51
-
52
- #define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) do { \
53
- int result = git_mutex_##op(&(pb)->mtx); \
54
- assert(!result); \
55
- GIT_UNUSED(result); \
56
- } while (0)
57
-
51
+ # define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) git_mutex_##op(&(pb)->mtx)
58
52
  #else
59
-
60
- #define GIT_PACKBUILDER__MUTEX_OP(pb,mtx,op) GIT_UNUSED(pb)
61
-
62
- #endif /* GIT_THREADS */
53
+ # define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) git__noop()
54
+ #endif
63
55
 
64
56
  #define git_packbuilder__cache_lock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, cache_mutex, lock)
65
57
  #define git_packbuilder__cache_unlock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, cache_mutex, unlock)
@@ -141,14 +133,11 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo)
141
133
  pb = git__calloc(1, sizeof(*pb));
142
134
  GIT_ERROR_CHECK_ALLOC(pb);
143
135
 
144
- if (git_oidmap_new(&pb->object_ix) < 0)
145
- goto on_error;
146
-
147
- if (git_oidmap_new(&pb->walk_objects) < 0)
136
+ if (git_oidmap_new(&pb->object_ix) < 0 ||
137
+ git_oidmap_new(&pb->walk_objects) < 0 ||
138
+ git_pool_init(&pb->object_pool, sizeof(struct walk_object)) < 0)
148
139
  goto on_error;
149
140
 
150
- git_pool_init(&pb->object_pool, sizeof(struct walk_object));
151
-
152
141
  pb->repo = repo;
153
142
  pb->nr_threads = 1; /* do not spawn any thread by default */
154
143
 
@@ -180,13 +169,13 @@ on_error:
180
169
 
181
170
  unsigned int git_packbuilder_set_threads(git_packbuilder *pb, unsigned int n)
182
171
  {
183
- assert(pb);
172
+ GIT_ASSERT_ARG(pb);
184
173
 
185
174
  #ifdef GIT_THREADS
186
175
  pb->nr_threads = n;
187
176
  #else
188
177
  GIT_UNUSED(n);
189
- assert(1 == pb->nr_threads);
178
+ GIT_ASSERT(pb->nr_threads == 1);
190
179
  #endif
191
180
 
192
181
  return pb->nr_threads;
@@ -214,7 +203,8 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
214
203
  size_t newsize;
215
204
  int ret;
216
205
 
217
- assert(pb && oid);
206
+ GIT_ASSERT_ARG(pb);
207
+ GIT_ASSERT_ARG(oid);
218
208
 
219
209
  /* If the object already exists in the hash table, then we don't
220
210
  * have any work to do */
@@ -261,7 +251,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
261
251
  double current_time = git__timer();
262
252
  double elapsed = current_time - pb->last_progress_report_time;
263
253
 
264
- if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
254
+ if (elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
265
255
  pb->last_progress_report_time = current_time;
266
256
 
267
257
  ret = pb->progress_cb(
@@ -350,10 +340,9 @@ static int write_object(
350
340
  }
351
341
 
352
342
  /* Write header */
353
- hdr_len = git_packfile__object_header(hdr, data_len, type);
354
-
355
- if ((error = write_cb(hdr, hdr_len, cb_data)) < 0 ||
356
- (error = git_hash_update(&pb->ctx, hdr, hdr_len)) < 0)
343
+ if ((error = git_packfile__object_header(&hdr_len, hdr, data_len, type)) < 0 ||
344
+ (error = write_cb(hdr, hdr_len, cb_data)) < 0 ||
345
+ (error = git_hash_update(&pb->ctx, hdr, hdr_len)) < 0)
357
346
  goto done;
358
347
 
359
348
  if (type == GIT_OBJECT_REF_DELTA) {
@@ -528,13 +517,18 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data)
528
517
  return 0;
529
518
  }
530
519
 
531
- static git_pobject **compute_write_order(git_packbuilder *pb)
520
+ static int compute_write_order(git_pobject ***out, git_packbuilder *pb)
532
521
  {
533
522
  size_t i, wo_end, last_untagged;
534
523
  git_pobject **wo;
535
524
 
525
+ *out = NULL;
526
+
527
+ if (!pb->nr_objects)
528
+ return 0;
529
+
536
530
  if ((wo = git__mallocarray(pb->nr_objects, sizeof(*wo))) == NULL)
537
- return NULL;
531
+ return -1;
538
532
 
539
533
  for (i = 0; i < pb->nr_objects; i++) {
540
534
  git_pobject *po = pb->object_list + i;
@@ -563,7 +557,7 @@ static git_pobject **compute_write_order(git_packbuilder *pb)
563
557
  */
564
558
  if (git_tag_foreach(pb->repo, &cb_tag_foreach, pb) < 0) {
565
559
  git__free(wo);
566
- return NULL;
560
+ return -1;
567
561
  }
568
562
 
569
563
  /*
@@ -620,10 +614,11 @@ static git_pobject **compute_write_order(git_packbuilder *pb)
620
614
  if (wo_end != pb->nr_objects) {
621
615
  git__free(wo);
622
616
  git_error_set(GIT_ERROR_INVALID, "invalid write order");
623
- return NULL;
617
+ return -1;
624
618
  }
625
619
 
626
- return wo;
620
+ *out = wo;
621
+ return 0;
627
622
  }
628
623
 
629
624
  static int write_pack(git_packbuilder *pb,
@@ -636,15 +631,15 @@ static int write_pack(git_packbuilder *pb,
636
631
  struct git_pack_header ph;
637
632
  git_oid entry_oid;
638
633
  size_t i = 0;
639
- int error = 0;
634
+ int error;
640
635
 
641
- write_order = compute_write_order(pb);
642
- if (write_order == NULL)
643
- return -1;
636
+ if ((error = compute_write_order(&write_order, pb)) < 0)
637
+ return error;
644
638
 
645
639
  if (!git__is_uint32(pb->nr_objects)) {
646
640
  git_error_set(GIT_ERROR_INVALID, "too many objects");
647
- return -1;
641
+ error = -1;
642
+ goto done;
648
643
  }
649
644
 
650
645
  /* Write pack header */
@@ -855,10 +850,11 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
855
850
  }
856
851
  }
857
852
 
858
- git_packbuilder__cache_lock(pb);
853
+ GIT_ASSERT(git_packbuilder__cache_lock(pb) == 0);
854
+
859
855
  if (trg_object->delta_data) {
860
856
  git__free(trg_object->delta_data);
861
- assert(pb->delta_cache_size >= trg_object->delta_size);
857
+ GIT_ASSERT(pb->delta_cache_size >= trg_object->delta_size);
862
858
  pb->delta_cache_size -= trg_object->delta_size;
863
859
  trg_object->delta_data = NULL;
864
860
  }
@@ -866,7 +862,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
866
862
  bool overflow = git__add_sizet_overflow(
867
863
  &pb->delta_cache_size, pb->delta_cache_size, delta_size);
868
864
 
869
- git_packbuilder__cache_unlock(pb);
865
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
870
866
 
871
867
  if (overflow) {
872
868
  git__free(delta_buf);
@@ -877,7 +873,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
877
873
  GIT_ERROR_CHECK_ALLOC(trg_object->delta_data);
878
874
  } else {
879
875
  /* create delta when writing the pack */
880
- git_packbuilder__cache_unlock(pb);
876
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
881
877
  git__free(delta_buf);
882
878
  }
883
879
 
@@ -932,7 +928,7 @@ static int report_delta_progress(
932
928
  double current_time = git__timer();
933
929
  double elapsed = current_time - pb->last_progress_report_time;
934
930
 
935
- if (force || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
931
+ if (force || elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
936
932
  pb->last_progress_report_time = current_time;
937
933
 
938
934
  ret = pb->progress_cb(
@@ -965,9 +961,9 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
965
961
  struct unpacked *n = array + idx;
966
962
  size_t max_depth, j, best_base = SIZE_MAX;
967
963
 
968
- git_packbuilder__progress_lock(pb);
964
+ GIT_ASSERT(git_packbuilder__progress_lock(pb) == 0);
969
965
  if (!*list_size) {
970
- git_packbuilder__progress_unlock(pb);
966
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
971
967
  break;
972
968
  }
973
969
 
@@ -976,7 +972,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
976
972
 
977
973
  po = *list++;
978
974
  (*list_size)--;
979
- git_packbuilder__progress_unlock(pb);
975
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
980
976
 
981
977
  mem_usage -= free_unpacked(n);
982
978
  n->object = po;
@@ -1051,10 +1047,10 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
1051
1047
  po->z_delta_size = zbuf.size;
1052
1048
  git_buf_clear(&zbuf);
1053
1049
 
1054
- git_packbuilder__cache_lock(pb);
1050
+ GIT_ASSERT(git_packbuilder__cache_lock(pb) == 0);
1055
1051
  pb->delta_cache_size -= po->delta_size;
1056
1052
  pb->delta_cache_size += po->z_delta_size;
1057
- git_packbuilder__cache_unlock(pb);
1053
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
1058
1054
  }
1059
1055
 
1060
1056
  /*
@@ -1132,10 +1128,10 @@ static void *threaded_find_deltas(void *arg)
1132
1128
  ; /* TODO */
1133
1129
  }
1134
1130
 
1135
- git_packbuilder__progress_lock(me->pb);
1131
+ GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_lock(me->pb) == 0, NULL);
1136
1132
  me->working = 0;
1137
1133
  git_cond_signal(&me->pb->progress_cond);
1138
- git_packbuilder__progress_unlock(me->pb);
1134
+ GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_unlock(me->pb) == 0, NULL);
1139
1135
 
1140
1136
  if (git_mutex_lock(&me->mutex)) {
1141
1137
  git_error_set(GIT_ERROR_THREAD, "unable to lock packfile condition mutex");
@@ -1168,7 +1164,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1168
1164
  int ret, active_threads = 0;
1169
1165
 
1170
1166
  if (!pb->nr_threads)
1171
- pb->nr_threads = git_online_cpus();
1167
+ pb->nr_threads = git__online_cpus();
1172
1168
 
1173
1169
  if (pb->nr_threads <= 1) {
1174
1170
  find_deltas(pb, list, &list_size, window, depth);
@@ -1240,7 +1236,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1240
1236
  * 'working' flag from 1 -> 0. This indicates that it is
1241
1237
  * ready to receive more work using our work-stealing
1242
1238
  * algorithm. */
1243
- git_packbuilder__progress_lock(pb);
1239
+ GIT_ASSERT(git_packbuilder__progress_lock(pb) == 0);
1244
1240
  for (;;) {
1245
1241
  for (i = 0; !target && i < pb->nr_threads; i++)
1246
1242
  if (!p[i].working)
@@ -1283,7 +1279,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1283
1279
  target->list_size = sub_size;
1284
1280
  target->remaining = sub_size;
1285
1281
  target->working = 1;
1286
- git_packbuilder__progress_unlock(pb);
1282
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
1287
1283
 
1288
1284
  if (git_mutex_lock(&target->mutex)) {
1289
1285
  git_error_set(GIT_ERROR_THREAD, "unable to lock packfile condition mutex");
@@ -1366,8 +1362,13 @@ int git_packbuilder_foreach(git_packbuilder *pb, int (*cb)(void *buf, size_t siz
1366
1362
 
1367
1363
  int git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb)
1368
1364
  {
1365
+ int error;
1366
+
1367
+ if ((error = git_buf_sanitize(buf)) < 0)
1368
+ return error;
1369
+
1369
1370
  PREPARE_PACK;
1370
- git_buf_sanitize(buf);
1371
+
1371
1372
  return write_pack(pb, &write_pack_buf, buf);
1372
1373
  }
1373
1374
 
@@ -1384,20 +1385,29 @@ int git_packbuilder_write(
1384
1385
  git_indexer_progress_cb progress_cb,
1385
1386
  void *progress_cb_payload)
1386
1387
  {
1388
+ int error = -1;
1389
+ git_buf object_path = GIT_BUF_INIT;
1387
1390
  git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT;
1388
- git_indexer *indexer;
1391
+ git_indexer *indexer = NULL;
1389
1392
  git_indexer_progress stats;
1390
1393
  struct pack_write_context ctx;
1391
1394
  int t;
1392
1395
 
1393
1396
  PREPARE_PACK;
1394
1397
 
1398
+ if (path == NULL) {
1399
+ if ((error = git_repository_item_path(&object_path, pb->repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0)
1400
+ goto cleanup;
1401
+ if ((error = git_buf_joinpath(&object_path, git_buf_cstr(&object_path), "pack")) < 0)
1402
+ goto cleanup;
1403
+ path = git_buf_cstr(&object_path);
1404
+ }
1405
+
1395
1406
  opts.progress_cb = progress_cb;
1396
1407
  opts.progress_cb_payload = progress_cb_payload;
1397
1408
 
1398
- if (git_indexer_new(
1399
- &indexer, path, mode, pb->odb, &opts) < 0)
1400
- return -1;
1409
+ if ((error = git_indexer_new(&indexer, path, mode, pb->odb, &opts)) < 0)
1410
+ goto cleanup;
1401
1411
 
1402
1412
  if (!git_repository__configmap_lookup(&t, pb->repo, GIT_CONFIGMAP_FSYNCOBJECTFILES) && t)
1403
1413
  git_indexer__set_fsync(indexer, 1);
@@ -1405,16 +1415,18 @@ int git_packbuilder_write(
1405
1415
  ctx.indexer = indexer;
1406
1416
  ctx.stats = &stats;
1407
1417
 
1408
- if (git_packbuilder_foreach(pb, write_cb, &ctx) < 0 ||
1409
- git_indexer_commit(indexer, &stats) < 0) {
1410
- git_indexer_free(indexer);
1411
- return -1;
1412
- }
1418
+ if ((error = git_packbuilder_foreach(pb, write_cb, &ctx)) < 0)
1419
+ goto cleanup;
1420
+
1421
+ if ((error = git_indexer_commit(indexer, &stats)) < 0)
1422
+ goto cleanup;
1413
1423
 
1414
1424
  git_oid_cpy(&pb->pack_oid, git_indexer_hash(indexer));
1415
1425
 
1426
+ cleanup:
1416
1427
  git_indexer_free(indexer);
1417
- return 0;
1428
+ git_buf_dispose(&object_path);
1429
+ return error;
1418
1430
  }
1419
1431
 
1420
1432
  #undef PREPARE_PACK
@@ -1478,7 +1490,8 @@ int git_packbuilder_insert_recur(git_packbuilder *pb, const git_oid *id, const c
1478
1490
  git_object *obj;
1479
1491
  int error;
1480
1492
 
1481
- assert(pb && id);
1493
+ GIT_ASSERT_ARG(pb);
1494
+ GIT_ASSERT_ARG(id);
1482
1495
 
1483
1496
  if ((error = git_object_lookup(&obj, pb->repo, id, GIT_OBJECT_ANY)) < 0)
1484
1497
  return error;
@@ -1634,7 +1647,7 @@ static int mark_edges_uninteresting(git_packbuilder *pb, git_commit_list *commit
1634
1647
  return 0;
1635
1648
  }
1636
1649
 
1637
- int insert_tree(git_packbuilder *pb, git_tree *tree)
1650
+ static int pack_objects_insert_tree(git_packbuilder *pb, git_tree *tree)
1638
1651
  {
1639
1652
  size_t i;
1640
1653
  int error;
@@ -1661,7 +1674,7 @@ int insert_tree(git_packbuilder *pb, git_tree *tree)
1661
1674
  if ((error = git_tree_lookup(&subtree, pb->repo, entry_id)) < 0)
1662
1675
  return error;
1663
1676
 
1664
- error = insert_tree(pb, subtree);
1677
+ error = pack_objects_insert_tree(pb, subtree);
1665
1678
  git_tree_free(subtree);
1666
1679
 
1667
1680
  if (error < 0)
@@ -1687,7 +1700,7 @@ int insert_tree(git_packbuilder *pb, git_tree *tree)
1687
1700
  return error;
1688
1701
  }
1689
1702
 
1690
- int insert_commit(git_packbuilder *pb, struct walk_object *obj)
1703
+ static int pack_objects_insert_commit(git_packbuilder *pb, struct walk_object *obj)
1691
1704
  {
1692
1705
  int error;
1693
1706
  git_commit *commit = NULL;
@@ -1704,7 +1717,7 @@ int insert_commit(git_packbuilder *pb, struct walk_object *obj)
1704
1717
  if ((error = git_tree_lookup(&tree, pb->repo, git_commit_tree_id(commit))) < 0)
1705
1718
  goto cleanup;
1706
1719
 
1707
- if ((error = insert_tree(pb, tree)) < 0)
1720
+ if ((error = pack_objects_insert_tree(pb, tree)) < 0)
1708
1721
  goto cleanup;
1709
1722
 
1710
1723
  cleanup:
@@ -1719,7 +1732,8 @@ int git_packbuilder_insert_walk(git_packbuilder *pb, git_revwalk *walk)
1719
1732
  git_oid id;
1720
1733
  struct walk_object *obj;
1721
1734
 
1722
- assert(pb && walk);
1735
+ GIT_ASSERT_ARG(pb);
1736
+ GIT_ASSERT_ARG(walk);
1723
1737
 
1724
1738
  if ((error = mark_edges_uninteresting(pb, walk->user_input)) < 0)
1725
1739
  return error;
@@ -1739,7 +1753,7 @@ int git_packbuilder_insert_walk(git_packbuilder *pb, git_revwalk *walk)
1739
1753
  if (obj->seen || obj->uninteresting)
1740
1754
  continue;
1741
1755
 
1742
- if ((error = insert_commit(pb, obj)) < 0)
1756
+ if ((error = pack_objects_insert_commit(pb, obj)) < 0)
1743
1757
  return error;
1744
1758
  }
1745
1759
 
@@ -12,12 +12,13 @@
12
12
  #include "mwindow.h"
13
13
  #include "odb.h"
14
14
  #include "oid.h"
15
+ #include "oidarray.h"
15
16
 
16
17
  /* Option to bypass checking existence of '.keep' files */
17
18
  bool git_disable_pack_keep_file_checks = false;
18
19
 
19
- static int packfile_open(struct git_pack_file *p);
20
- static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n);
20
+ static int packfile_open_locked(struct git_pack_file *p);
21
+ static off64_t nth_packed_object_offset_locked(struct git_pack_file *p, uint32_t n);
21
22
  static int packfile_unpack_compressed(
22
23
  git_rawobj *obj,
23
24
  struct git_pack_file *p,
@@ -56,7 +57,7 @@ static git_pack_cache_entry *new_cache_object(git_rawobj *source)
56
57
  if (!e)
57
58
  return NULL;
58
59
 
59
- git_atomic_inc(&e->refcount);
60
+ git_atomic32_inc(&e->refcount);
60
61
  memcpy(&e->raw, source, sizeof(git_rawobj));
61
62
 
62
63
  return e;
@@ -67,7 +68,6 @@ static void free_cache_object(void *o)
67
68
  git_pack_cache_entry *e = (git_pack_cache_entry *)o;
68
69
 
69
70
  if (e != NULL) {
70
- assert(e->refcount.val == 0);
71
71
  git__free(e->raw.data);
72
72
  git__free(e);
73
73
  }
@@ -114,7 +114,7 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, off64_t offset)
114
114
  return NULL;
115
115
 
116
116
  if ((entry = git_offmap_get(cache->entries, offset)) != NULL) {
117
- git_atomic_inc(&entry->refcount);
117
+ git_atomic32_inc(&entry->refcount);
118
118
  entry->last_usage = cache->use_ctr++;
119
119
  }
120
120
  git_mutex_unlock(&cache->lock);
@@ -129,7 +129,7 @@ static void free_lowest_entry(git_pack_cache *cache)
129
129
  git_pack_cache_entry *entry;
130
130
 
131
131
  git_offmap_foreach(cache->entries, offset, entry, {
132
- if (entry && entry->refcount.val == 0) {
132
+ if (entry && git_atomic32_get(&entry->refcount) == 0) {
133
133
  cache->memory_used -= entry->raw.len;
134
134
  git_offmap_delete(cache->entries, offset);
135
135
  free_cache_object(entry);
@@ -196,7 +196,8 @@ static void pack_index_free(struct git_pack_file *p)
196
196
  }
197
197
  }
198
198
 
199
- static int pack_index_check(const char *path, struct git_pack_file *p)
199
+ /* Run with the packfile lock held */
200
+ static int pack_index_check_locked(const char *path, struct git_pack_file *p)
200
201
  {
201
202
  struct git_pack_idx_header *hdr;
202
203
  uint32_t version, nr, i, *index;
@@ -302,40 +303,36 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
302
303
  return 0;
303
304
  }
304
305
 
305
- static int pack_index_open(struct git_pack_file *p)
306
+ /* Run with the packfile lock held */
307
+ static int pack_index_open_locked(struct git_pack_file *p)
306
308
  {
307
309
  int error = 0;
308
310
  size_t name_len;
309
- git_buf idx_name;
311
+ git_buf idx_name = GIT_BUF_INIT;
310
312
 
311
313
  if (p->index_version > -1)
312
- return 0;
314
+ goto cleanup;
313
315
 
316
+ /* checked by git_pack_file alloc */
314
317
  name_len = strlen(p->pack_name);
315
- assert(name_len > strlen(".pack")); /* checked by git_pack_file alloc */
318
+ GIT_ASSERT(name_len > strlen(".pack"));
316
319
 
317
- if (git_buf_init(&idx_name, name_len) < 0)
318
- return -1;
320
+ if ((error = git_buf_init(&idx_name, name_len)) < 0)
321
+ goto cleanup;
319
322
 
320
323
  git_buf_put(&idx_name, p->pack_name, name_len - strlen(".pack"));
321
324
  git_buf_puts(&idx_name, ".idx");
322
325
  if (git_buf_oom(&idx_name)) {
323
- git_buf_dispose(&idx_name);
324
- return -1;
325
- }
326
-
327
- if ((error = git_mutex_lock(&p->lock)) < 0) {
328
- git_buf_dispose(&idx_name);
329
- return error;
326
+ error = -1;
327
+ goto cleanup;
330
328
  }
331
329
 
332
330
  if (p->index_version == -1)
333
- error = pack_index_check(idx_name.ptr, p);
331
+ error = pack_index_check_locked(idx_name.ptr, p);
334
332
 
333
+ cleanup:
335
334
  git_buf_dispose(&idx_name);
336
335
 
337
- git_mutex_unlock(&p->lock);
338
-
339
336
  return error;
340
337
  }
341
338
 
@@ -345,8 +342,20 @@ static unsigned char *pack_window_open(
345
342
  off64_t offset,
346
343
  unsigned int *left)
347
344
  {
348
- if (p->mwf.fd == -1 && packfile_open(p) < 0)
345
+ unsigned char *pack_data = NULL;
346
+
347
+ if (git_mutex_lock(&p->lock) < 0) {
348
+ git_error_set(GIT_ERROR_THREAD, "unable to lock packfile");
349
349
  return NULL;
350
+ }
351
+ if (git_mutex_lock(&p->mwf.lock) < 0) {
352
+ git_mutex_unlock(&p->lock);
353
+ git_error_set(GIT_ERROR_THREAD, "unable to lock packfile");
354
+ return NULL;
355
+ }
356
+
357
+ if (p->mwf.fd == -1 && packfile_open_locked(p) < 0)
358
+ goto cleanup;
350
359
 
351
360
  /* Since packfiles end in a hash of their content and it's
352
361
  * pointless to ask for an offset into the middle of that
@@ -357,11 +366,16 @@ static unsigned char *pack_window_open(
357
366
  * around.
358
367
  */
359
368
  if (offset > (p->mwf.size - 20))
360
- return NULL;
369
+ goto cleanup;
361
370
  if (offset < 0)
362
- return NULL;
371
+ goto cleanup;
363
372
 
364
- return git_mwindow_open(&p->mwf, w_cursor, offset, 20, left);
373
+ pack_data = git_mwindow_open(&p->mwf, w_cursor, offset, 20, left);
374
+
375
+ cleanup:
376
+ git_mutex_unlock(&p->mwf.lock);
377
+ git_mutex_unlock(&p->lock);
378
+ return pack_data;
365
379
  }
366
380
 
367
381
  /*
@@ -372,12 +386,12 @@ static unsigned char *pack_window_open(
372
386
  * - each byte afterwards: low seven bits are size continuation,
373
387
  * with the high bit being "size continues"
374
388
  */
375
- size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_object_t type)
389
+ int git_packfile__object_header(size_t *out, unsigned char *hdr, size_t size, git_object_t type)
376
390
  {
377
391
  unsigned char *hdr_base;
378
392
  unsigned char c;
379
393
 
380
- assert(type >= GIT_OBJECT_COMMIT && type <= GIT_OBJECT_REF_DELTA);
394
+ GIT_ASSERT_ARG(type >= GIT_OBJECT_COMMIT && type <= GIT_OBJECT_REF_DELTA);
381
395
 
382
396
  /* TODO: add support for chunked objects; see git.git 6c0d19b1 */
383
397
 
@@ -392,7 +406,8 @@ size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_object_t
392
406
  }
393
407
  *hdr++ = c;
394
408
 
395
- return (hdr - hdr_base);
409
+ *out = (hdr - hdr_base);
410
+ return 0;
396
411
  }
397
412
 
398
413
 
@@ -436,14 +451,27 @@ static int packfile_unpack_header1(
436
451
  int git_packfile_unpack_header(
437
452
  size_t *size_p,
438
453
  git_object_t *type_p,
439
- git_mwindow_file *mwf,
454
+ struct git_pack_file *p,
440
455
  git_mwindow **w_curs,
441
456
  off64_t *curpos)
442
457
  {
443
458
  unsigned char *base;
444
459
  unsigned int left;
445
460
  unsigned long used;
446
- int ret;
461
+ int error;
462
+
463
+ if ((error = git_mutex_lock(&p->lock)) < 0)
464
+ return error;
465
+ if ((error = git_mutex_lock(&p->mwf.lock)) < 0) {
466
+ git_mutex_unlock(&p->lock);
467
+ return error;
468
+ }
469
+
470
+ if (p->mwf.fd == -1 && (error = packfile_open_locked(p)) < 0) {
471
+ git_mutex_unlock(&p->lock);
472
+ git_mutex_unlock(&p->mwf.lock);
473
+ return error;
474
+ }
447
475
 
448
476
  /* pack_window_open() assures us we have [base, base + 20) available
449
477
  * as a range that we can look at at. (Its actually the hash
@@ -451,16 +479,17 @@ int git_packfile_unpack_header(
451
479
  * the maximum deflated object size is 2^137, which is just
452
480
  * insane, so we know won't exceed what we have been given.
453
481
  */
454
- /* base = pack_window_open(p, w_curs, *curpos, &left); */
455
- base = git_mwindow_open(mwf, w_curs, *curpos, 20, &left);
482
+ base = git_mwindow_open(&p->mwf, w_curs, *curpos, 20, &left);
483
+ git_mutex_unlock(&p->lock);
484
+ git_mutex_unlock(&p->mwf.lock);
456
485
  if (base == NULL)
457
486
  return GIT_EBUFS;
458
487
 
459
- ret = packfile_unpack_header1(&used, size_p, type_p, base, left);
488
+ error = packfile_unpack_header1(&used, size_p, type_p, base, left);
460
489
  git_mwindow_close(w_curs);
461
- if (ret == GIT_EBUFS)
462
- return ret;
463
- else if (ret < 0)
490
+ if (error == GIT_EBUFS)
491
+ return error;
492
+ else if (error < 0)
464
493
  return packfile_error("header length is zero");
465
494
 
466
495
  *curpos += used;
@@ -480,7 +509,27 @@ int git_packfile_resolve_header(
480
509
  off64_t base_offset;
481
510
  int error;
482
511
 
483
- error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
512
+ error = git_mutex_lock(&p->lock);
513
+ if (error < 0) {
514
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
515
+ return error;
516
+ }
517
+ error = git_mutex_lock(&p->mwf.lock);
518
+ if (error < 0) {
519
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
520
+ git_mutex_unlock(&p->lock);
521
+ return error;
522
+ }
523
+
524
+ if (p->mwf.fd == -1 && (error = packfile_open_locked(p)) < 0) {
525
+ git_mutex_unlock(&p->mwf.lock);
526
+ git_mutex_unlock(&p->lock);
527
+ return error;
528
+ }
529
+ git_mutex_unlock(&p->mwf.lock);
530
+ git_mutex_unlock(&p->lock);
531
+
532
+ error = git_packfile_unpack_header(&size, &type, p, &w_curs, &curpos);
484
533
  if (error < 0)
485
534
  return error;
486
535
 
@@ -488,8 +537,12 @@ int git_packfile_resolve_header(
488
537
  size_t base_size;
489
538
  git_packfile_stream stream;
490
539
 
491
- base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
540
+ error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, offset);
492
541
  git_mwindow_close(&w_curs);
542
+
543
+ if (error < 0)
544
+ return error;
545
+
493
546
  if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0)
494
547
  return error;
495
548
  error = git_delta_read_header_fromstream(&base_size, size_p, &stream);
@@ -503,13 +556,17 @@ int git_packfile_resolve_header(
503
556
 
504
557
  while (type == GIT_OBJECT_OFS_DELTA || type == GIT_OBJECT_REF_DELTA) {
505
558
  curpos = base_offset;
506
- error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
559
+ error = git_packfile_unpack_header(&size, &type, p, &w_curs, &curpos);
507
560
  if (error < 0)
508
561
  return error;
509
562
  if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
510
563
  break;
511
- base_offset = get_delta_base(p, &w_curs, &curpos, type, base_offset);
564
+
565
+ error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, base_offset);
512
566
  git_mwindow_close(&w_curs);
567
+
568
+ if (error < 0)
569
+ return error;
513
570
  }
514
571
  *type_p = type;
515
572
 
@@ -570,8 +627,7 @@ static int pack_dependency_chain(git_dependency_chain *chain_out,
570
627
 
571
628
  elem->base_key = obj_offset;
572
629
 
573
- error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
574
-
630
+ error = git_packfile_unpack_header(&size, &type, p, &w_curs, &curpos);
575
631
  if (error < 0)
576
632
  goto on_error;
577
633
 
@@ -583,17 +639,11 @@ static int pack_dependency_chain(git_dependency_chain *chain_out,
583
639
  if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
584
640
  break;
585
641
 
586
- base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
642
+ error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, obj_offset);
587
643
  git_mwindow_close(&w_curs);
588
644
 
589
- if (base_offset == 0) {
590
- error = packfile_error("delta offset is zero");
591
- goto on_error;
592
- }
593
- if (base_offset < 0) { /* must actually be an error code */
594
- error = (int)base_offset;
645
+ if (error < 0)
595
646
  goto on_error;
596
- }
597
647
 
598
648
  /* we need to pass the pos *after* the delta-base bit */
599
649
  elem->offset = curpos;
@@ -628,6 +678,25 @@ int git_packfile_unpack(
628
678
  size_t stack_size = 0, elem_pos, alloclen;
629
679
  git_object_t base_type;
630
680
 
681
+ error = git_mutex_lock(&p->lock);
682
+ if (error < 0) {
683
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
684
+ return error;
685
+ }
686
+ error = git_mutex_lock(&p->mwf.lock);
687
+ if (error < 0) {
688
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
689
+ git_mutex_unlock(&p->lock);
690
+ return error;
691
+ }
692
+
693
+ if (p->mwf.fd == -1)
694
+ error = packfile_open_locked(p);
695
+ git_mutex_unlock(&p->mwf.lock);
696
+ git_mutex_unlock(&p->lock);
697
+ if (error < 0)
698
+ return error;
699
+
631
700
  /*
632
701
  * TODO: optionally check the CRC on the packfile
633
702
  */
@@ -690,7 +759,7 @@ int git_packfile_unpack(
690
759
  GIT_ERROR_CHECK_ALLOC(obj->data);
691
760
 
692
761
  memcpy(obj->data, data, obj->len + 1);
693
- git_atomic_dec(&cached->refcount);
762
+ git_atomic32_dec(&cached->refcount);
694
763
  goto cleanup;
695
764
  }
696
765
 
@@ -738,7 +807,7 @@ int git_packfile_unpack(
738
807
  }
739
808
 
740
809
  if (cached) {
741
- git_atomic_dec(&cached->refcount);
810
+ git_atomic32_dec(&cached->refcount);
742
811
  cached = NULL;
743
812
  }
744
813
 
@@ -752,7 +821,7 @@ cleanup:
752
821
  if (error < 0) {
753
822
  git__free(obj->data);
754
823
  if (cached)
755
- git_atomic_dec(&cached->refcount);
824
+ git_atomic32_dec(&cached->refcount);
756
825
  }
757
826
 
758
827
  if (elem)
@@ -839,10 +908,13 @@ static int packfile_unpack_compressed(
839
908
 
840
909
  do {
841
910
  size_t bytes = buffer_len - total;
842
- unsigned int window_len;
911
+ unsigned int window_len, consumed;
843
912
  unsigned char *in;
844
913
 
845
- in = pack_window_open(p, mwindow, *position, &window_len);
914
+ if ((in = pack_window_open(p, mwindow, *position, &window_len)) == NULL) {
915
+ error = -1;
916
+ goto out;
917
+ }
846
918
 
847
919
  if ((error = git_zstream_set_input(&zstream, in, window_len)) < 0 ||
848
920
  (error = git_zstream_get_output_chunk(data + total, &bytes, &zstream)) < 0) {
@@ -852,9 +924,17 @@ static int packfile_unpack_compressed(
852
924
 
853
925
  git_mwindow_close(mwindow);
854
926
 
855
- *position += window_len - zstream.in_len;
927
+ consumed = window_len - (unsigned int)zstream.in_len;
928
+
929
+ if (!bytes && !consumed) {
930
+ git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream");
931
+ error = -1;
932
+ goto out;
933
+ }
934
+
935
+ *position += consumed;
856
936
  total += bytes;
857
- } while (total < size);
937
+ } while (!git_zstream_eos(&zstream));
858
938
 
859
939
  if (total != size || !git_zstream_eos(&zstream)) {
860
940
  git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream");
@@ -878,18 +958,21 @@ out:
878
958
  * curpos is where the data starts, delta_obj_offset is the where the
879
959
  * header starts
880
960
  */
881
- off64_t get_delta_base(
882
- struct git_pack_file *p,
883
- git_mwindow **w_curs,
884
- off64_t *curpos,
885
- git_object_t type,
886
- off64_t delta_obj_offset)
961
+ int get_delta_base(
962
+ off64_t *delta_base_out,
963
+ struct git_pack_file *p,
964
+ git_mwindow **w_curs,
965
+ off64_t *curpos,
966
+ git_object_t type,
967
+ off64_t delta_obj_offset)
887
968
  {
888
969
  unsigned int left = 0;
889
970
  unsigned char *base_info;
890
971
  off64_t base_offset;
891
972
  git_oid unused;
892
973
 
974
+ GIT_ASSERT_ARG(delta_base_out);
975
+
893
976
  base_info = pack_window_open(p, w_curs, *curpos, &left);
894
977
  /* Assumption: the only reason this would fail is because the file is too small */
895
978
  if (base_info == NULL)
@@ -909,12 +992,12 @@ off64_t get_delta_base(
909
992
  return GIT_EBUFS;
910
993
  unsigned_base_offset += 1;
911
994
  if (!unsigned_base_offset || MSB(unsigned_base_offset, 7))
912
- return 0; /* overflow */
995
+ return packfile_error("overflow");
913
996
  c = base_info[used++];
914
997
  unsigned_base_offset = (unsigned_base_offset << 7) + (c & 127);
915
998
  }
916
999
  if (unsigned_base_offset == 0 || (size_t)delta_obj_offset <= unsigned_base_offset)
917
- return 0; /* out of bound */
1000
+ return packfile_error("out of bounds");
918
1001
  base_offset = delta_obj_offset - unsigned_base_offset;
919
1002
  *curpos += used;
920
1003
  } else if (type == GIT_OBJECT_REF_DELTA) {
@@ -925,8 +1008,12 @@ off64_t get_delta_base(
925
1008
 
926
1009
  git_oid_fromraw(&oid, base_info);
927
1010
  if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) {
1011
+ if (entry->offset == 0)
1012
+ return packfile_error("delta offset is zero");
1013
+
928
1014
  *curpos += 20;
929
- return entry->offset;
1015
+ *delta_base_out = entry->offset;
1016
+ return 0;
930
1017
  } else {
931
1018
  /* If we're building an index, don't try to find the pack
932
1019
  * entry; we just haven't seen it yet. We'll make
@@ -941,9 +1028,13 @@ off64_t get_delta_base(
941
1028
  return packfile_error("base entry delta is not in the same pack");
942
1029
  *curpos += 20;
943
1030
  } else
944
- return 0;
1031
+ return packfile_error("unknown object type");
945
1032
 
946
- return base_offset;
1033
+ if (base_offset == 0)
1034
+ return packfile_error("delta offset is zero");
1035
+
1036
+ *delta_base_out = base_offset;
1037
+ return 0;
947
1038
  }
948
1039
 
949
1040
  /***********************************************************
@@ -952,63 +1043,63 @@ off64_t get_delta_base(
952
1043
  *
953
1044
  ***********************************************************/
954
1045
 
955
- void git_packfile_close(struct git_pack_file *p, bool unlink_packfile)
1046
+ void git_packfile_free(struct git_pack_file *p, bool unlink_packfile)
956
1047
  {
1048
+ bool locked = true;
1049
+
1050
+ if (!p)
1051
+ return;
1052
+
1053
+ cache_free(&p->bases);
1054
+
1055
+ if (git_mutex_lock(&p->lock) < 0) {
1056
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile");
1057
+ locked = false;
1058
+ }
957
1059
  if (p->mwf.fd >= 0) {
958
- git_mwindow_free_all_locked(&p->mwf);
1060
+ git_mwindow_free_all(&p->mwf);
959
1061
  p_close(p->mwf.fd);
960
1062
  p->mwf.fd = -1;
961
1063
  }
1064
+ if (locked)
1065
+ git_mutex_unlock(&p->lock);
962
1066
 
963
1067
  if (unlink_packfile)
964
1068
  p_unlink(p->pack_name);
965
- }
966
-
967
- void git_packfile_free(struct git_pack_file *p)
968
- {
969
- if (!p)
970
- return;
971
-
972
- cache_free(&p->bases);
973
-
974
- git_packfile_close(p, false);
975
1069
 
976
1070
  pack_index_free(p);
977
1071
 
978
1072
  git__free(p->bad_object_sha1);
979
1073
 
980
- git_mutex_free(&p->lock);
981
1074
  git_mutex_free(&p->bases.lock);
1075
+ git_mutex_free(&p->mwf.lock);
1076
+ git_mutex_free(&p->lock);
982
1077
  git__free(p);
983
1078
  }
984
1079
 
985
- static int packfile_open(struct git_pack_file *p)
1080
+ /* Run with the packfile and mwf locks held */
1081
+ static int packfile_open_locked(struct git_pack_file *p)
986
1082
  {
987
1083
  struct stat st;
988
1084
  struct git_pack_header hdr;
989
1085
  git_oid sha1;
990
1086
  unsigned char *idx_sha1;
991
1087
 
992
- if (p->index_version == -1 && pack_index_open(p) < 0)
1088
+ if (pack_index_open_locked(p) < 0)
993
1089
  return git_odb__error_notfound("failed to open packfile", NULL, 0);
994
1090
 
995
- /* if mwf opened by another thread, return now */
996
- if (git_mutex_lock(&p->lock) < 0)
997
- return packfile_error("failed to get lock for open");
998
-
999
- if (p->mwf.fd >= 0) {
1000
- git_mutex_unlock(&p->lock);
1091
+ if (p->mwf.fd >= 0)
1001
1092
  return 0;
1002
- }
1003
1093
 
1004
1094
  /* TODO: open with noatime */
1005
1095
  p->mwf.fd = git_futils_open_ro(p->pack_name);
1006
1096
  if (p->mwf.fd < 0)
1007
1097
  goto cleanup;
1008
1098
 
1009
- if (p_fstat(p->mwf.fd, &st) < 0 ||
1010
- git_mwindow_file_register(&p->mwf) < 0)
1099
+ if (p_fstat(p->mwf.fd, &st) < 0) {
1100
+ git_error_set(GIT_ERROR_OS, "could not stat packfile");
1011
1101
  goto cleanup;
1102
+ }
1012
1103
 
1013
1104
  /* If we created the struct before we had the pack we lack size. */
1014
1105
  if (!p->mwf.size) {
@@ -1039,8 +1130,7 @@ static int packfile_open(struct git_pack_file *p)
1039
1130
 
1040
1131
  /* Verify the pack matches its index. */
1041
1132
  if (p->num_objects != ntohl(hdr.hdr_entries) ||
1042
- p_lseek(p->mwf.fd, p->mwf.size - GIT_OID_RAWSZ, SEEK_SET) == -1 ||
1043
- p_read(p->mwf.fd, sha1.id, GIT_OID_RAWSZ) < 0)
1133
+ p_pread(p->mwf.fd, sha1.id, GIT_OID_RAWSZ, p->mwf.size - GIT_OID_RAWSZ) < 0)
1044
1134
  goto cleanup;
1045
1135
 
1046
1136
  idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
@@ -1048,7 +1138,9 @@ static int packfile_open(struct git_pack_file *p)
1048
1138
  if (git_oid__cmp(&sha1, (git_oid *)idx_sha1) != 0)
1049
1139
  goto cleanup;
1050
1140
 
1051
- git_mutex_unlock(&p->lock);
1141
+ if (git_mwindow_file_register(&p->mwf) < 0)
1142
+ goto cleanup;
1143
+
1052
1144
  return 0;
1053
1145
 
1054
1146
  cleanup:
@@ -1058,8 +1150,6 @@ cleanup:
1058
1150
  p_close(p->mwf.fd);
1059
1151
  p->mwf.fd = -1;
1060
1152
 
1061
- git_mutex_unlock(&p->lock);
1062
-
1063
1153
  return -1;
1064
1154
  }
1065
1155
 
@@ -1129,13 +1219,22 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
1129
1219
  p->mtime = (git_time_t)st.st_mtime;
1130
1220
  p->index_version = -1;
1131
1221
 
1132
- if (git_mutex_init(&p->lock)) {
1222
+ if (git_mutex_init(&p->lock) < 0) {
1133
1223
  git_error_set(GIT_ERROR_OS, "failed to initialize packfile mutex");
1134
1224
  git__free(p);
1135
1225
  return -1;
1136
1226
  }
1137
1227
 
1228
+ if (git_mutex_init(&p->mwf.lock) < 0) {
1229
+ git_error_set(GIT_ERROR_OS, "failed to initialize packfile window mutex");
1230
+ git_mutex_free(&p->lock);
1231
+ git__free(p);
1232
+ return -1;
1233
+ }
1234
+
1138
1235
  if (cache_init(&p->bases) < 0) {
1236
+ git_mutex_free(&p->mwf.lock);
1237
+ git_mutex_free(&p->lock);
1139
1238
  git__free(p);
1140
1239
  return -1;
1141
1240
  }
@@ -1151,28 +1250,29 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
1151
1250
  *
1152
1251
  ***********************************************************/
1153
1252
 
1154
- static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n)
1253
+ static off64_t nth_packed_object_offset_locked(struct git_pack_file *p, uint32_t n)
1155
1254
  {
1156
- const unsigned char *index = p->index_map.data;
1157
- const unsigned char *end = index + p->index_map.len;
1255
+ const unsigned char *index, *end;
1256
+ uint32_t off32;
1257
+
1258
+ index = p->index_map.data;
1259
+ end = index + p->index_map.len;
1158
1260
  index += 4 * 256;
1159
- if (p->index_version == 1) {
1261
+ if (p->index_version == 1)
1160
1262
  return ntohl(*((uint32_t *)(index + 24 * n)));
1161
- } else {
1162
- uint32_t off;
1163
- index += 8 + p->num_objects * (20 + 4);
1164
- off = ntohl(*((uint32_t *)(index + 4 * n)));
1165
- if (!(off & 0x80000000))
1166
- return off;
1167
- index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
1168
-
1169
- /* Make sure we're not being sent out of bounds */
1170
- if (index >= end - 8)
1171
- return -1;
1172
1263
 
1173
- return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
1174
- ntohl(*((uint32_t *)(index + 4)));
1175
- }
1264
+ index += 8 + p->num_objects * (20 + 4);
1265
+ off32 = ntohl(*((uint32_t *)(index + 4 * n)));
1266
+ if (!(off32 & 0x80000000))
1267
+ return off32;
1268
+ index += p->num_objects * 4 + (off32 & 0x7fffffff) * 8;
1269
+
1270
+ /* Make sure we're not being sent out of bounds */
1271
+ if (index >= end - 8)
1272
+ return -1;
1273
+
1274
+ return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
1275
+ ntohl(*((uint32_t *)(index + 4)));
1176
1276
  }
1177
1277
 
1178
1278
  static int git__memcmp4(const void *a, const void *b) {
@@ -1184,33 +1284,45 @@ int git_pack_foreach_entry(
1184
1284
  git_odb_foreach_cb cb,
1185
1285
  void *data)
1186
1286
  {
1187
- const unsigned char *index = p->index_map.data, *current;
1287
+ const unsigned char *index, *current;
1188
1288
  uint32_t i;
1189
1289
  int error = 0;
1290
+ git_array_oid_t oids = GIT_ARRAY_INIT;
1291
+ git_oid *oid;
1190
1292
 
1191
- if (index == NULL) {
1192
- if ((error = pack_index_open(p)) < 0)
1193
- return error;
1293
+ if (git_mutex_lock(&p->lock) < 0)
1294
+ return packfile_error("failed to get lock for git_pack_foreach_entry");
1194
1295
 
1195
- assert(p->index_map.data);
1296
+ if ((error = pack_index_open_locked(p)) < 0) {
1297
+ git_mutex_unlock(&p->lock);
1298
+ return error;
1299
+ }
1196
1300
 
1197
- index = p->index_map.data;
1301
+ if (!p->index_map.data) {
1302
+ git_error_set(GIT_ERROR_INTERNAL, "internal error: p->index_map.data == NULL");
1303
+ git_mutex_unlock(&p->lock);
1304
+ return -1;
1198
1305
  }
1199
1306
 
1200
- if (p->index_version > 1) {
1307
+ index = p->index_map.data;
1308
+
1309
+ if (p->index_version > 1)
1201
1310
  index += 8;
1202
- }
1203
1311
 
1204
1312
  index += 4 * 256;
1205
1313
 
1206
1314
  if (p->oids == NULL) {
1207
1315
  git_vector offsets, oids;
1208
1316
 
1209
- if ((error = git_vector_init(&oids, p->num_objects, NULL)))
1317
+ if ((error = git_vector_init(&oids, p->num_objects, NULL))) {
1318
+ git_mutex_unlock(&p->lock);
1210
1319
  return error;
1320
+ }
1211
1321
 
1212
- if ((error = git_vector_init(&offsets, p->num_objects, git__memcmp4)))
1322
+ if ((error = git_vector_init(&offsets, p->num_objects, git__memcmp4))) {
1323
+ git_mutex_unlock(&p->lock);
1213
1324
  return error;
1325
+ }
1214
1326
 
1215
1327
  if (p->index_version > 1) {
1216
1328
  const unsigned char *off = index + 24 * p->num_objects;
@@ -1231,21 +1343,115 @@ int git_pack_foreach_entry(
1231
1343
  p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids);
1232
1344
  }
1233
1345
 
1234
- for (i = 0; i < p->num_objects; i++)
1235
- if ((error = cb(p->oids[i], data)) != 0)
1236
- return git_error_set_after_callback(error);
1346
+ /* We need to copy the OIDs to another array before we relinquish the lock to avoid races. */
1347
+ git_array_init_to_size(oids, p->num_objects);
1348
+ if (!oids.ptr) {
1349
+ git_mutex_unlock(&p->lock);
1350
+ git_array_clear(oids);
1351
+ GIT_ERROR_CHECK_ARRAY(oids);
1352
+ }
1353
+ for (i = 0; i < p->num_objects; i++) {
1354
+ oid = git_array_alloc(oids);
1355
+ if (!oid) {
1356
+ git_mutex_unlock(&p->lock);
1357
+ git_array_clear(oids);
1358
+ GIT_ERROR_CHECK_ALLOC(oid);
1359
+ }
1360
+ git_oid_cpy(oid, p->oids[i]);
1361
+ }
1362
+
1363
+ git_mutex_unlock(&p->lock);
1364
+
1365
+ git_array_foreach(oids, i, oid) {
1366
+ if ((error = cb(oid, data)) != 0) {
1367
+ git_error_set_after_callback(error);
1368
+ break;
1369
+ }
1370
+ }
1371
+
1372
+ git_array_clear(oids);
1373
+ return error;
1374
+ }
1375
+
1376
+ int git_pack_foreach_entry_offset(
1377
+ struct git_pack_file *p,
1378
+ git_pack_foreach_entry_offset_cb cb,
1379
+ void *data)
1380
+ {
1381
+ const unsigned char *index;
1382
+ off64_t current_offset;
1383
+ const git_oid *current_oid;
1384
+ uint32_t i;
1385
+ int error = 0;
1386
+
1387
+ if (git_mutex_lock(&p->lock) < 0)
1388
+ return packfile_error("failed to get lock for git_pack_foreach_entry_offset");
1389
+
1390
+ index = p->index_map.data;
1391
+ if (index == NULL) {
1392
+ if ((error = pack_index_open_locked(p)) < 0)
1393
+ goto cleanup;
1394
+
1395
+ if (!p->index_map.data) {
1396
+ git_error_set(GIT_ERROR_INTERNAL, "internal error: p->index_map.data == NULL");
1397
+ goto cleanup;
1398
+ }
1399
+
1400
+ index = p->index_map.data;
1401
+ }
1402
+
1403
+ if (p->index_version > 1)
1404
+ index += 8;
1405
+
1406
+ index += 4 * 256;
1407
+
1408
+ /* all offsets should have been validated by pack_index_check_locked */
1409
+ if (p->index_version > 1) {
1410
+ const unsigned char *offsets = index + 24 * p->num_objects;
1411
+ const unsigned char *large_offset_ptr;
1412
+ const unsigned char *large_offsets = index + 28 * p->num_objects;
1413
+ const unsigned char *large_offsets_end = ((const unsigned char *)p->index_map.data) + p->index_map.len - 20;
1414
+ for (i = 0; i < p->num_objects; i++) {
1415
+ current_offset = ntohl(*(const uint32_t *)(offsets + 4 * i));
1416
+ if (current_offset & 0x80000000) {
1417
+ large_offset_ptr = large_offsets + (current_offset & 0x7fffffff) * 8;
1418
+ if (large_offset_ptr >= large_offsets_end) {
1419
+ error = packfile_error("invalid large offset");
1420
+ goto cleanup;
1421
+ }
1422
+ current_offset = (((off64_t)ntohl(*((uint32_t *)(large_offset_ptr + 0)))) << 32) |
1423
+ ntohl(*((uint32_t *)(large_offset_ptr + 4)));
1424
+ }
1425
+ current_oid = (const git_oid *)(index + 20 * i);
1426
+ if ((error = cb(current_oid, current_offset, data)) != 0) {
1427
+ error = git_error_set_after_callback(error);
1428
+ goto cleanup;
1429
+ }
1430
+ }
1431
+ } else {
1432
+ for (i = 0; i < p->num_objects; i++) {
1433
+ current_offset = ntohl(*(const uint32_t *)(index + 24 * i));
1434
+ current_oid = (const git_oid *)(index + 24 * i + 4);
1435
+ if ((error = cb(current_oid, current_offset, data)) != 0) {
1436
+ error = git_error_set_after_callback(error);
1437
+ goto cleanup;
1438
+ }
1439
+ }
1440
+ }
1237
1441
 
1442
+ cleanup:
1443
+ git_mutex_unlock(&p->lock);
1238
1444
  return error;
1239
1445
  }
1240
1446
 
1241
- static int sha1_position(const void *table, size_t stride, unsigned lo,
1242
- unsigned hi, const unsigned char *key)
1447
+ int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned lo,
1448
+ unsigned hi, const unsigned char *oid_prefix)
1243
1449
  {
1244
- const unsigned char *base = table;
1450
+ const unsigned char *base = oid_lookup_table;
1245
1451
 
1246
1452
  while (lo < hi) {
1247
1453
  unsigned mi = (lo + hi) / 2;
1248
- int cmp = git_oid__hashcmp(base + mi * stride, key);
1454
+ int cmp = git_oid__hashcmp(base + mi * stride, oid_prefix);
1249
1455
 
1250
1456
  if (!cmp)
1251
1457
  return mi;
@@ -1272,15 +1478,19 @@ static int pack_entry_find_offset(
1272
1478
  int pos, found = 0;
1273
1479
  off64_t offset;
1274
1480
  const unsigned char *current = 0;
1481
+ int error = 0;
1275
1482
 
1276
1483
  *offset_out = 0;
1277
1484
 
1278
- if (p->index_version == -1) {
1279
- int error;
1485
+ if (git_mutex_lock(&p->lock) < 0)
1486
+ return packfile_error("failed to get lock for pack_entry_find_offset");
1280
1487
 
1281
- if ((error = pack_index_open(p)) < 0)
1282
- return error;
1283
- assert(p->index_map.data);
1488
+ if ((error = pack_index_open_locked(p)) < 0)
1489
+ goto cleanup;
1490
+
1491
+ if (!p->index_map.data) {
1492
+ git_error_set(GIT_ERROR_INTERNAL, "internal error: p->index_map.data == NULL");
1493
+ goto cleanup;
1284
1494
  }
1285
1495
 
1286
1496
  index = p->index_map.data;
@@ -1307,7 +1517,7 @@ static int pack_entry_find_offset(
1307
1517
  short_oid->id[0], short_oid->id[1], short_oid->id[2], lo, hi, p->num_objects);
1308
1518
  #endif
1309
1519
 
1310
- pos = sha1_position(index, stride, lo, hi, short_oid->id);
1520
+ pos = git_pack__lookup_sha1(index, stride, lo, hi, short_oid->id);
1311
1521
 
1312
1522
  if (pos >= 0) {
1313
1523
  /* An object matching exactly the oid was found */
@@ -1334,14 +1544,19 @@ static int pack_entry_find_offset(
1334
1544
  }
1335
1545
  }
1336
1546
 
1337
- if (!found)
1338
- return git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
1339
- if (found > 1)
1340
- return git_odb__error_ambiguous("found multiple offsets for pack entry");
1547
+ if (!found) {
1548
+ error = git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
1549
+ goto cleanup;
1550
+ }
1551
+ if (found > 1) {
1552
+ error = git_odb__error_ambiguous("found multiple offsets for pack entry");
1553
+ goto cleanup;
1554
+ }
1341
1555
 
1342
- if ((offset = nth_packed_object_offset(p, pos)) < 0) {
1556
+ if ((offset = nth_packed_object_offset_locked(p, pos)) < 0) {
1343
1557
  git_error_set(GIT_ERROR_ODB, "packfile index is corrupt");
1344
- return -1;
1558
+ error = -1;
1559
+ goto cleanup;
1345
1560
  }
1346
1561
 
1347
1562
  *offset_out = offset;
@@ -1356,7 +1571,9 @@ static int pack_entry_find_offset(
1356
1571
  }
1357
1572
  #endif
1358
1573
 
1359
- return 0;
1574
+ cleanup:
1575
+ git_mutex_unlock(&p->lock);
1576
+ return error;
1360
1577
  }
1361
1578
 
1362
1579
  int git_pack_entry_find(
@@ -1369,7 +1586,7 @@ int git_pack_entry_find(
1369
1586
  git_oid found_oid;
1370
1587
  int error;
1371
1588
 
1372
- assert(p);
1589
+ GIT_ASSERT_ARG(p);
1373
1590
 
1374
1591
  if (len == GIT_OID_HEXSZ && p->num_bad_objects) {
1375
1592
  unsigned i;
@@ -1382,10 +1599,26 @@ int git_pack_entry_find(
1382
1599
  if (error < 0)
1383
1600
  return error;
1384
1601
 
1602
+ error = git_mutex_lock(&p->lock);
1603
+ if (error < 0) {
1604
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
1605
+ return error;
1606
+ }
1607
+ error = git_mutex_lock(&p->mwf.lock);
1608
+ if (error < 0) {
1609
+ git_mutex_unlock(&p->lock);
1610
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
1611
+ return error;
1612
+ }
1613
+
1385
1614
  /* we found a unique entry in the index;
1386
1615
  * make sure the packfile backing the index
1387
1616
  * still exists on disk */
1388
- if (p->mwf.fd == -1 && (error = packfile_open(p)) < 0)
1617
+ if (p->mwf.fd == -1)
1618
+ error = packfile_open_locked(p);
1619
+ git_mutex_unlock(&p->mwf.lock);
1620
+ git_mutex_unlock(&p->lock);
1621
+ if (error < 0)
1389
1622
  return error;
1390
1623
 
1391
1624
  e->offset = offset;