rugged 1.1.1 → 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 (277) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -0
  3. data/README.md +1 -1
  4. data/ext/rugged/rugged.c +7 -4
  5. data/ext/rugged/rugged_object.c +1 -1
  6. data/ext/rugged/rugged_repo.c +3 -3
  7. data/lib/rugged/repository.rb +2 -2
  8. data/lib/rugged/version.rb +1 -1
  9. data/vendor/libgit2/CMakeLists.txt +11 -6
  10. data/vendor/libgit2/COPYING +109 -1
  11. data/vendor/libgit2/cmake/Findfutimens.cmake +14 -0
  12. data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +4 -0
  13. data/vendor/libgit2/cmake/SelectHashes.cmake +1 -0
  14. data/vendor/libgit2/deps/chromium-zlib/CMakeLists.txt +101 -0
  15. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +17 -5
  16. data/vendor/libgit2/deps/ntlmclient/crypt.h +14 -9
  17. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +20 -20
  18. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.h +3 -3
  19. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +37 -36
  20. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.h +4 -3
  21. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +178 -51
  22. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.h +74 -5
  23. data/vendor/libgit2/deps/ntlmclient/ntlm.c +150 -118
  24. data/vendor/libgit2/deps/ntlmclient/ntlm.h +13 -9
  25. data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +16 -3
  26. data/vendor/libgit2/deps/ntlmclient/unicode.h +10 -4
  27. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +16 -27
  28. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.h +20 -0
  29. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +28 -52
  30. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.h +22 -0
  31. data/vendor/libgit2/include/git2/attr.h +89 -0
  32. data/vendor/libgit2/include/git2/blame.h +93 -42
  33. data/vendor/libgit2/include/git2/blob.h +14 -2
  34. data/vendor/libgit2/include/git2/branch.h +25 -0
  35. data/vendor/libgit2/include/git2/cert.h +42 -5
  36. data/vendor/libgit2/include/git2/checkout.h +28 -12
  37. data/vendor/libgit2/include/git2/commit.h +35 -19
  38. data/vendor/libgit2/include/git2/common.h +14 -4
  39. data/vendor/libgit2/include/git2/deprecated.h +206 -6
  40. data/vendor/libgit2/include/git2/diff.h +34 -19
  41. data/vendor/libgit2/include/git2/errors.h +6 -6
  42. data/vendor/libgit2/include/git2/filter.h +57 -17
  43. data/vendor/libgit2/include/git2/graph.h +20 -2
  44. data/vendor/libgit2/include/git2/index.h +2 -2
  45. data/vendor/libgit2/include/git2/odb.h +29 -0
  46. data/vendor/libgit2/include/git2/patch.h +8 -0
  47. data/vendor/libgit2/include/git2/rebase.h +25 -1
  48. data/vendor/libgit2/include/git2/refs.h +6 -2
  49. data/vendor/libgit2/include/git2/remote.h +59 -6
  50. data/vendor/libgit2/include/git2/revparse.h +5 -5
  51. data/vendor/libgit2/include/git2/status.h +115 -59
  52. data/vendor/libgit2/include/git2/submodule.h +9 -0
  53. data/vendor/libgit2/include/git2/sys/commit_graph.h +174 -0
  54. data/vendor/libgit2/include/git2/sys/filter.h +49 -28
  55. data/vendor/libgit2/include/git2/sys/midx.h +74 -0
  56. data/vendor/libgit2/include/git2/sys/odb_backend.h +7 -0
  57. data/vendor/libgit2/include/git2/sys/transport.h +1 -0
  58. data/vendor/libgit2/include/git2/tag.h +12 -0
  59. data/vendor/libgit2/include/git2/tree.h +0 -14
  60. data/vendor/libgit2/include/git2/types.h +9 -0
  61. data/vendor/libgit2/include/git2/version.h +4 -4
  62. data/vendor/libgit2/include/git2/worktree.h +1 -0
  63. data/vendor/libgit2/src/CMakeLists.txt +25 -4
  64. data/vendor/libgit2/src/alloc.c +21 -8
  65. data/vendor/libgit2/src/allocators/failalloc.c +92 -0
  66. data/vendor/libgit2/src/allocators/failalloc.h +23 -0
  67. data/vendor/libgit2/src/allocators/stdalloc.c +41 -10
  68. data/vendor/libgit2/src/allocators/win32_leakcheck.c +118 -0
  69. data/vendor/libgit2/src/allocators/{win32_crtdbg.h → win32_leakcheck.h} +3 -3
  70. data/vendor/libgit2/src/annotated_commit.c +21 -9
  71. data/vendor/libgit2/src/apply.c +16 -7
  72. data/vendor/libgit2/src/array.h +11 -11
  73. data/vendor/libgit2/src/attr.c +181 -74
  74. data/vendor/libgit2/src/attr_file.c +84 -39
  75. data/vendor/libgit2/src/attr_file.h +32 -11
  76. data/vendor/libgit2/src/attrcache.c +42 -37
  77. data/vendor/libgit2/src/attrcache.h +4 -5
  78. data/vendor/libgit2/src/blame.c +11 -5
  79. data/vendor/libgit2/src/blob.c +35 -24
  80. data/vendor/libgit2/src/branch.c +69 -17
  81. data/vendor/libgit2/src/buffer.c +334 -25
  82. data/vendor/libgit2/src/buffer.h +153 -2
  83. data/vendor/libgit2/src/cache.c +2 -2
  84. data/vendor/libgit2/src/cache.h +7 -7
  85. data/vendor/libgit2/src/cc-compat.h +10 -2
  86. data/vendor/libgit2/src/checkout.c +48 -26
  87. data/vendor/libgit2/src/cherrypick.c +6 -2
  88. data/vendor/libgit2/src/clone.c +41 -47
  89. data/vendor/libgit2/src/commit.c +41 -28
  90. data/vendor/libgit2/src/commit_graph.c +1209 -0
  91. data/vendor/libgit2/src/commit_graph.h +162 -0
  92. data/vendor/libgit2/src/commit_list.c +46 -0
  93. data/vendor/libgit2/src/commit_list.h +2 -0
  94. data/vendor/libgit2/src/common.h +25 -2
  95. data/vendor/libgit2/src/config.c +37 -15
  96. data/vendor/libgit2/src/config_cache.c +5 -3
  97. data/vendor/libgit2/src/config_file.c +16 -8
  98. data/vendor/libgit2/src/config_parse.c +4 -6
  99. data/vendor/libgit2/src/crlf.c +16 -6
  100. data/vendor/libgit2/src/date.c +4 -3
  101. data/vendor/libgit2/src/delta.c +1 -1
  102. data/vendor/libgit2/src/describe.c +6 -3
  103. data/vendor/libgit2/src/diff.c +11 -8
  104. data/vendor/libgit2/src/diff_driver.c +21 -17
  105. data/vendor/libgit2/src/diff_file.c +2 -6
  106. data/vendor/libgit2/src/diff_generate.c +46 -17
  107. data/vendor/libgit2/src/diff_print.c +19 -6
  108. data/vendor/libgit2/src/diff_stats.c +7 -5
  109. data/vendor/libgit2/src/diff_tform.c +9 -8
  110. data/vendor/libgit2/src/diff_xdiff.c +4 -2
  111. data/vendor/libgit2/src/diff_xdiff.h +1 -1
  112. data/vendor/libgit2/src/errors.c +24 -19
  113. data/vendor/libgit2/src/features.h.in +5 -1
  114. data/vendor/libgit2/src/fetch.c +5 -2
  115. data/vendor/libgit2/src/fetchhead.c +8 -4
  116. data/vendor/libgit2/src/filebuf.c +9 -7
  117. data/vendor/libgit2/src/filter.c +206 -110
  118. data/vendor/libgit2/src/filter.h +24 -5
  119. data/vendor/libgit2/src/futils.c +5 -5
  120. data/vendor/libgit2/src/futils.h +1 -1
  121. data/vendor/libgit2/src/graph.c +64 -9
  122. data/vendor/libgit2/src/hash/sha1/collisiondetect.c +3 -3
  123. data/vendor/libgit2/src/hash/sha1/common_crypto.c +3 -3
  124. data/vendor/libgit2/src/hash/sha1/generic.h +1 -1
  125. data/vendor/libgit2/src/hash/sha1/mbedtls.c +12 -12
  126. data/vendor/libgit2/src/hash/sha1/openssl.c +3 -3
  127. data/vendor/libgit2/src/hash/sha1/sha1dc/sha1.c +0 -2
  128. data/vendor/libgit2/src/hash/sha1/win32.c +15 -11
  129. data/vendor/libgit2/src/hash.c +16 -13
  130. data/vendor/libgit2/src/hash.h +1 -1
  131. data/vendor/libgit2/src/hashsig.c +23 -10
  132. data/vendor/libgit2/src/ident.c +13 -3
  133. data/vendor/libgit2/src/ignore.c +35 -19
  134. data/vendor/libgit2/src/index.c +106 -70
  135. data/vendor/libgit2/src/index.h +1 -1
  136. data/vendor/libgit2/src/indexer.c +31 -29
  137. data/vendor/libgit2/src/integer.h +64 -2
  138. data/vendor/libgit2/src/iterator.c +36 -24
  139. data/vendor/libgit2/src/iterator.h +1 -1
  140. data/vendor/libgit2/src/khash.h +2 -11
  141. data/vendor/libgit2/src/{settings.c → libgit2.c} +117 -50
  142. data/vendor/libgit2/src/libgit2.h +15 -0
  143. data/vendor/libgit2/src/mailmap.c +23 -10
  144. data/vendor/libgit2/src/map.h +3 -3
  145. data/vendor/libgit2/src/merge.c +70 -30
  146. data/vendor/libgit2/src/merge.h +2 -1
  147. data/vendor/libgit2/src/merge_driver.c +19 -13
  148. data/vendor/libgit2/src/merge_file.c +11 -3
  149. data/vendor/libgit2/src/message.c +3 -1
  150. data/vendor/libgit2/src/midx.c +471 -10
  151. data/vendor/libgit2/src/midx.h +28 -1
  152. data/vendor/libgit2/src/mwindow.c +103 -59
  153. data/vendor/libgit2/src/mwindow.h +3 -3
  154. data/vendor/libgit2/src/net.c +127 -3
  155. data/vendor/libgit2/src/net.h +16 -2
  156. data/vendor/libgit2/src/netops.c +6 -4
  157. data/vendor/libgit2/src/netops.h +2 -2
  158. data/vendor/libgit2/src/notes.c +10 -10
  159. data/vendor/libgit2/src/object.c +22 -14
  160. data/vendor/libgit2/src/odb.c +285 -48
  161. data/vendor/libgit2/src/odb.h +16 -2
  162. data/vendor/libgit2/src/odb_loose.c +28 -18
  163. data/vendor/libgit2/src/odb_mempack.c +1 -1
  164. data/vendor/libgit2/src/odb_pack.c +391 -114
  165. data/vendor/libgit2/src/oid.c +5 -4
  166. data/vendor/libgit2/src/pack-objects.c +54 -48
  167. data/vendor/libgit2/src/pack.c +329 -119
  168. data/vendor/libgit2/src/pack.h +25 -7
  169. data/vendor/libgit2/src/patch.c +14 -7
  170. data/vendor/libgit2/src/patch_generate.c +2 -2
  171. data/vendor/libgit2/src/patch_parse.c +2 -1
  172. data/vendor/libgit2/src/path.c +98 -53
  173. data/vendor/libgit2/src/path.h +79 -6
  174. data/vendor/libgit2/src/pathspec.c +8 -8
  175. data/vendor/libgit2/src/pool.c +13 -7
  176. data/vendor/libgit2/src/posix.c +11 -3
  177. data/vendor/libgit2/src/reader.c +10 -6
  178. data/vendor/libgit2/src/rebase.c +93 -49
  179. data/vendor/libgit2/src/refdb.c +30 -13
  180. data/vendor/libgit2/src/refdb_fs.c +121 -69
  181. data/vendor/libgit2/src/reflog.c +19 -14
  182. data/vendor/libgit2/src/refs.c +76 -41
  183. data/vendor/libgit2/src/refspec.c +32 -12
  184. data/vendor/libgit2/src/remote.c +272 -102
  185. data/vendor/libgit2/src/remote.h +2 -1
  186. data/vendor/libgit2/src/repository.c +176 -103
  187. data/vendor/libgit2/src/repository.h +12 -1
  188. data/vendor/libgit2/src/reset.c +7 -6
  189. data/vendor/libgit2/src/revert.c +6 -2
  190. data/vendor/libgit2/src/revparse.c +14 -9
  191. data/vendor/libgit2/src/revwalk.c +32 -15
  192. data/vendor/libgit2/src/runtime.c +162 -0
  193. data/vendor/libgit2/src/runtime.h +62 -0
  194. data/vendor/libgit2/src/settings.h +11 -0
  195. data/vendor/libgit2/src/signature.c +6 -5
  196. data/vendor/libgit2/src/sortedcache.h +10 -8
  197. data/vendor/libgit2/src/stash.c +3 -1
  198. data/vendor/libgit2/src/status.c +7 -4
  199. data/vendor/libgit2/src/strarray.c +2 -1
  200. data/vendor/libgit2/src/streams/mbedtls.c +14 -17
  201. data/vendor/libgit2/src/streams/mbedtls.h +1 -1
  202. data/vendor/libgit2/src/streams/openssl.c +101 -201
  203. data/vendor/libgit2/src/streams/openssl.h +9 -1
  204. data/vendor/libgit2/src/streams/openssl_dynamic.c +309 -0
  205. data/vendor/libgit2/src/streams/openssl_dynamic.h +348 -0
  206. data/vendor/libgit2/src/streams/openssl_legacy.c +203 -0
  207. data/vendor/libgit2/src/streams/openssl_legacy.h +63 -0
  208. data/vendor/libgit2/src/streams/registry.c +5 -6
  209. data/vendor/libgit2/src/streams/socket.c +6 -2
  210. data/vendor/libgit2/src/streams/stransport.c +6 -3
  211. data/vendor/libgit2/src/streams/tls.c +5 -3
  212. data/vendor/libgit2/src/submodule.c +128 -62
  213. data/vendor/libgit2/src/submodule.h +9 -9
  214. data/vendor/libgit2/src/sysdir.c +4 -6
  215. data/vendor/libgit2/src/tag.c +47 -11
  216. data/vendor/libgit2/src/thread.c +140 -0
  217. data/vendor/libgit2/src/thread.h +479 -0
  218. data/vendor/libgit2/src/threadstate.c +83 -0
  219. data/vendor/libgit2/src/threadstate.h +24 -0
  220. data/vendor/libgit2/src/trace.c +2 -2
  221. data/vendor/libgit2/src/trace.h +17 -13
  222. data/vendor/libgit2/src/transaction.c +19 -8
  223. data/vendor/libgit2/src/transport.c +3 -3
  224. data/vendor/libgit2/src/transports/auth.c +1 -1
  225. data/vendor/libgit2/src/transports/auth_negotiate.c +11 -4
  226. data/vendor/libgit2/src/transports/auth_ntlm.c +10 -6
  227. data/vendor/libgit2/src/transports/credential.c +15 -7
  228. data/vendor/libgit2/src/transports/git.c +1 -3
  229. data/vendor/libgit2/src/transports/http.c +19 -17
  230. data/vendor/libgit2/src/transports/http.h +1 -0
  231. data/vendor/libgit2/src/transports/httpclient.c +53 -26
  232. data/vendor/libgit2/src/transports/httpclient.h +1 -1
  233. data/vendor/libgit2/src/transports/local.c +3 -3
  234. data/vendor/libgit2/src/transports/smart.c +12 -7
  235. data/vendor/libgit2/src/transports/smart.h +1 -1
  236. data/vendor/libgit2/src/transports/smart_protocol.c +11 -5
  237. data/vendor/libgit2/src/transports/ssh.c +51 -17
  238. data/vendor/libgit2/src/transports/winhttp.c +41 -31
  239. data/vendor/libgit2/src/tree.c +100 -77
  240. data/vendor/libgit2/src/tree.h +1 -0
  241. data/vendor/libgit2/src/tsort.c +0 -2
  242. data/vendor/libgit2/src/unix/map.c +3 -1
  243. data/vendor/libgit2/src/unix/pthread.h +2 -1
  244. data/vendor/libgit2/src/utf8.c +150 -0
  245. data/vendor/libgit2/src/utf8.h +52 -0
  246. data/vendor/libgit2/src/util.c +53 -129
  247. data/vendor/libgit2/src/util.h +33 -39
  248. data/vendor/libgit2/src/vector.c +23 -19
  249. data/vendor/libgit2/src/vector.h +4 -2
  250. data/vendor/libgit2/src/win32/findfile.c +4 -2
  251. data/vendor/libgit2/src/win32/map.c +1 -1
  252. data/vendor/libgit2/src/win32/msvc-compat.h +9 -1
  253. data/vendor/libgit2/src/win32/path_w32.c +22 -24
  254. data/vendor/libgit2/src/win32/path_w32.h +0 -1
  255. data/vendor/libgit2/src/win32/posix_w32.c +7 -1
  256. data/vendor/libgit2/src/win32/precompiled.h +0 -1
  257. data/vendor/libgit2/src/win32/reparse.h +4 -4
  258. data/vendor/libgit2/src/win32/thread.c +24 -15
  259. data/vendor/libgit2/src/win32/thread.h +1 -1
  260. data/vendor/libgit2/src/win32/w32_buffer.c +3 -3
  261. data/vendor/libgit2/src/win32/w32_common.h +18 -9
  262. data/vendor/libgit2/src/win32/{w32_crtdbg_stacktrace.c → w32_leakcheck.c} +269 -33
  263. data/vendor/libgit2/src/win32/w32_leakcheck.h +222 -0
  264. data/vendor/libgit2/src/win32/w32_util.h +6 -6
  265. data/vendor/libgit2/src/worktree.c +27 -16
  266. data/vendor/libgit2/src/zstream.c +1 -1
  267. metadata +32 -16
  268. data/vendor/libgit2/src/allocators/win32_crtdbg.c +0 -118
  269. data/vendor/libgit2/src/buf_text.c +0 -316
  270. data/vendor/libgit2/src/buf_text.h +0 -122
  271. data/vendor/libgit2/src/global.c +0 -363
  272. data/vendor/libgit2/src/global.h +0 -41
  273. data/vendor/libgit2/src/thread-utils.c +0 -58
  274. data/vendor/libgit2/src/thread-utils.h +0 -369
  275. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +0 -127
  276. data/vendor/libgit2/src/win32/w32_stack.c +0 -188
  277. 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
  }
@@ -316,7 +317,7 @@ git_oid_shorten *git_oid_shorten_new(size_t min_length)
316
317
  {
317
318
  git_oid_shorten *os;
318
319
 
319
- assert((size_t)((int)min_length) == min_length);
320
+ GIT_ASSERT_ARG_WITH_RETVAL((size_t)((int)min_length) == min_length, NULL);
320
321
 
321
322
  os = git__calloc(1, sizeof(git_oid_shorten));
322
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)
@@ -177,13 +169,13 @@ on_error:
177
169
 
178
170
  unsigned int git_packbuilder_set_threads(git_packbuilder *pb, unsigned int n)
179
171
  {
180
- assert(pb);
172
+ GIT_ASSERT_ARG(pb);
181
173
 
182
174
  #ifdef GIT_THREADS
183
175
  pb->nr_threads = n;
184
176
  #else
185
177
  GIT_UNUSED(n);
186
- assert(1 == pb->nr_threads);
178
+ GIT_ASSERT(pb->nr_threads == 1);
187
179
  #endif
188
180
 
189
181
  return pb->nr_threads;
@@ -211,7 +203,8 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
211
203
  size_t newsize;
212
204
  int ret;
213
205
 
214
- assert(pb && oid);
206
+ GIT_ASSERT_ARG(pb);
207
+ GIT_ASSERT_ARG(oid);
215
208
 
216
209
  /* If the object already exists in the hash table, then we don't
217
210
  * have any work to do */
@@ -258,7 +251,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
258
251
  double current_time = git__timer();
259
252
  double elapsed = current_time - pb->last_progress_report_time;
260
253
 
261
- if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
254
+ if (elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
262
255
  pb->last_progress_report_time = current_time;
263
256
 
264
257
  ret = pb->progress_cb(
@@ -347,10 +340,9 @@ static int write_object(
347
340
  }
348
341
 
349
342
  /* Write header */
350
- hdr_len = git_packfile__object_header(hdr, data_len, type);
351
-
352
- if ((error = write_cb(hdr, hdr_len, cb_data)) < 0 ||
353
- (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)
354
346
  goto done;
355
347
 
356
348
  if (type == GIT_OBJECT_REF_DELTA) {
@@ -525,13 +517,18 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data)
525
517
  return 0;
526
518
  }
527
519
 
528
- static git_pobject **compute_write_order(git_packbuilder *pb)
520
+ static int compute_write_order(git_pobject ***out, git_packbuilder *pb)
529
521
  {
530
522
  size_t i, wo_end, last_untagged;
531
523
  git_pobject **wo;
532
524
 
525
+ *out = NULL;
526
+
527
+ if (!pb->nr_objects)
528
+ return 0;
529
+
533
530
  if ((wo = git__mallocarray(pb->nr_objects, sizeof(*wo))) == NULL)
534
- return NULL;
531
+ return -1;
535
532
 
536
533
  for (i = 0; i < pb->nr_objects; i++) {
537
534
  git_pobject *po = pb->object_list + i;
@@ -560,7 +557,7 @@ static git_pobject **compute_write_order(git_packbuilder *pb)
560
557
  */
561
558
  if (git_tag_foreach(pb->repo, &cb_tag_foreach, pb) < 0) {
562
559
  git__free(wo);
563
- return NULL;
560
+ return -1;
564
561
  }
565
562
 
566
563
  /*
@@ -617,10 +614,11 @@ static git_pobject **compute_write_order(git_packbuilder *pb)
617
614
  if (wo_end != pb->nr_objects) {
618
615
  git__free(wo);
619
616
  git_error_set(GIT_ERROR_INVALID, "invalid write order");
620
- return NULL;
617
+ return -1;
621
618
  }
622
619
 
623
- return wo;
620
+ *out = wo;
621
+ return 0;
624
622
  }
625
623
 
626
624
  static int write_pack(git_packbuilder *pb,
@@ -633,15 +631,15 @@ static int write_pack(git_packbuilder *pb,
633
631
  struct git_pack_header ph;
634
632
  git_oid entry_oid;
635
633
  size_t i = 0;
636
- int error = 0;
634
+ int error;
637
635
 
638
- write_order = compute_write_order(pb);
639
- if (write_order == NULL)
640
- return -1;
636
+ if ((error = compute_write_order(&write_order, pb)) < 0)
637
+ return error;
641
638
 
642
639
  if (!git__is_uint32(pb->nr_objects)) {
643
640
  git_error_set(GIT_ERROR_INVALID, "too many objects");
644
- return -1;
641
+ error = -1;
642
+ goto done;
645
643
  }
646
644
 
647
645
  /* Write pack header */
@@ -852,10 +850,11 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
852
850
  }
853
851
  }
854
852
 
855
- git_packbuilder__cache_lock(pb);
853
+ GIT_ASSERT(git_packbuilder__cache_lock(pb) == 0);
854
+
856
855
  if (trg_object->delta_data) {
857
856
  git__free(trg_object->delta_data);
858
- assert(pb->delta_cache_size >= trg_object->delta_size);
857
+ GIT_ASSERT(pb->delta_cache_size >= trg_object->delta_size);
859
858
  pb->delta_cache_size -= trg_object->delta_size;
860
859
  trg_object->delta_data = NULL;
861
860
  }
@@ -863,7 +862,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
863
862
  bool overflow = git__add_sizet_overflow(
864
863
  &pb->delta_cache_size, pb->delta_cache_size, delta_size);
865
864
 
866
- git_packbuilder__cache_unlock(pb);
865
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
867
866
 
868
867
  if (overflow) {
869
868
  git__free(delta_buf);
@@ -874,7 +873,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
874
873
  GIT_ERROR_CHECK_ALLOC(trg_object->delta_data);
875
874
  } else {
876
875
  /* create delta when writing the pack */
877
- git_packbuilder__cache_unlock(pb);
876
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
878
877
  git__free(delta_buf);
879
878
  }
880
879
 
@@ -929,7 +928,7 @@ static int report_delta_progress(
929
928
  double current_time = git__timer();
930
929
  double elapsed = current_time - pb->last_progress_report_time;
931
930
 
932
- if (force || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
931
+ if (force || elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
933
932
  pb->last_progress_report_time = current_time;
934
933
 
935
934
  ret = pb->progress_cb(
@@ -962,9 +961,9 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
962
961
  struct unpacked *n = array + idx;
963
962
  size_t max_depth, j, best_base = SIZE_MAX;
964
963
 
965
- git_packbuilder__progress_lock(pb);
964
+ GIT_ASSERT(git_packbuilder__progress_lock(pb) == 0);
966
965
  if (!*list_size) {
967
- git_packbuilder__progress_unlock(pb);
966
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
968
967
  break;
969
968
  }
970
969
 
@@ -973,7 +972,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
973
972
 
974
973
  po = *list++;
975
974
  (*list_size)--;
976
- git_packbuilder__progress_unlock(pb);
975
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
977
976
 
978
977
  mem_usage -= free_unpacked(n);
979
978
  n->object = po;
@@ -1048,10 +1047,10 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
1048
1047
  po->z_delta_size = zbuf.size;
1049
1048
  git_buf_clear(&zbuf);
1050
1049
 
1051
- git_packbuilder__cache_lock(pb);
1050
+ GIT_ASSERT(git_packbuilder__cache_lock(pb) == 0);
1052
1051
  pb->delta_cache_size -= po->delta_size;
1053
1052
  pb->delta_cache_size += po->z_delta_size;
1054
- git_packbuilder__cache_unlock(pb);
1053
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
1055
1054
  }
1056
1055
 
1057
1056
  /*
@@ -1129,10 +1128,10 @@ static void *threaded_find_deltas(void *arg)
1129
1128
  ; /* TODO */
1130
1129
  }
1131
1130
 
1132
- git_packbuilder__progress_lock(me->pb);
1131
+ GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_lock(me->pb) == 0, NULL);
1133
1132
  me->working = 0;
1134
1133
  git_cond_signal(&me->pb->progress_cond);
1135
- git_packbuilder__progress_unlock(me->pb);
1134
+ GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_unlock(me->pb) == 0, NULL);
1136
1135
 
1137
1136
  if (git_mutex_lock(&me->mutex)) {
1138
1137
  git_error_set(GIT_ERROR_THREAD, "unable to lock packfile condition mutex");
@@ -1165,7 +1164,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1165
1164
  int ret, active_threads = 0;
1166
1165
 
1167
1166
  if (!pb->nr_threads)
1168
- pb->nr_threads = git_online_cpus();
1167
+ pb->nr_threads = git__online_cpus();
1169
1168
 
1170
1169
  if (pb->nr_threads <= 1) {
1171
1170
  find_deltas(pb, list, &list_size, window, depth);
@@ -1237,7 +1236,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1237
1236
  * 'working' flag from 1 -> 0. This indicates that it is
1238
1237
  * ready to receive more work using our work-stealing
1239
1238
  * algorithm. */
1240
- git_packbuilder__progress_lock(pb);
1239
+ GIT_ASSERT(git_packbuilder__progress_lock(pb) == 0);
1241
1240
  for (;;) {
1242
1241
  for (i = 0; !target && i < pb->nr_threads; i++)
1243
1242
  if (!p[i].working)
@@ -1280,7 +1279,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1280
1279
  target->list_size = sub_size;
1281
1280
  target->remaining = sub_size;
1282
1281
  target->working = 1;
1283
- git_packbuilder__progress_unlock(pb);
1282
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
1284
1283
 
1285
1284
  if (git_mutex_lock(&target->mutex)) {
1286
1285
  git_error_set(GIT_ERROR_THREAD, "unable to lock packfile condition mutex");
@@ -1363,8 +1362,13 @@ int git_packbuilder_foreach(git_packbuilder *pb, int (*cb)(void *buf, size_t siz
1363
1362
 
1364
1363
  int git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb)
1365
1364
  {
1365
+ int error;
1366
+
1367
+ if ((error = git_buf_sanitize(buf)) < 0)
1368
+ return error;
1369
+
1366
1370
  PREPARE_PACK;
1367
- git_buf_sanitize(buf);
1371
+
1368
1372
  return write_pack(pb, &write_pack_buf, buf);
1369
1373
  }
1370
1374
 
@@ -1486,7 +1490,8 @@ int git_packbuilder_insert_recur(git_packbuilder *pb, const git_oid *id, const c
1486
1490
  git_object *obj;
1487
1491
  int error;
1488
1492
 
1489
- assert(pb && id);
1493
+ GIT_ASSERT_ARG(pb);
1494
+ GIT_ASSERT_ARG(id);
1490
1495
 
1491
1496
  if ((error = git_object_lookup(&obj, pb->repo, id, GIT_OBJECT_ANY)) < 0)
1492
1497
  return error;
@@ -1727,7 +1732,8 @@ int git_packbuilder_insert_walk(git_packbuilder *pb, git_revwalk *walk)
1727
1732
  git_oid id;
1728
1733
  struct walk_object *obj;
1729
1734
 
1730
- assert(pb && walk);
1735
+ GIT_ASSERT_ARG(pb);
1736
+ GIT_ASSERT_ARG(walk);
1731
1737
 
1732
1738
  if ((error = mark_edges_uninteresting(pb, walk->user_input)) < 0)
1733
1739
  return error;
@@ -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
+ 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");
349
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;
372
+
373
+ pack_data = git_mwindow_open(&p->mwf, w_cursor, offset, 20, left);
363
374
 
364
- return git_mwindow_open(&p->mwf, w_cursor, offset, 20, left);
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
 
@@ -507,7 +556,7 @@ int git_packfile_resolve_header(
507
556
 
508
557
  while (type == GIT_OBJECT_OFS_DELTA || type == GIT_OBJECT_REF_DELTA) {
509
558
  curpos = base_offset;
510
- error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
559
+ error = git_packfile_unpack_header(&size, &type, p, &w_curs, &curpos);
511
560
  if (error < 0)
512
561
  return error;
513
562
  if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
@@ -578,8 +627,7 @@ static int pack_dependency_chain(git_dependency_chain *chain_out,
578
627
 
579
628
  elem->base_key = obj_offset;
580
629
 
581
- error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
582
-
630
+ error = git_packfile_unpack_header(&size, &type, p, &w_curs, &curpos);
583
631
  if (error < 0)
584
632
  goto on_error;
585
633
 
@@ -630,6 +678,25 @@ int git_packfile_unpack(
630
678
  size_t stack_size = 0, elem_pos, alloclen;
631
679
  git_object_t base_type;
632
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
+
633
700
  /*
634
701
  * TODO: optionally check the CRC on the packfile
635
702
  */
@@ -692,7 +759,7 @@ int git_packfile_unpack(
692
759
  GIT_ERROR_CHECK_ALLOC(obj->data);
693
760
 
694
761
  memcpy(obj->data, data, obj->len + 1);
695
- git_atomic_dec(&cached->refcount);
762
+ git_atomic32_dec(&cached->refcount);
696
763
  goto cleanup;
697
764
  }
698
765
 
@@ -740,7 +807,7 @@ int git_packfile_unpack(
740
807
  }
741
808
 
742
809
  if (cached) {
743
- git_atomic_dec(&cached->refcount);
810
+ git_atomic32_dec(&cached->refcount);
744
811
  cached = NULL;
745
812
  }
746
813
 
@@ -754,7 +821,7 @@ cleanup:
754
821
  if (error < 0) {
755
822
  git__free(obj->data);
756
823
  if (cached)
757
- git_atomic_dec(&cached->refcount);
824
+ git_atomic32_dec(&cached->refcount);
758
825
  }
759
826
 
760
827
  if (elem)
@@ -904,7 +971,7 @@ int get_delta_base(
904
971
  off64_t base_offset;
905
972
  git_oid unused;
906
973
 
907
- assert(delta_base_out);
974
+ GIT_ASSERT_ARG(delta_base_out);
908
975
 
909
976
  base_info = pack_window_open(p, w_curs, *curpos, &left);
910
977
  /* Assumption: the only reason this would fail is because the file is too small */
@@ -976,63 +1043,63 @@ int get_delta_base(
976
1043
  *
977
1044
  ***********************************************************/
978
1045
 
979
- 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)
980
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
+ }
981
1059
  if (p->mwf.fd >= 0) {
982
- git_mwindow_free_all_locked(&p->mwf);
1060
+ git_mwindow_free_all(&p->mwf);
983
1061
  p_close(p->mwf.fd);
984
1062
  p->mwf.fd = -1;
985
1063
  }
1064
+ if (locked)
1065
+ git_mutex_unlock(&p->lock);
986
1066
 
987
1067
  if (unlink_packfile)
988
1068
  p_unlink(p->pack_name);
989
- }
990
-
991
- void git_packfile_free(struct git_pack_file *p)
992
- {
993
- if (!p)
994
- return;
995
-
996
- cache_free(&p->bases);
997
-
998
- git_packfile_close(p, false);
999
1069
 
1000
1070
  pack_index_free(p);
1001
1071
 
1002
1072
  git__free(p->bad_object_sha1);
1003
1073
 
1004
- git_mutex_free(&p->lock);
1005
1074
  git_mutex_free(&p->bases.lock);
1075
+ git_mutex_free(&p->mwf.lock);
1076
+ git_mutex_free(&p->lock);
1006
1077
  git__free(p);
1007
1078
  }
1008
1079
 
1009
- 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)
1010
1082
  {
1011
1083
  struct stat st;
1012
1084
  struct git_pack_header hdr;
1013
1085
  git_oid sha1;
1014
1086
  unsigned char *idx_sha1;
1015
1087
 
1016
- if (p->index_version == -1 && pack_index_open(p) < 0)
1088
+ if (pack_index_open_locked(p) < 0)
1017
1089
  return git_odb__error_notfound("failed to open packfile", NULL, 0);
1018
1090
 
1019
- /* if mwf opened by another thread, return now */
1020
- if (git_mutex_lock(&p->lock) < 0)
1021
- return packfile_error("failed to get lock for open");
1022
-
1023
- if (p->mwf.fd >= 0) {
1024
- git_mutex_unlock(&p->lock);
1091
+ if (p->mwf.fd >= 0)
1025
1092
  return 0;
1026
- }
1027
1093
 
1028
1094
  /* TODO: open with noatime */
1029
1095
  p->mwf.fd = git_futils_open_ro(p->pack_name);
1030
1096
  if (p->mwf.fd < 0)
1031
1097
  goto cleanup;
1032
1098
 
1033
- if (p_fstat(p->mwf.fd, &st) < 0 ||
1034
- 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");
1035
1101
  goto cleanup;
1102
+ }
1036
1103
 
1037
1104
  /* If we created the struct before we had the pack we lack size. */
1038
1105
  if (!p->mwf.size) {
@@ -1071,7 +1138,9 @@ static int packfile_open(struct git_pack_file *p)
1071
1138
  if (git_oid__cmp(&sha1, (git_oid *)idx_sha1) != 0)
1072
1139
  goto cleanup;
1073
1140
 
1074
- git_mutex_unlock(&p->lock);
1141
+ if (git_mwindow_file_register(&p->mwf) < 0)
1142
+ goto cleanup;
1143
+
1075
1144
  return 0;
1076
1145
 
1077
1146
  cleanup:
@@ -1081,8 +1150,6 @@ cleanup:
1081
1150
  p_close(p->mwf.fd);
1082
1151
  p->mwf.fd = -1;
1083
1152
 
1084
- git_mutex_unlock(&p->lock);
1085
-
1086
1153
  return -1;
1087
1154
  }
1088
1155
 
@@ -1152,13 +1219,22 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
1152
1219
  p->mtime = (git_time_t)st.st_mtime;
1153
1220
  p->index_version = -1;
1154
1221
 
1155
- if (git_mutex_init(&p->lock)) {
1222
+ if (git_mutex_init(&p->lock) < 0) {
1156
1223
  git_error_set(GIT_ERROR_OS, "failed to initialize packfile mutex");
1157
1224
  git__free(p);
1158
1225
  return -1;
1159
1226
  }
1160
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
+
1161
1235
  if (cache_init(&p->bases) < 0) {
1236
+ git_mutex_free(&p->mwf.lock);
1237
+ git_mutex_free(&p->lock);
1162
1238
  git__free(p);
1163
1239
  return -1;
1164
1240
  }
@@ -1174,28 +1250,29 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
1174
1250
  *
1175
1251
  ***********************************************************/
1176
1252
 
1177
- 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)
1178
1254
  {
1179
- const unsigned char *index = p->index_map.data;
1180
- 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;
1181
1260
  index += 4 * 256;
1182
- if (p->index_version == 1) {
1261
+ if (p->index_version == 1)
1183
1262
  return ntohl(*((uint32_t *)(index + 24 * n)));
1184
- } else {
1185
- uint32_t off;
1186
- index += 8 + p->num_objects * (20 + 4);
1187
- off = ntohl(*((uint32_t *)(index + 4 * n)));
1188
- if (!(off & 0x80000000))
1189
- return off;
1190
- index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
1191
-
1192
- /* Make sure we're not being sent out of bounds */
1193
- if (index >= end - 8)
1194
- return -1;
1195
1263
 
1196
- return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
1197
- ntohl(*((uint32_t *)(index + 4)));
1198
- }
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)));
1199
1276
  }
1200
1277
 
1201
1278
  static int git__memcmp4(const void *a, const void *b) {
@@ -1207,33 +1284,45 @@ int git_pack_foreach_entry(
1207
1284
  git_odb_foreach_cb cb,
1208
1285
  void *data)
1209
1286
  {
1210
- const unsigned char *index = p->index_map.data, *current;
1287
+ const unsigned char *index, *current;
1211
1288
  uint32_t i;
1212
1289
  int error = 0;
1290
+ git_array_oid_t oids = GIT_ARRAY_INIT;
1291
+ git_oid *oid;
1213
1292
 
1214
- if (index == NULL) {
1215
- if ((error = pack_index_open(p)) < 0)
1216
- return error;
1293
+ if (git_mutex_lock(&p->lock) < 0)
1294
+ return packfile_error("failed to get lock for git_pack_foreach_entry");
1217
1295
 
1218
- assert(p->index_map.data);
1296
+ if ((error = pack_index_open_locked(p)) < 0) {
1297
+ git_mutex_unlock(&p->lock);
1298
+ return error;
1299
+ }
1219
1300
 
1220
- 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;
1221
1305
  }
1222
1306
 
1223
- if (p->index_version > 1) {
1307
+ index = p->index_map.data;
1308
+
1309
+ if (p->index_version > 1)
1224
1310
  index += 8;
1225
- }
1226
1311
 
1227
1312
  index += 4 * 256;
1228
1313
 
1229
1314
  if (p->oids == NULL) {
1230
1315
  git_vector offsets, oids;
1231
1316
 
1232
- 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);
1233
1319
  return error;
1320
+ }
1234
1321
 
1235
- 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);
1236
1324
  return error;
1325
+ }
1237
1326
 
1238
1327
  if (p->index_version > 1) {
1239
1328
  const unsigned char *off = index + 24 * p->num_objects;
@@ -1254,10 +1343,104 @@ int git_pack_foreach_entry(
1254
1343
  p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids);
1255
1344
  }
1256
1345
 
1257
- for (i = 0; i < p->num_objects; i++)
1258
- if ((error = cb(p->oids[i], data)) != 0)
1259
- 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
+ }
1260
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
+ }
1441
+
1442
+ cleanup:
1443
+ git_mutex_unlock(&p->lock);
1261
1444
  return error;
1262
1445
  }
1263
1446
 
@@ -1295,15 +1478,19 @@ static int pack_entry_find_offset(
1295
1478
  int pos, found = 0;
1296
1479
  off64_t offset;
1297
1480
  const unsigned char *current = 0;
1481
+ int error = 0;
1298
1482
 
1299
1483
  *offset_out = 0;
1300
1484
 
1301
- if (p->index_version == -1) {
1302
- int error;
1485
+ if (git_mutex_lock(&p->lock) < 0)
1486
+ return packfile_error("failed to get lock for pack_entry_find_offset");
1303
1487
 
1304
- if ((error = pack_index_open(p)) < 0)
1305
- return error;
1306
- 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;
1307
1494
  }
1308
1495
 
1309
1496
  index = p->index_map.data;
@@ -1357,14 +1544,19 @@ static int pack_entry_find_offset(
1357
1544
  }
1358
1545
  }
1359
1546
 
1360
- if (!found)
1361
- return git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
1362
- if (found > 1)
1363
- 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
+ }
1364
1555
 
1365
- if ((offset = nth_packed_object_offset(p, pos)) < 0) {
1556
+ if ((offset = nth_packed_object_offset_locked(p, pos)) < 0) {
1366
1557
  git_error_set(GIT_ERROR_ODB, "packfile index is corrupt");
1367
- return -1;
1558
+ error = -1;
1559
+ goto cleanup;
1368
1560
  }
1369
1561
 
1370
1562
  *offset_out = offset;
@@ -1379,7 +1571,9 @@ static int pack_entry_find_offset(
1379
1571
  }
1380
1572
  #endif
1381
1573
 
1382
- return 0;
1574
+ cleanup:
1575
+ git_mutex_unlock(&p->lock);
1576
+ return error;
1383
1577
  }
1384
1578
 
1385
1579
  int git_pack_entry_find(
@@ -1392,7 +1586,7 @@ int git_pack_entry_find(
1392
1586
  git_oid found_oid;
1393
1587
  int error;
1394
1588
 
1395
- assert(p);
1589
+ GIT_ASSERT_ARG(p);
1396
1590
 
1397
1591
  if (len == GIT_OID_HEXSZ && p->num_bad_objects) {
1398
1592
  unsigned i;
@@ -1405,10 +1599,26 @@ int git_pack_entry_find(
1405
1599
  if (error < 0)
1406
1600
  return error;
1407
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
+
1408
1614
  /* we found a unique entry in the index;
1409
1615
  * make sure the packfile backing the index
1410
1616
  * still exists on disk */
1411
- 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)
1412
1622
  return error;
1413
1623
 
1414
1624
  e->offset = offset;