rugged 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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;