summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuang Li <yuangli88@hotmail.com>2022-06-24 13:21:48 +0100
committerYuang Li <yuangli88@hotmail.com>2022-06-24 13:21:48 +0100
commite07aa9c3c4f5d0462662e2c7fc1ae8120a29d740 (patch)
treeda61eddd173c43d09a6545f75b35360f0a48f68b
parent79af067665c37b6dc0b31edb35596c362b0cd9a0 (diff)
parentb7bad55e4bb0a285b073ba5e02b01d3f522fc95d (diff)
downloadlibgit2-e07aa9c3c4f5d0462662e2c7fc1ae8120a29d740.tar.gz
Merge branch 'main' into pr/pks-t/5254
-rw-r--r--.devcontainer/devcontainer.json3
-rwxr-xr-x.devcontainer/setup.sh9
-rw-r--r--.gitattributes1
-rw-r--r--.github/workflows/codeql.yml36
-rw-r--r--.github/workflows/main.yml169
-rw-r--r--.github/workflows/nightly.yml339
-rw-r--r--.gitignore5
-rw-r--r--.vscode/launch.json27
-rw-r--r--.vscode/tasks.json27
-rw-r--r--CMakeLists.txt29
-rw-r--r--COPYING110
-rw-r--r--README.md43
-rw-r--r--azure-pipelines.yml190
-rw-r--r--azure-pipelines/bash.yml17
-rw-r--r--azure-pipelines/coverity.yml26
-rw-r--r--azure-pipelines/docker.yml51
-rw-r--r--azure-pipelines/docker/entrypoint.sh4
-rw-r--r--azure-pipelines/nightly.yml219
-rwxr-xr-xci/build.sh (renamed from azure-pipelines/build.sh)30
-rwxr-xr-xci/coverity.sh (renamed from azure-pipelines/coverity.sh)0
-rw-r--r--ci/docker/bionic (renamed from azure-pipelines/docker/bionic)15
-rw-r--r--ci/docker/centos755
-rw-r--r--ci/docker/centos849
-rw-r--r--ci/docker/docurium (renamed from azure-pipelines/docker/docurium)4
-rw-r--r--ci/docker/focal79
-rw-r--r--ci/docker/xenial (renamed from azure-pipelines/docker/xenial)16
-rwxr-xr-xci/getcontainer.sh (renamed from azure-pipelines/getcontainer.sh)28
-rwxr-xr-xci/setup-mingw.sh (renamed from azure-pipelines/setup-mingw.sh)4
-rwxr-xr-xci/setup-osx.sh (renamed from azure-pipelines/setup-osx.sh)0
-rwxr-xr-xci/test.sh (renamed from azure-pipelines/test.sh)19
-rw-r--r--cmake/CheckPrototypeDefinition.c.in29
-rw-r--r--cmake/CheckPrototypeDefinition.cmake96
-rw-r--r--cmake/FindLibSSH2.cmake13
-rw-r--r--cmake/Findfutimens.cmake14
-rw-r--r--cmake/SelectHTTPSBackend.cmake4
-rw-r--r--cmake/SelectHashes.cmake1
-rw-r--r--deps/chromium-zlib/CMakeLists.txt101
-rw-r--r--deps/ntlmclient/CMakeLists.txt23
-rw-r--r--deps/ntlmclient/compat.h27
-rw-r--r--deps/ntlmclient/crypt.h23
-rw-r--r--deps/ntlmclient/crypt_commoncrypto.c40
-rw-r--r--deps/ntlmclient/crypt_commoncrypto.h6
-rw-r--r--deps/ntlmclient/crypt_mbedtls.c73
-rw-r--r--deps/ntlmclient/crypt_mbedtls.h7
-rw-r--r--deps/ntlmclient/crypt_openssl.c229
-rw-r--r--deps/ntlmclient/crypt_openssl.h79
-rw-r--r--deps/ntlmclient/ntlm.c299
-rw-r--r--deps/ntlmclient/ntlm.h22
-rw-r--r--deps/ntlmclient/ntlmclient.h19
-rw-r--r--deps/ntlmclient/unicode.h14
-rw-r--r--deps/ntlmclient/unicode_builtin.c43
-rw-r--r--deps/ntlmclient/unicode_builtin.h20
-rw-r--r--deps/ntlmclient/unicode_iconv.c80
-rw-r--r--deps/ntlmclient/unicode_iconv.h22
-rw-r--r--deps/ntlmclient/util.c16
-rw-r--r--deps/ntlmclient/util.h3
-rw-r--r--deps/pcre/LICENCE93
-rw-r--r--deps/pcre/pcre.h4
-rw-r--r--deps/pcre/pcre_compile.c46
-rw-r--r--deps/pcre/pcre_jit_compile.c8
-rw-r--r--deps/pcre/pcreposix.c5
-rw-r--r--deps/zlib/deflate.c1
-rw-r--r--docs/changelog.md338
-rw-r--r--docs/coding-style.md2
-rw-r--r--docs/contributing.md10
-rw-r--r--docs/release.md6
-rw-r--r--docs/win32-longpaths.md36
-rw-r--r--examples/blame.c2
-rw-r--r--examples/checkout.c2
-rw-r--r--examples/common.h2
-rw-r--r--examples/config.c9
-rw-r--r--examples/general.c7
-rw-r--r--examples/log.c6
-rw-r--r--examples/rev-list.c2
-rw-r--r--examples/rev-parse.c6
-rw-r--r--examples/tag.c4
-rw-r--r--fuzzers/commit_graph_fuzzer.c80
-rw-r--r--fuzzers/corpora/commit_graph/005682ce1cb5b20c20fccf4be5dbd47ca399e53ebin0 -> 1092 bytes
-rw-r--r--fuzzers/corpora/commit_graph/00574fc29fd1323e93d18d625cde80d3ea20e8ccbin0 -> 2428 bytes
-rw-r--r--fuzzers/corpora/commit_graph/00916ec21ddbd3c622bde6e4dc824250176b9e88bin0 -> 223 bytes
-rw-r--r--fuzzers/corpora/commit_graph/00b6dde4b8d5e68a5ec40d88c39134cf2f1f8bc3bin0 -> 82 bytes
-rw-r--r--fuzzers/corpora/commit_graph/020f0e77e42d8b3810019050f4c5ceadd205b37cbin0 -> 965 bytes
-rw-r--r--fuzzers/corpora/commit_graph/02739c05abc1715fac1ce995b532e482abc8d4dcbin0 -> 982 bytes
-rw-r--r--fuzzers/corpora/commit_graph/02a276faa5dc8c7df5b82a57ab6cd195a13e4ae0bin0 -> 671 bytes
-rw-r--r--fuzzers/corpora/commit_graph/02de15987d68a97db3d9fd964cfd785bcbd54d3abin0 -> 96 bytes
-rw-r--r--fuzzers/corpora/commit_graph/02e106f97a91b1d3aef4dd2d31368ae5077bd42bbin0 -> 146 bytes
-rw-r--r--fuzzers/corpora/commit_graph/038555bcb4cc2daf764840f79ebce4023bdb7670bin0 -> 240 bytes
-rw-r--r--fuzzers/corpora/commit_graph/04c159a04b0732e04ac4c59ed3356860af8dffcebin0 -> 1385 bytes
-rw-r--r--fuzzers/corpora/commit_graph/0560ec993882ffbd8d46dcab0ed430089c4f2aa1bin0 -> 86 bytes
-rw-r--r--fuzzers/corpora/commit_graph/059b3aab3fde6b4c9404aff83fed638596f594bbbin0 -> 90 bytes
-rw-r--r--fuzzers/corpora/commit_graph/06168e726aa0260f520165be4ea0c88244831049bin0 -> 430 bytes
-rw-r--r--fuzzers/corpora/commit_graph/066d1ec700a526b97009cedd0305b6a47242fababin0 -> 1980 bytes
-rw-r--r--fuzzers/corpora/commit_graph/086a5f8cbfa9f058b5c938a6eb724c9e4c5f84f3bin0 -> 68 bytes
-rw-r--r--fuzzers/corpora/commit_graph/089313c698f3e351433e9a45af2ace1d85b9673ebin0 -> 86 bytes
-rw-r--r--fuzzers/corpora/commit_graph/092eb973a771fa14cf0b567d65bd2c99130f543ebin0 -> 32 bytes
-rw-r--r--fuzzers/corpora/commit_graph/094b8cd1aa3e40b1f9ff83680892d52e246df0f8bin0 -> 155 bytes
-rw-r--r--fuzzers/corpora/commit_graph/0ce990c9c2ec121b8c78ba2bdf84679e04c0bdaebin0 -> 278 bytes
-rw-r--r--fuzzers/corpora/commit_graph/0dd0770c34fcf6b1f13219450190616d344db021bin0 -> 264 bytes
-rw-r--r--fuzzers/corpora/commit_graph/0e2b2e6a32733b8a625bc7e812e2ea508d69a5e4bin0 -> 2221 bytes
-rw-r--r--fuzzers/corpora/commit_graph/0e8d0bd07c543d708aecaca377106492b7a74fa3bin0 -> 287 bytes
-rw-r--r--fuzzers/corpora/commit_graph/0f0d16e1b8c8671dbe1074115c1d86aa9b359e7ebin0 -> 551 bytes
-rw-r--r--fuzzers/corpora/commit_graph/102ef78036de5a30927e7f751377b05441c41a08bin0 -> 1980 bytes
-rw-r--r--fuzzers/corpora/commit_graph/10494e7cc9cb8dff289c431d7560bcee0d1b14edbin0 -> 157 bytes
-rw-r--r--fuzzers/corpora/commit_graph/107b11d86381345f50aa19b8485477a870ff399fbin0 -> 2908 bytes
-rw-r--r--fuzzers/corpora/commit_graph/10bb37e18fb3c0897dabacf9c464b4d324007dc3bin0 -> 346 bytes
-rw-r--r--fuzzers/corpora/commit_graph/10ee715f64b08549c3e8261204276694728eb841bin0 -> 174 bytes
-rw-r--r--fuzzers/corpora/commit_graph/123e4eeb7a731f48d06e336b4d29af717f8b6550bin0 -> 123 bytes
-rw-r--r--fuzzers/corpora/commit_graph/125a228afb923970e0a6d4412f7257ba998594a1bin0 -> 283 bytes
-rw-r--r--fuzzers/corpora/commit_graph/130d96c16fba06dcbe7e2a661ab959a3274a4bd9bin0 -> 214 bytes
-rw-r--r--fuzzers/corpora/commit_graph/131c5a2fec55cb0d63f7dc055d6fad5f3dc3c974bin0 -> 408 bytes
-rw-r--r--fuzzers/corpora/commit_graph/13e562d61acb3aa36260a819a00b07ff16450335bin0 -> 3784 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1414e6e8ab6bad1b5c51fed807c514a9d6575e66bin0 -> 584 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1432d191846ae2d0e381813efcfacff2f1dba0e4bin0 -> 475 bytes
-rw-r--r--fuzzers/corpora/commit_graph/14a84cdc6f8d432be4cd3d3eafce92ae385e472fbin0 -> 472 bytes
-rw-r--r--fuzzers/corpora/commit_graph/14e3e735dba88791f2cadd6e0dc5d662a104a6d7bin0 -> 214 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1574abb020203103ea629d677edd21c967fc0f4cbin0 -> 96 bytes
-rw-r--r--fuzzers/corpora/commit_graph/169cc492ba94948a6206765436881a1a0c601780bin0 -> 199 bytes
-rw-r--r--fuzzers/corpora/commit_graph/16a2130c1d75129f3bae3bf8f2c2de41fb3533c0bin0 -> 351 bytes
-rw-r--r--fuzzers/corpora/commit_graph/16ba602eadfc9a3f74c0845394eda0de42b61571bin0 -> 345 bytes
-rw-r--r--fuzzers/corpora/commit_graph/17555fb2dfc444d171ba686667d72e388bd6c041bin0 -> 63 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1a10450d99c1e53d9b7f97b8014cb7fc01906ef2bin0 -> 956 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1af670b5515231fc04b2be9038ee30a7e066b09bbin0 -> 650 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1b72cfa68259e3f3b3802906902a0a29368f86b5bin0 -> 227 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1c62ac5d632aa9e449a4335b675941107d8825aebin0 -> 497 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1d95b5db2f802011b33d10212a66fbe40827dfd4bin0 -> 284 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1e068537ce1211a325aab42ae1263a109131c9f9bin0 -> 81 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1e9c882c9d33304a5791ef6c98eee65e142bd7fdbin0 -> 114 bytes
-rw-r--r--fuzzers/corpora/commit_graph/1f54935df929403a29e77591c97f767d94871aeabin0 -> 202 bytes
-rw-r--r--fuzzers/corpora/commit_graph/206015659641771bb0d668728c2fdc4209e65ddabin0 -> 152 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2096493a2bcc2d15b7ae5bf3112fe49c39976ad8bin0 -> 146 bytes
-rw-r--r--fuzzers/corpora/commit_graph/209b74e08abe8c787b7c5ba81e51cb69c57ecdedbin0 -> 519 bytes
-rw-r--r--fuzzers/corpora/commit_graph/21137876575fbca357fc0c96db1de73c6737e1aebin0 -> 32 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2143d9db9802f076c72a71184cd9d0cb4581e9e7bin0 -> 466 bytes
-rw-r--r--fuzzers/corpora/commit_graph/21a52a5282145407d951ac73c2ff27876783899dbin0 -> 408 bytes
-rw-r--r--fuzzers/corpora/commit_graph/21d5c8c8ac3a09bcba5388c472df32795986a5cb1
-rw-r--r--fuzzers/corpora/commit_graph/22170d1110a1c18009b7feb21a470681f55e85fbbin0 -> 469 bytes
-rw-r--r--fuzzers/corpora/commit_graph/22f55dff94785f24252d7a070f713840f59b0870bin0 -> 609 bytes
-rw-r--r--fuzzers/corpora/commit_graph/23d10ee9694e1c66bedc7060990f19a2ac3eaee3bin0 -> 766 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2435430ca19502c3b0ec4987508d4a8fbdbc898cbin0 -> 349 bytes
-rw-r--r--fuzzers/corpora/commit_graph/244d2ea0c5c3117000b599cfab37680ba8f04513bin0 -> 216 bytes
-rw-r--r--fuzzers/corpora/commit_graph/248bf94143d150da2459cfdca099c30c6daff00abin0 -> 1049 bytes
-rw-r--r--fuzzers/corpora/commit_graph/25bc53498129bb3717671f00c355d2637a91c86abin0 -> 531 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2614f60da2d7e291501397238366d27513bff773bin0 -> 80 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2651b3d5a8b4616b1faa81dabe27ab2712a27561bin0 -> 787 bytes
-rw-r--r--fuzzers/corpora/commit_graph/270257a2872b33dd13c4fd466cbc1ae67d613f9bbin0 -> 600 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2830c6244c74656f6c5649c8226953905a582a38bin0 -> 353 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2889a85c07c20551ff0b97fc640e3c91b33aa4a1bin0 -> 1067 bytes
-rw-r--r--fuzzers/corpora/commit_graph/295ce43fdd56def8948d1ba2bfa7fdf0c47b5318bin0 -> 2227 bytes
-rw-r--r--fuzzers/corpora/commit_graph/296cbb94c4e68ab86972a174405308ee34d0c40fbin0 -> 3003 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2975adf222cad108ec90d8225fd655e30e3bf253bin0 -> 407 bytes
-rw-r--r--fuzzers/corpora/commit_graph/29f5d27760c9254ab4db661a6cd0323dd11c34cabin0 -> 282 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2a359fb09eaad968e57d353453908027645873d1bin0 -> 190 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2a6b65a8d6c28febaa081d220a4433f8366d02bcbin0 -> 3325 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2b14dcade4d0919b0a17830fe353738015f492a6bin0 -> 214 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2b298a13abbd9829e965424a1486baa13d4166c4bin0 -> 146 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2b44d8cd8e70e25172b4c740ebe38ef411c965b3bin0 -> 168 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2b590c4e61fdfcf21c017b29440747a1894b1534bin0 -> 217 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2becb18a971ae30e1a8f6680982fd7305708caa0bin0 -> 324 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2bf78b02099a1fe4ce50d065254e843ca55e280fbin0 -> 412 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2c1541ecd01aa7b9e99bccfe9804198b3e79f118bin0 -> 2267 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2c6798057af5894c27631ff63e845fe1e4bdc9eebin0 -> 221 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2cf7eb7fe489e5acd64df755e820c871784c2ba1bin0 -> 182 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2d49ba35ca404baa0d593925f36a81ce53943c8dbin0 -> 466 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2d507d42ca43ffc2f3c8892826e1db74144ec096bin0 -> 2772 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2e4da693e3e336d2b1a40311a7ccf94def035b6bbin0 -> 280 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2e71ff86128b5618f0f067c407a76ff645ae2019bin0 -> 602 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2eb777c6d7e6ee9bd7a44e37372595043aad596bbin0 -> 141 bytes
-rw-r--r--fuzzers/corpora/commit_graph/2ec3ebffba165b9dd49e755a9e77e23aed796628bin0 -> 138 bytes
-rw-r--r--fuzzers/corpora/commit_graph/302703e3b0d74219868aca39ee7593944c0b2400bin0 -> 126 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3048c6908dc3176707fa8bcb0196824e3358357abin0 -> 395 bytes
-rw-r--r--fuzzers/corpora/commit_graph/30616cb39d3ad6060324fada03709d611ad28d5cbin0 -> 2593 bytes
-rw-r--r--fuzzers/corpora/commit_graph/306beadd9b3135a00037323760eb5377c88a403ebin0 -> 315 bytes
-rw-r--r--fuzzers/corpora/commit_graph/31464a6fbad023923a7e4700fc11564e811bcbd2bin0 -> 2182 bytes
-rw-r--r--fuzzers/corpora/commit_graph/317f4bcfecf066961ef1982d551cd14e63c9f008bin0 -> 215 bytes
-rw-r--r--fuzzers/corpora/commit_graph/31b2248faaabbec69a06098c8cb0f69c5d0aa208bin0 -> 3848 bytes
-rw-r--r--fuzzers/corpora/commit_graph/31d1c3d1147385d58dbe6f82898a5523320fbcacbin0 -> 415 bytes
-rw-r--r--fuzzers/corpora/commit_graph/32c9bc1616a78a230a3724abc02150db1cc40aa0bin0 -> 152 bytes
-rw-r--r--fuzzers/corpora/commit_graph/331e2866416b091252f0299e98d32cfb29237029bin0 -> 5 bytes
-rw-r--r--fuzzers/corpora/commit_graph/331eb3876dd2f3f0bd51f380ac431d86d6e3bb5ebin0 -> 1072 bytes
-rw-r--r--fuzzers/corpora/commit_graph/346bd6eaeadeafcb840ff9441614b309330db63ebin0 -> 2850 bytes
-rw-r--r--fuzzers/corpora/commit_graph/349931f447981f21476481448576e805c093a25bbin0 -> 269 bytes
-rw-r--r--fuzzers/corpora/commit_graph/34a2da1e9adaac1b4be1d40b1ece81fe00643d49bin0 -> 1302 bytes
-rw-r--r--fuzzers/corpora/commit_graph/34bb8f475e7384a8a39618fd15fdc5fb1b12c1a1bin0 -> 391 bytes
-rw-r--r--fuzzers/corpora/commit_graph/351a036c6eb95db9364706b861f7e75ad26194e8bin0 -> 1980 bytes
-rw-r--r--fuzzers/corpora/commit_graph/355452c1da8e7689d816d67cdde040b5df7eabd7bin0 -> 298 bytes
-rw-r--r--fuzzers/corpora/commit_graph/35c157ad2b100b4f334cddcf3dea6ef2d85462bebin0 -> 127 bytes
-rw-r--r--fuzzers/corpora/commit_graph/36a81a45eabfcf53e1ae0361aa234791e2fdb750bin0 -> 128 bytes
-rw-r--r--fuzzers/corpora/commit_graph/36ee20f6dbeb3a34e91eafbbe2e379f9ac6cfa43bin0 -> 86 bytes
-rw-r--r--fuzzers/corpora/commit_graph/377627c19bcac6adc880202048a9eac07b5417d4bin0 -> 350 bytes
-rw-r--r--fuzzers/corpora/commit_graph/38747e7c8bec2f9c923739d50ba54ff88ba6503fbin0 -> 603 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3945843a6fab2ec71030f09b237c125b97cd3ea5bin0 -> 601 bytes
-rw-r--r--fuzzers/corpora/commit_graph/396321d39b82ffaccbc64115117df7e822b0f515bin0 -> 207 bytes
-rw-r--r--fuzzers/corpora/commit_graph/396e78eb9b54e2cefb52cd76a22137c8abd6cbcfbin0 -> 868 bytes
-rw-r--r--fuzzers/corpora/commit_graph/39c1ab66035adc104cd06a6d98b77668172d21afbin0 -> 243 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3a1078c35f5401ce09b5ba921fc348dde37530bbbin0 -> 260 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3aa3d8f40392d1c863d23799b8ec0aedc7191302bin0 -> 192 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3b08c505601271cb92345ec7f0ff0b28daf90a9cbin0 -> 525 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3b41702587be45f678b36823ad2f7e5002337dc4bin0 -> 343 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3b69108cc919aba0248f9b864d4e71c5f6d1931ebin0 -> 208 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3b90507501bb3bcfe0094f9c92cc2869f1a7dda5bin0 -> 135 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3bc7fe44c3a1464dd35a4d22b482f46cdeda0405bin0 -> 188 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3ce99994986efb6df3f3568423e0077b53c7ef78bin0 -> 1178 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3d6cb3ba21181c9f0ab08b2608eab773f36773f2bin0 -> 279 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3d8ec41450b943d5dea73fb1e393960b03d7c3b9bin0 -> 2210 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3e29e8baaac0f6c7e4cf3d5adca2ab3a2c491ac7bin0 -> 310 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3e9469b3c68ba334671aacda7a7669b0e97b74d6bin0 -> 76 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3eeda3bfa7abef69911c94520c009a08c49b9942bin0 -> 237 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3f0f5021016451b57f673d0603cd9e4830c2198dbin0 -> 473 bytes
-rw-r--r--fuzzers/corpora/commit_graph/3f46540fbd94bf0337c1d0d7437ec992a3568f09bin0 -> 178 bytes
-rw-r--r--fuzzers/corpora/commit_graph/402d9c25d5833d42630882ab5c57833266bef785bin0 -> 617 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4048bb3c26d67c345630ff9e86db551a3add6549bin0 -> 1308 bytes
-rw-r--r--fuzzers/corpora/commit_graph/40792f23c1281842dab671e8b213fc408d1ec39fbin0 -> 816 bytes
-rw-r--r--fuzzers/corpora/commit_graph/41cd0b5d9a9540947b7b1841a55e4c11bd4346a2bin0 -> 32 bytes
-rw-r--r--fuzzers/corpora/commit_graph/41d86e5ea3df4a0de60d42aeb16e2a5599aedeaebin0 -> 465 bytes
-rw-r--r--fuzzers/corpora/commit_graph/42b4e5430b2b1b17a361067fb9dd33ab74e52232bin0 -> 202 bytes
-rw-r--r--fuzzers/corpora/commit_graph/42ef1c9d234b90acaf1651d930fc52d5f8f158f2bin0 -> 275 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4570c8ff26d7f31afe73b3d9a35a29bc1274d68abin0 -> 153 bytes
-rw-r--r--fuzzers/corpora/commit_graph/45cf4751a5929930a7c30ec10134434b9ee13c3dbin0 -> 2873 bytes
-rw-r--r--fuzzers/corpora/commit_graph/46e9d351dd5bb71f7d4d8f15b3fad312c781452ebin0 -> 164 bytes
-rw-r--r--fuzzers/corpora/commit_graph/472421633b984556b96bc20f1fcf7a98c25736f3bin0 -> 322 bytes
-rw-r--r--fuzzers/corpora/commit_graph/47f35b91699caee098cacdde0161ffab21bdfc57bin0 -> 123 bytes
-rw-r--r--fuzzers/corpora/commit_graph/48b9da327218f9409287687a43b7eead4789a588bin0 -> 217 bytes
-rw-r--r--fuzzers/corpora/commit_graph/48d14fca326d5d591d18d34c2821a457277819a2bin0 -> 153 bytes
-rw-r--r--fuzzers/corpora/commit_graph/48f3a33e2a027f5735d0a333ec4acd5a2aa57118bin0 -> 2166 bytes
-rw-r--r--fuzzers/corpora/commit_graph/49e0eee24eab094a9c62f6b37b6ba01f8aece4e4bin0 -> 2095 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4b45bcb707d2a0bc23b415e9bc3d7eb1f7f0e188bin0 -> 659 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4c428300fe4866fe81cff02ad4bc14b6848f7f73bin0 -> 281 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4d69c567df2e858c5f248b3fc8e4a9c04f02481cbin0 -> 696 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4d88b6c9b513d5db2e07313a39b43d112d3d4562bin0 -> 66 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4da73370cf854ef8bd08c7f79b92a187cdbff278bin0 -> 81 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4e4b2827351bbfd414b718052a8f950a9e3eb7eebin0 -> 738 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4ed43f7d3c0305461edcbc86f62e0c6ad56df01ebin0 -> 804 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4f011529809e88205421fa8ce39dcc025293bcb8bin0 -> 216 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4f1928b6376369ab6acf8a282284366cc3bf71efbin0 -> 2654 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4f669eca3416c44f0d003ef2720d03e697e2230ebin0 -> 80 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4f750f24ecb5080bea2845061cfd3ce4529d30eebin0 -> 280 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4fab9bb2bacf562e65f4a8681c429e6ea92aaed7bin0 -> 1863 bytes
-rw-r--r--fuzzers/corpora/commit_graph/4fd757c7251c17413b3005fb38aee0fd029d89ecbin0 -> 861 bytes
-rw-r--r--fuzzers/corpora/commit_graph/506092de91dcf93254cdd5ad9e02a953a38099eabin0 -> 280 bytes
-rw-r--r--fuzzers/corpora/commit_graph/50e934fb52d9bc5cd2a531adced1cad7f102a112bin0 -> 385 bytes
-rw-r--r--fuzzers/corpora/commit_graph/512e49a9e789656964988950009e6534907e6317bin0 -> 2021 bytes
-rw-r--r--fuzzers/corpora/commit_graph/51404149f1ea30ee6959fafe81a52acabed97e9ebin0 -> 607 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5150f8a67399ee16178a2b08198cf91a90c0e53ebin0 -> 538 bytes
-rw-r--r--fuzzers/corpora/commit_graph/51a1fd23dfe5a8062cd4601d235509247f3bc2dcbin0 -> 218 bytes
-rw-r--r--fuzzers/corpora/commit_graph/51a963486f041a60c422f0dd6da3b69c52f12fb7bin0 -> 131 bytes
-rw-r--r--fuzzers/corpora/commit_graph/51fbf57a2a35ec33164838fa254fe605a3c868e9bin0 -> 986 bytes
-rw-r--r--fuzzers/corpora/commit_graph/53068b9f9cb54bb52d076e9602ccd55f169ef39abin0 -> 410 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5314619e15fa5ee67df44481b8213a53786d39c5bin0 -> 146 bytes
-rw-r--r--fuzzers/corpora/commit_graph/533f5f00275968129846522fe01e2819746272ebbin0 -> 80 bytes
-rw-r--r--fuzzers/corpora/commit_graph/53a62799135c282435a17e032deda03eaf9daf0fbin0 -> 83 bytes
-rw-r--r--fuzzers/corpora/commit_graph/53c9d5cd849977e523d92dd2d639e9b0e721be50bin0 -> 680 bytes
-rw-r--r--fuzzers/corpora/commit_graph/54767a0bb3b96d39f5b2004ce3f274465f1a927ebin0 -> 2022 bytes
-rw-r--r--fuzzers/corpora/commit_graph/548de37dbe6a3829b73d976996ec9838cf608554bin0 -> 296 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5522cefa54b798ea4aba8ef2a42ad248a7fb02eebin0 -> 60 bytes
-rw-r--r--fuzzers/corpora/commit_graph/554fab3eef5d8709f06d1d4319efe5c0c437421bbin0 -> 192 bytes
-rw-r--r--fuzzers/corpora/commit_graph/567fe73919dae39b0bcb78b03d655643a71714a8bin0 -> 409 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5717a281aa722ee4a32dfa1cc72fc5d6081f6755bin0 -> 2126 bytes
-rw-r--r--fuzzers/corpora/commit_graph/577d814e0be43df9321c5b27119c398bd00a00c5bin0 -> 317 bytes
-rw-r--r--fuzzers/corpora/commit_graph/58680611707c6188f9f067f8747b699cd2fe82d3bin0 -> 453 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5915b7f91dd43ec37a4718061c90cbec2686b916bin0 -> 1339 bytes
-rw-r--r--fuzzers/corpora/commit_graph/599516e368ff621dd06d8450837350f4e9558c38bin0 -> 452 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5a2d01d141e4d523e718c30e20cb07c3ad98f33dbin0 -> 308 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5a9803ef8cd88d1e8f1d6e5920b8afd170cafb11bin0 -> 280 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5ba93c9db0cff93f52b521d7420e43f6eda2784fbin0 -> 1 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5bf0ca772092e6fa34b6822f61a1b1c3d7f2c6e3bin0 -> 318 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5cfbfb3e12b629dc9f74baf0a8741345ec288795bin0 -> 802 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5d8cc97b739c39820b761b6551d34dd647da6816bin0 -> 342 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5dcbb3e1c2fc9a191dd3f3443b86f6bc38c39e37bin0 -> 176 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5ec17d081aef9872f746e88ad8b03553719f9c36bin0 -> 402 bytes
-rw-r--r--fuzzers/corpora/commit_graph/5f88e3ba60c11be25c47a842763d8870d23cc7f2bin0 -> 675 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6045e4d2bf85013c78a32e71b014ba3d4a4b7c61bin0 -> 540 bytes
-rw-r--r--fuzzers/corpora/commit_graph/615c7ba7ffbce955ffd964682e2a0f7ef3c767e4bin0 -> 86 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6189f29cbbe88ac6cb32fdefecda1bd6194332a6bin0 -> 1007 bytes
-rw-r--r--fuzzers/corpora/commit_graph/627224cb8484c62992dcbc4cdebdbfa48a3c021abin0 -> 153 bytes
-rw-r--r--fuzzers/corpora/commit_graph/629fff0962d298a7283a3d1e1d1b940dfef9b315bin0 -> 251 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6322594cff2a99d0abb1139e6a43b06df76d539abin0 -> 284 bytes
-rw-r--r--fuzzers/corpora/commit_graph/63de5e8e042222d53bf05640c87da376aefb76ccbin0 -> 2084 bytes
-rw-r--r--fuzzers/corpora/commit_graph/647dbb1d05fe0fab685bfe126bd9ac3a12b6bccfbin0 -> 279 bytes
-rw-r--r--fuzzers/corpora/commit_graph/647e5e265d8d1079784fc2a3da25f7ba58126acdbin0 -> 73 bytes
-rw-r--r--fuzzers/corpora/commit_graph/653bd480dfd1e5f4bdca702aba3dfd8da0c204b7bin0 -> 103 bytes
-rw-r--r--fuzzers/corpora/commit_graph/65485740a465377213c80fa68028727f281299fbbin0 -> 80 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6551f8c8c3028006d0cc4997943df8a86ee3f598bin0 -> 444 bytes
-rw-r--r--fuzzers/corpora/commit_graph/67799e79d33883510f85ae9705ab3932862128a2bin0 -> 991 bytes
-rw-r--r--fuzzers/corpora/commit_graph/67b475481e5a21351b49789874adbc988aefd64cbin0 -> 89 bytes
-rw-r--r--fuzzers/corpora/commit_graph/67e5a649967dee002d1c181e079748c404e29767bin0 -> 1116 bytes
-rw-r--r--fuzzers/corpora/commit_graph/687424a4a31a66a78d1637c680c9c10746741007bin0 -> 1573 bytes
-rw-r--r--fuzzers/corpora/commit_graph/68fa6dd52832657cb8dd7e1485d6fbafd4e93903bin0 -> 536 bytes
-rw-r--r--fuzzers/corpora/commit_graph/691696af1c042115f4d9f9b8e24f7b8c06ed189bbin0 -> 284 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6a80152f9b1afa3a3080bf3f6aa48e84c2e18497bin0 -> 2116 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6af27e4cf4c7bcce128a5949ee27fc73ab2cc71ebin0 -> 1620 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6afd8f82d5639b774de0dfd418ae85322f4168ddbin0 -> 253 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6c64a9e26e0e1480bb5e60b7044ca6ce17104a80bin0 -> 1043 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6c850c17db130ca0152f7c75562fa191f7ef89debin0 -> 41 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6c9afe4527371a2baf33c5e220e4ca21a3207f94bin0 -> 640 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6ce3d40b0225923a7f4123a919b1c5d70841fad7bin0 -> 268 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6cfd064aa6197813eb18f38df967ae4cdba9c6dabin0 -> 357 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6e6675676c53bcddc870e06605d2432e3429f224bin0 -> 616 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6e6e82579b7abae2b43d90448d3f2ead4dfcba78bin0 -> 2115 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6f13d23c75a562eddefafe85e208e602832294e2bin0 -> 236 bytes
-rw-r--r--fuzzers/corpora/commit_graph/6fed59b0472927f5d2396d0ee4d7fd13579377cebin0 -> 751 bytes
-rw-r--r--fuzzers/corpora/commit_graph/71f7724196f9f8fcfe3ee0161a84893bb9c4ab11bin0 -> 795 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7335ecb1d41e713bf3909adf5802b90e22bc1581bin0 -> 153 bytes
-rw-r--r--fuzzers/corpora/commit_graph/73afaa73175f461e1d19d5138e055c1649926dfebin0 -> 544 bytes
-rw-r--r--fuzzers/corpora/commit_graph/73e2fcb45c4df90d19091056b235e7a317631a62bin0 -> 150 bytes
-rw-r--r--fuzzers/corpora/commit_graph/741cb2d5ae11b0a9e0608b58ec7284d75129a1f2bin0 -> 69 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7431bb0097a9bb52e1ceaaa8674a13cd3486a387bin0 -> 1223 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7455b805995d0c96ac12f8a1c1264caaffcfac1cbin0 -> 742 bytes
-rw-r--r--fuzzers/corpora/commit_graph/74e39b8a82fc06f9ed8f83ea30545ddf6df66811bin0 -> 268 bytes
-rw-r--r--fuzzers/corpora/commit_graph/75d51e413d3e916560dc0c2ee5092d2f4972aec1bin0 -> 343 bytes
-rw-r--r--fuzzers/corpora/commit_graph/75e068964ea6beb7310a154d763de74a70071f48bin0 -> 453 bytes
-rw-r--r--fuzzers/corpora/commit_graph/763bf498dd847bd2b4af7b611199619bd428bea6bin0 -> 1188 bytes
-rw-r--r--fuzzers/corpora/commit_graph/77064ae04581a3c6d2a77158ef1a0b1e60db414abin0 -> 314 bytes
-rw-r--r--fuzzers/corpora/commit_graph/783bb14d68021061f592601607f40fe232ad17c4bin0 -> 210 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7862814cb684310b54ef920b35403515efaba13cbin0 -> 276 bytes
-rw-r--r--fuzzers/corpora/commit_graph/791fd85b6ffb2429e9fa5ba29eebdce214ad88c7bin0 -> 436 bytes
-rw-r--r--fuzzers/corpora/commit_graph/79396d4f6142a53e26e14aa6ccb4afb4fd8fc580bin0 -> 216 bytes
-rw-r--r--fuzzers/corpora/commit_graph/79661b8e529e2182d5c612faba9f26e32a122b78bin0 -> 102 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7969143acb3334bffac46c6dfd96362c81644191bin0 -> 418 bytes
-rw-r--r--fuzzers/corpora/commit_graph/79d84866dc8c067508c02516b65c0e48cf689b56bin0 -> 83 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7b61f8f4a96e309bbe64ed82637fc81492a9652fbin0 -> 2710 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7b8123f973edfb0f3cab027c0cd6b8efc7b11d6bbin0 -> 805 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7b8dd3093efba07f7a4d3bab4b90b8f6e4f28bfbbin0 -> 1049 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7cc771aab0f3be7730881a46d952ae0a06958201bin0 -> 740 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7d177f4207de78d50df2493a3bc07f2cd578b363bin0 -> 82 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7d2df075f3e73ea9809c31586c37ece0f568b7fabin0 -> 362 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7d386e68e4c733a1fb11c0117f379fb4b9955fbb1
-rw-r--r--fuzzers/corpora/commit_graph/7e4260830352479d29310bd6e1022e19a68ffe76bin0 -> 412 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7e4dfdae52be18cf95555c2eb1f54af7f69c6ddebin0 -> 217 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7eafedf7e7f20e86ecdf9ba51febf8492bdbc1f1bin0 -> 593 bytes
-rw-r--r--fuzzers/corpora/commit_graph/7ef1829a378d66b1dd70a767729127a0dc5edcaebin0 -> 4 bytes
-rw-r--r--fuzzers/corpora/commit_graph/80b7d2b9d7e8c8fd7ae239b8d307b592f97ee000bin0 -> 2303 bytes
-rw-r--r--fuzzers/corpora/commit_graph/810f577ff5c1af7807a26226af912687558158cdbin0 -> 281 bytes
-rw-r--r--fuzzers/corpora/commit_graph/81603f1fe8d8e29005418d0fc9a9b33972366038bin0 -> 212 bytes
-rw-r--r--fuzzers/corpora/commit_graph/81c8b4d6884f954935fa4a8e828c4637db04b61abin0 -> 262 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8226846e9b092561f85cc2956ab89d8cc1ae61e0bin0 -> 197 bytes
-rw-r--r--fuzzers/corpora/commit_graph/825cfceea434e2392cce161356e3cb5f81ec2b3abin0 -> 274 bytes
-rw-r--r--fuzzers/corpora/commit_graph/82603febce83d95adf68b85cabf15d43ca0c4ee9bin0 -> 532 bytes
-rw-r--r--fuzzers/corpora/commit_graph/827f0826cc4156e19b4c4938bec74e38de62fe9cbin0 -> 346 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8486397ff8d1156249676c19b419a7758ff53f9abin0 -> 1361 bytes
-rw-r--r--fuzzers/corpora/commit_graph/84d99ee359bec1b8ee0f59e9bd96f1da062030b7bin0 -> 376 bytes
-rw-r--r--fuzzers/corpora/commit_graph/84e629bc7416039f1feb81fa9168d7c1ee3141c2bin0 -> 539 bytes
-rw-r--r--fuzzers/corpora/commit_graph/84e885752179076fb38739ca7bc4345716bee56abin0 -> 217 bytes
-rw-r--r--fuzzers/corpora/commit_graph/859ef05494c8070057810b5c20df00fc81f81cf5bin0 -> 2796 bytes
-rw-r--r--fuzzers/corpora/commit_graph/859fe592f33abc1d959c0e73ecd6cd4bffe23a97bin0 -> 345 bytes
-rw-r--r--fuzzers/corpora/commit_graph/860da5e8a468805b76a44b9ac99b4575be16ea15bin0 -> 338 bytes
-rw-r--r--fuzzers/corpora/commit_graph/865e415745cead02a826f058a5ee49099bdf9562bin0 -> 417 bytes
-rw-r--r--fuzzers/corpora/commit_graph/878bfce051a9c7462847d4e99b7e926dc821b7b8bin0 -> 95 bytes
-rw-r--r--fuzzers/corpora/commit_graph/880492e4dc7259577c227bb4f075d7165e875c29bin0 -> 150 bytes
-rw-r--r--fuzzers/corpora/commit_graph/88b7de1bd1c96454a1350286d115c0ee368511f9bin0 -> 120 bytes
-rw-r--r--fuzzers/corpora/commit_graph/896268e4a5775b7ce33923ac6daeb0810420c55bbin0 -> 3274 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8978f8da89f9652878edabad164f5513ef508f27bin0 -> 244 bytes
-rw-r--r--fuzzers/corpora/commit_graph/89a6525b7db0e6ec211a484efd2880abef928d4ebin0 -> 152 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8ae86cba2bba6664fc5eb97be8e9777b8825d823bin0 -> 506 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8b845fbd2aa14e4f83c4dbc8b4b0b54d06482acdbin0 -> 273 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8c4121e6ce5956cfa408b980f16d276f456374dcbin0 -> 152 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8cb6a5b8ab41e3d27668d5735b5c09ff1f2eab65bin0 -> 403 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8d80a70ffd362a89b88663e27f11e8ab69b70c1bbin0 -> 274 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8db603c1720b3680047f831f2ea9862567a7cdc4bin0 -> 1009 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8dd40b2d27c7dd4b986c35d87f826da287c09c4cbin0 -> 229 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8e9d6e6408e5f708a1924e8370e687e2c202a4c4bin0 -> 519 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8f2dff1a30ee28e5985cb9379828aea5658d5849bin0 -> 222 bytes
-rw-r--r--fuzzers/corpora/commit_graph/8f7d18cdd6e605b85784ada14571fd5e5a184f2abin0 -> 1125 bytes
-rw-r--r--fuzzers/corpora/commit_graph/903ae52f0ac9af8348038b12f9259741b0de42f1bin0 -> 1198 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9119e331f59e9337d419739c324f49d1bd62c8bfbin0 -> 3311 bytes
-rw-r--r--fuzzers/corpora/commit_graph/91d54d03b0917314ea1d67a70690df9247dd08d2bin0 -> 536 bytes
-rw-r--r--fuzzers/corpora/commit_graph/922da3b96725bfd0e3f6ce119f1e2249d53f9086bin0 -> 542 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9277561e0524cccba2f851970b0d88ec4f4d3f5ebin0 -> 1304 bytes
-rw-r--r--fuzzers/corpora/commit_graph/92a4d571804026b7bbe957396185e079e756b894bin0 -> 334 bytes
-rw-r--r--fuzzers/corpora/commit_graph/931224cc80168fd362a360d99bab813ed7bbf8cebin0 -> 127 bytes
-rw-r--r--fuzzers/corpora/commit_graph/936ea5dad3bf023c552aa0bbeea8f7f66a11612cbin0 -> 454 bytes
-rw-r--r--fuzzers/corpora/commit_graph/93aa4e0b1864933dce0abc0df69fe3d261f117f2bin0 -> 146 bytes
-rw-r--r--fuzzers/corpora/commit_graph/93d5b084965cf1b09085c4079a972e25207b3659bin0 -> 159 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9443fd3468bcc0bc3ff8dfe765225f045ab43d0abin0 -> 225 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9624c26cefb5804b7906147d262e81ee4000b6d6bin0 -> 2327 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9890933a73f39208627bd36e2fe88a6d54343a74bin0 -> 186 bytes
-rw-r--r--fuzzers/corpora/commit_graph/989dad0448e79af10040d5080f74eba2b8a401babin0 -> 191 bytes
-rw-r--r--fuzzers/corpora/commit_graph/98ed4808b4a8da66a91fcea1be63be6371a7c7acbin0 -> 214 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9928e516b85e22fbad58d562d3b7e814d9ce812dbin0 -> 213 bytes
-rw-r--r--fuzzers/corpora/commit_graph/994c7cc5599252b5628d89cd0ba4b5574d32bf00bin0 -> 3091 bytes
-rw-r--r--fuzzers/corpora/commit_graph/99c8557c2a02ea030de42869af42c1f7c77114dbbin0 -> 86 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9a14c867272f102b84efdba73662d318c3e51cfebin0 -> 2161 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9a6f158c176d4a1982d541be2bc27a8afba4ea57bin0 -> 99 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9aa4af603192823a2fdc53d95ed36896bc3309b2bin0 -> 371 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9b40c2190123cec66af3b37212f6c567869efda3bin0 -> 152 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9b6268c11d78c35db5164f1346905e602b6a49febin0 -> 989 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9c6883ba5cedb7d711b12733d66ef1a1156dd0afbin0 -> 1988 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9c85c90f44b454ce0d52882c447f5ecb8d303634bin0 -> 348 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9cb7a2e89ec636da3fd41ecc49ebe25e5344e2c6bin0 -> 477 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9d912dc5a3497e4b5b40b37202fc0ffbf5263666bin0 -> 3848 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9dcbafe8c5345194ee0ce7eb4f6efaeb55543626bin0 -> 3972 bytes
-rw-r--r--fuzzers/corpora/commit_graph/9f4b0f3d2d25e6405ba6093f24d0605327711573bin0 -> 452 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a047bf683239fa208dbac09424b105820ac23f43bin0 -> 539 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a1379dcd89ef5e73eabbfcc395113e3636e0ae09bin0 -> 134 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a38c7ef56adabd0916abac514154b1f362d40434bin0 -> 1704 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a38ec6ad4a8466b4feb88e67b16524e8f3feac64bin0 -> 487 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a3fdea21020268b3b2409c1115d50697d9ae8f8cbin0 -> 257 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a45f1987a444b2c27e90fc1477e8b0815f75383fbin0 -> 607 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a4682958fb7029384c0a01a4a1356ac6f2f44fe1bin0 -> 78 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a4de41561725960d6f48f210a4fb74d527f7b0c2bin0 -> 965 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a5935f34435ecdd6587ad4f77b20d479d3387dbebin0 -> 279 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a5b394beb2b1d463ad80924a8c8c70584bf5c629bin0 -> 234 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a62bc806f8c98ba7986243c2185a0548a8dd57efbin0 -> 118 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a7013e97948893e0118c686c06e332cc611bea7ebin0 -> 214 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a74f5df8c7f25c37c15c0f74ed50019d17338225bin0 -> 539 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a7ab3559fb3da3f027e67091116253f3bdfd7828bin0 -> 1626 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a845c8258a02022d447ea9249788b345f5504648bin0 -> 144 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a8d3e026e2393587eb170afb32e94ff0e1f8a8bebin0 -> 353 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a8d547e41ee21e163e65cf0a186d469dfa50ec19bin0 -> 2448 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a8fa22521dd6813e595cc0a9586ee71fff305fe2bin0 -> 127 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a9969442d585d9a53259c71c73b095701280eac5bin0 -> 160 bytes
-rw-r--r--fuzzers/corpora/commit_graph/a99789d0ce2d7b937aaa8afa3cfc0f4ccd7be95fbin0 -> 150 bytes
-rw-r--r--fuzzers/corpora/commit_graph/aaca30ee3ab38edfa2b061fcbcbca0c0ea657f15bin0 -> 108 bytes
-rw-r--r--fuzzers/corpora/commit_graph/aacdec3f05e98eb6eedddb9c6edb968e1a63c551bin0 -> 3654 bytes
-rw-r--r--fuzzers/corpora/commit_graph/aadd85127241b94a41d02d9e9699e3e9773de1c9bin0 -> 539 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ab8ad126702803d21dbafc85713bbee7f25f36e5bin0 -> 3031 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ac26f9afd599ff6f33396c2e02130654f3e2390cbin0 -> 324 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ac8b129e4756fda0c50c9dd0eb13e34c7b41ce8e1
-rw-r--r--fuzzers/corpora/commit_graph/aceaf3b72c2627dd3dd065974b854150681c093fbin0 -> 793 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ad1fcdc3bf806392e754a902eba9edd3b344c31fbin0 -> 98 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ad8c80e532482f9dfbfbb7c0d447f1f4e592bf72bin0 -> 457 bytes
-rw-r--r--fuzzers/corpora/commit_graph/add92b71bf897da2f71f691e6abcb6d02cb8e99fbin0 -> 231 bytes
-rw-r--r--fuzzers/corpora/commit_graph/aeb8ccf6d82be9236c9e689e1580d043bd701eb0bin0 -> 3419 bytes
-rw-r--r--fuzzers/corpora/commit_graph/af1a827aedbf674fff2bdeb5589554eec62787abbin0 -> 215 bytes
-rw-r--r--fuzzers/corpora/commit_graph/afaab9a75414d231176ad4582b6f8d81b5dbedb3bin0 -> 2686 bytes
-rw-r--r--fuzzers/corpora/commit_graph/afc12c4ebed1f3ab962d7dcef110b5328b1e24c3bin0 -> 673 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b0044f3744cf019658d668a33f8d1e53ef8bd6cebin0 -> 406 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b06adc81a4e1cdcda3786970ca07ed9dee0b6401bin0 -> 344 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b139802a1cc90fd5b86cae044c221361892c688dbin0 -> 3071 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b1b8f251542db01bdb01be3b6d5b117b07db1834bin0 -> 790 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b1b9af93f84ed6861b9c0ade39980e89ef828c8fbin0 -> 213 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b2eae68035cafd4077f6a4c3e4e961fdc1e8122bbin0 -> 1878 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b32897a6aedaa8c5a6e656dd808bafabc4ee5608bin0 -> 343 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b376e4fc517297f92ac1713803ae3b60d5ebbe43bin0 -> 32 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b3fd100b139cfbffaad68aacf7d462861e9dca35bin0 -> 136 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b40808ca955faab4829811bced1cccb2ab58ea58bin0 -> 87 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b43daf9f87a514bce74af3e5a39284c69c4e7011bin0 -> 187 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b477da07f3e5796ff4a98c8a5bdb0e4a634954bfbin0 -> 342 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b4a2ef09cf59ca5ccf810a6f001cce710cc02f6bbin0 -> 1248 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b4b75e588cb83430c502a34ec3dcfaf774a00359bin0 -> 1976 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b4ce98acd2b288b6cfc00461e2e15e0f8004030cbin0 -> 1246 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b75563f30f7e4fb369d2449b723ee8b282d03effbin0 -> 1989 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b7a0a820afa7057081de186728d0d887131d9314bin0 -> 3572 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b7e880446146c735a3f820fb93969c8c172c2fb5bin0 -> 275 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b833073d3006e7cbac03c494603a9b75e7b2a723bin0 -> 150 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b89459c1fb6fc918db4c81a32a75ee66217f9ab8bin0 -> 101 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b8aab6c9b2c706f8df0ff695ff94969171f9c807bin0 -> 136 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b9751182a36acb79b77585e1e379857a530e95c8bin0 -> 1247 bytes
-rw-r--r--fuzzers/corpora/commit_graph/b9ddb239b5a2c1348d972ec70a08507c35ba4432bin0 -> 247 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ba8f573256a0fbb95c5626f399ebc3ef50bbd826bin0 -> 69 bytes
-rw-r--r--fuzzers/corpora/commit_graph/bc165749042d5425c5d6d4e29b17769a2315a80dbin0 -> 344 bytes
-rw-r--r--fuzzers/corpora/commit_graph/bc910bd349319e1ed44d7c7266e3ac99cc29ecc6bin0 -> 410 bytes
-rw-r--r--fuzzers/corpora/commit_graph/bc97b1d4f57eb7770bc3983e2d57c8c01b21d29ebin0 -> 942 bytes
-rw-r--r--fuzzers/corpora/commit_graph/bd06f768e35ded4437cb88e2bc0ddd0bea3fa84cbin0 -> 68 bytes
-rw-r--r--fuzzers/corpora/commit_graph/bd702faff9725a7a1957fd0f85cc52799f37b682bin0 -> 411 bytes
-rw-r--r--fuzzers/corpora/commit_graph/bee4464861e1cae3cfdd5fbcb340efbf02e8d8cabin0 -> 1840 bytes
-rw-r--r--fuzzers/corpora/commit_graph/bf7ad994b098ec85d62683a16e067635e21a8af5bin0 -> 2455 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c054fc89ed72101dec861668ff1738ef85b728b9bin0 -> 114 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c06752415ac037fefe5172dc7245cd7c49ca7fcabin0 -> 280 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c0c8b54354d172a0be751e3e9b80be961bb15ddbbin0 -> 2211 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c0e7ca9b5b4d0e72d23d7dc9e9d1f2463a17a20dbin0 -> 282 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c13576a29c98bee02aa47f646f5f170f9b7d83f9bin0 -> 1523 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c14edf1d34f40b3cc74772c81ebe5d72172cc662bin0 -> 956 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c2789364cb35d111f08f924d0d7550ea9785c61ebin0 -> 2130 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c2d8b07acb13e43a89b6c4afb3ecb9817dd4a8e9bin0 -> 2088 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c36ed796c1bf839668db8fc3475a2ffb32ad8cebbin0 -> 1708 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c41ec9dd94427423e4704721e7f21eae0c44ef20bin0 -> 473 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c42c544fa9dbb1264b39bf920b40985384db1d16bin0 -> 1990 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c45ec3f594abc15de0a8cc3ad748ba23cb34ec64bin0 -> 81 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c49004d980961f288616a4eb9ebf68123fd68ffabin0 -> 129 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c4c3c3c8df24adf505127627b3090116de78d9a6bin0 -> 151 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c5c1921293af4a5953cb386092694042715fcfb3bin0 -> 89 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c615caad21cd8a754fcb2008420234c5511c62b7bin0 -> 2534 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c6a9ee3f8fdc42566c4799db3912a83c8c438d7fbin0 -> 396 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c6b661e976282051285b913b3728383f36103ef8bin0 -> 792 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c716ba47f810c238fe7bda1fbdc7b1ccc34e98481
-rw-r--r--fuzzers/corpora/commit_graph/c85b2fa4421302e2fa333a9e33d59a882aa04f4fbin0 -> 2112 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c871d135f2d3117b326688355bc0fa6f26d56cd6bin0 -> 83 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c915b02265a27d185a8b028305f082ddb3ebd704bin0 -> 201 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c952d38b3e642db4795d7f954b85f4f6d2a041aabin0 -> 107 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c98ee52065736c4172f6ee0c31977bf1b560d685bin0 -> 471 bytes
-rw-r--r--fuzzers/corpora/commit_graph/c99b183a2cd0dd8a4c1a141cc6eebb0311501fa51
-rw-r--r--fuzzers/corpora/commit_graph/ca0cd26baff2f2c0759e619800ebbe7314d2bb95bin0 -> 262 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ca3e0d745c35d7cceb0f6e3f8a709eb658b7e5a8bin0 -> 86 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cac667320e99e93a796bb89842de4675735eb4a4bin0 -> 353 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cb41b00e9db33a07e27b3ee05d3bbecaf853b963bin0 -> 2238 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cbdbd3f320eee627097778f15b9fb2c1dc2bd15fbin0 -> 2318 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cc7f114000c83abb2ab17f0deab6dcfc2acde7f5bin0 -> 806 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cc9bb93a6b7a1362a15f04898845dbe1447ec382bin0 -> 392 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cce7355f826bbcf3955394596d358abc7df6fe6fbin0 -> 2458 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cceff2878a558166fb5bf2a0354c1be31dcc4e21bin0 -> 2605 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cd96909f3ded7aa54bb2ffd2f2f47f8acc6f99e2bin0 -> 81 bytes
-rw-r--r--fuzzers/corpora/commit_graph/cee9f69d7d1a227833fba127a529ea2a10341da3bin0 -> 68 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d064f27a3109afde629165432f78f389da73ff07bin0 -> 32 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d07e3094f02b0c0e3bab370684c2d8c5634224d5bin0 -> 1178 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d0ba3413d5706de17de64824d78233d48c6efbecbin0 -> 97 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d136511364a74973b009f2be9b021d4122f71a6cbin0 -> 655 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d1d215c40bcc8dd4ce02b0c0621e90b183b40b3ebin0 -> 191 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d1e35b137b2027b61def408f3f3c8cf9bcab274ebin0 -> 1848 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d349d137e57fb1a60ab8babd20e2acedc7a9042ebin0 -> 1989 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d3714ec4d3acc6262295b0fc99c6ba699f5bfe65bin0 -> 594 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d419df696512216074f1c6b17ea1dfc81c0e6e20bin0 -> 1251 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d49ad4fdafac251ceec32481826228c1698360aabin0 -> 1001 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d4f85ba549c87ccaba59971a25da7e07b57c9f4ebin0 -> 538 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d51ade0715bcea7decee2a045934599a10c1b07abin0 -> 227 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d5447fb72c97462a3f47c8b2d55deb0afaa225f8bin0 -> 1113 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d6611a91c29291872ed2932455cb15ddb3801323bin0 -> 83 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d676f5e7efd6de6f2e1773231479471d2bba7261bin0 -> 37 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d6a21eaa08a957d8f428192e193c2508fca2c218bin0 -> 179 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d778052a29539344a9e3144e262e68df9628ebdebin0 -> 330 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d884f6944adfff7cb41728062bf91cac5cdacfc9bin0 -> 466 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d89aae18d8e320bbae55eaae6a0514d7e005a883bin0 -> 2410 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d926fde818c63f7b34f38c9f018bc833bc0bf7e1bin0 -> 409 bytes
-rw-r--r--fuzzers/corpora/commit_graph/d9d542d7c56774143cb6362e5a63739055469349bin0 -> 2801 bytes
-rw-r--r--fuzzers/corpora/commit_graph/da99bc9ce5b831f132dfb2eb11b8537e5cccfcd4bin0 -> 120 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dabff2729fa69ab507fb00b7392aee1262056a29bin0 -> 296 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dac4f4b91e33847bcedf7c66ef6e4ad0181e8ad8bin0 -> 153 bytes
-rw-r--r--fuzzers/corpora/commit_graph/db10ff6d01c7a66aa1823b9f99193590ddce99c6bin0 -> 252 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dbbda2208fa688a5275dda0d304630db01ca081dbin0 -> 284 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dc47c5037be68a2747ff8a9fa450e1078a5ac5a5bin0 -> 209 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dc760f136b123e38677aec72853e3365f08010fcbin0 -> 602 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dca41b901bf1612d4197e6a450366a00ac036ec3bin0 -> 346 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dca62f21fce50d1c8c51b82e0d7eeedc6746e652bin0 -> 169 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dcc7e6c444f95b10d634b1137413824e2cd68f62bin0 -> 152 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dcf4b6addda69040f792c9b860ade2af0b77a14cbin0 -> 1888 bytes
-rw-r--r--fuzzers/corpora/commit_graph/dd6178166ac1eed82d132fea491bcda0d953227cbin0 -> 566 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ddbd5d3074323ccd7cd70bf5de5a2f30de977d99bin0 -> 130 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ddd8ec5632bf1b8153d03a4537d3d76517c497d5bin0 -> 150 bytes
-rw-r--r--fuzzers/corpora/commit_graph/de7a56f36e10d7b9ff43160b1cea3e76b24386d1bin0 -> 146 bytes
-rw-r--r--fuzzers/corpora/commit_graph/defa60aa46ea5a47c09b6962b4e4296ef1bcad92bin0 -> 80 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e0ae419425207832518d66c0ef35d11cbdc20361bin0 -> 1691 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e0f519accbf15bc57a1bf1d7cc46d2a0b07a67f5bin0 -> 214 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e128eff8ca7572d9bb0bfc84f64d79c52afc2c67bin0 -> 536 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e17fdc21ae03243bd1d31bb6301b4187cab6fe47bin0 -> 1617 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e340ace35a2db7f89d6aa21cc1300766a74be4e1bin0 -> 536 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e36dfc11bcaab1e42df13924a2d7da024684db2ebin0 -> 353 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e39e0c87ac5ce0b78c89ae2df84226baba666372bin0 -> 864 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e46b4666c6bfcd6f589ec3617a48cce9c968e833bin0 -> 406 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e57219555e11f9221d3166d5029ed2ad92300608bin0 -> 101 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e58ce590c2454e7ebe18e0a31a943b0b754fbd13bin0 -> 2317 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e595f8fef5c8014cb0867978c6580301078ca0d9bin0 -> 2474 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e5b76398f60628e879328d7009b9fa89feea14cbbin0 -> 452 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e5cec0217eea93b18a59d76b0aed6b46b13fa6a9bin0 -> 921 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e637b4e0b47d0d6cd870502e6a2d6a53bf917f73bin0 -> 1782 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e7a6cb6e5a1552837fdbee9025fc48a9373f8564bin0 -> 1370 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e7f57c48016e1180c9af95acd34470881f10bd06bin0 -> 90 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e8253c668bfe37df5c5ada3226860cee74fb33a2bin0 -> 218 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e8f9981443c34ece02bca3c66130f3429d7b3375bin0 -> 474 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e91ed5416bbcd1b03803197b99c08f42c9869139bin0 -> 537 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e94201cfa88df7b198abd3abae9007a6780b52a7bin0 -> 345 bytes
-rw-r--r--fuzzers/corpora/commit_graph/e967bbd6a0d251ae62c9c38b784271d707f792c0bin0 -> 138 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ea01737ceed783b3e0f66d9d0c409cb496c1d526bin0 -> 86 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ea40f7879a58d1e52a46404c761f76a949e14a31bin0 -> 69 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ea5ad04a54f95963baea1f47845847626e08dd55bin0 -> 211 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ea608a401f54b0ca70e42b897f0c8ce6efdbc0efbin0 -> 404 bytes
-rw-r--r--fuzzers/corpora/commit_graph/eb8700d6b3728e6e70c2a0fe504543771639f2b6bin0 -> 1989 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ec1f271b04c322353865f4819153d46df7def873bin0 -> 1754 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ee215536e7f0cfbd07b53dd65c5af9a604a01830bin0 -> 948 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ee4d4393d7d79b755f85ef5bf8f6e3d743bfa258bin0 -> 468 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ee8099331b2c392e7e036ffcd4a9b36ec2c2082dbin0 -> 1908 bytes
-rw-r--r--fuzzers/corpora/commit_graph/eede9da76db25513f8347f972e170102831de91abin0 -> 80 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ef707cdeaa9548b6c820f769c1d8ad607b3c4514bin0 -> 119 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ef98609d8196dc158365dfcbbc47e3d1699c50c2bin0 -> 1944 bytes
-rw-r--r--fuzzers/corpora/commit_graph/efa38b4269f978f3714b44b501831bea678244e0bin0 -> 357 bytes
-rw-r--r--fuzzers/corpora/commit_graph/efba428e29811d233720ccaaf41966a309312a29bin0 -> 86 bytes
-rw-r--r--fuzzers/corpora/commit_graph/efd514f056d8d83498b4724249c4623560e0390dbin0 -> 177 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f00e449ba67ef15e7f29df1e6948c28155d72baabin0 -> 3505 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f0a83929d588466051dced6eae0c387db307d646bin0 -> 944 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f0e53b72e5d69467e7c014474028ea734f4fcb26bin0 -> 5 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f186265b3f10f4383f4174e9fb74f0a0cdfa3fcabin0 -> 95 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f18932fcce5a9db5d6c8f59d622eabc25e255e12bin0 -> 100 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f2ea163bddb95d67597e2a747779ebf4651cb2a9bin0 -> 417 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f2f7d48a6d86143ecb4969808d634163576065b1bin0 -> 2677 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f34a833faf2b0dcbae8aaad142c76c7c7e534e99bin0 -> 71 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f5c044ce01645c069334698fb8c4750e44835912bin0 -> 2625 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f680112645c2502f0612e9d017bbb50cb28affbfbin0 -> 580 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f6b778d1b34415a7715905f54968c8b6eb057912bin0 -> 296 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f6ca6a62dc885c6b2a4b40c4aa1a7cb8118e30bbbin0 -> 355 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f733a8770c23fde182d2fef7e0d96e67244274d5bin0 -> 90 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f8529ddf17d4505c0932c3d40abe33cbfd8c6f22bin0 -> 453 bytes
-rw-r--r--fuzzers/corpora/commit_graph/f96f8419a3fc3719ae86d64e1147e7b7f66a2470bin0 -> 2139 bytes
-rw-r--r--fuzzers/corpora/commit_graph/fae241a6c87af37781a3b49e534b7ddb6636eda8bin0 -> 803 bytes
-rw-r--r--fuzzers/corpora/commit_graph/faf8817a04b77c6a976ab0a3d1e905f79bb7f799bin0 -> 1757 bytes
-rw-r--r--fuzzers/corpora/commit_graph/fb3e769019fb25d384d4be9d38e4cbce00a6adbcbin0 -> 1790 bytes
-rw-r--r--fuzzers/corpora/commit_graph/fb9b4b2a46f1c65076340a7bd03b076eb101b760bin0 -> 144 bytes
-rw-r--r--fuzzers/corpora/commit_graph/fca9b0a398832c9ba02cdc811f625b97d5beb18ebin0 -> 351 bytes
-rw-r--r--fuzzers/corpora/commit_graph/fcb1b42c706e61245d5e86f708be777ae63f2772bin0 -> 469 bytes
-rw-r--r--fuzzers/corpora/commit_graph/fd6c463e7c30b0e51198c0d1ebbea25f20145e3fbin0 -> 357 bytes
-rw-r--r--fuzzers/corpora/commit_graph/fdcbaa49097ad120c6d7709b29d5b65b8cf8e719bin0 -> 613 bytes
-rw-r--r--fuzzers/corpora/commit_graph/fe46775b28a2923b8770b44381552a8a1560d875bin0 -> 154 bytes
-rw-r--r--fuzzers/corpora/commit_graph/ff04441135ef3308fec2687cf688069c6df8aa31bin0 -> 601 bytes
-rw-r--r--fuzzers/corpora/midx/037cbbe0dc03807dd9d9e8629f1712d7df34ee18bin0 -> 45 bytes
-rw-r--r--fuzzers/corpora/midx/039ee34fef8f323ed618a10abc0109df123d0cb5bin0 -> 1062 bytes
-rw-r--r--fuzzers/corpora/midx/054ee2c82bdb6a170106eb5d35f21bde2119d5841
-rw-r--r--fuzzers/corpora/midx/055ca4cbc961ebf5fd5c922b4f73880d3fbfe39dbin0 -> 1880 bytes
-rw-r--r--fuzzers/corpora/midx/05c4e5eb1b97bc9b6973921fcb30d4c5e2eb79e4bin0 -> 227 bytes
-rw-r--r--fuzzers/corpora/midx/0672eeda541a191cfc68d521a3c7ac0aac4057a6bin0 -> 2600 bytes
-rw-r--r--fuzzers/corpora/midx/06a58d1bd5562a668ebf01ef297fd774e0e587a6bin0 -> 143 bytes
-rw-r--r--fuzzers/corpora/midx/06bf7c2461ae1049030f31b83ae76babfcc20c83bin0 -> 26 bytes
-rw-r--r--fuzzers/corpora/midx/06c2db67ea65758d971346bfd6beaa61ed12f22cbin0 -> 108 bytes
-rw-r--r--fuzzers/corpora/midx/07f88eefaf12609b7370fe78b82be2955f1b41fdbin0 -> 96 bytes
-rw-r--r--fuzzers/corpora/midx/08495c5f3828a56c167de870d385c46ffdce03c5bin0 -> 40 bytes
-rw-r--r--fuzzers/corpora/midx/08ec8594e5b35fb9e8e0726584f720154f0b2b5dbin0 -> 133 bytes
-rw-r--r--fuzzers/corpora/midx/0903e378a493c596298074d6bff8de7f9ac25aa71
-rw-r--r--fuzzers/corpora/midx/09144a846f90f894049ef8a0ed0cc7ab4588dc6c1
-rw-r--r--fuzzers/corpora/midx/09b40dd618373bfe4d3f2838f686a70f645e640bbin0 -> 97 bytes
-rw-r--r--fuzzers/corpora/midx/0a00ef44d234c18d365ec41724dbf4f21b09d0c5bin0 -> 1987 bytes
-rw-r--r--fuzzers/corpora/midx/0a94e9f4a9b8cf56d52a9e3e7f2fa9a0a5c80d30bin0 -> 172 bytes
-rw-r--r--fuzzers/corpora/midx/0b35a123104b7872a7f15a710a23ef3594ace04dbin0 -> 1115 bytes
-rw-r--r--fuzzers/corpora/midx/0c3d7e6be32c014ea873440b0f095961d391af1abin0 -> 243 bytes
-rw-r--r--fuzzers/corpora/midx/0c65de477b89afc312a7e89cde06f8a17f65bd54bin0 -> 52 bytes
-rw-r--r--fuzzers/corpora/midx/0c81d0f368e979d2a0eb4598cbf1c9283936ba0cbin0 -> 308 bytes
-rw-r--r--fuzzers/corpora/midx/0c95a44ae995070a5279a2991c36de2251081460bin0 -> 450 bytes
-rw-r--r--fuzzers/corpora/midx/0de38e2cb13167df7d5a882570633596f64bc4f4bin0 -> 121 bytes
-rw-r--r--fuzzers/corpora/midx/0de96aa193045315457ade63c2614610c503db9ebin0 -> 59 bytes
-rw-r--r--fuzzers/corpora/midx/0e02deca2b16d71f8637933bd56dc8592ed9fdff1
-rw-r--r--fuzzers/corpora/midx/0e44fc9176fe2c1bae4209369da5bc057f54b2d2bin0 -> 2325 bytes
-rw-r--r--fuzzers/corpora/midx/0f6c5fc9b6a68835364bbef8937560ee5a4819381
-rw-r--r--fuzzers/corpora/midx/10d542d5c7da060a5f0664e21478a0d598e29844bin0 -> 322 bytes
-rw-r--r--fuzzers/corpora/midx/118735f7786ae6b4c2f6b36314ab1f2cafe9c3c81
-rw-r--r--fuzzers/corpora/midx/119b58eb353aa344264005016297fb911510ea0dbin0 -> 261 bytes
-rw-r--r--fuzzers/corpora/midx/127626832c30d6d94bb29384c0fde7ac6bca75ecbin0 -> 151 bytes
-rw-r--r--fuzzers/corpora/midx/1284f1a162588d4de87ca17149474644a0863b27bin0 -> 59 bytes
-rw-r--r--fuzzers/corpora/midx/1458599f19f1a967c787562bf8ec3e67677da9c8bin0 -> 386 bytes
-rw-r--r--fuzzers/corpora/midx/14ba6c1ddd05b22c6f2eae5f894721cd3efcbb16bin0 -> 57 bytes
-rw-r--r--fuzzers/corpora/midx/158cdc0a5aa005f167a8588d0beed9eee4aa36f2bin0 -> 145 bytes
-rw-r--r--fuzzers/corpora/midx/15dafc6fa800327f694b5eb2fc4ebf007be9c117bin0 -> 185 bytes
-rw-r--r--fuzzers/corpora/midx/1613ed4b2e909871f8897fd6354ff80a4ac12f87bin0 -> 120 bytes
-rw-r--r--fuzzers/corpora/midx/16daf4cb967bb47cf4566e9be7d96d3125bd2e12bin0 -> 252 bytes
-rw-r--r--fuzzers/corpora/midx/177783dce78efee878f6d6020fd87ab107bb11a1bin0 -> 121 bytes
-rw-r--r--fuzzers/corpora/midx/17a5090400a1fedc45070e4b530a26f320a89097bin0 -> 133 bytes
-rw-r--r--fuzzers/corpora/midx/17dea5cfa498f4d54384289a1daed0d15a85e7ccbin0 -> 450 bytes
-rw-r--r--fuzzers/corpora/midx/17e76ae5b54316679981113f52c27edc87dbcdeabin0 -> 426 bytes
-rw-r--r--fuzzers/corpora/midx/191ed5e9334693c53fc843f692dbc3c2c63e8241bin0 -> 379 bytes
-rw-r--r--fuzzers/corpora/midx/196a0ba4edb5bbfd66c1cda669abf0496573cf0ebin0 -> 123 bytes
-rw-r--r--fuzzers/corpora/midx/19742b6cee79fa5bf9b27dcbe367c82d0a399904bin0 -> 237 bytes
-rw-r--r--fuzzers/corpora/midx/1a21d7581d3b0a8d67934d48e91d45bd818836e8bin0 -> 1814 bytes
-rw-r--r--fuzzers/corpora/midx/1b2f96c5d75c7ca09b1012be4e6c3a7b248ed924bin0 -> 211 bytes
-rw-r--r--fuzzers/corpora/midx/1b604ff0683d0e23dc7945431f6514ba30d6ca0dbin0 -> 137 bytes
-rw-r--r--fuzzers/corpora/midx/1b771dd5bd3ae2b1c42c4efe6c896c83b88a4f91bin0 -> 450 bytes
-rw-r--r--fuzzers/corpora/midx/1b793a4ee73fa8bf423da70fca5f39ef32a8d288bin0 -> 311 bytes
-rw-r--r--fuzzers/corpora/midx/1c9599ce00978780519272be279f508c402e32681
-rw-r--r--fuzzers/corpora/midx/1cc0068f9f63b12dc8fdd38f9ebfb96c42664e95bin0 -> 1664 bytes
-rw-r--r--fuzzers/corpora/midx/1de6e1f5579da6e5c40f4ee23ac62e29e4f90541bin0 -> 282 bytes
-rw-r--r--fuzzers/corpora/midx/1eec93083260ebfab5f4c6d13119cf27c374b7e9bin0 -> 363 bytes
-rw-r--r--fuzzers/corpora/midx/1f0f574addd363d1fed131289f301c5c033aaa8fbin0 -> 66 bytes
-rw-r--r--fuzzers/corpora/midx/1f3e85cffdb545c1ba7c8bbe1ca18ec13e341038bin0 -> 156 bytes
-rw-r--r--fuzzers/corpora/midx/1f6a66a92d5f083a73a82280a0a1ae0800e56ae5bin0 -> 115 bytes
-rw-r--r--fuzzers/corpora/midx/208e422322052efcdaeb1a09bbf06c5f476b8efcbin0 -> 259 bytes
-rw-r--r--fuzzers/corpora/midx/22d75b2c3937957b14eded621b638283ce7fe1febin0 -> 1351 bytes
-rw-r--r--fuzzers/corpora/midx/22f90ff68166a409acf8f89bf60a31ad2c64ab37bin0 -> 255 bytes
-rw-r--r--fuzzers/corpora/midx/236ebad449d432b039d6ace1f250ef1fa2aa364dbin0 -> 390 bytes
-rw-r--r--fuzzers/corpora/midx/252a4e4bf7fb21792ec2f305fd88fa7c9168505fbin0 -> 123 bytes
-rw-r--r--fuzzers/corpora/midx/259e1faf7b7f12250062d36ded1193a9dbcae0f5bin0 -> 3 bytes
-rw-r--r--fuzzers/corpora/midx/25ad3dfb655ab4c853d0d277872310d9579c8e83bin0 -> 258 bytes
-rw-r--r--fuzzers/corpora/midx/26210f5b8fdbf81b312feea48659ec6e2e083c0bbin0 -> 953 bytes
-rw-r--r--fuzzers/corpora/midx/263a2a0915be36d8cb2bc30774e37e0344262347bin0 -> 65 bytes
-rw-r--r--fuzzers/corpora/midx/2679bfbc2f4f7c10a304245da4e156e235377b63bin0 -> 130 bytes
-rw-r--r--fuzzers/corpora/midx/270b7b567a63dd94bb2a90448bbbc2e2bbc4a261bin0 -> 2293 bytes
-rw-r--r--fuzzers/corpora/midx/271cd5c5e254a293d115588ee130040ef26b59e8bin0 -> 328 bytes
-rw-r--r--fuzzers/corpora/midx/27839a8035b48f8c19ab073808a03a95b6a90cc3bin0 -> 144 bytes
-rw-r--r--fuzzers/corpora/midx/2810c385c9285cbdb65bcdab5175999fe547cbadbin0 -> 449 bytes
-rw-r--r--fuzzers/corpora/midx/28afaf4ab4b092ccf987661e58009f96126bba63bin0 -> 2041 bytes
-rw-r--r--fuzzers/corpora/midx/29f842e86a891cff9f0b44c8aec19f7e23a47000bin0 -> 105 bytes
-rw-r--r--fuzzers/corpora/midx/2aa2549f617f19402d1feac61d4ca1af3545cc8abin0 -> 41 bytes
-rw-r--r--fuzzers/corpora/midx/2b73c2902eda6da41321493601003b29c3445713bin0 -> 257 bytes
-rw-r--r--fuzzers/corpora/midx/2bcec1274c5e7b2d7a581d851c016ef5b553fabebin0 -> 208 bytes
-rw-r--r--fuzzers/corpora/midx/2dd9a328b6d4e29e42684347be5c4b7cd7dc1a66bin0 -> 152 bytes
-rw-r--r--fuzzers/corpora/midx/2ddc17ee7ee89bb7dbc673328d5f3e55c76e686ebin0 -> 377 bytes
-rw-r--r--fuzzers/corpora/midx/2f71d5e99dc93618ed99fdb7c244a8f5e4a7eb4abin0 -> 961 bytes
-rw-r--r--fuzzers/corpora/midx/2f7cd0154d71a83e7b104670b2a77fbd285ffde2bin0 -> 247 bytes
-rw-r--r--fuzzers/corpora/midx/2f9d40ef790f5213234e95d123dce942b2d1d389bin0 -> 269 bytes
-rw-r--r--fuzzers/corpora/midx/31577bacbca7017308d2a0c9ebfdd4fce513bbe4bin0 -> 517 bytes
-rw-r--r--fuzzers/corpora/midx/3278f1bab88b80597d0066812d49f8bd3c7b1dcfbin0 -> 121 bytes
-rw-r--r--fuzzers/corpora/midx/328160cae6235605ff70951a2f6ac669ba7bb397bin0 -> 8 bytes
-rw-r--r--fuzzers/corpora/midx/337ed1bf91701a4c8926840259077e55938c6efcbin0 -> 517 bytes
-rw-r--r--fuzzers/corpora/midx/33a97d83ff7a774797b1751ea4bffbb4a22c58d9bin0 -> 644 bytes
-rw-r--r--fuzzers/corpora/midx/341021da9516401cf364ed2b7dfdda346db04f2fbin0 -> 320 bytes
-rw-r--r--fuzzers/corpora/midx/341773a439cdecc58f55fb205ac584cd93ffe0f21
-rw-r--r--fuzzers/corpora/midx/366091157510e40bca08fc2102b9018ccf4697debin0 -> 1172 bytes
-rw-r--r--fuzzers/corpora/midx/37096157e2f9f2ec8e0b97b21d335bd653f3edbdbin0 -> 199 bytes
-rw-r--r--fuzzers/corpora/midx/373a74b8613d09babcb567f91047e7b556a8de90bin0 -> 199 bytes
-rw-r--r--fuzzers/corpora/midx/3748b07ee7bec7bdd202ee14222cefca182417d1bin0 -> 122 bytes
-rw-r--r--fuzzers/corpora/midx/38b7906b9f956dca01dc92d0a901388ec1cbc8b1bin0 -> 112 bytes
-rw-r--r--fuzzers/corpora/midx/38ddf3424559f1a6e7687eff8469a358184b833b1
-rw-r--r--fuzzers/corpora/midx/38e31d0a7dcc3835ce1a4afeeda8446fb3d7ed73bin0 -> 11 bytes
-rw-r--r--fuzzers/corpora/midx/3955ec4497b226391ef9eb40f38af6dee4fa26b7bin0 -> 260 bytes
-rw-r--r--fuzzers/corpora/midx/3b6b424342133feb0f587f22bcd8f21595c004e5bin0 -> 252 bytes
-rw-r--r--fuzzers/corpora/midx/3bb71f41200e0ebf8d19532e7d6e384c48aa2d03bin0 -> 18 bytes
-rw-r--r--fuzzers/corpora/midx/3c5a6063797aba9ffe5ea9903bbfcf87193652d3bin0 -> 1091 bytes
-rw-r--r--fuzzers/corpora/midx/3dfb9927d959f2462f6944a32d080b60a265abfebin0 -> 418 bytes
-rw-r--r--fuzzers/corpora/midx/3e19242a63ec92a0c3f7138ebbc31bfe7cbd40cdbin0 -> 78 bytes
-rw-r--r--fuzzers/corpora/midx/3ec53ce4ea1f41f040a3c2beed929572af95dd43bin0 -> 7 bytes
-rw-r--r--fuzzers/corpora/midx/3f0762fdf49a58c0d8fd6683964a85caddee391bbin0 -> 89 bytes
-rw-r--r--fuzzers/corpora/midx/3f71ae863c4e9bac98e49a554b8ec4d78b17492d1
-rw-r--r--fuzzers/corpora/midx/3f9df30bfb66a28fbe6f1951ef7ae4ca9f19fdf2bin0 -> 56 bytes
-rw-r--r--fuzzers/corpora/midx/3fabb14670c008c22094c1d7cd7b1e23b4c48b3dbin0 -> 288 bytes
-rw-r--r--fuzzers/corpora/midx/408fba9c66c5d1deb31e4c69f1dd0677844dbc1bbin0 -> 85 bytes
-rw-r--r--fuzzers/corpora/midx/40ca8645081087e950ad61bccf8d43450366356ebin0 -> 342 bytes
-rw-r--r--fuzzers/corpora/midx/412faec949b9d04498de939561664ee559a583a71
-rw-r--r--fuzzers/corpora/midx/4148bd5336f89e73b2a5416c67d491c0ec4a2b7dbin0 -> 3 bytes
-rw-r--r--fuzzers/corpora/midx/41933e61fa20fbe2b190f9ae7ceae4a4b1220021bin0 -> 149 bytes
-rw-r--r--fuzzers/corpora/midx/423d90f3fc7ddc146095ec5a4b4f455aa876b69bbin0 -> 2941 bytes
-rw-r--r--fuzzers/corpora/midx/42a6c52249aa12cfef1db1bf302a483a01c972f3bin0 -> 2732 bytes
-rw-r--r--fuzzers/corpora/midx/42a82726f0e70da9b87b6c52bc1b3415576025f2bin0 -> 10 bytes
-rw-r--r--fuzzers/corpora/midx/4458e19f99e38c61ad9792b0b3bf8ac79f8236f11
-rw-r--r--fuzzers/corpora/midx/44a4411a8d6ed67ee3ea61d91d2afafe89295b0fbin0 -> 252 bytes
-rw-r--r--fuzzers/corpora/midx/44e04754d1b6c0c045e05509dd7033d19a926b10bin0 -> 2282 bytes
-rw-r--r--fuzzers/corpora/midx/45259e9f0a2cc7739a94eccaafb37c1570f73884bin0 -> 459 bytes
-rw-r--r--fuzzers/corpora/midx/46c0d7e952200cabc08b9cd776a9f6759f4208c3bin0 -> 73 bytes
-rw-r--r--fuzzers/corpora/midx/46deac8631633ea3c32005124e20a2bc2bbabadebin0 -> 387 bytes
-rw-r--r--fuzzers/corpora/midx/46e7edf6e9d6cbcdabde3b48f1c4efd93be40348bin0 -> 687 bytes
-rw-r--r--fuzzers/corpora/midx/46fe9556c28c94f7321baa2519a3cbeabbd54d09bin0 -> 1986 bytes
-rw-r--r--fuzzers/corpora/midx/49223681729e73b48b26a2262e4a66b2ba00e176bin0 -> 100 bytes
-rw-r--r--fuzzers/corpora/midx/499e61b689f6cc7e4efb0631684739c2a6f97c7dbin0 -> 1813 bytes
-rw-r--r--fuzzers/corpora/midx/4a06ad8c4d717bd048a7a1315a3d609d70f0162dbin0 -> 41 bytes
-rw-r--r--fuzzers/corpora/midx/4adb7d4791a4c6370478dff2eb987d715554bf09bin0 -> 1794 bytes
-rw-r--r--fuzzers/corpora/midx/4b01c479cdc9b750a31d5e7ac5004309222d218dbin0 -> 442 bytes
-rw-r--r--fuzzers/corpora/midx/4bce7460a6becba6d26984bb438d7d3aa4e4fc56bin0 -> 517 bytes
-rw-r--r--fuzzers/corpora/midx/4cc96483b6800dda296f00887b12a35154115090bin0 -> 57 bytes
-rw-r--r--fuzzers/corpora/midx/4f3aa59bae0619c9a06b631d9cb7767591810ab0bin0 -> 505 bytes
-rw-r--r--fuzzers/corpora/midx/501840d963cedd2945018de59e0202444d7ebf4bbin0 -> 57 bytes
-rw-r--r--fuzzers/corpora/midx/50479958c030d1addceb1ca8c27f24447e555e65bin0 -> 247 bytes
-rw-r--r--fuzzers/corpora/midx/508ba8ef164a809f739834a39d690e700101a7a1bin0 -> 521 bytes
-rw-r--r--fuzzers/corpora/midx/521d345313812e54bc6c944485e19dbb39a87768bin0 -> 258 bytes
-rw-r--r--fuzzers/corpora/midx/5369d74ac157f85b597c1b28bbd6768105e9327bbin0 -> 194 bytes
-rw-r--r--fuzzers/corpora/midx/53997b0146ff49bfe464be203b130a67ea93fd26bin0 -> 309 bytes
-rw-r--r--fuzzers/corpora/midx/560ea8bd7d11b00e0d21631b6d9ec7e63f0a5286bin0 -> 794 bytes
-rw-r--r--fuzzers/corpora/midx/5682ebc6878e247ce9bc636d34ada6ad338fcaf0bin0 -> 148 bytes
-rw-r--r--fuzzers/corpora/midx/5762abb5234edd913754b69e1ab03274c711ee68bin0 -> 2043 bytes
-rw-r--r--fuzzers/corpora/midx/579406f055070559bda3c6120107feb3e637c4812
-rw-r--r--fuzzers/corpora/midx/5837d16af4a9c1f2616467cc4aa9ec8836e05c58bin0 -> 155 bytes
-rw-r--r--fuzzers/corpora/midx/58901e865fe20b9fa136cca4b253d3ae73c2b78ebin0 -> 4 bytes
-rw-r--r--fuzzers/corpora/midx/58a87098a14572e46b53c87340083f999d8fcfc2bin0 -> 156 bytes
-rw-r--r--fuzzers/corpora/midx/59ae139a21448e0eb7371ddc6ef57f0c9dfe9c85bin0 -> 560 bytes
-rw-r--r--fuzzers/corpora/midx/5a7e81419f895168c555ac9b4e75a1ad4f04b34abin0 -> 166 bytes
-rw-r--r--fuzzers/corpora/midx/5b848c1f56a150d64020e9b0bb398a286dca4096bin0 -> 200 bytes
-rw-r--r--fuzzers/corpora/midx/5bd311bd846336149b2815666052fdb7e8bf2ea6bin0 -> 395 bytes
-rw-r--r--fuzzers/corpora/midx/5ce77eb98473a2e01d04909939edf7aabef5762cbin0 -> 267 bytes
-rw-r--r--fuzzers/corpora/midx/5e5cd5819811507ac69bd8abad27433ccd6b7521bin0 -> 389 bytes
-rw-r--r--fuzzers/corpora/midx/5ea114ae3dbb140364000c416152b0f32ce3de23bin0 -> 3368 bytes
-rw-r--r--fuzzers/corpora/midx/5f181bb0a79603c84534a9b8e37ecdeb1d2aeeb51
-rw-r--r--fuzzers/corpora/midx/5f428ce1169e28353cedb8be3e2f6edd0ef354e4bin0 -> 7 bytes
-rw-r--r--fuzzers/corpora/midx/5f9bc7729dc331e3c4d8e52df0688abad6d4aee8bin0 -> 7 bytes
-rw-r--r--fuzzers/corpora/midx/619527e1d650cd1c26e9bc61e424c9fdc04b17b9bin0 -> 202 bytes
-rw-r--r--fuzzers/corpora/midx/625d3676de25188865e05db2a3933c38508406fcbin0 -> 65 bytes
-rw-r--r--fuzzers/corpora/midx/6368569cfde7fbe369a0ee4695fa4d5a7d7887a6bin0 -> 1089 bytes
-rw-r--r--fuzzers/corpora/midx/6388fe4d630064ea1ea33aa85381d9c82e328e95bin0 -> 51 bytes
-rw-r--r--fuzzers/corpora/midx/64cff4e110f0bcb3ea833c1afda6e27a57dac0bcbin0 -> 78 bytes
-rw-r--r--fuzzers/corpora/midx/66449b87ce47b681c6326f337bebf03366a0ee99bin0 -> 507 bytes
-rw-r--r--fuzzers/corpora/midx/66ae3584497a1823a955c33e5bc53f7434c13e49bin0 -> 93 bytes
-rw-r--r--fuzzers/corpora/midx/66e238a6ad70fb30c82171ff1b73ea71b4379355bin0 -> 577 bytes
-rw-r--r--fuzzers/corpora/midx/66f345dc060ac5a1fe8bcf0828102d072deb1111bin0 -> 213 bytes
-rw-r--r--fuzzers/corpora/midx/66f839146ef46deed25fd2cd169a4f1a2a3533fabin0 -> 2001 bytes
-rw-r--r--fuzzers/corpora/midx/671720ee2b7ba45920b41b8016eb5206b88168eebin0 -> 253 bytes
-rw-r--r--fuzzers/corpora/midx/679c7140ad60ed32aeb7ee464499dd52b0fc212fbin0 -> 194 bytes
-rw-r--r--fuzzers/corpora/midx/67c5e6ce7bb47cefe54d749374f3288a2c915936bin0 -> 962 bytes
-rw-r--r--fuzzers/corpora/midx/69592399b45f2f83e0cc823c5f0e3865ac3fa611bin0 -> 205 bytes
-rw-r--r--fuzzers/corpora/midx/6abf97508f0ed808b7fe0d9bb2439981153badd2bin0 -> 240 bytes
-rw-r--r--fuzzers/corpora/midx/6b2dfb51b35b78680cb02ff54e06f0c983c04866bin0 -> 604 bytes
-rw-r--r--fuzzers/corpora/midx/6bbf6ab605fedd41ed6c7581ec9f87c75403e9c3bin0 -> 2361 bytes
-rw-r--r--fuzzers/corpora/midx/6c0656104902e1323f3a19c46df7cffecae94f1cbin0 -> 146 bytes
-rw-r--r--fuzzers/corpora/midx/6c0ce8006b3ebd8202e61fe5f4cc2285248bd1babin0 -> 237 bytes
-rw-r--r--fuzzers/corpora/midx/6cc635e6dd4e430ed4fb68a9f5add38aa02ae14fbin0 -> 391 bytes
-rw-r--r--fuzzers/corpora/midx/6d1b281d7bdd9887e53505fd5d040731db18ba48bin0 -> 1019 bytes
-rw-r--r--fuzzers/corpora/midx/6d5c35f9d87253b2fbe383bfde3775a9f737da121
-rw-r--r--fuzzers/corpora/midx/6d95355018cadedd97bed65c45a44a7ff6f065f7bin0 -> 966 bytes
-rw-r--r--fuzzers/corpora/midx/6dd70e887ab94db3327d9aaa0335914a1f4986b7bin0 -> 441 bytes
-rw-r--r--fuzzers/corpora/midx/6ed51a953a8b6671de417406e340d8d0a211aa12bin0 -> 198 bytes
-rw-r--r--fuzzers/corpora/midx/6f911f19652a4457c93ef92b594bc1dc2ca900f8bin0 -> 11 bytes
-rw-r--r--fuzzers/corpora/midx/6fa76cbaeb3cf0417c7a372132167bcd737db66bbin0 -> 516 bytes
-rw-r--r--fuzzers/corpora/midx/71f66d3f7da318d69681a22ebbceb1a2bb290658bin0 -> 1029 bytes
-rw-r--r--fuzzers/corpora/midx/7227a2dc335af13e7225536c49969f46a800750a1
-rw-r--r--fuzzers/corpora/midx/72fce27bbccf582f2023f5e168853251e576592abin0 -> 962 bytes
-rw-r--r--fuzzers/corpora/midx/738e5543ae005a6de85dfcd960eb8e3e6faa8947bin0 -> 623 bytes
-rw-r--r--fuzzers/corpora/midx/739d9c8868445202305d0a4e5766df1c68932688bin0 -> 1091 bytes
-rw-r--r--fuzzers/corpora/midx/7438b07314917c84d348e7d9629e3712190c7da7bin0 -> 586 bytes
-rw-r--r--fuzzers/corpora/midx/7490f00d660f5d8dedfa606cca241bd07be86a4fbin0 -> 587 bytes
-rw-r--r--fuzzers/corpora/midx/75c64e8b61af41b28516c2c0fe902362d55a24f3bin0 -> 3684 bytes
-rw-r--r--fuzzers/corpora/midx/75e94b59a41e7f086b6f7ab3bca801251744ae3dbin0 -> 316 bytes
-rw-r--r--fuzzers/corpora/midx/7612ceb3a989f97a7bb19f57c7f9c61366953642bin0 -> 356 bytes
-rw-r--r--fuzzers/corpora/midx/76ac2328e1c979bca648b4082b8bfe6f2e2e73eabin0 -> 245 bytes
-rw-r--r--fuzzers/corpora/midx/76f296039ba4d666c9147ad234d43b55050808e3bin0 -> 258 bytes
-rw-r--r--fuzzers/corpora/midx/777f248eea53e3dd2b726e1e0de5eeda43b6d3231
-rw-r--r--fuzzers/corpora/midx/792fcd0075bd8031a98a68ce04d6a9f23feef7b4bin0 -> 3612 bytes
-rw-r--r--fuzzers/corpora/midx/7a936c3e69013b2c71dcb72f0eccd99c93367533bin0 -> 194 bytes
-rw-r--r--fuzzers/corpora/midx/7b30d0cd07108f2e45ce1a3fab3f971b25dcf5cdbin0 -> 89 bytes
-rw-r--r--fuzzers/corpora/midx/7b87f367b5fa3bf29bae19031814e5d0120a15babin0 -> 277 bytes
-rw-r--r--fuzzers/corpora/midx/7c12e4bca60858eae13c47a66e54cd9e96a50909bin0 -> 513 bytes
-rw-r--r--fuzzers/corpora/midx/7c59f95e649b3be6344f4f835afd0d9a894c1144bin0 -> 142 bytes
-rw-r--r--fuzzers/corpora/midx/7dcb6494c3614a8690dc496309f90e0f23634c37bin0 -> 1776 bytes
-rw-r--r--fuzzers/corpora/midx/7e64b86827ea98f0a4eb54736c460a59b0c30420bin0 -> 166 bytes
-rw-r--r--fuzzers/corpora/midx/8125d9eaa09b3d2283fea73223866cb36877c4a4bin0 -> 333 bytes
-rw-r--r--fuzzers/corpora/midx/81c7fc514fa9a07b5b87b94cf9c00df2b1325a74bin0 -> 455 bytes
-rw-r--r--fuzzers/corpora/midx/81f9df0493052d980ca13918637bc6ce565615b3bin0 -> 65 bytes
-rw-r--r--fuzzers/corpora/midx/82556b9345134dd689cb9d0d08d3dc8459454181bin0 -> 196 bytes
-rw-r--r--fuzzers/corpora/midx/82d35a7a6ffb333b02d0d597e88ffdd481237a8bbin0 -> 232 bytes
-rw-r--r--fuzzers/corpora/midx/82e931da372a2c69c0f10274342173c2be091f1cbin0 -> 334 bytes
-rw-r--r--fuzzers/corpora/midx/83e2b53f22afe8f7ee21d30fae2619ad0d6a71e3bin0 -> 216 bytes
-rw-r--r--fuzzers/corpora/midx/83f4d70189dbc0d3aaf5025977c53d4d34fc5893bin0 -> 699 bytes
-rw-r--r--fuzzers/corpora/midx/85e17cceba7850be893afdc04c8233bea1ef6e72bin0 -> 83 bytes
-rw-r--r--fuzzers/corpora/midx/874d4abdcd7db751eb930928231669afe90589f5bin0 -> 2633 bytes
-rw-r--r--fuzzers/corpora/midx/87894ec663568153d7837f49b80f6d2e99818bd7bin0 -> 186 bytes
-rw-r--r--fuzzers/corpora/midx/88052b76108b4ede342f3dd87bb6835b2f71ea83bin0 -> 77 bytes
-rw-r--r--fuzzers/corpora/midx/884c54256c0ec2cf1c5fa08a0b3d9c2fea021300bin0 -> 573 bytes
-rw-r--r--fuzzers/corpora/midx/8858f36373db5fd6b805a768af55c21019c664b2bin0 -> 213 bytes
-rw-r--r--fuzzers/corpora/midx/88fe8b6767c1bd32308208b22e0b00697e5eddf7bin0 -> 159 bytes
-rw-r--r--fuzzers/corpora/midx/898cac1610f2f2fb67eb092cd053f0006c3070e3bin0 -> 175 bytes
-rw-r--r--fuzzers/corpora/midx/89d0f5573ae1b524e7e9bdb1fb54ea4ce99e3ef0bin0 -> 4 bytes
-rw-r--r--fuzzers/corpora/midx/8a55300e400efd56be5e12258ebf575c4f3b55edbin0 -> 98 bytes
-rw-r--r--fuzzers/corpora/midx/8bf7b464aaa2c2b536aa1d76a1297c19155f56031
-rw-r--r--fuzzers/corpora/midx/8c05e8ef26302a79c89670ad3aa4e8d0bc921923bin0 -> 194 bytes
-rw-r--r--fuzzers/corpora/midx/8c15f5a268ded9663197d66e8d7d4098e0ae9bf5bin0 -> 27 bytes
-rw-r--r--fuzzers/corpora/midx/8ca9e85a9e628f0016ea4e6413945b3830730c24bin0 -> 228 bytes
-rw-r--r--fuzzers/corpora/midx/8e74126a239927900a8f655c813a4b230191a5babin0 -> 297 bytes
-rw-r--r--fuzzers/corpora/midx/8ee63e791c004427dd033b468b2ed7446ee6e2e0bin0 -> 255 bytes
-rw-r--r--fuzzers/corpora/midx/9028113aa78b649e13ff259027a4e450d469e5dabin0 -> 71 bytes
-rw-r--r--fuzzers/corpora/midx/90db2115b8262ebecbefbe8f0a07c451e39bca07bin0 -> 217 bytes
-rw-r--r--fuzzers/corpora/midx/923f28a4d1917e20ee0736b90695c2123c0c987cbin0 -> 728 bytes
-rw-r--r--fuzzers/corpora/midx/92a5c74e0506d65d1a12686496452870367b169abin0 -> 2584 bytes
-rw-r--r--fuzzers/corpora/midx/92dcf94eb2f92b4e1a232eab3b3f808f4236f118bin0 -> 195 bytes
-rw-r--r--fuzzers/corpora/midx/9414502aedbef5e307897683625418dd4ac575acbin0 -> 1758 bytes
-rw-r--r--fuzzers/corpora/midx/9422e25bec5fec9f84603a85673b54b1a5e77a40bin0 -> 33 bytes
-rw-r--r--fuzzers/corpora/midx/943754e865888063e0684aec838222522390d43ebin0 -> 205 bytes
-rw-r--r--fuzzers/corpora/midx/943e067806ae069afbc029ea7a612410e5395687bin0 -> 553 bytes
-rw-r--r--fuzzers/corpora/midx/9547646cc1a5d260df099b00ea7ee2b95567aee1bin0 -> 208 bytes
-rw-r--r--fuzzers/corpora/midx/968f7027ec9fbf75a519069ea5189e85a81448b2bin0 -> 1239 bytes
-rw-r--r--fuzzers/corpora/midx/9691046a2f8b31319a6fdfde0506c9a72aed839abin0 -> 2082 bytes
-rw-r--r--fuzzers/corpora/midx/96a8cd5c33986cc26cc00eb2de627149f5259e33bin0 -> 458 bytes
-rw-r--r--fuzzers/corpora/midx/972466bbc33d2d7d7c21be21c7594b51e78675c5bin0 -> 131 bytes
-rw-r--r--fuzzers/corpora/midx/980f21a3609762154030f7cf0fe98a892d20f220bin0 -> 149 bytes
-rw-r--r--fuzzers/corpora/midx/9865f12189ef977418d8410fceebb6830c74d820bin0 -> 296 bytes
-rw-r--r--fuzzers/corpora/midx/98a1096d609545083878d5126743bbc5985786a9bin0 -> 2325 bytes
-rw-r--r--fuzzers/corpora/midx/98c3b6bbf5dc19bc4aad894087277a36d7c79669bin0 -> 57 bytes
-rw-r--r--fuzzers/corpora/midx/98f9cd44400b592f809596004125267acf848435bin0 -> 31 bytes
-rw-r--r--fuzzers/corpora/midx/9a97260f04ecfe0918499ede95cf4bcb3dbc2b51bin0 -> 66 bytes
-rw-r--r--fuzzers/corpora/midx/9ba0dba2ca4405d04113086309882dac6182e6b8bin0 -> 2063 bytes
-rw-r--r--fuzzers/corpora/midx/9c329ee4b02f2d26ee1a399c873b0452aedca3c0bin0 -> 638 bytes
-rw-r--r--fuzzers/corpora/midx/9e8e638837e202d83ff606a22dd0e310150fa260bin0 -> 387 bytes
-rw-r--r--fuzzers/corpora/midx/9ee03d17e070df72547e423a412da0b6a60ad565bin0 -> 396 bytes
-rw-r--r--fuzzers/corpora/midx/9fad6bd2b07d65e607039bb2bcda0816410cf983bin0 -> 1841 bytes
-rw-r--r--fuzzers/corpora/midx/9fcbd21f4dd194a623d832422384a1519742f0bbbin0 -> 7 bytes
-rw-r--r--fuzzers/corpora/midx/a019fb7f17aa36a9743c530e1f11d5613b8b1158bin0 -> 2 bytes
-rw-r--r--fuzzers/corpora/midx/a0b8c6ef20198377b19f59e41f08f4cf2107f460bin0 -> 64 bytes
-rw-r--r--fuzzers/corpora/midx/a14079a3e8cbc2112da4fa747ef20cdfd580e068bin0 -> 66 bytes
-rw-r--r--fuzzers/corpora/midx/a14d61ba0c609665d37e6c6da929cb53c5b70545bin0 -> 322 bytes
-rw-r--r--fuzzers/corpora/midx/a15cf2a13e408cb76af0091a0c286af7ffce58e1bin0 -> 663 bytes
-rw-r--r--fuzzers/corpora/midx/a1ddedbdd05eac99b8b31322635771cd9c999f8abin0 -> 805 bytes
-rw-r--r--fuzzers/corpora/midx/a235661c3f8b0174a1658e9c435a69577c49256abin0 -> 365 bytes
-rw-r--r--fuzzers/corpora/midx/a261397a4db5ac196c72d73ba6999e9fd4fc5c1fbin0 -> 63 bytes
-rw-r--r--fuzzers/corpora/midx/a3a803fd6a56d31269717983bbdf2fceebb626c3bin0 -> 327 bytes
-rw-r--r--fuzzers/corpora/midx/a3d5b0b21d977e8f94d401250de1bbd4fa1d0ee0bin0 -> 321 bytes
-rw-r--r--fuzzers/corpora/midx/a42f2900ca519bd15b8d6f507449d1a07de2ef75bin0 -> 3549 bytes
-rw-r--r--fuzzers/corpora/midx/a4884775b414eaf9643224564f3be405519cf99abin0 -> 77 bytes
-rw-r--r--fuzzers/corpora/midx/a48da63e9a5709c24cb66f598a7a964cbc7ccfc7bin0 -> 456 bytes
-rw-r--r--fuzzers/corpora/midx/a5789fd83dff18079ea7ba41c999f57bee4db41bbin0 -> 381 bytes
-rw-r--r--fuzzers/corpora/midx/a5bb1c60191742df4a91afb622e9b22a2f0b7765bin0 -> 128 bytes
-rw-r--r--fuzzers/corpora/midx/a5fdfade1cef5e7e494dd6e3791bca5a663d7012bin0 -> 299 bytes
-rw-r--r--fuzzers/corpora/midx/a6c66f79f5aaf2c1a26ff16754fe1a8c22627e0cbin0 -> 983 bytes
-rw-r--r--fuzzers/corpora/midx/a7478a05a1fc04a9e035be5593bfb6a281ec460fbin0 -> 188 bytes
-rw-r--r--fuzzers/corpora/midx/a75193dd600661d2b417d4e29b23faa7d721c214bin0 -> 193 bytes
-rw-r--r--fuzzers/corpora/midx/a7ccae74c641ffcdda0042e6c04438d5b32c4cf3bin0 -> 1220 bytes
-rw-r--r--fuzzers/corpora/midx/a94aa5881abdea5374775b8155812121673f89c3bin0 -> 525 bytes
-rw-r--r--fuzzers/corpora/midx/a98d794f0f24be7a36917826121fc14a241208931
-rw-r--r--fuzzers/corpora/midx/a993077e321bc4e1831bb5a8ac7511d90d32ae27bin0 -> 193 bytes
-rw-r--r--fuzzers/corpora/midx/aa3bc67656945e43f9342d3aaaef247584d96cfabin0 -> 66 bytes
-rw-r--r--fuzzers/corpora/midx/ab111c4d72e3d6796e3d7391e9f35b4e6fefc04abin0 -> 129 bytes
-rw-r--r--fuzzers/corpora/midx/ab248c42f77952d5d17d6f5203adaa5925c05c64bin0 -> 260 bytes
-rw-r--r--fuzzers/corpora/midx/ab8451fadf805e5087837d9f6d91ef7eb6fa5edbbin0 -> 240 bytes
-rw-r--r--fuzzers/corpora/midx/abbee3b37aff879b1cef47390001b89b0f6ebc0abin0 -> 126 bytes
-rw-r--r--fuzzers/corpora/midx/ac15b23f03af8be6dbbb3bbb8d3877a1f9e074a3bin0 -> 321 bytes
-rw-r--r--fuzzers/corpora/midx/ac47bda12269c06d773f5f3c6517f78513a54a08bin0 -> 435 bytes
-rw-r--r--fuzzers/corpora/midx/ad1f4fb57f481a00a9bb231517a3155ef0d0877fbin0 -> 58 bytes
-rw-r--r--fuzzers/corpora/midx/ad25e7ffabedd94833d2529886af4d459529ec9dbin0 -> 182 bytes
-rw-r--r--fuzzers/corpora/midx/ad796ebb423f58187806c4a7ee7b787394353ce6bin0 -> 281 bytes
-rw-r--r--fuzzers/corpora/midx/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc1
-rw-r--r--fuzzers/corpora/midx/ae14b80f26f5cee2d85d5154c2cef1eefafa8cc9bin0 -> 527 bytes
-rw-r--r--fuzzers/corpora/midx/ae3ba892de543801b3c1dfbce370eb2c80a6fb27bin0 -> 850 bytes
-rw-r--r--fuzzers/corpora/midx/aecc0c7f08810803da234e26e7c6fa7a9f1c0593bin0 -> 393 bytes
-rw-r--r--fuzzers/corpora/midx/aed2e85d5d39d25e738a34f30a722680bde30368bin0 -> 229 bytes
-rw-r--r--fuzzers/corpora/midx/b00a75de1987c6f549bf73a63e8f23a2de6641b3bin0 -> 6 bytes
-rw-r--r--fuzzers/corpora/midx/b02e9f951ce9f10a8eb80f1fc61cd3d2832dd7f4bin0 -> 234 bytes
-rw-r--r--fuzzers/corpora/midx/b04aff8ab2e133d45bf44565bd4bf9e33b795a97bin0 -> 2242 bytes
-rw-r--r--fuzzers/corpora/midx/b12097ed83db761f7bb79411a59e2474de9b1199bin0 -> 261 bytes
-rw-r--r--fuzzers/corpora/midx/b1beb2f462b4cb30a09d534b9f49f2e08d76363c1
-rw-r--r--fuzzers/corpora/midx/b201733b6165f4544578bd6aad3f55aeafd9a194bin0 -> 259 bytes
-rw-r--r--fuzzers/corpora/midx/b2699f25c21ffe453dcce20e31b3093e0f9b2abf1
-rw-r--r--fuzzers/corpora/midx/b34a5760a1036f909e0243cd857fcef65e40d752bin0 -> 1931 bytes
-rw-r--r--fuzzers/corpora/midx/b3fdacd639073cc1954bcb1f31046d094e2d2296bin0 -> 449 bytes
-rw-r--r--fuzzers/corpora/midx/b40a6dbe32c8e6a9b777331e7fd97f0d94ceca1cbin0 -> 7 bytes
-rw-r--r--fuzzers/corpora/midx/b52ff2010f22ae6758cde5d529fd19de2a7d5fc5bin0 -> 123 bytes
-rw-r--r--fuzzers/corpora/midx/b53a7a2afd9dfc55c328b4e06a36882c53126e95bin0 -> 524 bytes
-rw-r--r--fuzzers/corpora/midx/b548ae8a77a62b7f375b8b48e7184ceed59bc8f8bin0 -> 327 bytes
-rw-r--r--fuzzers/corpora/midx/b66eaf0b689495cc7c194ab1fca7d36ae9da9758bin0 -> 172 bytes
-rw-r--r--fuzzers/corpora/midx/b680bf23da22b8b7e77d847169fe9b6968d79e8b1
-rw-r--r--fuzzers/corpora/midx/b70d6e7d230fb1393b8f665adcd5658cad7059febin0 -> 70 bytes
-rw-r--r--fuzzers/corpora/midx/b87a59f78adb3ef18b0176a8e7fe7e90c2ab4ef7bin0 -> 127 bytes
-rw-r--r--fuzzers/corpora/midx/b88c5233090e859e923acbdfa9b168f95d7fc14bbin0 -> 145 bytes
-rw-r--r--fuzzers/corpora/midx/ba1923ea69eec8fe765e8d1222eccb928ca6c3c2bin0 -> 554 bytes
-rw-r--r--fuzzers/corpora/midx/ba4d695c1eb02c702bd99a3db27838c7ba617d79bin0 -> 519 bytes
-rw-r--r--fuzzers/corpora/midx/ba7e4f999dc22d223c7f75db36646bfa05848572bin0 -> 2252 bytes
-rw-r--r--fuzzers/corpora/midx/bc5f0cd338d1d17a230378390aa810bc7b103cdabin0 -> 1371 bytes
-rw-r--r--fuzzers/corpora/midx/bcbb4cf10018a177dd9a6c642d887e0de3d8e522bin0 -> 209 bytes
-rw-r--r--fuzzers/corpora/midx/bcfeb114df6d5c6e0c85cbe1081631bc321ff65bbin0 -> 508 bytes
-rw-r--r--fuzzers/corpora/midx/bd582237a9293e2a53d8222722a69e7d215822bfbin0 -> 500 bytes
-rw-r--r--fuzzers/corpora/midx/bdc83a415da40f74825379203538a2e4d27cffa7bin0 -> 130 bytes
-rw-r--r--fuzzers/corpora/midx/be160536594c87dc07554a71c7d24cd1d718aeccbin0 -> 185 bytes
-rw-r--r--fuzzers/corpora/midx/be8f3c744a23f67fb316a39609ca11ddac025b58bin0 -> 325 bytes
-rw-r--r--fuzzers/corpora/midx/bf873b027b48f3fd7b727473c832486d99ddb196bin0 -> 151 bytes
-rw-r--r--fuzzers/corpora/midx/bf8e20ef6b79131ef9bab8c9c1bb7dbecbead6a5bin0 -> 259 bytes
-rw-r--r--fuzzers/corpora/midx/bf90507b8f7c7eebb89edeaabf6a432d86e7df4abin0 -> 164 bytes
-rw-r--r--fuzzers/corpora/midx/bfa7a5ce666899fb3e2a7216dbf59886da672658bin0 -> 979 bytes
-rw-r--r--fuzzers/corpora/midx/bfeaa454d8db33efabba88f146bee6c803369ba0bin0 -> 523 bytes
-rw-r--r--fuzzers/corpora/midx/c0388910e8d88dcd2e65848ba2cef465caa6b258bin0 -> 223 bytes
-rw-r--r--fuzzers/corpora/midx/c0db293f75bb44668bcbb79286ebed87df141a85bin0 -> 448 bytes
-rw-r--r--fuzzers/corpora/midx/c1234da1441255244aba15ecad2a4fa7fd47115ebin0 -> 130 bytes
-rw-r--r--fuzzers/corpora/midx/c2206ac3c289a759ee0e9d0d31cc336f0802f7bc1
-rw-r--r--fuzzers/corpora/midx/c22340ab36e5cff088a58272f63cf69e54a1a9f4bin0 -> 78 bytes
-rw-r--r--fuzzers/corpora/midx/c242c9336c4c22b316e0e56d616b2d45b3318ca4bin0 -> 1933 bytes
-rw-r--r--fuzzers/corpora/midx/c25a51d8dfaf58d5b609729bb156a80e3b0d892fbin0 -> 48 bytes
-rw-r--r--fuzzers/corpora/midx/c3419450240d06982b0d828911b188a903355216bin0 -> 953 bytes
-rw-r--r--fuzzers/corpora/midx/c36ea7651f76ae817d8d60cae580e47638741372bin0 -> 3715 bytes
-rw-r--r--fuzzers/corpora/midx/c42300c021bfd35702f564e917839503922cbe9abin0 -> 775 bytes
-rw-r--r--fuzzers/corpora/midx/c45d82ddade99ef857b563e435f2efe89e58b0bebin0 -> 11 bytes
-rw-r--r--fuzzers/corpora/midx/c4d1e9187de1e13353b3beb3c1ab16dd62cda571bin0 -> 1290 bytes
-rw-r--r--fuzzers/corpora/midx/c4e98278a25011c54734494d4534a97489cf4c24bin0 -> 704 bytes
-rw-r--r--fuzzers/corpora/midx/c4f996ab08f56ce2e9fec7a0428ded510dd6a04abin0 -> 5 bytes
-rw-r--r--fuzzers/corpora/midx/c544850a7325e7226583895204f99de730525803bin0 -> 393 bytes
-rw-r--r--fuzzers/corpora/midx/c56629528d5bebdb94f85522caf0f36bbcb19106bin0 -> 245 bytes
-rw-r--r--fuzzers/corpora/midx/c5c75b58883ccf41b20b140740e2ce763c6086cdbin0 -> 2377 bytes
-rw-r--r--fuzzers/corpora/midx/c62da85dca0d4dfb1d7af5d0520eb74993a1e3b0bin0 -> 97 bytes
-rw-r--r--fuzzers/corpora/midx/c6379aaaecd282b8ed6d0b4291d0d9fdc763160abin0 -> 198 bytes
-rw-r--r--fuzzers/corpora/midx/c6431921184e3edf4fd3e47384c69654cdac0189bin0 -> 840 bytes
-rw-r--r--fuzzers/corpora/midx/c6f2ca17c6d313a35676cbacd094eb40fd74b23ebin0 -> 64 bytes
-rw-r--r--fuzzers/corpora/midx/c83e04d58e04fccac37b9dd313eab72011fe8ea1bin0 -> 257 bytes
-rw-r--r--fuzzers/corpora/midx/c88dc350b98a5c5ae0503683318c1f30443906a81
-rw-r--r--fuzzers/corpora/midx/c89ee2e9e30a474b5f9532ec61d7aad78377baa0bin0 -> 367 bytes
-rw-r--r--fuzzers/corpora/midx/c921be4abeb44d1ff07f76f632a16e86526bc4bebin0 -> 52 bytes
-rw-r--r--fuzzers/corpora/midx/c98bdc0431aaece1e8a721aff0ea511cfb8062a6bin0 -> 81 bytes
-rw-r--r--fuzzers/corpora/midx/c9c456fd3e35a942ef4ab756e04e725cf1f71167bin0 -> 1503 bytes
-rw-r--r--fuzzers/corpora/midx/cd1f1a31b79af77e1e764102942ba7a79dcd24cfbin0 -> 10 bytes
-rw-r--r--fuzzers/corpora/midx/cd57e5904254c2278e9ecf28ed7414d7aed8eef1bin0 -> 108 bytes
-rw-r--r--fuzzers/corpora/midx/cd665cdc2bd6a26eb68c9af6d1728a7d4f6eb309bin0 -> 33 bytes
-rw-r--r--fuzzers/corpora/midx/ce72111c4314b22c4c7824bc8ea340ebd6d3fa84bin0 -> 218 bytes
-rw-r--r--fuzzers/corpora/midx/ceacc7ace2f4be962b0db2eeeea3fe6a00ca9dd6bin0 -> 58 bytes
-rw-r--r--fuzzers/corpora/midx/cf40769d8b4fcbac1b10ced2e0c3c1294f23fcddbin0 -> 1095 bytes
-rw-r--r--fuzzers/corpora/midx/d120111a77a3e3d1d504a04bbfc5f53effa14eb0bin0 -> 275 bytes
-rw-r--r--fuzzers/corpora/midx/d1ce81240a32aec2de1b0d779aa29a62c36f291fbin0 -> 1166 bytes
-rw-r--r--fuzzers/corpora/midx/d21869b290cd2b448e7b8103dced97e62fefffccbin0 -> 258 bytes
-rw-r--r--fuzzers/corpora/midx/d2bffcd01e87ce9860007b244ff1e79ecd3d4d0fbin0 -> 260 bytes
-rw-r--r--fuzzers/corpora/midx/d2d668b6e28fca83da5146021879c2b006406fa4bin0 -> 2113 bytes
-rw-r--r--fuzzers/corpora/midx/d37abe0d299b8ad1e90f5b7af302c24f411a7ed1bin0 -> 357 bytes
-rw-r--r--fuzzers/corpora/midx/d3d689a12ab3808313d5ba0044e8c67ecb4337e4bin0 -> 208 bytes
-rw-r--r--fuzzers/corpora/midx/d48eb559213edf05aa2850a14194885ae2086ba4bin0 -> 33 bytes
-rw-r--r--fuzzers/corpora/midx/d490f365693e49ebdeaf658b3f549311a399c6a8bin0 -> 503 bytes
-rw-r--r--fuzzers/corpora/midx/d54821b652a8611c486bedd8645081d3a4b1c8d1bin0 -> 252 bytes
-rw-r--r--fuzzers/corpora/midx/d5586a91f9a879e8a67ec7b09a48038909918ad9bin0 -> 509 bytes
-rw-r--r--fuzzers/corpora/midx/d696362920a2fad8e280293e8d1c92b18c87e4aebin0 -> 235 bytes
-rw-r--r--fuzzers/corpora/midx/d6b546a2b1bc1c8f80028e4be10c45a06014b32dbin0 -> 868 bytes
-rw-r--r--fuzzers/corpora/midx/d7f04cbca92b2122e0f437ed4dd8fd1782d40f7fbin0 -> 1163 bytes
-rw-r--r--fuzzers/corpora/midx/d81944a0c1ed56d11129533d9a3d0d038113d53dbin0 -> 300 bytes
-rw-r--r--fuzzers/corpora/midx/d8524e83ea63c9b365c2e93af75a8100a08b1b69bin0 -> 248 bytes
-rw-r--r--fuzzers/corpora/midx/d8d9a2d06763cf6feb433cef92a80ef14baab31abin0 -> 169 bytes
-rw-r--r--fuzzers/corpora/midx/d917fbd641cc40786246387456a636899d56b5a6bin0 -> 597 bytes
-rw-r--r--fuzzers/corpora/midx/d99f9ec8b504029457185ac03ea8ba21c2611737bin0 -> 188 bytes
-rw-r--r--fuzzers/corpora/midx/d9c9c90c1bbc55beb81875838e9067c473d0fa92bin0 -> 47 bytes
-rw-r--r--fuzzers/corpora/midx/d9e908317a6ef08a7528924672836a550d34cb5fbin0 -> 193 bytes
-rw-r--r--fuzzers/corpora/midx/d9ef71deb57fa6f40e027be2c84fa37d288e1cc5bin0 -> 646 bytes
-rw-r--r--fuzzers/corpora/midx/da8841b9d04382d62d4aeb3fde4dc78466f31543bin0 -> 447 bytes
-rw-r--r--fuzzers/corpora/midx/db3fbb74c9c9c4185f91eca85f14c3d2c3d9f487bin0 -> 24 bytes
-rw-r--r--fuzzers/corpora/midx/db7a31de22258d4dc17d44a27d9340946e9c9ee9bin0 -> 179 bytes
-rw-r--r--fuzzers/corpora/midx/dbbe57fc653930b4ff43f168565ba84ef25f60c2bin0 -> 261 bytes
-rw-r--r--fuzzers/corpora/midx/dbe74c0d9e7b62c1fd87d5e3ea73ee04f0337154bin0 -> 1995 bytes
-rw-r--r--fuzzers/corpora/midx/dbebf36a6b91568ac059142c3ca3211226da12a8bin0 -> 284 bytes
-rw-r--r--fuzzers/corpora/midx/ddacbb379242b31a00d62fdff5777dffc1e899c2bin0 -> 786 bytes
-rw-r--r--fuzzers/corpora/midx/decd2cd9cef352610ac9e5cc461df1829543f9f03
-rw-r--r--fuzzers/corpora/midx/deeae69363db06972798b296a0c5c99e02cb2b4cbin0 -> 2078 bytes
-rw-r--r--fuzzers/corpora/midx/e03e105323e6e7b2af90ad876b5c547af90d8f6bbin0 -> 15 bytes
-rw-r--r--fuzzers/corpora/midx/e3133215848c9cde428338c9d51424c8a81b96f5bin0 -> 745 bytes
-rw-r--r--fuzzers/corpora/midx/e32a25f0347b0e95d4bea16c27a1f374847683bdbin0 -> 130 bytes
-rw-r--r--fuzzers/corpora/midx/e45ce97522194abcdd7ff9beb931e20b86c97a79bin0 -> 1993 bytes
-rw-r--r--fuzzers/corpora/midx/e484023d50fc1036e46a437053b965c527700d42bin0 -> 154 bytes
-rw-r--r--fuzzers/corpora/midx/e4e60e77fe3a050940d0afcc7dbab7ef06b04ba3bin0 -> 137 bytes
-rw-r--r--fuzzers/corpora/midx/e51629784092d9cf811ea1bd894297f062ed7ec4bin0 -> 583 bytes
-rw-r--r--fuzzers/corpora/midx/e5a7e837029178b3fb6a26d77ea4574ffeaa219dbin0 -> 3162 bytes
-rw-r--r--fuzzers/corpora/midx/e5c616e9efdd9c80181f9210d0e3a81c08fe9b4dbin0 -> 1981 bytes
-rw-r--r--fuzzers/corpora/midx/e5e6e84e2c7770537c744bcfdbe8303afe39ef92bin0 -> 263 bytes
-rw-r--r--fuzzers/corpora/midx/e5fb20928feec1ee3114597317edc0e06c413749bin0 -> 95 bytes
-rw-r--r--fuzzers/corpora/midx/e789319791fe704e5a8ffd7cb570c8d2722ac35fbin0 -> 587 bytes
-rw-r--r--fuzzers/corpora/midx/e9fdb9f08f225b4231f01dda9c7b61e7b78bf7d3bin0 -> 132 bytes
-rw-r--r--fuzzers/corpora/midx/ea6780324dca9a06db28598dfb590436d846d99fbin0 -> 419 bytes
-rw-r--r--fuzzers/corpora/midx/ea6afcc92b8a6c9e14cc053d351909ad5b0a3fdfbin0 -> 450 bytes
-rw-r--r--fuzzers/corpora/midx/ea8c569029c0cacc4ae75e95b2f4e84abb6867f4bin0 -> 2099 bytes
-rw-r--r--fuzzers/corpora/midx/eb3e80c3ea9cfe9e08b2eef117aaa522a51a619cbin0 -> 955 bytes
-rw-r--r--fuzzers/corpora/midx/ec55b30741fe8fffeec584176c8d20f6a679cfa1bin0 -> 441 bytes
-rw-r--r--fuzzers/corpora/midx/ed0724a6c3804a3ab20a980b5ca48671689a602fbin0 -> 1167 bytes
-rw-r--r--fuzzers/corpora/midx/edeb545d1cf852dc9582fa764010fe844a5e3515bin0 -> 258 bytes
-rw-r--r--fuzzers/corpora/midx/ee70b920de91f1be6b4448070ee2d1bd9e08286dbin0 -> 2337 bytes
-rw-r--r--fuzzers/corpora/midx/ef004af4e947d25b4d1d1dd16502260d4c7a99cdbin0 -> 142 bytes
-rw-r--r--fuzzers/corpora/midx/f009d226503b73aed0f1fd952ef8725433d158bebin0 -> 1995 bytes
-rw-r--r--fuzzers/corpora/midx/f0a821dffe21afd357932febaf6e8ee331f53197bin0 -> 200 bytes
-rw-r--r--fuzzers/corpora/midx/f101a2fe93dfaaed1c596022b4e509cf3a591c8abin0 -> 186 bytes
-rw-r--r--fuzzers/corpora/midx/f1101f71657385174f8cb920026a761404b4395dbin0 -> 316 bytes
-rw-r--r--fuzzers/corpora/midx/f138c84e42d3cc61a219c4be9db791750f0541c81
-rw-r--r--fuzzers/corpora/midx/f1da273522bfff4a4971b4ffc31e365f60fdbbfebin0 -> 969 bytes
-rw-r--r--fuzzers/corpora/midx/f2fe69d30ec47e78a9e92f1423698a52270672b2bin0 -> 192 bytes
-rw-r--r--fuzzers/corpora/midx/f368bb6f633587a7bb271de7e20695f178c89686bin0 -> 2021 bytes
-rw-r--r--fuzzers/corpora/midx/f38ced5a16edaceb5f527ebc35e7870f42586c90bin0 -> 215 bytes
-rw-r--r--fuzzers/corpora/midx/f404371362ae68ffb2837ce1766346ebb645d173bin0 -> 71 bytes
-rw-r--r--fuzzers/corpora/midx/f473b5e1cf51502345f5c1840ec3948d308dd314bin0 -> 25 bytes
-rw-r--r--fuzzers/corpora/midx/f4ad43d6f913c3be6243dfc439e4b6f5b2e814b9bin0 -> 241 bytes
-rw-r--r--fuzzers/corpora/midx/f4cde4083a974d755a38bf5ea3820f78b576754abin0 -> 508 bytes
-rw-r--r--fuzzers/corpora/midx/f5888d0dcacda196d73772aabc18fe2ad6e1dfa2bin0 -> 179 bytes
-rw-r--r--fuzzers/corpora/midx/f5c3577a62d401f071d5edaa77c54ae98d6a03181
-rw-r--r--fuzzers/corpora/midx/f5dee0d9da0d6950069ac36b1880090a20f50f3ebin0 -> 96 bytes
-rw-r--r--fuzzers/corpora/midx/f605fff495fef2719585c706c05c350812402a35bin0 -> 397 bytes
-rw-r--r--fuzzers/corpora/midx/f6fdaf4e77e29c780b9e0b91637777575bebfab4bin0 -> 33 bytes
-rw-r--r--fuzzers/corpora/midx/f72700bd65fa86c588607ec50d60a9c684c86f43bin0 -> 258 bytes
-rw-r--r--fuzzers/corpora/midx/f777db12ef18f002febd5af13e2b948c95d964c3bin0 -> 69 bytes
-rw-r--r--fuzzers/corpora/midx/f777e9274d508e7ac1069e2a04bedc042942491cbin0 -> 92 bytes
-rw-r--r--fuzzers/corpora/midx/f81306f8ceaec3d06d5d34afa9769d15f0d209ebbin0 -> 528 bytes
-rw-r--r--fuzzers/corpora/midx/f84c2b36689f22809d9bda00febab557c381ffa4bin0 -> 259 bytes
-rw-r--r--fuzzers/corpora/midx/f98168fa74c26b17ad0c3002f2263beb0af7c0cebin0 -> 259 bytes
-rw-r--r--fuzzers/corpora/midx/fa6759d6a2807bbad83ba21761772c0119122c35bin0 -> 263 bytes
-rw-r--r--fuzzers/corpora/midx/fa8b927b25a67fa3d60b12c53ac365366cc2b52dbin0 -> 191 bytes
-rw-r--r--fuzzers/corpora/midx/fc5e4b78e59daebed1118389b57a386981f2430ebin0 -> 237 bytes
-rw-r--r--fuzzers/corpora/midx/fdaf408880429153cfcf5d978727cd7b84c3d60ebin0 -> 33 bytes
-rw-r--r--fuzzers/corpora/midx/fe50e7564a28683b24c57f8bcdcb3fbfa61f5c6abin0 -> 583 bytes
-rw-r--r--fuzzers/corpora/midx/fe64b998872d3ad87df2019173ddc52686841d7dbin0 -> 1818 bytes
-rw-r--r--fuzzers/corpora/midx/fec56c7cc86871aaa9c7a947c4084307cac2778dbin0 -> 219 bytes
-rw-r--r--fuzzers/corpora/midx/ff164dfc56dd28709488130dc6dfc17406bf9e9dbin0 -> 811 bytes
-rw-r--r--fuzzers/corpora/midx/ff7035b3c055718728a6025b3cdf55c34c4c744bbin0 -> 251 bytes
-rw-r--r--fuzzers/midx_fuzzer.c76
-rw-r--r--git.git-authors4
-rw-r--r--include/git2.h1
-rw-r--r--include/git2/annotated_commit.h2
-rw-r--r--include/git2/apply.h2
-rw-r--r--include/git2/attr.h95
-rw-r--r--include/git2/blame.h135
-rw-r--r--include/git2/blob.h40
-rw-r--r--include/git2/branch.h25
-rw-r--r--include/git2/cert.h47
-rw-r--r--include/git2/checkout.h40
-rw-r--r--include/git2/clone.h2
-rw-r--r--include/git2/commit.h54
-rw-r--r--include/git2/common.h57
-rw-r--r--include/git2/config.h2
-rw-r--r--include/git2/deprecated.h340
-rw-r--r--include/git2/diff.h147
-rw-r--r--include/git2/email.h127
-rw-r--r--include/git2/errors.h12
-rw-r--r--include/git2/filter.h80
-rw-r--r--include/git2/graph.h22
-rw-r--r--include/git2/index.h6
-rw-r--r--include/git2/indexer.h3
-rw-r--r--include/git2/notes.h4
-rw-r--r--include/git2/odb.h64
-rw-r--r--include/git2/oidarray.h13
-rw-r--r--include/git2/patch.h8
-rw-r--r--include/git2/rebase.h26
-rw-r--r--include/git2/refs.h14
-rw-r--r--include/git2/remote.h71
-rw-r--r--include/git2/repository.h169
-rw-r--r--include/git2/revparse.h10
-rw-r--r--include/git2/stash.h2
-rw-r--r--include/git2/status.h174
-rw-r--r--include/git2/stdint.h6
-rw-r--r--include/git2/submodule.h9
-rw-r--r--include/git2/sys/commit_graph.h174
-rw-r--r--include/git2/sys/email.h45
-rw-r--r--include/git2/sys/filter.h77
-rw-r--r--include/git2/sys/midx.h74
-rw-r--r--include/git2/sys/odb_backend.h7
-rw-r--r--include/git2/sys/transport.h1
-rw-r--r--include/git2/tag.h12
-rw-r--r--include/git2/transport.h2
-rw-r--r--include/git2/tree.h16
-rw-r--r--include/git2/types.h9
-rw-r--r--include/git2/version.h6
-rw-r--r--include/git2/worktree.h1
-rw-r--r--package.json2
-rwxr-xr-xscript/release.py9
-rw-r--r--script/sanitizers.supp4
-rw-r--r--script/thread-sanitizer.supp26
-rw-r--r--script/valgrind.supp64
-rw-r--r--src/CMakeLists.txt90
-rw-r--r--src/alloc.c29
-rw-r--r--src/allocators/failalloc.c92
-rw-r--r--src/allocators/failalloc.h23
-rw-r--r--src/allocators/stdalloc.c51
-rw-r--r--src/allocators/win32_crtdbg.c118
-rw-r--r--src/allocators/win32_leakcheck.c118
-rw-r--r--src/allocators/win32_leakcheck.h (renamed from src/allocators/win32_crtdbg.h)6
-rw-r--r--src/annotated_commit.c30
-rw-r--r--src/apply.c26
-rw-r--r--src/array.h22
-rw-r--r--src/attr.c262
-rw-r--r--src/attr_file.c129
-rw-r--r--src/attr_file.h43
-rw-r--r--src/attrcache.c79
-rw-r--r--src/attrcache.h9
-rw-r--r--src/blame.c49
-rw-r--r--src/blame_git.c2
-rw-r--r--src/blob.c90
-rw-r--r--src/branch.c122
-rw-r--r--src/buf_text.c316
-rw-r--r--src/buf_text.h122
-rw-r--r--src/buffer.c376
-rw-r--r--src/buffer.h156
-rw-r--r--src/cache.c6
-rw-r--r--src/cache.h14
-rw-r--r--src/cc-compat.h18
-rw-r--r--src/checkout.c87
-rw-r--r--src/cherrypick.c8
-rw-r--r--src/clone.c133
-rw-r--r--src/commit.c69
-rw-r--r--src/commit_graph.c1209
-rw-r--r--src/commit_graph.h162
-rw-r--r--src/commit_list.c46
-rw-r--r--src/commit_list.h2
-rw-r--r--src/common.h27
-rw-r--r--src/config.c62
-rw-r--r--src/config_cache.c13
-rw-r--r--src/config_entries.c62
-rw-r--r--src/config_file.c26
-rw-r--r--src/config_parse.c14
-rw-r--r--src/crlf.c22
-rw-r--r--src/date.c7
-rw-r--r--src/delta.c2
-rw-r--r--src/describe.c13
-rw-r--r--src/diff.c233
-rw-r--r--src/diff_driver.c38
-rw-r--r--src/diff_file.c12
-rw-r--r--src/diff_generate.c63
-rw-r--r--src/diff_print.c25
-rw-r--r--src/diff_stats.c23
-rw-r--r--src/diff_tform.c21
-rw-r--r--src/diff_xdiff.c6
-rw-r--r--src/diff_xdiff.h2
-rw-r--r--src/email.c299
-rw-r--r--src/email.h25
-rw-r--r--src/errors.c43
-rw-r--r--src/features.h.in6
-rw-r--r--src/fetch.c7
-rw-r--r--src/fetchhead.c12
-rw-r--r--src/filebuf.c16
-rw-r--r--src/filter.c322
-rw-r--r--src/filter.h29
-rw-r--r--src/futils.c10
-rw-r--r--src/futils.h2
-rw-r--r--src/global.c361
-rw-r--r--src/global.h41
-rw-r--r--src/graph.c73
-rw-r--r--src/hash.c29
-rw-r--r--src/hash.h2
-rw-r--r--src/hash/sha1/collisiondetect.c6
-rw-r--r--src/hash/sha1/common_crypto.c6
-rw-r--r--src/hash/sha1/generic.h2
-rw-r--r--src/hash/sha1/mbedtls.c24
-rw-r--r--src/hash/sha1/openssl.c6
-rw-r--r--src/hash/sha1/sha1dc/sha1.c18
-rw-r--r--src/hash/sha1/win32.c26
-rw-r--r--src/hashsig.c33
-rw-r--r--src/ident.c16
-rw-r--r--src/ignore.c50
-rw-r--r--src/index.c201
-rw-r--r--src/index.h2
-rw-r--r--src/indexer.c123
-rw-r--r--src/integer.h81
-rw-r--r--src/iterator.c60
-rw-r--r--src/iterator.h2
-rw-r--r--src/khash.h13
-rw-r--r--src/libgit2.c (renamed from src/settings.c)197
-rw-r--r--src/libgit2.h15
-rw-r--r--src/mailmap.c33
-rw-r--r--src/map.h6
-rw-r--r--src/merge.c118
-rw-r--r--src/merge.h3
-rw-r--r--src/merge_driver.c32
-rw-r--r--src/merge_file.c14
-rw-r--r--src/message.c4
-rw-r--r--src/midx.c879
-rw-r--r--src/midx.h110
-rw-r--r--src/mwindow.c309
-rw-r--r--src/mwindow.h6
-rw-r--r--src/net.c137
-rw-r--r--src/net.h18
-rw-r--r--src/netops.c10
-rw-r--r--src/netops.h4
-rw-r--r--src/notes.c80
-rw-r--r--src/object.c39
-rw-r--r--src/odb.c353
-rw-r--r--src/odb.h18
-rw-r--r--src/odb_loose.c52
-rw-r--r--src/odb_mempack.c2
-rw-r--r--src/odb_pack.c505
-rw-r--r--src/oid.c9
-rw-r--r--src/oidarray.c11
-rw-r--r--src/pack-objects.c102
-rw-r--r--src/pack.c480
-rw-r--r--src/pack.h45
-rw-r--r--src/patch.c21
-rw-r--r--src/patch_generate.c8
-rw-r--r--src/patch_parse.c6
-rw-r--r--src/path.c155
-rw-r--r--src/path.h87
-rw-r--r--src/pathspec.c16
-rw-r--r--src/pool.c48
-rw-r--r--src/pool.h8
-rw-r--r--src/posix.c55
-rw-r--r--src/posix.h9
-rw-r--r--src/reader.c16
-rw-r--r--src/rebase.c142
-rw-r--r--src/refdb.c178
-rw-r--r--src/refdb.h69
-rw-r--r--src/refdb_fs.c293
-rw-r--r--src/reflog.c33
-rw-r--r--src/refs.c382
-rw-r--r--src/refs.h21
-rw-r--r--src/refspec.c126
-rw-r--r--src/regexp.c4
-rw-r--r--src/remote.c434
-rw-r--r--src/remote.h3
-rw-r--r--src/repository.c638
-rw-r--r--src/repository.h56
-rw-r--r--src/reset.c15
-rw-r--r--src/revert.c8
-rw-r--r--src/revparse.c31
-rw-r--r--src/revwalk.c47
-rw-r--r--src/runtime.c162
-rw-r--r--src/runtime.h62
-rw-r--r--src/settings.h11
-rw-r--r--src/signature.c11
-rw-r--r--src/sortedcache.h18
-rw-r--r--src/stash.c6
-rw-r--r--src/status.c11
-rw-r--r--src/strarray.c3
-rw-r--r--src/streams/mbedtls.c31
-rw-r--r--src/streams/mbedtls.h2
-rw-r--r--src/streams/openssl.c302
-rw-r--r--src/streams/openssl.h10
-rw-r--r--src/streams/openssl_dynamic.c309
-rw-r--r--src/streams/openssl_dynamic.h348
-rw-r--r--src/streams/openssl_legacy.c203
-rw-r--r--src/streams/openssl_legacy.h63
-rw-r--r--src/streams/registry.c11
-rw-r--r--src/streams/socket.c8
-rw-r--r--src/streams/stransport.c9
-rw-r--r--src/streams/tls.c8
-rw-r--r--src/submodule.c190
-rw-r--r--src/submodule.h18
-rw-r--r--src/sysdir.c15
-rw-r--r--src/tag.c58
-rw-r--r--src/thread-utils.c58
-rw-r--r--src/thread-utils.h246
-rw-r--r--src/thread.c140
-rw-r--r--src/thread.h479
-rw-r--r--src/threadstate.c84
-rw-r--r--src/threadstate.h24
-rw-r--r--src/trace.c4
-rw-r--r--src/trace.h30
-rw-r--r--src/trailer.c2
-rw-r--r--src/transaction.c27
-rw-r--r--src/transport.c6
-rw-r--r--src/transports/auth.c2
-rw-r--r--src/transports/auth_negotiate.c15
-rw-r--r--src/transports/auth_ntlm.c16
-rw-r--r--src/transports/credential.c22
-rw-r--r--src/transports/git.c4
-rw-r--r--src/transports/http.c36
-rw-r--r--src/transports/http.h1
-rw-r--r--src/transports/httpclient.c104
-rw-r--r--src/transports/httpclient.h2
-rw-r--r--src/transports/local.c6
-rw-r--r--src/transports/smart.c19
-rw-r--r--src/transports/smart.h2
-rw-r--r--src/transports/smart_protocol.c16
-rw-r--r--src/transports/ssh.c76
-rw-r--r--src/transports/winhttp.c246
-rw-r--r--src/tree.c177
-rw-r--r--src/tree.h1
-rw-r--r--src/tsort.c2
-rw-r--r--src/unix/map.c4
-rw-r--r--src/unix/posix.h17
-rw-r--r--src/unix/pthread.h3
-rw-r--r--src/utf8.c150
-rw-r--r--src/utf8.h52
-rw-r--r--src/util.c184
-rw-r--r--src/util.h74
-rw-r--r--src/vector.c42
-rw-r--r--src/vector.h6
-rw-r--r--src/win32/findfile.c8
-rw-r--r--src/win32/git2.rc21
-rw-r--r--src/win32/map.c2
-rw-r--r--src/win32/msvc-compat.h10
-rw-r--r--src/win32/path_w32.c46
-rw-r--r--src/win32/path_w32.h1
-rw-r--r--src/win32/posix.h12
-rw-r--r--src/win32/posix_w32.c93
-rw-r--r--src/win32/precompiled.h1
-rw-r--r--src/win32/reparse.h8
-rw-r--r--src/win32/thread.c39
-rw-r--r--src/win32/thread.h2
-rw-r--r--src/win32/w32_buffer.c6
-rw-r--r--src/win32/w32_common.h27
-rw-r--r--src/win32/w32_crtdbg_stacktrace.h127
-rw-r--r--src/win32/w32_leakcheck.c (renamed from src/win32/w32_crtdbg_stacktrace.c)302
-rw-r--r--src/win32/w32_leakcheck.h222
-rw-r--r--src/win32/w32_stack.c188
-rw-r--r--src/win32/w32_stack.h140
-rw-r--r--src/win32/w32_util.h12
-rw-r--r--src/worktree.c46
-rw-r--r--src/zstream.c2
-rw-r--r--tests/CMakeLists.txt5
-rw-r--r--tests/apply/apply_helpers.h9
-rw-r--r--tests/apply/both.c11
-rw-r--r--tests/apply/fromdiff.c1
-rw-r--r--tests/apply/fromfile.c1
-rw-r--r--tests/apply/partial.c1
-rw-r--r--tests/attr/lookup.c3
-rw-r--r--tests/attr/repo.c14
-rw-r--r--tests/checkout/tree.c48
-rw-r--r--tests/clar/fs.h86
-rw-r--r--tests/clar/sandbox.h11
-rw-r--r--tests/clar_libgit2.c7
-rw-r--r--tests/clar_libgit2_trace.c4
-rw-r--r--tests/clone/empty.c17
-rw-r--r--tests/clone/nonetwork.c8
-rw-r--r--tests/config/include.c24
-rw-r--r--tests/config/read.c83
-rw-r--r--tests/config/stress.c5
-rw-r--r--tests/core/buffer.c104
-rw-r--r--tests/core/encoding.c6
-rw-r--r--tests/core/integer.c253
-rw-r--r--tests/core/link.c10
-rw-r--r--tests/core/opts.c46
-rw-r--r--tests/core/path.c28
-rw-r--r--tests/core/sha1.c2
-rw-r--r--tests/core/sortedcache.c6
-rw-r--r--tests/core/string.c11
-rw-r--r--tests/core/strtol.c10
-rw-r--r--tests/core/structinit.c13
-rw-r--r--tests/core/useragent.c2
-rw-r--r--tests/core/utf8.c19
-rw-r--r--tests/core/vector.c12
-rw-r--r--tests/diff/format_email.c24
-rw-r--r--tests/diff/parse.c23
-rw-r--r--tests/diff/patch.c1
-rw-r--r--tests/diff/rename.c58
-rw-r--r--tests/diff/stats.c38
-rw-r--r--tests/diff/workdir.c35
-rw-r--r--tests/email/create.c363
-rw-r--r--tests/fetchhead/nonetwork.c31
-rw-r--r--tests/filter/bare.c56
-rw-r--r--tests/filter/crlf.c116
-rw-r--r--tests/filter/custom.c30
-rw-r--r--tests/filter/custom_helpers.c27
-rw-r--r--tests/filter/stream.c1
-rw-r--r--tests/filter/wildcard.c32
-rw-r--r--tests/graph/commit_graph.c125
-rw-r--r--tests/graph/reachable_from_any.c236
-rw-r--r--tests/ignore/path.c8
-rw-r--r--tests/ignore/status.c4
-rw-r--r--tests/index/addall.c4
-rw-r--r--tests/index/bypath.c5
-rw-r--r--tests/iterator/workdir.c2
-rw-r--r--tests/mailmap/parsing.c3
-rw-r--r--tests/main.c13
-rw-r--r--tests/merge/workdir/setup.c4
-rw-r--r--tests/network/refspecs.c2
-rw-r--r--tests/network/remote/isvalidname.c23
-rw-r--r--tests/network/remote/remotes.c95
-rw-r--r--tests/network/url/joinpath.c (renamed from tests/network/joinpath.c)16
-rw-r--r--tests/network/url/parse.c557
-rw-r--r--tests/network/url/pattern.c103
-rw-r--r--tests/network/url/redirect.c (renamed from tests/network/redirect.c)24
-rw-r--r--tests/network/urlparse.c168
-rw-r--r--tests/object/blob/filter.c9
-rw-r--r--tests/object/tag/list.c6
-rw-r--r--tests/odb/foreach.c2
-rw-r--r--tests/odb/sorting.c29
-rw-r--r--tests/online/badssl.c9
-rw-r--r--tests/online/clone.c36
-rw-r--r--tests/online/customcert.c79
-rw-r--r--tests/online/fetch.c40
-rw-r--r--tests/online/push_util.c4
-rw-r--r--tests/online/push_util.h2
-rw-r--r--tests/pack/filelimit.c136
-rw-r--r--tests/pack/midx.c110
-rw-r--r--tests/pack/threadsafety.c62
-rw-r--r--tests/path/core.c459
-rw-r--r--tests/path/dotgit.c8
-rw-r--r--tests/path/win32.c10
-rw-r--r--tests/rebase/sign.c254
-rw-r--r--tests/refs/basic.c41
-rw-r--r--tests/refs/branches/name.c17
-rw-r--r--tests/refs/branches/upstream.c25
-rw-r--r--tests/refs/isvalidname.c51
-rw-r--r--tests/refs/races.c18
-rw-r--r--tests/refs/reflog/messages.c9
-rw-r--r--tests/refs/revparse.c26
-rw-r--r--tests/refs/tags/name.c17
-rw-r--r--tests/remote/fetch.c169
-rw-r--r--tests/remote/httpproxy.c188
-rw-r--r--tests/repo/extensions.c72
-rw-r--r--tests/repo/getters.c13
-rw-r--r--tests/repo/hashfile.c89
-rw-r--r--tests/repo/init.c233
-rw-r--r--tests/repo/open.c42
-rw-r--r--tests/resources/certs/61f2ddb6.031
-rw-r--r--tests/resources/certs/db4f60b0.031
-rw-r--r--tests/resources/config/config1210
-rw-r--r--tests/resources/config/config215
-rw-r--r--tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fbbin0 -> 20 bytes
-rw-r--r--tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322dbin0 -> 170 bytes
-rw-r--r--tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341cbin0 -> 658 bytes
-rw-r--r--tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0bin0 -> 658 bytes
-rw-r--r--tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f03
-rw-r--r--tests/resources/crlf.git/refs/heads/ident1
-rw-r--r--tests/resources/crlf.git/refs/heads/no-ident1
-rw-r--r--tests/resources/merge-recursive/.gitted/objects/info/commit-graphbin0 -> 4624 bytes
-rw-r--r--tests/resources/renames/.gitted/ORIG_HEAD1
-rw-r--r--tests/resources/renames/.gitted/indexbin352 -> 385 bytes
-rw-r--r--tests/resources/renames/.gitted/logs/HEAD5
-rw-r--r--tests/resources/renames/.gitted/objects/41/2a2eaf2c13103ea976b3b02c17abee7a358432bin0 -> 82 bytes
-rw-r--r--tests/resources/renames/.gitted/objects/5a/71babaaac78a758b52576a60cea3c218c8b546bin0 -> 2804 bytes
-rw-r--r--tests/resources/renames/.gitted/objects/7e/7bfb88ba9bc65fd700fee1819cf1c317aafa562
-rw-r--r--tests/resources/renames/.gitted/objects/bf/102db0c9c0c1513909a90e0611b5dddfc87c932
-rw-r--r--tests/resources/renames/.gitted/objects/cc/980ffac5f1393696d4cd703ea9d2fde67dd367bin0 -> 2801 bytes
-rw-r--r--tests/resources/renames/.gitted/objects/db/98035f715427eef1f5e17f03e1801c05301e9ebin0 -> 199 bytes
-rw-r--r--tests/resources/renames/.gitted/objects/eb/b3b7af1d25c8492d2f626826c92458b7cefd60bin0 -> 5164 bytes
-rw-r--r--tests/resources/renames/.gitted/objects/ed/2a95c4a6c295b9afcea50baff63ec544ccf600bin0 -> 5161 bytes
-rw-r--r--tests/resources/renames/.gitted/objects/f6/7e2f70efe89665e829ea0d77c46965ad1307e4bin0 -> 5164 bytes
-rw-r--r--tests/resources/renames/.gitted/refs/heads/break_rewrite1
-rw-r--r--tests/resources/revert-rename.git/HEAD1
-rw-r--r--tests/resources/revert-rename.git/config5
-rw-r--r--tests/resources/revert-rename.git/indexbin0 -> 209 bytes
-rw-r--r--tests/resources/revert-rename.git/objects/info/packs2
-rw-r--r--tests/resources/revert-rename.git/objects/pack/pack-4363774fb90141e8aa7a326ace0566366114e869.idxbin0 -> 1296 bytes
-rw-r--r--tests/resources/revert-rename.git/objects/pack/pack-4363774fb90141e8aa7a326ace0566366114e869.packbin0 -> 783 bytes
-rw-r--r--tests/resources/revert-rename.git/packed-refs2
-rw-r--r--tests/resources/revert-rename.git/refs/heads/master1
-rw-r--r--tests/resources/self-signed.pem20
-rw-r--r--tests/resources/testrepo.git/objects/info/commit-graphbin0 -> 1940 bytes
-rw-r--r--tests/resources/testrepo.git/objects/pack/multi-pack-indexbin0 -> 47188 bytes
-rw-r--r--tests/revert/rename.c49
-rw-r--r--tests/revwalk/basic.c2
-rw-r--r--tests/revwalk/mergebase.c74
-rw-r--r--tests/status/worktree.c41
-rw-r--r--tests/submodule/lookup.c40
-rw-r--r--tests/threads/atomic.c125
-rw-r--r--tests/threads/basic.c8
-rw-r--r--tests/threads/diff.c18
-rw-r--r--tests/threads/thread_helpers.h2
-rw-r--r--tests/threads/tlsdata.c65
-rw-r--r--tests/trace/windows/stacktrace.c106
-rw-r--r--tests/win32/longpath.c99
-rw-r--r--tests/worktree/merge.c6
-rw-r--r--tests/worktree/refs.c5
-rw-r--r--tests/worktree/repository.c5
-rw-r--r--tests/worktree/worktree.c76
1460 files changed, 22764 insertions, 8257 deletions
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 000000000..bc6344b93
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,3 @@
+{
+ "postCreateCommand": "bash .devcontainer/setup.sh"
+}
diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh
new file mode 100755
index 000000000..c328bf3b9
--- /dev/null
+++ b/.devcontainer/setup.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -e
+
+sudo apt-get update
+sudo apt-get -y --no-install-recommends install cmake
+
+mkdir build
+cd build
+cmake .. \ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
index 176a458f9..3d90b7d61 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,2 @@
* text=auto
+tests/resources/** linguist-vendored
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000..38b4a044a
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,36 @@
+name: "CodeQL"
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '21 3 * * 1'
+
+env:
+ docker-registry: docker.pkg.github.com
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: 'cpp'
+
+ - name: Build
+ run: |
+ mkdir build
+ cd build
+ cmake .. -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ cmake --build .
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 02f19e2c6..572f02544 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,16 +1,17 @@
# Continuous integration and pull request validation builds for the
-# master and maintenance branches.
+# main and maintenance branches.
name: CI Build
on:
push:
- branches: [ master, maint/* ]
+ branches: [ main, maint/* ]
pull_request:
- branches: [ master, maint/* ]
+ branches: [ main, maint/* ]
+ workflow_dispatch:
env:
docker-registry: docker.pkg.github.com
- docker-config-path: azure-pipelines/docker
+ docker-config-path: source/ci/docker
jobs:
# Build the docker container images that we will use for our Linux
@@ -26,72 +27,141 @@ jobs:
strategy:
matrix:
container:
- - xenial
- - bionic
- - docurium
+ - name: xenial
+ - name: bionic
+ - name: focal
+ - name: docurium
+ - name: bionic-x86
+ dockerfile: bionic
+ base: multiarch/ubuntu-core:x86-bionic
+ qemu: true
+ - name: bionic-arm32
+ dockerfile: bionic
+ base: multiarch/ubuntu-core:armhf-bionic
+ qemu: true
+ - name: bionic-arm64
+ dockerfile: bionic
+ base: multiarch/ubuntu-core:arm64-bionic
+ qemu: true
+ - name: centos7
+ - name: centos8
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v2
with:
+ path: source
fetch-depth: 0
- if: github.event_name == 'push'
+ if: github.event_name != 'pull_request'
+ - name: Setup QEMU
+ run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
+ if: matrix.container.qemu == true
- name: Download existing container
- run: azure-pipelines/getcontainer.sh ${{ env.docker-config-path }}/${{ matrix.container }}
+ run: |
+ "${{ github.workspace }}/source/ci/getcontainer.sh" "${{ matrix.container.name }}" "${{ matrix.container.dockerfile }}"
env:
DOCKER_REGISTRY: ${{ env.docker-registry }}
GITHUB_TOKEN: ${{ secrets.github_token }}
- if: github.event_name == 'push'
+ working-directory: ${{ env.docker-config-path }}
+ if: github.event_name != 'pull_request'
- name: Build and publish image
run: |
- docker build -t ${{ env.docker-registry-container-sha }} --build-arg BASE=${{ matrix.container.base }} -f ${{ matrix.container }} .
+ if [ "${{ matrix.container.base }}" != "" ]; then
+ BASE_ARG="--build-arg BASE=${{ matrix.container.base }}"
+ fi
+ docker build -t ${{ env.docker-registry-container-sha }} ${BASE_ARG} -f ${{ env.dockerfile }} .
+ docker tag ${{ env.docker-registry-container-sha }} ${{ env.docker-registry-container-latest }}
docker push ${{ env.docker-registry-container-sha }}
+ docker push ${{ env.docker-registry-container-latest }}
working-directory: ${{ env.docker-config-path }}
- if: github.event_name == 'push' && env.docker-container-exists != 'true'
+ if: github.event_name != 'pull_request' && env.docker-container-exists != 'true'
# Run our CI/CD builds. We build a matrix with the various build targets
# and their details. Then we build either in a docker container (Linux)
# or on the actual hosts (macOS, Windows).
build:
name: Build
- needs: [build_containers]
+ needs: [ build_containers ]
strategy:
matrix:
platform:
- # Xenial, GCC, OpenSSL
- image: xenial
+ container:
+ name: xenial
env:
CC: gcc
CMAKE_GENERATOR: Ninja
- CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DDEBUG_STRICT_ALLOC=ON -DDEBUG_STRICT_OPEN=ON
os: ubuntu-latest
- # Xenial, GCC, mbedTLS
- image: xenial
+ container:
+ name: xenial
env:
CC: gcc
CMAKE_GENERATOR: Ninja
CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
os: ubuntu-latest
- # Xenial, Clang, OpenSSL
- image: xenial
+ container:
+ name: xenial
env:
CC: clang
CMAKE_GENERATOR: Ninja
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
os: ubuntu-latest
- # Xenial, Clang, mbedTLS
- image: xenial
+ container:
+ name: xenial
env:
CC: clang
CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
CMAKE_GENERATOR: Ninja
os: ubuntu-latest
+ - # Focal, Clang 10, mbedTLS, MemorySanitizer
+ container:
+ name: focal
+ env:
+ CC: clang-10
+ CFLAGS: -fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
+ CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ CMAKE_GENERATOR: Ninja
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
+ UBSAN_OPTIONS: print_stacktrace=1
+ os: ubuntu-latest
+ - # Focal, Clang 10, OpenSSL, UndefinedBehaviorSanitizer
+ container:
+ name: focal
+ env:
+ CC: clang-10
+ CFLAGS: -fsanitize=undefined,nullability -fno-sanitize-recover=undefined,nullability -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
+ CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ CMAKE_GENERATOR: Ninja
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
+ UBSAN_OPTIONS: print_stacktrace=1
+ os: ubuntu-latest
+ - # Focal, Clang 10, OpenSSL, ThreadSanitizer
+ container:
+ name: focal
+ env:
+ CC: clang-10
+ CFLAGS: -fsanitize=thread -fno-optimize-sibling-calls -fno-omit-frame-pointer
+ CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ CMAKE_GENERATOR: Ninja
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
+ UBSAN_OPTIONS: print_stacktrace=1
+ TSAN_OPTIONS: suppressions=/home/libgit2/source/script/thread-sanitizer.supp second_deadlock_stack=1
+ os: ubuntu-latest
- # macOS
os: macos-10.15
env:
CC: clang
CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON
- CMAKE_GENERATOR: Ninja
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
@@ -101,7 +171,7 @@ jobs:
env:
ARCH: amd64
CMAKE_GENERATOR: Visual Studio 16 2019
- CMAKE_OPTIONS: -A x64 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON
+ CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- # Windows x86 Visual Studio
@@ -109,7 +179,7 @@ jobs:
env:
ARCH: x86
CMAKE_GENERATOR: Visual Studio 16 2019
- CMAKE_OPTIONS: -A Win32 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
+ CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- # Windows amd64 mingw
@@ -141,38 +211,61 @@ jobs:
- name: Check out repository
uses: actions/checkout@v2
with:
+ path: source
fetch-depth: 0
- name: Set up build environment
- run: azure-pipelines/setup-${{ matrix.platform.setup-script }}.sh
+ run: source/ci/setup-${{ matrix.platform.setup-script }}.sh
shell: bash
if: matrix.platform.setup-script != ''
+ - name: Setup QEMU
+ run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
+ if: matrix.platform.container.qemu == true
- name: Download container
- run: azure-pipelines/getcontainer.sh ${{ env.docker-config-path }}/${{ matrix.platform.image }}
+ run: |
+ "${{ github.workspace }}/source/ci/getcontainer.sh" "${{ matrix.platform.container.name }}" "${{ matrix.platform.container.dockerfile }}"
env:
DOCKER_REGISTRY: ${{ env.docker-registry }}
GITHUB_TOKEN: ${{ secrets.github_token }}
- if: matrix.platform.image != ''
+ working-directory: ${{ env.docker-config-path }}
+ if: matrix.platform.container.name != ''
- name: Create container
- run: docker build -t ${{ env.docker-registry-container-sha }} -f ${{ matrix.platform.image }} .
+ run: docker build -t ${{ env.docker-registry-container-sha }} -f ${{ env.dockerfile }} .
working-directory: ${{ env.docker-config-path }}
- if: matrix.platform.image != '' && env.docker-container-exists != 'true'
+ if: matrix.platform.container.name != '' && env.docker-container-exists != 'true'
- name: Build and test
run: |
export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
- if [ -n "${{ matrix.platform.image }}" ]; then
- docker run -v $(pwd):/home/libgit2/source -w /home/libgit2/source -e CC -e CMAKE_GENERATOR -e CMAKE_OPTIONS -e PKG_CONFIG_PATH -e GITTEST_NEGOTIATE_PASSWORD -e SKIP_SSH_TESTS -e SKIP_NEGOTIATE_TESTS ${{ env.docker-registry-container-sha }} /bin/bash -c "mkdir build && cd build && ../azure-pipelines/build.sh && ../azure-pipelines/test.sh"
+ if [ -n "${{ matrix.platform.container.name }}" ]; then
+ docker run \
+ --rm \
+ --user libgit2:libgit2 \
+ -v "$(pwd)/source:/home/libgit2/source" \
+ -w /home/libgit2 \
+ -e ASAN_SYMBOLIZER_PATH \
+ -e CC \
+ -e CFLAGS \
+ -e CMAKE_GENERATOR \
+ -e CMAKE_OPTIONS \
+ -e GITTEST_NEGOTIATE_PASSWORD \
+ -e PKG_CONFIG_PATH \
+ -e SKIP_NEGOTIATE_TESTS \
+ -e SKIP_SSH_TESTS \
+ -e TSAN_OPTIONS \
+ -e UBSAN_OPTIONS \
+ ${{ env.docker-registry-container-sha }} \
+ /bin/bash -c "mkdir build && cd build && ../source/ci/build.sh && ../source/ci/test.sh"
else
mkdir build && cd build
- ../azure-pipelines/build.sh
- ../azure-pipelines/test.sh
+ ../source/ci/build.sh
+ ../source/ci/test.sh
fi
shell: bash
# Generate documentation using docurium. We'll upload the documentation
# as a build artifact so that it can be reviewed as part of a pull
# request or in a forked build. For CI builds in the main repository's
- # master branch, we'll push the gh-pages branch back up so that it is
+ # main branch, we'll push the gh-pages branch back up so that it is
# published to our documentation site.
documentation:
name: Generate documentation
@@ -182,21 +275,29 @@ jobs:
- name: Check out repository
uses: actions/checkout@v2
with:
+ path: source
fetch-depth: 0
- name: Generate documentation
+ working-directory: source
run: |
git config user.name 'Documentation Generation'
git config user.email 'libgit2@users.noreply.github.com'
git branch gh-pages origin/gh-pages
docker login https://${{ env.docker-registry }} -u ${{ github.actor }} -p ${{ github.token }}
- docker run --rm -v $(pwd):/home/libgit2/source -w /home/libgit2/source ${{ env.docker-registry }}/${{ github.repository }}/docurium:latest cm doc api.docurium
+ docker run \
+ --rm \
+ -v "$(pwd):/home/libgit2" \
+ -w /home/libgit2 \
+ ${{ env.docker-registry }}/${{ github.repository }}/docurium:latest \
+ cm doc api.docurium
git checkout gh-pages
zip --exclude .git/\* --exclude .gitignore --exclude .gitattributes -r api-documentation.zip .
- uses: actions/upload-artifact@v2
name: Upload artifact
with:
name: api-documentation
- path: api-documentation.zip
+ path: source/api-documentation.zip
- name: Push documentation branch
+ working-directory: source
run: git push origin gh-pages
- if: github.event_name == 'push' && github.repository == 'libgit2/libgit2'
+ if: github.event_name != 'pull_request' && github.repository == 'libgit2/libgit2'
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
new file mode 100644
index 000000000..47ebf464d
--- /dev/null
+++ b/.github/workflows/nightly.yml
@@ -0,0 +1,339 @@
+# Nightly build for the main branch across multiple targets.
+name: Nightly Build
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '15 1 * * *'
+
+env:
+ docker-registry: docker.pkg.github.com
+ docker-config-path: source/ci/docker
+
+jobs:
+ # Run our nightly builds. We build a matrix with the various build
+ # targets and their details. Then we build either in a docker container
+ # (Linux) or on the actual hosts (macOS, Windows).
+ build:
+ name: Build
+ strategy:
+ matrix:
+ platform:
+ - # Xenial, GCC, OpenSSL
+ container:
+ name: xenial
+ env:
+ CC: gcc
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ os: ubuntu-latest
+ - # Xenial, GCC, mbedTLS
+ container:
+ name: xenial
+ env:
+ CC: gcc
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ os: ubuntu-latest
+ - # Xenial, Clang, OpenSSL
+ container:
+ name: xenial
+ env:
+ CC: clang
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ os: ubuntu-latest
+ - # Xenial, Clang, mbedTLS
+ container:
+ name: xenial
+ env:
+ CC: clang
+ CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ CMAKE_GENERATOR: Ninja
+ os: ubuntu-latest
+ - # Xenial, GCC, thread-free
+ container:
+ name: xenial
+ env:
+ CC: gcc
+ CMAKE_OPTIONS: -DTHREADSAFE=OFF -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ CMAKE_GENERATOR: Ninja
+ os: ubuntu-latest
+ - # Xenial, Clang, OpenSSL (dynamically loaded)
+ container:
+ name: xenial
+ env:
+ CC: clang
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ CMAKE_GENERATOR: Ninja
+ os: ubuntu-latest
+ - # Focal, Clang 10, mbedTLS, MemorySanitizer
+ container:
+ name: focal
+ env:
+ CC: clang-10
+ CFLAGS: -fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
+ CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ CMAKE_GENERATOR: Ninja
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
+ os: ubuntu-latest
+ - # Focal, Clang 10, OpenSSL, UndefinedBehaviorSanitizer
+ container:
+ name: focal
+ env:
+ CC: clang-10
+ CFLAGS: -fsanitize=undefined,nullability -fno-sanitize-recover=undefined,nullability -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
+ CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ CMAKE_GENERATOR: Ninja
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
+ os: ubuntu-latest
+ - # Focal, Clang 10, OpenSSL, ThreadSanitizer
+ container:
+ name: focal
+ env:
+ CC: clang-10
+ CFLAGS: -fsanitize=thread -fno-optimize-sibling-calls -fno-omit-frame-pointer
+ CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ CMAKE_GENERATOR: Ninja
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
+ TSAN_OPTIONS: suppressions=/home/libgit2/source/script/thread-sanitizer.supp second_deadlock_stack=1
+ os: ubuntu-latest
+ - # Focal, Clang 10, mmap emulation (NO_MMAP)
+ container:
+ name: focal
+ env:
+ CC: clang-10
+ CFLAGS: -DNO_MMAP
+ CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local
+ CMAKE_GENERATOR: Ninja
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ os: ubuntu-latest
+ - # CentOS 7
+ container:
+ name: centos7
+ env:
+ CMAKE_OPTIONS: -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
+ SKIP_NEGOTIATE_TESTS: true
+ os: ubuntu-latest
+ - # CentOS 7, OpenSSL (dynamically loaded)
+ container:
+ name: centos7
+ env:
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
+ SKIP_NEGOTIATE_TESTS: true
+ os: ubuntu-latest
+ - # CentOS 8
+ container:
+ name: centos8
+ env:
+ CMAKE_OPTIONS: -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
+ SKIP_NEGOTIATE_TESTS: true
+ SKIP_SSH_TESTS: true
+ os: ubuntu-latest
+ - # CentOS 8, OpenSSL (dynamically loaded)
+ container:
+ name: centos8
+ env:
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
+ SKIP_NEGOTIATE_TESTS: true
+ SKIP_SSH_TESTS: true
+ os: ubuntu-latest
+ - # macOS
+ os: macos-10.15
+ env:
+ CC: clang
+ CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON
+ PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ setup-script: osx
+ - # Windows amd64 Visual Studio
+ os: windows-2019
+ env:
+ ARCH: amd64
+ CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ - # Windows amd64 Visual Studio (NO_MMAP)
+ os: windows-2019
+ env:
+ ARCH: amd64
+ CMAKE_GENERATOR: Visual Studio 16 2019
+ CFLAGS: -DNO_MMAP
+ CMAKE_OPTIONS: -A x64 -DDEPRECATE_HARD=ON
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ - # Windows x86 Visual Studio
+ os: windows-2019
+ env:
+ ARCH: x86
+ CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ - # Windows amd64 mingw
+ os: windows-2019
+ setup-script: mingw
+ env:
+ ARCH: amd64
+ CMAKE_GENERATOR: MinGW Makefiles
+ CMAKE_OPTIONS: -DDEPRECATE_HARD=ON
+ BUILD_TEMP: D:\Temp
+ BUILD_PATH: D:\Temp\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ - # Windows x86 mingw
+ os: windows-2019
+ setup-script: mingw
+ env:
+ ARCH: x86
+ CMAKE_GENERATOR: MinGW Makefiles
+ CMAKE_OPTIONS: -DDEPRECATE_HARD=ON
+ BUILD_TEMP: D:\Temp
+ BUILD_PATH: D:\Temp\mingw32\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
+ SKIP_SSH_TESTS: true
+ SKIP_NEGOTIATE_TESTS: true
+ - # Bionic, GCC, OpenSSL (dynamically loaded)
+ container:
+ name: bionic
+ dockerfile: bionic
+ env:
+ CC: gcc
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL-Dynamic -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ RUN_INVASIVE_TESTS: true
+ os: ubuntu-latest
+ - # Bionic, x86, Clang, OpenSSL
+ container:
+ name: bionic-x86
+ dockerfile: bionic
+ qemu: true
+ env:
+ CC: clang
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ RUN_INVASIVE_TESTS: true
+ os: ubuntu-latest
+ - # Bionic, x86, GCC, OpenSSL
+ container:
+ name: bionic-x86
+ dockerfile: bionic
+ env:
+ CC: gcc
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
+ RUN_INVASIVE_TESTS: true
+ os: ubuntu-latest
+ - # Bionic, arm32, GCC, OpenSSL
+ container:
+ name: bionic-arm32
+ dockerfile: bionic
+ qemu: true
+ env:
+ CC: gcc
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON
+ RUN_INVASIVE_TESTS: true
+ SKIP_PROXY_TESTS: true
+ os: ubuntu-latest
+ - # Bionic, arm64, GCC, OpenSSL
+ container:
+ name: bionic-arm64
+ dockerfile: bionic
+ qemu: true
+ env:
+ CC: gcc
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON
+ RUN_INVASIVE_TESTS: true
+ SKIP_PROXY_TESTS: true
+ os: ubuntu-latest
+ fail-fast: false
+ env: ${{ matrix.platform.env }}
+ runs-on: ${{ matrix.platform.os }}
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v2
+ with:
+ path: source
+ fetch-depth: 0
+ - name: Set up build environment
+ run: source/ci/setup-${{ matrix.platform.setup-script }}.sh
+ shell: bash
+ if: matrix.platform.setup-script != ''
+ - name: Setup QEMU
+ run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
+ if: matrix.platform.container.qemu == true
+ - name: Download container
+ run: |
+ "${{ github.workspace }}/source/ci/getcontainer.sh" "${{ matrix.platform.container.name }}" "${{ matrix.platform.container.dockerfile }}"
+ env:
+ DOCKER_REGISTRY: ${{ env.docker-registry }}
+ GITHUB_TOKEN: ${{ secrets.github_token }}
+ working-directory: ${{ env.docker-config-path }}
+ if: matrix.platform.container.name != ''
+ - name: Create container
+ run: docker build -t ${{ env.docker-registry-container-sha }} -f ${{ env.dockerfile }} .
+ working-directory: ${{ env.docker-config-path }}
+ if: matrix.platform.container.name != '' && env.docker-container-exists != 'true'
+ - name: Build and test
+ run: |
+ export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
+
+ if [ -n "${{ matrix.platform.container.name }}" ]; then
+ docker run \
+ --rm \
+ --user libgit2:libgit2 \
+ -v "$(pwd)/source:/home/libgit2/source" \
+ -w /home/libgit2 \
+ -e ASAN_SYMBOLIZER_PATH \
+ -e CC \
+ -e CFLAGS \
+ -e CMAKE_GENERATOR \
+ -e CMAKE_OPTIONS \
+ -e GITTEST_NEGOTIATE_PASSWORD \
+ -e PKG_CONFIG_PATH \
+ -e SKIP_NEGOTIATE_TESTS \
+ -e SKIP_SSH_TESTS \
+ -e TSAN_OPTIONS \
+ ${{ env.docker-registry-container-sha }} \
+ /bin/bash -c "mkdir build && cd build && ../source/ci/build.sh && ../source/ci/test.sh"
+ else
+ mkdir build && cd build
+ ../source/ci/build.sh
+ ../source/ci/test.sh
+ fi
+ shell: bash
+
+ coverity:
+ name: Coverity
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v2
+ with:
+ path: source
+ fetch-depth: 0
+ - name: Download container
+ run: |
+ "${{ github.workspace }}/source/ci/getcontainer.sh" xenial
+ env:
+ DOCKER_REGISTRY: ${{ env.docker-registry }}
+ GITHUB_TOKEN: ${{ secrets.github_token }}
+ working-directory: ${{ env.docker-config-path }}
+ - name: Run Coverity
+ run: source/ci/coverity.sh
+ env:
+ COVERITY_TOKEN: ${{ secrets.coverity_token }}
diff --git a/.gitignore b/.gitignore
index b38b7e16e..1b482f038 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,8 @@
-build/
+/build/
.DS_Store
*~
.*.swp
-tags
+/tags
CMakeSettings.json
.vs
+.idea
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 000000000..d47d93aab
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,27 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "(gdb) Launch",
+ "type": "cppdbg",
+ "request": "launch",
+ "program": "${workspaceFolder}/build/libgit2_clar",
+ "args": [],
+ "stopAtEntry": false,
+ "cwd": "${fileDirname}",
+ "environment": [],
+ "externalConsole": false,
+ "MIMode": "gdb",
+ "setupCommands": [
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 000000000..64142d341
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,27 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Build",
+ "type": "shell",
+ "command": "cd build && cmake --build . --parallel",
+ "group": "build",
+ "presentation": {
+ "reveal": "always",
+ "panel": "new"
+ }
+ },
+ {
+ "label": "Run Tests",
+ "type": "shell",
+ "command": "build/libgit2_clar -v",
+ "group": "test",
+ "presentation": {
+ "reveal": "always",
+ "panel": "new"
+ }
+ }
+ ]
+ } \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fb5202fd1..3dccec310 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,7 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.5.1)
-project(libgit2 C)
+project(libgit2 VERSION "1.3.0" LANGUAGES C)
# Add find modules to the path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${libgit2_SOURCE_DIR}/cmake/")
@@ -27,6 +27,7 @@ INCLUDE(AddCFlagIfSupported)
INCLUDE(FindPkgLibraries)
INCLUDE(FindThreads)
INCLUDE(FindStatNsec)
+INCLUDE(Findfutimens)
INCLUDE(GNUInstallDirs)
INCLUDE(IdeSplitSources)
INCLUDE(FeatureSummary)
@@ -49,8 +50,10 @@ OPTION(USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF)
OPTION(USE_STANDALONE_FUZZERS "Enable standalone fuzzers (compatible with gcc)" OFF)
OPTION(USE_LEAK_CHECKER "Run tests with leak checker" OFF)
OPTION(DEBUG_POOL "Enable debug pool allocator" OFF)
+OPTION(DEBUG_STRICT_ALLOC "Enable strict allocator behavior" OFF)
+OPTION(DEBUG_STRICT_OPEN "Enable path validation in open" OFF)
OPTION(ENABLE_WERROR "Enable compilation with -Werror" OFF)
-OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF)
+OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib. Can be set to one of Bundled(ON)/Chromium. The Chromium option requires a x86_64 processor with SSE4.2 and CLMUL" OFF)
SET(USE_HTTP_PARSER "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.")
OPTION(DEPRECATE_HARD "Do not include deprecated functions in the library" OFF)
SET(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
@@ -89,20 +92,10 @@ IF(WIN32)
ENDIF()
IF(MSVC)
- # Enable MSVC CRTDBG memory leak reporting when in debug mode.
- OPTION(MSVC_CRTDBG "Enable CRTDBG memory leak reporting" OFF)
+ # Enable leak checking using the debugging C runtime.
+ OPTION(WIN32_LEAKCHECK "Enable leak reporting via crtdbg" OFF)
ENDIF()
-FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER REGEX "^#define LIBGIT2_VERSION \"[^\"]*\"$")
-
-STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"([0-9]+).*$" "\\1" LIBGIT2_VERSION_MAJOR "${GIT2_HEADER}")
-STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_MINOR "${GIT2_HEADER}")
-STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}")
-SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}")
-
-FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION \"([0-9.]+)\"$")
-STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION \"([0-9.]+)\"$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}")
-
IF (DEPRECATE_HARD)
ADD_DEFINITIONS(-DGIT_DEPRECATE_HARD)
ENDIF()
@@ -139,8 +132,8 @@ IF (MSVC)
SET(CRT_FLAG_RELEASE "/MD")
ENDIF()
- IF (MSVC_CRTDBG)
- SET(GIT_MSVC_CRTDBG 1)
+ IF (WIN32_LEAKCHECK)
+ SET(GIT_WIN32_LEAKCHECK 1)
SET(CRT_FLAG_DEBUG "${CRT_FLAG_DEBUG}")
SET(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} Dbghelp.lib")
ENDIF()
@@ -175,7 +168,7 @@ IF (MSVC)
# /NXCOMPAT - Data execution prevention (DEP)
# /LARGEADDRESSAWARE - >2GB user address space on x86
# /VERSION - Embed version information in PE header
- SET(CMAKE_EXE_LINKER_FLAGS "/DYNAMICBASE /NXCOMPAT /LARGEADDRESSAWARE /VERSION:${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}")
+ SET(CMAKE_EXE_LINKER_FLAGS "/DYNAMICBASE /NXCOMPAT /LARGEADDRESSAWARE /VERSION:${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}")
IF (NOT (MSVC_VERSION LESS 1900))
# /GUARD:CF - Enable Control Flow Guard
@@ -241,6 +234,8 @@ ELSE ()
enable_warnings(unused-const-variable)
enable_warnings(unused-function)
enable_warnings(int-conversion)
+ enable_warnings(c11-extensions)
+ enable_warnings(c99-c11-compat)
# MinGW uses gcc, which expects POSIX formatting for printf, but
# uses the Windows C library, which uses its own format specifiers.
diff --git a/COPYING b/COPYING
index c0f61fb91..6bb39b0c1 100644
--- a/COPYING
+++ b/COPYING
@@ -420,7 +420,7 @@ The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
-
+
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@@ -1019,3 +1019,111 @@ following restrictions are are met:
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+----------------------------------------------------------------------
+
+Portions of the OpenSSL headers are included under the OpenSSL license:
+
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+All rights reserved.
+
+This package is an SSL implementation written
+by Eric Young (eay@cryptsoft.com).
+The implementation was written so as to conform with Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as
+the following conditions are aheared to. The following conditions
+apply to all code found in this distribution, be it the RC4, RSA,
+lhash, DES, etc., code; not just the SSL code. The SSL documentation
+included with this distribution is covered by the same copyright terms
+except that the holder is Tim Hudson (tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in
+the code are not to be removed.
+If this package is used in a product, Eric Young should be given attribution
+as the author of the parts of the library used.
+This can be in the form of a textual message at program startup or
+in documentation (online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ "This product includes cryptographic software written by
+ Eric Young (eay@cryptsoft.com)"
+ The word 'cryptographic' can be left out if the rouines from the library
+ being used are not cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from
+ the apps directory (application code) you must include an acknowledgement:
+ "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence
+[including the GNU Public Licence.]
+
+====================================================================
+Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ endorse or promote products derived from this software without
+ prior written permission. For written permission, please contact
+ openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL"
+ nor may "OpenSSL" appear in their names without prior written
+ permission of the OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/README.md b/README.md
index a91f16067..0cbde525b 100644
--- a/README.md
+++ b/README.md
@@ -3,10 +3,10 @@ libgit2 - the Git linkable library
| Build Status | |
| ------------ | - |
-| **master** branch CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=master)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=master) |
-| **v1.0 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v1.0)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v1.0) |
-| **v0.28 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v0.28)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v0.28) |
-| **Nightly** builds | [![Azure Pipelines Build Status](https://libgit2.visualstudio.com/libgit2/_apis/build/status/nightly?branchName=master&label=Full+Build)](https://libgit2.visualstudio.com/libgit2/_build/latest?definitionId=9&branchName=master) [![Coverity Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/coverity?branchName=master&label=Coverity+Build)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=21?branchName=master) [![Coverity Scan Build Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639) |
+| **main** branch CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush) |
+| **v1.2 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.2&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.2) |
+| **v1.1 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.1&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.1) |
+| **Nightly** builds | [![Nightly Build](https://github.com/libgit2/libgit2/workflows/Nightly%20Build/badge.svg)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22Nightly+Build%22) [![Coverity Scan Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639) |
`libgit2` is a portable, pure C implementation of the Git core methods
provided as a linkable library with a solid API, allowing to build Git
@@ -33,6 +33,7 @@ Additionally, the example code has been released to the public domain (see the
Table of Contents
=================
+* [Using libgit2](#using-libgit2)
* [Quick Start](#quick-start)
* [Getting Help](#getting-help)
* [What It Can Do](#what-it-can-do)
@@ -52,6 +53,28 @@ Table of Contents
* [How Can I Contribute?](#how-can-i-contribute)
* [License](#license)
+Using libgit2
+=============
+
+Most of these instructions assume that you're writing an application
+in C and want to use libgit2 directly. If you're _not_ using C,
+and you're writing in a different language or platform like .NET,
+Node.js, or Ruby, then there is probably a
+"[language binding](#language-bindings)" that you can use to take care
+of the messy tasks of calling into native code.
+
+But if you _do_ want to use libgit2 directly - because you're building
+an application in C - then you may be able use an existing binary.
+There are packages for the
+[vcpkg](https://github.com/Microsoft/vcpkg) and
+[conan](https://conan.io/center/libgit2)
+package managers. And libgit2 is available in
+[Homebrew](https://formulae.brew.sh/formula/libgit2) and most Linux
+distributions.
+
+However, these versions _may_ be outdated and we recommend using the
+latest version if possible. Thankfully libgit2 is not hard to compile.
+
Quick Start
===========
@@ -81,7 +104,8 @@ Getting Help
**Chat with us**
-- via IRC: join [#libgit2](https://webchat.freenode.net/#libgit2) on Freenode
+- via IRC: join [#libgit2](https://web.libera.chat/#libgit2) on
+ [libera](https://libera.chat).
- via Slack: visit [slack.libgit2.org](http://slack.libgit2.org/) to sign up,
then join us in `#libgit2`
@@ -201,6 +225,8 @@ On most systems you can build the library using the following commands
Alternatively you can point the CMake GUI tool to the CMakeLists.txt file and generate platform specific build project or IDE workspace.
+If you're not familiar with CMake, [a more detailed explanation](https://preshing.com/20170511/how-to-build-a-cmake-based-project/) may be helpful.
+
Running Tests
-------------
@@ -219,7 +245,7 @@ run the index tests:
$ ./libgit2_clar -sindex
To run a single test named `index::racy::diff`, which corresponds to the test
-function [`test_index_racy__diff`](https://github.com/libgit2/libgit2/blob/master/tests/index/racy.c#L23):
+function [`test_index_racy__diff`](https://github.com/libgit2/libgit2/blob/main/tests/index/racy.c#L23):
$ ./libgit2_clar -sindex::racy::diff
@@ -229,7 +255,7 @@ applicable to your platform or is particularly expensive.
**Note:** There should be _no_ failing tests when you build an unmodified
source tree from a [release](https://github.com/libgit2/libgit2/releases),
-or from the [master branch](https://github.com/libgit2/libgit2/tree/master).
+or from the [main branch](https://github.com/libgit2/libgit2/tree/main).
Please contact us or [open an issue](https://github.com/libgit2/libgit2/issues)
if you see test failures.
@@ -332,6 +358,7 @@ Here are the bindings to libgit2 that are currently available:
* dlibgit <https://github.com/s-ludwig/dlibgit>
* Delphi
* GitForDelphi <https://github.com/libgit2/GitForDelphi>
+ * libgit2-delphi <https://github.com/todaysoftware/libgit2-delphi>
* Erlang
* Geef <https://github.com/carlosmn/geef>
* Go
@@ -344,6 +371,7 @@ Here are the bindings to libgit2 that are currently available:
* hgit2 <https://github.com/jwiegley/gitlib>
* Java
* Jagged <https://github.com/ethomson/jagged>
+ * Git24j <https://github.com/git24j/git24j>
* Javascript / WebAssembly ( browser and nodejs )
* WASM-git <https://github.com/petersalomonsen/wasm-git>
* Julia
@@ -369,6 +397,7 @@ Here are the bindings to libgit2 that are currently available:
* Python
* pygit2 <https://github.com/libgit2/pygit2>
* R
+ * gert <https://docs.ropensci.org/gert>
* git2r <https://github.com/ropensci/git2r>
* Ruby
* Rugged <https://github.com/libgit2/rugged>
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
deleted file mode 100644
index 28fbc1613..000000000
--- a/azure-pipelines.yml
+++ /dev/null
@@ -1,190 +0,0 @@
-resources:
-- repo: self
-
-trigger:
-- master
-- maint/*
-
-jobs:
-- job: linux_amd64_xenial_gcc_openssl
- displayName: 'Linux (amd64; Xenial; GCC; OpenSSL)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: azure-pipelines/docker.yml
- parameters:
- docker:
- image: xenial
- base: ubuntu:xenial
- environmentVariables: |
- CC=gcc
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
- GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
-
-- job: linux_amd64_xenial_gcc_mbedtls
- displayName: 'Linux (amd64; Xenial; GCC; mbedTLS)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: azure-pipelines/docker.yml
- parameters:
- docker:
- image: xenial
- base: ubuntu:xenial
- environmentVariables: |
- CC=gcc
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
- GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
-
-- job: linux_amd64_xenial_clang_openssl
- displayName: 'Linux (amd64; Xenial; Clang; OpenSSL)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: azure-pipelines/docker.yml
- parameters:
- docker:
- image: xenial
- base: ubuntu:xenial
- environmentVariables: |
- CC=clang
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
- GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
-
-- job: linux_amd64_xenial_clang_mbedtls
- displayName: 'Linux (amd64; Xenial; Clang; mbedTLS)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: azure-pipelines/docker.yml
- parameters:
- docker:
- image: xenial
- base: ubuntu:xenial
- environmentVariables: |
- CC=clang
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
- GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
-
-- job: macos
- displayName: 'macOS (amd64; 10.15)'
- pool:
- vmImage: 'macOS-10.15'
- steps:
- - bash: . '$(Build.SourcesDirectory)/azure-pipelines/setup-osx.sh'
- displayName: Setup
- - template: azure-pipelines/bash.yml
- parameters:
- environmentVariables:
- TMPDIR: $(Agent.TempDirectory)
- PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
- CMAKE_GENERATOR: Ninja
- CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON
- SKIP_SSH_TESTS: true
- GITTEST_NEGOTIATE_PASSWORD: ${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
-
-- job: windows_vs_amd64
- displayName: 'Windows (amd64; Visual Studio)'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - template: azure-pipelines/bash.yml
- parameters:
- environmentVariables:
- CMAKE_GENERATOR: Visual Studio 15 2017
- CMAKE_OPTIONS: -A x64 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
- SKIP_SSH_TESTS: true
- SKIP_NEGOTIATE_TESTS: true
-
-- job: windows_vs_x86
- displayName: 'Windows (x86; Visual Studio)'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - template: azure-pipelines/bash.yml
- parameters:
- environmentVariables:
- CMAKE_GENERATOR: Visual Studio 15 2017
- CMAKE_OPTIONS: -A Win32 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
- SKIP_SSH_TESTS: true
- SKIP_NEGOTIATE_TESTS: true
-
-- job: windows_mingw_amd64
- displayName: 'Windows (amd64; MinGW)'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - bash: . '$(Build.SourcesDirectory)\azure-pipelines\setup-mingw.sh'
- displayName: Setup
- env:
- TEMP: $(Agent.TempDirectory)
- ARCH: amd64
- - template: azure-pipelines/bash.yml
- parameters:
- environmentVariables:
- BUILD_PATH: $(Agent.TempDirectory)\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
- CMAKE_GENERATOR: MinGW Makefiles
- CMAKE_OPTIONS: -DDEPRECATE_HARD=ON
- SKIP_SSH_TESTS: true
- SKIP_NEGOTIATE_TESTS: true
-
-- job: windows_mingw_x86
- displayName: 'Windows (x86; MinGW)'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - bash: . '$(Build.SourcesDirectory)\azure-pipelines\setup-mingw.sh'
- displayName: Setup
- workingDirectory: '$(Build.BinariesDirectory)'
- env:
- TEMP: $(Agent.TempDirectory)
- ARCH: x86
- - template: azure-pipelines/bash.yml
- parameters:
- environmentVariables:
- BUILD_PATH: $(Agent.TempDirectory)\mingw32\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
- CMAKE_GENERATOR: MinGW Makefiles
- CMAKE_OPTIONS: -DDEPRECATE_HARD=ON
- SKIP_SSH_TESTS: true
- SKIP_NEGOTIATE_TESTS: true
-
-- job: documentation
- displayName: 'Generate Documentation'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - script: |
- cd $(Build.SourcesDirectory)/azure-pipelines/docker
- docker build -t libgit2/docurium --build-arg BASE=ubuntu:trusty -f docurium .
- displayName: 'Build Docker image'
- - script: |
- git config user.name 'Documentation Generation'
- git config user.email 'libgit2@users.noreply.github.com'
- git branch gh-pages origin/gh-pages
- docker run --rm -v $(Build.SourcesDirectory):/home/libgit2/source -w /home/libgit2/source libgit2/docurium:latest cm doc api.docurium
- git checkout gh-pages
- cp -R * '$(Build.BinariesDirectory)'
- displayName: 'Generate Documentation'
- - task: archivefiles@2
- displayName: 'Archive Documentation'
- inputs:
- rootFolderOrFile: '$(Build.BinariesDirectory)'
- includeRootFolder: false
- archiveFile: '$(Build.ArtifactStagingDirectory)/api-documentation.zip'
- - task: publishbuildartifacts@1
- displayName: 'Upload Documentation Artifact'
- inputs:
- pathToPublish: '$(Build.ArtifactStagingDirectory)'
- artifactName: 'docs'
- - script: |
- git remote -v
- echo 'machine github.com' > ~/.netrc
- echo 'login $(GITHUB_USERNAME)' >> ~/.netrc
- echo 'password $(GITHUB_PAT)' >> ~/.netrc
- git push origin gh-pages
- displayName: 'Publish Documentation'
- condition: and(eq(variables['Build.Repository.Name'], 'libgit2/libgit2'), eq(variables['Build.Reason'], 'IndividualCI'))
diff --git a/azure-pipelines/bash.yml b/azure-pipelines/bash.yml
deleted file mode 100644
index 33a442b57..000000000
--- a/azure-pipelines/bash.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-# These are the steps used for building on machines with bash.
-steps:
-- bash: . '$(Build.SourcesDirectory)/azure-pipelines/build.sh'
- displayName: Build
- workingDirectory: '$(Build.BinariesDirectory)'
- env: ${{ parameters.environmentVariables }}
-- bash: . '$(Build.SourcesDirectory)/azure-pipelines/test.sh'
- displayName: Test
- workingDirectory: '$(Build.BinariesDirectory)'
- env: ${{ parameters.environmentVariables }}
-- task: PublishTestResults@2
- displayName: Publish Test Results
- condition: succeededOrFailed()
- inputs:
- testResultsFiles: 'results_*.xml'
- searchFolder: '$(Build.BinariesDirectory)'
- mergeTestResults: true
diff --git a/azure-pipelines/coverity.yml b/azure-pipelines/coverity.yml
deleted file mode 100644
index a8747db73..000000000
--- a/azure-pipelines/coverity.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-resources:
-- repo: self
-
-jobs:
-- job: coverity
- displayName: 'Coverity'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - script: |
- cd $(Build.SourcesDirectory)/azure-pipelines/docker
- docker build -t libgit2/xenial --build-arg BASE=ubuntu:xenial -f xenial .
- displayName: 'Build Docker image'
- - task: Docker@0
- displayName: Analyze
- inputs:
- action: 'Run an image'
- imageName: libgit2/xenial
- volumes: |
- $(Build.SourcesDirectory):/home/libgit2/source
- $(Build.BinariesDirectory):/home/libgit2/build
- envVars: |
- COVERITY_TOKEN=$(COVERITY_TOKEN)
- workDir: '/home/libgit2/build'
- containerCommand: '/home/libgit2/source/azure-pipelines/coverity.sh'
- detached: false
diff --git a/azure-pipelines/docker.yml b/azure-pipelines/docker.yml
deleted file mode 100644
index 0f0885770..000000000
--- a/azure-pipelines/docker.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-# These are the steps used in a container-based build in VSTS.
-steps:
-- ${{ if eq(parameters.qemu, 'true') }}:
- - script: docker run --rm --privileged multiarch/qemu-user-static:register --reset
- displayName: 'Register Docker QEMU'
-
-- task: cache@2
- displayName: Cache Docker layers
- inputs:
- key: docker
- path: /tmp/dockercache
-- script: |
- if [ -f /tmp/dockercache/${{parameters.docker.image}}.tar ]; then docker load < /tmp/dockercache/${{parameters.docker.image}}.tar; fi
- displayName: 'Load Docker cache'
-- script: |
- cd $(Build.SourcesDirectory)/azure-pipelines/docker &&
- docker build -t libgit2/${{parameters.docker.image}} --build-arg BASE=${{parameters.docker.base}} -f ${{parameters.docker.image}} . &&
- if [ ! -d /tmp/dockercache ]; then mkdir /tmp/dockercache; fi &&
- docker save libgit2/${{parameters.docker.image}} $(docker history -q libgit2/${{parameters.docker.image}} | grep -v '<missing>') > /tmp/dockercache/${{parameters.docker.image}}.tar
- displayName: 'Build Docker image'
-- task: docker@0
- displayName: Build
- inputs:
- action: 'Run an image'
- imageName: libgit2/${{ parameters.docker.image }}
- volumes: |
- $(Build.SourcesDirectory):/home/libgit2/source
- $(Build.BinariesDirectory):/home/libgit2/build
- envVars: ${{ parameters.environmentVariables }}
- workDir: '/home/libgit2/build'
- containerCommand: '/home/libgit2/source/azure-pipelines/build.sh'
- detached: false
-- task: docker@0
- displayName: Test
- inputs:
- action: 'Run an image'
- imageName: libgit2/${{ parameters.docker.image }}
- volumes: |
- $(Build.SourcesDirectory):/home/libgit2/source
- $(Build.BinariesDirectory):/home/libgit2/build
- envVars: ${{ parameters.environmentVariables }}
- workDir: '/home/libgit2/build'
- containerCommand: '/home/libgit2/source/azure-pipelines/test.sh'
- detached: false
-- task: publishtestresults@2
- displayName: Publish Test Results
- condition: succeededOrFailed()
- inputs:
- testResultsFiles: 'results_*.xml'
- searchFolder: '$(Build.BinariesDirectory)'
- mergeTestResults: true
diff --git a/azure-pipelines/docker/entrypoint.sh b/azure-pipelines/docker/entrypoint.sh
deleted file mode 100644
index 8d96e3acd..000000000
--- a/azure-pipelines/docker/entrypoint.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash -e
-useradd --shell /bin/bash libgit2
-chown --recursive libgit2:libgit2 /home/libgit2
-exec sudo --preserve-env --set-home --user=libgit2 "$@"
diff --git a/azure-pipelines/nightly.yml b/azure-pipelines/nightly.yml
deleted file mode 100644
index a75a9cc24..000000000
--- a/azure-pipelines/nightly.yml
+++ /dev/null
@@ -1,219 +0,0 @@
-resources:
-- repo: self
-
-jobs:
-- job: linux_amd64_xenial_gcc_openssl
- displayName: 'Linux (amd64; Xenial; GCC; OpenSSL)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: docker.yml
- parameters:
- docker:
- image: xenial
- base: ubuntu:xenial
- environmentVariables: |
- CC=gcc
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind
- RUN_INVASIVE_TESTS=true
-
-- job: linux_amd64_xenial_gcc_mbedtls
- displayName: 'Linux (amd64; Xenial; GCC; mbedTLS)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: docker.yml
- parameters:
- docker:
- image: xenial
- base: ubuntu:xenial
- environmentVariables: |
- CC=gcc
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind
- RUN_INVASIVE_TESTS=true
-
-- job: linux_amd64_xenial_clang_openssl
- displayName: 'Linux (amd64; Xenial; Clang; OpenSSL)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: docker.yml
- parameters:
- docker:
- image: xenial
- base: ubuntu:xenial
- environmentVariables: |
- CC=clang
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind
- RUN_INVASIVE_TESTS=true
-
-- job: linux_amd64_xenial_clang_mbedtls
- displayName: 'Linux (amd64; Xenial; Clang; mbedTLS)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: docker.yml
- parameters:
- docker:
- image: xenial
- base: ubuntu:xenial
- environmentVariables: |
- CC=clang
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind
- RUN_INVASIVE_TESTS=true
-
-- job: macos
- displayName: 'macOS (amd64; 10.15)'
- pool:
- vmImage: 'macOS-10.15'
- steps:
- - bash: . '$(Build.SourcesDirectory)/azure-pipelines/setup-osx.sh'
- displayName: Setup
- - template: bash.yml
- parameters:
- environmentVariables:
- TMPDIR: $(Agent.TempDirectory)
- PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
- CMAKE_GENERATOR: Ninja
- CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON
- RUN_INVASIVE_TESTS: true
- SKIP_SSH_TESTS: true
-
-- job: windows_vs_amd64
- displayName: 'Windows (amd64; Visual Studio)'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - template: bash.yml
- parameters:
- environmentVariables:
- CMAKE_GENERATOR: Visual Studio 15 2017
- CMAKE_OPTIONS: -A x64 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON
- RUN_INVASIVE_TESTS: true
- SKIP_SSH_TESTS: true
-
-- job: windows_vs_x86
- displayName: 'Windows (x86; Visual Studio)'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - template: bash.yml
- parameters:
- environmentVariables:
- CMAKE_GENERATOR: Visual Studio 15 2017
- CMAKE_OPTIONS: -A Win32 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS
- RUN_INVASIVE_TESTS: true
- SKIP_SSH_TESTS: true
-
-- job: windows_mingw_amd64
- displayName: 'Windows (amd64; MinGW)'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - bash: . '$(Build.SourcesDirectory)\azure-pipelines\setup-mingw.sh'
- displayName: Setup
- env:
- TEMP: $(Agent.TempDirectory)
- ARCH: amd64
- - template: bash.yml
- parameters:
- environmentVariables:
- BUILD_PATH: $(Agent.TempDirectory)\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
- CMAKE_GENERATOR: MinGW Makefiles
- CMAKE_OPTIONS: -DDEPRECATE_HARD=ON
- RUN_INVASIVE_TESTS: true
- SKIP_SSH_TESTS: true
-
-- job: windows_mingw_x86
- displayName: 'Windows (x86; MinGW)'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - bash: . '$(Build.SourcesDirectory)\azure-pipelines\setup-mingw.sh'
- displayName: Setup
- workingDirectory: '$(Build.BinariesDirectory)'
- env:
- TEMP: $(Agent.TempDirectory)
- ARCH: x86
- - template: bash.yml
- parameters:
- environmentVariables:
- BUILD_PATH: $(Agent.TempDirectory)\mingw32\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
- CMAKE_GENERATOR: MinGW Makefiles
- CMAKE_OPTIONS: -DDEPRECATE_HARD=ON
- RUN_INVASIVE_TESTS: true
- SKIP_SSH_TESTS: true
-
-- job: linux_x86_bionic_gcc_openssl
- displayName: 'Linux (x86; Bionic; GCC; OpenSSL)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: docker.yml
- parameters:
- qemu: 'true'
- docker:
- image: bionic
- base: multiarch/ubuntu-core:x86-bionic
- environmentVariables: |
- CC=gcc
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind
- RUN_INVASIVE_TESTS=true
-
-- job: linux_x86_bionic_clang_openssl
- displayName: 'Linux (x86; Bionic; Clang; OpenSSL)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: docker.yml
- parameters:
- qemu: 'true'
- docker:
- image: bionic
- base: multiarch/ubuntu-core:x86-bionic
- environmentVariables: |
- CC=clang
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind
- RUN_INVASIVE_TESTS=true
-
-- job: linux_arm32_bionic_gcc_openssl
- displayName: 'Linux (arm32; Bionic; GCC; OpenSSL)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: docker.yml
- parameters:
- qemu: 'true'
- docker:
- image: bionic
- base: multiarch/ubuntu-core:armhf-bionic
- environmentVariables: |
- CC=gcc
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON
- RUN_INVASIVE_TESTS=true
- SKIP_PROXY_TESTS=true
-
-- job: linux_arm64_bionic_gcc_openssl
- displayName: 'Linux (arm64; Bionic; GCC; OpenSSL)'
- pool:
- vmImage: 'ubuntu-18.04'
- steps:
- - template: docker.yml
- parameters:
- qemu: 'true'
- docker:
- image: bionic
- base: multiarch/ubuntu-core:arm64-bionic
- environmentVariables: |
- CC=gcc
- CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON
- RUN_INVASIVE_TESTS=true
- SKIP_PROXY_TESTS=true
diff --git a/azure-pipelines/build.sh b/ci/build.sh
index bec855d4a..5a51f925a 100755
--- a/azure-pipelines/build.sh
+++ b/ci/build.sh
@@ -33,15 +33,25 @@ if [ -f "/etc/debian_version" ]; then
(source /etc/lsb-release && echo "${DISTRIB_DESCRIPTION}") | indent
fi
+CORES=$(getconf _NPROCESSORS_ONLN || true)
+echo "Number of cores: ${CORES:-(Unknown)}"
+
echo "Kernel version:"
uname -a 2>&1 | indent
echo "CMake version:"
-env PATH="$BUILD_PATH" "$CMAKE" --version 2>&1 | indent
+env PATH="${BUILD_PATH}" "${CMAKE}" --version 2>&1 | indent
-if test -n "$CC"; then
+if test -n "${CC}"; then
echo "Compiler version:"
- "$CC" --version 2>&1 | indent
+ "${CC}" --version 2>&1 | indent
+fi
+echo "Environment:"
+if test -n "${CC}"; then
+ echo "CC=${CC}" | indent
+fi
+if test -n "${CFLAGS}"; then
+ echo "CFLAGS=${CFLAGS}" | indent
fi
echo ""
@@ -49,12 +59,20 @@ echo "##########################################################################
echo "## Configuring build environment"
echo "##############################################################################"
-echo cmake ${SOURCE_DIR} -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G \"${CMAKE_GENERATOR}\" ${CMAKE_OPTIONS}
-env PATH="$BUILD_PATH" "$CMAKE" ${SOURCE_DIR} -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G "${CMAKE_GENERATOR}" ${CMAKE_OPTIONS}
+echo cmake -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G \"${CMAKE_GENERATOR}\" ${CMAKE_OPTIONS} -S \"${SOURCE_DIR}\"
+env PATH="${BUILD_PATH}" "${CMAKE}" -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G "${CMAKE_GENERATOR}" ${CMAKE_OPTIONS} -S "${SOURCE_DIR}"
echo ""
echo "##############################################################################"
echo "## Building libgit2"
echo "##############################################################################"
-env PATH="$BUILD_PATH" "$CMAKE" --build .
+# Determine parallelism; newer cmake supports `--build --parallel` but
+# we cannot yet rely on that.
+if [ "${CMAKE_GENERATOR}" = "Unix Makefiles" -a "${CORES}" != "" ]; then
+ BUILDER=(make -j ${CORES})
+else
+ BUILDER=("${CMAKE}" --build .)
+fi
+
+env PATH="${BUILD_PATH}" "${BUILDER[@]}"
diff --git a/azure-pipelines/coverity.sh b/ci/coverity.sh
index c68b6f8cc..c68b6f8cc 100755
--- a/azure-pipelines/coverity.sh
+++ b/ci/coverity.sh
diff --git a/azure-pipelines/docker/bionic b/ci/docker/bionic
index 5918584dc..51af5c01c 100644
--- a/azure-pipelines/docker/bionic
+++ b/ci/docker/bionic
@@ -1,4 +1,6 @@
-FROM ubuntu:bionic AS apt
+ARG BASE=ubuntu:bionic
+
+FROM ${BASE} AS apt
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
clang \
@@ -6,7 +8,9 @@ RUN apt-get update && \
curl \
gcc \
git \
+ krb5-user \
libcurl4-openssl-dev \
+ libkrb5-dev \
libpcre3-dev \
libssh2-1-dev \
libssl-dev \
@@ -33,9 +37,8 @@ RUN cd /tmp && \
cd .. && \
rm -rf mbedtls-2.16.2
-FROM mbedtls AS configure
-COPY entrypoint.sh /usr/local/bin/entrypoint.sh
-RUN chmod a+x /usr/local/bin/entrypoint.sh
-RUN mkdir /var/run/sshd
+FROM mbedtls AS adduser
+RUN useradd --shell /bin/bash libgit2 --create-home
-ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
+FROM adduser AS configure
+RUN mkdir /var/run/sshd
diff --git a/ci/docker/centos7 b/ci/docker/centos7
new file mode 100644
index 000000000..8105f1442
--- /dev/null
+++ b/ci/docker/centos7
@@ -0,0 +1,55 @@
+ARG BASE=centos:7
+
+FROM ${BASE} AS yum
+RUN yum install -y \
+ which \
+ bzip2 \
+ git \
+ libarchive \
+ gcc \
+ gcc-c++ \
+ make \
+ openssl-devel \
+ openssh-server \
+ git-daemon \
+ java-1.8.0-openjdk-headless \
+ sudo \
+ python
+
+FROM yum AS libssh2
+RUN cd /tmp && \
+ curl --location --silent --show-error https://www.libssh2.org/download/libssh2-1.8.0.tar.gz | tar -xz && \
+ cd libssh2-1.8.0 && \
+ ./configure && \
+ make && \
+ make install && \
+ cd .. && \
+ rm -rf libssh-1.8.0
+
+FROM libssh2 AS valgrind
+RUN cd /tmp && \
+ curl --insecure --location --silent --show-error https://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2 | \
+ tar -xj && \
+ cd valgrind-3.15.0 && \
+ ./configure && \
+ make MAKEFLAGS="-j -l$(grep -c ^processor /proc/cpuinfo)" && \
+ make install && \
+ cd .. && \
+ rm -rf valgrind-3.15.0
+
+FROM valgrind AS cmake
+RUN cd /tmp && \
+ curl -L https://github.com/Kitware/CMake/releases/download/v3.21.1/cmake-3.21.1.tar.gz | tar -xz && \
+ cd cmake-3.21.1 && \
+ ./configure && \
+ make && \
+ make install && \
+ cd .. && \
+ rm -rf cmake-3.21.1
+
+FROM cmake AS adduser
+RUN useradd --shell /bin/bash libgit2 --create-home
+
+FROM adduser AS configure
+ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
+RUN mkdir /var/run/sshd
diff --git a/ci/docker/centos8 b/ci/docker/centos8
new file mode 100644
index 000000000..cca088103
--- /dev/null
+++ b/ci/docker/centos8
@@ -0,0 +1,49 @@
+ARG BASE=centos:8
+
+FROM ${BASE} AS yum
+RUN yum install -y \
+ which \
+ bzip2 \
+ git \
+ libarchive \
+ cmake \
+ gcc \
+ make \
+ openssl-devel \
+ openssh-server \
+ git-daemon \
+ java-1.8.0-openjdk-headless \
+ sudo \
+ python39 \
+ krb5-workstation \
+ krb5-libs
+
+FROM yum AS libssh2
+RUN cd /tmp && \
+ curl --location --silent --show-error https://www.libssh2.org/download/libssh2-1.8.0.tar.gz | tar -xz && \
+ cd libssh2-1.8.0 && \
+ ./configure && \
+ make && \
+ make install && \
+ cd .. && \
+ rm -rf libssh2-1.8.0
+
+FROM libssh2 AS valgrind
+RUN cd /tmp && \
+ curl --insecure --location --silent --show-error https://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2 | \
+ tar -xj && \
+ cd valgrind-3.15.0 && \
+ ./configure && \
+ make MAKEFLAGS="-j -l$(grep -c ^processor /proc/cpuinfo)" && \
+ make install && \
+ cd .. && \
+ rm -rf valgrind-3.15.0
+
+FROM valgrind AS adduser
+RUN useradd --shell /bin/bash libgit2 --create-home
+
+FROM adduser AS configure
+ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
+RUN mkdir /var/run/sshd
+RUN echo "/usr/local/lib" > /etc/ld.so.conf.d/local && \
+ ldconfig
diff --git a/azure-pipelines/docker/docurium b/ci/docker/docurium
index 54a4202b6..1957bbb3b 100644
--- a/azure-pipelines/docker/docurium
+++ b/ci/docker/docurium
@@ -1,3 +1,5 @@
-FROM ubuntu:bionic
+ARG BASE=ubuntu:bionic
+
+FROM ${BASE}
RUN apt update && apt install -y cmake pkg-config ruby ruby-dev llvm libclang-dev libssl-dev python-pygments
RUN gem install docurium
diff --git a/ci/docker/focal b/ci/docker/focal
new file mode 100644
index 000000000..37d7d6356
--- /dev/null
+++ b/ci/docker/focal
@@ -0,0 +1,79 @@
+ARG BASE=ubuntu:focal
+
+FROM ${BASE} AS apt
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+ bzip2 \
+ clang-10 \
+ cmake \
+ curl \
+ gcc-10 \
+ git \
+ krb5-user \
+ libcurl4-gnutls-dev \
+ libgcrypt20-dev \
+ libkrb5-dev \
+ libpcre3-dev \
+ libssl-dev \
+ libz-dev \
+ llvm-10 \
+ make \
+ ninja-build \
+ openjdk-8-jre-headless \
+ openssh-server \
+ openssl \
+ pkgconf \
+ python \
+ sudo \
+ valgrind \
+ && \
+ rm -rf /var/lib/apt/lists/* && \
+ mkdir /usr/local/msan
+
+FROM apt AS mbedtls
+RUN cd /tmp && \
+ curl --location --silent --show-error https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \
+ tar -xz && \
+ cd mbedtls-2.16.2 && \
+ scripts/config.pl unset MBEDTLS_AESNI_C && \
+ scripts/config.pl set MBEDTLS_MD4_C 1 && \
+ mkdir build build-msan && \
+ cd build && \
+ CC=clang-10 CFLAGS="-fPIC" cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=/usr/local -DCMAKE_INSTALL_PREFIX=/usr/local .. && \
+ ninja install && \
+ cd ../build-msan && \
+ CC=clang-10 CFLAGS="-fPIC" cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF -DCMAKE_BUILD_TYPE=MemSanDbg -DCMAKE_INSTALL_PREFIX=/usr/local/msan .. && \
+ ninja install && \
+ cd .. && \
+ rm -rf mbedtls-2.16.2
+
+FROM mbedtls AS libssh2
+RUN cd /tmp && \
+ curl --location --silent --show-error https://www.libssh2.org/download/libssh2-1.9.0.tar.gz | tar -xz && \
+ cd libssh2-1.9.0 && \
+ mkdir build build-msan && \
+ cd build && \
+ CC=clang-10 CFLAGS="-fPIC" cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCRYPTO_BACKEND=Libgcrypt -DCMAKE_PREFIX_PATH=/usr/local -DCMAKE_INSTALL_PREFIX=/usr/local .. && \
+ ninja install && \
+ cd ../build-msan && \
+ CC=clang-10 CFLAGS="-fPIC -fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" LDFLAGS="-fsanitize=memory" cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCRYPTO_BACKEND=mbedTLS -DCMAKE_PREFIX_PATH=/usr/local/msan -DCMAKE_INSTALL_PREFIX=/usr/local/msan .. && \
+ ninja install && \
+ cd .. && \
+ rm -rf libssh2-1.9.0
+
+FROM libssh2 AS valgrind
+RUN cd /tmp && \
+ curl --insecure --location --silent --show-error https://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2 | \
+ tar -xj && \
+ cd valgrind-3.15.0 && \
+ CC=clang-10 ./configure && \
+ make MAKEFLAGS="-j -l$(grep -c ^processor /proc/cpuinfo)" && \
+ make install && \
+ cd .. && \
+ rm -rf valgrind-3.15.0
+
+FROM valgrind AS adduser
+RUN useradd --shell /bin/bash libgit2 --create-home
+
+FROM adduser AS configure
+RUN mkdir /var/run/sshd
diff --git a/azure-pipelines/docker/xenial b/ci/docker/xenial
index 67867edc6..c19fe421d 100644
--- a/azure-pipelines/docker/xenial
+++ b/ci/docker/xenial
@@ -1,4 +1,6 @@
-FROM ubuntu:xenial AS apt
+ARG BASE=ubuntu:xenial
+
+FROM ${BASE} AS apt
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
bzip2 \
@@ -39,8 +41,7 @@ RUN cd /tmp && \
FROM mbedtls AS libssh2
RUN cd /tmp && \
- curl --insecure --location --silent --show-error https://www.libssh2.org/download/libssh2-1.8.2.tar.gz | \
- tar -xz && \
+ curl --location --silent --show-error https://www.libssh2.org/download/libssh2-1.8.2.tar.gz | tar -xz && \
cd libssh2-1.8.2 && \
CFLAGS=-fPIC cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCRYPTO_BACKEND=Libgcrypt . && \
ninja install && \
@@ -58,9 +59,8 @@ RUN cd /tmp && \
cd .. && \
rm -rf valgrind-3.15.0
-FROM valgrind AS configure
-COPY entrypoint.sh /usr/local/bin/entrypoint.sh
-RUN chmod a+x /usr/local/bin/entrypoint.sh
-RUN mkdir /var/run/sshd
+FROM valgrind AS adduser
+RUN useradd --shell /bin/bash libgit2 --create-home
-ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
+FROM adduser AS configure
+RUN mkdir /var/run/sshd
diff --git a/azure-pipelines/getcontainer.sh b/ci/getcontainer.sh
index bc93f4919..07ef7b8ea 100755
--- a/azure-pipelines/getcontainer.sh
+++ b/ci/getcontainer.sh
@@ -2,34 +2,40 @@
set -e
-DOCKERFILE_PATH=$1
+IMAGE_NAME=$1
+DOCKERFILE_PATH=$2
-if [ "${DOCKERFILE_PATH}" = "" ]; then
- echo "usage: $0 dockerfile"
+if [ "${IMAGE_NAME}" = "" ]; then
+ echo "usage: $0 image_name [dockerfile]"
exit 1
fi
+if [ "${DOCKERFILE_PATH}" = "" ]; then
+ DOCKERFILE_PATH="${IMAGE_NAME}"
+fi
+
if [ "${DOCKER_REGISTRY}" = "" ]; then
echo "DOCKER_REGISTRY environment variable is unset."
echo "Not running inside GitHub Actions or misconfigured?"
exit 1
fi
-DOCKER_CONTAINER="${GITHUB_REPOSITORY}/$(basename ${DOCKERFILE_PATH})"
+DOCKER_CONTAINER="${GITHUB_REPOSITORY}/${IMAGE_NAME}"
DOCKER_REGISTRY_CONTAINER="${DOCKER_REGISTRY}/${DOCKER_CONTAINER}"
-echo "::set-env name=docker-container::${DOCKER_CONTAINER}"
-echo "::set-env name=docker-registry-container::${DOCKER_REGISTRY_CONTAINER}"
+echo "dockerfile=${DOCKERFILE_PATH}" >> $GITHUB_ENV
+echo "docker-container=${DOCKER_CONTAINER}" >> $GITHUB_ENV
+echo "docker-registry-container=${DOCKER_REGISTRY_CONTAINER}" >> $GITHUB_ENV
# Identify the last git commit that touched the Dockerfiles
# Use this as a hash to identify the resulting docker containers
DOCKER_SHA=$(git log -1 --pretty=format:"%h" -- "${DOCKERFILE_PATH}")
-echo "::set-env name=docker-sha::${DOCKER_SHA}"
+echo "docker-sha=${DOCKER_SHA}" >> $GITHUB_ENV
DOCKER_REGISTRY_CONTAINER_SHA="${DOCKER_REGISTRY_CONTAINER}:${DOCKER_SHA}"
-echo "::set-env name=docker-registry-container-sha::${DOCKER_REGISTRY_CONTAINER_SHA}"
-echo "::set-env name=docker-registry-container-latest::${DOCKER_REGISTRY_CONTAINER}:latest"
+echo "docker-registry-container-sha=${DOCKER_REGISTRY_CONTAINER_SHA}" >> $GITHUB_ENV
+echo "docker-registry-container-latest=${DOCKER_REGISTRY_CONTAINER}:latest" >> $GITHUB_ENV
exists="true"
docker login https://${DOCKER_REGISTRY} -u ${GITHUB_ACTOR} -p ${GITHUB_TOKEN} || exists="false"
@@ -39,7 +45,7 @@ if [ "${exists}" != "false" ]; then
fi
if [ "${exists}" = "true" ]; then
- echo "::set-env name=docker-container-exists::true"
+ echo "docker-container-exists=true" >> $GITHUB_ENV
else
- echo "::set-env name=docker-container-exists::false"
+ echo "docker-container-exists=false" >> $GITHUB_ENV
fi
diff --git a/azure-pipelines/setup-mingw.sh b/ci/setup-mingw.sh
index d500da058..f5a882d2b 100755
--- a/azure-pipelines/setup-mingw.sh
+++ b/ci/setup-mingw.sh
@@ -9,9 +9,9 @@ BUILD_TEMP=$(cygpath $BUILD_TEMP)
case "$ARCH" in
amd64)
- MINGW_URI="https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-x86_64-8.1.0-release-win32-seh-rt_v6-rev0.zip";;
+ MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2021-05-04/mingw-x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
x86)
- MINGW_URI="https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
+ MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2021-05-04/mingw-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
esac
if [ -z "$MINGW_URI" ]; then
diff --git a/azure-pipelines/setup-osx.sh b/ci/setup-osx.sh
index 2e630eedb..2e630eedb 100755
--- a/azure-pipelines/setup-osx.sh
+++ b/ci/setup-osx.sh
diff --git a/azure-pipelines/test.sh b/ci/test.sh
index 2b43ba198..4d6c41f76 100755
--- a/azure-pipelines/test.sh
+++ b/ci/test.sh
@@ -17,6 +17,7 @@ TMPDIR=${TMPDIR:-/tmp}
USER=${USER:-$(whoami)}
SUCCESS=1
+CONTINUE_ON_FAILURE=0
cleanup() {
echo "Cleaning up..."
@@ -64,6 +65,10 @@ run_test() {
done
if [ "$FAILED" -ne 0 ]; then
+ if [ "$CONTINUE_ON_FAILURE" -ne 1 ]; then
+ exit 1
+ fi
+
SUCCESS=0
fi
}
@@ -174,9 +179,9 @@ if [ -n "$RUN_INVASIVE_TESTS" ]; then
fi
if [ -z "$SKIP_ONLINE_TESTS" ]; then
- # Run the various online tests. The "online" test suite only includes the
- # default online tests that do not require additional configuration. The
- # "proxy" and "ssh" test suites require further setup.
+ # Run the online tests. The "online" test suite only includes the
+ # default online tests that do not require additional configuration.
+ # The "proxy" and "ssh" test suites require further setup.
echo ""
echo "##############################################################################"
@@ -186,6 +191,14 @@ if [ -z "$SKIP_ONLINE_TESTS" ]; then
export GITTEST_FLAKY_RETRY=5
run_test online
unset GITTEST_FLAKY_RETRY
+
+ # Run the online tests that immutably change global state separately
+ # to avoid polluting the test environment.
+ echo ""
+ echo "##############################################################################"
+ echo "## Running (online_customcert) tests"
+ echo "##############################################################################"
+ run_test online_customcert
fi
if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
diff --git a/cmake/CheckPrototypeDefinition.c.in b/cmake/CheckPrototypeDefinition.c.in
deleted file mode 100644
index a97344ac3..000000000
--- a/cmake/CheckPrototypeDefinition.c.in
+++ /dev/null
@@ -1,29 +0,0 @@
-@CHECK_PROTOTYPE_DEFINITION_HEADER@
-
-static void cmakeRequireSymbol(int dummy, ...) {
- (void) dummy;
-}
-
-static void checkSymbol(void) {
-#ifndef @CHECK_PROTOTYPE_DEFINITION_SYMBOL@
- cmakeRequireSymbol(0, &@CHECK_PROTOTYPE_DEFINITION_SYMBOL@);
-#endif
-}
-
-@CHECK_PROTOTYPE_DEFINITION_PROTO@ {
- return @CHECK_PROTOTYPE_DEFINITION_RETURN@;
-}
-
-#ifdef __CLASSIC_C__
-int main() {
- int ac;
- char*av[];
-#else
-int main(int ac, char *av[]) {
-#endif
- checkSymbol();
- if (ac > 1000) {
- return *av[0];
- }
- return 0;
-}
diff --git a/cmake/CheckPrototypeDefinition.cmake b/cmake/CheckPrototypeDefinition.cmake
deleted file mode 100644
index 244b9b53b..000000000
--- a/cmake/CheckPrototypeDefinition.cmake
+++ /dev/null
@@ -1,96 +0,0 @@
-# - Check if the protoype we expect is correct.
-# check_prototype_definition(FUNCTION PROTOTYPE RETURN HEADER VARIABLE)
-# FUNCTION - The name of the function (used to check if prototype exists)
-# PROTOTYPE- The prototype to check.
-# RETURN - The return value of the function.
-# HEADER - The header files required.
-# VARIABLE - The variable to store the result.
-# Example:
-# check_prototype_definition(getpwent_r
-# "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)"
-# "NULL"
-# "unistd.h;pwd.h"
-# SOLARIS_GETPWENT_R)
-# The following variables may be set before calling this macro to
-# modify the way the check is run:
-#
-# CMAKE_REQUIRED_FLAGS = string of compile command line flags
-# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
-# CMAKE_REQUIRED_INCLUDES = list of include directories
-# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
-
-#=============================================================================
-# Copyright 2005-2009 Kitware, Inc.
-# Copyright 2010-2011 Andreas Schneider <asn@cryptomilk.org>
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-# License text for the above reference.)
-#
-
-get_filename_component(__check_proto_def_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-function(CHECK_PROTOTYPE_DEFINITION _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIABLE)
-
- if ("${_VARIABLE}" MATCHES "^${_VARIABLE}$")
- set(CHECK_PROTOTYPE_DEFINITION_CONTENT "/* */\n")
-
- set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS})
- if (CMAKE_REQUIRED_LIBRARIES)
- set(CHECK_PROTOTYPE_DEFINITION_LIBS
- "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
- else(CMAKE_REQUIRED_LIBRARIES)
- set(CHECK_PROTOTYPE_DEFINITION_LIBS)
- endif(CMAKE_REQUIRED_LIBRARIES)
- if (CMAKE_REQUIRED_INCLUDES)
- set(CMAKE_SYMBOL_EXISTS_INCLUDES
- "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
- else(CMAKE_REQUIRED_INCLUDES)
- set(CMAKE_SYMBOL_EXISTS_INCLUDES)
- endif(CMAKE_REQUIRED_INCLUDES)
-
- foreach(_FILE ${_HEADER})
- set(CHECK_PROTOTYPE_DEFINITION_HEADER
- "${CHECK_PROTOTYPE_DEFINITION_HEADER}#include <${_FILE}>\n")
- endforeach(_FILE)
-
- set(CHECK_PROTOTYPE_DEFINITION_SYMBOL ${_FUNCTION})
- set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE})
- set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN})
-
- configure_file("${__check_proto_def_dir}/CheckPrototypeDefinition.c.in"
- "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c" @ONLY)
-
- file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c _SOURCE)
-
- try_compile(${_VARIABLE}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c
- COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
- CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CHECK_PROTOTYPE_DEFINITION_FLAGS}
- "${CHECK_PROTOTYPE_DEFINITION_LIBS}"
- "${CMAKE_SYMBOL_EXISTS_INCLUDES}"
- OUTPUT_VARIABLE OUTPUT)
-
- if (${_VARIABLE})
- set(${_VARIABLE} 1 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
- message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - True")
- file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
- "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} passed with the following output:\n"
- "${OUTPUT}\n\n")
- else (${_VARIABLE})
- message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - False")
- set(${_VARIABLE} 0 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
- file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} failed with the following output:\n"
- "${OUTPUT}\n\n${_SOURCE}\n\n")
- endif (${_VARIABLE})
- endif("${_VARIABLE}" MATCHES "^${_VARIABLE}$")
-
-endfunction(CHECK_PROTOTYPE_DEFINITION)
diff --git a/cmake/FindLibSSH2.cmake b/cmake/FindLibSSH2.cmake
new file mode 100644
index 000000000..ff5893525
--- /dev/null
+++ b/cmake/FindLibSSH2.cmake
@@ -0,0 +1,13 @@
+# LIBSSH2_FOUND - system has the libssh2 library
+# LIBSSH2_INCLUDE_DIR - the libssh2 include directory
+# LIBSSH2_LIBRARY - the libssh2 library name
+
+FIND_PATH(LIBSSH2_INCLUDE_DIR libssh2.h)
+
+FIND_LIBRARY(LIBSSH2_LIBRARY NAMES ssh2 libssh2)
+
+INCLUDE(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LibSSH2
+ REQUIRED_VARS LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR)
+
+MARK_AS_ADVANCED(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY)
diff --git a/cmake/Findfutimens.cmake b/cmake/Findfutimens.cmake
new file mode 100644
index 000000000..73b79528a
--- /dev/null
+++ b/cmake/Findfutimens.cmake
@@ -0,0 +1,14 @@
+INCLUDE(EnableWarnings)
+
+IF (APPLE)
+ # We cannot simply CHECK_FUNCTION_EXISTS on macOS because
+ # MACOSX_DEPLOYMENT_TARGET may be set to a version in the past
+ # that doesn't have futimens. Instead we need to enable warnings
+ # as errors, then check for the symbol existing in `sys/stat.h`,
+ # then reset warnings as errors.
+ ENABLE_WARNINGS(error)
+ CHECK_SYMBOL_EXISTS(futimens sys/stat.h HAVE_FUTIMENS)
+ DISABLE_WARNINGS(error)
+ELSE ()
+ CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS)
+ENDIF ()
diff --git a/cmake/SelectHTTPSBackend.cmake b/cmake/SelectHTTPSBackend.cmake
index afbeac424..4998f0f2a 100644
--- a/cmake/SelectHTTPSBackend.cmake
+++ b/cmake/SelectHTTPSBackend.cmake
@@ -108,6 +108,10 @@ IF(USE_HTTPS)
LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES})
ELSEIF (USE_HTTPS STREQUAL "WinHTTP")
# WinHTTP setup was handled in the WinHTTP-specific block above
+ ELSEIF (USE_HTTPS STREQUAL "OpenSSL-Dynamic")
+ SET(GIT_OPENSSL 1)
+ SET(GIT_OPENSSL_DYNAMIC 1)
+ LIST(APPEND LIBGIT2_LIBS dl)
ELSE()
MESSAGE(FATAL_ERROR "Asked for backend ${USE_HTTPS} but it wasn't found")
ENDIF()
diff --git a/cmake/SelectHashes.cmake b/cmake/SelectHashes.cmake
index 06672ab03..092cdfd05 100644
--- a/cmake/SelectHashes.cmake
+++ b/cmake/SelectHashes.cmake
@@ -56,6 +56,7 @@ ELSE()
MESSAGE(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
ENDIF()
+list(APPEND SRC_SHA1 "hash/sha1.h")
list(SORT SRC_SHA1)
ADD_FEATURE_INFO(SHA ON "using ${USE_SHA1}")
diff --git a/deps/chromium-zlib/CMakeLists.txt b/deps/chromium-zlib/CMakeLists.txt
new file mode 100644
index 000000000..bbb35d4e6
--- /dev/null
+++ b/deps/chromium-zlib/CMakeLists.txt
@@ -0,0 +1,101 @@
+# CMake build script for the bundled Chromium zlib implementation. So far, it
+# is only supported for x86_64 processors with CLMUL, SSE3, SSE4.2.
+#
+# TODO: The Chromium build file (in deps/chromium-zlib/zlib/BUILD.gn) supports
+# more platforms (like ARM with NEON), more can be enabled as needed.
+
+CMAKE_MINIMUM_REQUIRED(VERSION 3.11)
+
+include(FetchContent)
+include(FindGit)
+
+# Ensure that the git binary is present to download the sources.
+find_package(Git)
+IF(NOT Git_FOUND)
+ message(FATAL_ERROR "git is required to download the Chromium zlib sources")
+ENDIF()
+
+FetchContent_Populate(chromium_zlib_src
+ GIT_REPOSITORY https://chromium.googlesource.com/chromium/src/third_party/zlib.git
+ GIT_TAG 2c183c9f93a328bfb3121284da13cf89a0f7e64a
+ QUIET
+)
+
+# The Chromium build globally disables some warnings.
+disable_warnings(implicit-fallthrough)
+disable_warnings(unused-function)
+disable_warnings(unused-parameter)
+disable_warnings(sign-compare)
+disable_warnings(declaration-after-statement)
+disable_warnings(missing-declarations)
+
+# -O3 is also set by the Chromium configuration and has been deemed safe enough
+# for them.
+SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG")
+SET(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
+
+# Common definitions.
+add_definitions(
+ -DSTDC
+ -DNO_GZIP
+ -DZLIB_IMPLEMENTATION
+)
+list(APPEND SRC_ZLIB
+ "${chromium_zlib_src_SOURCE_DIR}/adler32.c"
+ "${chromium_zlib_src_SOURCE_DIR}/chromeconf.h"
+ "${chromium_zlib_src_SOURCE_DIR}/compress.c"
+ "${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/insert_string.h"
+ "${chromium_zlib_src_SOURCE_DIR}/cpu_features.c"
+ "${chromium_zlib_src_SOURCE_DIR}/cpu_features.h"
+ "${chromium_zlib_src_SOURCE_DIR}/crc32.c"
+ "${chromium_zlib_src_SOURCE_DIR}/crc32.h"
+ "${chromium_zlib_src_SOURCE_DIR}/deflate.c"
+ "${chromium_zlib_src_SOURCE_DIR}/deflate.h"
+ "${chromium_zlib_src_SOURCE_DIR}/gzclose.c"
+ "${chromium_zlib_src_SOURCE_DIR}/gzguts.h"
+ "${chromium_zlib_src_SOURCE_DIR}/gzlib.c"
+ "${chromium_zlib_src_SOURCE_DIR}/gzread.c"
+ "${chromium_zlib_src_SOURCE_DIR}/gzwrite.c"
+ "${chromium_zlib_src_SOURCE_DIR}/infback.c"
+ "${chromium_zlib_src_SOURCE_DIR}/inffast.c"
+ "${chromium_zlib_src_SOURCE_DIR}/inffast.h"
+ "${chromium_zlib_src_SOURCE_DIR}/inffixed.h"
+ "${chromium_zlib_src_SOURCE_DIR}/inflate.h"
+ "${chromium_zlib_src_SOURCE_DIR}/inftrees.c"
+ "${chromium_zlib_src_SOURCE_DIR}/inftrees.h"
+ "${chromium_zlib_src_SOURCE_DIR}/trees.c"
+ "${chromium_zlib_src_SOURCE_DIR}/trees.h"
+ "${chromium_zlib_src_SOURCE_DIR}/uncompr.c"
+ "${chromium_zlib_src_SOURCE_DIR}/zconf.h"
+ "${chromium_zlib_src_SOURCE_DIR}/zlib.h"
+ "${chromium_zlib_src_SOURCE_DIR}/zutil.c"
+ "${chromium_zlib_src_SOURCE_DIR}/zutil.h"
+)
+
+# x86_64-specific optimizations
+string(APPEND CMAKE_C_FLAGS " -mssse3 -msse4.2 -mpclmul")
+add_definitions(
+ -DCHROMIUM_ZLIB_NO_CHROMECONF
+ -DX86_NOT_WINDOWS
+ -DADLER32_SIMD_SSSE3
+ -DCRC32_SIMD_SSE42_PCLMUL
+ -DDEFLATE_FILL_WINDOW_SSE2
+ -DINFLATE_CHUNK_READ_64LE
+ -DINFLATE_CHUNK_SIMD_SSE2
+)
+list(APPEND SRC_ZLIB
+ "${chromium_zlib_src_SOURCE_DIR}/adler32_simd.c"
+ "${chromium_zlib_src_SOURCE_DIR}/adler32_simd.h"
+ "${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/chunkcopy.h"
+ "${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/inffast_chunk.c"
+ "${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/inffast_chunk.h"
+ "${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/inflate.c"
+ "${chromium_zlib_src_SOURCE_DIR}/crc32_simd.c"
+ "${chromium_zlib_src_SOURCE_DIR}/crc32_simd.h"
+ "${chromium_zlib_src_SOURCE_DIR}/crc_folding.c"
+ "${chromium_zlib_src_SOURCE_DIR}/fill_window_sse.c"
+)
+
+list(SORT SRC_ZLIB)
+include_directories("${chromium_zlib_src_SOURCE_DIR}")
+add_library(chromium_zlib OBJECT ${SRC_ZLIB})
diff --git a/deps/ntlmclient/CMakeLists.txt b/deps/ntlmclient/CMakeLists.txt
index 5fbf0d0f4..3e0d2c817 100644
--- a/deps/ntlmclient/CMakeLists.txt
+++ b/deps/ntlmclient/CMakeLists.txt
@@ -1,24 +1,37 @@
-FILE(GLOB SRC_NTLMCLIENT "ntlm.c" "unicode_builtin.c" "util.c")
+FILE(GLOB SRC_NTLMCLIENT "ntlm.c" "ntlm.h" "util.c" "util.h")
LIST(SORT SRC_NTLMCLIENT)
ADD_DEFINITIONS(-DNTLM_STATIC=1)
DISABLE_WARNINGS(implicit-fallthrough)
+IF(USE_ICONV)
+ ADD_DEFINITIONS(-DUNICODE_ICONV=1)
+ FILE(GLOB SRC_NTLMCLIENT_UNICODE "unicode_iconv.c" "unicode_iconv.h")
+ELSE()
+ ADD_DEFINITIONS(-DUNICODE_BUILTIN=1)
+ FILE(GLOB SRC_NTLMCLIENT_UNICODE "unicode_builtin.c" "unicode_builtin.h")
+ENDIF()
+
IF(USE_HTTPS STREQUAL "SecureTransport")
ADD_DEFINITIONS(-DCRYPT_COMMONCRYPTO)
- SET(SRC_NTLMCLIENT_CRYPTO "crypt_commoncrypto.c")
+ SET(SRC_NTLMCLIENT_CRYPTO "crypt_commoncrypto.c" "crypt_commoncrypto.h")
# CC_MD4 has been deprecated in macOS 10.15.
SET_SOURCE_FILES_PROPERTIES("crypt_commoncrypto.c" COMPILE_FLAGS "-Wno-deprecated")
ELSEIF(USE_HTTPS STREQUAL "OpenSSL")
ADD_DEFINITIONS(-DCRYPT_OPENSSL)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
- SET(SRC_NTLMCLIENT_CRYPTO "crypt_openssl.c")
+ SET(SRC_NTLMCLIENT_CRYPTO "crypt_openssl.c" "crypt_openssl.h")
+ELSEIF(USE_HTTPS STREQUAL "OpenSSL-Dynamic")
+ ADD_DEFINITIONS(-DCRYPT_OPENSSL)
+ ADD_DEFINITIONS(-DCRYPT_OPENSSL_DYNAMIC)
+ SET(SRC_NTLMCLIENT_CRYPTO "crypt_openssl.c" "crypt_openssl.h")
ELSEIF(USE_HTTPS STREQUAL "mbedTLS")
ADD_DEFINITIONS(-DCRYPT_MBEDTLS)
- SET(SRC_NTLMCLIENT_CRYPTO "crypt_mbedtls.c")
+ INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR})
+ SET(SRC_NTLMCLIENT_CRYPTO "crypt_mbedtls.c" "crypt_mbedtls.h")
ELSE()
MESSAGE(FATAL_ERROR "Unable to use libgit2's HTTPS backend (${USE_HTTPS}) for NTLM crypto")
ENDIF()
-ADD_LIBRARY(ntlmclient OBJECT ${SRC_NTLMCLIENT} ${SRC_NTLMCLIENT_CRYPTO})
+ADD_LIBRARY(ntlmclient OBJECT ${SRC_NTLMCLIENT} ${SRC_NTLMCLIENT_UNICODE} ${SRC_NTLMCLIENT_CRYPTO})
diff --git a/deps/ntlmclient/compat.h b/deps/ntlmclient/compat.h
index f4d859aec..befc7cc4f 100644
--- a/deps/ntlmclient/compat.h
+++ b/deps/ntlmclient/compat.h
@@ -21,33 +21,6 @@
# include <stdbool.h>
#endif
-#ifdef __linux__
-/* See man page endian(3) */
-# include <endian.h>
-# define htonll htobe64
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-/* See man page htobe64(3) */
-# include <endian.h>
-# define htonll htobe64
-#elif defined(__FreeBSD__)
-/* See man page bwaps64(9) */
-# include <sys/endian.h>
-# define htonll htobe64
-#elif defined(sun) || defined(__sun)
-/* See man page byteorder(3SOCKET) */
-# include <sys/types.h>
-# include <netinet/in.h>
-# include <inttypes.h>
-
-# if !defined(htonll)
-# if defined(_BIG_ENDIAN)
-# define htonll(x) (x)
-# else
-# define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl((uint64_t)(x) >> 32))
-# endif
-# endif
-#endif
-
#ifndef MIN
# define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
diff --git a/deps/ntlmclient/crypt.h b/deps/ntlmclient/crypt.h
index 48be39946..4ad543ef7 100644
--- a/deps/ntlmclient/crypt.h
+++ b/deps/ntlmclient/crypt.h
@@ -9,6 +9,9 @@
#ifndef PRIVATE_CRYPT_COMMON_H__
#define PRIVATE_CRYPT_COMMON_H__
+#include "ntlmclient.h"
+#include "ntlm.h"
+
#if defined(CRYPT_OPENSSL)
# include "crypt_openssl.h"
#elif defined(CRYPT_MBEDTLS)
@@ -25,40 +28,42 @@
typedef unsigned char ntlm_des_block[CRYPT_DES_BLOCKSIZE];
+typedef struct ntlm_crypt_ctx ntlm_crypt_ctx;
+
+extern bool ntlm_crypt_init(ntlm_client *ntlm);
+
extern bool ntlm_random_bytes(
- ntlm_client *ntlm,
unsigned char *out,
+ ntlm_client *ntlm,
size_t len);
extern bool ntlm_des_encrypt(
ntlm_des_block *out,
+ ntlm_client *ntlm,
ntlm_des_block *plaintext,
ntlm_des_block *key);
extern bool ntlm_md4_digest(
unsigned char out[CRYPT_MD4_DIGESTSIZE],
+ ntlm_client *ntlm,
const unsigned char *in,
size_t in_len);
-extern ntlm_hmac_ctx *ntlm_hmac_ctx_init(void);
-
-extern bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx);
-
extern bool ntlm_hmac_md5_init(
- ntlm_hmac_ctx *ctx,
+ ntlm_client *ntlm,
const unsigned char *key,
size_t key_len);
extern bool ntlm_hmac_md5_update(
- ntlm_hmac_ctx *ctx,
+ ntlm_client *ntlm,
const unsigned char *data,
size_t data_len);
extern bool ntlm_hmac_md5_final(
unsigned char *out,
size_t *out_len,
- ntlm_hmac_ctx *ctx);
+ ntlm_client *ntlm);
-extern void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx);
+extern void ntlm_crypt_shutdown(ntlm_client *ntlm);
#endif /* PRIVATE_CRYPT_COMMON_H__ */
diff --git a/deps/ntlmclient/crypt_commoncrypto.c b/deps/ntlmclient/crypt_commoncrypto.c
index 54a0f097b..4ff57edd2 100644
--- a/deps/ntlmclient/crypt_commoncrypto.c
+++ b/deps/ntlmclient/crypt_commoncrypto.c
@@ -18,9 +18,15 @@
#include "ntlm.h"
#include "crypt.h"
+bool ntlm_crypt_init(ntlm_client *ntlm)
+{
+ memset(&ntlm->crypt_ctx, 0, sizeof(ntlm_crypt_ctx));
+ return true;
+}
+
bool ntlm_random_bytes(
- ntlm_client *ntlm,
unsigned char *out,
+ ntlm_client *ntlm,
size_t len)
{
int fd, ret;
@@ -49,11 +55,14 @@ bool ntlm_random_bytes(
bool ntlm_des_encrypt(
ntlm_des_block *out,
+ ntlm_client *ntlm,
ntlm_des_block *plaintext,
ntlm_des_block *key)
{
size_t written;
+ NTLM_UNUSED(ntlm);
+
CCCryptorStatus result = CCCrypt(kCCEncrypt,
kCCAlgorithmDES, kCCOptionECBMode,
key, sizeof(ntlm_des_block), NULL,
@@ -65,56 +74,47 @@ bool ntlm_des_encrypt(
bool ntlm_md4_digest(
unsigned char out[CRYPT_MD4_DIGESTSIZE],
+ ntlm_client *ntlm,
const unsigned char *in,
size_t in_len)
{
+ NTLM_UNUSED(ntlm);
return !!CC_MD4(in, in_len, out);
}
-ntlm_hmac_ctx *ntlm_hmac_ctx_init(void)
-{
- return calloc(1, sizeof(ntlm_hmac_ctx));
-}
-
-bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx)
-{
- memset(ctx, 0, sizeof(ntlm_hmac_ctx));
- return true;
-}
-
bool ntlm_hmac_md5_init(
- ntlm_hmac_ctx *ctx,
+ ntlm_client *ntlm,
const unsigned char *key,
size_t key_len)
{
- CCHmacInit(&ctx->native, kCCHmacAlgMD5, key, key_len);
+ CCHmacInit(&ntlm->crypt_ctx.hmac, kCCHmacAlgMD5, key, key_len);
return true;
}
bool ntlm_hmac_md5_update(
- ntlm_hmac_ctx *ctx,
+ ntlm_client *ntlm,
const unsigned char *data,
size_t data_len)
{
- CCHmacUpdate(&ctx->native, data, data_len);
+ CCHmacUpdate(&ntlm->crypt_ctx.hmac, data, data_len);
return true;
}
bool ntlm_hmac_md5_final(
unsigned char *out,
size_t *out_len,
- ntlm_hmac_ctx *ctx)
+ ntlm_client *ntlm)
{
if (*out_len < CRYPT_MD5_DIGESTSIZE)
return false;
- CCHmacFinal(&ctx->native, out);
+ CCHmacFinal(&ntlm->crypt_ctx.hmac, out);
*out_len = CRYPT_MD5_DIGESTSIZE;
return true;
}
-void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx)
+void ntlm_crypt_shutdown(ntlm_client *ntlm)
{
- free(ctx);
+ NTLM_UNUSED(ntlm);
}
diff --git a/deps/ntlmclient/crypt_commoncrypto.h b/deps/ntlmclient/crypt_commoncrypto.h
index e4075c9f6..e4df91d29 100644
--- a/deps/ntlmclient/crypt_commoncrypto.h
+++ b/deps/ntlmclient/crypt_commoncrypto.h
@@ -11,8 +11,8 @@
#include <CommonCrypto/CommonCrypto.h>
-typedef struct {
- CCHmacContext native;
-} ntlm_hmac_ctx;
+struct ntlm_crypt_ctx {
+ CCHmacContext hmac;
+};
#endif /* PRIVATE_CRYPT_COMMONCRYPTO_H__ */
diff --git a/deps/ntlmclient/crypt_mbedtls.c b/deps/ntlmclient/crypt_mbedtls.c
index bbab02d7d..6283c3eec 100644
--- a/deps/ntlmclient/crypt_mbedtls.c
+++ b/deps/ntlmclient/crypt_mbedtls.c
@@ -17,9 +17,24 @@
#include "ntlm.h"
#include "crypt.h"
+bool ntlm_crypt_init(ntlm_client *ntlm)
+{
+ const mbedtls_md_info_t *info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
+
+ mbedtls_md_init(&ntlm->crypt_ctx.hmac);
+
+ if (mbedtls_md_setup(&ntlm->crypt_ctx.hmac, info, 1) != 0) {
+ ntlm_client_set_errmsg(ntlm, "could not setup mbedtls digest");
+ return false;
+ }
+
+ return true;
+}
+
+
bool ntlm_random_bytes(
- ntlm_client *ntlm,
unsigned char *out,
+ ntlm_client *ntlm,
size_t len)
{
mbedtls_ctr_drbg_context ctr_drbg;
@@ -51,6 +66,7 @@ bool ntlm_random_bytes(
bool ntlm_des_encrypt(
ntlm_des_block *out,
+ ntlm_client *ntlm,
ntlm_des_block *plaintext,
ntlm_des_block *key)
{
@@ -60,8 +76,10 @@ bool ntlm_des_encrypt(
mbedtls_des_init(&ctx);
if (mbedtls_des_setkey_enc(&ctx, *key) ||
- mbedtls_des_crypt_ecb(&ctx, *plaintext, *out))
+ mbedtls_des_crypt_ecb(&ctx, *plaintext, *out)) {
+ ntlm_client_set_errmsg(ntlm, "DES encryption failed");
goto done;
+ }
success = true;
@@ -72,11 +90,14 @@ done:
bool ntlm_md4_digest(
unsigned char out[CRYPT_MD4_DIGESTSIZE],
+ ntlm_client *ntlm,
const unsigned char *in,
size_t in_len)
{
mbedtls_md4_context ctx;
+ NTLM_UNUSED(ntlm);
+
mbedtls_md4_init(&ctx);
mbedtls_md4_starts(&ctx);
mbedtls_md4_update(&ctx, in, in_len);
@@ -86,60 +107,40 @@ bool ntlm_md4_digest(
return true;
}
-ntlm_hmac_ctx *ntlm_hmac_ctx_init(void)
-{
- ntlm_hmac_ctx *ctx;
- const mbedtls_md_info_t *info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
-
- if ((ctx = calloc(1, sizeof(ntlm_hmac_ctx))) == NULL)
- return NULL;
-
- mbedtls_md_init(&ctx->mbed);
-
- if (mbedtls_md_setup(&ctx->mbed, info, 1) != 0) {
- free(ctx);
- return false;
- }
-
- return ctx;
-}
-
-bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx)
-{
- return !mbedtls_md_hmac_reset(&ctx->mbed);
-}
-
bool ntlm_hmac_md5_init(
- ntlm_hmac_ctx *ctx,
+ ntlm_client *ntlm,
const unsigned char *key,
size_t key_len)
{
- return !mbedtls_md_hmac_starts(&ctx->mbed, key, key_len);
+ if (ntlm->crypt_ctx.hmac_initialized) {
+ if (mbedtls_md_hmac_reset(&ntlm->crypt_ctx.hmac))
+ return false;
+ }
+
+ ntlm->crypt_ctx.hmac_initialized = !mbedtls_md_hmac_starts(&ntlm->crypt_ctx.hmac, key, key_len);
+ return ntlm->crypt_ctx.hmac_initialized;
}
bool ntlm_hmac_md5_update(
- ntlm_hmac_ctx *ctx,
+ ntlm_client *ntlm,
const unsigned char *in,
size_t in_len)
{
- return !mbedtls_md_hmac_update(&ctx->mbed, in, in_len);
+ return !mbedtls_md_hmac_update(&ntlm->crypt_ctx.hmac, in, in_len);
}
bool ntlm_hmac_md5_final(
unsigned char *out,
size_t *out_len,
- ntlm_hmac_ctx *ctx)
+ ntlm_client *ntlm)
{
if (*out_len < CRYPT_MD5_DIGESTSIZE)
return false;
- return !mbedtls_md_hmac_finish(&ctx->mbed, out);
+ return !mbedtls_md_hmac_finish(&ntlm->crypt_ctx.hmac, out);
}
-void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx)
+void ntlm_crypt_shutdown(ntlm_client *ntlm)
{
- if (ctx) {
- mbedtls_md_free(&ctx->mbed);
- free(ctx);
- }
+ mbedtls_md_free(&ntlm->crypt_ctx.hmac);
}
diff --git a/deps/ntlmclient/crypt_mbedtls.h b/deps/ntlmclient/crypt_mbedtls.h
index eb49a4596..2fc85035d 100644
--- a/deps/ntlmclient/crypt_mbedtls.h
+++ b/deps/ntlmclient/crypt_mbedtls.h
@@ -11,8 +11,9 @@
#include "mbedtls/md.h"
-typedef struct {
- mbedtls_md_context_t mbed;
-} ntlm_hmac_ctx;
+struct ntlm_crypt_ctx {
+ mbedtls_md_context_t hmac;
+ unsigned int hmac_initialized : 1;
+};
#endif /* PRIVATE_CRYPT_MBEDTLS_H__ */
diff --git a/deps/ntlmclient/crypt_openssl.c b/deps/ntlmclient/crypt_openssl.c
index 785be10e5..463eae4f8 100644
--- a/deps/ntlmclient/crypt_openssl.c
+++ b/deps/ntlmclient/crypt_openssl.c
@@ -9,26 +9,166 @@
#include <stdlib.h>
#include <string.h>
-#include <openssl/rand.h>
-#include <openssl/des.h>
-#include <openssl/md4.h>
-#include <openssl/hmac.h>
-#include <openssl/err.h>
+#ifdef CRYPT_OPENSSL_DYNAMIC
+# include <dlfcn.h>
+#else
+# include <openssl/rand.h>
+# include <openssl/des.h>
+# include <openssl/md4.h>
+# include <openssl/hmac.h>
+# include <openssl/err.h>
+#endif
#include "ntlm.h"
#include "compat.h"
#include "util.h"
#include "crypt.h"
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(CRYPT_OPENSSL_DYNAMIC)
+
+static inline HMAC_CTX *HMAC_CTX_new(void)
+{
+ return calloc(1, sizeof(HMAC_CTX));
+}
+
+static inline int HMAC_CTX_reset(HMAC_CTX *ctx)
+{
+ ntlm_memzero(ctx, sizeof(HMAC_CTX));
+ return 1;
+}
+
+static inline void HMAC_CTX_free(HMAC_CTX *ctx)
+{
+ free(ctx);
+}
+
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(CRYPT_OPENSSL_DYNAMIC)
+
+static inline void HMAC_CTX_cleanup(HMAC_CTX *ctx)
+{
+ NTLM_UNUSED(ctx);
+}
+
+#endif
+
+
+#ifdef CRYPT_OPENSSL_DYNAMIC
+
+static bool ntlm_crypt_init_functions(ntlm_client *ntlm)
+{
+ void *handle;
+
+ if ((handle = dlopen("libssl.so.1.1", RTLD_NOW)) == NULL &&
+ (handle = dlopen("libssl.1.1.dylib", RTLD_NOW)) == NULL &&
+ (handle = dlopen("libssl.so.1.0.0", RTLD_NOW)) == NULL &&
+ (handle = dlopen("libssl.1.0.0.dylib", RTLD_NOW)) == NULL &&
+ (handle = dlopen("libssl.so.10", RTLD_NOW)) == NULL) {
+ ntlm_client_set_errmsg(ntlm, "could not open libssl");
+ return false;
+ }
+
+ ntlm->crypt_ctx.des_set_key_fn = dlsym(handle, "DES_set_key");
+ ntlm->crypt_ctx.des_ecb_encrypt_fn = dlsym(handle, "DES_ecb_encrypt");
+ ntlm->crypt_ctx.err_get_error_fn = dlsym(handle, "ERR_get_error");
+ ntlm->crypt_ctx.err_lib_error_string_fn = dlsym(handle, "ERR_lib_error_string");
+ ntlm->crypt_ctx.evp_md5_fn = dlsym(handle, "EVP_md5");
+ ntlm->crypt_ctx.hmac_ctx_new_fn = dlsym(handle, "HMAC_CTX_new");
+ ntlm->crypt_ctx.hmac_ctx_free_fn = dlsym(handle, "HMAC_CTX_free");
+ ntlm->crypt_ctx.hmac_ctx_reset_fn = dlsym(handle, "HMAC_CTX_reset");
+ ntlm->crypt_ctx.hmac_init_ex_fn = dlsym(handle, "HMAC_Init_ex");
+ ntlm->crypt_ctx.hmac_update_fn = dlsym(handle, "HMAC_Update");
+ ntlm->crypt_ctx.hmac_final_fn = dlsym(handle, "HMAC_Final");
+ ntlm->crypt_ctx.md4_fn = dlsym(handle, "MD4");
+ ntlm->crypt_ctx.rand_bytes_fn = dlsym(handle, "RAND_bytes");
+
+ if (!ntlm->crypt_ctx.des_set_key_fn ||
+ !ntlm->crypt_ctx.des_ecb_encrypt_fn ||
+ !ntlm->crypt_ctx.err_get_error_fn ||
+ !ntlm->crypt_ctx.err_lib_error_string_fn ||
+ !ntlm->crypt_ctx.evp_md5_fn ||
+ !ntlm->crypt_ctx.hmac_init_ex_fn ||
+ !ntlm->crypt_ctx.hmac_update_fn ||
+ !ntlm->crypt_ctx.hmac_final_fn ||
+ !ntlm->crypt_ctx.md4_fn ||
+ !ntlm->crypt_ctx.rand_bytes_fn) {
+ ntlm_client_set_errmsg(ntlm, "could not load libssl functions");
+ dlclose(handle);
+ return false;
+ }
+
+ /* Toggle legacy HMAC context functions */
+ if (ntlm->crypt_ctx.hmac_ctx_new_fn &&
+ ntlm->crypt_ctx.hmac_ctx_free_fn &&
+ ntlm->crypt_ctx.hmac_ctx_reset_fn) {
+ ntlm->crypt_ctx.hmac_ctx_cleanup_fn = HMAC_CTX_cleanup;
+ } else {
+ ntlm->crypt_ctx.hmac_ctx_cleanup_fn = dlsym(handle, "HMAC_CTX_cleanup");
+
+ if (!ntlm->crypt_ctx.hmac_ctx_cleanup_fn) {
+ ntlm_client_set_errmsg(ntlm, "could not load legacy libssl functions");
+ dlclose(handle);
+ return false;
+ }
+
+ ntlm->crypt_ctx.hmac_ctx_new_fn = HMAC_CTX_new;
+ ntlm->crypt_ctx.hmac_ctx_free_fn = HMAC_CTX_free;
+ ntlm->crypt_ctx.hmac_ctx_reset_fn = HMAC_CTX_reset;
+ }
+
+ ntlm->crypt_ctx.openssl_handle = handle;
+ return true;
+}
+
+#else /* CRYPT_OPENSSL_DYNAMIC */
+
+static bool ntlm_crypt_init_functions(ntlm_client *ntlm)
+{
+ ntlm->crypt_ctx.des_set_key_fn = DES_set_key;
+ ntlm->crypt_ctx.des_ecb_encrypt_fn = DES_ecb_encrypt;
+ ntlm->crypt_ctx.err_get_error_fn = ERR_get_error;
+ ntlm->crypt_ctx.err_lib_error_string_fn = ERR_lib_error_string;
+ ntlm->crypt_ctx.evp_md5_fn = EVP_md5;
+ ntlm->crypt_ctx.hmac_ctx_new_fn = HMAC_CTX_new;
+ ntlm->crypt_ctx.hmac_ctx_free_fn = HMAC_CTX_free;
+ ntlm->crypt_ctx.hmac_ctx_reset_fn = HMAC_CTX_reset;
+ ntlm->crypt_ctx.hmac_ctx_cleanup_fn = HMAC_CTX_cleanup;
+ ntlm->crypt_ctx.hmac_init_ex_fn = HMAC_Init_ex;
+ ntlm->crypt_ctx.hmac_update_fn = HMAC_Update;
+ ntlm->crypt_ctx.hmac_final_fn = HMAC_Final;
+ ntlm->crypt_ctx.md4_fn = MD4;
+ ntlm->crypt_ctx.rand_bytes_fn = RAND_bytes;
+
+ return true;
+}
+
+#endif /* CRYPT_OPENSSL_DYNAMIC */
+
+bool ntlm_crypt_init(ntlm_client *ntlm)
+{
+ if (!ntlm_crypt_init_functions(ntlm))
+ return false;
+
+ ntlm->crypt_ctx.hmac = ntlm->crypt_ctx.hmac_ctx_new_fn();
+
+ if (ntlm->crypt_ctx.hmac == NULL) {
+ ntlm_client_set_errmsg(ntlm, "out of memory");
+ return false;
+ }
+
+ return true;
+}
+
bool ntlm_random_bytes(
- ntlm_client *ntlm,
unsigned char *out,
+ ntlm_client *ntlm,
size_t len)
{
- int rc = RAND_bytes(out, len);
+ int rc = ntlm->crypt_ctx.rand_bytes_fn(out, len);
if (rc != 1) {
- ntlm_client_set_errmsg(ntlm, ERR_lib_error_string(ERR_get_error()));
+ ntlm_client_set_errmsg(ntlm, ntlm->crypt_ctx.err_lib_error_string_fn(ntlm->crypt_ctx.err_get_error_fn()));
return false;
}
@@ -37,94 +177,81 @@ bool ntlm_random_bytes(
bool ntlm_des_encrypt(
ntlm_des_block *out,
+ ntlm_client *ntlm,
ntlm_des_block *plaintext,
ntlm_des_block *key)
{
DES_key_schedule keysched;
+ NTLM_UNUSED(ntlm);
+
memset(out, 0, sizeof(ntlm_des_block));
- DES_set_key(key, &keysched);
- DES_ecb_encrypt(plaintext, out, &keysched, DES_ENCRYPT);
+ ntlm->crypt_ctx.des_set_key_fn(key, &keysched);
+ ntlm->crypt_ctx.des_ecb_encrypt_fn(plaintext, out, &keysched, DES_ENCRYPT);
return true;
}
bool ntlm_md4_digest(
unsigned char out[CRYPT_MD4_DIGESTSIZE],
+ ntlm_client *ntlm,
const unsigned char *in,
size_t in_len)
{
- MD4(in, in_len, out);
+ ntlm->crypt_ctx.md4_fn(in, in_len, out);
return true;
}
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-static inline void HMAC_CTX_free(HMAC_CTX *ctx)
-{
- if (ctx)
- HMAC_CTX_cleanup(ctx);
-
- free(ctx);
-}
-
-static inline int HMAC_CTX_reset(HMAC_CTX *ctx)
-{
- HMAC_CTX_cleanup(ctx);
- memzero(ctx, sizeof(HMAC_CTX));
- return 1;
-}
-
-static inline HMAC_CTX *HMAC_CTX_new(void)
-{
- return calloc(1, sizeof(HMAC_CTX));
-}
-#endif
-
-ntlm_hmac_ctx *ntlm_hmac_ctx_init(void)
-{
- return HMAC_CTX_new();
-}
-
-bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx)
-{
- return HMAC_CTX_reset(ctx);
-}
-
bool ntlm_hmac_md5_init(
- ntlm_hmac_ctx *ctx,
+ ntlm_client *ntlm,
const unsigned char *key,
size_t key_len)
{
- return HMAC_Init_ex(ctx, key, key_len, EVP_md5(), NULL);
+ const EVP_MD *md5 = ntlm->crypt_ctx.evp_md5_fn();
+
+ ntlm->crypt_ctx.hmac_ctx_cleanup_fn(ntlm->crypt_ctx.hmac);
+
+ return ntlm->crypt_ctx.hmac_ctx_reset_fn(ntlm->crypt_ctx.hmac) &&
+ ntlm->crypt_ctx.hmac_init_ex_fn(ntlm->crypt_ctx.hmac, key, key_len, md5, NULL);
}
bool ntlm_hmac_md5_update(
- ntlm_hmac_ctx *ctx,
+ ntlm_client *ntlm,
const unsigned char *in,
size_t in_len)
{
- return HMAC_Update(ctx, in, in_len);
+ return ntlm->crypt_ctx.hmac_update_fn(ntlm->crypt_ctx.hmac, in, in_len);
}
bool ntlm_hmac_md5_final(
unsigned char *out,
size_t *out_len,
- ntlm_hmac_ctx *ctx)
+ ntlm_client *ntlm)
{
unsigned int len;
if (*out_len < CRYPT_MD5_DIGESTSIZE)
return false;
- if (!HMAC_Final(ctx, out, &len))
+ if (!ntlm->crypt_ctx.hmac_final_fn(ntlm->crypt_ctx.hmac, out, &len))
return false;
*out_len = len;
return true;
}
-void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx)
+void ntlm_crypt_shutdown(ntlm_client *ntlm)
{
- HMAC_CTX_free(ctx);
+ if (ntlm->crypt_ctx.hmac) {
+ ntlm->crypt_ctx.hmac_ctx_cleanup_fn(ntlm->crypt_ctx.hmac);
+ ntlm->crypt_ctx.hmac_ctx_free_fn(ntlm->crypt_ctx.hmac);
+ }
+
+#ifdef CRYPT_OPENSSL_DYNAMIC
+ if (ntlm->crypt_ctx.openssl_handle)
+ dlclose(ntlm->crypt_ctx.openssl_handle);
+#endif
+
+ memset(&ntlm->crypt_ctx, 0, sizeof(ntlm_crypt_ctx));
}
diff --git a/deps/ntlmclient/crypt_openssl.h b/deps/ntlmclient/crypt_openssl.h
index 4195db9a5..8654027db 100644
--- a/deps/ntlmclient/crypt_openssl.h
+++ b/deps/ntlmclient/crypt_openssl.h
@@ -9,13 +9,82 @@
#ifndef PRIVATE_CRYPT_OPENSSL_H__
#define PRIVATE_CRYPT_OPENSSL_H__
-#include <openssl/hmac.h>
+#ifndef CRYPT_OPENSSL_DYNAMIC
+# include <openssl/des.h>
+# include <openssl/hmac.h>
+#endif
/* OpenSSL 1.1.0 uses opaque structs, we'll reuse these. */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-typedef struct hmac_ctx_st ntlm_hmac_ctx;
-#else
-# define ntlm_hmac_ctx HMAC_CTX
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
+# define HMAC_CTX struct hmac_ctx_st
+#endif
+
+#ifdef CRYPT_OPENSSL_DYNAMIC
+typedef unsigned char DES_cblock[8];
+typedef unsigned char const_DES_cblock[8];
+
+typedef unsigned long DES_LONG;
+
+typedef struct DES_ks {
+ union {
+ DES_cblock cblock;
+ DES_LONG deslong[2];
+ } ks[16];
+} DES_key_schedule;
+
+#define DES_ENCRYPT 1
+
+typedef void EVP_MD;
+typedef void ENGINE;
+typedef void EVP_PKEY_CTX;
+
+#define HMAC_MAX_MD_CBLOCK 128
+
+typedef struct env_md_ctx_st EVP_MD_CTX;
+struct env_md_ctx_st {
+ const EVP_MD *digest;
+ ENGINE *engine;
+ unsigned long flags;
+ void *md_data;
+ EVP_PKEY_CTX *pctx;
+ int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
+};
+
+typedef struct hmac_ctx_st {
+ const EVP_MD *md;
+ EVP_MD_CTX md_ctx;
+ EVP_MD_CTX i_ctx;
+ EVP_MD_CTX o_ctx;
+ unsigned int key_length;
+ unsigned char key[HMAC_MAX_MD_CBLOCK];
+} HMAC_CTX;
#endif
+struct ntlm_crypt_ctx {
+ HMAC_CTX *hmac;
+
+ void *openssl_handle;
+
+ void (*des_ecb_encrypt_fn)(const_DES_cblock *input, DES_cblock *output, DES_key_schedule *ks, int enc);
+ int (*des_set_key_fn)(const_DES_cblock *key, DES_key_schedule *schedule);
+
+ unsigned long (*err_get_error_fn)(void);
+ const char *(*err_lib_error_string_fn)(unsigned long e);
+
+ const EVP_MD *(*evp_md5_fn)(void);
+
+ HMAC_CTX *(*hmac_ctx_new_fn)(void);
+ int (*hmac_ctx_reset_fn)(HMAC_CTX *ctx);
+ void (*hmac_ctx_free_fn)(HMAC_CTX *ctx);
+ void (*hmac_ctx_cleanup_fn)(HMAC_CTX *ctx);
+
+ int (*hmac_init_ex_fn)(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl);
+ int (*hmac_update_fn)(HMAC_CTX *ctx, const unsigned char *data, size_t len);
+ int (*hmac_final_fn)(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
+
+ unsigned char *(*md4_fn)(const unsigned char *d, size_t n, unsigned char *md);
+
+ int (*rand_bytes_fn)(unsigned char *buf, int num);
+};
+
#endif /* PRIVATE_CRYPT_OPENSSL_H__ */
diff --git a/deps/ntlmclient/ntlm.c b/deps/ntlmclient/ntlm.c
index 24b08f658..3393be915 100644
--- a/deps/ntlmclient/ntlm.c
+++ b/deps/ntlmclient/ntlm.c
@@ -9,7 +9,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
-#include <assert.h>
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
@@ -24,6 +23,18 @@
#include "compat.h"
#include "util.h"
+#define NTLM_ASSERT_ARG(expr) do { \
+ if (!(expr)) \
+ return NTLM_CLIENT_ERROR_INVALID_INPUT; \
+ } while(0)
+
+#define NTLM_ASSERT(ntlm, expr) do { \
+ if (!(expr)) { \
+ ntlm_client_set_errmsg(ntlm, "internal error: " #expr); \
+ return -1; \
+ } \
+ } while(0)
+
unsigned char ntlm_client_signature[] = NTLM_SIGNATURE;
static bool supports_unicode(ntlm_client *ntlm)
@@ -47,24 +58,25 @@ ntlm_client *ntlm_client_init(ntlm_client_flags flags)
{
ntlm_client *ntlm = NULL;
- if ((ntlm = malloc(sizeof(ntlm_client))) == NULL)
+ if ((ntlm = calloc(1, sizeof(ntlm_client))) == NULL)
return NULL;
- memset(ntlm, 0, sizeof(ntlm_client));
-
ntlm->flags = flags;
- if ((ntlm->hmac_ctx = ntlm_hmac_ctx_init()) == NULL ||
- (ntlm->unicode_ctx = ntlm_unicode_ctx_init(ntlm)) == NULL) {
- ntlm_hmac_ctx_free(ntlm->hmac_ctx);
- ntlm_unicode_ctx_free(ntlm->unicode_ctx);
- free(ntlm);
- return NULL;
- }
-
return ntlm;
}
+#define ENSURE_INITIALIZED(ntlm) \
+ do { \
+ if (!(ntlm)->unicode_initialized) \
+ (ntlm)->unicode_initialized = ntlm_unicode_init((ntlm)); \
+ if (!(ntlm)->crypt_initialized) \
+ (ntlm)->crypt_initialized = ntlm_crypt_init((ntlm)); \
+ if (!(ntlm)->unicode_initialized || \
+ !(ntlm)->crypt_initialized) \
+ return -1; \
+ } while(0)
+
void ntlm_client_set_errmsg(ntlm_client *ntlm, const char *errmsg)
{
ntlm->state = NTLM_STATE_ERROR;
@@ -73,7 +85,9 @@ void ntlm_client_set_errmsg(ntlm_client *ntlm, const char *errmsg)
const char *ntlm_client_errmsg(ntlm_client *ntlm)
{
- assert(ntlm);
+ if (!ntlm)
+ return "internal error";
+
return ntlm->errmsg ? ntlm->errmsg : "no error";
}
@@ -83,7 +97,7 @@ int ntlm_client_set_version(
uint8_t minor,
uint16_t build)
{
- assert(ntlm);
+ NTLM_ASSERT_ARG(ntlm);
ntlm->host_version.major = major;
ntlm->host_version.minor = minor;
@@ -95,20 +109,25 @@ int ntlm_client_set_version(
return 0;
}
+#define reset(ptr) do { free(ptr); ptr = NULL; } while(0)
+
+static void free_hostname(ntlm_client *ntlm)
+{
+ reset(ntlm->hostname);
+ reset(ntlm->hostdomain);
+ reset(ntlm->hostname_utf16);
+ ntlm->hostname_utf16_len = 0;
+}
+
int ntlm_client_set_hostname(
ntlm_client *ntlm,
const char *hostname,
const char *domain)
{
- assert(ntlm);
+ NTLM_ASSERT_ARG(ntlm);
+ ENSURE_INITIALIZED(ntlm);
- free(ntlm->hostname);
- free(ntlm->hostdomain);
- free(ntlm->hostname_utf16);
-
- ntlm->hostname = NULL;
- ntlm->hostdomain = NULL;
- ntlm->hostname_utf16 = NULL;
+ free_hostname(ntlm);
if (hostname && (ntlm->hostname = strdup(hostname)) == NULL) {
ntlm_client_set_errmsg(ntlm, "out of memory");
@@ -123,7 +142,7 @@ int ntlm_client_set_hostname(
if (hostname && supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16(
&ntlm->hostname_utf16,
&ntlm->hostname_utf16_len,
- ntlm->unicode_ctx,
+ ntlm,
hostname,
strlen(hostname)))
return -1;
@@ -134,30 +153,25 @@ int ntlm_client_set_hostname(
static void free_credentials(ntlm_client *ntlm)
{
if (ntlm->password)
- memzero(ntlm->password, strlen(ntlm->password));
+ ntlm_memzero(ntlm->password, strlen(ntlm->password));
if (ntlm->password_utf16)
- memzero(ntlm->password_utf16, ntlm->password_utf16_len);
-
- free(ntlm->username);
- free(ntlm->username_upper);
- free(ntlm->userdomain);
- free(ntlm->password);
-
- free(ntlm->username_utf16);
- free(ntlm->username_upper_utf16);
- free(ntlm->userdomain_utf16);
- free(ntlm->password_utf16);
-
- ntlm->username = NULL;
- ntlm->username_upper = NULL;
- ntlm->userdomain = NULL;
- ntlm->password = NULL;
-
- ntlm->username_utf16 = NULL;
- ntlm->username_upper_utf16 = NULL;
- ntlm->userdomain_utf16 = NULL;
- ntlm->password_utf16 = NULL;
+ ntlm_memzero(ntlm->password_utf16, ntlm->password_utf16_len);
+
+ reset(ntlm->username);
+ reset(ntlm->username_upper);
+ reset(ntlm->userdomain);
+ reset(ntlm->password);
+
+ reset(ntlm->username_utf16);
+ reset(ntlm->username_upper_utf16);
+ reset(ntlm->userdomain_utf16);
+ reset(ntlm->password_utf16);
+
+ ntlm->username_utf16_len = 0;
+ ntlm->username_upper_utf16_len = 0;
+ ntlm->userdomain_utf16_len = 0;
+ ntlm->password_utf16_len = 0;
}
int ntlm_client_set_credentials(
@@ -166,7 +180,8 @@ int ntlm_client_set_credentials(
const char *domain,
const char *password)
{
- assert(ntlm);
+ NTLM_ASSERT_ARG(ntlm);
+ ENSURE_INITIALIZED(ntlm);
free_credentials(ntlm);
@@ -187,7 +202,7 @@ int ntlm_client_set_credentials(
if (!ntlm_unicode_utf8_to_16(
&ntlm->username_utf16,
&ntlm->username_utf16_len,
- ntlm->unicode_ctx,
+ ntlm,
ntlm->username,
strlen(ntlm->username)))
return -1;
@@ -195,7 +210,7 @@ int ntlm_client_set_credentials(
if (!ntlm_unicode_utf8_to_16(
&ntlm->username_upper_utf16,
&ntlm->username_upper_utf16_len,
- ntlm->unicode_ctx,
+ ntlm,
ntlm->username_upper,
strlen(ntlm->username_upper)))
return -1;
@@ -204,7 +219,7 @@ int ntlm_client_set_credentials(
if (domain && supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16(
&ntlm->userdomain_utf16,
&ntlm->userdomain_utf16_len,
- ntlm->unicode_ctx,
+ ntlm,
ntlm->userdomain,
strlen(ntlm->userdomain)))
return -1;
@@ -214,7 +229,8 @@ int ntlm_client_set_credentials(
int ntlm_client_set_target(ntlm_client *ntlm, const char *target)
{
- assert(ntlm);
+ NTLM_ASSERT_ARG(ntlm);
+ ENSURE_INITIALIZED(ntlm);
free(ntlm->target);
free(ntlm->target_utf16);
@@ -231,7 +247,7 @@ int ntlm_client_set_target(ntlm_client *ntlm, const char *target)
if (supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16(
&ntlm->target_utf16,
&ntlm->target_utf16_len,
- ntlm->unicode_ctx,
+ ntlm,
ntlm->target,
strlen(ntlm->target)))
return -1;
@@ -242,14 +258,16 @@ int ntlm_client_set_target(ntlm_client *ntlm, const char *target)
int ntlm_client_set_nonce(ntlm_client *ntlm, uint64_t nonce)
{
- assert(ntlm);
+ NTLM_ASSERT_ARG(ntlm);
+
ntlm->nonce = nonce;
return 0;
}
int ntlm_client_set_timestamp(ntlm_client *ntlm, uint64_t timestamp)
{
- assert(ntlm);
+ NTLM_ASSERT_ARG(ntlm);
+
ntlm->timestamp = timestamp;
return 0;
}
@@ -260,6 +278,9 @@ static inline bool write_buf(
const unsigned char *buf,
size_t len)
{
+ if (!len)
+ return true;
+
if (out->len - out->pos < len) {
ntlm_client_set_errmsg(ntlm, "out of buffer space");
return false;
@@ -474,7 +495,7 @@ static inline bool read_string_unicode(
size_t out_len;
int ret = ntlm_unicode_utf16_to_8(out,
&out_len,
- ntlm->unicode_ctx,
+ ntlm,
(char *)&message->buf[message->pos],
string_len);
@@ -592,7 +613,9 @@ int ntlm_client_negotiate(
size_t hostname_offset = 0;
uint32_t flags = 0;
- assert(out && out_len && ntlm);
+ NTLM_ASSERT_ARG(out);
+ NTLM_ASSERT_ARG(out_len);
+ NTLM_ASSERT_ARG(ntlm);
*out = NULL;
*out_len = 0;
@@ -648,13 +671,11 @@ int ntlm_client_negotiate(
return -1;
}
- if ((ntlm->negotiate.buf = malloc(ntlm->negotiate.len)) == NULL) {
+ if ((ntlm->negotiate.buf = calloc(1, ntlm->negotiate.len)) == NULL) {
ntlm_client_set_errmsg(ntlm, "out of memory");
return -1;
}
- memset(ntlm->negotiate.buf, 0, ntlm->negotiate.len);
-
if (!write_buf(ntlm, &ntlm->negotiate,
ntlm_client_signature, sizeof(ntlm_client_signature)) ||
!write_int32(ntlm, &ntlm->negotiate, 1) ||
@@ -677,20 +698,22 @@ int ntlm_client_negotiate(
return -1;
if (hostname_len > 0) {
- assert(hostname_offset == ntlm->negotiate.pos);
+ NTLM_ASSERT(ntlm, hostname_offset == ntlm->negotiate.pos);
+
if (!write_buf(ntlm, &ntlm->negotiate,
(const unsigned char *)ntlm->hostname, hostname_len))
return -1;
}
if (domain_len > 0) {
- assert(domain_offset == ntlm->negotiate.pos);
+ NTLM_ASSERT(ntlm, domain_offset == ntlm->negotiate.pos);
+
if (!write_buf(ntlm, &ntlm->negotiate,
(const unsigned char *)ntlm->hostdomain, domain_len))
return -1;
}
- assert(ntlm->negotiate.pos == ntlm->negotiate.len);
+ NTLM_ASSERT(ntlm, ntlm->negotiate.pos == ntlm->negotiate.len);
ntlm->state = NTLM_STATE_CHALLENGE;
@@ -712,7 +735,10 @@ int ntlm_client_set_challenge(
uint32_t name_offset, info_offset = 0;
bool unicode, has_target_info = false;
- assert(ntlm && (challenge_msg || !challenge_msg_len));
+ NTLM_ASSERT_ARG(ntlm);
+ NTLM_ASSERT_ARG(challenge_msg || !challenge_msg_len);
+
+ ENSURE_INITIALIZED(ntlm);
if (ntlm->state != NTLM_STATE_NEGOTIATE &&
ntlm->state != NTLM_STATE_CHALLENGE) {
@@ -941,6 +967,7 @@ static void des_key_from_password(
static inline bool generate_lm_hash(
ntlm_des_block out[2],
+ ntlm_client *ntlm,
const char *password)
{
/* LM encrypts this known plaintext using the password as a key */
@@ -969,8 +996,8 @@ static inline bool generate_lm_hash(
des_key_from_password(&key1, keystr1, keystr1_len);
des_key_from_password(&key2, keystr2, keystr2_len);
- return ntlm_des_encrypt(&out[0], &plaintext, &key1) &&
- ntlm_des_encrypt(&out[1], &plaintext, &key2);
+ return ntlm_des_encrypt(&out[0], ntlm, &plaintext, &key1) &&
+ ntlm_des_encrypt(&out[1], ntlm, &plaintext, &key2);
}
static void des_keys_from_lm_hash(ntlm_des_block out[3], ntlm_des_block lm_hash[2])
@@ -995,16 +1022,16 @@ static bool generate_lm_response(ntlm_client *ntlm)
ntlm_des_block *challenge = (ntlm_des_block *)&ntlm->challenge.nonce;
/* Generate the LM hash from the password */
- if (!generate_lm_hash(lm_hash, ntlm->password))
+ if (!generate_lm_hash(lm_hash, ntlm, ntlm->password))
return false;
/* Convert that LM hash to three DES keys */
des_keys_from_lm_hash(key, lm_hash);
/* Finally, encrypt the challenge with each of these keys */
- if (!ntlm_des_encrypt(&lm_response[0], challenge, &key[0]) ||
- !ntlm_des_encrypt(&lm_response[1], challenge, &key[1]) ||
- !ntlm_des_encrypt(&lm_response[2], challenge, &key[2]))
+ if (!ntlm_des_encrypt(&lm_response[0], ntlm, challenge, &key[0]) ||
+ !ntlm_des_encrypt(&lm_response[1], ntlm, challenge, &key[1]) ||
+ !ntlm_des_encrypt(&lm_response[2], ntlm, challenge, &key[2]))
return false;
memcpy(&ntlm->lm_response[0], lm_response[0], 8);
@@ -1023,12 +1050,13 @@ static bool generate_ntlm_hash(
if (ntlm->password && !ntlm_unicode_utf8_to_16(
&ntlm->password_utf16,
&ntlm->password_utf16_len,
- ntlm->unicode_ctx,
+ ntlm,
ntlm->password,
strlen(ntlm->password)))
return false;
return ntlm_md4_digest(out,
+ ntlm,
(const unsigned char *)ntlm->password_utf16,
ntlm->password_utf16_len);
}
@@ -1049,9 +1077,9 @@ static bool generate_ntlm_response(ntlm_client *ntlm)
des_key_from_password(&key[2], &ntlm_hash[14], 2);
/* Finally, encrypt the challenge with each of these keys */
- if (!ntlm_des_encrypt(&ntlm_response[0], challenge, &key[0]) ||
- !ntlm_des_encrypt(&ntlm_response[1], challenge, &key[1]) ||
- !ntlm_des_encrypt(&ntlm_response[2], challenge, &key[2]))
+ if (!ntlm_des_encrypt(&ntlm_response[0], ntlm, challenge, &key[0]) ||
+ !ntlm_des_encrypt(&ntlm_response[1], ntlm, challenge, &key[1]) ||
+ !ntlm_des_encrypt(&ntlm_response[2], ntlm, challenge, &key[2]))
return false;
memcpy(&ntlm->ntlm_response[0], ntlm_response[0], 8);
@@ -1082,16 +1110,15 @@ static bool generate_ntlm2_hash(
target_len = ntlm->target_utf16_len;
}
- if (!ntlm_hmac_ctx_reset(ntlm->hmac_ctx) ||
- !ntlm_hmac_md5_init(ntlm->hmac_ctx, ntlm_hash, sizeof(ntlm_hash)) ||
- !ntlm_hmac_md5_update(ntlm->hmac_ctx, username, username_len) ||
- !ntlm_hmac_md5_update(ntlm->hmac_ctx, target, target_len) ||
- !ntlm_hmac_md5_final(out, &out_len, ntlm->hmac_ctx)) {
+ if (!ntlm_hmac_md5_init(ntlm, ntlm_hash, sizeof(ntlm_hash)) ||
+ !ntlm_hmac_md5_update(ntlm, username, username_len) ||
+ !ntlm_hmac_md5_update(ntlm, target, target_len) ||
+ !ntlm_hmac_md5_final(out, &out_len, ntlm)) {
ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5");
return false;
}
- assert(out_len == NTLM_NTLM2_HASH_LEN);
+ NTLM_ASSERT(ntlm, out_len == NTLM_NTLM2_HASH_LEN);
return true;
}
@@ -1104,43 +1131,36 @@ static bool generate_ntlm2_challengehash(
{
size_t out_len = 16;
- if (!ntlm_hmac_ctx_reset(ntlm->hmac_ctx) ||
- !ntlm_hmac_md5_init(ntlm->hmac_ctx,
- ntlm2_hash, NTLM_NTLM2_HASH_LEN) ||
- !ntlm_hmac_md5_update(ntlm->hmac_ctx,
- (const unsigned char *)&ntlm->challenge.nonce, 8) ||
- !ntlm_hmac_md5_update(ntlm->hmac_ctx, blob, blob_len) ||
- !ntlm_hmac_md5_final(out, &out_len, ntlm->hmac_ctx)) {
+ if (!ntlm_hmac_md5_init(ntlm, ntlm2_hash, NTLM_NTLM2_HASH_LEN) ||
+ !ntlm_hmac_md5_update(ntlm, (const unsigned char *)&ntlm->challenge.nonce, 8) ||
+ !ntlm_hmac_md5_update(ntlm, blob, blob_len) ||
+ !ntlm_hmac_md5_final(out, &out_len, ntlm)) {
ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5");
return false;
}
- assert(out_len == 16);
+ NTLM_ASSERT(ntlm, out_len == 16);
return true;
}
static bool generate_lm2_response(ntlm_client *ntlm,
unsigned char ntlm2_hash[NTLM_NTLM2_HASH_LEN])
{
- unsigned char lm2_challengehash[16];
+ unsigned char lm2_challengehash[16] = {0};
size_t lm2_len = 16;
uint64_t local_nonce;
- local_nonce = htonll(ntlm->nonce);
+ local_nonce = ntlm_htonll(ntlm->nonce);
- if (!ntlm_hmac_ctx_reset(ntlm->hmac_ctx) ||
- !ntlm_hmac_md5_init(ntlm->hmac_ctx,
- ntlm2_hash, NTLM_NTLM2_HASH_LEN) ||
- !ntlm_hmac_md5_update(ntlm->hmac_ctx,
- (const unsigned char *)&ntlm->challenge.nonce, 8) ||
- !ntlm_hmac_md5_update(ntlm->hmac_ctx,
- (const unsigned char *)&local_nonce, 8) ||
- !ntlm_hmac_md5_final(lm2_challengehash, &lm2_len, ntlm->hmac_ctx)) {
+ if (!ntlm_hmac_md5_init(ntlm, ntlm2_hash, NTLM_NTLM2_HASH_LEN) ||
+ !ntlm_hmac_md5_update(ntlm, (const unsigned char *)&ntlm->challenge.nonce, 8) ||
+ !ntlm_hmac_md5_update(ntlm, (const unsigned char *)&local_nonce, 8) ||
+ !ntlm_hmac_md5_final(lm2_challengehash, &lm2_len, ntlm)) {
ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5");
return false;
}
- assert(lm2_len == 16);
+ NTLM_ASSERT(ntlm, lm2_len == 16);
memcpy(&ntlm->lm_response[0], lm2_challengehash, 16);
memcpy(&ntlm->lm_response[16], &local_nonce, 8);
@@ -1164,7 +1184,7 @@ static bool generate_nonce(ntlm_client *ntlm)
if (ntlm->nonce)
return true;
- if (!ntlm_random_bytes(ntlm, buf, 8))
+ if (!ntlm_random_bytes(buf, ntlm, 8))
return false;
memcpy(&ntlm->nonce, buf, sizeof(uint64_t));
@@ -1177,7 +1197,7 @@ static bool generate_ntlm2_response(ntlm_client *ntlm)
uint32_t signature;
uint64_t timestamp, nonce;
unsigned char ntlm2_hash[NTLM_NTLM2_HASH_LEN];
- unsigned char challengehash[16];
+ unsigned char challengehash[16] = {0};
unsigned char *blob;
if (!generate_timestamp(ntlm) ||
@@ -1198,8 +1218,8 @@ static bool generate_ntlm2_response(ntlm_client *ntlm)
/* the blob's integer values are in network byte order */
signature = htonl(0x01010000);
- timestamp = htonll(ntlm->timestamp);
- nonce = htonll(ntlm->nonce);
+ timestamp = ntlm_htonll(ntlm->timestamp);
+ nonce = ntlm_htonll(ntlm->nonce);
/* construct the blob */
memcpy(&blob[0], &signature, 4);
@@ -1234,7 +1254,11 @@ int ntlm_client_response(
uint32_t flags = 0;
bool unicode;
- assert(out && out_len && ntlm);
+ NTLM_ASSERT_ARG(out);
+ NTLM_ASSERT_ARG(out_len);
+ NTLM_ASSERT_ARG(ntlm);
+
+ ENSURE_INITIALIZED(ntlm);
*out = NULL;
*out_len = 0;
@@ -1334,13 +1358,11 @@ int ntlm_client_response(
return -1;
}
- if ((ntlm->response.buf = malloc(ntlm->response.len)) == NULL) {
+ if ((ntlm->response.buf = calloc(1, ntlm->response.len)) == NULL) {
ntlm_client_set_errmsg(ntlm, "out of memory");
return -1;
}
- memset(ntlm->response.buf, 0, ntlm->response.len);
-
if (!write_buf(ntlm, &ntlm->response,
ntlm_client_signature, sizeof(ntlm_client_signature)) ||
!write_int32(ntlm, &ntlm->response, 3) ||
@@ -1359,7 +1381,7 @@ int ntlm_client_response(
!write_buf(ntlm, &ntlm->response, session, session_len))
return -1;
- assert(ntlm->response.pos == ntlm->response.len);
+ NTLM_ASSERT(ntlm, ntlm->response.pos == ntlm->response.len);
ntlm->state = NTLM_STATE_COMPLETE;
@@ -1371,41 +1393,48 @@ int ntlm_client_response(
void ntlm_client_reset(ntlm_client *ntlm)
{
- ntlm_client_flags flags;
- ntlm_hmac_ctx *hmac_ctx;
- ntlm_unicode_ctx *unicode_ctx;
-
- assert(ntlm);
+ if (!ntlm)
+ return;
- free(ntlm->negotiate.buf);
- free(ntlm->challenge.target_info);
- free(ntlm->challenge.target);
- free(ntlm->challenge.target_domain);
- free(ntlm->challenge.target_domain_dns);
- free(ntlm->challenge.target_server);
- free(ntlm->challenge.target_server_dns);
- free(ntlm->response.buf);
+ ntlm->state = NTLM_STATE_NEGOTIATE;
- free(ntlm->hostname);
- free(ntlm->hostname_utf16);
- free(ntlm->hostdomain);
+ free_hostname(ntlm);
- free(ntlm->target);
- free(ntlm->target_utf16);
+ memset(&ntlm->host_version, 0, sizeof(ntlm_version));
- free(ntlm->ntlm2_response);
+ reset(ntlm->target);
+ reset(ntlm->target_utf16);
+ ntlm->target_utf16_len = 0;
free_credentials(ntlm);
- flags = ntlm->flags;
- hmac_ctx = ntlm->hmac_ctx;
- unicode_ctx = ntlm->unicode_ctx;
+ ntlm->nonce = 0;
+ ntlm->timestamp = 0;
- memset(ntlm, 0, sizeof(struct ntlm_client));
+ memset(ntlm->lm_response, 0, NTLM_LM_RESPONSE_LEN);
+ ntlm->lm_response_len = 0;
- ntlm->flags = flags;
- ntlm->hmac_ctx = hmac_ctx;
- ntlm->unicode_ctx = unicode_ctx;
+ memset(ntlm->ntlm_response, 0, NTLM_NTLM_RESPONSE_LEN);
+ ntlm->ntlm_response_len = 0;
+
+ reset(ntlm->ntlm2_response);
+ ntlm->ntlm2_response_len = 0;
+
+ reset(ntlm->negotiate.buf);
+ ntlm->negotiate.pos = 0;
+ ntlm->negotiate.len = 0;
+
+ reset(ntlm->response.buf);
+ ntlm->response.pos = 0;
+ ntlm->response.len = 0;
+
+ free(ntlm->challenge.target_info);
+ free(ntlm->challenge.target);
+ free(ntlm->challenge.target_domain);
+ free(ntlm->challenge.target_domain_dns);
+ free(ntlm->challenge.target_server);
+ free(ntlm->challenge.target_server_dns);
+ memset(&ntlm->challenge, 0, sizeof(ntlm_challenge));
}
void ntlm_client_free(ntlm_client *ntlm)
@@ -1413,10 +1442,10 @@ void ntlm_client_free(ntlm_client *ntlm)
if (!ntlm)
return;
- ntlm_client_reset(ntlm);
+ ntlm_crypt_shutdown(ntlm);
+ ntlm_unicode_shutdown(ntlm);
- ntlm_hmac_ctx_free(ntlm->hmac_ctx);
- ntlm_unicode_ctx_free(ntlm->unicode_ctx);
+ ntlm_client_reset(ntlm);
free(ntlm);
}
diff --git a/deps/ntlmclient/ntlm.h b/deps/ntlmclient/ntlm.h
index 0dad91ec0..227f5bcba 100644
--- a/deps/ntlmclient/ntlm.h
+++ b/deps/ntlmclient/ntlm.h
@@ -14,6 +14,8 @@
#include "crypt.h"
#include "compat.h"
+#define NTLM_UNUSED(x) ((void)(x))
+
#define NTLM_LM_RESPONSE_LEN 24
#define NTLM_NTLM_RESPONSE_LEN 24
#define NTLM_NTLM_HASH_LEN 16
@@ -66,9 +68,11 @@ struct ntlm_client {
ntlm_state state;
- /* crypto contexts */
- ntlm_hmac_ctx *hmac_ctx;
- ntlm_unicode_ctx *unicode_ctx;
+ /* subsystem contexts */
+ ntlm_crypt_ctx crypt_ctx;
+ ntlm_unicode_ctx unicode_ctx;
+ int crypt_initialized : 1,
+ unicode_initialized : 1;
/* error message as set by the library */
const char *errmsg;
@@ -85,24 +89,24 @@ struct ntlm_client {
char *password;
/* strings as converted to utf16 */
+ char *hostname_utf16;
char *target_utf16;
char *username_utf16;
char *username_upper_utf16;
char *userdomain_utf16;
- char *hostname_utf16;
char *password_utf16;
- /* timestamp and nonce; only for debugging */
- uint64_t nonce;
- uint64_t timestamp;
-
+ size_t hostname_utf16_len;
size_t username_utf16_len;
size_t username_upper_utf16_len;
size_t userdomain_utf16_len;
- size_t hostname_utf16_len;
size_t password_utf16_len;
size_t target_utf16_len;
+ /* timestamp and nonce; only for debugging */
+ uint64_t nonce;
+ uint64_t timestamp;
+
unsigned char lm_response[NTLM_LM_RESPONSE_LEN];
size_t lm_response_len;
diff --git a/deps/ntlmclient/ntlmclient.h b/deps/ntlmclient/ntlmclient.h
index d109a5c89..bf57b17c6 100644
--- a/deps/ntlmclient/ntlmclient.h
+++ b/deps/ntlmclient/ntlmclient.h
@@ -15,13 +15,26 @@
extern "C" {
#endif
-#define NTLM_CLIENT_VERSION "0.0.1"
+#define NTLM_CLIENT_VERSION "0.9.0"
#define NTLM_CLIENT_VERSION_MAJOR 0
-#define NTLM_CLIENT_VERSION_MINOR 0
-#define NTLM_CLIENT_VERSION_TEENY 1
+#define NTLM_CLIENT_VERSION_MINOR 9
+#define NTLM_CLIENT_VERSION_TEENY 0
typedef struct ntlm_client ntlm_client;
+typedef enum {
+ /**
+ * An error occurred; more details are available by querying
+ * `ntlm_client_errmsg`.
+ */
+ NTLM_CLIENT_ERROR = -1,
+
+ /**
+ * The input provided to the function is missing or invalid.
+ */
+ NTLM_CLIENT_ERROR_INVALID_INPUT = -2,
+} ntlm_error_code;
+
/*
* Flags for initializing the `ntlm_client` context. A combination of
* these flags can be provided to `ntlm_client_init`.
diff --git a/deps/ntlmclient/unicode.h b/deps/ntlmclient/unicode.h
index e3b17bcf7..b7c63f2ed 100644
--- a/deps/ntlmclient/unicode.h
+++ b/deps/ntlmclient/unicode.h
@@ -11,26 +11,32 @@
#include "compat.h"
+#ifdef UNICODE_ICONV
+# include "unicode_iconv.h"
+#elif UNICODE_BUILTIN
+# include "unicode_builtin.h"
+#endif
+
#define NTLM_UNICODE_MAX_LEN 2048
typedef struct ntlm_unicode_ctx ntlm_unicode_ctx;
-extern ntlm_unicode_ctx *ntlm_unicode_ctx_init(ntlm_client *ntlm);
+extern bool ntlm_unicode_init(ntlm_client *ntlm);
bool ntlm_unicode_utf8_to_16(
char **converted,
size_t *converted_len,
- ntlm_unicode_ctx *ctx,
+ ntlm_client *ntlm,
const char *string,
size_t string_len);
bool ntlm_unicode_utf16_to_8(
char **converted,
size_t *converted_len,
- ntlm_unicode_ctx *ctx,
+ ntlm_client *ntlm,
const char *string,
size_t string_len);
-extern void ntlm_unicode_ctx_free(ntlm_unicode_ctx *ctx);
+extern void ntlm_unicode_shutdown(ntlm_client *ntlm);
#endif /* PRIVATE_UNICODE_H__ */
diff --git a/deps/ntlmclient/unicode_builtin.c b/deps/ntlmclient/unicode_builtin.c
index e1856cca9..e2ee0abf7 100644
--- a/deps/ntlmclient/unicode_builtin.c
+++ b/deps/ntlmclient/unicode_builtin.c
@@ -13,10 +13,6 @@
#include "unicode.h"
#include "compat.h"
-struct ntlm_unicode_ctx {
- ntlm_client *ntlm;
-};
-
typedef unsigned int UTF32; /* at least 32 bits */
typedef unsigned short UTF16; /* at least 16 bits */
typedef unsigned char UTF8; /* typically 8 bits */
@@ -281,15 +277,10 @@ static ConversionResult ConvertUTF8toUTF16 (
}
-ntlm_unicode_ctx *ntlm_unicode_ctx_init(ntlm_client *ntlm)
+bool ntlm_unicode_init(ntlm_client *ntlm)
{
- ntlm_unicode_ctx *ctx;
-
- if ((ctx = malloc(sizeof(ntlm_unicode_ctx))) == NULL)
- return NULL;
-
- ctx->ntlm = ntlm;
- return ctx;
+ NTLM_UNUSED(ntlm);
+ return true;
}
typedef enum {
@@ -300,7 +291,7 @@ typedef enum {
static inline bool unicode_builtin_encoding_convert(
char **converted,
size_t *converted_len,
- ntlm_unicode_ctx *ctx,
+ ntlm_client *ntlm,
const char *string,
size_t string_len,
unicode_builtin_encoding_direction direction)
@@ -332,7 +323,7 @@ static inline bool unicode_builtin_encoding_convert(
out_size = (out_size + 7) & ~7;
if ((out = malloc(out_size)) == NULL) {
- ntlm_client_set_errmsg(ctx->ntlm, "out of memory");
+ ntlm_client_set_errmsg(ntlm, "out of memory");
return false;
}
@@ -358,17 +349,17 @@ static inline bool unicode_builtin_encoding_convert(
success = true;
goto done;
case sourceExhausted:
- ntlm_client_set_errmsg(ctx->ntlm,
+ ntlm_client_set_errmsg(ntlm,
"invalid unicode string; trailing data remains");
goto done;
case targetExhausted:
break;
case sourceIllegal:
- ntlm_client_set_errmsg(ctx->ntlm,
+ ntlm_client_set_errmsg(ntlm,
"invalid unicode string; trailing data remains");
goto done;
default:
- ntlm_client_set_errmsg(ctx->ntlm,
+ ntlm_client_set_errmsg(ntlm,
"unknown unicode conversion failure");
goto done;
}
@@ -377,13 +368,12 @@ static inline bool unicode_builtin_encoding_convert(
out_size = ((((out_size << 1) - (out_size >> 1)) + 7) & ~7);
if (out_size > NTLM_UNICODE_MAX_LEN) {
- ntlm_client_set_errmsg(ctx->ntlm,
- "unicode conversion too large");
+ ntlm_client_set_errmsg(ntlm, "unicode conversion too large");
goto done;
}
if ((new_out = realloc(out, out_size)) == NULL) {
- ntlm_client_set_errmsg(ctx->ntlm, "out of memory");
+ ntlm_client_set_errmsg(ntlm, "out of memory");
goto done;
}
@@ -419,27 +409,26 @@ done:
bool ntlm_unicode_utf8_to_16(
char **converted,
size_t *converted_len,
- ntlm_unicode_ctx *ctx,
+ ntlm_client *client,
const char *string,
size_t string_len)
{
return unicode_builtin_encoding_convert(converted, converted_len,
- ctx, string, string_len, unicode_builtin_utf8_to_16);
+ client, string, string_len, unicode_builtin_utf8_to_16);
}
bool ntlm_unicode_utf16_to_8(
char **converted,
size_t *converted_len,
- ntlm_unicode_ctx *ctx,
+ ntlm_client *client,
const char *string,
size_t string_len)
{
return unicode_builtin_encoding_convert(converted, converted_len,
- ctx, string, string_len, unicode_builtin_utf16_to_8);
+ client, string, string_len, unicode_builtin_utf16_to_8);
}
-void ntlm_unicode_ctx_free(ntlm_unicode_ctx *ctx)
+void ntlm_unicode_shutdown(ntlm_client *ntlm)
{
- if (ctx)
- free(ctx);
+ NTLM_UNUSED(ntlm);
}
diff --git a/deps/ntlmclient/unicode_builtin.h b/deps/ntlmclient/unicode_builtin.h
new file mode 100644
index 000000000..eabec40bf
--- /dev/null
+++ b/deps/ntlmclient/unicode_builtin.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) Edward Thomson. All rights reserved.
+ *
+ * This file is part of ntlmclient, distributed under the MIT license.
+ * For full terms and copyright information, and for third-party
+ * copyright information, see the included LICENSE.txt file.
+ */
+
+#ifndef PRIVATE_UNICODE_BUILTIN_H__
+#define PRIVATE_UNICODE_BUILTIN_H__
+
+#include <locale.h>
+#include <iconv.h>
+
+#include "ntlmclient.h"
+
+struct ntlm_unicode_ctx {
+};
+
+#endif /* PRIVATE_UNICODE_BUILTIN_H__ */
diff --git a/deps/ntlmclient/unicode_iconv.c b/deps/ntlmclient/unicode_iconv.c
index d1fe07e26..e14da21f5 100644
--- a/deps/ntlmclient/unicode_iconv.c
+++ b/deps/ntlmclient/unicode_iconv.c
@@ -16,43 +16,23 @@
#include "ntlm.h"
#include "compat.h"
-struct ntlm_unicode_ctx {
- ntlm_client *ntlm;
- iconv_t utf8_to_16;
- iconv_t utf16_to_8;
-};
-
-ntlm_unicode_ctx *ntlm_unicode_ctx_init(ntlm_client *ntlm)
-{
- ntlm_unicode_ctx *ctx;
-
- if ((ctx = calloc(1, sizeof(ntlm_unicode_ctx))) == NULL)
- return NULL;
-
- ctx->ntlm = ntlm;
- ctx->utf8_to_16 = (iconv_t)-1;
- ctx->utf16_to_8 = (iconv_t)-1;
-
- return ctx;
-}
-
typedef enum {
unicode_iconv_utf8_to_16,
unicode_iconv_utf16_to_8
} unicode_iconv_encoding_direction;
-static inline bool unicode_iconv_init(ntlm_unicode_ctx *ctx)
+bool ntlm_unicode_init(ntlm_client *ntlm)
{
- if (ctx->utf8_to_16 != (iconv_t)-1 || ctx->utf16_to_8 != (iconv_t)-1)
- return true;
+ ntlm->unicode_ctx.utf8_to_16 = iconv_open("UTF-16LE", "UTF-8");
+ ntlm->unicode_ctx.utf16_to_8 = iconv_open("UTF-8", "UTF-16LE");
- if ((ctx->utf8_to_16 = iconv_open("UTF-16LE", "UTF-8")) == (iconv_t)-1 ||
- (ctx->utf16_to_8 = iconv_open("UTF-8", "UTF-16LE")) == (iconv_t)-1) {
+ if (ntlm->unicode_ctx.utf8_to_16 == (iconv_t)-1 ||
+ ntlm->unicode_ctx.utf16_to_8 == (iconv_t)-1) {
if (errno == EINVAL)
- ntlm_client_set_errmsg(ctx->ntlm,
+ ntlm_client_set_errmsg(ntlm,
"iconv does not support UTF8 <-> UTF16 conversion");
else
- ntlm_client_set_errmsg(ctx->ntlm, strerror(errno));
+ ntlm_client_set_errmsg(ntlm, strerror(errno));
return false;
}
@@ -63,7 +43,7 @@ static inline bool unicode_iconv_init(ntlm_unicode_ctx *ctx)
static inline bool unicode_iconv_encoding_convert(
char **converted,
size_t *converted_len,
- ntlm_unicode_ctx *ctx,
+ ntlm_client *ntlm,
const char *string,
size_t string_len,
unicode_iconv_encoding_direction direction)
@@ -75,9 +55,6 @@ static inline bool unicode_iconv_encoding_convert(
*converted = NULL;
*converted_len = 0;
- if (!unicode_iconv_init(ctx))
- return false;
-
/*
* When translating UTF8 to UTF16, these strings are only used
* internally, and we obey the given length, so we can simply
@@ -86,11 +63,11 @@ static inline bool unicode_iconv_encoding_convert(
* terminate and expect an extra byte for UTF8, two for UTF16.
*/
if (direction == unicode_iconv_utf8_to_16) {
- converter = ctx->utf8_to_16;
+ converter = ntlm->unicode_ctx.utf8_to_16;
out_size = (string_len * 2) + 2;
nul_size = 2;
} else {
- converter = ctx->utf16_to_8;
+ converter = ntlm->unicode_ctx.utf16_to_8;
out_size = (string_len / 2) + 1;
nul_size = 1;
}
@@ -99,7 +76,7 @@ static inline bool unicode_iconv_encoding_convert(
out_size = (out_size + 7) & ~7;
if ((out = malloc(out_size)) == NULL) {
- ntlm_client_set_errmsg(ctx->ntlm, "out of memory");
+ ntlm_client_set_errmsg(ntlm, "out of memory");
return false;
}
@@ -117,7 +94,7 @@ static inline bool unicode_iconv_encoding_convert(
break;
if (ret == (size_t)-1 && errno != E2BIG) {
- ntlm_client_set_errmsg(ctx->ntlm, strerror(errno));
+ ntlm_client_set_errmsg(ntlm, strerror(errno));
goto on_error;
}
@@ -125,13 +102,12 @@ static inline bool unicode_iconv_encoding_convert(
out_size = ((((out_size << 1) - (out_size >> 1)) + 7) & ~7);
if (out_size > NTLM_UNICODE_MAX_LEN) {
- ntlm_client_set_errmsg(ctx->ntlm,
- "unicode conversion too large");
+ ntlm_client_set_errmsg(ntlm, "unicode conversion too large");
goto on_error;
}
if ((new_out = realloc(out, out_size)) == NULL) {
- ntlm_client_set_errmsg(ctx->ntlm, "out of memory");
+ ntlm_client_set_errmsg(ntlm, "out of memory");
goto on_error;
}
@@ -139,7 +115,7 @@ static inline bool unicode_iconv_encoding_convert(
}
if (in_start_len != 0) {
- ntlm_client_set_errmsg(ctx->ntlm,
+ ntlm_client_set_errmsg(ntlm,
"invalid unicode string; trailing data remains");
goto on_error;
}
@@ -165,37 +141,37 @@ on_error:
bool ntlm_unicode_utf8_to_16(
char **converted,
size_t *converted_len,
- ntlm_unicode_ctx *ctx,
+ ntlm_client *ntlm,
const char *string,
size_t string_len)
{
return unicode_iconv_encoding_convert(
- converted, converted_len, ctx, string, string_len,
+ converted, converted_len, ntlm, string, string_len,
unicode_iconv_utf8_to_16);
}
bool ntlm_unicode_utf16_to_8(
char **converted,
size_t *converted_len,
- ntlm_unicode_ctx *ctx,
+ ntlm_client *ntlm,
const char *string,
size_t string_len)
{
return unicode_iconv_encoding_convert(
- converted, converted_len, ctx, string, string_len,
+ converted, converted_len, ntlm, string, string_len,
unicode_iconv_utf16_to_8);
}
-void ntlm_unicode_ctx_free(ntlm_unicode_ctx *ctx)
+void ntlm_unicode_shutdown(ntlm_client *ntlm)
{
- if (!ctx)
- return;
-
- if (ctx->utf16_to_8 != (iconv_t)-1)
- iconv_close(ctx->utf16_to_8);
+ if (ntlm->unicode_ctx.utf16_to_8 != (iconv_t)0 &&
+ ntlm->unicode_ctx.utf16_to_8 != (iconv_t)-1)
+ iconv_close(ntlm->unicode_ctx.utf16_to_8);
- if (ctx->utf8_to_16 != (iconv_t)-1)
- iconv_close(ctx->utf8_to_16);
+ if (ntlm->unicode_ctx.utf8_to_16 != (iconv_t)0 &&
+ ntlm->unicode_ctx.utf8_to_16 != (iconv_t)-1)
+ iconv_close(ntlm->unicode_ctx.utf8_to_16);
- free(ctx);
+ ntlm->unicode_ctx.utf8_to_16 = (iconv_t)-1;
+ ntlm->unicode_ctx.utf16_to_8 = (iconv_t)-1;
}
diff --git a/deps/ntlmclient/unicode_iconv.h b/deps/ntlmclient/unicode_iconv.h
new file mode 100644
index 000000000..87a96a67d
--- /dev/null
+++ b/deps/ntlmclient/unicode_iconv.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) Edward Thomson. All rights reserved.
+ *
+ * This file is part of ntlmclient, distributed under the MIT license.
+ * For full terms and copyright information, and for third-party
+ * copyright information, see the included LICENSE.txt file.
+ */
+
+#ifndef PRIVATE_UNICODE_ICONV_H__
+#define PRIVATE_UNICODE_ICONV_H__
+
+#include <locale.h>
+#include <iconv.h>
+
+#include "ntlmclient.h"
+
+struct ntlm_unicode_ctx {
+ iconv_t utf8_to_16;
+ iconv_t utf16_to_8;
+};
+
+#endif /* PRIVATE_UNICODE_ICONV_H__ */
diff --git a/deps/ntlmclient/util.c b/deps/ntlmclient/util.c
index d0e3e53be..07d10f6c6 100644
--- a/deps/ntlmclient/util.c
+++ b/deps/ntlmclient/util.c
@@ -8,14 +8,28 @@
#include <stdlib.h>
#include <stdint.h>
+#include <arpa/inet.h>
#include "compat.h"
#include "util.h"
-void memzero(void *data, size_t size)
+void ntlm_memzero(void *data, size_t size)
{
volatile uint8_t *scan = (volatile uint8_t *)data;
while (size--)
*scan++ = 0x0;
}
+
+uint64_t ntlm_htonll(uint64_t value)
+{
+ static union {
+ uint32_t i;
+ char c[8];
+ } test = { 0x01020304 };
+
+ if (test.c[0] == 0x01)
+ return value;
+ else
+ return ((uint64_t)htonl(value) << 32) | htonl((uint64_t)value >> 32);
+}
diff --git a/deps/ntlmclient/util.h b/deps/ntlmclient/util.h
index 1c1806ba3..d4bb472cc 100644
--- a/deps/ntlmclient/util.h
+++ b/deps/ntlmclient/util.h
@@ -9,6 +9,7 @@
#ifndef PRIVATE_UTIL_H__
#define PRIVATE_UTIL_H__
-extern void memzero(void *data, size_t size);
+extern void ntlm_memzero(void *data, size_t size);
+extern uint64_t ntlm_htonll(uint64_t value);
#endif /* PRIVATE_UTIL_H__ */
diff --git a/deps/pcre/LICENCE b/deps/pcre/LICENCE
new file mode 100644
index 000000000..57a544814
--- /dev/null
+++ b/deps/pcre/LICENCE
@@ -0,0 +1,93 @@
+PCRE LICENCE
+------------
+
+PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
+specified below. The documentation for PCRE, supplied in the "doc"
+directory, is distributed under the same terms as the software itself. The data
+in the testdata directory is not copyrighted and is in the public domain.
+
+The basic library functions are written in C and are freestanding. Also
+included in the distribution is a set of C++ wrapper functions, and a
+just-in-time compiler that can be used to optimize pattern matching. These
+are both optional features that can be omitted when the library is built.
+
+
+THE BASIC LIBRARY FUNCTIONS
+---------------------------
+
+Written by: Philip Hazel
+Email local part: ph10
+Email domain: cam.ac.uk
+
+University of Cambridge Computing Service,
+Cambridge, England.
+
+Copyright (c) 1997-2020 University of Cambridge
+All rights reserved.
+
+
+PCRE JUST-IN-TIME COMPILATION SUPPORT
+-------------------------------------
+
+Written by: Zoltan Herczeg
+Email local part: hzmester
+Email domain: freemail.hu
+
+Copyright(c) 2010-2020 Zoltan Herczeg
+All rights reserved.
+
+
+STACK-LESS JUST-IN-TIME COMPILER
+--------------------------------
+
+Written by: Zoltan Herczeg
+Email local part: hzmester
+Email domain: freemail.hu
+
+Copyright(c) 2009-2020 Zoltan Herczeg
+All rights reserved.
+
+
+THE C++ WRAPPER FUNCTIONS
+-------------------------
+
+Contributed by: Google Inc.
+
+Copyright (c) 2007-2012, Google Inc.
+All rights reserved.
+
+
+THE "BSD" LICENCE
+-----------------
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the name of Google
+ Inc. nor the names of their contributors may be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+End
diff --git a/deps/pcre/pcre.h b/deps/pcre/pcre.h
index 15592b9e5..5b147b9f8 100644
--- a/deps/pcre/pcre.h
+++ b/deps/pcre/pcre.h
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE_MAJOR 8
-#define PCRE_MINOR 42
+#define PCRE_MINOR 44
#define PCRE_PRERELEASE
-#define PCRE_DATE 2018-03-20
+#define PCRE_DATE 2020-02-12
#define PCRE_EXP_DECL extern
diff --git a/deps/pcre/pcre_compile.c b/deps/pcre/pcre_compile.c
index 02de494b1..a3f20fd35 100644
--- a/deps/pcre/pcre_compile.c
+++ b/deps/pcre/pcre_compile.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2016 University of Cambridge
+ Copyright (c) 1997-2020 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -68,7 +68,7 @@ COMPILE_PCREx macro will already be appropriately set. */
/* Macro for setting individual bits in class bitmaps. */
-#define SETBIT(a,b) a[(b)/8] |= (1 << ((b)&7))
+#define SETBIT(a,b) a[(b)/8] |= (1U << ((b)&7))
/* Maximum length value to check against when making sure that the integer that
holds the compiled pattern length does not overflow. We make it a bit less than
@@ -129,8 +129,8 @@ overrun before it actually does run off the end of the data block. */
/* Private flags added to firstchar and reqchar. */
-#define REQ_CASELESS (1 << 0) /* Indicates caselessness */
-#define REQ_VARY (1 << 1) /* Reqchar followed non-literal item */
+#define REQ_CASELESS (1U << 0) /* Indicates caselessness */
+#define REQ_VARY (1U << 1) /* Reqchar followed non-literal item */
/* Negative values for the firstchar and reqchar flags */
#define REQ_UNSET (-2)
#define REQ_NONE (-1)
@@ -3299,7 +3299,7 @@ for(;;)
if ((*xclass_flags & XCL_MAP) == 0)
{
/* No bits are set for characters < 256. */
- if (list[1] == 0) return TRUE;
+ if (list[1] == 0) return (*xclass_flags & XCL_NOT) == 0;
/* Might be an empty repeat. */
continue;
}
@@ -3611,7 +3611,7 @@ for(;;)
if (chr > 255) break;
class_bitset = (pcre_uint8 *)
((list_ptr == list ? code : base_end) - list_ptr[2]);
- if ((class_bitset[chr >> 3] & (1 << (chr & 7))) != 0) return FALSE;
+ if ((class_bitset[chr >> 3] & (1U << (chr & 7))) != 0) return FALSE;
break;
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
@@ -7135,17 +7135,19 @@ for (;; ptr++)
int n = 0;
ptr++;
while(IS_DIGIT(*ptr))
+ {
n = n * 10 + *ptr++ - CHAR_0;
+ if (n > 255)
+ {
+ *errorcodeptr = ERR38;
+ goto FAILED;
+ }
+ }
if (*ptr != CHAR_RIGHT_PARENTHESIS)
{
*errorcodeptr = ERR39;
goto FAILED;
}
- if (n > 255)
- {
- *errorcodeptr = ERR38;
- goto FAILED;
- }
*code++ = n;
PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */
PUT(code, LINK_SIZE, 0); /* Default length */
@@ -7461,7 +7463,7 @@ for (;; ptr++)
{
open_capitem *oc;
recno = GET2(slot, 0);
- cd->backref_map |= (recno < 32)? (1 << recno) : 1;
+ cd->backref_map |= (recno < 32)? (1U << recno) : 1;
if (recno > cd->top_backref) cd->top_backref = recno;
/* Check to see if this back reference is recursive, that it, it
@@ -7647,6 +7649,8 @@ for (;; ptr++)
/* Can't determine a first byte now */
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ zerofirstchar = firstchar;
+ zerofirstcharflags = firstcharflags;
continue;
@@ -8070,7 +8074,7 @@ for (;; ptr++)
item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
PUT2INC(code, 0, recno);
- cd->backref_map |= (recno < 32)? (1 << recno) : 1;
+ cd->backref_map |= (recno < 32)? (1U << recno) : 1;
if (recno > cd->top_backref) cd->top_backref = recno;
/* Check to see if this back reference is recursive, that it, it
@@ -8683,14 +8687,22 @@ do {
op == OP_SCBRA || op == OP_SCBRAPOS)
{
int n = GET2(scode, 1+LINK_SIZE);
- int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
+ int new_map = bracket_map | ((n < 32)? (1U << n) : 1);
if (!is_anchored(scode, new_map, cd, atomcount)) return FALSE;
}
- /* Positive forward assertions and conditions */
+ /* Positive forward assertion */
+
+ else if (op == OP_ASSERT)
+ {
+ if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE;
+ }
+
+ /* Condition; not anchored if no second branch */
- else if (op == OP_ASSERT || op == OP_COND)
+ else if (op == OP_COND)
{
+ if (scode[GET(scode,1)] != OP_ALT) return FALSE;
if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE;
}
@@ -8803,7 +8815,7 @@ do {
op == OP_SCBRA || op == OP_SCBRAPOS)
{
int n = GET2(scode, 1+LINK_SIZE);
- int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
+ int new_map = bracket_map | ((n < 32)? (1U << n) : 1);
if (!is_startline(scode, new_map, cd, atomcount, inassert)) return FALSE;
}
diff --git a/deps/pcre/pcre_jit_compile.c b/deps/pcre/pcre_jit_compile.c
index 2bad74b02..4dcf8fc21 100644
--- a/deps/pcre/pcre_jit_compile.c
+++ b/deps/pcre/pcre_jit_compile.c
@@ -3938,10 +3938,10 @@ static sljit_s32 character_to_int32(pcre_uchar chr)
sljit_s32 value = (sljit_s32)chr;
#if defined COMPILE_PCRE8
#define SSE2_COMPARE_TYPE_INDEX 0
-return (value << 24) | (value << 16) | (value << 8) | value;
+return ((unsigned int)value << 24) | ((unsigned int)value << 16) | ((unsigned int)value << 8) | (unsigned int)value;
#elif defined COMPILE_PCRE16
#define SSE2_COMPARE_TYPE_INDEX 1
-return (value << 16) | value;
+return ((unsigned int)value << 16) | value;
#elif defined COMPILE_PCRE32
#define SSE2_COMPARE_TYPE_INDEX 2
return value;
@@ -8507,7 +8507,7 @@ if (opcode == OP_ONCE)
/* We temporarily encode the needs_control_head in the lowest bit.
Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns
the same value for small signed numbers (including negative numbers). */
- BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
+ BACKTRACK_AS(bracket_backtrack)->u.framesize = ((unsigned int)BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
}
return cc + repeat_length;
}
@@ -9002,7 +9002,7 @@ if (exact > 1)
#ifdef SUPPORT_UTF
&& !common->utf
#endif
- )
+ && type != OP_ANYNL && type != OP_EXTUNI)
{
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));
add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0));
diff --git a/deps/pcre/pcreposix.c b/deps/pcre/pcreposix.c
index 77dbddb66..f9e423b31 100644
--- a/deps/pcre/pcreposix.c
+++ b/deps/pcre/pcreposix.c
@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2018 University of Cambridge
+ Copyright (c) 1997-2020 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -287,6 +287,7 @@ if (preg->re_pcre == NULL)
(void)pcre_fullinfo((const pcre *)preg->re_pcre, NULL, PCRE_INFO_CAPTURECOUNT,
&re_nsub);
preg->re_nsub = (size_t)re_nsub;
+preg->re_erroffset = (size_t)(-1); /* No meaning after successful compile */
return 0;
}
@@ -324,8 +325,6 @@ if ((eflags & PCRE_REG_NOTBOL) != 0) options |= PCRE_NOTBOL;
if ((eflags & PCRE_REG_NOTEOL) != 0) options |= PCRE_NOTEOL;
if ((eflags & PCRE_REG_NOTEMPTY) != 0) options |= PCRE_NOTEMPTY;
-((pcre_regex_t *)preg)->re_erroffset = (size_t)(-1); /* Only has meaning after compile */
-
/* When no string data is being returned, or no vector has been passed in which
to put it, ensure that nmatch is zero. Otherwise, ensure the vector for holding
the return data is large enough. */
diff --git a/deps/zlib/deflate.c b/deps/zlib/deflate.c
index 1ec761448..8d44869e6 100644
--- a/deps/zlib/deflate.c
+++ b/deps/zlib/deflate.c
@@ -320,6 +320,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ memset(s->prev, 0, s->w_size * sizeof(Pos));
s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
s->high_water = 0; /* nothing written to s->window yet */
diff --git a/docs/changelog.md b/docs/changelog.md
index 97cf94c6b..8060874df 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,3 +1,326 @@
+v1.3
+----
+
+This is release v1.3.0, "Zugunruhe". This release includes only minor new features that will be helpful for users to have an orderly transition to the v2.0 lineage.
+
+## New Features
+* Support custom git extensions by @ethomson in https://github.com/libgit2/libgit2/pull/6031
+* Introduce `git_email_create`; deprecate `git_diff_format_email` by @ethomson in https://github.com/libgit2/libgit2/pull/6061
+
+## Deprecated APIs
+* `git_oidarray_free` is deprecated; callers should use `git_oidarray_dispose`
+
+## Bug fixes
+* #6028: Check if `threadstate->error_t.message` is not `git_buf__initbuf` before freeing. by @arroz in https://github.com/libgit2/libgit2/pull/6029
+* remote: Mark `git_remote_name_is_valid` as `GIT_EXTERN` by @lhchavez in https://github.com/libgit2/libgit2/pull/6032
+* Fix config parsing for multiline with multiple quoted comment chars by @basile-henry in https://github.com/libgit2/libgit2/pull/6043
+* indexer: Avoid one `mmap(2)`/`munmap(2)` pair per `git_indexer_append` call by @lhchavez in https://github.com/libgit2/libgit2/pull/6039
+* merge: Check file mode when resolving renames by @ccstolley in https://github.com/libgit2/libgit2/pull/6060
+* Allow proxy options when connecting with a detached remote. by @lrm29 in https://github.com/libgit2/libgit2/pull/6058
+* win32: allow empty environment variables by @ethomson in https://github.com/libgit2/libgit2/pull/6063
+* Fixes for deprecated APIs by @ethomson in https://github.com/libgit2/libgit2/pull/6066
+* filter: use a `git_oid` in filter options, not a pointer by @ethomson in https://github.com/libgit2/libgit2/pull/6067
+* diff: update `GIT_DIFF_IGNORE_BLANK_LINES` by @ethomson in https://github.com/libgit2/libgit2/pull/6068
+* Attribute lookups are always on relative paths by @ethomson in https://github.com/libgit2/libgit2/pull/6073
+* Handle long paths when querying attributes by @ethomson in https://github.com/libgit2/libgit2/pull/6075
+
+## Code cleanups
+* notes: use a buffer internally by @ethomson in https://github.com/libgit2/libgit2/pull/6047
+* Fix coding style for pointer by @punkymaniac in https://github.com/libgit2/libgit2/pull/6045
+* Use __typeof__ GNUC keyword for ISO C compatibility by @duncanthomson in https://github.com/libgit2/libgit2/pull/6041
+* Discover libssh2 without pkg-config by @stac47 in https://github.com/libgit2/libgit2/pull/6053
+* Longpath filter bug by @lrm29 in https://github.com/libgit2/libgit2/pull/6055
+* Add test to ensure empty proxy env behaves like unset env by @sathieu in https://github.com/libgit2/libgit2/pull/6052
+* Stdint header condition has been reverted. by @lolgear in https://github.com/libgit2/libgit2/pull/6020
+* buf: `common_prefix` takes a string array by @ethomson in https://github.com/libgit2/libgit2/pull/6077
+* oidarray: introduce `git_oidarray_dispose` by @ethomson in https://github.com/libgit2/libgit2/pull/6076
+* examples: Free the git_config and git_config_entry after use by @257 in https://github.com/libgit2/libgit2/pull/6071
+
+## CI Improvements
+* ci: pull libssh2 from www.libssh2.org by @ethomson in https://github.com/libgit2/libgit2/pull/6064
+
+## Documentation changes
+* Update README.md by @shijinglu in https://github.com/libgit2/libgit2/pull/6050
+
+## New Contributors
+* @basile-henry made their first contribution in https://github.com/libgit2/libgit2/pull/6043
+* @duncanthomson made their first contribution in https://github.com/libgit2/libgit2/pull/6041
+* @stac47 made their first contribution in https://github.com/libgit2/libgit2/pull/6053
+* @shijinglu made their first contribution in https://github.com/libgit2/libgit2/pull/6050
+* @ccstolley made their first contribution in https://github.com/libgit2/libgit2/pull/6060
+* @sathieu made their first contribution in https://github.com/libgit2/libgit2/pull/6052
+* @257 made their first contribution in https://github.com/libgit2/libgit2/pull/6071
+
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.2.0...v1.3.0
+
+---------------------------------------------------------------------
+
+v1.2
+-----
+
+This is release v1.2.0, "Absacker". This release includes many new features: in particular, support for commit graphs, multi-pack indexes, and `core.longpaths` support.
+
+This is meant to be the final minor release in the v1 lineage. v2.0 will be the next major release and will remove deprecated APIs and may include breaking changes.
+
+## Deprecated APIs
+
+* revspec: rename git_revparse_mode_t to git_revspec_t by @ethomson in https://github.com/libgit2/libgit2/pull/5786
+* tree: deprecate `git_treebuilder_write_with_buffer` by @ethomson in https://github.com/libgit2/libgit2/pull/5815
+* Deprecate `is_valid_name` functions; replace with `name_is_valid` functions by @ethomson in https://github.com/libgit2/libgit2/pull/5659
+* filter: stop taking git_buf as user input by @ethomson in https://github.com/libgit2/libgit2/pull/5859
+* remote: introduce remote_ready_cb, deprecate resolve_url callback by @ethomson in https://github.com/libgit2/libgit2/pull/6012
+* Introduce `create_commit_cb`, deprecate `signing_cb` by @ethomson in https://github.com/libgit2/libgit2/pull/6016
+* filter: filter drivers stop taking git_buf as user input by @ethomson in https://github.com/libgit2/libgit2/pull/6011
+* buf: deprecate public git_buf writing functions by @ethomson in https://github.com/libgit2/libgit2/pull/6017
+
+## New features
+
+* winhttp: support optional client cert by @ianhattendorf in https://github.com/libgit2/libgit2/pull/5384
+* Add support for additional SSH hostkey types. by @arroz in https://github.com/libgit2/libgit2/pull/5750
+* Handle ipv6 addresses by @ethomson in https://github.com/libgit2/libgit2/pull/5741
+* zlib: Add support for building with Chromium's zlib implementation by @lhchavez in https://github.com/libgit2/libgit2/pull/5748
+* commit-graph: Introduce a parser for commit-graph files by @lhchavez in https://github.com/libgit2/libgit2/pull/5762
+* patch: add owner accessor by @KOLANICH in https://github.com/libgit2/libgit2/pull/5731
+* commit-graph: Support lookups of entries in a commit-graph by @lhchavez in https://github.com/libgit2/libgit2/pull/5763
+* commit-graph: Introduce `git_commit_graph_needs_refresh()` by @lhchavez in https://github.com/libgit2/libgit2/pull/5764
+* Working directory path validation by @ethomson in https://github.com/libgit2/libgit2/pull/5823
+* Support `core.longpaths` on Windows by @ethomson in https://github.com/libgit2/libgit2/pull/5857
+* git_reference_create_matching: Treat all-zero OID as "must be absent" by @novalis in https://github.com/libgit2/libgit2/pull/5842
+* diff:add option to ignore blank line changes by @yuuri in https://github.com/libgit2/libgit2/pull/5853
+* [Submodule] Git submodule dup by @lolgear in https://github.com/libgit2/libgit2/pull/5890
+* commit-graph: Use the commit-graph in revwalks by @lhchavez in https://github.com/libgit2/libgit2/pull/5765
+* commit-graph: Introduce `git_commit_list_generation_cmp` by @lhchavez in https://github.com/libgit2/libgit2/pull/5766
+* graph: Create `git_graph_reachable_from_any()` by @lhchavez in https://github.com/libgit2/libgit2/pull/5767
+* Support reading attributes from a specific commit by @ethomson in https://github.com/libgit2/libgit2/pull/5952
+* [Branch] Branch upstream with format by @lolgear in https://github.com/libgit2/libgit2/pull/5861
+* Dynamically load OpenSSL (optionally) by @ethomson in https://github.com/libgit2/libgit2/pull/5974
+* Set refs/remotes/origin/HEAD to default branch when branch is specified by @A-Ovchinnikov-mx in https://github.com/libgit2/libgit2/pull/6010
+* midx: Add a way to write multi-pack-index files by @lhchavez in https://github.com/libgit2/libgit2/pull/5404
+* Use error code GIT_EAUTH for authentication failures by @josharian in https://github.com/libgit2/libgit2/pull/5395
+* midx: Introduce git_odb_write_multi_pack_index() by @lhchavez in https://github.com/libgit2/libgit2/pull/5405
+* Checkout dry-run by @J0Nes90 in https://github.com/libgit2/libgit2/pull/5841
+* mbedTLS: Fix setting certificate directory by @mikezackles in https://github.com/libgit2/libgit2/pull/6004
+* remote: introduce remote_ready_cb, deprecate resolve_url callback by @ethomson in https://github.com/libgit2/libgit2/pull/6012
+* Introduce `create_commit_cb`, deprecate `signing_cb` by @ethomson in https://github.com/libgit2/libgit2/pull/6016
+* commit-graph: Add a way to write commit-graph files by @lhchavez in https://github.com/libgit2/libgit2/pull/5778
+
+## Bug fixes
+
+* Define `git___load` when building with `-DTHREADSAFE=OFF` by @lhchavez in https://github.com/libgit2/libgit2/pull/5664
+* Make the Windows leak detection more robust by @lhchavez in https://github.com/libgit2/libgit2/pull/5661
+* Refactor "global" state by @ethomson in https://github.com/libgit2/libgit2/pull/5546
+* threadstate: rename tlsdata when building w/o threads by @ethomson in https://github.com/libgit2/libgit2/pull/5668
+* Include `${MBEDTLS_INCLUDE_DIR}` when compiling `crypt_mbedtls.c` by @staticfloat in https://github.com/libgit2/libgit2/pull/5685
+* Fix the `-DTHREADSAFE=OFF` build by @lhchavez in https://github.com/libgit2/libgit2/pull/5690
+* Add missing worktree_dir check and test case by @rbmclean in https://github.com/libgit2/libgit2/pull/5692
+* msvc crtdbg -> win32 leakcheck by @ethomson in https://github.com/libgit2/libgit2/pull/5580
+* Introduce GIT_ASSERT macros by @ethomson in https://github.com/libgit2/libgit2/pull/5327
+* Also add the raw hostkey to `git_cert_hostkey` by @lhchavez in https://github.com/libgit2/libgit2/pull/5704
+* Make the odb race-free by @lhchavez in https://github.com/libgit2/libgit2/pull/5595
+* Make the pack and mwindow implementations data-race-free by @lhchavez in https://github.com/libgit2/libgit2/pull/5593
+* Thread-free implementation by @ethomson in https://github.com/libgit2/libgit2/pull/5719
+* Thread-local storage: a generic internal library (with no allocations) by @ethomson in https://github.com/libgit2/libgit2/pull/5720
+* Friendlier getting started in the lack of git_libgit2_init by @ethomson in https://github.com/libgit2/libgit2/pull/5578
+* Make git__strntol64() ~70%* faster by @lhchavez in https://github.com/libgit2/libgit2/pull/5735
+* Cache the parsed submodule config when diffing by @lhchavez in https://github.com/libgit2/libgit2/pull/5727
+* pack: continue zlib while we can make progress by @ethomson in https://github.com/libgit2/libgit2/pull/5740
+* Avoid using `__builtin_mul_overflow` with the clang+32-bit combo by @lhchavez in https://github.com/libgit2/libgit2/pull/5742
+* repository: use intptr_t's in the config map cache by @ethomson in https://github.com/libgit2/libgit2/pull/5746
+* Build with NO_MMAP by @0xdky in https://github.com/libgit2/libgit2/pull/5583
+* Add documentation for git_blob_filter_options.version by @JoshuaS3 in https://github.com/libgit2/libgit2/pull/5759
+* blob: fix name of `GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD` by @ethomson in https://github.com/libgit2/libgit2/pull/5760
+* Cope with empty default branch by @ethomson in https://github.com/libgit2/libgit2/pull/5770
+* README: instructions for using libgit2 without compiling by @ethomson in https://github.com/libgit2/libgit2/pull/5772
+* Use `p_pwrite`/`p_pread` consistently throughout the codebase by @lhchavez in https://github.com/libgit2/libgit2/pull/5769
+* midx: Fix a bug in `git_midx_needs_refresh()` by @lhchavez in https://github.com/libgit2/libgit2/pull/5768
+* mwindow: Fix a bug in the LRU window finding code by @lhchavez in https://github.com/libgit2/libgit2/pull/5783
+* refdb_fs: Check git_sortedcache wlock/rlock errors by @mamapanda in https://github.com/libgit2/libgit2/pull/5800
+* index: Check git_vector_dup error in write_entries by @mamapanda in https://github.com/libgit2/libgit2/pull/5801
+* Fix documentation formating on repository.h by @punkymaniac in https://github.com/libgit2/libgit2/pull/5806
+* include: fix typos in comments by @tniessen in https://github.com/libgit2/libgit2/pull/5805
+* Fix some typos by @aaronfranke in https://github.com/libgit2/libgit2/pull/5797
+* Check git_signature_dup failure by @mamapanda in https://github.com/libgit2/libgit2/pull/5817
+* merge: Check insert_head_ids error in create_virtual_base by @mamapanda in https://github.com/libgit2/libgit2/pull/5818
+* winhttp: skip certificate check if unable to send request by @ianhattendorf in https://github.com/libgit2/libgit2/pull/5814
+* Default to GIT_BRANCH_DEFAULT if init.defaultBranch is empty string by @ianhattendorf in https://github.com/libgit2/libgit2/pull/5832
+* Fix diff_entrycount -> diff_num_deltas doc typo by @mjsir911 in https://github.com/libgit2/libgit2/pull/5838
+* repo: specify init.defaultbranch is meant to be a branch name by @carlosmn in https://github.com/libgit2/libgit2/pull/5835
+* repo: remove an inappropriate use of PASSTHROUGH by @carlosmn in https://github.com/libgit2/libgit2/pull/5834
+* src: fix typos in header files by @tniessen in https://github.com/libgit2/libgit2/pull/5843
+* test: clean up memory leaks by @ethomson in https://github.com/libgit2/libgit2/pull/5858
+* buf: remove unnecessary buf_text namespace by @ethomson in https://github.com/libgit2/libgit2/pull/5860
+* Fix bug in git_diff_find_similar. by @staktrace in https://github.com/libgit2/libgit2/pull/5839
+* Fix issues with Proxy Authentication after httpclient refactor by @implausible in https://github.com/libgit2/libgit2/pull/5852
+* tests: clean up memory leak, fail on leak for win32 by @ethomson in https://github.com/libgit2/libgit2/pull/5892
+* Tolerate readlink size less than st_size by @dtolnay in https://github.com/libgit2/libgit2/pull/5900
+* Define WINHTTP_NO_CLIENT_CERT_CONTEXT if needed by @jacquesg in https://github.com/libgit2/libgit2/pull/5929
+* Update from regex to pcre licensing information in docs/contributing.md by @boretrk in https://github.com/libgit2/libgit2/pull/5916
+* Consider files executable only if the user can execute them by @novalis in https://github.com/libgit2/libgit2/pull/5915
+* git__timer: Limit ITimer usage to AmigaOS4 by @boretrk in https://github.com/libgit2/libgit2/pull/5936
+* Fix memory leak in git_smart__connect by @punkymaniac in https://github.com/libgit2/libgit2/pull/5908
+* config: fix included configs not refreshed more than once by @Batchyx in https://github.com/libgit2/libgit2/pull/5926
+* Fix wrong time_t used in function by @NattyNarwhal in https://github.com/libgit2/libgit2/pull/5938
+* fix check for ignoring of negate rules by @palmin in https://github.com/libgit2/libgit2/pull/5824
+* Make `FIND_PACKAGE(PythonInterp)` prefer `python3` by @lhchavez in https://github.com/libgit2/libgit2/pull/5913
+* git__timer: Allow compilation on systems without CLOCK_MONOTONIC by @boretrk in https://github.com/libgit2/libgit2/pull/5945
+* stdintification: use int64_t and INT64_C instead of long long by @NattyNarwhal in https://github.com/libgit2/libgit2/pull/5941
+* Optional stricter allocation checking (for `malloc(0)` cases) by @ethomson in https://github.com/libgit2/libgit2/pull/5951
+* Variadic arguments aren't in C89 by @NattyNarwhal in https://github.com/libgit2/libgit2/pull/5948
+* Fix typo in general.c by @Crayon2000 in https://github.com/libgit2/libgit2/pull/5954
+* common.h: use inline when compiling for C99 and later by @boretrk in https://github.com/libgit2/libgit2/pull/5953
+* Fix one memory leak in master by @lhchavez in https://github.com/libgit2/libgit2/pull/5957
+* tests: reset odb backend priority by @ethomson in https://github.com/libgit2/libgit2/pull/5961
+* cmake: extended futimens checking on macOS by @ethomson in https://github.com/libgit2/libgit2/pull/5962
+* amiga: use ';' as path list separator on AmigaOS by @boretrk in https://github.com/libgit2/libgit2/pull/5978
+* Respect the force flag on refspecs in git_remote_fetch by @alexjg in https://github.com/libgit2/libgit2/pull/5854
+* Fix LIBGIT2_FILENAME not being passed to the resource compiler by @jairbubbles in https://github.com/libgit2/libgit2/pull/5994
+* sha1dc: remove conditional for <sys/types.h> by @boretrk in https://github.com/libgit2/libgit2/pull/5997
+* openssl: don't fail when we can't customize allocators by @ethomson in https://github.com/libgit2/libgit2/pull/5999
+* C11 warnings by @boretrk in https://github.com/libgit2/libgit2/pull/6005
+* open: input validation for empty segments in path by @boretrk in https://github.com/libgit2/libgit2/pull/5950
+* Introduce GIT_WARN_UNUSED_RESULT by @lhchavez in https://github.com/libgit2/libgit2/pull/5802
+* GCC C11 warnings by @boretrk in https://github.com/libgit2/libgit2/pull/6006
+* array: check dereference from void * type by @boretrk in https://github.com/libgit2/libgit2/pull/6007
+* Homogenize semantics for atomic-related functions by @lhchavez in https://github.com/libgit2/libgit2/pull/5747
+* git_array_alloc: return objects of correct type by @boretrk in https://github.com/libgit2/libgit2/pull/6008
+* CMake. hash sha1 header has been added. by @lolgear in https://github.com/libgit2/libgit2/pull/6013
+* tests: change comments to c89 style by @boretrk in https://github.com/libgit2/libgit2/pull/6015
+* Set Host Header to match CONNECT authority target by @lollipopman in https://github.com/libgit2/libgit2/pull/6022
+* Fix worktree iteration when repository has no common directory by @kcsaul in https://github.com/libgit2/libgit2/pull/5943
+
+## Documentation improvements
+
+* Update README.md for additional Delphi bindings by @todaysoftware in https://github.com/libgit2/libgit2/pull/5831
+* Fix documentation formatting by @punkymaniac in https://github.com/libgit2/libgit2/pull/5850
+* docs: fix incorrect comment marker by @tiennou in https://github.com/libgit2/libgit2/pull/5897
+* Patch documentation by @punkymaniac in https://github.com/libgit2/libgit2/pull/5903
+* Fix misleading doc for `git_index_find` by @arxanas in https://github.com/libgit2/libgit2/pull/5910
+* docs: stop mentioning libgit2's "master" branch by @Batchyx in https://github.com/libgit2/libgit2/pull/5925
+* docs: fix some missing includes that cause Docurium to error out by @tiennou in https://github.com/libgit2/libgit2/pull/5917
+* Patch documentation by @punkymaniac in https://github.com/libgit2/libgit2/pull/5940
+
+## Development improvements
+
+* WIP: .devcontainer: settings for a codespace workflow by @ethomson in https://github.com/libgit2/libgit2/pull/5508
+
+## CI Improvements
+
+* Add a ThreadSanitizer build by @lhchavez in https://github.com/libgit2/libgit2/pull/5597
+* ci: more GitHub Actions by @ethomson in https://github.com/libgit2/libgit2/pull/5706
+* ci: run coverity in the nightly builds by @ethomson in https://github.com/libgit2/libgit2/pull/5707
+* ci: only report main branch in README status by @ethomson in https://github.com/libgit2/libgit2/pull/5708
+* Fix the `ENABLE_WERROR=ON` build in Groovy Gorilla (gcc 10.2) by @lhchavez in https://github.com/libgit2/libgit2/pull/5715
+* Re-enable the RC4 test by @carlosmn in https://github.com/libgit2/libgit2/pull/4418
+* ci: run codeql by @ethomson in https://github.com/libgit2/libgit2/pull/5709
+* github-actions: Also rename the main branch here by @lhchavez in https://github.com/libgit2/libgit2/pull/5771
+* ci: don't use ninja on macOS by @ethomson in https://github.com/libgit2/libgit2/pull/5780
+* ci: use GitHub for storing mingw-w64 build dependency by @ethomson in https://github.com/libgit2/libgit2/pull/5855
+* docker: remove the entrypoint by @ethomson in https://github.com/libgit2/libgit2/pull/5980
+* http: don't require a password by @ethomson in https://github.com/libgit2/libgit2/pull/5972
+* ci: update nightly to use source path by @ethomson in https://github.com/libgit2/libgit2/pull/5989
+* ci: add centos 7 and centos 8 by @ethomson in https://github.com/libgit2/libgit2/pull/5992
+* ci: update centos builds by @ethomson in https://github.com/libgit2/libgit2/pull/5995
+* ci: tag new containers with the latest tag by @ethomson in https://github.com/libgit2/libgit2/pull/6000
+
+## Dependency updates
+
+* ntlm: [ntlmclient](https://github.com/ethomson/ntlmclient) is now v0.9.1
+
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.1.0...v1.2.0
+
+---------------------------------------------------------------------
+
+v1.1
+----
+
+This is release v1.1, "Fernweh".
+
+### Changes or improvements
+
+* Our bundled PCRE dependency has been updated to 8.44.
+
+* The `refs/remotes/origin/HEAD` file will be created at clone time to
+ point to the origin's default branch.
+
+* libgit2 now uses the `__atomic_` intrinsics instead of `__sync_`
+ intrinsics on supported gcc and clang versions.
+
+* The `init.defaultBranch` setting is now respected and `master` is
+ no longer the hardcoded as the default branch name.
+
+* Patch files that do not contain an `index` line can now be parsed.
+
+* Configuration files with multi-line values can now contain quotes
+ split across multiple lines.
+
+* Windows clients now attempt to use TLS1.3 when available.
+
+* Servers that request an upgrade to a newer HTTP version are
+ silently ignored instead of erroneously failing.
+
+* Users can pass `NULL` to the options argument to
+ `git_describe_commit`.
+
+* Clones and fetches of very large packfiles now succeeds on 32-bit
+ platforms.
+
+* Custom reference database backends can now handle the repository's
+ `HEAD` correctly.
+
+* Repositories with a large number of packfiles no longer exhaust the
+ number of file descriptors.
+
+* The test framework now supports TAP output when the `-t` flag is
+ specified.
+
+* The test framework can now specify an exact match to a test
+ function using a trailing `$`.
+
+* All checkout types support `GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH`.
+
+* `git_blame` now can ignore whitespace changes using the option
+ `GIT_BLAME_IGNORE_WHITESPACE`.
+
+* Several new examples have been created, including an examples for
+ commit, add and push.
+
+* Mode changes during rename are now supported in patch application.
+
+* `git_checkout_head` now correctly removes untracked files in a
+ subdirectory when the `FORCE | REMOVE_UNTRACKED` options are specified.
+
+v1.0.1
+------
+
+This is a bugfix release with the following changes:
+
+- Calculating information about renamed files during merges is more
+ efficient because dissimilarity about files is now being cached and
+ no longer needs to be recomputed.
+
+- The `git_worktree_prune_init_options` has been correctly restored for
+ backward compatibility. In v1.0 it was incorrectly deprecated with a
+ typo.
+
+- The optional ntlmclient dependency now supports NetBSD.
+
+- A bug where attempting to stash on a bare repository may have failed
+ has been fixed.
+
+- Configuration files that are unreadable due to permissions are now
+ silently ignored, and treated as if they do not exist. This matches
+ git's behavior; previously this case would have been an error.
+
+- v4 index files are now correctly written; previously we would read
+ them correctly but would not write the prefix-compression accurately,
+ causing corruption.
+
+- A bug where the smart HTTP transport could not read large data packets
+ has been fixed. Previously, fetching from servers like Gerrit, that
+ sent large data packets, would error.
+
+---------------------------------------------------------------------
+
v1.0
----
@@ -401,6 +724,9 @@ with v0.28.0.
The breaking change is that the `username` member of the underlying struct
is now hidden, and a new `git_cred_get_username` function has been provided.
+* Some errors of class `GIT_ERROR_NET` now have class `GIT_ERROR_HTTP`.
+ Most authentication failures now have error code `GIT_EAUTH` instead of `GIT_ERROR`.
+
### Breaking CMake configuration changes
* The CMake option to use a system http-parser library, instead of the
@@ -474,6 +800,8 @@ release:
* Tyler Ang-Wanek
* Tyler Wanek
+---------------------------------------------------------------------
+
v0.28
-----
@@ -622,6 +950,8 @@ v0.28
out such files is not allowed as this can make a Git implementation write
outside of the repository and bypass the fsck checks for CVE-2018-11235.
+---------------------------------------------------------------------
+
v0.27
---------
@@ -738,6 +1068,8 @@ v0.27
`git_odb_backend` interface have changed their signatures to allow providing
the object's size and type to the caller.
+---------------------------------------------------------------------
+
v0.26
-----
@@ -982,6 +1314,8 @@ v0.25
to provide the name of a merge driver to be used to handle files changed
during a merge.
+---------------------------------------------------------------------
+
v0.24
-------
@@ -1097,6 +1431,8 @@ v0.24
* `git_remote_connect()` now takes a `custom_headers` argument to set
the extra HTTP header fields to send.
+---------------------------------------------------------------------
+
v0.23
------
@@ -1396,6 +1732,8 @@ v0.23
* It is no longer allowed to call `git_buf_grow()` on buffers
borrowing the memory they point to.
+---------------------------------------------------------------------
+
v0.22
------
diff --git a/docs/coding-style.md b/docs/coding-style.md
index d5188f0bc..b8b94d69c 100644
--- a/docs/coding-style.md
+++ b/docs/coding-style.md
@@ -172,7 +172,7 @@ tags:
*
* @param s String to froznicate
* @return A newly allocated string or `NULL` in case an error occurred.
- * /
+ */
char *froznicate(const char *s);
```
diff --git a/docs/contributing.md b/docs/contributing.md
index 21e42b1d9..f3e559c9d 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -18,7 +18,7 @@ The bundled dependencies in the `deps` directories are governed
by the following licenses:
- http-parser is licensed under [MIT license](../deps/http-parser/COPYING)
-- regex is governed by [LGPL v2.1+ license](../deps/regex/COPYING)
+- pcre is governed by [BSD license](../deps/pcre/LICENCE)
- winhttp is governed by [LGPL v2.1+](../deps/winhttp/COPYING.LGPL) and [GPL v2 with linking exception](../deps/winhttp/COPYING.GPL)
- zlib is governed by [zlib license](../deps/zlib/COPYING)
@@ -35,7 +35,7 @@ easily accessible permanent record of the conversation.
## Libgit2 Versions
-The `master` branch is the main branch where development happens.
+The `main` branch is the main branch where development happens.
Releases are tagged
(e.g. [v0.21.0](https://github.com/libgit2/libgit2/releases/tag/v0.21.0) )
and when a critical bug fix needs to be backported, it will be done on a
@@ -51,7 +51,7 @@ commit SHA
Using [`git describe`](http://git-scm.com/docs/git-describe) is a
great way to tell us what version you're working with.
-If you're not running against the latest `master` branch version,
+If you're not running against the latest `main` branch version,
please compile and test against that to avoid re-reporting an issue that's
already been fixed.
@@ -68,11 +68,11 @@ flow](https://guides.github.com/introduction/flow/index.html), where
contributors fork the [libgit2 repository](https://github.com/libgit2/libgit2),
make their changes on branch, and submit a
[Pull Request](https://help.github.com/articles/using-pull-requests)
-(a.k.a. "PR"). Pull requests should usually be targeted at the `master`
+(a.k.a. "PR"). Pull requests should usually be targeted at the `main`
branch.
Life will be a lot easier for you (and us) if you follow this pattern
-(i.e. fork, named branch, submit PR). If you use your fork's `master`
+(i.e. fork, named branch, submit PR). If you use your fork's `main`
branch directly, things can get messy.
Please include a nice description of your changes when you submit your PR;
diff --git a/docs/release.md b/docs/release.md
index 22b35ede7..3200c4449 100644
--- a/docs/release.md
+++ b/docs/release.md
@@ -1,6 +1,6 @@
# Releasing the library
-We have three kinds of releases: "full" releases, maintenance releases and security releases. Full ones release the state of the `master` branch whereas maintenance releases provide bugfixes building on top of the currently released series. Security releases are also for the current series but only contain security fixes on top of the previous release.
+We have three kinds of releases: "full" releases, maintenance releases and security releases. Full ones release the state of the `main` branch whereas maintenance releases provide bugfixes building on top of the currently released series. Security releases are also for the current series but only contain security fixes on top of the previous release.
## Full release
@@ -40,7 +40,7 @@ followed by the three sections in the changelog. For release candidates we can a
During the freeze, and certainly after the first release candidate, any bindings the core team work with should be updated in order to discover any issues that might come up with the multitude of approaches to memory management, embedding or linking.
-Create a branch `maint/v0.X` at the current state of `master` after you've created the tag. This will be used for maintenance releases and lets our dependents track the latest state of the series.
+Create a branch `maint/v0.X` at the current state of `main` after you've created the tag. This will be used for maintenance releases and lets our dependents track the latest state of the series.
## Maintenance release
@@ -76,7 +76,7 @@ We use docurium to generate our documentation. It is a tool written in ruby whic
gem install docurium
-and run it against our description file with the tip of master checked out.
+and run it against our description file with the tip of `main` checked out.
cm doc api.docurium
diff --git a/docs/win32-longpaths.md b/docs/win32-longpaths.md
new file mode 100644
index 000000000..a18152fc9
--- /dev/null
+++ b/docs/win32-longpaths.md
@@ -0,0 +1,36 @@
+core.longpaths support
+======================
+
+Historically, Windows has limited absolute path lengths to `MAX_PATH`
+(260) characters.
+
+Unfortunately, 260 characters is a punishing small maximum. This is
+especially true for developers where dependencies may have dependencies
+in a folder, each dependency themselves having dependencies in a
+sub-folder, ad (seemingly) infinitum.
+
+So although the Windows APIs _by default_ honor this 260 character
+maximum, you can get around this by using separate APIs. Git honors a
+`core.longpaths` configuration option that allows some paths on Windows
+to exceed these 260 character limits.
+
+And because they've gone and done it, that means that libgit2 has to
+honor this value, too.
+
+Since `core.longpaths` is a _configuration option_ that means that we
+need to be able to resolve a configuration - including in _the repository
+itself_ in order to know whether long paths should be supported.
+
+Therefore, in libgit2, `core.longpaths` affects paths in working
+directories _only_. Paths to the repository, and to items inside the
+`.git` folder, must be no longer than 260 characters.
+
+This definition is required to avoid a paradoxical setting: if you
+had a repository in a folder that was 280 characters long, how would
+you know whether `core.longpaths` support should be enabled? Even if
+`core.longpaths` was set to true in a system configuration file, the
+repository itself may set `core.longpaths` to false in _its_ configuration
+file, which you could only read if `core.longpaths` were set to true.
+
+Thus, `core.longpaths` must _only_ apply to working directory items,
+and cannot apply to the `.git` folder or its contents.
diff --git a/examples/blame.c b/examples/blame.c
index 49350fc0f..954c97b17 100644
--- a/examples/blame.c
+++ b/examples/blame.c
@@ -54,7 +54,7 @@ int lg2_blame(git_repository *repo, int argc, char *argv[])
*/
if (o.commitspec) {
check_lg2(git_revparse(&revspec, repo, o.commitspec), "Couldn't parse commit spec", NULL);
- if (revspec.flags & GIT_REVPARSE_SINGLE) {
+ if (revspec.flags & GIT_REVSPEC_SINGLE) {
git_oid_cpy(&blameopts.newest_commit, git_object_id(revspec.from));
git_object_free(revspec.from);
} else {
diff --git a/examples/checkout.c b/examples/checkout.c
index 204b58d88..ac7b7422d 100644
--- a/examples/checkout.c
+++ b/examples/checkout.c
@@ -14,7 +14,7 @@
#include "common.h"
-/* Define the printf format specifer to use for size_t output */
+/* Define the printf format specifier to use for size_t output */
#if defined(_MSC_VER) || defined(__MINGW32__)
# define PRIuZ "Iu"
# define PRIxZ "Ix"
diff --git a/examples/common.h b/examples/common.h
index 0126568ab..f86e92c35 100644
--- a/examples/common.h
+++ b/examples/common.h
@@ -36,7 +36,7 @@
#endif
#ifndef PRIuZ
-/* Define the printf format specifer to use for size_t output */
+/* Define the printf format specifier to use for size_t output */
#if defined(_MSC_VER) || defined(__MINGW32__)
# define PRIuZ "Iu"
#else
diff --git a/examples/config.c b/examples/config.c
index f7fa70e4d..6e14ce8c8 100644
--- a/examples/config.c
+++ b/examples/config.c
@@ -26,6 +26,10 @@ static int config_get(git_config *cfg, const char *key)
}
puts(entry->value);
+
+ /* Free the git_config_entry after use with `git_config_entry_free()`. */
+ git_config_entry_free(entry);
+
return 0;
}
@@ -57,6 +61,11 @@ int lg2_config(git_repository *repo, int argc, char **argv)
error = 1;
}
+ /**
+ * The configuration file must be freed once it's no longer
+ * being used by the user.
+ */
+ git_config_free(cfg);
out:
return error;
}
diff --git a/examples/general.c b/examples/general.c
index 1622ff8b0..2127ec0e1 100644
--- a/examples/general.c
+++ b/examples/general.c
@@ -158,11 +158,6 @@ static void oid_parsing(git_oid *oid)
* If you have a oid, you can easily get the hex value of the SHA as well.
*/
git_oid_fmt(out, oid);
-
- /**
- * If you have a oid, you can easily get the hex value of the SHA as well.
- */
- git_oid_fmt(out, oid);
printf("SHA hex string: %s\n", out);
}
@@ -713,7 +708,7 @@ static void reference_listing(git_repository *repo)
/**
* ### Config Files
*
- * The [config API][config] allows you to list and updatee config values
+ * The [config API][config] allows you to list and update config values
* in any of the accessible config file locations (system, global, local).
*
* [config]: http://libgit2.github.com/libgit2/#HEAD/group/config
diff --git a/examples/log.c b/examples/log.c
index ee18df542..9060f3f3e 100644
--- a/examples/log.c
+++ b/examples/log.c
@@ -245,7 +245,7 @@ static int add_revision(struct log_state *s, const char *revstr)
}
if (*revstr == '^') {
- revs.flags = GIT_REVPARSE_SINGLE;
+ revs.flags = GIT_REVSPEC_SINGLE;
hide = !hide;
if (git_revparse_single(&revs.from, s->repo, revstr + 1) < 0)
@@ -253,12 +253,12 @@ static int add_revision(struct log_state *s, const char *revstr)
} else if (git_revparse(&revs, s->repo, revstr) < 0)
return -1;
- if ((revs.flags & GIT_REVPARSE_SINGLE) != 0)
+ if ((revs.flags & GIT_REVSPEC_SINGLE) != 0)
push_rev(s, revs.from, hide);
else {
push_rev(s, revs.to, hide);
- if ((revs.flags & GIT_REVPARSE_MERGE_BASE) != 0) {
+ if ((revs.flags & GIT_REVSPEC_MERGE_BASE) != 0) {
git_oid base;
check_lg2(git_merge_base(&base, s->repo,
git_object_id(revs.from), git_object_id(revs.to)),
diff --git a/examples/rev-list.c b/examples/rev-list.c
index 75fb19e70..d10f16690 100644
--- a/examples/rev-list.c
+++ b/examples/rev-list.c
@@ -73,7 +73,7 @@ static int push_range(git_repository *repo, git_revwalk *walk, const char *range
if ((error = git_revparse(&revspec, repo, range)))
return error;
- if (revspec.flags & GIT_REVPARSE_MERGE_BASE) {
+ if (revspec.flags & GIT_REVSPEC_MERGE_BASE) {
/* TODO: support "<commit>...<commit>" */
return GIT_EINVALIDSPEC;
}
diff --git a/examples/rev-parse.c b/examples/rev-parse.c
index 7d6e9986f..90258c101 100644
--- a/examples/rev-parse.c
+++ b/examples/rev-parse.c
@@ -69,17 +69,17 @@ static int parse_revision(git_repository *repo, struct parse_state *ps)
check_lg2(git_revparse(&rs, repo, ps->spec), "Could not parse", ps->spec);
- if ((rs.flags & GIT_REVPARSE_SINGLE) != 0) {
+ if ((rs.flags & GIT_REVSPEC_SINGLE) != 0) {
git_oid_tostr(str, sizeof(str), git_object_id(rs.from));
printf("%s\n", str);
git_object_free(rs.from);
}
- else if ((rs.flags & GIT_REVPARSE_RANGE) != 0) {
+ else if ((rs.flags & GIT_REVSPEC_RANGE) != 0) {
git_oid_tostr(str, sizeof(str), git_object_id(rs.to));
printf("%s\n", str);
git_object_free(rs.to);
- if ((rs.flags & GIT_REVPARSE_MERGE_BASE) != 0) {
+ if ((rs.flags & GIT_REVSPEC_MERGE_BASE) != 0) {
git_oid base;
check_lg2(git_merge_base(&base, repo,
git_object_id(rs.from), git_object_id(rs.to)),
diff --git a/examples/tag.c b/examples/tag.c
index 03d9c2bf9..e4f71ae62 100644
--- a/examples/tag.c
+++ b/examples/tag.c
@@ -188,7 +188,7 @@ static void action_delete_tag(tag_state *state)
git_object_free(obj);
}
-static void action_create_lighweight_tag(tag_state *state)
+static void action_create_lightweight_tag(tag_state *state)
{
git_repository *repo = state->repo;
struct tag_options *opts = state->opts;
@@ -260,7 +260,7 @@ static void parse_options(tag_action *action, struct tag_options *opts, int argc
print_usage();
if (*action != &action_create_tag)
- *action = &action_create_lighweight_tag;
+ *action = &action_create_lightweight_tag;
} else if (!strcmp(curr, "-n")) {
opts->num_lines = 1;
*action = &action_list_tags;
diff --git a/fuzzers/commit_graph_fuzzer.c b/fuzzers/commit_graph_fuzzer.c
new file mode 100644
index 000000000..b41816ed9
--- /dev/null
+++ b/fuzzers/commit_graph_fuzzer.c
@@ -0,0 +1,80 @@
+/*
+ * libgit2 commit-graph fuzzer target.
+ *
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include <stdio.h>
+
+#include "git2.h"
+
+#include "buffer.h"
+#include "common.h"
+#include "futils.h"
+#include "hash.h"
+#include "commit_graph.h"
+
+int LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ GIT_UNUSED(argc);
+ GIT_UNUSED(argv);
+
+ if (git_libgit2_init() < 0) {
+ fprintf(stderr, "Failed to initialize libgit2\n");
+ abort();
+ }
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ git_commit_graph_file file = {{0}};
+ git_commit_graph_entry e;
+ git_buf commit_graph_buf = GIT_BUF_INIT;
+ git_oid oid = {{0}};
+ bool append_hash = false;
+
+ if (size < 4)
+ return 0;
+
+ /*
+ * If the first byte in the stream has the high bit set, append the
+ * SHA1 hash so that the file is somewhat valid.
+ */
+ append_hash = *data & 0x80;
+ /* Keep a 4-byte alignment to avoid unaligned accesses. */
+ data += 4;
+ size -= 4;
+
+ if (append_hash) {
+ if (git_buf_init(&commit_graph_buf, size + sizeof(oid)) < 0)
+ goto cleanup;
+ if (git_hash_buf(&oid, data, size) < 0) {
+ fprintf(stderr, "Failed to compute the SHA1 hash\n");
+ abort();
+ }
+ memcpy(commit_graph_buf.ptr, data, size);
+ memcpy(commit_graph_buf.ptr + size, &oid, sizeof(oid));
+ } else {
+ git_buf_attach_notowned(&commit_graph_buf, (char *)data, size);
+ }
+
+ if (git_commit_graph_file_parse(
+ &file,
+ (const unsigned char *)git_buf_cstr(&commit_graph_buf),
+ git_buf_len(&commit_graph_buf))
+ < 0)
+ goto cleanup;
+
+ /* Search for any oid, just to exercise that codepath. */
+ if (git_commit_graph_entry_find(&e, &file, &oid, GIT_OID_HEXSZ) < 0)
+ goto cleanup;
+
+cleanup:
+ git_commit_graph_file_close(&file);
+ git_buf_dispose(&commit_graph_buf);
+ return 0;
+}
diff --git a/fuzzers/corpora/commit_graph/005682ce1cb5b20c20fccf4be5dbd47ca399e53e b/fuzzers/corpora/commit_graph/005682ce1cb5b20c20fccf4be5dbd47ca399e53e
new file mode 100644
index 000000000..15d0d2813
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/005682ce1cb5b20c20fccf4be5dbd47ca399e53e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/00574fc29fd1323e93d18d625cde80d3ea20e8cc b/fuzzers/corpora/commit_graph/00574fc29fd1323e93d18d625cde80d3ea20e8cc
new file mode 100644
index 000000000..4eabd00da
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/00574fc29fd1323e93d18d625cde80d3ea20e8cc
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/00916ec21ddbd3c622bde6e4dc824250176b9e88 b/fuzzers/corpora/commit_graph/00916ec21ddbd3c622bde6e4dc824250176b9e88
new file mode 100644
index 000000000..d069fb5cb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/00916ec21ddbd3c622bde6e4dc824250176b9e88
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/00b6dde4b8d5e68a5ec40d88c39134cf2f1f8bc3 b/fuzzers/corpora/commit_graph/00b6dde4b8d5e68a5ec40d88c39134cf2f1f8bc3
new file mode 100644
index 000000000..98f2d0e9d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/00b6dde4b8d5e68a5ec40d88c39134cf2f1f8bc3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/020f0e77e42d8b3810019050f4c5ceadd205b37c b/fuzzers/corpora/commit_graph/020f0e77e42d8b3810019050f4c5ceadd205b37c
new file mode 100644
index 000000000..d09327d54
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/020f0e77e42d8b3810019050f4c5ceadd205b37c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/02739c05abc1715fac1ce995b532e482abc8d4dc b/fuzzers/corpora/commit_graph/02739c05abc1715fac1ce995b532e482abc8d4dc
new file mode 100644
index 000000000..b9de08e1d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/02739c05abc1715fac1ce995b532e482abc8d4dc
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/02a276faa5dc8c7df5b82a57ab6cd195a13e4ae0 b/fuzzers/corpora/commit_graph/02a276faa5dc8c7df5b82a57ab6cd195a13e4ae0
new file mode 100644
index 000000000..891d3efbe
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/02a276faa5dc8c7df5b82a57ab6cd195a13e4ae0
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/02de15987d68a97db3d9fd964cfd785bcbd54d3a b/fuzzers/corpora/commit_graph/02de15987d68a97db3d9fd964cfd785bcbd54d3a
new file mode 100644
index 000000000..b8bd4ce97
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/02de15987d68a97db3d9fd964cfd785bcbd54d3a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/02e106f97a91b1d3aef4dd2d31368ae5077bd42b b/fuzzers/corpora/commit_graph/02e106f97a91b1d3aef4dd2d31368ae5077bd42b
new file mode 100644
index 000000000..f1277396c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/02e106f97a91b1d3aef4dd2d31368ae5077bd42b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/038555bcb4cc2daf764840f79ebce4023bdb7670 b/fuzzers/corpora/commit_graph/038555bcb4cc2daf764840f79ebce4023bdb7670
new file mode 100644
index 000000000..239f4e6e3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/038555bcb4cc2daf764840f79ebce4023bdb7670
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/04c159a04b0732e04ac4c59ed3356860af8dffce b/fuzzers/corpora/commit_graph/04c159a04b0732e04ac4c59ed3356860af8dffce
new file mode 100644
index 000000000..856af0f76
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/04c159a04b0732e04ac4c59ed3356860af8dffce
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/0560ec993882ffbd8d46dcab0ed430089c4f2aa1 b/fuzzers/corpora/commit_graph/0560ec993882ffbd8d46dcab0ed430089c4f2aa1
new file mode 100644
index 000000000..a236d1a2e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/0560ec993882ffbd8d46dcab0ed430089c4f2aa1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/059b3aab3fde6b4c9404aff83fed638596f594bb b/fuzzers/corpora/commit_graph/059b3aab3fde6b4c9404aff83fed638596f594bb
new file mode 100644
index 000000000..4900105ff
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/059b3aab3fde6b4c9404aff83fed638596f594bb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/06168e726aa0260f520165be4ea0c88244831049 b/fuzzers/corpora/commit_graph/06168e726aa0260f520165be4ea0c88244831049
new file mode 100644
index 000000000..4c9e9df03
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/06168e726aa0260f520165be4ea0c88244831049
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/066d1ec700a526b97009cedd0305b6a47242faba b/fuzzers/corpora/commit_graph/066d1ec700a526b97009cedd0305b6a47242faba
new file mode 100644
index 000000000..f5b17612a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/066d1ec700a526b97009cedd0305b6a47242faba
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/086a5f8cbfa9f058b5c938a6eb724c9e4c5f84f3 b/fuzzers/corpora/commit_graph/086a5f8cbfa9f058b5c938a6eb724c9e4c5f84f3
new file mode 100644
index 000000000..aa9cdca97
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/086a5f8cbfa9f058b5c938a6eb724c9e4c5f84f3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/089313c698f3e351433e9a45af2ace1d85b9673e b/fuzzers/corpora/commit_graph/089313c698f3e351433e9a45af2ace1d85b9673e
new file mode 100644
index 000000000..14fd3bbc3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/089313c698f3e351433e9a45af2ace1d85b9673e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/092eb973a771fa14cf0b567d65bd2c99130f543e b/fuzzers/corpora/commit_graph/092eb973a771fa14cf0b567d65bd2c99130f543e
new file mode 100644
index 000000000..3092a2bc4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/092eb973a771fa14cf0b567d65bd2c99130f543e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/094b8cd1aa3e40b1f9ff83680892d52e246df0f8 b/fuzzers/corpora/commit_graph/094b8cd1aa3e40b1f9ff83680892d52e246df0f8
new file mode 100644
index 000000000..ed62ec9e5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/094b8cd1aa3e40b1f9ff83680892d52e246df0f8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/0ce990c9c2ec121b8c78ba2bdf84679e04c0bdae b/fuzzers/corpora/commit_graph/0ce990c9c2ec121b8c78ba2bdf84679e04c0bdae
new file mode 100644
index 000000000..d708b6837
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/0ce990c9c2ec121b8c78ba2bdf84679e04c0bdae
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/0dd0770c34fcf6b1f13219450190616d344db021 b/fuzzers/corpora/commit_graph/0dd0770c34fcf6b1f13219450190616d344db021
new file mode 100644
index 000000000..aea94b2c8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/0dd0770c34fcf6b1f13219450190616d344db021
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/0e2b2e6a32733b8a625bc7e812e2ea508d69a5e4 b/fuzzers/corpora/commit_graph/0e2b2e6a32733b8a625bc7e812e2ea508d69a5e4
new file mode 100644
index 000000000..58e88014e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/0e2b2e6a32733b8a625bc7e812e2ea508d69a5e4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/0e8d0bd07c543d708aecaca377106492b7a74fa3 b/fuzzers/corpora/commit_graph/0e8d0bd07c543d708aecaca377106492b7a74fa3
new file mode 100644
index 000000000..98a92307d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/0e8d0bd07c543d708aecaca377106492b7a74fa3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/0f0d16e1b8c8671dbe1074115c1d86aa9b359e7e b/fuzzers/corpora/commit_graph/0f0d16e1b8c8671dbe1074115c1d86aa9b359e7e
new file mode 100644
index 000000000..bc322de2b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/0f0d16e1b8c8671dbe1074115c1d86aa9b359e7e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/102ef78036de5a30927e7f751377b05441c41a08 b/fuzzers/corpora/commit_graph/102ef78036de5a30927e7f751377b05441c41a08
new file mode 100644
index 000000000..3b14c352f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/102ef78036de5a30927e7f751377b05441c41a08
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/10494e7cc9cb8dff289c431d7560bcee0d1b14ed b/fuzzers/corpora/commit_graph/10494e7cc9cb8dff289c431d7560bcee0d1b14ed
new file mode 100644
index 000000000..293c49d36
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/10494e7cc9cb8dff289c431d7560bcee0d1b14ed
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/107b11d86381345f50aa19b8485477a870ff399f b/fuzzers/corpora/commit_graph/107b11d86381345f50aa19b8485477a870ff399f
new file mode 100644
index 000000000..53bb34eee
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/107b11d86381345f50aa19b8485477a870ff399f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/10bb37e18fb3c0897dabacf9c464b4d324007dc3 b/fuzzers/corpora/commit_graph/10bb37e18fb3c0897dabacf9c464b4d324007dc3
new file mode 100644
index 000000000..e75a9c511
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/10bb37e18fb3c0897dabacf9c464b4d324007dc3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/10ee715f64b08549c3e8261204276694728eb841 b/fuzzers/corpora/commit_graph/10ee715f64b08549c3e8261204276694728eb841
new file mode 100644
index 000000000..104eda6c3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/10ee715f64b08549c3e8261204276694728eb841
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/123e4eeb7a731f48d06e336b4d29af717f8b6550 b/fuzzers/corpora/commit_graph/123e4eeb7a731f48d06e336b4d29af717f8b6550
new file mode 100644
index 000000000..22d148278
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/123e4eeb7a731f48d06e336b4d29af717f8b6550
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/125a228afb923970e0a6d4412f7257ba998594a1 b/fuzzers/corpora/commit_graph/125a228afb923970e0a6d4412f7257ba998594a1
new file mode 100644
index 000000000..3de2c87e3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/125a228afb923970e0a6d4412f7257ba998594a1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/130d96c16fba06dcbe7e2a661ab959a3274a4bd9 b/fuzzers/corpora/commit_graph/130d96c16fba06dcbe7e2a661ab959a3274a4bd9
new file mode 100644
index 000000000..66a409794
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/130d96c16fba06dcbe7e2a661ab959a3274a4bd9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/131c5a2fec55cb0d63f7dc055d6fad5f3dc3c974 b/fuzzers/corpora/commit_graph/131c5a2fec55cb0d63f7dc055d6fad5f3dc3c974
new file mode 100644
index 000000000..b54bfadad
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/131c5a2fec55cb0d63f7dc055d6fad5f3dc3c974
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/13e562d61acb3aa36260a819a00b07ff16450335 b/fuzzers/corpora/commit_graph/13e562d61acb3aa36260a819a00b07ff16450335
new file mode 100644
index 000000000..6682c84e6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/13e562d61acb3aa36260a819a00b07ff16450335
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1414e6e8ab6bad1b5c51fed807c514a9d6575e66 b/fuzzers/corpora/commit_graph/1414e6e8ab6bad1b5c51fed807c514a9d6575e66
new file mode 100644
index 000000000..c7f2386d0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1414e6e8ab6bad1b5c51fed807c514a9d6575e66
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1432d191846ae2d0e381813efcfacff2f1dba0e4 b/fuzzers/corpora/commit_graph/1432d191846ae2d0e381813efcfacff2f1dba0e4
new file mode 100644
index 000000000..cf5b990a6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1432d191846ae2d0e381813efcfacff2f1dba0e4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/14a84cdc6f8d432be4cd3d3eafce92ae385e472f b/fuzzers/corpora/commit_graph/14a84cdc6f8d432be4cd3d3eafce92ae385e472f
new file mode 100644
index 000000000..8f8665113
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/14a84cdc6f8d432be4cd3d3eafce92ae385e472f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/14e3e735dba88791f2cadd6e0dc5d662a104a6d7 b/fuzzers/corpora/commit_graph/14e3e735dba88791f2cadd6e0dc5d662a104a6d7
new file mode 100644
index 000000000..32fb99378
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/14e3e735dba88791f2cadd6e0dc5d662a104a6d7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1574abb020203103ea629d677edd21c967fc0f4c b/fuzzers/corpora/commit_graph/1574abb020203103ea629d677edd21c967fc0f4c
new file mode 100644
index 000000000..b3da74c1a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1574abb020203103ea629d677edd21c967fc0f4c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/169cc492ba94948a6206765436881a1a0c601780 b/fuzzers/corpora/commit_graph/169cc492ba94948a6206765436881a1a0c601780
new file mode 100644
index 000000000..2ce25f66b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/169cc492ba94948a6206765436881a1a0c601780
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/16a2130c1d75129f3bae3bf8f2c2de41fb3533c0 b/fuzzers/corpora/commit_graph/16a2130c1d75129f3bae3bf8f2c2de41fb3533c0
new file mode 100644
index 000000000..0b6638518
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/16a2130c1d75129f3bae3bf8f2c2de41fb3533c0
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/16ba602eadfc9a3f74c0845394eda0de42b61571 b/fuzzers/corpora/commit_graph/16ba602eadfc9a3f74c0845394eda0de42b61571
new file mode 100644
index 000000000..c44bd060e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/16ba602eadfc9a3f74c0845394eda0de42b61571
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/17555fb2dfc444d171ba686667d72e388bd6c041 b/fuzzers/corpora/commit_graph/17555fb2dfc444d171ba686667d72e388bd6c041
new file mode 100644
index 000000000..3d0002693
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/17555fb2dfc444d171ba686667d72e388bd6c041
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1a10450d99c1e53d9b7f97b8014cb7fc01906ef2 b/fuzzers/corpora/commit_graph/1a10450d99c1e53d9b7f97b8014cb7fc01906ef2
new file mode 100644
index 000000000..f1fec6037
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1a10450d99c1e53d9b7f97b8014cb7fc01906ef2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1af670b5515231fc04b2be9038ee30a7e066b09b b/fuzzers/corpora/commit_graph/1af670b5515231fc04b2be9038ee30a7e066b09b
new file mode 100644
index 000000000..3bf73452f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1af670b5515231fc04b2be9038ee30a7e066b09b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1b72cfa68259e3f3b3802906902a0a29368f86b5 b/fuzzers/corpora/commit_graph/1b72cfa68259e3f3b3802906902a0a29368f86b5
new file mode 100644
index 000000000..e6509d176
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1b72cfa68259e3f3b3802906902a0a29368f86b5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1c62ac5d632aa9e449a4335b675941107d8825ae b/fuzzers/corpora/commit_graph/1c62ac5d632aa9e449a4335b675941107d8825ae
new file mode 100644
index 000000000..10c9e7490
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1c62ac5d632aa9e449a4335b675941107d8825ae
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1d95b5db2f802011b33d10212a66fbe40827dfd4 b/fuzzers/corpora/commit_graph/1d95b5db2f802011b33d10212a66fbe40827dfd4
new file mode 100644
index 000000000..2353450fe
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1d95b5db2f802011b33d10212a66fbe40827dfd4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1e068537ce1211a325aab42ae1263a109131c9f9 b/fuzzers/corpora/commit_graph/1e068537ce1211a325aab42ae1263a109131c9f9
new file mode 100644
index 000000000..035173872
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1e068537ce1211a325aab42ae1263a109131c9f9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1e9c882c9d33304a5791ef6c98eee65e142bd7fd b/fuzzers/corpora/commit_graph/1e9c882c9d33304a5791ef6c98eee65e142bd7fd
new file mode 100644
index 000000000..d5b9da4e5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1e9c882c9d33304a5791ef6c98eee65e142bd7fd
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/1f54935df929403a29e77591c97f767d94871aea b/fuzzers/corpora/commit_graph/1f54935df929403a29e77591c97f767d94871aea
new file mode 100644
index 000000000..6f9b0a07b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/1f54935df929403a29e77591c97f767d94871aea
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/206015659641771bb0d668728c2fdc4209e65dda b/fuzzers/corpora/commit_graph/206015659641771bb0d668728c2fdc4209e65dda
new file mode 100644
index 000000000..086ab6469
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/206015659641771bb0d668728c2fdc4209e65dda
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2096493a2bcc2d15b7ae5bf3112fe49c39976ad8 b/fuzzers/corpora/commit_graph/2096493a2bcc2d15b7ae5bf3112fe49c39976ad8
new file mode 100644
index 000000000..7b33d38e2
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2096493a2bcc2d15b7ae5bf3112fe49c39976ad8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/209b74e08abe8c787b7c5ba81e51cb69c57ecded b/fuzzers/corpora/commit_graph/209b74e08abe8c787b7c5ba81e51cb69c57ecded
new file mode 100644
index 000000000..55dca76e7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/209b74e08abe8c787b7c5ba81e51cb69c57ecded
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/21137876575fbca357fc0c96db1de73c6737e1ae b/fuzzers/corpora/commit_graph/21137876575fbca357fc0c96db1de73c6737e1ae
new file mode 100644
index 000000000..fea1ac18c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/21137876575fbca357fc0c96db1de73c6737e1ae
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2143d9db9802f076c72a71184cd9d0cb4581e9e7 b/fuzzers/corpora/commit_graph/2143d9db9802f076c72a71184cd9d0cb4581e9e7
new file mode 100644
index 000000000..bacbe8830
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2143d9db9802f076c72a71184cd9d0cb4581e9e7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/21a52a5282145407d951ac73c2ff27876783899d b/fuzzers/corpora/commit_graph/21a52a5282145407d951ac73c2ff27876783899d
new file mode 100644
index 000000000..1b5d2f0ca
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/21a52a5282145407d951ac73c2ff27876783899d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/21d5c8c8ac3a09bcba5388c472df32795986a5cb b/fuzzers/corpora/commit_graph/21d5c8c8ac3a09bcba5388c472df32795986a5cb
new file mode 100644
index 000000000..b148c6feb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/21d5c8c8ac3a09bcba5388c472df32795986a5cb
@@ -0,0 +1 @@
+ÿúÿ¦ \ No newline at end of file
diff --git a/fuzzers/corpora/commit_graph/22170d1110a1c18009b7feb21a470681f55e85fb b/fuzzers/corpora/commit_graph/22170d1110a1c18009b7feb21a470681f55e85fb
new file mode 100644
index 000000000..6c16354e8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/22170d1110a1c18009b7feb21a470681f55e85fb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/22f55dff94785f24252d7a070f713840f59b0870 b/fuzzers/corpora/commit_graph/22f55dff94785f24252d7a070f713840f59b0870
new file mode 100644
index 000000000..b45c99ad2
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/22f55dff94785f24252d7a070f713840f59b0870
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/23d10ee9694e1c66bedc7060990f19a2ac3eaee3 b/fuzzers/corpora/commit_graph/23d10ee9694e1c66bedc7060990f19a2ac3eaee3
new file mode 100644
index 000000000..8790bfd9f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/23d10ee9694e1c66bedc7060990f19a2ac3eaee3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2435430ca19502c3b0ec4987508d4a8fbdbc898c b/fuzzers/corpora/commit_graph/2435430ca19502c3b0ec4987508d4a8fbdbc898c
new file mode 100644
index 000000000..e1d58bd0d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2435430ca19502c3b0ec4987508d4a8fbdbc898c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/244d2ea0c5c3117000b599cfab37680ba8f04513 b/fuzzers/corpora/commit_graph/244d2ea0c5c3117000b599cfab37680ba8f04513
new file mode 100644
index 000000000..5eedc854b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/244d2ea0c5c3117000b599cfab37680ba8f04513
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/248bf94143d150da2459cfdca099c30c6daff00a b/fuzzers/corpora/commit_graph/248bf94143d150da2459cfdca099c30c6daff00a
new file mode 100644
index 000000000..8b5f81b46
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/248bf94143d150da2459cfdca099c30c6daff00a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/25bc53498129bb3717671f00c355d2637a91c86a b/fuzzers/corpora/commit_graph/25bc53498129bb3717671f00c355d2637a91c86a
new file mode 100644
index 000000000..d86bb32ef
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/25bc53498129bb3717671f00c355d2637a91c86a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2614f60da2d7e291501397238366d27513bff773 b/fuzzers/corpora/commit_graph/2614f60da2d7e291501397238366d27513bff773
new file mode 100644
index 000000000..57cd70aba
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2614f60da2d7e291501397238366d27513bff773
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2651b3d5a8b4616b1faa81dabe27ab2712a27561 b/fuzzers/corpora/commit_graph/2651b3d5a8b4616b1faa81dabe27ab2712a27561
new file mode 100644
index 000000000..5f838deaa
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2651b3d5a8b4616b1faa81dabe27ab2712a27561
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/270257a2872b33dd13c4fd466cbc1ae67d613f9b b/fuzzers/corpora/commit_graph/270257a2872b33dd13c4fd466cbc1ae67d613f9b
new file mode 100644
index 000000000..30904964e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/270257a2872b33dd13c4fd466cbc1ae67d613f9b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2830c6244c74656f6c5649c8226953905a582a38 b/fuzzers/corpora/commit_graph/2830c6244c74656f6c5649c8226953905a582a38
new file mode 100644
index 000000000..895a8efcc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2830c6244c74656f6c5649c8226953905a582a38
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2889a85c07c20551ff0b97fc640e3c91b33aa4a1 b/fuzzers/corpora/commit_graph/2889a85c07c20551ff0b97fc640e3c91b33aa4a1
new file mode 100644
index 000000000..349ff154c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2889a85c07c20551ff0b97fc640e3c91b33aa4a1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/295ce43fdd56def8948d1ba2bfa7fdf0c47b5318 b/fuzzers/corpora/commit_graph/295ce43fdd56def8948d1ba2bfa7fdf0c47b5318
new file mode 100644
index 000000000..4a3ce801f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/295ce43fdd56def8948d1ba2bfa7fdf0c47b5318
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/296cbb94c4e68ab86972a174405308ee34d0c40f b/fuzzers/corpora/commit_graph/296cbb94c4e68ab86972a174405308ee34d0c40f
new file mode 100644
index 000000000..45c218ea3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/296cbb94c4e68ab86972a174405308ee34d0c40f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2975adf222cad108ec90d8225fd655e30e3bf253 b/fuzzers/corpora/commit_graph/2975adf222cad108ec90d8225fd655e30e3bf253
new file mode 100644
index 000000000..6a16429c5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2975adf222cad108ec90d8225fd655e30e3bf253
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/29f5d27760c9254ab4db661a6cd0323dd11c34ca b/fuzzers/corpora/commit_graph/29f5d27760c9254ab4db661a6cd0323dd11c34ca
new file mode 100644
index 000000000..a9d81e1d4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/29f5d27760c9254ab4db661a6cd0323dd11c34ca
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2a359fb09eaad968e57d353453908027645873d1 b/fuzzers/corpora/commit_graph/2a359fb09eaad968e57d353453908027645873d1
new file mode 100644
index 000000000..a17910b8a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2a359fb09eaad968e57d353453908027645873d1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2a6b65a8d6c28febaa081d220a4433f8366d02bc b/fuzzers/corpora/commit_graph/2a6b65a8d6c28febaa081d220a4433f8366d02bc
new file mode 100644
index 000000000..597f363ae
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2a6b65a8d6c28febaa081d220a4433f8366d02bc
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2b14dcade4d0919b0a17830fe353738015f492a6 b/fuzzers/corpora/commit_graph/2b14dcade4d0919b0a17830fe353738015f492a6
new file mode 100644
index 000000000..33f4e6efb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2b14dcade4d0919b0a17830fe353738015f492a6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2b298a13abbd9829e965424a1486baa13d4166c4 b/fuzzers/corpora/commit_graph/2b298a13abbd9829e965424a1486baa13d4166c4
new file mode 100644
index 000000000..837e45f32
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2b298a13abbd9829e965424a1486baa13d4166c4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2b44d8cd8e70e25172b4c740ebe38ef411c965b3 b/fuzzers/corpora/commit_graph/2b44d8cd8e70e25172b4c740ebe38ef411c965b3
new file mode 100644
index 000000000..8059ce413
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2b44d8cd8e70e25172b4c740ebe38ef411c965b3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2b590c4e61fdfcf21c017b29440747a1894b1534 b/fuzzers/corpora/commit_graph/2b590c4e61fdfcf21c017b29440747a1894b1534
new file mode 100644
index 000000000..c3ea72932
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2b590c4e61fdfcf21c017b29440747a1894b1534
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2becb18a971ae30e1a8f6680982fd7305708caa0 b/fuzzers/corpora/commit_graph/2becb18a971ae30e1a8f6680982fd7305708caa0
new file mode 100644
index 000000000..4b133a7f8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2becb18a971ae30e1a8f6680982fd7305708caa0
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2bf78b02099a1fe4ce50d065254e843ca55e280f b/fuzzers/corpora/commit_graph/2bf78b02099a1fe4ce50d065254e843ca55e280f
new file mode 100644
index 000000000..9b459e209
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2bf78b02099a1fe4ce50d065254e843ca55e280f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2c1541ecd01aa7b9e99bccfe9804198b3e79f118 b/fuzzers/corpora/commit_graph/2c1541ecd01aa7b9e99bccfe9804198b3e79f118
new file mode 100644
index 000000000..92daa0a2e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2c1541ecd01aa7b9e99bccfe9804198b3e79f118
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2c6798057af5894c27631ff63e845fe1e4bdc9ee b/fuzzers/corpora/commit_graph/2c6798057af5894c27631ff63e845fe1e4bdc9ee
new file mode 100644
index 000000000..06a7d31fa
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2c6798057af5894c27631ff63e845fe1e4bdc9ee
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2cf7eb7fe489e5acd64df755e820c871784c2ba1 b/fuzzers/corpora/commit_graph/2cf7eb7fe489e5acd64df755e820c871784c2ba1
new file mode 100644
index 000000000..5614c74b9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2cf7eb7fe489e5acd64df755e820c871784c2ba1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2d49ba35ca404baa0d593925f36a81ce53943c8d b/fuzzers/corpora/commit_graph/2d49ba35ca404baa0d593925f36a81ce53943c8d
new file mode 100644
index 000000000..36d6b853b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2d49ba35ca404baa0d593925f36a81ce53943c8d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2d507d42ca43ffc2f3c8892826e1db74144ec096 b/fuzzers/corpora/commit_graph/2d507d42ca43ffc2f3c8892826e1db74144ec096
new file mode 100644
index 000000000..35c28f488
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2d507d42ca43ffc2f3c8892826e1db74144ec096
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2e4da693e3e336d2b1a40311a7ccf94def035b6b b/fuzzers/corpora/commit_graph/2e4da693e3e336d2b1a40311a7ccf94def035b6b
new file mode 100644
index 000000000..42727e958
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2e4da693e3e336d2b1a40311a7ccf94def035b6b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2e71ff86128b5618f0f067c407a76ff645ae2019 b/fuzzers/corpora/commit_graph/2e71ff86128b5618f0f067c407a76ff645ae2019
new file mode 100644
index 000000000..32f02fcaf
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2e71ff86128b5618f0f067c407a76ff645ae2019
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2eb777c6d7e6ee9bd7a44e37372595043aad596b b/fuzzers/corpora/commit_graph/2eb777c6d7e6ee9bd7a44e37372595043aad596b
new file mode 100644
index 000000000..7203c91c0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2eb777c6d7e6ee9bd7a44e37372595043aad596b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/2ec3ebffba165b9dd49e755a9e77e23aed796628 b/fuzzers/corpora/commit_graph/2ec3ebffba165b9dd49e755a9e77e23aed796628
new file mode 100644
index 000000000..d4018de50
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/2ec3ebffba165b9dd49e755a9e77e23aed796628
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/302703e3b0d74219868aca39ee7593944c0b2400 b/fuzzers/corpora/commit_graph/302703e3b0d74219868aca39ee7593944c0b2400
new file mode 100644
index 000000000..6b692e19c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/302703e3b0d74219868aca39ee7593944c0b2400
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3048c6908dc3176707fa8bcb0196824e3358357a b/fuzzers/corpora/commit_graph/3048c6908dc3176707fa8bcb0196824e3358357a
new file mode 100644
index 000000000..c58805fc4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3048c6908dc3176707fa8bcb0196824e3358357a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/30616cb39d3ad6060324fada03709d611ad28d5c b/fuzzers/corpora/commit_graph/30616cb39d3ad6060324fada03709d611ad28d5c
new file mode 100644
index 000000000..1fd655ed8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/30616cb39d3ad6060324fada03709d611ad28d5c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/306beadd9b3135a00037323760eb5377c88a403e b/fuzzers/corpora/commit_graph/306beadd9b3135a00037323760eb5377c88a403e
new file mode 100644
index 000000000..86c867230
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/306beadd9b3135a00037323760eb5377c88a403e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/31464a6fbad023923a7e4700fc11564e811bcbd2 b/fuzzers/corpora/commit_graph/31464a6fbad023923a7e4700fc11564e811bcbd2
new file mode 100644
index 000000000..102de5c14
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/31464a6fbad023923a7e4700fc11564e811bcbd2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/317f4bcfecf066961ef1982d551cd14e63c9f008 b/fuzzers/corpora/commit_graph/317f4bcfecf066961ef1982d551cd14e63c9f008
new file mode 100644
index 000000000..5c2a5d70f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/317f4bcfecf066961ef1982d551cd14e63c9f008
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/31b2248faaabbec69a06098c8cb0f69c5d0aa208 b/fuzzers/corpora/commit_graph/31b2248faaabbec69a06098c8cb0f69c5d0aa208
new file mode 100644
index 000000000..555c7b18f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/31b2248faaabbec69a06098c8cb0f69c5d0aa208
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/31d1c3d1147385d58dbe6f82898a5523320fbcac b/fuzzers/corpora/commit_graph/31d1c3d1147385d58dbe6f82898a5523320fbcac
new file mode 100644
index 000000000..1c5ef0719
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/31d1c3d1147385d58dbe6f82898a5523320fbcac
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/32c9bc1616a78a230a3724abc02150db1cc40aa0 b/fuzzers/corpora/commit_graph/32c9bc1616a78a230a3724abc02150db1cc40aa0
new file mode 100644
index 000000000..cfc45a1f7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/32c9bc1616a78a230a3724abc02150db1cc40aa0
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/331e2866416b091252f0299e98d32cfb29237029 b/fuzzers/corpora/commit_graph/331e2866416b091252f0299e98d32cfb29237029
new file mode 100644
index 000000000..241e719a5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/331e2866416b091252f0299e98d32cfb29237029
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/331eb3876dd2f3f0bd51f380ac431d86d6e3bb5e b/fuzzers/corpora/commit_graph/331eb3876dd2f3f0bd51f380ac431d86d6e3bb5e
new file mode 100644
index 000000000..a52780fe2
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/331eb3876dd2f3f0bd51f380ac431d86d6e3bb5e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/346bd6eaeadeafcb840ff9441614b309330db63e b/fuzzers/corpora/commit_graph/346bd6eaeadeafcb840ff9441614b309330db63e
new file mode 100644
index 000000000..50b7f93a8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/346bd6eaeadeafcb840ff9441614b309330db63e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/349931f447981f21476481448576e805c093a25b b/fuzzers/corpora/commit_graph/349931f447981f21476481448576e805c093a25b
new file mode 100644
index 000000000..ae5b758d9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/349931f447981f21476481448576e805c093a25b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/34a2da1e9adaac1b4be1d40b1ece81fe00643d49 b/fuzzers/corpora/commit_graph/34a2da1e9adaac1b4be1d40b1ece81fe00643d49
new file mode 100644
index 000000000..f5d660f12
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/34a2da1e9adaac1b4be1d40b1ece81fe00643d49
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/34bb8f475e7384a8a39618fd15fdc5fb1b12c1a1 b/fuzzers/corpora/commit_graph/34bb8f475e7384a8a39618fd15fdc5fb1b12c1a1
new file mode 100644
index 000000000..f940f66f8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/34bb8f475e7384a8a39618fd15fdc5fb1b12c1a1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/351a036c6eb95db9364706b861f7e75ad26194e8 b/fuzzers/corpora/commit_graph/351a036c6eb95db9364706b861f7e75ad26194e8
new file mode 100644
index 000000000..197bee17a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/351a036c6eb95db9364706b861f7e75ad26194e8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/355452c1da8e7689d816d67cdde040b5df7eabd7 b/fuzzers/corpora/commit_graph/355452c1da8e7689d816d67cdde040b5df7eabd7
new file mode 100644
index 000000000..f135872e5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/355452c1da8e7689d816d67cdde040b5df7eabd7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/35c157ad2b100b4f334cddcf3dea6ef2d85462be b/fuzzers/corpora/commit_graph/35c157ad2b100b4f334cddcf3dea6ef2d85462be
new file mode 100644
index 000000000..7d73ba721
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/35c157ad2b100b4f334cddcf3dea6ef2d85462be
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/36a81a45eabfcf53e1ae0361aa234791e2fdb750 b/fuzzers/corpora/commit_graph/36a81a45eabfcf53e1ae0361aa234791e2fdb750
new file mode 100644
index 000000000..fc1b8dde6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/36a81a45eabfcf53e1ae0361aa234791e2fdb750
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/36ee20f6dbeb3a34e91eafbbe2e379f9ac6cfa43 b/fuzzers/corpora/commit_graph/36ee20f6dbeb3a34e91eafbbe2e379f9ac6cfa43
new file mode 100644
index 000000000..769017a8b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/36ee20f6dbeb3a34e91eafbbe2e379f9ac6cfa43
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/377627c19bcac6adc880202048a9eac07b5417d4 b/fuzzers/corpora/commit_graph/377627c19bcac6adc880202048a9eac07b5417d4
new file mode 100644
index 000000000..d4ef66b69
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/377627c19bcac6adc880202048a9eac07b5417d4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/38747e7c8bec2f9c923739d50ba54ff88ba6503f b/fuzzers/corpora/commit_graph/38747e7c8bec2f9c923739d50ba54ff88ba6503f
new file mode 100644
index 000000000..6d94b5766
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/38747e7c8bec2f9c923739d50ba54ff88ba6503f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3945843a6fab2ec71030f09b237c125b97cd3ea5 b/fuzzers/corpora/commit_graph/3945843a6fab2ec71030f09b237c125b97cd3ea5
new file mode 100644
index 000000000..76191cad0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3945843a6fab2ec71030f09b237c125b97cd3ea5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/396321d39b82ffaccbc64115117df7e822b0f515 b/fuzzers/corpora/commit_graph/396321d39b82ffaccbc64115117df7e822b0f515
new file mode 100644
index 000000000..74715a920
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/396321d39b82ffaccbc64115117df7e822b0f515
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/396e78eb9b54e2cefb52cd76a22137c8abd6cbcf b/fuzzers/corpora/commit_graph/396e78eb9b54e2cefb52cd76a22137c8abd6cbcf
new file mode 100644
index 000000000..b5648c453
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/396e78eb9b54e2cefb52cd76a22137c8abd6cbcf
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/39c1ab66035adc104cd06a6d98b77668172d21af b/fuzzers/corpora/commit_graph/39c1ab66035adc104cd06a6d98b77668172d21af
new file mode 100644
index 000000000..f9649f7bf
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/39c1ab66035adc104cd06a6d98b77668172d21af
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3a1078c35f5401ce09b5ba921fc348dde37530bb b/fuzzers/corpora/commit_graph/3a1078c35f5401ce09b5ba921fc348dde37530bb
new file mode 100644
index 000000000..7e519f87f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3a1078c35f5401ce09b5ba921fc348dde37530bb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3aa3d8f40392d1c863d23799b8ec0aedc7191302 b/fuzzers/corpora/commit_graph/3aa3d8f40392d1c863d23799b8ec0aedc7191302
new file mode 100644
index 000000000..3cbeaaf68
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3aa3d8f40392d1c863d23799b8ec0aedc7191302
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3b08c505601271cb92345ec7f0ff0b28daf90a9c b/fuzzers/corpora/commit_graph/3b08c505601271cb92345ec7f0ff0b28daf90a9c
new file mode 100644
index 000000000..69b9baba1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3b08c505601271cb92345ec7f0ff0b28daf90a9c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3b41702587be45f678b36823ad2f7e5002337dc4 b/fuzzers/corpora/commit_graph/3b41702587be45f678b36823ad2f7e5002337dc4
new file mode 100644
index 000000000..29069abc7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3b41702587be45f678b36823ad2f7e5002337dc4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3b69108cc919aba0248f9b864d4e71c5f6d1931e b/fuzzers/corpora/commit_graph/3b69108cc919aba0248f9b864d4e71c5f6d1931e
new file mode 100644
index 000000000..207df2469
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3b69108cc919aba0248f9b864d4e71c5f6d1931e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3b90507501bb3bcfe0094f9c92cc2869f1a7dda5 b/fuzzers/corpora/commit_graph/3b90507501bb3bcfe0094f9c92cc2869f1a7dda5
new file mode 100644
index 000000000..57272325b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3b90507501bb3bcfe0094f9c92cc2869f1a7dda5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3bc7fe44c3a1464dd35a4d22b482f46cdeda0405 b/fuzzers/corpora/commit_graph/3bc7fe44c3a1464dd35a4d22b482f46cdeda0405
new file mode 100644
index 000000000..e1a8bd350
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3bc7fe44c3a1464dd35a4d22b482f46cdeda0405
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3ce99994986efb6df3f3568423e0077b53c7ef78 b/fuzzers/corpora/commit_graph/3ce99994986efb6df3f3568423e0077b53c7ef78
new file mode 100644
index 000000000..21f9ab814
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3ce99994986efb6df3f3568423e0077b53c7ef78
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3d6cb3ba21181c9f0ab08b2608eab773f36773f2 b/fuzzers/corpora/commit_graph/3d6cb3ba21181c9f0ab08b2608eab773f36773f2
new file mode 100644
index 000000000..548a1295b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3d6cb3ba21181c9f0ab08b2608eab773f36773f2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3d8ec41450b943d5dea73fb1e393960b03d7c3b9 b/fuzzers/corpora/commit_graph/3d8ec41450b943d5dea73fb1e393960b03d7c3b9
new file mode 100644
index 000000000..150ed2c92
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3d8ec41450b943d5dea73fb1e393960b03d7c3b9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3e29e8baaac0f6c7e4cf3d5adca2ab3a2c491ac7 b/fuzzers/corpora/commit_graph/3e29e8baaac0f6c7e4cf3d5adca2ab3a2c491ac7
new file mode 100644
index 000000000..bc9597d42
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3e29e8baaac0f6c7e4cf3d5adca2ab3a2c491ac7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3e9469b3c68ba334671aacda7a7669b0e97b74d6 b/fuzzers/corpora/commit_graph/3e9469b3c68ba334671aacda7a7669b0e97b74d6
new file mode 100644
index 000000000..cb20df0df
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3e9469b3c68ba334671aacda7a7669b0e97b74d6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3eeda3bfa7abef69911c94520c009a08c49b9942 b/fuzzers/corpora/commit_graph/3eeda3bfa7abef69911c94520c009a08c49b9942
new file mode 100644
index 000000000..dbf559f73
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3eeda3bfa7abef69911c94520c009a08c49b9942
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3f0f5021016451b57f673d0603cd9e4830c2198d b/fuzzers/corpora/commit_graph/3f0f5021016451b57f673d0603cd9e4830c2198d
new file mode 100644
index 000000000..2f4c52326
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3f0f5021016451b57f673d0603cd9e4830c2198d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/3f46540fbd94bf0337c1d0d7437ec992a3568f09 b/fuzzers/corpora/commit_graph/3f46540fbd94bf0337c1d0d7437ec992a3568f09
new file mode 100644
index 000000000..7fbf35089
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/3f46540fbd94bf0337c1d0d7437ec992a3568f09
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/402d9c25d5833d42630882ab5c57833266bef785 b/fuzzers/corpora/commit_graph/402d9c25d5833d42630882ab5c57833266bef785
new file mode 100644
index 000000000..660028196
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/402d9c25d5833d42630882ab5c57833266bef785
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4048bb3c26d67c345630ff9e86db551a3add6549 b/fuzzers/corpora/commit_graph/4048bb3c26d67c345630ff9e86db551a3add6549
new file mode 100644
index 000000000..a07e1957b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4048bb3c26d67c345630ff9e86db551a3add6549
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/40792f23c1281842dab671e8b213fc408d1ec39f b/fuzzers/corpora/commit_graph/40792f23c1281842dab671e8b213fc408d1ec39f
new file mode 100644
index 000000000..9a0f9c298
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/40792f23c1281842dab671e8b213fc408d1ec39f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/41cd0b5d9a9540947b7b1841a55e4c11bd4346a2 b/fuzzers/corpora/commit_graph/41cd0b5d9a9540947b7b1841a55e4c11bd4346a2
new file mode 100644
index 000000000..a1b3a077a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/41cd0b5d9a9540947b7b1841a55e4c11bd4346a2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/41d86e5ea3df4a0de60d42aeb16e2a5599aedeae b/fuzzers/corpora/commit_graph/41d86e5ea3df4a0de60d42aeb16e2a5599aedeae
new file mode 100644
index 000000000..d749cf6e0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/41d86e5ea3df4a0de60d42aeb16e2a5599aedeae
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/42b4e5430b2b1b17a361067fb9dd33ab74e52232 b/fuzzers/corpora/commit_graph/42b4e5430b2b1b17a361067fb9dd33ab74e52232
new file mode 100644
index 000000000..6adf001bd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/42b4e5430b2b1b17a361067fb9dd33ab74e52232
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/42ef1c9d234b90acaf1651d930fc52d5f8f158f2 b/fuzzers/corpora/commit_graph/42ef1c9d234b90acaf1651d930fc52d5f8f158f2
new file mode 100644
index 000000000..0514ae837
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/42ef1c9d234b90acaf1651d930fc52d5f8f158f2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4570c8ff26d7f31afe73b3d9a35a29bc1274d68a b/fuzzers/corpora/commit_graph/4570c8ff26d7f31afe73b3d9a35a29bc1274d68a
new file mode 100644
index 000000000..834d62b34
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4570c8ff26d7f31afe73b3d9a35a29bc1274d68a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/45cf4751a5929930a7c30ec10134434b9ee13c3d b/fuzzers/corpora/commit_graph/45cf4751a5929930a7c30ec10134434b9ee13c3d
new file mode 100644
index 000000000..b761279db
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/45cf4751a5929930a7c30ec10134434b9ee13c3d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/46e9d351dd5bb71f7d4d8f15b3fad312c781452e b/fuzzers/corpora/commit_graph/46e9d351dd5bb71f7d4d8f15b3fad312c781452e
new file mode 100644
index 000000000..ce2623533
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/46e9d351dd5bb71f7d4d8f15b3fad312c781452e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/472421633b984556b96bc20f1fcf7a98c25736f3 b/fuzzers/corpora/commit_graph/472421633b984556b96bc20f1fcf7a98c25736f3
new file mode 100644
index 000000000..4a2faa137
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/472421633b984556b96bc20f1fcf7a98c25736f3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/47f35b91699caee098cacdde0161ffab21bdfc57 b/fuzzers/corpora/commit_graph/47f35b91699caee098cacdde0161ffab21bdfc57
new file mode 100644
index 000000000..a0f24ef48
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/47f35b91699caee098cacdde0161ffab21bdfc57
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/48b9da327218f9409287687a43b7eead4789a588 b/fuzzers/corpora/commit_graph/48b9da327218f9409287687a43b7eead4789a588
new file mode 100644
index 000000000..c6f2b79c7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/48b9da327218f9409287687a43b7eead4789a588
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/48d14fca326d5d591d18d34c2821a457277819a2 b/fuzzers/corpora/commit_graph/48d14fca326d5d591d18d34c2821a457277819a2
new file mode 100644
index 000000000..d223341ed
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/48d14fca326d5d591d18d34c2821a457277819a2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/48f3a33e2a027f5735d0a333ec4acd5a2aa57118 b/fuzzers/corpora/commit_graph/48f3a33e2a027f5735d0a333ec4acd5a2aa57118
new file mode 100644
index 000000000..0604edbac
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/48f3a33e2a027f5735d0a333ec4acd5a2aa57118
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/49e0eee24eab094a9c62f6b37b6ba01f8aece4e4 b/fuzzers/corpora/commit_graph/49e0eee24eab094a9c62f6b37b6ba01f8aece4e4
new file mode 100644
index 000000000..78f942579
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/49e0eee24eab094a9c62f6b37b6ba01f8aece4e4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4b45bcb707d2a0bc23b415e9bc3d7eb1f7f0e188 b/fuzzers/corpora/commit_graph/4b45bcb707d2a0bc23b415e9bc3d7eb1f7f0e188
new file mode 100644
index 000000000..3a1fdd7bc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4b45bcb707d2a0bc23b415e9bc3d7eb1f7f0e188
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4c428300fe4866fe81cff02ad4bc14b6848f7f73 b/fuzzers/corpora/commit_graph/4c428300fe4866fe81cff02ad4bc14b6848f7f73
new file mode 100644
index 000000000..d7f09e3ba
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4c428300fe4866fe81cff02ad4bc14b6848f7f73
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4d69c567df2e858c5f248b3fc8e4a9c04f02481c b/fuzzers/corpora/commit_graph/4d69c567df2e858c5f248b3fc8e4a9c04f02481c
new file mode 100644
index 000000000..26ba52528
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4d69c567df2e858c5f248b3fc8e4a9c04f02481c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4d88b6c9b513d5db2e07313a39b43d112d3d4562 b/fuzzers/corpora/commit_graph/4d88b6c9b513d5db2e07313a39b43d112d3d4562
new file mode 100644
index 000000000..bfe64c948
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4d88b6c9b513d5db2e07313a39b43d112d3d4562
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4da73370cf854ef8bd08c7f79b92a187cdbff278 b/fuzzers/corpora/commit_graph/4da73370cf854ef8bd08c7f79b92a187cdbff278
new file mode 100644
index 000000000..da1801e77
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4da73370cf854ef8bd08c7f79b92a187cdbff278
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4e4b2827351bbfd414b718052a8f950a9e3eb7ee b/fuzzers/corpora/commit_graph/4e4b2827351bbfd414b718052a8f950a9e3eb7ee
new file mode 100644
index 000000000..77d2e785e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4e4b2827351bbfd414b718052a8f950a9e3eb7ee
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4ed43f7d3c0305461edcbc86f62e0c6ad56df01e b/fuzzers/corpora/commit_graph/4ed43f7d3c0305461edcbc86f62e0c6ad56df01e
new file mode 100644
index 000000000..cfef7a1fd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4ed43f7d3c0305461edcbc86f62e0c6ad56df01e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4f011529809e88205421fa8ce39dcc025293bcb8 b/fuzzers/corpora/commit_graph/4f011529809e88205421fa8ce39dcc025293bcb8
new file mode 100644
index 000000000..2331acfe7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4f011529809e88205421fa8ce39dcc025293bcb8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4f1928b6376369ab6acf8a282284366cc3bf71ef b/fuzzers/corpora/commit_graph/4f1928b6376369ab6acf8a282284366cc3bf71ef
new file mode 100644
index 000000000..ad3d1739c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4f1928b6376369ab6acf8a282284366cc3bf71ef
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4f669eca3416c44f0d003ef2720d03e697e2230e b/fuzzers/corpora/commit_graph/4f669eca3416c44f0d003ef2720d03e697e2230e
new file mode 100644
index 000000000..6a143b3a1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4f669eca3416c44f0d003ef2720d03e697e2230e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4f750f24ecb5080bea2845061cfd3ce4529d30ee b/fuzzers/corpora/commit_graph/4f750f24ecb5080bea2845061cfd3ce4529d30ee
new file mode 100644
index 000000000..ea36bdc1e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4f750f24ecb5080bea2845061cfd3ce4529d30ee
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4fab9bb2bacf562e65f4a8681c429e6ea92aaed7 b/fuzzers/corpora/commit_graph/4fab9bb2bacf562e65f4a8681c429e6ea92aaed7
new file mode 100644
index 000000000..d00a7944d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4fab9bb2bacf562e65f4a8681c429e6ea92aaed7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/4fd757c7251c17413b3005fb38aee0fd029d89ec b/fuzzers/corpora/commit_graph/4fd757c7251c17413b3005fb38aee0fd029d89ec
new file mode 100644
index 000000000..4f4db7d47
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/4fd757c7251c17413b3005fb38aee0fd029d89ec
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/506092de91dcf93254cdd5ad9e02a953a38099ea b/fuzzers/corpora/commit_graph/506092de91dcf93254cdd5ad9e02a953a38099ea
new file mode 100644
index 000000000..64c5405f2
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/506092de91dcf93254cdd5ad9e02a953a38099ea
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/50e934fb52d9bc5cd2a531adced1cad7f102a112 b/fuzzers/corpora/commit_graph/50e934fb52d9bc5cd2a531adced1cad7f102a112
new file mode 100644
index 000000000..b63017975
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/50e934fb52d9bc5cd2a531adced1cad7f102a112
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/512e49a9e789656964988950009e6534907e6317 b/fuzzers/corpora/commit_graph/512e49a9e789656964988950009e6534907e6317
new file mode 100644
index 000000000..7cf8e3181
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/512e49a9e789656964988950009e6534907e6317
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/51404149f1ea30ee6959fafe81a52acabed97e9e b/fuzzers/corpora/commit_graph/51404149f1ea30ee6959fafe81a52acabed97e9e
new file mode 100644
index 000000000..394e4bfaa
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/51404149f1ea30ee6959fafe81a52acabed97e9e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5150f8a67399ee16178a2b08198cf91a90c0e53e b/fuzzers/corpora/commit_graph/5150f8a67399ee16178a2b08198cf91a90c0e53e
new file mode 100644
index 000000000..c0867a0a7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5150f8a67399ee16178a2b08198cf91a90c0e53e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/51a1fd23dfe5a8062cd4601d235509247f3bc2dc b/fuzzers/corpora/commit_graph/51a1fd23dfe5a8062cd4601d235509247f3bc2dc
new file mode 100644
index 000000000..c44892873
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/51a1fd23dfe5a8062cd4601d235509247f3bc2dc
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/51a963486f041a60c422f0dd6da3b69c52f12fb7 b/fuzzers/corpora/commit_graph/51a963486f041a60c422f0dd6da3b69c52f12fb7
new file mode 100644
index 000000000..f8a1c562e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/51a963486f041a60c422f0dd6da3b69c52f12fb7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/51fbf57a2a35ec33164838fa254fe605a3c868e9 b/fuzzers/corpora/commit_graph/51fbf57a2a35ec33164838fa254fe605a3c868e9
new file mode 100644
index 000000000..d0c77cd13
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/51fbf57a2a35ec33164838fa254fe605a3c868e9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/53068b9f9cb54bb52d076e9602ccd55f169ef39a b/fuzzers/corpora/commit_graph/53068b9f9cb54bb52d076e9602ccd55f169ef39a
new file mode 100644
index 000000000..bed0af620
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/53068b9f9cb54bb52d076e9602ccd55f169ef39a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5314619e15fa5ee67df44481b8213a53786d39c5 b/fuzzers/corpora/commit_graph/5314619e15fa5ee67df44481b8213a53786d39c5
new file mode 100644
index 000000000..a00e14dac
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5314619e15fa5ee67df44481b8213a53786d39c5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/533f5f00275968129846522fe01e2819746272eb b/fuzzers/corpora/commit_graph/533f5f00275968129846522fe01e2819746272eb
new file mode 100644
index 000000000..0830b01dc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/533f5f00275968129846522fe01e2819746272eb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/53a62799135c282435a17e032deda03eaf9daf0f b/fuzzers/corpora/commit_graph/53a62799135c282435a17e032deda03eaf9daf0f
new file mode 100644
index 000000000..f6bfddbef
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/53a62799135c282435a17e032deda03eaf9daf0f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/53c9d5cd849977e523d92dd2d639e9b0e721be50 b/fuzzers/corpora/commit_graph/53c9d5cd849977e523d92dd2d639e9b0e721be50
new file mode 100644
index 000000000..ed30c5e7b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/53c9d5cd849977e523d92dd2d639e9b0e721be50
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/54767a0bb3b96d39f5b2004ce3f274465f1a927e b/fuzzers/corpora/commit_graph/54767a0bb3b96d39f5b2004ce3f274465f1a927e
new file mode 100644
index 000000000..fd9a0ac65
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/54767a0bb3b96d39f5b2004ce3f274465f1a927e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/548de37dbe6a3829b73d976996ec9838cf608554 b/fuzzers/corpora/commit_graph/548de37dbe6a3829b73d976996ec9838cf608554
new file mode 100644
index 000000000..89772e200
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/548de37dbe6a3829b73d976996ec9838cf608554
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5522cefa54b798ea4aba8ef2a42ad248a7fb02ee b/fuzzers/corpora/commit_graph/5522cefa54b798ea4aba8ef2a42ad248a7fb02ee
new file mode 100644
index 000000000..6a4da7812
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5522cefa54b798ea4aba8ef2a42ad248a7fb02ee
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/554fab3eef5d8709f06d1d4319efe5c0c437421b b/fuzzers/corpora/commit_graph/554fab3eef5d8709f06d1d4319efe5c0c437421b
new file mode 100644
index 000000000..7a54bd0fe
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/554fab3eef5d8709f06d1d4319efe5c0c437421b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/567fe73919dae39b0bcb78b03d655643a71714a8 b/fuzzers/corpora/commit_graph/567fe73919dae39b0bcb78b03d655643a71714a8
new file mode 100644
index 000000000..56b1e141a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/567fe73919dae39b0bcb78b03d655643a71714a8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5717a281aa722ee4a32dfa1cc72fc5d6081f6755 b/fuzzers/corpora/commit_graph/5717a281aa722ee4a32dfa1cc72fc5d6081f6755
new file mode 100644
index 000000000..77f0e516e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5717a281aa722ee4a32dfa1cc72fc5d6081f6755
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/577d814e0be43df9321c5b27119c398bd00a00c5 b/fuzzers/corpora/commit_graph/577d814e0be43df9321c5b27119c398bd00a00c5
new file mode 100644
index 000000000..c892728c8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/577d814e0be43df9321c5b27119c398bd00a00c5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/58680611707c6188f9f067f8747b699cd2fe82d3 b/fuzzers/corpora/commit_graph/58680611707c6188f9f067f8747b699cd2fe82d3
new file mode 100644
index 000000000..81efaf38a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/58680611707c6188f9f067f8747b699cd2fe82d3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5915b7f91dd43ec37a4718061c90cbec2686b916 b/fuzzers/corpora/commit_graph/5915b7f91dd43ec37a4718061c90cbec2686b916
new file mode 100644
index 000000000..f22d2aa7f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5915b7f91dd43ec37a4718061c90cbec2686b916
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/599516e368ff621dd06d8450837350f4e9558c38 b/fuzzers/corpora/commit_graph/599516e368ff621dd06d8450837350f4e9558c38
new file mode 100644
index 000000000..6aff8eef6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/599516e368ff621dd06d8450837350f4e9558c38
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5a2d01d141e4d523e718c30e20cb07c3ad98f33d b/fuzzers/corpora/commit_graph/5a2d01d141e4d523e718c30e20cb07c3ad98f33d
new file mode 100644
index 000000000..fb20c583a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5a2d01d141e4d523e718c30e20cb07c3ad98f33d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5a9803ef8cd88d1e8f1d6e5920b8afd170cafb11 b/fuzzers/corpora/commit_graph/5a9803ef8cd88d1e8f1d6e5920b8afd170cafb11
new file mode 100644
index 000000000..38c2c086a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5a9803ef8cd88d1e8f1d6e5920b8afd170cafb11
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5ba93c9db0cff93f52b521d7420e43f6eda2784f b/fuzzers/corpora/commit_graph/5ba93c9db0cff93f52b521d7420e43f6eda2784f
new file mode 100644
index 000000000..f76dd238a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5ba93c9db0cff93f52b521d7420e43f6eda2784f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5bf0ca772092e6fa34b6822f61a1b1c3d7f2c6e3 b/fuzzers/corpora/commit_graph/5bf0ca772092e6fa34b6822f61a1b1c3d7f2c6e3
new file mode 100644
index 000000000..06dd1e1a8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5bf0ca772092e6fa34b6822f61a1b1c3d7f2c6e3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5cfbfb3e12b629dc9f74baf0a8741345ec288795 b/fuzzers/corpora/commit_graph/5cfbfb3e12b629dc9f74baf0a8741345ec288795
new file mode 100644
index 000000000..73e257d4b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5cfbfb3e12b629dc9f74baf0a8741345ec288795
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5d8cc97b739c39820b761b6551d34dd647da6816 b/fuzzers/corpora/commit_graph/5d8cc97b739c39820b761b6551d34dd647da6816
new file mode 100644
index 000000000..7a241f330
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5d8cc97b739c39820b761b6551d34dd647da6816
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5dcbb3e1c2fc9a191dd3f3443b86f6bc38c39e37 b/fuzzers/corpora/commit_graph/5dcbb3e1c2fc9a191dd3f3443b86f6bc38c39e37
new file mode 100644
index 000000000..04a1639c6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5dcbb3e1c2fc9a191dd3f3443b86f6bc38c39e37
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5ec17d081aef9872f746e88ad8b03553719f9c36 b/fuzzers/corpora/commit_graph/5ec17d081aef9872f746e88ad8b03553719f9c36
new file mode 100644
index 000000000..84fa131ec
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5ec17d081aef9872f746e88ad8b03553719f9c36
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/5f88e3ba60c11be25c47a842763d8870d23cc7f2 b/fuzzers/corpora/commit_graph/5f88e3ba60c11be25c47a842763d8870d23cc7f2
new file mode 100644
index 000000000..36693877d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/5f88e3ba60c11be25c47a842763d8870d23cc7f2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6045e4d2bf85013c78a32e71b014ba3d4a4b7c61 b/fuzzers/corpora/commit_graph/6045e4d2bf85013c78a32e71b014ba3d4a4b7c61
new file mode 100644
index 000000000..5ebec5aee
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6045e4d2bf85013c78a32e71b014ba3d4a4b7c61
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/615c7ba7ffbce955ffd964682e2a0f7ef3c767e4 b/fuzzers/corpora/commit_graph/615c7ba7ffbce955ffd964682e2a0f7ef3c767e4
new file mode 100644
index 000000000..8360672e4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/615c7ba7ffbce955ffd964682e2a0f7ef3c767e4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6189f29cbbe88ac6cb32fdefecda1bd6194332a6 b/fuzzers/corpora/commit_graph/6189f29cbbe88ac6cb32fdefecda1bd6194332a6
new file mode 100644
index 000000000..40ec5b1bb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6189f29cbbe88ac6cb32fdefecda1bd6194332a6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/627224cb8484c62992dcbc4cdebdbfa48a3c021a b/fuzzers/corpora/commit_graph/627224cb8484c62992dcbc4cdebdbfa48a3c021a
new file mode 100644
index 000000000..f73b59d91
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/627224cb8484c62992dcbc4cdebdbfa48a3c021a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/629fff0962d298a7283a3d1e1d1b940dfef9b315 b/fuzzers/corpora/commit_graph/629fff0962d298a7283a3d1e1d1b940dfef9b315
new file mode 100644
index 000000000..1c0c2c482
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/629fff0962d298a7283a3d1e1d1b940dfef9b315
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6322594cff2a99d0abb1139e6a43b06df76d539a b/fuzzers/corpora/commit_graph/6322594cff2a99d0abb1139e6a43b06df76d539a
new file mode 100644
index 000000000..4dabbce05
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6322594cff2a99d0abb1139e6a43b06df76d539a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/63de5e8e042222d53bf05640c87da376aefb76cc b/fuzzers/corpora/commit_graph/63de5e8e042222d53bf05640c87da376aefb76cc
new file mode 100644
index 000000000..2fd95a3fd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/63de5e8e042222d53bf05640c87da376aefb76cc
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/647dbb1d05fe0fab685bfe126bd9ac3a12b6bccf b/fuzzers/corpora/commit_graph/647dbb1d05fe0fab685bfe126bd9ac3a12b6bccf
new file mode 100644
index 000000000..245d46b18
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/647dbb1d05fe0fab685bfe126bd9ac3a12b6bccf
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/647e5e265d8d1079784fc2a3da25f7ba58126acd b/fuzzers/corpora/commit_graph/647e5e265d8d1079784fc2a3da25f7ba58126acd
new file mode 100644
index 000000000..633a2a3db
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/647e5e265d8d1079784fc2a3da25f7ba58126acd
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/653bd480dfd1e5f4bdca702aba3dfd8da0c204b7 b/fuzzers/corpora/commit_graph/653bd480dfd1e5f4bdca702aba3dfd8da0c204b7
new file mode 100644
index 000000000..d12360225
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/653bd480dfd1e5f4bdca702aba3dfd8da0c204b7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/65485740a465377213c80fa68028727f281299fb b/fuzzers/corpora/commit_graph/65485740a465377213c80fa68028727f281299fb
new file mode 100644
index 000000000..c100bdb51
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/65485740a465377213c80fa68028727f281299fb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6551f8c8c3028006d0cc4997943df8a86ee3f598 b/fuzzers/corpora/commit_graph/6551f8c8c3028006d0cc4997943df8a86ee3f598
new file mode 100644
index 000000000..0ff4ddab7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6551f8c8c3028006d0cc4997943df8a86ee3f598
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/67799e79d33883510f85ae9705ab3932862128a2 b/fuzzers/corpora/commit_graph/67799e79d33883510f85ae9705ab3932862128a2
new file mode 100644
index 000000000..2782b4f37
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/67799e79d33883510f85ae9705ab3932862128a2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/67b475481e5a21351b49789874adbc988aefd64c b/fuzzers/corpora/commit_graph/67b475481e5a21351b49789874adbc988aefd64c
new file mode 100644
index 000000000..263753aaf
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/67b475481e5a21351b49789874adbc988aefd64c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/67e5a649967dee002d1c181e079748c404e29767 b/fuzzers/corpora/commit_graph/67e5a649967dee002d1c181e079748c404e29767
new file mode 100644
index 000000000..3bb8714af
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/67e5a649967dee002d1c181e079748c404e29767
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/687424a4a31a66a78d1637c680c9c10746741007 b/fuzzers/corpora/commit_graph/687424a4a31a66a78d1637c680c9c10746741007
new file mode 100644
index 000000000..6b26c194a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/687424a4a31a66a78d1637c680c9c10746741007
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/68fa6dd52832657cb8dd7e1485d6fbafd4e93903 b/fuzzers/corpora/commit_graph/68fa6dd52832657cb8dd7e1485d6fbafd4e93903
new file mode 100644
index 000000000..fb966ffe9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/68fa6dd52832657cb8dd7e1485d6fbafd4e93903
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/691696af1c042115f4d9f9b8e24f7b8c06ed189b b/fuzzers/corpora/commit_graph/691696af1c042115f4d9f9b8e24f7b8c06ed189b
new file mode 100644
index 000000000..e407bd3c7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/691696af1c042115f4d9f9b8e24f7b8c06ed189b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6a80152f9b1afa3a3080bf3f6aa48e84c2e18497 b/fuzzers/corpora/commit_graph/6a80152f9b1afa3a3080bf3f6aa48e84c2e18497
new file mode 100644
index 000000000..a706cb042
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6a80152f9b1afa3a3080bf3f6aa48e84c2e18497
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6af27e4cf4c7bcce128a5949ee27fc73ab2cc71e b/fuzzers/corpora/commit_graph/6af27e4cf4c7bcce128a5949ee27fc73ab2cc71e
new file mode 100644
index 000000000..d0b2fd2d8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6af27e4cf4c7bcce128a5949ee27fc73ab2cc71e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6afd8f82d5639b774de0dfd418ae85322f4168dd b/fuzzers/corpora/commit_graph/6afd8f82d5639b774de0dfd418ae85322f4168dd
new file mode 100644
index 000000000..7840c31b1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6afd8f82d5639b774de0dfd418ae85322f4168dd
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6c64a9e26e0e1480bb5e60b7044ca6ce17104a80 b/fuzzers/corpora/commit_graph/6c64a9e26e0e1480bb5e60b7044ca6ce17104a80
new file mode 100644
index 000000000..752046b9a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6c64a9e26e0e1480bb5e60b7044ca6ce17104a80
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6c850c17db130ca0152f7c75562fa191f7ef89de b/fuzzers/corpora/commit_graph/6c850c17db130ca0152f7c75562fa191f7ef89de
new file mode 100644
index 000000000..a7f693ba4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6c850c17db130ca0152f7c75562fa191f7ef89de
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6c9afe4527371a2baf33c5e220e4ca21a3207f94 b/fuzzers/corpora/commit_graph/6c9afe4527371a2baf33c5e220e4ca21a3207f94
new file mode 100644
index 000000000..d7b8ffca0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6c9afe4527371a2baf33c5e220e4ca21a3207f94
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6ce3d40b0225923a7f4123a919b1c5d70841fad7 b/fuzzers/corpora/commit_graph/6ce3d40b0225923a7f4123a919b1c5d70841fad7
new file mode 100644
index 000000000..3a2836b2c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6ce3d40b0225923a7f4123a919b1c5d70841fad7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6cfd064aa6197813eb18f38df967ae4cdba9c6da b/fuzzers/corpora/commit_graph/6cfd064aa6197813eb18f38df967ae4cdba9c6da
new file mode 100644
index 000000000..51778d55c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6cfd064aa6197813eb18f38df967ae4cdba9c6da
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6e6675676c53bcddc870e06605d2432e3429f224 b/fuzzers/corpora/commit_graph/6e6675676c53bcddc870e06605d2432e3429f224
new file mode 100644
index 000000000..1ddebeff1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6e6675676c53bcddc870e06605d2432e3429f224
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6e6e82579b7abae2b43d90448d3f2ead4dfcba78 b/fuzzers/corpora/commit_graph/6e6e82579b7abae2b43d90448d3f2ead4dfcba78
new file mode 100644
index 000000000..a528901ac
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6e6e82579b7abae2b43d90448d3f2ead4dfcba78
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6f13d23c75a562eddefafe85e208e602832294e2 b/fuzzers/corpora/commit_graph/6f13d23c75a562eddefafe85e208e602832294e2
new file mode 100644
index 000000000..49a53932f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6f13d23c75a562eddefafe85e208e602832294e2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/6fed59b0472927f5d2396d0ee4d7fd13579377ce b/fuzzers/corpora/commit_graph/6fed59b0472927f5d2396d0ee4d7fd13579377ce
new file mode 100644
index 000000000..6b3970fbf
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/6fed59b0472927f5d2396d0ee4d7fd13579377ce
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/71f7724196f9f8fcfe3ee0161a84893bb9c4ab11 b/fuzzers/corpora/commit_graph/71f7724196f9f8fcfe3ee0161a84893bb9c4ab11
new file mode 100644
index 000000000..9e5c8ddb3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/71f7724196f9f8fcfe3ee0161a84893bb9c4ab11
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7335ecb1d41e713bf3909adf5802b90e22bc1581 b/fuzzers/corpora/commit_graph/7335ecb1d41e713bf3909adf5802b90e22bc1581
new file mode 100644
index 000000000..02e2fa6d1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7335ecb1d41e713bf3909adf5802b90e22bc1581
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/73afaa73175f461e1d19d5138e055c1649926dfe b/fuzzers/corpora/commit_graph/73afaa73175f461e1d19d5138e055c1649926dfe
new file mode 100644
index 000000000..0f45e0bdb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/73afaa73175f461e1d19d5138e055c1649926dfe
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/73e2fcb45c4df90d19091056b235e7a317631a62 b/fuzzers/corpora/commit_graph/73e2fcb45c4df90d19091056b235e7a317631a62
new file mode 100644
index 000000000..549eeb306
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/73e2fcb45c4df90d19091056b235e7a317631a62
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/741cb2d5ae11b0a9e0608b58ec7284d75129a1f2 b/fuzzers/corpora/commit_graph/741cb2d5ae11b0a9e0608b58ec7284d75129a1f2
new file mode 100644
index 000000000..a16738d6f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/741cb2d5ae11b0a9e0608b58ec7284d75129a1f2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7431bb0097a9bb52e1ceaaa8674a13cd3486a387 b/fuzzers/corpora/commit_graph/7431bb0097a9bb52e1ceaaa8674a13cd3486a387
new file mode 100644
index 000000000..d681b26cd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7431bb0097a9bb52e1ceaaa8674a13cd3486a387
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7455b805995d0c96ac12f8a1c1264caaffcfac1c b/fuzzers/corpora/commit_graph/7455b805995d0c96ac12f8a1c1264caaffcfac1c
new file mode 100644
index 000000000..b3d2620ff
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7455b805995d0c96ac12f8a1c1264caaffcfac1c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/74e39b8a82fc06f9ed8f83ea30545ddf6df66811 b/fuzzers/corpora/commit_graph/74e39b8a82fc06f9ed8f83ea30545ddf6df66811
new file mode 100644
index 000000000..3cc9debcb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/74e39b8a82fc06f9ed8f83ea30545ddf6df66811
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/75d51e413d3e916560dc0c2ee5092d2f4972aec1 b/fuzzers/corpora/commit_graph/75d51e413d3e916560dc0c2ee5092d2f4972aec1
new file mode 100644
index 000000000..68f34e7cc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/75d51e413d3e916560dc0c2ee5092d2f4972aec1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/75e068964ea6beb7310a154d763de74a70071f48 b/fuzzers/corpora/commit_graph/75e068964ea6beb7310a154d763de74a70071f48
new file mode 100644
index 000000000..a08ee5890
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/75e068964ea6beb7310a154d763de74a70071f48
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/763bf498dd847bd2b4af7b611199619bd428bea6 b/fuzzers/corpora/commit_graph/763bf498dd847bd2b4af7b611199619bd428bea6
new file mode 100644
index 000000000..4c2893554
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/763bf498dd847bd2b4af7b611199619bd428bea6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/77064ae04581a3c6d2a77158ef1a0b1e60db414a b/fuzzers/corpora/commit_graph/77064ae04581a3c6d2a77158ef1a0b1e60db414a
new file mode 100644
index 000000000..fbd0ca79e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/77064ae04581a3c6d2a77158ef1a0b1e60db414a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/783bb14d68021061f592601607f40fe232ad17c4 b/fuzzers/corpora/commit_graph/783bb14d68021061f592601607f40fe232ad17c4
new file mode 100644
index 000000000..3cfa562ac
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/783bb14d68021061f592601607f40fe232ad17c4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7862814cb684310b54ef920b35403515efaba13c b/fuzzers/corpora/commit_graph/7862814cb684310b54ef920b35403515efaba13c
new file mode 100644
index 000000000..3066626ba
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7862814cb684310b54ef920b35403515efaba13c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/791fd85b6ffb2429e9fa5ba29eebdce214ad88c7 b/fuzzers/corpora/commit_graph/791fd85b6ffb2429e9fa5ba29eebdce214ad88c7
new file mode 100644
index 000000000..2c4739bb8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/791fd85b6ffb2429e9fa5ba29eebdce214ad88c7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/79396d4f6142a53e26e14aa6ccb4afb4fd8fc580 b/fuzzers/corpora/commit_graph/79396d4f6142a53e26e14aa6ccb4afb4fd8fc580
new file mode 100644
index 000000000..ef5434203
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/79396d4f6142a53e26e14aa6ccb4afb4fd8fc580
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/79661b8e529e2182d5c612faba9f26e32a122b78 b/fuzzers/corpora/commit_graph/79661b8e529e2182d5c612faba9f26e32a122b78
new file mode 100644
index 000000000..75ebe29ce
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/79661b8e529e2182d5c612faba9f26e32a122b78
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7969143acb3334bffac46c6dfd96362c81644191 b/fuzzers/corpora/commit_graph/7969143acb3334bffac46c6dfd96362c81644191
new file mode 100644
index 000000000..6ea2e6681
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7969143acb3334bffac46c6dfd96362c81644191
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/79d84866dc8c067508c02516b65c0e48cf689b56 b/fuzzers/corpora/commit_graph/79d84866dc8c067508c02516b65c0e48cf689b56
new file mode 100644
index 000000000..3080da739
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/79d84866dc8c067508c02516b65c0e48cf689b56
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7b61f8f4a96e309bbe64ed82637fc81492a9652f b/fuzzers/corpora/commit_graph/7b61f8f4a96e309bbe64ed82637fc81492a9652f
new file mode 100644
index 000000000..28d93b7a1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7b61f8f4a96e309bbe64ed82637fc81492a9652f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7b8123f973edfb0f3cab027c0cd6b8efc7b11d6b b/fuzzers/corpora/commit_graph/7b8123f973edfb0f3cab027c0cd6b8efc7b11d6b
new file mode 100644
index 000000000..1c6699bc4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7b8123f973edfb0f3cab027c0cd6b8efc7b11d6b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7b8dd3093efba07f7a4d3bab4b90b8f6e4f28bfb b/fuzzers/corpora/commit_graph/7b8dd3093efba07f7a4d3bab4b90b8f6e4f28bfb
new file mode 100644
index 000000000..3e686e9d5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7b8dd3093efba07f7a4d3bab4b90b8f6e4f28bfb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7cc771aab0f3be7730881a46d952ae0a06958201 b/fuzzers/corpora/commit_graph/7cc771aab0f3be7730881a46d952ae0a06958201
new file mode 100644
index 000000000..ba94bfe7d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7cc771aab0f3be7730881a46d952ae0a06958201
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7d177f4207de78d50df2493a3bc07f2cd578b363 b/fuzzers/corpora/commit_graph/7d177f4207de78d50df2493a3bc07f2cd578b363
new file mode 100644
index 000000000..a936354f3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7d177f4207de78d50df2493a3bc07f2cd578b363
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7d2df075f3e73ea9809c31586c37ece0f568b7fa b/fuzzers/corpora/commit_graph/7d2df075f3e73ea9809c31586c37ece0f568b7fa
new file mode 100644
index 000000000..897276b67
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7d2df075f3e73ea9809c31586c37ece0f568b7fa
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7d386e68e4c733a1fb11c0117f379fb4b9955fbb b/fuzzers/corpora/commit_graph/7d386e68e4c733a1fb11c0117f379fb4b9955fbb
new file mode 100644
index 000000000..f4f4d75bd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7d386e68e4c733a1fb11c0117f379fb4b9955fbb
@@ -0,0 +1 @@
+Øúö \ No newline at end of file
diff --git a/fuzzers/corpora/commit_graph/7e4260830352479d29310bd6e1022e19a68ffe76 b/fuzzers/corpora/commit_graph/7e4260830352479d29310bd6e1022e19a68ffe76
new file mode 100644
index 000000000..f478389ff
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7e4260830352479d29310bd6e1022e19a68ffe76
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7e4dfdae52be18cf95555c2eb1f54af7f69c6dde b/fuzzers/corpora/commit_graph/7e4dfdae52be18cf95555c2eb1f54af7f69c6dde
new file mode 100644
index 000000000..0f6d97684
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7e4dfdae52be18cf95555c2eb1f54af7f69c6dde
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7eafedf7e7f20e86ecdf9ba51febf8492bdbc1f1 b/fuzzers/corpora/commit_graph/7eafedf7e7f20e86ecdf9ba51febf8492bdbc1f1
new file mode 100644
index 000000000..ae5f7c56c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7eafedf7e7f20e86ecdf9ba51febf8492bdbc1f1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/7ef1829a378d66b1dd70a767729127a0dc5edcae b/fuzzers/corpora/commit_graph/7ef1829a378d66b1dd70a767729127a0dc5edcae
new file mode 100644
index 000000000..e5d735591
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/7ef1829a378d66b1dd70a767729127a0dc5edcae
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/80b7d2b9d7e8c8fd7ae239b8d307b592f97ee000 b/fuzzers/corpora/commit_graph/80b7d2b9d7e8c8fd7ae239b8d307b592f97ee000
new file mode 100644
index 000000000..58ddc12d3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/80b7d2b9d7e8c8fd7ae239b8d307b592f97ee000
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/810f577ff5c1af7807a26226af912687558158cd b/fuzzers/corpora/commit_graph/810f577ff5c1af7807a26226af912687558158cd
new file mode 100644
index 000000000..be8be9c08
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/810f577ff5c1af7807a26226af912687558158cd
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/81603f1fe8d8e29005418d0fc9a9b33972366038 b/fuzzers/corpora/commit_graph/81603f1fe8d8e29005418d0fc9a9b33972366038
new file mode 100644
index 000000000..d9cb488e0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/81603f1fe8d8e29005418d0fc9a9b33972366038
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/81c8b4d6884f954935fa4a8e828c4637db04b61a b/fuzzers/corpora/commit_graph/81c8b4d6884f954935fa4a8e828c4637db04b61a
new file mode 100644
index 000000000..47ae17be3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/81c8b4d6884f954935fa4a8e828c4637db04b61a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8226846e9b092561f85cc2956ab89d8cc1ae61e0 b/fuzzers/corpora/commit_graph/8226846e9b092561f85cc2956ab89d8cc1ae61e0
new file mode 100644
index 000000000..80d1cd91c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8226846e9b092561f85cc2956ab89d8cc1ae61e0
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/825cfceea434e2392cce161356e3cb5f81ec2b3a b/fuzzers/corpora/commit_graph/825cfceea434e2392cce161356e3cb5f81ec2b3a
new file mode 100644
index 000000000..01f87eda7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/825cfceea434e2392cce161356e3cb5f81ec2b3a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/82603febce83d95adf68b85cabf15d43ca0c4ee9 b/fuzzers/corpora/commit_graph/82603febce83d95adf68b85cabf15d43ca0c4ee9
new file mode 100644
index 000000000..d828b05af
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/82603febce83d95adf68b85cabf15d43ca0c4ee9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/827f0826cc4156e19b4c4938bec74e38de62fe9c b/fuzzers/corpora/commit_graph/827f0826cc4156e19b4c4938bec74e38de62fe9c
new file mode 100644
index 000000000..a391d62a9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/827f0826cc4156e19b4c4938bec74e38de62fe9c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8486397ff8d1156249676c19b419a7758ff53f9a b/fuzzers/corpora/commit_graph/8486397ff8d1156249676c19b419a7758ff53f9a
new file mode 100644
index 000000000..dac9bbe4c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8486397ff8d1156249676c19b419a7758ff53f9a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/84d99ee359bec1b8ee0f59e9bd96f1da062030b7 b/fuzzers/corpora/commit_graph/84d99ee359bec1b8ee0f59e9bd96f1da062030b7
new file mode 100644
index 000000000..a2e7cf305
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/84d99ee359bec1b8ee0f59e9bd96f1da062030b7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/84e629bc7416039f1feb81fa9168d7c1ee3141c2 b/fuzzers/corpora/commit_graph/84e629bc7416039f1feb81fa9168d7c1ee3141c2
new file mode 100644
index 000000000..8ae4e395c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/84e629bc7416039f1feb81fa9168d7c1ee3141c2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/84e885752179076fb38739ca7bc4345716bee56a b/fuzzers/corpora/commit_graph/84e885752179076fb38739ca7bc4345716bee56a
new file mode 100644
index 000000000..dd0c42692
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/84e885752179076fb38739ca7bc4345716bee56a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/859ef05494c8070057810b5c20df00fc81f81cf5 b/fuzzers/corpora/commit_graph/859ef05494c8070057810b5c20df00fc81f81cf5
new file mode 100644
index 000000000..2e3f29900
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/859ef05494c8070057810b5c20df00fc81f81cf5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/859fe592f33abc1d959c0e73ecd6cd4bffe23a97 b/fuzzers/corpora/commit_graph/859fe592f33abc1d959c0e73ecd6cd4bffe23a97
new file mode 100644
index 000000000..5289c8e1c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/859fe592f33abc1d959c0e73ecd6cd4bffe23a97
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/860da5e8a468805b76a44b9ac99b4575be16ea15 b/fuzzers/corpora/commit_graph/860da5e8a468805b76a44b9ac99b4575be16ea15
new file mode 100644
index 000000000..c8b03da24
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/860da5e8a468805b76a44b9ac99b4575be16ea15
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/865e415745cead02a826f058a5ee49099bdf9562 b/fuzzers/corpora/commit_graph/865e415745cead02a826f058a5ee49099bdf9562
new file mode 100644
index 000000000..a4ce65883
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/865e415745cead02a826f058a5ee49099bdf9562
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/878bfce051a9c7462847d4e99b7e926dc821b7b8 b/fuzzers/corpora/commit_graph/878bfce051a9c7462847d4e99b7e926dc821b7b8
new file mode 100644
index 000000000..efb0bc551
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/878bfce051a9c7462847d4e99b7e926dc821b7b8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/880492e4dc7259577c227bb4f075d7165e875c29 b/fuzzers/corpora/commit_graph/880492e4dc7259577c227bb4f075d7165e875c29
new file mode 100644
index 000000000..c977dffaf
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/880492e4dc7259577c227bb4f075d7165e875c29
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/88b7de1bd1c96454a1350286d115c0ee368511f9 b/fuzzers/corpora/commit_graph/88b7de1bd1c96454a1350286d115c0ee368511f9
new file mode 100644
index 000000000..7261eec17
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/88b7de1bd1c96454a1350286d115c0ee368511f9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/896268e4a5775b7ce33923ac6daeb0810420c55b b/fuzzers/corpora/commit_graph/896268e4a5775b7ce33923ac6daeb0810420c55b
new file mode 100644
index 000000000..0897bdad0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/896268e4a5775b7ce33923ac6daeb0810420c55b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8978f8da89f9652878edabad164f5513ef508f27 b/fuzzers/corpora/commit_graph/8978f8da89f9652878edabad164f5513ef508f27
new file mode 100644
index 000000000..0dd9ba492
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8978f8da89f9652878edabad164f5513ef508f27
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/89a6525b7db0e6ec211a484efd2880abef928d4e b/fuzzers/corpora/commit_graph/89a6525b7db0e6ec211a484efd2880abef928d4e
new file mode 100644
index 000000000..e5dd1cdf8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/89a6525b7db0e6ec211a484efd2880abef928d4e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8ae86cba2bba6664fc5eb97be8e9777b8825d823 b/fuzzers/corpora/commit_graph/8ae86cba2bba6664fc5eb97be8e9777b8825d823
new file mode 100644
index 000000000..04a4aa532
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8ae86cba2bba6664fc5eb97be8e9777b8825d823
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8b845fbd2aa14e4f83c4dbc8b4b0b54d06482acd b/fuzzers/corpora/commit_graph/8b845fbd2aa14e4f83c4dbc8b4b0b54d06482acd
new file mode 100644
index 000000000..c711793c8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8b845fbd2aa14e4f83c4dbc8b4b0b54d06482acd
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8c4121e6ce5956cfa408b980f16d276f456374dc b/fuzzers/corpora/commit_graph/8c4121e6ce5956cfa408b980f16d276f456374dc
new file mode 100644
index 000000000..1ba18917f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8c4121e6ce5956cfa408b980f16d276f456374dc
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8cb6a5b8ab41e3d27668d5735b5c09ff1f2eab65 b/fuzzers/corpora/commit_graph/8cb6a5b8ab41e3d27668d5735b5c09ff1f2eab65
new file mode 100644
index 000000000..e23d11256
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8cb6a5b8ab41e3d27668d5735b5c09ff1f2eab65
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8d80a70ffd362a89b88663e27f11e8ab69b70c1b b/fuzzers/corpora/commit_graph/8d80a70ffd362a89b88663e27f11e8ab69b70c1b
new file mode 100644
index 000000000..02f765ea2
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8d80a70ffd362a89b88663e27f11e8ab69b70c1b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8db603c1720b3680047f831f2ea9862567a7cdc4 b/fuzzers/corpora/commit_graph/8db603c1720b3680047f831f2ea9862567a7cdc4
new file mode 100644
index 000000000..d02cb0354
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8db603c1720b3680047f831f2ea9862567a7cdc4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8dd40b2d27c7dd4b986c35d87f826da287c09c4c b/fuzzers/corpora/commit_graph/8dd40b2d27c7dd4b986c35d87f826da287c09c4c
new file mode 100644
index 000000000..11aa235b1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8dd40b2d27c7dd4b986c35d87f826da287c09c4c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8e9d6e6408e5f708a1924e8370e687e2c202a4c4 b/fuzzers/corpora/commit_graph/8e9d6e6408e5f708a1924e8370e687e2c202a4c4
new file mode 100644
index 000000000..cbeb46b17
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8e9d6e6408e5f708a1924e8370e687e2c202a4c4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8f2dff1a30ee28e5985cb9379828aea5658d5849 b/fuzzers/corpora/commit_graph/8f2dff1a30ee28e5985cb9379828aea5658d5849
new file mode 100644
index 000000000..b7220c3cb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8f2dff1a30ee28e5985cb9379828aea5658d5849
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/8f7d18cdd6e605b85784ada14571fd5e5a184f2a b/fuzzers/corpora/commit_graph/8f7d18cdd6e605b85784ada14571fd5e5a184f2a
new file mode 100644
index 000000000..80fe175ba
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/8f7d18cdd6e605b85784ada14571fd5e5a184f2a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/903ae52f0ac9af8348038b12f9259741b0de42f1 b/fuzzers/corpora/commit_graph/903ae52f0ac9af8348038b12f9259741b0de42f1
new file mode 100644
index 000000000..da8c2209c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/903ae52f0ac9af8348038b12f9259741b0de42f1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9119e331f59e9337d419739c324f49d1bd62c8bf b/fuzzers/corpora/commit_graph/9119e331f59e9337d419739c324f49d1bd62c8bf
new file mode 100644
index 000000000..fc3a6963c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9119e331f59e9337d419739c324f49d1bd62c8bf
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/91d54d03b0917314ea1d67a70690df9247dd08d2 b/fuzzers/corpora/commit_graph/91d54d03b0917314ea1d67a70690df9247dd08d2
new file mode 100644
index 000000000..290da4da4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/91d54d03b0917314ea1d67a70690df9247dd08d2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/922da3b96725bfd0e3f6ce119f1e2249d53f9086 b/fuzzers/corpora/commit_graph/922da3b96725bfd0e3f6ce119f1e2249d53f9086
new file mode 100644
index 000000000..c3bb009f3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/922da3b96725bfd0e3f6ce119f1e2249d53f9086
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9277561e0524cccba2f851970b0d88ec4f4d3f5e b/fuzzers/corpora/commit_graph/9277561e0524cccba2f851970b0d88ec4f4d3f5e
new file mode 100644
index 000000000..07d1da19b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9277561e0524cccba2f851970b0d88ec4f4d3f5e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/92a4d571804026b7bbe957396185e079e756b894 b/fuzzers/corpora/commit_graph/92a4d571804026b7bbe957396185e079e756b894
new file mode 100644
index 000000000..63b98b3b4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/92a4d571804026b7bbe957396185e079e756b894
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/931224cc80168fd362a360d99bab813ed7bbf8ce b/fuzzers/corpora/commit_graph/931224cc80168fd362a360d99bab813ed7bbf8ce
new file mode 100644
index 000000000..df27b3696
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/931224cc80168fd362a360d99bab813ed7bbf8ce
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/936ea5dad3bf023c552aa0bbeea8f7f66a11612c b/fuzzers/corpora/commit_graph/936ea5dad3bf023c552aa0bbeea8f7f66a11612c
new file mode 100644
index 000000000..847b537ac
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/936ea5dad3bf023c552aa0bbeea8f7f66a11612c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/93aa4e0b1864933dce0abc0df69fe3d261f117f2 b/fuzzers/corpora/commit_graph/93aa4e0b1864933dce0abc0df69fe3d261f117f2
new file mode 100644
index 000000000..ac830ca5f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/93aa4e0b1864933dce0abc0df69fe3d261f117f2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/93d5b084965cf1b09085c4079a972e25207b3659 b/fuzzers/corpora/commit_graph/93d5b084965cf1b09085c4079a972e25207b3659
new file mode 100644
index 000000000..02a711a98
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/93d5b084965cf1b09085c4079a972e25207b3659
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9443fd3468bcc0bc3ff8dfe765225f045ab43d0a b/fuzzers/corpora/commit_graph/9443fd3468bcc0bc3ff8dfe765225f045ab43d0a
new file mode 100644
index 000000000..d1667ca74
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9443fd3468bcc0bc3ff8dfe765225f045ab43d0a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9624c26cefb5804b7906147d262e81ee4000b6d6 b/fuzzers/corpora/commit_graph/9624c26cefb5804b7906147d262e81ee4000b6d6
new file mode 100644
index 000000000..4c1883146
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9624c26cefb5804b7906147d262e81ee4000b6d6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9890933a73f39208627bd36e2fe88a6d54343a74 b/fuzzers/corpora/commit_graph/9890933a73f39208627bd36e2fe88a6d54343a74
new file mode 100644
index 000000000..dfbb39dde
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9890933a73f39208627bd36e2fe88a6d54343a74
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/989dad0448e79af10040d5080f74eba2b8a401ba b/fuzzers/corpora/commit_graph/989dad0448e79af10040d5080f74eba2b8a401ba
new file mode 100644
index 000000000..202bbd65b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/989dad0448e79af10040d5080f74eba2b8a401ba
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/98ed4808b4a8da66a91fcea1be63be6371a7c7ac b/fuzzers/corpora/commit_graph/98ed4808b4a8da66a91fcea1be63be6371a7c7ac
new file mode 100644
index 000000000..b06a1674e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/98ed4808b4a8da66a91fcea1be63be6371a7c7ac
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9928e516b85e22fbad58d562d3b7e814d9ce812d b/fuzzers/corpora/commit_graph/9928e516b85e22fbad58d562d3b7e814d9ce812d
new file mode 100644
index 000000000..d1e5a0412
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9928e516b85e22fbad58d562d3b7e814d9ce812d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/994c7cc5599252b5628d89cd0ba4b5574d32bf00 b/fuzzers/corpora/commit_graph/994c7cc5599252b5628d89cd0ba4b5574d32bf00
new file mode 100644
index 000000000..d51d00d06
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/994c7cc5599252b5628d89cd0ba4b5574d32bf00
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/99c8557c2a02ea030de42869af42c1f7c77114db b/fuzzers/corpora/commit_graph/99c8557c2a02ea030de42869af42c1f7c77114db
new file mode 100644
index 000000000..18f5349b6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/99c8557c2a02ea030de42869af42c1f7c77114db
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9a14c867272f102b84efdba73662d318c3e51cfe b/fuzzers/corpora/commit_graph/9a14c867272f102b84efdba73662d318c3e51cfe
new file mode 100644
index 000000000..fc473b2b7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9a14c867272f102b84efdba73662d318c3e51cfe
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9a6f158c176d4a1982d541be2bc27a8afba4ea57 b/fuzzers/corpora/commit_graph/9a6f158c176d4a1982d541be2bc27a8afba4ea57
new file mode 100644
index 000000000..b99bc2032
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9a6f158c176d4a1982d541be2bc27a8afba4ea57
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9aa4af603192823a2fdc53d95ed36896bc3309b2 b/fuzzers/corpora/commit_graph/9aa4af603192823a2fdc53d95ed36896bc3309b2
new file mode 100644
index 000000000..c36e298fc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9aa4af603192823a2fdc53d95ed36896bc3309b2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9b40c2190123cec66af3b37212f6c567869efda3 b/fuzzers/corpora/commit_graph/9b40c2190123cec66af3b37212f6c567869efda3
new file mode 100644
index 000000000..166232492
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9b40c2190123cec66af3b37212f6c567869efda3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9b6268c11d78c35db5164f1346905e602b6a49fe b/fuzzers/corpora/commit_graph/9b6268c11d78c35db5164f1346905e602b6a49fe
new file mode 100644
index 000000000..4106e2037
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9b6268c11d78c35db5164f1346905e602b6a49fe
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9c6883ba5cedb7d711b12733d66ef1a1156dd0af b/fuzzers/corpora/commit_graph/9c6883ba5cedb7d711b12733d66ef1a1156dd0af
new file mode 100644
index 000000000..84a193c45
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9c6883ba5cedb7d711b12733d66ef1a1156dd0af
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9c85c90f44b454ce0d52882c447f5ecb8d303634 b/fuzzers/corpora/commit_graph/9c85c90f44b454ce0d52882c447f5ecb8d303634
new file mode 100644
index 000000000..e17438bf8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9c85c90f44b454ce0d52882c447f5ecb8d303634
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9cb7a2e89ec636da3fd41ecc49ebe25e5344e2c6 b/fuzzers/corpora/commit_graph/9cb7a2e89ec636da3fd41ecc49ebe25e5344e2c6
new file mode 100644
index 000000000..55f76fd22
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9cb7a2e89ec636da3fd41ecc49ebe25e5344e2c6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9d912dc5a3497e4b5b40b37202fc0ffbf5263666 b/fuzzers/corpora/commit_graph/9d912dc5a3497e4b5b40b37202fc0ffbf5263666
new file mode 100644
index 000000000..c71c31afc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9d912dc5a3497e4b5b40b37202fc0ffbf5263666
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9dcbafe8c5345194ee0ce7eb4f6efaeb55543626 b/fuzzers/corpora/commit_graph/9dcbafe8c5345194ee0ce7eb4f6efaeb55543626
new file mode 100644
index 000000000..42c5e7d3a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9dcbafe8c5345194ee0ce7eb4f6efaeb55543626
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/9f4b0f3d2d25e6405ba6093f24d0605327711573 b/fuzzers/corpora/commit_graph/9f4b0f3d2d25e6405ba6093f24d0605327711573
new file mode 100644
index 000000000..0dc94be84
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/9f4b0f3d2d25e6405ba6093f24d0605327711573
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a047bf683239fa208dbac09424b105820ac23f43 b/fuzzers/corpora/commit_graph/a047bf683239fa208dbac09424b105820ac23f43
new file mode 100644
index 000000000..925c86c6d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a047bf683239fa208dbac09424b105820ac23f43
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a1379dcd89ef5e73eabbfcc395113e3636e0ae09 b/fuzzers/corpora/commit_graph/a1379dcd89ef5e73eabbfcc395113e3636e0ae09
new file mode 100644
index 000000000..43d31b6d2
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a1379dcd89ef5e73eabbfcc395113e3636e0ae09
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a38c7ef56adabd0916abac514154b1f362d40434 b/fuzzers/corpora/commit_graph/a38c7ef56adabd0916abac514154b1f362d40434
new file mode 100644
index 000000000..944b4ea50
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a38c7ef56adabd0916abac514154b1f362d40434
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a38ec6ad4a8466b4feb88e67b16524e8f3feac64 b/fuzzers/corpora/commit_graph/a38ec6ad4a8466b4feb88e67b16524e8f3feac64
new file mode 100644
index 000000000..a9d1adbb3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a38ec6ad4a8466b4feb88e67b16524e8f3feac64
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a3fdea21020268b3b2409c1115d50697d9ae8f8c b/fuzzers/corpora/commit_graph/a3fdea21020268b3b2409c1115d50697d9ae8f8c
new file mode 100644
index 000000000..8d4f934fa
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a3fdea21020268b3b2409c1115d50697d9ae8f8c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a45f1987a444b2c27e90fc1477e8b0815f75383f b/fuzzers/corpora/commit_graph/a45f1987a444b2c27e90fc1477e8b0815f75383f
new file mode 100644
index 000000000..d211a8b1f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a45f1987a444b2c27e90fc1477e8b0815f75383f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a4682958fb7029384c0a01a4a1356ac6f2f44fe1 b/fuzzers/corpora/commit_graph/a4682958fb7029384c0a01a4a1356ac6f2f44fe1
new file mode 100644
index 000000000..e8f66dc88
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a4682958fb7029384c0a01a4a1356ac6f2f44fe1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a4de41561725960d6f48f210a4fb74d527f7b0c2 b/fuzzers/corpora/commit_graph/a4de41561725960d6f48f210a4fb74d527f7b0c2
new file mode 100644
index 000000000..ac4c41c9c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a4de41561725960d6f48f210a4fb74d527f7b0c2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a5935f34435ecdd6587ad4f77b20d479d3387dbe b/fuzzers/corpora/commit_graph/a5935f34435ecdd6587ad4f77b20d479d3387dbe
new file mode 100644
index 000000000..2e00f596b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a5935f34435ecdd6587ad4f77b20d479d3387dbe
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a5b394beb2b1d463ad80924a8c8c70584bf5c629 b/fuzzers/corpora/commit_graph/a5b394beb2b1d463ad80924a8c8c70584bf5c629
new file mode 100644
index 000000000..eb8f70052
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a5b394beb2b1d463ad80924a8c8c70584bf5c629
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a62bc806f8c98ba7986243c2185a0548a8dd57ef b/fuzzers/corpora/commit_graph/a62bc806f8c98ba7986243c2185a0548a8dd57ef
new file mode 100644
index 000000000..fb30d9e49
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a62bc806f8c98ba7986243c2185a0548a8dd57ef
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a7013e97948893e0118c686c06e332cc611bea7e b/fuzzers/corpora/commit_graph/a7013e97948893e0118c686c06e332cc611bea7e
new file mode 100644
index 000000000..ab501138e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a7013e97948893e0118c686c06e332cc611bea7e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a74f5df8c7f25c37c15c0f74ed50019d17338225 b/fuzzers/corpora/commit_graph/a74f5df8c7f25c37c15c0f74ed50019d17338225
new file mode 100644
index 000000000..b234c1583
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a74f5df8c7f25c37c15c0f74ed50019d17338225
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a7ab3559fb3da3f027e67091116253f3bdfd7828 b/fuzzers/corpora/commit_graph/a7ab3559fb3da3f027e67091116253f3bdfd7828
new file mode 100644
index 000000000..838337a5d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a7ab3559fb3da3f027e67091116253f3bdfd7828
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a845c8258a02022d447ea9249788b345f5504648 b/fuzzers/corpora/commit_graph/a845c8258a02022d447ea9249788b345f5504648
new file mode 100644
index 000000000..78311d95f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a845c8258a02022d447ea9249788b345f5504648
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a8d3e026e2393587eb170afb32e94ff0e1f8a8be b/fuzzers/corpora/commit_graph/a8d3e026e2393587eb170afb32e94ff0e1f8a8be
new file mode 100644
index 000000000..54457f3e5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a8d3e026e2393587eb170afb32e94ff0e1f8a8be
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a8d547e41ee21e163e65cf0a186d469dfa50ec19 b/fuzzers/corpora/commit_graph/a8d547e41ee21e163e65cf0a186d469dfa50ec19
new file mode 100644
index 000000000..52d265bcd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a8d547e41ee21e163e65cf0a186d469dfa50ec19
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a8fa22521dd6813e595cc0a9586ee71fff305fe2 b/fuzzers/corpora/commit_graph/a8fa22521dd6813e595cc0a9586ee71fff305fe2
new file mode 100644
index 000000000..5f9099585
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a8fa22521dd6813e595cc0a9586ee71fff305fe2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a9969442d585d9a53259c71c73b095701280eac5 b/fuzzers/corpora/commit_graph/a9969442d585d9a53259c71c73b095701280eac5
new file mode 100644
index 000000000..f75792824
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a9969442d585d9a53259c71c73b095701280eac5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/a99789d0ce2d7b937aaa8afa3cfc0f4ccd7be95f b/fuzzers/corpora/commit_graph/a99789d0ce2d7b937aaa8afa3cfc0f4ccd7be95f
new file mode 100644
index 000000000..471add50a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/a99789d0ce2d7b937aaa8afa3cfc0f4ccd7be95f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/aaca30ee3ab38edfa2b061fcbcbca0c0ea657f15 b/fuzzers/corpora/commit_graph/aaca30ee3ab38edfa2b061fcbcbca0c0ea657f15
new file mode 100644
index 000000000..cc981c1eb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/aaca30ee3ab38edfa2b061fcbcbca0c0ea657f15
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/aacdec3f05e98eb6eedddb9c6edb968e1a63c551 b/fuzzers/corpora/commit_graph/aacdec3f05e98eb6eedddb9c6edb968e1a63c551
new file mode 100644
index 000000000..622c24795
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/aacdec3f05e98eb6eedddb9c6edb968e1a63c551
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/aadd85127241b94a41d02d9e9699e3e9773de1c9 b/fuzzers/corpora/commit_graph/aadd85127241b94a41d02d9e9699e3e9773de1c9
new file mode 100644
index 000000000..b84e5f17d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/aadd85127241b94a41d02d9e9699e3e9773de1c9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ab8ad126702803d21dbafc85713bbee7f25f36e5 b/fuzzers/corpora/commit_graph/ab8ad126702803d21dbafc85713bbee7f25f36e5
new file mode 100644
index 000000000..9a19eda0f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ab8ad126702803d21dbafc85713bbee7f25f36e5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ac26f9afd599ff6f33396c2e02130654f3e2390c b/fuzzers/corpora/commit_graph/ac26f9afd599ff6f33396c2e02130654f3e2390c
new file mode 100644
index 000000000..843eaa25c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ac26f9afd599ff6f33396c2e02130654f3e2390c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ac8b129e4756fda0c50c9dd0eb13e34c7b41ce8e b/fuzzers/corpora/commit_graph/ac8b129e4756fda0c50c9dd0eb13e34c7b41ce8e
new file mode 100644
index 000000000..4b41d07c7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ac8b129e4756fda0c50c9dd0eb13e34c7b41ce8e
@@ -0,0 +1 @@
+ïïïœïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï@ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïë \ No newline at end of file
diff --git a/fuzzers/corpora/commit_graph/aceaf3b72c2627dd3dd065974b854150681c093f b/fuzzers/corpora/commit_graph/aceaf3b72c2627dd3dd065974b854150681c093f
new file mode 100644
index 000000000..d490782e1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/aceaf3b72c2627dd3dd065974b854150681c093f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ad1fcdc3bf806392e754a902eba9edd3b344c31f b/fuzzers/corpora/commit_graph/ad1fcdc3bf806392e754a902eba9edd3b344c31f
new file mode 100644
index 000000000..1379b75e8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ad1fcdc3bf806392e754a902eba9edd3b344c31f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ad8c80e532482f9dfbfbb7c0d447f1f4e592bf72 b/fuzzers/corpora/commit_graph/ad8c80e532482f9dfbfbb7c0d447f1f4e592bf72
new file mode 100644
index 000000000..bfe39118a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ad8c80e532482f9dfbfbb7c0d447f1f4e592bf72
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/add92b71bf897da2f71f691e6abcb6d02cb8e99f b/fuzzers/corpora/commit_graph/add92b71bf897da2f71f691e6abcb6d02cb8e99f
new file mode 100644
index 000000000..1676dbfaf
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/add92b71bf897da2f71f691e6abcb6d02cb8e99f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/aeb8ccf6d82be9236c9e689e1580d043bd701eb0 b/fuzzers/corpora/commit_graph/aeb8ccf6d82be9236c9e689e1580d043bd701eb0
new file mode 100644
index 000000000..10688e3db
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/aeb8ccf6d82be9236c9e689e1580d043bd701eb0
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/af1a827aedbf674fff2bdeb5589554eec62787ab b/fuzzers/corpora/commit_graph/af1a827aedbf674fff2bdeb5589554eec62787ab
new file mode 100644
index 000000000..6f08ae509
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/af1a827aedbf674fff2bdeb5589554eec62787ab
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/afaab9a75414d231176ad4582b6f8d81b5dbedb3 b/fuzzers/corpora/commit_graph/afaab9a75414d231176ad4582b6f8d81b5dbedb3
new file mode 100644
index 000000000..870178010
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/afaab9a75414d231176ad4582b6f8d81b5dbedb3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/afc12c4ebed1f3ab962d7dcef110b5328b1e24c3 b/fuzzers/corpora/commit_graph/afc12c4ebed1f3ab962d7dcef110b5328b1e24c3
new file mode 100644
index 000000000..0e10f7736
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/afc12c4ebed1f3ab962d7dcef110b5328b1e24c3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b0044f3744cf019658d668a33f8d1e53ef8bd6ce b/fuzzers/corpora/commit_graph/b0044f3744cf019658d668a33f8d1e53ef8bd6ce
new file mode 100644
index 000000000..ede7bfe90
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b0044f3744cf019658d668a33f8d1e53ef8bd6ce
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b06adc81a4e1cdcda3786970ca07ed9dee0b6401 b/fuzzers/corpora/commit_graph/b06adc81a4e1cdcda3786970ca07ed9dee0b6401
new file mode 100644
index 000000000..b5f08b21f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b06adc81a4e1cdcda3786970ca07ed9dee0b6401
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b139802a1cc90fd5b86cae044c221361892c688d b/fuzzers/corpora/commit_graph/b139802a1cc90fd5b86cae044c221361892c688d
new file mode 100644
index 000000000..c21f39ef8
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b139802a1cc90fd5b86cae044c221361892c688d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b1b8f251542db01bdb01be3b6d5b117b07db1834 b/fuzzers/corpora/commit_graph/b1b8f251542db01bdb01be3b6d5b117b07db1834
new file mode 100644
index 000000000..b42f7263b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b1b8f251542db01bdb01be3b6d5b117b07db1834
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b1b9af93f84ed6861b9c0ade39980e89ef828c8f b/fuzzers/corpora/commit_graph/b1b9af93f84ed6861b9c0ade39980e89ef828c8f
new file mode 100644
index 000000000..b367b87d9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b1b9af93f84ed6861b9c0ade39980e89ef828c8f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b2eae68035cafd4077f6a4c3e4e961fdc1e8122b b/fuzzers/corpora/commit_graph/b2eae68035cafd4077f6a4c3e4e961fdc1e8122b
new file mode 100644
index 000000000..1c6289886
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b2eae68035cafd4077f6a4c3e4e961fdc1e8122b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b32897a6aedaa8c5a6e656dd808bafabc4ee5608 b/fuzzers/corpora/commit_graph/b32897a6aedaa8c5a6e656dd808bafabc4ee5608
new file mode 100644
index 000000000..b3fbb813c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b32897a6aedaa8c5a6e656dd808bafabc4ee5608
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b376e4fc517297f92ac1713803ae3b60d5ebbe43 b/fuzzers/corpora/commit_graph/b376e4fc517297f92ac1713803ae3b60d5ebbe43
new file mode 100644
index 000000000..637eafdeb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b376e4fc517297f92ac1713803ae3b60d5ebbe43
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b3fd100b139cfbffaad68aacf7d462861e9dca35 b/fuzzers/corpora/commit_graph/b3fd100b139cfbffaad68aacf7d462861e9dca35
new file mode 100644
index 000000000..da105f5fc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b3fd100b139cfbffaad68aacf7d462861e9dca35
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b40808ca955faab4829811bced1cccb2ab58ea58 b/fuzzers/corpora/commit_graph/b40808ca955faab4829811bced1cccb2ab58ea58
new file mode 100644
index 000000000..4daa74138
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b40808ca955faab4829811bced1cccb2ab58ea58
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b43daf9f87a514bce74af3e5a39284c69c4e7011 b/fuzzers/corpora/commit_graph/b43daf9f87a514bce74af3e5a39284c69c4e7011
new file mode 100644
index 000000000..5c8129df1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b43daf9f87a514bce74af3e5a39284c69c4e7011
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b477da07f3e5796ff4a98c8a5bdb0e4a634954bf b/fuzzers/corpora/commit_graph/b477da07f3e5796ff4a98c8a5bdb0e4a634954bf
new file mode 100644
index 000000000..dbe8abee3
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b477da07f3e5796ff4a98c8a5bdb0e4a634954bf
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b4a2ef09cf59ca5ccf810a6f001cce710cc02f6b b/fuzzers/corpora/commit_graph/b4a2ef09cf59ca5ccf810a6f001cce710cc02f6b
new file mode 100644
index 000000000..3a5817375
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b4a2ef09cf59ca5ccf810a6f001cce710cc02f6b
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b4b75e588cb83430c502a34ec3dcfaf774a00359 b/fuzzers/corpora/commit_graph/b4b75e588cb83430c502a34ec3dcfaf774a00359
new file mode 100644
index 000000000..4afd45262
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b4b75e588cb83430c502a34ec3dcfaf774a00359
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b4ce98acd2b288b6cfc00461e2e15e0f8004030c b/fuzzers/corpora/commit_graph/b4ce98acd2b288b6cfc00461e2e15e0f8004030c
new file mode 100644
index 000000000..a70742673
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b4ce98acd2b288b6cfc00461e2e15e0f8004030c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b75563f30f7e4fb369d2449b723ee8b282d03eff b/fuzzers/corpora/commit_graph/b75563f30f7e4fb369d2449b723ee8b282d03eff
new file mode 100644
index 000000000..a101bca5e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b75563f30f7e4fb369d2449b723ee8b282d03eff
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b7a0a820afa7057081de186728d0d887131d9314 b/fuzzers/corpora/commit_graph/b7a0a820afa7057081de186728d0d887131d9314
new file mode 100644
index 000000000..915cc26be
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b7a0a820afa7057081de186728d0d887131d9314
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b7e880446146c735a3f820fb93969c8c172c2fb5 b/fuzzers/corpora/commit_graph/b7e880446146c735a3f820fb93969c8c172c2fb5
new file mode 100644
index 000000000..cd26631d7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b7e880446146c735a3f820fb93969c8c172c2fb5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b833073d3006e7cbac03c494603a9b75e7b2a723 b/fuzzers/corpora/commit_graph/b833073d3006e7cbac03c494603a9b75e7b2a723
new file mode 100644
index 000000000..0798037e5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b833073d3006e7cbac03c494603a9b75e7b2a723
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b89459c1fb6fc918db4c81a32a75ee66217f9ab8 b/fuzzers/corpora/commit_graph/b89459c1fb6fc918db4c81a32a75ee66217f9ab8
new file mode 100644
index 000000000..bdc6de684
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b89459c1fb6fc918db4c81a32a75ee66217f9ab8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b8aab6c9b2c706f8df0ff695ff94969171f9c807 b/fuzzers/corpora/commit_graph/b8aab6c9b2c706f8df0ff695ff94969171f9c807
new file mode 100644
index 000000000..810a30544
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b8aab6c9b2c706f8df0ff695ff94969171f9c807
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b9751182a36acb79b77585e1e379857a530e95c8 b/fuzzers/corpora/commit_graph/b9751182a36acb79b77585e1e379857a530e95c8
new file mode 100644
index 000000000..eeb1ed05d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b9751182a36acb79b77585e1e379857a530e95c8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/b9ddb239b5a2c1348d972ec70a08507c35ba4432 b/fuzzers/corpora/commit_graph/b9ddb239b5a2c1348d972ec70a08507c35ba4432
new file mode 100644
index 000000000..0d746e52c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/b9ddb239b5a2c1348d972ec70a08507c35ba4432
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ba8f573256a0fbb95c5626f399ebc3ef50bbd826 b/fuzzers/corpora/commit_graph/ba8f573256a0fbb95c5626f399ebc3ef50bbd826
new file mode 100644
index 000000000..330229e41
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ba8f573256a0fbb95c5626f399ebc3ef50bbd826
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/bc165749042d5425c5d6d4e29b17769a2315a80d b/fuzzers/corpora/commit_graph/bc165749042d5425c5d6d4e29b17769a2315a80d
new file mode 100644
index 000000000..af0d232ab
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/bc165749042d5425c5d6d4e29b17769a2315a80d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/bc910bd349319e1ed44d7c7266e3ac99cc29ecc6 b/fuzzers/corpora/commit_graph/bc910bd349319e1ed44d7c7266e3ac99cc29ecc6
new file mode 100644
index 000000000..a38abe580
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/bc910bd349319e1ed44d7c7266e3ac99cc29ecc6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/bc97b1d4f57eb7770bc3983e2d57c8c01b21d29e b/fuzzers/corpora/commit_graph/bc97b1d4f57eb7770bc3983e2d57c8c01b21d29e
new file mode 100644
index 000000000..631754c10
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/bc97b1d4f57eb7770bc3983e2d57c8c01b21d29e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/bd06f768e35ded4437cb88e2bc0ddd0bea3fa84c b/fuzzers/corpora/commit_graph/bd06f768e35ded4437cb88e2bc0ddd0bea3fa84c
new file mode 100644
index 000000000..954e73d68
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/bd06f768e35ded4437cb88e2bc0ddd0bea3fa84c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/bd702faff9725a7a1957fd0f85cc52799f37b682 b/fuzzers/corpora/commit_graph/bd702faff9725a7a1957fd0f85cc52799f37b682
new file mode 100644
index 000000000..928fe58f7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/bd702faff9725a7a1957fd0f85cc52799f37b682
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/bee4464861e1cae3cfdd5fbcb340efbf02e8d8ca b/fuzzers/corpora/commit_graph/bee4464861e1cae3cfdd5fbcb340efbf02e8d8ca
new file mode 100644
index 000000000..8f636ce9b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/bee4464861e1cae3cfdd5fbcb340efbf02e8d8ca
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/bf7ad994b098ec85d62683a16e067635e21a8af5 b/fuzzers/corpora/commit_graph/bf7ad994b098ec85d62683a16e067635e21a8af5
new file mode 100644
index 000000000..71ca10745
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/bf7ad994b098ec85d62683a16e067635e21a8af5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c054fc89ed72101dec861668ff1738ef85b728b9 b/fuzzers/corpora/commit_graph/c054fc89ed72101dec861668ff1738ef85b728b9
new file mode 100644
index 000000000..988ab6be6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c054fc89ed72101dec861668ff1738ef85b728b9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c06752415ac037fefe5172dc7245cd7c49ca7fca b/fuzzers/corpora/commit_graph/c06752415ac037fefe5172dc7245cd7c49ca7fca
new file mode 100644
index 000000000..d03fcac6c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c06752415ac037fefe5172dc7245cd7c49ca7fca
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c0c8b54354d172a0be751e3e9b80be961bb15ddb b/fuzzers/corpora/commit_graph/c0c8b54354d172a0be751e3e9b80be961bb15ddb
new file mode 100644
index 000000000..233aa4e03
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c0c8b54354d172a0be751e3e9b80be961bb15ddb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c0e7ca9b5b4d0e72d23d7dc9e9d1f2463a17a20d b/fuzzers/corpora/commit_graph/c0e7ca9b5b4d0e72d23d7dc9e9d1f2463a17a20d
new file mode 100644
index 000000000..c36f7c16f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c0e7ca9b5b4d0e72d23d7dc9e9d1f2463a17a20d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c13576a29c98bee02aa47f646f5f170f9b7d83f9 b/fuzzers/corpora/commit_graph/c13576a29c98bee02aa47f646f5f170f9b7d83f9
new file mode 100644
index 000000000..95bdcb90c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c13576a29c98bee02aa47f646f5f170f9b7d83f9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c14edf1d34f40b3cc74772c81ebe5d72172cc662 b/fuzzers/corpora/commit_graph/c14edf1d34f40b3cc74772c81ebe5d72172cc662
new file mode 100644
index 000000000..63b1e3900
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c14edf1d34f40b3cc74772c81ebe5d72172cc662
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c2789364cb35d111f08f924d0d7550ea9785c61e b/fuzzers/corpora/commit_graph/c2789364cb35d111f08f924d0d7550ea9785c61e
new file mode 100644
index 000000000..0044eb503
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c2789364cb35d111f08f924d0d7550ea9785c61e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c2d8b07acb13e43a89b6c4afb3ecb9817dd4a8e9 b/fuzzers/corpora/commit_graph/c2d8b07acb13e43a89b6c4afb3ecb9817dd4a8e9
new file mode 100644
index 000000000..8cf6a914d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c2d8b07acb13e43a89b6c4afb3ecb9817dd4a8e9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c36ed796c1bf839668db8fc3475a2ffb32ad8ceb b/fuzzers/corpora/commit_graph/c36ed796c1bf839668db8fc3475a2ffb32ad8ceb
new file mode 100644
index 000000000..77dd76b6b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c36ed796c1bf839668db8fc3475a2ffb32ad8ceb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c41ec9dd94427423e4704721e7f21eae0c44ef20 b/fuzzers/corpora/commit_graph/c41ec9dd94427423e4704721e7f21eae0c44ef20
new file mode 100644
index 000000000..9b828b8cf
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c41ec9dd94427423e4704721e7f21eae0c44ef20
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c42c544fa9dbb1264b39bf920b40985384db1d16 b/fuzzers/corpora/commit_graph/c42c544fa9dbb1264b39bf920b40985384db1d16
new file mode 100644
index 000000000..60889805d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c42c544fa9dbb1264b39bf920b40985384db1d16
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c45ec3f594abc15de0a8cc3ad748ba23cb34ec64 b/fuzzers/corpora/commit_graph/c45ec3f594abc15de0a8cc3ad748ba23cb34ec64
new file mode 100644
index 000000000..6a711bab2
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c45ec3f594abc15de0a8cc3ad748ba23cb34ec64
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c49004d980961f288616a4eb9ebf68123fd68ffa b/fuzzers/corpora/commit_graph/c49004d980961f288616a4eb9ebf68123fd68ffa
new file mode 100644
index 000000000..0b5a6bcfe
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c49004d980961f288616a4eb9ebf68123fd68ffa
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c4c3c3c8df24adf505127627b3090116de78d9a6 b/fuzzers/corpora/commit_graph/c4c3c3c8df24adf505127627b3090116de78d9a6
new file mode 100644
index 000000000..528725c93
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c4c3c3c8df24adf505127627b3090116de78d9a6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c5c1921293af4a5953cb386092694042715fcfb3 b/fuzzers/corpora/commit_graph/c5c1921293af4a5953cb386092694042715fcfb3
new file mode 100644
index 000000000..2256d19b9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c5c1921293af4a5953cb386092694042715fcfb3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c615caad21cd8a754fcb2008420234c5511c62b7 b/fuzzers/corpora/commit_graph/c615caad21cd8a754fcb2008420234c5511c62b7
new file mode 100644
index 000000000..fa4c9cc73
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c615caad21cd8a754fcb2008420234c5511c62b7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c6a9ee3f8fdc42566c4799db3912a83c8c438d7f b/fuzzers/corpora/commit_graph/c6a9ee3f8fdc42566c4799db3912a83c8c438d7f
new file mode 100644
index 000000000..c3c69fcb5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c6a9ee3f8fdc42566c4799db3912a83c8c438d7f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c6b661e976282051285b913b3728383f36103ef8 b/fuzzers/corpora/commit_graph/c6b661e976282051285b913b3728383f36103ef8
new file mode 100644
index 000000000..6a156d2fd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c6b661e976282051285b913b3728383f36103ef8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c716ba47f810c238fe7bda1fbdc7b1ccc34e9848 b/fuzzers/corpora/commit_graph/c716ba47f810c238fe7bda1fbdc7b1ccc34e9848
new file mode 100644
index 000000000..271ec76f9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c716ba47f810c238fe7bda1fbdc7b1ccc34e9848
@@ -0,0 +1 @@
+ïïïœïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï@ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï \ No newline at end of file
diff --git a/fuzzers/corpora/commit_graph/c85b2fa4421302e2fa333a9e33d59a882aa04f4f b/fuzzers/corpora/commit_graph/c85b2fa4421302e2fa333a9e33d59a882aa04f4f
new file mode 100644
index 000000000..eba46a67c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c85b2fa4421302e2fa333a9e33d59a882aa04f4f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c871d135f2d3117b326688355bc0fa6f26d56cd6 b/fuzzers/corpora/commit_graph/c871d135f2d3117b326688355bc0fa6f26d56cd6
new file mode 100644
index 000000000..6ead612d7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c871d135f2d3117b326688355bc0fa6f26d56cd6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c915b02265a27d185a8b028305f082ddb3ebd704 b/fuzzers/corpora/commit_graph/c915b02265a27d185a8b028305f082ddb3ebd704
new file mode 100644
index 000000000..1960dfb47
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c915b02265a27d185a8b028305f082ddb3ebd704
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c952d38b3e642db4795d7f954b85f4f6d2a041aa b/fuzzers/corpora/commit_graph/c952d38b3e642db4795d7f954b85f4f6d2a041aa
new file mode 100644
index 000000000..b8ee30556
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c952d38b3e642db4795d7f954b85f4f6d2a041aa
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c98ee52065736c4172f6ee0c31977bf1b560d685 b/fuzzers/corpora/commit_graph/c98ee52065736c4172f6ee0c31977bf1b560d685
new file mode 100644
index 000000000..f8d7a23f1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c98ee52065736c4172f6ee0c31977bf1b560d685
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/c99b183a2cd0dd8a4c1a141cc6eebb0311501fa5 b/fuzzers/corpora/commit_graph/c99b183a2cd0dd8a4c1a141cc6eebb0311501fa5
new file mode 100644
index 000000000..9cd1ad4cf
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/c99b183a2cd0dd8a4c1a141cc6eebb0311501fa5
@@ -0,0 +1 @@
+Ëó@ÿ~ \ No newline at end of file
diff --git a/fuzzers/corpora/commit_graph/ca0cd26baff2f2c0759e619800ebbe7314d2bb95 b/fuzzers/corpora/commit_graph/ca0cd26baff2f2c0759e619800ebbe7314d2bb95
new file mode 100644
index 000000000..78a357b55
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ca0cd26baff2f2c0759e619800ebbe7314d2bb95
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ca3e0d745c35d7cceb0f6e3f8a709eb658b7e5a8 b/fuzzers/corpora/commit_graph/ca3e0d745c35d7cceb0f6e3f8a709eb658b7e5a8
new file mode 100644
index 000000000..174863ddb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ca3e0d745c35d7cceb0f6e3f8a709eb658b7e5a8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cac667320e99e93a796bb89842de4675735eb4a4 b/fuzzers/corpora/commit_graph/cac667320e99e93a796bb89842de4675735eb4a4
new file mode 100644
index 000000000..20e9db998
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cac667320e99e93a796bb89842de4675735eb4a4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cb41b00e9db33a07e27b3ee05d3bbecaf853b963 b/fuzzers/corpora/commit_graph/cb41b00e9db33a07e27b3ee05d3bbecaf853b963
new file mode 100644
index 000000000..612843d8a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cb41b00e9db33a07e27b3ee05d3bbecaf853b963
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cbdbd3f320eee627097778f15b9fb2c1dc2bd15f b/fuzzers/corpora/commit_graph/cbdbd3f320eee627097778f15b9fb2c1dc2bd15f
new file mode 100644
index 000000000..a922018ee
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cbdbd3f320eee627097778f15b9fb2c1dc2bd15f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cc7f114000c83abb2ab17f0deab6dcfc2acde7f5 b/fuzzers/corpora/commit_graph/cc7f114000c83abb2ab17f0deab6dcfc2acde7f5
new file mode 100644
index 000000000..7c9f84c33
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cc7f114000c83abb2ab17f0deab6dcfc2acde7f5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cc9bb93a6b7a1362a15f04898845dbe1447ec382 b/fuzzers/corpora/commit_graph/cc9bb93a6b7a1362a15f04898845dbe1447ec382
new file mode 100644
index 000000000..5dde22529
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cc9bb93a6b7a1362a15f04898845dbe1447ec382
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cce7355f826bbcf3955394596d358abc7df6fe6f b/fuzzers/corpora/commit_graph/cce7355f826bbcf3955394596d358abc7df6fe6f
new file mode 100644
index 000000000..9b7803800
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cce7355f826bbcf3955394596d358abc7df6fe6f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cceff2878a558166fb5bf2a0354c1be31dcc4e21 b/fuzzers/corpora/commit_graph/cceff2878a558166fb5bf2a0354c1be31dcc4e21
new file mode 100644
index 000000000..94fec1bbc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cceff2878a558166fb5bf2a0354c1be31dcc4e21
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cd96909f3ded7aa54bb2ffd2f2f47f8acc6f99e2 b/fuzzers/corpora/commit_graph/cd96909f3ded7aa54bb2ffd2f2f47f8acc6f99e2
new file mode 100644
index 000000000..22bbade2d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cd96909f3ded7aa54bb2ffd2f2f47f8acc6f99e2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/cee9f69d7d1a227833fba127a529ea2a10341da3 b/fuzzers/corpora/commit_graph/cee9f69d7d1a227833fba127a529ea2a10341da3
new file mode 100644
index 000000000..2fff45e83
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/cee9f69d7d1a227833fba127a529ea2a10341da3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d064f27a3109afde629165432f78f389da73ff07 b/fuzzers/corpora/commit_graph/d064f27a3109afde629165432f78f389da73ff07
new file mode 100644
index 000000000..e6d98c089
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d064f27a3109afde629165432f78f389da73ff07
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d07e3094f02b0c0e3bab370684c2d8c5634224d5 b/fuzzers/corpora/commit_graph/d07e3094f02b0c0e3bab370684c2d8c5634224d5
new file mode 100644
index 000000000..29d86aadb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d07e3094f02b0c0e3bab370684c2d8c5634224d5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d0ba3413d5706de17de64824d78233d48c6efbec b/fuzzers/corpora/commit_graph/d0ba3413d5706de17de64824d78233d48c6efbec
new file mode 100644
index 000000000..96c820760
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d0ba3413d5706de17de64824d78233d48c6efbec
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d136511364a74973b009f2be9b021d4122f71a6c b/fuzzers/corpora/commit_graph/d136511364a74973b009f2be9b021d4122f71a6c
new file mode 100644
index 000000000..a663ab915
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d136511364a74973b009f2be9b021d4122f71a6c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d1d215c40bcc8dd4ce02b0c0621e90b183b40b3e b/fuzzers/corpora/commit_graph/d1d215c40bcc8dd4ce02b0c0621e90b183b40b3e
new file mode 100644
index 000000000..a328d3e9c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d1d215c40bcc8dd4ce02b0c0621e90b183b40b3e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d1e35b137b2027b61def408f3f3c8cf9bcab274e b/fuzzers/corpora/commit_graph/d1e35b137b2027b61def408f3f3c8cf9bcab274e
new file mode 100644
index 000000000..79c43fd21
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d1e35b137b2027b61def408f3f3c8cf9bcab274e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d349d137e57fb1a60ab8babd20e2acedc7a9042e b/fuzzers/corpora/commit_graph/d349d137e57fb1a60ab8babd20e2acedc7a9042e
new file mode 100644
index 000000000..981aaf6be
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d349d137e57fb1a60ab8babd20e2acedc7a9042e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d3714ec4d3acc6262295b0fc99c6ba699f5bfe65 b/fuzzers/corpora/commit_graph/d3714ec4d3acc6262295b0fc99c6ba699f5bfe65
new file mode 100644
index 000000000..7f6e30995
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d3714ec4d3acc6262295b0fc99c6ba699f5bfe65
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d419df696512216074f1c6b17ea1dfc81c0e6e20 b/fuzzers/corpora/commit_graph/d419df696512216074f1c6b17ea1dfc81c0e6e20
new file mode 100644
index 000000000..47c701932
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d419df696512216074f1c6b17ea1dfc81c0e6e20
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d49ad4fdafac251ceec32481826228c1698360aa b/fuzzers/corpora/commit_graph/d49ad4fdafac251ceec32481826228c1698360aa
new file mode 100644
index 000000000..9d4756c4b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d49ad4fdafac251ceec32481826228c1698360aa
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d4f85ba549c87ccaba59971a25da7e07b57c9f4e b/fuzzers/corpora/commit_graph/d4f85ba549c87ccaba59971a25da7e07b57c9f4e
new file mode 100644
index 000000000..e6d72e7bd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d4f85ba549c87ccaba59971a25da7e07b57c9f4e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d51ade0715bcea7decee2a045934599a10c1b07a b/fuzzers/corpora/commit_graph/d51ade0715bcea7decee2a045934599a10c1b07a
new file mode 100644
index 000000000..2403b3551
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d51ade0715bcea7decee2a045934599a10c1b07a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d5447fb72c97462a3f47c8b2d55deb0afaa225f8 b/fuzzers/corpora/commit_graph/d5447fb72c97462a3f47c8b2d55deb0afaa225f8
new file mode 100644
index 000000000..07e14a4b0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d5447fb72c97462a3f47c8b2d55deb0afaa225f8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d6611a91c29291872ed2932455cb15ddb3801323 b/fuzzers/corpora/commit_graph/d6611a91c29291872ed2932455cb15ddb3801323
new file mode 100644
index 000000000..361431c73
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d6611a91c29291872ed2932455cb15ddb3801323
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d676f5e7efd6de6f2e1773231479471d2bba7261 b/fuzzers/corpora/commit_graph/d676f5e7efd6de6f2e1773231479471d2bba7261
new file mode 100644
index 000000000..f9756ab7e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d676f5e7efd6de6f2e1773231479471d2bba7261
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d6a21eaa08a957d8f428192e193c2508fca2c218 b/fuzzers/corpora/commit_graph/d6a21eaa08a957d8f428192e193c2508fca2c218
new file mode 100644
index 000000000..f845fbb6e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d6a21eaa08a957d8f428192e193c2508fca2c218
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d778052a29539344a9e3144e262e68df9628ebde b/fuzzers/corpora/commit_graph/d778052a29539344a9e3144e262e68df9628ebde
new file mode 100644
index 000000000..beace901b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d778052a29539344a9e3144e262e68df9628ebde
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d884f6944adfff7cb41728062bf91cac5cdacfc9 b/fuzzers/corpora/commit_graph/d884f6944adfff7cb41728062bf91cac5cdacfc9
new file mode 100644
index 000000000..f6de6519c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d884f6944adfff7cb41728062bf91cac5cdacfc9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d89aae18d8e320bbae55eaae6a0514d7e005a883 b/fuzzers/corpora/commit_graph/d89aae18d8e320bbae55eaae6a0514d7e005a883
new file mode 100644
index 000000000..1f0bbf302
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d89aae18d8e320bbae55eaae6a0514d7e005a883
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d926fde818c63f7b34f38c9f018bc833bc0bf7e1 b/fuzzers/corpora/commit_graph/d926fde818c63f7b34f38c9f018bc833bc0bf7e1
new file mode 100644
index 000000000..fe1e2743e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d926fde818c63f7b34f38c9f018bc833bc0bf7e1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/d9d542d7c56774143cb6362e5a63739055469349 b/fuzzers/corpora/commit_graph/d9d542d7c56774143cb6362e5a63739055469349
new file mode 100644
index 000000000..946106f79
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/d9d542d7c56774143cb6362e5a63739055469349
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/da99bc9ce5b831f132dfb2eb11b8537e5cccfcd4 b/fuzzers/corpora/commit_graph/da99bc9ce5b831f132dfb2eb11b8537e5cccfcd4
new file mode 100644
index 000000000..91ed5b2f7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/da99bc9ce5b831f132dfb2eb11b8537e5cccfcd4
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dabff2729fa69ab507fb00b7392aee1262056a29 b/fuzzers/corpora/commit_graph/dabff2729fa69ab507fb00b7392aee1262056a29
new file mode 100644
index 000000000..9318cec85
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dabff2729fa69ab507fb00b7392aee1262056a29
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dac4f4b91e33847bcedf7c66ef6e4ad0181e8ad8 b/fuzzers/corpora/commit_graph/dac4f4b91e33847bcedf7c66ef6e4ad0181e8ad8
new file mode 100644
index 000000000..9587c539b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dac4f4b91e33847bcedf7c66ef6e4ad0181e8ad8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/db10ff6d01c7a66aa1823b9f99193590ddce99c6 b/fuzzers/corpora/commit_graph/db10ff6d01c7a66aa1823b9f99193590ddce99c6
new file mode 100644
index 000000000..2d8d09986
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/db10ff6d01c7a66aa1823b9f99193590ddce99c6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dbbda2208fa688a5275dda0d304630db01ca081d b/fuzzers/corpora/commit_graph/dbbda2208fa688a5275dda0d304630db01ca081d
new file mode 100644
index 000000000..7edfc3b97
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dbbda2208fa688a5275dda0d304630db01ca081d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dc47c5037be68a2747ff8a9fa450e1078a5ac5a5 b/fuzzers/corpora/commit_graph/dc47c5037be68a2747ff8a9fa450e1078a5ac5a5
new file mode 100644
index 000000000..e4ac972c2
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dc47c5037be68a2747ff8a9fa450e1078a5ac5a5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dc760f136b123e38677aec72853e3365f08010fc b/fuzzers/corpora/commit_graph/dc760f136b123e38677aec72853e3365f08010fc
new file mode 100644
index 000000000..855c7b3a7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dc760f136b123e38677aec72853e3365f08010fc
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dca41b901bf1612d4197e6a450366a00ac036ec3 b/fuzzers/corpora/commit_graph/dca41b901bf1612d4197e6a450366a00ac036ec3
new file mode 100644
index 000000000..9eec2738f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dca41b901bf1612d4197e6a450366a00ac036ec3
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dca62f21fce50d1c8c51b82e0d7eeedc6746e652 b/fuzzers/corpora/commit_graph/dca62f21fce50d1c8c51b82e0d7eeedc6746e652
new file mode 100644
index 000000000..f8188c691
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dca62f21fce50d1c8c51b82e0d7eeedc6746e652
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dcc7e6c444f95b10d634b1137413824e2cd68f62 b/fuzzers/corpora/commit_graph/dcc7e6c444f95b10d634b1137413824e2cd68f62
new file mode 100644
index 000000000..247d648ab
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dcc7e6c444f95b10d634b1137413824e2cd68f62
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dcf4b6addda69040f792c9b860ade2af0b77a14c b/fuzzers/corpora/commit_graph/dcf4b6addda69040f792c9b860ade2af0b77a14c
new file mode 100644
index 000000000..6cbb0b721
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dcf4b6addda69040f792c9b860ade2af0b77a14c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/dd6178166ac1eed82d132fea491bcda0d953227c b/fuzzers/corpora/commit_graph/dd6178166ac1eed82d132fea491bcda0d953227c
new file mode 100644
index 000000000..4c13f9985
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/dd6178166ac1eed82d132fea491bcda0d953227c
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ddbd5d3074323ccd7cd70bf5de5a2f30de977d99 b/fuzzers/corpora/commit_graph/ddbd5d3074323ccd7cd70bf5de5a2f30de977d99
new file mode 100644
index 000000000..646febd1f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ddbd5d3074323ccd7cd70bf5de5a2f30de977d99
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ddd8ec5632bf1b8153d03a4537d3d76517c497d5 b/fuzzers/corpora/commit_graph/ddd8ec5632bf1b8153d03a4537d3d76517c497d5
new file mode 100644
index 000000000..e948534f6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ddd8ec5632bf1b8153d03a4537d3d76517c497d5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/de7a56f36e10d7b9ff43160b1cea3e76b24386d1 b/fuzzers/corpora/commit_graph/de7a56f36e10d7b9ff43160b1cea3e76b24386d1
new file mode 100644
index 000000000..6cae1f2c4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/de7a56f36e10d7b9ff43160b1cea3e76b24386d1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/defa60aa46ea5a47c09b6962b4e4296ef1bcad92 b/fuzzers/corpora/commit_graph/defa60aa46ea5a47c09b6962b4e4296ef1bcad92
new file mode 100644
index 000000000..297875550
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/defa60aa46ea5a47c09b6962b4e4296ef1bcad92
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e0ae419425207832518d66c0ef35d11cbdc20361 b/fuzzers/corpora/commit_graph/e0ae419425207832518d66c0ef35d11cbdc20361
new file mode 100644
index 000000000..89404f4cc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e0ae419425207832518d66c0ef35d11cbdc20361
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e0f519accbf15bc57a1bf1d7cc46d2a0b07a67f5 b/fuzzers/corpora/commit_graph/e0f519accbf15bc57a1bf1d7cc46d2a0b07a67f5
new file mode 100644
index 000000000..af59e9d06
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e0f519accbf15bc57a1bf1d7cc46d2a0b07a67f5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e128eff8ca7572d9bb0bfc84f64d79c52afc2c67 b/fuzzers/corpora/commit_graph/e128eff8ca7572d9bb0bfc84f64d79c52afc2c67
new file mode 100644
index 000000000..d963f77b5
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e128eff8ca7572d9bb0bfc84f64d79c52afc2c67
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e17fdc21ae03243bd1d31bb6301b4187cab6fe47 b/fuzzers/corpora/commit_graph/e17fdc21ae03243bd1d31bb6301b4187cab6fe47
new file mode 100644
index 000000000..381f8e1bd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e17fdc21ae03243bd1d31bb6301b4187cab6fe47
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e340ace35a2db7f89d6aa21cc1300766a74be4e1 b/fuzzers/corpora/commit_graph/e340ace35a2db7f89d6aa21cc1300766a74be4e1
new file mode 100644
index 000000000..00cb20b46
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e340ace35a2db7f89d6aa21cc1300766a74be4e1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e36dfc11bcaab1e42df13924a2d7da024684db2e b/fuzzers/corpora/commit_graph/e36dfc11bcaab1e42df13924a2d7da024684db2e
new file mode 100644
index 000000000..25dd8eacd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e36dfc11bcaab1e42df13924a2d7da024684db2e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e39e0c87ac5ce0b78c89ae2df84226baba666372 b/fuzzers/corpora/commit_graph/e39e0c87ac5ce0b78c89ae2df84226baba666372
new file mode 100644
index 000000000..acfc88121
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e39e0c87ac5ce0b78c89ae2df84226baba666372
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e46b4666c6bfcd6f589ec3617a48cce9c968e833 b/fuzzers/corpora/commit_graph/e46b4666c6bfcd6f589ec3617a48cce9c968e833
new file mode 100644
index 000000000..92bca774e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e46b4666c6bfcd6f589ec3617a48cce9c968e833
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e57219555e11f9221d3166d5029ed2ad92300608 b/fuzzers/corpora/commit_graph/e57219555e11f9221d3166d5029ed2ad92300608
new file mode 100644
index 000000000..6f9d153f9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e57219555e11f9221d3166d5029ed2ad92300608
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e58ce590c2454e7ebe18e0a31a943b0b754fbd13 b/fuzzers/corpora/commit_graph/e58ce590c2454e7ebe18e0a31a943b0b754fbd13
new file mode 100644
index 000000000..89d479039
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e58ce590c2454e7ebe18e0a31a943b0b754fbd13
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e595f8fef5c8014cb0867978c6580301078ca0d9 b/fuzzers/corpora/commit_graph/e595f8fef5c8014cb0867978c6580301078ca0d9
new file mode 100644
index 000000000..339b09efd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e595f8fef5c8014cb0867978c6580301078ca0d9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e5b76398f60628e879328d7009b9fa89feea14cb b/fuzzers/corpora/commit_graph/e5b76398f60628e879328d7009b9fa89feea14cb
new file mode 100644
index 000000000..6ed637f6e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e5b76398f60628e879328d7009b9fa89feea14cb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e5cec0217eea93b18a59d76b0aed6b46b13fa6a9 b/fuzzers/corpora/commit_graph/e5cec0217eea93b18a59d76b0aed6b46b13fa6a9
new file mode 100644
index 000000000..7ae3eb418
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e5cec0217eea93b18a59d76b0aed6b46b13fa6a9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e637b4e0b47d0d6cd870502e6a2d6a53bf917f73 b/fuzzers/corpora/commit_graph/e637b4e0b47d0d6cd870502e6a2d6a53bf917f73
new file mode 100644
index 000000000..f84ee8c61
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e637b4e0b47d0d6cd870502e6a2d6a53bf917f73
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e7a6cb6e5a1552837fdbee9025fc48a9373f8564 b/fuzzers/corpora/commit_graph/e7a6cb6e5a1552837fdbee9025fc48a9373f8564
new file mode 100644
index 000000000..a5ae268ec
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e7a6cb6e5a1552837fdbee9025fc48a9373f8564
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e7f57c48016e1180c9af95acd34470881f10bd06 b/fuzzers/corpora/commit_graph/e7f57c48016e1180c9af95acd34470881f10bd06
new file mode 100644
index 000000000..07bbb9c5b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e7f57c48016e1180c9af95acd34470881f10bd06
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e8253c668bfe37df5c5ada3226860cee74fb33a2 b/fuzzers/corpora/commit_graph/e8253c668bfe37df5c5ada3226860cee74fb33a2
new file mode 100644
index 000000000..0cb7581d9
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e8253c668bfe37df5c5ada3226860cee74fb33a2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e8f9981443c34ece02bca3c66130f3429d7b3375 b/fuzzers/corpora/commit_graph/e8f9981443c34ece02bca3c66130f3429d7b3375
new file mode 100644
index 000000000..09fe9ddc0
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e8f9981443c34ece02bca3c66130f3429d7b3375
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e91ed5416bbcd1b03803197b99c08f42c9869139 b/fuzzers/corpora/commit_graph/e91ed5416bbcd1b03803197b99c08f42c9869139
new file mode 100644
index 000000000..3267ebb7b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e91ed5416bbcd1b03803197b99c08f42c9869139
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e94201cfa88df7b198abd3abae9007a6780b52a7 b/fuzzers/corpora/commit_graph/e94201cfa88df7b198abd3abae9007a6780b52a7
new file mode 100644
index 000000000..0279a3c3b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e94201cfa88df7b198abd3abae9007a6780b52a7
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/e967bbd6a0d251ae62c9c38b784271d707f792c0 b/fuzzers/corpora/commit_graph/e967bbd6a0d251ae62c9c38b784271d707f792c0
new file mode 100644
index 000000000..2baf05081
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/e967bbd6a0d251ae62c9c38b784271d707f792c0
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ea01737ceed783b3e0f66d9d0c409cb496c1d526 b/fuzzers/corpora/commit_graph/ea01737ceed783b3e0f66d9d0c409cb496c1d526
new file mode 100644
index 000000000..75c988e03
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ea01737ceed783b3e0f66d9d0c409cb496c1d526
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ea40f7879a58d1e52a46404c761f76a949e14a31 b/fuzzers/corpora/commit_graph/ea40f7879a58d1e52a46404c761f76a949e14a31
new file mode 100644
index 000000000..0fe4b3006
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ea40f7879a58d1e52a46404c761f76a949e14a31
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ea5ad04a54f95963baea1f47845847626e08dd55 b/fuzzers/corpora/commit_graph/ea5ad04a54f95963baea1f47845847626e08dd55
new file mode 100644
index 000000000..79a1c4f80
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ea5ad04a54f95963baea1f47845847626e08dd55
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ea608a401f54b0ca70e42b897f0c8ce6efdbc0ef b/fuzzers/corpora/commit_graph/ea608a401f54b0ca70e42b897f0c8ce6efdbc0ef
new file mode 100644
index 000000000..26c55fe6e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ea608a401f54b0ca70e42b897f0c8ce6efdbc0ef
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/eb8700d6b3728e6e70c2a0fe504543771639f2b6 b/fuzzers/corpora/commit_graph/eb8700d6b3728e6e70c2a0fe504543771639f2b6
new file mode 100644
index 000000000..cf359369b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/eb8700d6b3728e6e70c2a0fe504543771639f2b6
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ec1f271b04c322353865f4819153d46df7def873 b/fuzzers/corpora/commit_graph/ec1f271b04c322353865f4819153d46df7def873
new file mode 100644
index 000000000..95cfa61ff
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ec1f271b04c322353865f4819153d46df7def873
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ee215536e7f0cfbd07b53dd65c5af9a604a01830 b/fuzzers/corpora/commit_graph/ee215536e7f0cfbd07b53dd65c5af9a604a01830
new file mode 100644
index 000000000..82241f000
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ee215536e7f0cfbd07b53dd65c5af9a604a01830
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ee4d4393d7d79b755f85ef5bf8f6e3d743bfa258 b/fuzzers/corpora/commit_graph/ee4d4393d7d79b755f85ef5bf8f6e3d743bfa258
new file mode 100644
index 000000000..3d0d7d45d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ee4d4393d7d79b755f85ef5bf8f6e3d743bfa258
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ee8099331b2c392e7e036ffcd4a9b36ec2c2082d b/fuzzers/corpora/commit_graph/ee8099331b2c392e7e036ffcd4a9b36ec2c2082d
new file mode 100644
index 000000000..4e8f26bc1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ee8099331b2c392e7e036ffcd4a9b36ec2c2082d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/eede9da76db25513f8347f972e170102831de91a b/fuzzers/corpora/commit_graph/eede9da76db25513f8347f972e170102831de91a
new file mode 100644
index 000000000..d3646058f
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/eede9da76db25513f8347f972e170102831de91a
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ef707cdeaa9548b6c820f769c1d8ad607b3c4514 b/fuzzers/corpora/commit_graph/ef707cdeaa9548b6c820f769c1d8ad607b3c4514
new file mode 100644
index 000000000..31daa3b31
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ef707cdeaa9548b6c820f769c1d8ad607b3c4514
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ef98609d8196dc158365dfcbbc47e3d1699c50c2 b/fuzzers/corpora/commit_graph/ef98609d8196dc158365dfcbbc47e3d1699c50c2
new file mode 100644
index 000000000..6cac8493c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ef98609d8196dc158365dfcbbc47e3d1699c50c2
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/efa38b4269f978f3714b44b501831bea678244e0 b/fuzzers/corpora/commit_graph/efa38b4269f978f3714b44b501831bea678244e0
new file mode 100644
index 000000000..923b8c514
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/efa38b4269f978f3714b44b501831bea678244e0
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/efba428e29811d233720ccaaf41966a309312a29 b/fuzzers/corpora/commit_graph/efba428e29811d233720ccaaf41966a309312a29
new file mode 100644
index 000000000..b803c2ea1
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/efba428e29811d233720ccaaf41966a309312a29
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/efd514f056d8d83498b4724249c4623560e0390d b/fuzzers/corpora/commit_graph/efd514f056d8d83498b4724249c4623560e0390d
new file mode 100644
index 000000000..d0e1a33d4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/efd514f056d8d83498b4724249c4623560e0390d
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f00e449ba67ef15e7f29df1e6948c28155d72baa b/fuzzers/corpora/commit_graph/f00e449ba67ef15e7f29df1e6948c28155d72baa
new file mode 100644
index 000000000..32153f74d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f00e449ba67ef15e7f29df1e6948c28155d72baa
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f0a83929d588466051dced6eae0c387db307d646 b/fuzzers/corpora/commit_graph/f0a83929d588466051dced6eae0c387db307d646
new file mode 100644
index 000000000..fc53a85f4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f0a83929d588466051dced6eae0c387db307d646
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f0e53b72e5d69467e7c014474028ea734f4fcb26 b/fuzzers/corpora/commit_graph/f0e53b72e5d69467e7c014474028ea734f4fcb26
new file mode 100644
index 000000000..bad38e83b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f0e53b72e5d69467e7c014474028ea734f4fcb26
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f186265b3f10f4383f4174e9fb74f0a0cdfa3fca b/fuzzers/corpora/commit_graph/f186265b3f10f4383f4174e9fb74f0a0cdfa3fca
new file mode 100644
index 000000000..2cc2dd040
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f186265b3f10f4383f4174e9fb74f0a0cdfa3fca
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f18932fcce5a9db5d6c8f59d622eabc25e255e12 b/fuzzers/corpora/commit_graph/f18932fcce5a9db5d6c8f59d622eabc25e255e12
new file mode 100644
index 000000000..85c6e0eac
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f18932fcce5a9db5d6c8f59d622eabc25e255e12
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f2ea163bddb95d67597e2a747779ebf4651cb2a9 b/fuzzers/corpora/commit_graph/f2ea163bddb95d67597e2a747779ebf4651cb2a9
new file mode 100644
index 000000000..f974087cb
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f2ea163bddb95d67597e2a747779ebf4651cb2a9
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f2f7d48a6d86143ecb4969808d634163576065b1 b/fuzzers/corpora/commit_graph/f2f7d48a6d86143ecb4969808d634163576065b1
new file mode 100644
index 000000000..f2ad4a684
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f2f7d48a6d86143ecb4969808d634163576065b1
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f34a833faf2b0dcbae8aaad142c76c7c7e534e99 b/fuzzers/corpora/commit_graph/f34a833faf2b0dcbae8aaad142c76c7c7e534e99
new file mode 100644
index 000000000..2eaa521d6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f34a833faf2b0dcbae8aaad142c76c7c7e534e99
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f5c044ce01645c069334698fb8c4750e44835912 b/fuzzers/corpora/commit_graph/f5c044ce01645c069334698fb8c4750e44835912
new file mode 100644
index 000000000..a67affa6c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f5c044ce01645c069334698fb8c4750e44835912
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f680112645c2502f0612e9d017bbb50cb28affbf b/fuzzers/corpora/commit_graph/f680112645c2502f0612e9d017bbb50cb28affbf
new file mode 100644
index 000000000..dec09a840
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f680112645c2502f0612e9d017bbb50cb28affbf
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f6b778d1b34415a7715905f54968c8b6eb057912 b/fuzzers/corpora/commit_graph/f6b778d1b34415a7715905f54968c8b6eb057912
new file mode 100644
index 000000000..a93cb662b
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f6b778d1b34415a7715905f54968c8b6eb057912
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f6ca6a62dc885c6b2a4b40c4aa1a7cb8118e30bb b/fuzzers/corpora/commit_graph/f6ca6a62dc885c6b2a4b40c4aa1a7cb8118e30bb
new file mode 100644
index 000000000..29ed04c9c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f6ca6a62dc885c6b2a4b40c4aa1a7cb8118e30bb
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f733a8770c23fde182d2fef7e0d96e67244274d5 b/fuzzers/corpora/commit_graph/f733a8770c23fde182d2fef7e0d96e67244274d5
new file mode 100644
index 000000000..c6aa7585e
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f733a8770c23fde182d2fef7e0d96e67244274d5
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f8529ddf17d4505c0932c3d40abe33cbfd8c6f22 b/fuzzers/corpora/commit_graph/f8529ddf17d4505c0932c3d40abe33cbfd8c6f22
new file mode 100644
index 000000000..f004ecbb7
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f8529ddf17d4505c0932c3d40abe33cbfd8c6f22
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/f96f8419a3fc3719ae86d64e1147e7b7f66a2470 b/fuzzers/corpora/commit_graph/f96f8419a3fc3719ae86d64e1147e7b7f66a2470
new file mode 100644
index 000000000..5dee3ca7c
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/f96f8419a3fc3719ae86d64e1147e7b7f66a2470
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/fae241a6c87af37781a3b49e534b7ddb6636eda8 b/fuzzers/corpora/commit_graph/fae241a6c87af37781a3b49e534b7ddb6636eda8
new file mode 100644
index 000000000..fc4e26bfd
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/fae241a6c87af37781a3b49e534b7ddb6636eda8
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/faf8817a04b77c6a976ab0a3d1e905f79bb7f799 b/fuzzers/corpora/commit_graph/faf8817a04b77c6a976ab0a3d1e905f79bb7f799
new file mode 100644
index 000000000..5164ecb6a
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/faf8817a04b77c6a976ab0a3d1e905f79bb7f799
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/fb3e769019fb25d384d4be9d38e4cbce00a6adbc b/fuzzers/corpora/commit_graph/fb3e769019fb25d384d4be9d38e4cbce00a6adbc
new file mode 100644
index 000000000..008337c8d
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/fb3e769019fb25d384d4be9d38e4cbce00a6adbc
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/fb9b4b2a46f1c65076340a7bd03b076eb101b760 b/fuzzers/corpora/commit_graph/fb9b4b2a46f1c65076340a7bd03b076eb101b760
new file mode 100644
index 000000000..8d0c735e4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/fb9b4b2a46f1c65076340a7bd03b076eb101b760
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/fca9b0a398832c9ba02cdc811f625b97d5beb18e b/fuzzers/corpora/commit_graph/fca9b0a398832c9ba02cdc811f625b97d5beb18e
new file mode 100644
index 000000000..b2681f0c4
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/fca9b0a398832c9ba02cdc811f625b97d5beb18e
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/fcb1b42c706e61245d5e86f708be777ae63f2772 b/fuzzers/corpora/commit_graph/fcb1b42c706e61245d5e86f708be777ae63f2772
new file mode 100644
index 000000000..a98b66141
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/fcb1b42c706e61245d5e86f708be777ae63f2772
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/fd6c463e7c30b0e51198c0d1ebbea25f20145e3f b/fuzzers/corpora/commit_graph/fd6c463e7c30b0e51198c0d1ebbea25f20145e3f
new file mode 100644
index 000000000..b25332139
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/fd6c463e7c30b0e51198c0d1ebbea25f20145e3f
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/fdcbaa49097ad120c6d7709b29d5b65b8cf8e719 b/fuzzers/corpora/commit_graph/fdcbaa49097ad120c6d7709b29d5b65b8cf8e719
new file mode 100644
index 000000000..2167806d6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/fdcbaa49097ad120c6d7709b29d5b65b8cf8e719
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/fe46775b28a2923b8770b44381552a8a1560d875 b/fuzzers/corpora/commit_graph/fe46775b28a2923b8770b44381552a8a1560d875
new file mode 100644
index 000000000..0acef6edc
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/fe46775b28a2923b8770b44381552a8a1560d875
Binary files differ
diff --git a/fuzzers/corpora/commit_graph/ff04441135ef3308fec2687cf688069c6df8aa31 b/fuzzers/corpora/commit_graph/ff04441135ef3308fec2687cf688069c6df8aa31
new file mode 100644
index 000000000..33afa05c6
--- /dev/null
+++ b/fuzzers/corpora/commit_graph/ff04441135ef3308fec2687cf688069c6df8aa31
Binary files differ
diff --git a/fuzzers/corpora/midx/037cbbe0dc03807dd9d9e8629f1712d7df34ee18 b/fuzzers/corpora/midx/037cbbe0dc03807dd9d9e8629f1712d7df34ee18
new file mode 100644
index 000000000..2e5bda8c6
--- /dev/null
+++ b/fuzzers/corpora/midx/037cbbe0dc03807dd9d9e8629f1712d7df34ee18
Binary files differ
diff --git a/fuzzers/corpora/midx/039ee34fef8f323ed618a10abc0109df123d0cb5 b/fuzzers/corpora/midx/039ee34fef8f323ed618a10abc0109df123d0cb5
new file mode 100644
index 000000000..0c97a38f5
--- /dev/null
+++ b/fuzzers/corpora/midx/039ee34fef8f323ed618a10abc0109df123d0cb5
Binary files differ
diff --git a/fuzzers/corpora/midx/054ee2c82bdb6a170106eb5d35f21bde2119d584 b/fuzzers/corpora/midx/054ee2c82bdb6a170106eb5d35f21bde2119d584
new file mode 100644
index 000000000..f7711e496
--- /dev/null
+++ b/fuzzers/corpora/midx/054ee2c82bdb6a170106eb5d35f21bde2119d584
@@ -0,0 +1 @@
+ãMÿãa \ No newline at end of file
diff --git a/fuzzers/corpora/midx/055ca4cbc961ebf5fd5c922b4f73880d3fbfe39d b/fuzzers/corpora/midx/055ca4cbc961ebf5fd5c922b4f73880d3fbfe39d
new file mode 100644
index 000000000..adb91f935
--- /dev/null
+++ b/fuzzers/corpora/midx/055ca4cbc961ebf5fd5c922b4f73880d3fbfe39d
Binary files differ
diff --git a/fuzzers/corpora/midx/05c4e5eb1b97bc9b6973921fcb30d4c5e2eb79e4 b/fuzzers/corpora/midx/05c4e5eb1b97bc9b6973921fcb30d4c5e2eb79e4
new file mode 100644
index 000000000..1a53734a2
--- /dev/null
+++ b/fuzzers/corpora/midx/05c4e5eb1b97bc9b6973921fcb30d4c5e2eb79e4
Binary files differ
diff --git a/fuzzers/corpora/midx/0672eeda541a191cfc68d521a3c7ac0aac4057a6 b/fuzzers/corpora/midx/0672eeda541a191cfc68d521a3c7ac0aac4057a6
new file mode 100644
index 000000000..5b6495587
--- /dev/null
+++ b/fuzzers/corpora/midx/0672eeda541a191cfc68d521a3c7ac0aac4057a6
Binary files differ
diff --git a/fuzzers/corpora/midx/06a58d1bd5562a668ebf01ef297fd774e0e587a6 b/fuzzers/corpora/midx/06a58d1bd5562a668ebf01ef297fd774e0e587a6
new file mode 100644
index 000000000..30e454a42
--- /dev/null
+++ b/fuzzers/corpora/midx/06a58d1bd5562a668ebf01ef297fd774e0e587a6
Binary files differ
diff --git a/fuzzers/corpora/midx/06bf7c2461ae1049030f31b83ae76babfcc20c83 b/fuzzers/corpora/midx/06bf7c2461ae1049030f31b83ae76babfcc20c83
new file mode 100644
index 000000000..10751dc37
--- /dev/null
+++ b/fuzzers/corpora/midx/06bf7c2461ae1049030f31b83ae76babfcc20c83
Binary files differ
diff --git a/fuzzers/corpora/midx/06c2db67ea65758d971346bfd6beaa61ed12f22c b/fuzzers/corpora/midx/06c2db67ea65758d971346bfd6beaa61ed12f22c
new file mode 100644
index 000000000..5641570e1
--- /dev/null
+++ b/fuzzers/corpora/midx/06c2db67ea65758d971346bfd6beaa61ed12f22c
Binary files differ
diff --git a/fuzzers/corpora/midx/07f88eefaf12609b7370fe78b82be2955f1b41fd b/fuzzers/corpora/midx/07f88eefaf12609b7370fe78b82be2955f1b41fd
new file mode 100644
index 000000000..8e09bb462
--- /dev/null
+++ b/fuzzers/corpora/midx/07f88eefaf12609b7370fe78b82be2955f1b41fd
Binary files differ
diff --git a/fuzzers/corpora/midx/08495c5f3828a56c167de870d385c46ffdce03c5 b/fuzzers/corpora/midx/08495c5f3828a56c167de870d385c46ffdce03c5
new file mode 100644
index 000000000..b4f569772
--- /dev/null
+++ b/fuzzers/corpora/midx/08495c5f3828a56c167de870d385c46ffdce03c5
Binary files differ
diff --git a/fuzzers/corpora/midx/08ec8594e5b35fb9e8e0726584f720154f0b2b5d b/fuzzers/corpora/midx/08ec8594e5b35fb9e8e0726584f720154f0b2b5d
new file mode 100644
index 000000000..772b4fd4f
--- /dev/null
+++ b/fuzzers/corpora/midx/08ec8594e5b35fb9e8e0726584f720154f0b2b5d
Binary files differ
diff --git a/fuzzers/corpora/midx/0903e378a493c596298074d6bff8de7f9ac25aa7 b/fuzzers/corpora/midx/0903e378a493c596298074d6bff8de7f9ac25aa7
new file mode 100644
index 000000000..34f5f3b25
--- /dev/null
+++ b/fuzzers/corpora/midx/0903e378a493c596298074d6bff8de7f9ac25aa7
@@ -0,0 +1 @@
+ãü7 \ No newline at end of file
diff --git a/fuzzers/corpora/midx/09144a846f90f894049ef8a0ed0cc7ab4588dc6c b/fuzzers/corpora/midx/09144a846f90f894049ef8a0ed0cc7ab4588dc6c
new file mode 100644
index 000000000..ce7a43d9c
--- /dev/null
+++ b/fuzzers/corpora/midx/09144a846f90f894049ef8a0ed0cc7ab4588dc6c
@@ -0,0 +1 @@
+ÃØseed \ No newline at end of file
diff --git a/fuzzers/corpora/midx/09b40dd618373bfe4d3f2838f686a70f645e640b b/fuzzers/corpora/midx/09b40dd618373bfe4d3f2838f686a70f645e640b
new file mode 100644
index 000000000..09473b7de
--- /dev/null
+++ b/fuzzers/corpora/midx/09b40dd618373bfe4d3f2838f686a70f645e640b
Binary files differ
diff --git a/fuzzers/corpora/midx/0a00ef44d234c18d365ec41724dbf4f21b09d0c5 b/fuzzers/corpora/midx/0a00ef44d234c18d365ec41724dbf4f21b09d0c5
new file mode 100644
index 000000000..861a9869a
--- /dev/null
+++ b/fuzzers/corpora/midx/0a00ef44d234c18d365ec41724dbf4f21b09d0c5
Binary files differ
diff --git a/fuzzers/corpora/midx/0a94e9f4a9b8cf56d52a9e3e7f2fa9a0a5c80d30 b/fuzzers/corpora/midx/0a94e9f4a9b8cf56d52a9e3e7f2fa9a0a5c80d30
new file mode 100644
index 000000000..11f08c02d
--- /dev/null
+++ b/fuzzers/corpora/midx/0a94e9f4a9b8cf56d52a9e3e7f2fa9a0a5c80d30
Binary files differ
diff --git a/fuzzers/corpora/midx/0b35a123104b7872a7f15a710a23ef3594ace04d b/fuzzers/corpora/midx/0b35a123104b7872a7f15a710a23ef3594ace04d
new file mode 100644
index 000000000..eac151bd6
--- /dev/null
+++ b/fuzzers/corpora/midx/0b35a123104b7872a7f15a710a23ef3594ace04d
Binary files differ
diff --git a/fuzzers/corpora/midx/0c3d7e6be32c014ea873440b0f095961d391af1a b/fuzzers/corpora/midx/0c3d7e6be32c014ea873440b0f095961d391af1a
new file mode 100644
index 000000000..e9c66219d
--- /dev/null
+++ b/fuzzers/corpora/midx/0c3d7e6be32c014ea873440b0f095961d391af1a
Binary files differ
diff --git a/fuzzers/corpora/midx/0c65de477b89afc312a7e89cde06f8a17f65bd54 b/fuzzers/corpora/midx/0c65de477b89afc312a7e89cde06f8a17f65bd54
new file mode 100644
index 000000000..8f4b25ca5
--- /dev/null
+++ b/fuzzers/corpora/midx/0c65de477b89afc312a7e89cde06f8a17f65bd54
Binary files differ
diff --git a/fuzzers/corpora/midx/0c81d0f368e979d2a0eb4598cbf1c9283936ba0c b/fuzzers/corpora/midx/0c81d0f368e979d2a0eb4598cbf1c9283936ba0c
new file mode 100644
index 000000000..a2dd1636c
--- /dev/null
+++ b/fuzzers/corpora/midx/0c81d0f368e979d2a0eb4598cbf1c9283936ba0c
Binary files differ
diff --git a/fuzzers/corpora/midx/0c95a44ae995070a5279a2991c36de2251081460 b/fuzzers/corpora/midx/0c95a44ae995070a5279a2991c36de2251081460
new file mode 100644
index 000000000..821b07bc9
--- /dev/null
+++ b/fuzzers/corpora/midx/0c95a44ae995070a5279a2991c36de2251081460
Binary files differ
diff --git a/fuzzers/corpora/midx/0de38e2cb13167df7d5a882570633596f64bc4f4 b/fuzzers/corpora/midx/0de38e2cb13167df7d5a882570633596f64bc4f4
new file mode 100644
index 000000000..80a27f682
--- /dev/null
+++ b/fuzzers/corpora/midx/0de38e2cb13167df7d5a882570633596f64bc4f4
Binary files differ
diff --git a/fuzzers/corpora/midx/0de96aa193045315457ade63c2614610c503db9e b/fuzzers/corpora/midx/0de96aa193045315457ade63c2614610c503db9e
new file mode 100644
index 000000000..342c6c9a6
--- /dev/null
+++ b/fuzzers/corpora/midx/0de96aa193045315457ade63c2614610c503db9e
Binary files differ
diff --git a/fuzzers/corpora/midx/0e02deca2b16d71f8637933bd56dc8592ed9fdff b/fuzzers/corpora/midx/0e02deca2b16d71f8637933bd56dc8592ed9fdff
new file mode 100644
index 000000000..d3b5fe27f
--- /dev/null
+++ b/fuzzers/corpora/midx/0e02deca2b16d71f8637933bd56dc8592ed9fdff
@@ -0,0 +1 @@
+ãH \ No newline at end of file
diff --git a/fuzzers/corpora/midx/0e44fc9176fe2c1bae4209369da5bc057f54b2d2 b/fuzzers/corpora/midx/0e44fc9176fe2c1bae4209369da5bc057f54b2d2
new file mode 100644
index 000000000..74690025f
--- /dev/null
+++ b/fuzzers/corpora/midx/0e44fc9176fe2c1bae4209369da5bc057f54b2d2
Binary files differ
diff --git a/fuzzers/corpora/midx/0f6c5fc9b6a68835364bbef8937560ee5a481938 b/fuzzers/corpora/midx/0f6c5fc9b6a68835364bbef8937560ee5a481938
new file mode 100644
index 000000000..309e2d84f
--- /dev/null
+++ b/fuzzers/corpora/midx/0f6c5fc9b6a68835364bbef8937560ee5a481938
@@ -0,0 +1 @@
+©* \ No newline at end of file
diff --git a/fuzzers/corpora/midx/10d542d5c7da060a5f0664e21478a0d598e29844 b/fuzzers/corpora/midx/10d542d5c7da060a5f0664e21478a0d598e29844
new file mode 100644
index 000000000..777d32aa0
--- /dev/null
+++ b/fuzzers/corpora/midx/10d542d5c7da060a5f0664e21478a0d598e29844
Binary files differ
diff --git a/fuzzers/corpora/midx/118735f7786ae6b4c2f6b36314ab1f2cafe9c3c8 b/fuzzers/corpora/midx/118735f7786ae6b4c2f6b36314ab1f2cafe9c3c8
new file mode 100644
index 000000000..a91dbc912
--- /dev/null
+++ b/fuzzers/corpora/midx/118735f7786ae6b4c2f6b36314ab1f2cafe9c3c8
@@ -0,0 +1 @@
+ãÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛŠÛÛÛÛÛÛÛÛÛÛËÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛËÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ \ No newline at end of file
diff --git a/fuzzers/corpora/midx/119b58eb353aa344264005016297fb911510ea0d b/fuzzers/corpora/midx/119b58eb353aa344264005016297fb911510ea0d
new file mode 100644
index 000000000..b4883c29c
--- /dev/null
+++ b/fuzzers/corpora/midx/119b58eb353aa344264005016297fb911510ea0d
Binary files differ
diff --git a/fuzzers/corpora/midx/127626832c30d6d94bb29384c0fde7ac6bca75ec b/fuzzers/corpora/midx/127626832c30d6d94bb29384c0fde7ac6bca75ec
new file mode 100644
index 000000000..3a0fe06c9
--- /dev/null
+++ b/fuzzers/corpora/midx/127626832c30d6d94bb29384c0fde7ac6bca75ec
Binary files differ
diff --git a/fuzzers/corpora/midx/1284f1a162588d4de87ca17149474644a0863b27 b/fuzzers/corpora/midx/1284f1a162588d4de87ca17149474644a0863b27
new file mode 100644
index 000000000..03a9f9779
--- /dev/null
+++ b/fuzzers/corpora/midx/1284f1a162588d4de87ca17149474644a0863b27
Binary files differ
diff --git a/fuzzers/corpora/midx/1458599f19f1a967c787562bf8ec3e67677da9c8 b/fuzzers/corpora/midx/1458599f19f1a967c787562bf8ec3e67677da9c8
new file mode 100644
index 000000000..e9dc36e96
--- /dev/null
+++ b/fuzzers/corpora/midx/1458599f19f1a967c787562bf8ec3e67677da9c8
Binary files differ
diff --git a/fuzzers/corpora/midx/14ba6c1ddd05b22c6f2eae5f894721cd3efcbb16 b/fuzzers/corpora/midx/14ba6c1ddd05b22c6f2eae5f894721cd3efcbb16
new file mode 100644
index 000000000..e0f281c6f
--- /dev/null
+++ b/fuzzers/corpora/midx/14ba6c1ddd05b22c6f2eae5f894721cd3efcbb16
Binary files differ
diff --git a/fuzzers/corpora/midx/158cdc0a5aa005f167a8588d0beed9eee4aa36f2 b/fuzzers/corpora/midx/158cdc0a5aa005f167a8588d0beed9eee4aa36f2
new file mode 100644
index 000000000..98de253d8
--- /dev/null
+++ b/fuzzers/corpora/midx/158cdc0a5aa005f167a8588d0beed9eee4aa36f2
Binary files differ
diff --git a/fuzzers/corpora/midx/15dafc6fa800327f694b5eb2fc4ebf007be9c117 b/fuzzers/corpora/midx/15dafc6fa800327f694b5eb2fc4ebf007be9c117
new file mode 100644
index 000000000..ff07ca2bd
--- /dev/null
+++ b/fuzzers/corpora/midx/15dafc6fa800327f694b5eb2fc4ebf007be9c117
Binary files differ
diff --git a/fuzzers/corpora/midx/1613ed4b2e909871f8897fd6354ff80a4ac12f87 b/fuzzers/corpora/midx/1613ed4b2e909871f8897fd6354ff80a4ac12f87
new file mode 100644
index 000000000..1afb32e28
--- /dev/null
+++ b/fuzzers/corpora/midx/1613ed4b2e909871f8897fd6354ff80a4ac12f87
Binary files differ
diff --git a/fuzzers/corpora/midx/16daf4cb967bb47cf4566e9be7d96d3125bd2e12 b/fuzzers/corpora/midx/16daf4cb967bb47cf4566e9be7d96d3125bd2e12
new file mode 100644
index 000000000..729b22a63
--- /dev/null
+++ b/fuzzers/corpora/midx/16daf4cb967bb47cf4566e9be7d96d3125bd2e12
Binary files differ
diff --git a/fuzzers/corpora/midx/177783dce78efee878f6d6020fd87ab107bb11a1 b/fuzzers/corpora/midx/177783dce78efee878f6d6020fd87ab107bb11a1
new file mode 100644
index 000000000..cc1810e6c
--- /dev/null
+++ b/fuzzers/corpora/midx/177783dce78efee878f6d6020fd87ab107bb11a1
Binary files differ
diff --git a/fuzzers/corpora/midx/17a5090400a1fedc45070e4b530a26f320a89097 b/fuzzers/corpora/midx/17a5090400a1fedc45070e4b530a26f320a89097
new file mode 100644
index 000000000..7255c8577
--- /dev/null
+++ b/fuzzers/corpora/midx/17a5090400a1fedc45070e4b530a26f320a89097
Binary files differ
diff --git a/fuzzers/corpora/midx/17dea5cfa498f4d54384289a1daed0d15a85e7cc b/fuzzers/corpora/midx/17dea5cfa498f4d54384289a1daed0d15a85e7cc
new file mode 100644
index 000000000..00572bbea
--- /dev/null
+++ b/fuzzers/corpora/midx/17dea5cfa498f4d54384289a1daed0d15a85e7cc
Binary files differ
diff --git a/fuzzers/corpora/midx/17e76ae5b54316679981113f52c27edc87dbcdea b/fuzzers/corpora/midx/17e76ae5b54316679981113f52c27edc87dbcdea
new file mode 100644
index 000000000..5f0e0d56c
--- /dev/null
+++ b/fuzzers/corpora/midx/17e76ae5b54316679981113f52c27edc87dbcdea
Binary files differ
diff --git a/fuzzers/corpora/midx/191ed5e9334693c53fc843f692dbc3c2c63e8241 b/fuzzers/corpora/midx/191ed5e9334693c53fc843f692dbc3c2c63e8241
new file mode 100644
index 000000000..17fddd8d1
--- /dev/null
+++ b/fuzzers/corpora/midx/191ed5e9334693c53fc843f692dbc3c2c63e8241
Binary files differ
diff --git a/fuzzers/corpora/midx/196a0ba4edb5bbfd66c1cda669abf0496573cf0e b/fuzzers/corpora/midx/196a0ba4edb5bbfd66c1cda669abf0496573cf0e
new file mode 100644
index 000000000..4d685869b
--- /dev/null
+++ b/fuzzers/corpora/midx/196a0ba4edb5bbfd66c1cda669abf0496573cf0e
Binary files differ
diff --git a/fuzzers/corpora/midx/19742b6cee79fa5bf9b27dcbe367c82d0a399904 b/fuzzers/corpora/midx/19742b6cee79fa5bf9b27dcbe367c82d0a399904
new file mode 100644
index 000000000..39e705417
--- /dev/null
+++ b/fuzzers/corpora/midx/19742b6cee79fa5bf9b27dcbe367c82d0a399904
Binary files differ
diff --git a/fuzzers/corpora/midx/1a21d7581d3b0a8d67934d48e91d45bd818836e8 b/fuzzers/corpora/midx/1a21d7581d3b0a8d67934d48e91d45bd818836e8
new file mode 100644
index 000000000..616b808d9
--- /dev/null
+++ b/fuzzers/corpora/midx/1a21d7581d3b0a8d67934d48e91d45bd818836e8
Binary files differ
diff --git a/fuzzers/corpora/midx/1b2f96c5d75c7ca09b1012be4e6c3a7b248ed924 b/fuzzers/corpora/midx/1b2f96c5d75c7ca09b1012be4e6c3a7b248ed924
new file mode 100644
index 000000000..148aad968
--- /dev/null
+++ b/fuzzers/corpora/midx/1b2f96c5d75c7ca09b1012be4e6c3a7b248ed924
Binary files differ
diff --git a/fuzzers/corpora/midx/1b604ff0683d0e23dc7945431f6514ba30d6ca0d b/fuzzers/corpora/midx/1b604ff0683d0e23dc7945431f6514ba30d6ca0d
new file mode 100644
index 000000000..1456048ac
--- /dev/null
+++ b/fuzzers/corpora/midx/1b604ff0683d0e23dc7945431f6514ba30d6ca0d
Binary files differ
diff --git a/fuzzers/corpora/midx/1b771dd5bd3ae2b1c42c4efe6c896c83b88a4f91 b/fuzzers/corpora/midx/1b771dd5bd3ae2b1c42c4efe6c896c83b88a4f91
new file mode 100644
index 000000000..92f637662
--- /dev/null
+++ b/fuzzers/corpora/midx/1b771dd5bd3ae2b1c42c4efe6c896c83b88a4f91
Binary files differ
diff --git a/fuzzers/corpora/midx/1b793a4ee73fa8bf423da70fca5f39ef32a8d288 b/fuzzers/corpora/midx/1b793a4ee73fa8bf423da70fca5f39ef32a8d288
new file mode 100644
index 000000000..8c4478cfc
--- /dev/null
+++ b/fuzzers/corpora/midx/1b793a4ee73fa8bf423da70fca5f39ef32a8d288
Binary files differ
diff --git a/fuzzers/corpora/midx/1c9599ce00978780519272be279f508c402e3268 b/fuzzers/corpora/midx/1c9599ce00978780519272be279f508c402e3268
new file mode 100644
index 000000000..c70f12828
--- /dev/null
+++ b/fuzzers/corpora/midx/1c9599ce00978780519272be279f508c402e3268
@@ -0,0 +1 @@
+ãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏ \ No newline at end of file
diff --git a/fuzzers/corpora/midx/1cc0068f9f63b12dc8fdd38f9ebfb96c42664e95 b/fuzzers/corpora/midx/1cc0068f9f63b12dc8fdd38f9ebfb96c42664e95
new file mode 100644
index 000000000..c41e6a879
--- /dev/null
+++ b/fuzzers/corpora/midx/1cc0068f9f63b12dc8fdd38f9ebfb96c42664e95
Binary files differ
diff --git a/fuzzers/corpora/midx/1de6e1f5579da6e5c40f4ee23ac62e29e4f90541 b/fuzzers/corpora/midx/1de6e1f5579da6e5c40f4ee23ac62e29e4f90541
new file mode 100644
index 000000000..d8c3fbf0a
--- /dev/null
+++ b/fuzzers/corpora/midx/1de6e1f5579da6e5c40f4ee23ac62e29e4f90541
Binary files differ
diff --git a/fuzzers/corpora/midx/1eec93083260ebfab5f4c6d13119cf27c374b7e9 b/fuzzers/corpora/midx/1eec93083260ebfab5f4c6d13119cf27c374b7e9
new file mode 100644
index 000000000..5f9c27fac
--- /dev/null
+++ b/fuzzers/corpora/midx/1eec93083260ebfab5f4c6d13119cf27c374b7e9
Binary files differ
diff --git a/fuzzers/corpora/midx/1f0f574addd363d1fed131289f301c5c033aaa8f b/fuzzers/corpora/midx/1f0f574addd363d1fed131289f301c5c033aaa8f
new file mode 100644
index 000000000..12cbb60c2
--- /dev/null
+++ b/fuzzers/corpora/midx/1f0f574addd363d1fed131289f301c5c033aaa8f
Binary files differ
diff --git a/fuzzers/corpora/midx/1f3e85cffdb545c1ba7c8bbe1ca18ec13e341038 b/fuzzers/corpora/midx/1f3e85cffdb545c1ba7c8bbe1ca18ec13e341038
new file mode 100644
index 000000000..36b2d5ea2
--- /dev/null
+++ b/fuzzers/corpora/midx/1f3e85cffdb545c1ba7c8bbe1ca18ec13e341038
Binary files differ
diff --git a/fuzzers/corpora/midx/1f6a66a92d5f083a73a82280a0a1ae0800e56ae5 b/fuzzers/corpora/midx/1f6a66a92d5f083a73a82280a0a1ae0800e56ae5
new file mode 100644
index 000000000..ea50ac7be
--- /dev/null
+++ b/fuzzers/corpora/midx/1f6a66a92d5f083a73a82280a0a1ae0800e56ae5
Binary files differ
diff --git a/fuzzers/corpora/midx/208e422322052efcdaeb1a09bbf06c5f476b8efc b/fuzzers/corpora/midx/208e422322052efcdaeb1a09bbf06c5f476b8efc
new file mode 100644
index 000000000..ce98394b3
--- /dev/null
+++ b/fuzzers/corpora/midx/208e422322052efcdaeb1a09bbf06c5f476b8efc
Binary files differ
diff --git a/fuzzers/corpora/midx/22d75b2c3937957b14eded621b638283ce7fe1fe b/fuzzers/corpora/midx/22d75b2c3937957b14eded621b638283ce7fe1fe
new file mode 100644
index 000000000..0aa34c4ef
--- /dev/null
+++ b/fuzzers/corpora/midx/22d75b2c3937957b14eded621b638283ce7fe1fe
Binary files differ
diff --git a/fuzzers/corpora/midx/22f90ff68166a409acf8f89bf60a31ad2c64ab37 b/fuzzers/corpora/midx/22f90ff68166a409acf8f89bf60a31ad2c64ab37
new file mode 100644
index 000000000..cdecbb60c
--- /dev/null
+++ b/fuzzers/corpora/midx/22f90ff68166a409acf8f89bf60a31ad2c64ab37
Binary files differ
diff --git a/fuzzers/corpora/midx/236ebad449d432b039d6ace1f250ef1fa2aa364d b/fuzzers/corpora/midx/236ebad449d432b039d6ace1f250ef1fa2aa364d
new file mode 100644
index 000000000..0e213a171
--- /dev/null
+++ b/fuzzers/corpora/midx/236ebad449d432b039d6ace1f250ef1fa2aa364d
Binary files differ
diff --git a/fuzzers/corpora/midx/252a4e4bf7fb21792ec2f305fd88fa7c9168505f b/fuzzers/corpora/midx/252a4e4bf7fb21792ec2f305fd88fa7c9168505f
new file mode 100644
index 000000000..b23555c93
--- /dev/null
+++ b/fuzzers/corpora/midx/252a4e4bf7fb21792ec2f305fd88fa7c9168505f
Binary files differ
diff --git a/fuzzers/corpora/midx/259e1faf7b7f12250062d36ded1193a9dbcae0f5 b/fuzzers/corpora/midx/259e1faf7b7f12250062d36ded1193a9dbcae0f5
new file mode 100644
index 000000000..f2f1de5c6
--- /dev/null
+++ b/fuzzers/corpora/midx/259e1faf7b7f12250062d36ded1193a9dbcae0f5
Binary files differ
diff --git a/fuzzers/corpora/midx/25ad3dfb655ab4c853d0d277872310d9579c8e83 b/fuzzers/corpora/midx/25ad3dfb655ab4c853d0d277872310d9579c8e83
new file mode 100644
index 000000000..325c38585
--- /dev/null
+++ b/fuzzers/corpora/midx/25ad3dfb655ab4c853d0d277872310d9579c8e83
Binary files differ
diff --git a/fuzzers/corpora/midx/26210f5b8fdbf81b312feea48659ec6e2e083c0b b/fuzzers/corpora/midx/26210f5b8fdbf81b312feea48659ec6e2e083c0b
new file mode 100644
index 000000000..479a291fa
--- /dev/null
+++ b/fuzzers/corpora/midx/26210f5b8fdbf81b312feea48659ec6e2e083c0b
Binary files differ
diff --git a/fuzzers/corpora/midx/263a2a0915be36d8cb2bc30774e37e0344262347 b/fuzzers/corpora/midx/263a2a0915be36d8cb2bc30774e37e0344262347
new file mode 100644
index 000000000..8a9076140
--- /dev/null
+++ b/fuzzers/corpora/midx/263a2a0915be36d8cb2bc30774e37e0344262347
Binary files differ
diff --git a/fuzzers/corpora/midx/2679bfbc2f4f7c10a304245da4e156e235377b63 b/fuzzers/corpora/midx/2679bfbc2f4f7c10a304245da4e156e235377b63
new file mode 100644
index 000000000..dbf598d81
--- /dev/null
+++ b/fuzzers/corpora/midx/2679bfbc2f4f7c10a304245da4e156e235377b63
Binary files differ
diff --git a/fuzzers/corpora/midx/270b7b567a63dd94bb2a90448bbbc2e2bbc4a261 b/fuzzers/corpora/midx/270b7b567a63dd94bb2a90448bbbc2e2bbc4a261
new file mode 100644
index 000000000..0c08b8c13
--- /dev/null
+++ b/fuzzers/corpora/midx/270b7b567a63dd94bb2a90448bbbc2e2bbc4a261
Binary files differ
diff --git a/fuzzers/corpora/midx/271cd5c5e254a293d115588ee130040ef26b59e8 b/fuzzers/corpora/midx/271cd5c5e254a293d115588ee130040ef26b59e8
new file mode 100644
index 000000000..89309dc1a
--- /dev/null
+++ b/fuzzers/corpora/midx/271cd5c5e254a293d115588ee130040ef26b59e8
Binary files differ
diff --git a/fuzzers/corpora/midx/27839a8035b48f8c19ab073808a03a95b6a90cc3 b/fuzzers/corpora/midx/27839a8035b48f8c19ab073808a03a95b6a90cc3
new file mode 100644
index 000000000..459506950
--- /dev/null
+++ b/fuzzers/corpora/midx/27839a8035b48f8c19ab073808a03a95b6a90cc3
Binary files differ
diff --git a/fuzzers/corpora/midx/2810c385c9285cbdb65bcdab5175999fe547cbad b/fuzzers/corpora/midx/2810c385c9285cbdb65bcdab5175999fe547cbad
new file mode 100644
index 000000000..0d3fc30b8
--- /dev/null
+++ b/fuzzers/corpora/midx/2810c385c9285cbdb65bcdab5175999fe547cbad
Binary files differ
diff --git a/fuzzers/corpora/midx/28afaf4ab4b092ccf987661e58009f96126bba63 b/fuzzers/corpora/midx/28afaf4ab4b092ccf987661e58009f96126bba63
new file mode 100644
index 000000000..6a29fb12c
--- /dev/null
+++ b/fuzzers/corpora/midx/28afaf4ab4b092ccf987661e58009f96126bba63
Binary files differ
diff --git a/fuzzers/corpora/midx/29f842e86a891cff9f0b44c8aec19f7e23a47000 b/fuzzers/corpora/midx/29f842e86a891cff9f0b44c8aec19f7e23a47000
new file mode 100644
index 000000000..5644eb8af
--- /dev/null
+++ b/fuzzers/corpora/midx/29f842e86a891cff9f0b44c8aec19f7e23a47000
Binary files differ
diff --git a/fuzzers/corpora/midx/2aa2549f617f19402d1feac61d4ca1af3545cc8a b/fuzzers/corpora/midx/2aa2549f617f19402d1feac61d4ca1af3545cc8a
new file mode 100644
index 000000000..77045850a
--- /dev/null
+++ b/fuzzers/corpora/midx/2aa2549f617f19402d1feac61d4ca1af3545cc8a
Binary files differ
diff --git a/fuzzers/corpora/midx/2b73c2902eda6da41321493601003b29c3445713 b/fuzzers/corpora/midx/2b73c2902eda6da41321493601003b29c3445713
new file mode 100644
index 000000000..402d06647
--- /dev/null
+++ b/fuzzers/corpora/midx/2b73c2902eda6da41321493601003b29c3445713
Binary files differ
diff --git a/fuzzers/corpora/midx/2bcec1274c5e7b2d7a581d851c016ef5b553fabe b/fuzzers/corpora/midx/2bcec1274c5e7b2d7a581d851c016ef5b553fabe
new file mode 100644
index 000000000..43e18c8cc
--- /dev/null
+++ b/fuzzers/corpora/midx/2bcec1274c5e7b2d7a581d851c016ef5b553fabe
Binary files differ
diff --git a/fuzzers/corpora/midx/2dd9a328b6d4e29e42684347be5c4b7cd7dc1a66 b/fuzzers/corpora/midx/2dd9a328b6d4e29e42684347be5c4b7cd7dc1a66
new file mode 100644
index 000000000..a3e6da55c
--- /dev/null
+++ b/fuzzers/corpora/midx/2dd9a328b6d4e29e42684347be5c4b7cd7dc1a66
Binary files differ
diff --git a/fuzzers/corpora/midx/2ddc17ee7ee89bb7dbc673328d5f3e55c76e686e b/fuzzers/corpora/midx/2ddc17ee7ee89bb7dbc673328d5f3e55c76e686e
new file mode 100644
index 000000000..7b789f304
--- /dev/null
+++ b/fuzzers/corpora/midx/2ddc17ee7ee89bb7dbc673328d5f3e55c76e686e
Binary files differ
diff --git a/fuzzers/corpora/midx/2f71d5e99dc93618ed99fdb7c244a8f5e4a7eb4a b/fuzzers/corpora/midx/2f71d5e99dc93618ed99fdb7c244a8f5e4a7eb4a
new file mode 100644
index 000000000..7d2f004ba
--- /dev/null
+++ b/fuzzers/corpora/midx/2f71d5e99dc93618ed99fdb7c244a8f5e4a7eb4a
Binary files differ
diff --git a/fuzzers/corpora/midx/2f7cd0154d71a83e7b104670b2a77fbd285ffde2 b/fuzzers/corpora/midx/2f7cd0154d71a83e7b104670b2a77fbd285ffde2
new file mode 100644
index 000000000..645a39bff
--- /dev/null
+++ b/fuzzers/corpora/midx/2f7cd0154d71a83e7b104670b2a77fbd285ffde2
Binary files differ
diff --git a/fuzzers/corpora/midx/2f9d40ef790f5213234e95d123dce942b2d1d389 b/fuzzers/corpora/midx/2f9d40ef790f5213234e95d123dce942b2d1d389
new file mode 100644
index 000000000..bca234806
--- /dev/null
+++ b/fuzzers/corpora/midx/2f9d40ef790f5213234e95d123dce942b2d1d389
Binary files differ
diff --git a/fuzzers/corpora/midx/31577bacbca7017308d2a0c9ebfdd4fce513bbe4 b/fuzzers/corpora/midx/31577bacbca7017308d2a0c9ebfdd4fce513bbe4
new file mode 100644
index 000000000..72972b16b
--- /dev/null
+++ b/fuzzers/corpora/midx/31577bacbca7017308d2a0c9ebfdd4fce513bbe4
Binary files differ
diff --git a/fuzzers/corpora/midx/3278f1bab88b80597d0066812d49f8bd3c7b1dcf b/fuzzers/corpora/midx/3278f1bab88b80597d0066812d49f8bd3c7b1dcf
new file mode 100644
index 000000000..4177febbb
--- /dev/null
+++ b/fuzzers/corpora/midx/3278f1bab88b80597d0066812d49f8bd3c7b1dcf
Binary files differ
diff --git a/fuzzers/corpora/midx/328160cae6235605ff70951a2f6ac669ba7bb397 b/fuzzers/corpora/midx/328160cae6235605ff70951a2f6ac669ba7bb397
new file mode 100644
index 000000000..1585907e0
--- /dev/null
+++ b/fuzzers/corpora/midx/328160cae6235605ff70951a2f6ac669ba7bb397
Binary files differ
diff --git a/fuzzers/corpora/midx/337ed1bf91701a4c8926840259077e55938c6efc b/fuzzers/corpora/midx/337ed1bf91701a4c8926840259077e55938c6efc
new file mode 100644
index 000000000..915128f16
--- /dev/null
+++ b/fuzzers/corpora/midx/337ed1bf91701a4c8926840259077e55938c6efc
Binary files differ
diff --git a/fuzzers/corpora/midx/33a97d83ff7a774797b1751ea4bffbb4a22c58d9 b/fuzzers/corpora/midx/33a97d83ff7a774797b1751ea4bffbb4a22c58d9
new file mode 100644
index 000000000..852d8dc19
--- /dev/null
+++ b/fuzzers/corpora/midx/33a97d83ff7a774797b1751ea4bffbb4a22c58d9
Binary files differ
diff --git a/fuzzers/corpora/midx/341021da9516401cf364ed2b7dfdda346db04f2f b/fuzzers/corpora/midx/341021da9516401cf364ed2b7dfdda346db04f2f
new file mode 100644
index 000000000..13c21ab3c
--- /dev/null
+++ b/fuzzers/corpora/midx/341021da9516401cf364ed2b7dfdda346db04f2f
Binary files differ
diff --git a/fuzzers/corpora/midx/341773a439cdecc58f55fb205ac584cd93ffe0f2 b/fuzzers/corpora/midx/341773a439cdecc58f55fb205ac584cd93ffe0f2
new file mode 100644
index 000000000..0446a8866
--- /dev/null
+++ b/fuzzers/corpora/midx/341773a439cdecc58f55fb205ac584cd93ffe0f2
@@ -0,0 +1 @@
+ãyyyyyššyyyyyyyyÅÅ \ No newline at end of file
diff --git a/fuzzers/corpora/midx/366091157510e40bca08fc2102b9018ccf4697de b/fuzzers/corpora/midx/366091157510e40bca08fc2102b9018ccf4697de
new file mode 100644
index 000000000..f2148a165
--- /dev/null
+++ b/fuzzers/corpora/midx/366091157510e40bca08fc2102b9018ccf4697de
Binary files differ
diff --git a/fuzzers/corpora/midx/37096157e2f9f2ec8e0b97b21d335bd653f3edbd b/fuzzers/corpora/midx/37096157e2f9f2ec8e0b97b21d335bd653f3edbd
new file mode 100644
index 000000000..03600aa65
--- /dev/null
+++ b/fuzzers/corpora/midx/37096157e2f9f2ec8e0b97b21d335bd653f3edbd
Binary files differ
diff --git a/fuzzers/corpora/midx/373a74b8613d09babcb567f91047e7b556a8de90 b/fuzzers/corpora/midx/373a74b8613d09babcb567f91047e7b556a8de90
new file mode 100644
index 000000000..9427eb0c7
--- /dev/null
+++ b/fuzzers/corpora/midx/373a74b8613d09babcb567f91047e7b556a8de90
Binary files differ
diff --git a/fuzzers/corpora/midx/3748b07ee7bec7bdd202ee14222cefca182417d1 b/fuzzers/corpora/midx/3748b07ee7bec7bdd202ee14222cefca182417d1
new file mode 100644
index 000000000..9699411c0
--- /dev/null
+++ b/fuzzers/corpora/midx/3748b07ee7bec7bdd202ee14222cefca182417d1
Binary files differ
diff --git a/fuzzers/corpora/midx/38b7906b9f956dca01dc92d0a901388ec1cbc8b1 b/fuzzers/corpora/midx/38b7906b9f956dca01dc92d0a901388ec1cbc8b1
new file mode 100644
index 000000000..d7b26a331
--- /dev/null
+++ b/fuzzers/corpora/midx/38b7906b9f956dca01dc92d0a901388ec1cbc8b1
Binary files differ
diff --git a/fuzzers/corpora/midx/38ddf3424559f1a6e7687eff8469a358184b833b b/fuzzers/corpora/midx/38ddf3424559f1a6e7687eff8469a358184b833b
new file mode 100644
index 000000000..972dd750d
--- /dev/null
+++ b/fuzzers/corpora/midx/38ddf3424559f1a6e7687eff8469a358184b833b
@@ -0,0 +1 @@
+ðã½D \ No newline at end of file
diff --git a/fuzzers/corpora/midx/38e31d0a7dcc3835ce1a4afeeda8446fb3d7ed73 b/fuzzers/corpora/midx/38e31d0a7dcc3835ce1a4afeeda8446fb3d7ed73
new file mode 100644
index 000000000..2afdc8fb5
--- /dev/null
+++ b/fuzzers/corpora/midx/38e31d0a7dcc3835ce1a4afeeda8446fb3d7ed73
Binary files differ
diff --git a/fuzzers/corpora/midx/3955ec4497b226391ef9eb40f38af6dee4fa26b7 b/fuzzers/corpora/midx/3955ec4497b226391ef9eb40f38af6dee4fa26b7
new file mode 100644
index 000000000..cff10d886
--- /dev/null
+++ b/fuzzers/corpora/midx/3955ec4497b226391ef9eb40f38af6dee4fa26b7
Binary files differ
diff --git a/fuzzers/corpora/midx/3b6b424342133feb0f587f22bcd8f21595c004e5 b/fuzzers/corpora/midx/3b6b424342133feb0f587f22bcd8f21595c004e5
new file mode 100644
index 000000000..9f2bea4f5
--- /dev/null
+++ b/fuzzers/corpora/midx/3b6b424342133feb0f587f22bcd8f21595c004e5
Binary files differ
diff --git a/fuzzers/corpora/midx/3bb71f41200e0ebf8d19532e7d6e384c48aa2d03 b/fuzzers/corpora/midx/3bb71f41200e0ebf8d19532e7d6e384c48aa2d03
new file mode 100644
index 000000000..28fa1334e
--- /dev/null
+++ b/fuzzers/corpora/midx/3bb71f41200e0ebf8d19532e7d6e384c48aa2d03
Binary files differ
diff --git a/fuzzers/corpora/midx/3c5a6063797aba9ffe5ea9903bbfcf87193652d3 b/fuzzers/corpora/midx/3c5a6063797aba9ffe5ea9903bbfcf87193652d3
new file mode 100644
index 000000000..4a5725e81
--- /dev/null
+++ b/fuzzers/corpora/midx/3c5a6063797aba9ffe5ea9903bbfcf87193652d3
Binary files differ
diff --git a/fuzzers/corpora/midx/3dfb9927d959f2462f6944a32d080b60a265abfe b/fuzzers/corpora/midx/3dfb9927d959f2462f6944a32d080b60a265abfe
new file mode 100644
index 000000000..c234cd149
--- /dev/null
+++ b/fuzzers/corpora/midx/3dfb9927d959f2462f6944a32d080b60a265abfe
Binary files differ
diff --git a/fuzzers/corpora/midx/3e19242a63ec92a0c3f7138ebbc31bfe7cbd40cd b/fuzzers/corpora/midx/3e19242a63ec92a0c3f7138ebbc31bfe7cbd40cd
new file mode 100644
index 000000000..c0e1b1d4a
--- /dev/null
+++ b/fuzzers/corpora/midx/3e19242a63ec92a0c3f7138ebbc31bfe7cbd40cd
Binary files differ
diff --git a/fuzzers/corpora/midx/3ec53ce4ea1f41f040a3c2beed929572af95dd43 b/fuzzers/corpora/midx/3ec53ce4ea1f41f040a3c2beed929572af95dd43
new file mode 100644
index 000000000..9a7ec6f79
--- /dev/null
+++ b/fuzzers/corpora/midx/3ec53ce4ea1f41f040a3c2beed929572af95dd43
Binary files differ
diff --git a/fuzzers/corpora/midx/3f0762fdf49a58c0d8fd6683964a85caddee391b b/fuzzers/corpora/midx/3f0762fdf49a58c0d8fd6683964a85caddee391b
new file mode 100644
index 000000000..aec9b3d42
--- /dev/null
+++ b/fuzzers/corpora/midx/3f0762fdf49a58c0d8fd6683964a85caddee391b
Binary files differ
diff --git a/fuzzers/corpora/midx/3f71ae863c4e9bac98e49a554b8ec4d78b17492d b/fuzzers/corpora/midx/3f71ae863c4e9bac98e49a554b8ec4d78b17492d
new file mode 100644
index 000000000..a9e06c79d
--- /dev/null
+++ b/fuzzers/corpora/midx/3f71ae863c4e9bac98e49a554b8ec4d78b17492d
@@ -0,0 +1 @@
+ãïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï*ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïéïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï \ No newline at end of file
diff --git a/fuzzers/corpora/midx/3f9df30bfb66a28fbe6f1951ef7ae4ca9f19fdf2 b/fuzzers/corpora/midx/3f9df30bfb66a28fbe6f1951ef7ae4ca9f19fdf2
new file mode 100644
index 000000000..ebb1cde86
--- /dev/null
+++ b/fuzzers/corpora/midx/3f9df30bfb66a28fbe6f1951ef7ae4ca9f19fdf2
Binary files differ
diff --git a/fuzzers/corpora/midx/3fabb14670c008c22094c1d7cd7b1e23b4c48b3d b/fuzzers/corpora/midx/3fabb14670c008c22094c1d7cd7b1e23b4c48b3d
new file mode 100644
index 000000000..1d2d0828c
--- /dev/null
+++ b/fuzzers/corpora/midx/3fabb14670c008c22094c1d7cd7b1e23b4c48b3d
Binary files differ
diff --git a/fuzzers/corpora/midx/408fba9c66c5d1deb31e4c69f1dd0677844dbc1b b/fuzzers/corpora/midx/408fba9c66c5d1deb31e4c69f1dd0677844dbc1b
new file mode 100644
index 000000000..1cded0704
--- /dev/null
+++ b/fuzzers/corpora/midx/408fba9c66c5d1deb31e4c69f1dd0677844dbc1b
Binary files differ
diff --git a/fuzzers/corpora/midx/40ca8645081087e950ad61bccf8d43450366356e b/fuzzers/corpora/midx/40ca8645081087e950ad61bccf8d43450366356e
new file mode 100644
index 000000000..834daf8c9
--- /dev/null
+++ b/fuzzers/corpora/midx/40ca8645081087e950ad61bccf8d43450366356e
Binary files differ
diff --git a/fuzzers/corpora/midx/412faec949b9d04498de939561664ee559a583a7 b/fuzzers/corpora/midx/412faec949b9d04498de939561664ee559a583a7
new file mode 100644
index 000000000..f15b10e73
--- /dev/null
+++ b/fuzzers/corpora/midx/412faec949b9d04498de939561664ee559a583a7
@@ -0,0 +1 @@
+ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïñïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïçïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïÿÿÿÿ \ No newline at end of file
diff --git a/fuzzers/corpora/midx/4148bd5336f89e73b2a5416c67d491c0ec4a2b7d b/fuzzers/corpora/midx/4148bd5336f89e73b2a5416c67d491c0ec4a2b7d
new file mode 100644
index 000000000..894ac62ea
--- /dev/null
+++ b/fuzzers/corpora/midx/4148bd5336f89e73b2a5416c67d491c0ec4a2b7d
Binary files differ
diff --git a/fuzzers/corpora/midx/41933e61fa20fbe2b190f9ae7ceae4a4b1220021 b/fuzzers/corpora/midx/41933e61fa20fbe2b190f9ae7ceae4a4b1220021
new file mode 100644
index 000000000..727789d6c
--- /dev/null
+++ b/fuzzers/corpora/midx/41933e61fa20fbe2b190f9ae7ceae4a4b1220021
Binary files differ
diff --git a/fuzzers/corpora/midx/423d90f3fc7ddc146095ec5a4b4f455aa876b69b b/fuzzers/corpora/midx/423d90f3fc7ddc146095ec5a4b4f455aa876b69b
new file mode 100644
index 000000000..fc73bd07f
--- /dev/null
+++ b/fuzzers/corpora/midx/423d90f3fc7ddc146095ec5a4b4f455aa876b69b
Binary files differ
diff --git a/fuzzers/corpora/midx/42a6c52249aa12cfef1db1bf302a483a01c972f3 b/fuzzers/corpora/midx/42a6c52249aa12cfef1db1bf302a483a01c972f3
new file mode 100644
index 000000000..e35ab98be
--- /dev/null
+++ b/fuzzers/corpora/midx/42a6c52249aa12cfef1db1bf302a483a01c972f3
Binary files differ
diff --git a/fuzzers/corpora/midx/42a82726f0e70da9b87b6c52bc1b3415576025f2 b/fuzzers/corpora/midx/42a82726f0e70da9b87b6c52bc1b3415576025f2
new file mode 100644
index 000000000..46117b4a9
--- /dev/null
+++ b/fuzzers/corpora/midx/42a82726f0e70da9b87b6c52bc1b3415576025f2
Binary files differ
diff --git a/fuzzers/corpora/midx/4458e19f99e38c61ad9792b0b3bf8ac79f8236f1 b/fuzzers/corpora/midx/4458e19f99e38c61ad9792b0b3bf8ac79f8236f1
new file mode 100644
index 000000000..80407ab45
--- /dev/null
+++ b/fuzzers/corpora/midx/4458e19f99e38c61ad9792b0b3bf8ac79f8236f1
@@ -0,0 +1 @@
+ã]]ÿÿÿÿÿÿs4 \ No newline at end of file
diff --git a/fuzzers/corpora/midx/44a4411a8d6ed67ee3ea61d91d2afafe89295b0f b/fuzzers/corpora/midx/44a4411a8d6ed67ee3ea61d91d2afafe89295b0f
new file mode 100644
index 000000000..e9933b1fa
--- /dev/null
+++ b/fuzzers/corpora/midx/44a4411a8d6ed67ee3ea61d91d2afafe89295b0f
Binary files differ
diff --git a/fuzzers/corpora/midx/44e04754d1b6c0c045e05509dd7033d19a926b10 b/fuzzers/corpora/midx/44e04754d1b6c0c045e05509dd7033d19a926b10
new file mode 100644
index 000000000..5fe8e2e84
--- /dev/null
+++ b/fuzzers/corpora/midx/44e04754d1b6c0c045e05509dd7033d19a926b10
Binary files differ
diff --git a/fuzzers/corpora/midx/45259e9f0a2cc7739a94eccaafb37c1570f73884 b/fuzzers/corpora/midx/45259e9f0a2cc7739a94eccaafb37c1570f73884
new file mode 100644
index 000000000..90134d1da
--- /dev/null
+++ b/fuzzers/corpora/midx/45259e9f0a2cc7739a94eccaafb37c1570f73884
Binary files differ
diff --git a/fuzzers/corpora/midx/46c0d7e952200cabc08b9cd776a9f6759f4208c3 b/fuzzers/corpora/midx/46c0d7e952200cabc08b9cd776a9f6759f4208c3
new file mode 100644
index 000000000..e3a7a837b
--- /dev/null
+++ b/fuzzers/corpora/midx/46c0d7e952200cabc08b9cd776a9f6759f4208c3
Binary files differ
diff --git a/fuzzers/corpora/midx/46deac8631633ea3c32005124e20a2bc2bbabade b/fuzzers/corpora/midx/46deac8631633ea3c32005124e20a2bc2bbabade
new file mode 100644
index 000000000..5f54eacd6
--- /dev/null
+++ b/fuzzers/corpora/midx/46deac8631633ea3c32005124e20a2bc2bbabade
Binary files differ
diff --git a/fuzzers/corpora/midx/46e7edf6e9d6cbcdabde3b48f1c4efd93be40348 b/fuzzers/corpora/midx/46e7edf6e9d6cbcdabde3b48f1c4efd93be40348
new file mode 100644
index 000000000..0314f2c23
--- /dev/null
+++ b/fuzzers/corpora/midx/46e7edf6e9d6cbcdabde3b48f1c4efd93be40348
Binary files differ
diff --git a/fuzzers/corpora/midx/46fe9556c28c94f7321baa2519a3cbeabbd54d09 b/fuzzers/corpora/midx/46fe9556c28c94f7321baa2519a3cbeabbd54d09
new file mode 100644
index 000000000..75e8e6fa7
--- /dev/null
+++ b/fuzzers/corpora/midx/46fe9556c28c94f7321baa2519a3cbeabbd54d09
Binary files differ
diff --git a/fuzzers/corpora/midx/49223681729e73b48b26a2262e4a66b2ba00e176 b/fuzzers/corpora/midx/49223681729e73b48b26a2262e4a66b2ba00e176
new file mode 100644
index 000000000..3068c356c
--- /dev/null
+++ b/fuzzers/corpora/midx/49223681729e73b48b26a2262e4a66b2ba00e176
Binary files differ
diff --git a/fuzzers/corpora/midx/499e61b689f6cc7e4efb0631684739c2a6f97c7d b/fuzzers/corpora/midx/499e61b689f6cc7e4efb0631684739c2a6f97c7d
new file mode 100644
index 000000000..d3c735b3b
--- /dev/null
+++ b/fuzzers/corpora/midx/499e61b689f6cc7e4efb0631684739c2a6f97c7d
Binary files differ
diff --git a/fuzzers/corpora/midx/4a06ad8c4d717bd048a7a1315a3d609d70f0162d b/fuzzers/corpora/midx/4a06ad8c4d717bd048a7a1315a3d609d70f0162d
new file mode 100644
index 000000000..caef1688b
--- /dev/null
+++ b/fuzzers/corpora/midx/4a06ad8c4d717bd048a7a1315a3d609d70f0162d
Binary files differ
diff --git a/fuzzers/corpora/midx/4adb7d4791a4c6370478dff2eb987d715554bf09 b/fuzzers/corpora/midx/4adb7d4791a4c6370478dff2eb987d715554bf09
new file mode 100644
index 000000000..ced147746
--- /dev/null
+++ b/fuzzers/corpora/midx/4adb7d4791a4c6370478dff2eb987d715554bf09
Binary files differ
diff --git a/fuzzers/corpora/midx/4b01c479cdc9b750a31d5e7ac5004309222d218d b/fuzzers/corpora/midx/4b01c479cdc9b750a31d5e7ac5004309222d218d
new file mode 100644
index 000000000..4ea5a8800
--- /dev/null
+++ b/fuzzers/corpora/midx/4b01c479cdc9b750a31d5e7ac5004309222d218d
Binary files differ
diff --git a/fuzzers/corpora/midx/4bce7460a6becba6d26984bb438d7d3aa4e4fc56 b/fuzzers/corpora/midx/4bce7460a6becba6d26984bb438d7d3aa4e4fc56
new file mode 100644
index 000000000..41c7c3ace
--- /dev/null
+++ b/fuzzers/corpora/midx/4bce7460a6becba6d26984bb438d7d3aa4e4fc56
Binary files differ
diff --git a/fuzzers/corpora/midx/4cc96483b6800dda296f00887b12a35154115090 b/fuzzers/corpora/midx/4cc96483b6800dda296f00887b12a35154115090
new file mode 100644
index 000000000..4f0179da8
--- /dev/null
+++ b/fuzzers/corpora/midx/4cc96483b6800dda296f00887b12a35154115090
Binary files differ
diff --git a/fuzzers/corpora/midx/4f3aa59bae0619c9a06b631d9cb7767591810ab0 b/fuzzers/corpora/midx/4f3aa59bae0619c9a06b631d9cb7767591810ab0
new file mode 100644
index 000000000..0a677236c
--- /dev/null
+++ b/fuzzers/corpora/midx/4f3aa59bae0619c9a06b631d9cb7767591810ab0
Binary files differ
diff --git a/fuzzers/corpora/midx/501840d963cedd2945018de59e0202444d7ebf4b b/fuzzers/corpora/midx/501840d963cedd2945018de59e0202444d7ebf4b
new file mode 100644
index 000000000..cd26169c2
--- /dev/null
+++ b/fuzzers/corpora/midx/501840d963cedd2945018de59e0202444d7ebf4b
Binary files differ
diff --git a/fuzzers/corpora/midx/50479958c030d1addceb1ca8c27f24447e555e65 b/fuzzers/corpora/midx/50479958c030d1addceb1ca8c27f24447e555e65
new file mode 100644
index 000000000..22159a49e
--- /dev/null
+++ b/fuzzers/corpora/midx/50479958c030d1addceb1ca8c27f24447e555e65
Binary files differ
diff --git a/fuzzers/corpora/midx/508ba8ef164a809f739834a39d690e700101a7a1 b/fuzzers/corpora/midx/508ba8ef164a809f739834a39d690e700101a7a1
new file mode 100644
index 000000000..7cf01e116
--- /dev/null
+++ b/fuzzers/corpora/midx/508ba8ef164a809f739834a39d690e700101a7a1
Binary files differ
diff --git a/fuzzers/corpora/midx/521d345313812e54bc6c944485e19dbb39a87768 b/fuzzers/corpora/midx/521d345313812e54bc6c944485e19dbb39a87768
new file mode 100644
index 000000000..6e9550f74
--- /dev/null
+++ b/fuzzers/corpora/midx/521d345313812e54bc6c944485e19dbb39a87768
Binary files differ
diff --git a/fuzzers/corpora/midx/5369d74ac157f85b597c1b28bbd6768105e9327b b/fuzzers/corpora/midx/5369d74ac157f85b597c1b28bbd6768105e9327b
new file mode 100644
index 000000000..bda1f8c5d
--- /dev/null
+++ b/fuzzers/corpora/midx/5369d74ac157f85b597c1b28bbd6768105e9327b
Binary files differ
diff --git a/fuzzers/corpora/midx/53997b0146ff49bfe464be203b130a67ea93fd26 b/fuzzers/corpora/midx/53997b0146ff49bfe464be203b130a67ea93fd26
new file mode 100644
index 000000000..12ea4cd28
--- /dev/null
+++ b/fuzzers/corpora/midx/53997b0146ff49bfe464be203b130a67ea93fd26
Binary files differ
diff --git a/fuzzers/corpora/midx/560ea8bd7d11b00e0d21631b6d9ec7e63f0a5286 b/fuzzers/corpora/midx/560ea8bd7d11b00e0d21631b6d9ec7e63f0a5286
new file mode 100644
index 000000000..0c984e107
--- /dev/null
+++ b/fuzzers/corpora/midx/560ea8bd7d11b00e0d21631b6d9ec7e63f0a5286
Binary files differ
diff --git a/fuzzers/corpora/midx/5682ebc6878e247ce9bc636d34ada6ad338fcaf0 b/fuzzers/corpora/midx/5682ebc6878e247ce9bc636d34ada6ad338fcaf0
new file mode 100644
index 000000000..1b881402f
--- /dev/null
+++ b/fuzzers/corpora/midx/5682ebc6878e247ce9bc636d34ada6ad338fcaf0
Binary files differ
diff --git a/fuzzers/corpora/midx/5762abb5234edd913754b69e1ab03274c711ee68 b/fuzzers/corpora/midx/5762abb5234edd913754b69e1ab03274c711ee68
new file mode 100644
index 000000000..668572272
--- /dev/null
+++ b/fuzzers/corpora/midx/5762abb5234edd913754b69e1ab03274c711ee68
Binary files differ
diff --git a/fuzzers/corpora/midx/579406f055070559bda3c6120107feb3e637c481 b/fuzzers/corpora/midx/579406f055070559bda3c6120107feb3e637c481
new file mode 100644
index 000000000..be7a59b5c
--- /dev/null
+++ b/fuzzers/corpora/midx/579406f055070559bda3c6120107feb3e637c481
@@ -0,0 +1,2 @@
+ÿ&ã
+ÿÿ)Å \ No newline at end of file
diff --git a/fuzzers/corpora/midx/5837d16af4a9c1f2616467cc4aa9ec8836e05c58 b/fuzzers/corpora/midx/5837d16af4a9c1f2616467cc4aa9ec8836e05c58
new file mode 100644
index 000000000..69bf0eb68
--- /dev/null
+++ b/fuzzers/corpora/midx/5837d16af4a9c1f2616467cc4aa9ec8836e05c58
Binary files differ
diff --git a/fuzzers/corpora/midx/58901e865fe20b9fa136cca4b253d3ae73c2b78e b/fuzzers/corpora/midx/58901e865fe20b9fa136cca4b253d3ae73c2b78e
new file mode 100644
index 000000000..c3605201e
--- /dev/null
+++ b/fuzzers/corpora/midx/58901e865fe20b9fa136cca4b253d3ae73c2b78e
Binary files differ
diff --git a/fuzzers/corpora/midx/58a87098a14572e46b53c87340083f999d8fcfc2 b/fuzzers/corpora/midx/58a87098a14572e46b53c87340083f999d8fcfc2
new file mode 100644
index 000000000..f3711cd08
--- /dev/null
+++ b/fuzzers/corpora/midx/58a87098a14572e46b53c87340083f999d8fcfc2
Binary files differ
diff --git a/fuzzers/corpora/midx/59ae139a21448e0eb7371ddc6ef57f0c9dfe9c85 b/fuzzers/corpora/midx/59ae139a21448e0eb7371ddc6ef57f0c9dfe9c85
new file mode 100644
index 000000000..953072ca1
--- /dev/null
+++ b/fuzzers/corpora/midx/59ae139a21448e0eb7371ddc6ef57f0c9dfe9c85
Binary files differ
diff --git a/fuzzers/corpora/midx/5a7e81419f895168c555ac9b4e75a1ad4f04b34a b/fuzzers/corpora/midx/5a7e81419f895168c555ac9b4e75a1ad4f04b34a
new file mode 100644
index 000000000..c6b2c583f
--- /dev/null
+++ b/fuzzers/corpora/midx/5a7e81419f895168c555ac9b4e75a1ad4f04b34a
Binary files differ
diff --git a/fuzzers/corpora/midx/5b848c1f56a150d64020e9b0bb398a286dca4096 b/fuzzers/corpora/midx/5b848c1f56a150d64020e9b0bb398a286dca4096
new file mode 100644
index 000000000..17e91c12e
--- /dev/null
+++ b/fuzzers/corpora/midx/5b848c1f56a150d64020e9b0bb398a286dca4096
Binary files differ
diff --git a/fuzzers/corpora/midx/5bd311bd846336149b2815666052fdb7e8bf2ea6 b/fuzzers/corpora/midx/5bd311bd846336149b2815666052fdb7e8bf2ea6
new file mode 100644
index 000000000..ccfa796ec
--- /dev/null
+++ b/fuzzers/corpora/midx/5bd311bd846336149b2815666052fdb7e8bf2ea6
Binary files differ
diff --git a/fuzzers/corpora/midx/5ce77eb98473a2e01d04909939edf7aabef5762c b/fuzzers/corpora/midx/5ce77eb98473a2e01d04909939edf7aabef5762c
new file mode 100644
index 000000000..b8ed8eea9
--- /dev/null
+++ b/fuzzers/corpora/midx/5ce77eb98473a2e01d04909939edf7aabef5762c
Binary files differ
diff --git a/fuzzers/corpora/midx/5e5cd5819811507ac69bd8abad27433ccd6b7521 b/fuzzers/corpora/midx/5e5cd5819811507ac69bd8abad27433ccd6b7521
new file mode 100644
index 000000000..9069e16c1
--- /dev/null
+++ b/fuzzers/corpora/midx/5e5cd5819811507ac69bd8abad27433ccd6b7521
Binary files differ
diff --git a/fuzzers/corpora/midx/5ea114ae3dbb140364000c416152b0f32ce3de23 b/fuzzers/corpora/midx/5ea114ae3dbb140364000c416152b0f32ce3de23
new file mode 100644
index 000000000..2c0394488
--- /dev/null
+++ b/fuzzers/corpora/midx/5ea114ae3dbb140364000c416152b0f32ce3de23
Binary files differ
diff --git a/fuzzers/corpora/midx/5f181bb0a79603c84534a9b8e37ecdeb1d2aeeb5 b/fuzzers/corpora/midx/5f181bb0a79603c84534a9b8e37ecdeb1d2aeeb5
new file mode 100644
index 000000000..c1a826f37
--- /dev/null
+++ b/fuzzers/corpora/midx/5f181bb0a79603c84534a9b8e37ecdeb1d2aeeb5
@@ -0,0 +1 @@
+ãÂë®<™“ V¨Ý`oÓ¤Ük @rÜshuffleéDHE-PSK-ARÿÿÿÿÿÿÿ'MIDÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛßÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛàÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÙÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÙÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ \ No newline at end of file
diff --git a/fuzzers/corpora/midx/5f428ce1169e28353cedb8be3e2f6edd0ef354e4 b/fuzzers/corpora/midx/5f428ce1169e28353cedb8be3e2f6edd0ef354e4
new file mode 100644
index 000000000..e2b08527f
--- /dev/null
+++ b/fuzzers/corpora/midx/5f428ce1169e28353cedb8be3e2f6edd0ef354e4
Binary files differ
diff --git a/fuzzers/corpora/midx/5f9bc7729dc331e3c4d8e52df0688abad6d4aee8 b/fuzzers/corpora/midx/5f9bc7729dc331e3c4d8e52df0688abad6d4aee8
new file mode 100644
index 000000000..31b96f9a9
--- /dev/null
+++ b/fuzzers/corpora/midx/5f9bc7729dc331e3c4d8e52df0688abad6d4aee8
Binary files differ
diff --git a/fuzzers/corpora/midx/619527e1d650cd1c26e9bc61e424c9fdc04b17b9 b/fuzzers/corpora/midx/619527e1d650cd1c26e9bc61e424c9fdc04b17b9
new file mode 100644
index 000000000..87c36d778
--- /dev/null
+++ b/fuzzers/corpora/midx/619527e1d650cd1c26e9bc61e424c9fdc04b17b9
Binary files differ
diff --git a/fuzzers/corpora/midx/625d3676de25188865e05db2a3933c38508406fc b/fuzzers/corpora/midx/625d3676de25188865e05db2a3933c38508406fc
new file mode 100644
index 000000000..95c2db2f0
--- /dev/null
+++ b/fuzzers/corpora/midx/625d3676de25188865e05db2a3933c38508406fc
Binary files differ
diff --git a/fuzzers/corpora/midx/6368569cfde7fbe369a0ee4695fa4d5a7d7887a6 b/fuzzers/corpora/midx/6368569cfde7fbe369a0ee4695fa4d5a7d7887a6
new file mode 100644
index 000000000..47ffb54a7
--- /dev/null
+++ b/fuzzers/corpora/midx/6368569cfde7fbe369a0ee4695fa4d5a7d7887a6
Binary files differ
diff --git a/fuzzers/corpora/midx/6388fe4d630064ea1ea33aa85381d9c82e328e95 b/fuzzers/corpora/midx/6388fe4d630064ea1ea33aa85381d9c82e328e95
new file mode 100644
index 000000000..85cf1e1d9
--- /dev/null
+++ b/fuzzers/corpora/midx/6388fe4d630064ea1ea33aa85381d9c82e328e95
Binary files differ
diff --git a/fuzzers/corpora/midx/64cff4e110f0bcb3ea833c1afda6e27a57dac0bc b/fuzzers/corpora/midx/64cff4e110f0bcb3ea833c1afda6e27a57dac0bc
new file mode 100644
index 000000000..29ac450b3
--- /dev/null
+++ b/fuzzers/corpora/midx/64cff4e110f0bcb3ea833c1afda6e27a57dac0bc
Binary files differ
diff --git a/fuzzers/corpora/midx/66449b87ce47b681c6326f337bebf03366a0ee99 b/fuzzers/corpora/midx/66449b87ce47b681c6326f337bebf03366a0ee99
new file mode 100644
index 000000000..a2b3b25d4
--- /dev/null
+++ b/fuzzers/corpora/midx/66449b87ce47b681c6326f337bebf03366a0ee99
Binary files differ
diff --git a/fuzzers/corpora/midx/66ae3584497a1823a955c33e5bc53f7434c13e49 b/fuzzers/corpora/midx/66ae3584497a1823a955c33e5bc53f7434c13e49
new file mode 100644
index 000000000..0d5dcff5e
--- /dev/null
+++ b/fuzzers/corpora/midx/66ae3584497a1823a955c33e5bc53f7434c13e49
Binary files differ
diff --git a/fuzzers/corpora/midx/66e238a6ad70fb30c82171ff1b73ea71b4379355 b/fuzzers/corpora/midx/66e238a6ad70fb30c82171ff1b73ea71b4379355
new file mode 100644
index 000000000..6f28e8dfd
--- /dev/null
+++ b/fuzzers/corpora/midx/66e238a6ad70fb30c82171ff1b73ea71b4379355
Binary files differ
diff --git a/fuzzers/corpora/midx/66f345dc060ac5a1fe8bcf0828102d072deb1111 b/fuzzers/corpora/midx/66f345dc060ac5a1fe8bcf0828102d072deb1111
new file mode 100644
index 000000000..6d3181f63
--- /dev/null
+++ b/fuzzers/corpora/midx/66f345dc060ac5a1fe8bcf0828102d072deb1111
Binary files differ
diff --git a/fuzzers/corpora/midx/66f839146ef46deed25fd2cd169a4f1a2a3533fa b/fuzzers/corpora/midx/66f839146ef46deed25fd2cd169a4f1a2a3533fa
new file mode 100644
index 000000000..5a6223d74
--- /dev/null
+++ b/fuzzers/corpora/midx/66f839146ef46deed25fd2cd169a4f1a2a3533fa
Binary files differ
diff --git a/fuzzers/corpora/midx/671720ee2b7ba45920b41b8016eb5206b88168ee b/fuzzers/corpora/midx/671720ee2b7ba45920b41b8016eb5206b88168ee
new file mode 100644
index 000000000..564ff2b1b
--- /dev/null
+++ b/fuzzers/corpora/midx/671720ee2b7ba45920b41b8016eb5206b88168ee
Binary files differ
diff --git a/fuzzers/corpora/midx/679c7140ad60ed32aeb7ee464499dd52b0fc212f b/fuzzers/corpora/midx/679c7140ad60ed32aeb7ee464499dd52b0fc212f
new file mode 100644
index 000000000..189132305
--- /dev/null
+++ b/fuzzers/corpora/midx/679c7140ad60ed32aeb7ee464499dd52b0fc212f
Binary files differ
diff --git a/fuzzers/corpora/midx/67c5e6ce7bb47cefe54d749374f3288a2c915936 b/fuzzers/corpora/midx/67c5e6ce7bb47cefe54d749374f3288a2c915936
new file mode 100644
index 000000000..7e3303af9
--- /dev/null
+++ b/fuzzers/corpora/midx/67c5e6ce7bb47cefe54d749374f3288a2c915936
Binary files differ
diff --git a/fuzzers/corpora/midx/69592399b45f2f83e0cc823c5f0e3865ac3fa611 b/fuzzers/corpora/midx/69592399b45f2f83e0cc823c5f0e3865ac3fa611
new file mode 100644
index 000000000..272619cb6
--- /dev/null
+++ b/fuzzers/corpora/midx/69592399b45f2f83e0cc823c5f0e3865ac3fa611
Binary files differ
diff --git a/fuzzers/corpora/midx/6abf97508f0ed808b7fe0d9bb2439981153badd2 b/fuzzers/corpora/midx/6abf97508f0ed808b7fe0d9bb2439981153badd2
new file mode 100644
index 000000000..800363386
--- /dev/null
+++ b/fuzzers/corpora/midx/6abf97508f0ed808b7fe0d9bb2439981153badd2
Binary files differ
diff --git a/fuzzers/corpora/midx/6b2dfb51b35b78680cb02ff54e06f0c983c04866 b/fuzzers/corpora/midx/6b2dfb51b35b78680cb02ff54e06f0c983c04866
new file mode 100644
index 000000000..2909a341a
--- /dev/null
+++ b/fuzzers/corpora/midx/6b2dfb51b35b78680cb02ff54e06f0c983c04866
Binary files differ
diff --git a/fuzzers/corpora/midx/6bbf6ab605fedd41ed6c7581ec9f87c75403e9c3 b/fuzzers/corpora/midx/6bbf6ab605fedd41ed6c7581ec9f87c75403e9c3
new file mode 100644
index 000000000..d41ae611d
--- /dev/null
+++ b/fuzzers/corpora/midx/6bbf6ab605fedd41ed6c7581ec9f87c75403e9c3
Binary files differ
diff --git a/fuzzers/corpora/midx/6c0656104902e1323f3a19c46df7cffecae94f1c b/fuzzers/corpora/midx/6c0656104902e1323f3a19c46df7cffecae94f1c
new file mode 100644
index 000000000..a47781bdf
--- /dev/null
+++ b/fuzzers/corpora/midx/6c0656104902e1323f3a19c46df7cffecae94f1c
Binary files differ
diff --git a/fuzzers/corpora/midx/6c0ce8006b3ebd8202e61fe5f4cc2285248bd1ba b/fuzzers/corpora/midx/6c0ce8006b3ebd8202e61fe5f4cc2285248bd1ba
new file mode 100644
index 000000000..ca2e6fb53
--- /dev/null
+++ b/fuzzers/corpora/midx/6c0ce8006b3ebd8202e61fe5f4cc2285248bd1ba
Binary files differ
diff --git a/fuzzers/corpora/midx/6cc635e6dd4e430ed4fb68a9f5add38aa02ae14f b/fuzzers/corpora/midx/6cc635e6dd4e430ed4fb68a9f5add38aa02ae14f
new file mode 100644
index 000000000..8f04f864c
--- /dev/null
+++ b/fuzzers/corpora/midx/6cc635e6dd4e430ed4fb68a9f5add38aa02ae14f
Binary files differ
diff --git a/fuzzers/corpora/midx/6d1b281d7bdd9887e53505fd5d040731db18ba48 b/fuzzers/corpora/midx/6d1b281d7bdd9887e53505fd5d040731db18ba48
new file mode 100644
index 000000000..93f359a47
--- /dev/null
+++ b/fuzzers/corpora/midx/6d1b281d7bdd9887e53505fd5d040731db18ba48
Binary files differ
diff --git a/fuzzers/corpora/midx/6d5c35f9d87253b2fbe383bfde3775a9f737da12 b/fuzzers/corpora/midx/6d5c35f9d87253b2fbe383bfde3775a9f737da12
new file mode 100644
index 000000000..fe238cdfd
--- /dev/null
+++ b/fuzzers/corpora/midx/6d5c35f9d87253b2fbe383bfde3775a9f737da12
@@ -0,0 +1 @@
+ãÿÿÿÿÿÿÿïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïÿÿÿÿÿÿÓïïïïïïïïïïïïïïïïïïïï÷ïïïïïïïïïïïÿ \ No newline at end of file
diff --git a/fuzzers/corpora/midx/6d95355018cadedd97bed65c45a44a7ff6f065f7 b/fuzzers/corpora/midx/6d95355018cadedd97bed65c45a44a7ff6f065f7
new file mode 100644
index 000000000..1c1a35486
--- /dev/null
+++ b/fuzzers/corpora/midx/6d95355018cadedd97bed65c45a44a7ff6f065f7
Binary files differ
diff --git a/fuzzers/corpora/midx/6dd70e887ab94db3327d9aaa0335914a1f4986b7 b/fuzzers/corpora/midx/6dd70e887ab94db3327d9aaa0335914a1f4986b7
new file mode 100644
index 000000000..c1edd0b5d
--- /dev/null
+++ b/fuzzers/corpora/midx/6dd70e887ab94db3327d9aaa0335914a1f4986b7
Binary files differ
diff --git a/fuzzers/corpora/midx/6ed51a953a8b6671de417406e340d8d0a211aa12 b/fuzzers/corpora/midx/6ed51a953a8b6671de417406e340d8d0a211aa12
new file mode 100644
index 000000000..d21f30c03
--- /dev/null
+++ b/fuzzers/corpora/midx/6ed51a953a8b6671de417406e340d8d0a211aa12
Binary files differ
diff --git a/fuzzers/corpora/midx/6f911f19652a4457c93ef92b594bc1dc2ca900f8 b/fuzzers/corpora/midx/6f911f19652a4457c93ef92b594bc1dc2ca900f8
new file mode 100644
index 000000000..8c537dc8d
--- /dev/null
+++ b/fuzzers/corpora/midx/6f911f19652a4457c93ef92b594bc1dc2ca900f8
Binary files differ
diff --git a/fuzzers/corpora/midx/6fa76cbaeb3cf0417c7a372132167bcd737db66b b/fuzzers/corpora/midx/6fa76cbaeb3cf0417c7a372132167bcd737db66b
new file mode 100644
index 000000000..a506334e0
--- /dev/null
+++ b/fuzzers/corpora/midx/6fa76cbaeb3cf0417c7a372132167bcd737db66b
Binary files differ
diff --git a/fuzzers/corpora/midx/71f66d3f7da318d69681a22ebbceb1a2bb290658 b/fuzzers/corpora/midx/71f66d3f7da318d69681a22ebbceb1a2bb290658
new file mode 100644
index 000000000..317820a99
--- /dev/null
+++ b/fuzzers/corpora/midx/71f66d3f7da318d69681a22ebbceb1a2bb290658
Binary files differ
diff --git a/fuzzers/corpora/midx/7227a2dc335af13e7225536c49969f46a800750a b/fuzzers/corpora/midx/7227a2dc335af13e7225536c49969f46a800750a
new file mode 100644
index 000000000..d7b9d6f34
--- /dev/null
+++ b/fuzzers/corpora/midx/7227a2dc335af13e7225536c49969f46a800750a
@@ -0,0 +1 @@
+ãj \ No newline at end of file
diff --git a/fuzzers/corpora/midx/72fce27bbccf582f2023f5e168853251e576592a b/fuzzers/corpora/midx/72fce27bbccf582f2023f5e168853251e576592a
new file mode 100644
index 000000000..646d858bf
--- /dev/null
+++ b/fuzzers/corpora/midx/72fce27bbccf582f2023f5e168853251e576592a
Binary files differ
diff --git a/fuzzers/corpora/midx/738e5543ae005a6de85dfcd960eb8e3e6faa8947 b/fuzzers/corpora/midx/738e5543ae005a6de85dfcd960eb8e3e6faa8947
new file mode 100644
index 000000000..33dd640b4
--- /dev/null
+++ b/fuzzers/corpora/midx/738e5543ae005a6de85dfcd960eb8e3e6faa8947
Binary files differ
diff --git a/fuzzers/corpora/midx/739d9c8868445202305d0a4e5766df1c68932688 b/fuzzers/corpora/midx/739d9c8868445202305d0a4e5766df1c68932688
new file mode 100644
index 000000000..58450d924
--- /dev/null
+++ b/fuzzers/corpora/midx/739d9c8868445202305d0a4e5766df1c68932688
Binary files differ
diff --git a/fuzzers/corpora/midx/7438b07314917c84d348e7d9629e3712190c7da7 b/fuzzers/corpora/midx/7438b07314917c84d348e7d9629e3712190c7da7
new file mode 100644
index 000000000..197006e44
--- /dev/null
+++ b/fuzzers/corpora/midx/7438b07314917c84d348e7d9629e3712190c7da7
Binary files differ
diff --git a/fuzzers/corpora/midx/7490f00d660f5d8dedfa606cca241bd07be86a4f b/fuzzers/corpora/midx/7490f00d660f5d8dedfa606cca241bd07be86a4f
new file mode 100644
index 000000000..9f056b2b5
--- /dev/null
+++ b/fuzzers/corpora/midx/7490f00d660f5d8dedfa606cca241bd07be86a4f
Binary files differ
diff --git a/fuzzers/corpora/midx/75c64e8b61af41b28516c2c0fe902362d55a24f3 b/fuzzers/corpora/midx/75c64e8b61af41b28516c2c0fe902362d55a24f3
new file mode 100644
index 000000000..7832dbce6
--- /dev/null
+++ b/fuzzers/corpora/midx/75c64e8b61af41b28516c2c0fe902362d55a24f3
Binary files differ
diff --git a/fuzzers/corpora/midx/75e94b59a41e7f086b6f7ab3bca801251744ae3d b/fuzzers/corpora/midx/75e94b59a41e7f086b6f7ab3bca801251744ae3d
new file mode 100644
index 000000000..573a589e9
--- /dev/null
+++ b/fuzzers/corpora/midx/75e94b59a41e7f086b6f7ab3bca801251744ae3d
Binary files differ
diff --git a/fuzzers/corpora/midx/7612ceb3a989f97a7bb19f57c7f9c61366953642 b/fuzzers/corpora/midx/7612ceb3a989f97a7bb19f57c7f9c61366953642
new file mode 100644
index 000000000..1dddb9d6d
--- /dev/null
+++ b/fuzzers/corpora/midx/7612ceb3a989f97a7bb19f57c7f9c61366953642
Binary files differ
diff --git a/fuzzers/corpora/midx/76ac2328e1c979bca648b4082b8bfe6f2e2e73ea b/fuzzers/corpora/midx/76ac2328e1c979bca648b4082b8bfe6f2e2e73ea
new file mode 100644
index 000000000..fa3ab13d8
--- /dev/null
+++ b/fuzzers/corpora/midx/76ac2328e1c979bca648b4082b8bfe6f2e2e73ea
Binary files differ
diff --git a/fuzzers/corpora/midx/76f296039ba4d666c9147ad234d43b55050808e3 b/fuzzers/corpora/midx/76f296039ba4d666c9147ad234d43b55050808e3
new file mode 100644
index 000000000..114e764aa
--- /dev/null
+++ b/fuzzers/corpora/midx/76f296039ba4d666c9147ad234d43b55050808e3
Binary files differ
diff --git a/fuzzers/corpora/midx/777f248eea53e3dd2b726e1e0de5eeda43b6d323 b/fuzzers/corpora/midx/777f248eea53e3dd2b726e1e0de5eeda43b6d323
new file mode 100644
index 000000000..120ffd6ed
--- /dev/null
+++ b/fuzzers/corpora/midx/777f248eea53e3dd2b726e1e0de5eeda43b6d323
@@ -0,0 +1 @@
+› \ No newline at end of file
diff --git a/fuzzers/corpora/midx/792fcd0075bd8031a98a68ce04d6a9f23feef7b4 b/fuzzers/corpora/midx/792fcd0075bd8031a98a68ce04d6a9f23feef7b4
new file mode 100644
index 000000000..ca5572e9c
--- /dev/null
+++ b/fuzzers/corpora/midx/792fcd0075bd8031a98a68ce04d6a9f23feef7b4
Binary files differ
diff --git a/fuzzers/corpora/midx/7a936c3e69013b2c71dcb72f0eccd99c93367533 b/fuzzers/corpora/midx/7a936c3e69013b2c71dcb72f0eccd99c93367533
new file mode 100644
index 000000000..8c3d72944
--- /dev/null
+++ b/fuzzers/corpora/midx/7a936c3e69013b2c71dcb72f0eccd99c93367533
Binary files differ
diff --git a/fuzzers/corpora/midx/7b30d0cd07108f2e45ce1a3fab3f971b25dcf5cd b/fuzzers/corpora/midx/7b30d0cd07108f2e45ce1a3fab3f971b25dcf5cd
new file mode 100644
index 000000000..08ddd3465
--- /dev/null
+++ b/fuzzers/corpora/midx/7b30d0cd07108f2e45ce1a3fab3f971b25dcf5cd
Binary files differ
diff --git a/fuzzers/corpora/midx/7b87f367b5fa3bf29bae19031814e5d0120a15ba b/fuzzers/corpora/midx/7b87f367b5fa3bf29bae19031814e5d0120a15ba
new file mode 100644
index 000000000..146d3ee7f
--- /dev/null
+++ b/fuzzers/corpora/midx/7b87f367b5fa3bf29bae19031814e5d0120a15ba
Binary files differ
diff --git a/fuzzers/corpora/midx/7c12e4bca60858eae13c47a66e54cd9e96a50909 b/fuzzers/corpora/midx/7c12e4bca60858eae13c47a66e54cd9e96a50909
new file mode 100644
index 000000000..a3cb4abe1
--- /dev/null
+++ b/fuzzers/corpora/midx/7c12e4bca60858eae13c47a66e54cd9e96a50909
Binary files differ
diff --git a/fuzzers/corpora/midx/7c59f95e649b3be6344f4f835afd0d9a894c1144 b/fuzzers/corpora/midx/7c59f95e649b3be6344f4f835afd0d9a894c1144
new file mode 100644
index 000000000..4a9c07ce0
--- /dev/null
+++ b/fuzzers/corpora/midx/7c59f95e649b3be6344f4f835afd0d9a894c1144
Binary files differ
diff --git a/fuzzers/corpora/midx/7dcb6494c3614a8690dc496309f90e0f23634c37 b/fuzzers/corpora/midx/7dcb6494c3614a8690dc496309f90e0f23634c37
new file mode 100644
index 000000000..ef09d98dc
--- /dev/null
+++ b/fuzzers/corpora/midx/7dcb6494c3614a8690dc496309f90e0f23634c37
Binary files differ
diff --git a/fuzzers/corpora/midx/7e64b86827ea98f0a4eb54736c460a59b0c30420 b/fuzzers/corpora/midx/7e64b86827ea98f0a4eb54736c460a59b0c30420
new file mode 100644
index 000000000..6062c8d5e
--- /dev/null
+++ b/fuzzers/corpora/midx/7e64b86827ea98f0a4eb54736c460a59b0c30420
Binary files differ
diff --git a/fuzzers/corpora/midx/8125d9eaa09b3d2283fea73223866cb36877c4a4 b/fuzzers/corpora/midx/8125d9eaa09b3d2283fea73223866cb36877c4a4
new file mode 100644
index 000000000..d91f4ebd1
--- /dev/null
+++ b/fuzzers/corpora/midx/8125d9eaa09b3d2283fea73223866cb36877c4a4
Binary files differ
diff --git a/fuzzers/corpora/midx/81c7fc514fa9a07b5b87b94cf9c00df2b1325a74 b/fuzzers/corpora/midx/81c7fc514fa9a07b5b87b94cf9c00df2b1325a74
new file mode 100644
index 000000000..2c19a2acf
--- /dev/null
+++ b/fuzzers/corpora/midx/81c7fc514fa9a07b5b87b94cf9c00df2b1325a74
Binary files differ
diff --git a/fuzzers/corpora/midx/81f9df0493052d980ca13918637bc6ce565615b3 b/fuzzers/corpora/midx/81f9df0493052d980ca13918637bc6ce565615b3
new file mode 100644
index 000000000..1030a4bca
--- /dev/null
+++ b/fuzzers/corpora/midx/81f9df0493052d980ca13918637bc6ce565615b3
Binary files differ
diff --git a/fuzzers/corpora/midx/82556b9345134dd689cb9d0d08d3dc8459454181 b/fuzzers/corpora/midx/82556b9345134dd689cb9d0d08d3dc8459454181
new file mode 100644
index 000000000..e8a113f06
--- /dev/null
+++ b/fuzzers/corpora/midx/82556b9345134dd689cb9d0d08d3dc8459454181
Binary files differ
diff --git a/fuzzers/corpora/midx/82d35a7a6ffb333b02d0d597e88ffdd481237a8b b/fuzzers/corpora/midx/82d35a7a6ffb333b02d0d597e88ffdd481237a8b
new file mode 100644
index 000000000..1f2de8ae6
--- /dev/null
+++ b/fuzzers/corpora/midx/82d35a7a6ffb333b02d0d597e88ffdd481237a8b
Binary files differ
diff --git a/fuzzers/corpora/midx/82e931da372a2c69c0f10274342173c2be091f1c b/fuzzers/corpora/midx/82e931da372a2c69c0f10274342173c2be091f1c
new file mode 100644
index 000000000..34a1c15ff
--- /dev/null
+++ b/fuzzers/corpora/midx/82e931da372a2c69c0f10274342173c2be091f1c
Binary files differ
diff --git a/fuzzers/corpora/midx/83e2b53f22afe8f7ee21d30fae2619ad0d6a71e3 b/fuzzers/corpora/midx/83e2b53f22afe8f7ee21d30fae2619ad0d6a71e3
new file mode 100644
index 000000000..8815c9beb
--- /dev/null
+++ b/fuzzers/corpora/midx/83e2b53f22afe8f7ee21d30fae2619ad0d6a71e3
Binary files differ
diff --git a/fuzzers/corpora/midx/83f4d70189dbc0d3aaf5025977c53d4d34fc5893 b/fuzzers/corpora/midx/83f4d70189dbc0d3aaf5025977c53d4d34fc5893
new file mode 100644
index 000000000..78b1f7c95
--- /dev/null
+++ b/fuzzers/corpora/midx/83f4d70189dbc0d3aaf5025977c53d4d34fc5893
Binary files differ
diff --git a/fuzzers/corpora/midx/85e17cceba7850be893afdc04c8233bea1ef6e72 b/fuzzers/corpora/midx/85e17cceba7850be893afdc04c8233bea1ef6e72
new file mode 100644
index 000000000..0e157c96c
--- /dev/null
+++ b/fuzzers/corpora/midx/85e17cceba7850be893afdc04c8233bea1ef6e72
Binary files differ
diff --git a/fuzzers/corpora/midx/874d4abdcd7db751eb930928231669afe90589f5 b/fuzzers/corpora/midx/874d4abdcd7db751eb930928231669afe90589f5
new file mode 100644
index 000000000..238ca42c3
--- /dev/null
+++ b/fuzzers/corpora/midx/874d4abdcd7db751eb930928231669afe90589f5
Binary files differ
diff --git a/fuzzers/corpora/midx/87894ec663568153d7837f49b80f6d2e99818bd7 b/fuzzers/corpora/midx/87894ec663568153d7837f49b80f6d2e99818bd7
new file mode 100644
index 000000000..d2775fdab
--- /dev/null
+++ b/fuzzers/corpora/midx/87894ec663568153d7837f49b80f6d2e99818bd7
Binary files differ
diff --git a/fuzzers/corpora/midx/88052b76108b4ede342f3dd87bb6835b2f71ea83 b/fuzzers/corpora/midx/88052b76108b4ede342f3dd87bb6835b2f71ea83
new file mode 100644
index 000000000..c0a6a3209
--- /dev/null
+++ b/fuzzers/corpora/midx/88052b76108b4ede342f3dd87bb6835b2f71ea83
Binary files differ
diff --git a/fuzzers/corpora/midx/884c54256c0ec2cf1c5fa08a0b3d9c2fea021300 b/fuzzers/corpora/midx/884c54256c0ec2cf1c5fa08a0b3d9c2fea021300
new file mode 100644
index 000000000..e0980eed5
--- /dev/null
+++ b/fuzzers/corpora/midx/884c54256c0ec2cf1c5fa08a0b3d9c2fea021300
Binary files differ
diff --git a/fuzzers/corpora/midx/8858f36373db5fd6b805a768af55c21019c664b2 b/fuzzers/corpora/midx/8858f36373db5fd6b805a768af55c21019c664b2
new file mode 100644
index 000000000..50c738d68
--- /dev/null
+++ b/fuzzers/corpora/midx/8858f36373db5fd6b805a768af55c21019c664b2
Binary files differ
diff --git a/fuzzers/corpora/midx/88fe8b6767c1bd32308208b22e0b00697e5eddf7 b/fuzzers/corpora/midx/88fe8b6767c1bd32308208b22e0b00697e5eddf7
new file mode 100644
index 000000000..da39bf149
--- /dev/null
+++ b/fuzzers/corpora/midx/88fe8b6767c1bd32308208b22e0b00697e5eddf7
Binary files differ
diff --git a/fuzzers/corpora/midx/898cac1610f2f2fb67eb092cd053f0006c3070e3 b/fuzzers/corpora/midx/898cac1610f2f2fb67eb092cd053f0006c3070e3
new file mode 100644
index 000000000..babd31d25
--- /dev/null
+++ b/fuzzers/corpora/midx/898cac1610f2f2fb67eb092cd053f0006c3070e3
Binary files differ
diff --git a/fuzzers/corpora/midx/89d0f5573ae1b524e7e9bdb1fb54ea4ce99e3ef0 b/fuzzers/corpora/midx/89d0f5573ae1b524e7e9bdb1fb54ea4ce99e3ef0
new file mode 100644
index 000000000..43858e291
--- /dev/null
+++ b/fuzzers/corpora/midx/89d0f5573ae1b524e7e9bdb1fb54ea4ce99e3ef0
Binary files differ
diff --git a/fuzzers/corpora/midx/8a55300e400efd56be5e12258ebf575c4f3b55ed b/fuzzers/corpora/midx/8a55300e400efd56be5e12258ebf575c4f3b55ed
new file mode 100644
index 000000000..bf76c1a0d
--- /dev/null
+++ b/fuzzers/corpora/midx/8a55300e400efd56be5e12258ebf575c4f3b55ed
Binary files differ
diff --git a/fuzzers/corpora/midx/8bf7b464aaa2c2b536aa1d76a1297c19155f5603 b/fuzzers/corpora/midx/8bf7b464aaa2c2b536aa1d76a1297c19155f5603
new file mode 100644
index 000000000..6b10f9584
--- /dev/null
+++ b/fuzzers/corpora/midx/8bf7b464aaa2c2b536aa1d76a1297c19155f5603
@@ -0,0 +1 @@
+Ã \ No newline at end of file
diff --git a/fuzzers/corpora/midx/8c05e8ef26302a79c89670ad3aa4e8d0bc921923 b/fuzzers/corpora/midx/8c05e8ef26302a79c89670ad3aa4e8d0bc921923
new file mode 100644
index 000000000..9f142f008
--- /dev/null
+++ b/fuzzers/corpora/midx/8c05e8ef26302a79c89670ad3aa4e8d0bc921923
Binary files differ
diff --git a/fuzzers/corpora/midx/8c15f5a268ded9663197d66e8d7d4098e0ae9bf5 b/fuzzers/corpora/midx/8c15f5a268ded9663197d66e8d7d4098e0ae9bf5
new file mode 100644
index 000000000..9b1b882c9
--- /dev/null
+++ b/fuzzers/corpora/midx/8c15f5a268ded9663197d66e8d7d4098e0ae9bf5
Binary files differ
diff --git a/fuzzers/corpora/midx/8ca9e85a9e628f0016ea4e6413945b3830730c24 b/fuzzers/corpora/midx/8ca9e85a9e628f0016ea4e6413945b3830730c24
new file mode 100644
index 000000000..e64a7c9dd
--- /dev/null
+++ b/fuzzers/corpora/midx/8ca9e85a9e628f0016ea4e6413945b3830730c24
Binary files differ
diff --git a/fuzzers/corpora/midx/8e74126a239927900a8f655c813a4b230191a5ba b/fuzzers/corpora/midx/8e74126a239927900a8f655c813a4b230191a5ba
new file mode 100644
index 000000000..32005e34a
--- /dev/null
+++ b/fuzzers/corpora/midx/8e74126a239927900a8f655c813a4b230191a5ba
Binary files differ
diff --git a/fuzzers/corpora/midx/8ee63e791c004427dd033b468b2ed7446ee6e2e0 b/fuzzers/corpora/midx/8ee63e791c004427dd033b468b2ed7446ee6e2e0
new file mode 100644
index 000000000..a9d264ac2
--- /dev/null
+++ b/fuzzers/corpora/midx/8ee63e791c004427dd033b468b2ed7446ee6e2e0
Binary files differ
diff --git a/fuzzers/corpora/midx/9028113aa78b649e13ff259027a4e450d469e5da b/fuzzers/corpora/midx/9028113aa78b649e13ff259027a4e450d469e5da
new file mode 100644
index 000000000..12c09a392
--- /dev/null
+++ b/fuzzers/corpora/midx/9028113aa78b649e13ff259027a4e450d469e5da
Binary files differ
diff --git a/fuzzers/corpora/midx/90db2115b8262ebecbefbe8f0a07c451e39bca07 b/fuzzers/corpora/midx/90db2115b8262ebecbefbe8f0a07c451e39bca07
new file mode 100644
index 000000000..38fc26c2c
--- /dev/null
+++ b/fuzzers/corpora/midx/90db2115b8262ebecbefbe8f0a07c451e39bca07
Binary files differ
diff --git a/fuzzers/corpora/midx/923f28a4d1917e20ee0736b90695c2123c0c987c b/fuzzers/corpora/midx/923f28a4d1917e20ee0736b90695c2123c0c987c
new file mode 100644
index 000000000..8961e95f2
--- /dev/null
+++ b/fuzzers/corpora/midx/923f28a4d1917e20ee0736b90695c2123c0c987c
Binary files differ
diff --git a/fuzzers/corpora/midx/92a5c74e0506d65d1a12686496452870367b169a b/fuzzers/corpora/midx/92a5c74e0506d65d1a12686496452870367b169a
new file mode 100644
index 000000000..4e08402b6
--- /dev/null
+++ b/fuzzers/corpora/midx/92a5c74e0506d65d1a12686496452870367b169a
Binary files differ
diff --git a/fuzzers/corpora/midx/92dcf94eb2f92b4e1a232eab3b3f808f4236f118 b/fuzzers/corpora/midx/92dcf94eb2f92b4e1a232eab3b3f808f4236f118
new file mode 100644
index 000000000..0999c8a25
--- /dev/null
+++ b/fuzzers/corpora/midx/92dcf94eb2f92b4e1a232eab3b3f808f4236f118
Binary files differ
diff --git a/fuzzers/corpora/midx/9414502aedbef5e307897683625418dd4ac575ac b/fuzzers/corpora/midx/9414502aedbef5e307897683625418dd4ac575ac
new file mode 100644
index 000000000..98260fb4c
--- /dev/null
+++ b/fuzzers/corpora/midx/9414502aedbef5e307897683625418dd4ac575ac
Binary files differ
diff --git a/fuzzers/corpora/midx/9422e25bec5fec9f84603a85673b54b1a5e77a40 b/fuzzers/corpora/midx/9422e25bec5fec9f84603a85673b54b1a5e77a40
new file mode 100644
index 000000000..e0d9ca7f0
--- /dev/null
+++ b/fuzzers/corpora/midx/9422e25bec5fec9f84603a85673b54b1a5e77a40
Binary files differ
diff --git a/fuzzers/corpora/midx/943754e865888063e0684aec838222522390d43e b/fuzzers/corpora/midx/943754e865888063e0684aec838222522390d43e
new file mode 100644
index 000000000..2a6ba4eb5
--- /dev/null
+++ b/fuzzers/corpora/midx/943754e865888063e0684aec838222522390d43e
Binary files differ
diff --git a/fuzzers/corpora/midx/943e067806ae069afbc029ea7a612410e5395687 b/fuzzers/corpora/midx/943e067806ae069afbc029ea7a612410e5395687
new file mode 100644
index 000000000..d51ab5fbf
--- /dev/null
+++ b/fuzzers/corpora/midx/943e067806ae069afbc029ea7a612410e5395687
Binary files differ
diff --git a/fuzzers/corpora/midx/9547646cc1a5d260df099b00ea7ee2b95567aee1 b/fuzzers/corpora/midx/9547646cc1a5d260df099b00ea7ee2b95567aee1
new file mode 100644
index 000000000..92426bcf9
--- /dev/null
+++ b/fuzzers/corpora/midx/9547646cc1a5d260df099b00ea7ee2b95567aee1
Binary files differ
diff --git a/fuzzers/corpora/midx/968f7027ec9fbf75a519069ea5189e85a81448b2 b/fuzzers/corpora/midx/968f7027ec9fbf75a519069ea5189e85a81448b2
new file mode 100644
index 000000000..56dfbcdd3
--- /dev/null
+++ b/fuzzers/corpora/midx/968f7027ec9fbf75a519069ea5189e85a81448b2
Binary files differ
diff --git a/fuzzers/corpora/midx/9691046a2f8b31319a6fdfde0506c9a72aed839a b/fuzzers/corpora/midx/9691046a2f8b31319a6fdfde0506c9a72aed839a
new file mode 100644
index 000000000..e3cfcb079
--- /dev/null
+++ b/fuzzers/corpora/midx/9691046a2f8b31319a6fdfde0506c9a72aed839a
Binary files differ
diff --git a/fuzzers/corpora/midx/96a8cd5c33986cc26cc00eb2de627149f5259e33 b/fuzzers/corpora/midx/96a8cd5c33986cc26cc00eb2de627149f5259e33
new file mode 100644
index 000000000..85fb8fa3c
--- /dev/null
+++ b/fuzzers/corpora/midx/96a8cd5c33986cc26cc00eb2de627149f5259e33
Binary files differ
diff --git a/fuzzers/corpora/midx/972466bbc33d2d7d7c21be21c7594b51e78675c5 b/fuzzers/corpora/midx/972466bbc33d2d7d7c21be21c7594b51e78675c5
new file mode 100644
index 000000000..b8fd7b35c
--- /dev/null
+++ b/fuzzers/corpora/midx/972466bbc33d2d7d7c21be21c7594b51e78675c5
Binary files differ
diff --git a/fuzzers/corpora/midx/980f21a3609762154030f7cf0fe98a892d20f220 b/fuzzers/corpora/midx/980f21a3609762154030f7cf0fe98a892d20f220
new file mode 100644
index 000000000..d89f9cd77
--- /dev/null
+++ b/fuzzers/corpora/midx/980f21a3609762154030f7cf0fe98a892d20f220
Binary files differ
diff --git a/fuzzers/corpora/midx/9865f12189ef977418d8410fceebb6830c74d820 b/fuzzers/corpora/midx/9865f12189ef977418d8410fceebb6830c74d820
new file mode 100644
index 000000000..c4d3f67dc
--- /dev/null
+++ b/fuzzers/corpora/midx/9865f12189ef977418d8410fceebb6830c74d820
Binary files differ
diff --git a/fuzzers/corpora/midx/98a1096d609545083878d5126743bbc5985786a9 b/fuzzers/corpora/midx/98a1096d609545083878d5126743bbc5985786a9
new file mode 100644
index 000000000..6cf168ee1
--- /dev/null
+++ b/fuzzers/corpora/midx/98a1096d609545083878d5126743bbc5985786a9
Binary files differ
diff --git a/fuzzers/corpora/midx/98c3b6bbf5dc19bc4aad894087277a36d7c79669 b/fuzzers/corpora/midx/98c3b6bbf5dc19bc4aad894087277a36d7c79669
new file mode 100644
index 000000000..7a11bb57f
--- /dev/null
+++ b/fuzzers/corpora/midx/98c3b6bbf5dc19bc4aad894087277a36d7c79669
Binary files differ
diff --git a/fuzzers/corpora/midx/98f9cd44400b592f809596004125267acf848435 b/fuzzers/corpora/midx/98f9cd44400b592f809596004125267acf848435
new file mode 100644
index 000000000..d4e6332b9
--- /dev/null
+++ b/fuzzers/corpora/midx/98f9cd44400b592f809596004125267acf848435
Binary files differ
diff --git a/fuzzers/corpora/midx/9a97260f04ecfe0918499ede95cf4bcb3dbc2b51 b/fuzzers/corpora/midx/9a97260f04ecfe0918499ede95cf4bcb3dbc2b51
new file mode 100644
index 000000000..ba3011ba7
--- /dev/null
+++ b/fuzzers/corpora/midx/9a97260f04ecfe0918499ede95cf4bcb3dbc2b51
Binary files differ
diff --git a/fuzzers/corpora/midx/9ba0dba2ca4405d04113086309882dac6182e6b8 b/fuzzers/corpora/midx/9ba0dba2ca4405d04113086309882dac6182e6b8
new file mode 100644
index 000000000..4513cd9f6
--- /dev/null
+++ b/fuzzers/corpora/midx/9ba0dba2ca4405d04113086309882dac6182e6b8
Binary files differ
diff --git a/fuzzers/corpora/midx/9c329ee4b02f2d26ee1a399c873b0452aedca3c0 b/fuzzers/corpora/midx/9c329ee4b02f2d26ee1a399c873b0452aedca3c0
new file mode 100644
index 000000000..ac164f4ad
--- /dev/null
+++ b/fuzzers/corpora/midx/9c329ee4b02f2d26ee1a399c873b0452aedca3c0
Binary files differ
diff --git a/fuzzers/corpora/midx/9e8e638837e202d83ff606a22dd0e310150fa260 b/fuzzers/corpora/midx/9e8e638837e202d83ff606a22dd0e310150fa260
new file mode 100644
index 000000000..93f205f64
--- /dev/null
+++ b/fuzzers/corpora/midx/9e8e638837e202d83ff606a22dd0e310150fa260
Binary files differ
diff --git a/fuzzers/corpora/midx/9ee03d17e070df72547e423a412da0b6a60ad565 b/fuzzers/corpora/midx/9ee03d17e070df72547e423a412da0b6a60ad565
new file mode 100644
index 000000000..874ce8f02
--- /dev/null
+++ b/fuzzers/corpora/midx/9ee03d17e070df72547e423a412da0b6a60ad565
Binary files differ
diff --git a/fuzzers/corpora/midx/9fad6bd2b07d65e607039bb2bcda0816410cf983 b/fuzzers/corpora/midx/9fad6bd2b07d65e607039bb2bcda0816410cf983
new file mode 100644
index 000000000..160c9ab57
--- /dev/null
+++ b/fuzzers/corpora/midx/9fad6bd2b07d65e607039bb2bcda0816410cf983
Binary files differ
diff --git a/fuzzers/corpora/midx/9fcbd21f4dd194a623d832422384a1519742f0bb b/fuzzers/corpora/midx/9fcbd21f4dd194a623d832422384a1519742f0bb
new file mode 100644
index 000000000..cce3746eb
--- /dev/null
+++ b/fuzzers/corpora/midx/9fcbd21f4dd194a623d832422384a1519742f0bb
Binary files differ
diff --git a/fuzzers/corpora/midx/a019fb7f17aa36a9743c530e1f11d5613b8b1158 b/fuzzers/corpora/midx/a019fb7f17aa36a9743c530e1f11d5613b8b1158
new file mode 100644
index 000000000..e6a45fad9
--- /dev/null
+++ b/fuzzers/corpora/midx/a019fb7f17aa36a9743c530e1f11d5613b8b1158
Binary files differ
diff --git a/fuzzers/corpora/midx/a0b8c6ef20198377b19f59e41f08f4cf2107f460 b/fuzzers/corpora/midx/a0b8c6ef20198377b19f59e41f08f4cf2107f460
new file mode 100644
index 000000000..f10d52cea
--- /dev/null
+++ b/fuzzers/corpora/midx/a0b8c6ef20198377b19f59e41f08f4cf2107f460
Binary files differ
diff --git a/fuzzers/corpora/midx/a14079a3e8cbc2112da4fa747ef20cdfd580e068 b/fuzzers/corpora/midx/a14079a3e8cbc2112da4fa747ef20cdfd580e068
new file mode 100644
index 000000000..1d17566b8
--- /dev/null
+++ b/fuzzers/corpora/midx/a14079a3e8cbc2112da4fa747ef20cdfd580e068
Binary files differ
diff --git a/fuzzers/corpora/midx/a14d61ba0c609665d37e6c6da929cb53c5b70545 b/fuzzers/corpora/midx/a14d61ba0c609665d37e6c6da929cb53c5b70545
new file mode 100644
index 000000000..d70d19ef9
--- /dev/null
+++ b/fuzzers/corpora/midx/a14d61ba0c609665d37e6c6da929cb53c5b70545
Binary files differ
diff --git a/fuzzers/corpora/midx/a15cf2a13e408cb76af0091a0c286af7ffce58e1 b/fuzzers/corpora/midx/a15cf2a13e408cb76af0091a0c286af7ffce58e1
new file mode 100644
index 000000000..23b70ad6f
--- /dev/null
+++ b/fuzzers/corpora/midx/a15cf2a13e408cb76af0091a0c286af7ffce58e1
Binary files differ
diff --git a/fuzzers/corpora/midx/a1ddedbdd05eac99b8b31322635771cd9c999f8a b/fuzzers/corpora/midx/a1ddedbdd05eac99b8b31322635771cd9c999f8a
new file mode 100644
index 000000000..066e405c2
--- /dev/null
+++ b/fuzzers/corpora/midx/a1ddedbdd05eac99b8b31322635771cd9c999f8a
Binary files differ
diff --git a/fuzzers/corpora/midx/a235661c3f8b0174a1658e9c435a69577c49256a b/fuzzers/corpora/midx/a235661c3f8b0174a1658e9c435a69577c49256a
new file mode 100644
index 000000000..ca719f251
--- /dev/null
+++ b/fuzzers/corpora/midx/a235661c3f8b0174a1658e9c435a69577c49256a
Binary files differ
diff --git a/fuzzers/corpora/midx/a261397a4db5ac196c72d73ba6999e9fd4fc5c1f b/fuzzers/corpora/midx/a261397a4db5ac196c72d73ba6999e9fd4fc5c1f
new file mode 100644
index 000000000..ae0d0428a
--- /dev/null
+++ b/fuzzers/corpora/midx/a261397a4db5ac196c72d73ba6999e9fd4fc5c1f
Binary files differ
diff --git a/fuzzers/corpora/midx/a3a803fd6a56d31269717983bbdf2fceebb626c3 b/fuzzers/corpora/midx/a3a803fd6a56d31269717983bbdf2fceebb626c3
new file mode 100644
index 000000000..f813f2576
--- /dev/null
+++ b/fuzzers/corpora/midx/a3a803fd6a56d31269717983bbdf2fceebb626c3
Binary files differ
diff --git a/fuzzers/corpora/midx/a3d5b0b21d977e8f94d401250de1bbd4fa1d0ee0 b/fuzzers/corpora/midx/a3d5b0b21d977e8f94d401250de1bbd4fa1d0ee0
new file mode 100644
index 000000000..151c74bf9
--- /dev/null
+++ b/fuzzers/corpora/midx/a3d5b0b21d977e8f94d401250de1bbd4fa1d0ee0
Binary files differ
diff --git a/fuzzers/corpora/midx/a42f2900ca519bd15b8d6f507449d1a07de2ef75 b/fuzzers/corpora/midx/a42f2900ca519bd15b8d6f507449d1a07de2ef75
new file mode 100644
index 000000000..efd2d8793
--- /dev/null
+++ b/fuzzers/corpora/midx/a42f2900ca519bd15b8d6f507449d1a07de2ef75
Binary files differ
diff --git a/fuzzers/corpora/midx/a4884775b414eaf9643224564f3be405519cf99a b/fuzzers/corpora/midx/a4884775b414eaf9643224564f3be405519cf99a
new file mode 100644
index 000000000..7e6260b4c
--- /dev/null
+++ b/fuzzers/corpora/midx/a4884775b414eaf9643224564f3be405519cf99a
Binary files differ
diff --git a/fuzzers/corpora/midx/a48da63e9a5709c24cb66f598a7a964cbc7ccfc7 b/fuzzers/corpora/midx/a48da63e9a5709c24cb66f598a7a964cbc7ccfc7
new file mode 100644
index 000000000..2e553bf4e
--- /dev/null
+++ b/fuzzers/corpora/midx/a48da63e9a5709c24cb66f598a7a964cbc7ccfc7
Binary files differ
diff --git a/fuzzers/corpora/midx/a5789fd83dff18079ea7ba41c999f57bee4db41b b/fuzzers/corpora/midx/a5789fd83dff18079ea7ba41c999f57bee4db41b
new file mode 100644
index 000000000..5d0a92655
--- /dev/null
+++ b/fuzzers/corpora/midx/a5789fd83dff18079ea7ba41c999f57bee4db41b
Binary files differ
diff --git a/fuzzers/corpora/midx/a5bb1c60191742df4a91afb622e9b22a2f0b7765 b/fuzzers/corpora/midx/a5bb1c60191742df4a91afb622e9b22a2f0b7765
new file mode 100644
index 000000000..967cd2599
--- /dev/null
+++ b/fuzzers/corpora/midx/a5bb1c60191742df4a91afb622e9b22a2f0b7765
Binary files differ
diff --git a/fuzzers/corpora/midx/a5fdfade1cef5e7e494dd6e3791bca5a663d7012 b/fuzzers/corpora/midx/a5fdfade1cef5e7e494dd6e3791bca5a663d7012
new file mode 100644
index 000000000..0739dd639
--- /dev/null
+++ b/fuzzers/corpora/midx/a5fdfade1cef5e7e494dd6e3791bca5a663d7012
Binary files differ
diff --git a/fuzzers/corpora/midx/a6c66f79f5aaf2c1a26ff16754fe1a8c22627e0c b/fuzzers/corpora/midx/a6c66f79f5aaf2c1a26ff16754fe1a8c22627e0c
new file mode 100644
index 000000000..8d2257752
--- /dev/null
+++ b/fuzzers/corpora/midx/a6c66f79f5aaf2c1a26ff16754fe1a8c22627e0c
Binary files differ
diff --git a/fuzzers/corpora/midx/a7478a05a1fc04a9e035be5593bfb6a281ec460f b/fuzzers/corpora/midx/a7478a05a1fc04a9e035be5593bfb6a281ec460f
new file mode 100644
index 000000000..f25cd8e2c
--- /dev/null
+++ b/fuzzers/corpora/midx/a7478a05a1fc04a9e035be5593bfb6a281ec460f
Binary files differ
diff --git a/fuzzers/corpora/midx/a75193dd600661d2b417d4e29b23faa7d721c214 b/fuzzers/corpora/midx/a75193dd600661d2b417d4e29b23faa7d721c214
new file mode 100644
index 000000000..765d7f1d5
--- /dev/null
+++ b/fuzzers/corpora/midx/a75193dd600661d2b417d4e29b23faa7d721c214
Binary files differ
diff --git a/fuzzers/corpora/midx/a7ccae74c641ffcdda0042e6c04438d5b32c4cf3 b/fuzzers/corpora/midx/a7ccae74c641ffcdda0042e6c04438d5b32c4cf3
new file mode 100644
index 000000000..c180cfacd
--- /dev/null
+++ b/fuzzers/corpora/midx/a7ccae74c641ffcdda0042e6c04438d5b32c4cf3
Binary files differ
diff --git a/fuzzers/corpora/midx/a94aa5881abdea5374775b8155812121673f89c3 b/fuzzers/corpora/midx/a94aa5881abdea5374775b8155812121673f89c3
new file mode 100644
index 000000000..3e2266b74
--- /dev/null
+++ b/fuzzers/corpora/midx/a94aa5881abdea5374775b8155812121673f89c3
Binary files differ
diff --git a/fuzzers/corpora/midx/a98d794f0f24be7a36917826121fc14a24120893 b/fuzzers/corpora/midx/a98d794f0f24be7a36917826121fc14a24120893
new file mode 100644
index 000000000..2529c4e04
--- /dev/null
+++ b/fuzzers/corpora/midx/a98d794f0f24be7a36917826121fc14a24120893
@@ -0,0 +1 @@
+Ñã \ No newline at end of file
diff --git a/fuzzers/corpora/midx/a993077e321bc4e1831bb5a8ac7511d90d32ae27 b/fuzzers/corpora/midx/a993077e321bc4e1831bb5a8ac7511d90d32ae27
new file mode 100644
index 000000000..c0d4c9b0a
--- /dev/null
+++ b/fuzzers/corpora/midx/a993077e321bc4e1831bb5a8ac7511d90d32ae27
Binary files differ
diff --git a/fuzzers/corpora/midx/aa3bc67656945e43f9342d3aaaef247584d96cfa b/fuzzers/corpora/midx/aa3bc67656945e43f9342d3aaaef247584d96cfa
new file mode 100644
index 000000000..a6e20c9db
--- /dev/null
+++ b/fuzzers/corpora/midx/aa3bc67656945e43f9342d3aaaef247584d96cfa
Binary files differ
diff --git a/fuzzers/corpora/midx/ab111c4d72e3d6796e3d7391e9f35b4e6fefc04a b/fuzzers/corpora/midx/ab111c4d72e3d6796e3d7391e9f35b4e6fefc04a
new file mode 100644
index 000000000..4b65b4d2a
--- /dev/null
+++ b/fuzzers/corpora/midx/ab111c4d72e3d6796e3d7391e9f35b4e6fefc04a
Binary files differ
diff --git a/fuzzers/corpora/midx/ab248c42f77952d5d17d6f5203adaa5925c05c64 b/fuzzers/corpora/midx/ab248c42f77952d5d17d6f5203adaa5925c05c64
new file mode 100644
index 000000000..87bc32739
--- /dev/null
+++ b/fuzzers/corpora/midx/ab248c42f77952d5d17d6f5203adaa5925c05c64
Binary files differ
diff --git a/fuzzers/corpora/midx/ab8451fadf805e5087837d9f6d91ef7eb6fa5edb b/fuzzers/corpora/midx/ab8451fadf805e5087837d9f6d91ef7eb6fa5edb
new file mode 100644
index 000000000..ad08d1cd8
--- /dev/null
+++ b/fuzzers/corpora/midx/ab8451fadf805e5087837d9f6d91ef7eb6fa5edb
Binary files differ
diff --git a/fuzzers/corpora/midx/abbee3b37aff879b1cef47390001b89b0f6ebc0a b/fuzzers/corpora/midx/abbee3b37aff879b1cef47390001b89b0f6ebc0a
new file mode 100644
index 000000000..0cfebbdff
--- /dev/null
+++ b/fuzzers/corpora/midx/abbee3b37aff879b1cef47390001b89b0f6ebc0a
Binary files differ
diff --git a/fuzzers/corpora/midx/ac15b23f03af8be6dbbb3bbb8d3877a1f9e074a3 b/fuzzers/corpora/midx/ac15b23f03af8be6dbbb3bbb8d3877a1f9e074a3
new file mode 100644
index 000000000..15ed8032d
--- /dev/null
+++ b/fuzzers/corpora/midx/ac15b23f03af8be6dbbb3bbb8d3877a1f9e074a3
Binary files differ
diff --git a/fuzzers/corpora/midx/ac47bda12269c06d773f5f3c6517f78513a54a08 b/fuzzers/corpora/midx/ac47bda12269c06d773f5f3c6517f78513a54a08
new file mode 100644
index 000000000..7ba9b5691
--- /dev/null
+++ b/fuzzers/corpora/midx/ac47bda12269c06d773f5f3c6517f78513a54a08
Binary files differ
diff --git a/fuzzers/corpora/midx/ad1f4fb57f481a00a9bb231517a3155ef0d0877f b/fuzzers/corpora/midx/ad1f4fb57f481a00a9bb231517a3155ef0d0877f
new file mode 100644
index 000000000..7ae9220e3
--- /dev/null
+++ b/fuzzers/corpora/midx/ad1f4fb57f481a00a9bb231517a3155ef0d0877f
Binary files differ
diff --git a/fuzzers/corpora/midx/ad25e7ffabedd94833d2529886af4d459529ec9d b/fuzzers/corpora/midx/ad25e7ffabedd94833d2529886af4d459529ec9d
new file mode 100644
index 000000000..a1de60487
--- /dev/null
+++ b/fuzzers/corpora/midx/ad25e7ffabedd94833d2529886af4d459529ec9d
Binary files differ
diff --git a/fuzzers/corpora/midx/ad796ebb423f58187806c4a7ee7b787394353ce6 b/fuzzers/corpora/midx/ad796ebb423f58187806c4a7ee7b787394353ce6
new file mode 100644
index 000000000..17e5905e7
--- /dev/null
+++ b/fuzzers/corpora/midx/ad796ebb423f58187806c4a7ee7b787394353ce6
Binary files differ
diff --git a/fuzzers/corpora/midx/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc b/fuzzers/corpora/midx/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/fuzzers/corpora/midx/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
@@ -0,0 +1 @@
+
diff --git a/fuzzers/corpora/midx/ae14b80f26f5cee2d85d5154c2cef1eefafa8cc9 b/fuzzers/corpora/midx/ae14b80f26f5cee2d85d5154c2cef1eefafa8cc9
new file mode 100644
index 000000000..d0309c3e1
--- /dev/null
+++ b/fuzzers/corpora/midx/ae14b80f26f5cee2d85d5154c2cef1eefafa8cc9
Binary files differ
diff --git a/fuzzers/corpora/midx/ae3ba892de543801b3c1dfbce370eb2c80a6fb27 b/fuzzers/corpora/midx/ae3ba892de543801b3c1dfbce370eb2c80a6fb27
new file mode 100644
index 000000000..7f0f42dde
--- /dev/null
+++ b/fuzzers/corpora/midx/ae3ba892de543801b3c1dfbce370eb2c80a6fb27
Binary files differ
diff --git a/fuzzers/corpora/midx/aecc0c7f08810803da234e26e7c6fa7a9f1c0593 b/fuzzers/corpora/midx/aecc0c7f08810803da234e26e7c6fa7a9f1c0593
new file mode 100644
index 000000000..8edc20975
--- /dev/null
+++ b/fuzzers/corpora/midx/aecc0c7f08810803da234e26e7c6fa7a9f1c0593
Binary files differ
diff --git a/fuzzers/corpora/midx/aed2e85d5d39d25e738a34f30a722680bde30368 b/fuzzers/corpora/midx/aed2e85d5d39d25e738a34f30a722680bde30368
new file mode 100644
index 000000000..006970c68
--- /dev/null
+++ b/fuzzers/corpora/midx/aed2e85d5d39d25e738a34f30a722680bde30368
Binary files differ
diff --git a/fuzzers/corpora/midx/b00a75de1987c6f549bf73a63e8f23a2de6641b3 b/fuzzers/corpora/midx/b00a75de1987c6f549bf73a63e8f23a2de6641b3
new file mode 100644
index 000000000..6b7abb024
--- /dev/null
+++ b/fuzzers/corpora/midx/b00a75de1987c6f549bf73a63e8f23a2de6641b3
Binary files differ
diff --git a/fuzzers/corpora/midx/b02e9f951ce9f10a8eb80f1fc61cd3d2832dd7f4 b/fuzzers/corpora/midx/b02e9f951ce9f10a8eb80f1fc61cd3d2832dd7f4
new file mode 100644
index 000000000..1bc7029e6
--- /dev/null
+++ b/fuzzers/corpora/midx/b02e9f951ce9f10a8eb80f1fc61cd3d2832dd7f4
Binary files differ
diff --git a/fuzzers/corpora/midx/b04aff8ab2e133d45bf44565bd4bf9e33b795a97 b/fuzzers/corpora/midx/b04aff8ab2e133d45bf44565bd4bf9e33b795a97
new file mode 100644
index 000000000..fbba22081
--- /dev/null
+++ b/fuzzers/corpora/midx/b04aff8ab2e133d45bf44565bd4bf9e33b795a97
Binary files differ
diff --git a/fuzzers/corpora/midx/b12097ed83db761f7bb79411a59e2474de9b1199 b/fuzzers/corpora/midx/b12097ed83db761f7bb79411a59e2474de9b1199
new file mode 100644
index 000000000..75c785561
--- /dev/null
+++ b/fuzzers/corpora/midx/b12097ed83db761f7bb79411a59e2474de9b1199
Binary files differ
diff --git a/fuzzers/corpora/midx/b1beb2f462b4cb30a09d534b9f49f2e08d76363c b/fuzzers/corpora/midx/b1beb2f462b4cb30a09d534b9f49f2e08d76363c
new file mode 100644
index 000000000..1f4bc7b24
--- /dev/null
+++ b/fuzzers/corpora/midx/b1beb2f462b4cb30a09d534b9f49f2e08d76363c
@@ -0,0 +1 @@
+ãðc½D \ No newline at end of file
diff --git a/fuzzers/corpora/midx/b201733b6165f4544578bd6aad3f55aeafd9a194 b/fuzzers/corpora/midx/b201733b6165f4544578bd6aad3f55aeafd9a194
new file mode 100644
index 000000000..51e078769
--- /dev/null
+++ b/fuzzers/corpora/midx/b201733b6165f4544578bd6aad3f55aeafd9a194
Binary files differ
diff --git a/fuzzers/corpora/midx/b2699f25c21ffe453dcce20e31b3093e0f9b2abf b/fuzzers/corpora/midx/b2699f25c21ffe453dcce20e31b3093e0f9b2abf
new file mode 100644
index 000000000..19e656b32
--- /dev/null
+++ b/fuzzers/corpora/midx/b2699f25c21ffe453dcce20e31b3093e0f9b2abf
@@ -0,0 +1 @@
+Åç \ No newline at end of file
diff --git a/fuzzers/corpora/midx/b34a5760a1036f909e0243cd857fcef65e40d752 b/fuzzers/corpora/midx/b34a5760a1036f909e0243cd857fcef65e40d752
new file mode 100644
index 000000000..1a9d7cefc
--- /dev/null
+++ b/fuzzers/corpora/midx/b34a5760a1036f909e0243cd857fcef65e40d752
Binary files differ
diff --git a/fuzzers/corpora/midx/b3fdacd639073cc1954bcb1f31046d094e2d2296 b/fuzzers/corpora/midx/b3fdacd639073cc1954bcb1f31046d094e2d2296
new file mode 100644
index 000000000..f393c6843
--- /dev/null
+++ b/fuzzers/corpora/midx/b3fdacd639073cc1954bcb1f31046d094e2d2296
Binary files differ
diff --git a/fuzzers/corpora/midx/b40a6dbe32c8e6a9b777331e7fd97f0d94ceca1c b/fuzzers/corpora/midx/b40a6dbe32c8e6a9b777331e7fd97f0d94ceca1c
new file mode 100644
index 000000000..c8ea5fc1a
--- /dev/null
+++ b/fuzzers/corpora/midx/b40a6dbe32c8e6a9b777331e7fd97f0d94ceca1c
Binary files differ
diff --git a/fuzzers/corpora/midx/b52ff2010f22ae6758cde5d529fd19de2a7d5fc5 b/fuzzers/corpora/midx/b52ff2010f22ae6758cde5d529fd19de2a7d5fc5
new file mode 100644
index 000000000..ffe413839
--- /dev/null
+++ b/fuzzers/corpora/midx/b52ff2010f22ae6758cde5d529fd19de2a7d5fc5
Binary files differ
diff --git a/fuzzers/corpora/midx/b53a7a2afd9dfc55c328b4e06a36882c53126e95 b/fuzzers/corpora/midx/b53a7a2afd9dfc55c328b4e06a36882c53126e95
new file mode 100644
index 000000000..1624d98d7
--- /dev/null
+++ b/fuzzers/corpora/midx/b53a7a2afd9dfc55c328b4e06a36882c53126e95
Binary files differ
diff --git a/fuzzers/corpora/midx/b548ae8a77a62b7f375b8b48e7184ceed59bc8f8 b/fuzzers/corpora/midx/b548ae8a77a62b7f375b8b48e7184ceed59bc8f8
new file mode 100644
index 000000000..290535642
--- /dev/null
+++ b/fuzzers/corpora/midx/b548ae8a77a62b7f375b8b48e7184ceed59bc8f8
Binary files differ
diff --git a/fuzzers/corpora/midx/b66eaf0b689495cc7c194ab1fca7d36ae9da9758 b/fuzzers/corpora/midx/b66eaf0b689495cc7c194ab1fca7d36ae9da9758
new file mode 100644
index 000000000..c02a2407b
--- /dev/null
+++ b/fuzzers/corpora/midx/b66eaf0b689495cc7c194ab1fca7d36ae9da9758
Binary files differ
diff --git a/fuzzers/corpora/midx/b680bf23da22b8b7e77d847169fe9b6968d79e8b b/fuzzers/corpora/midx/b680bf23da22b8b7e77d847169fe9b6968d79e8b
new file mode 100644
index 000000000..e75d39a56
--- /dev/null
+++ b/fuzzers/corpora/midx/b680bf23da22b8b7e77d847169fe9b6968d79e8b
@@ -0,0 +1 @@
+ãoÙ¬ÿÿ \ No newline at end of file
diff --git a/fuzzers/corpora/midx/b70d6e7d230fb1393b8f665adcd5658cad7059fe b/fuzzers/corpora/midx/b70d6e7d230fb1393b8f665adcd5658cad7059fe
new file mode 100644
index 000000000..54a848653
--- /dev/null
+++ b/fuzzers/corpora/midx/b70d6e7d230fb1393b8f665adcd5658cad7059fe
Binary files differ
diff --git a/fuzzers/corpora/midx/b87a59f78adb3ef18b0176a8e7fe7e90c2ab4ef7 b/fuzzers/corpora/midx/b87a59f78adb3ef18b0176a8e7fe7e90c2ab4ef7
new file mode 100644
index 000000000..0b9db199d
--- /dev/null
+++ b/fuzzers/corpora/midx/b87a59f78adb3ef18b0176a8e7fe7e90c2ab4ef7
Binary files differ
diff --git a/fuzzers/corpora/midx/b88c5233090e859e923acbdfa9b168f95d7fc14b b/fuzzers/corpora/midx/b88c5233090e859e923acbdfa9b168f95d7fc14b
new file mode 100644
index 000000000..a3841a89e
--- /dev/null
+++ b/fuzzers/corpora/midx/b88c5233090e859e923acbdfa9b168f95d7fc14b
Binary files differ
diff --git a/fuzzers/corpora/midx/ba1923ea69eec8fe765e8d1222eccb928ca6c3c2 b/fuzzers/corpora/midx/ba1923ea69eec8fe765e8d1222eccb928ca6c3c2
new file mode 100644
index 000000000..e5534a264
--- /dev/null
+++ b/fuzzers/corpora/midx/ba1923ea69eec8fe765e8d1222eccb928ca6c3c2
Binary files differ
diff --git a/fuzzers/corpora/midx/ba4d695c1eb02c702bd99a3db27838c7ba617d79 b/fuzzers/corpora/midx/ba4d695c1eb02c702bd99a3db27838c7ba617d79
new file mode 100644
index 000000000..2a60fe951
--- /dev/null
+++ b/fuzzers/corpora/midx/ba4d695c1eb02c702bd99a3db27838c7ba617d79
Binary files differ
diff --git a/fuzzers/corpora/midx/ba7e4f999dc22d223c7f75db36646bfa05848572 b/fuzzers/corpora/midx/ba7e4f999dc22d223c7f75db36646bfa05848572
new file mode 100644
index 000000000..b94268612
--- /dev/null
+++ b/fuzzers/corpora/midx/ba7e4f999dc22d223c7f75db36646bfa05848572
Binary files differ
diff --git a/fuzzers/corpora/midx/bc5f0cd338d1d17a230378390aa810bc7b103cda b/fuzzers/corpora/midx/bc5f0cd338d1d17a230378390aa810bc7b103cda
new file mode 100644
index 000000000..9b147c438
--- /dev/null
+++ b/fuzzers/corpora/midx/bc5f0cd338d1d17a230378390aa810bc7b103cda
Binary files differ
diff --git a/fuzzers/corpora/midx/bcbb4cf10018a177dd9a6c642d887e0de3d8e522 b/fuzzers/corpora/midx/bcbb4cf10018a177dd9a6c642d887e0de3d8e522
new file mode 100644
index 000000000..400d7bb42
--- /dev/null
+++ b/fuzzers/corpora/midx/bcbb4cf10018a177dd9a6c642d887e0de3d8e522
Binary files differ
diff --git a/fuzzers/corpora/midx/bcfeb114df6d5c6e0c85cbe1081631bc321ff65b b/fuzzers/corpora/midx/bcfeb114df6d5c6e0c85cbe1081631bc321ff65b
new file mode 100644
index 000000000..200a997a0
--- /dev/null
+++ b/fuzzers/corpora/midx/bcfeb114df6d5c6e0c85cbe1081631bc321ff65b
Binary files differ
diff --git a/fuzzers/corpora/midx/bd582237a9293e2a53d8222722a69e7d215822bf b/fuzzers/corpora/midx/bd582237a9293e2a53d8222722a69e7d215822bf
new file mode 100644
index 000000000..9b34fbc94
--- /dev/null
+++ b/fuzzers/corpora/midx/bd582237a9293e2a53d8222722a69e7d215822bf
Binary files differ
diff --git a/fuzzers/corpora/midx/bdc83a415da40f74825379203538a2e4d27cffa7 b/fuzzers/corpora/midx/bdc83a415da40f74825379203538a2e4d27cffa7
new file mode 100644
index 000000000..af4b9e3c2
--- /dev/null
+++ b/fuzzers/corpora/midx/bdc83a415da40f74825379203538a2e4d27cffa7
Binary files differ
diff --git a/fuzzers/corpora/midx/be160536594c87dc07554a71c7d24cd1d718aecc b/fuzzers/corpora/midx/be160536594c87dc07554a71c7d24cd1d718aecc
new file mode 100644
index 000000000..220794194
--- /dev/null
+++ b/fuzzers/corpora/midx/be160536594c87dc07554a71c7d24cd1d718aecc
Binary files differ
diff --git a/fuzzers/corpora/midx/be8f3c744a23f67fb316a39609ca11ddac025b58 b/fuzzers/corpora/midx/be8f3c744a23f67fb316a39609ca11ddac025b58
new file mode 100644
index 000000000..e90303655
--- /dev/null
+++ b/fuzzers/corpora/midx/be8f3c744a23f67fb316a39609ca11ddac025b58
Binary files differ
diff --git a/fuzzers/corpora/midx/bf873b027b48f3fd7b727473c832486d99ddb196 b/fuzzers/corpora/midx/bf873b027b48f3fd7b727473c832486d99ddb196
new file mode 100644
index 000000000..f96da4c2b
--- /dev/null
+++ b/fuzzers/corpora/midx/bf873b027b48f3fd7b727473c832486d99ddb196
Binary files differ
diff --git a/fuzzers/corpora/midx/bf8e20ef6b79131ef9bab8c9c1bb7dbecbead6a5 b/fuzzers/corpora/midx/bf8e20ef6b79131ef9bab8c9c1bb7dbecbead6a5
new file mode 100644
index 000000000..199ed39f0
--- /dev/null
+++ b/fuzzers/corpora/midx/bf8e20ef6b79131ef9bab8c9c1bb7dbecbead6a5
Binary files differ
diff --git a/fuzzers/corpora/midx/bf90507b8f7c7eebb89edeaabf6a432d86e7df4a b/fuzzers/corpora/midx/bf90507b8f7c7eebb89edeaabf6a432d86e7df4a
new file mode 100644
index 000000000..428e5678a
--- /dev/null
+++ b/fuzzers/corpora/midx/bf90507b8f7c7eebb89edeaabf6a432d86e7df4a
Binary files differ
diff --git a/fuzzers/corpora/midx/bfa7a5ce666899fb3e2a7216dbf59886da672658 b/fuzzers/corpora/midx/bfa7a5ce666899fb3e2a7216dbf59886da672658
new file mode 100644
index 000000000..45cf661dd
--- /dev/null
+++ b/fuzzers/corpora/midx/bfa7a5ce666899fb3e2a7216dbf59886da672658
Binary files differ
diff --git a/fuzzers/corpora/midx/bfeaa454d8db33efabba88f146bee6c803369ba0 b/fuzzers/corpora/midx/bfeaa454d8db33efabba88f146bee6c803369ba0
new file mode 100644
index 000000000..82b09f3c3
--- /dev/null
+++ b/fuzzers/corpora/midx/bfeaa454d8db33efabba88f146bee6c803369ba0
Binary files differ
diff --git a/fuzzers/corpora/midx/c0388910e8d88dcd2e65848ba2cef465caa6b258 b/fuzzers/corpora/midx/c0388910e8d88dcd2e65848ba2cef465caa6b258
new file mode 100644
index 000000000..01e4b8994
--- /dev/null
+++ b/fuzzers/corpora/midx/c0388910e8d88dcd2e65848ba2cef465caa6b258
Binary files differ
diff --git a/fuzzers/corpora/midx/c0db293f75bb44668bcbb79286ebed87df141a85 b/fuzzers/corpora/midx/c0db293f75bb44668bcbb79286ebed87df141a85
new file mode 100644
index 000000000..bb56c1416
--- /dev/null
+++ b/fuzzers/corpora/midx/c0db293f75bb44668bcbb79286ebed87df141a85
Binary files differ
diff --git a/fuzzers/corpora/midx/c1234da1441255244aba15ecad2a4fa7fd47115e b/fuzzers/corpora/midx/c1234da1441255244aba15ecad2a4fa7fd47115e
new file mode 100644
index 000000000..e79db44bf
--- /dev/null
+++ b/fuzzers/corpora/midx/c1234da1441255244aba15ecad2a4fa7fd47115e
Binary files differ
diff --git a/fuzzers/corpora/midx/c2206ac3c289a759ee0e9d0d31cc336f0802f7bc b/fuzzers/corpora/midx/c2206ac3c289a759ee0e9d0d31cc336f0802f7bc
new file mode 100644
index 000000000..66a47b970
--- /dev/null
+++ b/fuzzers/corpora/midx/c2206ac3c289a759ee0e9d0d31cc336f0802f7bc
@@ -0,0 +1 @@
+ãïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï;ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï \ No newline at end of file
diff --git a/fuzzers/corpora/midx/c22340ab36e5cff088a58272f63cf69e54a1a9f4 b/fuzzers/corpora/midx/c22340ab36e5cff088a58272f63cf69e54a1a9f4
new file mode 100644
index 000000000..5f2f36ceb
--- /dev/null
+++ b/fuzzers/corpora/midx/c22340ab36e5cff088a58272f63cf69e54a1a9f4
Binary files differ
diff --git a/fuzzers/corpora/midx/c242c9336c4c22b316e0e56d616b2d45b3318ca4 b/fuzzers/corpora/midx/c242c9336c4c22b316e0e56d616b2d45b3318ca4
new file mode 100644
index 000000000..b4824b458
--- /dev/null
+++ b/fuzzers/corpora/midx/c242c9336c4c22b316e0e56d616b2d45b3318ca4
Binary files differ
diff --git a/fuzzers/corpora/midx/c25a51d8dfaf58d5b609729bb156a80e3b0d892f b/fuzzers/corpora/midx/c25a51d8dfaf58d5b609729bb156a80e3b0d892f
new file mode 100644
index 000000000..1209373c9
--- /dev/null
+++ b/fuzzers/corpora/midx/c25a51d8dfaf58d5b609729bb156a80e3b0d892f
Binary files differ
diff --git a/fuzzers/corpora/midx/c3419450240d06982b0d828911b188a903355216 b/fuzzers/corpora/midx/c3419450240d06982b0d828911b188a903355216
new file mode 100644
index 000000000..b0ac7f488
--- /dev/null
+++ b/fuzzers/corpora/midx/c3419450240d06982b0d828911b188a903355216
Binary files differ
diff --git a/fuzzers/corpora/midx/c36ea7651f76ae817d8d60cae580e47638741372 b/fuzzers/corpora/midx/c36ea7651f76ae817d8d60cae580e47638741372
new file mode 100644
index 000000000..92ef97229
--- /dev/null
+++ b/fuzzers/corpora/midx/c36ea7651f76ae817d8d60cae580e47638741372
Binary files differ
diff --git a/fuzzers/corpora/midx/c42300c021bfd35702f564e917839503922cbe9a b/fuzzers/corpora/midx/c42300c021bfd35702f564e917839503922cbe9a
new file mode 100644
index 000000000..553b6ee2a
--- /dev/null
+++ b/fuzzers/corpora/midx/c42300c021bfd35702f564e917839503922cbe9a
Binary files differ
diff --git a/fuzzers/corpora/midx/c45d82ddade99ef857b563e435f2efe89e58b0be b/fuzzers/corpora/midx/c45d82ddade99ef857b563e435f2efe89e58b0be
new file mode 100644
index 000000000..a45b45e7c
--- /dev/null
+++ b/fuzzers/corpora/midx/c45d82ddade99ef857b563e435f2efe89e58b0be
Binary files differ
diff --git a/fuzzers/corpora/midx/c4d1e9187de1e13353b3beb3c1ab16dd62cda571 b/fuzzers/corpora/midx/c4d1e9187de1e13353b3beb3c1ab16dd62cda571
new file mode 100644
index 000000000..12fdcbdc5
--- /dev/null
+++ b/fuzzers/corpora/midx/c4d1e9187de1e13353b3beb3c1ab16dd62cda571
Binary files differ
diff --git a/fuzzers/corpora/midx/c4e98278a25011c54734494d4534a97489cf4c24 b/fuzzers/corpora/midx/c4e98278a25011c54734494d4534a97489cf4c24
new file mode 100644
index 000000000..4cef0a128
--- /dev/null
+++ b/fuzzers/corpora/midx/c4e98278a25011c54734494d4534a97489cf4c24
Binary files differ
diff --git a/fuzzers/corpora/midx/c4f996ab08f56ce2e9fec7a0428ded510dd6a04a b/fuzzers/corpora/midx/c4f996ab08f56ce2e9fec7a0428ded510dd6a04a
new file mode 100644
index 000000000..78d9033c1
--- /dev/null
+++ b/fuzzers/corpora/midx/c4f996ab08f56ce2e9fec7a0428ded510dd6a04a
Binary files differ
diff --git a/fuzzers/corpora/midx/c544850a7325e7226583895204f99de730525803 b/fuzzers/corpora/midx/c544850a7325e7226583895204f99de730525803
new file mode 100644
index 000000000..cd87f9b9f
--- /dev/null
+++ b/fuzzers/corpora/midx/c544850a7325e7226583895204f99de730525803
Binary files differ
diff --git a/fuzzers/corpora/midx/c56629528d5bebdb94f85522caf0f36bbcb19106 b/fuzzers/corpora/midx/c56629528d5bebdb94f85522caf0f36bbcb19106
new file mode 100644
index 000000000..6416cd684
--- /dev/null
+++ b/fuzzers/corpora/midx/c56629528d5bebdb94f85522caf0f36bbcb19106
Binary files differ
diff --git a/fuzzers/corpora/midx/c5c75b58883ccf41b20b140740e2ce763c6086cd b/fuzzers/corpora/midx/c5c75b58883ccf41b20b140740e2ce763c6086cd
new file mode 100644
index 000000000..9f9a51a5d
--- /dev/null
+++ b/fuzzers/corpora/midx/c5c75b58883ccf41b20b140740e2ce763c6086cd
Binary files differ
diff --git a/fuzzers/corpora/midx/c62da85dca0d4dfb1d7af5d0520eb74993a1e3b0 b/fuzzers/corpora/midx/c62da85dca0d4dfb1d7af5d0520eb74993a1e3b0
new file mode 100644
index 000000000..8f9050c48
--- /dev/null
+++ b/fuzzers/corpora/midx/c62da85dca0d4dfb1d7af5d0520eb74993a1e3b0
Binary files differ
diff --git a/fuzzers/corpora/midx/c6379aaaecd282b8ed6d0b4291d0d9fdc763160a b/fuzzers/corpora/midx/c6379aaaecd282b8ed6d0b4291d0d9fdc763160a
new file mode 100644
index 000000000..2478f3579
--- /dev/null
+++ b/fuzzers/corpora/midx/c6379aaaecd282b8ed6d0b4291d0d9fdc763160a
Binary files differ
diff --git a/fuzzers/corpora/midx/c6431921184e3edf4fd3e47384c69654cdac0189 b/fuzzers/corpora/midx/c6431921184e3edf4fd3e47384c69654cdac0189
new file mode 100644
index 000000000..2acd685af
--- /dev/null
+++ b/fuzzers/corpora/midx/c6431921184e3edf4fd3e47384c69654cdac0189
Binary files differ
diff --git a/fuzzers/corpora/midx/c6f2ca17c6d313a35676cbacd094eb40fd74b23e b/fuzzers/corpora/midx/c6f2ca17c6d313a35676cbacd094eb40fd74b23e
new file mode 100644
index 000000000..d1c63b98a
--- /dev/null
+++ b/fuzzers/corpora/midx/c6f2ca17c6d313a35676cbacd094eb40fd74b23e
Binary files differ
diff --git a/fuzzers/corpora/midx/c83e04d58e04fccac37b9dd313eab72011fe8ea1 b/fuzzers/corpora/midx/c83e04d58e04fccac37b9dd313eab72011fe8ea1
new file mode 100644
index 000000000..d11f86a44
--- /dev/null
+++ b/fuzzers/corpora/midx/c83e04d58e04fccac37b9dd313eab72011fe8ea1
Binary files differ
diff --git a/fuzzers/corpora/midx/c88dc350b98a5c5ae0503683318c1f30443906a8 b/fuzzers/corpora/midx/c88dc350b98a5c5ae0503683318c1f30443906a8
new file mode 100644
index 000000000..528a69e7b
--- /dev/null
+++ b/fuzzers/corpora/midx/c88dc350b98a5c5ae0503683318c1f30443906a8
@@ -0,0 +1 @@
+ãp \ No newline at end of file
diff --git a/fuzzers/corpora/midx/c89ee2e9e30a474b5f9532ec61d7aad78377baa0 b/fuzzers/corpora/midx/c89ee2e9e30a474b5f9532ec61d7aad78377baa0
new file mode 100644
index 000000000..6280ce2ae
--- /dev/null
+++ b/fuzzers/corpora/midx/c89ee2e9e30a474b5f9532ec61d7aad78377baa0
Binary files differ
diff --git a/fuzzers/corpora/midx/c921be4abeb44d1ff07f76f632a16e86526bc4be b/fuzzers/corpora/midx/c921be4abeb44d1ff07f76f632a16e86526bc4be
new file mode 100644
index 000000000..6f53b9df4
--- /dev/null
+++ b/fuzzers/corpora/midx/c921be4abeb44d1ff07f76f632a16e86526bc4be
Binary files differ
diff --git a/fuzzers/corpora/midx/c98bdc0431aaece1e8a721aff0ea511cfb8062a6 b/fuzzers/corpora/midx/c98bdc0431aaece1e8a721aff0ea511cfb8062a6
new file mode 100644
index 000000000..cc0580ca3
--- /dev/null
+++ b/fuzzers/corpora/midx/c98bdc0431aaece1e8a721aff0ea511cfb8062a6
Binary files differ
diff --git a/fuzzers/corpora/midx/c9c456fd3e35a942ef4ab756e04e725cf1f71167 b/fuzzers/corpora/midx/c9c456fd3e35a942ef4ab756e04e725cf1f71167
new file mode 100644
index 000000000..6a7c367dd
--- /dev/null
+++ b/fuzzers/corpora/midx/c9c456fd3e35a942ef4ab756e04e725cf1f71167
Binary files differ
diff --git a/fuzzers/corpora/midx/cd1f1a31b79af77e1e764102942ba7a79dcd24cf b/fuzzers/corpora/midx/cd1f1a31b79af77e1e764102942ba7a79dcd24cf
new file mode 100644
index 000000000..883c745b1
--- /dev/null
+++ b/fuzzers/corpora/midx/cd1f1a31b79af77e1e764102942ba7a79dcd24cf
Binary files differ
diff --git a/fuzzers/corpora/midx/cd57e5904254c2278e9ecf28ed7414d7aed8eef1 b/fuzzers/corpora/midx/cd57e5904254c2278e9ecf28ed7414d7aed8eef1
new file mode 100644
index 000000000..709c1a458
--- /dev/null
+++ b/fuzzers/corpora/midx/cd57e5904254c2278e9ecf28ed7414d7aed8eef1
Binary files differ
diff --git a/fuzzers/corpora/midx/cd665cdc2bd6a26eb68c9af6d1728a7d4f6eb309 b/fuzzers/corpora/midx/cd665cdc2bd6a26eb68c9af6d1728a7d4f6eb309
new file mode 100644
index 000000000..094e31ba1
--- /dev/null
+++ b/fuzzers/corpora/midx/cd665cdc2bd6a26eb68c9af6d1728a7d4f6eb309
Binary files differ
diff --git a/fuzzers/corpora/midx/ce72111c4314b22c4c7824bc8ea340ebd6d3fa84 b/fuzzers/corpora/midx/ce72111c4314b22c4c7824bc8ea340ebd6d3fa84
new file mode 100644
index 000000000..9bf41358a
--- /dev/null
+++ b/fuzzers/corpora/midx/ce72111c4314b22c4c7824bc8ea340ebd6d3fa84
Binary files differ
diff --git a/fuzzers/corpora/midx/ceacc7ace2f4be962b0db2eeeea3fe6a00ca9dd6 b/fuzzers/corpora/midx/ceacc7ace2f4be962b0db2eeeea3fe6a00ca9dd6
new file mode 100644
index 000000000..6ddf30de7
--- /dev/null
+++ b/fuzzers/corpora/midx/ceacc7ace2f4be962b0db2eeeea3fe6a00ca9dd6
Binary files differ
diff --git a/fuzzers/corpora/midx/cf40769d8b4fcbac1b10ced2e0c3c1294f23fcdd b/fuzzers/corpora/midx/cf40769d8b4fcbac1b10ced2e0c3c1294f23fcdd
new file mode 100644
index 000000000..18327c918
--- /dev/null
+++ b/fuzzers/corpora/midx/cf40769d8b4fcbac1b10ced2e0c3c1294f23fcdd
Binary files differ
diff --git a/fuzzers/corpora/midx/d120111a77a3e3d1d504a04bbfc5f53effa14eb0 b/fuzzers/corpora/midx/d120111a77a3e3d1d504a04bbfc5f53effa14eb0
new file mode 100644
index 000000000..84043fe32
--- /dev/null
+++ b/fuzzers/corpora/midx/d120111a77a3e3d1d504a04bbfc5f53effa14eb0
Binary files differ
diff --git a/fuzzers/corpora/midx/d1ce81240a32aec2de1b0d779aa29a62c36f291f b/fuzzers/corpora/midx/d1ce81240a32aec2de1b0d779aa29a62c36f291f
new file mode 100644
index 000000000..f49192cdc
--- /dev/null
+++ b/fuzzers/corpora/midx/d1ce81240a32aec2de1b0d779aa29a62c36f291f
Binary files differ
diff --git a/fuzzers/corpora/midx/d21869b290cd2b448e7b8103dced97e62fefffcc b/fuzzers/corpora/midx/d21869b290cd2b448e7b8103dced97e62fefffcc
new file mode 100644
index 000000000..1b98c7fe9
--- /dev/null
+++ b/fuzzers/corpora/midx/d21869b290cd2b448e7b8103dced97e62fefffcc
Binary files differ
diff --git a/fuzzers/corpora/midx/d2bffcd01e87ce9860007b244ff1e79ecd3d4d0f b/fuzzers/corpora/midx/d2bffcd01e87ce9860007b244ff1e79ecd3d4d0f
new file mode 100644
index 000000000..a7ef0a4f5
--- /dev/null
+++ b/fuzzers/corpora/midx/d2bffcd01e87ce9860007b244ff1e79ecd3d4d0f
Binary files differ
diff --git a/fuzzers/corpora/midx/d2d668b6e28fca83da5146021879c2b006406fa4 b/fuzzers/corpora/midx/d2d668b6e28fca83da5146021879c2b006406fa4
new file mode 100644
index 000000000..b4692596c
--- /dev/null
+++ b/fuzzers/corpora/midx/d2d668b6e28fca83da5146021879c2b006406fa4
Binary files differ
diff --git a/fuzzers/corpora/midx/d37abe0d299b8ad1e90f5b7af302c24f411a7ed1 b/fuzzers/corpora/midx/d37abe0d299b8ad1e90f5b7af302c24f411a7ed1
new file mode 100644
index 000000000..81365c3b3
--- /dev/null
+++ b/fuzzers/corpora/midx/d37abe0d299b8ad1e90f5b7af302c24f411a7ed1
Binary files differ
diff --git a/fuzzers/corpora/midx/d3d689a12ab3808313d5ba0044e8c67ecb4337e4 b/fuzzers/corpora/midx/d3d689a12ab3808313d5ba0044e8c67ecb4337e4
new file mode 100644
index 000000000..4afea5eac
--- /dev/null
+++ b/fuzzers/corpora/midx/d3d689a12ab3808313d5ba0044e8c67ecb4337e4
Binary files differ
diff --git a/fuzzers/corpora/midx/d48eb559213edf05aa2850a14194885ae2086ba4 b/fuzzers/corpora/midx/d48eb559213edf05aa2850a14194885ae2086ba4
new file mode 100644
index 000000000..0b91a6fa3
--- /dev/null
+++ b/fuzzers/corpora/midx/d48eb559213edf05aa2850a14194885ae2086ba4
Binary files differ
diff --git a/fuzzers/corpora/midx/d490f365693e49ebdeaf658b3f549311a399c6a8 b/fuzzers/corpora/midx/d490f365693e49ebdeaf658b3f549311a399c6a8
new file mode 100644
index 000000000..7ed6c9128
--- /dev/null
+++ b/fuzzers/corpora/midx/d490f365693e49ebdeaf658b3f549311a399c6a8
Binary files differ
diff --git a/fuzzers/corpora/midx/d54821b652a8611c486bedd8645081d3a4b1c8d1 b/fuzzers/corpora/midx/d54821b652a8611c486bedd8645081d3a4b1c8d1
new file mode 100644
index 000000000..eda0c25d7
--- /dev/null
+++ b/fuzzers/corpora/midx/d54821b652a8611c486bedd8645081d3a4b1c8d1
Binary files differ
diff --git a/fuzzers/corpora/midx/d5586a91f9a879e8a67ec7b09a48038909918ad9 b/fuzzers/corpora/midx/d5586a91f9a879e8a67ec7b09a48038909918ad9
new file mode 100644
index 000000000..0abb2188a
--- /dev/null
+++ b/fuzzers/corpora/midx/d5586a91f9a879e8a67ec7b09a48038909918ad9
Binary files differ
diff --git a/fuzzers/corpora/midx/d696362920a2fad8e280293e8d1c92b18c87e4ae b/fuzzers/corpora/midx/d696362920a2fad8e280293e8d1c92b18c87e4ae
new file mode 100644
index 000000000..b72ac49a9
--- /dev/null
+++ b/fuzzers/corpora/midx/d696362920a2fad8e280293e8d1c92b18c87e4ae
Binary files differ
diff --git a/fuzzers/corpora/midx/d6b546a2b1bc1c8f80028e4be10c45a06014b32d b/fuzzers/corpora/midx/d6b546a2b1bc1c8f80028e4be10c45a06014b32d
new file mode 100644
index 000000000..75ee6a9f2
--- /dev/null
+++ b/fuzzers/corpora/midx/d6b546a2b1bc1c8f80028e4be10c45a06014b32d
Binary files differ
diff --git a/fuzzers/corpora/midx/d7f04cbca92b2122e0f437ed4dd8fd1782d40f7f b/fuzzers/corpora/midx/d7f04cbca92b2122e0f437ed4dd8fd1782d40f7f
new file mode 100644
index 000000000..3b0ada6d8
--- /dev/null
+++ b/fuzzers/corpora/midx/d7f04cbca92b2122e0f437ed4dd8fd1782d40f7f
Binary files differ
diff --git a/fuzzers/corpora/midx/d81944a0c1ed56d11129533d9a3d0d038113d53d b/fuzzers/corpora/midx/d81944a0c1ed56d11129533d9a3d0d038113d53d
new file mode 100644
index 000000000..fa170d1e5
--- /dev/null
+++ b/fuzzers/corpora/midx/d81944a0c1ed56d11129533d9a3d0d038113d53d
Binary files differ
diff --git a/fuzzers/corpora/midx/d8524e83ea63c9b365c2e93af75a8100a08b1b69 b/fuzzers/corpora/midx/d8524e83ea63c9b365c2e93af75a8100a08b1b69
new file mode 100644
index 000000000..68f680b7d
--- /dev/null
+++ b/fuzzers/corpora/midx/d8524e83ea63c9b365c2e93af75a8100a08b1b69
Binary files differ
diff --git a/fuzzers/corpora/midx/d8d9a2d06763cf6feb433cef92a80ef14baab31a b/fuzzers/corpora/midx/d8d9a2d06763cf6feb433cef92a80ef14baab31a
new file mode 100644
index 000000000..2f47818c5
--- /dev/null
+++ b/fuzzers/corpora/midx/d8d9a2d06763cf6feb433cef92a80ef14baab31a
Binary files differ
diff --git a/fuzzers/corpora/midx/d917fbd641cc40786246387456a636899d56b5a6 b/fuzzers/corpora/midx/d917fbd641cc40786246387456a636899d56b5a6
new file mode 100644
index 000000000..e2d69484c
--- /dev/null
+++ b/fuzzers/corpora/midx/d917fbd641cc40786246387456a636899d56b5a6
Binary files differ
diff --git a/fuzzers/corpora/midx/d99f9ec8b504029457185ac03ea8ba21c2611737 b/fuzzers/corpora/midx/d99f9ec8b504029457185ac03ea8ba21c2611737
new file mode 100644
index 000000000..c3e992a9b
--- /dev/null
+++ b/fuzzers/corpora/midx/d99f9ec8b504029457185ac03ea8ba21c2611737
Binary files differ
diff --git a/fuzzers/corpora/midx/d9c9c90c1bbc55beb81875838e9067c473d0fa92 b/fuzzers/corpora/midx/d9c9c90c1bbc55beb81875838e9067c473d0fa92
new file mode 100644
index 000000000..b14945649
--- /dev/null
+++ b/fuzzers/corpora/midx/d9c9c90c1bbc55beb81875838e9067c473d0fa92
Binary files differ
diff --git a/fuzzers/corpora/midx/d9e908317a6ef08a7528924672836a550d34cb5f b/fuzzers/corpora/midx/d9e908317a6ef08a7528924672836a550d34cb5f
new file mode 100644
index 000000000..1c5b0c801
--- /dev/null
+++ b/fuzzers/corpora/midx/d9e908317a6ef08a7528924672836a550d34cb5f
Binary files differ
diff --git a/fuzzers/corpora/midx/d9ef71deb57fa6f40e027be2c84fa37d288e1cc5 b/fuzzers/corpora/midx/d9ef71deb57fa6f40e027be2c84fa37d288e1cc5
new file mode 100644
index 000000000..87ef310c2
--- /dev/null
+++ b/fuzzers/corpora/midx/d9ef71deb57fa6f40e027be2c84fa37d288e1cc5
Binary files differ
diff --git a/fuzzers/corpora/midx/da8841b9d04382d62d4aeb3fde4dc78466f31543 b/fuzzers/corpora/midx/da8841b9d04382d62d4aeb3fde4dc78466f31543
new file mode 100644
index 000000000..10eae46bf
--- /dev/null
+++ b/fuzzers/corpora/midx/da8841b9d04382d62d4aeb3fde4dc78466f31543
Binary files differ
diff --git a/fuzzers/corpora/midx/db3fbb74c9c9c4185f91eca85f14c3d2c3d9f487 b/fuzzers/corpora/midx/db3fbb74c9c9c4185f91eca85f14c3d2c3d9f487
new file mode 100644
index 000000000..a6344ce7a
--- /dev/null
+++ b/fuzzers/corpora/midx/db3fbb74c9c9c4185f91eca85f14c3d2c3d9f487
Binary files differ
diff --git a/fuzzers/corpora/midx/db7a31de22258d4dc17d44a27d9340946e9c9ee9 b/fuzzers/corpora/midx/db7a31de22258d4dc17d44a27d9340946e9c9ee9
new file mode 100644
index 000000000..32c8a8e8a
--- /dev/null
+++ b/fuzzers/corpora/midx/db7a31de22258d4dc17d44a27d9340946e9c9ee9
Binary files differ
diff --git a/fuzzers/corpora/midx/dbbe57fc653930b4ff43f168565ba84ef25f60c2 b/fuzzers/corpora/midx/dbbe57fc653930b4ff43f168565ba84ef25f60c2
new file mode 100644
index 000000000..9219ff3f5
--- /dev/null
+++ b/fuzzers/corpora/midx/dbbe57fc653930b4ff43f168565ba84ef25f60c2
Binary files differ
diff --git a/fuzzers/corpora/midx/dbe74c0d9e7b62c1fd87d5e3ea73ee04f0337154 b/fuzzers/corpora/midx/dbe74c0d9e7b62c1fd87d5e3ea73ee04f0337154
new file mode 100644
index 000000000..4ebae470a
--- /dev/null
+++ b/fuzzers/corpora/midx/dbe74c0d9e7b62c1fd87d5e3ea73ee04f0337154
Binary files differ
diff --git a/fuzzers/corpora/midx/dbebf36a6b91568ac059142c3ca3211226da12a8 b/fuzzers/corpora/midx/dbebf36a6b91568ac059142c3ca3211226da12a8
new file mode 100644
index 000000000..d180a9bf2
--- /dev/null
+++ b/fuzzers/corpora/midx/dbebf36a6b91568ac059142c3ca3211226da12a8
Binary files differ
diff --git a/fuzzers/corpora/midx/ddacbb379242b31a00d62fdff5777dffc1e899c2 b/fuzzers/corpora/midx/ddacbb379242b31a00d62fdff5777dffc1e899c2
new file mode 100644
index 000000000..999ece9f7
--- /dev/null
+++ b/fuzzers/corpora/midx/ddacbb379242b31a00d62fdff5777dffc1e899c2
Binary files differ
diff --git a/fuzzers/corpora/midx/decd2cd9cef352610ac9e5cc461df1829543f9f0 b/fuzzers/corpora/midx/decd2cd9cef352610ac9e5cc461df1829543f9f0
new file mode 100644
index 000000000..28af13b4a
--- /dev/null
+++ b/fuzzers/corpora/midx/decd2cd9cef352610ac9e5cc461df1829543f9f0
@@ -0,0 +1,3 @@
+yã
+y \ No newline at end of file
diff --git a/fuzzers/corpora/midx/deeae69363db06972798b296a0c5c99e02cb2b4c b/fuzzers/corpora/midx/deeae69363db06972798b296a0c5c99e02cb2b4c
new file mode 100644
index 000000000..63cffc896
--- /dev/null
+++ b/fuzzers/corpora/midx/deeae69363db06972798b296a0c5c99e02cb2b4c
Binary files differ
diff --git a/fuzzers/corpora/midx/e03e105323e6e7b2af90ad876b5c547af90d8f6b b/fuzzers/corpora/midx/e03e105323e6e7b2af90ad876b5c547af90d8f6b
new file mode 100644
index 000000000..020fa1752
--- /dev/null
+++ b/fuzzers/corpora/midx/e03e105323e6e7b2af90ad876b5c547af90d8f6b
Binary files differ
diff --git a/fuzzers/corpora/midx/e3133215848c9cde428338c9d51424c8a81b96f5 b/fuzzers/corpora/midx/e3133215848c9cde428338c9d51424c8a81b96f5
new file mode 100644
index 000000000..460d60898
--- /dev/null
+++ b/fuzzers/corpora/midx/e3133215848c9cde428338c9d51424c8a81b96f5
Binary files differ
diff --git a/fuzzers/corpora/midx/e32a25f0347b0e95d4bea16c27a1f374847683bd b/fuzzers/corpora/midx/e32a25f0347b0e95d4bea16c27a1f374847683bd
new file mode 100644
index 000000000..3329d6155
--- /dev/null
+++ b/fuzzers/corpora/midx/e32a25f0347b0e95d4bea16c27a1f374847683bd
Binary files differ
diff --git a/fuzzers/corpora/midx/e45ce97522194abcdd7ff9beb931e20b86c97a79 b/fuzzers/corpora/midx/e45ce97522194abcdd7ff9beb931e20b86c97a79
new file mode 100644
index 000000000..137a820e0
--- /dev/null
+++ b/fuzzers/corpora/midx/e45ce97522194abcdd7ff9beb931e20b86c97a79
Binary files differ
diff --git a/fuzzers/corpora/midx/e484023d50fc1036e46a437053b965c527700d42 b/fuzzers/corpora/midx/e484023d50fc1036e46a437053b965c527700d42
new file mode 100644
index 000000000..996f1e633
--- /dev/null
+++ b/fuzzers/corpora/midx/e484023d50fc1036e46a437053b965c527700d42
Binary files differ
diff --git a/fuzzers/corpora/midx/e4e60e77fe3a050940d0afcc7dbab7ef06b04ba3 b/fuzzers/corpora/midx/e4e60e77fe3a050940d0afcc7dbab7ef06b04ba3
new file mode 100644
index 000000000..31520a8cd
--- /dev/null
+++ b/fuzzers/corpora/midx/e4e60e77fe3a050940d0afcc7dbab7ef06b04ba3
Binary files differ
diff --git a/fuzzers/corpora/midx/e51629784092d9cf811ea1bd894297f062ed7ec4 b/fuzzers/corpora/midx/e51629784092d9cf811ea1bd894297f062ed7ec4
new file mode 100644
index 000000000..1f4127cd6
--- /dev/null
+++ b/fuzzers/corpora/midx/e51629784092d9cf811ea1bd894297f062ed7ec4
Binary files differ
diff --git a/fuzzers/corpora/midx/e5a7e837029178b3fb6a26d77ea4574ffeaa219d b/fuzzers/corpora/midx/e5a7e837029178b3fb6a26d77ea4574ffeaa219d
new file mode 100644
index 000000000..7607ce3ad
--- /dev/null
+++ b/fuzzers/corpora/midx/e5a7e837029178b3fb6a26d77ea4574ffeaa219d
Binary files differ
diff --git a/fuzzers/corpora/midx/e5c616e9efdd9c80181f9210d0e3a81c08fe9b4d b/fuzzers/corpora/midx/e5c616e9efdd9c80181f9210d0e3a81c08fe9b4d
new file mode 100644
index 000000000..476b4fd75
--- /dev/null
+++ b/fuzzers/corpora/midx/e5c616e9efdd9c80181f9210d0e3a81c08fe9b4d
Binary files differ
diff --git a/fuzzers/corpora/midx/e5e6e84e2c7770537c744bcfdbe8303afe39ef92 b/fuzzers/corpora/midx/e5e6e84e2c7770537c744bcfdbe8303afe39ef92
new file mode 100644
index 000000000..79045de27
--- /dev/null
+++ b/fuzzers/corpora/midx/e5e6e84e2c7770537c744bcfdbe8303afe39ef92
Binary files differ
diff --git a/fuzzers/corpora/midx/e5fb20928feec1ee3114597317edc0e06c413749 b/fuzzers/corpora/midx/e5fb20928feec1ee3114597317edc0e06c413749
new file mode 100644
index 000000000..d6758cfb1
--- /dev/null
+++ b/fuzzers/corpora/midx/e5fb20928feec1ee3114597317edc0e06c413749
Binary files differ
diff --git a/fuzzers/corpora/midx/e789319791fe704e5a8ffd7cb570c8d2722ac35f b/fuzzers/corpora/midx/e789319791fe704e5a8ffd7cb570c8d2722ac35f
new file mode 100644
index 000000000..19fdbe717
--- /dev/null
+++ b/fuzzers/corpora/midx/e789319791fe704e5a8ffd7cb570c8d2722ac35f
Binary files differ
diff --git a/fuzzers/corpora/midx/e9fdb9f08f225b4231f01dda9c7b61e7b78bf7d3 b/fuzzers/corpora/midx/e9fdb9f08f225b4231f01dda9c7b61e7b78bf7d3
new file mode 100644
index 000000000..576a1f88e
--- /dev/null
+++ b/fuzzers/corpora/midx/e9fdb9f08f225b4231f01dda9c7b61e7b78bf7d3
Binary files differ
diff --git a/fuzzers/corpora/midx/ea6780324dca9a06db28598dfb590436d846d99f b/fuzzers/corpora/midx/ea6780324dca9a06db28598dfb590436d846d99f
new file mode 100644
index 000000000..d8b617ccb
--- /dev/null
+++ b/fuzzers/corpora/midx/ea6780324dca9a06db28598dfb590436d846d99f
Binary files differ
diff --git a/fuzzers/corpora/midx/ea6afcc92b8a6c9e14cc053d351909ad5b0a3fdf b/fuzzers/corpora/midx/ea6afcc92b8a6c9e14cc053d351909ad5b0a3fdf
new file mode 100644
index 000000000..8393e3675
--- /dev/null
+++ b/fuzzers/corpora/midx/ea6afcc92b8a6c9e14cc053d351909ad5b0a3fdf
Binary files differ
diff --git a/fuzzers/corpora/midx/ea8c569029c0cacc4ae75e95b2f4e84abb6867f4 b/fuzzers/corpora/midx/ea8c569029c0cacc4ae75e95b2f4e84abb6867f4
new file mode 100644
index 000000000..2a86dc532
--- /dev/null
+++ b/fuzzers/corpora/midx/ea8c569029c0cacc4ae75e95b2f4e84abb6867f4
Binary files differ
diff --git a/fuzzers/corpora/midx/eb3e80c3ea9cfe9e08b2eef117aaa522a51a619c b/fuzzers/corpora/midx/eb3e80c3ea9cfe9e08b2eef117aaa522a51a619c
new file mode 100644
index 000000000..d1fb9997b
--- /dev/null
+++ b/fuzzers/corpora/midx/eb3e80c3ea9cfe9e08b2eef117aaa522a51a619c
Binary files differ
diff --git a/fuzzers/corpora/midx/ec55b30741fe8fffeec584176c8d20f6a679cfa1 b/fuzzers/corpora/midx/ec55b30741fe8fffeec584176c8d20f6a679cfa1
new file mode 100644
index 000000000..69efa4a31
--- /dev/null
+++ b/fuzzers/corpora/midx/ec55b30741fe8fffeec584176c8d20f6a679cfa1
Binary files differ
diff --git a/fuzzers/corpora/midx/ed0724a6c3804a3ab20a980b5ca48671689a602f b/fuzzers/corpora/midx/ed0724a6c3804a3ab20a980b5ca48671689a602f
new file mode 100644
index 000000000..85ec5a60c
--- /dev/null
+++ b/fuzzers/corpora/midx/ed0724a6c3804a3ab20a980b5ca48671689a602f
Binary files differ
diff --git a/fuzzers/corpora/midx/edeb545d1cf852dc9582fa764010fe844a5e3515 b/fuzzers/corpora/midx/edeb545d1cf852dc9582fa764010fe844a5e3515
new file mode 100644
index 000000000..3187fc701
--- /dev/null
+++ b/fuzzers/corpora/midx/edeb545d1cf852dc9582fa764010fe844a5e3515
Binary files differ
diff --git a/fuzzers/corpora/midx/ee70b920de91f1be6b4448070ee2d1bd9e08286d b/fuzzers/corpora/midx/ee70b920de91f1be6b4448070ee2d1bd9e08286d
new file mode 100644
index 000000000..6d1f0a2ed
--- /dev/null
+++ b/fuzzers/corpora/midx/ee70b920de91f1be6b4448070ee2d1bd9e08286d
Binary files differ
diff --git a/fuzzers/corpora/midx/ef004af4e947d25b4d1d1dd16502260d4c7a99cd b/fuzzers/corpora/midx/ef004af4e947d25b4d1d1dd16502260d4c7a99cd
new file mode 100644
index 000000000..ac39a8eed
--- /dev/null
+++ b/fuzzers/corpora/midx/ef004af4e947d25b4d1d1dd16502260d4c7a99cd
Binary files differ
diff --git a/fuzzers/corpora/midx/f009d226503b73aed0f1fd952ef8725433d158be b/fuzzers/corpora/midx/f009d226503b73aed0f1fd952ef8725433d158be
new file mode 100644
index 000000000..55470add6
--- /dev/null
+++ b/fuzzers/corpora/midx/f009d226503b73aed0f1fd952ef8725433d158be
Binary files differ
diff --git a/fuzzers/corpora/midx/f0a821dffe21afd357932febaf6e8ee331f53197 b/fuzzers/corpora/midx/f0a821dffe21afd357932febaf6e8ee331f53197
new file mode 100644
index 000000000..c4464b19c
--- /dev/null
+++ b/fuzzers/corpora/midx/f0a821dffe21afd357932febaf6e8ee331f53197
Binary files differ
diff --git a/fuzzers/corpora/midx/f101a2fe93dfaaed1c596022b4e509cf3a591c8a b/fuzzers/corpora/midx/f101a2fe93dfaaed1c596022b4e509cf3a591c8a
new file mode 100644
index 000000000..5576bd013
--- /dev/null
+++ b/fuzzers/corpora/midx/f101a2fe93dfaaed1c596022b4e509cf3a591c8a
Binary files differ
diff --git a/fuzzers/corpora/midx/f1101f71657385174f8cb920026a761404b4395d b/fuzzers/corpora/midx/f1101f71657385174f8cb920026a761404b4395d
new file mode 100644
index 000000000..59bd02e18
--- /dev/null
+++ b/fuzzers/corpora/midx/f1101f71657385174f8cb920026a761404b4395d
Binary files differ
diff --git a/fuzzers/corpora/midx/f138c84e42d3cc61a219c4be9db791750f0541c8 b/fuzzers/corpora/midx/f138c84e42d3cc61a219c4be9db791750f0541c8
new file mode 100644
index 000000000..ab2d713fa
--- /dev/null
+++ b/fuzzers/corpora/midx/f138c84e42d3cc61a219c4be9db791750f0541c8
@@ -0,0 +1 @@
+ã]]ÿÿÿÿÿs5e \ No newline at end of file
diff --git a/fuzzers/corpora/midx/f1da273522bfff4a4971b4ffc31e365f60fdbbfe b/fuzzers/corpora/midx/f1da273522bfff4a4971b4ffc31e365f60fdbbfe
new file mode 100644
index 000000000..7417bb73b
--- /dev/null
+++ b/fuzzers/corpora/midx/f1da273522bfff4a4971b4ffc31e365f60fdbbfe
Binary files differ
diff --git a/fuzzers/corpora/midx/f2fe69d30ec47e78a9e92f1423698a52270672b2 b/fuzzers/corpora/midx/f2fe69d30ec47e78a9e92f1423698a52270672b2
new file mode 100644
index 000000000..6eb21da0e
--- /dev/null
+++ b/fuzzers/corpora/midx/f2fe69d30ec47e78a9e92f1423698a52270672b2
Binary files differ
diff --git a/fuzzers/corpora/midx/f368bb6f633587a7bb271de7e20695f178c89686 b/fuzzers/corpora/midx/f368bb6f633587a7bb271de7e20695f178c89686
new file mode 100644
index 000000000..0c0cac9cd
--- /dev/null
+++ b/fuzzers/corpora/midx/f368bb6f633587a7bb271de7e20695f178c89686
Binary files differ
diff --git a/fuzzers/corpora/midx/f38ced5a16edaceb5f527ebc35e7870f42586c90 b/fuzzers/corpora/midx/f38ced5a16edaceb5f527ebc35e7870f42586c90
new file mode 100644
index 000000000..adc467ac6
--- /dev/null
+++ b/fuzzers/corpora/midx/f38ced5a16edaceb5f527ebc35e7870f42586c90
Binary files differ
diff --git a/fuzzers/corpora/midx/f404371362ae68ffb2837ce1766346ebb645d173 b/fuzzers/corpora/midx/f404371362ae68ffb2837ce1766346ebb645d173
new file mode 100644
index 000000000..a0b47bc8f
--- /dev/null
+++ b/fuzzers/corpora/midx/f404371362ae68ffb2837ce1766346ebb645d173
Binary files differ
diff --git a/fuzzers/corpora/midx/f473b5e1cf51502345f5c1840ec3948d308dd314 b/fuzzers/corpora/midx/f473b5e1cf51502345f5c1840ec3948d308dd314
new file mode 100644
index 000000000..301811de6
--- /dev/null
+++ b/fuzzers/corpora/midx/f473b5e1cf51502345f5c1840ec3948d308dd314
Binary files differ
diff --git a/fuzzers/corpora/midx/f4ad43d6f913c3be6243dfc439e4b6f5b2e814b9 b/fuzzers/corpora/midx/f4ad43d6f913c3be6243dfc439e4b6f5b2e814b9
new file mode 100644
index 000000000..9e3bc983c
--- /dev/null
+++ b/fuzzers/corpora/midx/f4ad43d6f913c3be6243dfc439e4b6f5b2e814b9
Binary files differ
diff --git a/fuzzers/corpora/midx/f4cde4083a974d755a38bf5ea3820f78b576754a b/fuzzers/corpora/midx/f4cde4083a974d755a38bf5ea3820f78b576754a
new file mode 100644
index 000000000..0699a327c
--- /dev/null
+++ b/fuzzers/corpora/midx/f4cde4083a974d755a38bf5ea3820f78b576754a
Binary files differ
diff --git a/fuzzers/corpora/midx/f5888d0dcacda196d73772aabc18fe2ad6e1dfa2 b/fuzzers/corpora/midx/f5888d0dcacda196d73772aabc18fe2ad6e1dfa2
new file mode 100644
index 000000000..488911f2f
--- /dev/null
+++ b/fuzzers/corpora/midx/f5888d0dcacda196d73772aabc18fe2ad6e1dfa2
Binary files differ
diff --git a/fuzzers/corpora/midx/f5c3577a62d401f071d5edaa77c54ae98d6a0318 b/fuzzers/corpora/midx/f5c3577a62d401f071d5edaa77c54ae98d6a0318
new file mode 100644
index 000000000..bfec0079b
--- /dev/null
+++ b/fuzzers/corpora/midx/f5c3577a62d401f071d5edaa77c54ae98d6a0318
@@ -0,0 +1 @@
+Ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï \ No newline at end of file
diff --git a/fuzzers/corpora/midx/f5dee0d9da0d6950069ac36b1880090a20f50f3e b/fuzzers/corpora/midx/f5dee0d9da0d6950069ac36b1880090a20f50f3e
new file mode 100644
index 000000000..9330af78a
--- /dev/null
+++ b/fuzzers/corpora/midx/f5dee0d9da0d6950069ac36b1880090a20f50f3e
Binary files differ
diff --git a/fuzzers/corpora/midx/f605fff495fef2719585c706c05c350812402a35 b/fuzzers/corpora/midx/f605fff495fef2719585c706c05c350812402a35
new file mode 100644
index 000000000..7cae730c1
--- /dev/null
+++ b/fuzzers/corpora/midx/f605fff495fef2719585c706c05c350812402a35
Binary files differ
diff --git a/fuzzers/corpora/midx/f6fdaf4e77e29c780b9e0b91637777575bebfab4 b/fuzzers/corpora/midx/f6fdaf4e77e29c780b9e0b91637777575bebfab4
new file mode 100644
index 000000000..0b2545e7a
--- /dev/null
+++ b/fuzzers/corpora/midx/f6fdaf4e77e29c780b9e0b91637777575bebfab4
Binary files differ
diff --git a/fuzzers/corpora/midx/f72700bd65fa86c588607ec50d60a9c684c86f43 b/fuzzers/corpora/midx/f72700bd65fa86c588607ec50d60a9c684c86f43
new file mode 100644
index 000000000..3dfa423ce
--- /dev/null
+++ b/fuzzers/corpora/midx/f72700bd65fa86c588607ec50d60a9c684c86f43
Binary files differ
diff --git a/fuzzers/corpora/midx/f777db12ef18f002febd5af13e2b948c95d964c3 b/fuzzers/corpora/midx/f777db12ef18f002febd5af13e2b948c95d964c3
new file mode 100644
index 000000000..1869c3da1
--- /dev/null
+++ b/fuzzers/corpora/midx/f777db12ef18f002febd5af13e2b948c95d964c3
Binary files differ
diff --git a/fuzzers/corpora/midx/f777e9274d508e7ac1069e2a04bedc042942491c b/fuzzers/corpora/midx/f777e9274d508e7ac1069e2a04bedc042942491c
new file mode 100644
index 000000000..cb62442ca
--- /dev/null
+++ b/fuzzers/corpora/midx/f777e9274d508e7ac1069e2a04bedc042942491c
Binary files differ
diff --git a/fuzzers/corpora/midx/f81306f8ceaec3d06d5d34afa9769d15f0d209eb b/fuzzers/corpora/midx/f81306f8ceaec3d06d5d34afa9769d15f0d209eb
new file mode 100644
index 000000000..4a36e1fac
--- /dev/null
+++ b/fuzzers/corpora/midx/f81306f8ceaec3d06d5d34afa9769d15f0d209eb
Binary files differ
diff --git a/fuzzers/corpora/midx/f84c2b36689f22809d9bda00febab557c381ffa4 b/fuzzers/corpora/midx/f84c2b36689f22809d9bda00febab557c381ffa4
new file mode 100644
index 000000000..de7f301bd
--- /dev/null
+++ b/fuzzers/corpora/midx/f84c2b36689f22809d9bda00febab557c381ffa4
Binary files differ
diff --git a/fuzzers/corpora/midx/f98168fa74c26b17ad0c3002f2263beb0af7c0ce b/fuzzers/corpora/midx/f98168fa74c26b17ad0c3002f2263beb0af7c0ce
new file mode 100644
index 000000000..c1c20439e
--- /dev/null
+++ b/fuzzers/corpora/midx/f98168fa74c26b17ad0c3002f2263beb0af7c0ce
Binary files differ
diff --git a/fuzzers/corpora/midx/fa6759d6a2807bbad83ba21761772c0119122c35 b/fuzzers/corpora/midx/fa6759d6a2807bbad83ba21761772c0119122c35
new file mode 100644
index 000000000..79b7fe107
--- /dev/null
+++ b/fuzzers/corpora/midx/fa6759d6a2807bbad83ba21761772c0119122c35
Binary files differ
diff --git a/fuzzers/corpora/midx/fa8b927b25a67fa3d60b12c53ac365366cc2b52d b/fuzzers/corpora/midx/fa8b927b25a67fa3d60b12c53ac365366cc2b52d
new file mode 100644
index 000000000..22522c2c5
--- /dev/null
+++ b/fuzzers/corpora/midx/fa8b927b25a67fa3d60b12c53ac365366cc2b52d
Binary files differ
diff --git a/fuzzers/corpora/midx/fc5e4b78e59daebed1118389b57a386981f2430e b/fuzzers/corpora/midx/fc5e4b78e59daebed1118389b57a386981f2430e
new file mode 100644
index 000000000..5c6a22d0c
--- /dev/null
+++ b/fuzzers/corpora/midx/fc5e4b78e59daebed1118389b57a386981f2430e
Binary files differ
diff --git a/fuzzers/corpora/midx/fdaf408880429153cfcf5d978727cd7b84c3d60e b/fuzzers/corpora/midx/fdaf408880429153cfcf5d978727cd7b84c3d60e
new file mode 100644
index 000000000..76f7c5276
--- /dev/null
+++ b/fuzzers/corpora/midx/fdaf408880429153cfcf5d978727cd7b84c3d60e
Binary files differ
diff --git a/fuzzers/corpora/midx/fe50e7564a28683b24c57f8bcdcb3fbfa61f5c6a b/fuzzers/corpora/midx/fe50e7564a28683b24c57f8bcdcb3fbfa61f5c6a
new file mode 100644
index 000000000..f20372060
--- /dev/null
+++ b/fuzzers/corpora/midx/fe50e7564a28683b24c57f8bcdcb3fbfa61f5c6a
Binary files differ
diff --git a/fuzzers/corpora/midx/fe64b998872d3ad87df2019173ddc52686841d7d b/fuzzers/corpora/midx/fe64b998872d3ad87df2019173ddc52686841d7d
new file mode 100644
index 000000000..1b4e28ef7
--- /dev/null
+++ b/fuzzers/corpora/midx/fe64b998872d3ad87df2019173ddc52686841d7d
Binary files differ
diff --git a/fuzzers/corpora/midx/fec56c7cc86871aaa9c7a947c4084307cac2778d b/fuzzers/corpora/midx/fec56c7cc86871aaa9c7a947c4084307cac2778d
new file mode 100644
index 000000000..c57cd188a
--- /dev/null
+++ b/fuzzers/corpora/midx/fec56c7cc86871aaa9c7a947c4084307cac2778d
Binary files differ
diff --git a/fuzzers/corpora/midx/ff164dfc56dd28709488130dc6dfc17406bf9e9d b/fuzzers/corpora/midx/ff164dfc56dd28709488130dc6dfc17406bf9e9d
new file mode 100644
index 000000000..ceda10e93
--- /dev/null
+++ b/fuzzers/corpora/midx/ff164dfc56dd28709488130dc6dfc17406bf9e9d
Binary files differ
diff --git a/fuzzers/corpora/midx/ff7035b3c055718728a6025b3cdf55c34c4c744b b/fuzzers/corpora/midx/ff7035b3c055718728a6025b3cdf55c34c4c744b
new file mode 100644
index 000000000..8c963ab05
--- /dev/null
+++ b/fuzzers/corpora/midx/ff7035b3c055718728a6025b3cdf55c34c4c744b
Binary files differ
diff --git a/fuzzers/midx_fuzzer.c b/fuzzers/midx_fuzzer.c
new file mode 100644
index 000000000..e67873faa
--- /dev/null
+++ b/fuzzers/midx_fuzzer.c
@@ -0,0 +1,76 @@
+/*
+ * libgit2 multi-pack-index fuzzer target.
+ *
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include <stdio.h>
+
+#include "git2.h"
+
+#include "buffer.h"
+#include "common.h"
+#include "futils.h"
+#include "hash.h"
+#include "midx.h"
+
+int LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ GIT_UNUSED(argc);
+ GIT_UNUSED(argv);
+
+ if (git_libgit2_init() < 0) {
+ fprintf(stderr, "Failed to initialize libgit2\n");
+ abort();
+ }
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ git_midx_file idx = {{0}};
+ git_midx_entry e;
+ git_buf midx_buf = GIT_BUF_INIT;
+ git_oid oid = {{0}};
+ bool append_hash = false;
+
+ if (size < 4)
+ return 0;
+
+ /*
+ * If the first byte in the stream has the high bit set, append the
+ * SHA1 hash so that the packfile is somewhat valid.
+ */
+ append_hash = *data & 0x80;
+ /* Keep a 4-byte alignment to avoid unaligned accesses. */
+ data += 4;
+ size -= 4;
+
+ if (append_hash) {
+ if (git_buf_init(&midx_buf, size + sizeof(oid)) < 0)
+ goto cleanup;
+ if (git_hash_buf(&oid, data, size) < 0) {
+ fprintf(stderr, "Failed to compute the SHA1 hash\n");
+ abort();
+ }
+ memcpy(midx_buf.ptr, data, size);
+ memcpy(midx_buf.ptr + size, &oid, sizeof(oid));
+ } else {
+ git_buf_attach_notowned(&midx_buf, (char *)data, size);
+ }
+
+ if (git_midx_parse(&idx, (const unsigned char *)git_buf_cstr(&midx_buf), git_buf_len(&midx_buf)) < 0)
+ goto cleanup;
+
+ /* Search for any oid, just to exercise that codepath. */
+ if (git_midx_entry_find(&e, &idx, &oid, GIT_OID_HEXSZ) < 0)
+ goto cleanup;
+
+cleanup:
+ git_midx_close(&idx);
+ git_buf_dispose(&midx_buf);
+ return 0;
+}
diff --git a/git.git-authors b/git.git-authors
index 905bdd24f..d9a911419 100644
--- a/git.git-authors
+++ b/git.git-authors
@@ -25,9 +25,9 @@
# contributed code (possibly with some exceptions)
# "no" means the author does not consent
# "ask" means that the contributor wants to give/withhold
-# his/her consent on a patch-by-patch basis.
+# their consent on a patch-by-patch basis.
# "???" means the person is a prominent contributor who has
-# not yet made his/her standpoint clear.
+# not yet made their standpoint clear.
#
# Please try to keep the list alphabetically ordered. It will
# help in case we get all 600-ish git.git authors on it.
diff --git a/include/git2.h b/include/git2.h
index f39d7fbe2..2961cc3e5 100644
--- a/include/git2.h
+++ b/include/git2.h
@@ -26,6 +26,7 @@
#include "git2/deprecated.h"
#include "git2/describe.h"
#include "git2/diff.h"
+#include "git2/email.h"
#include "git2/errors.h"
#include "git2/filter.h"
#include "git2/global.h"
diff --git a/include/git2/annotated_commit.h b/include/git2/annotated_commit.h
index fa795bfc4..3b7103f20 100644
--- a/include/git2/annotated_commit.h
+++ b/include/git2/annotated_commit.h
@@ -78,7 +78,7 @@ GIT_EXTERN(int) git_annotated_commit_lookup(
const git_oid *id);
/**
- * Creates a `git_annotated_comit` from a revision string.
+ * Creates a `git_annotated_commit` from a revision string.
*
* See `man gitrevisions`, or
* http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for
diff --git a/include/git2/apply.h b/include/git2/apply.h
index b248eaafe..bc637df1c 100644
--- a/include/git2/apply.h
+++ b/include/git2/apply.h
@@ -100,6 +100,7 @@ GIT_EXTERN(int) git_apply_options_init(git_apply_options *opts, unsigned int ver
* @param preimage the tree to apply the diff to
* @param diff the diff to apply
* @param options the options for the apply (or null for defaults)
+ * @return 0 or an error code
*/
GIT_EXTERN(int) git_apply_to_tree(
git_index **out,
@@ -137,6 +138,7 @@ typedef enum {
* @param diff the diff to apply
* @param location the location to apply (workdir, index or both)
* @param options the options for the apply (or null for defaults)
+ * @return 0 or an error code
*/
GIT_EXTERN(int) git_apply(
git_repository *repo,
diff --git a/include/git2/attr.h b/include/git2/attr.h
index a3ab5a7a2..3891a0c97 100644
--- a/include/git2/attr.h
+++ b/include/git2/attr.h
@@ -130,9 +130,38 @@ GIT_EXTERN(git_attr_value_t) git_attr_value(const char *attr);
*
* Passing the `GIT_ATTR_CHECK_INCLUDE_HEAD` flag will use attributes
* from a `.gitattributes` file in the repository at the HEAD revision.
+ *
+ * Passing the `GIT_ATTR_CHECK_INCLUDE_COMMIT` flag will use attributes
+ * from a `.gitattributes` file in a specific commit.
*/
#define GIT_ATTR_CHECK_NO_SYSTEM (1 << 2)
#define GIT_ATTR_CHECK_INCLUDE_HEAD (1 << 3)
+#define GIT_ATTR_CHECK_INCLUDE_COMMIT (1 << 4)
+
+/**
+* An options structure for querying attributes.
+*/
+typedef struct {
+ unsigned int version;
+
+ /** A combination of GIT_ATTR_CHECK flags */
+ unsigned int flags;
+
+#ifdef GIT_DEPRECATE_HARD
+ void *reserved;
+#else
+ git_oid *commit_id;
+#endif
+
+ /**
+ * The commit to load attributes from, when
+ * `GIT_ATTR_CHECK_INCLUDE_COMMIT` is specified.
+ */
+ git_oid attr_commit_id;
+} git_attr_options;
+
+#define GIT_ATTR_OPTIONS_VERSION 1
+#define GIT_ATTR_OPTIONS_INIT {GIT_ATTR_OPTIONS_VERSION}
/**
* Look up the value of one git attribute for path.
@@ -157,6 +186,28 @@ GIT_EXTERN(int) git_attr_get(
const char *name);
/**
+ * Look up the value of one git attribute for path with extended options.
+ *
+ * @param value_out Output of the value of the attribute. Use the GIT_ATTR_...
+ * macros to test for TRUE, FALSE, UNSPECIFIED, etc. or just
+ * use the string value for attributes set to a value. You
+ * should NOT modify or free this value.
+ * @param repo The repository containing the path.
+ * @param opts The `git_attr_options` to use when querying these attributes.
+ * @param path The path to check for attributes. Relative paths are
+ * interpreted relative to the repo root. The file does
+ * not have to exist, but if it does not, then it will be
+ * treated as a plain file (not a directory).
+ * @param name The name of the attribute to look up.
+ */
+GIT_EXTERN(int) git_attr_get_ext(
+ const char **value_out,
+ git_repository *repo,
+ git_attr_options *opts,
+ const char *path,
+ const char *name);
+
+/**
* Look up a list of git attributes for path.
*
* Use this if you have a known list of attributes that you want to
@@ -194,6 +245,30 @@ GIT_EXTERN(int) git_attr_get_many(
const char **names);
/**
+ * Look up a list of git attributes for path with extended options.
+ *
+ * @param values_out An array of num_attr entries that will have string
+ * pointers written into it for the values of the attributes.
+ * You should not modify or free the values that are written
+ * into this array (although of course, you should free the
+ * array itself if you allocated it).
+ * @param repo The repository containing the path.
+ * @param opts The `git_attr_options` to use when querying these attributes.
+ * @param path The path inside the repo to check attributes. This
+ * does not have to exist, but if it does not, then
+ * it will be treated as a plain file (i.e. not a directory).
+ * @param num_attr The number of attributes being looked up
+ * @param names An array of num_attr strings containing attribute names.
+ */
+GIT_EXTERN(int) git_attr_get_many_ext(
+ const char **values_out,
+ git_repository *repo,
+ git_attr_options *opts,
+ const char *path,
+ size_t num_attr,
+ const char **names);
+
+/**
* The callback used with git_attr_foreach.
*
* This callback will be invoked only once per attribute name, even if there
@@ -232,6 +307,26 @@ GIT_EXTERN(int) git_attr_foreach(
void *payload);
/**
+ * Loop over all the git attributes for a path with extended options.
+ *
+ * @param repo The repository containing the path.
+ * @param opts The `git_attr_options` to use when querying these attributes.
+ * @param path Path inside the repo to check attributes. This does not have
+ * to exist, but if it does not, then it will be treated as a
+ * plain file (i.e. not a directory).
+ * @param callback Function to invoke on each attribute name and value.
+ * See git_attr_foreach_cb.
+ * @param payload Passed on as extra parameter to callback function.
+ * @return 0 on success, non-zero callback return value, or error code
+ */
+GIT_EXTERN(int) git_attr_foreach_ext(
+ git_repository *repo,
+ git_attr_options *opts,
+ const char *path,
+ git_attr_foreach_cb callback,
+ void *payload);
+
+/**
* Flush the gitattributes cache.
*
* Call this if you have reason to believe that the attributes files on
diff --git a/include/git2/blame.h b/include/git2/blame.h
index f42c81552..d193ce14e 100644
--- a/include/git2/blame.h
+++ b/include/git2/blame.h
@@ -26,27 +26,52 @@ GIT_BEGIN_DECL
typedef enum {
/** Normal blame, the default */
GIT_BLAME_NORMAL = 0,
- /** Track lines that have moved within a file (like `git blame -M`).
- * NOT IMPLEMENTED. */
+
+ /**
+ * Track lines that have moved within a file (like `git blame -M`).
+ *
+ * This is not yet implemented and reserved for future use.
+ */
GIT_BLAME_TRACK_COPIES_SAME_FILE = (1<<0),
- /** Track lines that have moved across files in the same commit (like `git blame -C`).
- * NOT IMPLEMENTED. */
+
+ /**
+ * Track lines that have moved across files in the same commit
+ * (like `git blame -C`).
+ *
+ * This is not yet implemented and reserved for future use.
+ */
GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES = (1<<1),
- /** Track lines that have been copied from another file that exists in the
- * same commit (like `git blame -CC`). Implies SAME_FILE.
- * NOT IMPLEMENTED. */
+
+ /**
+ * Track lines that have been copied from another file that exists
+ * in the same commit (like `git blame -CC`). Implies SAME_FILE.
+ *
+ * This is not yet implemented and reserved for future use.
+ */
GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES = (1<<2),
- /** Track lines that have been copied from another file that exists in *any*
- * commit (like `git blame -CCC`). Implies SAME_COMMIT_COPIES.
- * NOT IMPLEMENTED. */
+
+ /**
+ * Track lines that have been copied from another file that exists in
+ * *any* commit (like `git blame -CCC`). Implies SAME_COMMIT_COPIES.
+ *
+ * This is not yet implemented and reserved for future use.
+ */
GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3),
- /** Restrict the search of commits to those reachable following only the
- * first parents. */
+
+ /**
+ * Restrict the search of commits to those reachable following only
+ * the first parents.
+ */
GIT_BLAME_FIRST_PARENT = (1<<4),
- /** Use mailmap file to map author and committer names and email addresses
- * to canonical real names and email addresses. The mailmap will be read
- * from the working directory, or HEAD in a bare repository. */
+
+ /**
+ * Use mailmap file to map author and committer names and email
+ * addresses to canonical real names and email addresses. The
+ * mailmap will be read from the working directory, or HEAD in a
+ * bare repository.
+ */
GIT_BLAME_USE_MAILMAP = (1<<5),
+
/** Ignore whitespace differences */
GIT_BLAME_IGNORE_WHITESPACE = (1<<6),
} git_blame_flag_t;
@@ -63,25 +88,33 @@ typedef struct git_blame_options {
/** A combination of `git_blame_flag_t` */
uint32_t flags;
- /** The lower bound on the number of alphanumeric
- * characters that must be detected as moving/copying within a file for it to
- * associate those lines with the parent commit. The default value is 20.
- * This value only takes effect if any of the `GIT_BLAME_TRACK_COPIES_*`
- * flags are specified.
+
+ /**
+ * The lower bound on the number of alphanumeric characters that
+ * must be detected as moving/copying within a file for it to
+ * associate those lines with the parent commit. The default value
+ * is 20.
+ *
+ * This value only takes effect if any of the `GIT_BLAME_TRACK_COPIES_*`
+ * flags are specified.
*/
uint16_t min_match_characters;
+
/** The id of the newest commit to consider. The default is HEAD. */
git_oid newest_commit;
+
/**
* The id of the oldest commit to consider.
* The default is the first commit encountered with a NULL parent.
*/
git_oid oldest_commit;
+
/**
* The first line in the file to blame.
* The default is 1 (line numbers start with 1).
*/
size_t min_line;
+
/**
* The last line in the file to blame.
* The default is the last line of the file.
@@ -108,41 +141,59 @@ GIT_EXTERN(int) git_blame_options_init(
/**
* Structure that represents a blame hunk.
- *
- * - `lines_in_hunk` is the number of lines in this hunk
- * - `final_commit_id` is the OID of the commit where this line was last
- * changed.
- * - `final_start_line_number` is the 1-based line number where this hunk
- * begins, in the final version of the file
- * - `final_signature` is the author of `final_commit_id`. If
- * `GIT_BLAME_USE_MAILMAP` has been specified, it will contain the canonical
- * real name and email address.
- * - `orig_commit_id` is the OID of the commit where this hunk was found. This
- * will usually be the same as `final_commit_id`, except when
- * `GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES` has been specified.
- * - `orig_path` is the path to the file where this hunk originated, as of the
- * commit specified by `orig_commit_id`.
- * - `orig_start_line_number` is the 1-based line number where this hunk begins
- * in the file named by `orig_path` in the commit specified by
- * `orig_commit_id`.
- * - `orig_signature` is the author of `orig_commit_id`. If
- * `GIT_BLAME_USE_MAILMAP` has been specified, it will contain the canonical
- * real name and email address.
- * - `boundary` is 1 iff the hunk has been tracked to a boundary commit (the
- * root, or the commit specified in git_blame_options.oldest_commit)
*/
typedef struct git_blame_hunk {
+ /**
+ * The number of lines in this hunk.
+ */
size_t lines_in_hunk;
+ /**
+ * The OID of the commit where this line was last changed.
+ */
git_oid final_commit_id;
+
+ /**
+ * The 1-based line number where this hunk begins, in the final version
+ * of the file.
+ */
size_t final_start_line_number;
+
+ /**
+ * The author of `final_commit_id`. If `GIT_BLAME_USE_MAILMAP` has been
+ * specified, it will contain the canonical real name and email address.
+ */
git_signature *final_signature;
+ /**
+ * The OID of the commit where this hunk was found.
+ * This will usually be the same as `final_commit_id`, except when
+ * `GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES` has been specified.
+ */
git_oid orig_commit_id;
+
+ /**
+ * The path to the file where this hunk originated, as of the commit
+ * specified by `orig_commit_id`.
+ */
const char *orig_path;
+
+ /**
+ * The 1-based line number where this hunk begins in the file named by
+ * `orig_path` in the commit specified by `orig_commit_id`.
+ */
size_t orig_start_line_number;
+
+ /**
+ * The author of `orig_commit_id`. If `GIT_BLAME_USE_MAILMAP` has been
+ * specified, it will contain the canonical real name and email address.
+ */
git_signature *orig_signature;
+ /**
+ * The 1 iff the hunk has been tracked to a boundary commit (the root,
+ * or the commit specified in git_blame_options.oldest_commit)
+ */
char boundary;
} git_blame_hunk;
diff --git a/include/git2/blob.h b/include/git2/blob.h
index 7e2a745d1..8fc73919d 100644
--- a/include/git2/blob.h
+++ b/include/git2/blob.h
@@ -84,7 +84,7 @@ GIT_EXTERN(git_repository *) git_blob_owner(const git_blob *blob);
* time.
*
* @param blob pointer to the blob
- * @return the pointer
+ * @return the pointer, or NULL on error
*/
GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob);
@@ -113,23 +113,57 @@ typedef enum {
* When set, filters will be loaded from a `.gitattributes` file
* in the HEAD commit.
*/
- GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD = (1 << 2),
+ GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD = (1 << 2),
+
+ /**
+ * When set, filters will be loaded from a `.gitattributes` file
+ * in the specified commit.
+ */
+ GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT = (1 << 3),
} git_blob_filter_flag_t;
/**
* The options used when applying filter options to a file.
+ *
+ * Initialize with `GIT_BLOB_FILTER_OPTIONS_INIT`. Alternatively, you can
+ * use `git_blob_filter_options_init`.
+ *
*/
typedef struct {
int version;
/** Flags to control the filtering process, see `git_blob_filter_flag_t` above */
uint32_t flags;
+
+#ifdef GIT_DEPRECATE_HARD
+ void *reserved;
+#else
+ git_oid *commit_id;
+#endif
+
+ /**
+ * The commit to load attributes from, when
+ * `GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT` is specified.
+ */
+ git_oid attr_commit_id;
} git_blob_filter_options;
#define GIT_BLOB_FILTER_OPTIONS_VERSION 1
#define GIT_BLOB_FILTER_OPTIONS_INIT {GIT_BLOB_FILTER_OPTIONS_VERSION, GIT_BLOB_FILTER_CHECK_FOR_BINARY}
/**
+ * Initialize git_blob_filter_options structure
+ *
+ * Initializes a `git_blob_filter_options` with default values. Equivalent
+ * to creating an instance with `GIT_BLOB_FILTER_OPTIONS_INIT`.
+ *
+ * @param opts The `git_blob_filter_options` struct to initialize.
+ * @param version The struct version; pass `GIT_BLOB_FILTER_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_blob_filter_options_init(git_blob_filter_options *opts, unsigned int version);
+
+/**
* Get a buffer with the filtered content of a blob.
*
* This applies filters as if the blob was being checked out to the
@@ -229,7 +263,7 @@ GIT_EXTERN(int) git_blob_create_from_stream_commit(
* Write an in-memory buffer to the ODB as a blob
*
* @param id return the id of the written blob
- * @param repo repository where to blob will be written
+ * @param repo repository where the blob will be written
* @param buffer data to be written into the blob
* @param len length of the data
* @return 0 or an error code
diff --git a/include/git2/branch.h b/include/git2/branch.h
index ba6235900..24ea7f7d0 100644
--- a/include/git2/branch.h
+++ b/include/git2/branch.h
@@ -304,6 +304,31 @@ GIT_EXTERN(int) git_branch_remote_name(
*/
GIT_EXTERN(int) git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname);
+/**
+ * Retrieve the upstream merge of a local branch
+ *
+ * This will return the currently configured "branch.*.merge" for a given
+ * branch. This branch must be local.
+ *
+ * @param buf the buffer into which to write the name
+ * @param repo the repository in which to look
+ * @param refname the full name of the branch
+ * @return 0 or an error code
+ */
+ GIT_EXTERN(int) git_branch_upstream_merge(git_buf *buf, git_repository *repo, const char *refname);
+
+/**
+ * Determine whether a branch name is valid, meaning that (when prefixed
+ * with `refs/heads/`) that it is a valid reference name, and that any
+ * additional branch name restrictions are imposed (eg, it cannot start
+ * with a `-`).
+ *
+ * @param valid output pointer to set with validity of given branch name
+ * @param name a branch name to test
+ * @return 0 on success or an error code
+ */
+GIT_EXTERN(int) git_branch_name_is_valid(int *valid, const char *name);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/cert.h b/include/git2/cert.h
index e8cd2d180..0ed38ffcd 100644
--- a/include/git2/cert.h
+++ b/include/git2/cert.h
@@ -8,6 +8,7 @@
#define INCLUDE_git_cert_h__
#include "common.h"
+#include "types.h"
/**
* @file git2/cert.h
@@ -80,8 +81,27 @@ typedef enum {
GIT_CERT_SSH_SHA1 = (1 << 1),
/** SHA-256 is available */
GIT_CERT_SSH_SHA256 = (1 << 2),
+ /** Raw hostkey is available */
+ GIT_CERT_SSH_RAW = (1 << 3),
} git_cert_ssh_t;
+typedef enum {
+ /** The raw key is of an unknown type. */
+ GIT_CERT_SSH_RAW_TYPE_UNKNOWN = 0,
+ /** The raw key is an RSA key. */
+ GIT_CERT_SSH_RAW_TYPE_RSA = 1,
+ /** The raw key is a DSS key. */
+ GIT_CERT_SSH_RAW_TYPE_DSS = 2,
+ /** The raw key is a ECDSA 256 key. */
+ GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 = 3,
+ /** The raw key is a ECDSA 384 key. */
+ GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 = 4,
+ /** The raw key is a ECDSA 521 key. */
+ GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 = 5,
+ /** The raw key is a ED25519 key. */
+ GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 = 6
+} git_cert_ssh_raw_type_t;
+
/**
* Hostkey information taken from libssh2
*/
@@ -89,28 +109,45 @@ typedef struct {
git_cert parent; /**< The parent cert */
/**
- * A hostkey type from libssh2, either
- * `GIT_CERT_SSH_MD5` or `GIT_CERT_SSH_SHA1`
+ * A bitmask containing the available fields.
*/
git_cert_ssh_t type;
/**
- * Hostkey hash. If type has `GIT_CERT_SSH_MD5` set, this will
+ * Hostkey hash. If `type` has `GIT_CERT_SSH_MD5` set, this will
* have the MD5 hash of the hostkey.
*/
unsigned char hash_md5[16];
/**
- * Hostkey hash. If type has `GIT_CERT_SSH_SHA1` set, this will
+ * Hostkey hash. If `type` has `GIT_CERT_SSH_SHA1` set, this will
* have the SHA-1 hash of the hostkey.
*/
unsigned char hash_sha1[20];
/**
- * Hostkey hash. If type has `GIT_CERT_SSH_SHA256` set, this will
+ * Hostkey hash. If `type` has `GIT_CERT_SSH_SHA256` set, this will
* have the SHA-256 hash of the hostkey.
*/
unsigned char hash_sha256[32];
+
+ /**
+ * Raw hostkey type. If `type` has `GIT_CERT_SSH_RAW` set, this will
+ * have the type of the raw hostkey.
+ */
+ git_cert_ssh_raw_type_t raw_type;
+
+ /**
+ * Pointer to the raw hostkey. If `type` has `GIT_CERT_SSH_RAW` set,
+ * this will have the raw contents of the hostkey.
+ */
+ const char *hostkey;
+
+ /**
+ * Raw hostkey length. If `type` has `GIT_CERT_SSH_RAW` set, this will
+ * have the length of the raw contents of the hostkey.
+ */
+ size_t hostkey_len;
} git_cert_hostkey;
/**
diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index 3c87001bf..c7aeee431 100644
--- a/include/git2/checkout.h
+++ b/include/git2/checkout.h
@@ -178,6 +178,12 @@ typedef enum {
GIT_CHECKOUT_DONT_WRITE_INDEX = (1u << 23),
/**
+ * Show what would be done by a checkout. Stop after sending
+ * notifications; don't update the working directory or index.
+ */
+ GIT_CHECKOUT_DRY_RUN = (1u << 24),
+
+ /**
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
*/
@@ -194,18 +200,6 @@ typedef enum {
* Checkout will invoke an options notification callback (`notify_cb`) for
* certain cases - you pick which ones via `notify_flags`:
*
- * - GIT_CHECKOUT_NOTIFY_CONFLICT invokes checkout on conflicting paths.
- *
- * - GIT_CHECKOUT_NOTIFY_DIRTY notifies about "dirty" files, i.e. those that
- * do not need an update but no longer match the baseline. Core git
- * displays these files when checkout runs, but won't stop the checkout.
- *
- * - GIT_CHECKOUT_NOTIFY_UPDATED sends notification for any file changed.
- *
- * - GIT_CHECKOUT_NOTIFY_UNTRACKED notifies about untracked files.
- *
- * - GIT_CHECKOUT_NOTIFY_IGNORED notifies about ignored files.
- *
* Returning a non-zero value from this callback will cancel the checkout.
* The non-zero return value will be propagated back and returned by the
* git_checkout_... call.
@@ -216,10 +210,32 @@ typedef enum {
*/
typedef enum {
GIT_CHECKOUT_NOTIFY_NONE = 0,
+
+ /**
+ * Invokes checkout on conflicting paths.
+ */
GIT_CHECKOUT_NOTIFY_CONFLICT = (1u << 0),
+
+ /**
+ * Notifies about "dirty" files, i.e. those that do not need an update
+ * but no longer match the baseline. Core git displays these files when
+ * checkout runs, but won't stop the checkout.
+ */
GIT_CHECKOUT_NOTIFY_DIRTY = (1u << 1),
+
+ /**
+ * Sends notification for any file changed.
+ */
GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2),
+
+ /**
+ * Notifies about untracked files.
+ */
GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3),
+
+ /**
+ * Notifies about ignored files.
+ */
GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4),
GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu
diff --git a/include/git2/clone.h b/include/git2/clone.h
index 2d6f68705..3c3ea260e 100644
--- a/include/git2/clone.h
+++ b/include/git2/clone.h
@@ -133,7 +133,7 @@ typedef struct git_clone_options {
* The name of the branch to checkout. NULL means use the
* remote's default branch.
*/
- const char* checkout_branch;
+ const char *checkout_branch;
/**
* A callback used to create the new repository into which to
diff --git a/include/git2/commit.h b/include/git2/commit.h
index e6c4656a9..4d74b8994 100644
--- a/include/git2/commit.h
+++ b/include/git2/commit.h
@@ -503,25 +503,41 @@ GIT_EXTERN(int) git_commit_create_with_signature(
GIT_EXTERN(int) git_commit_dup(git_commit **out, git_commit *source);
/**
- * Commit signing callback.
- *
- * The callback will be called with the commit content, giving a user an
- * opportunity to sign the commit content. The signature_field
- * buf may be left empty to specify the default field "gpgsig".
- *
- * Signatures can take the form of any string, and can be created on an arbitrary
- * header field. Signatures are most commonly used for verifying authorship of a
- * commit using GPG or a similar cryptographically secure signing algorithm.
- * See https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work for more
- * details.
- *
- * When the callback:
- * - returns GIT_PASSTHROUGH, no signature will be added to the commit.
- * - returns < 0, commit creation will be aborted.
- * - returns GIT_OK, the signature parameter is expected to be filled.
- */
-typedef int (*git_commit_signing_cb)(
- git_buf *signature, git_buf *signature_field, const char *commit_content, void *payload);
+ * Commit creation callback: used when a function is going to create
+ * commits (for example, in `git_rebase_commit`) to allow callers to
+ * override the commit creation behavior. For example, users may
+ * wish to sign commits by providing this information to
+ * `git_commit_create_buffer`, signing that buffer, then calling
+ * `git_commit_create_with_signature`. The resultant commit id
+ * should be set in the `out` object id parameter.
+ *
+ * @param out pointer that this callback will populate with the object
+ * id of the commit that is created
+ * @param author the author name and time of the commit
+ * @param committer the committer name and time of the commit
+ * @param message_encoding the encoding of the given message, or NULL
+ * to assume UTF8
+ * @param message the commit message
+ * @param tree the tree to be committed
+ * @param parent_count the number of parents for this commit
+ * @param parents the commit parents
+ * @param payload the payload pointer in the rebase options
+ * @return 0 if this callback has created the commit and populated the out
+ * parameter, GIT_PASSTHROUGH if the callback has not created a
+ * commit and wants the calling function to create the commit as
+ * if no callback had been specified, any other value to stop
+ * and return a failure
+ */
+typedef int (*git_commit_create_cb)(
+ git_oid *out,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message_encoding,
+ const char *message,
+ const git_tree *tree,
+ size_t parent_count,
+ const git_commit *parents[],
+ void *payload);
/** @} */
GIT_END_DECL
diff --git a/include/git2/common.h b/include/git2/common.h
index d6696061d..2ee829025 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -91,10 +91,10 @@ GIT_BEGIN_DECL
/**
* The separator used in path list strings (ie like in the PATH
- * environment variable). A semi-colon ";" is used on Windows, and
- * a colon ":" for all other systems.
+ * environment variable). A semi-colon ";" is used on Windows and
+ * AmigaOS, and a colon ":" for all other systems.
*/
-#ifdef GIT_WIN32
+#if defined(GIT_WIN32) || defined(AMIGA)
#define GIT_PATH_LIST_SEPARATOR ';'
#else
#define GIT_PATH_LIST_SEPARATOR ':'
@@ -205,7 +205,13 @@ typedef enum {
GIT_OPT_GET_PACK_MAX_OBJECTS,
GIT_OPT_SET_PACK_MAX_OBJECTS,
GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS,
- GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE
+ GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE,
+ GIT_OPT_GET_MWINDOW_FILE_LIMIT,
+ GIT_OPT_SET_MWINDOW_FILE_LIMIT,
+ GIT_OPT_SET_ODB_PACKED_PRIORITY,
+ GIT_OPT_SET_ODB_LOOSE_PRIORITY,
+ GIT_OPT_GET_EXTENSIONS,
+ GIT_OPT_SET_EXTENSIONS
} git_libgit2_opt_t;
/**
@@ -227,8 +233,18 @@ typedef enum {
*
* * opts(GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, size_t):
*
- * >Set the maximum amount of memory that can be mapped at any time
- * by the library
+ * > Set the maximum amount of memory that can be mapped at any time
+ * > by the library
+ *
+ * * opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, size_t *):
+ *
+ * > Get the maximum number of files that will be mapped at any time by the
+ * > library
+ *
+ * * opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, size_t):
+ *
+ * > Set the maximum number of files that can be mapped at any time
+ * > by the library. The default (0) is unlimited.
*
* * opts(GIT_OPT_GET_SEARCH_PATH, int level, git_buf *buf)
*
@@ -344,6 +360,11 @@ typedef enum {
* >
* > - `ciphers` is the list of ciphers that are eanbled.
*
+ * * opts(GIT_OPT_GET_USER_AGENT, git_buf *out)
+ *
+ * > Get the value of the User-Agent header.
+ * > The User-Agent is written to the `out` buffer.
+ *
* * opts(GIT_OPT_ENABLE_OFS_DELTA, int enabled)
*
* > Enable or disable the use of "offset deltas" when creating packfiles,
@@ -404,6 +425,30 @@ typedef enum {
* > authentication, use expect/continue when POSTing data.
* > This option is not available on Windows.
*
+ * opts(GIT_OPT_SET_ODB_PACKED_PRIORITY, int priority)
+ * > Override the default priority of the packed ODB backend which
+ * > is added when default backends are assigned to a repository
+ *
+ * opts(GIT_OPT_SET_ODB_LOOSE_PRIORITY, int priority)
+ * > Override the default priority of the loose ODB backend which
+ * > is added when default backends are assigned to a repository
+ *
+ * opts(GIT_OPT_GET_EXTENSIONS, git_strarray *out)
+ * > Returns the list of git extensions that are supported. This
+ * > is the list of built-in extensions supported by libgit2 and
+ * > custom extensions that have been added with
+ * > `GIT_OPT_SET_EXTENSIONS`. Extensions that have been negated
+ * > will not be returned. The returned list should be released
+ * > with `git_strarray_dispose`.
+ *
+ * opts(GIT_OPT_SET_EXTENSIONS, const char **extensions, size_t len)
+ * > Set that the given git extensions are supported by the caller.
+ * > Extensions supported by libgit2 may be negated by prefixing
+ * > them with a `!`. For example: setting extensions to
+ * > { "!noop", "newext" } indicates that the caller does not want
+ * > to support repositories with the `noop` extension but does want
+ * > to support repositories with the `newext` extension.
+ *
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
diff --git a/include/git2/config.h b/include/git2/config.h
index abf5bbbd0..7c8e388b2 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -263,7 +263,7 @@ GIT_EXTERN(int) git_config_open_level(
*
* Git allows you to store your global configuration at
* `$HOME/.gitconfig` or `$XDG_CONFIG_HOME/git/config`. For backwards
- * compatability, the XDG file shouldn't be used unless the use has
+ * compatibility, the XDG file shouldn't be used unless the use has
* created it explicitly. With this function you'll open the correct
* one to write to.
*
diff --git a/include/git2/deprecated.h b/include/git2/deprecated.h
index ffef14597..37b9fa0e2 100644
--- a/include/git2/deprecated.h
+++ b/include/git2/deprecated.h
@@ -18,6 +18,7 @@
#include "describe.h"
#include "diff.h"
#include "errors.h"
+#include "filter.h"
#include "index.h"
#include "indexer.h"
#include "merge.h"
@@ -29,6 +30,7 @@
#include "trace.h"
#include "repository.h"
#include "revert.h"
+#include "revparse.h"
#include "stash.h"
#include "status.h"
#include "submodule.h"
@@ -80,16 +82,19 @@ typedef git_attr_value_t git_attr_t;
/**@}*/
-/** @name Deprecated Blob Functions
+/** @name Deprecated Blob Functions and Constants
*
- * These functions are retained for backward compatibility. The newer
- * versions of these functions should be preferred in all new code.
+ * These functions and enumeration values are retained for backward
+ * compatibility. The newer versions of these functions and values
+ * should be preferred in all new code.
*
* There is no plan to remove these backward compatibility values at
* this time.
*/
/**@{*/
+#define GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD
+
GIT_EXTERN(int) git_blob_create_fromworkdir(git_oid *id, git_repository *repo, const char *relative_path);
GIT_EXTERN(int) git_blob_create_fromdisk(git_oid *id, git_repository *repo, const char *path);
GIT_EXTERN(int) git_blob_create_fromstream(
@@ -102,7 +107,11 @@ GIT_EXTERN(int) git_blob_create_fromstream_commit(
GIT_EXTERN(int) git_blob_create_frombuffer(
git_oid *id, git_repository *repo, const void *buffer, size_t len);
-/** Deprecated in favor of @see git_blob_filter */
+/** Deprecated in favor of `git_blob_filter`.
+ *
+ * @deprecated Use git_blob_filter
+ * @see git_blob_filter
+ */
GIT_EXTERN(int) git_blob_filtered_content(
git_buf *out,
git_blob *blob,
@@ -111,6 +120,66 @@ GIT_EXTERN(int) git_blob_filtered_content(
/**@}*/
+/** @name Deprecated Filter Functions
+ *
+ * These functions are retained for backward compatibility. The
+ * newer versions of these functions should be preferred in all
+ * new code.
+ *
+ * There is no plan to remove these backward compatibility values at
+ * this time.
+ */
+/**@{*/
+
+/** Deprecated in favor of `git_filter_list_stream_buffer`.
+ *
+ * @deprecated Use git_filter_list_stream_buffer
+ * @see Use git_filter_list_stream_buffer
+ */
+GIT_EXTERN(int) git_filter_list_stream_data(
+ git_filter_list *filters,
+ git_buf *data,
+ git_writestream *target);
+
+/** Deprecated in favor of `git_filter_list_apply_to_buffer`.
+ *
+ * @deprecated Use git_filter_list_apply_to_buffer
+ * @see Use git_filter_list_apply_to_buffer
+ */
+GIT_EXTERN(int) git_filter_list_apply_to_data(
+ git_buf *out,
+ git_filter_list *filters,
+ git_buf *in);
+
+/**@}*/
+
+/** @name Deprecated Tree Functions
+ *
+ * These functions are retained for backward compatibility. The
+ * newer versions of these functions and values should be preferred
+ * in all new code.
+ *
+ * There is no plan to remove these backward compatibility values at
+ * this time.
+ */
+/**@{*/
+
+/**
+ * Write the contents of the tree builder as a tree object.
+ * This is an alias of `git_treebuilder_write` and is preserved
+ * for backward compatibility.
+ *
+ * This function is deprecated, but there is no plan to remove this
+ * function at this time.
+ *
+ * @deprecated Use git_treebuilder_write
+ * @see git_treebuilder_write
+ */
+GIT_EXTERN(int) git_treebuilder_write_with_buffer(
+ git_oid *oid, git_treebuilder *bld, git_buf *tree);
+
+/**@}*/
+
/** @name Deprecated Buffer Functions
*
* These functions and enumeration values are retained for backward
@@ -123,6 +192,61 @@ GIT_EXTERN(int) git_blob_filtered_content(
/**@{*/
/**
+ * Static initializer for git_buf from static buffer
+ */
+#define GIT_BUF_INIT_CONST(STR,LEN) { (char *)(STR), 0, (size_t)(LEN) }
+
+/**
+ * Resize the buffer allocation to make more space.
+ *
+ * This will attempt to grow the buffer to accommodate the target size.
+ *
+ * If the buffer refers to memory that was not allocated by libgit2 (i.e.
+ * the `asize` field is zero), then `ptr` will be replaced with a newly
+ * allocated block of data. Be careful so that memory allocated by the
+ * caller is not lost. As a special variant, if you pass `target_size` as
+ * 0 and the memory is not allocated by libgit2, this will allocate a new
+ * buffer of size `size` and copy the external data into it.
+ *
+ * Currently, this will never shrink a buffer, only expand it.
+ *
+ * If the allocation fails, this will return an error and the buffer will be
+ * marked as invalid for future operations, invaliding the contents.
+ *
+ * @param buffer The buffer to be resized; may or may not be allocated yet
+ * @param target_size The desired available size
+ * @return 0 on success, -1 on allocation failure
+ */
+GIT_EXTERN(int) git_buf_grow(git_buf *buffer, size_t target_size);
+
+/**
+ * Set buffer to a copy of some raw data.
+ *
+ * @param buffer The buffer to set
+ * @param data The data to copy into the buffer
+ * @param datalen The length of the data to copy into the buffer
+ * @return 0 on success, -1 on allocation failure
+ */
+GIT_EXTERN(int) git_buf_set(
+ git_buf *buffer, const void *data, size_t datalen);
+
+/**
+* Check quickly if buffer looks like it contains binary data
+*
+* @param buf Buffer to check
+* @return 1 if buffer looks like non-text data
+*/
+GIT_EXTERN(int) git_buf_is_binary(const git_buf *buf);
+
+/**
+* Check quickly if buffer contains a NUL byte
+*
+* @param buf Buffer to check
+* @return 1 if buffer contains a NUL byte
+*/
+GIT_EXTERN(int) git_buf_contains_nul(const git_buf *buf);
+
+/**
* Free the memory referred to by the git_buf. This is an alias of
* `git_buf_dispose` and is preserved for backward compatibility.
*
@@ -136,6 +260,27 @@ GIT_EXTERN(void) git_buf_free(git_buf *buffer);
/**@}*/
+/** @name Deprecated Commit Definitions
+ */
+/**@{*/
+
+/**
+ * Provide a commit signature during commit creation.
+ *
+ * Callers should instead define a `git_commit_create_cb` that
+ * generates a commit buffer using `git_commit_create_buffer`, sign
+ * that buffer and call `git_commit_create_with_signature`.
+ *
+ * @deprecated use a `git_commit_create_cb` instead
+ */
+typedef int (*git_commit_signing_cb)(
+ git_buf *signature,
+ git_buf *signature_field,
+ const char *commit_content,
+ void *payload);
+
+/**@}*/
+
/** @name Deprecated Config Functions and Constants
*/
/**@{*/
@@ -149,6 +294,102 @@ typedef git_configmap git_cvar_map;
/**@}*/
+/** @name Deprecated Diff Functions and Constants
+ *
+ * These functions and enumeration values are retained for backward
+ * compatibility. The newer versions of these functions and values
+ * should be preferred in all new code.
+ *
+ * There is no plan to remove these backward compatibility values at
+ * this time.
+ */
+/**@{*/
+
+/**
+ * Formatting options for diff e-mail generation
+ */
+typedef enum {
+ /** Normal patch, the default */
+ GIT_DIFF_FORMAT_EMAIL_NONE = 0,
+
+ /** Don't insert "[PATCH]" in the subject header*/
+ GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0),
+
+} git_diff_format_email_flags_t;
+
+/**
+ * Options for controlling the formatting of the generated e-mail.
+ */
+typedef struct {
+ unsigned int version;
+
+ /** see `git_diff_format_email_flags_t` above */
+ uint32_t flags;
+
+ /** This patch number */
+ size_t patch_no;
+
+ /** Total number of patches in this series */
+ size_t total_patches;
+
+ /** id to use for the commit */
+ const git_oid *id;
+
+ /** Summary of the change */
+ const char *summary;
+
+ /** Commit message's body */
+ const char *body;
+
+ /** Author of the change */
+ const git_signature *author;
+} git_diff_format_email_options;
+
+#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1
+#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL, NULL}
+
+/**
+ * Create an e-mail ready patch from a diff.
+ *
+ * @deprecated git_email_create_from_diff
+ * @see git_email_create_from_diff
+ */
+GIT_EXTERN(int) git_diff_format_email(
+ git_buf *out,
+ git_diff *diff,
+ const git_diff_format_email_options *opts);
+
+/**
+ * Create an e-mail ready patch for a commit.
+ *
+ * @deprecated git_email_create_from_commit
+ * @see git_email_create_from_commit
+ */
+GIT_EXTERN(int) git_diff_commit_as_email(
+ git_buf *out,
+ git_repository *repo,
+ git_commit *commit,
+ size_t patch_no,
+ size_t total_patches,
+ uint32_t flags,
+ const git_diff_options *diff_opts);
+
+/**
+ * Initialize git_diff_format_email_options structure
+ *
+ * Initializes a `git_diff_format_email_options` with default values. Equivalent
+ * to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
+ *
+ * @param opts The `git_blame_options` struct to initialize.
+ * @param version The struct version; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_diff_format_email_options_init(
+ git_diff_format_email_options *opts,
+ unsigned int version);
+
+/**@}*/
+
/** @name Deprecated Error Functions and Constants
*
* These functions and enumeration values are retained for backward
@@ -233,7 +474,7 @@ GIT_EXTERN(void) giterr_clear(void);
GIT_EXTERN(void) giterr_set_str(int error_class, const char *string);
/**
- * Indicates that an out-of-memory situation occured. This is an alias
+ * Indicates that an out-of-memory situation occurred. This is an alias
* of `git_error_set_oom` and is preserved for backward compatibility.
*
* This function is deprecated, but there is no plan to remove this
@@ -336,10 +577,32 @@ GIT_EXTERN(size_t) git_object__size(git_object_t type);
/**@}*/
-/** @name Deprecated Reference Constants
+/** @name Deprecated Remote Functions
*
- * These enumeration values are retained for backward compatibility. The
- * newer versions of these values should be preferred in all new code.
+ * These functions are retained for backward compatibility. The newer
+ * versions of these functions should be preferred in all new code.
+ *
+ * There is no plan to remove these backward compatibility functions at
+ * this time.
+ */
+/**@{*/
+
+/**
+ * Ensure the remote name is well-formed.
+ *
+ * @deprecated Use git_remote_name_is_valid
+ * @param remote_name name to be checked.
+ * @return 1 if the reference name is acceptable; 0 if it isn't
+ */
+GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name);
+
+/**@}*/
+
+/** @name Deprecated Reference Functions and Constants
+ *
+ * These functions and enumeration values are retained for backward
+ * compatibility. The newer versions of these values should be
+ * preferred in all new code.
*
* There is no plan to remove these backward compatibility values at
* this time.
@@ -360,6 +623,23 @@ GIT_EXTERN(size_t) git_object__size(git_object_t type);
#define GIT_REF_FORMAT_REFSPEC_PATTERN GIT_REFERENCE_FORMAT_REFSPEC_PATTERN
#define GIT_REF_FORMAT_REFSPEC_SHORTHAND GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND
+/**
+ * Ensure the reference name is well-formed.
+ *
+ * Valid reference names must follow one of two patterns:
+ *
+ * 1. Top-level names must contain only capital letters and underscores,
+ * and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD").
+ * 2. Names prefixed with "refs/" can be almost anything. You must avoid
+ * the characters '~', '^', ':', '\\', '?', '[', and '*', and the
+ * sequences ".." and "@{" which have special meaning to revparse.
+ *
+ * @deprecated Use git_reference_name_is_valid
+ * @param refname name to be checked.
+ * @return 1 if the reference name is acceptable; 0 if it isn't
+ */
+GIT_EXTERN(int) git_reference_is_valid_name(const char *refname);
+
GIT_EXTERN(int) git_tag_create_frombuffer(
git_oid *oid,
git_repository *repo,
@@ -368,6 +648,25 @@ GIT_EXTERN(int) git_tag_create_frombuffer(
/**@}*/
+/** @name Deprecated Revspec Constants
+ *
+ * These enumeration values are retained for backward compatibility.
+ * The newer versions of these values should be preferred in all new
+ * code.
+ *
+ * There is no plan to remove these backward compatibility values at
+ * this time.
+ */
+/**@{*/
+
+typedef git_revspec_t git_revparse_mode_t;
+
+#define GIT_REVPARSE_SINGLE GIT_REVSPEC_SINGLE
+#define GIT_REVPARSE_RANGE GIT_REVSPEC_RANGE
+#define GIT_REVPARSE_MERGE_BASE GIT_REVSPEC_MERGE_BASE
+
+/**@}*/
+
/** @name Deprecated Credential Types
*
* These types are retained for backward compatibility. The newer
@@ -376,6 +675,7 @@ GIT_EXTERN(int) git_tag_create_frombuffer(
* There is no plan to remove these backward compatibility values at
* this time.
*/
+/**@{*/
typedef git_credential git_cred;
typedef git_credential_userpass_plaintext git_cred_userpass_plaintext;
@@ -479,6 +779,30 @@ GIT_EXTERN(int) git_oid_iszero(const git_oid *id);
/**@}*/
+/** @name Deprecated OID Array Functions
+ *
+ * These types are retained for backward compatibility. The newer
+ * versions of these values should be preferred in all new code.
+ *
+ * There is no plan to remove these backward compatibility values at
+ * this time.
+ */
+/**@{*/
+
+/**
+ * Free the memory referred to by the git_oidarray. This is an alias of
+ * `git_oidarray_dispose` and is preserved for backward compatibility.
+ *
+ * This function is deprecated, but there is no plan to remove this
+ * function at this time.
+ *
+ * @deprecated Use git_oidarray_dispose
+ * @see git_oidarray_dispose
+ */
+GIT_EXTERN(void) git_oidarray_free(git_oidarray *array);
+
+/**@}*/
+
/** @name Deprecated Transfer Progress Types
*
* These types are retained for backward compatibility. The newer
diff --git a/include/git2/diff.h b/include/git2/diff.h
index 3976ab1b9..a14c01993 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -133,6 +133,9 @@ typedef enum {
*/
GIT_DIFF_INDENT_HEURISTIC = (1u << 18),
+ /** Ignore blank lines */
+ GIT_DIFF_IGNORE_BLANK_LINES = (1u << 19),
+
/** Treat all files as text, disabling binary attributes & detection */
GIT_DIFF_FORCE_TEXT = (1u << 20),
/** Treat all files as binary, disabling text diffs */
@@ -237,32 +240,43 @@ typedef enum {
* Although this is called a "file", it could represent a file, a symbolic
* link, a submodule commit id, or even a tree (although that only if you
* are tracking type changes or ignored/untracked directories).
- *
- * The `id` is the `git_oid` of the item. If the entry represents an
- * absent side of a diff (e.g. the `old_file` of a `GIT_DELTA_ADDED` delta),
- * then the oid will be zeroes.
- *
- * `path` is the NUL-terminated path to the entry relative to the working
- * directory of the repository.
- *
- * `size` is the size of the entry in bytes.
- *
- * `flags` is a combination of the `git_diff_flag_t` types
- *
- * `mode` is, roughly, the stat() `st_mode` value for the item. This will
- * be restricted to one of the `git_filemode_t` values.
- *
- * The `id_abbrev` represents the known length of the `id` field, when
- * converted to a hex string. It is generally `GIT_OID_HEXSZ`, unless this
- * delta was created from reading a patch file, in which case it may be
- * abbreviated to something reasonable, like 7 characters.
*/
typedef struct {
+ /**
+ * The `git_oid` of the item. If the entry represents an
+ * absent side of a diff (e.g. the `old_file` of a `GIT_DELTA_ADDED` delta),
+ * then the oid will be zeroes.
+ */
git_oid id;
+
+ /**
+ * The NUL-terminated path to the entry relative to the working
+ * directory of the repository.
+ */
const char *path;
+
+ /**
+ * The size of the entry in bytes.
+ */
git_object_size_t size;
+
+ /**
+ * A combination of the `git_diff_flag_t` types
+ */
uint32_t flags;
+
+ /**
+ * Roughly, the stat() `st_mode` value for the item. This will
+ * be restricted to one of the `git_filemode_t` values.
+ */
uint16_t mode;
+
+ /**
+ * Represents the known length of the `id` field, when
+ * converted to a hex string. It is generally `GIT_OID_HEXSZ`, unless this
+ * delta was created from reading a patch file, in which case it may be
+ * abbreviated to something reasonable, like 7 characters.
+ */
uint16_t id_abbrev;
} git_diff_file;
@@ -998,7 +1012,7 @@ GIT_EXTERN(size_t) git_diff_num_deltas(const git_diff *diff);
/**
* Query how many diff deltas are there in a diff filtered by type.
*
- * This works just like `git_diff_entrycount()` with an extra parameter
+ * This works just like `git_diff_num_deltas()` with an extra parameter
* that is a `git_delta_t` and returns just the count of how many deltas
* match that particular type.
*
@@ -1362,99 +1376,6 @@ GIT_EXTERN(int) git_diff_stats_to_buf(
GIT_EXTERN(void) git_diff_stats_free(git_diff_stats *stats);
/**
- * Formatting options for diff e-mail generation
- */
-typedef enum {
- /** Normal patch, the default */
- GIT_DIFF_FORMAT_EMAIL_NONE = 0,
-
- /** Don't insert "[PATCH]" in the subject header*/
- GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0),
-
-} git_diff_format_email_flags_t;
-
-/**
- * Options for controlling the formatting of the generated e-mail.
- */
-typedef struct {
- unsigned int version;
-
- /** see `git_diff_format_email_flags_t` above */
- uint32_t flags;
-
- /** This patch number */
- size_t patch_no;
-
- /** Total number of patches in this series */
- size_t total_patches;
-
- /** id to use for the commit */
- const git_oid *id;
-
- /** Summary of the change */
- const char *summary;
-
- /** Commit message's body */
- const char *body;
-
- /** Author of the change */
- const git_signature *author;
-} git_diff_format_email_options;
-
-#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1
-#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL, NULL}
-
-/**
- * Create an e-mail ready patch from a diff.
- *
- * @param out buffer to store the e-mail patch in
- * @param diff containing the commit
- * @param opts structure with options to influence content and formatting.
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_diff_format_email(
- git_buf *out,
- git_diff *diff,
- const git_diff_format_email_options *opts);
-
-/**
- * Create an e-mail ready patch for a commit.
- *
- * Does not support creating patches for merge commits (yet).
- *
- * @param out buffer to store the e-mail patch in
- * @param repo containing the commit
- * @param commit pointer to up commit
- * @param patch_no patch number of the commit
- * @param total_patches total number of patches in the patch set
- * @param flags determines the formatting of the e-mail
- * @param diff_opts structure with options to influence diff or NULL for defaults.
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_diff_commit_as_email(
- git_buf *out,
- git_repository *repo,
- git_commit *commit,
- size_t patch_no,
- size_t total_patches,
- uint32_t flags,
- const git_diff_options *diff_opts);
-
-/**
- * Initialize git_diff_format_email_options structure
- *
- * Initializes a `git_diff_format_email_options` with default values. Equivalent
- * to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
- *
- * @param opts The `git_blame_options` struct to initialize.
- * @param version The struct version; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`.
- * @return Zero on success; -1 on failure.
- */
-GIT_EXTERN(int) git_diff_format_email_options_init(
- git_diff_format_email_options *opts,
- unsigned int version);
-
-/**
* Patch ID options structure
*
* Initialize with `GIT_PATCHID_OPTIONS_INIT`. Alternatively, you can
diff --git a/include/git2/email.h b/include/git2/email.h
new file mode 100644
index 000000000..b56be5d0e
--- /dev/null
+++ b/include/git2/email.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_git_email_h__
+#define INCLUDE_git_email_h__
+
+#include "common.h"
+
+/**
+ * @file git2/email.h
+ * @brief Git email formatting and application routines.
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Formatting options for diff e-mail generation
+ */
+typedef enum {
+ /** Normal patch, the default */
+ GIT_EMAIL_CREATE_DEFAULT = 0,
+
+ /** Do not include patch numbers in the subject prefix. */
+ GIT_EMAIL_CREATE_OMIT_NUMBERS = (1u << 0),
+
+ /**
+ * Include numbers in the subject prefix even when the
+ * patch is for a single commit (1/1).
+ */
+ GIT_EMAIL_CREATE_ALWAYS_NUMBER = (1u << 1),
+
+ /** Do not perform rename or similarity detection. */
+ GIT_EMAIL_CREATE_NO_RENAMES = (1u << 2),
+} git_email_create_flags_t;
+
+/**
+ * Options for controlling the formatting of the generated e-mail.
+ */
+typedef struct {
+ unsigned int version;
+
+ /** see `git_email_create_flags_t` above */
+ uint32_t flags;
+
+ /** Options to use when creating diffs */
+ git_diff_options diff_opts;
+
+ /** Options for finding similarities within diffs */
+ git_diff_find_options diff_find_opts;
+
+ /**
+ * The subject prefix, by default "PATCH". If set to an empty
+ * string ("") then only the patch numbers will be shown in the
+ * prefix. If the subject_prefix is empty and patch numbers
+ * are not being shown, the prefix will be omitted entirely.
+ */
+ const char *subject_prefix;
+
+ /**
+ * The starting patch number; this cannot be 0. By default,
+ * this is 1.
+ */
+ size_t start_number;
+
+ /** The "re-roll" number. By default, there is no re-roll. */
+ size_t reroll_number;
+} git_email_create_options;
+
+/*
+ * By default, our options include rename detection and binary
+ * diffs to match `git format-patch`.
+ */
+#define GIT_EMAIL_CREATE_OPTIONS_VERSION 1
+#define GIT_EMAIL_CREATE_OPTIONS_INIT \
+{ \
+ GIT_EMAIL_CREATE_OPTIONS_VERSION, \
+ GIT_EMAIL_CREATE_DEFAULT, \
+ { GIT_DIFF_OPTIONS_VERSION, GIT_DIFF_SHOW_BINARY, GIT_SUBMODULE_IGNORE_UNSPECIFIED, {NULL,0}, NULL, NULL, NULL, 3 }, \
+ GIT_DIFF_FIND_OPTIONS_INIT \
+}
+
+/**
+ * Create a diff for a commit in mbox format for sending via email.
+ *
+ * @param out buffer to store the e-mail patch in
+ * @param diff the changes to include in the email
+ * @param patch_idx the patch index
+ * @param patch_count the total number of patches that will be included
+ * @param commit_id the commit id for this change
+ * @param summary the commit message for this change
+ * @param body optional text to include above the diffstat
+ * @param author the person who authored this commit
+ * @param opts email creation options
+ */
+GIT_EXTERN(int) git_email_create_from_diff(
+ git_buf *out,
+ git_diff *diff,
+ size_t patch_idx,
+ size_t patch_count,
+ const git_oid *commit_id,
+ const char *summary,
+ const char *body,
+ const git_signature *author,
+ const git_email_create_options *opts);
+
+/**
+ * Create a diff for a commit in mbox format for sending via email.
+ * The commit must not be a merge commit.
+ *
+ * @param out buffer to store the e-mail patch in
+ * @param commit commit to create a patch for
+ * @param opts email creation options
+ */
+GIT_EXTERN(int) git_email_create_from_commit(
+ git_buf *out,
+ git_commit *commit,
+ const git_email_create_options *opts);
+
+GIT_END_DECL
+
+/** @} */
+
+#endif
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 47a79b76c..9bb9f25e6 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -42,14 +42,14 @@ typedef enum {
GIT_ECONFLICT = -13, /**< Checkout conflicts prevented operation */
GIT_ELOCKED = -14, /**< Lock file prevented operation */
GIT_EMODIFIED = -15, /**< Reference value does not match expected */
- GIT_EAUTH = -16, /**< Authentication error */
- GIT_ECERTIFICATE = -17, /**< Server certificate is invalid */
+ GIT_EAUTH = -16, /**< Authentication error */
+ GIT_ECERTIFICATE = -17, /**< Server certificate is invalid */
GIT_EAPPLIED = -18, /**< Patch/merge has already been applied */
- GIT_EPEEL = -19, /**< The requested peel operation is not possible */
- GIT_EEOF = -20, /**< Unexpected EOF */
- GIT_EINVALID = -21, /**< Invalid operation or input */
+ GIT_EPEEL = -19, /**< The requested peel operation is not possible */
+ GIT_EEOF = -20, /**< Unexpected EOF */
+ GIT_EINVALID = -21, /**< Invalid operation or input */
GIT_EUNCOMMITTED = -22, /**< Uncommitted changes in index prevented operation */
- GIT_EDIRECTORY = -23, /**< The operation is not valid for a directory */
+ GIT_EDIRECTORY = -23, /**< The operation is not valid for a directory */
GIT_EMERGECONFLICT = -24, /**< A merge conflict exists and cannot continue */
GIT_PASSTHROUGH = -30, /**< A user-configured callback refused to act */
diff --git a/include/git2/filter.h b/include/git2/filter.h
index 886059051..0465e5b14 100644
--- a/include/git2/filter.h
+++ b/include/git2/filter.h
@@ -49,9 +49,40 @@ typedef enum {
/** Load attributes from `.gitattributes` in the root of HEAD */
GIT_FILTER_ATTRIBUTES_FROM_HEAD = (1u << 2),
+
+ /**
+ * Load attributes from `.gitattributes` in a given commit.
+ * This can only be specified in a `git_filter_options`.
+ */
+ GIT_FILTER_ATTRIBUTES_FROM_COMMIT = (1u << 3),
} git_filter_flag_t;
/**
+ * Filtering options
+ */
+typedef struct {
+ unsigned int version;
+
+ /** See `git_filter_flag_t` above */
+ uint32_t flags;
+
+#ifdef GIT_DEPRECATE_HARD
+ void *reserved;
+#else
+ git_oid *commit_id;
+#endif
+
+ /**
+ * The commit to load attributes from, when
+ * `GIT_FILTER_ATTRIBUTES_FROM_COMMIT` is specified.
+ */
+ git_oid attr_commit_id;
+} git_filter_options;
+
+ #define GIT_FILTER_OPTIONS_VERSION 1
+ #define GIT_FILTER_OPTIONS_INIT {GIT_FILTER_OPTIONS_VERSION}
+
+/**
* A filter that can transform file data
*
* This represents a filter that can be used to transform or even replace
@@ -104,6 +135,29 @@ GIT_EXTERN(int) git_filter_list_load(
uint32_t flags);
/**
+ * Load the filter list for a given path.
+ *
+ * This will return 0 (success) but set the output git_filter_list to NULL
+ * if no filters are requested for the given file.
+ *
+ * @param filters Output newly created git_filter_list (or NULL)
+ * @param repo Repository object that contains `path`
+ * @param blob The blob to which the filter will be applied (if known)
+ * @param path Relative path of the file to be filtered
+ * @param mode Filtering direction (WT->ODB or ODB->WT)
+ * @param opts The `git_filter_options` to use when loading filters
+ * @return 0 on success (which could still return NULL if no filters are
+ * needed for the requested file), <0 on error
+ */
+GIT_EXTERN(int) git_filter_list_load_ext(
+ git_filter_list **filters,
+ git_repository *repo,
+ git_blob *blob,
+ const char *path,
+ git_filter_mode_t mode,
+ git_filter_options *opts);
+
+/**
* Query the filter list to see if a given filter (by name) will run.
* The built-in filters "crlf" and "ident" can be queried, otherwise this
* is the name of the filter specified by the filter attribute.
@@ -122,27 +176,17 @@ GIT_EXTERN(int) git_filter_list_contains(
/**
* Apply filter list to a data buffer.
*
- * See `git2/buffer.h` for background on `git_buf` objects.
- *
- * If the `in` buffer holds data allocated by libgit2 (i.e. `in->asize` is
- * not zero), then it will be overwritten when applying the filters. If
- * not, then it will be left untouched.
- *
- * If there are no filters to apply (or `filters` is NULL), then the `out`
- * buffer will reference the `in` buffer data (with `asize` set to zero)
- * instead of allocating data. This keeps allocations to a minimum, but
- * it means you have to be careful about freeing the `in` data since `out`
- * may be pointing to it!
- *
* @param out Buffer to store the result of the filtering
* @param filters A loaded git_filter_list (or NULL)
* @param in Buffer containing the data to filter
+ * @param in_len The length of the input buffer
* @return 0 on success, an error code otherwise
*/
-GIT_EXTERN(int) git_filter_list_apply_to_data(
+GIT_EXTERN(int) git_filter_list_apply_to_buffer(
git_buf *out,
git_filter_list *filters,
- git_buf *in);
+ const char *in,
+ size_t in_len);
/**
* Apply a filter list to the contents of a file on disk
@@ -175,12 +219,14 @@ GIT_EXTERN(int) git_filter_list_apply_to_blob(
* Apply a filter list to an arbitrary buffer as a stream
*
* @param filters the list of filters to apply
- * @param data the buffer to filter
+ * @param buffer the buffer to filter
+ * @param len the size of the buffer
* @param target the stream into which the data will be written
*/
-GIT_EXTERN(int) git_filter_list_stream_data(
+GIT_EXTERN(int) git_filter_list_stream_buffer(
git_filter_list *filters,
- git_buf *data,
+ const char *buffer,
+ size_t len,
git_writestream *target);
/**
diff --git a/include/git2/graph.h b/include/git2/graph.h
index 213ae9777..712ae474a 100644
--- a/include/git2/graph.h
+++ b/include/git2/graph.h
@@ -43,8 +43,9 @@ GIT_EXTERN(int) git_graph_ahead_behind(size_t *ahead, size_t *behind, git_reposi
* Note that a commit is not considered a descendant of itself, in contrast
* to `git merge-base --is-ancestor`.
*
- * @param commit a previously loaded commit.
- * @param ancestor a potential ancestor commit.
+ * @param repo the repository where the commits exist
+ * @param commit a previously loaded commit
+ * @param ancestor a potential ancestor commit
* @return 1 if the given commit is a descendant of the potential ancestor,
* 0 if not, error code otherwise.
*/
@@ -53,6 +54,23 @@ GIT_EXTERN(int) git_graph_descendant_of(
const git_oid *commit,
const git_oid *ancestor);
+/**
+ * Determine if a commit is reachable from any of a list of commits by
+ * following parent edges.
+ *
+ * @param repo the repository where the commits exist
+ * @param commit a previously loaded commit
+ * @param length the number of commits in the provided `descendant_array`
+ * @param descendant_array oids of the commits
+ * @return 1 if the given commit is an ancestor of any of the given potential
+ * descendants, 0 if not, error code otherwise.
+ */
+GIT_EXTERN(int) git_graph_reachable_from_any(
+ git_repository *repo,
+ const git_oid *commit,
+ const git_oid descendant_array[],
+ size_t length);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/index.h b/include/git2/index.h
index 314135109..532a52091 100644
--- a/include/git2/index.h
+++ b/include/git2/index.h
@@ -349,7 +349,7 @@ GIT_EXTERN(int) git_index_write_tree(git_oid *out, git_index *index);
*
* The index must not contain any file in conflict.
*
- * @param out Pointer where to store OID of the the written tree
+ * @param out Pointer where to store OID of the written tree
* @param index Index to write
* @param repo Repository where to write the tree
* @return 0 on success, GIT_EUNMERGED when the index is not clean
@@ -702,7 +702,7 @@ GIT_EXTERN(int) git_index_update_all(
* @param at_pos the address to which the position of the index entry is written (optional)
* @param index an existing index object
* @param path path to search
- * @return a zero-based position in the index if found; GIT_ENOTFOUND otherwise
+ * @return 0 or an error code
*/
GIT_EXTERN(int) git_index_find(size_t *at_pos, git_index *index, const char *path);
@@ -713,7 +713,7 @@ GIT_EXTERN(int) git_index_find(size_t *at_pos, git_index *index, const char *pat
* @param at_pos the address to which the position of the index entry is written (optional)
* @param index an existing index object
* @param prefix the prefix to search for
- * @return 0 with valid value in at_pos; an error code otherwise
+ * @return 0 or an error code
*/
GIT_EXTERN(int) git_index_find_prefix(size_t *at_pos, git_index *index, const char *prefix);
diff --git a/include/git2/indexer.h b/include/git2/indexer.h
index 8059e4db3..a434d243f 100644
--- a/include/git2/indexer.h
+++ b/include/git2/indexer.h
@@ -51,7 +51,7 @@ typedef struct git_indexer_progress {
* Type for progress callbacks during indexing. Return a value less
* than zero to cancel the indexing or download.
*
- * @param stats Structure containing information about the state of the tran sfer
+ * @param stats Structure containing information about the state of the transfer
* @param payload Payload provided by caller
*/
typedef int GIT_CALLBACK(git_indexer_progress_cb)(const git_indexer_progress *stats, void *payload);
@@ -64,6 +64,7 @@ typedef struct git_indexer_options {
/** progress_cb function to call with progress information */
git_indexer_progress_cb progress_cb;
+
/** progress_cb_payload payload for the progress callback */
void *progress_cb_payload;
diff --git a/include/git2/notes.h b/include/git2/notes.h
index c36149e5b..c135881a7 100644
--- a/include/git2/notes.h
+++ b/include/git2/notes.h
@@ -84,8 +84,8 @@ GIT_EXTERN(void) git_note_iterator_free(git_note_iterator *it);
* (negative value)
*/
GIT_EXTERN(int) git_note_next(
- git_oid* note_id,
- git_oid* annotated_id,
+ git_oid *note_id,
+ git_oid *annotated_id,
git_note_iterator *it);
diff --git a/include/git2/odb.h b/include/git2/odb.h
index c4bfa5290..dd484553f 100644
--- a/include/git2/odb.h
+++ b/include/git2/odb.h
@@ -70,7 +70,7 @@ GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
*
* @param odb database to add the backend to
* @param path path to the objects folder for the alternate
- * @return 0 on success; error code otherwise
+ * @return 0 on success, error code otherwise
*/
GIT_EXTERN(int) git_odb_add_disk_alternate(git_odb *odb, const char *path);
@@ -94,9 +94,8 @@ GIT_EXTERN(void) git_odb_free(git_odb *db);
* @param out pointer where to store the read object
* @param db database to search for the object in.
* @param id identity of the object to read.
- * @return
- * - 0 if the object was read;
- * - GIT_ENOTFOUND if the object is not in the database.
+ * @return 0 if the object was read, GIT_ENOTFOUND if the object is
+ * not in the database.
*/
GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id);
@@ -122,10 +121,9 @@ GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *i
* @param db database to search for the object in.
* @param short_id a prefix of the id of the object to read.
* @param len the length of the prefix
- * @return
- * - 0 if the object was read;
- * - GIT_ENOTFOUND if the object is not in the database.
- * - GIT_EAMBIGUOUS if the prefix is ambiguous (several objects match the prefix)
+ * @return 0 if the object was read, GIT_ENOTFOUND if the object is not in the
+ * database. GIT_EAMBIGUOUS if the prefix is ambiguous
+ * (several objects match the prefix)
*/
GIT_EXTERN(int) git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_id, size_t len);
@@ -143,9 +141,8 @@ GIT_EXTERN(int) git_odb_read_prefix(git_odb_object **out, git_odb *db, const git
* @param type_out pointer where to store the type
* @param db database to search for the object in.
* @param id identity of the object to read.
- * @return
- * - 0 if the object was read;
- * - GIT_ENOTFOUND if the object is not in the database.
+ * @return 0 if the object was read, GIT_ENOTFOUND if the object is not
+ * in the database.
*/
GIT_EXTERN(int) git_odb_read_header(size_t *len_out, git_object_t *type_out, git_odb *db, const git_oid *id);
@@ -154,9 +151,7 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_out, git_object_t *type_out, git
*
* @param db database to be searched for the given object.
* @param id the object to search for.
- * @return
- * - 1, if the object was found
- * - 0, otherwise
+ * @return 1 if the object was found, 0 otherwise
*/
GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
@@ -305,7 +300,7 @@ GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **out, git_odb *db, git_obje
* @param stream the stream
* @param buffer the data to write
* @param len the buffer's length
- * @return 0 if the write succeeded; error code otherwise
+ * @return 0 if the write succeeded, error code otherwise
*/
GIT_EXTERN(int) git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len);
@@ -320,7 +315,7 @@ GIT_EXTERN(int) git_odb_stream_write(git_odb_stream *stream, const char *buffer,
*
* @param out pointer to store the resulting object's id
* @param stream the stream
- * @return 0 on success; an error code otherwise
+ * @return 0 on success, an error code otherwise
*/
GIT_EXTERN(int) git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream);
@@ -362,7 +357,7 @@ GIT_EXTERN(void) git_odb_stream_free(git_odb_stream *stream);
* @param type pointer where to store the type of the object
* @param db object database where the stream will read from
* @param oid oid of the object the stream will read from
- * @return 0 if the stream was created; error code otherwise
+ * @return 0 if the stream was created, error code otherwise
*/
GIT_EXTERN(int) git_odb_open_rstream(
git_odb_stream **out,
@@ -396,6 +391,20 @@ GIT_EXTERN(int) git_odb_write_pack(
void *progress_payload);
/**
+ * Write a `multi-pack-index` file from all the `.pack` files in the ODB.
+ *
+ * If the ODB layer understands pack files, then this will create a file called
+ * `multi-pack-index` next to the `.pack` and `.idx` files, which will contain
+ * an index of all objects stored in `.pack` files. This will allow for
+ * O(log n) lookup for n objects (regardless of how many packfiles there
+ * exist).
+ *
+ * @param db object database where the `multi-pack-index` file will be written.
+ */
+GIT_EXTERN(int) git_odb_write_multi_pack_index(
+ git_odb *db);
+
+/**
* Determine the object-ID (sha1 hash) of a data buffer
*
* The resulting SHA-1 OID will be the identifier for the data
@@ -501,7 +510,7 @@ GIT_EXTERN(git_object_t) git_odb_object_type(git_odb_object *object);
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
* @param priority Value for ordering the backends queue
- * @return 0 on success; error code otherwise
+ * @return 0 on success, error code otherwise
*/
GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority);
@@ -522,7 +531,7 @@ GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
* @param priority Value for ordering the backends queue
- * @return 0 on success; error code otherwise
+ * @return 0 on success, error code otherwise
*/
GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority);
@@ -540,10 +549,25 @@ GIT_EXTERN(size_t) git_odb_num_backends(git_odb *odb);
* @param out output pointer to ODB backend at pos
* @param odb object database
* @param pos index into object database backend list
- * @return 0 on success; GIT_ENOTFOUND if pos is invalid; other errors < 0
+ * @return 0 on success, GIT_ENOTFOUND if pos is invalid, other errors < 0
*/
GIT_EXTERN(int) git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos);
+/**
+ * Set the git commit-graph for the ODB.
+ *
+ * After a successfull call, the ownership of the cgraph parameter will be
+ * transferred to libgit2, and the caller should not free it.
+ *
+ * The commit-graph can also be unset by explicitly passing NULL as the cgraph
+ * parameter.
+ *
+ * @param odb object database
+ * @param cgraph the git commit-graph
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_odb_set_commit_graph(git_odb *odb, git_commit_graph *cgraph);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/oidarray.h b/include/git2/oidarray.h
index 0b3204597..94fc58dab 100644
--- a/include/git2/oidarray.h
+++ b/include/git2/oidarray.h
@@ -19,19 +19,16 @@ typedef struct git_oidarray {
} git_oidarray;
/**
- * Free the OID array
- *
- * This method must (and must only) be called on `git_oidarray`
- * objects where the array is allocated by the library. Not doing so,
- * will result in a memory leak.
+ * Free the object IDs contained in an oid_array. This method should
+ * be called on `git_oidarray` objects that were provided by the
+ * library. Not doing so will result in a memory leak.
*
* This does not free the `git_oidarray` itself, since the library will
- * never allocate that object directly itself (it is more commonly embedded
- * inside another struct or created on the stack).
+ * never allocate that object directly itself.
*
* @param array git_oidarray from which to free oid data
*/
-GIT_EXTERN(void) git_oidarray_free(git_oidarray *array);
+GIT_EXTERN(void) git_oidarray_dispose(git_oidarray *array);
/** @} */
GIT_END_DECL
diff --git a/include/git2/patch.h b/include/git2/patch.h
index b177798e6..fde9659e7 100644
--- a/include/git2/patch.h
+++ b/include/git2/patch.h
@@ -29,6 +29,14 @@ GIT_BEGIN_DECL
typedef struct git_patch git_patch;
/**
+ * Get the repository associated with this patch. May be NULL.
+ *
+ * @param patch the patch
+ * @return a pointer to the repository
+ */
+GIT_EXTERN(git_repository *) git_patch_owner(const git_patch *patch);
+
+/**
* Return a patch for an entry in the diff list.
*
* The `git_patch` is a newly created object contains the text diffs
diff --git a/include/git2/rebase.h b/include/git2/rebase.h
index 99a02fef9..11e452cbf 100644
--- a/include/git2/rebase.h
+++ b/include/git2/rebase.h
@@ -75,13 +75,37 @@ typedef struct {
git_checkout_options checkout_options;
/**
+ * Optional callback that allows users to override commit
+ * creation in `git_rebase_commit`. If specified, users can
+ * create their own commit and provide the commit ID, which
+ * may be useful for signing commits or otherwise customizing
+ * the commit creation.
+ *
+ * If this callback returns `GIT_PASSTHROUGH`, then
+ * `git_rebase_commit` will continue to create the commit.
+ */
+ git_commit_create_cb commit_create_cb;
+
+#ifdef GIT_DEPRECATE_HARD
+ void *reserved;
+#else
+ /**
* If provided, this will be called with the commit content, allowing
* a signature to be added to the rebase commit. Can be skipped with
* GIT_PASSTHROUGH. If GIT_PASSTHROUGH is returned, a commit will be made
* without a signature.
+ *
* This field is only used when performing git_rebase_commit.
+ *
+ * This callback is not invoked if a `git_commit_create_cb` is
+ * specified.
+ *
+ * This callback is deprecated; users should provide a
+ * creation callback as `commit_create_cb` that produces a
+ * commit buffer, signs it, and commits it.
*/
- git_commit_signing_cb signing_cb;
+ int (*signing_cb)(git_buf *, git_buf *, const char *, void *);
+#endif
/**
* This will be passed to each of the callbacks in this struct
diff --git a/include/git2/refs.h b/include/git2/refs.h
index c9cce2212..7ebb209b2 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -97,6 +97,9 @@ GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, co
* of updating does not match the one passed through `current_value`
* (i.e. if the ref has changed since the user read it).
*
+ * If `current_value` is all zeros, this function will return GIT_EMODIFIED
+ * if the ref already exists.
+ *
* @param out Pointer to the newly created reference
* @param repo Repository where that reference will live
* @param name The name of the reference
@@ -169,7 +172,7 @@ GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repositor
*
* The message for the reflog will be ignored if the reference does
* not belong in the standard set (HEAD, branches and remote-tracking
- * branches) and and it does not have a reflog.
+ * branches) and it does not have a reflog.
*
* @param out Pointer to the newly created reference
* @param repo Repository where that reference will live
@@ -206,7 +209,7 @@ GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo,
*
* The message for the reflog will be ignored if the reference does
* not belong in the standard set (HEAD, branches and remote-tracking
- * branches) and and it does not have a reflog.
+ * branches) and it does not have a reflog.
*
* It will return GIT_EMODIFIED if the reference's value at the time
* of updating does not match the one passed through `current_id`
@@ -318,7 +321,7 @@ GIT_EXTERN(git_repository *) git_reference_owner(const git_reference *ref);
*
* The message for the reflog will be ignored if the reference does
* not belong in the standard set (HEAD, branches and remote-tracking
- * branches) and and it does not have a reflog.
+ * branches) and it does not have a reflog.
*
* @param out Pointer to the newly created reference
* @param ref The reference
@@ -743,10 +746,11 @@ GIT_EXTERN(int) git_reference_peel(
* the characters '~', '^', ':', '\\', '?', '[', and '*', and the
* sequences ".." and "@{" which have special meaning to revparse.
*
+ * @param valid output pointer to set with validity of given reference name
* @param refname name to be checked.
- * @return 1 if the reference name is acceptable; 0 if it isn't
+ * @return 0 on success or an error code
*/
-GIT_EXTERN(int) git_reference_is_valid_name(const char *refname);
+GIT_EXTERN(int) git_reference_name_is_valid(int *valid, const char *refname);
/**
* Get the reference's short name
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 51d9c7235..4d57eaaf7 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -212,7 +212,8 @@ GIT_EXTERN(const char *) git_remote_name(const git_remote *remote);
* Get the remote's url
*
* If url.*.insteadOf has been configured for this URL, it will
- * return the modified URL.
+ * return the modified URL. If `git_remote_set_instance_pushurl`
+ * has been called for this remote, then that URL will be returned.
*
* @param remote the remote
* @return a pointer to the url
@@ -220,10 +221,11 @@ GIT_EXTERN(const char *) git_remote_name(const git_remote *remote);
GIT_EXTERN(const char *) git_remote_url(const git_remote *remote);
/**
- * Get the remote's url for pushing
+ * Get the remote's url for pushing.
*
* If url.*.pushInsteadOf has been configured for this URL, it
- * will return the modified URL.
+ * will return the modified URL. If `git_remote_set_instance_pushurl`
+ * has been called for this remote, then that URL will be returned.
*
* @param remote the remote
* @return a pointer to the url or NULL if no special url for pushing is set
@@ -241,7 +243,7 @@ GIT_EXTERN(const char *) git_remote_pushurl(const git_remote *remote);
* @param url the url to set
* @return 0 or an error value
*/
-GIT_EXTERN(int) git_remote_set_url(git_repository *repo, const char *remote, const char* url);
+GIT_EXTERN(int) git_remote_set_url(git_repository *repo, const char *remote, const char *url);
/**
* Set the remote's url for pushing in the configuration.
@@ -253,8 +255,29 @@ GIT_EXTERN(int) git_remote_set_url(git_repository *repo, const char *remote, con
* @param repo the repository in which to perform the change
* @param remote the remote's name
* @param url the url to set
+ * @return 0, or an error code
*/
-GIT_EXTERN(int) git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url);
+GIT_EXTERN(int) git_remote_set_pushurl(git_repository *repo, const char *remote, const char *url);
+
+/**
+ * Set the url for this particular url instance. The URL in the
+ * configuration will be ignored, and will not be changed.
+ *
+ * @param remote the remote's name
+ * @param url the url to set
+ * @return 0 or an error value
+ */
+GIT_EXTERN(int) git_remote_set_instance_url(git_remote *remote, const char *url);
+
+/**
+ * Set the push url for this particular url instance. The URL in the
+ * configuration will be ignored, and will not be changed.
+ *
+ * @param remote the remote's name
+ * @param url the url to set
+ * @return 0 or an error value
+ */
+GIT_EXTERN(int) git_remote_set_instance_pushurl(git_remote *remote, const char *url);
/**
* Add a fetch refspec to the remote's configuration
@@ -428,7 +451,7 @@ typedef int GIT_CALLBACK(git_push_transfer_progress_cb)(
unsigned int current,
unsigned int total,
size_t bytes,
- void* payload);
+ void *payload);
/**
* Represents an update which will be performed on the remote during push
@@ -476,6 +499,7 @@ typedef int GIT_CALLBACK(git_push_negotiation)(const git_push_update **updates,
*/
typedef int GIT_CALLBACK(git_push_update_reference_cb)(const char *refname, const char *status, void *data);
+#ifndef GIT_DEPRECATE_HARD
/**
* Callback to resolve URLs before connecting to remote
*
@@ -487,8 +511,22 @@ typedef int GIT_CALLBACK(git_push_update_reference_cb)(const char *refname, cons
* @param direction GIT_DIRECTION_FETCH or GIT_DIRECTION_PUSH
* @param payload Payload provided by the caller
* @return 0 on success, GIT_PASSTHROUGH or an error
+ * @deprecated Use `git_remote_set_instance_url`
*/
typedef int GIT_CALLBACK(git_url_resolve_cb)(git_buf *url_resolved, const char *url, int direction, void *payload);
+#endif
+
+/**
+ * Callback invoked immediately before we attempt to connect to the
+ * given url. Callers may change the URL before the connection by
+ * calling `git_remote_set_instance_url` in the callback.
+ *
+ * @param remote The remote to be connected
+ * @param direction GIT_DIRECTION_FETCH or GIT_DIRECTION_PUSH
+ * @param payload Payload provided by the caller
+ * @return 0 on success, or an error
+ */
+typedef int GIT_CALLBACK(git_remote_ready_cb)(git_remote *remote, int direction, void *payload);
/**
* The callback settings structure
@@ -575,16 +613,28 @@ struct git_remote_callbacks {
git_transport_cb transport;
/**
+ * Callback when the remote is ready to connect.
+ */
+ git_remote_ready_cb remote_ready;
+
+ /**
* This will be passed to each of the callbacks in this struct
* as the last parameter.
*/
void *payload;
+#ifdef GIT_DEPRECATE_HARD
+ void *reserved;
+#else
/**
* Resolve URL before connecting to remote.
* The returned URL will be used to connect to the remote instead.
+ *
+ * This callback is deprecated; users should use
+ * git_remote_ready_cb and configure the instance URL instead.
*/
git_url_resolve_cb resolve_url;
+#endif
};
#define GIT_REMOTE_CALLBACKS_VERSION 1
@@ -876,8 +926,10 @@ GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(const git_remote *rem
* @param repo the repository in which to make the change
* @param remote the name of the remote
* @param value the new value to take.
+ * @return 0, or an error code.
*/
GIT_EXTERN(int) git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_autotag_option_t value);
+
/**
* Retrieve the ref-prune setting
*
@@ -915,10 +967,11 @@ GIT_EXTERN(int) git_remote_rename(
/**
* Ensure the remote name is well-formed.
*
+ * @param valid output pointer to set with validity of given remote name
* @param remote_name name to be checked.
- * @return 1 if the reference name is acceptable; 0 if it isn't
+ * @return 0 on success or an error code
*/
-GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name);
+GIT_EXTERN(int) git_remote_name_is_valid(int *valid, const char *remote_name);
/**
* Delete an existing persisted remote.
@@ -943,7 +996,7 @@ GIT_EXTERN(int) git_remote_delete(git_repository *repo, const char *name);
*
* This function must only be called after connecting.
*
- * @param out the buffern in which to store the reference name
+ * @param out the buffer in which to store the reference name
* @param remote the remote
* @return 0, GIT_ENOTFOUND if the remote does not have any references
* or none of them point to HEAD's commit, or an error message.
diff --git a/include/git2/repository.h b/include/git2/repository.h
index aa81e3843..ec8adfb29 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -220,36 +220,54 @@ GIT_EXTERN(int) git_repository_init(
*
* These flags configure extra behaviors to `git_repository_init_ext`.
* In every case, the default behavior is the zero value (i.e. flag is
- * not set). Just OR the flag values together for the `flags` parameter
- * when initializing a new repo. Details of individual values are:
- *
- * * BARE - Create a bare repository with no working directory.
- * * NO_REINIT - Return an GIT_EEXISTS error if the repo_path appears to
- * already be an git repository.
- * * NO_DOTGIT_DIR - Normally a "/.git/" will be appended to the repo
- * path for non-bare repos (if it is not already there), but
- * passing this flag prevents that behavior.
- * * MKDIR - Make the repo_path (and workdir_path) as needed. Init is
- * always willing to create the ".git" directory even without this
- * flag. This flag tells init to create the trailing component of
- * the repo and workdir paths as needed.
- * * MKPATH - Recursively make all components of the repo and workdir
- * paths as necessary.
- * * EXTERNAL_TEMPLATE - libgit2 normally uses internal templates to
- * initialize a new repo. This flags enables external templates,
- * looking the "template_path" from the options if set, or the
- * `init.templatedir` global config if not, or falling back on
- * "/usr/share/git-core/templates" if it exists.
- * * GIT_REPOSITORY_INIT_RELATIVE_GITLINK - If an alternate workdir is
- * specified, use relative paths for the gitdir and core.worktree.
+ * not set). Just OR the flag values together for the `flags` parameter
+ * when initializing a new repo.
*/
typedef enum {
+ /**
+ * Create a bare repository with no working directory.
+ */
GIT_REPOSITORY_INIT_BARE = (1u << 0),
+
+ /**
+ * Return an GIT_EEXISTS error if the repo_path appears to already be
+ * an git repository.
+ */
GIT_REPOSITORY_INIT_NO_REINIT = (1u << 1),
+
+ /**
+ * Normally a "/.git/" will be appended to the repo path for
+ * non-bare repos (if it is not already there), but passing this flag
+ * prevents that behavior.
+ */
GIT_REPOSITORY_INIT_NO_DOTGIT_DIR = (1u << 2),
+
+ /**
+ * Make the repo_path (and workdir_path) as needed. Init is always willing
+ * to create the ".git" directory even without this flag. This flag tells
+ * init to create the trailing component of the repo and workdir paths
+ * as needed.
+ */
GIT_REPOSITORY_INIT_MKDIR = (1u << 3),
+
+ /**
+ * Recursively make all components of the repo and workdir paths as
+ * necessary.
+ */
GIT_REPOSITORY_INIT_MKPATH = (1u << 4),
+
+ /**
+ * libgit2 normally uses internal templates to initialize a new repo.
+ * This flags enables external templates, looking the "template_path" from
+ * the options if set, or the `init.templatedir` global config if not,
+ * or falling back on "/usr/share/git-core/templates" if it exists.
+ */
GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE = (1u << 5),
+
+ /**
+ * If an alternate workdir is specified, use relative paths for the gitdir
+ * and core.worktree.
+ */
GIT_REPOSITORY_INIT_RELATIVE_GITLINK = (1u << 6),
} git_repository_init_flag_t;
@@ -258,17 +276,23 @@ typedef enum {
*
* Set the mode field of the `git_repository_init_options` structure
* either to the custom mode that you would like, or to one of the
- * following modes:
- *
- * * SHARED_UMASK - Use permissions configured by umask - the default.
- * * SHARED_GROUP - Use "--shared=group" behavior, chmod'ing the new repo
- * to be group writable and "g+sx" for sticky group assignment.
- * * SHARED_ALL - Use "--shared=all" behavior, adding world readability.
- * * Anything else - Set to custom value.
+ * defined modes.
*/
typedef enum {
+ /**
+ * Use permissions configured by umask - the default.
+ */
GIT_REPOSITORY_INIT_SHARED_UMASK = 0,
+
+ /**
+ * Use "--shared=group" behavior, chmod'ing the new repo to be group
+ * writable and "g+sx" for sticky group assignment.
+ */
GIT_REPOSITORY_INIT_SHARED_GROUP = 0002775,
+
+ /**
+ * Use "--shared=all" behavior, adding world readability.
+ */
GIT_REPOSITORY_INIT_SHARED_ALL = 0002777,
} git_repository_init_mode_t;
@@ -276,38 +300,57 @@ typedef enum {
* Extended options structure for `git_repository_init_ext`.
*
* This contains extra options for `git_repository_init_ext` that enable
- * additional initialization features. The fields are:
- *
- * * flags - Combination of GIT_REPOSITORY_INIT flags above.
- * * mode - Set to one of the standard GIT_REPOSITORY_INIT_SHARED_...
- * constants above, or to a custom value that you would like.
- * * workdir_path - The path to the working dir or NULL for default (i.e.
- * repo_path parent on non-bare repos). IF THIS IS RELATIVE PATH,
- * IT WILL BE EVALUATED RELATIVE TO THE REPO_PATH. If this is not
- * the "natural" working directory, a .git gitlink file will be
- * created here linking to the repo_path.
- * * description - If set, this will be used to initialize the "description"
- * file in the repository, instead of using the template content.
- * * template_path - When GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE is set,
- * this contains the path to use for the template directory. If
- * this is NULL, the config or default directory options will be
- * used instead.
- * * initial_head - The name of the head to point HEAD at. If NULL, then
- * this will be treated as "master" and the HEAD ref will be set
- * to "refs/heads/master". If this begins with "refs/" it will be
- * used verbatim; otherwise "refs/heads/" will be prefixed.
- * * origin_url - If this is non-NULL, then after the rest of the
- * repository initialization is completed, an "origin" remote
- * will be added pointing to this URL.
+ * additional initialization features.
*/
typedef struct {
unsigned int version;
+
+ /**
+ * Combination of GIT_REPOSITORY_INIT flags above.
+ */
uint32_t flags;
+
+ /**
+ * Set to one of the standard GIT_REPOSITORY_INIT_SHARED_... constants
+ * above, or to a custom value that you would like.
+ */
uint32_t mode;
+
+ /**
+ * The path to the working dir or NULL for default (i.e. repo_path parent
+ * on non-bare repos). IF THIS IS RELATIVE PATH, IT WILL BE EVALUATED
+ * RELATIVE TO THE REPO_PATH. If this is not the "natural" working
+ * directory, a .git gitlink file will be created here linking to the
+ * repo_path.
+ */
const char *workdir_path;
+
+ /**
+ * If set, this will be used to initialize the "description" file in the
+ * repository, instead of using the template content.
+ */
const char *description;
+
+ /**
+ * When GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE is set, this contains
+ * the path to use for the template directory. If this is NULL, the config
+ * or default directory options will be used instead.
+ */
const char *template_path;
+
+ /**
+ * The name of the head to point HEAD at. If NULL, then this will be
+ * treated as "master" and the HEAD ref will be set to "refs/heads/master".
+ * If this begins with "refs/" it will be used verbatim;
+ * otherwise "refs/heads/" will be prefixed.
+ */
const char *initial_head;
+
+ /**
+ * If this is non-NULL, then after the rest of the repository
+ * initialization is completed, an "origin" remote will be added
+ * pointing to this URL.
+ */
const char *origin_url;
} git_repository_init_options;
@@ -720,13 +763,15 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(
*
* @param out Output value of calculated SHA
* @param repo Repository pointer
- * @param path Path to file on disk whose contents should be hashed. If the
- * repository is not NULL, this can be a relative path.
+ * @param path Path to file on disk whose contents should be hashed. This
+ * may be an absolute path or a relative path, in which case it
+ * will be treated as a path within the working directory.
* @param type The object type to hash as (e.g. GIT_OBJECT_BLOB)
* @param as_path The path to use to look up filtering rules. If this is
- * NULL, then the `path` parameter will be used instead. If
- * this is passed as the empty string, then no filters will be
- * applied when calculating the hash.
+ * an empty string then no filters will be applied when
+ * calculating the hash. If this is `NULL` and the `path`
+ * parameter is a file within the repository's working
+ * directory, then the `path` will be used.
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_hashfile(
@@ -755,8 +800,8 @@ GIT_EXTERN(int) git_repository_hashfile(
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_set_head(
- git_repository* repo,
- const char* refname);
+ git_repository *repo,
+ const char *refname);
/**
* Make the repository HEAD directly point to the Commit.
@@ -775,8 +820,8 @@ GIT_EXTERN(int) git_repository_set_head(
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_set_head_detached(
- git_repository* repo,
- const git_oid* commitish);
+ git_repository *repo,
+ const git_oid *commitish);
/**
* Make the repository HEAD directly point to the Commit.
@@ -812,7 +857,7 @@ GIT_EXTERN(int) git_repository_set_head_detached_from_annotated(
* branch or an error code
*/
GIT_EXTERN(int) git_repository_detach_head(
- git_repository* repo);
+ git_repository *repo);
/**
* Repository state
diff --git a/include/git2/revparse.h b/include/git2/revparse.h
index d170e1621..e14ddee96 100644
--- a/include/git2/revparse.h
+++ b/include/git2/revparse.h
@@ -70,12 +70,12 @@ GIT_EXTERN(int) git_revparse_ext(
*/
typedef enum {
/** The spec targeted a single object. */
- GIT_REVPARSE_SINGLE = 1 << 0,
+ GIT_REVSPEC_SINGLE = 1 << 0,
/** The spec targeted a range of commits. */
- GIT_REVPARSE_RANGE = 1 << 1,
+ GIT_REVSPEC_RANGE = 1 << 1,
/** The spec used the '...' operator, which invokes special semantics. */
- GIT_REVPARSE_MERGE_BASE = 1 << 2,
-} git_revparse_mode_t;
+ GIT_REVSPEC_MERGE_BASE = 1 << 2,
+} git_revspec_t;
/**
* Git Revision Spec: output of a `git_revparse` operation
@@ -85,7 +85,7 @@ typedef struct {
git_object *from;
/** The right element of the revspec; must be freed by the user */
git_object *to;
- /** The intent of the revspec (i.e. `git_revparse_mode_t` flags) */
+ /** The intent of the revspec (i.e. `git_revspec_mode_t` flags) */
unsigned int flags;
} git_revspec;
diff --git a/include/git2/stash.h b/include/git2/stash.h
index 625e51b4b..795920ebc 100644
--- a/include/git2/stash.h
+++ b/include/git2/stash.h
@@ -200,7 +200,7 @@ GIT_EXTERN(int) git_stash_apply(
*/
typedef int GIT_CALLBACK(git_stash_cb)(
size_t index,
- const char* message,
+ const char *message,
const git_oid *stash_id,
void *payload);
diff --git a/include/git2/status.h b/include/git2/status.h
index 9693cc478..543e3faa8 100644
--- a/include/git2/status.h
+++ b/include/git2/status.h
@@ -69,89 +69,141 @@ typedef int GIT_CALLBACK(git_status_cb)(
* With `git_status_foreach_ext`, this will control which changes get
* callbacks. With `git_status_list_new`, these will control which
* changes are included in the list.
- *
- * - GIT_STATUS_SHOW_INDEX_AND_WORKDIR is the default. This roughly
- * matches `git status --porcelain` regarding which files are
- * included and in what order.
- * - GIT_STATUS_SHOW_INDEX_ONLY only gives status based on HEAD to index
- * comparison, not looking at working directory changes.
- * - GIT_STATUS_SHOW_WORKDIR_ONLY only gives status based on index to
- * working directory comparison, not comparing the index to the HEAD.
*/
typedef enum {
+ /**
+ * The default. This roughly matches `git status --porcelain` regarding
+ * which files are included and in what order.
+ */
GIT_STATUS_SHOW_INDEX_AND_WORKDIR = 0,
+
+ /**
+ * Only gives status based on HEAD to index comparison, not looking at
+ * working directory changes.
+ */
GIT_STATUS_SHOW_INDEX_ONLY = 1,
+
+ /**
+ * Only gives status based on index to working directory comparison,
+ * not comparing the index to the HEAD.
+ */
GIT_STATUS_SHOW_WORKDIR_ONLY = 2,
} git_status_show_t;
/**
* Flags to control status callbacks
*
- * - GIT_STATUS_OPT_INCLUDE_UNTRACKED says that callbacks should be made
- * on untracked files. These will only be made if the workdir files are
- * included in the status "show" option.
- * - GIT_STATUS_OPT_INCLUDE_IGNORED says that ignored files get callbacks.
- * Again, these callbacks will only be made if the workdir files are
- * included in the status "show" option.
- * - GIT_STATUS_OPT_INCLUDE_UNMODIFIED indicates that callback should be
- * made even on unmodified files.
- * - GIT_STATUS_OPT_EXCLUDE_SUBMODULES indicates that submodules should be
- * skipped. This only applies if there are no pending typechanges to
- * the submodule (either from or to another type).
- * - GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS indicates that all files in
- * untracked directories should be included. Normally if an entire
- * directory is new, then just the top-level directory is included (with
- * a trailing slash on the entry name). This flag says to include all
- * of the individual files in the directory instead.
- * - GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH indicates that the given path
- * should be treated as a literal path, and not as a pathspec pattern.
- * - GIT_STATUS_OPT_RECURSE_IGNORED_DIRS indicates that the contents of
- * ignored directories should be included in the status. This is like
- * doing `git ls-files -o -i --exclude-standard` with core git.
- * - GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX indicates that rename detection
- * should be processed between the head and the index and enables
- * the GIT_STATUS_INDEX_RENAMED as a possible status flag.
- * - GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR indicates that rename
- * detection should be run between the index and the working directory
- * and enabled GIT_STATUS_WT_RENAMED as a possible status flag.
- * - GIT_STATUS_OPT_SORT_CASE_SENSITIVELY overrides the native case
- * sensitivity for the file system and forces the output to be in
- * case-sensitive order
- * - GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY overrides the native case
- * sensitivity for the file system and forces the output to be in
- * case-insensitive order
- * - GIT_STATUS_OPT_RENAMES_FROM_REWRITES indicates that rename detection
- * should include rewritten files
- * - GIT_STATUS_OPT_NO_REFRESH bypasses the default status behavior of
- * doing a "soft" index reload (i.e. reloading the index data if the
- * file on disk has been modified outside libgit2).
- * - GIT_STATUS_OPT_UPDATE_INDEX tells libgit2 to refresh the stat cache
- * in the index for files that are unchanged but have out of date stat
- * information in the index. It will result in less work being done on
- * subsequent calls to get status. This is mutually exclusive with the
- * NO_REFRESH option.
- *
* Calling `git_status_foreach()` is like calling the extended version
* with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED,
* and GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS. Those options are bundled
* together as `GIT_STATUS_OPT_DEFAULTS` if you want them as a baseline.
*/
typedef enum {
+ /**
+ * Says that callbacks should be made on untracked files.
+ * These will only be made if the workdir files are included in the status
+ * "show" option.
+ */
GIT_STATUS_OPT_INCLUDE_UNTRACKED = (1u << 0),
+
+ /**
+ * Says that ignored files get callbacks.
+ * Again, these callbacks will only be made if the workdir files are
+ * included in the status "show" option.
+ */
GIT_STATUS_OPT_INCLUDE_IGNORED = (1u << 1),
+
+ /**
+ * Indicates that callback should be made even on unmodified files.
+ */
GIT_STATUS_OPT_INCLUDE_UNMODIFIED = (1u << 2),
+
+ /**
+ * Indicates that submodules should be skipped.
+ * This only applies if there are no pending typechanges to the submodule
+ * (either from or to another type).
+ */
GIT_STATUS_OPT_EXCLUDE_SUBMODULES = (1u << 3),
+
+ /**
+ * Indicates that all files in untracked directories should be included.
+ * Normally if an entire directory is new, then just the top-level
+ * directory is included (with a trailing slash on the entry name).
+ * This flag says to include all of the individual files in the directory
+ * instead.
+ */
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = (1u << 4),
+
+ /**
+ * Indicates that the given path should be treated as a literal path,
+ * and not as a pathspec pattern.
+ */
GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH = (1u << 5),
+
+ /**
+ * Indicates that the contents of ignored directories should be included
+ * in the status. This is like doing `git ls-files -o -i --exclude-standard`
+ * with core git.
+ */
GIT_STATUS_OPT_RECURSE_IGNORED_DIRS = (1u << 6),
+
+ /**
+ * Indicates that rename detection should be processed between the head and
+ * the index and enables the GIT_STATUS_INDEX_RENAMED as a possible status
+ * flag.
+ */
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX = (1u << 7),
+
+ /**
+ * Indicates that rename detection should be run between the index and the
+ * working directory and enabled GIT_STATUS_WT_RENAMED as a possible status
+ * flag.
+ */
GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR = (1u << 8),
+
+ /**
+ * Overrides the native case sensitivity for the file system and forces
+ * the output to be in case-sensitive order.
+ */
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = (1u << 9),
+
+ /**
+ * Overrides the native case sensitivity for the file system and forces
+ * the output to be in case-insensitive order.
+ */
GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10),
+
+ /**
+ * Iindicates that rename detection should include rewritten files.
+ */
GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11),
+
+ /**
+ * Bypasses the default status behavior of doing a "soft" index reload
+ * (i.e. reloading the index data if the file on disk has been modified
+ * outside libgit2).
+ */
GIT_STATUS_OPT_NO_REFRESH = (1u << 12),
+
+ /**
+ * Tells libgit2 to refresh the stat cache in the index for files that are
+ * unchanged but have out of date stat einformation in the index.
+ * It will result in less work being done on subsequent calls to get status.
+ * This is mutually exclusive with the NO_REFRESH option.
+ */
GIT_STATUS_OPT_UPDATE_INDEX = (1u << 13),
+
+ /**
+ * Normally files that cannot be opened or read are ignored as
+ * these are often transient files; this option will return
+ * unreadable files as `GIT_STATUS_WT_UNREADABLE`.
+ */
GIT_STATUS_OPT_INCLUDE_UNREADABLE = (1u << 14),
+
+ /**
+ * Unreadable files will be detected and given the status
+ * untracked instead of unreadable.
+ */
GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 15),
} git_status_opt_t;
@@ -168,7 +220,10 @@ typedef enum {
*
*/
typedef struct {
- unsigned int version; /**< The version */
+ /**
+ * The struct version; pass `GIT_STATUS_OPTIONS_VERSION`.
+ */
+ unsigned int version;
/**
* The `show` value is one of the `git_status_show_t` constants that
@@ -177,21 +232,22 @@ typedef struct {
git_status_show_t show;
/**
- * The `flags` value is an OR'ed combination of the `git_status_opt_t`
- * values above.
+ * The `flags` value is an OR'ed combination of the
+ * `git_status_opt_t` values above.
*/
unsigned int flags;
/**
* The `pathspec` is an array of path patterns to match (using
- * fnmatch-style matching), or just an array of paths to match exactly if
- * `GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH` is specified in the flags.
+ * fnmatch-style matching), or just an array of paths to match
+ * exactly if `GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH` is specified
+ * in the flags.
*/
git_strarray pathspec;
/**
- * The `baseline` is the tree to be used for comparison to the working directory
- * and index; defaults to HEAD.
+ * The `baseline` is the tree to be used for comparison to the
+ * working directory and index; defaults to HEAD.
*/
git_tree *baseline;
} git_status_options;
diff --git a/include/git2/stdint.h b/include/git2/stdint.h
index c66fbb817..6950427d2 100644
--- a/include/git2/stdint.h
+++ b/include/git2/stdint.h
@@ -29,9 +29,7 @@
//
///////////////////////////////////////////////////////////////////////////////
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
+#ifdef _MSC_VER // [
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
@@ -245,3 +243,5 @@ typedef uint64_t uintmax_t;
#endif // _MSC_STDINT_H_ ]
+
+#endif // _MSC_VER ] \ No newline at end of file
diff --git a/include/git2/submodule.h b/include/git2/submodule.h
index bedd76d6a..29d8bc1ce 100644
--- a/include/git2/submodule.h
+++ b/include/git2/submodule.h
@@ -224,6 +224,15 @@ GIT_EXTERN(int) git_submodule_lookup(
const char *name);
/**
+ * Create an in-memory copy of a submodule. The copy must be explicitly
+ * free'd or it will leak.
+ *
+ * @param out Pointer to store the copy of the submodule.
+ * @param source Original submodule to copy.
+ */
+GIT_EXTERN(int) git_submodule_dup(git_submodule **out, git_submodule *source);
+
+/**
* Release a submodule
*
* @param submodule Submodule object
diff --git a/include/git2/sys/commit_graph.h b/include/git2/sys/commit_graph.h
new file mode 100644
index 000000000..f6c0fc4b5
--- /dev/null
+++ b/include/git2/sys/commit_graph.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_sys_git_commit_graph_h__
+#define INCLUDE_sys_git_commit_graph_h__
+
+#include "git2/common.h"
+#include "git2/types.h"
+
+/**
+ * @file git2/sys/commit_graph.h
+ * @brief Git commit-graph
+ * @defgroup git_commit_graph Git commit-graph APIs
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Opens a `git_commit_graph` from a path to an objects directory.
+ *
+ * This finds, opens, and validates the `commit-graph` file.
+ *
+ * @param cgraph_out the `git_commit_graph` struct to initialize.
+ * @param objects_dir the path to a git objects directory.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_commit_graph_open(git_commit_graph **cgraph_out, const char *objects_dir);
+
+/**
+ * Frees commit-graph data. This should only be called when memory allocated
+ * using `git_commit_graph_open` is not returned to libgit2 because it was not
+ * associated with the ODB through a successful call to
+ * `git_odb_set_commit_graph`.
+ *
+ * @param cgraph the commit-graph object to free. If NULL, no action is taken.
+ */
+GIT_EXTERN(void) git_commit_graph_free(git_commit_graph *cgraph);
+
+/**
+ * Create a new writer for `commit-graph` files.
+ *
+ * @param out Location to store the writer pointer.
+ * @param objects_info_dir The `objects/info` directory.
+ * The `commit-graph` file will be written in this directory.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_commit_graph_writer_new(
+ git_commit_graph_writer **out,
+ const char *objects_info_dir);
+
+/**
+ * Free the commit-graph writer and its resources.
+ *
+ * @param w The writer to free. If NULL no action is taken.
+ */
+GIT_EXTERN(void) git_commit_graph_writer_free(git_commit_graph_writer *w);
+
+/**
+ * Add an `.idx` file (associated to a packfile) to the writer.
+ *
+ * @param w The writer.
+ * @param repo The repository that owns the `.idx` file.
+ * @param idx_path The path of an `.idx` file.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_commit_graph_writer_add_index_file(
+ git_commit_graph_writer *w,
+ git_repository *repo,
+ const char *idx_path);
+
+/**
+ * Add a revwalk to the writer. This will add all the commits from the revwalk
+ * to the commit-graph.
+ *
+ * @param w The writer.
+ * @param walk The git_revwalk.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_commit_graph_writer_add_revwalk(
+ git_commit_graph_writer *w,
+ git_revwalk *walk);
+
+
+/**
+ * The strategy to use when adding a new set of commits to a pre-existing
+ * commit-graph chain.
+ */
+typedef enum {
+ /**
+ * Do not split commit-graph files. The other split strategy-related option
+ * fields are ignored.
+ */
+ GIT_COMMIT_GRAPH_SPLIT_STRATEGY_SINGLE_FILE = 0,
+} git_commit_graph_split_strategy_t;
+
+/**
+ * Options structure for
+ * `git_commit_graph_writer_commit`/`git_commit_graph_writer_dump`.
+ *
+ * Initialize with `GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT`. Alternatively, you
+ * can use `git_commit_graph_writer_options_init`.
+ */
+typedef struct {
+ unsigned int version;
+
+ /**
+ * The strategy to use when adding new commits to a pre-existing commit-graph
+ * chain.
+ */
+ git_commit_graph_split_strategy_t split_strategy;
+
+ /**
+ * The number of commits in level N is less than X times the number of
+ * commits in level N + 1. Default is 2.
+ */
+ float size_multiple;
+
+ /**
+ * The number of commits in level N + 1 is more than C commits.
+ * Default is 64000.
+ */
+ size_t max_commits;
+} git_commit_graph_writer_options;
+
+#define GIT_COMMIT_GRAPH_WRITER_OPTIONS_VERSION 1
+#define GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT { \
+ GIT_COMMIT_GRAPH_WRITER_OPTIONS_VERSION \
+ }
+
+/**
+ * Initialize git_commit_graph_writer_options structure
+ *
+ * Initializes a `git_commit_graph_writer_options` with default values. Equivalent to
+ * creating an instance with `GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT`.
+ *
+ * @param opts The `git_commit_graph_writer_options` struct to initialize.
+ * @param version The struct version; pass `GIT_COMMIT_GRAPH_WRITER_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_commit_graph_writer_options_init(
+ git_commit_graph_writer_options *opts,
+ unsigned int version);
+
+/**
+ * Write a `commit-graph` file to a file.
+ *
+ * @param w The writer
+ * @param opts Pointer to git_commit_graph_writer_options struct.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_commit_graph_writer_commit(
+ git_commit_graph_writer *w,
+ git_commit_graph_writer_options *opts);
+
+/**
+ * Dump the contents of the `commit-graph` to an in-memory buffer.
+ *
+ * @param buffer Buffer where to store the contents of the `commit-graph`.
+ * @param w The writer.
+ * @param opts Pointer to git_commit_graph_writer_options struct.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_commit_graph_writer_dump(
+ git_buf *buffer,
+ git_commit_graph_writer *w,
+ git_commit_graph_writer_options *opts);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/include/git2/sys/email.h b/include/git2/sys/email.h
new file mode 100644
index 000000000..6f4a28662
--- /dev/null
+++ b/include/git2/sys/email.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_sys_git_email_h__
+#define INCLUDE_sys_git_email_h__
+
+/**
+ * @file git2/sys/email.h
+ * @brief Advanced git email creation routines
+ * @defgroup git_email Advanced git email creation routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Create a diff for a commit in mbox format for sending via email.
+ *
+ * @param out buffer to store the e-mail patch in
+ * @param diff the changes to include in the email
+ * @param patch_idx the patch index
+ * @param patch_count the total number of patches that will be included
+ * @param commit_id the commit id for this change
+ * @param summary the commit message for this change
+ * @param body optional text to include above the diffstat
+ * @param author the person who authored this commit
+ * @param opts email creation options
+ */
+GIT_EXTERN(int) git_email_create_from_diff(
+ git_buf *out,
+ git_diff *diff,
+ size_t patch_idx,
+ size_t patch_count,
+ const git_oid *commit_id,
+ const char *summary,
+ const char *body,
+ const git_signature *author,
+ const git_email_create_options *opts);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h
index e43fde55c..b3759416a 100644
--- a/include/git2/sys/filter.h
+++ b/include/git2/sys/filter.h
@@ -167,17 +167,18 @@ typedef void GIT_CALLBACK(git_filter_shutdown_fn)(git_filter *self);
*
* The `payload` will be a pointer to a reference payload for the filter.
* This will start as NULL, but `check` can assign to this pointer for
- * later use by the `apply` callback. Note that the value should be heap
- * allocated (not stack), so that it doesn't go away before the `apply`
+ * later use by the `stream` callback. Note that the value should be heap
+ * allocated (not stack), so that it doesn't go away before the `stream`
* callback can use it. If a filter allocates and assigns a value to the
* `payload`, it will need a `cleanup` callback to free the payload.
*/
typedef int GIT_CALLBACK(git_filter_check_fn)(
- git_filter *self,
- void **payload, /* points to NULL ptr on entry, may be set */
+ git_filter *self,
+ void **payload, /* NULL on entry, may be set */
const git_filter_source *src,
- const char **attr_values);
+ const char **attr_values);
+#ifndef GIT_DEPRECATE_HARD
/**
* Callback to actually perform the data filtering
*
@@ -189,32 +190,45 @@ typedef int GIT_CALLBACK(git_filter_check_fn)(
*
* The `payload` value will refer to any payload that was set by the
* `check` callback. It may be read from or written to as needed.
+ *
+ * @deprecated use git_filter_stream_fn
*/
typedef int GIT_CALLBACK(git_filter_apply_fn)(
- git_filter *self,
- void **payload, /* may be read and/or set */
- git_buf *to,
- const git_buf *from,
+ git_filter *self,
+ void **payload, /* may be read and/or set */
+ git_buf *to,
+ const git_buf *from,
const git_filter_source *src);
+#endif
+/**
+ * Callback to perform the data filtering.
+ *
+ * Specified as `filter.stream`, this is a callback that filters data
+ * in a streaming manner. This function will provide a
+ * `git_writestream` that will the original data will be written to;
+ * with that data, the `git_writestream` will then perform the filter
+ * translation and stream the filtered data out to the `next` location.
+ */
typedef int GIT_CALLBACK(git_filter_stream_fn)(
- git_writestream **out,
- git_filter *self,
- void **payload,
+ git_writestream **out,
+ git_filter *self,
+ void **payload,
const git_filter_source *src,
- git_writestream *next);
+ git_writestream *next);
/**
* Callback to clean up after filtering has been applied
*
* Specified as `filter.cleanup`, this is an optional callback invoked
- * after the filter has been applied. If the `check` or `apply` callbacks
- * allocated a `payload` to keep per-source filter state, use this
- * callback to free that payload and release resources as required.
+ * after the filter has been applied. If the `check`, `apply`, or
+ * `stream` callbacks allocated a `payload` to keep per-source filter
+ * state, use this callback to free that payload and release resources
+ * as required.
*/
typedef void GIT_CALLBACK(git_filter_cleanup_fn)(
- git_filter *self,
- void *payload);
+ git_filter *self,
+ void *payload);
/**
* Filter structure used to register custom filters.
@@ -248,21 +262,28 @@ struct git_filter {
/**
* Called to determine whether the filter should be invoked for a
* given file. If this function returns `GIT_PASSTHROUGH` then the
- * `apply` function will not be invoked and the contents will be passed
- * through unmodified.
+ * `stream` or `apply` functions will not be invoked and the
+ * contents will be passed through unmodified.
*/
git_filter_check_fn check;
+#ifdef GIT_DEPRECATE_HARD
+ void *reserved;
+#else
/**
- * Called to actually apply the filter to file contents. If this
- * function returns `GIT_PASSTHROUGH` then the contents will be passed
- * through unmodified.
+ * Provided for backward compatibility; this will apply the
+ * filter to the given contents in a `git_buf`. Callers should
+ * provide a `stream` function instead.
*/
git_filter_apply_fn apply;
+#endif
/**
- * Called to apply the filter in a streaming manner. If this is not
- * specified then the system will call `apply` with the whole buffer.
+ * Called to apply the filter, this function will provide a
+ * `git_writestream` that will the original data will be
+ * written to; with that data, the `git_writestream` will then
+ * perform the filter translation and stream the filtered data
+ * out to the `next` location.
*/
git_filter_stream_fn stream;
@@ -289,9 +310,9 @@ GIT_EXTERN(int) git_filter_init(git_filter *filter, unsigned int version);
* As mentioned elsewhere, the initialize callback will not be invoked
* immediately. It is deferred until the filter is used in some way.
*
- * A filter's attribute checks and `check` and `apply` callbacks will be
- * issued in order of `priority` on smudge (to workdir), and in reverse
- * order of `priority` on clean (to odb).
+ * A filter's attribute checks and `check` and `stream` (or `apply`)
+ * callbacks will be issued in order of `priority` on smudge (to
+ * workdir), and in reverse order of `priority` on clean (to odb).
*
* Two filters are preregistered with libgit2:
* - GIT_FILTER_CRLF with priority 0
diff --git a/include/git2/sys/midx.h b/include/git2/sys/midx.h
new file mode 100644
index 000000000..e3d749829
--- /dev/null
+++ b/include/git2/sys/midx.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_sys_git_midx_h__
+#define INCLUDE_sys_git_midx_h__
+
+#include "git2/common.h"
+#include "git2/types.h"
+
+/**
+ * @file git2/midx.h
+ * @brief Git multi-pack-index routines
+ * @defgroup git_midx Git multi-pack-index routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Create a new writer for `multi-pack-index` files.
+ *
+ * @param out location to store the writer pointer.
+ * @param pack_dir the directory where the `.pack` and `.idx` files are. The
+ * `multi-pack-index` file will be written in this directory, too.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_midx_writer_new(
+ git_midx_writer **out,
+ const char *pack_dir);
+
+/**
+ * Free the multi-pack-index writer and its resources.
+ *
+ * @param w the writer to free. If NULL no action is taken.
+ */
+GIT_EXTERN(void) git_midx_writer_free(git_midx_writer *w);
+
+/**
+ * Add an `.idx` file to the writer.
+ *
+ * @param w the writer
+ * @param idx_path the path of an `.idx` file.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_midx_writer_add(
+ git_midx_writer *w,
+ const char *idx_path);
+
+/**
+ * Write a `multi-pack-index` file to a file.
+ *
+ * @param w the writer
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_midx_writer_commit(
+ git_midx_writer *w);
+
+/**
+ * Dump the contents of the `multi-pack-index` to an in-memory buffer.
+ *
+ * @param midx Buffer where to store the contents of the `multi-pack-index`.
+ * @param w the writer
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_midx_writer_dump(
+ git_buf *midx,
+ git_midx_writer *w);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/include/git2/sys/odb_backend.h b/include/git2/sys/odb_backend.h
index 4dba460af..9ae0ed9b3 100644
--- a/include/git2/sys/odb_backend.h
+++ b/include/git2/sys/odb_backend.h
@@ -85,6 +85,13 @@ struct git_odb_backend {
git_indexer_progress_cb progress_cb, void *progress_payload);
/**
+ * If the backend supports pack files, this will create a
+ * `multi-pack-index` file which will contain an index of all objects
+ * across all the `.pack` files.
+ */
+ int GIT_CALLBACK(writemidx)(git_odb_backend *);
+
+ /**
* "Freshens" an already existing object, updating its last-used
* time. This occurs when `git_odb_write` was called, but the
* object already existed (and will not be re-written). The
diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h
index 6cee42f54..fee34544f 100644
--- a/include/git2/sys/transport.h
+++ b/include/git2/sys/transport.h
@@ -9,6 +9,7 @@
#define INCLUDE_sys_git_transport_h
#include "git2/net.h"
+#include "git2/transport.h"
#include "git2/types.h"
#include "git2/strarray.h"
#include "git2/proxy.h"
diff --git a/include/git2/tag.h b/include/git2/tag.h
index 4e5fe1db1..a3921369d 100644
--- a/include/git2/tag.h
+++ b/include/git2/tag.h
@@ -365,6 +365,18 @@ GIT_EXTERN(int) git_tag_peel(
*/
GIT_EXTERN(int) git_tag_dup(git_tag **out, git_tag *source);
+/**
+ * Determine whether a tag name is valid, meaning that (when prefixed
+ * with `refs/tags/`) that it is a valid reference name, and that any
+ * additional tag name restrictions are imposed (eg, it cannot start
+ * with a `-`).
+ *
+ * @param valid output pointer to set with validity of given tag name
+ * @param name a tag name to test
+ * @return 0 on success or an error code
+ */
+GIT_EXTERN(int) git_tag_name_is_valid(int *valid, const char *name);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/transport.h b/include/git2/transport.h
index fc99ce8f3..5a27de9a8 100644
--- a/include/git2/transport.h
+++ b/include/git2/transport.h
@@ -23,7 +23,7 @@
GIT_BEGIN_DECL
/**
- * Callback for messages recieved by the transport.
+ * Callback for messages received by the transport.
*
* Return a negative value to cancel the network operation.
*
diff --git a/include/git2/tree.h b/include/git2/tree.h
index 1a8e155fc..f2289fc7e 100644
--- a/include/git2/tree.h
+++ b/include/git2/tree.h
@@ -334,6 +334,7 @@ GIT_EXTERN(int) git_treebuilder_insert(
*
* @param bld Tree builder
* @param filename Filename of the entry to remove
+ * @return 0 or an error code
*/
GIT_EXTERN(int) git_treebuilder_remove(
git_treebuilder *bld, const char *filename);
@@ -378,20 +379,6 @@ GIT_EXTERN(int) git_treebuilder_filter(
GIT_EXTERN(int) git_treebuilder_write(
git_oid *id, git_treebuilder *bld);
-/**
- * Write the contents of the tree builder as a tree object
- * using a shared git_buf.
- *
- * @see git_treebuilder_write
- *
- * @param oid Pointer to store the OID of the newly written tree
- * @param bld Tree builder to write
- * @param tree Shared buffer for writing the tree. Will be grown as necessary.
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_treebuilder_write_with_buffer(
- git_oid *oid, git_treebuilder *bld, git_buf *tree);
-
/** Callback for the tree traversal method */
typedef int GIT_CALLBACK(git_treewalk_cb)(
const char *root, const git_tree_entry *entry, void *payload);
@@ -477,6 +464,7 @@ typedef struct {
* @param baseline the tree to base these changes on
* @param nupdates the number of elements in the update list
* @param updates the list of updates to perform
+ * @return 0 or an error code
*/
GIT_EXTERN(int) git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseline, size_t nupdates, const git_tree_update *updates);
diff --git a/include/git2/types.h b/include/git2/types.h
index ade0c7d32..aac8e42e2 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -96,12 +96,21 @@ typedef struct git_odb_stream git_odb_stream;
/** A stream to write a packfile to the ODB */
typedef struct git_odb_writepack git_odb_writepack;
+/** a writer for multi-pack-index files. */
+typedef struct git_midx_writer git_midx_writer;
+
/** An open refs database handle. */
typedef struct git_refdb git_refdb;
/** A custom backend for refs */
typedef struct git_refdb_backend git_refdb_backend;
+/** A git commit-graph */
+typedef struct git_commit_graph git_commit_graph;
+
+/** a writer for commit-graph files. */
+typedef struct git_commit_graph_writer git_commit_graph_writer;
+
/**
* Representation of an existing git repository,
* including all its object contents
diff --git a/include/git2/version.h b/include/git2/version.h
index b078e1ea2..3503a6278 100644
--- a/include/git2/version.h
+++ b/include/git2/version.h
@@ -7,12 +7,12 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
-#define LIBGIT2_VERSION "1.0.0"
+#define LIBGIT2_VERSION "1.3.0"
#define LIBGIT2_VER_MAJOR 1
-#define LIBGIT2_VER_MINOR 0
+#define LIBGIT2_VER_MINOR 3
#define LIBGIT2_VER_REVISION 0
#define LIBGIT2_VER_PATCH 0
-#define LIBGIT2_SOVERSION "1.0"
+#define LIBGIT2_SOVERSION "1.3"
#endif
diff --git a/include/git2/worktree.h b/include/git2/worktree.h
index 049511da1..23084d8cd 100644
--- a/include/git2/worktree.h
+++ b/include/git2/worktree.h
@@ -198,6 +198,7 @@ typedef enum {
typedef struct git_worktree_prune_options {
unsigned int version;
+ /** A combination of `git_worktree_prune_t` */
uint32_t flags;
} git_worktree_prune_options;
diff --git a/package.json b/package.json
index b4995b18f..e2e672f9f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "libgit2",
- "version": "1.0.0",
+ "version": "1.3.0",
"repo": "https://github.com/libgit2/libgit2",
"description": " A cross-platform, linkable library implementation of Git that you can use in your application.",
"install": "mkdir build && cd build && cmake .. && cmake --build ."
diff --git a/script/release.py b/script/release.py
index 99ff8ecaf..1a240deca 100755
--- a/script/release.py
+++ b/script/release.py
@@ -40,6 +40,15 @@ def verify_version(version):
'SOVERSION': [ '"{}.{}"'.format(version.major, version.minor), None ],
}
+ # Parse CMakeLists
+ with open('CMakeLists.txt') as f:
+ for line in f.readlines():
+ if line.startswith('project(libgit2 VERSION "{}"'.format(version)):
+ break
+ else:
+ raise Error("cmake: invalid project definition")
+
+ # Parse version.h
with open('include/git2/version.h') as f:
lines = f.readlines()
diff --git a/script/sanitizers.supp b/script/sanitizers.supp
new file mode 100644
index 000000000..4e0e9be83
--- /dev/null
+++ b/script/sanitizers.supp
@@ -0,0 +1,4 @@
+[undefined]
+# This library allows unaligned access on Intel-like processors. Prevent UBSan
+# from complaining about that.
+fun:sha1_compression_states
diff --git a/script/thread-sanitizer.supp b/script/thread-sanitizer.supp
new file mode 100644
index 000000000..97d23046f
--- /dev/null
+++ b/script/thread-sanitizer.supp
@@ -0,0 +1,26 @@
+# In attr_file_free, the locks are acquired in the opposite order in which they
+# are normally acquired. This is probably something worth fixing to have a
+# consistent lock hierarchy that is easy to understand.
+deadlock:attr_cache_lock
+
+# git_mwindow_file_register has the possibility of evicting some files from the
+# global cache. In order to avoid races and closing files that are currently
+# being accessed, before evicting any file it will attempt to acquire that
+# file's lock. Finally, git_mwindow_file_register is typically called with a
+# file lock held, because the caller will use the fd in the mwf immediately
+# after registering it. This causes ThreadSanitizer to observe different orders
+# of acquisition of the mutex (which implies a possibility of a deadlock),
+# _but_ since the files are added to the cache after other files have been
+# evicted, there cannot be a case where mwf A is trying to be registered while
+# evicting mwf B concurrently and viceversa: at most one of them can be present
+# in the cache.
+deadlock:git_mwindow_file_register
+
+# When invoking the time/timezone functions from git_signature_now(), they
+# access libc methods that need to be instrumented to correctly analyze the
+# data races.
+called_from_lib:libc.so.6
+
+# TODO(#5592): Investigate and fix this. It can be triggered by the `thread`
+# test suite.
+race:git_filter_list__load_ext
diff --git a/script/valgrind.supp b/script/valgrind.supp
index d938aa9c9..8c4549f62 100644
--- a/script/valgrind.supp
+++ b/script/valgrind.supp
@@ -42,6 +42,38 @@
}
{
+ ignore-openssl-init-leak
+ Memcheck:Leak
+ ...
+ fun:git_openssl_stream_global_init
+ ...
+}
+
+{
+ ignore-openssl-legacy-init-leak
+ Memcheck:Leak
+ ...
+ fun:OPENSSL_init_ssl__legacy
+ ...
+}
+
+{
+ ignore-openssl-malloc-leak
+ Memcheck:Leak
+ ...
+ fun:git_openssl_malloc
+ ...
+}
+
+{
+ ignore-openssl-realloc-leak
+ Memcheck:Leak
+ ...
+ fun:git_openssl_realloc
+ ...
+}
+
+{
ignore-glibc-getaddrinfo-cache
Memcheck:Leak
...
@@ -65,6 +97,22 @@
}
{
+ ignore-libssh2-session-create
+ Memcheck:Leak
+ ...
+ fun:_git_ssh_session_create
+ ...
+}
+
+{
+ ignore-libssh2-setup-conn
+ Memcheck:Leak
+ ...
+ fun:_git_ssh_setup_conn
+ ...
+}
+
+{
ignore-libssh2-gcrypt-control-leak
Memcheck:Leak
...
@@ -178,3 +226,19 @@
obj:*libcrypto.so*
...
}
+
+{
+ ignore-dlopen-leak
+ Memcheck:Leak
+ ...
+ fun:dlopen
+ ...
+}
+
+{
+ ignore-dlopen-leak
+ Memcheck:Leak
+ ...
+ fun:_dlerror_run
+ ...
+}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 481707c7a..fdb367335 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,9 +1,23 @@
+add_library(git2internal OBJECT)
+set_target_properties(git2internal PROPERTIES C_STANDARD 90)
+
IF(DEBUG_POOL)
SET(GIT_DEBUG_POOL 1)
ENDIF()
ADD_FEATURE_INFO(debugpool GIT_DEBUG_POOL "debug pool allocator")
+IF(DEBUG_STRICT_ALLOC)
+ SET(GIT_DEBUG_STRICT_ALLOC 1)
+ENDIF()
+ADD_FEATURE_INFO(debugalloc GIT_DEBUG_STRICT_ALLOC "debug strict allocators")
+
+IF(DEBUG_STRICT_OPEN)
+ SET(GIT_DEBUG_STRICT_OPEN 1)
+ENDIF()
+ADD_FEATURE_INFO(debugopen GIT_DEBUG_STRICT_OPEN "path validation in open")
+
INCLUDE(PkgBuildConfig)
+INCLUDE(SanitizeBool)
# This variable will contain the libraries we need to put into
# libgit2.pc's Requires.private. That is, what we're linking to or
@@ -29,28 +43,28 @@ IF(ENABLE_TRACE)
ENDIF()
ADD_FEATURE_INFO(tracing GIT_TRACE "tracing support")
-CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS)
IF (HAVE_FUTIMENS)
SET(GIT_USE_FUTIMENS 1)
ENDIF ()
+ADD_FEATURE_INFO(futimens GIT_USE_FUTIMENS "futimens support")
CHECK_PROTOTYPE_DEFINITION(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
"" "stdlib.h" HAVE_QSORT_R_BSD)
IF (HAVE_QSORT_R_BSD)
- ADD_DEFINITIONS(-DHAVE_QSORT_R_BSD)
+ target_compile_definitions(git2internal PRIVATE HAVE_QSORT_R_BSD)
ENDIF()
CHECK_PROTOTYPE_DEFINITION(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg)"
"" "stdlib.h" HAVE_QSORT_R_GNU)
IF (HAVE_QSORT_R_GNU)
- ADD_DEFINITIONS(-DHAVE_QSORT_R_GNU)
+ target_compile_definitions(git2internal PRIVATE HAVE_QSORT_R_GNU)
ENDIF()
CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S)
IF (HAVE_QSORT_S)
- ADD_DEFINITIONS(-DHAVE_QSORT_S)
+ target_compile_definitions(git2internal PRIVATE HAVE_QSORT_S)
ENDIF ()
# Find required dependencies
@@ -81,6 +95,8 @@ ADD_FEATURE_INFO(threadsafe THREADSAFE "threadsafe support")
if(WIN32 AND EMBED_SSH_PATH)
file(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
list(SORT SRC_SSH)
+ target_sources(git2internal PRIVATE ${SRC_SSH})
+
list(APPEND LIBGIT2_SYSTEM_INCLUDES "${EMBED_SSH_PATH}/include")
file(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"")
set(GIT_SSH 1)
@@ -104,8 +120,9 @@ IF (WIN32 AND WINHTTP)
LIST(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32")
ENDIF()
-Include(SelectHTTPSBackend)
-Include(SelectHashes)
+include(SelectHTTPSBackend)
+include(SelectHashes)
+target_sources(git2internal PRIVATE ${SRC_SHA1})
# Specify regular expression implementation
FIND_PACKAGE(PCRE)
@@ -180,7 +197,12 @@ ELSE()
ENDIF()
# Optional external dependency: zlib
-IF(NOT USE_BUNDLED_ZLIB)
+SanitizeBool(USE_BUNDLED_ZLIB)
+IF(USE_BUNDLED_ZLIB STREQUAL ON)
+ SET(USE_BUNDLED_ZLIB "Bundled")
+ENDIF()
+
+IF(USE_BUNDLED_ZLIB STREQUAL "OFF")
FIND_PACKAGE(ZLIB)
IF(ZLIB_FOUND)
LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${ZLIB_INCLUDE_DIRS})
@@ -195,7 +217,12 @@ IF(NOT USE_BUNDLED_ZLIB)
MESSAGE(STATUS "zlib was not found; using bundled 3rd-party sources." )
ENDIF()
ENDIF()
-IF(USE_BUNDLED_ZLIB OR NOT ZLIB_FOUND)
+IF(USE_BUNDLED_ZLIB STREQUAL "Chromium")
+ ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/chromium-zlib" "${libgit2_BINARY_DIR}/deps/chromium-zlib")
+ LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/chromium-zlib")
+ LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:chromium_zlib>)
+ ADD_FEATURE_INFO(zlib ON "using (Chromium) bundled zlib")
+ELSEIF(USE_BUNDLED_ZLIB OR NOT ZLIB_FOUND)
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/zlib" "${libgit2_BINARY_DIR}/deps/zlib")
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/zlib")
LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:zlib>)
@@ -205,6 +232,13 @@ ENDIF()
# Optional external dependency: libssh2
IF (USE_SSH)
FIND_PKGLIBRARIES(LIBSSH2 libssh2)
+ IF (NOT LIBSSH2_FOUND)
+ FIND_PACKAGE(LibSSH2)
+ SET(LIBSSH2_INCLUDE_DIRS ${LIBSSH2_INCLUDE_DIR})
+ GET_FILENAME_COMPONENT(LIBSSH2_LIBRARY_DIRS "${LIBSSH2_LIBRARY}" DIRECTORY)
+ SET(LIBSSH2_LIBRARIES ${LIBSSH2_LIBRARY})
+ SET(LIBSSH2_LDFLAGS "-lssh2")
+ ENDIF()
ENDIF()
IF (LIBSSH2_FOUND)
SET(GIT_SSH 1)
@@ -267,7 +301,7 @@ ELSEIF (HAVE_STRUCT_STAT_ST_MTIME_NSEC)
SET(GIT_USE_STAT_MTIME_NSEC 1)
ENDIF()
-ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
+target_compile_definitions(git2internal PRIVATE _FILE_OFFSET_BITS=64)
# Collect sourcefiles
file(GLOB SRC_H
@@ -275,24 +309,25 @@ file(GLOB SRC_H
"${libgit2_SOURCE_DIR}/include/git2/*.h"
"${libgit2_SOURCE_DIR}/include/git2/sys/*.h")
list(SORT SRC_H)
+target_sources(git2internal PRIVATE ${SRC_H})
# On Windows use specific platform sources
if(WIN32 AND NOT CYGWIN)
- if(MSVC)
- SET(WIN_RC "win32/git2.rc")
- endif()
+ SET(WIN_RC "win32/git2.rc")
file(GLOB SRC_OS win32/*.c win32/*.h)
list(SORT SRC_OS)
+ target_sources(git2internal PRIVATE ${SRC_OS})
elseif(AMIGA)
- add_definitions(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
+ target_compile_definitions(git2internal PRIVATE NO_ADDRINFO NO_READDIR_R NO_MMAP)
else()
file(GLOB SRC_OS unix/*.c unix/*.h)
list(SORT SRC_OS)
+ target_sources(git2internal PRIVATE ${SRC_OS})
endif()
IF (USE_LEAK_CHECKER STREQUAL "valgrind")
- ADD_DEFINITIONS(-DVALGRIND)
+ target_compile_definitions(git2internal PRIVATE VALGRIND)
ENDIF()
file(GLOB SRC_GIT2 *.c *.h
@@ -301,6 +336,7 @@ file(GLOB SRC_GIT2 *.c *.h
transports/*.c transports/*.h
xdiff/*.c xdiff/*.h)
list(SORT SRC_GIT2)
+target_sources(git2internal PRIVATE ${SRC_GIT2})
IF(APPLE)
# The old Secure Transport API has been deprecated in macOS 10.15.
@@ -327,10 +363,6 @@ ENDIF()
CONFIGURE_FILE(features.h.in git2/sys/features.h)
-SET(LIBGIT2_SOURCES ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_SSH} ${SRC_SHA1})
-
-ADD_LIBRARY(git2internal OBJECT ${LIBGIT2_SOURCES})
-SET_TARGET_PROPERTIES(git2internal PROPERTIES C_STANDARD 90)
IDE_SPLIT_SOURCES(git2internal)
LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:git2internal>)
@@ -366,19 +398,19 @@ ENDIF()
IDE_SPLIT_SOURCES(git2)
-IF (SONAME)
- SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
- SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_SOVERSION})
- IF (LIBGIT2_FILENAME)
- ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
- SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
- ELSEIF (DEFINED LIBGIT2_PREFIX)
- SET_TARGET_PROPERTIES(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
- ENDIF()
-ENDIF()
+if(SONAME)
+ set_target_properties(git2 PROPERTIES VERSION ${libgit2_VERSION})
+ set_target_properties(git2 PROPERTIES SOVERSION "${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}")
+ if(LIBGIT2_FILENAME)
+ target_compile_definitions(git2 PRIVATE LIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
+ set_target_properties(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
+ elseif(DEFINED LIBGIT2_PREFIX)
+ set_target_properties(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
+ endif()
+endif()
PKG_BUILD_CONFIG(NAME libgit2
- VERSION ${LIBGIT2_VERSION_STRING}
+ VERSION ${libgit2_VERSION}
DESCRIPTION "The git library, take 2"
LIBS_SELF git2
PRIVATE_LIBS ${LIBGIT2_PC_LIBS}
diff --git a/src/alloc.c b/src/alloc.c
index 51c4d8029..2820d84a2 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6,16 +6,29 @@
*/
#include "alloc.h"
+#include "runtime.h"
+#include "allocators/failalloc.h"
#include "allocators/stdalloc.h"
-#include "allocators/win32_crtdbg.h"
-
-git_allocator git__allocator;
+#include "allocators/win32_leakcheck.h"
+
+/* Fail any allocation until git_libgit2_init is called. */
+git_allocator git__allocator = {
+ git_failalloc_malloc,
+ git_failalloc_calloc,
+ git_failalloc_strdup,
+ git_failalloc_strndup,
+ git_failalloc_substrdup,
+ git_failalloc_realloc,
+ git_failalloc_reallocarray,
+ git_failalloc_mallocarray,
+ git_failalloc_free
+};
static int setup_default_allocator(void)
{
-#if defined(GIT_MSVC_CRTDBG)
- return git_win32_crtdbg_init_allocator(&git__allocator);
+#if defined(GIT_WIN32_LEAKCHECK)
+ return git_win32_leakcheck_init_allocator(&git__allocator);
#else
return git_stdalloc_init_allocator(&git__allocator);
#endif
@@ -24,10 +37,10 @@ static int setup_default_allocator(void)
int git_allocator_global_init(void)
{
/*
- * We don't want to overwrite any allocator which has been set before
- * the init function is called.
+ * We don't want to overwrite any allocator which has been set
+ * before the init function is called.
*/
- if (git__allocator.gmalloc != NULL)
+ if (git__allocator.gmalloc != git_failalloc_malloc)
return 0;
return setup_default_allocator();
diff --git a/src/allocators/failalloc.c b/src/allocators/failalloc.c
new file mode 100644
index 000000000..5257d1dec
--- /dev/null
+++ b/src/allocators/failalloc.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "failalloc.h"
+
+void *git_failalloc_malloc(size_t len, const char *file, int line)
+{
+ GIT_UNUSED(len);
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ return NULL;
+}
+
+void *git_failalloc_calloc(size_t nelem, size_t elsize, const char *file, int line)
+{
+ GIT_UNUSED(nelem);
+ GIT_UNUSED(elsize);
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ return NULL;
+}
+
+char *git_failalloc_strdup(const char *str, const char *file, int line)
+{
+ GIT_UNUSED(str);
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ return NULL;
+}
+
+char *git_failalloc_strndup(const char *str, size_t n, const char *file, int line)
+{
+ GIT_UNUSED(str);
+ GIT_UNUSED(n);
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ return NULL;
+}
+
+char *git_failalloc_substrdup(const char *start, size_t n, const char *file, int line)
+{
+ GIT_UNUSED(start);
+ GIT_UNUSED(n);
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ return NULL;
+}
+
+void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line)
+{
+ GIT_UNUSED(ptr);
+ GIT_UNUSED(size);
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ return NULL;
+}
+
+void *git_failalloc_reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
+{
+ GIT_UNUSED(ptr);
+ GIT_UNUSED(nelem);
+ GIT_UNUSED(elsize);
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ return NULL;
+}
+
+void *git_failalloc_mallocarray(size_t nelem, size_t elsize, const char *file, int line)
+{
+ GIT_UNUSED(nelem);
+ GIT_UNUSED(elsize);
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ return NULL;
+}
+
+void git_failalloc_free(void *ptr)
+{
+ GIT_UNUSED(ptr);
+}
diff --git a/src/allocators/failalloc.h b/src/allocators/failalloc.h
new file mode 100644
index 000000000..6115e51e7
--- /dev/null
+++ b/src/allocators/failalloc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#ifndef INCLUDE_allocators_failalloc_h__
+#define INCLUDE_allocators_failalloc_h__
+
+#include "common.h"
+
+extern void *git_failalloc_malloc(size_t len, const char *file, int line);
+extern void *git_failalloc_calloc(size_t nelem, size_t elsize, const char *file, int line);
+extern char *git_failalloc_strdup(const char *str, const char *file, int line);
+extern char *git_failalloc_strndup(const char *str, size_t n, const char *file, int line);
+extern char *git_failalloc_substrdup(const char *start, size_t n, const char *file, int line);
+extern void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line);
+extern void *git_failalloc_reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line);
+extern void *git_failalloc_mallocarray(size_t nelem, size_t elsize, const char *file, int line);
+extern void git_failalloc_free(void *ptr);
+
+#endif
diff --git a/src/allocators/stdalloc.c b/src/allocators/stdalloc.c
index c4938e32b..2b36d9f3d 100644
--- a/src/allocators/stdalloc.c
+++ b/src/allocators/stdalloc.c
@@ -9,34 +9,56 @@
static void *stdalloc__malloc(size_t len, const char *file, int line)
{
- void *ptr = malloc(len);
+ void *ptr;
GIT_UNUSED(file);
GIT_UNUSED(line);
- if (!ptr) git_error_set_oom();
+#ifdef GIT_DEBUG_STRICT_ALLOC
+ if (!len)
+ return NULL;
+#endif
+
+ ptr = malloc(len);
+
+ if (!ptr)
+ git_error_set_oom();
+
return ptr;
}
static void *stdalloc__calloc(size_t nelem, size_t elsize, const char *file, int line)
{
- void *ptr = calloc(nelem, elsize);
+ void *ptr;
GIT_UNUSED(file);
GIT_UNUSED(line);
- if (!ptr) git_error_set_oom();
+#ifdef GIT_DEBUG_STRICT_ALLOC
+ if (!elsize || !nelem)
+ return NULL;
+#endif
+
+ ptr = calloc(nelem, elsize);
+
+ if (!ptr)
+ git_error_set_oom();
+
return ptr;
}
static char *stdalloc__strdup(const char *str, const char *file, int line)
{
- char *ptr = strdup(str);
+ char *ptr;
GIT_UNUSED(file);
GIT_UNUSED(line);
- if (!ptr) git_error_set_oom();
+ ptr = strdup(str);
+
+ if (!ptr)
+ git_error_set_oom();
+
return ptr;
}
@@ -48,7 +70,7 @@ static char *stdalloc__strndup(const char *str, size_t n, const char *file, int
length = p_strnlen(str, n);
if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
- !(ptr = stdalloc__malloc(alloclength, file, line)))
+ !(ptr = stdalloc__malloc(alloclength, file, line)))
return NULL;
if (length)
@@ -65,7 +87,7 @@ static char *stdalloc__substrdup(const char *start, size_t n, const char *file,
size_t alloclen;
if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
- !(ptr = stdalloc__malloc(alloclen, file, line)))
+ !(ptr = stdalloc__malloc(alloclen, file, line)))
return NULL;
memcpy(ptr, start, n);
@@ -75,12 +97,21 @@ static char *stdalloc__substrdup(const char *start, size_t n, const char *file,
static void *stdalloc__realloc(void *ptr, size_t size, const char *file, int line)
{
- void *new_ptr = realloc(ptr, size);
+ void *new_ptr;
GIT_UNUSED(file);
GIT_UNUSED(line);
- if (!new_ptr) git_error_set_oom();
+#ifdef GIT_DEBUG_STRICT_ALLOC
+ if (!size)
+ return NULL;
+#endif
+
+ new_ptr = realloc(ptr, size);
+
+ if (!new_ptr)
+ git_error_set_oom();
+
return new_ptr;
}
diff --git a/src/allocators/win32_crtdbg.c b/src/allocators/win32_crtdbg.c
deleted file mode 100644
index 1187e2fcd..000000000
--- a/src/allocators/win32_crtdbg.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "win32_crtdbg.h"
-
-#if defined(GIT_MSVC_CRTDBG)
-
-#include "win32/w32_crtdbg_stacktrace.h"
-
-static void *crtdbg__malloc(size_t len, const char *file, int line)
-{
- void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
- if (!ptr) git_error_set_oom();
- return ptr;
-}
-
-static void *crtdbg__calloc(size_t nelem, size_t elsize, const char *file, int line)
-{
- void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
- if (!ptr) git_error_set_oom();
- return ptr;
-}
-
-static char *crtdbg__strdup(const char *str, const char *file, int line)
-{
- char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
- if (!ptr) git_error_set_oom();
- return ptr;
-}
-
-static char *crtdbg__strndup(const char *str, size_t n, const char *file, int line)
-{
- size_t length = 0, alloclength;
- char *ptr;
-
- length = p_strnlen(str, n);
-
- if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
- !(ptr = crtdbg__malloc(alloclength, file, line)))
- return NULL;
-
- if (length)
- memcpy(ptr, str, length);
-
- ptr[length] = '\0';
-
- return ptr;
-}
-
-static char *crtdbg__substrdup(const char *start, size_t n, const char *file, int line)
-{
- char *ptr;
- size_t alloclen;
-
- if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
- !(ptr = crtdbg__malloc(alloclen, file, line)))
- return NULL;
-
- memcpy(ptr, start, n);
- ptr[n] = '\0';
- return ptr;
-}
-
-static void *crtdbg__realloc(void *ptr, size_t size, const char *file, int line)
-{
- void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
- if (!new_ptr) git_error_set_oom();
- return new_ptr;
-}
-
-static void *crtdbg__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
-{
- size_t newsize;
-
- if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
- return NULL;
-
- return crtdbg__realloc(ptr, newsize, file, line);
-}
-
-static void *crtdbg__mallocarray(size_t nelem, size_t elsize, const char *file, int line)
-{
- return crtdbg__reallocarray(NULL, nelem, elsize, file, line);
-}
-
-static void crtdbg__free(void *ptr)
-{
- free(ptr);
-}
-
-int git_win32_crtdbg_init_allocator(git_allocator *allocator)
-{
- allocator->gmalloc = crtdbg__malloc;
- allocator->gcalloc = crtdbg__calloc;
- allocator->gstrdup = crtdbg__strdup;
- allocator->gstrndup = crtdbg__strndup;
- allocator->gsubstrdup = crtdbg__substrdup;
- allocator->grealloc = crtdbg__realloc;
- allocator->greallocarray = crtdbg__reallocarray;
- allocator->gmallocarray = crtdbg__mallocarray;
- allocator->gfree = crtdbg__free;
- return 0;
-}
-
-#else
-
-int git_win32_crtdbg_init_allocator(git_allocator *allocator)
-{
- GIT_UNUSED(allocator);
- git_error_set(GIT_EINVALID, "crtdbg memory allocator not available");
- return -1;
-}
-
-#endif
diff --git a/src/allocators/win32_leakcheck.c b/src/allocators/win32_leakcheck.c
new file mode 100644
index 000000000..fe06a14af
--- /dev/null
+++ b/src/allocators/win32_leakcheck.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "win32_leakcheck.h"
+
+#if defined(GIT_WIN32_LEAKCHECK)
+
+#include "win32/w32_leakcheck.h"
+
+static void *leakcheck_malloc(size_t len, const char *file, int line)
+{
+ void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, git_win32_leakcheck_stacktrace(1,file), line);
+ if (!ptr) git_error_set_oom();
+ return ptr;
+}
+
+static void *leakcheck_calloc(size_t nelem, size_t elsize, const char *file, int line)
+{
+ void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, git_win32_leakcheck_stacktrace(1,file), line);
+ if (!ptr) git_error_set_oom();
+ return ptr;
+}
+
+static char *leakcheck_strdup(const char *str, const char *file, int line)
+{
+ char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, git_win32_leakcheck_stacktrace(1,file), line);
+ if (!ptr) git_error_set_oom();
+ return ptr;
+}
+
+static char *leakcheck_strndup(const char *str, size_t n, const char *file, int line)
+{
+ size_t length = 0, alloclength;
+ char *ptr;
+
+ length = p_strnlen(str, n);
+
+ if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
+ !(ptr = leakcheck_malloc(alloclength, file, line)))
+ return NULL;
+
+ if (length)
+ memcpy(ptr, str, length);
+
+ ptr[length] = '\0';
+
+ return ptr;
+}
+
+static char *leakcheck_substrdup(const char *start, size_t n, const char *file, int line)
+{
+ char *ptr;
+ size_t alloclen;
+
+ if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
+ !(ptr = leakcheck_malloc(alloclen, file, line)))
+ return NULL;
+
+ memcpy(ptr, start, n);
+ ptr[n] = '\0';
+ return ptr;
+}
+
+static void *leakcheck_realloc(void *ptr, size_t size, const char *file, int line)
+{
+ void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, git_win32_leakcheck_stacktrace(1,file), line);
+ if (!new_ptr) git_error_set_oom();
+ return new_ptr;
+}
+
+static void *leakcheck_reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
+{
+ size_t newsize;
+
+ if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
+ return NULL;
+
+ return leakcheck_realloc(ptr, newsize, file, line);
+}
+
+static void *leakcheck_mallocarray(size_t nelem, size_t elsize, const char *file, int line)
+{
+ return leakcheck_reallocarray(NULL, nelem, elsize, file, line);
+}
+
+static void leakcheck_free(void *ptr)
+{
+ free(ptr);
+}
+
+int git_win32_leakcheck_init_allocator(git_allocator *allocator)
+{
+ allocator->gmalloc = leakcheck_malloc;
+ allocator->gcalloc = leakcheck_calloc;
+ allocator->gstrdup = leakcheck_strdup;
+ allocator->gstrndup = leakcheck_strndup;
+ allocator->gsubstrdup = leakcheck_substrdup;
+ allocator->grealloc = leakcheck_realloc;
+ allocator->greallocarray = leakcheck_reallocarray;
+ allocator->gmallocarray = leakcheck_mallocarray;
+ allocator->gfree = leakcheck_free;
+ return 0;
+}
+
+#else
+
+int git_win32_leakcheck_init_allocator(git_allocator *allocator)
+{
+ GIT_UNUSED(allocator);
+ git_error_set(GIT_EINVALID, "leakcheck memory allocator not available");
+ return -1;
+}
+
+#endif
diff --git a/src/allocators/win32_crtdbg.h b/src/allocators/win32_leakcheck.h
index 754c6b6fb..089690f90 100644
--- a/src/allocators/win32_crtdbg.h
+++ b/src/allocators/win32_leakcheck.h
@@ -5,13 +5,13 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#ifndef INCLUDE_allocators_crtdbg_h
-#define INCLUDE_allocators_crtdbg_h
+#ifndef INCLUDE_allocators_win32_leakcheck_h
+#define INCLUDE_allocators_win32_leakcheck_h
#include "common.h"
#include "alloc.h"
-int git_win32_crtdbg_init_allocator(git_allocator *allocator);
+int git_win32_leakcheck_init_allocator(git_allocator *allocator);
#endif
diff --git a/src/annotated_commit.c b/src/annotated_commit.c
index 5d4f37082..e48947679 100644
--- a/src/annotated_commit.c
+++ b/src/annotated_commit.c
@@ -26,7 +26,8 @@ static int annotated_commit_init(
git_annotated_commit *annotated_commit;
int error = 0;
- assert(out && commit);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(commit);
*out = NULL;
@@ -63,7 +64,9 @@ static int annotated_commit_init_from_id(
git_commit *commit = NULL;
int error = 0;
- assert(out && repo && id);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(id);
*out = NULL;
@@ -100,7 +103,9 @@ int git_annotated_commit_from_revspec(
git_object *obj, *commit;
int error;
- assert(out && repo && revspec);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(revspec);
if ((error = git_revparse_single(&obj, repo, revspec)) < 0)
return error;
@@ -126,7 +131,9 @@ int git_annotated_commit_from_ref(
git_object *peeled;
int error = 0;
- assert(out && repo && ref);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(ref);
*out = NULL;
@@ -154,11 +161,12 @@ int git_annotated_commit_from_head(
git_reference *head;
int error;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
*out = NULL;
- if ((error = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0)
+ if ((error = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0)
return -1;
error = git_annotated_commit_from_ref(out, repo, head);
@@ -174,7 +182,11 @@ int git_annotated_commit_from_fetchhead(
const char *remote_url,
const git_oid *id)
{
- assert(repo && id && branch_name && remote_url);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(branch_name);
+ GIT_ASSERT_ARG(remote_url);
+ GIT_ASSERT_ARG(id);
if (annotated_commit_init_from_id(out, repo, id, branch_name) < 0)
return -1;
@@ -192,14 +204,14 @@ int git_annotated_commit_from_fetchhead(
const git_oid *git_annotated_commit_id(
const git_annotated_commit *annotated_commit)
{
- assert(annotated_commit);
+ GIT_ASSERT_ARG_WITH_RETVAL(annotated_commit, NULL);
return git_commit_id(annotated_commit->commit);
}
const char *git_annotated_commit_ref(
const git_annotated_commit *annotated_commit)
{
- assert(annotated_commit);
+ GIT_ASSERT_ARG_WITH_RETVAL(annotated_commit, NULL);
return annotated_commit->ref_name;
}
diff --git a/src/apply.c b/src/apply.c
index f90166343..7c65cd79d 100644
--- a/src/apply.c
+++ b/src/apply.c
@@ -5,8 +5,6 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "apply.h"
-
#include "git2/apply.h"
#include "git2/patch.h"
#include "git2/filter.h"
@@ -21,6 +19,7 @@
#include "zstream.h"
#include "reader.h"
#include "index.h"
+#include "apply.h"
typedef struct {
/* The lines that we allocate ourself are allocated out of the pool.
@@ -66,6 +65,9 @@ static int patch_image_init_fromstr(
if (git_pool_init(&out->pool, sizeof(git_diff_line)) < 0)
return -1;
+ if (!in_len)
+ return 0;
+
for (start = in; start < in + in_len; start = end) {
end = memchr(start, '\n', in_len - (start - in));
@@ -396,7 +398,11 @@ int git_apply__patch(
unsigned int mode = 0;
int error = 0;
- assert(contents_out && filename_out && mode_out && (source || !source_len) && patch);
+ GIT_ASSERT_ARG(contents_out);
+ GIT_ASSERT_ARG(filename_out);
+ GIT_ASSERT_ARG(mode_out);
+ GIT_ASSERT_ARG(source || !source_len);
+ GIT_ASSERT_ARG(patch);
if (given_opts)
memcpy(&ctx.opts, given_opts, sizeof(git_apply_options));
@@ -621,7 +627,10 @@ int git_apply_to_tree(
size_t i;
int error = 0;
- assert(out && repo && preimage && diff);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(preimage);
+ GIT_ASSERT_ARG(diff);
*out = NULL;
@@ -769,6 +778,8 @@ done:
int git_apply_options_init(git_apply_options *opts, unsigned int version)
{
+ GIT_ASSERT_ARG(opts);
+
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
opts, version, git_apply_options, GIT_APPLY_OPTIONS_INIT);
return 0;
@@ -802,7 +813,8 @@ int git_apply(
git_apply_options opts = GIT_APPLY_OPTIONS_INIT;
int error = GIT_EINVALID;
- assert(repo && diff);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(diff);
GIT_ERROR_CHECK_VERSION(
given_opts, GIT_APPLY_OPTIONS_VERSION, "git_apply_options");
@@ -826,7 +838,7 @@ int git_apply(
error = git_reader_for_workdir(&pre_reader, repo, false);
break;
default:
- assert(false);
+ GIT_ASSERT(false);
}
if (error < 0)
@@ -866,7 +878,7 @@ int git_apply(
error = git_apply__to_workdir(repo, diff, preimage, postimage, location, &opts);
break;
default:
- assert(false);
+ GIT_ASSERT(false);
}
if (error < 0)
diff --git a/src/array.h b/src/array.h
index 03537e796..e97688b36 100644
--- a/src/array.h
+++ b/src/array.h
@@ -41,8 +41,8 @@
typedef git_array_t(char) git_array_generic_t;
-/* use a generic array for growth so this can return the new item */
-GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size)
+/* use a generic array for growth, return 0 on success */
+GIT_INLINE(int) git_array_grow(void *_a, size_t item_size)
{
volatile git_array_generic_t *a = _a;
size_t new_size;
@@ -59,24 +59,24 @@ GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size)
if ((new_array = git__reallocarray(a->ptr, new_size, item_size)) == NULL)
goto on_oom;
- a->ptr = new_array; a->asize = new_size; a->size++;
- return a->ptr + (a->size - 1) * item_size;
+ a->ptr = new_array;
+ a->asize = new_size;
+ return 0;
on_oom:
git_array_clear(*a);
- return NULL;
+ return -1;
}
#define git_array_alloc(a) \
- (((a).size >= (a).asize) ? \
- git_array_grow(&(a), sizeof(*(a).ptr)) : \
- ((a).ptr ? &(a).ptr[(a).size++] : NULL))
+ (((a).size < (a).asize || git_array_grow(&(a), sizeof(*(a).ptr)) == 0) ? \
+ &(a).ptr[(a).size++] : (void *)NULL)
-#define git_array_last(a) ((a).size ? &(a).ptr[(a).size - 1] : NULL)
+#define git_array_last(a) ((a).size ? &(a).ptr[(a).size - 1] : (void *)NULL)
-#define git_array_pop(a) ((a).size ? &(a).ptr[--(a).size] : NULL)
+#define git_array_pop(a) ((a).size ? &(a).ptr[--(a).size] : (void *)NULL)
-#define git_array_get(a, i) (((i) < (a).size) ? &(a).ptr[(i)] : NULL)
+#define git_array_get(a, i) (((i) < (a).size) ? &(a).ptr[(i)] : (void *)NULL)
#define git_array_size(a) (a).size
diff --git a/src/attr.c b/src/attr.c
index bd517cde3..95b49e3de 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -36,16 +36,16 @@ git_attr_value_t git_attr_value(const char *attr)
static int collect_attr_files(
git_repository *repo,
git_attr_session *attr_session,
- uint32_t flags,
+ git_attr_options *opts,
const char *path,
git_vector *files);
static void release_attr_files(git_vector *files);
-int git_attr_get(
+int git_attr_get_ext(
const char **value,
git_repository *repo,
- uint32_t flags,
+ git_attr_options *opts,
const char *pathname,
const char *name)
{
@@ -58,7 +58,10 @@ int git_attr_get(
git_attr_rule *rule;
git_dir_flag dir_flag = GIT_DIR_FLAG_UNKNOWN;
- assert(value && repo && name);
+ GIT_ASSERT_ARG(value);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
+ GIT_ERROR_CHECK_VERSION(opts, GIT_ATTR_OPTIONS_VERSION, "git_attr_options");
*value = NULL;
@@ -68,7 +71,7 @@ int git_attr_get(
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0)
return -1;
- if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0)
+ if ((error = collect_attr_files(repo, NULL, opts, pathname, &files)) < 0)
goto cleanup;
memset(&attr, 0, sizeof(attr));
@@ -95,6 +98,20 @@ cleanup:
return error;
}
+int git_attr_get(
+ const char **value,
+ git_repository *repo,
+ uint32_t flags,
+ const char *pathname,
+ const char *name)
+{
+ git_attr_options opts = GIT_ATTR_OPTIONS_INIT;
+
+ opts.flags = flags;
+
+ return git_attr_get_ext(value, repo, &opts, pathname, name);
+}
+
typedef struct {
git_attr_name name;
@@ -105,7 +122,7 @@ int git_attr_get_many_with_session(
const char **values,
git_repository *repo,
git_attr_session *attr_session,
- uint32_t flags,
+ git_attr_options *opts,
const char *pathname,
size_t num_attr,
const char **names)
@@ -123,7 +140,11 @@ int git_attr_get_many_with_session(
if (!num_attr)
return 0;
- assert(values && repo && names);
+ GIT_ASSERT_ARG(values);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(pathname);
+ GIT_ASSERT_ARG(names);
+ GIT_ERROR_CHECK_VERSION(opts, GIT_ATTR_OPTIONS_VERSION, "git_attr_options");
if (git_repository_is_bare(repo))
dir_flag = GIT_DIR_FLAG_FALSE;
@@ -131,7 +152,7 @@ int git_attr_get_many_with_session(
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0)
return -1;
- if ((error = collect_attr_files(repo, attr_session, flags, pathname, &files)) < 0)
+ if ((error = collect_attr_files(repo, attr_session, opts, pathname, &files)) < 0)
goto cleanup;
info = git__calloc(num_attr, sizeof(attr_get_many_info));
@@ -185,8 +206,24 @@ int git_attr_get_many(
size_t num_attr,
const char **names)
{
+ git_attr_options opts = GIT_ATTR_OPTIONS_INIT;
+
+ opts.flags = flags;
+
return git_attr_get_many_with_session(
- values, repo, NULL, flags, pathname, num_attr, names);
+ values, repo, NULL, &opts, pathname, num_attr, names);
+}
+
+int git_attr_get_many_ext(
+ const char **values,
+ git_repository *repo,
+ git_attr_options *opts,
+ const char *pathname,
+ size_t num_attr,
+ const char **names)
+{
+ return git_attr_get_many_with_session(
+ values, repo, NULL, opts, pathname, num_attr, names);
}
int git_attr_foreach(
@@ -196,6 +233,20 @@ int git_attr_foreach(
int (*callback)(const char *name, const char *value, void *payload),
void *payload)
{
+ git_attr_options opts = GIT_ATTR_OPTIONS_INIT;
+
+ opts.flags = flags;
+
+ return git_attr_foreach_ext(repo, &opts, pathname, callback, payload);
+}
+
+int git_attr_foreach_ext(
+ git_repository *repo,
+ git_attr_options *opts,
+ const char *pathname,
+ int (*callback)(const char *name, const char *value, void *payload),
+ void *payload)
+{
int error;
git_attr_path path;
git_vector files = GIT_VECTOR_INIT;
@@ -206,7 +257,9 @@ int git_attr_foreach(
git_strmap *seen = NULL;
git_dir_flag dir_flag = GIT_DIR_FLAG_UNKNOWN;
- assert(repo && callback);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(callback);
+ GIT_ERROR_CHECK_VERSION(opts, GIT_ATTR_OPTIONS_VERSION, "git_attr_options");
if (git_repository_is_bare(repo))
dir_flag = GIT_DIR_FLAG_FALSE;
@@ -214,7 +267,7 @@ int git_attr_foreach(
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0)
return -1;
- if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0 ||
+ if ((error = collect_attr_files(repo, NULL, opts, pathname, &files)) < 0 ||
(error = git_strmap_new(&seen)) < 0)
goto cleanup;
@@ -247,26 +300,43 @@ cleanup:
return error;
}
-static int preload_attr_file(
+static int preload_attr_source(
git_repository *repo,
git_attr_session *attr_session,
- git_attr_file_source source,
- const char *base,
- const char *file,
- bool allow_macros)
+ git_attr_file_source *source)
{
int error;
git_attr_file *preload = NULL;
- if (!file)
+ if (!source)
return 0;
- if (!(error = git_attr_cache__get(&preload, repo, attr_session, source, base, file,
- git_attr_file__parse_buffer, allow_macros)))
+
+ error = git_attr_cache__get(&preload, repo, attr_session, source,
+ git_attr_file__parse_buffer, true);
+
+ if (!error)
git_attr_file__free(preload);
return error;
}
+GIT_INLINE(int) preload_attr_file(
+ git_repository *repo,
+ git_attr_session *attr_session,
+ const char *base,
+ const char *filename)
+{
+ git_attr_file_source source = { GIT_ATTR_FILE_SOURCE_FILE };
+
+ if (!filename)
+ return 0;
+
+ source.base = base;
+ source.filename = filename;
+
+ return preload_attr_source(repo, attr_session, &source);
+}
+
static int system_attr_file(
git_buf *out,
git_attr_session *attr_session)
@@ -308,9 +378,12 @@ static int system_attr_file(
static int attr_setup(
git_repository *repo,
git_attr_session *attr_session,
- uint32_t flags)
+ git_attr_options *opts)
{
- git_buf path = GIT_BUF_INIT;
+ git_buf system = GIT_BUF_INIT, info = GIT_BUF_INIT;
+ git_attr_file_source index_source = { GIT_ATTR_FILE_SOURCE_INDEX, NULL, GIT_ATTR_FILE, NULL };
+ git_attr_file_source head_source = { GIT_ATTR_FILE_SOURCE_HEAD, NULL, GIT_ATTR_FILE, NULL };
+ git_attr_file_source commit_source = { GIT_ATTR_FILE_SOURCE_COMMIT, NULL, GIT_ATTR_FILE, NULL };
git_index *idx = NULL;
const char *workdir;
int error = 0;
@@ -326,45 +399,56 @@ static int attr_setup(
* definitions will be available for later file parsing.
*/
- if ((error = system_attr_file(&path, attr_session)) < 0 ||
- (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
- NULL, path.ptr, true)) < 0) {
+ if ((error = system_attr_file(&system, attr_session)) < 0 ||
+ (error = preload_attr_file(repo, attr_session, NULL, system.ptr)) < 0) {
if (error != GIT_ENOTFOUND)
goto out;
+
+ error = 0;
}
- if ((error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
- NULL, git_repository_attr_cache(repo)->cfg_attr_file, true)) < 0)
+ if ((error = preload_attr_file(repo, attr_session, NULL,
+ git_repository_attr_cache(repo)->cfg_attr_file)) < 0)
goto out;
- git_buf_clear(&path); /* git_repository_item_path expects an empty buffer, because it uses git_buf_set */
- if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
- (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
- path.ptr, GIT_ATTR_FILE_INREPO, true)) < 0) {
+ if ((error = git_repository_item_path(&info, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
+ (error = preload_attr_file(repo, attr_session, info.ptr, GIT_ATTR_FILE_INREPO)) < 0) {
if (error != GIT_ENOTFOUND)
goto out;
+
+ error = 0;
}
if ((workdir = git_repository_workdir(repo)) != NULL &&
- (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
- workdir, GIT_ATTR_FILE, true)) < 0)
+ (error = preload_attr_file(repo, attr_session, workdir, GIT_ATTR_FILE)) < 0)
goto out;
if ((error = git_repository_index__weakptr(&idx, repo)) < 0 ||
- (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_INDEX,
- NULL, GIT_ATTR_FILE, true)) < 0)
+ (error = preload_attr_source(repo, attr_session, &index_source)) < 0)
goto out;
- if ((flags & GIT_ATTR_CHECK_INCLUDE_HEAD) != 0 &&
- (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_HEAD,
- NULL, GIT_ATTR_FILE, true)) < 0)
+ if ((opts && (opts->flags & GIT_ATTR_CHECK_INCLUDE_HEAD) != 0) &&
+ (error = preload_attr_source(repo, attr_session, &head_source)) < 0)
goto out;
+ if ((opts && (opts->flags & GIT_ATTR_CHECK_INCLUDE_COMMIT) != 0)) {
+#ifndef GIT_DEPRECATE_HARD
+ if (opts->commit_id)
+ commit_source.commit_id = opts->commit_id;
+ else
+#endif
+ commit_source.commit_id = &opts->attr_commit_id;
+
+ if ((error = preload_attr_source(repo, attr_session, &commit_source)) < 0)
+ goto out;
+ }
+
if (attr_session)
attr_session->init_setup = 1;
out:
- git_buf_dispose(&path);
+ git_buf_dispose(&system);
+ git_buf_dispose(&info);
return error;
}
@@ -378,6 +462,9 @@ int git_attr_add_macro(
git_attr_rule *macro = NULL;
git_pool *pool;
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
+
if ((error = git_attr_cache__init(repo)) < 0)
return error;
@@ -406,56 +493,62 @@ int git_attr_add_macro(
typedef struct {
git_repository *repo;
git_attr_session *attr_session;
- uint32_t flags;
+ git_attr_options *opts;
const char *workdir;
git_index *index;
git_vector *files;
} attr_walk_up_info;
static int attr_decide_sources(
- uint32_t flags, bool has_wd, bool has_index, git_attr_file_source *srcs)
+ uint32_t flags,
+ bool has_wd,
+ bool has_index,
+ git_attr_file_source_t *srcs)
{
int count = 0;
switch (flags & 0x03) {
case GIT_ATTR_CHECK_FILE_THEN_INDEX:
if (has_wd)
- srcs[count++] = GIT_ATTR_FILE__FROM_FILE;
+ srcs[count++] = GIT_ATTR_FILE_SOURCE_FILE;
if (has_index)
- srcs[count++] = GIT_ATTR_FILE__FROM_INDEX;
+ srcs[count++] = GIT_ATTR_FILE_SOURCE_INDEX;
break;
case GIT_ATTR_CHECK_INDEX_THEN_FILE:
if (has_index)
- srcs[count++] = GIT_ATTR_FILE__FROM_INDEX;
+ srcs[count++] = GIT_ATTR_FILE_SOURCE_INDEX;
if (has_wd)
- srcs[count++] = GIT_ATTR_FILE__FROM_FILE;
+ srcs[count++] = GIT_ATTR_FILE_SOURCE_FILE;
break;
case GIT_ATTR_CHECK_INDEX_ONLY:
if (has_index)
- srcs[count++] = GIT_ATTR_FILE__FROM_INDEX;
+ srcs[count++] = GIT_ATTR_FILE_SOURCE_INDEX;
break;
}
if ((flags & GIT_ATTR_CHECK_INCLUDE_HEAD) != 0)
- srcs[count++] = GIT_ATTR_FILE__FROM_HEAD;
+ srcs[count++] = GIT_ATTR_FILE_SOURCE_HEAD;
+
+ if ((flags & GIT_ATTR_CHECK_INCLUDE_COMMIT) != 0)
+ srcs[count++] = GIT_ATTR_FILE_SOURCE_COMMIT;
return count;
}
-static int push_attr_file(
+static int push_attr_source(
git_repository *repo,
git_attr_session *attr_session,
git_vector *list,
- git_attr_file_source source,
- const char *base,
- const char *filename,
+ git_attr_file_source *source,
bool allow_macros)
{
int error = 0;
git_attr_file *file = NULL;
error = git_attr_cache__get(&file, repo, attr_session,
- source, base, filename, git_attr_file__parse_buffer, allow_macros);
+ source,
+ git_attr_file__parse_buffer,
+ allow_macros);
if (error < 0)
return error;
@@ -468,20 +561,46 @@ static int push_attr_file(
return error;
}
+GIT_INLINE(int) push_attr_file(
+ git_repository *repo,
+ git_attr_session *attr_session,
+ git_vector *list,
+ const char *base,
+ const char *filename)
+{
+ git_attr_file_source source = { GIT_ATTR_FILE_SOURCE_FILE, base, filename };
+ return push_attr_source(repo, attr_session, list, &source, true);
+}
+
static int push_one_attr(void *ref, const char *path)
{
attr_walk_up_info *info = (attr_walk_up_info *)ref;
- git_attr_file_source src[GIT_ATTR_FILE_NUM_SOURCES];
+ git_attr_file_source_t src[GIT_ATTR_FILE_NUM_SOURCES];
int error = 0, n_src, i;
bool allow_macros;
- n_src = attr_decide_sources(
- info->flags, info->workdir != NULL, info->index != NULL, src);
+ n_src = attr_decide_sources(info->opts ? info->opts->flags : 0,
+ info->workdir != NULL,
+ info->index != NULL,
+ src);
+
allow_macros = info->workdir ? !strcmp(info->workdir, path) : false;
- for (i = 0; !error && i < n_src; ++i)
- error = push_attr_file(info->repo, info->attr_session, info->files,
- src[i], path, GIT_ATTR_FILE, allow_macros);
+ for (i = 0; !error && i < n_src; ++i) {
+ git_attr_file_source source = { src[i], path, GIT_ATTR_FILE };
+
+ if (src[i] == GIT_ATTR_FILE_SOURCE_COMMIT && info->opts) {
+#ifndef GIT_DEPRECATE_HARD
+ if (info->opts->commit_id)
+ source.commit_id = info->opts->commit_id;
+ else
+#endif
+ source.commit_id = &info->opts->attr_commit_id;
+ }
+
+ error = push_attr_source(info->repo, info->attr_session, info->files,
+ &source, allow_macros);
+ }
return error;
}
@@ -501,7 +620,7 @@ static void release_attr_files(git_vector *files)
static int collect_attr_files(
git_repository *repo,
git_attr_session *attr_session,
- uint32_t flags,
+ git_attr_options *opts,
const char *path,
git_vector *files)
{
@@ -510,14 +629,20 @@ static int collect_attr_files(
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info = { NULL };
- if ((error = attr_setup(repo, attr_session, flags)) < 0)
+ GIT_ASSERT(!git_path_is_absolute(path));
+
+ if ((error = attr_setup(repo, attr_session, opts)) < 0)
return error;
/* Resolve path in a non-bare repo */
- if (workdir != NULL)
- error = git_path_find_dir(&dir, path, workdir);
- else
+ if (workdir != NULL) {
+ if (!(error = git_repository_workdir_path(&dir, repo, path)))
+ error = git_path_find_dir(&dir);
+ }
+ else {
error = git_path_dirname_r(&dir, path);
+ }
+
if (error < 0)
goto cleanup;
@@ -529,15 +654,14 @@ static int collect_attr_files(
*/
if ((error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
- (error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
- attrfile.ptr, GIT_ATTR_FILE_INREPO, true)) < 0) {
+ (error = push_attr_file(repo, attr_session, files, attrfile.ptr, GIT_ATTR_FILE_INREPO)) < 0) {
if (error != GIT_ENOTFOUND)
goto cleanup;
}
info.repo = repo;
info.attr_session = attr_session;
- info.flags = flags;
+ info.opts = opts;
info.workdir = workdir;
if (git_repository_index__weakptr(&info.index, repo) < 0)
git_error_clear(); /* no error even if there is no index */
@@ -552,18 +676,16 @@ static int collect_attr_files(
goto cleanup;
if (git_repository_attr_cache(repo)->cfg_attr_file != NULL) {
- error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
- NULL, git_repository_attr_cache(repo)->cfg_attr_file, true);
+ error = push_attr_file(repo, attr_session, files, NULL, git_repository_attr_cache(repo)->cfg_attr_file);
if (error < 0)
goto cleanup;
}
- if ((flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) {
+ if (!opts || (opts->flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) {
error = system_attr_file(&dir, attr_session);
if (!error)
- error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
- NULL, dir.ptr, true);
+ error = push_attr_file(repo, attr_session, files, NULL, dir.ptr);
else if (error == GIT_ENOTFOUND)
error = 0;
}
diff --git a/src/attr_file.c b/src/attr_file.c
index 3f69b5ffc..71bd20a0f 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -10,7 +10,6 @@
#include "repository.h"
#include "filebuf.h"
#include "attrcache.h"
-#include "buf_text.h"
#include "git2/blob.h"
#include "git2/tree.h"
#include "blob.h"
@@ -34,7 +33,7 @@ static void attr_file_free(git_attr_file *file)
int git_attr_file__new(
git_attr_file **out,
git_attr_file_entry *entry,
- git_attr_file_source source)
+ git_attr_file_source *source)
{
git_attr_file *attrs = git__calloc(1, sizeof(git_attr_file));
GIT_ERROR_CHECK_ALLOC(attrs);
@@ -48,8 +47,8 @@ int git_attr_file__new(
goto on_error;
GIT_REFCOUNT_INC(attrs);
- attrs->entry = entry;
- attrs->source = source;
+ attrs->entry = entry;
+ memcpy(&attrs->source, source, sizeof(git_attr_file_source));
*out = attrs;
return 0;
@@ -109,11 +108,12 @@ int git_attr_file__load(
git_repository *repo,
git_attr_session *attr_session,
git_attr_file_entry *entry,
- git_attr_file_source source,
+ git_attr_file_source *source,
git_attr_file_parser parser,
bool allow_macros)
{
int error = 0;
+ git_commit *commit = NULL;
git_tree *tree = NULL;
git_tree_entry *tree_entry = NULL;
git_blob *blob = NULL;
@@ -123,17 +123,17 @@ int git_attr_file__load(
struct stat st;
bool nonexistent = false;
int bom_offset;
- git_bom_t bom;
+ git_buf_bom_t bom;
git_oid id;
git_object_size_t blobsize;
*out = NULL;
- switch (source) {
- case GIT_ATTR_FILE__IN_MEMORY:
+ switch (source->type) {
+ case GIT_ATTR_FILE_SOURCE_MEMORY:
/* in-memory attribute file doesn't need data */
break;
- case GIT_ATTR_FILE__FROM_INDEX: {
+ case GIT_ATTR_FILE_SOURCE_INDEX: {
if ((error = attr_file_oid_from_index(&id, repo, entry->path)) < 0 ||
(error = git_blob_lookup(&blob, repo, &id)) < 0)
return error;
@@ -146,7 +146,7 @@ int git_attr_file__load(
git_buf_put(&content, git_blob_rawcontent(blob), (size_t)blobsize);
break;
}
- case GIT_ATTR_FILE__FROM_FILE: {
+ case GIT_ATTR_FILE_SOURCE_FILE: {
int fd = -1;
/* For open or read errors, pretend that we got ENOTFOUND. */
@@ -163,10 +163,32 @@ int git_attr_file__load(
break;
}
- case GIT_ATTR_FILE__FROM_HEAD: {
- if ((error = git_repository_head_tree(&tree, repo)) < 0 ||
- (error = git_tree_entry_bypath(&tree_entry, tree, entry->path)) < 0 ||
- (error = git_blob_lookup(&blob, repo, git_tree_entry_id(tree_entry))) < 0)
+ case GIT_ATTR_FILE_SOURCE_HEAD:
+ case GIT_ATTR_FILE_SOURCE_COMMIT: {
+ if (source->type == GIT_ATTR_FILE_SOURCE_COMMIT) {
+ if ((error = git_commit_lookup(&commit, repo, source->commit_id)) < 0 ||
+ (error = git_commit_tree(&tree, commit)) < 0)
+ goto cleanup;
+ } else {
+ if ((error = git_repository_head_tree(&tree, repo)) < 0)
+ goto cleanup;
+ }
+
+ if ((error = git_tree_entry_bypath(&tree_entry, tree, entry->path)) < 0) {
+ /*
+ * If the attributes file does not exist, we can
+ * cache an empty file for this commit to prevent
+ * needless future lookups.
+ */
+ if (error == GIT_ENOTFOUND) {
+ error = 0;
+ break;
+ }
+
+ goto cleanup;
+ }
+
+ if ((error = git_blob_lookup(&blob, repo, git_tree_entry_id(tree_entry))) < 0)
goto cleanup;
/*
@@ -183,7 +205,7 @@ int git_attr_file__load(
break;
}
default:
- git_error_set(GIT_ERROR_INVALID, "unknown file source %d", source);
+ git_error_set(GIT_ERROR_INVALID, "unknown file source %d", source->type);
return -1;
}
@@ -192,9 +214,9 @@ int git_attr_file__load(
/* advance over a UTF8 BOM */
content_str = git_buf_cstr(&content);
- bom_offset = git_buf_text_detect_bom(&bom, &content);
+ bom_offset = git_buf_detect_bom(&bom, &content);
- if (bom == GIT_BOM_UTF8)
+ if (bom == GIT_BUF_BOM_UTF8)
content_str += bom_offset;
/* store the key of the attr_reader; don't bother with cache
@@ -211,11 +233,13 @@ int git_attr_file__load(
/* write cache breakers */
if (nonexistent)
file->nonexistent = 1;
- else if (source == GIT_ATTR_FILE__FROM_INDEX)
+ else if (source->type == GIT_ATTR_FILE_SOURCE_INDEX)
git_oid_cpy(&file->cache_data.oid, git_blob_id(blob));
- else if (source == GIT_ATTR_FILE__FROM_HEAD)
+ else if (source->type == GIT_ATTR_FILE_SOURCE_HEAD)
git_oid_cpy(&file->cache_data.oid, git_tree_id(tree));
- else if (source == GIT_ATTR_FILE__FROM_FILE)
+ else if (source->type == GIT_ATTR_FILE_SOURCE_COMMIT)
+ git_oid_cpy(&file->cache_data.oid, git_tree_id(tree));
+ else if (source->type == GIT_ATTR_FILE_SOURCE_FILE)
git_futils_filestamp_set_from_stat(&file->cache_data.stamp, &st);
/* else always cacheable */
@@ -225,6 +249,7 @@ cleanup:
git_blob_free(blob);
git_tree_entry_free(tree_entry);
git_tree_free(tree);
+ git_commit_free(commit);
git_buf_dispose(&content);
return error;
@@ -233,7 +258,8 @@ cleanup:
int git_attr_file__out_of_date(
git_repository *repo,
git_attr_session *attr_session,
- git_attr_file *file)
+ git_attr_file *file,
+ git_attr_file_source *source)
{
if (!file)
return 1;
@@ -246,15 +272,15 @@ int git_attr_file__out_of_date(
else if (file->nonexistent)
return 1;
- switch (file->source) {
- case GIT_ATTR_FILE__IN_MEMORY:
+ switch (file->source.type) {
+ case GIT_ATTR_FILE_SOURCE_MEMORY:
return 0;
- case GIT_ATTR_FILE__FROM_FILE:
+ case GIT_ATTR_FILE_SOURCE_FILE:
return git_futils_filestamp_check(
&file->cache_data.stamp, file->entry->fullpath);
- case GIT_ATTR_FILE__FROM_INDEX: {
+ case GIT_ATTR_FILE_SOURCE_INDEX: {
int error;
git_oid id;
@@ -265,21 +291,41 @@ int git_attr_file__out_of_date(
return (git_oid__cmp(&file->cache_data.oid, &id) != 0);
}
- case GIT_ATTR_FILE__FROM_HEAD: {
- git_tree *tree;
+ case GIT_ATTR_FILE_SOURCE_HEAD: {
+ git_tree *tree = NULL;
+ int error = git_repository_head_tree(&tree, repo);
+
+ if (error < 0)
+ return error;
+
+ error = (git_oid__cmp(&file->cache_data.oid, git_tree_id(tree)) != 0);
+
+ git_tree_free(tree);
+ return error;
+ }
+
+ case GIT_ATTR_FILE_SOURCE_COMMIT: {
+ git_commit *commit = NULL;
+ git_tree *tree = NULL;
int error;
- if ((error = git_repository_head_tree(&tree, repo)) < 0)
+ if ((error = git_commit_lookup(&commit, repo, source->commit_id)) < 0)
+ return error;
+
+ error = git_commit_tree(&tree, commit);
+ git_commit_free(commit);
+
+ if (error < 0)
return error;
- error = git_oid__cmp(&file->cache_data.oid, git_tree_id(tree));
+ error = (git_oid__cmp(&file->cache_data.oid, git_tree_id(tree)) != 0);
git_tree_free(tree);
return error;
}
default:
- git_error_set(GIT_ERROR_INVALID, "invalid file type %d", file->source);
+ git_error_set(GIT_ERROR_INVALID, "invalid file type %d", file->source.type);
return -1;
}
}
@@ -351,7 +397,9 @@ uint32_t git_attr_file__name_hash(const char *name)
{
uint32_t h = 5381;
int c;
- assert(name);
+
+ GIT_ASSERT_ARG(name);
+
while ((c = (int)*name++) != 0)
h = ((h << 5) + h) + c;
return h;
@@ -388,6 +436,7 @@ int git_attr_file__lookup_one(
int git_attr_file__load_standalone(git_attr_file **out, const char *path)
{
git_buf content = GIT_BUF_INIT;
+ git_attr_file_source source = { GIT_ATTR_FILE_SOURCE_FILE };
git_attr_file *file = NULL;
int error;
@@ -399,9 +448,9 @@ int git_attr_file__load_standalone(git_attr_file **out, const char *path)
* don't have to free it - freeing file+pool will free cache entry, too.
*/
- if ((error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE__FROM_FILE)) < 0 ||
+ if ((error = git_attr_file__new(&file, NULL, &source)) < 0 ||
(error = git_attr_file__parse_buffer(NULL, file, content.ptr, true)) < 0 ||
- (error = git_attr_cache__alloc_file_entry(&file->entry, NULL, path, &file->pool)) < 0)
+ (error = git_attr_cache__alloc_file_entry(&file->entry, NULL, NULL, path, &file->pool)) < 0)
goto out;
*out = file;
@@ -501,7 +550,10 @@ git_attr_assignment *git_attr_rule__lookup_assignment(
}
int git_attr_path__init(
- git_attr_path *info, const char *path, const char *base, git_dir_flag dir_flag)
+ git_attr_path *info,
+ const char *path,
+ const char *base,
+ git_dir_flag dir_flag)
{
ssize_t root;
@@ -660,7 +712,8 @@ int git_attr_fnmatch__parse(
int slash_count, allow_space;
bool escaped;
- assert(spec && base && *base);
+ GIT_ASSERT_ARG(spec);
+ GIT_ASSERT_ARG(base && *base);
if (parse_optimized_patterns(spec, pool, *base))
return 0;
@@ -828,7 +881,7 @@ int git_attr_assignment__parse(
const char *scan = *base;
git_attr_assignment *assign = NULL;
- assert(assigns && !assigns->length);
+ GIT_ASSERT_ARG(assigns && !assigns->length);
git_vector_set_cmp(assigns, sort_by_hash_and_name);
@@ -954,10 +1007,10 @@ void git_attr_rule__free(git_attr_rule *rule)
int git_attr_session__init(git_attr_session *session, git_repository *repo)
{
- assert(repo);
+ GIT_ASSERT_ARG(repo);
memset(session, 0, sizeof(*session));
- session->key = git_atomic_inc(&repo->attr_session_key);
+ session->key = git_atomic32_inc(&repo->attr_session_key);
return 0;
}
diff --git a/src/attr_file.h b/src/attr_file.h
index 2b6b1d623..d634e6da9 100644
--- a/src/attr_file.h
+++ b/src/attr_file.h
@@ -37,12 +37,31 @@
(GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO)
typedef enum {
- GIT_ATTR_FILE__IN_MEMORY = 0,
- GIT_ATTR_FILE__FROM_FILE = 1,
- GIT_ATTR_FILE__FROM_INDEX = 2,
- GIT_ATTR_FILE__FROM_HEAD = 3,
+ GIT_ATTR_FILE_SOURCE_MEMORY = 0,
+ GIT_ATTR_FILE_SOURCE_FILE = 1,
+ GIT_ATTR_FILE_SOURCE_INDEX = 2,
+ GIT_ATTR_FILE_SOURCE_HEAD = 3,
+ GIT_ATTR_FILE_SOURCE_COMMIT = 4,
- GIT_ATTR_FILE_NUM_SOURCES = 4
+ GIT_ATTR_FILE_NUM_SOURCES = 5
+} git_attr_file_source_t;
+
+typedef struct {
+ /* The source location for the attribute file. */
+ git_attr_file_source_t type;
+
+ /*
+ * The filename of the attribute file to read (relative to the
+ * given base path).
+ */
+ const char *base;
+ const char *filename;
+
+ /*
+ * The commit ID when the given source type is a commit (or NULL
+ * for the repository's HEAD commit.)
+ */
+ git_oid *commit_id;
} git_attr_file_source;
extern const char *git_attr__true;
@@ -124,7 +143,7 @@ extern int git_attr_get_many_with_session(
const char **values_out,
git_repository *repo,
git_attr_session *attr_session,
- uint32_t flags,
+ git_attr_options *opts,
const char *path,
size_t num_attr,
const char **names);
@@ -142,7 +161,7 @@ typedef int (*git_attr_file_parser)(
int git_attr_file__new(
git_attr_file **out,
git_attr_file_entry *entry,
- git_attr_file_source source);
+ git_attr_file_source *source);
void git_attr_file__free(git_attr_file *file);
@@ -151,7 +170,7 @@ int git_attr_file__load(
git_repository *repo,
git_attr_session *attr_session,
git_attr_file_entry *ce,
- git_attr_file_source source,
+ git_attr_file_source *source,
git_attr_file_parser parser,
bool allow_macros);
@@ -159,7 +178,7 @@ int git_attr_file__load_standalone(
git_attr_file **out, const char *path);
int git_attr_file__out_of_date(
- git_repository *repo, git_attr_session *session, git_attr_file *file);
+ git_repository *repo, git_attr_session *session, git_attr_file *file, git_attr_file_source *source);
int git_attr_file__parse_buffer(
git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros);
@@ -207,8 +226,10 @@ extern git_attr_assignment *git_attr_rule__lookup_assignment(
typedef enum { GIT_DIR_FLAG_TRUE = 1, GIT_DIR_FLAG_FALSE = 0, GIT_DIR_FLAG_UNKNOWN = -1 } git_dir_flag;
extern int git_attr_path__init(
- git_attr_path *info, const char *path, const char *base, git_dir_flag is_dir);
-
+ git_attr_path *out,
+ const char *path,
+ const char *base,
+ git_dir_flag is_dir);
extern void git_attr_path__free(git_attr_path *info);
extern int git_attr_assignment__parse(
diff --git a/src/attrcache.c b/src/attrcache.c
index 47fb675e0..2b36b7a9c 100644
--- a/src/attrcache.c
+++ b/src/attrcache.c
@@ -38,6 +38,7 @@ GIT_INLINE(git_attr_file_entry *) attr_cache_lookup_entry(
int git_attr_cache__alloc_file_entry(
git_attr_file_entry **out,
+ git_repository *repo,
const char *base,
const char *path,
git_pool *pool)
@@ -65,6 +66,9 @@ int git_attr_cache__alloc_file_entry(
}
memcpy(&ce->fullpath[baselen], path, pathlen);
+ if (git_path_validate_workdir_with_len(repo, ce->fullpath, pathlen + baselen) < 0)
+ return -1;
+
ce->path = &ce->fullpath[baselen];
*out = ce;
@@ -79,8 +83,8 @@ static int attr_cache_make_entry(
git_attr_file_entry *entry = NULL;
int error;
- if ((error = git_attr_cache__alloc_file_entry(&entry, git_repository_workdir(repo),
- path, &cache->pool)) < 0)
+ if ((error = git_attr_cache__alloc_file_entry(&entry, repo,
+ git_repository_workdir(repo), path, &cache->pool)) < 0)
return error;
if ((error = git_strmap_set(cache->files, entry->path, entry)) < 0)
@@ -108,7 +112,7 @@ static int attr_cache_upsert(git_attr_cache *cache, git_attr_file *file)
* Replace the existing value if another thread has
* created it in the meantime.
*/
- old = git__swap(entry->file[file->source], file);
+ old = git_atomic_swap(entry->file[file->source.type], file);
if (old) {
GIT_REFCOUNT_OWN(old, NULL);
@@ -123,7 +127,7 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
{
int error = 0;
git_attr_file_entry *entry;
- git_attr_file *old = NULL;
+ git_attr_file *oldfile = NULL;
if (!file)
return 0;
@@ -132,13 +136,13 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
return error;
if ((entry = attr_cache_lookup_entry(cache, file->entry->path)) != NULL)
- old = git__compare_and_swap(&entry->file[file->source], file, NULL);
+ oldfile = git_atomic_compare_and_swap(&entry->file[file->source.type], file, NULL);
attr_cache_unlock(cache);
- if (old) {
- GIT_REFCOUNT_OWN(old, NULL);
- git_attr_file__free(old);
+ if (oldfile == file) {
+ GIT_REFCOUNT_OWN(file, NULL);
+ git_attr_file__free(file);
}
return error;
@@ -154,40 +158,42 @@ static int attr_cache_lookup(
git_attr_file_entry **out_entry,
git_repository *repo,
git_attr_session *attr_session,
- git_attr_file_source source,
- const char *base,
- const char *filename)
+ git_attr_file_source *source)
{
int error = 0;
git_buf path = GIT_BUF_INIT;
- const char *wd = git_repository_workdir(repo), *relfile;
+ const char *wd = git_repository_workdir(repo);
+ const char *filename;
git_attr_cache *cache = git_repository_attr_cache(repo);
git_attr_file_entry *entry = NULL;
git_attr_file *file = NULL;
/* join base and path as needed */
- if (base != NULL && git_path_root(filename) < 0) {
+ if (source->base != NULL && git_path_root(source->filename) < 0) {
git_buf *p = attr_session ? &attr_session->tmp : &path;
- if (git_buf_joinpath(p, base, filename) < 0)
+ if (git_buf_joinpath(p, source->base, source->filename) < 0 ||
+ git_path_validate_workdir_buf(repo, p) < 0)
return -1;
filename = p->ptr;
+ } else {
+ filename = source->filename;
}
- relfile = filename;
- if (wd && !git__prefixcmp(relfile, wd))
- relfile += strlen(wd);
+ if (wd && !git__prefixcmp(filename, wd))
+ filename += strlen(wd);
/* check cache for existing entry */
if ((error = attr_cache_lock(cache)) < 0)
goto cleanup;
- entry = attr_cache_lookup_entry(cache, relfile);
- if (!entry)
- error = attr_cache_make_entry(&entry, repo, relfile);
- else if (entry->file[source] != NULL) {
- file = entry->file[source];
+ entry = attr_cache_lookup_entry(cache, filename);
+
+ if (!entry) {
+ error = attr_cache_make_entry(&entry, repo, filename);
+ } else if (entry->file[source->type] != NULL) {
+ file = entry->file[source->type];
GIT_REFCOUNT_INC(file);
}
@@ -205,9 +211,7 @@ int git_attr_cache__get(
git_attr_file **out,
git_repository *repo,
git_attr_session *attr_session,
- git_attr_file_source source,
- const char *base,
- const char *filename,
+ git_attr_file_source *source,
git_attr_file_parser parser,
bool allow_macros)
{
@@ -216,19 +220,21 @@ int git_attr_cache__get(
git_attr_file_entry *entry = NULL;
git_attr_file *file = NULL, *updated = NULL;
- if ((error = attr_cache_lookup(
- &file, &entry, repo, attr_session, source, base, filename)) < 0)
+ if ((error = attr_cache_lookup(&file, &entry, repo, attr_session, source)) < 0)
return error;
/* load file if we don't have one or if existing one is out of date */
- if (!file || (error = git_attr_file__out_of_date(repo, attr_session, file)) > 0)
- error = git_attr_file__load(&updated, repo, attr_session, entry, source, parser, allow_macros);
+ if (!file ||
+ (error = git_attr_file__out_of_date(repo, attr_session, file, source)) > 0)
+ error = git_attr_file__load(&updated, repo, attr_session,
+ entry, source, parser,
+ allow_macros);
/* if we loaded the file, insert into and/or update cache */
if (updated) {
- if ((error = attr_cache_upsert(cache, updated)) < 0)
+ if ((error = attr_cache_upsert(cache, updated)) < 0) {
git_attr_file__free(updated);
- else {
+ } else {
git_attr_file__free(file); /* offset incref from lookup */
file = updated;
}
@@ -255,7 +261,7 @@ int git_attr_cache__get(
bool git_attr_cache__is_cached(
git_repository *repo,
- git_attr_file_source source,
+ git_attr_file_source_t source_type,
const char *filename)
{
git_attr_cache *cache = git_repository_attr_cache(repo);
@@ -268,7 +274,7 @@ bool git_attr_cache__is_cached(
if ((entry = git_strmap_get(files, filename)) == NULL)
return false;
- return entry && (entry->file[source] != NULL);
+ return entry && (entry->file[source_type] != NULL);
}
@@ -321,7 +327,7 @@ static void attr_cache__free(git_attr_cache *cache)
git_strmap_foreach_value(cache->files, entry, {
for (i = 0; i < GIT_ATTR_FILE_NUM_SOURCES; ++i) {
- if ((file = git__swap(entry->file[i], NULL)) != NULL) {
+ if ((file = git_atomic_swap(entry->file[i], NULL)) != NULL) {
GIT_REFCOUNT_OWN(file, NULL);
git_attr_file__free(file);
}
@@ -395,8 +401,7 @@ int git_attr_cache__init(git_repository *repo)
(ret = git_pool_init(&cache->pool, 1)) < 0)
goto cancel;
- cache = git__compare_and_swap(&repo->attrcache, NULL, cache);
- if (cache)
+ if (git_atomic_compare_and_swap(&repo->attrcache, NULL, cache) != NULL)
goto cancel; /* raced with another thread, free this but no error */
git_config_free(cfg);
@@ -417,7 +422,7 @@ int git_attr_cache_flush(git_repository *repo)
/* this could be done less expensively, but for now, we'll just free
* the entire attrcache and let the next use reinitialize it...
*/
- if (repo && (cache = git__swap(repo->attrcache, NULL)) != NULL)
+ if (repo && (cache = git_atomic_swap(repo->attrcache, NULL)) != NULL)
attr_cache__free(cache);
return 0;
diff --git a/src/attrcache.h b/src/attrcache.h
index 4b1d5ce31..b13e0e8f0 100644
--- a/src/attrcache.h
+++ b/src/attrcache.h
@@ -31,19 +31,18 @@ extern int git_attr_cache__get(
git_attr_file **file,
git_repository *repo,
git_attr_session *attr_session,
- git_attr_file_source source,
- const char *base,
- const char *filename,
+ git_attr_file_source *source,
git_attr_file_parser parser,
bool allow_macros);
extern bool git_attr_cache__is_cached(
git_repository *repo,
- git_attr_file_source source,
- const char *path);
+ git_attr_file_source_t source_type,
+ const char *filename);
extern int git_attr_cache__alloc_file_entry(
git_attr_file_entry **out,
+ git_repository *repo,
const char *base,
const char *path,
git_pool *pool);
diff --git a/src/blame.c b/src/blame.c
index 1046dab55..a6ab43efd 100644
--- a/src/blame.c
+++ b/src/blame.c
@@ -59,7 +59,7 @@ static bool hunk_starts_at_or_after_line(git_blame_hunk *hunk, size_t line)
return line <= hunk->final_start_line_number;
}
-static git_blame_hunk* new_hunk(
+static git_blame_hunk *new_hunk(
size_t start,
size_t lines,
size_t orig_start,
@@ -76,7 +76,15 @@ static git_blame_hunk* new_hunk(
return hunk;
}
-static git_blame_hunk* dup_hunk(git_blame_hunk *hunk)
+static void free_hunk(git_blame_hunk *hunk)
+{
+ git__free((void*)hunk->orig_path);
+ git_signature_free(hunk->final_signature);
+ git_signature_free(hunk->orig_signature);
+ git__free(hunk);
+}
+
+static git_blame_hunk *dup_hunk(git_blame_hunk *hunk)
{
git_blame_hunk *newhunk = new_hunk(
hunk->final_start_line_number,
@@ -90,17 +98,14 @@ static git_blame_hunk* dup_hunk(git_blame_hunk *hunk)
git_oid_cpy(&newhunk->orig_commit_id, &hunk->orig_commit_id);
git_oid_cpy(&newhunk->final_commit_id, &hunk->final_commit_id);
newhunk->boundary = hunk->boundary;
- git_signature_dup(&newhunk->final_signature, hunk->final_signature);
- git_signature_dup(&newhunk->orig_signature, hunk->orig_signature);
- return newhunk;
-}
-static void free_hunk(git_blame_hunk *hunk)
-{
- git__free((void*)hunk->orig_path);
- git_signature_free(hunk->final_signature);
- git_signature_free(hunk->orig_signature);
- git__free(hunk);
+ if (git_signature_dup(&newhunk->final_signature, hunk->final_signature) < 0 ||
+ git_signature_dup(&newhunk->orig_signature, hunk->orig_signature) < 0) {
+ free_hunk(newhunk);
+ return NULL;
+ }
+
+ return newhunk;
}
/* Starting with the hunk that includes start_line, shift all following hunks'
@@ -117,7 +122,7 @@ static void shift_hunks_by(git_vector *v, size_t start_line, int shift_by)
}
}
-git_blame* git_blame__alloc(
+git_blame *git_blame__alloc(
git_repository *repo,
git_blame_options opts,
const char *path)
@@ -171,20 +176,21 @@ void git_blame_free(git_blame *blame)
uint32_t git_blame_get_hunk_count(git_blame *blame)
{
- assert(blame);
+ GIT_ASSERT_ARG(blame);
return (uint32_t)blame->hunks.length;
}
const git_blame_hunk *git_blame_get_hunk_byindex(git_blame *blame, uint32_t index)
{
- assert(blame);
+ GIT_ASSERT_ARG_WITH_RETVAL(blame, NULL);
return (git_blame_hunk*)git_vector_get(&blame->hunks, index);
}
const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, size_t lineno)
{
size_t i, new_lineno = lineno;
- assert(blame);
+
+ GIT_ASSERT_ARG_WITH_RETVAL(blame, NULL);
if (!git_vector_bsearch2(&i, &blame->hunks, hunk_byfinalline_search_cmp, &new_lineno)) {
return git_blame_get_hunk_byindex(blame, (uint32_t)i);
@@ -293,7 +299,7 @@ static int index_blob_lines(git_blame *blame)
return blame->num_lines;
}
-static git_blame_hunk* hunk_from_entry(git_blame__entry *e, git_blame *blame)
+static git_blame_hunk *hunk_from_entry(git_blame__entry *e, git_blame *blame)
{
git_blame_hunk *h = new_hunk(
e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path);
@@ -388,7 +394,10 @@ int git_blame_file(
git_blame_options normOptions = GIT_BLAME_OPTIONS_INIT;
git_blame *blame = NULL;
- assert(out && repo && path);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(path);
+
if ((error = normalize_options(&normOptions, options, repo)) < 0)
goto on_error;
@@ -509,7 +518,9 @@ int git_blame_buffer(
diffopts.context_lines = 0;
- assert(out && reference && buffer && buffer_len);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(reference);
+ GIT_ASSERT_ARG(buffer && buffer_len);
blame = git_blame__alloc(reference->repository, reference->options, reference->path);
GIT_ERROR_CHECK_ALLOC(blame);
diff --git a/src/blame_git.c b/src/blame_git.c
index 073137a68..3d514a1bc 100644
--- a/src/blame_git.c
+++ b/src/blame_git.c
@@ -429,7 +429,7 @@ static int paths_on_dup(void **old, void *new)
return -1;
}
-static git_blame__origin* find_origin(
+static git_blame__origin *find_origin(
git_blame *blame,
git_commit *parent,
git_blame__origin *origin)
diff --git a/src/blob.c b/src/blob.c
index da4e6ffa5..09b5b5d91 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -14,11 +14,11 @@
#include "filebuf.h"
#include "filter.h"
-#include "buf_text.h"
const void *git_blob_rawcontent(const git_blob *blob)
{
- assert(blob);
+ GIT_ASSERT_ARG_WITH_RETVAL(blob, NULL);
+
if (blob->raw)
return blob->data.raw.data;
else
@@ -27,7 +27,8 @@ const void *git_blob_rawcontent(const git_blob *blob)
git_object_size_t git_blob_rawsize(const git_blob *blob)
{
- assert(blob);
+ GIT_ASSERT_ARG(blob);
+
if (blob->raw)
return blob->data.raw.size;
else
@@ -53,7 +54,9 @@ void git_blob__free(void *_blob)
int git_blob__parse_raw(void *_blob, const char *data, size_t size)
{
git_blob *blob = (git_blob *) _blob;
- assert(blob);
+
+ GIT_ASSERT_ARG(blob);
+
blob->raw = 1;
blob->data.raw.data = data;
blob->data.raw.size = size;
@@ -63,7 +66,9 @@ int git_blob__parse_raw(void *_blob, const char *data, size_t size)
int git_blob__parse(void *_blob, git_odb_object *odb_obj)
{
git_blob *blob = (git_blob *) _blob;
- assert(blob);
+
+ GIT_ASSERT_ARG(blob);
+
git_cached_obj_incref((git_cached_obj *)odb_obj);
blob->raw = 0;
blob->data.odb = odb_obj;
@@ -77,7 +82,8 @@ int git_blob_create_from_buffer(
git_odb *odb;
git_odb_stream *stream;
- assert(id && repo);
+ GIT_ASSERT_ARG(id);
+ GIT_ASSERT_ARG(repo);
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
(error = git_odb_open_wstream(&stream, odb, len, GIT_OBJECT_BLOB)) < 0)
@@ -132,12 +138,13 @@ static int write_file_filtered(
git_object_size_t *size,
git_odb *odb,
const char *full_path,
- git_filter_list *fl)
+ git_filter_list *fl,
+ git_repository* repo)
{
int error;
git_buf tgt = GIT_BUF_INIT;
- error = git_filter_list_apply_to_file(&tgt, fl, NULL, full_path);
+ error = git_filter_list_apply_to_file(&tgt, fl, repo, full_path);
/* Write the file to disk if it was properly filtered */
if (!error) {
@@ -188,14 +195,10 @@ int git_blob__create_from_paths(
mode_t mode;
git_buf path = GIT_BUF_INIT;
- assert(hint_path || !try_load_filters);
+ GIT_ASSERT_ARG(hint_path || !try_load_filters);
if (!content_path) {
- if (git_repository__ensure_not_bare(repo, "create blob from file") < 0)
- return GIT_EBAREREPO;
-
- if (git_buf_joinpath(
- &path, git_repository_workdir(repo), hint_path) < 0)
+ if (git_repository_workdir_path(&path, repo, hint_path) < 0)
return -1;
content_path = path.ptr;
@@ -236,7 +239,7 @@ int git_blob__create_from_paths(
error = write_file_stream(id, odb, content_path, size);
else {
/* We need to apply one or more filters */
- error = write_file_filtered(id, &size, odb, content_path, fl);
+ error = write_file_filtered(id, &size, odb, content_path, fl, repo);
git_filter_list_free(fl);
}
@@ -274,21 +277,20 @@ int git_blob_create_from_disk(
{
int error;
git_buf full_path = GIT_BUF_INIT;
- const char *workdir, *hintpath;
+ const char *workdir, *hintpath = NULL;
if ((error = git_path_prettify(&full_path, path, NULL)) < 0) {
git_buf_dispose(&full_path);
return error;
}
- hintpath = git_buf_cstr(&full_path);
workdir = git_repository_workdir(repo);
- if (workdir && !git__prefixcmp(hintpath, workdir))
- hintpath += strlen(workdir);
+ if (workdir && !git__prefixcmp(full_path.ptr, workdir))
+ hintpath = full_path.ptr + strlen(workdir);
error = git_blob__create_from_paths(
- id, NULL, repo, git_buf_cstr(&full_path), hintpath, 0, true);
+ id, NULL, repo, git_buf_cstr(&full_path), hintpath, 0, !!hintpath);
git_buf_dispose(&full_path);
return error;
@@ -331,7 +333,8 @@ int git_blob_create_from_stream(git_writestream **out, git_repository *repo, con
git_buf path = GIT_BUF_INIT;
blob_writestream *stream;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
stream = git__calloc(1, sizeof(blob_writestream));
GIT_ERROR_CHECK_ALLOC(stream);
@@ -391,13 +394,22 @@ int git_blob_is_binary(const git_blob *blob)
git_buf content = GIT_BUF_INIT;
git_object_size_t size;
- assert(blob);
+ GIT_ASSERT_ARG(blob);
size = git_blob_rawsize(blob);
git_buf_attach_notowned(&content, git_blob_rawcontent(blob),
(size_t)min(size, GIT_FILTER_BYTES_TO_CHECK_NUL));
- return git_buf_text_is_binary(&content);
+ return git_buf_is_binary(&content);
+}
+
+int git_blob_filter_options_init(
+ git_blob_filter_options *opts,
+ unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(opts, version,
+ git_blob_filter_options, GIT_BLOB_FILTER_OPTIONS_INIT);
+ return 0;
}
int git_blob_filter(
@@ -409,15 +421,18 @@ int git_blob_filter(
int error = 0;
git_filter_list *fl = NULL;
git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
- git_filter_flag_t flags = GIT_FILTER_DEFAULT;
-
- assert(blob && path && out);
+ git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
- git_buf_sanitize(out);
+ GIT_ASSERT_ARG(blob);
+ GIT_ASSERT_ARG(path);
+ GIT_ASSERT_ARG(out);
GIT_ERROR_CHECK_VERSION(
given_opts, GIT_BLOB_FILTER_OPTIONS_VERSION, "git_blob_filter_options");
+ if (git_buf_sanitize(out) < 0)
+ return -1;
+
if (given_opts != NULL)
memcpy(&opts, given_opts, sizeof(git_blob_filter_options));
@@ -426,14 +441,25 @@ int git_blob_filter(
return 0;
if ((opts.flags & GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES) != 0)
- flags |= GIT_FILTER_NO_SYSTEM_ATTRIBUTES;
+ filter_opts.flags |= GIT_FILTER_NO_SYSTEM_ATTRIBUTES;
+
+ if ((opts.flags & GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD) != 0)
+ filter_opts.flags |= GIT_FILTER_ATTRIBUTES_FROM_HEAD;
- if ((opts.flags & GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD) != 0)
- flags |= GIT_FILTER_ATTRIBUTES_FROM_HEAD;
+ if ((opts.flags & GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT) != 0) {
+ filter_opts.flags |= GIT_FILTER_ATTRIBUTES_FROM_COMMIT;
+
+#ifndef GIT_DEPRECATE_HARD
+ if (opts.commit_id)
+ git_oid_cpy(&filter_opts.attr_commit_id, opts.commit_id);
+ else
+#endif
+ git_oid_cpy(&filter_opts.attr_commit_id, &opts.attr_commit_id);
+ }
- if (!(error = git_filter_list_load(
+ if (!(error = git_filter_list_load_ext(
&fl, git_blob_owner(blob), blob, path,
- GIT_FILTER_TO_WORKTREE, flags))) {
+ GIT_FILTER_TO_WORKTREE, &filter_opts))) {
error = git_filter_list_apply_to_blob(out, fl, blob);
diff --git a/src/branch.c b/src/branch.c
index 770c9a1ee..e6818a86d 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -67,8 +67,10 @@ static int create_branch(
int error = -1;
int bare = git_repository_is_bare(repository);
- assert(branch_name && commit && ref_out);
- assert(git_object_owner((const git_object *)commit) == repository);
+ GIT_ASSERT_ARG(branch_name);
+ GIT_ASSERT_ARG(commit);
+ GIT_ASSERT_ARG(ref_out);
+ GIT_ASSERT_ARG(git_commit_owner(commit) == repository);
if (!git__strcmp(branch_name, "HEAD")) {
git_error_set(GIT_ERROR_REFERENCE, "'HEAD' is not a valid branch name");
@@ -134,39 +136,39 @@ int git_branch_create_from_annotated(
repository, branch_name, commit->commit, commit->description, force);
}
-static int branch_equals(git_repository *repo, const char *path, void *payload)
+static int branch_is_checked_out(git_repository *worktree, void *payload)
{
git_reference *branch = (git_reference *) payload;
git_reference *head = NULL;
- int equal = 0;
+ int error;
- if (git_reference__read_head(&head, repo, path) < 0 ||
- git_reference_type(head) != GIT_REFERENCE_SYMBOLIC)
- goto done;
+ if (git_repository_is_bare(worktree))
+ return 0;
- equal = !git__strcmp(head->target.symbolic, branch->name);
+ if ((error = git_reference_lookup(&head, worktree, GIT_HEAD_FILE)) < 0) {
+ if (error == GIT_ENOTFOUND)
+ error = 0;
+ goto out;
+ }
-done:
+ if (git_reference_type(head) != GIT_REFERENCE_SYMBOLIC)
+ goto out;
+
+ error = !git__strcmp(head->target.symbolic, branch->name);
+
+out:
git_reference_free(head);
- return equal;
+ return error;
}
int git_branch_is_checked_out(const git_reference *branch)
{
- git_repository *repo;
- int flags = 0;
-
- assert(branch);
+ GIT_ASSERT_ARG(branch);
if (!git_reference_is_branch(branch))
return 0;
-
- repo = git_reference_owner(branch);
-
- if (git_repository_is_bare(repo))
- flags |= GIT_REPOSITORY_FOREACH_HEAD_SKIP_REPO;
-
- return git_repository_foreach_head(repo, branch_equals, flags, (void *) branch) == 1;
+ return git_repository_foreach_worktree(git_reference_owner(branch),
+ branch_is_checked_out, (void *)branch) == 1;
}
int git_branch_delete(git_reference *branch)
@@ -175,7 +177,7 @@ int git_branch_delete(git_reference *branch)
git_buf config_section = GIT_BUF_INIT;
int error = -1;
- assert(branch);
+ GIT_ASSERT_ARG(branch);
if (!git_reference_is_branch(branch) && !git_reference_is_remote(branch)) {
git_error_set(GIT_ERROR_INVALID, "reference '%s' is not a valid branch.",
@@ -290,7 +292,8 @@ int git_branch_move(
log_message = GIT_BUF_INIT;
int error;
- assert(branch && new_branch_name);
+ GIT_ASSERT_ARG(branch);
+ GIT_ASSERT_ARG(new_branch_name);
if (!git_reference_is_branch(branch))
return not_a_local_branch(git_reference_name(branch));
@@ -335,7 +338,10 @@ int git_branch_lookup(
git_branch_t branch_type)
{
int error = -1;
- assert(ref_out && repo && branch_name);
+
+ GIT_ASSERT_ARG(ref_out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(branch_name);
switch (branch_type) {
case GIT_BRANCH_LOCAL:
@@ -348,7 +354,7 @@ int git_branch_lookup(
error = retrieve_branch_reference(ref_out, repo, branch_name, true);
break;
default:
- assert(false);
+ GIT_ASSERT(false);
}
return error;
}
@@ -359,7 +365,8 @@ int git_branch_name(
{
const char *branch_name;
- assert(out && ref);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(ref);
branch_name = ref->name;
@@ -407,9 +414,11 @@ int git_branch_upstream_name(
const git_refspec *refspec;
git_config *config;
- assert(out && refname);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(refname);
- git_buf_sanitize(out);
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
if (!git_reference__is_branch(refname))
return not_a_local_branch(refname);
@@ -459,7 +468,7 @@ cleanup:
return error;
}
-int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname)
+static int git_branch_upstream_with_format(git_buf *buf, git_repository *repo, const char *refname, const char *format, const char *format_name)
{
int error;
git_config *cfg;
@@ -470,13 +479,12 @@ int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *r
if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
return error;
- git_buf_sanitize(buf);
-
- if ((error = retrieve_upstream_configuration(buf, cfg, refname, "branch.%s.remote")) < 0)
+ if ((error = git_buf_sanitize(buf)) < 0 ||
+ (error = retrieve_upstream_configuration(buf, cfg, refname, format)) < 0)
return error;
if (git_buf_len(buf) == 0) {
- git_error_set(GIT_ERROR_REFERENCE, "branch '%s' does not have an upstream remote", refname);
+ git_error_set(GIT_ERROR_REFERENCE, "branch '%s' does not have an upstream %s", refname, format_name);
error = GIT_ENOTFOUND;
git_buf_clear(buf);
}
@@ -484,6 +492,16 @@ int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *r
return error;
}
+int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname)
+{
+ return git_branch_upstream_with_format(buf, repo, refname, "branch.%s.remote", "remote");
+}
+
+int git_branch_upstream_merge(git_buf *buf, git_repository *repo, const char *refname)
+{
+ return git_branch_upstream_with_format(buf, repo, refname, "branch.%s.merge", "merge");
+}
+
int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refname)
{
git_strarray remote_list = {0};
@@ -493,9 +511,12 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
int error = 0;
char *remote_name = NULL;
- assert(buf && repo && refname);
+ GIT_ASSERT_ARG(buf);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(refname);
- git_buf_sanitize(buf);
+ if ((error = git_buf_sanitize(buf)) < 0)
+ return error;
/* Verify that this is a remote branch */
if (!git_reference__is_remote(refname)) {
@@ -704,7 +725,7 @@ int git_branch_is_head(
bool is_same = false;
int error;
- assert(branch);
+ GIT_ASSERT_ARG(branch);
if (!git_reference_is_branch(branch))
return false;
@@ -725,3 +746,32 @@ int git_branch_is_head(
return is_same;
}
+
+int git_branch_name_is_valid(int *valid, const char *name)
+{
+ git_buf ref_name = GIT_BUF_INIT;
+ int error = 0;
+
+ GIT_ASSERT(valid);
+
+ *valid = 0;
+
+ /*
+ * Discourage branch name starting with dash,
+ * https://github.com/git/git/commit/6348624010888b
+ * and discourage HEAD as branch name,
+ * https://github.com/git/git/commit/a625b092cc5994
+ */
+ if (!name || name[0] == '-' || !git__strcmp(name, "HEAD"))
+ goto done;
+
+ if ((error = git_buf_puts(&ref_name, GIT_REFS_HEADS_DIR)) < 0 ||
+ (error = git_buf_puts(&ref_name, name)) < 0)
+ goto done;
+
+ error = git_reference_name_is_valid(valid, ref_name.ptr);
+
+done:
+ git_buf_dispose(&ref_name);
+ return error;
+}
diff --git a/src/buf_text.c b/src/buf_text.c
deleted file mode 100644
index 88fcb87dd..000000000
--- a/src/buf_text.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#include "buf_text.h"
-
-int git_buf_text_puts_escaped(
- git_buf *buf,
- const char *string,
- const char *esc_chars,
- const char *esc_with)
-{
- const char *scan;
- size_t total = 0, esc_len = strlen(esc_with), count, alloclen;
-
- if (!string)
- return 0;
-
- for (scan = string; *scan; ) {
- /* count run of non-escaped characters */
- count = strcspn(scan, esc_chars);
- total += count;
- scan += count;
- /* count run of escaped characters */
- count = strspn(scan, esc_chars);
- total += count * (esc_len + 1);
- scan += count;
- }
-
- GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, total, 1);
- if (git_buf_grow_by(buf, alloclen) < 0)
- return -1;
-
- for (scan = string; *scan; ) {
- count = strcspn(scan, esc_chars);
-
- memmove(buf->ptr + buf->size, scan, count);
- scan += count;
- buf->size += count;
-
- for (count = strspn(scan, esc_chars); count > 0; --count) {
- /* copy escape sequence */
- memmove(buf->ptr + buf->size, esc_with, esc_len);
- buf->size += esc_len;
- /* copy character to be escaped */
- buf->ptr[buf->size] = *scan;
- buf->size++;
- scan++;
- }
- }
-
- buf->ptr[buf->size] = '\0';
-
- return 0;
-}
-
-void git_buf_text_unescape(git_buf *buf)
-{
- buf->size = git__unescape(buf->ptr);
-}
-
-int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src)
-{
- const char *scan = src->ptr;
- const char *scan_end = src->ptr + src->size;
- const char *next = memchr(scan, '\r', src->size);
- size_t new_size;
- char *out;
-
- assert(tgt != src);
-
- if (!next)
- return git_buf_set(tgt, src->ptr, src->size);
-
- /* reduce reallocs while in the loop */
- GIT_ERROR_CHECK_ALLOC_ADD(&new_size, src->size, 1);
- if (git_buf_grow(tgt, new_size) < 0)
- return -1;
-
- out = tgt->ptr;
- tgt->size = 0;
-
- /* Find the next \r and copy whole chunk up to there to tgt */
- for (; next; scan = next + 1, next = memchr(scan, '\r', scan_end - scan)) {
- if (next > scan) {
- size_t copylen = (size_t)(next - scan);
- memcpy(out, scan, copylen);
- out += copylen;
- }
-
- /* Do not drop \r unless it is followed by \n */
- if (next + 1 == scan_end || next[1] != '\n')
- *out++ = '\r';
- }
-
- /* Copy remaining input into dest */
- if (scan < scan_end) {
- size_t remaining = (size_t)(scan_end - scan);
- memcpy(out, scan, remaining);
- out += remaining;
- }
-
- tgt->size = (size_t)(out - tgt->ptr);
- tgt->ptr[tgt->size] = '\0';
-
- return 0;
-}
-
-int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
-{
- const char *start = src->ptr;
- const char *end = start + src->size;
- const char *scan = start;
- const char *next = memchr(scan, '\n', src->size);
- size_t alloclen;
-
- assert(tgt != src);
-
- if (!next)
- return git_buf_set(tgt, src->ptr, src->size);
-
- /* attempt to reduce reallocs while in the loop */
- GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, src->size, src->size >> 4);
- GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
- if (git_buf_grow(tgt, alloclen) < 0)
- return -1;
- tgt->size = 0;
-
- for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) {
- size_t copylen = next - scan;
-
- /* if we find mixed line endings, carry on */
- if (copylen && next[-1] == '\r')
- copylen--;
-
- GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
- if (git_buf_grow_by(tgt, alloclen) < 0)
- return -1;
-
- if (copylen) {
- memcpy(tgt->ptr + tgt->size, scan, copylen);
- tgt->size += copylen;
- }
-
- tgt->ptr[tgt->size++] = '\r';
- tgt->ptr[tgt->size++] = '\n';
- }
-
- tgt->ptr[tgt->size] = '\0';
- return git_buf_put(tgt, scan, end - scan);
-}
-
-int git_buf_text_common_prefix(git_buf *buf, const git_strarray *strings)
-{
- size_t i;
- const char *str, *pfx;
-
- git_buf_clear(buf);
-
- if (!strings || !strings->count)
- return 0;
-
- /* initialize common prefix to first string */
- if (git_buf_sets(buf, strings->strings[0]) < 0)
- return -1;
-
- /* go through the rest of the strings, truncating to shared prefix */
- for (i = 1; i < strings->count; ++i) {
-
- for (str = strings->strings[i], pfx = buf->ptr;
- *str && *str == *pfx; str++, pfx++)
- /* scanning */;
-
- git_buf_truncate(buf, pfx - buf->ptr);
-
- if (!buf->size)
- break;
- }
-
- return 0;
-}
-
-bool git_buf_text_is_binary(const git_buf *buf)
-{
- const char *scan = buf->ptr, *end = buf->ptr + buf->size;
- git_bom_t bom;
- int printable = 0, nonprintable = 0;
-
- scan += git_buf_text_detect_bom(&bom, buf);
-
- if (bom > GIT_BOM_UTF8)
- return 1;
-
- while (scan < end) {
- unsigned char c = *scan++;
-
- /* Printable characters are those above SPACE (0x1F) excluding DEL,
- * and including BS, ESC and FF.
- */
- if ((c > 0x1F && c != 127) || c == '\b' || c == '\033' || c == '\014')
- printable++;
- else if (c == '\0')
- return true;
- else if (!git__isspace(c))
- nonprintable++;
- }
-
- return ((printable >> 7) < nonprintable);
-}
-
-bool git_buf_text_contains_nul(const git_buf *buf)
-{
- return (memchr(buf->ptr, '\0', buf->size) != NULL);
-}
-
-int git_buf_text_detect_bom(git_bom_t *bom, const git_buf *buf)
-{
- const char *ptr;
- size_t len;
-
- *bom = GIT_BOM_NONE;
- /* need at least 2 bytes to look for any BOM */
- if (buf->size < 2)
- return 0;
-
- ptr = buf->ptr;
- len = buf->size;
-
- switch (*ptr++) {
- case 0:
- if (len >= 4 && ptr[0] == 0 && ptr[1] == '\xFE' && ptr[2] == '\xFF') {
- *bom = GIT_BOM_UTF32_BE;
- return 4;
- }
- break;
- case '\xEF':
- if (len >= 3 && ptr[0] == '\xBB' && ptr[1] == '\xBF') {
- *bom = GIT_BOM_UTF8;
- return 3;
- }
- break;
- case '\xFE':
- if (*ptr == '\xFF') {
- *bom = GIT_BOM_UTF16_BE;
- return 2;
- }
- break;
- case '\xFF':
- if (*ptr != '\xFE')
- break;
- if (len >= 4 && ptr[1] == 0 && ptr[2] == 0) {
- *bom = GIT_BOM_UTF32_LE;
- return 4;
- } else {
- *bom = GIT_BOM_UTF16_LE;
- return 2;
- }
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-bool git_buf_text_gather_stats(
- git_buf_text_stats *stats, const git_buf *buf, bool skip_bom)
-{
- const char *scan = buf->ptr, *end = buf->ptr + buf->size;
- int skip;
-
- memset(stats, 0, sizeof(*stats));
-
- /* BOM detection */
- skip = git_buf_text_detect_bom(&stats->bom, buf);
- if (skip_bom)
- scan += skip;
-
- /* Ignore EOF character */
- if (buf->size > 0 && end[-1] == '\032')
- end--;
-
- /* Counting loop */
- while (scan < end) {
- unsigned char c = *scan++;
-
- if (c > 0x1F && c != 0x7F)
- stats->printable++;
- else switch (c) {
- case '\0':
- stats->nul++;
- stats->nonprintable++;
- break;
- case '\n':
- stats->lf++;
- break;
- case '\r':
- stats->cr++;
- if (scan < end && *scan == '\n')
- stats->crlf++;
- break;
- case '\t': case '\f': case '\v': case '\b': case 0x1b: /*ESC*/
- stats->printable++;
- break;
- default:
- stats->nonprintable++;
- break;
- }
- }
-
- /* Treat files with a bare CR as binary */
- return (stats->cr != stats->crlf || stats->nul > 0 ||
- ((stats->printable >> 7) < stats->nonprintable));
-}
diff --git a/src/buf_text.h b/src/buf_text.h
deleted file mode 100644
index 726b0ae7b..000000000
--- a/src/buf_text.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef INCLUDE_buf_text_h__
-#define INCLUDE_buf_text_h__
-
-#include "common.h"
-
-#include "buffer.h"
-
-typedef enum {
- GIT_BOM_NONE = 0,
- GIT_BOM_UTF8 = 1,
- GIT_BOM_UTF16_LE = 2,
- GIT_BOM_UTF16_BE = 3,
- GIT_BOM_UTF32_LE = 4,
- GIT_BOM_UTF32_BE = 5
-} git_bom_t;
-
-typedef struct {
- git_bom_t bom; /* BOM found at head of text */
- unsigned int nul, cr, lf, crlf; /* NUL, CR, LF and CRLF counts */
- unsigned int printable, nonprintable; /* These are just approximations! */
-} git_buf_text_stats;
-
-/**
- * Append string to buffer, prefixing each character from `esc_chars` with
- * `esc_with` string.
- *
- * @param buf Buffer to append data to
- * @param string String to escape and append
- * @param esc_chars Characters to be escaped
- * @param esc_with String to insert in from of each found character
- * @return 0 on success, <0 on failure (probably allocation problem)
- */
-extern int git_buf_text_puts_escaped(
- git_buf *buf,
- const char *string,
- const char *esc_chars,
- const char *esc_with);
-
-/**
- * Append string escaping characters that are regex special
- */
-GIT_INLINE(int) git_buf_text_puts_escape_regex(git_buf *buf, const char *string)
-{
- return git_buf_text_puts_escaped(buf, string, "^.[]$()|*+?{}\\", "\\");
-}
-
-/**
- * Unescape all characters in a buffer in place
- *
- * I.e. remove backslashes
- */
-extern void git_buf_text_unescape(git_buf *buf);
-
-/**
- * Replace all \r\n with \n.
- *
- * @return 0 on success, -1 on memory error
- */
-extern int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src);
-
-/**
- * Replace all \n with \r\n. Does not modify existing \r\n.
- *
- * @return 0 on success, -1 on memory error
- */
-extern int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src);
-
-/**
- * Fill buffer with the common prefix of a array of strings
- *
- * Buffer will be set to empty if there is no common prefix
- */
-extern int git_buf_text_common_prefix(git_buf *buf, const git_strarray *strs);
-
-/**
- * Check quickly if buffer looks like it contains binary data
- *
- * @param buf Buffer to check
- * @return true if buffer looks like non-text data
- */
-extern bool git_buf_text_is_binary(const git_buf *buf);
-
-/**
- * Check quickly if buffer contains a NUL byte
- *
- * @param buf Buffer to check
- * @return true if buffer contains a NUL byte
- */
-extern bool git_buf_text_contains_nul(const git_buf *buf);
-
-/**
- * Check if a buffer begins with a UTF BOM
- *
- * @param bom Set to the type of BOM detected or GIT_BOM_NONE
- * @param buf Buffer in which to check the first bytes for a BOM
- * @return Number of bytes of BOM data (or 0 if no BOM found)
- */
-extern int git_buf_text_detect_bom(git_bom_t *bom, const git_buf *buf);
-
-/**
- * Gather stats for a piece of text
- *
- * Fill the `stats` structure with counts of unreadable characters, carriage
- * returns, etc, so it can be used in heuristics. This automatically skips
- * a trailing EOF (\032 character). Also it will look for a BOM at the
- * start of the text and can be told to skip that as well.
- *
- * @param stats Structure to be filled in
- * @param buf Text to process
- * @param skip_bom Exclude leading BOM from stats if true
- * @return Does the buffer heuristically look like binary data
- */
-extern bool git_buf_text_gather_stats(
- git_buf_text_stats *stats, const git_buf *buf, bool skip_bom);
-
-#endif
diff --git a/src/buffer.c b/src/buffer.c
index 3ee2775b1..fe087ea11 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -7,7 +7,6 @@
#include "buffer.h"
#include "posix.h"
#include "git2/buffer.h"
-#include "buf_text.h"
#include <ctype.h>
/* Used as default value for git_buf->ptr so that people can always
@@ -140,13 +139,17 @@ void git_buf_free(git_buf *buf)
}
#endif
-void git_buf_sanitize(git_buf *buf)
+int git_buf_sanitize(git_buf *buf)
{
if (buf->ptr == NULL) {
- assert(buf->size == 0 && buf->asize == 0);
+ GIT_ASSERT_ARG(buf->size == 0 && buf->asize == 0);
+
buf->ptr = git_buf__initbuf;
- } else if (buf->asize > buf->size)
+ } else if (buf->asize > buf->size) {
buf->ptr[buf->size] = '\0';
+ }
+
+ return 0;
}
void git_buf_clear(git_buf *buf)
@@ -183,16 +186,6 @@ int git_buf_set(git_buf *buf, const void *data, size_t len)
return 0;
}
-int git_buf_is_binary(const git_buf *buf)
-{
- return git_buf_text_is_binary(buf);
-}
-
-int git_buf_contains_nul(const git_buf *buf)
-{
- return git_buf_text_contains_nul(buf);
-}
-
int git_buf_sets(git_buf *buf, const char *string)
{
return git_buf_set(buf, string, string ? strlen(string) : 0);
@@ -225,7 +218,7 @@ int git_buf_put(git_buf *buf, const char *data, size_t len)
if (len) {
size_t new_size;
- assert(data);
+ GIT_ASSERT_ARG(data);
GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len);
GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
@@ -239,7 +232,8 @@ int git_buf_put(git_buf *buf, const char *data, size_t len)
int git_buf_puts(git_buf *buf, const char *string)
{
- assert(string);
+ GIT_ASSERT_ARG(string);
+
return git_buf_put(buf, string, strlen(string));
}
@@ -319,7 +313,7 @@ int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len)
return -1;
}
- assert(len % 4 == 0);
+ GIT_ASSERT_ARG(len % 4 == 0);
GIT_ERROR_CHECK_ALLOC_ADD(&new_size, (len / 4 * 3), buf->size);
GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
ENSURE_SIZE(buf, new_size);
@@ -365,7 +359,7 @@ int git_buf_encode_base85(git_buf *buf, const char *data, size_t len)
for (i = 24; i >= 0; i -= 8) {
uint8_t ch = *data++;
- acc |= ch << i;
+ acc |= (uint32_t)ch << i;
if (--len == 0)
break;
@@ -551,22 +545,26 @@ int git_buf_printf(git_buf *buf, const char *format, ...)
return r;
}
-void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf)
+int git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf)
{
size_t copylen;
- assert(data && datasize && buf);
+ GIT_ASSERT_ARG(data);
+ GIT_ASSERT_ARG(datasize);
+ GIT_ASSERT_ARG(buf);
data[0] = '\0';
if (buf->size == 0 || buf->asize <= 0)
- return;
+ return 0;
copylen = buf->size;
if (copylen > datasize - 1)
copylen = datasize - 1;
memmove(data, buf->ptr, copylen);
data[copylen] = '\0';
+
+ return 0;
}
void git_buf_consume_bytes(git_buf *buf, size_t len)
@@ -602,6 +600,13 @@ void git_buf_shorten(git_buf *buf, size_t amount)
git_buf_clear(buf);
}
+void git_buf_truncate_at_char(git_buf *buf, char separator)
+{
+ ssize_t idx = git_buf_find(buf, separator);
+ if (idx >= 0)
+ git_buf_truncate(buf, (size_t)idx);
+}
+
void git_buf_rtruncate_at_char(git_buf *buf, char separator)
{
ssize_t idx = git_buf_rfind_next(buf, separator);
@@ -672,7 +677,7 @@ int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
va_start(ap, nbuf);
for (i = 0; i < nbuf; ++i) {
- const char* segment;
+ const char *segment;
size_t segment_len;
segment = va_arg(ap, const char *);
@@ -704,7 +709,7 @@ int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
va_start(ap, nbuf);
for (i = 0; i < nbuf; ++i) {
- const char* segment;
+ const char *segment;
size_t segment_len;
segment = va_arg(ap, const char *);
@@ -759,7 +764,8 @@ int git_buf_join(
ssize_t offset_a = -1;
/* not safe to have str_b point internally to the buffer */
- assert(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
+ if (buf->size)
+ GIT_ASSERT_ARG(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
/* figure out if we need to insert a separator */
if (separator && strlen_a) {
@@ -769,7 +775,7 @@ int git_buf_join(
}
/* str_a could be part of the buffer */
- if (str_a >= buf->ptr && str_a < buf->ptr + buf->size)
+ if (buf->size && str_a >= buf->ptr && str_a < buf->ptr + buf->size)
offset_a = str_a - buf->ptr;
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, strlen_a, strlen_b);
@@ -809,9 +815,9 @@ int git_buf_join3(
char *tgt;
/* for this function, disallow pointers into the existing buffer */
- assert(str_a < buf->ptr || str_a >= buf->ptr + buf->size);
- assert(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
- assert(str_c < buf->ptr || str_c >= buf->ptr + buf->size);
+ GIT_ASSERT(str_a < buf->ptr || str_a >= buf->ptr + buf->size);
+ GIT_ASSERT(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
+ GIT_ASSERT(str_c < buf->ptr || str_c >= buf->ptr + buf->size);
if (separator) {
if (len_a > 0) {
@@ -884,7 +890,9 @@ int git_buf_splice(
char *splice_loc;
size_t new_size, alloc_size;
- assert(buf && where <= buf->size && nb_to_remove <= buf->size - where);
+ GIT_ASSERT(buf);
+ GIT_ASSERT(where <= buf->size);
+ GIT_ASSERT(nb_to_remove <= buf->size - where);
splice_loc = buf->ptr + where;
@@ -1046,3 +1054,313 @@ invalid:
git_error_set(GIT_ERROR_INVALID, "invalid quoted line");
return -1;
}
+
+int git_buf_puts_escaped(
+ git_buf *buf,
+ const char *string,
+ const char *esc_chars,
+ const char *esc_with)
+{
+ const char *scan;
+ size_t total = 0, esc_len = strlen(esc_with), count, alloclen;
+
+ if (!string)
+ return 0;
+
+ for (scan = string; *scan; ) {
+ /* count run of non-escaped characters */
+ count = strcspn(scan, esc_chars);
+ total += count;
+ scan += count;
+ /* count run of escaped characters */
+ count = strspn(scan, esc_chars);
+ total += count * (esc_len + 1);
+ scan += count;
+ }
+
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, total, 1);
+ if (git_buf_grow_by(buf, alloclen) < 0)
+ return -1;
+
+ for (scan = string; *scan; ) {
+ count = strcspn(scan, esc_chars);
+
+ memmove(buf->ptr + buf->size, scan, count);
+ scan += count;
+ buf->size += count;
+
+ for (count = strspn(scan, esc_chars); count > 0; --count) {
+ /* copy escape sequence */
+ memmove(buf->ptr + buf->size, esc_with, esc_len);
+ buf->size += esc_len;
+ /* copy character to be escaped */
+ buf->ptr[buf->size] = *scan;
+ buf->size++;
+ scan++;
+ }
+ }
+
+ buf->ptr[buf->size] = '\0';
+
+ return 0;
+}
+
+void git_buf_unescape(git_buf *buf)
+{
+ buf->size = git__unescape(buf->ptr);
+}
+
+int git_buf_crlf_to_lf(git_buf *tgt, const git_buf *src)
+{
+ const char *scan = src->ptr;
+ const char *scan_end = src->ptr + src->size;
+ const char *next = memchr(scan, '\r', src->size);
+ size_t new_size;
+ char *out;
+
+ GIT_ASSERT(tgt != src);
+
+ if (!next)
+ return git_buf_set(tgt, src->ptr, src->size);
+
+ /* reduce reallocs while in the loop */
+ GIT_ERROR_CHECK_ALLOC_ADD(&new_size, src->size, 1);
+ if (git_buf_grow(tgt, new_size) < 0)
+ return -1;
+
+ out = tgt->ptr;
+ tgt->size = 0;
+
+ /* Find the next \r and copy whole chunk up to there to tgt */
+ for (; next; scan = next + 1, next = memchr(scan, '\r', scan_end - scan)) {
+ if (next > scan) {
+ size_t copylen = (size_t)(next - scan);
+ memcpy(out, scan, copylen);
+ out += copylen;
+ }
+
+ /* Do not drop \r unless it is followed by \n */
+ if (next + 1 == scan_end || next[1] != '\n')
+ *out++ = '\r';
+ }
+
+ /* Copy remaining input into dest */
+ if (scan < scan_end) {
+ size_t remaining = (size_t)(scan_end - scan);
+ memcpy(out, scan, remaining);
+ out += remaining;
+ }
+
+ tgt->size = (size_t)(out - tgt->ptr);
+ tgt->ptr[tgt->size] = '\0';
+
+ return 0;
+}
+
+int git_buf_lf_to_crlf(git_buf *tgt, const git_buf *src)
+{
+ const char *start = src->ptr;
+ const char *end = start + src->size;
+ const char *scan = start;
+ const char *next = memchr(scan, '\n', src->size);
+ size_t alloclen;
+
+ GIT_ASSERT(tgt != src);
+
+ if (!next)
+ return git_buf_set(tgt, src->ptr, src->size);
+
+ /* attempt to reduce reallocs while in the loop */
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, src->size, src->size >> 4);
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
+ if (git_buf_grow(tgt, alloclen) < 0)
+ return -1;
+ tgt->size = 0;
+
+ for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) {
+ size_t copylen = next - scan;
+
+ /* if we find mixed line endings, carry on */
+ if (copylen && next[-1] == '\r')
+ copylen--;
+
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
+ if (git_buf_grow_by(tgt, alloclen) < 0)
+ return -1;
+
+ if (copylen) {
+ memcpy(tgt->ptr + tgt->size, scan, copylen);
+ tgt->size += copylen;
+ }
+
+ tgt->ptr[tgt->size++] = '\r';
+ tgt->ptr[tgt->size++] = '\n';
+ }
+
+ tgt->ptr[tgt->size] = '\0';
+ return git_buf_put(tgt, scan, end - scan);
+}
+
+int git_buf_common_prefix(git_buf *buf, char *const *const strings, size_t count)
+{
+ size_t i;
+ const char *str, *pfx;
+
+ git_buf_clear(buf);
+
+ if (!strings || !count)
+ return 0;
+
+ /* initialize common prefix to first string */
+ if (git_buf_sets(buf, strings[0]) < 0)
+ return -1;
+
+ /* go through the rest of the strings, truncating to shared prefix */
+ for (i = 1; i < count; ++i) {
+
+ for (str = strings[i], pfx = buf->ptr;
+ *str && *str == *pfx;
+ str++, pfx++)
+ /* scanning */;
+
+ git_buf_truncate(buf, pfx - buf->ptr);
+
+ if (!buf->size)
+ break;
+ }
+
+ return 0;
+}
+
+int git_buf_is_binary(const git_buf *buf)
+{
+ const char *scan = buf->ptr, *end = buf->ptr + buf->size;
+ git_buf_bom_t bom;
+ int printable = 0, nonprintable = 0;
+
+ scan += git_buf_detect_bom(&bom, buf);
+
+ if (bom > GIT_BUF_BOM_UTF8)
+ return 1;
+
+ while (scan < end) {
+ unsigned char c = *scan++;
+
+ /* Printable characters are those above SPACE (0x1F) excluding DEL,
+ * and including BS, ESC and FF.
+ */
+ if ((c > 0x1F && c != 127) || c == '\b' || c == '\033' || c == '\014')
+ printable++;
+ else if (c == '\0')
+ return true;
+ else if (!git__isspace(c))
+ nonprintable++;
+ }
+
+ return ((printable >> 7) < nonprintable);
+}
+
+int git_buf_contains_nul(const git_buf *buf)
+{
+ return (memchr(buf->ptr, '\0', buf->size) != NULL);
+}
+
+int git_buf_detect_bom(git_buf_bom_t *bom, const git_buf *buf)
+{
+ const char *ptr;
+ size_t len;
+
+ *bom = GIT_BUF_BOM_NONE;
+ /* need at least 2 bytes to look for any BOM */
+ if (buf->size < 2)
+ return 0;
+
+ ptr = buf->ptr;
+ len = buf->size;
+
+ switch (*ptr++) {
+ case 0:
+ if (len >= 4 && ptr[0] == 0 && ptr[1] == '\xFE' && ptr[2] == '\xFF') {
+ *bom = GIT_BUF_BOM_UTF32_BE;
+ return 4;
+ }
+ break;
+ case '\xEF':
+ if (len >= 3 && ptr[0] == '\xBB' && ptr[1] == '\xBF') {
+ *bom = GIT_BUF_BOM_UTF8;
+ return 3;
+ }
+ break;
+ case '\xFE':
+ if (*ptr == '\xFF') {
+ *bom = GIT_BUF_BOM_UTF16_BE;
+ return 2;
+ }
+ break;
+ case '\xFF':
+ if (*ptr != '\xFE')
+ break;
+ if (len >= 4 && ptr[1] == 0 && ptr[2] == 0) {
+ *bom = GIT_BUF_BOM_UTF32_LE;
+ return 4;
+ } else {
+ *bom = GIT_BUF_BOM_UTF16_LE;
+ return 2;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+bool git_buf_gather_text_stats(
+ git_buf_text_stats *stats, const git_buf *buf, bool skip_bom)
+{
+ const char *scan = buf->ptr, *end = buf->ptr + buf->size;
+ int skip;
+
+ memset(stats, 0, sizeof(*stats));
+
+ /* BOM detection */
+ skip = git_buf_detect_bom(&stats->bom, buf);
+ if (skip_bom)
+ scan += skip;
+
+ /* Ignore EOF character */
+ if (buf->size > 0 && end[-1] == '\032')
+ end--;
+
+ /* Counting loop */
+ while (scan < end) {
+ unsigned char c = *scan++;
+
+ if (c > 0x1F && c != 0x7F)
+ stats->printable++;
+ else switch (c) {
+ case '\0':
+ stats->nul++;
+ stats->nonprintable++;
+ break;
+ case '\n':
+ stats->lf++;
+ break;
+ case '\r':
+ stats->cr++;
+ if (scan < end && *scan == '\n')
+ stats->crlf++;
+ break;
+ case '\t': case '\f': case '\v': case '\b': case 0x1b: /*ESC*/
+ stats->printable++;
+ break;
+ default:
+ stats->nonprintable++;
+ break;
+ }
+ }
+
+ /* Treat files with a bare CR as binary */
+ return (stats->cr != stats->crlf || stats->nul > 0 ||
+ ((stats->printable >> 7) < stats->nonprintable));
+}
diff --git a/src/buffer.h b/src/buffer.h
index 6b717d2e9..75930e209 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -17,12 +17,34 @@
* } git_buf;
*/
+typedef enum {
+ GIT_BUF_BOM_NONE = 0,
+ GIT_BUF_BOM_UTF8 = 1,
+ GIT_BUF_BOM_UTF16_LE = 2,
+ GIT_BUF_BOM_UTF16_BE = 3,
+ GIT_BUF_BOM_UTF32_LE = 4,
+ GIT_BUF_BOM_UTF32_BE = 5
+} git_buf_bom_t;
+
+typedef struct {
+ git_buf_bom_t bom; /* BOM found at head of text */
+ unsigned int nul, cr, lf, crlf; /* NUL, CR, LF and CRLF counts */
+ unsigned int printable, nonprintable; /* These are just approximations! */
+} git_buf_text_stats;
+
extern char git_buf__initbuf[];
extern char git_buf__oom[];
/* Use to initialize buffer structure when git_buf is on stack */
#define GIT_BUF_INIT { git_buf__initbuf, 0, 0 }
+/**
+ * Static initializer for git_buf from static buffer
+ */
+#ifdef GIT_DEPRECATE_HARD
+# define GIT_BUF_INIT_CONST(STR,LEN) { (char *)(STR), 0, (size_t)(LEN) }
+#endif
+
GIT_INLINE(bool) git_buf_is_allocated(const git_buf *buf)
{
return (buf->ptr != NULL && buf->asize > 0);
@@ -36,6 +58,33 @@ GIT_INLINE(bool) git_buf_is_allocated(const git_buf *buf)
*/
extern int git_buf_init(git_buf *buf, size_t initial_size);
+#ifdef GIT_DEPRECATE_HARD
+
+/**
+ * Resize the buffer allocation to make more space.
+ *
+ * This will attempt to grow the buffer to accommodate the target size.
+ *
+ * If the buffer refers to memory that was not allocated by libgit2 (i.e.
+ * the `asize` field is zero), then `ptr` will be replaced with a newly
+ * allocated block of data. Be careful so that memory allocated by the
+ * caller is not lost. As a special variant, if you pass `target_size` as
+ * 0 and the memory is not allocated by libgit2, this will allocate a new
+ * buffer of size `size` and copy the external data into it.
+ *
+ * Currently, this will never shrink a buffer, only expand it.
+ *
+ * If the allocation fails, this will return an error and the buffer will be
+ * marked as invalid for future operations, invaliding the contents.
+ *
+ * @param buffer The buffer to be resized; may or may not be allocated yet
+ * @param target_size The desired available size
+ * @return 0 on success, -1 on allocation failure
+ */
+int git_buf_grow(git_buf *buffer, size_t target_size);
+
+#endif
+
/**
* Resize the buffer allocation to make more space.
*
@@ -69,7 +118,7 @@ extern int git_buf_try_grow(
* git_buf__initbuf. If a buffer with a non-NULL ptr is passed in, this method
* assures that the buffer is '\0'-terminated.
*/
-extern void git_buf_sanitize(git_buf *buf);
+extern int git_buf_sanitize(git_buf *buf);
extern void git_buf_swap(git_buf *buf_a, git_buf *buf_b);
extern char *git_buf_detach(git_buf *buf);
@@ -105,6 +154,11 @@ GIT_INLINE(bool) git_buf_oom(const git_buf *buf)
* return code of these functions and call them in a series then just call
* git_buf_oom at the end.
*/
+
+#ifdef GIT_DEPRECATE_HARD
+int git_buf_set(git_buf *buffer, const void *data, size_t datalen);
+#endif
+
int git_buf_sets(git_buf *buf, const char *string);
int git_buf_putc(git_buf *buf, char c);
int git_buf_putcn(git_buf *buf, char c, size_t len);
@@ -117,6 +171,7 @@ void git_buf_consume_bytes(git_buf *buf, size_t len);
void git_buf_consume(git_buf *buf, const char *end);
void git_buf_truncate(git_buf *buf, size_t len);
void git_buf_shorten(git_buf *buf, size_t amount);
+void git_buf_truncate_at_char(git_buf *buf, char separator);
void git_buf_rtruncate_at_char(git_buf *path, char separator);
/** General join with separator */
@@ -145,7 +200,7 @@ GIT_INLINE(size_t) git_buf_len(const git_buf *buf)
return buf->size;
}
-void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf);
+int git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf);
#define git_buf_PUTS(buf, str) git_buf_put(buf, str, sizeof(str) - 1)
@@ -219,4 +274,101 @@ int git_buf_splice(
const char *data,
size_t nb_to_insert);
+/**
+ * Append string to buffer, prefixing each character from `esc_chars` with
+ * `esc_with` string.
+ *
+ * @param buf Buffer to append data to
+ * @param string String to escape and append
+ * @param esc_chars Characters to be escaped
+ * @param esc_with String to insert in from of each found character
+ * @return 0 on success, <0 on failure (probably allocation problem)
+ */
+extern int git_buf_puts_escaped(
+ git_buf *buf,
+ const char *string,
+ const char *esc_chars,
+ const char *esc_with);
+
+/**
+ * Append string escaping characters that are regex special
+ */
+GIT_INLINE(int) git_buf_puts_escape_regex(git_buf *buf, const char *string)
+{
+ return git_buf_puts_escaped(buf, string, "^.[]$()|*+?{}\\", "\\");
+}
+
+/**
+ * Unescape all characters in a buffer in place
+ *
+ * I.e. remove backslashes
+ */
+extern void git_buf_unescape(git_buf *buf);
+
+/**
+ * Replace all \r\n with \n.
+ *
+ * @return 0 on success, -1 on memory error
+ */
+extern int git_buf_crlf_to_lf(git_buf *tgt, const git_buf *src);
+
+/**
+ * Replace all \n with \r\n. Does not modify existing \r\n.
+ *
+ * @return 0 on success, -1 on memory error
+ */
+extern int git_buf_lf_to_crlf(git_buf *tgt, const git_buf *src);
+
+/**
+ * Fill buffer with the common prefix of a array of strings
+ *
+ * Buffer will be set to empty if there is no common prefix
+ */
+extern int git_buf_common_prefix(git_buf *buf, char *const *const strings, size_t count);
+
+/**
+ * Check if a buffer begins with a UTF BOM
+ *
+ * @param bom Set to the type of BOM detected or GIT_BOM_NONE
+ * @param buf Buffer in which to check the first bytes for a BOM
+ * @return Number of bytes of BOM data (or 0 if no BOM found)
+ */
+extern int git_buf_detect_bom(git_buf_bom_t *bom, const git_buf *buf);
+
+/**
+ * Gather stats for a piece of text
+ *
+ * Fill the `stats` structure with counts of unreadable characters, carriage
+ * returns, etc, so it can be used in heuristics. This automatically skips
+ * a trailing EOF (\032 character). Also it will look for a BOM at the
+ * start of the text and can be told to skip that as well.
+ *
+ * @param stats Structure to be filled in
+ * @param buf Text to process
+ * @param skip_bom Exclude leading BOM from stats if true
+ * @return Does the buffer heuristically look like binary data
+ */
+extern bool git_buf_gather_text_stats(
+ git_buf_text_stats *stats, const git_buf *buf, bool skip_bom);
+
+#ifdef GIT_DEPRECATE_HARD
+
+/**
+* Check quickly if buffer looks like it contains binary data
+*
+* @param buf Buffer to check
+* @return 1 if buffer looks like non-text data
+*/
+int git_buf_is_binary(const git_buf *buf);
+
+/**
+* Check quickly if buffer contains a NUL byte
+*
+* @param buf Buffer to check
+* @return 1 if buffer contains a NUL byte
+*/
+int git_buf_contains_nul(const git_buf *buf);
+
+#endif
+
#endif
diff --git a/src/cache.c b/src/cache.c
index 1d2c0158d..2f68e357c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -9,7 +9,7 @@
#include "repository.h"
#include "commit.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "util.h"
#include "odb.h"
#include "object.h"
@@ -168,7 +168,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
return entry;
/* soften the load on the cache */
- if (git_cache__current_storage.val > git_cache__max_storage)
+ if (git_atomic_ssize_get(&git_cache__current_storage) > git_cache__max_storage)
cache_evict_entries(cache);
/* not found */
@@ -235,7 +235,7 @@ void git_cached_obj_decref(void *_obj)
{
git_cached_obj *obj = _obj;
- if (git_atomic_dec(&obj->refcount) == 0) {
+ if (git_atomic32_dec(&obj->refcount) == 0) {
switch (obj->flags) {
case GIT_CACHE_STORE_RAW:
git_odb_object__free(_obj);
diff --git a/src/cache.h b/src/cache.h
index 1e6179236..42c4fa80d 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -13,7 +13,7 @@
#include "git2/oid.h"
#include "git2/odb.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "oidmap.h"
enum {
@@ -23,11 +23,11 @@ enum {
};
typedef struct {
- git_oid oid;
- int16_t type; /* git_object_t value */
- uint16_t flags; /* GIT_CACHE_STORE value */
- size_t size;
- git_atomic refcount;
+ git_oid oid;
+ int16_t type; /* git_object_t value */
+ uint16_t flags; /* GIT_CACHE_STORE value */
+ size_t size;
+ git_atomic32 refcount;
} git_cached_obj;
typedef struct {
@@ -61,7 +61,7 @@ GIT_INLINE(size_t) git_cache_size(git_cache *cache)
GIT_INLINE(void) git_cached_obj_incref(void *_obj)
{
git_cached_obj *obj = _obj;
- git_atomic_inc(&obj->refcount);
+ git_atomic32_inc(&obj->refcount);
}
void git_cached_obj_decref(void *_obj);
diff --git a/src/cc-compat.h b/src/cc-compat.h
index 7ade561f3..f701b2d93 100644
--- a/src/cc-compat.h
+++ b/src/cc-compat.h
@@ -29,12 +29,6 @@
# endif
#endif
-#ifdef __GNUC__
-# define GIT_TYPEOF(x) (__typeof__(x))
-#else
-# define GIT_TYPEOF(x)
-#endif
-
#if defined(__GNUC__)
# define GIT_ALIGN(x,size) x __attribute__ ((aligned(size)))
#elif defined(_MSC_VER)
@@ -43,9 +37,17 @@
# define GIT_ALIGN(x,size) x
#endif
-#define GIT_UNUSED(x) ((void)(x))
+#if defined(__GNUC__)
+# define GIT_UNUSED(x) \
+ do { \
+ __typeof__(x) _unused __attribute__((unused)); \
+ _unused = (x); \
+ } while (0)
+#else
+# define GIT_UNUSED(x) ((void)(x))
+#endif
-/* Define the printf format specifer to use for size_t output */
+/* Define the printf format specifier to use for size_t output */
#if defined(_MSC_VER) || defined(__MINGW32__)
/* Visual Studio 2012 and prior lack PRId64 entirely */
diff --git a/src/checkout.c b/src/checkout.c
index 94a2cb9fa..3a171066b 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -26,7 +26,6 @@
#include "diff.h"
#include "diff_generate.h"
#include "pathspec.h"
-#include "buf_text.h"
#include "diff_xdiff.h"
#include "path.h"
#include "attr.h"
@@ -329,6 +328,9 @@ static int checkout_target_fullpath(
if (path && git_buf_puts(&data->target_path, path) < 0)
return -1;
+ if (git_path_validate_workdir_buf(data->repo, &data->target_path) < 0)
+ return -1;
+
*out = &data->target_path;
return 0;
@@ -1243,7 +1245,7 @@ static int checkout_conflict_append_remove(
checkout_data *data = payload;
const char *name;
- assert(ancestor || ours || theirs);
+ GIT_ASSERT_ARG(ancestor || ours || theirs);
if (ancestor)
name = git__strdup(ancestor->path);
@@ -1278,14 +1280,14 @@ static int checkout_verify_paths(
unsigned int flags = GIT_PATH_REJECT_WORKDIR_DEFAULTS;
if (action & CHECKOUT_ACTION__REMOVE) {
- if (!git_path_isvalid(repo, delta->old_file.path, delta->old_file.mode, flags)) {
+ if (!git_path_validate(repo, delta->old_file.path, delta->old_file.mode, flags)) {
git_error_set(GIT_ERROR_CHECKOUT, "cannot remove invalid path '%s'", delta->old_file.path);
return -1;
}
}
if (action & ~CHECKOUT_ACTION__REMOVE) {
- if (!git_path_isvalid(repo, delta->new_file.path, delta->new_file.mode, flags)) {
+ if (!git_path_validate(repo, delta->new_file.path, delta->new_file.mode, flags)) {
git_error_set(GIT_ERROR_CHECKOUT, "cannot checkout to invalid path '%s'", delta->new_file.path);
return -1;
}
@@ -1487,7 +1489,9 @@ static int checkout_stream_write(
static int checkout_stream_close(git_writestream *s)
{
struct checkout_stream *stream = (struct checkout_stream *)s;
- assert(stream && stream->open);
+
+ GIT_ASSERT_ARG(stream);
+ GIT_ASSERT_ARG(stream->open);
stream->open = 0;
return p_close(stream->fd);
@@ -1509,15 +1513,14 @@ static int blob_content_to_file(
int flags = data->opts.file_open_flags;
mode_t file_mode = data->opts.file_mode ?
data->opts.file_mode : entry_filemode;
- git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
+ git_filter_session filter_session = GIT_FILTER_SESSION_INIT;
struct checkout_stream writer;
mode_t mode;
git_filter_list *fl = NULL;
int fd;
int error = 0;
- if (hint_path == NULL)
- hint_path = path;
+ GIT_ASSERT(hint_path != NULL);
if ((error = mkpath2file(data, path, data->opts.dir_mode)) < 0)
return error;
@@ -1532,13 +1535,13 @@ static int blob_content_to_file(
return fd;
}
- filter_opts.attr_session = &data->attr_session;
- filter_opts.temp_buf = &data->tmp;
+ filter_session.attr_session = &data->attr_session;
+ filter_session.temp_buf = &data->tmp;
if (!data->opts.disable_filters &&
- (error = git_filter_list__load_ext(
+ (error = git_filter_list__load(
&fl, data->repo, blob, hint_path,
- GIT_FILTER_TO_WORKTREE, &filter_opts))) {
+ GIT_FILTER_TO_WORKTREE, &filter_session))) {
p_close(fd);
return error;
}
@@ -1554,7 +1557,7 @@ static int blob_content_to_file(
error = git_filter_list_stream_blob(fl, blob, &writer.base);
- assert(writer.open == 0);
+ GIT_ASSERT(writer.open == 0);
git_filter_list_free(fl);
@@ -1785,7 +1788,7 @@ static int checkout_blob(
}
error = checkout_write_content(
- data, &file->id, fullpath->ptr, NULL, file->mode, &st);
+ data, &file->id, fullpath->ptr, file->path, file->mode, &st);
/* update the index unless prevented */
if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
@@ -1971,12 +1974,12 @@ static int checkout_write_entry(
checkout_conflictdata *conflict,
const git_index_entry *side)
{
- const char *hint_path = NULL, *suffix;
+ const char *hint_path, *suffix;
git_buf *fullpath;
struct stat st;
int error;
- assert (side == conflict->ours || side == conflict->theirs);
+ GIT_ASSERT(side == conflict->ours || side == conflict->theirs);
if (checkout_target_fullpath(&fullpath, data, side->path) < 0)
return -1;
@@ -1994,10 +1997,10 @@ static int checkout_write_entry(
if (checkout_path_suffixed(fullpath, suffix) < 0)
return -1;
-
- hint_path = side->path;
}
+ hint_path = side->path;
+
if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 &&
(error = checkout_safe_for_update_only(data, fullpath->ptr, side->mode)) <= 0)
return error;
@@ -2030,7 +2033,8 @@ static int checkout_merge_path(
const char *our_label_raw, *their_label_raw, *suffix;
int error = 0;
- if ((error = git_buf_joinpath(out, git_repository_workdir(data->repo), result->path)) < 0)
+ if ((error = git_buf_joinpath(out, data->opts.target_directory, result->path)) < 0 ||
+ (error = git_path_validate_workdir_buf(data->repo, out)) < 0)
return error;
/* Most conflicts simply use the filename in the index */
@@ -2059,7 +2063,7 @@ static int checkout_write_merge(
git_merge_file_result result = {0};
git_filebuf output = GIT_FILEBUF_INIT;
git_filter_list *fl = NULL;
- git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
+ git_filter_session filter_session = GIT_FILTER_SESSION_INIT;
int error = 0;
if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
@@ -2109,13 +2113,13 @@ static int checkout_write_merge(
in_data.ptr = (char *)result.ptr;
in_data.size = result.len;
- filter_opts.attr_session = &data->attr_session;
- filter_opts.temp_buf = &data->tmp;
+ filter_session.attr_session = &data->attr_session;
+ filter_session.temp_buf = &data->tmp;
- if ((error = git_filter_list__load_ext(
- &fl, data->repo, NULL, git_buf_cstr(&path_workdir),
- GIT_FILTER_TO_WORKTREE, &filter_opts)) < 0 ||
- (error = git_filter_list_apply_to_data(&out_data, fl, &in_data)) < 0)
+ if ((error = git_filter_list__load(
+ &fl, data->repo, NULL, result.path,
+ GIT_FILTER_TO_WORKTREE, &filter_session)) < 0 ||
+ (error = git_filter_list__convert_buf(&out_data, fl, &in_data)) < 0)
goto done;
} else {
out_data.ptr = (char *)result.ptr;
@@ -2329,6 +2333,22 @@ static void checkout_data_clear(checkout_data *data)
git_attr_session__free(&data->attr_session);
}
+static int validate_target_directory(checkout_data *data)
+{
+ int error;
+
+ if ((error = git_path_validate_workdir(data->repo, data->opts.target_directory)) < 0)
+ return error;
+
+ if (git_path_isdir(data->opts.target_directory))
+ return 0;
+
+ error = checkout_mkdir(data, data->opts.target_directory, NULL,
+ GIT_DIR_MODE, GIT_MKDIR_VERIFY_DIR);
+
+ return error;
+}
+
static int checkout_data_init(
checkout_data *data,
git_iterator *target,
@@ -2361,10 +2381,7 @@ static int checkout_data_init(
if (!data->opts.target_directory)
data->opts.target_directory = git_repository_workdir(repo);
- else if (!git_path_isdir(data->opts.target_directory) &&
- (error = checkout_mkdir(data,
- data->opts.target_directory, NULL,
- GIT_DIR_MODE, GIT_MKDIR_VERIFY_DIR)) < 0)
+ else if ((error = validate_target_directory(data)) < 0)
goto cleanup;
if ((error = git_repository_index(&data->index, data->repo)) < 0)
@@ -2588,7 +2605,7 @@ int git_checkout_iterator(
}
/* Should not have case insensitivity mismatch */
- assert(git_iterator_ignore_case(workdir) == git_iterator_ignore_case(baseline));
+ GIT_ASSERT(git_iterator_ignore_case(workdir) == git_iterator_ignore_case(baseline));
/* Generate baseline-to-target diff which will include an entry for
* every possible update that might need to be made.
@@ -2604,6 +2621,9 @@ int git_checkout_iterator(
if ((error = checkout_get_actions(&actions, &counts, &data, workdir)) != 0)
goto cleanup;
+ if (data.strategy & GIT_CHECKOUT_DRY_RUN)
+ goto cleanup;
+
data.total_steps = counts[CHECKOUT_ACTION__REMOVE] +
counts[CHECKOUT_ACTION__REMOVE_CONFLICT] +
counts[CHECKOUT_ACTION__UPDATE_BLOB] +
@@ -2639,7 +2659,7 @@ int git_checkout_iterator(
(error = checkout_extensions_update_index(&data)) < 0)
goto cleanup;
- assert(data.completed_steps == data.total_steps);
+ GIT_ASSERT(data.completed_steps == data.total_steps);
if (data.opts.perfdata_cb)
data.opts.perfdata_cb(&data.perfdata, data.opts.perfdata_payload);
@@ -2767,7 +2787,8 @@ int git_checkout_head(
git_repository *repo,
const git_checkout_options *opts)
{
- assert(repo);
+ GIT_ASSERT_ARG(repo);
+
return git_checkout_tree(repo, NULL, opts);
}
diff --git a/src/cherrypick.c b/src/cherrypick.c
index 103897aae..4287956c9 100644
--- a/src/cherrypick.c
+++ b/src/cherrypick.c
@@ -126,7 +126,10 @@ int git_cherrypick_commit(
git_tree *parent_tree = NULL, *our_tree = NULL, *cherrypick_tree = NULL;
int parent = 0, error = 0;
- assert(out && repo && cherrypick_commit && our_commit);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(cherrypick_commit);
+ GIT_ASSERT_ARG(our_commit);
if (git_commit_parentcount(cherrypick_commit) > 1) {
if (!mainline)
@@ -177,7 +180,8 @@ int git_cherrypick(
git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
int error = 0;
- assert(repo && commit);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(commit);
GIT_ERROR_CHECK_VERSION(given_opts, GIT_CHERRYPICK_OPTIONS_VERSION, "git_cherrypick_options");
diff --git a/src/clone.c b/src/clone.c
index 8ca6cea1d..752df3b92 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -137,6 +137,80 @@ static int update_head_to_new_branch(
return error;
}
+static int update_head_to_default(git_repository *repo)
+{
+ git_buf initialbranch = GIT_BUF_INIT;
+ const char *branch_name;
+ int error = 0;
+
+ if ((error = git_repository_initialbranch(&initialbranch, repo)) < 0)
+ goto done;
+
+ if (git__prefixcmp(initialbranch.ptr, GIT_REFS_HEADS_DIR) != 0) {
+ git_error_set(GIT_ERROR_INVALID, "invalid initial branch '%s'", initialbranch.ptr);
+ error = -1;
+ goto done;
+ }
+
+ branch_name = initialbranch.ptr + strlen(GIT_REFS_HEADS_DIR);
+
+ error = setup_tracking_config(repo, branch_name, GIT_REMOTE_ORIGIN,
+ initialbranch.ptr);
+
+done:
+ git_buf_dispose(&initialbranch);
+ return error;
+}
+
+static int update_remote_head(
+ git_repository *repo,
+ git_remote *remote,
+ git_buf *target,
+ const char *reflog_message)
+{
+ git_refspec *refspec;
+ git_reference *remote_head = NULL;
+ git_buf remote_head_name = GIT_BUF_INIT;
+ git_buf remote_branch_name = GIT_BUF_INIT;
+ int error;
+
+ /* Determine the remote tracking ref name from the local branch */
+ refspec = git_remote__matching_refspec(remote, git_buf_cstr(target));
+
+ if (refspec == NULL) {
+ git_error_set(GIT_ERROR_NET, "the remote's default branch does not fit the refspec configuration");
+ error = GIT_EINVALIDSPEC;
+ goto cleanup;
+ }
+
+ if ((error = git_refspec_transform(
+ &remote_branch_name,
+ refspec,
+ git_buf_cstr(target))) < 0)
+ goto cleanup;
+
+ if ((error = git_buf_printf(&remote_head_name,
+ "%s%s/%s",
+ GIT_REFS_REMOTES_DIR,
+ git_remote_name(remote),
+ GIT_HEAD_FILE)) < 0)
+ goto cleanup;
+
+ error = git_reference_symbolic_create(
+ &remote_head,
+ repo,
+ git_buf_cstr(&remote_head_name),
+ git_buf_cstr(&remote_branch_name),
+ true,
+ reflog_message);
+
+cleanup:
+ git_reference_free(remote_head);
+ git_buf_dispose(&remote_branch_name);
+ git_buf_dispose(&remote_head_name);
+ return error;
+}
+
static int update_head_to_remote(
git_repository *repo,
git_remote *remote,
@@ -144,10 +218,8 @@ static int update_head_to_remote(
{
int error = 0;
size_t refs_len;
- git_refspec *refspec;
const git_remote_head *remote_head, **refs;
const git_oid *remote_head_id;
- git_buf remote_master_name = GIT_BUF_INIT;
git_buf branch = GIT_BUF_INIT;
if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0)
@@ -155,12 +227,11 @@ static int update_head_to_remote(
/* We cloned an empty repository or one with an unborn HEAD */
if (refs_len == 0 || strcmp(refs[0]->name, GIT_HEAD_FILE))
- return setup_tracking_config(
- repo, "master", GIT_REMOTE_ORIGIN, GIT_REFS_HEADS_MASTER_FILE);
+ return update_head_to_default(repo);
/* We know we have HEAD, let's see where it points */
remote_head = refs[0];
- assert(remote_head);
+ GIT_ASSERT(remote_head);
remote_head_id = &remote_head->oid;
@@ -171,19 +242,7 @@ static int update_head_to_remote(
goto cleanup;
}
- refspec = git_remote__matching_refspec(remote, git_buf_cstr(&branch));
-
- if (refspec == NULL) {
- git_error_set(GIT_ERROR_NET, "the remote's default branch does not fit the refspec configuration");
- error = GIT_EINVALIDSPEC;
- goto cleanup;
- }
-
- /* Determine the remote tracking reference name from the local master */
- if ((error = git_refspec_transform(
- &remote_master_name,
- refspec,
- git_buf_cstr(&branch))) < 0)
+ if ((error = update_remote_head(repo, remote, &branch, reflog_message)) < 0)
goto cleanup;
error = update_head_to_new_branch(
@@ -193,7 +252,6 @@ static int update_head_to_remote(
reflog_message);
cleanup:
- git_buf_dispose(&remote_master_name);
git_buf_dispose(&branch);
return error;
@@ -201,29 +259,41 @@ cleanup:
static int update_head_to_branch(
git_repository *repo,
- const char *remote_name,
+ git_remote *remote,
const char *branch,
const char *reflog_message)
{
int retcode;
git_buf remote_branch_name = GIT_BUF_INIT;
- git_reference* remote_ref = NULL;
+ git_reference *remote_ref = NULL;
+ git_buf default_branch = GIT_BUF_INIT;
- assert(remote_name && branch);
+ GIT_ASSERT_ARG(remote);
+ GIT_ASSERT_ARG(branch);
if ((retcode = git_buf_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s",
- remote_name, branch)) < 0 )
+ git_remote_name(remote), branch)) < 0 )
goto cleanup;
if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
goto cleanup;
- retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
- reflog_message);
+ if ((retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
+ reflog_message)) < 0)
+ goto cleanup;
+
+ if ((retcode = git_remote_default_branch(&default_branch, remote)) < 0)
+ goto cleanup;
+
+ if (!git_remote__matching_refspec(remote, git_buf_cstr(&default_branch)))
+ goto cleanup;
+
+ retcode = update_remote_head(repo, remote, &default_branch, reflog_message);
cleanup:
git_reference_free(remote_ref);
git_buf_dispose(&remote_branch_name);
+ git_buf_dispose(&default_branch);
return retcode;
}
@@ -308,8 +378,7 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c
int error;
if (branch)
- error = update_head_to_branch(repo, git_remote_name(remote), branch,
- reflog_message);
+ error = update_head_to_branch(repo, remote, branch, reflog_message);
/* Point HEAD to the same ref as the remote's head */
else
error = update_head_to_remote(repo, remote, reflog_message);
@@ -327,7 +396,8 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch
git_fetch_options fetch_opts;
git_remote *remote;
- assert(repo && _remote);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(_remote);
if (!git_repository_is_empty(repo)) {
git_error_set(GIT_ERROR_INVALID, "the repository is not empty");
@@ -394,7 +464,9 @@ static int git__clone(
uint32_t rmdir_flags = GIT_RMDIR_REMOVE_FILES;
git_repository_create_cb repository_cb;
- assert(out && url && local_path);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(url);
+ GIT_ASSERT_ARG(local_path);
if (_options)
memcpy(&options, _options, sizeof(git_clone_options));
@@ -517,7 +589,8 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
git_buf src_odb = GIT_BUF_INIT, dst_odb = GIT_BUF_INIT, src_path = GIT_BUF_INIT;
git_buf reflog_message = GIT_BUF_INIT;
- assert(repo && remote);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(remote);
if (!git_repository_is_empty(repo)) {
git_error_set(GIT_ERROR_INVALID, "the repository is not empty");
diff --git a/src/commit.c b/src/commit.c
index b498fd77e..2a1bafae2 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -54,7 +54,8 @@ static int git_commit__create_buffer_internal(
size_t i = 0;
const git_oid *parent;
- assert(out && tree);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(tree);
git_oid__writebuf(out, "tree ", tree);
@@ -230,7 +231,8 @@ int git_commit_create_v(
int error = 0;
commit_parent_varargs data;
- assert(tree && git_tree_owner(tree) == repo);
+ GIT_ASSERT_ARG(tree);
+ GIT_ASSERT_ARG(git_tree_owner(tree) == repo);
data.total = parent_count;
va_start(data.args, parent_count);
@@ -307,7 +309,8 @@ int git_commit_create(
{
commit_parent_data data = { parent_count, parents, repo };
- assert(tree && git_tree_owner(tree) == repo);
+ GIT_ASSERT_ARG(tree);
+ GIT_ASSERT_ARG(git_tree_owner(tree) == repo);
return git_commit__create_internal(
id, repo, update_ref, author, committer,
@@ -338,7 +341,8 @@ int git_commit_amend(
git_reference *ref;
int error;
- assert(id && commit_to_amend);
+ GIT_ASSERT_ARG(id);
+ GIT_ASSERT_ARG(commit_to_amend);
repo = git_commit_owner(commit_to_amend);
@@ -357,7 +361,7 @@ int git_commit_amend(
git_oid_cpy(&tree_id, git_tree_id(old_tree));
git_tree_free(old_tree);
} else {
- assert(git_tree_owner(tree) == repo);
+ GIT_ASSERT_ARG(git_tree_owner(tree) == repo);
git_oid_cpy(&tree_id, git_tree_id(tree));
}
@@ -393,7 +397,8 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
size_t header_len;
git_signature dummy_sig;
- assert(commit && data);
+ GIT_ASSERT_ARG(commit);
+ GIT_ASSERT_ARG(data);
buffer = buffer_start;
@@ -526,28 +531,28 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
return git_commit__parse_ext(_commit, odb_obj, 0);
}
-#define GIT_COMMIT_GETTER(_rvalue, _name, _return) \
+#define GIT_COMMIT_GETTER(_rvalue, _name, _return, _invalid) \
_rvalue git_commit_##_name(const git_commit *commit) \
{\
- assert(commit); \
+ GIT_ASSERT_ARG_WITH_RETVAL(commit, _invalid); \
return _return; \
}
-GIT_COMMIT_GETTER(const git_signature *, author, commit->author)
-GIT_COMMIT_GETTER(const git_signature *, committer, commit->committer)
-GIT_COMMIT_GETTER(const char *, message_raw, commit->raw_message)
-GIT_COMMIT_GETTER(const char *, message_encoding, commit->message_encoding)
-GIT_COMMIT_GETTER(const char *, raw_header, commit->raw_header)
-GIT_COMMIT_GETTER(git_time_t, time, commit->committer->when.time)
-GIT_COMMIT_GETTER(int, time_offset, commit->committer->when.offset)
-GIT_COMMIT_GETTER(unsigned int, parentcount, (unsigned int)git_array_size(commit->parent_ids))
-GIT_COMMIT_GETTER(const git_oid *, tree_id, &commit->tree_id)
+GIT_COMMIT_GETTER(const git_signature *, author, commit->author, NULL)
+GIT_COMMIT_GETTER(const git_signature *, committer, commit->committer, NULL)
+GIT_COMMIT_GETTER(const char *, message_raw, commit->raw_message, NULL)
+GIT_COMMIT_GETTER(const char *, message_encoding, commit->message_encoding, NULL)
+GIT_COMMIT_GETTER(const char *, raw_header, commit->raw_header, NULL)
+GIT_COMMIT_GETTER(git_time_t, time, commit->committer->when.time, INT64_MIN)
+GIT_COMMIT_GETTER(int, time_offset, commit->committer->when.offset, -1)
+GIT_COMMIT_GETTER(unsigned int, parentcount, (unsigned int)git_array_size(commit->parent_ids), 0)
+GIT_COMMIT_GETTER(const git_oid *, tree_id, &commit->tree_id, NULL)
const char *git_commit_message(const git_commit *commit)
{
const char *message;
- assert(commit);
+ GIT_ASSERT_ARG_WITH_RETVAL(commit, NULL);
message = commit->raw_message;
@@ -564,7 +569,7 @@ const char *git_commit_summary(git_commit *commit)
const char *msg, *space;
bool space_contains_newline = false;
- assert(commit);
+ GIT_ASSERT_ARG_WITH_RETVAL(commit, NULL);
if (!commit->summary) {
for (msg = git_commit_message(commit), space = NULL; *msg; ++msg) {
@@ -607,7 +612,7 @@ const char *git_commit_body(git_commit *commit)
{
const char *msg, *end;
- assert(commit);
+ GIT_ASSERT_ARG_WITH_RETVAL(commit, NULL);
if (!commit->body) {
/* search for end of summary */
@@ -632,14 +637,14 @@ const char *git_commit_body(git_commit *commit)
int git_commit_tree(git_tree **tree_out, const git_commit *commit)
{
- assert(commit);
+ GIT_ASSERT_ARG(commit);
return git_tree_lookup(tree_out, commit->object.repo, &commit->tree_id);
}
const git_oid *git_commit_parent_id(
const git_commit *commit, unsigned int n)
{
- assert(commit);
+ GIT_ASSERT_ARG_WITH_RETVAL(commit, NULL);
return git_array_get(commit->parent_ids, n);
}
@@ -648,7 +653,7 @@ int git_commit_parent(
git_commit **parent, const git_commit *commit, unsigned int n)
{
const git_oid *parent_id;
- assert(commit);
+ GIT_ASSERT_ARG(commit);
parent_id = git_commit_parent_id(commit, n);
if (parent_id == NULL) {
@@ -667,7 +672,8 @@ int git_commit_nth_gen_ancestor(
git_commit *current, *parent = NULL;
int error;
- assert(ancestor && commit);
+ GIT_ASSERT_ARG(ancestor);
+ GIT_ASSERT_ARG(commit);
if (git_commit_dup(&current, (git_commit *)commit) < 0)
return -1;
@@ -860,7 +866,8 @@ int git_commit_create_buffer(git_buf *out,
git_array_oid_t parents_arr = GIT_ARRAY_INIT;
const git_oid *tree_id;
- assert(tree && git_tree_owner(tree) == repo);
+ GIT_ASSERT_ARG(tree);
+ GIT_ASSERT_ARG(git_tree_owner(tree) == repo);
tree_id = git_tree_id(tree);
@@ -879,11 +886,13 @@ int git_commit_create_buffer(git_buf *out,
/**
* Append to 'out' properly marking continuations when there's a newline in 'content'
*/
-static void format_header_field(git_buf *out, const char *field, const char *content)
+static int format_header_field(git_buf *out, const char *field, const char *content)
{
const char *lf;
- assert(out && field && content);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(field);
+ GIT_ASSERT_ARG(content);
git_buf_puts(out, field);
git_buf_putc(out, ' ');
@@ -896,6 +905,8 @@ static void format_header_field(git_buf *out, const char *field, const char *con
git_buf_puts(out, content);
git_buf_putc(out, '\n');
+
+ return git_buf_oom(out) ? -1 : 0;
}
static const git_oid *commit_parent_from_commit(size_t n, void *payload)
@@ -946,7 +957,9 @@ int git_commit_create_with_signature(
if (signature != NULL) {
field = signature_field ? signature_field : "gpgsig";
- format_header_field(&commit, field, signature);
+
+ if ((error = format_header_field(&commit, field, signature)) < 0)
+ goto cleanup;
}
git_buf_puts(&commit, header_end);
diff --git a/src/commit_graph.c b/src/commit_graph.c
new file mode 100644
index 000000000..f663fc5d3
--- /dev/null
+++ b/src/commit_graph.c
@@ -0,0 +1,1209 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "commit_graph.h"
+
+#include "array.h"
+#include "filebuf.h"
+#include "futils.h"
+#include "hash.h"
+#include "oidarray.h"
+#include "oidmap.h"
+#include "pack.h"
+#include "repository.h"
+#include "revwalk.h"
+
+#define GIT_COMMIT_GRAPH_MISSING_PARENT 0x70000000
+#define GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX 0x3FFFFFFF
+#define GIT_COMMIT_GRAPH_GENERATION_NUMBER_INFINITY 0xFFFFFFFF
+
+#define COMMIT_GRAPH_SIGNATURE 0x43475048 /* "CGPH" */
+#define COMMIT_GRAPH_VERSION 1
+#define COMMIT_GRAPH_OBJECT_ID_VERSION 1
+struct git_commit_graph_header {
+ uint32_t signature;
+ uint8_t version;
+ uint8_t object_id_version;
+ uint8_t chunks;
+ uint8_t base_graph_files;
+};
+
+#define COMMIT_GRAPH_OID_FANOUT_ID 0x4f494446 /* "OIDF" */
+#define COMMIT_GRAPH_OID_LOOKUP_ID 0x4f49444c /* "OIDL" */
+#define COMMIT_GRAPH_COMMIT_DATA_ID 0x43444154 /* "CDAT" */
+#define COMMIT_GRAPH_EXTRA_EDGE_LIST_ID 0x45444745 /* "EDGE" */
+#define COMMIT_GRAPH_BLOOM_FILTER_INDEX_ID 0x42494458 /* "BIDX" */
+#define COMMIT_GRAPH_BLOOM_FILTER_DATA_ID 0x42444154 /* "BDAT" */
+
+struct git_commit_graph_chunk {
+ off64_t offset;
+ size_t length;
+};
+
+typedef git_array_t(size_t) parent_index_array_t;
+
+struct packed_commit {
+ size_t index;
+ git_oid sha1;
+ git_oid tree_oid;
+ uint32_t generation;
+ git_time_t commit_time;
+ git_array_oid_t parents;
+ parent_index_array_t parent_indices;
+};
+
+static void packed_commit_free(struct packed_commit *p)
+{
+ if (!p)
+ return;
+
+ git_array_clear(p->parents);
+ git_array_clear(p->parent_indices);
+ git__free(p);
+}
+
+static struct packed_commit *packed_commit_new(git_commit *commit)
+{
+ unsigned int i, parentcount = git_commit_parentcount(commit);
+ struct packed_commit *p = git__calloc(1, sizeof(struct packed_commit));
+ if (!p)
+ goto cleanup;
+
+ git_array_init_to_size(p->parents, parentcount);
+ if (parentcount && !p->parents.ptr)
+ goto cleanup;
+
+ if (git_oid_cpy(&p->sha1, git_commit_id(commit)) < 0)
+ goto cleanup;
+ if (git_oid_cpy(&p->tree_oid, git_commit_tree_id(commit)) < 0)
+ goto cleanup;
+ p->commit_time = git_commit_time(commit);
+
+ for (i = 0; i < parentcount; ++i) {
+ git_oid *parent_id = git_array_alloc(p->parents);
+ if (!parent_id)
+ goto cleanup;
+ if (git_oid_cpy(parent_id, git_commit_parent_id(commit, i)) < 0)
+ goto cleanup;
+ }
+
+ return p;
+
+cleanup:
+ packed_commit_free(p);
+ return NULL;
+}
+
+typedef int (*commit_graph_write_cb)(const char *buf, size_t size, void *cb_data);
+
+static int commit_graph_error(const char *message)
+{
+ git_error_set(GIT_ERROR_ODB, "invalid commit-graph file - %s", message);
+ return -1;
+}
+
+static int commit_graph_parse_oid_fanout(
+ git_commit_graph_file *file,
+ const unsigned char *data,
+ struct git_commit_graph_chunk *chunk_oid_fanout)
+{
+ uint32_t i, nr;
+ if (chunk_oid_fanout->offset == 0)
+ return commit_graph_error("missing OID Fanout chunk");
+ if (chunk_oid_fanout->length == 0)
+ return commit_graph_error("empty OID Fanout chunk");
+ if (chunk_oid_fanout->length != 256 * 4)
+ return commit_graph_error("OID Fanout chunk has wrong length");
+
+ file->oid_fanout = (const uint32_t *)(data + chunk_oid_fanout->offset);
+ nr = 0;
+ for (i = 0; i < 256; ++i) {
+ uint32_t n = ntohl(file->oid_fanout[i]);
+ if (n < nr)
+ return commit_graph_error("index is non-monotonic");
+ nr = n;
+ }
+ file->num_commits = nr;
+ return 0;
+}
+
+static int commit_graph_parse_oid_lookup(
+ git_commit_graph_file *file,
+ const unsigned char *data,
+ struct git_commit_graph_chunk *chunk_oid_lookup)
+{
+ uint32_t i;
+ git_oid *oid, *prev_oid, zero_oid = {{0}};
+
+ if (chunk_oid_lookup->offset == 0)
+ return commit_graph_error("missing OID Lookup chunk");
+ if (chunk_oid_lookup->length == 0)
+ return commit_graph_error("empty OID Lookup chunk");
+ if (chunk_oid_lookup->length != file->num_commits * GIT_OID_RAWSZ)
+ return commit_graph_error("OID Lookup chunk has wrong length");
+
+ file->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset);
+ prev_oid = &zero_oid;
+ for (i = 0; i < file->num_commits; ++i, ++oid) {
+ if (git_oid_cmp(prev_oid, oid) >= 0)
+ return commit_graph_error("OID Lookup index is non-monotonic");
+ prev_oid = oid;
+ }
+
+ return 0;
+}
+
+static int commit_graph_parse_commit_data(
+ git_commit_graph_file *file,
+ const unsigned char *data,
+ struct git_commit_graph_chunk *chunk_commit_data)
+{
+ if (chunk_commit_data->offset == 0)
+ return commit_graph_error("missing Commit Data chunk");
+ if (chunk_commit_data->length == 0)
+ return commit_graph_error("empty Commit Data chunk");
+ if (chunk_commit_data->length != file->num_commits * (GIT_OID_RAWSZ + 16))
+ return commit_graph_error("Commit Data chunk has wrong length");
+
+ file->commit_data = data + chunk_commit_data->offset;
+
+ return 0;
+}
+
+static int commit_graph_parse_extra_edge_list(
+ git_commit_graph_file *file,
+ const unsigned char *data,
+ struct git_commit_graph_chunk *chunk_extra_edge_list)
+{
+ if (chunk_extra_edge_list->length == 0)
+ return 0;
+ if (chunk_extra_edge_list->length % 4 != 0)
+ return commit_graph_error("malformed Extra Edge List chunk");
+
+ file->extra_edge_list = data + chunk_extra_edge_list->offset;
+ file->num_extra_edge_list = chunk_extra_edge_list->length / 4;
+
+ return 0;
+}
+
+int git_commit_graph_file_parse(
+ git_commit_graph_file *file,
+ const unsigned char *data,
+ size_t size)
+{
+ struct git_commit_graph_header *hdr;
+ const unsigned char *chunk_hdr;
+ struct git_commit_graph_chunk *last_chunk;
+ uint32_t i;
+ off64_t last_chunk_offset, chunk_offset, trailer_offset;
+ git_oid cgraph_checksum = {{0}};
+ int error;
+ struct git_commit_graph_chunk chunk_oid_fanout = {0}, chunk_oid_lookup = {0},
+ chunk_commit_data = {0}, chunk_extra_edge_list = {0},
+ chunk_unsupported = {0};
+
+ GIT_ASSERT_ARG(file);
+
+ if (size < sizeof(struct git_commit_graph_header) + GIT_OID_RAWSZ)
+ return commit_graph_error("commit-graph is too short");
+
+ hdr = ((struct git_commit_graph_header *)data);
+
+ if (hdr->signature != htonl(COMMIT_GRAPH_SIGNATURE) || hdr->version != COMMIT_GRAPH_VERSION
+ || hdr->object_id_version != COMMIT_GRAPH_OBJECT_ID_VERSION) {
+ return commit_graph_error("unsupported commit-graph version");
+ }
+ if (hdr->chunks == 0)
+ return commit_graph_error("no chunks in commit-graph");
+
+ /*
+ * The very first chunk's offset should be after the header, all the chunk
+ * headers, and a special zero chunk.
+ */
+ last_chunk_offset = sizeof(struct git_commit_graph_header) + (1 + hdr->chunks) * 12;
+ trailer_offset = size - GIT_OID_RAWSZ;
+ if (trailer_offset < last_chunk_offset)
+ return commit_graph_error("wrong commit-graph size");
+ git_oid_cpy(&file->checksum, (git_oid *)(data + trailer_offset));
+
+ if (git_hash_buf(&cgraph_checksum, data, (size_t)trailer_offset) < 0)
+ return commit_graph_error("could not calculate signature");
+ if (!git_oid_equal(&cgraph_checksum, &file->checksum))
+ return commit_graph_error("index signature mismatch");
+
+ chunk_hdr = data + sizeof(struct git_commit_graph_header);
+ last_chunk = NULL;
+ for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
+ chunk_offset = ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) << 32
+ | ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 8))));
+ if (chunk_offset < last_chunk_offset)
+ return commit_graph_error("chunks are non-monotonic");
+ if (chunk_offset >= trailer_offset)
+ return commit_graph_error("chunks extend beyond the trailer");
+ if (last_chunk != NULL)
+ last_chunk->length = (size_t)(chunk_offset - last_chunk_offset);
+ last_chunk_offset = chunk_offset;
+
+ switch (ntohl(*((uint32_t *)(chunk_hdr + 0)))) {
+ case COMMIT_GRAPH_OID_FANOUT_ID:
+ chunk_oid_fanout.offset = last_chunk_offset;
+ last_chunk = &chunk_oid_fanout;
+ break;
+
+ case COMMIT_GRAPH_OID_LOOKUP_ID:
+ chunk_oid_lookup.offset = last_chunk_offset;
+ last_chunk = &chunk_oid_lookup;
+ break;
+
+ case COMMIT_GRAPH_COMMIT_DATA_ID:
+ chunk_commit_data.offset = last_chunk_offset;
+ last_chunk = &chunk_commit_data;
+ break;
+
+ case COMMIT_GRAPH_EXTRA_EDGE_LIST_ID:
+ chunk_extra_edge_list.offset = last_chunk_offset;
+ last_chunk = &chunk_extra_edge_list;
+ break;
+
+ case COMMIT_GRAPH_BLOOM_FILTER_INDEX_ID:
+ case COMMIT_GRAPH_BLOOM_FILTER_DATA_ID:
+ chunk_unsupported.offset = last_chunk_offset;
+ last_chunk = &chunk_unsupported;
+ break;
+
+ default:
+ return commit_graph_error("unrecognized chunk ID");
+ }
+ }
+ last_chunk->length = (size_t)(trailer_offset - last_chunk_offset);
+
+ error = commit_graph_parse_oid_fanout(file, data, &chunk_oid_fanout);
+ if (error < 0)
+ return error;
+ error = commit_graph_parse_oid_lookup(file, data, &chunk_oid_lookup);
+ if (error < 0)
+ return error;
+ error = commit_graph_parse_commit_data(file, data, &chunk_commit_data);
+ if (error < 0)
+ return error;
+ error = commit_graph_parse_extra_edge_list(file, data, &chunk_extra_edge_list);
+ if (error < 0)
+ return error;
+
+ return 0;
+}
+
+int git_commit_graph_new(git_commit_graph **cgraph_out, const char *objects_dir, bool open_file)
+{
+ git_commit_graph *cgraph = NULL;
+ int error = 0;
+
+ GIT_ASSERT_ARG(cgraph_out);
+ GIT_ASSERT_ARG(objects_dir);
+
+ cgraph = git__calloc(1, sizeof(git_commit_graph));
+ GIT_ERROR_CHECK_ALLOC(cgraph);
+
+ error = git_buf_joinpath(&cgraph->filename, objects_dir, "info/commit-graph");
+ if (error < 0)
+ goto error;
+
+ if (open_file) {
+ error = git_commit_graph_file_open(&cgraph->file, git_buf_cstr(&cgraph->filename));
+ if (error < 0)
+ goto error;
+ cgraph->checked = 1;
+ }
+
+ *cgraph_out = cgraph;
+ return 0;
+
+error:
+ git_commit_graph_free(cgraph);
+ return error;
+}
+
+int git_commit_graph_open(git_commit_graph **cgraph_out, const char *objects_dir)
+{
+ return git_commit_graph_new(cgraph_out, objects_dir, true);
+}
+
+int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *path)
+{
+ git_commit_graph_file *file;
+ git_file fd = -1;
+ size_t cgraph_size;
+ struct stat st;
+ int error;
+
+ /* TODO: properly open the file without access time using O_NOATIME */
+ fd = git_futils_open_ro(path);
+ if (fd < 0)
+ return fd;
+
+ if (p_fstat(fd, &st) < 0) {
+ p_close(fd);
+ git_error_set(GIT_ERROR_ODB, "commit-graph file not found - '%s'", path);
+ return GIT_ENOTFOUND;
+ }
+
+ if (!S_ISREG(st.st_mode) || !git__is_sizet(st.st_size)) {
+ p_close(fd);
+ git_error_set(GIT_ERROR_ODB, "invalid pack index '%s'", path);
+ return GIT_ENOTFOUND;
+ }
+ cgraph_size = (size_t)st.st_size;
+
+ file = git__calloc(1, sizeof(git_commit_graph_file));
+ GIT_ERROR_CHECK_ALLOC(file);
+
+ error = git_futils_mmap_ro(&file->graph_map, fd, 0, cgraph_size);
+ p_close(fd);
+ if (error < 0) {
+ git_commit_graph_file_free(file);
+ return error;
+ }
+
+ if ((error = git_commit_graph_file_parse(file, file->graph_map.data, cgraph_size)) < 0) {
+ git_commit_graph_file_free(file);
+ return error;
+ }
+
+ *file_out = file;
+ return 0;
+}
+
+int git_commit_graph_get_file(git_commit_graph_file **file_out, git_commit_graph *cgraph)
+{
+ if (!cgraph->checked) {
+ int error = 0;
+ git_commit_graph_file *result = NULL;
+
+ /* We only check once, no matter the result. */
+ cgraph->checked = 1;
+
+ /* Best effort */
+ error = git_commit_graph_file_open(&result, git_buf_cstr(&cgraph->filename));
+
+ if (error < 0)
+ return error;
+
+ cgraph->file = result;
+ }
+ if (!cgraph->file)
+ return GIT_ENOTFOUND;
+
+ *file_out = cgraph->file;
+ return 0;
+}
+
+void git_commit_graph_refresh(git_commit_graph *cgraph)
+{
+ if (!cgraph->checked)
+ return;
+
+ if (cgraph->file
+ && git_commit_graph_file_needs_refresh(cgraph->file, git_buf_cstr(&cgraph->filename))) {
+ /* We just free the commit graph. The next time it is requested, it will be
+ * re-loaded. */
+ git_commit_graph_file_free(cgraph->file);
+ cgraph->file = NULL;
+ }
+ /* Force a lazy re-check next time it is needed. */
+ cgraph->checked = 0;
+}
+
+static int git_commit_graph_entry_get_byindex(
+ git_commit_graph_entry *e,
+ const git_commit_graph_file *file,
+ size_t pos)
+{
+ const unsigned char *commit_data;
+
+ GIT_ASSERT_ARG(e);
+ GIT_ASSERT_ARG(file);
+
+ if (pos >= file->num_commits) {
+ git_error_set(GIT_ERROR_INVALID, "commit index %zu does not exist", pos);
+ return GIT_ENOTFOUND;
+ }
+
+ commit_data = file->commit_data + pos * (GIT_OID_RAWSZ + 4 * sizeof(uint32_t));
+ git_oid_cpy(&e->tree_oid, (const git_oid *)commit_data);
+ e->parent_indices[0] = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ)));
+ e->parent_indices[1] = ntohl(
+ *((uint32_t *)(commit_data + GIT_OID_RAWSZ + sizeof(uint32_t))));
+ e->parent_count = (e->parent_indices[0] != GIT_COMMIT_GRAPH_MISSING_PARENT)
+ + (e->parent_indices[1] != GIT_COMMIT_GRAPH_MISSING_PARENT);
+ e->generation = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ + 2 * sizeof(uint32_t))));
+ e->commit_time = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ + 3 * sizeof(uint32_t))));
+
+ e->commit_time |= (e->generation & UINT64_C(0x3)) << UINT64_C(32);
+ e->generation >>= 2u;
+ if (e->parent_indices[1] & 0x80000000u) {
+ uint32_t extra_edge_list_pos = e->parent_indices[1] & 0x7fffffff;
+
+ /* Make sure we're not being sent out of bounds */
+ if (extra_edge_list_pos >= file->num_extra_edge_list) {
+ git_error_set(GIT_ERROR_INVALID,
+ "commit %u does not exist",
+ extra_edge_list_pos);
+ return GIT_ENOTFOUND;
+ }
+
+ e->extra_parents_index = extra_edge_list_pos;
+ while (extra_edge_list_pos < file->num_extra_edge_list
+ && (ntohl(*(
+ (uint32_t *)(file->extra_edge_list
+ + extra_edge_list_pos * sizeof(uint32_t))))
+ & 0x80000000u)
+ == 0) {
+ extra_edge_list_pos++;
+ e->parent_count++;
+ }
+ }
+ git_oid_cpy(&e->sha1, &file->oid_lookup[pos]);
+ return 0;
+}
+
+bool git_commit_graph_file_needs_refresh(const git_commit_graph_file *file, const char *path)
+{
+ git_file fd = -1;
+ struct stat st;
+ ssize_t bytes_read;
+ git_oid cgraph_checksum = {{0}};
+
+ /* TODO: properly open the file without access time using O_NOATIME */
+ fd = git_futils_open_ro(path);
+ if (fd < 0)
+ return true;
+
+ if (p_fstat(fd, &st) < 0) {
+ p_close(fd);
+ return true;
+ }
+
+ if (!S_ISREG(st.st_mode) || !git__is_sizet(st.st_size)
+ || (size_t)st.st_size != file->graph_map.len) {
+ p_close(fd);
+ return true;
+ }
+
+ bytes_read = p_pread(fd, cgraph_checksum.id, GIT_OID_RAWSZ, st.st_size - GIT_OID_RAWSZ);
+ p_close(fd);
+ if (bytes_read != GIT_OID_RAWSZ)
+ return true;
+
+ return !git_oid_equal(&cgraph_checksum, &file->checksum);
+}
+
+int git_commit_graph_entry_find(
+ git_commit_graph_entry *e,
+ const git_commit_graph_file *file,
+ const git_oid *short_oid,
+ size_t len)
+{
+ int pos, found = 0;
+ uint32_t hi, lo;
+ const git_oid *current = NULL;
+
+ GIT_ASSERT_ARG(e);
+ GIT_ASSERT_ARG(file);
+ GIT_ASSERT_ARG(short_oid);
+
+ hi = ntohl(file->oid_fanout[(int)short_oid->id[0]]);
+ lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(file->oid_fanout[(int)short_oid->id[0] - 1]));
+
+ pos = git_pack__lookup_sha1(file->oid_lookup, GIT_OID_RAWSZ, lo, hi, short_oid->id);
+
+ if (pos >= 0) {
+ /* An object matching exactly the oid was found */
+ found = 1;
+ current = file->oid_lookup + pos;
+ } else {
+ /* No object was found */
+ /* pos refers to the object with the "closest" oid to short_oid */
+ pos = -1 - pos;
+ if (pos < (int)file->num_commits) {
+ current = file->oid_lookup + pos;
+
+ if (!git_oid_ncmp(short_oid, current, len))
+ found = 1;
+ }
+ }
+
+ if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)file->num_commits) {
+ /* Check for ambiguousity */
+ const git_oid *next = current + 1;
+
+ if (!git_oid_ncmp(short_oid, next, len)) {
+ found = 2;
+ }
+ }
+
+ if (!found)
+ return git_odb__error_notfound(
+ "failed to find offset for commit-graph index entry", short_oid, len);
+ if (found > 1)
+ return git_odb__error_ambiguous(
+ "found multiple offsets for commit-graph index entry");
+
+ return git_commit_graph_entry_get_byindex(e, file, pos);
+}
+
+int git_commit_graph_entry_parent(
+ git_commit_graph_entry *parent,
+ const git_commit_graph_file *file,
+ const git_commit_graph_entry *entry,
+ size_t n)
+{
+ GIT_ASSERT_ARG(parent);
+ GIT_ASSERT_ARG(file);
+
+ if (n >= entry->parent_count) {
+ git_error_set(GIT_ERROR_INVALID, "parent index %zu does not exist", n);
+ return GIT_ENOTFOUND;
+ }
+
+ if (n == 0 || (n == 1 && entry->parent_count == 2))
+ return git_commit_graph_entry_get_byindex(parent, file, entry->parent_indices[n]);
+
+ return git_commit_graph_entry_get_byindex(
+ parent,
+ file,
+ ntohl(
+ *(uint32_t *)(file->extra_edge_list
+ + (entry->extra_parents_index + n - 1)
+ * sizeof(uint32_t)))
+ & 0x7fffffff);
+}
+
+int git_commit_graph_file_close(git_commit_graph_file *file)
+{
+ GIT_ASSERT_ARG(file);
+
+ if (file->graph_map.data)
+ git_futils_mmap_free(&file->graph_map);
+
+ return 0;
+}
+
+void git_commit_graph_free(git_commit_graph *cgraph)
+{
+ if (!cgraph)
+ return;
+
+ git_buf_dispose(&cgraph->filename);
+ git_commit_graph_file_free(cgraph->file);
+ git__free(cgraph);
+}
+
+void git_commit_graph_file_free(git_commit_graph_file *file)
+{
+ if (!file)
+ return;
+
+ git_commit_graph_file_close(file);
+ git__free(file);
+}
+
+static int packed_commit__cmp(const void *a_, const void *b_)
+{
+ const struct packed_commit *a = a_;
+ const struct packed_commit *b = b_;
+ return git_oid_cmp(&a->sha1, &b->sha1);
+}
+
+int git_commit_graph_writer_new(git_commit_graph_writer **out, const char *objects_info_dir)
+{
+ git_commit_graph_writer *w = git__calloc(1, sizeof(git_commit_graph_writer));
+ GIT_ERROR_CHECK_ALLOC(w);
+
+ if (git_buf_sets(&w->objects_info_dir, objects_info_dir) < 0) {
+ git__free(w);
+ return -1;
+ }
+
+ if (git_vector_init(&w->commits, 0, packed_commit__cmp) < 0) {
+ git_buf_dispose(&w->objects_info_dir);
+ git__free(w);
+ return -1;
+ }
+
+ *out = w;
+ return 0;
+}
+
+void git_commit_graph_writer_free(git_commit_graph_writer *w)
+{
+ struct packed_commit *packed_commit;
+ size_t i;
+
+ if (!w)
+ return;
+
+ git_vector_foreach (&w->commits, i, packed_commit)
+ packed_commit_free(packed_commit);
+ git_vector_free(&w->commits);
+ git_buf_dispose(&w->objects_info_dir);
+ git__free(w);
+}
+
+struct object_entry_cb_state {
+ git_repository *repo;
+ git_odb *db;
+ git_vector *commits;
+};
+
+static int object_entry__cb(const git_oid *id, void *data)
+{
+ struct object_entry_cb_state *state = (struct object_entry_cb_state *)data;
+ git_commit *commit = NULL;
+ struct packed_commit *packed_commit = NULL;
+ size_t header_len;
+ git_object_t header_type;
+ int error = 0;
+
+ error = git_odb_read_header(&header_len, &header_type, state->db, id);
+ if (error < 0)
+ return error;
+
+ if (header_type != GIT_OBJECT_COMMIT)
+ return 0;
+
+ error = git_commit_lookup(&commit, state->repo, id);
+ if (error < 0)
+ return error;
+
+ packed_commit = packed_commit_new(commit);
+ git_commit_free(commit);
+ GIT_ERROR_CHECK_ALLOC(packed_commit);
+
+ error = git_vector_insert(state->commits, packed_commit);
+ if (error < 0) {
+ packed_commit_free(packed_commit);
+ return error;
+ }
+
+ return 0;
+}
+
+int git_commit_graph_writer_add_index_file(
+ git_commit_graph_writer *w,
+ git_repository *repo,
+ const char *idx_path)
+{
+ int error;
+ struct git_pack_file *p = NULL;
+ struct object_entry_cb_state state = {0};
+ state.repo = repo;
+ state.commits = &w->commits;
+
+ error = git_repository_odb(&state.db, repo);
+ if (error < 0)
+ goto cleanup;
+
+ error = git_mwindow_get_pack(&p, idx_path);
+ if (error < 0)
+ goto cleanup;
+
+ error = git_pack_foreach_entry(p, object_entry__cb, &state);
+ if (error < 0)
+ goto cleanup;
+
+cleanup:
+ if (p)
+ git_mwindow_put_pack(p);
+ git_odb_free(state.db);
+ return error;
+}
+
+int git_commit_graph_writer_add_revwalk(git_commit_graph_writer *w, git_revwalk *walk)
+{
+ int error;
+ git_oid id;
+ git_repository *repo = git_revwalk_repository(walk);
+ git_commit *commit;
+ struct packed_commit *packed_commit;
+
+ while ((git_revwalk_next(&id, walk)) == 0) {
+ error = git_commit_lookup(&commit, repo, &id);
+ if (error < 0)
+ return error;
+
+ packed_commit = packed_commit_new(commit);
+ git_commit_free(commit);
+ GIT_ERROR_CHECK_ALLOC(packed_commit);
+
+ error = git_vector_insert(&w->commits, packed_commit);
+ if (error < 0) {
+ packed_commit_free(packed_commit);
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+enum generation_number_commit_state {
+ GENERATION_NUMBER_COMMIT_STATE_UNVISITED = 0,
+ GENERATION_NUMBER_COMMIT_STATE_ADDED = 1,
+ GENERATION_NUMBER_COMMIT_STATE_EXPANDED = 2,
+ GENERATION_NUMBER_COMMIT_STATE_VISITED = 3,
+};
+
+static int compute_generation_numbers(git_vector *commits)
+{
+ git_array_t(size_t) index_stack = GIT_ARRAY_INIT;
+ size_t i, j;
+ size_t *parent_idx;
+ enum generation_number_commit_state *commit_states = NULL;
+ struct packed_commit *child_packed_commit;
+ git_oidmap *packed_commit_map = NULL;
+ int error = 0;
+
+ /* First populate the parent indices fields */
+ error = git_oidmap_new(&packed_commit_map);
+ if (error < 0)
+ goto cleanup;
+ git_vector_foreach (commits, i, child_packed_commit) {
+ child_packed_commit->index = i;
+ error = git_oidmap_set(
+ packed_commit_map, &child_packed_commit->sha1, child_packed_commit);
+ if (error < 0)
+ goto cleanup;
+ }
+
+ git_vector_foreach (commits, i, child_packed_commit) {
+ size_t parent_i, *parent_idx_ptr;
+ struct packed_commit *parent_packed_commit;
+ git_oid *parent_id;
+ git_array_init_to_size(
+ child_packed_commit->parent_indices,
+ git_array_size(child_packed_commit->parents));
+ if (git_array_size(child_packed_commit->parents)
+ && !child_packed_commit->parent_indices.ptr) {
+ error = -1;
+ goto cleanup;
+ }
+ git_array_foreach (child_packed_commit->parents, parent_i, parent_id) {
+ parent_packed_commit = git_oidmap_get(packed_commit_map, parent_id);
+ if (!parent_packed_commit) {
+ git_error_set(GIT_ERROR_ODB,
+ "parent commit %s not found in commit graph",
+ git_oid_tostr_s(parent_id));
+ error = GIT_ENOTFOUND;
+ goto cleanup;
+ }
+ parent_idx_ptr = git_array_alloc(child_packed_commit->parent_indices);
+ if (!parent_idx_ptr) {
+ error = -1;
+ goto cleanup;
+ }
+ *parent_idx_ptr = parent_packed_commit->index;
+ }
+ }
+
+ /*
+ * We copy all the commits to the stack and then during visitation,
+ * each node can be added up to two times to the stack.
+ */
+ git_array_init_to_size(index_stack, 3 * git_vector_length(commits));
+ if (!index_stack.ptr) {
+ error = -1;
+ goto cleanup;
+ }
+
+ commit_states = (enum generation_number_commit_state *)git__calloc(
+ git_vector_length(commits), sizeof(enum generation_number_commit_state));
+ if (!commit_states) {
+ error = -1;
+ goto cleanup;
+ }
+
+ /*
+ * Perform a Post-Order traversal so that all parent nodes are fully
+ * visited before the child node.
+ */
+ git_vector_foreach (commits, i, child_packed_commit)
+ *(size_t *)git_array_alloc(index_stack) = i;
+
+ while (git_array_size(index_stack)) {
+ size_t *index_ptr = git_array_pop(index_stack);
+ i = *index_ptr;
+ child_packed_commit = git_vector_get(commits, i);
+
+ if (commit_states[i] == GENERATION_NUMBER_COMMIT_STATE_VISITED) {
+ /* This commit has already been fully visited. */
+ continue;
+ }
+ if (commit_states[i] == GENERATION_NUMBER_COMMIT_STATE_EXPANDED) {
+ /* All of the commits parents have been visited. */
+ child_packed_commit->generation = 0;
+ git_array_foreach (child_packed_commit->parent_indices, j, parent_idx) {
+ struct packed_commit *parent = git_vector_get(commits, *parent_idx);
+ if (child_packed_commit->generation < parent->generation)
+ child_packed_commit->generation = parent->generation;
+ }
+ if (child_packed_commit->generation
+ < GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX) {
+ ++child_packed_commit->generation;
+ }
+ commit_states[i] = GENERATION_NUMBER_COMMIT_STATE_VISITED;
+ continue;
+ }
+
+ /*
+ * This is the first time we see this commit. We need
+ * to visit all its parents before we can fully visit
+ * it.
+ */
+ if (git_array_size(child_packed_commit->parent_indices) == 0) {
+ /*
+ * Special case: if the commit has no parents, there's
+ * no need to add it to the stack just to immediately
+ * remove it.
+ */
+ commit_states[i] = GENERATION_NUMBER_COMMIT_STATE_VISITED;
+ child_packed_commit->generation = 1;
+ continue;
+ }
+
+ /*
+ * Add this current commit again so that it is visited
+ * again once all its children have been visited.
+ */
+ *(size_t *)git_array_alloc(index_stack) = i;
+ git_array_foreach (child_packed_commit->parent_indices, j, parent_idx) {
+ if (commit_states[*parent_idx]
+ != GENERATION_NUMBER_COMMIT_STATE_UNVISITED) {
+ /* This commit has already been considered. */
+ continue;
+ }
+
+ commit_states[*parent_idx] = GENERATION_NUMBER_COMMIT_STATE_ADDED;
+ *(size_t *)git_array_alloc(index_stack) = *parent_idx;
+ }
+ commit_states[i] = GENERATION_NUMBER_COMMIT_STATE_EXPANDED;
+ }
+
+cleanup:
+ git_oidmap_free(packed_commit_map);
+ git__free(commit_states);
+ git_array_clear(index_stack);
+
+ return error;
+}
+
+static int write_offset(off64_t offset, commit_graph_write_cb write_cb, void *cb_data)
+{
+ int error;
+ uint32_t word;
+
+ word = htonl((uint32_t)((offset >> 32) & 0xffffffffu));
+ error = write_cb((const char *)&word, sizeof(word), cb_data);
+ if (error < 0)
+ return error;
+ word = htonl((uint32_t)((offset >> 0) & 0xffffffffu));
+ error = write_cb((const char *)&word, sizeof(word), cb_data);
+ if (error < 0)
+ return error;
+
+ return 0;
+}
+
+static int write_chunk_header(
+ int chunk_id,
+ off64_t offset,
+ commit_graph_write_cb write_cb,
+ void *cb_data)
+{
+ uint32_t word = htonl(chunk_id);
+ int error = write_cb((const char *)&word, sizeof(word), cb_data);
+ if (error < 0)
+ return error;
+ return write_offset(offset, write_cb, cb_data);
+}
+
+static int commit_graph_write_buf(const char *buf, size_t size, void *data)
+{
+ git_buf *b = (git_buf *)data;
+ return git_buf_put(b, buf, size);
+}
+
+struct commit_graph_write_hash_context {
+ commit_graph_write_cb write_cb;
+ void *cb_data;
+ git_hash_ctx *ctx;
+};
+
+static int commit_graph_write_hash(const char *buf, size_t size, void *data)
+{
+ struct commit_graph_write_hash_context *ctx = data;
+ int error;
+
+ error = git_hash_update(ctx->ctx, buf, size);
+ if (error < 0)
+ return error;
+
+ return ctx->write_cb(buf, size, ctx->cb_data);
+}
+
+static void packed_commit_free_dup(void *packed_commit)
+{
+ packed_commit_free(packed_commit);
+}
+
+static int commit_graph_write(
+ git_commit_graph_writer *w,
+ commit_graph_write_cb write_cb,
+ void *cb_data)
+{
+ int error = 0;
+ size_t i;
+ struct packed_commit *packed_commit;
+ struct git_commit_graph_header hdr = {0};
+ uint32_t oid_fanout_count;
+ uint32_t extra_edge_list_count;
+ uint32_t oid_fanout[256];
+ off64_t offset;
+ git_buf oid_lookup = GIT_BUF_INIT, commit_data = GIT_BUF_INIT,
+ extra_edge_list = GIT_BUF_INIT;
+ git_oid cgraph_checksum = {{0}};
+ git_hash_ctx ctx;
+ struct commit_graph_write_hash_context hash_cb_data = {0};
+
+ hdr.signature = htonl(COMMIT_GRAPH_SIGNATURE);
+ hdr.version = COMMIT_GRAPH_VERSION;
+ hdr.object_id_version = COMMIT_GRAPH_OBJECT_ID_VERSION;
+ hdr.chunks = 0;
+ hdr.base_graph_files = 0;
+ hash_cb_data.write_cb = write_cb;
+ hash_cb_data.cb_data = cb_data;
+ hash_cb_data.ctx = &ctx;
+
+ error = git_hash_ctx_init(&ctx);
+ if (error < 0)
+ return error;
+ cb_data = &hash_cb_data;
+ write_cb = commit_graph_write_hash;
+
+ /* Sort the commits. */
+ git_vector_sort(&w->commits);
+ git_vector_uniq(&w->commits, packed_commit_free_dup);
+ error = compute_generation_numbers(&w->commits);
+ if (error < 0)
+ goto cleanup;
+
+ /* Fill the OID Fanout table. */
+ oid_fanout_count = 0;
+ for (i = 0; i < 256; i++) {
+ while (oid_fanout_count < git_vector_length(&w->commits) &&
+ (packed_commit = (struct packed_commit *)git_vector_get(&w->commits, oid_fanout_count)) &&
+ packed_commit->sha1.id[0] <= i)
+ ++oid_fanout_count;
+ oid_fanout[i] = htonl(oid_fanout_count);
+ }
+
+ /* Fill the OID Lookup table. */
+ git_vector_foreach (&w->commits, i, packed_commit) {
+ error = git_buf_put(&oid_lookup,
+ (const char *)&packed_commit->sha1, sizeof(git_oid));
+ if (error < 0)
+ goto cleanup;
+ }
+
+ /* Fill the Commit Data and Extra Edge List tables. */
+ extra_edge_list_count = 0;
+ git_vector_foreach (&w->commits, i, packed_commit) {
+ uint64_t commit_time;
+ uint32_t generation;
+ uint32_t word;
+ size_t *packed_index;
+ unsigned int parentcount = (unsigned int)git_array_size(packed_commit->parents);
+
+ error = git_buf_put(&commit_data,
+ (const char *)&packed_commit->tree_oid,
+ sizeof(git_oid));
+ if (error < 0)
+ goto cleanup;
+
+ if (parentcount == 0) {
+ word = htonl(GIT_COMMIT_GRAPH_MISSING_PARENT);
+ } else {
+ packed_index = git_array_get(packed_commit->parent_indices, 0);
+ word = htonl((uint32_t)*packed_index);
+ }
+ error = git_buf_put(&commit_data, (const char *)&word, sizeof(word));
+ if (error < 0)
+ goto cleanup;
+
+ if (parentcount < 2) {
+ word = htonl(GIT_COMMIT_GRAPH_MISSING_PARENT);
+ } else if (parentcount == 2) {
+ packed_index = git_array_get(packed_commit->parent_indices, 1);
+ word = htonl((uint32_t)*packed_index);
+ } else {
+ word = htonl(0x80000000u | extra_edge_list_count);
+ }
+ error = git_buf_put(&commit_data, (const char *)&word, sizeof(word));
+ if (error < 0)
+ goto cleanup;
+
+ if (parentcount > 2) {
+ unsigned int parent_i;
+ for (parent_i = 1; parent_i < parentcount; ++parent_i) {
+ packed_index = git_array_get(
+ packed_commit->parent_indices, parent_i);
+ word = htonl((uint32_t)(*packed_index | (parent_i + 1 == parentcount ? 0x80000000u : 0)));
+
+ error = git_buf_put(&extra_edge_list,
+ (const char *)&word,
+ sizeof(word));
+ if (error < 0)
+ goto cleanup;
+ }
+ extra_edge_list_count += parentcount - 1;
+ }
+
+ generation = packed_commit->generation;
+ commit_time = (uint64_t)packed_commit->commit_time;
+ if (generation > GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX)
+ generation = GIT_COMMIT_GRAPH_GENERATION_NUMBER_MAX;
+ word = ntohl((uint32_t)((generation << 2) | ((commit_time >> 32ull) & 0x3ull)));
+ error = git_buf_put(&commit_data, (const char *)&word, sizeof(word));
+ if (error < 0)
+ goto cleanup;
+ word = ntohl((uint32_t)(commit_time & 0xffffffffull));
+ error = git_buf_put(&commit_data, (const char *)&word, sizeof(word));
+ if (error < 0)
+ goto cleanup;
+ }
+
+ /* Write the header. */
+ hdr.chunks = 3;
+ if (git_buf_len(&extra_edge_list) > 0)
+ hdr.chunks++;
+ error = write_cb((const char *)&hdr, sizeof(hdr), cb_data);
+ if (error < 0)
+ goto cleanup;
+
+ /* Write the chunk headers. */
+ offset = sizeof(hdr) + (hdr.chunks + 1) * 12;
+ error = write_chunk_header(COMMIT_GRAPH_OID_FANOUT_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += sizeof(oid_fanout);
+ error = write_chunk_header(COMMIT_GRAPH_OID_LOOKUP_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += git_buf_len(&oid_lookup);
+ error = write_chunk_header(COMMIT_GRAPH_COMMIT_DATA_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += git_buf_len(&commit_data);
+ if (git_buf_len(&extra_edge_list) > 0) {
+ error = write_chunk_header(
+ COMMIT_GRAPH_EXTRA_EDGE_LIST_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += git_buf_len(&extra_edge_list);
+ }
+ error = write_chunk_header(0, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+
+ /* Write all the chunks. */
+ error = write_cb((const char *)oid_fanout, sizeof(oid_fanout), cb_data);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb(git_buf_cstr(&oid_lookup), git_buf_len(&oid_lookup), cb_data);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb(git_buf_cstr(&commit_data), git_buf_len(&commit_data), cb_data);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb(git_buf_cstr(&extra_edge_list), git_buf_len(&extra_edge_list), cb_data);
+ if (error < 0)
+ goto cleanup;
+
+ /* Finalize the checksum and write the trailer. */
+ error = git_hash_final(&cgraph_checksum, &ctx);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb((const char *)&cgraph_checksum, sizeof(cgraph_checksum), cb_data);
+ if (error < 0)
+ goto cleanup;
+
+cleanup:
+ git_buf_dispose(&oid_lookup);
+ git_buf_dispose(&commit_data);
+ git_buf_dispose(&extra_edge_list);
+ git_hash_ctx_cleanup(&ctx);
+ return error;
+}
+
+static int commit_graph_write_filebuf(const char *buf, size_t size, void *data)
+{
+ git_filebuf *f = (git_filebuf *)data;
+ return git_filebuf_write(f, buf, size);
+}
+
+int git_commit_graph_writer_options_init(
+ git_commit_graph_writer_options *opts,
+ unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
+ opts,
+ version,
+ git_commit_graph_writer_options,
+ GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT);
+ return 0;
+}
+
+int git_commit_graph_writer_commit(
+ git_commit_graph_writer *w,
+ git_commit_graph_writer_options *opts)
+{
+ int error;
+ int filebuf_flags = GIT_FILEBUF_DO_NOT_BUFFER;
+ git_buf commit_graph_path = GIT_BUF_INIT;
+ git_filebuf output = GIT_FILEBUF_INIT;
+
+ /* TODO: support options and fill in defaults. */
+ GIT_UNUSED(opts);
+
+ error = git_buf_joinpath(
+ &commit_graph_path, git_buf_cstr(&w->objects_info_dir), "commit-graph");
+ if (error < 0)
+ return error;
+
+ if (git_repository__fsync_gitdir)
+ filebuf_flags |= GIT_FILEBUF_FSYNC;
+ error = git_filebuf_open(&output, git_buf_cstr(&commit_graph_path), filebuf_flags, 0644);
+ git_buf_dispose(&commit_graph_path);
+ if (error < 0)
+ return error;
+
+ error = commit_graph_write(w, commit_graph_write_filebuf, &output);
+ if (error < 0) {
+ git_filebuf_cleanup(&output);
+ return error;
+ }
+
+ return git_filebuf_commit(&output);
+}
+
+int git_commit_graph_writer_dump(
+ git_buf *cgraph,
+ git_commit_graph_writer *w,
+ git_commit_graph_writer_options *opts)
+{
+ /* TODO: support options. */
+ GIT_UNUSED(opts);
+ return commit_graph_write(w, commit_graph_write_buf, cgraph);
+}
diff --git a/src/commit_graph.h b/src/commit_graph.h
new file mode 100644
index 000000000..9d0a827de
--- /dev/null
+++ b/src/commit_graph.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#ifndef INCLUDE_commit_graph_h__
+#define INCLUDE_commit_graph_h__
+
+#include "common.h"
+
+#include "git2/types.h"
+#include "git2/sys/commit_graph.h"
+
+#include "map.h"
+#include "vector.h"
+
+/**
+ * A commit-graph file.
+ *
+ * This file contains metadata about commits, particularly the generation
+ * number for each one. This can help speed up graph operations without
+ * requiring a full graph traversal.
+ *
+ * Support for this feature was added in git 2.19.
+ */
+typedef struct git_commit_graph_file {
+ git_map graph_map;
+
+ /* The OID Fanout table. */
+ const uint32_t *oid_fanout;
+ /* The total number of commits in the graph. */
+ uint32_t num_commits;
+
+ /* The OID Lookup table. */
+ git_oid *oid_lookup;
+
+ /*
+ * The Commit Data table. Each entry contains the OID of the commit followed
+ * by two 8-byte fields in network byte order:
+ * - The indices of the first two parents (32 bits each).
+ * - The generation number (first 30 bits) and commit time in seconds since
+ * UNIX epoch (34 bits).
+ */
+ const unsigned char *commit_data;
+
+ /*
+ * The Extra Edge List table. Each 4-byte entry is a network byte order index
+ * of one of the i-th (i > 0) parents of commits in the `commit_data` table,
+ * when the commit has more than 2 parents.
+ */
+ const unsigned char *extra_edge_list;
+ /* The number of entries in the Extra Edge List table. Each entry is 4 bytes wide. */
+ size_t num_extra_edge_list;
+
+ /* The trailer of the file. Contains the SHA1-checksum of the whole file. */
+ git_oid checksum;
+} git_commit_graph_file;
+
+/**
+ * An entry in the commit-graph file. Provides a subset of the information that
+ * can be obtained from the commit header.
+ */
+typedef struct git_commit_graph_entry {
+ /* The generation number of the commit within the graph */
+ size_t generation;
+
+ /* Time in seconds from UNIX epoch. */
+ git_time_t commit_time;
+
+ /* The number of parents of the commit. */
+ size_t parent_count;
+
+ /*
+ * The indices of the parent commits within the Commit Data table. The value
+ * of `GIT_COMMIT_GRAPH_MISSING_PARENT` indicates that no parent is in that
+ * position.
+ */
+ size_t parent_indices[2];
+
+ /* The index within the Extra Edge List of any parent after the first two. */
+ size_t extra_parents_index;
+
+ /* The SHA-1 hash of the root tree of the commit. */
+ git_oid tree_oid;
+
+ /* The SHA-1 hash of the requested commit. */
+ git_oid sha1;
+} git_commit_graph_entry;
+
+/* A wrapper for git_commit_graph_file to enable lazy loading in the ODB. */
+struct git_commit_graph {
+ /* The path to the commit-graph file. Something like ".git/objects/info/commit-graph". */
+ git_buf filename;
+
+ /* The underlying commit-graph file. */
+ git_commit_graph_file *file;
+
+ /* Whether the commit-graph file was already checked for validity. */
+ bool checked;
+};
+
+/** Create a new commit-graph, optionally opening the underlying file. */
+int git_commit_graph_new(git_commit_graph **cgraph_out, const char *objects_dir, bool open_file);
+
+/** Open and validate a commit-graph file. */
+int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *path);
+
+/*
+ * Attempt to get the git_commit_graph's commit-graph file. This object is
+ * still owned by the git_commit_graph. If the repository does not contain a commit graph,
+ * it will return GIT_ENOTFOUND.
+ *
+ * This function is not thread-safe.
+ */
+int git_commit_graph_get_file(git_commit_graph_file **file_out, git_commit_graph *cgraph);
+
+/* Marks the commit-graph file as needing a refresh. */
+void git_commit_graph_refresh(git_commit_graph *cgraph);
+
+/*
+ * A writer for `commit-graph` files.
+ */
+struct git_commit_graph_writer {
+ /*
+ * The path of the `objects/info` directory where the `commit-graph` will be
+ * stored.
+ */
+ git_buf objects_info_dir;
+
+ /* The list of packed commits. */
+ git_vector commits;
+};
+
+/*
+ * Returns whether the git_commit_graph_file needs to be reloaded since the
+ * contents of the commit-graph file have changed on disk.
+ */
+bool git_commit_graph_file_needs_refresh(
+ const git_commit_graph_file *file, const char *path);
+
+int git_commit_graph_entry_find(
+ git_commit_graph_entry *e,
+ const git_commit_graph_file *file,
+ const git_oid *short_oid,
+ size_t len);
+int git_commit_graph_entry_parent(
+ git_commit_graph_entry *parent,
+ const git_commit_graph_file *file,
+ const git_commit_graph_entry *entry,
+ size_t n);
+int git_commit_graph_file_close(git_commit_graph_file *cgraph);
+void git_commit_graph_file_free(git_commit_graph_file *cgraph);
+
+/* This is exposed for use in the fuzzers. */
+int git_commit_graph_file_parse(
+ git_commit_graph_file *file,
+ const unsigned char *data,
+ size_t size);
+
+#endif
diff --git a/src/commit_list.c b/src/commit_list.c
index 2e103ec22..692b1495f 100644
--- a/src/commit_list.c
+++ b/src/commit_list.c
@@ -12,6 +12,24 @@
#include "odb.h"
#include "commit.h"
+int git_commit_list_generation_cmp(const void *a, const void *b)
+{
+ uint32_t generation_a = ((git_commit_list_node *) a)->generation;
+ uint32_t generation_b = ((git_commit_list_node *) b)->generation;
+
+ if (!generation_a || !generation_b) {
+ /* Fall back to comparing by timestamps if at least one commit lacks a generation. */
+ return git_commit_list_time_cmp(a, b);
+ }
+
+ if (generation_a < generation_b)
+ return 1;
+ if (generation_a > generation_b)
+ return -1;
+
+ return 0;
+}
+
int git_commit_list_time_cmp(const void *a, const void *b)
{
int64_t time_a = ((git_commit_list_node *) a)->time;
@@ -124,6 +142,7 @@ static int commit_quick_parse(
return -1;
}
+ node->generation = 0;
node->time = commit->committer->when.time;
node->out_degree = (uint16_t) git_array_size(commit->parent_ids);
node->parents = alloc_parents(walk, node, node->out_degree);
@@ -143,11 +162,38 @@ static int commit_quick_parse(
int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit)
{
git_odb_object *obj;
+ git_commit_graph_file *cgraph_file = NULL;
int error;
if (commit->parsed)
return 0;
+ /* Let's try to use the commit graph first. */
+ git_odb__get_commit_graph_file(&cgraph_file, walk->odb);
+ if (cgraph_file) {
+ git_commit_graph_entry e;
+
+ error = git_commit_graph_entry_find(&e, cgraph_file, &commit->oid, GIT_OID_RAWSZ);
+ if (error == 0 && git__is_uint16(e.parent_count)) {
+ size_t i;
+ commit->generation = (uint32_t)e.generation;
+ commit->time = e.commit_time;
+ commit->out_degree = (uint16_t)e.parent_count;
+ commit->parents = alloc_parents(walk, commit, commit->out_degree);
+ GIT_ERROR_CHECK_ALLOC(commit->parents);
+
+ for (i = 0; i < commit->out_degree; ++i) {
+ git_commit_graph_entry parent;
+ error = git_commit_graph_entry_parent(&parent, cgraph_file, &e, i);
+ if (error < 0)
+ return error;
+ commit->parents[i] = git_revwalk__commit_lookup(walk, &parent.sha1);
+ }
+ commit->parsed = 1;
+ return 0;
+ }
+ }
+
if ((error = git_odb_read(&obj, walk->odb, &commit->oid)) < 0)
return error;
diff --git a/src/commit_list.h b/src/commit_list.h
index 6a65f8a76..aad39f351 100644
--- a/src/commit_list.h
+++ b/src/commit_list.h
@@ -26,6 +26,7 @@
typedef struct git_commit_list_node {
git_oid oid;
int64_t time;
+ uint32_t generation;
unsigned int seen:1,
uninteresting:1,
topo_delay:1,
@@ -45,6 +46,7 @@ typedef struct git_commit_list {
} git_commit_list;
git_commit_list_node *git_commit_list_alloc_node(git_revwalk *walk);
+int git_commit_list_generation_cmp(const void *a, const void *b);
int git_commit_list_time_cmp(const void *a, const void *b);
void git_commit_list_free(git_commit_list **list_p);
git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p);
diff --git a/src/common.h b/src/common.h
index 2b1a4a456..9bb1116b5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -19,6 +19,8 @@
# define GIT_INLINE(type) static __inline type
#elif defined(__GNUC__)
# define GIT_INLINE(type) static __inline__ type
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define GIT_INLINE(type) static inline type
#else
# define GIT_INLINE(type) static type
#endif
@@ -28,6 +30,24 @@
# define __has_builtin(x) 0
#endif
+/**
+ * Declare that a function's return value must be used.
+ *
+ * Used mostly to guard against potential silent bugs at runtime. This is
+ * recommended to be added to functions that:
+ *
+ * - Allocate / reallocate memory. This prevents memory leaks or errors where
+ * buffers are expected to have grown to a certain size, but could not be
+ * resized.
+ * - Acquire locks. When a lock cannot be acquired, that will almost certainly
+ * cause a data race / undefined behavior.
+ */
+#if defined(__GNUC__)
+# define GIT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+# define GIT_WARN_UNUSED_RESULT
+#endif
+
#include <assert.h>
#include <errno.h>
#include <limits.h>
@@ -63,7 +83,9 @@
# include <pthread.h>
# include <sched.h>
# endif
-#define GIT_STDLIB_CALL
+
+#define GIT_LIBGIT2_CALL
+#define GIT_SYSTEM_CALL
#ifdef GIT_USE_STAT_ATIMESPEC
# define st_atim st_atimespec
@@ -78,9 +100,10 @@
#include "git2/types.h"
#include "git2/errors.h"
#include "errors.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "integer.h"
#include "assert_safe.h"
+#include "utf8.h"
/*
* Include the declarations for deprecated functions; this ensures
diff --git a/src/config.c b/src/config.c
index 81f010fa2..3251cd51f 100644
--- a/src/config.c
+++ b/src/config.c
@@ -10,7 +10,6 @@
#include "git2/config.h"
#include "git2/sys/config.h"
-#include "buf_text.h"
#include "config_backend.h"
#include "regexp.h"
#include "sysdir.h"
@@ -108,7 +107,8 @@ int git_config_add_file_ondisk(
struct stat st;
int res;
- assert(cfg && path);
+ GIT_ASSERT_ARG(cfg);
+ GIT_ASSERT_ARG(path);
res = p_stat(path, &st);
if (res < 0 && errno != ENOENT && errno != ENOTDIR) {
@@ -316,7 +316,8 @@ int git_config_add_backend(
backend_internal *internal;
int result;
- assert(cfg && backend);
+ GIT_ASSERT_ARG(cfg);
+ GIT_ASSERT_ARG(backend);
GIT_ERROR_CHECK_VERSION(backend, GIT_CONFIG_BACKEND_VERSION, "git_config_backend");
@@ -510,11 +511,12 @@ int git_config_backend_foreach_match(
void *payload)
{
git_config_entry *entry;
- git_config_iterator* iter;
+ git_config_iterator *iter;
git_regexp regex;
int error = 0;
- assert(backend && cb);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(cb);
if (regexp && git_regexp_compile(&regex, regexp, 0) < 0)
return -1;
@@ -886,7 +888,8 @@ int git_config_get_string_buf(
int ret;
const char *str;
- git_buf_sanitize(out);
+ if ((ret = git_buf_sanitize(out)) < 0)
+ return ret;
ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
str = !ret ? (entry->value ? entry->value : "") : NULL;
@@ -1084,19 +1087,31 @@ void git_config_iterator_free(git_config_iterator *iter)
int git_config_find_global(git_buf *path)
{
- git_buf_sanitize(path);
+ int error;
+
+ if ((error = git_buf_sanitize(path)) < 0)
+ return error;
+
return git_sysdir_find_global_file(path, GIT_CONFIG_FILENAME_GLOBAL);
}
int git_config_find_xdg(git_buf *path)
{
- git_buf_sanitize(path);
+ int error;
+
+ if ((error = git_buf_sanitize(path)) < 0)
+ return error;
+
return git_sysdir_find_xdg_file(path, GIT_CONFIG_FILENAME_XDG);
}
int git_config_find_system(git_buf *path)
{
- git_buf_sanitize(path);
+ int error;
+
+ if ((error = git_buf_sanitize(path)) < 0)
+ return error;
+
return git_sysdir_find_system_file(path, GIT_CONFIG_FILENAME_SYSTEM);
}
@@ -1104,7 +1119,9 @@ int git_config_find_programdata(git_buf *path)
{
int ret;
- git_buf_sanitize(path);
+ if ((ret = git_buf_sanitize(path)) < 0)
+ return ret;
+
ret = git_sysdir_find_programdata_file(path,
GIT_CONFIG_FILENAME_PROGRAMDATA);
if (ret != GIT_OK)
@@ -1182,7 +1199,7 @@ int git_config_lock(git_transaction **out, git_config *cfg)
git_config_backend *backend;
backend_internal *internal;
- assert(cfg);
+ GIT_ASSERT_ARG(cfg);
internal = git_vector_get(&cfg->backends, 0);
if (!internal || !internal->backend) {
@@ -1202,7 +1219,7 @@ int git_config_unlock(git_config *cfg, int commit)
git_config_backend *backend;
backend_internal *internal;
- assert(cfg);
+ GIT_ASSERT_ARG(cfg);
internal = git_vector_get(&cfg->backends, 0);
if (!internal || !internal->backend) {
@@ -1227,9 +1244,6 @@ int git_config_lookup_map_value(
{
size_t i;
- if (!value)
- goto fail_parse;
-
for (i = 0; i < map_n; ++i) {
const git_configmap *m = maps + i;
@@ -1238,7 +1252,7 @@ int git_config_lookup_map_value(
case GIT_CONFIGMAP_TRUE: {
int bool_val;
- if (git__parse_bool(&bool_val, value) == 0 &&
+ if (git_config_parse_bool(&bool_val, value) == 0 &&
bool_val == (int)m->type) {
*out = m->map_value;
return 0;
@@ -1252,7 +1266,7 @@ int git_config_lookup_map_value(
break;
case GIT_CONFIGMAP_STRING:
- if (strcasecmp(value, m->str_match) == 0) {
+ if (value && strcasecmp(value, m->str_match) == 0) {
*out = m->map_value;
return 0;
}
@@ -1260,7 +1274,6 @@ int git_config_lookup_map_value(
}
}
-fail_parse:
git_error_set(GIT_ERROR_CONFIG, "failed to map '%s'", value);
return -1;
}
@@ -1364,9 +1377,13 @@ fail_parse:
int git_config_parse_path(git_buf *out, const char *value)
{
- assert(out && value);
+ int error;
- git_buf_sanitize(out);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(value);
+
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
if (value[0] == '~') {
if (value[1] != '\0' && value[1] != '/') {
@@ -1409,7 +1426,8 @@ int git_config__normalize_name(const char *in, char **out)
{
char *name, *fdot, *ldot;
- assert(in && out);
+ GIT_ASSERT_ARG(in);
+ GIT_ASSERT_ARG(out);
name = git__strdup(in);
GIT_ERROR_CHECK_ALLOC(name);
@@ -1478,7 +1496,7 @@ int git_config_rename_section(
int error = 0;
struct rename_data data;
- git_buf_text_puts_escape_regex(&pattern, old_section_name);
+ git_buf_puts_escape_regex(&pattern, old_section_name);
if ((error = git_buf_puts(&pattern, "\\..+")) < 0)
goto cleanup;
diff --git a/src/config_cache.c b/src/config_cache.c
index e4e071b54..4bb91f52b 100644
--- a/src/config_cache.c
+++ b/src/config_cache.c
@@ -86,6 +86,7 @@ static struct map_data _configmaps[] = {
{"core.protecthfs", NULL, 0, GIT_PROTECTHFS_DEFAULT },
{"core.protectntfs", NULL, 0, GIT_PROTECTNTFS_DEFAULT },
{"core.fsyncobjectfiles", NULL, 0, GIT_FSYNCOBJECTFILES_DEFAULT },
+ {"core.longpaths", NULL, 0, GIT_LONGPATHS_DEFAULT },
};
int git_config__configmap_lookup(int *out, git_config *config, git_configmap_item item)
@@ -111,17 +112,21 @@ int git_config__configmap_lookup(int *out, git_config *config, git_configmap_ite
int git_repository__configmap_lookup(int *out, git_repository *repo, git_configmap_item item)
{
- *out = repo->configmap_cache[(int)item];
+ intptr_t value = (intptr_t)git_atomic_load(repo->configmap_cache[(int)item]);
- if (*out == GIT_CONFIGMAP_NOT_CACHED) {
- int error;
+ *out = (int)value;
+
+ if (value == GIT_CONFIGMAP_NOT_CACHED) {
git_config *config;
+ intptr_t oldval = value;
+ int error;
if ((error = git_repository_config__weakptr(&config, repo)) < 0 ||
(error = git_config__configmap_lookup(out, config, item)) < 0)
return error;
- repo->configmap_cache[(int)item] = *out;
+ value = *out;
+ git_atomic_compare_and_swap(&repo->configmap_cache[(int)item], (void *)oldval, (void *)value);
}
return 0;
diff --git a/src/config_entries.c b/src/config_entries.c
index 3ddd3369a..66aae096d 100644
--- a/src/config_entries.c
+++ b/src/config_entries.c
@@ -11,9 +11,13 @@ typedef struct config_entry_list {
struct config_entry_list *next;
struct config_entry_list *last;
git_config_entry *entry;
- bool first;
} config_entry_list;
+typedef struct {
+ git_config_entry *entry;
+ bool multivar;
+} config_entry_map_head;
+
typedef struct config_entries_iterator {
git_config_iterator parent;
git_config_entries *entries;
@@ -102,14 +106,16 @@ void git_config_entries_incref(git_config_entries *entries)
static void config_entries_free(git_config_entries *entries)
{
config_entry_list *list = NULL, *next;
+ config_entry_map_head *head;
+ git_strmap_foreach_value(entries->map, head,
+ git__free((char *) head->entry->name); git__free(head)
+ );
git_strmap_free(entries->map);
list = entries->list;
while (list != NULL) {
next = list->next;
- if (list->first)
- git__free((char *) list->entry->name);
git__free((char *) list->entry->value);
git__free(list->entry);
git__free(list);
@@ -127,40 +133,42 @@ void git_config_entries_free(git_config_entries *entries)
int git_config_entries_append(git_config_entries *entries, git_config_entry *entry)
{
- config_entry_list *existing, *head;
-
- head = git__calloc(1, sizeof(config_entry_list));
- GIT_ERROR_CHECK_ALLOC(head);
- head->entry = entry;
-
- /*
- * This is a micro-optimization for configuration files
- * with a lot of same keys. As for multivars the entry's
- * key will be the same for all entries, we can just free
- * all except the first entry's name and just re-use it.
- */
- if ((existing = git_strmap_get(entries->map, entry->name)) != NULL) {
+ config_entry_list *list_head;
+ config_entry_map_head *map_head;
+
+ if ((map_head = git_strmap_get(entries->map, entry->name)) != NULL) {
+ map_head->multivar = true;
+ /*
+ * This is a micro-optimization for configuration files
+ * with a lot of same keys. As for multivars the entry's
+ * key will be the same for all entries, we can just free
+ * all except the first entry's name and just re-use it.
+ */
git__free((char *) entry->name);
- entry->name = existing->entry->name;
+ entry->name = map_head->entry->name;
} else {
- head->first = 1;
+ map_head = git__calloc(1, sizeof(*map_head));
+ if ((git_strmap_set(entries->map, entry->name, map_head)) < 0)
+ return -1;
}
+ map_head->entry = entry;
+
+ list_head = git__calloc(1, sizeof(config_entry_list));
+ GIT_ERROR_CHECK_ALLOC(list_head);
+ list_head->entry = entry;
if (entries->list)
- entries->list->last->next = head;
+ entries->list->last->next = list_head;
else
- entries->list = head;
- entries->list->last = head;
-
- if (git_strmap_set(entries->map, entry->name, head) < 0)
- return -1;
+ entries->list = list_head;
+ entries->list->last = list_head;
return 0;
}
int git_config_entries_get(git_config_entry **out, git_config_entries *entries, const char *key)
{
- config_entry_list *entry;
+ config_entry_map_head *entry;
if ((entry = git_strmap_get(entries->map, key)) == NULL)
return GIT_ENOTFOUND;
*out = entry->entry;
@@ -169,12 +177,12 @@ int git_config_entries_get(git_config_entry **out, git_config_entries *entries,
int git_config_entries_get_unique(git_config_entry **out, git_config_entries *entries, const char *key)
{
- config_entry_list *entry;
+ config_entry_map_head *entry;
if ((entry = git_strmap_get(entries->map, key)) == NULL)
return GIT_ENOTFOUND;
- if (!entry->first) {
+ if (entry->multivar) {
git_error_set(GIT_ERROR_CONFIG, "entry is not unique due to being a multivar");
return -1;
}
diff --git a/src/config_file.c b/src/config_file.c
index b1e002836..3588e6be6 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -164,23 +164,27 @@ out:
return error;
}
+static void config_file_clear_includes(config_file_backend *cfg)
+{
+ config_file *include;
+ uint32_t i;
+
+ git_array_foreach(cfg->file.includes, i, include)
+ config_file_clear(include);
+ git_array_clear(cfg->file.includes);
+}
+
static int config_file_set_entries(git_config_backend *cfg, git_config_entries *entries)
{
config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
git_config_entries *old = NULL;
- config_file *include;
int error;
- uint32_t i;
if (b->parent.readonly) {
git_error_set(GIT_ERROR_CONFIG, "this backend is read-only");
return -1;
}
- git_array_foreach(b->file.includes, i, include)
- config_file_clear(include);
- git_array_clear(b->file.includes);
-
if ((error = git_mutex_lock(&b->values_mutex)) < 0) {
git_error_set(GIT_ERROR_OS, "failed to lock config backend");
goto out;
@@ -202,6 +206,8 @@ static int config_file_refresh_from_buffer(git_config_backend *cfg, const char *
git_config_entries *entries = NULL;
int error;
+ config_file_clear_includes(b);
+
if ((error = git_config_entries_new(&entries)) < 0 ||
(error = config_file_read_buffer(entries, b->repo, &b->file,
b->level, 0, buf, buflen)) < 0 ||
@@ -229,6 +235,8 @@ static int config_file_refresh(git_config_backend *cfg)
if (!modified)
return 0;
+ config_file_clear_includes(b);
+
if ((error = git_config_entries_new(&entries)) < 0 ||
(error = config_file_read(entries, b->repo, &b->file, b->level, 0)) < 0 ||
(error = config_file_set_entries(cfg, entries)) < 0)
@@ -365,7 +373,7 @@ static int config_file_set_multivar(
int result;
char *key;
- assert(regexp);
+ GIT_ASSERT_ARG(regexp);
if ((result = git_config__normalize_name(name, &key)) < 0)
return result;
@@ -531,7 +539,7 @@ static char *escape_value(const char *ptr)
size_t len;
const char *esc;
- assert(ptr);
+ GIT_ASSERT_ARG_WITH_RETVAL(ptr, NULL);
len = strlen(ptr);
if (!len)
@@ -1096,7 +1104,7 @@ static int write_on_eof(
/*
* This is pretty much the parsing, except we write out anything we don't have
*/
-static int config_file_write(config_file_backend *cfg, const char *orig_key, const char *key, const git_regexp *preg, const char* value)
+static int config_file_write(config_file_backend *cfg, const char *orig_key, const char *key, const git_regexp *preg, const char *value)
{
char *orig_section = NULL, *section = NULL, *orig_name, *name, *ldot;
diff --git a/src/config_parse.c b/src/config_parse.c
index 48ad1164f..9f95e67d7 100644
--- a/src/config_parse.c
+++ b/src/config_parse.c
@@ -7,8 +7,6 @@
#include "config_parse.h"
-#include "buf_text.h"
-
#include <ctype.h>
const char *git_config_escapes = "ntb\"\\";
@@ -187,7 +185,7 @@ static int parse_section_header(git_config_parser *reader, char **section_out)
/* Make sure we were given a section header */
c = line[pos++];
- assert(c == '[');
+ GIT_ASSERT(c == '[');
c = line[pos++];
@@ -230,10 +228,10 @@ fail_parse:
static int skip_bom(git_parse_ctx *parser)
{
git_buf buf = GIT_BUF_INIT_CONST(parser->content, parser->content_len);
- git_bom_t bom;
- int bom_offset = git_buf_text_detect_bom(&bom, &buf);
+ git_buf_bom_t bom;
+ int bom_offset = git_buf_detect_bom(&bom, &buf);
- if (bom == GIT_BOM_UTF8)
+ if (bom == GIT_BUF_BOM_UTF8)
git_parse_advance_chars(parser, bom_offset);
/* TODO: reference implementation is pretty stupid with BoM */
@@ -351,7 +349,7 @@ static int parse_multiline_variable(git_config_parser *reader, git_buf *value, i
}
/* If it was just a comment, pretend it didn't exist */
- quote_count = strip_comments(line, !!in_quotes);
+ quote_count = strip_comments(line, in_quotes);
if (line[0] == '\0')
goto next;
@@ -451,7 +449,7 @@ static int parse_variable(git_config_parser *reader, char **var_name, char **var
git_buf_attach(&multi_value, value, 0);
value = NULL;
- if (parse_multiline_variable(reader, &multi_value, quote_count) < 0 ||
+ if (parse_multiline_variable(reader, &multi_value, quote_count % 2) < 0 ||
git_buf_oom(&multi_value)) {
error = -1;
git_buf_dispose(&multi_value);
diff --git a/src/crlf.c b/src/crlf.c
index 81b5216bc..406f7140f 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -15,7 +15,6 @@
#include "futils.h"
#include "hash.h"
#include "filter.h"
-#include "buf_text.h"
#include "repository.h"
typedef enum {
@@ -219,7 +218,7 @@ static int crlf_apply_to_odb(
if (ca->crlf_action == GIT_CRLF_BINARY || !git_buf_len(from))
return GIT_PASSTHROUGH;
- is_binary = git_buf_text_gather_stats(&stats, from, false);
+ is_binary = git_buf_gather_text_stats(&stats, from, false);
/* Heuristics to see if we can skip the conversion.
* Straight from Core Git.
@@ -247,7 +246,7 @@ static int crlf_apply_to_odb(
return GIT_PASSTHROUGH;
/* Actually drop the carriage returns */
- return git_buf_text_crlf_to_lf(to, from);
+ return git_buf_crlf_to_lf(to, from);
}
static int crlf_apply_to_workdir(
@@ -262,7 +261,7 @@ static int crlf_apply_to_workdir(
if (git_buf_len(from) == 0 || output_eol(ca) != GIT_EOL_CRLF)
return GIT_PASSTHROUGH;
- is_binary = git_buf_text_gather_stats(&stats, from, false);
+ is_binary = git_buf_gather_text_stats(&stats, from, false);
/* If there are no LFs, or all LFs are part of a CRLF, nothing to do */
if (stats.lf == 0 || stats.lf == stats.crlf)
@@ -281,7 +280,7 @@ static int crlf_apply_to_workdir(
return GIT_PASSTHROUGH;
}
- return git_buf_text_lf_to_crlf(to, from);
+ return git_buf_lf_to_crlf(to, from);
}
static int convert_attrs(
@@ -387,6 +386,17 @@ static int crlf_apply(
return crlf_apply_to_odb(*payload, to, from, src);
}
+static int crlf_stream(
+ git_writestream **out,
+ git_filter *self,
+ void **payload,
+ const git_filter_source *src,
+ git_writestream *next)
+{
+ return git_filter_buffered_stream_new(out,
+ self, crlf_apply, NULL, payload, src, next);
+}
+
static void crlf_cleanup(
git_filter *self,
void *payload)
@@ -406,7 +416,7 @@ git_filter *git_crlf_filter_new(void)
f->f.initialize = NULL;
f->f.shutdown = git_filter_free;
f->f.check = crlf_check;
- f->f.apply = crlf_apply;
+ f->f.stream = crlf_stream;
f->f.cleanup = crlf_cleanup;
return (git_filter *)f;
diff --git a/src/date.c b/src/date.c
index 0e1b31aee..2297ee66c 100644
--- a/src/date.c
+++ b/src/date.c
@@ -204,7 +204,7 @@ static int is_date(int year, int month, int day, struct tm *now_tm, time_t now,
if (month > 0 && month < 13 && day > 0 && day < 32) {
struct tm check = *tm;
struct tm *r = (now_tm ? &check : tm);
- time_t specified;
+ git_time_t specified;
r->tm_mon = month - 1;
r->tm_mday = day;
@@ -722,7 +722,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
while (tl->type) {
size_t len = strlen(tl->type);
if (match_string(date, tl->type) >= len-1) {
- update_tm(tm, now, tl->length * *num);
+ update_tm(tm, now, tl->length * (unsigned long)*num);
*num = 0;
*touched = 1;
return end;
@@ -881,7 +881,8 @@ int git__date_rfc2822_fmt(char *out, size_t len, const git_time *date)
struct tm gmt;
time_t t;
- assert(out && date);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(date);
t = (time_t) (date->time + date->offset * 60);
diff --git a/src/delta.c b/src/delta.c
index 1ff7752c7..2d2c5fa85 100644
--- a/src/delta.c
+++ b/src/delta.c
@@ -256,7 +256,7 @@ void git_delta_index_free(git_delta_index *index)
size_t git_delta_index_size(git_delta_index *index)
{
- assert(index);
+ GIT_ASSERT_ARG(index);
return index->memsize;
}
diff --git a/src/describe.c b/src/describe.c
index c8a175214..103d0da5c 100644
--- a/src/describe.c
+++ b/src/describe.c
@@ -391,7 +391,7 @@ static int show_suffix(
git_buf *buf,
int depth,
git_repository *repo,
- const git_oid* id,
+ const git_oid *id,
unsigned int abbrev_size)
{
int error, size = 0;
@@ -655,7 +655,8 @@ int git_describe_commit(
int error = -1;
git_describe_options normalized;
- assert(committish);
+ GIT_ASSERT_ARG(result);
+ GIT_ASSERT_ARG(committish);
data.result = git__calloc(1, sizeof(git_describe_result));
GIT_ERROR_CHECK_ALLOC(data.result);
@@ -685,7 +686,7 @@ int git_describe_commit(
get_name, &data)) < 0)
goto cleanup;
- if (git_oidmap_size(data.names) == 0 && !opts->show_commit_oid_as_fallback) {
+ if (git_oidmap_size(data.names) == 0 && !normalized.show_commit_oid_as_fallback) {
git_error_set(GIT_ERROR_DESCRIBE, "cannot describe - "
"no reference found, cannot describe anything.");
error = -1;
@@ -775,12 +776,14 @@ int git_describe_format(git_buf *out, const git_describe_result *result, const g
struct commit_name *name;
git_describe_format_options opts;
- assert(out && result);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(result);
GIT_ERROR_CHECK_VERSION(given, GIT_DESCRIBE_FORMAT_OPTIONS_VERSION, "git_describe_format_options");
normalize_format_options(&opts, given);
- git_buf_sanitize(out);
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
if (opts.always_use_long_format && opts.abbreviated_size == 0) {
diff --git a/src/diff.c b/src/diff.c
index 3e52e3f18..30b9f647a 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -7,11 +7,15 @@
#include "diff.h"
-#include "git2/version.h"
-#include "diff_generate.h"
+#include "common.h"
#include "patch.h"
+#include "email.h"
#include "commit.h"
#include "index.h"
+#include "diff_generate.h"
+
+#include "git2/version.h"
+#include "git2/email.h"
struct patch_id_args {
git_hash_ctx ctx;
@@ -77,7 +81,7 @@ void git_diff_addref(git_diff *diff)
size_t git_diff_num_deltas(const git_diff *diff)
{
- assert(diff);
+ GIT_ASSERT_ARG(diff);
return diff->deltas.length;
}
@@ -86,7 +90,7 @@ size_t git_diff_num_deltas_of_type(const git_diff *diff, git_delta_t type)
size_t i, count = 0;
const git_diff_delta *delta;
- assert(diff);
+ GIT_ASSERT_ARG(diff);
git_vector_foreach(&diff->deltas, i, delta) {
count += (delta->status == type);
@@ -97,7 +101,7 @@ size_t git_diff_num_deltas_of_type(const git_diff *diff, git_delta_t type)
const git_diff_delta *git_diff_get_delta(const git_diff *diff, size_t idx)
{
- assert(diff);
+ GIT_ASSERT_ARG_WITH_RETVAL(diff, NULL);
return git_vector_get(&diff->deltas, idx);
}
@@ -108,7 +112,7 @@ int git_diff_is_sorted_icase(const git_diff *diff)
int git_diff_get_perfdata(git_diff_perfdata *out, const git_diff *diff)
{
- assert(out);
+ GIT_ASSERT_ARG(out);
GIT_ERROR_CHECK_VERSION(out, GIT_DIFF_PERFDATA_VERSION, "git_diff_perfdata");
out->stat_calls = diff->perf.stat_calls;
out->oid_calculations = diff->perf.oid_calculations;
@@ -127,7 +131,7 @@ int git_diff_foreach(
git_diff_delta *delta;
size_t idx;
- assert(diff);
+ GIT_ASSERT_ARG(diff);
git_vector_foreach(&diff->deltas, idx, delta) {
git_patch *patch;
@@ -150,164 +154,31 @@ int git_diff_foreach(
return error;
}
-static int diff_format_email_append_header_tobuf(
- git_buf *out,
- const git_oid *id,
- const git_signature *author,
- const char *summary,
- const char *body,
- size_t patch_no,
- size_t total_patches,
- bool exclude_patchno_marker)
-{
- char idstr[GIT_OID_HEXSZ + 1];
- char date_str[GIT_DATE_RFC2822_SZ];
- int error = 0;
-
- git_oid_fmt(idstr, id);
- idstr[GIT_OID_HEXSZ] = '\0';
-
- if ((error = git__date_rfc2822_fmt(date_str, sizeof(date_str),
- &author->when)) < 0)
- return error;
-
- error = git_buf_printf(out,
- "From %s Mon Sep 17 00:00:00 2001\n" \
- "From: %s <%s>\n" \
- "Date: %s\n" \
- "Subject: ",
- idstr,
- author->name, author->email,
- date_str);
-
- if (error < 0)
- return error;
-
- if (!exclude_patchno_marker) {
- if (total_patches == 1) {
- error = git_buf_puts(out, "[PATCH] ");
- } else {
- error = git_buf_printf(out, "[PATCH %"PRIuZ"/%"PRIuZ"] ",
- patch_no, total_patches);
- }
-
- if (error < 0)
- return error;
- }
-
- error = git_buf_printf(out, "%s\n\n", summary);
-
- if (body) {
- git_buf_puts(out, body);
-
- if (out->ptr[out->size - 1] != '\n')
- git_buf_putc(out, '\n');
- }
-
- return error;
-}
-
-static int diff_format_email_append_patches_tobuf(
- git_buf *out,
- git_diff *diff)
-{
- size_t i, deltas;
- int error = 0;
-
- deltas = git_diff_num_deltas(diff);
-
- for (i = 0; i < deltas; ++i) {
- git_patch *patch = NULL;
-
- if ((error = git_patch_from_diff(&patch, diff, i)) >= 0)
- error = git_patch_to_buf(out, patch);
-
- git_patch_free(patch);
-
- if (error < 0)
- break;
- }
-
- return error;
-}
+#ifndef GIT_DEPRECATE_HARD
int git_diff_format_email(
git_buf *out,
git_diff *diff,
const git_diff_format_email_options *opts)
{
- git_diff_stats *stats = NULL;
- char *summary = NULL, *loc = NULL;
- bool ignore_marker;
- unsigned int format_flags = 0;
- size_t allocsize;
+ git_email_create_options email_create_opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
int error;
- assert(out && diff && opts);
- assert(opts->summary && opts->id && opts->author);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(diff);
+ GIT_ASSERT_ARG(opts && opts->summary && opts->id && opts->author);
GIT_ERROR_CHECK_VERSION(opts,
GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION,
"git_format_email_options");
- ignore_marker = (opts->flags &
- GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER) != 0;
-
- if (!ignore_marker) {
- if (opts->patch_no > opts->total_patches) {
- git_error_set(GIT_ERROR_INVALID,
- "patch %"PRIuZ" out of range. max %"PRIuZ,
- opts->patch_no, opts->total_patches);
- return -1;
- }
+ if ((opts->flags & GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER) != 0)
+ email_create_opts.subject_prefix = "";
- if (opts->patch_no == 0) {
- git_error_set(GIT_ERROR_INVALID,
- "invalid patch no %"PRIuZ". should be >0", opts->patch_no);
- return -1;
- }
- }
- /* the summary we receive may not be clean.
- * it could potentially contain new line characters
- * or not be set, sanitize, */
- if ((loc = strpbrk(opts->summary, "\r\n")) != NULL) {
- size_t offset = 0;
-
- if ((offset = (loc - opts->summary)) == 0) {
- git_error_set(GIT_ERROR_INVALID, "summary is empty");
- error = -1;
- goto on_error;
- }
-
- GIT_ERROR_CHECK_ALLOC_ADD(&allocsize, offset, 1);
- summary = git__calloc(allocsize, sizeof(char));
- GIT_ERROR_CHECK_ALLOC(summary);
-
- strncpy(summary, opts->summary, offset);
- }
-
- error = diff_format_email_append_header_tobuf(out,
- opts->id, opts->author, summary == NULL ? opts->summary : summary,
- opts->body, opts->patch_no, opts->total_patches, ignore_marker);
-
- if (error < 0)
- goto on_error;
-
- format_flags = GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY;
-
- if ((error = git_buf_puts(out, "---\n")) < 0 ||
- (error = git_diff_get_stats(&stats, diff)) < 0 ||
- (error = git_diff_stats_to_buf(out, stats, format_flags, 0)) < 0 ||
- (error = git_buf_putc(out, '\n')) < 0 ||
- (error = diff_format_email_append_patches_tobuf(out, diff)) < 0)
- goto on_error;
-
- error = git_buf_puts(out, "--\nlibgit2 " LIBGIT2_VERSION "\n\n");
-
-on_error:
- git__free(summary);
- git_diff_stats_free(stats);
+ error = git_email__append_from_diff(out, diff, opts->patch_no,
+ opts->total_patches, opts->id, opts->summary, opts->body,
+ opts->author, &email_create_opts);
return error;
}
@@ -322,58 +193,43 @@ int git_diff_commit_as_email(
const git_diff_options *diff_opts)
{
git_diff *diff = NULL;
- git_diff_format_email_options opts =
- GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
+ git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+ const git_oid *commit_id;
+ const char *summary, *body;
+ const git_signature *author;
int error;
- assert (out && repo && commit);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(commit);
+
+ commit_id = git_commit_id(commit);
+ summary = git_commit_summary(commit);
+ body = git_commit_body(commit);
+ author = git_commit_author(commit);
- opts.flags = flags;
- opts.patch_no = patch_no;
- opts.total_patches = total_patches;
- opts.id = git_commit_id(commit);
- opts.summary = git_commit_summary(commit);
- opts.body = git_commit_body(commit);
- opts.author = git_commit_author(commit);
+ if ((flags & GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER) != 0)
+ opts.subject_prefix = "";
if ((error = git_diff__commit(&diff, repo, commit, diff_opts)) < 0)
return error;
- error = git_diff_format_email(out, diff, &opts);
+ error = git_email_create_from_diff(out, diff, patch_no, total_patches, commit_id, summary, body, author, &opts);
git_diff_free(diff);
return error;
}
-int git_diff_options_init(git_diff_options *opts, unsigned int version)
-{
- GIT_INIT_STRUCTURE_FROM_TEMPLATE(
- opts, version, git_diff_options, GIT_DIFF_OPTIONS_INIT);
- return 0;
-}
-
-#ifndef GIT_DEPRECATE_HARD
int git_diff_init_options(git_diff_options *opts, unsigned int version)
{
return git_diff_options_init(opts, version);
}
-#endif
-int git_diff_find_options_init(
- git_diff_find_options *opts, unsigned int version)
-{
- GIT_INIT_STRUCTURE_FROM_TEMPLATE(
- opts, version, git_diff_find_options, GIT_DIFF_FIND_OPTIONS_INIT);
- return 0;
-}
-
-#ifndef GIT_DEPRECATE_HARD
int git_diff_find_init_options(
git_diff_find_options *opts, unsigned int version)
{
return git_diff_find_options_init(opts, version);
}
-#endif
int git_diff_format_email_options_init(
git_diff_format_email_options *opts, unsigned int version)
@@ -384,14 +240,29 @@ int git_diff_format_email_options_init(
return 0;
}
-#ifndef GIT_DEPRECATE_HARD
int git_diff_format_email_init_options(
git_diff_format_email_options *opts, unsigned int version)
{
return git_diff_format_email_options_init(opts, version);
}
+
#endif
+int git_diff_options_init(git_diff_options *opts, unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
+ opts, version, git_diff_options, GIT_DIFF_OPTIONS_INIT);
+ return 0;
+}
+
+int git_diff_find_options_init(
+ git_diff_find_options *opts, unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
+ opts, version, git_diff_find_options, GIT_DIFF_FIND_OPTIONS_INIT);
+ return 0;
+}
+
static int flush_hunk(git_oid *result, git_hash_ctx *ctx)
{
git_oid hash;
diff --git a/src/diff_driver.c b/src/diff_driver.c
index 831d3262d..a3892d35e 100644
--- a/src/diff_driver.c
+++ b/src/diff_driver.c
@@ -13,7 +13,6 @@
#include "diff.h"
#include "strmap.h"
#include "map.h"
-#include "buf_text.h"
#include "config.h"
#include "regexp.h"
#include "repository.h"
@@ -142,18 +141,23 @@ static int diff_driver_funcname(const git_config_entry *entry, void *payload)
static git_diff_driver_registry *git_repository_driver_registry(
git_repository *repo)
{
- if (!repo->diff_drivers) {
- git_diff_driver_registry *reg = git_diff_driver_registry_new();
- reg = git__compare_and_swap(&repo->diff_drivers, NULL, reg);
+ git_diff_driver_registry *reg = git_atomic_load(repo->diff_drivers), *newreg;
+ if (reg)
+ return reg;
- if (reg != NULL) /* if we race, free losing allocation */
- git_diff_driver_registry_free(reg);
- }
-
- if (!repo->diff_drivers)
+ newreg = git_diff_driver_registry_new();
+ if (!newreg) {
git_error_set(GIT_ERROR_REPOSITORY, "unable to create diff driver registry");
-
- return repo->diff_drivers;
+ return newreg;
+ }
+ reg = git_atomic_compare_and_swap(&repo->diff_drivers, NULL, newreg);
+ if (!reg) {
+ reg = newreg;
+ } else {
+ /* if we race, free losing allocation */
+ git_diff_driver_registry_free(newreg);
+ }
+ return reg;
}
static int diff_driver_alloc(
@@ -358,7 +362,7 @@ int git_diff_driver_lookup(
int error = 0;
const char *values[1], *attrs[] = { "diff" };
- assert(out);
+ GIT_ASSERT_ARG(out);
*out = NULL;
if (!repo || !path || !strlen(path))
@@ -390,13 +394,13 @@ int git_diff_driver_lookup(
void git_diff_driver_free(git_diff_driver *driver)
{
- size_t i;
+ git_diff_driver_pattern *pat;
if (!driver)
return;
- for (i = 0; i < git_array_size(driver->fn_patterns); ++i)
- git_regexp_dispose(& git_array_get(driver->fn_patterns, i)->re);
+ while ((pat = git_array_pop(driver->fn_patterns)) != NULL)
+ git_regexp_dispose(&pat->re);
git_array_clear(driver->fn_patterns);
git_regexp_dispose(&driver->word_pattern);
@@ -428,8 +432,8 @@ int git_diff_driver_content_is_binary(
* let's just use the simple NUL-byte detection that core git uses.
*/
- /* previously was: if (git_buf_text_is_binary(&search)) */
- if (git_buf_text_contains_nul(&search))
+ /* previously was: if (git_buf_is_binary(&search)) */
+ if (git_buf_contains_nul(&search))
return 1;
return 0;
diff --git a/src/diff_file.c b/src/diff_file.c
index 621bff556..eeaf4a5a2 100644
--- a/src/diff_file.c
+++ b/src/diff_file.c
@@ -160,8 +160,10 @@ int git_diff_file_content__init_from_src(
fc->flags |= GIT_DIFF_FLAG__FREE_BLOB;
} else {
+ int error;
+ if ((error = git_odb_hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB)) < 0)
+ return error;
fc->file->size = src->buflen;
- git_odb_hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB);
fc->file->id_abbrev = GIT_OID_HEXSZ;
fc->map.len = src->buflen;
@@ -360,10 +362,7 @@ static int diff_file_content_load_workdir_file(
if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size))) {
git_buf out = GIT_BUF_INIT;
- error = git_filter_list_apply_to_data(&out, fl, &raw);
-
- if (out.ptr != raw.ptr)
- git_buf_dispose(&raw);
+ error = git_filter_list__convert_buf(&out, fl, &raw);
if (!error) {
fc->map.len = out.size;
@@ -392,8 +391,7 @@ static int diff_file_content_load_workdir(
if (fc->file->mode == GIT_FILEMODE_TREE)
return 0;
- if (git_buf_joinpath(
- &path, git_repository_workdir(fc->repo), fc->file->path) < 0)
+ if (git_repository_workdir_path(&path, fc->repo, fc->file->path) < 0)
return -1;
if (S_ISLNK(fc->file->mode))
diff --git a/src/diff_generate.c b/src/diff_generate.c
index e7bfd6223..aba9e52ba 100644
--- a/src/diff_generate.c
+++ b/src/diff_generate.c
@@ -128,7 +128,7 @@ static int diff_delta__from_one(
git_diff_delta *delta;
const char *matched_pathspec;
- assert((oitem != NULL) ^ (nitem != NULL));
+ GIT_ASSERT_ARG((oitem != NULL) ^ (nitem != NULL));
if (oitem) {
entry = oitem;
@@ -160,7 +160,7 @@ static int diff_delta__from_one(
GIT_ERROR_CHECK_ALLOC(delta);
/* This fn is just for single-sided diffs */
- assert(status != GIT_DELTA_MODIFIED);
+ GIT_ASSERT(status != GIT_DELTA_MODIFIED);
delta->nfiles = 1;
if (has_old) {
@@ -408,7 +408,9 @@ static git_diff_generated *diff_generated_alloc(
git_diff_generated *diff;
git_diff_options dflt = GIT_DIFF_OPTIONS_INIT;
- assert(repo && old_iter && new_iter);
+ GIT_ASSERT_ARG_WITH_RETVAL(repo, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(old_iter, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(new_iter, NULL);
if ((diff = git__calloc(1, sizeof(git_diff_generated))) == NULL)
return NULL;
@@ -589,13 +591,12 @@ int git_diff__oid_for_entry(
git_filter_list *fl = NULL;
int error = 0;
- assert(d->type == GIT_DIFF_TYPE_GENERATED);
+ GIT_ASSERT(d->type == GIT_DIFF_TYPE_GENERATED);
diff = (git_diff_generated *)d;
memset(out, 0, sizeof(*out));
- if (git_buf_joinpath(&full_path,
- git_repository_workdir(diff->base.repo), entry.path) < 0)
+ if (git_repository_workdir_path(&full_path, diff->base.repo, entry.path) < 0)
return -1;
if (!mode) {
@@ -678,6 +679,8 @@ typedef struct {
git_iterator *new_iter;
const git_index_entry *oitem;
const git_index_entry *nitem;
+ git_strmap *submodule_cache;
+ bool submodule_cache_initialized;
} diff_in_progress;
#define MODE_BITS_MASK 0000777
@@ -692,6 +695,7 @@ static int maybe_modified_submodule(
git_submodule *sub;
unsigned int sm_status = 0;
git_submodule_ignore_t ign = diff->base.opts.ignore_submodules;
+ git_strmap *submodule_cache = NULL;
*status = GIT_DELTA_UNMODIFIED;
@@ -699,8 +703,23 @@ static int maybe_modified_submodule(
ign == GIT_SUBMODULE_IGNORE_ALL)
return 0;
- if ((error = git_submodule_lookup(
- &sub, diff->base.repo, info->nitem->path)) < 0) {
+ if (diff->base.repo->submodule_cache != NULL) {
+ submodule_cache = diff->base.repo->submodule_cache;
+ } else {
+ if (!info->submodule_cache_initialized) {
+ info->submodule_cache_initialized = true;
+ /*
+ * Try to cache the submodule information to avoid having to parse it for
+ * every submodule. It is okay if it fails, the cache will still be NULL
+ * and the submodules will be attempted to be looked up individually.
+ */
+ git_submodule_cache_init(&info->submodule_cache, diff->base.repo);
+ }
+ submodule_cache = info->submodule_cache;
+ }
+
+ if ((error = git_submodule__lookup_with_cache(
+ &sub, diff->base.repo, info->nitem->path, submodule_cache)) < 0) {
/* GIT_EEXISTS means dir with .git in it was found - ignore it */
if (error == GIT_EEXISTS) {
@@ -1190,7 +1209,7 @@ int git_diff__from_iterators(
const git_diff_options *opts)
{
git_diff_generated *diff;
- diff_in_progress info;
+ diff_in_progress info = {0};
int error = 0;
*out = NULL;
@@ -1204,8 +1223,9 @@ int git_diff__from_iterators(
/* make iterators have matching icase behavior */
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE)) {
- git_iterator_set_ignore_case(old_iter, true);
- git_iterator_set_ignore_case(new_iter, true);
+ if ((error = git_iterator_set_ignore_case(old_iter, true)) < 0 ||
+ (error = git_iterator_set_ignore_case(new_iter, true)) < 0)
+ goto cleanup;
}
/* finish initialization */
@@ -1257,6 +1277,8 @@ cleanup:
*out = &diff->base;
else
git_diff_free(&diff->base);
+ if (info.submodule_cache)
+ git_submodule_cache_free(info.submodule_cache);
return error;
}
@@ -1302,7 +1324,8 @@ int git_diff_tree_to_tree(
char *prefix = NULL;
int error = 0;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
*out = NULL;
@@ -1358,7 +1381,8 @@ int git_diff_tree_to_index(
bool index_ignore_case = false;
int error = 0;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
*out = NULL;
@@ -1401,7 +1425,8 @@ int git_diff_index_to_workdir(
char *prefix = NULL;
int error = 0;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
*out = NULL;
@@ -1444,7 +1469,8 @@ int git_diff_tree_to_workdir(
git_index *index;
int error;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
*out = NULL;
@@ -1477,7 +1503,8 @@ int git_diff_tree_to_workdir_with_index(
git_index *index = NULL;
int error = 0;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
*out = NULL;
@@ -1513,7 +1540,9 @@ int git_diff_index_to_index(
char *prefix = NULL;
int error;
- assert(out && old_index && new_index);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(old_index);
+ GIT_ASSERT_ARG(new_index);
*out = NULL;
diff --git a/src/diff_print.c b/src/diff_print.c
index 9ce04d70e..062e267b0 100644
--- a/src/diff_print.c
+++ b/src/diff_print.c
@@ -95,7 +95,7 @@ static int diff_print_info_init_frompatch(
git_diff_line_cb cb,
void *payload)
{
- assert(patch);
+ GIT_ASSERT_ARG(patch);
memset(pi, 0, sizeof(diff_print_info));
@@ -764,8 +764,14 @@ int git_diff_print_callback__to_file_handle(
/* print a git_diff to a git_buf */
int git_diff_to_buf(git_buf *out, git_diff *diff, git_diff_format_t format)
{
- assert(out && diff);
- git_buf_sanitize(out);
+ int error;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(diff);
+
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
+
return git_diff_print(diff, format, git_diff_print_callback__to_buf, out);
}
@@ -779,7 +785,8 @@ int git_patch_print(
diff_print_info pi;
int error;
- assert(patch && print_cb);
+ GIT_ASSERT_ARG(patch);
+ GIT_ASSERT_ARG(print_cb);
if ((error = diff_print_info_init_frompatch(&pi, &temp, patch,
GIT_DIFF_FORMAT_PATCH, print_cb, payload)) < 0)
@@ -799,7 +806,13 @@ out:
/* print a git_patch to a git_buf */
int git_patch_to_buf(git_buf *out, git_patch *patch)
{
- assert(out && patch);
- git_buf_sanitize(out);
+ int error;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(patch);
+
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
+
return git_patch_print(patch, git_diff_print_callback__to_buf, out);
}
diff --git a/src/diff_stats.c b/src/diff_stats.c
index 1028b01a7..41a25bf8a 100644
--- a/src/diff_stats.c
+++ b/src/diff_stats.c
@@ -53,7 +53,7 @@ static int diff_file_stats_full_to_buf(
const git_diff_stats *stats,
size_t width)
{
- const char *old_path = NULL, *new_path = NULL;
+ const char *old_path = NULL, *new_path = NULL, *adddel_path = NULL;
size_t padding;
git_object_size_t old_size, new_size;
@@ -62,7 +62,7 @@ static int diff_file_stats_full_to_buf(
old_size = delta->old_file.size;
new_size = delta->new_file.size;
- if (strcmp(old_path, new_path) != 0) {
+ if (old_path && new_path && strcmp(old_path, new_path) != 0) {
size_t common_dirlen;
int error;
@@ -82,10 +82,11 @@ static int diff_file_stats_full_to_buf(
if (error < 0)
goto on_error;
} else {
- if (git_buf_printf(out, " %s", old_path) < 0)
+ adddel_path = new_path ? new_path : old_path;
+ if (git_buf_printf(out, " %s", adddel_path) < 0)
goto on_error;
- padding = stats->max_name - strlen(old_path);
+ padding = stats->max_name - strlen(adddel_path);
if (stats->renames > 0)
padding += strlen(DIFF_RENAME_FILE_SEPARATOR);
@@ -182,7 +183,8 @@ int git_diff_get_stats(
git_diff_stats *stats = NULL;
int error = 0;
- assert(out && diff);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(diff);
stats = git__calloc(1, sizeof(git_diff_stats));
GIT_ERROR_CHECK_ALLOC(stats);
@@ -211,7 +213,7 @@ int git_diff_get_stats(
/* TODO ugh */
namelen = strlen(delta->new_file.path);
- if (strcmp(delta->old_file.path, delta->new_file.path) != 0) {
+ if (delta->old_file.path && strcmp(delta->old_file.path, delta->new_file.path) != 0) {
namelen += strlen(delta->old_file.path);
stats->renames++;
}
@@ -250,7 +252,7 @@ int git_diff_get_stats(
size_t git_diff_stats_files_changed(
const git_diff_stats *stats)
{
- assert(stats);
+ GIT_ASSERT_ARG(stats);
return stats->files_changed;
}
@@ -258,7 +260,7 @@ size_t git_diff_stats_files_changed(
size_t git_diff_stats_insertions(
const git_diff_stats *stats)
{
- assert(stats);
+ GIT_ASSERT_ARG(stats);
return stats->insertions;
}
@@ -266,7 +268,7 @@ size_t git_diff_stats_insertions(
size_t git_diff_stats_deletions(
const git_diff_stats *stats)
{
- assert(stats);
+ GIT_ASSERT_ARG(stats);
return stats->deletions;
}
@@ -281,7 +283,8 @@ int git_diff_stats_to_buf(
size_t i;
const git_diff_delta *delta;
- assert(out && stats);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(stats);
if (format & GIT_DIFF_STATS_NUMBER) {
for (i = 0; i < stats->files_changed; ++i) {
diff --git a/src/diff_tform.c b/src/diff_tform.c
index 7de88bd0d..908175d34 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -87,7 +87,7 @@ git_diff_delta *git_diff__merge_like_cgit(
a->status == GIT_DELTA_UNREADABLE)
return dup;
- assert(b->status != GIT_DELTA_UNMODIFIED);
+ GIT_ASSERT_WITH_RETVAL(b->status != GIT_DELTA_UNMODIFIED, NULL);
/* A cgit exception is that the diff of a file that is only in the
* index (i.e. not in HEAD nor workdir) is given as empty.
@@ -121,7 +121,8 @@ int git_diff__merge(
bool ignore_case, reversed;
unsigned int i, j;
- assert(onto && from);
+ GIT_ASSERT_ARG(onto);
+ GIT_ASSERT_ARG(from);
if (!from->deltas.length)
return 0;
@@ -475,8 +476,8 @@ static int similarity_sig(
git_diff_file *file = info->file;
if (info->src == GIT_ITERATOR_WORKDIR) {
- if ((error = git_buf_joinpath(
- &info->data, git_repository_workdir(info->repo), file->path)) < 0)
+ if ((error = git_repository_workdir_path(
+ &info->data, info->repo, file->path)) < 0)
return error;
/* if path is not a regular file, just skip this item */
@@ -815,7 +816,7 @@ int git_diff_find_similar(
diff_find_match *best_match;
git_diff_file swap;
- assert(diff);
+ GIT_ASSERT_ARG(diff);
if ((error = normalize_find_opts(diff, &opts, given_opts)) < 0)
return error;
@@ -978,7 +979,7 @@ find_best_matches:
src->flags |= GIT_DIFF_FLAG__TO_DELETE;
num_rewrites++;
} else {
- assert(delta_is_split(tgt));
+ GIT_ASSERT(delta_is_split(tgt));
if (best_match->similarity < opts.rename_from_rewrite_threshold)
continue;
@@ -988,7 +989,7 @@ find_best_matches:
delta_make_rename(tgt, src, best_match->similarity);
num_rewrites--;
- assert(src->status == GIT_DELTA_DELETED);
+ GIT_ASSERT(src->status == GIT_DELTA_DELETED);
memcpy(&src->old_file, &swap, sizeof(src->old_file));
memset(&src->new_file, 0, sizeof(src->new_file));
src->new_file.path = src->old_file.path;
@@ -1024,7 +1025,7 @@ find_best_matches:
num_updates++;
} else {
- assert(delta_is_split(src));
+ GIT_ASSERT(delta_is_split(src));
if (best_match->similarity < opts.rename_from_rewrite_threshold)
continue;
@@ -1038,7 +1039,7 @@ find_best_matches:
memcpy(&src->old_file, &swap, sizeof(src->old_file));
/* if we've just swapped the new element into the correct
- * place, clear the SPLIT flag
+ * place, clear the SPLIT and RENAME_TARGET flags
*/
if (tgt2src[s].idx == t &&
tgt2src[s].similarity >
@@ -1046,7 +1047,7 @@ find_best_matches:
src->status = GIT_DELTA_RENAMED;
src->similarity = tgt2src[s].similarity;
tgt2src[s].similarity = 0;
- src->flags &= ~GIT_DIFF_FLAG__TO_SPLIT;
+ src->flags &= ~(GIT_DIFF_FLAG__TO_SPLIT | GIT_DIFF_FLAG__IS_RENAME_TARGET);
num_rewrites--;
}
/* otherwise, if we just overwrote a source, update mapping */
diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c
index c4668fa2f..278e2be36 100644
--- a/src/diff_xdiff.c
+++ b/src/diff_xdiff.c
@@ -6,7 +6,6 @@
*/
#include "diff_xdiff.h"
-#include "util.h"
#include "git2/errors.h"
#include "diff.h"
@@ -128,7 +127,7 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len)
info->hunk.header_len = sizeof(info->hunk.header) - 1;
/* Sanitize the hunk header in case there is invalid Unicode */
- buffer_len = git__utf8_valid_buf_length((const uint8_t *) bufs[0].ptr, info->hunk.header_len);
+ buffer_len = git_utf8_valid_buf_length(bufs[0].ptr, info->hunk.header_len);
/* Sanitizing the hunk header may delete the newline, so add it back again if there is room */
if (buffer_len < info->hunk.header_len) {
bufs[0].ptr[buffer_len] = '\n';
@@ -259,5 +258,8 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts)
if (flags & GIT_DIFF_MINIMAL)
xo->params.flags |= XDF_NEED_MINIMAL;
+ if (flags & GIT_DIFF_IGNORE_BLANK_LINES)
+ xo->params.flags |= XDF_IGNORE_BLANK_LINES;
+
xo->callback.outf = git_xdiff_cb;
}
diff --git a/src/diff_xdiff.h b/src/diff_xdiff.h
index aca80b131..9b303e9dc 100644
--- a/src/diff_xdiff.h
+++ b/src/diff_xdiff.h
@@ -16,7 +16,7 @@
/* xdiff cannot cope with large files. these files should not be passed to
* xdiff. callers should treat these large files as binary.
*/
-#define GIT_XDIFF_MAX_SIZE (1024LL * 1024 * 1023)
+#define GIT_XDIFF_MAX_SIZE (INT64_C(1024) * 1024 * 1023)
/* A git_xdiff_output is a git_patch_generate_output with extra fields
* necessary to use libxdiff. Calling git_xdiff_init() will set the diff_cb
diff --git a/src/email.c b/src/email.c
new file mode 100644
index 000000000..df63b6ec3
--- /dev/null
+++ b/src/email.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "email.h"
+
+#include "buffer.h"
+#include "common.h"
+#include "diff_generate.h"
+
+#include "git2/email.h"
+#include "git2/patch.h"
+#include "git2/version.h"
+
+/*
+ * Git uses a "magic" timestamp to indicate that an email message
+ * is from `git format-patch` (or our equivalent).
+ */
+#define EMAIL_TIMESTAMP "Mon Sep 17 00:00:00 2001"
+
+GIT_INLINE(int) include_prefix(
+ size_t patch_count,
+ git_email_create_options *opts)
+{
+ return ((!opts->subject_prefix || *opts->subject_prefix) ||
+ (opts->flags & GIT_EMAIL_CREATE_ALWAYS_NUMBER) != 0 ||
+ opts->reroll_number ||
+ (patch_count > 1 && !(opts->flags & GIT_EMAIL_CREATE_OMIT_NUMBERS)));
+}
+
+static int append_prefix(
+ git_buf *out,
+ size_t patch_idx,
+ size_t patch_count,
+ git_email_create_options *opts)
+{
+ const char *subject_prefix = opts->subject_prefix ?
+ opts->subject_prefix : "PATCH";
+
+ git_buf_putc(out, '[');
+
+ if (*subject_prefix)
+ git_buf_puts(out, subject_prefix);
+
+ if (opts->reroll_number) {
+ if (*subject_prefix)
+ git_buf_putc(out, ' ');
+
+ git_buf_printf(out, "v%" PRIuZ, opts->reroll_number);
+ }
+
+ if ((opts->flags & GIT_EMAIL_CREATE_ALWAYS_NUMBER) != 0 ||
+ (patch_count > 1 && !(opts->flags & GIT_EMAIL_CREATE_OMIT_NUMBERS))) {
+ size_t start_number = opts->start_number ?
+ opts->start_number : 1;
+
+ if (*subject_prefix || opts->reroll_number)
+ git_buf_putc(out, ' ');
+
+ git_buf_printf(out, "%" PRIuZ "/%" PRIuZ,
+ patch_idx + (start_number - 1),
+ patch_count + (start_number - 1));
+ }
+
+ git_buf_puts(out, "]");
+
+ return git_buf_oom(out) ? -1 : 0;
+}
+
+static int append_subject(
+ git_buf *out,
+ size_t patch_idx,
+ size_t patch_count,
+ const char *summary,
+ git_email_create_options *opts)
+{
+ bool prefix = include_prefix(patch_count, opts);
+ size_t summary_len = summary ? strlen(summary) : 0;
+ int error;
+
+ if (summary_len) {
+ const char *nl = strchr(summary, '\n');
+
+ if (nl)
+ summary_len = (nl - summary);
+ }
+
+ if ((error = git_buf_puts(out, "Subject: ")) < 0)
+ return error;
+
+ if (prefix &&
+ (error = append_prefix(out, patch_idx, patch_count, opts)) < 0)
+ return error;
+
+ if (prefix && summary_len && (error = git_buf_putc(out, ' ')) < 0)
+ return error;
+
+ if (summary_len &&
+ (error = git_buf_put(out, summary, summary_len)) < 0)
+ return error;
+
+ return git_buf_putc(out, '\n');
+}
+
+static int append_header(
+ git_buf *out,
+ size_t patch_idx,
+ size_t patch_count,
+ const git_oid *commit_id,
+ const char *summary,
+ const git_signature *author,
+ git_email_create_options *opts)
+{
+ char id[GIT_OID_HEXSZ];
+ char date[GIT_DATE_RFC2822_SZ];
+ int error;
+
+ if ((error = git_oid_fmt(id, commit_id)) < 0 ||
+ (error = git_buf_printf(out, "From %.*s %s\n", GIT_OID_HEXSZ, id, EMAIL_TIMESTAMP)) < 0 ||
+ (error = git_buf_printf(out, "From: %s <%s>\n", author->name, author->email)) < 0 ||
+ (error = git__date_rfc2822_fmt(date, sizeof(date), &author->when)) < 0 ||
+ (error = git_buf_printf(out, "Date: %s\n", date)) < 0 ||
+ (error = append_subject(out, patch_idx, patch_count, summary, opts)) < 0)
+ return error;
+
+ if ((error = git_buf_putc(out, '\n')) < 0)
+ return error;
+
+ return 0;
+}
+
+static int append_body(git_buf *out, const char *body)
+{
+ size_t body_len;
+ int error;
+
+ if (!body)
+ return 0;
+
+ body_len = strlen(body);
+
+ if ((error = git_buf_puts(out, body)) < 0)
+ return error;
+
+ if (body_len && body[body_len - 1] != '\n')
+ error = git_buf_putc(out, '\n');
+
+ return error;
+}
+
+static int append_diffstat(git_buf *out, git_diff *diff)
+{
+ git_diff_stats *stats = NULL;
+ unsigned int format_flags;
+ int error;
+
+ format_flags = GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY;
+
+ if ((error = git_diff_get_stats(&stats, diff)) == 0 &&
+ (error = git_diff_stats_to_buf(out, stats, format_flags, 0)) == 0)
+ error = git_buf_putc(out, '\n');
+
+ git_diff_stats_free(stats);
+ return error;
+}
+
+static int append_patches(git_buf *out, git_diff *diff)
+{
+ size_t i, deltas;
+ int error = 0;
+
+ deltas = git_diff_num_deltas(diff);
+
+ for (i = 0; i < deltas; ++i) {
+ git_patch *patch = NULL;
+
+ if ((error = git_patch_from_diff(&patch, diff, i)) >= 0)
+ error = git_patch_to_buf(out, patch);
+
+ git_patch_free(patch);
+
+ if (error < 0)
+ break;
+ }
+
+ return error;
+}
+
+int git_email__append_from_diff(
+ git_buf *out,
+ git_diff *diff,
+ size_t patch_idx,
+ size_t patch_count,
+ const git_oid *commit_id,
+ const char *summary,
+ const char *body,
+ const git_signature *author,
+ const git_email_create_options *given_opts)
+{
+ git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+ int error;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(diff);
+ GIT_ASSERT_ARG(!patch_idx || patch_idx <= patch_count);
+ GIT_ASSERT_ARG(commit_id);
+ GIT_ASSERT_ARG(author);
+
+ GIT_ERROR_CHECK_VERSION(given_opts,
+ GIT_EMAIL_CREATE_OPTIONS_VERSION,
+ "git_email_create_options");
+
+ if (given_opts)
+ memcpy(&opts, given_opts, sizeof(git_email_create_options));
+
+ git_buf_sanitize(out);
+
+ if ((error = append_header(out, patch_idx, patch_count, commit_id, summary, author, &opts)) == 0 &&
+ (error = append_body(out, body)) == 0 &&
+ (error = git_buf_puts(out, "---\n")) == 0 &&
+ (error = append_diffstat(out, diff)) == 0 &&
+ (error = append_patches(out, diff)) == 0)
+ error = git_buf_puts(out, "--\nlibgit2 " LIBGIT2_VERSION "\n\n");
+
+ return error;
+}
+
+int git_email_create_from_diff(
+ git_buf *out,
+ git_diff *diff,
+ size_t patch_idx,
+ size_t patch_count,
+ const git_oid *commit_id,
+ const char *summary,
+ const char *body,
+ const git_signature *author,
+ const git_email_create_options *given_opts)
+{
+ int error;
+
+ git_buf_sanitize(out);
+ git_buf_clear(out);
+
+ error = git_email__append_from_diff(out, diff, patch_idx,
+ patch_count, commit_id, summary, body, author,
+ given_opts);
+
+ return error;
+}
+
+int git_email_create_from_commit(
+ git_buf *out,
+ git_commit *commit,
+ const git_email_create_options *given_opts)
+{
+ git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+ git_diff *diff = NULL;
+ git_repository *repo;
+ git_diff_options *diff_opts;
+ git_diff_find_options *find_opts;
+ const git_signature *author;
+ const char *summary, *body;
+ const git_oid *commit_id;
+ int error = -1;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(commit);
+
+ GIT_ERROR_CHECK_VERSION(given_opts,
+ GIT_EMAIL_CREATE_OPTIONS_VERSION,
+ "git_email_create_options");
+
+ if (given_opts)
+ memcpy(&opts, given_opts, sizeof(git_email_create_options));
+
+ repo = git_commit_owner(commit);
+ author = git_commit_author(commit);
+ summary = git_commit_summary(commit);
+ body = git_commit_body(commit);
+ commit_id = git_commit_id(commit);
+ diff_opts = &opts.diff_opts;
+ find_opts = &opts.diff_find_opts;
+
+ if ((error = git_diff__commit(&diff, repo, commit, diff_opts)) < 0)
+ goto done;
+
+ if ((opts.flags & GIT_EMAIL_CREATE_NO_RENAMES) == 0 &&
+ (error = git_diff_find_similar(diff, find_opts)) < 0)
+ goto done;
+
+ error = git_email_create_from_diff(out, diff, 1, 1, commit_id, summary, body, author, &opts);
+
+done:
+ git_diff_free(diff);
+ return error;
+}
diff --git a/src/email.h b/src/email.h
new file mode 100644
index 000000000..7aeb462ab
--- /dev/null
+++ b/src/email.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_email_h__
+#define INCLUDE_email_h__
+
+#include "common.h"
+
+#include "git2/email.h"
+
+extern int git_email__append_from_diff(
+ git_buf *out,
+ git_diff *diff,
+ size_t patch_idx,
+ size_t patch_count,
+ const git_oid *commit_id,
+ const char *summary,
+ const char *body,
+ const git_signature *author,
+ const git_email_create_options *given_opts);
+
+#endif
diff --git a/src/errors.c b/src/errors.c
index 8570226b4..ce883b2da 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -7,9 +7,10 @@
#include "common.h"
-#include "global.h"
+#include "threadstate.h"
#include "posix.h"
#include "buffer.h"
+#include "libgit2.h"
/********************************************
* New error handling
@@ -20,20 +21,25 @@ static git_error g_git_oom_error = {
GIT_ERROR_NOMEMORY
};
+static git_error g_git_uninitialized_error = {
+ "libgit2 has not been initialized; you must call git_libgit2_init",
+ GIT_ERROR_INVALID
+};
+
static void set_error_from_buffer(int error_class)
{
- git_error *error = &GIT_GLOBAL->error_t;
- git_buf *buf = &GIT_GLOBAL->error_buf;
+ git_error *error = &GIT_THREADSTATE->error_t;
+ git_buf *buf = &GIT_THREADSTATE->error_buf;
error->message = buf->ptr;
error->klass = error_class;
- GIT_GLOBAL->last_error = error;
+ GIT_THREADSTATE->last_error = error;
}
static void set_error(int error_class, char *string)
{
- git_buf *buf = &GIT_GLOBAL->error_buf;
+ git_buf *buf = &GIT_THREADSTATE->error_buf;
git_buf_clear(buf);
if (string) {
@@ -46,7 +52,7 @@ static void set_error(int error_class, char *string)
void git_error_set_oom(void)
{
- GIT_GLOBAL->last_error = &g_git_oom_error;
+ GIT_THREADSTATE->last_error = &g_git_oom_error;
}
void git_error_set(int error_class, const char *fmt, ...)
@@ -64,7 +70,7 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
DWORD win32_error_code = (error_class == GIT_ERROR_OS) ? GetLastError() : 0;
#endif
int error_code = (error_class == GIT_ERROR_OS) ? errno : 0;
- git_buf *buf = &GIT_GLOBAL->error_buf;
+ git_buf *buf = &GIT_THREADSTATE->error_buf;
git_buf_clear(buf);
if (fmt) {
@@ -97,14 +103,9 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
int git_error_set_str(int error_class, const char *string)
{
- git_buf *buf = &GIT_GLOBAL->error_buf;
-
- assert(string);
+ git_buf *buf = &GIT_THREADSTATE->error_buf;
- if (!string) {
- git_error_set(GIT_ERROR_INVALID, "unspecified caller error");
- return -1;
- }
+ GIT_ASSERT_ARG(string);
git_buf_clear(buf);
git_buf_puts(buf, string);
@@ -118,9 +119,9 @@ int git_error_set_str(int error_class, const char *string)
void git_error_clear(void)
{
- if (GIT_GLOBAL->last_error != NULL) {
+ if (GIT_THREADSTATE->last_error != NULL) {
set_error(0, NULL);
- GIT_GLOBAL->last_error = NULL;
+ GIT_THREADSTATE->last_error = NULL;
}
errno = 0;
@@ -131,13 +132,17 @@ void git_error_clear(void)
const git_error *git_error_last(void)
{
- return GIT_GLOBAL->last_error;
+ /* If the library is not initialized, return a static error. */
+ if (!git_libgit2_init_count())
+ return &g_git_uninitialized_error;
+
+ return GIT_THREADSTATE->last_error;
}
int git_error_state_capture(git_error_state *state, int error_code)
{
- git_error *error = GIT_GLOBAL->last_error;
- git_buf *error_buf = &GIT_GLOBAL->error_buf;
+ git_error *error = GIT_THREADSTATE->last_error;
+ git_buf *error_buf = &GIT_THREADSTATE->error_buf;
memset(state, 0, sizeof(git_error_state));
diff --git a/src/features.h.in b/src/features.h.in
index e000de5e0..202cef49e 100644
--- a/src/features.h.in
+++ b/src/features.h.in
@@ -2,9 +2,12 @@
#define INCLUDE_features_h__
#cmakedefine GIT_DEBUG_POOL 1
+#cmakedefine GIT_DEBUG_STRICT_ALLOC 1
+#cmakedefine GIT_DEBUG_STRICT_OPEN 1
+
#cmakedefine GIT_TRACE 1
#cmakedefine GIT_THREADS 1
-#cmakedefine GIT_MSVC_CRTDBG 1
+#cmakedefine GIT_WIN32_LEAKCHECK 1
#cmakedefine GIT_ARCH_64 1
#cmakedefine GIT_ARCH_32 1
@@ -32,6 +35,7 @@
#cmakedefine GIT_WINHTTP 1
#cmakedefine GIT_HTTPS 1
#cmakedefine GIT_OPENSSL 1
+#cmakedefine GIT_OPENSSL_DYNAMIC 1
#cmakedefine GIT_SECURE_TRANSPORT 1
#cmakedefine GIT_MBEDTLS 1
diff --git a/src/fetch.c b/src/fetch.c
index f4a4c9f81..dedbb54fa 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -21,9 +21,12 @@
static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, git_refspec *tagspec, git_remote_autotag_option_t tagopt)
{
- int match = 0;
+ int match = 0, valid;
- if (!git_reference_is_valid_name(head->name))
+ if (git_reference_name_is_valid(&valid, head->name) < 0)
+ return -1;
+
+ if (!valid)
return 0;
if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
diff --git a/src/fetchhead.c b/src/fetchhead.c
index ea610f39a..88c567e48 100644
--- a/src/fetchhead.c
+++ b/src/fetchhead.c
@@ -73,7 +73,8 @@ int git_fetchhead_ref_create(
{
git_fetchhead_ref *fetchhead_ref;
- assert(out && oid);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(oid);
*out = NULL;
@@ -108,7 +109,8 @@ static int fetchhead_ref_write(
const char *type, *name;
int head = 0;
- assert(file && fetchhead_ref);
+ GIT_ASSERT_ARG(file);
+ GIT_ASSERT_ARG(fetchhead_ref);
git_oid_fmt(oid, &fetchhead_ref->oid);
oid[GIT_OID_HEXSZ] = '\0';
@@ -145,7 +147,8 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs)
unsigned int i;
git_fetchhead_ref *fetchhead_ref;
- assert(repo && fetchhead_refs);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(fetchhead_refs);
if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
return -1;
@@ -279,7 +282,8 @@ int git_repository_fetchhead_foreach(git_repository *repo,
size_t line_num = 0;
int error = 0;
- assert(repo && cb);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(cb);
if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
return -1;
diff --git a/src/filebuf.c b/src/filebuf.c
index e12a9eabf..a3f6b1483 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -184,7 +184,7 @@ static int write_deflate(git_filebuf *file, void *source, size_t len)
} while (zs->avail_out == 0);
- assert(zs->avail_in == 0);
+ GIT_ASSERT(zs->avail_in == 0);
if (file->compute_digest)
git_hash_update(&file->digest, source, len);
@@ -278,10 +278,9 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
int compression, error = -1;
size_t path_len, alloc_len;
- /* opening an already open buffer is a programming error;
- * assert that this never happens instead of returning
- * an error code */
- assert(file && path && file->buffer == NULL);
+ GIT_ASSERT_ARG(file);
+ GIT_ASSERT_ARG(path);
+ GIT_ASSERT(file->buffer == NULL);
memset(file, 0x0, sizeof(git_filebuf));
@@ -389,7 +388,9 @@ cleanup:
int git_filebuf_hash(git_oid *oid, git_filebuf *file)
{
- assert(oid && file && file->compute_digest);
+ GIT_ASSERT_ARG(oid);
+ GIT_ASSERT_ARG(file);
+ GIT_ASSERT_ARG(file->compute_digest);
flush_buffer(file);
@@ -415,7 +416,8 @@ int git_filebuf_commit_at(git_filebuf *file, const char *path)
int git_filebuf_commit(git_filebuf *file)
{
/* temporary files cannot be committed */
- assert(file && file->path_original);
+ GIT_ASSERT_ARG(file);
+ GIT_ASSERT(file->path_original);
file->flush_mode = Z_FINISH;
flush_buffer(file);
diff --git a/src/filter.c b/src/filter.c
index 09b57dc80..73497cb30 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -11,7 +11,7 @@
#include "futils.h"
#include "hash.h"
#include "repository.h"
-#include "global.h"
+#include "runtime.h"
#include "git2/sys/filter.h"
#include "git2/config.h"
#include "blob.h"
@@ -19,12 +19,12 @@
#include "array.h"
struct git_filter_source {
- git_repository *repo;
- const char *path;
- git_oid oid; /* zero if unknown (which is likely) */
- uint16_t filemode; /* zero if unknown */
- git_filter_mode_t mode;
- uint32_t flags;
+ git_repository *repo;
+ const char *path;
+ git_oid oid; /* zero if unknown (which is likely) */
+ uint16_t filemode; /* zero if unknown */
+ git_filter_mode_t mode;
+ git_filter_options options;
};
typedef struct {
@@ -206,7 +206,8 @@ int git_filter_global_init(void)
GIT_FILTER_IDENT, ident, GIT_FILTER_IDENT_PRIORITY) < 0)
error = -1;
- git__on_shutdown(git_filter_global_shutdown);
+ if (!error)
+ error = git_runtime_shutdown_register(git_filter_global_shutdown);
done:
if (error) {
@@ -266,7 +267,8 @@ int git_filter_register(
{
int error;
- assert(name && filter);
+ GIT_ASSERT_ARG(name);
+ GIT_ASSERT_ARG(filter);
if (git_rwlock_wrlock(&filter_registry.lock) < 0) {
git_error_set(GIT_ERROR_OS, "failed to lock filter registry");
@@ -293,7 +295,7 @@ int git_filter_unregister(const char *name)
git_filter_def *fdef;
int error = 0;
- assert(name);
+ GIT_ASSERT_ARG(name);
/* cannot unregister default filters */
if (!strcmp(GIT_FILTER_CRLF, name) || !strcmp(GIT_FILTER_IDENT, name)) {
@@ -395,7 +397,7 @@ git_filter_mode_t git_filter_source_mode(const git_filter_source *src)
uint32_t git_filter_source_flags(const git_filter_source *src)
{
- return src->flags;
+ return src->options.flags;
}
static int filter_list_new(
@@ -415,7 +417,8 @@ static int filter_list_new(
fl->source.repo = src->repo;
fl->source.path = fl->path;
fl->source.mode = src->mode;
- fl->source.flags = src->flags;
+
+ memcpy(&fl->source.options, &src->options, sizeof(git_filter_options));
*out = fl;
return 0;
@@ -424,25 +427,36 @@ static int filter_list_new(
static int filter_list_check_attributes(
const char ***out,
git_repository *repo,
- git_attr_session *attr_session,
+ git_filter_session *filter_session,
git_filter_def *fdef,
const git_filter_source *src)
{
const char **strs = git__calloc(fdef->nattrs, sizeof(const char *));
- uint32_t flags = 0;
+ git_attr_options attr_opts = GIT_ATTR_OPTIONS_INIT;
size_t i;
int error;
GIT_ERROR_CHECK_ALLOC(strs);
- if ((src->flags & GIT_FILTER_NO_SYSTEM_ATTRIBUTES) != 0)
- flags |= GIT_ATTR_CHECK_NO_SYSTEM;
+ if ((src->options.flags & GIT_FILTER_NO_SYSTEM_ATTRIBUTES) != 0)
+ attr_opts.flags |= GIT_ATTR_CHECK_NO_SYSTEM;
+
+ if ((src->options.flags & GIT_FILTER_ATTRIBUTES_FROM_HEAD) != 0)
+ attr_opts.flags |= GIT_ATTR_CHECK_INCLUDE_HEAD;
+
+ if ((src->options.flags & GIT_FILTER_ATTRIBUTES_FROM_COMMIT) != 0) {
+ attr_opts.flags |= GIT_ATTR_CHECK_INCLUDE_COMMIT;
- if ((src->flags & GIT_FILTER_ATTRIBUTES_FROM_HEAD) != 0)
- flags |= GIT_ATTR_CHECK_INCLUDE_HEAD;
+#ifndef GIT_DEPRECATE_HARD
+ if (src->options.commit_id)
+ git_oid_cpy(&attr_opts.attr_commit_id, src->options.commit_id);
+ else
+#endif
+ git_oid_cpy(&attr_opts.attr_commit_id, &src->options.attr_commit_id);
+ }
error = git_attr_get_many_with_session(
- strs, repo, attr_session, flags, src->path, fdef->nattrs, fdef->attrs);
+ strs, repo, filter_session->attr_session, &attr_opts, src->path, fdef->nattrs, fdef->attrs);
/* if no values were found but no matches are needed, it's okay! */
if (error == GIT_ENOTFOUND && !fdef->nmatches) {
@@ -487,17 +501,17 @@ int git_filter_list_new(
src.repo = repo;
src.path = NULL;
src.mode = mode;
- src.flags = flags;
+ src.options.flags = flags;
return filter_list_new(out, &src);
}
-int git_filter_list__load_ext(
+int git_filter_list__load(
git_filter_list **filters,
git_repository *repo,
git_blob *blob, /* can be NULL */
const char *path,
git_filter_mode_t mode,
- git_filter_options *filter_opts)
+ git_filter_session *filter_session)
{
int error = 0;
git_filter_list *fl = NULL;
@@ -514,7 +528,8 @@ int git_filter_list__load_ext(
src.repo = repo;
src.path = path;
src.mode = mode;
- src.flags = filter_opts->flags;
+
+ memcpy(&src.options, &filter_session->options, sizeof(git_filter_options));
if (blob)
git_oid_cpy(&src.oid, git_blob_id(blob));
@@ -528,7 +543,8 @@ int git_filter_list__load_ext(
if (fdef->nattrs > 0) {
error = filter_list_check_attributes(
- &values, repo, filter_opts->attr_session, fdef, &src);
+ &values, repo,
+ filter_session, fdef, &src);
if (error == GIT_ENOTFOUND) {
error = 0;
@@ -555,7 +571,7 @@ int git_filter_list__load_ext(
if ((error = filter_list_new(&fl, &src)) < 0)
break;
- fl->temp_buf = filter_opts->temp_buf;
+ fl->temp_buf = filter_session->temp_buf;
}
fe = git_array_alloc(fl->filters);
@@ -579,6 +595,23 @@ int git_filter_list__load_ext(
return error;
}
+int git_filter_list_load_ext(
+ git_filter_list **filters,
+ git_repository *repo,
+ git_blob *blob, /* can be NULL */
+ const char *path,
+ git_filter_mode_t mode,
+ git_filter_options *opts)
+{
+ git_filter_session filter_session = GIT_FILTER_SESSION_INIT;
+
+ if (opts)
+ memcpy(&filter_session.options, opts, sizeof(git_filter_options));
+
+ return git_filter_list__load(
+ filters, repo, blob, path, mode, &filter_session);
+}
+
int git_filter_list_load(
git_filter_list **filters,
git_repository *repo,
@@ -587,12 +620,12 @@ int git_filter_list_load(
git_filter_mode_t mode,
uint32_t flags)
{
- git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
+ git_filter_session filter_session = GIT_FILTER_SESSION_INIT;
- filter_opts.flags = flags;
+ filter_session.options.flags = flags;
- return git_filter_list__load_ext(
- filters, repo, blob, path, mode, &filter_opts);
+ return git_filter_list__load(
+ filters, repo, blob, path, mode, &filter_session);
}
void git_filter_list_free(git_filter_list *fl)
@@ -618,7 +651,7 @@ int git_filter_list_contains(
{
size_t i;
- assert(name);
+ GIT_ASSERT_ARG(name);
if (!fl)
return 0;
@@ -639,7 +672,8 @@ int git_filter_list_push(
git_filter_def *fdef = NULL;
git_filter_entry *fe;
- assert(fl && filter);
+ GIT_ASSERT_ARG(fl);
+ GIT_ASSERT_ARG(filter);
if (git_rwlock_rdlock(&filter_registry.lock) < 0) {
git_error_set(GIT_ERROR_OS, "failed to lock filter registry");
@@ -684,9 +718,8 @@ static int buf_stream_write(
git_writestream *s, const char *buffer, size_t len)
{
struct buf_stream *buf_stream = (struct buf_stream *)s;
- assert(buf_stream);
-
- assert(buf_stream->complete == 0);
+ GIT_ASSERT_ARG(buf_stream);
+ GIT_ASSERT(buf_stream->complete == 0);
return git_buf_put(buf_stream->target, buffer, len);
}
@@ -694,9 +727,9 @@ static int buf_stream_write(
static int buf_stream_close(git_writestream *s)
{
struct buf_stream *buf_stream = (struct buf_stream *)s;
- assert(buf_stream);
+ GIT_ASSERT_ARG(buf_stream);
- assert(buf_stream->complete == 0);
+ GIT_ASSERT(buf_stream->complete == 0);
buf_stream->complete = 1;
return 0;
@@ -719,27 +752,47 @@ static void buf_stream_init(struct buf_stream *writer, git_buf *target)
git_buf_clear(target);
}
-int git_filter_list_apply_to_data(
- git_buf *tgt, git_filter_list *filters, git_buf *src)
+int git_filter_list_apply_to_buffer(
+ git_buf *out,
+ git_filter_list *filters,
+ const char *in,
+ size_t in_len)
{
struct buf_stream writer;
int error;
- git_buf_sanitize(tgt);
- git_buf_sanitize(src);
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
- if (!filters) {
- git_buf_attach_notowned(tgt, src->ptr, src->size);
+ buf_stream_init(&writer, out);
+
+ if ((error = git_filter_list_stream_buffer(filters,
+ in, in_len, &writer.parent)) < 0)
+ return error;
+
+ GIT_ASSERT(writer.complete);
+ return error;
+}
+
+int git_filter_list__convert_buf(
+ git_buf *out,
+ git_filter_list *filters,
+ git_buf *in)
+{
+ int error;
+
+ if (!filters || git_filter_list_length(filters) == 0) {
+ git_buf_swap(out, in);
+ git_buf_dispose(in);
return 0;
}
- buf_stream_init(&writer, tgt);
+ error = git_filter_list_apply_to_buffer(out, filters,
+ in->ptr, in->size);
- if ((error = git_filter_list_stream_data(filters, src,
- &writer.parent)) < 0)
- return error;
+ if (!error)
+ git_buf_dispose(in);
- assert(writer.complete);
return error;
}
@@ -758,7 +811,7 @@ int git_filter_list_apply_to_file(
filters, repo, path, &writer.parent)) < 0)
return error;
- assert(writer.complete);
+ GIT_ASSERT(writer.complete);
return error;
}
@@ -789,13 +842,14 @@ int git_filter_list_apply_to_blob(
filters, blob, &writer.parent)) < 0)
return error;
- assert(writer.complete);
+ GIT_ASSERT(writer.complete);
return error;
}
-struct proxy_stream {
+struct buffered_stream {
git_writestream parent;
git_filter *filter;
+ int (*write_fn)(git_filter *, void **, git_buf *, const git_buf *, const git_filter_source *);
const git_filter_source *source;
void **payload;
git_buf input;
@@ -804,89 +858,120 @@ struct proxy_stream {
git_writestream *target;
};
-static int proxy_stream_write(
+static int buffered_stream_write(
git_writestream *s, const char *buffer, size_t len)
{
- struct proxy_stream *proxy_stream = (struct proxy_stream *)s;
- assert(proxy_stream);
+ struct buffered_stream *buffered_stream = (struct buffered_stream *)s;
+ GIT_ASSERT_ARG(buffered_stream);
- return git_buf_put(&proxy_stream->input, buffer, len);
+ return git_buf_put(&buffered_stream->input, buffer, len);
}
-static int proxy_stream_close(git_writestream *s)
+static int buffered_stream_close(git_writestream *s)
{
- struct proxy_stream *proxy_stream = (struct proxy_stream *)s;
+ struct buffered_stream *buffered_stream = (struct buffered_stream *)s;
git_buf *writebuf;
git_error_state error_state = {0};
int error;
- assert(proxy_stream);
+ GIT_ASSERT_ARG(buffered_stream);
- error = proxy_stream->filter->apply(
- proxy_stream->filter,
- proxy_stream->payload,
- proxy_stream->output,
- &proxy_stream->input,
- proxy_stream->source);
+ error = buffered_stream->write_fn(
+ buffered_stream->filter,
+ buffered_stream->payload,
+ buffered_stream->output,
+ &buffered_stream->input,
+ buffered_stream->source);
if (error == GIT_PASSTHROUGH) {
- writebuf = &proxy_stream->input;
+ writebuf = &buffered_stream->input;
} else if (error == 0) {
- git_buf_sanitize(proxy_stream->output);
- writebuf = proxy_stream->output;
+ if ((error = git_buf_sanitize(buffered_stream->output)) < 0)
+ return error;
+
+ writebuf = buffered_stream->output;
} else {
/* close stream before erroring out taking care
* to preserve the original error */
git_error_state_capture(&error_state, error);
- proxy_stream->target->close(proxy_stream->target);
+ buffered_stream->target->close(buffered_stream->target);
git_error_state_restore(&error_state);
return error;
}
- if ((error = proxy_stream->target->write(
- proxy_stream->target, writebuf->ptr, writebuf->size)) == 0)
- error = proxy_stream->target->close(proxy_stream->target);
+ if ((error = buffered_stream->target->write(
+ buffered_stream->target, writebuf->ptr, writebuf->size)) == 0)
+ error = buffered_stream->target->close(buffered_stream->target);
return error;
}
-static void proxy_stream_free(git_writestream *s)
+static void buffered_stream_free(git_writestream *s)
{
- struct proxy_stream *proxy_stream = (struct proxy_stream *)s;
- assert(proxy_stream);
+ struct buffered_stream *buffered_stream = (struct buffered_stream *)s;
- git_buf_dispose(&proxy_stream->input);
- git_buf_dispose(&proxy_stream->temp_buf);
- git__free(proxy_stream);
+ if (buffered_stream) {
+ git_buf_dispose(&buffered_stream->input);
+ git_buf_dispose(&buffered_stream->temp_buf);
+ git__free(buffered_stream);
+ }
}
-static int proxy_stream_init(
+int git_filter_buffered_stream_new(
git_writestream **out,
git_filter *filter,
+ int (*write_fn)(git_filter *, void **, git_buf *, const git_buf *, const git_filter_source *),
git_buf *temp_buf,
void **payload,
const git_filter_source *source,
git_writestream *target)
{
- struct proxy_stream *proxy_stream = git__calloc(1, sizeof(struct proxy_stream));
- GIT_ERROR_CHECK_ALLOC(proxy_stream);
-
- proxy_stream->parent.write = proxy_stream_write;
- proxy_stream->parent.close = proxy_stream_close;
- proxy_stream->parent.free = proxy_stream_free;
- proxy_stream->filter = filter;
- proxy_stream->payload = payload;
- proxy_stream->source = source;
- proxy_stream->target = target;
- proxy_stream->output = temp_buf ? temp_buf : &proxy_stream->temp_buf;
+ struct buffered_stream *buffered_stream = git__calloc(1, sizeof(struct buffered_stream));
+ GIT_ERROR_CHECK_ALLOC(buffered_stream);
+
+ buffered_stream->parent.write = buffered_stream_write;
+ buffered_stream->parent.close = buffered_stream_close;
+ buffered_stream->parent.free = buffered_stream_free;
+ buffered_stream->filter = filter;
+ buffered_stream->write_fn = write_fn;
+ buffered_stream->output = temp_buf ? temp_buf : &buffered_stream->temp_buf;
+ buffered_stream->payload = payload;
+ buffered_stream->source = source;
+ buffered_stream->target = target;
if (temp_buf)
git_buf_clear(temp_buf);
- *out = (git_writestream *)proxy_stream;
+ *out = (git_writestream *)buffered_stream;
return 0;
}
+static int setup_stream(
+ git_writestream **out,
+ git_filter_entry *fe,
+ git_filter_list *filters,
+ git_writestream *last_stream)
+{
+#ifndef GIT_DEPRECATE_HARD
+ GIT_ASSERT(fe->filter->stream || fe->filter->apply);
+
+ /*
+ * If necessary, create a stream that proxies the traditional
+ * application.
+ */
+ if (!fe->filter->stream) {
+ /* Create a stream that proxies the one-shot apply */
+ return git_filter_buffered_stream_new(out,
+ fe->filter, fe->filter->apply, filters->temp_buf,
+ &fe->payload, &filters->source, last_stream);
+ }
+#endif
+
+ GIT_ASSERT(fe->filter->stream);
+ return fe->filter->stream(out, fe->filter,
+ &fe->payload, &filters->source, last_stream);
+}
+
static int stream_list_init(
git_writestream **out,
git_vector *streams,
@@ -908,22 +993,11 @@ static int stream_list_init(
for (i = 0; i < git_array_size(filters->filters); ++i) {
size_t filter_idx = (filters->source.mode == GIT_FILTER_TO_WORKTREE) ?
git_array_size(filters->filters) - 1 - i : i;
+
git_filter_entry *fe = git_array_get(filters->filters, filter_idx);
git_writestream *filter_stream;
- assert(fe->filter->stream || fe->filter->apply);
-
- /* If necessary, create a stream that proxies the traditional
- * application.
- */
- if (fe->filter->stream)
- error = fe->filter->stream(&filter_stream, fe->filter,
- &fe->payload, &filters->source, last_stream);
- else
- /* Create a stream that proxies the one-shot apply */
- error = proxy_stream_init(&filter_stream, fe->filter,
- filters->temp_buf, &fe->payload, &filters->source,
- last_stream);
+ error = setup_stream(&filter_stream, fe, filters, last_stream);
if (error < 0)
goto out;
@@ -967,8 +1041,10 @@ int git_filter_list_stream_file(
if ((error = stream_list_init(
&stream_start, &filter_streams, filters, target)) < 0 ||
- (error = git_path_join_unrooted(&abspath, path, base, NULL)) < 0)
+ (error = git_path_join_unrooted(&abspath, path, base, NULL)) < 0 ||
+ (error = git_path_validate_workdir_buf(repo, &abspath)) < 0)
goto done;
+
initialized = 1;
if ((fd = git_futils_open_ro(abspath.ptr)) < 0) {
@@ -995,23 +1071,21 @@ done:
return error;
}
-int git_filter_list_stream_data(
+int git_filter_list_stream_buffer(
git_filter_list *filters,
- git_buf *data,
+ const char *buffer,
+ size_t len,
git_writestream *target)
{
git_vector filter_streams = GIT_VECTOR_INIT;
git_writestream *stream_start;
int error, initialized = 0;
- git_buf_sanitize(data);
-
if ((error = stream_list_init(&stream_start, &filter_streams, filters, target)) < 0)
goto out;
initialized = 1;
- if ((error = stream_start->write(
- stream_start, data->ptr, data->size)) < 0)
+ if ((error = stream_start->write(stream_start, buffer, len)) < 0)
goto out;
out:
@@ -1035,7 +1109,7 @@ int git_filter_list_stream_blob(
if (filters)
git_oid_cpy(&filters->source.oid, git_blob_id(blob));
- return git_filter_list_stream_data(filters, &in, target);
+ return git_filter_list_stream_buffer(filters, in.ptr, in.size, target);
}
int git_filter_init(git_filter *filter, unsigned int version)
@@ -1043,3 +1117,31 @@ int git_filter_init(git_filter *filter, unsigned int version)
GIT_INIT_STRUCTURE_FROM_TEMPLATE(filter, version, git_filter, GIT_FILTER_INIT);
return 0;
}
+
+#ifndef GIT_DEPRECATE_HARD
+
+int git_filter_list_stream_data(
+ git_filter_list *filters,
+ git_buf *data,
+ git_writestream *target)
+{
+ int error;
+
+ if ((error = git_buf_sanitize(data)) < 0)
+ return error;
+
+ return git_filter_list_stream_buffer(filters, data->ptr, data->size, target);
+}
+
+int git_filter_list_apply_to_data(
+ git_buf *tgt, git_filter_list *filters, git_buf *src)
+{
+ int error;
+
+ if ((error = git_buf_sanitize(src)) < 0)
+ return error;
+
+ return git_filter_list_apply_to_buffer(tgt, filters, src->ptr, src->size);
+}
+
+#endif
diff --git a/src/filter.h b/src/filter.h
index 34081fb4a..241791276 100644
--- a/src/filter.h
+++ b/src/filter.h
@@ -11,29 +11,39 @@
#include "attr_file.h"
#include "git2/filter.h"
+#include "git2/sys/filter.h"
/* Amount of file to examine for NUL byte when checking binary-ness */
#define GIT_FILTER_BYTES_TO_CHECK_NUL 8000
typedef struct {
+ git_filter_options options;
git_attr_session *attr_session;
git_buf *temp_buf;
- uint32_t flags;
-} git_filter_options;
+} git_filter_session;
-#define GIT_FILTER_OPTIONS_INIT {0}
+#define GIT_FILTER_SESSION_INIT {GIT_FILTER_OPTIONS_INIT, 0}
extern int git_filter_global_init(void);
extern void git_filter_free(git_filter *filter);
-extern int git_filter_list__load_ext(
+extern int git_filter_list__load(
git_filter_list **filters,
git_repository *repo,
git_blob *blob, /* can be NULL */
const char *path,
git_filter_mode_t mode,
- git_filter_options *filter_opts);
+ git_filter_session *filter_session);
+
+/*
+ * The given input buffer will be converted to the given output buffer.
+ * The input buffer will be freed (_if_ it was allocated).
+ */
+extern int git_filter_list__convert_buf(
+ git_buf *out,
+ git_filter_list *filters,
+ git_buf *in);
/*
* Available filters
@@ -42,4 +52,13 @@ extern int git_filter_list__load_ext(
extern git_filter *git_crlf_filter_new(void);
extern git_filter *git_ident_filter_new(void);
+extern int git_filter_buffered_stream_new(
+ git_writestream **out,
+ git_filter *filter,
+ int (*write_fn)(git_filter *, void **, git_buf *, const git_buf *, const git_filter_source *),
+ git_buf *temp_buf,
+ void **payload,
+ const git_filter_source *source,
+ git_writestream *target);
+
#endif
diff --git a/src/futils.c b/src/futils.c
index 8c0f008b3..a44820875 100644
--- a/src/futils.c
+++ b/src/futils.c
@@ -7,8 +7,9 @@
#include "futils.h"
-#include "global.h"
+#include "runtime.h"
#include "strmap.h"
+#include "hash.h"
#include <ctype.h>
#if GIT_WIN32
#include "win32/findfile.h"
@@ -184,7 +185,8 @@ int git_futils_readbuffer_updated(
git_buf buf = GIT_BUF_INIT;
git_oid checksum_new;
- assert(out && path && *path);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(path && *path);
if (updated != NULL)
*updated = 0;
@@ -492,7 +494,7 @@ int git_futils_mkdir(
goto done;
}
- assert(len);
+ GIT_ASSERT(len);
/*
* We've walked all the given path's parents and it's either relative
@@ -1127,8 +1129,6 @@ int git_futils_filestamp_check(
void git_futils_filestamp_set(
git_futils_filestamp *target, const git_futils_filestamp *source)
{
- assert(target);
-
if (source)
memcpy(target, source, sizeof(*target));
else
diff --git a/src/futils.h b/src/futils.h
index 4668d7b63..58936125a 100644
--- a/src/futils.h
+++ b/src/futils.h
@@ -257,7 +257,7 @@ extern int git_futils_truncate(const char *path, int mode);
*/
extern int git_futils_filesize(uint64_t *out, git_file fd);
-#define GIT_PERMS_IS_EXEC(MODE) (((MODE) & 0111) != 0)
+#define GIT_PERMS_IS_EXEC(MODE) (((MODE) & 0100) != 0)
#define GIT_PERMS_CANONICAL(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0755 : 0644)
#define GIT_PERMS_FOR_WRITE(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0777 : 0666)
diff --git a/src/global.c b/src/global.c
deleted file mode 100644
index 5af35aa62..000000000
--- a/src/global.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "global.h"
-
-#include "alloc.h"
-#include "hash.h"
-#include "sysdir.h"
-#include "filter.h"
-#include "merge_driver.h"
-#include "streams/registry.h"
-#include "streams/mbedtls.h"
-#include "streams/openssl.h"
-#include "thread-utils.h"
-#include "git2/global.h"
-#include "transports/ssh.h"
-
-#if defined(GIT_MSVC_CRTDBG)
-#include "win32/w32_stack.h"
-#include "win32/w32_crtdbg_stacktrace.h"
-#endif
-
-git_mutex git__mwindow_mutex;
-
-typedef int (*git_global_init_fn)(void);
-
-static git_global_init_fn git__init_callbacks[] = {
- git_allocator_global_init,
- git_hash_global_init,
- git_sysdir_global_init,
- git_filter_global_init,
- git_merge_driver_global_init,
- git_transport_ssh_global_init,
- git_stream_registry_global_init,
- git_openssl_stream_global_init,
- git_mbedtls_stream_global_init,
- git_mwindow_global_init
-};
-
-static git_global_shutdown_fn git__shutdown_callbacks[ARRAY_SIZE(git__init_callbacks)];
-
-static git_atomic git__n_shutdown_callbacks;
-static git_atomic git__n_inits;
-char *git__user_agent;
-char *git__ssl_ciphers;
-
-void git__on_shutdown(git_global_shutdown_fn callback)
-{
- int count = git_atomic_inc(&git__n_shutdown_callbacks);
- assert(count <= (int) ARRAY_SIZE(git__shutdown_callbacks) && count > 0);
- git__shutdown_callbacks[count - 1] = callback;
-}
-
-static void git__global_state_cleanup(git_global_st *st)
-{
- if (!st)
- return;
-
- git__free(st->error_t.message);
- st->error_t.message = NULL;
-}
-
-static int init_common(void)
-{
- size_t i;
- int ret;
-
- /* Initialize the CRT debug allocator first, before our first malloc */
-#if defined(GIT_MSVC_CRTDBG)
- git_win32__crtdbg_stacktrace_init();
- git_win32__stack_init();
-#endif
-
- /* Initialize subsystems that have global state */
- for (i = 0; i < ARRAY_SIZE(git__init_callbacks); i++)
- if ((ret = git__init_callbacks[i]()) != 0)
- break;
-
- GIT_MEMORY_BARRIER;
-
- return ret;
-}
-
-static void shutdown_common(void)
-{
- int pos;
-
- /* Shutdown subsystems that have registered */
- for (pos = git_atomic_get(&git__n_shutdown_callbacks);
- pos > 0;
- pos = git_atomic_dec(&git__n_shutdown_callbacks)) {
-
- git_global_shutdown_fn cb = git__swap(
- git__shutdown_callbacks[pos - 1], NULL);
-
- if (cb != NULL)
- cb();
- }
-
- git__free(git__user_agent);
- git__free(git__ssl_ciphers);
-}
-
-/**
- * Handle the global state with TLS
- *
- * If libgit2 is built with GIT_THREADS enabled,
- * the `git_libgit2_init()` function must be called
- * before calling any other function of the library.
- *
- * This function allocates a TLS index (using pthreads
- * or the native Win32 API) to store the global state
- * on a per-thread basis.
- *
- * Any internal method that requires global state will
- * then call `git__global_state()` which returns a pointer
- * to the global state structure; this pointer is lazily
- * allocated on each thread.
- *
- * Before shutting down the library, the
- * `git_libgit2_shutdown` method must be called to free
- * the previously reserved TLS index.
- *
- * If libgit2 is built without threading support, the
- * `git__global_statestate()` call returns a pointer to a single,
- * statically allocated global state. The `git_thread_`
- * functions are not available in that case.
- */
-
-/*
- * `git_libgit2_init()` allows subsystems to perform global setup,
- * which may take place in the global scope. An explicit memory
- * fence exists at the exit of `git_libgit2_init()`. Without this,
- * CPU cores are free to reorder cache invalidation of `_tls_init`
- * before cache invalidation of the subsystems' newly written global
- * state.
- */
-#if defined(GIT_THREADS) && defined(GIT_WIN32)
-
-static DWORD _fls_index;
-static volatile LONG _mutex = 0;
-
-static void WINAPI fls_free(void *st)
-{
- git__global_state_cleanup(st);
- git__free(st);
-}
-
-static int synchronized_threads_init(void)
-{
- int error;
-
- if ((_fls_index = FlsAlloc(fls_free)) == FLS_OUT_OF_INDEXES)
- return -1;
-
- git_threads_init();
-
- if (git_mutex_init(&git__mwindow_mutex))
- return -1;
-
- error = init_common();
-
- return error;
-}
-
-int git_libgit2_init(void)
-{
- int ret;
-
- /* Enter the lock */
- while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); }
-
- /* Only do work on a 0 -> 1 transition of the refcount */
- if ((ret = git_atomic_inc(&git__n_inits)) == 1) {
- if (synchronized_threads_init() < 0)
- ret = -1;
- }
-
- /* Exit the lock */
- InterlockedExchange(&_mutex, 0);
-
- return ret;
-}
-
-int git_libgit2_shutdown(void)
-{
- int ret;
-
- /* Enter the lock */
- while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); }
-
- /* Only do work on a 1 -> 0 transition of the refcount */
- if ((ret = git_atomic_dec(&git__n_inits)) == 0) {
- shutdown_common();
-
- FlsFree(_fls_index);
- git_mutex_free(&git__mwindow_mutex);
-
-#if defined(GIT_MSVC_CRTDBG)
- git_win32__crtdbg_stacktrace_cleanup();
- git_win32__stack_cleanup();
-#endif
- }
-
- /* Exit the lock */
- InterlockedExchange(&_mutex, 0);
-
- return ret;
-}
-
-git_global_st *git__global_state(void)
-{
- git_global_st *ptr;
-
- assert(git_atomic_get(&git__n_inits) > 0);
-
- if ((ptr = FlsGetValue(_fls_index)) != NULL)
- return ptr;
-
- ptr = git__calloc(1, sizeof(git_global_st));
- if (!ptr)
- return NULL;
-
- git_buf_init(&ptr->error_buf, 0);
-
- FlsSetValue(_fls_index, ptr);
- return ptr;
-}
-
-#elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
-
-static pthread_key_t _tls_key;
-static pthread_mutex_t _init_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_once_t _once_init = PTHREAD_ONCE_INIT;
-int init_error = 0;
-
-static void cb__free_status(void *st)
-{
- git__global_state_cleanup(st);
- git__free(st);
-}
-
-static void init_once(void)
-{
- if ((init_error = git_mutex_init(&git__mwindow_mutex)) != 0)
- return;
-
- pthread_key_create(&_tls_key, &cb__free_status);
-
- init_error = init_common();
-}
-
-int git_libgit2_init(void)
-{
- int ret, err;
-
- if ((err = pthread_mutex_lock(&_init_mutex)) != 0)
- return err;
-
- ret = git_atomic_inc(&git__n_inits);
- err = pthread_once(&_once_init, init_once);
- err |= pthread_mutex_unlock(&_init_mutex);
-
- if (err || init_error)
- return err | init_error;
-
- return ret;
-}
-
-int git_libgit2_shutdown(void)
-{
- void *ptr = NULL;
- pthread_once_t new_once = PTHREAD_ONCE_INIT;
- int error, ret;
-
- if ((error = pthread_mutex_lock(&_init_mutex)) != 0)
- return error;
-
- if ((ret = git_atomic_dec(&git__n_inits)) != 0)
- goto out;
-
- /* Shut down any subsystems that have global state */
- shutdown_common();
-
- ptr = pthread_getspecific(_tls_key);
- pthread_setspecific(_tls_key, NULL);
-
- git__global_state_cleanup(ptr);
- git__free(ptr);
-
- pthread_key_delete(_tls_key);
- git_mutex_free(&git__mwindow_mutex);
- _once_init = new_once;
-
-out:
- if ((error = pthread_mutex_unlock(&_init_mutex)) != 0)
- return error;
-
- return ret;
-}
-
-git_global_st *git__global_state(void)
-{
- git_global_st *ptr;
-
- assert(git_atomic_get(&git__n_inits) > 0);
-
- if ((ptr = pthread_getspecific(_tls_key)) != NULL)
- return ptr;
-
- ptr = git__calloc(1, sizeof(git_global_st));
- if (!ptr)
- return NULL;
-
- git_buf_init(&ptr->error_buf, 0);
- pthread_setspecific(_tls_key, ptr);
- return ptr;
-}
-
-#else
-
-static git_global_st __state;
-
-int git_libgit2_init(void)
-{
- int ret;
-
- /* Only init subsystems the first time */
- if ((ret = git_atomic_inc(&git__n_inits)) != 1)
- return ret;
-
- if ((ret = init_common()) < 0)
- return ret;
-
- return 1;
-}
-
-int git_libgit2_shutdown(void)
-{
- int ret;
-
- /* Shut down any subsystems that have global state */
- if ((ret = git_atomic_dec(&git__n_inits)) == 0) {
- shutdown_common();
- git__global_state_cleanup(&__state);
- memset(&__state, 0, sizeof(__state));
- }
-
- return ret;
-}
-
-git_global_st *git__global_state(void)
-{
- return &__state;
-}
-
-#endif /* GIT_THREADS */
diff --git a/src/global.h b/src/global.h
deleted file mode 100644
index db41dad1f..000000000
--- a/src/global.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef INCLUDE_global_h__
-#define INCLUDE_global_h__
-
-#include "common.h"
-
-#include "mwindow.h"
-#include "hash.h"
-
-typedef struct {
- git_error *last_error;
- git_error error_t;
- git_buf error_buf;
- char oid_fmt[GIT_OID_HEXSZ+1];
-
- /* On Windows, this is the current child thread that was started by
- * `git_thread_create`. This is used to set the thread's exit code
- * when terminated by `git_thread_exit`. It is unused on POSIX.
- */
- git_thread *current_thread;
-} git_global_st;
-
-git_global_st *git__global_state(void);
-
-extern git_mutex git__mwindow_mutex;
-
-#define GIT_GLOBAL (git__global_state())
-
-typedef void (*git_global_shutdown_fn)(void);
-
-extern void git__on_shutdown(git_global_shutdown_fn callback);
-
-extern const char *git_libgit2__user_agent(void);
-extern const char *git_libgit2__ssl_ciphers(void);
-
-#endif
diff --git a/src/graph.c b/src/graph.c
index df82f0f71..35e914f74 100644
--- a/src/graph.c
+++ b/src/graph.c
@@ -43,7 +43,7 @@ static int mark_parents(git_revwalk *walk, git_commit_list_node *one,
return 0;
}
- if (git_pqueue_init(&list, 0, 2, git_commit_list_time_cmp) < 0)
+ if (git_pqueue_init(&list, 0, 2, git_commit_list_generation_cmp) < 0)
return -1;
if (git_commit_list_parse(walk, one) < 0)
@@ -176,19 +176,74 @@ on_error:
int git_graph_descendant_of(git_repository *repo, const git_oid *commit, const git_oid *ancestor)
{
- git_oid merge_base;
- int error;
-
if (git_oid_equal(commit, ancestor))
return 0;
- error = git_merge_base(&merge_base, repo, commit, ancestor);
- /* No merge-base found, it's not a descendant */
- if (error == GIT_ENOTFOUND)
+ return git_graph_reachable_from_any(repo, ancestor, commit, 1);
+}
+
+int git_graph_reachable_from_any(
+ git_repository *repo,
+ const git_oid *commit_id,
+ const git_oid descendant_array[],
+ size_t length)
+{
+ git_revwalk *walk = NULL;
+ git_vector list;
+ git_commit_list *result = NULL;
+ git_commit_list_node *commit;
+ size_t i;
+ uint32_t minimum_generation = 0xffffffff;
+ int error = 0;
+
+ if (!length)
return 0;
- if (error < 0)
+ for (i = 0; i < length; ++i) {
+ if (git_oid_equal(commit_id, &descendant_array[i]))
+ return 1;
+ }
+
+ if ((error = git_vector_init(&list, length + 1, NULL)) < 0)
return error;
- return git_oid_equal(&merge_base, ancestor);
+ if ((error = git_revwalk_new(&walk, repo)) < 0)
+ goto done;
+
+ for (i = 0; i < length; i++) {
+ commit = git_revwalk__commit_lookup(walk, &descendant_array[i]);
+ if (commit == NULL) {
+ error = -1;
+ goto done;
+ }
+
+ git_vector_insert(&list, commit);
+ if (minimum_generation > commit->generation)
+ minimum_generation = commit->generation;
+ }
+
+ commit = git_revwalk__commit_lookup(walk, commit_id);
+ if (commit == NULL) {
+ error = -1;
+ goto done;
+ }
+
+ if (minimum_generation > commit->generation)
+ minimum_generation = commit->generation;
+
+ if ((error = git_merge__bases_many(&result, walk, commit, &list, minimum_generation)) < 0)
+ goto done;
+
+ if (result) {
+ error = git_oid_equal(commit_id, &result->item->oid);
+ } else {
+ /* No merge-base found, it's not a descendant */
+ error = 0;
+ }
+
+done:
+ git_commit_list_free(&result);
+ git_vector_free(&list);
+ git_revwalk_free(walk);
+ return error;
}
diff --git a/src/hash.c b/src/hash.c
index 405c46a9a..5a7278e42 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -16,7 +16,7 @@ int git_hash_ctx_init(git_hash_ctx *ctx)
{
int error;
- if ((error = git_hash_sha1_ctx_init(&ctx->sha1)) < 0)
+ if ((error = git_hash_sha1_ctx_init(&ctx->ctx.sha1)) < 0)
return error;
ctx->algo = GIT_HASH_ALGO_SHA1;
@@ -28,10 +28,10 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx)
{
switch (ctx->algo) {
case GIT_HASH_ALGO_SHA1:
- git_hash_sha1_ctx_cleanup(&ctx->sha1);
+ git_hash_sha1_ctx_cleanup(&ctx->ctx.sha1);
return;
default:
- assert(0);
+ /* unreachable */ ;
}
}
@@ -39,33 +39,36 @@ int git_hash_init(git_hash_ctx *ctx)
{
switch (ctx->algo) {
case GIT_HASH_ALGO_SHA1:
- return git_hash_sha1_init(&ctx->sha1);
+ return git_hash_sha1_init(&ctx->ctx.sha1);
default:
- assert(0);
- return -1;
+ /* unreachable */ ;
}
+ GIT_ASSERT(0);
+ return -1;
}
int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
{
switch (ctx->algo) {
case GIT_HASH_ALGO_SHA1:
- return git_hash_sha1_update(&ctx->sha1, data, len);
+ return git_hash_sha1_update(&ctx->ctx.sha1, data, len);
default:
- assert(0);
- return -1;
+ /* unreachable */ ;
}
+ GIT_ASSERT(0);
+ return -1;
}
int git_hash_final(git_oid *out, git_hash_ctx *ctx)
{
switch (ctx->algo) {
case GIT_HASH_ALGO_SHA1:
- return git_hash_sha1_final(out, &ctx->sha1);
+ return git_hash_sha1_final(out, &ctx->ctx.sha1);
default:
- assert(0);
- return -1;
+ /* unreachable */ ;
}
+ GIT_ASSERT(0);
+ return -1;
}
int git_hash_buf(git_oid *out, const void *data, size_t len)
@@ -80,7 +83,7 @@ int git_hash_buf(git_oid *out, const void *data, size_t len)
error = git_hash_final(out, &ctx);
git_hash_ctx_cleanup(&ctx);
-
+
return error;
}
diff --git a/src/hash.h b/src/hash.h
index 017bb286c..87305cc79 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -27,7 +27,7 @@ typedef enum {
typedef struct git_hash_ctx {
union {
git_hash_sha1_ctx sha1;
- };
+ } ctx;
git_hash_algo_t algo;
} git_hash_ctx;
diff --git a/src/hash/sha1/collisiondetect.c b/src/hash/sha1/collisiondetect.c
index e6a126780..722ebf36f 100644
--- a/src/hash/sha1/collisiondetect.c
+++ b/src/hash/sha1/collisiondetect.c
@@ -24,21 +24,21 @@ void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
{
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
SHA1DCInit(&ctx->c);
return 0;
}
int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
{
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
SHA1DCUpdate(&ctx->c, data, len);
return 0;
}
int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
{
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
if (SHA1DCFinal(out->id, &ctx->c)) {
git_error_set(GIT_ERROR_SHA1, "SHA1 collision attack detected");
return -1;
diff --git a/src/hash/sha1/common_crypto.c b/src/hash/sha1/common_crypto.c
index 0449a3c9d..4250e0b61 100644
--- a/src/hash/sha1/common_crypto.c
+++ b/src/hash/sha1/common_crypto.c
@@ -26,7 +26,7 @@ void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
{
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
CC_SHA1_Init(&ctx->c);
return 0;
}
@@ -35,7 +35,7 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *_data, size_t len)
{
const unsigned char *data = _data;
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
while (len > 0) {
CC_LONG chunk = (len > CC_LONG_MAX) ? CC_LONG_MAX : (CC_LONG)len;
@@ -51,7 +51,7 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *_data, size_t len)
int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
{
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
CC_SHA1_Final(out->id, &ctx->c);
return 0;
}
diff --git a/src/hash/sha1/generic.h b/src/hash/sha1/generic.h
index e4cc6026b..53fc0823e 100644
--- a/src/hash/sha1/generic.h
+++ b/src/hash/sha1/generic.h
@@ -11,7 +11,7 @@
#include "hash/sha1.h"
struct git_hash_sha1_ctx {
- unsigned long long size;
+ uint64_t size;
unsigned int H[5];
unsigned int W[16];
};
diff --git a/src/hash/sha1/mbedtls.c b/src/hash/sha1/mbedtls.c
index e44343fcf..04e7da5fa 100644
--- a/src/hash/sha1/mbedtls.c
+++ b/src/hash/sha1/mbedtls.c
@@ -19,28 +19,28 @@ int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx)
void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
{
- assert(ctx);
- mbedtls_sha1_free(&ctx->c);
+ if (ctx)
+ mbedtls_sha1_free(&ctx->c);
}
int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
{
- assert(ctx);
- mbedtls_sha1_init(&ctx->c);
- mbedtls_sha1_starts(&ctx->c);
- return 0;
+ GIT_ASSERT_ARG(ctx);
+ mbedtls_sha1_init(&ctx->c);
+ mbedtls_sha1_starts(&ctx->c);
+ return 0;
}
int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
{
- assert(ctx);
- mbedtls_sha1_update(&ctx->c, data, len);
- return 0;
+ GIT_ASSERT_ARG(ctx);
+ mbedtls_sha1_update(&ctx->c, data, len);
+ return 0;
}
int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
{
- assert(ctx);
- mbedtls_sha1_finish(&ctx->c, out->id);
- return 0;
+ GIT_ASSERT_ARG(ctx);
+ mbedtls_sha1_finish(&ctx->c, out->id);
+ return 0;
}
diff --git a/src/hash/sha1/openssl.c b/src/hash/sha1/openssl.c
index ba3212ff2..68d9611d4 100644
--- a/src/hash/sha1/openssl.c
+++ b/src/hash/sha1/openssl.c
@@ -24,7 +24,7 @@ void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
{
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
if (SHA1_Init(&ctx->c) != 1) {
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to initialize hash context");
@@ -36,7 +36,7 @@ int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
{
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
if (SHA1_Update(&ctx->c, data, len) != 1) {
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to update hash");
@@ -48,7 +48,7 @@ int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
{
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
if (SHA1_Final(out->id, &ctx->c) != 1) {
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to finalize hash");
diff --git a/src/hash/sha1/sha1dc/sha1.c b/src/hash/sha1/sha1dc/sha1.c
index 9d3cf81d4..4d03c75d8 100644
--- a/src/hash/sha1/sha1dc/sha1.c
+++ b/src/hash/sha1/sha1dc/sha1.c
@@ -10,10 +10,8 @@
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
-#ifdef __unix__
#include <sys/types.h> /* make sure macros like _BIG_ENDIAN visible */
#endif
-#endif
#ifdef SHA1DC_CUSTOM_INCLUDE_SHA1_C
#include SHA1DC_CUSTOM_INCLUDE_SHA1_C
@@ -1712,7 +1710,7 @@ static void sha1_recompression_step(uint32_t step, uint32_t ihvin[5], uint32_t i
-static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
+static void sha1_process(SHA1_CTX *ctx, const uint32_t block[16])
{
unsigned i, j;
uint32_t ubc_dv_mask[DVMASKSIZE] = { 0xFFFFFFFF };
@@ -1764,7 +1762,7 @@ static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
}
}
-void SHA1DCInit(SHA1_CTX* ctx)
+void SHA1DCInit(SHA1_CTX *ctx)
{
ctx->total = 0;
ctx->ihv[0] = 0x67452301;
@@ -1780,7 +1778,7 @@ void SHA1DCInit(SHA1_CTX* ctx)
ctx->callback = NULL;
}
-void SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash)
+void SHA1DCSetSafeHash(SHA1_CTX *ctx, int safehash)
{
if (safehash)
ctx->safe_hash = 1;
@@ -1789,7 +1787,7 @@ void SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash)
}
-void SHA1DCSetUseUBC(SHA1_CTX* ctx, int ubc_check)
+void SHA1DCSetUseUBC(SHA1_CTX *ctx, int ubc_check)
{
if (ubc_check)
ctx->ubc_check = 1;
@@ -1797,7 +1795,7 @@ void SHA1DCSetUseUBC(SHA1_CTX* ctx, int ubc_check)
ctx->ubc_check = 0;
}
-void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll)
+void SHA1DCSetUseDetectColl(SHA1_CTX *ctx, int detect_coll)
{
if (detect_coll)
ctx->detect_coll = 1;
@@ -1805,7 +1803,7 @@ void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll)
ctx->detect_coll = 0;
}
-void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX* ctx, int reduced_round_coll)
+void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX *ctx, int reduced_round_coll)
{
if (reduced_round_coll)
ctx->reduced_round_coll = 1;
@@ -1813,12 +1811,12 @@ void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX* ctx, int reduced_round_coll)
ctx->reduced_round_coll = 0;
}
-void SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback)
+void SHA1DCSetCallback(SHA1_CTX *ctx, collision_block_callback callback)
{
ctx->callback = callback;
}
-void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len)
+void SHA1DCUpdate(SHA1_CTX *ctx, const char *buf, size_t len)
{
unsigned left, fill;
diff --git a/src/hash/sha1/win32.c b/src/hash/sha1/win32.c
index c73695665..a6e7061c6 100644
--- a/src/hash/sha1/win32.c
+++ b/src/hash/sha1/win32.c
@@ -7,7 +7,7 @@
#include "win32.h"
-#include "global.h"
+#include "runtime.h"
#include <wincrypt.h>
#include <strsafe.h>
@@ -129,7 +129,8 @@ int git_hash_sha1_global_init(void)
if ((error = hash_cng_prov_init()) < 0)
error = hash_cryptoapi_prov_init();
- git__on_shutdown(sha1_shutdown);
+ if (!error)
+ error = git_runtime_shutdown_register(sha1_shutdown);
return error;
}
@@ -163,7 +164,7 @@ GIT_INLINE(int) hash_cryptoapi_update(git_hash_sha1_ctx *ctx, const void *_data,
{
const BYTE *data = (BYTE *)_data;
- assert(ctx->ctx.cryptoapi.valid);
+ GIT_ASSERT(ctx->ctx.cryptoapi.valid);
while (len > 0) {
DWORD chunk = (len > MAXDWORD) ? MAXDWORD : (DWORD)len;
@@ -185,7 +186,7 @@ GIT_INLINE(int) hash_cryptoapi_final(git_oid *out, git_hash_sha1_ctx *ctx)
DWORD len = 20;
int error = 0;
- assert(ctx->ctx.cryptoapi.valid);
+ GIT_ASSERT(ctx->ctx.cryptoapi.valid);
if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out->id, &len, 0)) {
git_error_set(GIT_ERROR_OS, "legacy hash data could not be finished");
@@ -285,7 +286,7 @@ int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx)
{
int error = 0;
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
/*
* When compiled with GIT_THREADS, the global hash_prov data is
@@ -302,27 +303,30 @@ int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx)
int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
{
- assert(ctx && ctx->type);
+ GIT_ASSERT_ARG(ctx);
+ GIT_ASSERT_ARG(ctx->type);
return (ctx->type == CNG) ? hash_cng_init(ctx) : hash_cryptoapi_init(ctx);
}
int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
{
- assert(ctx && ctx->type);
+ GIT_ASSERT_ARG(ctx);
+ GIT_ASSERT_ARG(ctx->type);
return (ctx->type == CNG) ? hash_cng_update(ctx, data, len) : hash_cryptoapi_update(ctx, data, len);
}
int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx)
{
- assert(ctx && ctx->type);
+ GIT_ASSERT_ARG(ctx);
+ GIT_ASSERT_ARG(ctx->type);
return (ctx->type == CNG) ? hash_cng_final(out, ctx) : hash_cryptoapi_final(out, ctx);
}
void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
{
- assert(ctx);
-
- if (ctx->type == CNG)
+ if (!ctx)
+ return;
+ else if (ctx->type == CNG)
hash_ctx_cng_cleanup(ctx);
else if(ctx->type == CRYPTOAPI)
hash_ctx_cryptoapi_cleanup(ctx);
diff --git a/src/hashsig.c b/src/hashsig.c
index 14ec34b2f..6b4fb8352 100644
--- a/src/hashsig.c
+++ b/src/hashsig.c
@@ -17,7 +17,7 @@ typedef uint64_t hashsig_state;
#define HASHSIG_SCALE 100
#define HASHSIG_MAX_RUN 80
-#define HASHSIG_HASH_START 0x012345678ABCDEF0LL
+#define HASHSIG_HASH_START INT64_C(0x012345678ABCDEF0)
#define HASHSIG_HASH_SHIFT 5
#define HASHSIG_HASH_MIX(S,CH) \
@@ -133,13 +133,13 @@ typedef struct {
uint8_t ignore_ch[256];
} hashsig_in_progress;
-static void hashsig_in_progress_init(
+static int hashsig_in_progress_init(
hashsig_in_progress *prog, git_hashsig *sig)
{
int i;
/* no more than one can be set */
- assert(!(sig->opt & GIT_HASHSIG_IGNORE_WHITESPACE) ||
+ GIT_ASSERT(!(sig->opt & GIT_HASHSIG_IGNORE_WHITESPACE) ||
!(sig->opt & GIT_HASHSIG_SMART_WHITESPACE));
if (sig->opt & GIT_HASHSIG_IGNORE_WHITESPACE) {
@@ -153,6 +153,8 @@ static void hashsig_in_progress_init(
} else {
memset(prog, 0, sizeof(*prog));
}
+
+ return 0;
}
static int hashsig_add_hashes(
@@ -251,7 +253,8 @@ int git_hashsig_create(
git_hashsig *sig = hashsig_alloc(opts);
GIT_ERROR_CHECK_ALLOC(sig);
- hashsig_in_progress_init(&prog, sig);
+ if ((error = hashsig_in_progress_init(&prog, sig)) < 0)
+ return error;
error = hashsig_add_hashes(sig, (const uint8_t *)buf, buflen, &prog);
@@ -283,7 +286,10 @@ int git_hashsig_create_fromfile(
return fd;
}
- hashsig_in_progress_init(&prog, sig);
+ if ((error = hashsig_in_progress_init(&prog, sig)) < 0) {
+ p_close(fd);
+ return error;
+ }
while (!error) {
if ((buflen = p_read(fd, buf, sizeof(buf))) <= 0) {
@@ -318,7 +324,7 @@ static int hashsig_heap_compare(const hashsig_heap *a, const hashsig_heap *b)
{
int matches = 0, i, j, cmp;
- assert(a->cmp == b->cmp);
+ GIT_ASSERT_WITH_RETVAL(a->cmp == b->cmp, 0);
/* hash heaps are sorted - just look for overlap vs total */
@@ -354,9 +360,16 @@ int git_hashsig_compare(const git_hashsig *a, const git_hashsig *b)
/* if we have fewer than the maximum number of elements, then just use
* one array since the two arrays will be the same
*/
- if (a->mins.size < HASHSIG_HEAP_SIZE)
+ if (a->mins.size < HASHSIG_HEAP_SIZE) {
return hashsig_heap_compare(&a->mins, &b->mins);
- else
- return (hashsig_heap_compare(&a->mins, &b->mins) +
- hashsig_heap_compare(&a->maxs, &b->maxs)) / 2;
+ } else {
+ int mins, maxs;
+
+ if ((mins = hashsig_heap_compare(&a->mins, &b->mins)) < 0)
+ return mins;
+ if ((maxs = hashsig_heap_compare(&a->maxs, &b->maxs)) < 0)
+ return maxs;
+
+ return (mins + maxs) / 2;
+ }
}
diff --git a/src/ident.c b/src/ident.c
index 7eccf9a43..e5aab80ed 100644
--- a/src/ident.c
+++ b/src/ident.c
@@ -10,7 +10,6 @@
#include "git2/sys/filter.h"
#include "filter.h"
#include "buffer.h"
-#include "buf_text.h"
static int ident_find_id(
const char **id_start, const char **id_end, const char *start, size_t len)
@@ -105,7 +104,7 @@ static int ident_apply(
GIT_UNUSED(self); GIT_UNUSED(payload);
/* Don't filter binary files */
- if (git_buf_text_is_binary(from))
+ if (git_buf_is_binary(from))
return GIT_PASSTHROUGH;
if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE)
@@ -114,6 +113,17 @@ static int ident_apply(
return ident_remove_id(to, from);
}
+static int ident_stream(
+ git_writestream **out,
+ git_filter *self,
+ void **payload,
+ const git_filter_source *src,
+ git_writestream *next)
+{
+ return git_filter_buffered_stream_new(out,
+ self, ident_apply, NULL, payload, src, next);
+}
+
git_filter *git_ident_filter_new(void)
{
git_filter *f = git__calloc(1, sizeof(git_filter));
@@ -123,7 +133,7 @@ git_filter *git_ident_filter_new(void)
f->version = GIT_FILTER_VERSION;
f->attributes = "+ident"; /* apply to files with ident attribute set */
f->shutdown = git_filter_free;
- f->apply = ident_apply;
+ f->stream = ident_stream;
return f;
}
diff --git a/src/ignore.c b/src/ignore.c
index f5fb507e6..9ead96ba6 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -101,7 +101,7 @@ static int does_negate_pattern(git_attr_fnmatch *rule, git_attr_fnmatch *neg)
*/
static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match)
{
- int error = 0, wildmatch_flags;
+ int error = 0, wildmatch_flags, effective_flags;
size_t i;
git_attr_fnmatch *rule;
char *path;
@@ -141,8 +141,17 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
if (git_buf_oom(&buf))
goto out;
+ /*
+ * if rule isn't for full path we match without PATHNAME flag
+ * as lines like *.txt should match something like dir/test.txt
+ * requiring * to also match /
+ */
+ effective_flags = wildmatch_flags;
+ if (!(rule->flags & GIT_ATTR_FNMATCH_FULLPATH))
+ effective_flags &= ~WM_PATHNAME;
+
/* if we found a match, we want to keep this rule */
- if ((wildmatch(git_buf_cstr(&buf), path, wildmatch_flags)) == WM_MATCH) {
+ if ((wildmatch(git_buf_cstr(&buf), path, effective_flags)) == WM_MATCH) {
*out = 1;
error = 0;
goto out;
@@ -238,11 +247,12 @@ static int push_ignore_file(
const char *base,
const char *filename)
{
- int error = 0;
+ git_attr_file_source source = { GIT_ATTR_FILE_SOURCE_FILE, base, filename };
git_attr_file *file = NULL;
+ int error = 0;
+
+ error = git_attr_cache__get(&file, ignores->repo, NULL, &source, parse_ignore_file, false);
- error = git_attr_cache__get(&file, ignores->repo, NULL, GIT_ATTR_FILE__FROM_FILE,
- base, filename, parse_ignore_file, false);
if (error < 0)
return error;
@@ -263,13 +273,13 @@ static int push_one_ignore(void *payload, const char *path)
static int get_internal_ignores(git_attr_file **out, git_repository *repo)
{
+ git_attr_file_source source = { GIT_ATTR_FILE_SOURCE_MEMORY, NULL, GIT_IGNORE_INTERNAL };
int error;
if ((error = git_attr_cache__init(repo)) < 0)
return error;
- error = git_attr_cache__get(out, repo, NULL, GIT_ATTR_FILE__IN_MEMORY, NULL,
- GIT_IGNORE_INTERNAL, NULL, false);
+ error = git_attr_cache__get(out, repo, NULL, &source, NULL, false);
/* if internal rules list is empty, insert default rules */
if (!error && !(*out)->rules.length)
@@ -287,7 +297,9 @@ int git_ignore__for_path(
const char *workdir = git_repository_workdir(repo);
git_buf infopath = GIT_BUF_INIT;
- assert(repo && ignores && path);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(ignores);
+ GIT_ASSERT_ARG(path);
memset(ignores, 0, sizeof(*ignores));
ignores->repo = repo;
@@ -307,12 +319,17 @@ int git_ignore__for_path(
if ((error = git_path_dirname_r(&local, path)) < 0 ||
(error = git_path_resolve_relative(&local, 0)) < 0 ||
(error = git_path_to_dir(&local)) < 0 ||
- (error = git_buf_joinpath(&ignores->dir, workdir, local.ptr)) < 0)
- {;} /* Nothing, we just want to stop on the first error */
+ (error = git_buf_joinpath(&ignores->dir, workdir, local.ptr)) < 0 ||
+ (error = git_path_validate_workdir_buf(repo, &ignores->dir)) < 0) {
+ /* Nothing, we just want to stop on the first error */
+ }
+
git_buf_dispose(&local);
} else {
- error = git_buf_joinpath(&ignores->dir, path, "");
+ if (!(error = git_buf_joinpath(&ignores->dir, path, "")))
+ error = git_path_validate_filesystem(ignores->dir.ptr, ignores->dir.size);
}
+
if (error < 0)
goto cleanup;
@@ -521,7 +538,9 @@ int git_ignore_path_is_ignored(
git_attr_file *file;
git_dir_flag dir_flag = GIT_DIR_FLAG_UNKNOWN;
- assert(repo && ignored && pathname);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(ignored);
+ GIT_ASSERT_ARG(pathname);
workdir = git_repository_workdir(repo);
@@ -586,7 +605,7 @@ int git_ignore__check_pathspec_for_exact_ignores(
git_attr_fnmatch *match;
int ignored;
git_buf path = GIT_BUF_INIT;
- const char *wd, *filename;
+ const char *filename;
git_index *idx;
if ((error = git_repository__ensure_not_bare(
@@ -594,8 +613,6 @@ int git_ignore__check_pathspec_for_exact_ignores(
(error = git_repository_index(&idx, repo)) < 0)
return error;
- wd = git_repository_workdir(repo);
-
git_vector_foreach(vspec, i, match) {
/* skip wildcard matches (if they are being used) */
if ((match->flags & GIT_ATTR_FNMATCH_HASWILD) != 0 &&
@@ -608,7 +625,7 @@ int git_ignore__check_pathspec_for_exact_ignores(
if (git_index_get_bypath(idx, filename, 0) != NULL)
continue;
- if ((error = git_buf_joinpath(&path, wd, filename)) < 0)
+ if ((error = git_repository_workdir_path(&path, repo, filename)) < 0)
break;
/* is there a file on disk that matches this exactly? */
@@ -632,4 +649,3 @@ int git_ignore__check_pathspec_for_exact_ignores(
return error;
}
-
diff --git a/src/index.c b/src/index.c
index 361288b8d..5c3305170 100644
--- a/src/index.c
+++ b/src/index.c
@@ -406,7 +406,7 @@ int git_index_open(git_index **index_out, const char *index_path)
git_index *index;
int error = -1;
- assert(index_out);
+ GIT_ASSERT_ARG(index_out);
index = git__calloc(1, sizeof(git_index));
GIT_ERROR_CHECK_ALLOC(index);
@@ -461,7 +461,8 @@ static void index_free(git_index *index)
/* index iterators increment the refcount of the index, so if we
* get here then there should be no outstanding iterators.
*/
- assert(!git_atomic_get(&index->readers));
+ if (git_atomic32_get(&index->readers))
+ return;
git_index_clear(index);
git_idxmap_free(index->entries_map);
@@ -487,14 +488,14 @@ void git_index_free(git_index *index)
/* call with locked index */
static void index_free_deleted(git_index *index)
{
- int readers = (int)git_atomic_get(&index->readers);
+ int readers = (int)git_atomic32_get(&index->readers);
size_t i;
if (readers > 0 || !index->deleted.length)
return;
for (i = 0; i < index->deleted.length; ++i) {
- git_index_entry *ie = git__swap(index->deleted.contents[i], NULL);
+ git_index_entry *ie = git_atomic_swap(index->deleted.contents[i], NULL);
index_entry_free(ie);
}
@@ -515,7 +516,7 @@ static int index_remove_entry(git_index *index, size_t pos)
error = git_vector_remove(&index->entries, pos);
if (!error) {
- if (git_atomic_get(&index->readers) > 0) {
+ if (git_atomic32_get(&index->readers) > 0) {
error = git_vector_insert(&index->deleted, entry);
} else {
index_entry_free(entry);
@@ -531,7 +532,7 @@ int git_index_clear(git_index *index)
{
int error = 0;
- assert(index);
+ GIT_ASSERT_ARG(index);
index->dirty = 1;
index->tree = NULL;
@@ -566,7 +567,7 @@ int git_index_set_caps(git_index *index, int caps)
{
unsigned int old_ignore_case;
- assert(index);
+ GIT_ASSERT_ARG(index);
old_ignore_case = index->ignore_case;
@@ -778,14 +779,14 @@ done:
unsigned git_index_version(git_index *index)
{
- assert(index);
+ GIT_ASSERT_ARG(index);
return index->version;
}
int git_index_set_version(git_index *index, unsigned int version)
{
- assert(index);
+ GIT_ASSERT_ARG(index);
if (version < INDEX_VERSION_NUMBER_LB ||
version > INDEX_VERSION_NUMBER_UB) {
@@ -814,9 +815,9 @@ int git_index_write(git_index *index)
return error;
}
-const char * git_index_path(const git_index *index)
+const char *git_index_path(const git_index *index)
{
- assert(index);
+ GIT_ASSERT_ARG_WITH_RETVAL(index, NULL);
return index->index_file_path;
}
@@ -824,7 +825,8 @@ int git_index_write_tree(git_oid *oid, git_index *index)
{
git_repository *repo;
- assert(oid && index);
+ GIT_ASSERT_ARG(oid);
+ GIT_ASSERT_ARG(index);
repo = INDEX_OWNER(index);
@@ -838,20 +840,25 @@ int git_index_write_tree(git_oid *oid, git_index *index)
int git_index_write_tree_to(
git_oid *oid, git_index *index, git_repository *repo)
{
- assert(oid && index && repo);
+ GIT_ASSERT_ARG(oid);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(repo);
+
return git_tree__write_index(oid, index, repo);
}
size_t git_index_entrycount(const git_index *index)
{
- assert(index);
+ GIT_ASSERT_ARG(index);
+
return index->entries.length;
}
const git_index_entry *git_index_get_byindex(
git_index *index, size_t n)
{
- assert(index);
+ GIT_ASSERT_ARG_WITH_RETVAL(index, NULL);
+
git_vector_sort(&index->entries);
return git_vector_get(&index->entries, n);
}
@@ -862,7 +869,7 @@ const git_index_entry *git_index_get_bypath(
git_index_entry key = {{ 0 }};
git_index_entry *value;
- assert(index);
+ GIT_ASSERT_ARG_WITH_RETVAL(index, NULL);
key.path = path;
GIT_INDEX_ENTRY_STAGE_SET(&key, stage);
@@ -937,7 +944,7 @@ static int index_entry_create(
if (st)
mode = st->st_mode;
- if (!git_path_isvalid(repo, path, mode, path_valid_flags)) {
+ if (!git_path_validate(repo, path, mode, path_valid_flags)) {
git_error_set(GIT_ERROR_INDEX, "invalid path: '%s'", path);
return -1;
}
@@ -981,7 +988,7 @@ static int index_entry_init(
if (git_repository__ensure_not_bare(repo, "create blob from file") < 0)
return GIT_EBAREREPO;
- if (git_buf_joinpath(&path, git_repository_workdir(repo), rel_path) < 0)
+ if (git_repository_workdir_path(&path, repo, rel_path) < 0)
return -1;
error = git_path_lstat(path.ptr, &st);
@@ -1039,23 +1046,24 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out,
{
git_index_reuc_entry *reuc = NULL;
- assert(reuc_out && path);
+ GIT_ASSERT_ARG(reuc_out);
+ GIT_ASSERT_ARG(path);
*reuc_out = reuc = reuc_entry_alloc(path);
GIT_ERROR_CHECK_ALLOC(reuc);
if ((reuc->mode[0] = ancestor_mode) > 0) {
- assert(ancestor_oid);
+ GIT_ASSERT(ancestor_oid);
git_oid_cpy(&reuc->oid[0], ancestor_oid);
}
if ((reuc->mode[1] = our_mode) > 0) {
- assert(our_oid);
+ GIT_ASSERT(our_oid);
git_oid_cpy(&reuc->oid[1], our_oid);
}
if ((reuc->mode[2] = their_mode) > 0) {
- assert(their_oid);
+ GIT_ASSERT(their_oid);
git_oid_cpy(&reuc->oid[2], their_oid);
}
@@ -1347,7 +1355,8 @@ static int index_insert(
size_t path_length, position;
int error;
- assert(index && entry_ptr);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(entry_ptr);
entry = *entry_ptr;
@@ -1472,7 +1481,8 @@ int git_index_add_from_buffer(
int error = 0;
git_oid id;
- assert(index && source_entry->path);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(source_entry && source_entry->path);
if (INDEX_OWNER(index) == NULL)
return create_index_error(-1,
@@ -1522,7 +1532,7 @@ static int add_repo_as_submodule(git_index_entry **out, git_index *index, const
struct stat st;
int error;
- if ((error = git_buf_joinpath(&abspath, git_repository_workdir(repo), path)) < 0)
+ if ((error = git_repository_workdir_path(&abspath, repo, path)) < 0)
return error;
if ((error = p_stat(abspath.ptr, &st)) < 0) {
@@ -1557,7 +1567,8 @@ int git_index_add_bypath(git_index *index, const char *path)
git_index_entry *entry = NULL;
int ret;
- assert(index && path);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(path);
if ((ret = index_entry_init(&entry, index, path)) == 0)
ret = index_insert(index, &entry, 1, false, false, true);
@@ -1609,7 +1620,8 @@ int git_index_remove_bypath(git_index *index, const char *path)
{
int ret;
- assert(index && path);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(path);
if (((ret = git_index_remove(index, path, 0)) < 0 &&
ret != GIT_ENOTFOUND) ||
@@ -1629,7 +1641,7 @@ int git_index__fill(git_index *index, const git_vector *source_entries)
int error = 0;
size_t i;
- assert(index);
+ GIT_ASSERT_ARG(index);
if (!source_entries->length)
return 0;
@@ -1670,7 +1682,8 @@ int git_index_add(git_index *index, const git_index_entry *source_entry)
git_index_entry *entry = NULL;
int ret;
- assert(index && source_entry && source_entry->path);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(source_entry && source_entry->path);
if (!valid_filemode(source_entry->mode)) {
git_error_set(GIT_ERROR_INDEX, "invalid entry mode");
@@ -1758,7 +1771,8 @@ int git_index_find_prefix(size_t *at_pos, git_index *index, const char *prefix)
int git_index__find_pos(
size_t *out, git_index *index, const char *path, size_t path_len, int stage)
{
- assert(index && path);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(path);
return index_find(out, index, path, path_len, stage);
}
@@ -1766,7 +1780,8 @@ int git_index_find(size_t *at_pos, git_index *index, const char *path)
{
size_t pos;
- assert(index && path);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(path);
if (git_vector_bsearch2(
&pos, &index->entries, index->entries_search_path, path) < 0) {
@@ -1799,7 +1814,7 @@ int git_index_conflict_add(git_index *index,
unsigned short i;
int ret = 0;
- assert (index);
+ GIT_ASSERT_ARG(index);
if ((ancestor_entry &&
(ret = index_entry_dup(&entries[0], index, ancestor_entry)) < 0) ||
@@ -1870,7 +1885,10 @@ static int index_conflict__get_byindex(
size_t count;
int stage, len = 0;
- assert(ancestor_out && our_out && their_out && index);
+ GIT_ASSERT_ARG(ancestor_out);
+ GIT_ASSERT_ARG(our_out);
+ GIT_ASSERT_ARG(their_out);
+ GIT_ASSERT_ARG(index);
*ancestor_out = NULL;
*our_out = NULL;
@@ -1916,7 +1934,11 @@ int git_index_conflict_get(
size_t pos;
int len = 0;
- assert(ancestor_out && our_out && their_out && index && path);
+ GIT_ASSERT_ARG(ancestor_out);
+ GIT_ASSERT_ARG(our_out);
+ GIT_ASSERT_ARG(their_out);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(path);
*ancestor_out = NULL;
*our_out = NULL;
@@ -1963,13 +1985,14 @@ static int index_conflict_remove(git_index *index, const char *path)
int git_index_conflict_remove(git_index *index, const char *path)
{
- assert(index && path);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(path);
return index_conflict_remove(index, path);
}
int git_index_conflict_cleanup(git_index *index)
{
- assert(index);
+ GIT_ASSERT_ARG(index);
return index_conflict_remove(index, NULL);
}
@@ -1978,7 +2001,7 @@ int git_index_has_conflicts(const git_index *index)
size_t i;
git_index_entry *entry;
- assert(index);
+ GIT_ASSERT_ARG(index);
git_vector_foreach(&index->entries, i, entry) {
if (GIT_INDEX_ENTRY_STAGE(entry) > 0)
@@ -1995,7 +2018,8 @@ int git_index_iterator_new(
git_index_iterator *it;
int error;
- assert(iterator_out && index);
+ GIT_ASSERT_ARG(iterator_out);
+ GIT_ASSERT_ARG(index);
it = git__calloc(1, sizeof(git_index_iterator));
GIT_ERROR_CHECK_ALLOC(it);
@@ -2015,7 +2039,8 @@ int git_index_iterator_next(
const git_index_entry **out,
git_index_iterator *it)
{
- assert(out && it);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(it);
if (it->cur >= git_vector_length(&it->snap))
return GIT_ITEROVER;
@@ -2039,7 +2064,8 @@ int git_index_conflict_iterator_new(
{
git_index_conflict_iterator *it = NULL;
- assert(iterator_out && index);
+ GIT_ASSERT_ARG(iterator_out);
+ GIT_ASSERT_ARG(index);
it = git__calloc(1, sizeof(git_index_conflict_iterator));
GIT_ERROR_CHECK_ALLOC(it);
@@ -2059,7 +2085,10 @@ int git_index_conflict_next(
const git_index_entry *entry;
int len;
- assert(ancestor_out && our_out && their_out && iterator);
+ GIT_ASSERT_ARG(ancestor_out);
+ GIT_ASSERT_ARG(our_out);
+ GIT_ASSERT_ARG(their_out);
+ GIT_ASSERT_ARG(iterator);
*ancestor_out = NULL;
*our_out = NULL;
@@ -2097,14 +2126,14 @@ void git_index_conflict_iterator_free(git_index_conflict_iterator *iterator)
size_t git_index_name_entrycount(git_index *index)
{
- assert(index);
+ GIT_ASSERT_ARG(index);
return index->names.length;
}
const git_index_name_entry *git_index_name_get_byindex(
git_index *index, size_t n)
{
- assert(index);
+ GIT_ASSERT_ARG_WITH_RETVAL(index, NULL);
git_vector_sort(&index->names);
return git_vector_get(&index->names, n);
@@ -2125,7 +2154,7 @@ int git_index_name_add(git_index *index,
{
git_index_name_entry *conflict_name;
- assert((ancestor && ours) || (ancestor && theirs) || (ours && theirs));
+ GIT_ASSERT_ARG((ancestor && ours) || (ancestor && theirs) || (ours && theirs));
conflict_name = git__calloc(1, sizeof(git_index_name_entry));
GIT_ERROR_CHECK_ALLOC(conflict_name);
@@ -2148,7 +2177,7 @@ int git_index_name_clear(git_index *index)
size_t i;
git_index_name_entry *conflict_name;
- assert(index);
+ GIT_ASSERT_ARG(index);
git_vector_foreach(&index->names, i, conflict_name)
index_name_entry_free(conflict_name);
@@ -2162,7 +2191,7 @@ int git_index_name_clear(git_index *index)
size_t git_index_reuc_entrycount(git_index *index)
{
- assert(index);
+ GIT_ASSERT_ARG(index);
return index->reuc.length;
}
@@ -2179,8 +2208,9 @@ static int index_reuc_insert(
{
int res;
- assert(index && reuc && reuc->path != NULL);
- assert(git_vector_is_sorted(&index->reuc));
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(reuc && reuc->path != NULL);
+ GIT_ASSERT(git_vector_is_sorted(&index->reuc));
res = git_vector_insert_sorted(&index->reuc, reuc, &index_reuc_on_dup);
index->dirty = 1;
@@ -2196,7 +2226,8 @@ int git_index_reuc_add(git_index *index, const char *path,
git_index_reuc_entry *reuc = NULL;
int error = 0;
- assert(index && path);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(path);
if ((error = index_entry_reuc_init(&reuc, path, ancestor_mode,
ancestor_oid, our_mode, our_oid, their_mode, their_oid)) < 0 ||
@@ -2215,12 +2246,14 @@ const git_index_reuc_entry *git_index_reuc_get_bypath(
git_index *index, const char *path)
{
size_t pos;
- assert(index && path);
+
+ GIT_ASSERT_ARG_WITH_RETVAL(index, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(path, NULL);
if (!index->reuc.length)
return NULL;
- assert(git_vector_is_sorted(&index->reuc));
+ GIT_ASSERT_WITH_RETVAL(git_vector_is_sorted(&index->reuc), NULL);
if (git_index_reuc_find(&pos, index, path) < 0)
return NULL;
@@ -2231,8 +2264,8 @@ const git_index_reuc_entry *git_index_reuc_get_bypath(
const git_index_reuc_entry *git_index_reuc_get_byindex(
git_index *index, size_t n)
{
- assert(index);
- assert(git_vector_is_sorted(&index->reuc));
+ GIT_ASSERT_ARG_WITH_RETVAL(index, NULL);
+ GIT_ASSERT_WITH_RETVAL(git_vector_is_sorted(&index->reuc), NULL);
return git_vector_get(&index->reuc, n);
}
@@ -2242,7 +2275,8 @@ int git_index_reuc_remove(git_index *index, size_t position)
int error;
git_index_reuc_entry *reuc;
- assert(git_vector_is_sorted(&index->reuc));
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT(git_vector_is_sorted(&index->reuc));
reuc = git_vector_get(&index->reuc, position);
error = git_vector_remove(&index->reuc, position);
@@ -2258,10 +2292,10 @@ int git_index_reuc_clear(git_index *index)
{
size_t i;
- assert(index);
+ GIT_ASSERT_ARG(index);
for (i = 0; i < index->reuc.length; ++i)
- index_entry_reuc_free(git__swap(index->reuc.contents[i], NULL));
+ index_entry_reuc_free(git_atomic_swap(index->reuc.contents[i], NULL));
git_vector_clear(&index->reuc);
@@ -2626,7 +2660,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
seek_forward(INDEX_HEADER_SIZE);
- assert(!index->entries.length);
+ GIT_ASSERT(!index->entries.length);
if ((error = index_map_resize(index->entries_map, header.entry_count, index->ignore_case)) < 0)
return error;
@@ -2781,23 +2815,26 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
ondisk.flags = htons(entry->flags);
if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) {
+ const size_t path_offset = offsetof(struct entry_long, path);
struct entry_long ondisk_ext;
memcpy(&ondisk_ext, &ondisk, sizeof(struct entry_short));
ondisk_ext.flags_extended = htons(entry->flags_extended &
GIT_INDEX_ENTRY_EXTENDED_FLAGS);
- memcpy(mem, &ondisk_ext, offsetof(struct entry_long, path));
- path = ((struct entry_long*)mem)->path;
- disk_size -= offsetof(struct entry_long, path);
+ memcpy(mem, &ondisk_ext, path_offset);
+ path = (char *)mem + path_offset;
+ disk_size -= path_offset;
} else {
- memcpy(mem, &ondisk, offsetof(struct entry_short, path));
- path = ((struct entry_short*)mem)->path;
- disk_size -= offsetof(struct entry_short, path);
+ const size_t path_offset = offsetof(struct entry_short, path);
+ memcpy(mem, &ondisk, path_offset);
+ path = (char *)mem + path_offset;
+ disk_size -= path_offset;
}
if (last) {
varint_len = git_encode_varint((unsigned char *) path,
disk_size, strlen(last) - same_len);
- assert(varint_len > 0);
+ GIT_ASSERT(varint_len > 0);
+
path += varint_len;
disk_size -= varint_len;
@@ -2805,14 +2842,14 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
* If using path compression, we are not allowed
* to have additional trailing NULs.
*/
- assert(disk_size == path_len + 1);
+ GIT_ASSERT(disk_size == path_len + 1);
} else {
/*
* If no path compression is used, we do have
* NULs as padding. As such, simply assert that
* we have enough space left to write the path.
*/
- assert(disk_size > path_len);
+ GIT_ASSERT(disk_size > path_len);
}
memcpy(path, path_start, path_len + 1);
@@ -2824,14 +2861,16 @@ static int write_entries(git_index *index, git_filebuf *file)
{
int error = 0;
size_t i;
- git_vector case_sorted, *entries;
+ git_vector case_sorted = GIT_VECTOR_INIT, *entries = NULL;
git_index_entry *entry;
const char *last = NULL;
/* If index->entries is sorted case-insensitively, then we need
* to re-sort it case-sensitively before writing */
if (index->ignore_case) {
- git_vector_dup(&case_sorted, &index->entries, git_index_entry_cmp);
+ if ((error = git_vector_dup(&case_sorted, &index->entries, git_index_entry_cmp)) < 0)
+ goto done;
+
git_vector_sort(&case_sorted);
entries = &case_sorted;
} else {
@@ -2848,9 +2887,8 @@ static int write_entries(git_index *index, git_filebuf *file)
last = entry->path;
}
- if (index->ignore_case)
- git_vector_free(&case_sorted);
-
+done:
+ git_vector_free(&case_sorted);
return error;
}
@@ -3008,7 +3046,8 @@ static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
bool is_extended;
uint32_t index_version_number;
- assert(index && file);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(file);
if (index->version <= INDEX_VERSION_NUMBER_EXT) {
is_extended = is_index_extended(index);
@@ -3159,7 +3198,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
/* well, this isn't good */;
} else {
git_vector_swap(&entries, &index->entries);
- entries_map = git__swap(index->entries_map, entries_map);
+ entries_map = git_atomic_swap(index->entries_map, entries_map);
}
index->dirty = 1;
@@ -3190,7 +3229,7 @@ static int git_index_read_iterator(
size_t i;
int error;
- assert((new_iterator->flags & GIT_ITERATOR_DONT_IGNORE_CASE));
+ GIT_ASSERT((new_iterator->flags & GIT_ITERATOR_DONT_IGNORE_CASE));
if ((error = git_vector_init(&new_entries, new_length_hint, index->entries._cmp)) < 0 ||
(error = git_vector_init(&remove_entries, index->entries.length, NULL)) < 0 ||
@@ -3293,7 +3332,7 @@ static int git_index_read_iterator(
goto done;
git_vector_swap(&new_entries, &index->entries);
- new_entries_map = git__swap(index->entries_map, new_entries_map);
+ new_entries_map = git_atomic_swap(index->entries_map, new_entries_map);
git_vector_foreach(&remove_entries, i, entry) {
if (index->tree)
@@ -3362,7 +3401,7 @@ int git_index_add_all(
git_pathspec ps;
bool no_fnmatch = (flags & GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH) != 0;
- assert(index);
+ GIT_ASSERT_ARG(index);
repo = INDEX_OWNER(index);
if ((error = git_repository__ensure_not_bare(repo, "index add all")) < 0)
@@ -3448,8 +3487,8 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr
payload,
};
- assert(index);
- assert(action == INDEX_ACTION_UPDATE || action == INDEX_ACTION_ADDALL);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(action == INDEX_ACTION_UPDATE || action == INDEX_ACTION_ADDALL);
repo = INDEX_OWNER(index);
@@ -3503,7 +3542,7 @@ static int index_apply_to_all(
const char *match;
git_buf path = GIT_BUF_INIT;
- assert(index);
+ GIT_ASSERT_ARG(index);
if ((error = git_pathspec__init(&ps, paths)) < 0)
return error;
@@ -3599,7 +3638,7 @@ int git_index_snapshot_new(git_vector *snap, git_index *index)
GIT_REFCOUNT_INC(index);
- git_atomic_inc(&index->readers);
+ git_atomic32_inc(&index->readers);
git_vector_sort(&index->entries);
error = git_vector_dup(snap, &index->entries, index->entries._cmp);
@@ -3614,7 +3653,7 @@ void git_index_snapshot_release(git_vector *snap, git_index *index)
{
git_vector_free(snap);
- git_atomic_dec(&index->readers);
+ git_atomic32_dec(&index->readers);
git_index_free(index);
}
diff --git a/src/index.h b/src/index.h
index 54402f563..a365867d0 100644
--- a/src/index.h
+++ b/src/index.h
@@ -33,7 +33,7 @@ struct git_index {
git_idxmap *entries_map;
git_vector deleted; /* deleted entries if readers > 0 */
- git_atomic readers; /* number of active iterators */
+ git_atomic32 readers; /* number of active iterators */
unsigned int on_disk:1;
unsigned int ignore_case:1;
diff --git a/src/indexer.c b/src/indexer.c
index 412dfc92d..ce7737500 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -24,8 +24,6 @@
#include "zstream.h"
#include "object.h"
-extern git_mutex git__mwindow_mutex;
-
size_t git_indexer__max_objects = UINT32_MAX;
#define UINT31_MAX (0x7FFFFFFF)
@@ -239,7 +237,8 @@ static int hash_object_stream(git_indexer*idx, git_packfile_stream *stream)
{
ssize_t read;
- assert(idx && stream);
+ GIT_ASSERT_ARG(idx);
+ GIT_ASSERT_ARG(stream);
do {
if ((read = git_packfile_stream_read(stream, idx->objbuf, sizeof(idx->objbuf))) < 0)
@@ -262,7 +261,7 @@ static int advance_delta_offset(git_indexer *idx, git_object_t type)
{
git_mwindow *w = NULL;
- assert(type == GIT_OBJECT_REF_DELTA || type == GIT_OBJECT_OFS_DELTA);
+ GIT_ASSERT_ARG(type == GIT_OBJECT_REF_DELTA || type == GIT_OBJECT_OFS_DELTA);
if (type == GIT_OBJECT_REF_DELTA) {
idx->off += GIT_OID_RAWSZ;
@@ -282,7 +281,7 @@ static int read_object_stream(git_indexer *idx, git_packfile_stream *stream)
{
ssize_t read;
- assert(stream);
+ GIT_ASSERT_ARG(stream);
do {
read = git_packfile_stream_read(stream, idx->objbuf, sizeof(idx->objbuf));
@@ -427,7 +426,10 @@ static int store_object(git_indexer *idx)
pentry = git__calloc(1, sizeof(struct git_pack_entry));
GIT_ERROR_CHECK_ALLOC(pentry);
- git_hash_final(&oid, &idx->hash_ctx);
+ if (git_hash_final(&oid, &idx->hash_ctx)) {
+ git__free(pentry);
+ goto on_error;
+ }
entry_size = idx->off - entry_start;
if (entry_start > UINT31_MAX) {
entry->offset = UINT32_MAX;
@@ -599,6 +601,48 @@ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
idx->inbuf_len += size - to_expell;
}
+#if defined(NO_MMAP) || !defined(GIT_WIN32)
+
+static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t size)
+{
+ size_t remaining_size = size;
+ const char *ptr = (const char *)data;
+
+ /* Handle data size larger that ssize_t */
+ while (remaining_size > 0) {
+ ssize_t nb;
+ HANDLE_EINTR(nb, p_pwrite(idx->pack->mwf.fd, (void *)ptr,
+ remaining_size, offset));
+ if (nb <= 0)
+ return -1;
+
+ ptr += nb;
+ offset += nb;
+ remaining_size -= nb;
+ }
+
+ return 0;
+}
+
+static int append_to_pack(git_indexer *idx, const void *data, size_t size)
+{
+ if (write_at(idx, data, idx->pack->mwf.size, size) < 0) {
+ git_error_set(GIT_ERROR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+#else
+
+/*
+ * Windows may keep different views to a networked file for the mmap- and
+ * open-accessed versions of a file, so any writes done through
+ * `write(2)`/`pwrite(2)` may not be reflected on the data that `mmap(2)` is
+ * able to read.
+ */
+
static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t size)
{
git_file fd = idx->pack->mwf.fd;
@@ -609,7 +653,8 @@ static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t s
git_map map;
int error;
- assert(data && size);
+ GIT_ASSERT_ARG(data);
+ GIT_ASSERT_ARG(size);
if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
return error;
@@ -635,7 +680,6 @@ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
size_t page_offset;
off64_t page_start;
off64_t current_size = idx->pack->mwf.size;
- int fd = idx->pack->mwf.fd;
int error;
if (!size)
@@ -652,8 +696,7 @@ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
page_offset = new_size % mmap_alignment;
page_start = new_size - page_offset;
- if (p_lseek(fd, page_start + mmap_alignment - 1, SEEK_SET) < 0 ||
- p_write(idx->pack->mwf.fd, data, 1) < 0) {
+ if (p_pwrite(idx->pack->mwf.fd, data, 1, page_start + mmap_alignment - 1) < 0) {
git_error_set(GIT_ERROR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
return -1;
}
@@ -661,6 +704,8 @@ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
return write_at(idx, data, idx->pack->mwf.size, size);
}
+#endif
+
static int read_stream_object(git_indexer *idx, git_indexer_progress *stats)
{
git_packfile_stream *stream = &idx->stream;
@@ -674,7 +719,7 @@ static int read_stream_object(git_indexer *idx, git_indexer_progress *stats)
return GIT_EBUFS;
if (!idx->have_stream) {
- error = git_packfile_unpack_header(&entry_size, &type, &idx->pack->mwf, &w, &idx->off);
+ error = git_packfile_unpack_header(&entry_size, &type, idx->pack, &w, &idx->off);
if (error == GIT_EBUFS) {
idx->off = entry_start;
return error;
@@ -756,7 +801,9 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_inde
struct git_pack_header *hdr = &idx->hdr;
git_mwindow_file *mwf = &idx->pack->mwf;
- assert(idx && data && stats);
+ GIT_ASSERT_ARG(idx);
+ GIT_ASSERT_ARG(data);
+ GIT_ASSERT_ARG(stats);
if ((error = append_to_pack(idx, data, size)) < 0)
return error;
@@ -810,7 +857,8 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_inde
/* Now that we have data in the pack, let's try to parse it */
/* As the file grows any windows we try to use will be out of date */
- git_mwindow_free_all(mwf);
+ if ((error = git_mwindow_free_all(mwf)) < 0)
+ goto on_error;
while (stats->indexed_objects < idx->nr_objects) {
if ((error = read_stream_object(idx, stats)) != 0) {
@@ -854,16 +902,16 @@ static int index_path(git_buf *path, git_indexer *idx, const char *suffix)
* Rewind the packfile by the trailer, as we might need to fix the
* packfile by injecting objects at the tail and must overwrite it.
*/
-static void seek_back_trailer(git_indexer *idx)
+static int seek_back_trailer(git_indexer *idx)
{
idx->pack->mwf.size -= GIT_OID_RAWSZ;
- git_mwindow_free_all(&idx->pack->mwf);
+ return git_mwindow_free_all(&idx->pack->mwf);
}
static int inject_object(git_indexer *idx, git_oid *id)
{
- git_odb_object *obj;
- struct entry *entry;
+ git_odb_object *obj = NULL;
+ struct entry *entry = NULL;
struct git_pack_entry *pentry = NULL;
git_oid foo = {{0}};
unsigned char hdr[64];
@@ -873,12 +921,14 @@ static int inject_object(git_indexer *idx, git_oid *id)
size_t len, hdr_len;
int error;
- seek_back_trailer(idx);
+ if ((error = seek_back_trailer(idx)) < 0)
+ goto cleanup;
+
entry_start = idx->pack->mwf.size;
- if (git_odb_read(&obj, idx->odb, id) < 0) {
+ if ((error = git_odb_read(&obj, idx->odb, id)) < 0) {
git_error_set(GIT_ERROR_INDEXER, "missing delta bases");
- return -1;
+ goto cleanup;
}
data = git_odb_object_data(obj);
@@ -890,8 +940,8 @@ static int inject_object(git_indexer *idx, git_oid *id)
entry->crc = crc32(0L, Z_NULL, 0);
/* Write out the object header */
- hdr_len = git_packfile__object_header(hdr, len, git_odb_object_type(obj));
- if ((error = append_to_pack(idx, hdr, hdr_len)) < 0)
+ if ((error = git_packfile__object_header(&hdr_len, hdr, len, git_odb_object_type(obj))) < 0 ||
+ (error = append_to_pack(idx, hdr, hdr_len)) < 0)
goto cleanup;
idx->pack->mwf.size += hdr_len;
@@ -947,7 +997,7 @@ static int fix_thin_pack(git_indexer *idx, git_indexer_progress *stats)
unsigned int left = 0;
git_oid base;
- assert(git_vector_length(&idx->deltas) > 0);
+ GIT_ASSERT(git_vector_length(&idx->deltas) > 0);
if (idx->odb == NULL) {
git_error_set(GIT_ERROR_INDEXER, "cannot fix a thin pack without an ODB");
@@ -960,7 +1010,7 @@ static int fix_thin_pack(git_indexer *idx, git_indexer_progress *stats)
continue;
curpos = delta->delta_off;
- error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos);
+ error = git_packfile_unpack_header(&size, &type, idx->pack, &w, &curpos);
if (error < 0)
return error;
@@ -1078,7 +1128,9 @@ static int update_header_and_rehash(git_indexer *idx, git_indexer_progress *stat
* hash_partially() keep the existing trailer out of the
* calculation.
*/
- git_mwindow_free_all(mwf);
+ if (git_mwindow_free_all(mwf) < 0)
+ return -1;
+
idx->inbuf_len = 0;
while (hashed < mwf->size) {
ptr = git_mwindow_open(mwf, &w, hashed, chunk, &left);
@@ -1250,13 +1302,22 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
if (git_filebuf_commit_at(&index_file, filename.ptr) < 0)
goto on_error;
- git_mwindow_free_all(&idx->pack->mwf);
+ if (git_mwindow_free_all(&idx->pack->mwf) < 0)
+ goto on_error;
- /* Truncate file to undo rounding up to next page_size in append_to_pack */
+#if !defined(NO_MMAP) && defined(GIT_WIN32)
+ /*
+ * Some non-Windows remote filesystems fail when truncating files if the
+ * file permissions change after opening the file (done by p_mkstemp).
+ *
+ * Truncation is only needed when mmap is used to undo rounding up to next
+ * page_size in append_to_pack.
+ */
if (p_ftruncate(idx->pack->mwf.fd, idx->pack->mwf.size) < 0) {
git_error_set(GIT_ERROR_OS, "failed to truncate pack file '%s'", idx->pack->pack_name);
return -1;
}
+#endif
if (idx->do_fsync && p_fsync(idx->pack->mwf.fd) < 0) {
git_error_set(GIT_ERROR_OS, "failed to fsync packfile");
@@ -1320,13 +1381,7 @@ void git_indexer_free(git_indexer *idx)
git_vector_free_deep(&idx->deltas);
- if (!git_mutex_lock(&git__mwindow_mutex)) {
- if (!idx->pack_committed)
- git_packfile_close(idx->pack, true);
-
- git_packfile_free(idx->pack);
- git_mutex_unlock(&git__mwindow_mutex);
- }
+ git_packfile_free(idx->pack, !idx->pack_committed);
iter = 0;
while (git_oidmap_iterate((void **) &value, idx->expected_oids, &iter, &key) == 0)
diff --git a/src/integer.h b/src/integer.h
index 067c0be1f..63277177b 100644
--- a/src/integer.h
+++ b/src/integer.h
@@ -43,10 +43,10 @@ GIT_INLINE(int) git__is_ulong(int64_t p)
}
/** @return true if p fits into the range of an int */
-GIT_INLINE(int) git__is_int(long long p)
+GIT_INLINE(int) git__is_int(int64_t p)
{
int r = (int)p;
- return p == (long long)r;
+ return p == (int64_t)r;
}
/* Use clang/gcc compiler intrinsics whenever possible */
@@ -77,6 +77,15 @@ GIT_INLINE(int) git__is_int(long long p)
# define git__sub_int_overflow(out, one, two) \
__builtin_ssub_overflow(one, two, out)
+# define git__add_int64_overflow(out, one, two) \
+ __builtin_add_overflow(one, two, out)
+
+/* clang on 32-bit systems produces an undefined reference to `__mulodi4`. */
+# if !defined(__clang__) || !defined(GIT_ARCH_32)
+# define git__multiply_int64_overflow(out, one, two) \
+ __builtin_mul_overflow(one, two, out)
+# endif
+
/* Use Microsoft's safe integer handling functions where available */
#elif defined(_MSC_VER)
@@ -87,11 +96,17 @@ GIT_INLINE(int) git__is_int(long long p)
(SizeTAdd(one, two, out) != S_OK)
# define git__multiply_sizet_overflow(out, one, two) \
(SizeTMult(one, two, out) != S_OK)
+
#define git__add_int_overflow(out, one, two) \
(IntAdd(one, two, out) != S_OK)
#define git__sub_int_overflow(out, one, two) \
(IntSub(one, two, out) != S_OK)
+#define git__add_int64_overflow(out, one, two) \
+ (LongLongAdd(one, two, out) != S_OK)
+#define git__multiply_int64_overflow(out, one, two) \
+ (LongLongMult(one, two, out) != S_OK)
+
#else
/**
@@ -136,6 +151,68 @@ GIT_INLINE(bool) git__sub_int_overflow(int *out, int one, int two)
return false;
}
+GIT_INLINE(bool) git__add_int64_overflow(int64_t *out, int64_t one, int64_t two)
+{
+ if ((two > 0 && one > (INT64_MAX - two)) ||
+ (two < 0 && one < (INT64_MIN - two)))
+ return true;
+ *out = one + two;
+ return false;
+}
+
+#endif
+
+/* If we could not provide an intrinsic implementation for this, provide a (slow) fallback. */
+#if !defined(git__multiply_int64_overflow)
+GIT_INLINE(bool) git__multiply_int64_overflow(int64_t *out, int64_t one, int64_t two)
+{
+ /*
+ * Detects whether `INT64_MAX < (one * two) || INT64_MIN > (one * two)`,
+ * without incurring in undefined behavior. That is done by performing the
+ * comparison with a division instead of a multiplication, which translates
+ * to `INT64_MAX / one < two || INT64_MIN / one > two`. Some caveats:
+ *
+ * - The comparison sign is inverted when both sides of the inequality are
+ * multiplied/divided by a negative number, so if `one < 0` the comparison
+ * needs to be flipped.
+ * - `INT64_MAX / -1` itself overflows (or traps), so that case should be
+ * avoided.
+ * - Since the overflow flag is defined as the discrepance between the result
+ * of performing the multiplication in a signed integer at twice the width
+ * of the operands, and the truncated+sign-extended version of that same
+ * result, there are four cases where the result is the opposite of what
+ * would be expected:
+ * * `INT64_MIN * -1` / `-1 * INT64_MIN`
+ * * `INT64_MIN * 1 / `1 * INT64_MIN`
+ */
+ if (one && two) {
+ if (one > 0 && two > 0) {
+ if (INT64_MAX / one < two)
+ return true;
+ } else if (one < 0 && two < 0) {
+ if ((one == -1 && two == INT64_MIN) ||
+ (two == -1 && one == INT64_MIN)) {
+ *out = INT64_MIN;
+ return false;
+ }
+ if (INT64_MAX / one > two)
+ return true;
+ } else if (one > 0 && two < 0) {
+ if ((one == 1 && two == INT64_MIN) ||
+ (INT64_MIN / one > two))
+ return true;
+ } else if (one == -1) {
+ if (INT64_MIN / two > one)
+ return true;
+ } else {
+ if ((one == INT64_MIN && two == 1) ||
+ (INT64_MIN / one < two))
+ return true;
+ }
+ }
+ *out = one * two;
+ return false;
+}
#endif
#endif
diff --git a/src/iterator.c b/src/iterator.c
index a393187c0..ce9f305ef 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -330,7 +330,7 @@ static iterator_pathlist_search_t iterator_pathlist_search(
break;
/* an exact match would have been matched by the bsearch above */
- assert(p[path_len]);
+ GIT_ASSERT_WITH_RETVAL(p[path_len], ITERATOR_PATHLIST_NONE);
/* is this a literal directory entry (eg `foo/`) or a file beneath */
if (p[path_len] == '/') {
@@ -678,14 +678,14 @@ done:
return error;
}
-static void tree_iterator_frame_pop(tree_iterator *iter)
+static int tree_iterator_frame_pop(tree_iterator *iter)
{
tree_iterator_frame *frame;
git_buf *buf = NULL;
git_tree *tree;
size_t i;
- assert(iter->frames.size);
+ GIT_ASSERT(iter->frames.size);
frame = git_array_pop(iter->frames);
@@ -705,6 +705,8 @@ static void tree_iterator_frame_pop(tree_iterator *iter)
git_vector_free(&frame->similar_trees);
git_buf_dispose(&frame->path);
+
+ return 0;
}
static int tree_iterator_current(
@@ -760,7 +762,9 @@ static int tree_iterator_advance(const git_index_entry **out, git_iterator *i)
/* no more entries in this frame. pop the frame out */
if (frame->next_idx == frame->entries.length) {
- tree_iterator_frame_pop(iter);
+ if ((error = tree_iterator_frame_pop(iter)) < 0)
+ break;
+
continue;
}
@@ -838,7 +842,7 @@ static int tree_iterator_advance_into(
const git_index_entry **out, git_iterator *i)
{
tree_iterator *iter = (tree_iterator *)i;
- tree_iterator_frame *frame;
+ tree_iterator_frame *frame;
tree_iterator_entry *prev_entry;
int error;
@@ -855,7 +859,7 @@ static int tree_iterator_advance_into(
* we will have pushed a new (empty) frame on to the stack for this
* new directory. since it's empty, its current_entry should be null.
*/
- assert(iterator__do_autoexpand(i) ^ (prev_entry != NULL));
+ GIT_ASSERT(iterator__do_autoexpand(i) ^ (prev_entry != NULL));
if (prev_entry) {
if (!git_tree_entry__is_tree(prev_entry->tree_entry))
@@ -973,7 +977,7 @@ int git_iterator_current_tree_entry(
tree_iterator_frame *frame;
tree_iterator_entry *entry;
- assert(i->type == GIT_ITERATOR_TREE);
+ GIT_ASSERT(i->type == GIT_ITERATOR_TREE);
iter = (tree_iterator *)i;
@@ -990,11 +994,11 @@ int git_iterator_current_parent_tree(
tree_iterator *iter;
tree_iterator_frame *frame;
- assert(i->type == GIT_ITERATOR_TREE);
+ GIT_ASSERT(i->type == GIT_ITERATOR_TREE);
iter = (tree_iterator *)i;
- assert(depth < iter->frames.size);
+ GIT_ASSERT(depth < iter->frames.size);
frame = &iter->frames.ptr[iter->frames.size-depth-1];
*parent_tree = frame->tree;
@@ -1274,7 +1278,8 @@ static int filesystem_iterator_entry_hash(
return git_repository_hashfile(&entry->id,
iter->base.repo, entry->path, GIT_OBJECT_BLOB, NULL);
- if (!(error = git_buf_joinpath(&fullpath, iter->root, entry->path)))
+ if (!(error = git_buf_joinpath(&fullpath, iter->root, entry->path)) &&
+ !(error = git_path_validate_workdir_buf(iter->base.repo, &fullpath)))
error = git_odb_hashfile(&entry->id, fullpath.ptr, GIT_OBJECT_BLOB);
git_buf_dispose(&fullpath);
@@ -1355,7 +1360,8 @@ static int filesystem_iterator_frame_push(
else
git_buf_puts(&root, iter->root);
- if (git_buf_oom(&root)) {
+ if (git_buf_oom(&root) ||
+ git_path_validate_workdir_buf(iter->base.repo, &root) < 0) {
error = -1;
goto done;
}
@@ -1385,10 +1391,11 @@ static int filesystem_iterator_frame_push(
iterator_pathlist_search_t pathlist_match = ITERATOR_PATHLIST_FULL;
bool dir_expected = false;
- if ((error = git_path_diriter_fullpath(&path, &path_len, &diriter)) < 0)
+ if ((error = git_path_diriter_fullpath(&path, &path_len, &diriter)) < 0 ||
+ (error = git_path_validate_workdir_with_len(iter->base.repo, path, path_len)) < 0)
goto done;
- assert(path_len > iter->root_len);
+ GIT_ASSERT(path_len > iter->root_len);
/* remove the prefix if requested */
path += iter->root_len;
@@ -1469,17 +1476,19 @@ done:
return error;
}
-GIT_INLINE(void) filesystem_iterator_frame_pop(filesystem_iterator *iter)
+GIT_INLINE(int) filesystem_iterator_frame_pop(filesystem_iterator *iter)
{
filesystem_iterator_frame *frame;
- assert(iter->frames.size);
+ GIT_ASSERT(iter->frames.size);
frame = git_array_pop(iter->frames);
filesystem_iterator_frame_pop_ignores(iter);
git_pool_clear(&frame->entry_pool);
git_vector_free(&frame->entries);
+
+ return 0;
}
static void filesystem_iterator_set_current(
@@ -1556,7 +1565,8 @@ static int filesystem_iterator_is_dir(
}
if ((error = git_buf_joinpath(&fullpath, iter->root, entry->path)) < 0 ||
- (error = p_stat(fullpath.ptr, &st)) < 0)
+ (error = git_path_validate_workdir_buf(iter->base.repo, &fullpath)) < 0 ||
+ (error = p_stat(fullpath.ptr, &st)) < 0)
goto done;
*is_dir = S_ISDIR(st.st_mode);
@@ -1646,7 +1656,7 @@ static int filesystem_iterator_advance_into(
* we will have pushed a new (empty) frame on to the stack for this
* new directory. since it's empty, its current_entry should be null.
*/
- assert(iterator__do_autoexpand(i) ^ (prev_entry != NULL));
+ GIT_ASSERT(iterator__do_autoexpand(i) ^ (prev_entry != NULL));
if (prev_entry) {
if (prev_entry->st.st_mode != GIT_FILEMODE_COMMIT &&
@@ -1762,12 +1772,13 @@ static int filesystem_iterator_advance_over(
*out = NULL;
*status = GIT_ITERATOR_STATUS_NORMAL;
- assert(iterator__has_been_accessed(i));
+ GIT_ASSERT(iterator__has_been_accessed(i));
current_frame = filesystem_iterator_current_frame(iter);
- assert(current_frame);
+ GIT_ASSERT(current_frame);
+
current_entry = filesystem_iterator_current_entry(current_frame);
- assert(current_entry);
+ GIT_ASSERT(current_entry);
if ((error = git_iterator_current(&entry, i)) < 0)
return error;
@@ -2065,8 +2076,8 @@ static bool index_iterator_create_pseudotree(
static int index_iterator_skip_pseudotree(index_iterator *iter)
{
- assert(iterator__has_been_accessed(&iter->base));
- assert(S_ISDIR(iter->entry->mode));
+ GIT_ASSERT(iterator__has_been_accessed(&iter->base));
+ GIT_ASSERT(S_ISDIR(iter->entry->mode));
while (true) {
const git_index_entry *next_entry = NULL;
@@ -2280,10 +2291,11 @@ int git_iterator_reset_range(
return i->cb->reset(i);
}
-void git_iterator_set_ignore_case(git_iterator *i, bool ignore_case)
+int git_iterator_set_ignore_case(git_iterator *i, bool ignore_case)
{
- assert(!iterator__has_been_accessed(i));
+ GIT_ASSERT(!iterator__has_been_accessed(i));
iterator_set_ignore_case(i, ignore_case);
+ return 0;
}
void git_iterator_free(git_iterator *iter)
diff --git a/src/iterator.h b/src/iterator.h
index ebd69362b..30465df2f 100644
--- a/src/iterator.h
+++ b/src/iterator.h
@@ -263,7 +263,7 @@ GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter)
return ((iter->flags & GIT_ITERATOR_IGNORE_CASE) != 0);
}
-extern void git_iterator_set_ignore_case(
+extern int git_iterator_set_ignore_case(
git_iterator *iter, bool ignore_case);
extern int git_iterator_current_tree_entry(
diff --git a/src/khash.h b/src/khash.h
index 40e2d1848..7adccdb00 100644
--- a/src/khash.h
+++ b/src/khash.h
@@ -131,17 +131,8 @@ int main() {
/* compiler specific configuration */
-#if UINT_MAX == 0xffffffffu
-typedef unsigned int khint32_t;
-#elif ULONG_MAX == 0xffffffffu
-typedef unsigned long khint32_t;
-#endif
-
-#if ULONG_MAX == ULLONG_MAX
-typedef unsigned long khint64_t;
-#else
-typedef unsigned long long khint64_t;
-#endif
+typedef uint32_t khint32_t;
+typedef uint64_t khint64_t;
#ifndef kh_inline
#ifdef _MSC_VER
diff --git a/src/settings.c b/src/libgit2.c
index f9f6b8497..cc793b458 100644
--- a/src/settings.c
+++ b/src/libgit2.c
@@ -5,29 +5,95 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
-
-#ifdef GIT_OPENSSL
-# include <openssl/err.h>
-#endif
-
-#ifdef GIT_MBEDTLS
-# include <mbedtls/error.h>
-#endif
+#include "libgit2.h"
#include <git2.h>
#include "alloc.h"
-#include "sysdir.h"
#include "cache.h"
-#include "global.h"
+#include "common.h"
+#include "filter.h"
+#include "hash.h"
+#include "index.h"
+#include "merge_driver.h"
+#include "pool.h"
+#include "mwindow.h"
#include "object.h"
#include "odb.h"
#include "refs.h"
-#include "index.h"
+#include "runtime.h"
+#include "sysdir.h"
+#include "thread.h"
+#include "threadstate.h"
+#include "git2/global.h"
+#include "streams/registry.h"
+#include "streams/mbedtls.h"
+#include "streams/openssl.h"
#include "transports/smart.h"
#include "transports/http.h"
-#include "streams/openssl.h"
-#include "streams/mbedtls.h"
+#include "transports/ssh.h"
+
+#ifdef GIT_WIN32
+# include "win32/w32_leakcheck.h"
+#endif
+
+/* Declarations for tuneable settings */
+extern size_t git_mwindow__window_size;
+extern size_t git_mwindow__mapped_limit;
+extern size_t git_mwindow__file_limit;
+extern size_t git_indexer__max_objects;
+extern bool git_disable_pack_keep_file_checks;
+extern int git_odb__packed_priority;
+extern int git_odb__loose_priority;
+
+char *git__user_agent;
+char *git__ssl_ciphers;
+
+static void libgit2_settings_global_shutdown(void)
+{
+ git__free(git__user_agent);
+ git__free(git__ssl_ciphers);
+ git_repository__free_extensions();
+}
+
+static int git_libgit2_settings_global_init(void)
+{
+ return git_runtime_shutdown_register(libgit2_settings_global_shutdown);
+}
+
+int git_libgit2_init(void)
+{
+ static git_runtime_init_fn init_fns[] = {
+#ifdef GIT_WIN32
+ git_win32_leakcheck_global_init,
+#endif
+ git_allocator_global_init,
+ git_threadstate_global_init,
+ git_threads_global_init,
+ git_hash_global_init,
+ git_sysdir_global_init,
+ git_filter_global_init,
+ git_merge_driver_global_init,
+ git_transport_ssh_global_init,
+ git_stream_registry_global_init,
+ git_openssl_stream_global_init,
+ git_mbedtls_stream_global_init,
+ git_mwindow_global_init,
+ git_pool_global_init,
+ git_libgit2_settings_global_init
+ };
+
+ return git_runtime_init(init_fns, ARRAY_SIZE(init_fns));
+}
+
+int git_libgit2_init_count(void)
+{
+ return git_runtime_init_count();
+}
+
+int git_libgit2_shutdown(void)
+{
+ return git_runtime_shutdown();
+}
int git_libgit2_version(int *major, int *minor, int *rev)
{
@@ -56,40 +122,30 @@ int git_libgit2_features(void)
;
}
-/* Declarations for tuneable settings */
-extern size_t git_mwindow__window_size;
-extern size_t git_mwindow__mapped_limit;
-extern size_t git_indexer__max_objects;
-extern bool git_disable_pack_keep_file_checks;
-
-static int config_level_to_sysdir(int config_level)
+static int config_level_to_sysdir(int *out, int config_level)
{
- int val = -1;
-
switch (config_level) {
case GIT_CONFIG_LEVEL_SYSTEM:
- val = GIT_SYSDIR_SYSTEM;
- break;
+ *out = GIT_SYSDIR_SYSTEM;
+ return 0;
case GIT_CONFIG_LEVEL_XDG:
- val = GIT_SYSDIR_XDG;
- break;
+ *out = GIT_SYSDIR_XDG;
+ return 0;
case GIT_CONFIG_LEVEL_GLOBAL:
- val = GIT_SYSDIR_GLOBAL;
- break;
+ *out = GIT_SYSDIR_GLOBAL;
+ return 0;
case GIT_CONFIG_LEVEL_PROGRAMDATA:
- val = GIT_SYSDIR_PROGRAMDATA;
- break;
+ *out = GIT_SYSDIR_PROGRAMDATA;
+ return 0;
default:
- git_error_set(
- GIT_ERROR_INVALID, "invalid config path selector %d", config_level);
+ break;
}
- return val;
+ git_error_set(
+ GIT_ERROR_INVALID, "invalid config path selector %d", config_level);
+ return -1;
}
-extern char *git__user_agent;
-extern char *git__ssl_ciphers;
-
const char *git_libgit2__user_agent(void)
{
return git__user_agent;
@@ -124,13 +180,24 @@ int git_libgit2_opts(int key, ...)
*(va_arg(ap, size_t *)) = git_mwindow__mapped_limit;
break;
+ case GIT_OPT_SET_MWINDOW_FILE_LIMIT:
+ git_mwindow__file_limit = va_arg(ap, size_t);
+ break;
+
+ case GIT_OPT_GET_MWINDOW_FILE_LIMIT:
+ *(va_arg(ap, size_t *)) = git_mwindow__file_limit;
+ break;
+
case GIT_OPT_GET_SEARCH_PATH:
- if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0) {
+ {
+ int sysdir = va_arg(ap, int);
git_buf *out = va_arg(ap, git_buf *);
const git_buf *tmp;
+ int level;
- git_buf_sanitize(out);
- if ((error = git_sysdir_get(&tmp, error)) < 0)
+ if ((error = config_level_to_sysdir(&level, sysdir)) < 0 ||
+ (error = git_buf_sanitize(out)) < 0 ||
+ (error = git_sysdir_get(&tmp, level)) < 0)
break;
error = git_buf_sets(out, tmp->ptr);
@@ -138,8 +205,12 @@ int git_libgit2_opts(int key, ...)
break;
case GIT_OPT_SET_SEARCH_PATH:
- if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0)
- error = git_sysdir_set(error, va_arg(ap, const char *));
+ {
+ int level;
+
+ if ((error = config_level_to_sysdir(&level, va_arg(ap, int))) >= 0)
+ error = git_sysdir_set(level, va_arg(ap, const char *));
+ }
break;
case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
@@ -168,8 +239,8 @@ int git_libgit2_opts(int key, ...)
git_buf *out = va_arg(ap, git_buf *);
const git_buf *tmp;
- git_buf_sanitize(out);
- if ((error = git_sysdir_get(&tmp, GIT_SYSDIR_TEMPLATE)) < 0)
+ if ((error = git_buf_sanitize(out)) < 0 ||
+ (error = git_sysdir_get(&tmp, GIT_SYSDIR_TEMPLATE)) < 0)
break;
error = git_buf_sets(out, tmp->ptr);
@@ -191,10 +262,7 @@ int git_libgit2_opts(int key, ...)
{
const char *file = va_arg(ap, const char *);
const char *path = va_arg(ap, const char *);
- if (file)
- error = git_mbedtls__set_cert_location(file, 0);
- if (error && path)
- error = git_mbedtls__set_cert_location(path, 1);
+ error = git_mbedtls__set_cert_location(file, path);
}
#else
git_error_set(GIT_ERROR_SSL, "TLS backend doesn't support certificate locations");
@@ -238,7 +306,8 @@ int git_libgit2_opts(int key, ...)
case GIT_OPT_GET_USER_AGENT:
{
git_buf *out = va_arg(ap, git_buf *);
- git_buf_sanitize(out);
+ if ((error = git_buf_sanitize(out)) < 0)
+ break;
error = git_buf_sets(out, git__user_agent);
}
break;
@@ -291,6 +360,36 @@ int git_libgit2_opts(int key, ...)
git_http__expect_continue = (va_arg(ap, int) != 0);
break;
+ case GIT_OPT_SET_ODB_PACKED_PRIORITY:
+ git_odb__packed_priority = va_arg(ap, int);
+ break;
+
+ case GIT_OPT_SET_ODB_LOOSE_PRIORITY:
+ git_odb__loose_priority = va_arg(ap, int);
+ break;
+
+ case GIT_OPT_SET_EXTENSIONS:
+ {
+ const char **extensions = va_arg(ap, const char **);
+ size_t len = va_arg(ap, size_t);
+ error = git_repository__set_extensions(extensions, len);
+ }
+ break;
+
+ case GIT_OPT_GET_EXTENSIONS:
+ {
+ git_strarray *out = va_arg(ap, git_strarray *);
+ char **extensions;
+ size_t len;
+
+ if ((error = git_repository__extensions(&extensions, &len)) < 0)
+ break;
+
+ out->strings = extensions;
+ out->count = len;
+ }
+ break;
+
default:
git_error_set(GIT_ERROR_INVALID, "invalid option key");
error = -1;
diff --git a/src/libgit2.h b/src/libgit2.h
new file mode 100644
index 000000000..a898367ae
--- /dev/null
+++ b/src/libgit2.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_libgit2_h__
+#define INCLUDE_libgit2_h__
+
+extern int git_libgit2_init_count(void);
+
+extern const char *git_libgit2__user_agent(void);
+extern const char *git_libgit2__ssl_ciphers(void);
+
+#endif
diff --git a/src/mailmap.c b/src/mailmap.c
index 409cdbd3c..b69d55e2e 100644
--- a/src/mailmap.c
+++ b/src/mailmap.c
@@ -43,7 +43,8 @@ static int mailmap_entry_cmp(const void *a_raw, const void *b_raw)
const git_mailmap_entry *b = (const git_mailmap_entry *)b_raw;
int cmp;
- assert(a && b && a->replace_email && b->replace_email);
+ GIT_ASSERT_ARG(a && a->replace_email);
+ GIT_ASSERT_ARG(b && b->replace_email);
cmp = git__strcmp(a->replace_email, b->replace_email);
if (cmp)
@@ -185,7 +186,8 @@ static int mailmap_add_entry_unterminated(
git_mailmap_entry *entry = git__calloc(1, sizeof(git_mailmap_entry));
GIT_ERROR_CHECK_ALLOC(entry);
- assert(mm && replace_email && *replace_email);
+ GIT_ASSERT_ARG(mm);
+ GIT_ASSERT_ARG(replace_email && *replace_email);
if (real_name_size > 0) {
entry->real_name = git__substrdup(real_name, real_name_size);
@@ -290,7 +292,8 @@ static int mailmap_add_blob(
git_buf content = GIT_BUF_INIT;
int error;
- assert(mm && repo);
+ GIT_ASSERT_ARG(mm);
+ GIT_ASSERT_ARG(repo);
error = git_revparse_single(&object, repo, rev);
if (error < 0)
@@ -327,6 +330,10 @@ static int mailmap_add_file_ondisk(
if (error < 0)
goto cleanup;
+ error = git_path_validate_workdir_buf(repo, &fullpath);
+ if (error < 0)
+ goto cleanup;
+
error = git_futils_readbuffer(&content, fullpath.ptr);
if (error < 0)
goto cleanup;
@@ -350,8 +357,6 @@ static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo)
const char *rev = NULL;
const char *path = NULL;
- assert(mm && repo);
-
/* If we're in a bare repo, default blob to 'HEAD:.mailmap' */
if (repo->is_bare)
rev = MM_BLOB_DEFAULT;
@@ -389,9 +394,14 @@ static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo)
int git_mailmap_from_repository(git_mailmap **out, git_repository *repo)
{
- int error = git_mailmap_new(out);
- if (error < 0)
+ int error;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+
+ if ((error = git_mailmap_new(out)) < 0)
return error;
+
mailmap_add_from_repository(*out, repo);
return 0;
}
@@ -408,7 +418,7 @@ const git_mailmap_entry *git_mailmap_entry_lookup(
git_mailmap_entry needle = { NULL };
needle.replace_email = (char *)email;
- assert(email);
+ GIT_ASSERT_ARG_WITH_RETVAL(email, NULL);
if (!mm)
return NULL;
@@ -431,7 +441,8 @@ const git_mailmap_entry *git_mailmap_entry_lookup(
if (git__strcmp(entry->replace_email, email))
break; /* it's a different email, so we're done looking */
- assert(entry->replace_name); /* should be specific */
+ /* should be specific */
+ GIT_ASSERT_WITH_RETVAL(entry->replace_name, NULL);
if (!name || !git__strcmp(entry->replace_name, name))
return entry;
}
@@ -447,7 +458,9 @@ int git_mailmap_resolve(
const char *name, const char *email)
{
const git_mailmap_entry *entry = NULL;
- assert(name && email);
+
+ GIT_ASSERT(name);
+ GIT_ASSERT(email);
*real_name = name;
*real_email = email;
diff --git a/src/map.h b/src/map.h
index 6328d8cf4..01931d199 100644
--- a/src/map.h
+++ b/src/map.h
@@ -36,9 +36,9 @@ typedef struct { /* memory mapped buffer */
} git_map;
#define GIT_MMAP_VALIDATE(out, len, prot, flags) do { \
- assert(out != NULL && len > 0); \
- assert((prot & GIT_PROT_WRITE) || (prot & GIT_PROT_READ)); \
- assert((flags & GIT_MAP_FIXED) == 0); } while (0)
+ GIT_ASSERT(out != NULL && len > 0); \
+ GIT_ASSERT((prot & GIT_PROT_WRITE) || (prot & GIT_PROT_READ)); \
+ GIT_ASSERT((flags & GIT_MAP_FIXED) == 0); } while (0)
extern int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset);
extern int p_munmap(git_map *map);
diff --git a/src/merge.c b/src/merge.c
index 2f6bf6fe7..d838e4ba9 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -112,7 +112,7 @@ static int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_r
if (commit == NULL)
goto on_error;
- if (git_merge__bases_many(&result, walk, commit, &list) < 0)
+ if (git_merge__bases_many(&result, walk, commit, &list, 0) < 0)
goto on_error;
if (!result) {
@@ -139,7 +139,9 @@ int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const
git_commit_list *result = NULL;
int error = 0;
- assert(out && repo && input_array);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(input_array);
if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
return error;
@@ -159,7 +161,9 @@ int git_merge_bases_many(git_oidarray *out, git_repository *repo, size_t length,
int error = 0;
git_array_oid_t array;
- assert(out && repo && input_array);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(input_array);
if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
return error;
@@ -193,7 +197,9 @@ int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, co
unsigned int i;
int error = -1;
- assert(out && repo && input_array);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(input_array);
if (length < 2) {
git_error_set(GIT_ERROR_INVALID, "at least two commits are required to find an ancestor");
@@ -237,7 +243,7 @@ static int merge_bases(git_commit_list **out, git_revwalk **walk_out, git_reposi
if (commit == NULL)
goto on_error;
- if (git_merge__bases_many(&result, walk, commit, &list) < 0)
+ if (git_merge__bases_many(&result, walk, commit, &list, 0) < 0)
goto on_error;
if (!result) {
@@ -372,7 +378,11 @@ static int clear_commit_marks(git_commit_list_node *commit, unsigned int mark)
}
static int paint_down_to_common(
- git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
+ git_commit_list **out,
+ git_revwalk *walk,
+ git_commit_list_node *one,
+ git_vector *twos,
+ uint32_t minimum_generation)
{
git_pqueue list;
git_commit_list *result = NULL;
@@ -381,7 +391,7 @@ static int paint_down_to_common(
int error;
unsigned int i;
- if (git_pqueue_init(&list, 0, twos->length * 2, git_commit_list_time_cmp) < 0)
+ if (git_pqueue_init(&list, 0, twos->length * 2, git_commit_list_generation_cmp) < 0)
return -1;
one->flags |= PARENT1;
@@ -393,7 +403,6 @@ static int paint_down_to_common(
return -1;
two->flags |= PARENT2;
-
if (git_pqueue_insert(&list, two) < 0)
return -1;
}
@@ -421,6 +430,8 @@ static int paint_down_to_common(
git_commit_list_node *p = commit->parents[i];
if ((p->flags & flags) == flags)
continue;
+ if (p->generation < minimum_generation)
+ continue;
if ((error = git_commit_list_parse(walk, p)) < 0)
return error;
@@ -436,7 +447,7 @@ static int paint_down_to_common(
return 0;
}
-static int remove_redundant(git_revwalk *walk, git_vector *commits)
+static int remove_redundant(git_revwalk *walk, git_vector *commits, uint32_t minimum_generation)
{
git_vector work = GIT_VECTOR_INIT;
unsigned char *redundant;
@@ -472,7 +483,7 @@ static int remove_redundant(git_revwalk *walk, git_vector *commits)
goto done;
}
- error = paint_down_to_common(&common, walk, commit, &work);
+ error = paint_down_to_common(&common, walk, commit, &work, minimum_generation);
if (error < 0)
goto done;
@@ -504,7 +515,12 @@ done:
return error;
}
-int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
+int git_merge__bases_many(
+ git_commit_list **out,
+ git_revwalk *walk,
+ git_commit_list_node *one,
+ git_vector *twos,
+ uint32_t minimum_generation)
{
int error;
unsigned int i;
@@ -526,7 +542,7 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l
if (git_commit_list_parse(walk, one) < 0)
return -1;
- error = paint_down_to_common(&result, walk, one, twos);
+ error = paint_down_to_common(&result, walk, one, twos, minimum_generation);
if (error < 0)
return error;
@@ -553,7 +569,7 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l
if ((error = clear_commit_marks(one, ALL_FLAGS)) < 0 ||
(error = clear_commit_marks_many(twos, ALL_FLAGS)) < 0 ||
- (error = remove_redundant(walk, &redundant)) < 0) {
+ (error = remove_redundant(walk, &redundant, minimum_generation)) < 0) {
git_vector_free(&redundant);
return error;
}
@@ -581,7 +597,8 @@ int git_repository_mergehead_foreach(
git_oid oid;
int error = 0;
- assert(repo && cb);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(cb);
if ((error = git_buf_joinpath(&merge_head_path, repo->gitdir,
GIT_MERGE_HEAD_FILE)) < 0)
@@ -650,7 +667,9 @@ static int merge_conflict_resolve_trivial(
git_index_entry const *result = NULL;
int error = 0;
- assert(resolved && diff_list && conflict);
+ GIT_ASSERT_ARG(resolved);
+ GIT_ASSERT_ARG(diff_list);
+ GIT_ASSERT_ARG(conflict);
*resolved = 0;
@@ -733,7 +752,9 @@ static int merge_conflict_resolve_one_removed(
int ours_changed, theirs_changed;
int error = 0;
- assert(resolved && diff_list && conflict);
+ GIT_ASSERT_ARG(resolved);
+ GIT_ASSERT_ARG(diff_list);
+ GIT_ASSERT_ARG(conflict);
*resolved = 0;
@@ -773,7 +794,9 @@ static int merge_conflict_resolve_one_renamed(
git_index_entry *merged;
int error = 0;
- assert(resolved && diff_list && conflict);
+ GIT_ASSERT_ARG(resolved);
+ GIT_ASSERT_ARG(diff_list);
+ GIT_ASSERT_ARG(conflict);
*resolved = 0;
@@ -793,8 +816,11 @@ static int merge_conflict_resolve_one_renamed(
conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
return 0;
- ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0);
- theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0);
+ ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0) ||
+ (conflict->ancestor_entry.mode != conflict->our_entry.mode);
+
+ theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0) ||
+ (conflict->ancestor_entry.mode != conflict->their_entry.mode);
/* if both are modified (and not to a common target) require a merge */
if (ours_changed && theirs_changed &&
@@ -917,7 +943,9 @@ static int merge_conflict_resolve_contents(
bool fallback = false;
int error;
- assert(resolved && diff_list && conflict);
+ GIT_ASSERT_ARG(resolved);
+ GIT_ASSERT_ARG(diff_list);
+ GIT_ASSERT_ARG(conflict);
*resolved = 0;
@@ -1126,7 +1154,7 @@ static void deletes_by_oid_free(git_oidmap *map) {
git_oidmap_free(map);
}
-static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx)
+static int deletes_by_oid_enqueue(git_oidmap *map, git_pool *pool, const git_oid *id, size_t idx)
{
deletes_by_oid_queue *queue;
size_t *array_entry;
@@ -1517,9 +1545,11 @@ int git_merge_diff_list__find_renames(
size_t src_count, tgt_count, i;
int error = 0;
- assert(diff_list && opts);
+ GIT_ASSERT_ARG(diff_list);
+ GIT_ASSERT_ARG(opts);
- if ((opts->flags & GIT_MERGE_FIND_RENAMES) == 0)
+ if ((opts->flags & GIT_MERGE_FIND_RENAMES) == 0 ||
+ !diff_list->conflicts.length)
return 0;
similarity_ours = git__calloc(diff_list->conflicts.length,
@@ -1843,7 +1873,8 @@ static int merge_normalize_opts(
git_config_entry *entry = NULL;
int error = 0;
- assert(repo && opts);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(opts);
if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
return error;
@@ -2070,7 +2101,8 @@ int git_merge__iterators(
size_t i;
int error = 0;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
*out = NULL;
@@ -2154,7 +2186,8 @@ int git_merge_trees(
git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
int error;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
/* if one side is treesame to the ancestor, take the other side */
if (ancestor_tree && merge_opts && (merge_opts->flags & GIT_MERGE_SKIP_REUC)) {
@@ -2258,8 +2291,11 @@ static int create_virtual_base(
result->type = GIT_ANNOTATED_COMMIT_VIRTUAL;
result->index = index;
- insert_head_ids(&result->parents, one);
- insert_head_ids(&result->parents, two);
+ if (insert_head_ids(&result->parents, one) < 0 ||
+ insert_head_ids(&result->parents, two) < 0) {
+ git_annotated_commit_free(result);
+ return -1;
+ }
*out = result;
return 0;
@@ -2333,7 +2369,7 @@ done:
git_annotated_commit_free(other);
git_annotated_commit_free(new_base);
- git_oidarray_free(&bases);
+ git_oidarray_dispose(&bases);
git_array_clear(head_ids);
return error;
}
@@ -2441,7 +2477,8 @@ static int write_merge_head(
size_t i;
int error = 0;
- assert(repo && heads);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(heads);
if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) < 0)
@@ -2469,7 +2506,7 @@ static int write_merge_mode(git_repository *repo)
git_buf file_path = GIT_BUF_INIT;
int error = 0;
- assert(repo);
+ GIT_ASSERT_ARG(repo);
if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MODE_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) < 0)
@@ -2689,7 +2726,8 @@ static int write_merge_msg(
char sep = 0;
int error = 0;
- assert(repo && heads);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(heads);
entries = git__calloc(heads_len, sizeof(struct merge_msg_entry));
GIT_ERROR_CHECK_ALLOC(entries);
@@ -2800,7 +2838,9 @@ int git_merge__setup(
{
int error = 0;
- assert (repo && our_head && heads);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(our_head);
+ GIT_ASSERT_ARG(heads);
if ((error = git_repository__set_orig_head(repo, git_annotated_commit_id(our_head))) == 0 &&
(error = write_merge_head(repo, heads, heads_len)) == 0 &&
@@ -2824,7 +2864,9 @@ static int merge_ancestor_head(
size_t i, alloc_len;
int error = 0;
- assert(repo && our_head && their_heads);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(our_head);
+ GIT_ASSERT_ARG(their_heads);
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, their_heads_len, 1);
oids = git__calloc(alloc_len, sizeof(git_oid));
@@ -3202,7 +3244,10 @@ int git_merge_analysis_for_ref(
int error = 0;
bool unborn;
- assert(analysis_out && preference_out && repo && their_heads && their_heads_len > 0);
+ GIT_ASSERT_ARG(analysis_out);
+ GIT_ASSERT_ARG(preference_out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(their_heads && their_heads_len > 0);
if (their_heads_len != 1) {
git_error_set(GIT_ERROR_MERGE, "can only merge a single branch");
@@ -3284,7 +3329,8 @@ int git_merge(
unsigned int checkout_strategy;
int error = 0;
- assert(repo && their_heads && their_heads_len > 0);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(their_heads && their_heads_len > 0);
if (their_heads_len != 1) {
git_error_set(GIT_ERROR_MERGE, "can only merge a single branch");
diff --git a/src/merge.h b/src/merge.h
index b0a7de2be..3e7f80c6e 100644
--- a/src/merge.h
+++ b/src/merge.h
@@ -129,7 +129,8 @@ int git_merge__bases_many(
git_commit_list **out,
git_revwalk *walk,
git_commit_list_node *one,
- git_vector *twos);
+ git_vector *twos,
+ uint32_t minimum_generation);
/*
* Three-way tree differencing
diff --git a/src/merge_driver.c b/src/merge_driver.c
index 666349b15..17c386a14 100644
--- a/src/merge_driver.c
+++ b/src/merge_driver.c
@@ -8,7 +8,7 @@
#include "merge_driver.h"
#include "vector.h"
-#include "global.h"
+#include "runtime.h"
#include "merge.h"
#include "git2/merge.h"
#include "git2/sys/merge.h"
@@ -32,33 +32,38 @@ static struct merge_driver_registry merge_driver_registry;
static void git_merge_driver_global_shutdown(void);
-git_repository* git_merge_driver_source_repo(const git_merge_driver_source *src)
+git_repository *git_merge_driver_source_repo(
+ const git_merge_driver_source *src)
{
- assert(src);
+ GIT_ASSERT_ARG_WITH_RETVAL(src, NULL);
return src->repo;
}
-const git_index_entry* git_merge_driver_source_ancestor(const git_merge_driver_source *src)
+const git_index_entry *git_merge_driver_source_ancestor(
+ const git_merge_driver_source *src)
{
- assert(src);
+ GIT_ASSERT_ARG_WITH_RETVAL(src, NULL);
return src->ancestor;
}
-const git_index_entry* git_merge_driver_source_ours(const git_merge_driver_source *src)
+const git_index_entry *git_merge_driver_source_ours(
+ const git_merge_driver_source *src)
{
- assert(src);
+ GIT_ASSERT_ARG_WITH_RETVAL(src, NULL);
return src->ours;
}
-const git_index_entry* git_merge_driver_source_theirs(const git_merge_driver_source *src)
+const git_index_entry *git_merge_driver_source_theirs(
+ const git_merge_driver_source *src)
{
- assert(src);
+ GIT_ASSERT_ARG_WITH_RETVAL(src, NULL);
return src->theirs;
}
-const git_merge_file_options* git_merge_driver_source_file_options(const git_merge_driver_source *src)
+const git_merge_file_options *git_merge_driver_source_file_options(
+ const git_merge_driver_source *src)
{
- assert(src);
+ GIT_ASSERT_ARG_WITH_RETVAL(src, NULL);
return src->file_opts;
}
@@ -209,7 +214,7 @@ int git_merge_driver_global_init(void)
merge_driver_name__binary, &git_merge_driver__binary)) < 0)
goto done;
- git__on_shutdown(git_merge_driver_global_shutdown);
+ error = git_runtime_shutdown_register(git_merge_driver_global_shutdown);
done:
if (error < 0)
@@ -262,7 +267,8 @@ int git_merge_driver_register(const char *name, git_merge_driver *driver)
{
int error;
- assert(name && driver);
+ GIT_ASSERT_ARG(name);
+ GIT_ASSERT_ARG(driver);
if (git_rwlock_wrlock(&merge_driver_registry.lock) < 0) {
git_error_set(GIT_ERROR_OS, "failed to lock merge driver registry");
diff --git a/src/merge_file.c b/src/merge_file.c
index 755340fa9..bfa3ec52e 100644
--- a/src/merge_file.c
+++ b/src/merge_file.c
@@ -36,7 +36,10 @@ static int merge_file_input_from_index(
{
int error = 0;
- assert(input_out && odb_object_out && odb && entry);
+ GIT_ASSERT_ARG(input_out);
+ GIT_ASSERT_ARG(odb_object_out);
+ GIT_ASSERT_ARG(odb);
+ GIT_ASSERT_ARG(entry);
if ((error = git_odb_read(odb_object_out, odb, &entry->id)) < 0)
goto done;
@@ -241,7 +244,9 @@ int git_merge_file(
{
git_merge_file_input inputs[3] = { {0} };
- assert(out && ours && theirs);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(ours);
+ GIT_ASSERT_ARG(theirs);
memset(out, 0x0, sizeof(git_merge_file_result));
@@ -268,7 +273,10 @@ int git_merge_file_from_index(
git_odb_object *odb_object[3] = { 0 };
int error = 0;
- assert(out && repo && ours && theirs);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(ours);
+ GIT_ASSERT_ARG(theirs);
memset(out, 0x0, sizeof(git_merge_file_result));
diff --git a/src/message.c b/src/message.c
index 6c5a2379f..327b984fc 100644
--- a/src/message.c
+++ b/src/message.c
@@ -28,8 +28,10 @@ int git_message_prettify(git_buf *message_out, const char *message, int strip_co
int consecutive_empty_lines = 0;
size_t i, line_length, rtrimmed_line_length;
char *next_newline;
+ int error;
- git_buf_sanitize(message_out);
+ if ((error = git_buf_sanitize(message_out)) < 0)
+ return error;
for (i = 0; i < strlen(message); i += line_length) {
next_newline = memchr(message + i, '\n', message_len - i);
diff --git a/src/midx.c b/src/midx.c
new file mode 100644
index 000000000..6a885eddc
--- /dev/null
+++ b/src/midx.c
@@ -0,0 +1,879 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "midx.h"
+
+#include "array.h"
+#include "buffer.h"
+#include "filebuf.h"
+#include "futils.h"
+#include "hash.h"
+#include "odb.h"
+#include "pack.h"
+#include "path.h"
+#include "repository.h"
+
+#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
+#define MIDX_VERSION 1
+#define MIDX_OBJECT_ID_VERSION 1
+struct git_midx_header {
+ uint32_t signature;
+ uint8_t version;
+ uint8_t object_id_version;
+ uint8_t chunks;
+ uint8_t base_midx_files;
+ uint32_t packfiles;
+};
+
+#define MIDX_PACKFILE_NAMES_ID 0x504e414d /* "PNAM" */
+#define MIDX_OID_FANOUT_ID 0x4f494446 /* "OIDF" */
+#define MIDX_OID_LOOKUP_ID 0x4f49444c /* "OIDL" */
+#define MIDX_OBJECT_OFFSETS_ID 0x4f4f4646 /* "OOFF" */
+#define MIDX_OBJECT_LARGE_OFFSETS_ID 0x4c4f4646 /* "LOFF" */
+
+struct git_midx_chunk {
+ off64_t offset;
+ size_t length;
+};
+
+typedef int (*midx_write_cb)(const char *buf, size_t size, void *cb_data);
+
+static int midx_error(const char *message)
+{
+ git_error_set(GIT_ERROR_ODB, "invalid multi-pack-index file - %s", message);
+ return -1;
+}
+
+static int midx_parse_packfile_names(
+ git_midx_file *idx,
+ const unsigned char *data,
+ uint32_t packfiles,
+ struct git_midx_chunk *chunk)
+{
+ int error;
+ uint32_t i;
+ char *packfile_name = (char *)(data + chunk->offset);
+ size_t chunk_size = chunk->length, len;
+ if (chunk->offset == 0)
+ return midx_error("missing Packfile Names chunk");
+ if (chunk->length == 0)
+ return midx_error("empty Packfile Names chunk");
+ if ((error = git_vector_init(&idx->packfile_names, packfiles, git__strcmp_cb)) < 0)
+ return error;
+ for (i = 0; i < packfiles; ++i) {
+ len = p_strnlen(packfile_name, chunk_size);
+ if (len == 0)
+ return midx_error("empty packfile name");
+ if (len + 1 > chunk_size)
+ return midx_error("unterminated packfile name");
+ git_vector_insert(&idx->packfile_names, packfile_name);
+ if (i && strcmp(git_vector_get(&idx->packfile_names, i - 1), packfile_name) >= 0)
+ return midx_error("packfile names are not sorted");
+ if (strlen(packfile_name) <= strlen(".idx") || git__suffixcmp(packfile_name, ".idx") != 0)
+ return midx_error("non-.idx packfile name");
+ if (strchr(packfile_name, '/') != NULL || strchr(packfile_name, '\\') != NULL)
+ return midx_error("non-local packfile");
+ packfile_name += len + 1;
+ chunk_size -= len + 1;
+ }
+ return 0;
+}
+
+static int midx_parse_oid_fanout(
+ git_midx_file *idx,
+ const unsigned char *data,
+ struct git_midx_chunk *chunk_oid_fanout)
+{
+ uint32_t i, nr;
+ if (chunk_oid_fanout->offset == 0)
+ return midx_error("missing OID Fanout chunk");
+ if (chunk_oid_fanout->length == 0)
+ return midx_error("empty OID Fanout chunk");
+ if (chunk_oid_fanout->length != 256 * 4)
+ return midx_error("OID Fanout chunk has wrong length");
+
+ idx->oid_fanout = (const uint32_t *)(data + chunk_oid_fanout->offset);
+ nr = 0;
+ for (i = 0; i < 256; ++i) {
+ uint32_t n = ntohl(idx->oid_fanout[i]);
+ if (n < nr)
+ return midx_error("index is non-monotonic");
+ nr = n;
+ }
+ idx->num_objects = nr;
+ return 0;
+}
+
+static int midx_parse_oid_lookup(
+ git_midx_file *idx,
+ const unsigned char *data,
+ struct git_midx_chunk *chunk_oid_lookup)
+{
+ uint32_t i;
+ git_oid *oid, *prev_oid, zero_oid = {{0}};
+
+ if (chunk_oid_lookup->offset == 0)
+ return midx_error("missing OID Lookup chunk");
+ if (chunk_oid_lookup->length == 0)
+ return midx_error("empty OID Lookup chunk");
+ if (chunk_oid_lookup->length != idx->num_objects * GIT_OID_RAWSZ)
+ return midx_error("OID Lookup chunk has wrong length");
+
+ idx->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset);
+ prev_oid = &zero_oid;
+ for (i = 0; i < idx->num_objects; ++i, ++oid) {
+ if (git_oid_cmp(prev_oid, oid) >= 0)
+ return midx_error("OID Lookup index is non-monotonic");
+ prev_oid = oid;
+ }
+
+ return 0;
+}
+
+static int midx_parse_object_offsets(
+ git_midx_file *idx,
+ const unsigned char *data,
+ struct git_midx_chunk *chunk_object_offsets)
+{
+ if (chunk_object_offsets->offset == 0)
+ return midx_error("missing Object Offsets chunk");
+ if (chunk_object_offsets->length == 0)
+ return midx_error("empty Object Offsets chunk");
+ if (chunk_object_offsets->length != idx->num_objects * 8)
+ return midx_error("Object Offsets chunk has wrong length");
+
+ idx->object_offsets = data + chunk_object_offsets->offset;
+
+ return 0;
+}
+
+static int midx_parse_object_large_offsets(
+ git_midx_file *idx,
+ const unsigned char *data,
+ struct git_midx_chunk *chunk_object_large_offsets)
+{
+ if (chunk_object_large_offsets->length == 0)
+ return 0;
+ if (chunk_object_large_offsets->length % 8 != 0)
+ return midx_error("malformed Object Large Offsets chunk");
+
+ idx->object_large_offsets = data + chunk_object_large_offsets->offset;
+ idx->num_object_large_offsets = chunk_object_large_offsets->length / 8;
+
+ return 0;
+}
+
+int git_midx_parse(
+ git_midx_file *idx,
+ const unsigned char *data,
+ size_t size)
+{
+ struct git_midx_header *hdr;
+ const unsigned char *chunk_hdr;
+ struct git_midx_chunk *last_chunk;
+ uint32_t i;
+ off64_t last_chunk_offset, chunk_offset, trailer_offset;
+ git_oid idx_checksum = {{0}};
+ int error;
+ struct git_midx_chunk chunk_packfile_names = {0},
+ chunk_oid_fanout = {0},
+ chunk_oid_lookup = {0},
+ chunk_object_offsets = {0},
+ chunk_object_large_offsets = {0};
+
+ GIT_ASSERT_ARG(idx);
+
+ if (size < sizeof(struct git_midx_header) + GIT_OID_RAWSZ)
+ return midx_error("multi-pack index is too short");
+
+ hdr = ((struct git_midx_header *)data);
+
+ if (hdr->signature != htonl(MIDX_SIGNATURE) ||
+ hdr->version != MIDX_VERSION ||
+ hdr->object_id_version != MIDX_OBJECT_ID_VERSION) {
+ return midx_error("unsupported multi-pack index version");
+ }
+ if (hdr->chunks == 0)
+ return midx_error("no chunks in multi-pack index");
+
+ /*
+ * The very first chunk's offset should be after the header, all the chunk
+ * headers, and a special zero chunk.
+ */
+ last_chunk_offset =
+ sizeof(struct git_midx_header) +
+ (1 + hdr->chunks) * 12;
+ trailer_offset = size - GIT_OID_RAWSZ;
+ if (trailer_offset < last_chunk_offset)
+ return midx_error("wrong index size");
+ git_oid_cpy(&idx->checksum, (git_oid *)(data + trailer_offset));
+
+ if (git_hash_buf(&idx_checksum, data, (size_t)trailer_offset) < 0)
+ return midx_error("could not calculate signature");
+ if (!git_oid_equal(&idx_checksum, &idx->checksum))
+ return midx_error("index signature mismatch");
+
+ chunk_hdr = data + sizeof(struct git_midx_header);
+ last_chunk = NULL;
+ for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
+ chunk_offset = ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) << 32 |
+ ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 8))));
+ if (chunk_offset < last_chunk_offset)
+ return midx_error("chunks are non-monotonic");
+ if (chunk_offset >= trailer_offset)
+ return midx_error("chunks extend beyond the trailer");
+ if (last_chunk != NULL)
+ last_chunk->length = (size_t)(chunk_offset - last_chunk_offset);
+ last_chunk_offset = chunk_offset;
+
+ switch (ntohl(*((uint32_t *)(chunk_hdr + 0)))) {
+ case MIDX_PACKFILE_NAMES_ID:
+ chunk_packfile_names.offset = last_chunk_offset;
+ last_chunk = &chunk_packfile_names;
+ break;
+
+ case MIDX_OID_FANOUT_ID:
+ chunk_oid_fanout.offset = last_chunk_offset;
+ last_chunk = &chunk_oid_fanout;
+ break;
+
+ case MIDX_OID_LOOKUP_ID:
+ chunk_oid_lookup.offset = last_chunk_offset;
+ last_chunk = &chunk_oid_lookup;
+ break;
+
+ case MIDX_OBJECT_OFFSETS_ID:
+ chunk_object_offsets.offset = last_chunk_offset;
+ last_chunk = &chunk_object_offsets;
+ break;
+
+ case MIDX_OBJECT_LARGE_OFFSETS_ID:
+ chunk_object_large_offsets.offset = last_chunk_offset;
+ last_chunk = &chunk_object_large_offsets;
+ break;
+
+ default:
+ return midx_error("unrecognized chunk ID");
+ }
+ }
+ last_chunk->length = (size_t)(trailer_offset - last_chunk_offset);
+
+ error = midx_parse_packfile_names(
+ idx, data, ntohl(hdr->packfiles), &chunk_packfile_names);
+ if (error < 0)
+ return error;
+ error = midx_parse_oid_fanout(idx, data, &chunk_oid_fanout);
+ if (error < 0)
+ return error;
+ error = midx_parse_oid_lookup(idx, data, &chunk_oid_lookup);
+ if (error < 0)
+ return error;
+ error = midx_parse_object_offsets(idx, data, &chunk_object_offsets);
+ if (error < 0)
+ return error;
+ error = midx_parse_object_large_offsets(idx, data, &chunk_object_large_offsets);
+ if (error < 0)
+ return error;
+
+ return 0;
+}
+
+int git_midx_open(
+ git_midx_file **idx_out,
+ const char *path)
+{
+ git_midx_file *idx;
+ git_file fd = -1;
+ size_t idx_size;
+ struct stat st;
+ int error;
+
+ /* TODO: properly open the file without access time using O_NOATIME */
+ fd = git_futils_open_ro(path);
+ if (fd < 0)
+ return fd;
+
+ if (p_fstat(fd, &st) < 0) {
+ p_close(fd);
+ git_error_set(GIT_ERROR_ODB, "multi-pack-index file not found - '%s'", path);
+ return -1;
+ }
+
+ if (!S_ISREG(st.st_mode) || !git__is_sizet(st.st_size)) {
+ p_close(fd);
+ git_error_set(GIT_ERROR_ODB, "invalid pack index '%s'", path);
+ return -1;
+ }
+ idx_size = (size_t)st.st_size;
+
+ idx = git__calloc(1, sizeof(git_midx_file));
+ GIT_ERROR_CHECK_ALLOC(idx);
+
+ error = git_buf_sets(&idx->filename, path);
+ if (error < 0)
+ return error;
+
+ error = git_futils_mmap_ro(&idx->index_map, fd, 0, idx_size);
+ p_close(fd);
+ if (error < 0) {
+ git_midx_free(idx);
+ return error;
+ }
+
+ if ((error = git_midx_parse(idx, idx->index_map.data, idx_size)) < 0) {
+ git_midx_free(idx);
+ return error;
+ }
+
+ *idx_out = idx;
+ return 0;
+}
+
+bool git_midx_needs_refresh(
+ const git_midx_file *idx,
+ const char *path)
+{
+ git_file fd = -1;
+ struct stat st;
+ ssize_t bytes_read;
+ git_oid idx_checksum = {{0}};
+
+ /* TODO: properly open the file without access time using O_NOATIME */
+ fd = git_futils_open_ro(path);
+ if (fd < 0)
+ return true;
+
+ if (p_fstat(fd, &st) < 0) {
+ p_close(fd);
+ return true;
+ }
+
+ if (!S_ISREG(st.st_mode) ||
+ !git__is_sizet(st.st_size) ||
+ (size_t)st.st_size != idx->index_map.len) {
+ p_close(fd);
+ return true;
+ }
+
+ bytes_read = p_pread(fd, &idx_checksum, GIT_OID_RAWSZ, st.st_size - GIT_OID_RAWSZ);
+ p_close(fd);
+
+ if (bytes_read != GIT_OID_RAWSZ)
+ return true;
+
+ return !git_oid_equal(&idx_checksum, &idx->checksum);
+}
+
+int git_midx_entry_find(
+ git_midx_entry *e,
+ git_midx_file *idx,
+ const git_oid *short_oid,
+ size_t len)
+{
+ int pos, found = 0;
+ size_t pack_index;
+ uint32_t hi, lo;
+ const git_oid *current = NULL;
+ const unsigned char *object_offset;
+ off64_t offset;
+
+ GIT_ASSERT_ARG(idx);
+
+ hi = ntohl(idx->oid_fanout[(int)short_oid->id[0]]);
+ lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(idx->oid_fanout[(int)short_oid->id[0] - 1]));
+
+ pos = git_pack__lookup_sha1(idx->oid_lookup, GIT_OID_RAWSZ, lo, hi, short_oid->id);
+
+ if (pos >= 0) {
+ /* An object matching exactly the oid was found */
+ found = 1;
+ current = idx->oid_lookup + pos;
+ } else {
+ /* No object was found */
+ /* pos refers to the object with the "closest" oid to short_oid */
+ pos = -1 - pos;
+ if (pos < (int)idx->num_objects) {
+ current = idx->oid_lookup + pos;
+
+ if (!git_oid_ncmp(short_oid, current, len))
+ found = 1;
+ }
+ }
+
+ if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)idx->num_objects) {
+ /* Check for ambiguousity */
+ const git_oid *next = current + 1;
+
+ if (!git_oid_ncmp(short_oid, next, len)) {
+ found = 2;
+ }
+ }
+
+ if (!found)
+ return git_odb__error_notfound("failed to find offset for multi-pack index entry", short_oid, len);
+ if (found > 1)
+ return git_odb__error_ambiguous("found multiple offsets for multi-pack index entry");
+
+ object_offset = idx->object_offsets + pos * 8;
+ offset = ntohl(*((uint32_t *)(object_offset + 4)));
+ if (offset & 0x80000000) {
+ uint32_t object_large_offsets_pos = offset & 0x7fffffff;
+ const unsigned char *object_large_offsets_index = idx->object_large_offsets;
+
+ /* Make sure we're not being sent out of bounds */
+ if (object_large_offsets_pos >= idx->num_object_large_offsets)
+ return git_odb__error_notfound("invalid index into the object large offsets table", short_oid, len);
+
+ object_large_offsets_index += 8 * object_large_offsets_pos;
+
+ offset = (((uint64_t)ntohl(*((uint32_t *)(object_large_offsets_index + 0)))) << 32) |
+ ntohl(*((uint32_t *)(object_large_offsets_index + 4)));
+ }
+ pack_index = ntohl(*((uint32_t *)(object_offset + 0)));
+ if (pack_index >= git_vector_length(&idx->packfile_names))
+ return midx_error("invalid index into the packfile names table");
+ e->pack_index = pack_index;
+ e->offset = offset;
+ git_oid_cpy(&e->sha1, current);
+ return 0;
+}
+
+int git_midx_foreach_entry(
+ git_midx_file *idx,
+ git_odb_foreach_cb cb,
+ void *data)
+{
+ size_t i;
+ int error;
+
+ GIT_ASSERT_ARG(idx);
+
+ for (i = 0; i < idx->num_objects; ++i) {
+ if ((error = cb(&idx->oid_lookup[i], data)) != 0)
+ return git_error_set_after_callback(error);
+ }
+
+ return error;
+}
+
+int git_midx_close(git_midx_file *idx)
+{
+ GIT_ASSERT_ARG(idx);
+
+ if (idx->index_map.data)
+ git_futils_mmap_free(&idx->index_map);
+
+ git_vector_free(&idx->packfile_names);
+
+ return 0;
+}
+
+void git_midx_free(git_midx_file *idx)
+{
+ if (!idx)
+ return;
+
+ git_buf_dispose(&idx->filename);
+ git_midx_close(idx);
+ git__free(idx);
+}
+
+static int packfile__cmp(const void *a_, const void *b_)
+{
+ const struct git_pack_file *a = a_;
+ const struct git_pack_file *b = b_;
+
+ return strcmp(a->pack_name, b->pack_name);
+}
+
+int git_midx_writer_new(
+ git_midx_writer **out,
+ const char *pack_dir)
+{
+ git_midx_writer *w = git__calloc(1, sizeof(git_midx_writer));
+ GIT_ERROR_CHECK_ALLOC(w);
+
+ if (git_buf_sets(&w->pack_dir, pack_dir) < 0) {
+ git__free(w);
+ return -1;
+ }
+ git_path_squash_slashes(&w->pack_dir);
+
+ if (git_vector_init(&w->packs, 0, packfile__cmp) < 0) {
+ git_buf_dispose(&w->pack_dir);
+ git__free(w);
+ return -1;
+ }
+
+ *out = w;
+ return 0;
+}
+
+void git_midx_writer_free(git_midx_writer *w)
+{
+ struct git_pack_file *p;
+ size_t i;
+
+ if (!w)
+ return;
+
+ git_vector_foreach (&w->packs, i, p)
+ git_mwindow_put_pack(p);
+ git_vector_free(&w->packs);
+ git_buf_dispose(&w->pack_dir);
+ git__free(w);
+}
+
+int git_midx_writer_add(
+ git_midx_writer *w,
+ const char *idx_path)
+{
+ git_buf idx_path_buf = GIT_BUF_INIT;
+ int error;
+ struct git_pack_file *p;
+
+ error = git_path_prettify(&idx_path_buf, idx_path, git_buf_cstr(&w->pack_dir));
+ if (error < 0)
+ return error;
+
+ error = git_mwindow_get_pack(&p, git_buf_cstr(&idx_path_buf));
+ git_buf_dispose(&idx_path_buf);
+ if (error < 0)
+ return error;
+
+ error = git_vector_insert(&w->packs, p);
+ if (error < 0) {
+ git_mwindow_put_pack(p);
+ return error;
+ }
+
+ return 0;
+}
+
+typedef git_array_t(git_midx_entry) object_entry_array_t;
+
+struct object_entry_cb_state {
+ uint32_t pack_index;
+ object_entry_array_t *object_entries_array;
+};
+
+static int object_entry__cb(const git_oid *oid, off64_t offset, void *data)
+{
+ struct object_entry_cb_state *state = (struct object_entry_cb_state *)data;
+
+ git_midx_entry *entry = git_array_alloc(*state->object_entries_array);
+ GIT_ERROR_CHECK_ALLOC(entry);
+
+ git_oid_cpy(&entry->sha1, oid);
+ entry->offset = offset;
+ entry->pack_index = state->pack_index;
+
+ return 0;
+}
+
+static int object_entry__cmp(const void *a_, const void *b_)
+{
+ const git_midx_entry *a = (const git_midx_entry *)a_;
+ const git_midx_entry *b = (const git_midx_entry *)b_;
+
+ return git_oid_cmp(&a->sha1, &b->sha1);
+}
+
+static int write_offset(off64_t offset, midx_write_cb write_cb, void *cb_data)
+{
+ int error;
+ uint32_t word;
+
+ word = htonl((uint32_t)((offset >> 32) & 0xffffffffu));
+ error = write_cb((const char *)&word, sizeof(word), cb_data);
+ if (error < 0)
+ return error;
+ word = htonl((uint32_t)((offset >> 0) & 0xffffffffu));
+ error = write_cb((const char *)&word, sizeof(word), cb_data);
+ if (error < 0)
+ return error;
+
+ return 0;
+}
+
+static int write_chunk_header(int chunk_id, off64_t offset, midx_write_cb write_cb, void *cb_data)
+{
+ uint32_t word = htonl(chunk_id);
+ int error = write_cb((const char *)&word, sizeof(word), cb_data);
+ if (error < 0)
+ return error;
+ return write_offset(offset, write_cb, cb_data);
+
+ return 0;
+}
+
+static int midx_write_buf(const char *buf, size_t size, void *data)
+{
+ git_buf *b = (git_buf *)data;
+ return git_buf_put(b, buf, size);
+}
+
+struct midx_write_hash_context {
+ midx_write_cb write_cb;
+ void *cb_data;
+ git_hash_ctx *ctx;
+};
+
+static int midx_write_hash(const char *buf, size_t size, void *data)
+{
+ struct midx_write_hash_context *ctx = (struct midx_write_hash_context *)data;
+ int error;
+
+ error = git_hash_update(ctx->ctx, buf, size);
+ if (error < 0)
+ return error;
+
+ return ctx->write_cb(buf, size, ctx->cb_data);
+}
+
+static int midx_write(
+ git_midx_writer *w,
+ midx_write_cb write_cb,
+ void *cb_data)
+{
+ int error = 0;
+ size_t i;
+ struct git_pack_file *p;
+ struct git_midx_header hdr = {0};
+ uint32_t oid_fanout_count;
+ uint32_t object_large_offsets_count;
+ uint32_t oid_fanout[256];
+ off64_t offset;
+ git_buf packfile_names = GIT_BUF_INIT,
+ oid_lookup = GIT_BUF_INIT,
+ object_offsets = GIT_BUF_INIT,
+ object_large_offsets = GIT_BUF_INIT;
+ git_oid idx_checksum = {{0}};
+ git_midx_entry *entry;
+ object_entry_array_t object_entries_array = GIT_ARRAY_INIT;
+ git_vector object_entries = GIT_VECTOR_INIT;
+ git_hash_ctx ctx;
+ struct midx_write_hash_context hash_cb_data = {0};
+
+ hdr.signature = htonl(MIDX_SIGNATURE);
+ hdr.version = MIDX_VERSION;
+ hdr.object_id_version = MIDX_OBJECT_ID_VERSION;
+ hdr.base_midx_files = 0;
+
+ hash_cb_data.write_cb = write_cb;
+ hash_cb_data.cb_data = cb_data;
+ hash_cb_data.ctx = &ctx;
+
+ error = git_hash_ctx_init(&ctx);
+ if (error < 0)
+ return error;
+ cb_data = &hash_cb_data;
+ write_cb = midx_write_hash;
+
+ git_vector_sort(&w->packs);
+ git_vector_foreach (&w->packs, i, p) {
+ git_buf relative_index = GIT_BUF_INIT;
+ struct object_entry_cb_state state = {0};
+ size_t path_len;
+
+ state.pack_index = (uint32_t)i;
+ state.object_entries_array = &object_entries_array;
+
+ error = git_buf_sets(&relative_index, p->pack_name);
+ if (error < 0)
+ goto cleanup;
+ error = git_path_make_relative(&relative_index, git_buf_cstr(&w->pack_dir));
+ if (error < 0) {
+ git_buf_dispose(&relative_index);
+ goto cleanup;
+ }
+ path_len = git_buf_len(&relative_index);
+ if (path_len <= strlen(".pack") || git__suffixcmp(git_buf_cstr(&relative_index), ".pack") != 0) {
+ git_buf_dispose(&relative_index);
+ git_error_set(GIT_ERROR_INVALID, "invalid packfile name: '%s'", p->pack_name);
+ error = -1;
+ goto cleanup;
+ }
+ path_len -= strlen(".pack");
+
+ git_buf_put(&packfile_names, git_buf_cstr(&relative_index), path_len);
+ git_buf_puts(&packfile_names, ".idx");
+ git_buf_putc(&packfile_names, '\0');
+ git_buf_dispose(&relative_index);
+
+ error = git_pack_foreach_entry_offset(p, object_entry__cb, &state);
+ if (error < 0)
+ goto cleanup;
+ }
+
+ /* Sort the object entries. */
+ error = git_vector_init(&object_entries, git_array_size(object_entries_array), object_entry__cmp);
+ if (error < 0)
+ goto cleanup;
+ git_array_foreach (object_entries_array, i, entry) {
+ if ((error = git_vector_set(NULL, &object_entries, i, entry)) < 0)
+ goto cleanup;
+ }
+ git_vector_set_sorted(&object_entries, 0);
+ git_vector_sort(&object_entries);
+ git_vector_uniq(&object_entries, NULL);
+
+ /* Pad the packfile names so it is a multiple of four. */
+ while (git_buf_len(&packfile_names) & 3)
+ git_buf_putc(&packfile_names, '\0');
+
+ /* Fill the OID Fanout table. */
+ oid_fanout_count = 0;
+ for (i = 0; i < 256; i++) {
+ while (oid_fanout_count < git_vector_length(&object_entries) &&
+ ((const git_midx_entry *)git_vector_get(&object_entries, oid_fanout_count))->sha1.id[0] <= i)
+ ++oid_fanout_count;
+ oid_fanout[i] = htonl(oid_fanout_count);
+ }
+
+ /* Fill the OID Lookup table. */
+ git_vector_foreach (&object_entries, i, entry) {
+ error = git_buf_put(&oid_lookup, (const char *)&entry->sha1, sizeof(entry->sha1));
+ if (error < 0)
+ goto cleanup;
+ }
+
+ /* Fill the Object Offsets and Object Large Offsets tables. */
+ object_large_offsets_count = 0;
+ git_vector_foreach (&object_entries, i, entry) {
+ uint32_t word;
+
+ word = htonl((uint32_t)entry->pack_index);
+ error = git_buf_put(&object_offsets, (const char *)&word, sizeof(word));
+ if (error < 0)
+ goto cleanup;
+ if (entry->offset >= 0x80000000l) {
+ word = htonl(0x80000000u | object_large_offsets_count++);
+ if ((error = write_offset(entry->offset, midx_write_buf, &object_large_offsets)) < 0)
+ goto cleanup;
+ } else {
+ word = htonl((uint32_t)entry->offset & 0x7fffffffu);
+ }
+
+ error = git_buf_put(&object_offsets, (const char *)&word, sizeof(word));
+ if (error < 0)
+ goto cleanup;
+ }
+
+ /* Write the header. */
+ hdr.packfiles = htonl((uint32_t)git_vector_length(&w->packs));
+ hdr.chunks = 4;
+ if (git_buf_len(&object_large_offsets) > 0)
+ hdr.chunks++;
+ error = write_cb((const char *)&hdr, sizeof(hdr), cb_data);
+ if (error < 0)
+ goto cleanup;
+
+ /* Write the chunk headers. */
+ offset = sizeof(hdr) + (hdr.chunks + 1) * 12;
+ error = write_chunk_header(MIDX_PACKFILE_NAMES_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += git_buf_len(&packfile_names);
+ error = write_chunk_header(MIDX_OID_FANOUT_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += sizeof(oid_fanout);
+ error = write_chunk_header(MIDX_OID_LOOKUP_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += git_buf_len(&oid_lookup);
+ error = write_chunk_header(MIDX_OBJECT_OFFSETS_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += git_buf_len(&object_offsets);
+ if (git_buf_len(&object_large_offsets) > 0) {
+ error = write_chunk_header(MIDX_OBJECT_LARGE_OFFSETS_ID, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+ offset += git_buf_len(&object_large_offsets);
+ }
+ error = write_chunk_header(0, offset, write_cb, cb_data);
+ if (error < 0)
+ goto cleanup;
+
+ /* Write all the chunks. */
+ error = write_cb(git_buf_cstr(&packfile_names), git_buf_len(&packfile_names), cb_data);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb((const char *)oid_fanout, sizeof(oid_fanout), cb_data);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb(git_buf_cstr(&oid_lookup), git_buf_len(&oid_lookup), cb_data);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb(git_buf_cstr(&object_offsets), git_buf_len(&object_offsets), cb_data);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb(git_buf_cstr(&object_large_offsets), git_buf_len(&object_large_offsets), cb_data);
+ if (error < 0)
+ goto cleanup;
+
+ /* Finalize the checksum and write the trailer. */
+ error = git_hash_final(&idx_checksum, &ctx);
+ if (error < 0)
+ goto cleanup;
+ error = write_cb((const char *)&idx_checksum, sizeof(idx_checksum), cb_data);
+ if (error < 0)
+ goto cleanup;
+
+cleanup:
+ git_array_clear(object_entries_array);
+ git_vector_free(&object_entries);
+ git_buf_dispose(&packfile_names);
+ git_buf_dispose(&oid_lookup);
+ git_buf_dispose(&object_offsets);
+ git_buf_dispose(&object_large_offsets);
+ git_hash_ctx_cleanup(&ctx);
+ return error;
+}
+
+static int midx_write_filebuf(const char *buf, size_t size, void *data)
+{
+ git_filebuf *f = (git_filebuf *)data;
+ return git_filebuf_write(f, buf, size);
+}
+
+int git_midx_writer_commit(
+ git_midx_writer *w)
+{
+ int error;
+ int filebuf_flags = GIT_FILEBUF_DO_NOT_BUFFER;
+ git_buf midx_path = GIT_BUF_INIT;
+ git_filebuf output = GIT_FILEBUF_INIT;
+
+ error = git_buf_joinpath(&midx_path, git_buf_cstr(&w->pack_dir), "multi-pack-index");
+ if (error < 0)
+ return error;
+
+ if (git_repository__fsync_gitdir)
+ filebuf_flags |= GIT_FILEBUF_FSYNC;
+ error = git_filebuf_open(&output, git_buf_cstr(&midx_path), filebuf_flags, 0644);
+ git_buf_dispose(&midx_path);
+ if (error < 0)
+ return error;
+
+ error = midx_write(w, midx_write_filebuf, &output);
+ if (error < 0) {
+ git_filebuf_cleanup(&output);
+ return error;
+ }
+
+ return git_filebuf_commit(&output);
+}
+
+int git_midx_writer_dump(
+ git_buf *midx,
+ git_midx_writer *w)
+{
+ return midx_write(w, midx_write_buf, midx);
+}
diff --git a/src/midx.h b/src/midx.h
new file mode 100644
index 000000000..4ce17ce73
--- /dev/null
+++ b/src/midx.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#ifndef INCLUDE_midx_h__
+#define INCLUDE_midx_h__
+
+#include "common.h"
+
+#include <ctype.h>
+
+#include "git2/sys/midx.h"
+
+#include "map.h"
+#include "mwindow.h"
+#include "odb.h"
+
+/*
+ * A multi-pack-index file.
+ *
+ * This file contains a merged index for multiple independent .pack files. This
+ * can help speed up locating objects without requiring a garbage collection
+ * cycle to create a single .pack file.
+ *
+ * Support for this feature was added in git 2.21, and requires the
+ * `core.multiPackIndex` config option to be set.
+ */
+typedef struct git_midx_file {
+ git_map index_map;
+
+ /* The table of Packfile Names. */
+ git_vector packfile_names;
+
+ /* The OID Fanout table. */
+ const uint32_t *oid_fanout;
+ /* The total number of objects in the index. */
+ uint32_t num_objects;
+
+ /* The OID Lookup table. */
+ git_oid *oid_lookup;
+
+ /* The Object Offsets table. Each entry has two 4-byte fields with the pack index and the offset. */
+ const unsigned char *object_offsets;
+
+ /* The Object Large Offsets table. */
+ const unsigned char *object_large_offsets;
+ /* The number of entries in the Object Large Offsets table. Each entry has an 8-byte with an offset */
+ size_t num_object_large_offsets;
+
+ /* The trailer of the file. Contains the SHA1-checksum of the whole file. */
+ git_oid checksum;
+
+ /* something like ".git/objects/pack/multi-pack-index". */
+ git_buf filename;
+} git_midx_file;
+
+/*
+ * An entry in the multi-pack-index file. Similar in purpose to git_pack_entry.
+ */
+typedef struct git_midx_entry {
+ /* The index within idx->packfile_names where the packfile name can be found. */
+ size_t pack_index;
+ /* The offset within the .pack file where the requested object is found. */
+ off64_t offset;
+ /* The SHA-1 hash of the requested object. */
+ git_oid sha1;
+} git_midx_entry;
+
+/*
+ * A writer for `multi-pack-index` files.
+ */
+struct git_midx_writer {
+ /*
+ * The path of the directory where the .pack/.idx files are stored. The
+ * `multi-pack-index` file will be written to the same directory.
+ */
+ git_buf pack_dir;
+
+ /* The list of `git_pack_file`s. */
+ git_vector packs;
+};
+
+int git_midx_open(
+ git_midx_file **idx_out,
+ const char *path);
+bool git_midx_needs_refresh(
+ const git_midx_file *idx,
+ const char *path);
+int git_midx_entry_find(
+ git_midx_entry *e,
+ git_midx_file *idx,
+ const git_oid *short_oid,
+ size_t len);
+int git_midx_foreach_entry(
+ git_midx_file *idx,
+ git_odb_foreach_cb cb,
+ void *data);
+int git_midx_close(git_midx_file *idx);
+void git_midx_free(git_midx_file *idx);
+
+/* This is exposed for use in the fuzzers. */
+int git_midx_parse(
+ git_midx_file *idx,
+ const unsigned char *data,
+ size_t size);
+
+#endif
diff --git a/src/mwindow.c b/src/mwindow.c
index 262786a5f..da2dae2b9 100644
--- a/src/mwindow.c
+++ b/src/mwindow.c
@@ -10,7 +10,7 @@
#include "vector.h"
#include "futils.h"
#include "map.h"
-#include "global.h"
+#include "runtime.h"
#include "strmap.h"
#include "pack.h"
@@ -20,31 +20,45 @@
: 32 * 1024 * 1024)
#define DEFAULT_MAPPED_LIMIT \
- ((1024 * 1024) * (sizeof(void*) >= 8 ? 8192ULL : 256UL))
+ ((1024 * 1024) * (sizeof(void*) >= 8 ? UINT64_C(8192) : UINT64_C(256)))
+
+/* default is unlimited */
+#define DEFAULT_FILE_LIMIT 0
size_t git_mwindow__window_size = DEFAULT_WINDOW_SIZE;
size_t git_mwindow__mapped_limit = DEFAULT_MAPPED_LIMIT;
+size_t git_mwindow__file_limit = DEFAULT_FILE_LIMIT;
+
+/* Mutex to control access to `git_mwindow__mem_ctl` and `git__pack_cache`. */
+git_mutex git__mwindow_mutex;
-/* Whenever you want to read or modify this, grab git__mwindow_mutex */
-static git_mwindow_ctl mem_ctl;
+/* Whenever you want to read or modify this, grab `git__mwindow_mutex` */
+git_mwindow_ctl git_mwindow__mem_ctl;
/* Global list of mwindow files, to open packs once across repos */
git_strmap *git__pack_cache = NULL;
-static void git_mwindow_files_free(void)
+static void git_mwindow_global_shutdown(void)
{
git_strmap *tmp = git__pack_cache;
+ git_mutex_free(&git__mwindow_mutex);
+
git__pack_cache = NULL;
git_strmap_free(tmp);
}
int git_mwindow_global_init(void)
{
- assert(!git__pack_cache);
+ int error;
+
+ GIT_ASSERT(!git__pack_cache);
- git__on_shutdown(git_mwindow_files_free);
- return git_strmap_new(&git__pack_cache);
+ if ((error = git_mutex_init(&git__mwindow_mutex)) < 0 ||
+ (error = git_strmap_new(&git__pack_cache)) < 0)
+ return error;
+
+ return git_runtime_shutdown_register(git_mwindow_global_shutdown);
}
int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
@@ -65,7 +79,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
git__free(packname);
if (pack != NULL) {
- git_atomic_inc(&pack->refcount);
+ git_atomic32_inc(&pack->refcount);
git_mutex_unlock(&git__mwindow_mutex);
*out = pack;
return 0;
@@ -77,62 +91,51 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
return error;
}
- git_atomic_inc(&pack->refcount);
+ git_atomic32_inc(&pack->refcount);
error = git_strmap_set(git__pack_cache, pack->pack_name, pack);
git_mutex_unlock(&git__mwindow_mutex);
-
if (error < 0) {
- git_packfile_free(pack);
- return -1;
+ git_packfile_free(pack, false);
+ return error;
}
*out = pack;
return 0;
}
-void git_mwindow_put_pack(struct git_pack_file *pack)
+int git_mwindow_put_pack(struct git_pack_file *pack)
{
- int count;
+ int count, error;
+ struct git_pack_file *pack_to_delete = NULL;
- if (git_mutex_lock(&git__mwindow_mutex) < 0)
- return;
+ if ((error = git_mutex_lock(&git__mwindow_mutex)) < 0)
+ return error;
/* put before get would be a corrupted state */
- assert(git__pack_cache);
+ GIT_ASSERT(git__pack_cache);
/* if we cannot find it, the state is corrupted */
- assert(git_strmap_exists(git__pack_cache, pack->pack_name));
+ GIT_ASSERT(git_strmap_exists(git__pack_cache, pack->pack_name));
- count = git_atomic_dec(&pack->refcount);
+ count = git_atomic32_dec(&pack->refcount);
if (count == 0) {
git_strmap_delete(git__pack_cache, pack->pack_name);
- git_packfile_free(pack);
+ pack_to_delete = pack;
}
-
git_mutex_unlock(&git__mwindow_mutex);
- return;
-}
-
-void git_mwindow_free_all(git_mwindow_file *mwf)
-{
- if (git_mutex_lock(&git__mwindow_mutex)) {
- git_error_set(GIT_ERROR_THREAD, "unable to lock mwindow mutex");
- return;
- }
-
- git_mwindow_free_all_locked(mwf);
+ git_packfile_free(pack_to_delete, false);
- git_mutex_unlock(&git__mwindow_mutex);
+ return 0;
}
/*
* Free all the windows in a sequence, typically because we're done
- * with the file
+ * with the file. Needs to hold the git__mwindow_mutex.
*/
-void git_mwindow_free_all_locked(git_mwindow_file *mwf)
+static int git_mwindow_free_all_locked(git_mwindow_file *mwf)
{
- git_mwindow_ctl *ctl = &mem_ctl;
+ git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
size_t i;
/*
@@ -152,7 +155,7 @@ void git_mwindow_free_all_locked(git_mwindow_file *mwf)
while (mwf->windows) {
git_mwindow *w = mwf->windows;
- assert(w->inuse_cnt == 0);
+ GIT_ASSERT(w->inuse_cnt == 0);
ctl->mapped -= w->window_map.len;
ctl->open_windows--;
@@ -162,6 +165,24 @@ void git_mwindow_free_all_locked(git_mwindow_file *mwf)
mwf->windows = w->next;
git__free(w);
}
+
+ return 0;
+}
+
+int git_mwindow_free_all(git_mwindow_file *mwf)
+{
+ int error;
+
+ if (git_mutex_lock(&git__mwindow_mutex)) {
+ git_error_set(GIT_ERROR_THREAD, "unable to lock mwindow mutex");
+ return -1;
+ }
+
+ error = git_mwindow_free_all_locked(mwf);
+
+ git_mutex_unlock(&git__mwindow_mutex);
+
+ return error;
}
/*
@@ -174,92 +195,154 @@ int git_mwindow_contains(git_mwindow *win, off64_t offset)
&& offset <= (off64_t)(win_off + win->window_map.len);
}
+#define GIT_MWINDOW__LRU -1
+#define GIT_MWINDOW__MRU 1
+
/*
- * Find the least-recently-used window in a file
+ * Find the least- or most-recently-used window in a file that is not currently
+ * being used. The 'only_unused' flag controls whether the caller requires the
+ * file to only have unused windows. If '*out_window' is non-null, it is used as
+ * a starting point for the comparison.
+ *
+ * Returns whether such a window was found in the file.
*/
-static void git_mwindow_scan_lru(
- git_mwindow_file *mwf,
- git_mwindow **lru_w,
- git_mwindow **lru_l)
+static bool git_mwindow_scan_recently_used(
+ git_mwindow_file *mwf,
+ git_mwindow **out_window,
+ git_mwindow **out_last,
+ bool only_unused,
+ int comparison_sign)
{
- git_mwindow *w, *w_l;
-
- for (w_l = NULL, w = mwf->windows; w; w = w->next) {
- if (!w->inuse_cnt) {
- /*
- * If the current one is more recent than the last one,
- * store it in the output parameter. If lru_w is NULL,
- * it's the first loop, so store it as well.
- */
- if (!*lru_w || w->last_used < (*lru_w)->last_used) {
- *lru_w = w;
- *lru_l = w_l;
- }
+ git_mwindow *w, *w_last;
+ git_mwindow *lru_window = NULL, *lru_last = NULL;
+ bool found = false;
+
+ GIT_ASSERT_ARG(mwf);
+ GIT_ASSERT_ARG(out_window);
+
+ lru_window = *out_window;
+ if (out_last)
+ lru_last = *out_last;
+
+ for (w_last = NULL, w = mwf->windows; w; w_last = w, w = w->next) {
+ if (w->inuse_cnt) {
+ if (only_unused)
+ return false;
+ /* This window is currently being used. Skip it. */
+ continue;
+ }
+
+ /*
+ * If the current one is more (or less) recent than the last one,
+ * store it in the output parameter. If lru_window is NULL,
+ * it's the first loop, so store it as well.
+ */
+ if (!lru_window ||
+ (comparison_sign == GIT_MWINDOW__LRU && lru_window->last_used > w->last_used) ||
+ (comparison_sign == GIT_MWINDOW__MRU && lru_window->last_used < w->last_used)) {
+ lru_window = w;
+ lru_last = w_last;
+ found = true;
}
- w_l = w;
}
+
+ if (!found)
+ return false;
+
+ *out_window = lru_window;
+ if (out_last)
+ *out_last = lru_last;
+ return true;
}
/*
- * Close the least recently used window. You should check to see if
- * the file descriptors need closing from time to time. Called under
- * lock from new_window.
+ * Close the least recently used window (that is currently not being used) out
+ * of all the files. Called under lock from new_window_locked.
*/
-static int git_mwindow_close_lru(git_mwindow_file *mwf)
+static int git_mwindow_close_lru_window_locked(void)
{
- git_mwindow_ctl *ctl = &mem_ctl;
+ git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
+ git_mwindow_file *cur;
size_t i;
- git_mwindow *lru_w = NULL, *lru_l = NULL, **list = &mwf->windows;
+ git_mwindow *lru_window = NULL, *lru_last = NULL, **list = NULL;
- /* FIXME: Does this give us any advantage? */
- if(mwf->windows)
- git_mwindow_scan_lru(mwf, &lru_w, &lru_l);
-
- for (i = 0; i < ctl->windowfiles.length; ++i) {
- git_mwindow *last = lru_w;
- git_mwindow_file *cur = git_vector_get(&ctl->windowfiles, i);
- git_mwindow_scan_lru(cur, &lru_w, &lru_l);
- if (lru_w != last)
+ git_vector_foreach(&ctl->windowfiles, i, cur) {
+ if (git_mwindow_scan_recently_used(
+ cur, &lru_window, &lru_last, false, GIT_MWINDOW__LRU)) {
list = &cur->windows;
+ }
}
- if (!lru_w) {
+ if (!lru_window) {
git_error_set(GIT_ERROR_OS, "failed to close memory window; couldn't find LRU");
return -1;
}
- ctl->mapped -= lru_w->window_map.len;
- git_futils_mmap_free(&lru_w->window_map);
+ ctl->mapped -= lru_window->window_map.len;
+ git_futils_mmap_free(&lru_window->window_map);
- if (lru_l)
- lru_l->next = lru_w->next;
+ if (lru_last)
+ lru_last->next = lru_window->next;
else
- *list = lru_w->next;
+ *list = lru_window->next;
- git__free(lru_w);
+ git__free(lru_window);
ctl->open_windows--;
return 0;
}
+/*
+ * Finds the file that does not have any open windows AND whose
+ * most-recently-used window is the least-recently used one across all
+ * currently open files.
+ *
+ * Called under lock from new_window_locked.
+ */
+static int git_mwindow_find_lru_file_locked(git_mwindow_file **out)
+{
+ git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
+ git_mwindow_file *lru_file = NULL, *current_file = NULL;
+ git_mwindow *lru_window = NULL;
+ size_t i;
+
+ git_vector_foreach(&ctl->windowfiles, i, current_file) {
+ git_mwindow *mru_window = NULL;
+ if (!git_mwindow_scan_recently_used(
+ current_file, &mru_window, NULL, true, GIT_MWINDOW__MRU)) {
+ continue;
+ }
+ if (!lru_window || lru_window->last_used > mru_window->last_used) {
+ lru_window = mru_window;
+ lru_file = current_file;
+ }
+ }
+
+ if (!lru_file) {
+ git_error_set(GIT_ERROR_OS, "failed to close memory window file; couldn't find LRU");
+ return -1;
+ }
+
+ *out = lru_file;
+ return 0;
+}
+
/* This gets called under lock from git_mwindow_open */
-static git_mwindow *new_window(
- git_mwindow_file *mwf,
+static git_mwindow *new_window_locked(
git_file fd,
off64_t size,
off64_t offset)
{
- git_mwindow_ctl *ctl = &mem_ctl;
+ git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
size_t walign = git_mwindow__window_size / 2;
off64_t len;
git_mwindow *w;
- w = git__malloc(sizeof(*w));
+ w = git__calloc(1, sizeof(*w));
if (w == NULL)
return NULL;
- memset(w, 0x0, sizeof(*w));
w->offset = (offset / walign) * walign;
len = size - w->offset;
@@ -269,7 +352,7 @@ static git_mwindow *new_window(
ctl->mapped += (size_t)len;
while (git_mwindow__mapped_limit < ctl->mapped &&
- git_mwindow_close_lru(mwf) == 0) /* nop */;
+ git_mwindow_close_lru_window_locked() == 0) /* nop */;
/*
* We treat `mapped_limit` as a soft limit. If we can't find a
@@ -283,7 +366,7 @@ static git_mwindow *new_window(
* we're below our soft limits, so free up what we can and try again.
*/
- while (git_mwindow_close_lru(mwf) == 0)
+ while (git_mwindow_close_lru_window_locked() == 0)
/* nop */;
if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < 0) {
@@ -315,7 +398,7 @@ unsigned char *git_mwindow_open(
size_t extra,
unsigned int *left)
{
- git_mwindow_ctl *ctl = &mem_ctl;
+ git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
git_mwindow *w = *cursor;
if (git_mutex_lock(&git__mwindow_mutex)) {
@@ -339,7 +422,7 @@ unsigned char *git_mwindow_open(
* one.
*/
if (!w) {
- w = new_window(mwf, mwf->fd, mwf->size, offset);
+ w = new_window_locked(mwf->fd, mwf->size, offset);
if (w == NULL) {
git_mutex_unlock(&git__mwindow_mutex);
return NULL;
@@ -367,8 +450,11 @@ unsigned char *git_mwindow_open(
int git_mwindow_file_register(git_mwindow_file *mwf)
{
- git_mwindow_ctl *ctl = &mem_ctl;
- int ret;
+ git_vector closed_files = GIT_VECTOR_INIT;
+ git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
+ int error;
+ size_t i;
+ git_mwindow_file *closed_file = NULL;
if (git_mutex_lock(&git__mwindow_mutex)) {
git_error_set(GIT_ERROR_THREAD, "unable to lock mwindow mutex");
@@ -376,20 +462,53 @@ int git_mwindow_file_register(git_mwindow_file *mwf)
}
if (ctl->windowfiles.length == 0 &&
- git_vector_init(&ctl->windowfiles, 8, NULL) < 0) {
+ (error = git_vector_init(&ctl->windowfiles, 8, NULL)) < 0) {
git_mutex_unlock(&git__mwindow_mutex);
- return -1;
+ goto cleanup;
+ }
+
+ if (git_mwindow__file_limit) {
+ git_mwindow_file *lru_file;
+ while (git_mwindow__file_limit <= ctl->windowfiles.length &&
+ git_mwindow_find_lru_file_locked(&lru_file) == 0) {
+ if ((error = git_vector_insert(&closed_files, lru_file)) < 0) {
+ /*
+ * Exceeding the file limit seems preferrable to being open to
+ * data races that can end up corrupting the heap.
+ */
+ break;
+ }
+ git_mwindow_free_all_locked(lru_file);
+ }
}
- ret = git_vector_insert(&ctl->windowfiles, mwf);
+ error = git_vector_insert(&ctl->windowfiles, mwf);
git_mutex_unlock(&git__mwindow_mutex);
+ if (error < 0)
+ goto cleanup;
+
+ /*
+ * Once we have released the global windowfiles lock, we can close each
+ * individual file. Before doing so, acquire that file's lock to avoid
+ * closing a file that is currently being used.
+ */
+ git_vector_foreach(&closed_files, i, closed_file) {
+ error = git_mutex_lock(&closed_file->lock);
+ if (error < 0)
+ continue;
+ p_close(closed_file->fd);
+ closed_file->fd = -1;
+ git_mutex_unlock(&closed_file->lock);
+ }
- return ret;
+cleanup:
+ git_vector_free(&closed_files);
+ return error;
}
void git_mwindow_file_deregister(git_mwindow_file *mwf)
{
- git_mwindow_ctl *ctl = &mem_ctl;
+ git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
git_mwindow_file *cur;
size_t i;
diff --git a/src/mwindow.h b/src/mwindow.h
index 1a391b055..e3a03f019 100644
--- a/src/mwindow.h
+++ b/src/mwindow.h
@@ -22,6 +22,7 @@ typedef struct git_mwindow {
} git_mwindow;
typedef struct git_mwindow_file {
+ git_mutex lock; /* protects updates to fd */
git_mwindow *windows;
int fd;
off64_t size;
@@ -38,8 +39,7 @@ typedef struct git_mwindow_ctl {
} git_mwindow_ctl;
int git_mwindow_contains(git_mwindow *win, off64_t offset);
-void git_mwindow_free_all(git_mwindow_file *mwf); /* locks */
-void git_mwindow_free_all_locked(git_mwindow_file *mwf); /* run under lock */
+int git_mwindow_free_all(git_mwindow_file *mwf); /* locks */
unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, off64_t offset, size_t extra, unsigned int *left);
int git_mwindow_file_register(git_mwindow_file *mwf);
void git_mwindow_file_deregister(git_mwindow_file *mwf);
@@ -49,6 +49,6 @@ extern int git_mwindow_global_init(void);
struct git_pack_file; /* just declaration to avoid cyclical includes */
int git_mwindow_get_pack(struct git_pack_file **out, const char *path);
-void git_mwindow_put_pack(struct git_pack_file *pack);
+int git_mwindow_put_pack(struct git_pack_file *pack);
#endif
diff --git a/src/net.c b/src/net.c
index d42fce52d..361e40e7b 100644
--- a/src/net.c
+++ b/src/net.c
@@ -14,7 +14,7 @@
#include "posix.h"
#include "buffer.h"
#include "http_parser.h"
-#include "global.h"
+#include "runtime.h"
#define DEFAULT_PORT_HTTP "80"
#define DEFAULT_PORT_HTTPS "443"
@@ -35,6 +35,46 @@ static const char *default_port_for_scheme(const char *scheme)
return NULL;
}
+int git_net_url_dup(git_net_url *out, git_net_url *in)
+{
+ if (in->scheme) {
+ out->scheme = git__strdup(in->scheme);
+ GIT_ERROR_CHECK_ALLOC(out->scheme);
+ }
+
+ if (in->host) {
+ out->host = git__strdup(in->host);
+ GIT_ERROR_CHECK_ALLOC(out->host);
+ }
+
+ if (in->port) {
+ out->port = git__strdup(in->port);
+ GIT_ERROR_CHECK_ALLOC(out->port);
+ }
+
+ if (in->path) {
+ out->path = git__strdup(in->path);
+ GIT_ERROR_CHECK_ALLOC(out->path);
+ }
+
+ if (in->query) {
+ out->query = git__strdup(in->query);
+ GIT_ERROR_CHECK_ALLOC(out->query);
+ }
+
+ if (in->username) {
+ out->username = git__strdup(in->username);
+ GIT_ERROR_CHECK_ALLOC(out->username);
+ }
+
+ if (in->password) {
+ out->password = git__strdup(in->password);
+ GIT_ERROR_CHECK_ALLOC(out->password);
+ }
+
+ return 0;
+}
+
int git_net_url_parse(git_net_url *url, const char *given)
{
struct http_parser_url u = {0};
@@ -281,7 +321,8 @@ int git_net_url_apply_redirect(
git_net_url tmp = GIT_NET_URL_INIT;
int error = 0;
- assert(url && redirect_location);
+ GIT_ASSERT(url);
+ GIT_ASSERT(redirect_location);
if (redirect_location[0] == '/') {
git__free(url->path);
@@ -334,9 +375,19 @@ bool git_net_url_valid(git_net_url *url)
return (url->host && url->port && url->path);
}
-int git_net_url_is_default_port(git_net_url *url)
+bool git_net_url_is_default_port(git_net_url *url)
{
- return (strcmp(url->port, default_port_for_scheme(url->scheme)) == 0);
+ const char *default_port;
+
+ if ((default_port = default_port_for_scheme(url->scheme)) != NULL)
+ return (strcmp(url->port, default_port) == 0);
+ else
+ return false;
+}
+
+bool git_net_url_is_ipv6(git_net_url *url)
+{
+ return (strchr(url->host, ':') != NULL);
}
void git_net_url_swap(git_net_url *a, git_net_url *b)
@@ -350,6 +401,10 @@ void git_net_url_swap(git_net_url *a, git_net_url *b)
int git_net_url_fmt(git_buf *buf, git_net_url *url)
{
+ GIT_ASSERT_ARG(url);
+ GIT_ASSERT_ARG(url->scheme);
+ GIT_ASSERT_ARG(url->host);
+
git_buf_puts(buf, url->scheme);
git_buf_puts(buf, "://");
@@ -393,6 +448,80 @@ int git_net_url_fmt_path(git_buf *buf, git_net_url *url)
return git_buf_oom(buf) ? -1 : 0;
}
+static bool matches_pattern(
+ git_net_url *url,
+ const char *pattern,
+ size_t pattern_len)
+{
+ const char *domain, *port = NULL, *colon;
+ size_t host_len, domain_len, port_len = 0, wildcard = 0;
+
+ GIT_UNUSED(url);
+ GIT_UNUSED(pattern);
+
+ if (!pattern_len)
+ return false;
+ else if (pattern_len == 1 && pattern[0] == '*')
+ return true;
+ else if (pattern_len > 1 && pattern[0] == '*' && pattern[1] == '.')
+ wildcard = 2;
+ else if (pattern[0] == '.')
+ wildcard = 1;
+
+ domain = pattern + wildcard;
+ domain_len = pattern_len - wildcard;
+
+ if ((colon = memchr(domain, ':', domain_len)) != NULL) {
+ domain_len = colon - domain;
+ port = colon + 1;
+ port_len = pattern_len - wildcard - domain_len - 1;
+ }
+
+ /* A pattern's port *must* match if it's specified */
+ if (port_len && git__strlcmp(url->port, port, port_len) != 0)
+ return false;
+
+ /* No wildcard? Host must match exactly. */
+ if (!wildcard)
+ return !git__strlcmp(url->host, domain, domain_len);
+
+ /* Wildcard: ensure there's (at least) a suffix match */
+ if ((host_len = strlen(url->host)) < domain_len ||
+ memcmp(url->host + (host_len - domain_len), domain, domain_len))
+ return false;
+
+ /* The pattern is *.domain and the host is simply domain */
+ if (host_len == domain_len)
+ return true;
+
+ /* The pattern is *.domain and the host is foo.domain */
+ return (url->host[host_len - domain_len - 1] == '.');
+}
+
+bool git_net_url_matches_pattern(git_net_url *url, const char *pattern)
+{
+ return matches_pattern(url, pattern, strlen(pattern));
+}
+
+bool git_net_url_matches_pattern_list(
+ git_net_url *url,
+ const char *pattern_list)
+{
+ const char *pattern, *pattern_end, *sep;
+
+ for (pattern = pattern_list;
+ pattern && *pattern;
+ pattern = sep ? sep + 1 : NULL) {
+ sep = strchr(pattern, ',');
+ pattern_end = sep ? sep : strchr(pattern, '\0');
+
+ if (matches_pattern(url, pattern, (pattern_end - pattern)))
+ return true;
+ }
+
+ return false;
+}
+
void git_net_url_dispose(git_net_url *url)
{
if (url->username)
diff --git a/src/net.h b/src/net.h
index 7e72db13f..322d0bda9 100644
--- a/src/net.h
+++ b/src/net.h
@@ -21,6 +21,9 @@ typedef struct git_net_url {
#define GIT_NET_URL_INIT { NULL }
+/** Duplicate a URL */
+extern int git_net_url_dup(git_net_url *out, git_net_url *in);
+
/** Parses a string containing a URL into a structure. */
extern int git_net_url_parse(git_net_url *url, const char *str);
@@ -33,8 +36,11 @@ extern int git_net_url_joinpath(
/** Ensures that a URL is minimally valid (contains a host, port and path) */
extern bool git_net_url_valid(git_net_url *url);
-/** Returns nonzero if the URL is on the default port. */
-extern int git_net_url_is_default_port(git_net_url *url);
+/** Returns true if the URL is on the default port. */
+extern bool git_net_url_is_default_port(git_net_url *url);
+
+/** Returns true if the host portion of the URL is an ipv6 address. */
+extern bool git_net_url_is_ipv6(git_net_url *url);
/* Applies a redirect to the URL with a git-aware service suffix. */
extern int git_net_url_apply_redirect(
@@ -51,6 +57,14 @@ extern int git_net_url_fmt(git_buf *out, git_net_url *url);
/** Place the path and query string into the given buffer. */
extern int git_net_url_fmt_path(git_buf *buf, git_net_url *url);
+/** Determines if the url matches given pattern or pattern list */
+extern bool git_net_url_matches_pattern(
+ git_net_url *url,
+ const char *pattern);
+extern bool git_net_url_matches_pattern_list(
+ git_net_url *url,
+ const char *pattern_list);
+
/** Disposes the contents of the structure. */
extern void git_net_url_dispose(git_net_url *url);
diff --git a/src/netops.c b/src/netops.c
index 04ae824cc..a1ee2927c 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -13,7 +13,7 @@
#include "posix.h"
#include "buffer.h"
#include "http_parser.h"
-#include "global.h"
+#include "runtime.h"
int gitno_recv(gitno_buffer *buf)
{
@@ -61,18 +61,20 @@ void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data
}
/* Consume up to ptr and move the rest of the buffer to the beginning */
-void gitno_consume(gitno_buffer *buf, const char *ptr)
+int gitno_consume(gitno_buffer *buf, const char *ptr)
{
size_t consumed;
- assert(ptr - buf->data >= 0);
- assert(ptr - buf->data <= (int) buf->len);
+ GIT_ASSERT(ptr - buf->data >= 0);
+ GIT_ASSERT(ptr - buf->data <= (int) buf->len);
consumed = ptr - buf->data;
memmove(buf->data, ptr, buf->offset - consumed);
memset(buf->data + buf->offset, 0x0, buf->len - buf->offset);
buf->offset -= consumed;
+
+ return 0;
}
/* Consume const bytes and move the rest of the buffer to the beginning */
diff --git a/src/netops.h b/src/netops.h
index 52f1cccb6..7140b39bc 100644
--- a/src/netops.h
+++ b/src/netops.h
@@ -14,7 +14,7 @@
#include "net.h"
#ifdef GIT_OPENSSL
-# include <openssl/ssl.h>
+# include "streams/openssl.h"
#endif
typedef struct gitno_ssl {
@@ -62,7 +62,7 @@ void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data
void gitno_buffer_setup_callback(gitno_buffer *buf, char *data, size_t len, int (*recv)(gitno_buffer *buf), void *cb_data);
int gitno_recv(gitno_buffer *buf);
-void gitno_consume(gitno_buffer *buf, const char *ptr);
+int gitno_consume(gitno_buffer *buf, const char *ptr);
void gitno_consume_n(gitno_buffer *buf, size_t cons);
#endif
diff --git a/src/notes.c b/src/notes.c
index 68d2ae9ec..95db334fb 100644
--- a/src/notes.c
+++ b/src/notes.c
@@ -407,31 +407,33 @@ cleanup:
return error;
}
-static int note_get_default_ref(char **out, git_repository *repo)
+static int note_get_default_ref(git_buf *out, git_repository *repo)
{
git_config *cfg;
- int ret = git_repository_config__weakptr(&cfg, repo);
+ int error;
+
+ if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
+ return error;
- *out = (ret != 0) ? NULL : git_config__get_string_force(
- cfg, "core.notesref", GIT_NOTES_DEFAULT_REF);
+ error = git_config_get_string_buf(out, cfg, "core.notesref");
- return ret;
+ if (error == GIT_ENOTFOUND)
+ error = git_buf_puts(out, GIT_NOTES_DEFAULT_REF);
+
+ return error;
}
-static int normalize_namespace(char **out, git_repository *repo, const char *notes_ref)
+static int normalize_namespace(git_buf *out, git_repository *repo, const char *notes_ref)
{
- if (notes_ref) {
- *out = git__strdup(notes_ref);
- GIT_ERROR_CHECK_ALLOC(*out);
- return 0;
- }
+ if (notes_ref)
+ return git_buf_puts(out, notes_ref);
return note_get_default_ref(out, repo);
}
static int retrieve_note_commit(
git_commit **commit_out,
- char **notes_ref_out,
+ git_buf *notes_ref_out,
git_repository *repo,
const char *notes_ref)
{
@@ -441,7 +443,7 @@ static int retrieve_note_commit(
if ((error = normalize_namespace(notes_ref_out, repo, notes_ref)) < 0)
return error;
- if ((error = git_reference_name_to_id(&oid, repo, *notes_ref_out)) < 0)
+ if ((error = git_reference_name_to_id(&oid, repo, notes_ref_out->ptr)) < 0)
return error;
if (git_commit_lookup(commit_out, repo, &oid) < 0)
@@ -476,7 +478,7 @@ int git_note_read(git_note **out, git_repository *repo,
const char *notes_ref_in, const git_oid *oid)
{
int error;
- char *notes_ref = NULL;
+ git_buf notes_ref = GIT_BUF_INIT;
git_commit *commit = NULL;
error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
@@ -487,7 +489,7 @@ int git_note_read(git_note **out, git_repository *repo,
error = git_note_commit_read(out, repo, commit, oid);
cleanup:
- git__free(notes_ref);
+ git_buf_dispose(&notes_ref);
git_commit_free(commit);
return error;
}
@@ -534,7 +536,7 @@ int git_note_create(
int allow_note_overwrite)
{
int error;
- char *notes_ref = NULL;
+ git_buf notes_ref = GIT_BUF_INIT;
git_commit *existing_notes_commit = NULL;
git_reference *ref = NULL;
git_oid notes_blob_oid, notes_commit_oid;
@@ -553,14 +555,14 @@ int git_note_create(
if (error < 0)
goto cleanup;
- error = git_reference_create(&ref, repo, notes_ref,
+ error = git_reference_create(&ref, repo, notes_ref.ptr,
&notes_commit_oid, 1, NULL);
if (out != NULL)
git_oid_cpy(out, &notes_blob_oid);
cleanup:
- git__free(notes_ref);
+ git_buf_dispose(&notes_ref);
git_commit_free(existing_notes_commit);
git_reference_free(ref);
return error;
@@ -596,7 +598,7 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
const git_oid *oid)
{
int error;
- char *notes_ref_target = NULL;
+ git_buf notes_ref_target = GIT_BUF_INIT;
git_commit *existing_notes_commit = NULL;
git_oid new_notes_commit;
git_reference *notes_ref = NULL;
@@ -612,11 +614,11 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
if (error < 0)
goto cleanup;
- error = git_reference_create(&notes_ref, repo, notes_ref_target,
+ error = git_reference_create(&notes_ref, repo, notes_ref_target.ptr,
&new_notes_commit, 1, NULL);
cleanup:
- git__free(notes_ref_target);
+ git_buf_dispose(&notes_ref_target);
git_reference_free(notes_ref);
git_commit_free(existing_notes_commit);
return error;
@@ -624,41 +626,39 @@ cleanup:
int git_note_default_ref(git_buf *out, git_repository *repo)
{
- char *default_ref;
int error;
- assert(out && repo);
-
- git_buf_sanitize(out);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
- if ((error = note_get_default_ref(&default_ref, repo)) < 0)
- return error;
+ if ((error = git_buf_sanitize(out)) < 0 ||
+ (error = note_get_default_ref(out, repo)) < 0)
+ git_buf_dispose(out);
- git_buf_attach(out, default_ref, strlen(default_ref));
- return 0;
+ return error;
}
const git_signature *git_note_committer(const git_note *note)
{
- assert(note);
+ GIT_ASSERT_ARG_WITH_RETVAL(note, NULL);
return note->committer;
}
const git_signature *git_note_author(const git_note *note)
{
- assert(note);
+ GIT_ASSERT_ARG_WITH_RETVAL(note, NULL);
return note->author;
}
-const char * git_note_message(const git_note *note)
+const char *git_note_message(const git_note *note)
{
- assert(note);
+ GIT_ASSERT_ARG_WITH_RETVAL(note, NULL);
return note->message;
}
-const git_oid * git_note_id(const git_note *note)
+const git_oid *git_note_id(const git_note *note)
{
- assert(note);
+ GIT_ASSERT_ARG_WITH_RETVAL(note, NULL);
return &note->id;
}
@@ -674,7 +674,7 @@ void git_note_free(git_note *note)
}
static int process_entry_path(
- const char* entry_path,
+ const char *entry_path,
git_oid *annotated_object_id)
{
int error = 0;
@@ -780,7 +780,7 @@ int git_note_iterator_new(
{
int error;
git_commit *commit = NULL;
- char *notes_ref;
+ git_buf notes_ref = GIT_BUF_INIT;
error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
if (error < 0)
@@ -789,15 +789,15 @@ int git_note_iterator_new(
error = git_note_commit_iterator_new(it, commit);
cleanup:
- git__free(notes_ref);
+ git_buf_dispose(&notes_ref);
git_commit_free(commit);
return error;
}
int git_note_next(
- git_oid* note_id,
- git_oid* annotated_id,
+ git_oid *note_id,
+ git_oid *annotated_id,
git_note_iterator *it)
{
int error;
diff --git a/src/object.c b/src/object.c
index 1b47ab1a6..42e1e46bc 100644
--- a/src/object.c
+++ b/src/object.c
@@ -67,7 +67,7 @@ int git_object__from_raw(
size_t object_size;
int error;
- assert(object_out);
+ GIT_ASSERT_ARG(object_out);
*object_out = NULL;
/* Validate type match */
@@ -86,11 +86,12 @@ int git_object__from_raw(
GIT_ERROR_CHECK_ALLOC(object);
object->cached.flags = GIT_CACHE_STORE_PARSED;
object->cached.type = type;
- git_odb_hash(&object->cached.oid, data, size, type);
+ if ((error = git_odb_hash(&object->cached.oid, data, size, type)) < 0)
+ return error;
/* Parse raw object data */
def = &git_objects_table[type];
- assert(def->free && def->parse_raw);
+ GIT_ASSERT(def->free && def->parse_raw);
if ((error = def->parse_raw(object, data, size)) < 0) {
def->free(object);
@@ -114,7 +115,7 @@ int git_object__from_odb_object(
git_object_def *def;
git_object *object = NULL;
- assert(object_out);
+ GIT_ASSERT_ARG(object_out);
*object_out = NULL;
/* Validate type match */
@@ -140,7 +141,7 @@ int git_object__from_odb_object(
/* Parse raw object data */
def = &git_objects_table[odb_obj->cached.type];
- assert(def->free && def->parse);
+ GIT_ASSERT(def->free && def->parse);
if ((error = def->parse(object, odb_obj)) < 0)
def->free(object);
@@ -173,7 +174,9 @@ int git_object_lookup_prefix(
git_odb_object *odb_obj = NULL;
int error = 0;
- assert(repo && object_out && id);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(object_out);
+ GIT_ASSERT_ARG(id);
if (len < GIT_OID_MINPREFIXLEN) {
git_error_set(GIT_ERROR_OBJECT, "ambiguous lookup - OID prefix is too short");
@@ -210,7 +213,7 @@ int git_object_lookup_prefix(
} else if (cached->flags == GIT_CACHE_STORE_RAW) {
odb_obj = (git_odb_object *)cached;
} else {
- assert(!"Wrong caching type in the global object cache");
+ GIT_ASSERT(!"Wrong caching type in the global object cache");
}
} else {
/* Object was not found in the cache, let's explore the backends.
@@ -262,19 +265,19 @@ void git_object_free(git_object *object)
const git_oid *git_object_id(const git_object *obj)
{
- assert(obj);
+ GIT_ASSERT_ARG_WITH_RETVAL(obj, NULL);
return &obj->cached.oid;
}
git_object_t git_object_type(const git_object *obj)
{
- assert(obj);
+ GIT_ASSERT_ARG_WITH_RETVAL(obj, GIT_OBJECT_INVALID);
return obj->cached.type;
}
git_repository *git_object_owner(const git_object *obj)
{
- assert(obj);
+ GIT_ASSERT_ARG_WITH_RETVAL(obj, NULL);
return obj->repo;
}
@@ -395,9 +398,10 @@ int git_object_peel(
git_object *source, *deref = NULL;
int error;
- assert(object && peeled);
+ GIT_ASSERT_ARG(object);
+ GIT_ASSERT_ARG(peeled);
- assert(target_type == GIT_OBJECT_TAG ||
+ GIT_ASSERT_ARG(target_type == GIT_OBJECT_TAG ||
target_type == GIT_OBJECT_COMMIT ||
target_type == GIT_OBJECT_TREE ||
target_type == GIT_OBJECT_BLOB ||
@@ -460,7 +464,9 @@ int git_object_lookup_bypath(
git_tree *tree = NULL;
git_tree_entry *entry = NULL;
- assert(out && treeish && path);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(treeish);
+ GIT_ASSERT_ARG(path);
if ((error = git_object_peel((git_object**)&tree, treeish, GIT_OBJECT_TREE)) < 0 ||
(error = git_tree_entry_bypath(&entry, tree, path)) < 0)
@@ -492,9 +498,12 @@ int git_object_short_id(git_buf *out, const git_object *obj)
git_oid id = {{0}};
git_odb *odb;
- assert(out && obj);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(obj);
+
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
- git_buf_sanitize(out);
repo = git_object_owner(obj);
if ((error = git_repository__configmap_lookup(&len, repo, GIT_CONFIGMAP_ABBREV)) < 0)
diff --git a/src/odb.c b/src/odb.c
index 90565b75b..7834e5f15 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -23,14 +23,14 @@
#define GIT_ALTERNATES_FILE "info/alternates"
+#define GIT_ALTERNATES_MAX_DEPTH 5
+
/*
* We work under the assumption that most objects for long-running
* operations will be packed
*/
-#define GIT_LOOSE_PRIORITY 1
-#define GIT_PACKED_PRIORITY 2
-
-#define GIT_ALTERNATES_MAX_DEPTH 5
+int git_odb__loose_priority = GIT_ODB_DEFAULT_LOOSE_PRIORITY;
+int git_odb__packed_priority = GIT_ODB_DEFAULT_PACKED_PRIORITY;
bool git_odb__strict_hash_verification = true;
@@ -44,8 +44,8 @@ typedef struct
static git_cache *odb_cache(git_odb *odb)
{
- if (odb->rc.owner != NULL) {
- git_repository *owner = odb->rc.owner;
+ git_repository *owner = GIT_REFCOUNT_OWNER(odb);
+ if (owner != NULL) {
return &owner->objects;
}
@@ -114,7 +114,8 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj)
size_t hdrlen;
int error;
- assert(id && obj);
+ GIT_ASSERT_ARG(id);
+ GIT_ASSERT_ARG(obj);
if (!git_object_typeisloose(obj->type)) {
git_error_set(GIT_ERROR_INVALID, "invalid object type");
@@ -259,9 +260,7 @@ int git_odb__hashfd_filtered(
if (!(error = git_futils_readbuffer_fd(&raw, fd, size))) {
git_buf post = GIT_BUF_INIT;
- error = git_filter_list_apply_to_data(&post, fl, &raw);
-
- git_buf_dispose(&raw);
+ error = git_filter_list__convert_buf(&post, fl, &raw);
if (!error)
error = git_odb_hash(out, post.ptr, post.size, type);
@@ -298,14 +297,15 @@ int git_odb__hashlink(git_oid *out, const char *path)
GIT_ERROR_CHECK_ALLOC(link_data);
read_len = p_readlink(path, link_data, size);
- link_data[size] = '\0';
- if (read_len != size) {
+ if (read_len == -1) {
git_error_set(GIT_ERROR_OS, "failed to read symlink data for '%s'", path);
git__free(link_data);
return -1;
}
+ GIT_ASSERT(read_len <= size);
+ link_data[read_len] = '\0';
- result = git_odb_hash(out, link_data, size, GIT_OBJECT_BLOB);
+ result = git_odb_hash(out, link_data, read_len, GIT_OBJECT_BLOB);
git__free(link_data);
} else {
int fd = git_futils_open_ro(path);
@@ -346,7 +346,7 @@ int git_odb_hash(git_oid *id, const void *data, size_t len, git_object_t type)
{
git_rawobj raw;
- assert(id);
+ GIT_ASSERT_ARG(id);
raw.data = (void *)data;
raw.len = len;
@@ -376,7 +376,7 @@ static int fake_wstream__write(git_odb_stream *_stream, const char *data, size_t
{
fake_wstream *stream = (fake_wstream *)_stream;
- assert(stream->written + len <= stream->size);
+ GIT_ASSERT(stream->written + len <= stream->size);
memcpy(stream->buffer + stream->written, data, len);
stream->written += len;
@@ -449,12 +449,18 @@ int git_odb_new(git_odb **out)
git_odb *db = git__calloc(1, sizeof(*db));
GIT_ERROR_CHECK_ALLOC(db);
+ if (git_mutex_init(&db->lock) < 0) {
+ git__free(db);
+ return -1;
+ }
if (git_cache_init(&db->own_cache) < 0) {
+ git_mutex_free(&db->lock);
git__free(db);
return -1;
}
if (git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) {
git_cache_dispose(&db->own_cache);
+ git_mutex_free(&db->lock);
git__free(db);
return -1;
}
@@ -470,12 +476,13 @@ static int add_backend_internal(
{
backend_internal *internal;
- assert(odb && backend);
+ GIT_ASSERT_ARG(odb);
+ GIT_ASSERT_ARG(backend);
GIT_ERROR_CHECK_VERSION(backend, GIT_ODB_BACKEND_VERSION, "git_odb_backend");
/* Check if the backend is already owned by another ODB */
- assert(!backend->odb || backend->odb == odb);
+ GIT_ASSERT(!backend->odb || backend->odb == odb);
internal = git__malloc(sizeof(backend_internal));
GIT_ERROR_CHECK_ALLOC(internal);
@@ -485,13 +492,18 @@ static int add_backend_internal(
internal->is_alternate = is_alternate;
internal->disk_inode = disk_inode;
+ if (git_mutex_lock(&odb->lock) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return -1;
+ }
if (git_vector_insert(&odb->backends, internal) < 0) {
+ git_mutex_unlock(&odb->lock);
git__free(internal);
return -1;
}
-
git_vector_sort(&odb->backends);
internal->backend->odb = odb;
+ git_mutex_unlock(&odb->lock);
return 0;
}
@@ -507,8 +519,19 @@ int git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority)
size_t git_odb_num_backends(git_odb *odb)
{
- assert(odb);
- return odb->backends.length;
+ size_t length;
+ bool locked = true;
+
+ GIT_ASSERT_ARG(odb);
+
+ if (git_mutex_lock(&odb->lock) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ locked = false;
+ }
+ length = odb->backends.length;
+ if (locked)
+ git_mutex_unlock(&odb->lock);
+ return length;
}
static int git_odb__error_unsupported_in_backend(const char *action)
@@ -522,24 +545,35 @@ static int git_odb__error_unsupported_in_backend(const char *action)
int git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos)
{
backend_internal *internal;
+ int error;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(odb);
- assert(out && odb);
+
+ if ((error = git_mutex_lock(&odb->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
internal = git_vector_get(&odb->backends, pos);
- if (internal && internal->backend) {
- *out = internal->backend;
- return 0;
+ if (!internal || !internal->backend) {
+ git_mutex_unlock(&odb->lock);
+
+ git_error_set(GIT_ERROR_ODB, "no ODB backend loaded at index %" PRIuZ, pos);
+ return GIT_ENOTFOUND;
}
+ *out = internal->backend;
+ git_mutex_unlock(&odb->lock);
- git_error_set(GIT_ERROR_ODB, "no ODB backend loaded at index %" PRIuZ, pos);
- return GIT_ENOTFOUND;
+ return 0;
}
int git_odb__add_default_backends(
git_odb *db, const char *objects_dir,
bool as_alternates, int alternate_depth)
{
- size_t i;
+ size_t i = 0;
struct stat st;
ino_t inode;
git_odb_backend *loose, *packed;
@@ -548,7 +582,7 @@ int git_odb__add_default_backends(
* a cross-platform workaround for this */
#ifdef GIT_WIN32
GIT_UNUSED(i);
- GIT_UNUSED(st);
+ GIT_UNUSED(&st);
inode = 0;
#else
@@ -563,23 +597,40 @@ int git_odb__add_default_backends(
inode = st.st_ino;
+ if (git_mutex_lock(&db->lock) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return -1;
+ }
for (i = 0; i < db->backends.length; ++i) {
backend_internal *backend = git_vector_get(&db->backends, i);
- if (backend->disk_inode == inode)
+ if (backend->disk_inode == inode) {
+ git_mutex_unlock(&db->lock);
return 0;
+ }
}
+ git_mutex_unlock(&db->lock);
#endif
/* add the loose object backend */
if (git_odb_backend_loose(&loose, objects_dir, -1, db->do_fsync, 0, 0) < 0 ||
- add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates, inode) < 0)
+ add_backend_internal(db, loose, git_odb__loose_priority, as_alternates, inode) < 0)
return -1;
/* add the packed file backend */
if (git_odb_backend_pack(&packed, objects_dir) < 0 ||
- add_backend_internal(db, packed, GIT_PACKED_PRIORITY, as_alternates, inode) < 0)
+ add_backend_internal(db, packed, git_odb__packed_priority, as_alternates, inode) < 0)
return -1;
+ if (git_mutex_lock(&db->lock) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return -1;
+ }
+ if (!db->cgraph && git_commit_graph_new(&db->cgraph, objects_dir, false) < 0) {
+ git_mutex_unlock(&db->lock);
+ return -1;
+ }
+ git_mutex_unlock(&db->lock);
+
return load_alternates(db, objects_dir, alternate_depth);
}
@@ -641,11 +692,29 @@ int git_odb_add_disk_alternate(git_odb *odb, const char *path)
return git_odb__add_default_backends(odb, path, true, 0);
}
+int git_odb_set_commit_graph(git_odb *odb, git_commit_graph *cgraph)
+{
+ int error = 0;
+
+ GIT_ASSERT_ARG(odb);
+
+ if ((error = git_mutex_lock(&odb->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the db lock");
+ return error;
+ }
+ git_commit_graph_free(odb->cgraph);
+ odb->cgraph = cgraph;
+ git_mutex_unlock(&odb->lock);
+
+ return error;
+}
+
int git_odb_open(git_odb **out, const char *objects_dir)
{
git_odb *db;
- assert(out && objects_dir);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(objects_dir);
*out = NULL;
@@ -664,7 +733,7 @@ int git_odb_open(git_odb **out, const char *objects_dir)
int git_odb__set_caps(git_odb *odb, int caps)
{
if (caps == GIT_ODB_CAP_FROM_OWNER) {
- git_repository *repo = odb->rc.owner;
+ git_repository *repo = GIT_REFCOUNT_OWNER(odb);
int val;
if (!repo) {
@@ -682,7 +751,12 @@ int git_odb__set_caps(git_odb *odb, int caps)
static void odb_free(git_odb *db)
{
size_t i;
+ bool locked = true;
+ if (git_mutex_lock(&db->lock) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ locked = false;
+ }
for (i = 0; i < db->backends.length; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *backend = internal->backend;
@@ -691,9 +765,13 @@ static void odb_free(git_odb *db)
git__free(internal);
}
+ if (locked)
+ git_mutex_unlock(&db->lock);
+ git_commit_graph_free(db->cgraph);
git_vector_free(&db->backends);
git_cache_dispose(&db->own_cache);
+ git_mutex_free(&db->lock);
git__memzero(db, sizeof(*db));
git__free(db);
@@ -714,7 +792,12 @@ static int odb_exists_1(
{
size_t i;
bool found = false;
+ int error;
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
for (i = 0; i < db->backends.length && !found; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -725,10 +808,34 @@ static int odb_exists_1(
if (b->exists != NULL)
found = (bool)b->exists(b, id);
}
+ git_mutex_unlock(&db->lock);
return (int)found;
}
+int git_odb__get_commit_graph_file(git_commit_graph_file **out, git_odb *db)
+{
+ int error = 0;
+ git_commit_graph_file *result = NULL;
+
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the db lock");
+ return error;
+ }
+ if (!db->cgraph) {
+ error = GIT_ENOTFOUND;
+ goto done;
+ }
+ error = git_commit_graph_get_file(&result, db->cgraph);
+ if (error)
+ goto done;
+ *out = result;
+
+done:
+ git_mutex_unlock(&db->lock);
+ return error;
+}
+
static int odb_freshen_1(
git_odb *db,
const git_oid *id,
@@ -736,7 +843,12 @@ static int odb_freshen_1(
{
size_t i;
bool found = false;
+ int error;
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
for (i = 0; i < db->backends.length && !found; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -749,13 +861,15 @@ static int odb_freshen_1(
else if (b->exists != NULL)
found = b->exists(b, id);
}
+ git_mutex_unlock(&db->lock);
return (int)found;
}
int git_odb__freshen(git_odb *db, const git_oid *id)
{
- assert(db && id);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(id);
if (odb_freshen_1(db, id, false))
return 1;
@@ -771,7 +885,8 @@ int git_odb_exists(git_odb *db, const git_oid *id)
{
git_odb_object *object;
- assert(db && id);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(id);
if (git_oid_is_zero(id))
return 0;
@@ -798,6 +913,11 @@ static int odb_exists_prefix_1(git_oid *out, git_odb *db,
int error = GIT_ENOTFOUND, num_found = 0;
git_oid last_found = {{0}}, found;
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
+ error = GIT_ENOTFOUND;
for (i = 0; i < db->backends.length; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -811,18 +931,23 @@ static int odb_exists_prefix_1(git_oid *out, git_odb *db,
error = b->exists_prefix(&found, b, key, len);
if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
continue;
- if (error)
+ if (error) {
+ git_mutex_unlock(&db->lock);
return error;
+ }
/* make sure found item doesn't introduce ambiguity */
if (num_found) {
- if (git_oid__cmp(&last_found, &found))
+ if (git_oid__cmp(&last_found, &found)) {
+ git_mutex_unlock(&db->lock);
return git_odb__error_ambiguous("multiple matches for prefix");
+ }
} else {
git_oid_cpy(&last_found, &found);
num_found++;
}
}
+ git_mutex_unlock(&db->lock);
if (!num_found)
return GIT_ENOTFOUND;
@@ -839,7 +964,8 @@ int git_odb_exists_prefix(
int error;
git_oid key = {{0}};
- assert(db && short_id);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(short_id);
if (len < GIT_OID_MINPREFIXLEN)
return git_odb__error_ambiguous("prefix length too short");
@@ -875,7 +1001,8 @@ int git_odb_expand_ids(
{
size_t i;
- assert(db && ids);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(ids);
for (i = 0; i < count; i++) {
git_odb_expand_id *query = &ids[i];
@@ -962,6 +1089,10 @@ static int odb_read_header_1(
return 0;
}
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
for (i = 0; i < db->backends.length; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -983,9 +1114,11 @@ static int odb_read_header_1(
case GIT_ENOTFOUND:
break;
default:
+ git_mutex_unlock(&db->lock);
return error;
}
}
+ git_mutex_unlock(&db->lock);
return passthrough ? GIT_PASSTHROUGH : GIT_ENOTFOUND;
}
@@ -997,7 +1130,11 @@ int git_odb__read_header_or_object(
int error = GIT_ENOTFOUND;
git_odb_object *object;
- assert(db && id && out && len_p && type_p);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(id);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(len_p);
+ GIT_ASSERT_ARG(type_p);
*out = NULL;
@@ -1054,6 +1191,10 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
return error;
}
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
for (i = 0; i < db->backends.length && !found; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -1066,12 +1207,15 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
if (error == GIT_PASSTHROUGH || error == GIT_ENOTFOUND)
continue;
- if (error < 0)
+ if (error < 0) {
+ git_mutex_unlock(&db->lock);
return error;
+ }
found = true;
}
}
+ git_mutex_unlock(&db->lock);
if (!found)
return GIT_ENOTFOUND;
@@ -1104,7 +1248,9 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
{
int error;
- assert(out && db && id);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(id);
if (git_oid_is_zero(id))
return error_null_oid(GIT_ENOTFOUND, "cannot read object");
@@ -1162,6 +1308,10 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
bool found = false;
git_odb_object *object;
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
for (i = 0; i < db->backends.length; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -1178,8 +1328,10 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
continue;
}
- if (error)
+ if (error) {
+ git_mutex_unlock(&db->lock);
goto out;
+ }
git__free(data);
data = raw.data;
@@ -1194,6 +1346,7 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
error = git_odb__error_ambiguous(buf.ptr);
git_buf_dispose(&buf);
+ git_mutex_unlock(&db->lock);
goto out;
}
@@ -1201,6 +1354,7 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
found = true;
}
}
+ git_mutex_unlock(&db->lock);
if (!found)
return GIT_ENOTFOUND;
@@ -1237,7 +1391,8 @@ int git_odb_read_prefix(
git_oid key = {{0}};
int error;
- assert(out && db);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(db);
if (len < GIT_OID_MINPREFIXLEN)
return git_odb__error_ambiguous("prefix length too short");
@@ -1267,28 +1422,46 @@ int git_odb_read_prefix(
int git_odb_foreach(git_odb *db, git_odb_foreach_cb cb, void *payload)
{
unsigned int i;
+ git_vector backends = GIT_VECTOR_INIT;
backend_internal *internal;
+ int error = 0;
+
+ /* Make a copy of the backends vector to invoke the callback without holding the lock. */
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ goto cleanup;
+ }
+ error = git_vector_dup(&backends, &db->backends, NULL);
+ git_mutex_unlock(&db->lock);
- git_vector_foreach(&db->backends, i, internal) {
+ if (error < 0)
+ goto cleanup;
+
+ git_vector_foreach(&backends, i, internal) {
git_odb_backend *b = internal->backend;
- int error = b->foreach(b, cb, payload);
+ error = b->foreach(b, cb, payload);
if (error != 0)
- return error;
+ goto cleanup;
}
- return 0;
+cleanup:
+ git_vector_free(&backends);
+
+ return error;
}
int git_odb_write(
git_oid *oid, git_odb *db, const void *data, size_t len, git_object_t type)
{
size_t i;
- int error = GIT_ERROR;
+ int error;
git_odb_stream *stream;
- assert(oid && db);
+ GIT_ASSERT_ARG(oid);
+ GIT_ASSERT_ARG(db);
- git_odb_hash(oid, data, len, type);
+ if ((error = git_odb_hash(oid, data, len, type)) < 0)
+ return error;
if (git_oid_is_zero(oid))
return error_null_oid(GIT_EINVALID, "cannot write object");
@@ -1296,7 +1469,11 @@ int git_odb_write(
if (git_odb__freshen(db, oid))
return 0;
- for (i = 0; i < db->backends.length && error < 0; ++i) {
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
+ for (i = 0, error = GIT_ERROR; i < db->backends.length && error < 0; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -1307,6 +1484,7 @@ int git_odb_write(
if (b->write != NULL)
error = b->write(b, oid, data, len, type);
}
+ git_mutex_unlock(&db->lock);
if (!error || error == GIT_PASSTHROUGH)
return 0;
@@ -1345,8 +1523,14 @@ int git_odb_open_wstream(
int error = GIT_ERROR;
git_hash_ctx *ctx = NULL;
- assert(stream && db);
+ GIT_ASSERT_ARG(stream);
+ GIT_ASSERT_ARG(db);
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
+ error = GIT_ERROR;
for (i = 0; i < db->backends.length && error < 0; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -1363,6 +1547,7 @@ int git_odb_open_wstream(
error = init_fake_wstream(stream, b, size, type);
}
}
+ git_mutex_unlock(&db->lock);
if (error < 0) {
if (error == GIT_PASSTHROUGH)
@@ -1455,8 +1640,14 @@ int git_odb_open_rstream(
size_t i, reads = 0;
int error = GIT_ERROR;
- assert(stream && db);
+ GIT_ASSERT_ARG(stream);
+ GIT_ASSERT_ARG(db);
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
+ error = GIT_ERROR;
for (i = 0; i < db->backends.length && error < 0; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -1466,6 +1657,7 @@ int git_odb_open_rstream(
error = b->readstream(stream, len, type, b, oid);
}
}
+ git_mutex_unlock(&db->lock);
if (error == GIT_PASSTHROUGH)
error = 0;
@@ -1480,8 +1672,14 @@ int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_indexer_
size_t i, writes = 0;
int error = GIT_ERROR;
- assert(out && db);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(db);
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
+ error = GIT_ERROR;
for (i = 0; i < db->backends.length && error < 0; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -1495,6 +1693,7 @@ int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_indexer_
error = b->writepack(out, b, db, progress_cb, progress_payload);
}
}
+ git_mutex_unlock(&db->lock);
if (error == GIT_PASSTHROUGH)
error = 0;
@@ -1504,6 +1703,35 @@ int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_indexer_
return error;
}
+int git_odb_write_multi_pack_index(git_odb *db)
+{
+ size_t i, writes = 0;
+ int error = GIT_ERROR;
+
+ GIT_ASSERT_ARG(db);
+
+ for (i = 0; i < db->backends.length && error < 0; ++i) {
+ backend_internal *internal = git_vector_get(&db->backends, i);
+ git_odb_backend *b = internal->backend;
+
+ /* we don't write in alternates! */
+ if (internal->is_alternate)
+ continue;
+
+ if (b->writemidx != NULL) {
+ ++writes;
+ error = b->writemidx(b);
+ }
+ }
+
+ if (error == GIT_PASSTHROUGH)
+ error = 0;
+ if (error < 0 && !writes)
+ error = git_odb__error_unsupported_in_backend("write multi-pack-index");
+
+ return error;
+}
+
void *git_odb_backend_data_alloc(git_odb_backend *backend, size_t len)
{
GIT_UNUSED(backend);
@@ -1526,18 +1754,29 @@ void git_odb_backend_data_free(git_odb_backend *backend, void *data)
int git_odb_refresh(struct git_odb *db)
{
size_t i;
- assert(db);
+ int error;
+
+ GIT_ASSERT_ARG(db);
+ if ((error = git_mutex_lock(&db->lock)) < 0) {
+ git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
+ return error;
+ }
for (i = 0; i < db->backends.length; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
if (b->refresh != NULL) {
int error = b->refresh(b);
- if (error < 0)
+ if (error < 0) {
+ git_mutex_unlock(&db->lock);
return error;
+ }
}
}
+ if (db->cgraph)
+ git_commit_graph_refresh(db->cgraph);
+ git_mutex_unlock(&db->lock);
return 0;
}
diff --git a/src/odb.h b/src/odb.h
index 8dd4efd64..4a8ebff19 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -12,16 +12,21 @@
#include "git2/odb.h"
#include "git2/oid.h"
#include "git2/types.h"
+#include "git2/sys/commit_graph.h"
-#include "vector.h"
#include "cache.h"
-#include "posix.h"
+#include "commit_graph.h"
#include "filter.h"
+#include "posix.h"
+#include "vector.h"
#define GIT_OBJECTS_DIR "objects/"
#define GIT_OBJECT_DIR_MODE 0777
#define GIT_OBJECT_FILE_MODE 0444
+#define GIT_ODB_DEFAULT_LOOSE_PRIORITY 1
+#define GIT_ODB_DEFAULT_PACKED_PRIORITY 2
+
extern bool git_odb__strict_hash_verification;
/* DO NOT EXPORT */
@@ -40,8 +45,10 @@ struct git_odb_object {
/* EXPORT */
struct git_odb {
git_refcount rc;
+ git_mutex lock; /* protects backends */
git_vector backends;
git_cache own_cache;
+ git_commit_graph *cgraph;
unsigned int do_fsync :1;
};
@@ -126,6 +133,13 @@ int git_odb__read_header_or_object(
git_odb_object **out, size_t *len_p, git_object_t *type_p,
git_odb *db, const git_oid *id);
+/*
+ * Attempt to get the ODB's commit-graph file. This object is still owned by
+ * the ODB. If the repository does not contain a commit-graph, it will return
+ * GIT_ENOTFOUND.
+ */
+int git_odb__get_commit_graph_file(git_commit_graph_file **out, git_odb *odb);
+
/* freshen an entry in the object database */
int git_odb__freshen(git_odb *db, const git_oid *id);
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 4a54b3fc0..b0abbbf4c 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -304,12 +304,12 @@ static int read_loose_standard(git_rawobj *out, git_buf *obj)
* (including the initial sequence in the head buffer).
*/
if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) ||
- (body = git__malloc(alloc_size)) == NULL) {
+ (body = git__calloc(1, alloc_size)) == NULL) {
error = -1;
goto done;
}
- assert(decompressed >= head_len);
+ GIT_ASSERT(decompressed >= head_len);
body_len = decompressed - head_len;
if (body_len)
@@ -344,7 +344,8 @@ static int read_loose(git_rawobj *out, git_buf *loc)
int error;
git_buf obj = GIT_BUF_INIT;
- assert(out && loc);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(loc);
if (git_buf_oom(loc))
return -1;
@@ -386,8 +387,8 @@ static int read_header_loose_standard(
git_rawobj *out, const unsigned char *data, size_t len)
{
git_zstream zs = GIT_ZSTREAM_INIT;
- obj_hdr hdr;
- unsigned char inflated[MAX_HEADER_LEN];
+ obj_hdr hdr = {0};
+ unsigned char inflated[MAX_HEADER_LEN] = {0};
size_t header_len, inflated_len = sizeof(inflated);
int error;
@@ -411,7 +412,8 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
ssize_t obj_len;
int fd, error;
- assert(out && loc);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(loc);
if (git_buf_oom(loc))
return -1;
@@ -585,7 +587,8 @@ static int loose_backend__read_header(size_t *len_p, git_object_t *type_p, git_o
git_rawobj raw;
int error;
- assert(backend && oid);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(oid);
raw.len = 0;
raw.type = GIT_OBJECT_INVALID;
@@ -609,7 +612,8 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_object_t *typ
git_rawobj raw;
int error = 0;
- assert(backend && oid);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(oid);
if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
error = git_odb__error_notfound("no matching loose object",
@@ -636,7 +640,7 @@ static int loose_backend__read_prefix(
{
int error = 0;
- assert(len >= GIT_OID_MINPREFIXLEN && len <= GIT_OID_HEXSZ);
+ GIT_ASSERT_ARG(len >= GIT_OID_MINPREFIXLEN && len <= GIT_OID_HEXSZ);
if (len == GIT_OID_HEXSZ) {
/* We can fall back to regular read method */
@@ -647,7 +651,7 @@ static int loose_backend__read_prefix(
git_buf object_path = GIT_BUF_INIT;
git_rawobj raw;
- assert(backend && short_oid);
+ GIT_ASSERT_ARG(backend && short_oid);
if ((error = locate_object_short_oid(&object_path, out_oid,
(loose_backend *)backend, short_oid, len)) == 0 &&
@@ -669,7 +673,8 @@ static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
git_buf object_path = GIT_BUF_INIT;
int error;
- assert(backend && oid);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(oid);
error = locate_object(&object_path, (loose_backend *)backend, oid);
@@ -684,7 +689,10 @@ static int loose_backend__exists_prefix(
git_buf object_path = GIT_BUF_INIT;
int error;
- assert(backend && out && short_id && len >= GIT_OID_MINPREFIXLEN);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(short_id);
+ GIT_ASSERT_ARG(len >= GIT_OID_MINPREFIXLEN);
error = locate_object_short_oid(
&object_path, out, (loose_backend *)backend, short_id, len);
@@ -759,7 +767,8 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb
struct foreach_state state;
loose_backend *backend = (loose_backend *) _backend;
- assert(backend && cb);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(cb);
objects_dir = backend->objects_dir;
@@ -833,7 +842,7 @@ static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backe
size_t hdrlen;
int error;
- assert(_backend);
+ GIT_ASSERT_ARG(_backend);
backend = (loose_backend *)_backend;
*stream_out = NULL;
@@ -991,7 +1000,11 @@ static int loose_backend__readstream(
obj_hdr hdr;
int error = 0;
- assert(stream_out && len_out && type_out && _backend && oid);
+ GIT_ASSERT_ARG(stream_out);
+ GIT_ASSERT_ARG(len_out);
+ GIT_ASSERT_ARG(type_out);
+ GIT_ASSERT_ARG(_backend);
+ GIT_ASSERT_ARG(oid);
backend = (loose_backend *)_backend;
*stream_out = NULL;
@@ -1108,11 +1121,7 @@ static int loose_backend__freshen(
static void loose_backend__free(git_odb_backend *_backend)
{
- loose_backend *backend;
- assert(_backend);
- backend = (loose_backend *)_backend;
-
- git__free(backend);
+ git__free(_backend);
}
int git_odb_backend_loose(
@@ -1126,7 +1135,8 @@ int git_odb_backend_loose(
loose_backend *backend;
size_t objects_dirlen, alloclen;
- assert(backend_out && objects_dir);
+ GIT_ASSERT_ARG(backend_out);
+ GIT_ASSERT_ARG(objects_dir);
objects_dirlen = strlen(objects_dir);
diff --git a/src/odb_mempack.c b/src/odb_mempack.c
index 6d20b39ba..d08356a8d 100644
--- a/src/odb_mempack.c
+++ b/src/odb_mempack.c
@@ -156,7 +156,7 @@ int git_mempack_new(git_odb_backend **out)
{
struct memory_packer_db *db;
- assert(out);
+ GIT_ASSERT_ARG(out);
db = git__calloc(1, sizeof(struct memory_packer_db));
GIT_ERROR_CHECK_ALLOC(db);
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 86c858df1..f4cb9a558 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -11,11 +11,12 @@
#include "git2/repository.h"
#include "git2/indexer.h"
#include "git2/sys/odb_backend.h"
+#include "delta.h"
#include "futils.h"
#include "hash.h"
-#include "odb.h"
-#include "delta.h"
+#include "midx.h"
#include "mwindow.h"
+#include "odb.h"
#include "pack.h"
#include "git2/odb_backend.h"
@@ -25,6 +26,8 @@
struct pack_backend {
git_odb_backend parent;
+ git_midx_file *midx;
+ git_vector midx_packs;
git_vector packs;
struct git_pack_file *last_found;
char *pack_folder;
@@ -47,36 +50,43 @@ struct pack_writepack {
* Initialization of the Pack Backend
* --------------------------------------------------
*
- * # git_odb_backend_pack
- * | Creates the pack backend structure, initializes the
- * | callback pointers to our default read() and exist() methods,
- * | and tries to preload all the known packfiles in the ODB.
+ * # git_odb_backend_pack
+ * | Creates the pack backend structure, initializes the
+ * | callback pointers to our default read() and exist() methods,
+ * | and tries to find the `pack` folder, if it exists. ODBs without a `pack`
+ * | folder are ignored altogether. If there is a `pack` folder, it tries to
+ * | preload all the known packfiles in the ODB.
* |
- * |-# packfile_load_all
- * | Tries to find the `pack` folder, if it exists. ODBs without
- * | a pack folder are ignored altogether. If there's a `pack` folder
- * | we run a `dirent` callback through every file in the pack folder
- * | to find our packfiles. The packfiles are then sorted according
- * | to a sorting callback.
- * |
- * |-# packfile_load__cb
- * | | This callback is called from `dirent` with every single file
- * | | inside the pack folder. We find the packs by actually locating
- * | | their index (ends in ".idx"). From that index, we verify that
- * | | the corresponding packfile exists and is valid, and if so, we
- * | | add it to the pack list.
- * | |
- * | |-# packfile_check
- * | Make sure that there's a packfile to back this index, and store
- * | some very basic information regarding the packfile itself,
- * | such as the full path, the size, and the modification time.
- * | We don't actually open the packfile to check for internal consistency.
- * |
- * |-# packfile_sort__cb
- * Sort all the preloaded packs according to some specific criteria:
- * we prioritize the "newer" packs because it's more likely they
- * contain the objects we are looking for, and we prioritize local
- * packs over remote ones.
+ * |-# pack_backend__refresh
+ * | The `multi-pack-index` is loaded if it exists and is valid.
+ * | Then we run a `dirent` callback through every file in the pack folder,
+ * | even those present in `multi-pack-index`. The unindexed packfiles are
+ * | then sorted according to a sorting callback.
+ * |
+ * |-# refresh_multi_pack_index
+ * | Detect the presence of the `multi-pack-index` file. If it needs to be
+ * | refreshed, frees the old copy and tries to load the new one, together
+ * | with all the packfiles it indexes. If the process fails, fall back to
+ * | the old behavior, as if the `multi-pack-index` file was not there.
+ * |
+ * |-# packfile_load__cb
+ * | | This callback is called from `dirent` with every single file
+ * | | inside the pack folder. We find the packs by actually locating
+ * | | their index (ends in ".idx"). From that index, we verify that
+ * | | the corresponding packfile exists and is valid, and if so, we
+ * | | add it to the pack list.
+ * | |
+ * | # git_mwindow_get_pack
+ * | Make sure that there's a packfile to back this index, and store
+ * | some very basic information regarding the packfile itself,
+ * | such as the full path, the size, and the modification time.
+ * | We don't actually open the packfile to check for internal consistency.
+ * |
+ * |-# packfile_sort__cb
+ * Sort all the preloaded packs according to some specific criteria:
+ * we prioritize the "newer" packs because it's more likely they
+ * contain the objects we are looking for, and we prioritize local
+ * packs over remote ones.
*
*
*
@@ -84,48 +94,66 @@ struct pack_writepack {
* A standard packed `exist` query for an OID
* --------------------------------------------------
*
- * # pack_backend__exists
- * | Check if the given SHA1 oid exists in any of the packs
- * | that have been loaded for our ODB.
+ * # pack_backend__exists / pack_backend__exists_prefix
+ * | Check if the given SHA1 oid (or a SHA1 oid prefix) exists in any of the
+ * | packs that have been loaded for our ODB.
* |
- * |-# pack_entry_find
- * | Iterate through all the packs that have been preloaded
- * | (starting by the pack where the latest object was found)
- * | to try to find the OID in one of them.
- * |
- * |-# pack_entry_find1
- * | Check the index of an individual pack to see if the SHA1
- * | OID can be found. If we can find the offset to that SHA1
- * | inside of the index, that means the object is contained
- * | inside of the packfile and we can stop searching.
- * | Before returning, we verify that the packfile behing the
- * | index we are searching still exists on disk.
- * |
- * |-# pack_entry_find_offset
- * | | Mmap the actual index file to disk if it hasn't been opened
- * | | yet, and run a binary search through it to find the OID.
- * | | See <http://book.git-scm.com/7_the_packfile.html> for specifics
- * | | on the Packfile Index format and how do we find entries in it.
- * | |
- * | |-# pack_index_open
- * | | Guess the name of the index based on the full path to the
- * | | packfile, open it and verify its contents. Only if the index
- * | | has not been opened already.
- * | |
- * | |-# pack_index_check
- * | Mmap the index file and do a quick run through the header
- * | to guess the index version (right now we support v1 and v2),
- * | and to verify that the size of the index makes sense.
- * |
- * |-# packfile_open
- * See `packfile_open` in Chapter 3
+ * |-# pack_entry_find / pack_entry_find_prefix
+ * | If there is a multi-pack-index present, search the SHA1 oid in that
+ * | index first. If it is not found there, iterate through all the unindexed
+ * | packs that have been preloaded (starting by the pack where the latest
+ * | object was found) to try to find the OID in one of them.
+ * |
+ * |-# git_midx_entry_find
+ * | Search for the SHA1 oid in the multi-pack-index. See
+ * | <https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt>
+ * | for specifics on the multi-pack-index format and how do we find
+ * | entries in it.
+ * |
+ * |-# git_pack_entry_find
+ * | Check the index of an individual unindexed pack to see if the SHA1
+ * | OID can be found. If we can find the offset to that SHA1 inside of the
+ * | index, that means the object is contained inside of the packfile and
+ * | we can stop searching. Before returning, we verify that the
+ * | packfile behing the index we are searching still exists on disk.
+ * |
+ * |-# pack_entry_find_offset
+ * | Mmap the actual index file to disk if it hasn't been opened
+ * | yet, and run a binary search through it to find the OID.
+ * | See <https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt>
+ * | for specifics on the Packfile Index format and how do we find
+ * | entries in it.
+ * |
+ * |-# pack_index_open
+ * | Guess the name of the index based on the full path to the
+ * | packfile, open it and verify its contents. Only if the index
+ * | has not been opened already.
+ * |
+ * |-# pack_index_check
+ * Mmap the index file and do a quick run through the header
+ * to guess the index version (right now we support v1 and v2),
+ * and to verify that the size of the index makes sense.
*
*
*
* Chapter 3: The neverending story...
* A standard packed `lookup` query for an OID
* --------------------------------------------------
- * TODO
+ *
+ * # pack_backend__read / pack_backend__read_prefix
+ * | Check if the given SHA1 oid (or a SHA1 oid prefix) exists in any of the
+ * | packs that have been loaded for our ODB. If it does, open the packfile and
+ * | read from it.
+ * |
+ * |-# git_packfile_unpack
+ * Armed with a packfile and the offset within it, we can finally unpack
+ * the object pointed at by the SHA1 oid. This involves mmapping part of
+ * the `.pack` file, and uncompressing the object within it (if it is
+ * stored in the undelfitied representation), or finding a base object and
+ * applying some deltas to its uncompressed representation (if it is stored
+ * in the deltified representation). See
+ * <https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt>
+ * for specifics on the Packfile format and how do we read from it.
*
*/
@@ -140,6 +168,8 @@ static int packfile_sort__cb(const void *a_, const void *b_);
static int packfile_load__cb(void *_data, git_buf *path);
+static int packfile_byname_search_cmp(const void *path, const void *pack_entry);
+
static int pack_entry_find(struct git_pack_entry *e,
struct pack_backend *backend, const git_oid *oid);
@@ -163,6 +193,14 @@ static int pack_entry_find_prefix(
*
***********************************************************/
+static int packfile_byname_search_cmp(const void *path_, const void *p_)
+{
+ const git_buf *path = (const git_buf *)path_;
+ const struct git_pack_file *p = (const struct git_pack_file *)p_;
+
+ return strncmp(p->pack_name, git_buf_cstr(path), git_buf_len(path));
+}
+
static int packfile_sort__cb(const void *a_, const void *b_)
{
const struct git_pack_file *a = a_;
@@ -198,20 +236,20 @@ static int packfile_load__cb(void *data, git_buf *path)
struct pack_backend *backend = data;
struct git_pack_file *pack;
const char *path_str = git_buf_cstr(path);
- size_t i, cmp_len = git_buf_len(path);
+ git_buf index_prefix = GIT_BUF_INIT;
+ size_t cmp_len = git_buf_len(path);
int error;
if (cmp_len <= strlen(".idx") || git__suffixcmp(path_str, ".idx") != 0)
return 0; /* not an index */
cmp_len -= strlen(".idx");
+ git_buf_attach_notowned(&index_prefix, path_str, cmp_len);
- for (i = 0; i < backend->packs.length; ++i) {
- struct git_pack_file *p = git_vector_get(&backend->packs, i);
-
- if (strncmp(p->pack_name, path_str, cmp_len) == 0)
- return 0;
- }
+ if (git_vector_search2(NULL, &backend->midx_packs, packfile_byname_search_cmp, &index_prefix) == 0)
+ return 0;
+ if (git_vector_search2(NULL, &backend->packs, packfile_byname_search_cmp, &index_prefix) == 0)
+ return 0;
error = git_mwindow_get_pack(&pack, path->ptr);
@@ -228,22 +266,26 @@ static int packfile_load__cb(void *data, git_buf *path)
}
-static int pack_entry_find_inner(
- struct git_pack_entry *e,
- struct pack_backend *backend,
- const git_oid *oid,
- struct git_pack_file *last_found)
+static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backend, const git_oid *oid)
{
+ struct git_pack_file *last_found = backend->last_found, *p;
+ git_midx_entry midx_entry;
size_t i;
+ if (backend->midx &&
+ git_midx_entry_find(&midx_entry, backend->midx, oid, GIT_OID_HEXSZ) == 0 &&
+ midx_entry.pack_index < git_vector_length(&backend->midx_packs)) {
+ e->offset = midx_entry.offset;
+ git_oid_cpy(&e->sha1, &midx_entry.sha1);
+ e->p = git_vector_get(&backend->midx_packs, midx_entry.pack_index);
+ return 0;
+ }
+
if (last_found &&
git_pack_entry_find(e, last_found, oid, GIT_OID_HEXSZ) == 0)
return 0;
- for (i = 0; i < backend->packs.length; ++i) {
- struct git_pack_file *p;
-
- p = git_vector_get(&backend->packs, i);
+ git_vector_foreach(&backend->packs, i, p) {
if (p == last_found)
continue;
@@ -253,20 +295,6 @@ static int pack_entry_find_inner(
}
}
- return -1;
-}
-
-static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backend, const git_oid *oid)
-{
- struct git_pack_file *last_found = backend->last_found;
-
- if (backend->last_found &&
- git_pack_entry_find(e, backend->last_found, oid, GIT_OID_HEXSZ) == 0)
- return 0;
-
- if (!pack_entry_find_inner(e, backend, oid, last_found))
- return 0;
-
return git_odb__error_notfound(
"failed to find pack entry", oid, GIT_OID_HEXSZ);
}
@@ -281,22 +309,35 @@ static int pack_entry_find_prefix(
size_t i;
git_oid found_full_oid = {{0}};
bool found = false;
- struct git_pack_file *last_found = backend->last_found;
+ struct git_pack_file *last_found = backend->last_found, *p;
+ git_midx_entry midx_entry;
+
+ if (backend->midx) {
+ error = git_midx_entry_find(&midx_entry, backend->midx, short_oid, len);
+ if (error == GIT_EAMBIGUOUS)
+ return error;
+ if (!error && midx_entry.pack_index < git_vector_length(&backend->midx_packs)) {
+ e->offset = midx_entry.offset;
+ git_oid_cpy(&e->sha1, &midx_entry.sha1);
+ e->p = git_vector_get(&backend->midx_packs, midx_entry.pack_index);
+ git_oid_cpy(&found_full_oid, &e->sha1);
+ found = true;
+ }
+ }
if (last_found) {
error = git_pack_entry_find(e, last_found, short_oid, len);
if (error == GIT_EAMBIGUOUS)
return error;
if (!error) {
+ if (found && git_oid_cmp(&e->sha1, &found_full_oid))
+ return git_odb__error_ambiguous("found multiple pack entries");
git_oid_cpy(&found_full_oid, &e->sha1);
found = true;
}
}
- for (i = 0; i < backend->packs.length; ++i) {
- struct git_pack_file *p;
-
- p = git_vector_get(&backend->packs, i);
+ git_vector_foreach(&backend->packs, i, p) {
if (p == last_found)
continue;
@@ -319,6 +360,139 @@ static int pack_entry_find_prefix(
return 0;
}
+/***********************************************************
+ *
+ * MULTI-PACK-INDEX SUPPORT
+ *
+ * Functions needed to support the multi-pack-index.
+ *
+ ***********************************************************/
+
+/*
+ * Remove the multi-pack-index, and move all midx_packs to packs.
+ */
+static int remove_multi_pack_index(struct pack_backend *backend)
+{
+ size_t i, j = git_vector_length(&backend->packs);
+ struct pack_backend *p;
+ int error = git_vector_size_hint(
+ &backend->packs,
+ j + git_vector_length(&backend->midx_packs));
+ if (error < 0)
+ return error;
+
+ git_vector_foreach(&backend->midx_packs, i, p)
+ git_vector_set(NULL, &backend->packs, j++, p);
+ git_vector_clear(&backend->midx_packs);
+
+ git_midx_free(backend->midx);
+ backend->midx = NULL;
+
+ return 0;
+}
+
+/*
+ * Loads a single .pack file referred to by the multi-pack-index. These must
+ * match the order in which they are declared in the multi-pack-index file,
+ * since these files are referred to by their index.
+ */
+static int process_multi_pack_index_pack(
+ struct pack_backend *backend,
+ size_t i,
+ const char *packfile_name)
+{
+ int error;
+ struct git_pack_file *pack;
+ size_t found_position;
+ git_buf pack_path = GIT_BUF_INIT, index_prefix = GIT_BUF_INIT;
+
+ error = git_buf_joinpath(&pack_path, backend->pack_folder, packfile_name);
+ if (error < 0)
+ return error;
+
+ /* This is ensured by midx_parse_packfile_name() */
+ if (git_buf_len(&pack_path) <= strlen(".idx") || git__suffixcmp(git_buf_cstr(&pack_path), ".idx") != 0)
+ return git_odb__error_notfound("midx file contained a non-index", NULL, 0);
+
+ git_buf_attach_notowned(&index_prefix, git_buf_cstr(&pack_path), git_buf_len(&pack_path) - strlen(".idx"));
+
+ if (git_vector_search2(&found_position, &backend->packs, packfile_byname_search_cmp, &index_prefix) == 0) {
+ /* Pack was found in the packs list. Moving it to the midx_packs list. */
+ git_buf_dispose(&pack_path);
+ git_vector_set(NULL, &backend->midx_packs, i, git_vector_get(&backend->packs, found_position));
+ git_vector_remove(&backend->packs, found_position);
+ return 0;
+ }
+
+ /* Pack was not found. Allocate a new one. */
+ error = git_mwindow_get_pack(&pack, git_buf_cstr(&pack_path));
+ git_buf_dispose(&pack_path);
+ if (error < 0)
+ return error;
+
+ git_vector_set(NULL, &backend->midx_packs, i, pack);
+ return 0;
+}
+
+/*
+ * Reads the multi-pack-index. If this fails for whatever reason, the
+ * multi-pack-index object is freed, and all the packfiles that are related to
+ * it are moved to the unindexed packfiles vector.
+ */
+static int refresh_multi_pack_index(struct pack_backend *backend)
+{
+ int error;
+ git_buf midx_path = GIT_BUF_INIT;
+ const char *packfile_name;
+ size_t i;
+
+ error = git_buf_joinpath(&midx_path, backend->pack_folder, "multi-pack-index");
+ if (error < 0)
+ return error;
+
+ /*
+ * Check whether the multi-pack-index has changed. If it has, close any
+ * old multi-pack-index and move all the packfiles to the unindexed
+ * packs. This is done to prevent losing any open packfiles in case
+ * refreshing the new multi-pack-index fails, or the file is deleted.
+ */
+ if (backend->midx) {
+ if (!git_midx_needs_refresh(backend->midx, git_buf_cstr(&midx_path))) {
+ git_buf_dispose(&midx_path);
+ return 0;
+ }
+ error = remove_multi_pack_index(backend);
+ if (error < 0) {
+ git_buf_dispose(&midx_path);
+ return error;
+ }
+ }
+
+ error = git_midx_open(&backend->midx, git_buf_cstr(&midx_path));
+ git_buf_dispose(&midx_path);
+ if (error < 0)
+ return error;
+
+ git_vector_resize_to(&backend->midx_packs, git_vector_length(&backend->midx->packfile_names));
+
+ git_vector_foreach(&backend->midx->packfile_names, i, packfile_name) {
+ error = process_multi_pack_index_pack(backend, i, packfile_name);
+ if (error < 0) {
+ /*
+ * Something failed during reading multi-pack-index.
+ * Restore the state of backend as if the
+ * multi-pack-index was never there, and move all
+ * packfiles that have been processed so far to the
+ * unindexed packs.
+ */
+ git_vector_resize_to(&backend->midx_packs, i);
+ remove_multi_pack_index(backend);
+ return error;
+ }
+ }
+
+ return 0;
+}
/***********************************************************
*
@@ -340,9 +514,16 @@ static int pack_backend__refresh(git_odb_backend *backend_)
if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
return git_odb__error_notfound("failed to refresh packfiles", NULL, 0);
- git_buf_sets(&path, backend->pack_folder);
+ if (refresh_multi_pack_index(backend) < 0) {
+ /*
+ * It is okay if this fails. We will just not use the
+ * multi-pack-index in this case.
+ */
+ git_error_clear();
+ }
/* reload all packs */
+ git_buf_sets(&path, backend->pack_folder);
error = git_path_direach(&path, 0, packfile_load__cb, backend);
git_buf_dispose(&path);
@@ -358,7 +539,10 @@ static int pack_backend__read_header(
struct git_pack_entry e;
int error;
- assert(len_p && type_p && backend && oid);
+ GIT_ASSERT_ARG(len_p);
+ GIT_ASSERT_ARG(type_p);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(oid);
if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < 0)
return error;
@@ -469,13 +653,17 @@ static int pack_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb c
struct pack_backend *backend;
unsigned int i;
- assert(_backend && cb);
+ GIT_ASSERT_ARG(_backend);
+ GIT_ASSERT_ARG(cb);
+
backend = (struct pack_backend *)_backend;
/* Make sure we know about the packfiles */
- if ((error = pack_backend__refresh(_backend)) < 0)
+ if ((error = pack_backend__refresh(_backend)) != 0)
return error;
+ if (backend->midx && (error = git_midx_foreach_entry(backend->midx, cb, data)) != 0)
+ return error;
git_vector_foreach(&backend->packs, i, p) {
if ((error = git_pack_foreach_entry(p, cb, data)) != 0)
return error;
@@ -488,7 +676,7 @@ static int pack_backend__writepack_append(struct git_odb_writepack *_writepack,
{
struct pack_writepack *writepack = (struct pack_writepack *)_writepack;
- assert(writepack);
+ GIT_ASSERT_ARG(writepack);
return git_indexer_append(writepack->indexer, data, size, stats);
}
@@ -497,16 +685,19 @@ static int pack_backend__writepack_commit(struct git_odb_writepack *_writepack,
{
struct pack_writepack *writepack = (struct pack_writepack *)_writepack;
- assert(writepack);
+ GIT_ASSERT_ARG(writepack);
return git_indexer_commit(writepack->indexer, stats);
}
static void pack_backend__writepack_free(struct git_odb_writepack *_writepack)
{
- struct pack_writepack *writepack = (struct pack_writepack *)_writepack;
+ struct pack_writepack *writepack;
- assert(writepack);
+ if (!_writepack)
+ return;
+
+ writepack = (struct pack_writepack *)_writepack;
git_indexer_free(writepack->indexer);
git__free(writepack);
@@ -522,7 +713,8 @@ static int pack_backend__writepack(struct git_odb_writepack **out,
struct pack_backend *backend;
struct pack_writepack *writepack;
- assert(out && _backend);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(_backend);
*out = NULL;
@@ -550,20 +742,99 @@ static int pack_backend__writepack(struct git_odb_writepack **out,
return 0;
}
+static int get_idx_path(
+ git_buf *idx_path,
+ struct pack_backend *backend,
+ struct git_pack_file *p)
+{
+ size_t path_len;
+ int error;
+
+ error = git_path_prettify(idx_path, p->pack_name, backend->pack_folder);
+ if (error < 0)
+ return error;
+ path_len = git_buf_len(idx_path);
+ if (path_len <= strlen(".pack") || git__suffixcmp(git_buf_cstr(idx_path), ".pack") != 0)
+ return git_odb__error_notfound("packfile does not end in .pack", NULL, 0);
+ path_len -= strlen(".pack");
+ error = git_buf_splice(idx_path, path_len, strlen(".pack"), ".idx", strlen(".idx"));
+ if (error < 0)
+ return error;
+
+ return 0;
+}
+
+static int pack_backend__writemidx(git_odb_backend *_backend)
+{
+ struct pack_backend *backend;
+ git_midx_writer *w = NULL;
+ struct git_pack_file *p;
+ size_t i;
+ int error = 0;
+
+ GIT_ASSERT_ARG(_backend);
+
+ backend = (struct pack_backend *)_backend;
+
+ error = git_midx_writer_new(&w, backend->pack_folder);
+ if (error < 0)
+ return error;
+
+ git_vector_foreach(&backend->midx_packs, i, p) {
+ git_buf idx_path = GIT_BUF_INIT;
+ error = get_idx_path(&idx_path, backend, p);
+ if (error < 0)
+ goto cleanup;
+ error = git_midx_writer_add(w, git_buf_cstr(&idx_path));
+ git_buf_dispose(&idx_path);
+ if (error < 0)
+ goto cleanup;
+ }
+ git_vector_foreach(&backend->packs, i, p) {
+ git_buf idx_path = GIT_BUF_INIT;
+ error = get_idx_path(&idx_path, backend, p);
+ if (error < 0)
+ goto cleanup;
+ error = git_midx_writer_add(w, git_buf_cstr(&idx_path));
+ git_buf_dispose(&idx_path);
+ if (error < 0)
+ goto cleanup;
+ }
+
+ /*
+ * Invalidate the previous midx before writing the new one.
+ */
+ error = remove_multi_pack_index(backend);
+ if (error < 0)
+ goto cleanup;
+ error = git_midx_writer_commit(w);
+ if (error < 0)
+ goto cleanup;
+ error = refresh_multi_pack_index(backend);
+
+cleanup:
+ git_midx_writer_free(w);
+ return error;
+}
+
static void pack_backend__free(git_odb_backend *_backend)
{
struct pack_backend *backend;
+ struct git_pack_file *p;
size_t i;
- assert(_backend);
+ if (!_backend)
+ return;
backend = (struct pack_backend *)_backend;
- for (i = 0; i < backend->packs.length; ++i) {
- struct git_pack_file *p = git_vector_get(&backend->packs, i);
+ git_vector_foreach(&backend->midx_packs, i, p)
+ git_mwindow_put_pack(p);
+ git_vector_foreach(&backend->packs, i, p)
git_mwindow_put_pack(p);
- }
+ git_midx_free(backend->midx);
+ git_vector_free(&backend->midx_packs);
git_vector_free(&backend->packs);
git__free(backend->pack_folder);
git__free(backend);
@@ -574,7 +845,12 @@ static int pack_backend__alloc(struct pack_backend **out, size_t initial_size)
struct pack_backend *backend = git__calloc(1, sizeof(struct pack_backend));
GIT_ERROR_CHECK_ALLOC(backend);
+ if (git_vector_init(&backend->midx_packs, 0, NULL) < 0) {
+ git__free(backend);
+ return -1;
+ }
if (git_vector_init(&backend->packs, initial_size, packfile_sort__cb) < 0) {
+ git_vector_free(&backend->midx_packs);
git__free(backend);
return -1;
}
@@ -589,6 +865,7 @@ static int pack_backend__alloc(struct pack_backend **out, size_t initial_size)
backend->parent.refresh = &pack_backend__refresh;
backend->parent.foreach = &pack_backend__foreach;
backend->parent.writepack = &pack_backend__writepack;
+ backend->parent.writemidx = &pack_backend__writemidx;
backend->parent.freshen = &pack_backend__freshen;
backend->parent.free = &pack_backend__free;
diff --git a/src/oid.c b/src/oid.c
index 7831aca89..893e2fc0f 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -9,7 +9,7 @@
#include "git2/oid.h"
#include "repository.h"
-#include "global.h"
+#include "threadstate.h"
#include <string.h>
#include <limits.h>
@@ -26,7 +26,8 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
size_t p;
int v;
- assert(out && str);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(str);
if (!length)
return oid_error_invalid("too short");
@@ -107,7 +108,7 @@ int git_oid_pathfmt(char *str, const git_oid *oid)
char *git_oid_tostr_s(const git_oid *oid)
{
- char *str = GIT_GLOBAL->oid_fmt;
+ char *str = GIT_THREADSTATE->oid_fmt;
git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
return str;
}
@@ -316,7 +317,7 @@ git_oid_shorten *git_oid_shorten_new(size_t min_length)
{
git_oid_shorten *os;
- assert((size_t)((int)min_length) == min_length);
+ GIT_ASSERT_ARG_WITH_RETVAL((size_t)((int)min_length) == min_length, NULL);
os = git__calloc(1, sizeof(git_oid_shorten));
if (os == NULL)
diff --git a/src/oidarray.c b/src/oidarray.c
index e70e9dd61..583017c4e 100644
--- a/src/oidarray.c
+++ b/src/oidarray.c
@@ -10,7 +10,7 @@
#include "git2/oidarray.h"
#include "array.h"
-void git_oidarray_free(git_oidarray *arr)
+void git_oidarray_dispose(git_oidarray *arr)
{
git__free(arr->ids);
}
@@ -32,3 +32,12 @@ void git_oidarray__reverse(git_oidarray *arr)
git_oid_cpy(&arr->ids[(arr->count-1)-i], &tmp);
}
}
+
+#ifndef GIT_DEPRECATE_HARD
+
+void git_oidarray_free(git_oidarray *arr)
+{
+ git_oidarray_dispose(arr);
+}
+
+#endif
diff --git a/src/pack-objects.c b/src/pack-objects.c
index cf10e6cb5..faff310b4 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -12,7 +12,7 @@
#include "iterator.h"
#include "netops.h"
#include "pack.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "tree.h"
#include "util.h"
#include "revwalk.h"
@@ -48,18 +48,10 @@ struct walk_object {
};
#ifdef GIT_THREADS
-
-#define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) do { \
- int result = git_mutex_##op(&(pb)->mtx); \
- assert(!result); \
- GIT_UNUSED(result); \
- } while (0)
-
+# define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) git_mutex_##op(&(pb)->mtx)
#else
-
-#define GIT_PACKBUILDER__MUTEX_OP(pb,mtx,op) GIT_UNUSED(pb)
-
-#endif /* GIT_THREADS */
+# define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) git__noop()
+#endif
#define git_packbuilder__cache_lock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, cache_mutex, lock)
#define git_packbuilder__cache_unlock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, cache_mutex, unlock)
@@ -177,13 +169,13 @@ on_error:
unsigned int git_packbuilder_set_threads(git_packbuilder *pb, unsigned int n)
{
- assert(pb);
+ GIT_ASSERT_ARG(pb);
#ifdef GIT_THREADS
pb->nr_threads = n;
#else
GIT_UNUSED(n);
- assert(1 == pb->nr_threads);
+ GIT_ASSERT(pb->nr_threads == 1);
#endif
return pb->nr_threads;
@@ -211,7 +203,8 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
size_t newsize;
int ret;
- assert(pb && oid);
+ GIT_ASSERT_ARG(pb);
+ GIT_ASSERT_ARG(oid);
/* If the object already exists in the hash table, then we don't
* have any work to do */
@@ -258,7 +251,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
double current_time = git__timer();
double elapsed = current_time - pb->last_progress_report_time;
- if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
+ if (elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
pb->last_progress_report_time = current_time;
ret = pb->progress_cb(
@@ -347,10 +340,9 @@ static int write_object(
}
/* Write header */
- hdr_len = git_packfile__object_header(hdr, data_len, type);
-
- if ((error = write_cb(hdr, hdr_len, cb_data)) < 0 ||
- (error = git_hash_update(&pb->ctx, hdr, hdr_len)) < 0)
+ if ((error = git_packfile__object_header(&hdr_len, hdr, data_len, type)) < 0 ||
+ (error = write_cb(hdr, hdr_len, cb_data)) < 0 ||
+ (error = git_hash_update(&pb->ctx, hdr, hdr_len)) < 0)
goto done;
if (type == GIT_OBJECT_REF_DELTA) {
@@ -525,13 +517,18 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data)
return 0;
}
-static git_pobject **compute_write_order(git_packbuilder *pb)
+static int compute_write_order(git_pobject ***out, git_packbuilder *pb)
{
size_t i, wo_end, last_untagged;
git_pobject **wo;
+ *out = NULL;
+
+ if (!pb->nr_objects)
+ return 0;
+
if ((wo = git__mallocarray(pb->nr_objects, sizeof(*wo))) == NULL)
- return NULL;
+ return -1;
for (i = 0; i < pb->nr_objects; i++) {
git_pobject *po = pb->object_list + i;
@@ -560,7 +557,7 @@ static git_pobject **compute_write_order(git_packbuilder *pb)
*/
if (git_tag_foreach(pb->repo, &cb_tag_foreach, pb) < 0) {
git__free(wo);
- return NULL;
+ return -1;
}
/*
@@ -617,10 +614,11 @@ static git_pobject **compute_write_order(git_packbuilder *pb)
if (wo_end != pb->nr_objects) {
git__free(wo);
git_error_set(GIT_ERROR_INVALID, "invalid write order");
- return NULL;
+ return -1;
}
- return wo;
+ *out = wo;
+ return 0;
}
static int write_pack(git_packbuilder *pb,
@@ -633,15 +631,15 @@ static int write_pack(git_packbuilder *pb,
struct git_pack_header ph;
git_oid entry_oid;
size_t i = 0;
- int error = 0;
+ int error;
- write_order = compute_write_order(pb);
- if (write_order == NULL)
- return -1;
+ if ((error = compute_write_order(&write_order, pb)) < 0)
+ return error;
if (!git__is_uint32(pb->nr_objects)) {
git_error_set(GIT_ERROR_INVALID, "too many objects");
- return -1;
+ error = -1;
+ goto done;
}
/* Write pack header */
@@ -852,10 +850,11 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
}
}
- git_packbuilder__cache_lock(pb);
+ GIT_ASSERT(git_packbuilder__cache_lock(pb) == 0);
+
if (trg_object->delta_data) {
git__free(trg_object->delta_data);
- assert(pb->delta_cache_size >= trg_object->delta_size);
+ GIT_ASSERT(pb->delta_cache_size >= trg_object->delta_size);
pb->delta_cache_size -= trg_object->delta_size;
trg_object->delta_data = NULL;
}
@@ -863,7 +862,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
bool overflow = git__add_sizet_overflow(
&pb->delta_cache_size, pb->delta_cache_size, delta_size);
- git_packbuilder__cache_unlock(pb);
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
if (overflow) {
git__free(delta_buf);
@@ -874,7 +873,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
GIT_ERROR_CHECK_ALLOC(trg_object->delta_data);
} else {
/* create delta when writing the pack */
- git_packbuilder__cache_unlock(pb);
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
git__free(delta_buf);
}
@@ -929,7 +928,7 @@ static int report_delta_progress(
double current_time = git__timer();
double elapsed = current_time - pb->last_progress_report_time;
- if (force || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
+ if (force || elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
pb->last_progress_report_time = current_time;
ret = pb->progress_cb(
@@ -962,9 +961,9 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
struct unpacked *n = array + idx;
size_t max_depth, j, best_base = SIZE_MAX;
- git_packbuilder__progress_lock(pb);
+ GIT_ASSERT(git_packbuilder__progress_lock(pb) == 0);
if (!*list_size) {
- git_packbuilder__progress_unlock(pb);
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
break;
}
@@ -973,7 +972,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
po = *list++;
(*list_size)--;
- git_packbuilder__progress_unlock(pb);
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
mem_usage -= free_unpacked(n);
n->object = po;
@@ -1048,10 +1047,10 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
po->z_delta_size = zbuf.size;
git_buf_clear(&zbuf);
- git_packbuilder__cache_lock(pb);
+ GIT_ASSERT(git_packbuilder__cache_lock(pb) == 0);
pb->delta_cache_size -= po->delta_size;
pb->delta_cache_size += po->z_delta_size;
- git_packbuilder__cache_unlock(pb);
+ GIT_ASSERT(git_packbuilder__cache_unlock(pb) == 0);
}
/*
@@ -1129,10 +1128,10 @@ static void *threaded_find_deltas(void *arg)
; /* TODO */
}
- git_packbuilder__progress_lock(me->pb);
+ GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_lock(me->pb) == 0, NULL);
me->working = 0;
git_cond_signal(&me->pb->progress_cond);
- git_packbuilder__progress_unlock(me->pb);
+ GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_unlock(me->pb) == 0, NULL);
if (git_mutex_lock(&me->mutex)) {
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,
int ret, active_threads = 0;
if (!pb->nr_threads)
- pb->nr_threads = git_online_cpus();
+ pb->nr_threads = git__online_cpus();
if (pb->nr_threads <= 1) {
find_deltas(pb, list, &list_size, window, depth);
@@ -1237,7 +1236,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
* 'working' flag from 1 -> 0. This indicates that it is
* ready to receive more work using our work-stealing
* algorithm. */
- git_packbuilder__progress_lock(pb);
+ GIT_ASSERT(git_packbuilder__progress_lock(pb) == 0);
for (;;) {
for (i = 0; !target && i < pb->nr_threads; i++)
if (!p[i].working)
@@ -1280,7 +1279,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
target->list_size = sub_size;
target->remaining = sub_size;
target->working = 1;
- git_packbuilder__progress_unlock(pb);
+ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
if (git_mutex_lock(&target->mutex)) {
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
int git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb)
{
+ int error;
+
+ if ((error = git_buf_sanitize(buf)) < 0)
+ return error;
+
PREPARE_PACK;
- git_buf_sanitize(buf);
+
return write_pack(pb, &write_pack_buf, buf);
}
@@ -1486,7 +1490,8 @@ int git_packbuilder_insert_recur(git_packbuilder *pb, const git_oid *id, const c
git_object *obj;
int error;
- assert(pb && id);
+ GIT_ASSERT_ARG(pb);
+ GIT_ASSERT_ARG(id);
if ((error = git_object_lookup(&obj, pb->repo, id, GIT_OBJECT_ANY)) < 0)
return error;
@@ -1727,7 +1732,8 @@ int git_packbuilder_insert_walk(git_packbuilder *pb, git_revwalk *walk)
git_oid id;
struct walk_object *obj;
- assert(pb && walk);
+ GIT_ASSERT_ARG(pb);
+ GIT_ASSERT_ARG(walk);
if ((error = mark_edges_uninteresting(pb, walk->user_input)) < 0)
return error;
diff --git a/src/pack.c b/src/pack.c
index 4294a6e32..aadf3f2be 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -12,12 +12,13 @@
#include "mwindow.h"
#include "odb.h"
#include "oid.h"
+#include "oidarray.h"
/* Option to bypass checking existence of '.keep' files */
bool git_disable_pack_keep_file_checks = false;
-static int packfile_open(struct git_pack_file *p);
-static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n);
+static int packfile_open_locked(struct git_pack_file *p);
+static off64_t nth_packed_object_offset_locked(struct git_pack_file *p, uint32_t n);
static int packfile_unpack_compressed(
git_rawobj *obj,
struct git_pack_file *p,
@@ -56,7 +57,7 @@ static git_pack_cache_entry *new_cache_object(git_rawobj *source)
if (!e)
return NULL;
- git_atomic_inc(&e->refcount);
+ git_atomic32_inc(&e->refcount);
memcpy(&e->raw, source, sizeof(git_rawobj));
return e;
@@ -67,7 +68,6 @@ static void free_cache_object(void *o)
git_pack_cache_entry *e = (git_pack_cache_entry *)o;
if (e != NULL) {
- assert(e->refcount.val == 0);
git__free(e->raw.data);
git__free(e);
}
@@ -114,7 +114,7 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, off64_t offset)
return NULL;
if ((entry = git_offmap_get(cache->entries, offset)) != NULL) {
- git_atomic_inc(&entry->refcount);
+ git_atomic32_inc(&entry->refcount);
entry->last_usage = cache->use_ctr++;
}
git_mutex_unlock(&cache->lock);
@@ -129,7 +129,7 @@ static void free_lowest_entry(git_pack_cache *cache)
git_pack_cache_entry *entry;
git_offmap_foreach(cache->entries, offset, entry, {
- if (entry && entry->refcount.val == 0) {
+ if (entry && git_atomic32_get(&entry->refcount) == 0) {
cache->memory_used -= entry->raw.len;
git_offmap_delete(cache->entries, offset);
free_cache_object(entry);
@@ -196,7 +196,8 @@ static void pack_index_free(struct git_pack_file *p)
}
}
-static int pack_index_check(const char *path, struct git_pack_file *p)
+/* Run with the packfile lock held */
+static int pack_index_check_locked(const char *path, struct git_pack_file *p)
{
struct git_pack_idx_header *hdr;
uint32_t version, nr, i, *index;
@@ -302,40 +303,36 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
return 0;
}
-static int pack_index_open(struct git_pack_file *p)
+/* Run with the packfile lock held */
+static int pack_index_open_locked(struct git_pack_file *p)
{
int error = 0;
size_t name_len;
- git_buf idx_name;
+ git_buf idx_name = GIT_BUF_INIT;
if (p->index_version > -1)
- return 0;
+ goto cleanup;
+ /* checked by git_pack_file alloc */
name_len = strlen(p->pack_name);
- assert(name_len > strlen(".pack")); /* checked by git_pack_file alloc */
+ GIT_ASSERT(name_len > strlen(".pack"));
- if (git_buf_init(&idx_name, name_len) < 0)
- return -1;
+ if ((error = git_buf_init(&idx_name, name_len)) < 0)
+ goto cleanup;
git_buf_put(&idx_name, p->pack_name, name_len - strlen(".pack"));
git_buf_puts(&idx_name, ".idx");
if (git_buf_oom(&idx_name)) {
- git_buf_dispose(&idx_name);
- return -1;
- }
-
- if ((error = git_mutex_lock(&p->lock)) < 0) {
- git_buf_dispose(&idx_name);
- return error;
+ error = -1;
+ goto cleanup;
}
if (p->index_version == -1)
- error = pack_index_check(idx_name.ptr, p);
+ error = pack_index_check_locked(idx_name.ptr, p);
+cleanup:
git_buf_dispose(&idx_name);
- git_mutex_unlock(&p->lock);
-
return error;
}
@@ -345,8 +342,20 @@ static unsigned char *pack_window_open(
off64_t offset,
unsigned int *left)
{
- if (p->mwf.fd == -1 && packfile_open(p) < 0)
+ unsigned char *pack_data = NULL;
+
+ if (git_mutex_lock(&p->lock) < 0) {
+ git_error_set(GIT_ERROR_THREAD, "unable to lock packfile");
+ return NULL;
+ }
+ if (git_mutex_lock(&p->mwf.lock) < 0) {
+ git_mutex_unlock(&p->lock);
+ git_error_set(GIT_ERROR_THREAD, "unable to lock packfile");
return NULL;
+ }
+
+ if (p->mwf.fd == -1 && packfile_open_locked(p) < 0)
+ goto cleanup;
/* Since packfiles end in a hash of their content and it's
* pointless to ask for an offset into the middle of that
@@ -357,11 +366,16 @@ static unsigned char *pack_window_open(
* around.
*/
if (offset > (p->mwf.size - 20))
- return NULL;
+ goto cleanup;
if (offset < 0)
- return NULL;
+ goto cleanup;
+
+ pack_data = git_mwindow_open(&p->mwf, w_cursor, offset, 20, left);
- return git_mwindow_open(&p->mwf, w_cursor, offset, 20, left);
+cleanup:
+ git_mutex_unlock(&p->mwf.lock);
+ git_mutex_unlock(&p->lock);
+ return pack_data;
}
/*
@@ -372,12 +386,12 @@ static unsigned char *pack_window_open(
* - each byte afterwards: low seven bits are size continuation,
* with the high bit being "size continues"
*/
-size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_object_t type)
+int git_packfile__object_header(size_t *out, unsigned char *hdr, size_t size, git_object_t type)
{
unsigned char *hdr_base;
unsigned char c;
- assert(type >= GIT_OBJECT_COMMIT && type <= GIT_OBJECT_REF_DELTA);
+ GIT_ASSERT_ARG(type >= GIT_OBJECT_COMMIT && type <= GIT_OBJECT_REF_DELTA);
/* TODO: add support for chunked objects; see git.git 6c0d19b1 */
@@ -392,7 +406,8 @@ size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_object_t
}
*hdr++ = c;
- return (hdr - hdr_base);
+ *out = (hdr - hdr_base);
+ return 0;
}
@@ -436,14 +451,27 @@ static int packfile_unpack_header1(
int git_packfile_unpack_header(
size_t *size_p,
git_object_t *type_p,
- git_mwindow_file *mwf,
+ struct git_pack_file *p,
git_mwindow **w_curs,
off64_t *curpos)
{
unsigned char *base;
unsigned int left;
unsigned long used;
- int ret;
+ int error;
+
+ if ((error = git_mutex_lock(&p->lock)) < 0)
+ return error;
+ if ((error = git_mutex_lock(&p->mwf.lock)) < 0) {
+ git_mutex_unlock(&p->lock);
+ return error;
+ }
+
+ if (p->mwf.fd == -1 && (error = packfile_open_locked(p)) < 0) {
+ git_mutex_unlock(&p->lock);
+ git_mutex_unlock(&p->mwf.lock);
+ return error;
+ }
/* pack_window_open() assures us we have [base, base + 20) available
* as a range that we can look at at. (Its actually the hash
@@ -451,16 +479,17 @@ int git_packfile_unpack_header(
* the maximum deflated object size is 2^137, which is just
* insane, so we know won't exceed what we have been given.
*/
-/* base = pack_window_open(p, w_curs, *curpos, &left); */
- base = git_mwindow_open(mwf, w_curs, *curpos, 20, &left);
+ base = git_mwindow_open(&p->mwf, w_curs, *curpos, 20, &left);
+ git_mutex_unlock(&p->lock);
+ git_mutex_unlock(&p->mwf.lock);
if (base == NULL)
return GIT_EBUFS;
- ret = packfile_unpack_header1(&used, size_p, type_p, base, left);
+ error = packfile_unpack_header1(&used, size_p, type_p, base, left);
git_mwindow_close(w_curs);
- if (ret == GIT_EBUFS)
- return ret;
- else if (ret < 0)
+ if (error == GIT_EBUFS)
+ return error;
+ else if (error < 0)
return packfile_error("header length is zero");
*curpos += used;
@@ -480,7 +509,27 @@ int git_packfile_resolve_header(
off64_t base_offset;
int error;
- error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
+ error = git_mutex_lock(&p->lock);
+ if (error < 0) {
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
+ return error;
+ }
+ error = git_mutex_lock(&p->mwf.lock);
+ if (error < 0) {
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
+ git_mutex_unlock(&p->lock);
+ return error;
+ }
+
+ if (p->mwf.fd == -1 && (error = packfile_open_locked(p)) < 0) {
+ git_mutex_unlock(&p->mwf.lock);
+ git_mutex_unlock(&p->lock);
+ return error;
+ }
+ git_mutex_unlock(&p->mwf.lock);
+ git_mutex_unlock(&p->lock);
+
+ error = git_packfile_unpack_header(&size, &type, p, &w_curs, &curpos);
if (error < 0)
return error;
@@ -507,7 +556,7 @@ int git_packfile_resolve_header(
while (type == GIT_OBJECT_OFS_DELTA || type == GIT_OBJECT_REF_DELTA) {
curpos = base_offset;
- error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
+ error = git_packfile_unpack_header(&size, &type, p, &w_curs, &curpos);
if (error < 0)
return error;
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,
elem->base_key = obj_offset;
- error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
-
+ error = git_packfile_unpack_header(&size, &type, p, &w_curs, &curpos);
if (error < 0)
goto on_error;
@@ -630,6 +678,25 @@ int git_packfile_unpack(
size_t stack_size = 0, elem_pos, alloclen;
git_object_t base_type;
+ error = git_mutex_lock(&p->lock);
+ if (error < 0) {
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
+ return error;
+ }
+ error = git_mutex_lock(&p->mwf.lock);
+ if (error < 0) {
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
+ git_mutex_unlock(&p->lock);
+ return error;
+ }
+
+ if (p->mwf.fd == -1)
+ error = packfile_open_locked(p);
+ git_mutex_unlock(&p->mwf.lock);
+ git_mutex_unlock(&p->lock);
+ if (error < 0)
+ return error;
+
/*
* TODO: optionally check the CRC on the packfile
*/
@@ -692,7 +759,7 @@ int git_packfile_unpack(
GIT_ERROR_CHECK_ALLOC(obj->data);
memcpy(obj->data, data, obj->len + 1);
- git_atomic_dec(&cached->refcount);
+ git_atomic32_dec(&cached->refcount);
goto cleanup;
}
@@ -740,7 +807,7 @@ int git_packfile_unpack(
}
if (cached) {
- git_atomic_dec(&cached->refcount);
+ git_atomic32_dec(&cached->refcount);
cached = NULL;
}
@@ -754,7 +821,7 @@ cleanup:
if (error < 0) {
git__free(obj->data);
if (cached)
- git_atomic_dec(&cached->refcount);
+ git_atomic32_dec(&cached->refcount);
}
if (elem)
@@ -841,10 +908,13 @@ static int packfile_unpack_compressed(
do {
size_t bytes = buffer_len - total;
- unsigned int window_len;
+ unsigned int window_len, consumed;
unsigned char *in;
- in = pack_window_open(p, mwindow, *position, &window_len);
+ if ((in = pack_window_open(p, mwindow, *position, &window_len)) == NULL) {
+ error = -1;
+ goto out;
+ }
if ((error = git_zstream_set_input(&zstream, in, window_len)) < 0 ||
(error = git_zstream_get_output_chunk(data + total, &bytes, &zstream)) < 0) {
@@ -854,9 +924,17 @@ static int packfile_unpack_compressed(
git_mwindow_close(mwindow);
- *position += window_len - zstream.in_len;
+ consumed = window_len - (unsigned int)zstream.in_len;
+
+ if (!bytes && !consumed) {
+ git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream");
+ error = -1;
+ goto out;
+ }
+
+ *position += consumed;
total += bytes;
- } while (total < size);
+ } while (!git_zstream_eos(&zstream));
if (total != size || !git_zstream_eos(&zstream)) {
git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream");
@@ -893,7 +971,7 @@ int get_delta_base(
off64_t base_offset;
git_oid unused;
- assert(delta_base_out);
+ GIT_ASSERT_ARG(delta_base_out);
base_info = pack_window_open(p, w_curs, *curpos, &left);
/* Assumption: the only reason this would fail is because the file is too small */
@@ -965,63 +1043,63 @@ int get_delta_base(
*
***********************************************************/
-void git_packfile_close(struct git_pack_file *p, bool unlink_packfile)
+void git_packfile_free(struct git_pack_file *p, bool unlink_packfile)
{
+ bool locked = true;
+
+ if (!p)
+ return;
+
+ cache_free(&p->bases);
+
+ if (git_mutex_lock(&p->lock) < 0) {
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile");
+ locked = false;
+ }
if (p->mwf.fd >= 0) {
- git_mwindow_free_all_locked(&p->mwf);
+ git_mwindow_free_all(&p->mwf);
p_close(p->mwf.fd);
p->mwf.fd = -1;
}
+ if (locked)
+ git_mutex_unlock(&p->lock);
if (unlink_packfile)
p_unlink(p->pack_name);
-}
-
-void git_packfile_free(struct git_pack_file *p)
-{
- if (!p)
- return;
-
- cache_free(&p->bases);
-
- git_packfile_close(p, false);
pack_index_free(p);
git__free(p->bad_object_sha1);
- git_mutex_free(&p->lock);
git_mutex_free(&p->bases.lock);
+ git_mutex_free(&p->mwf.lock);
+ git_mutex_free(&p->lock);
git__free(p);
}
-static int packfile_open(struct git_pack_file *p)
+/* Run with the packfile and mwf locks held */
+static int packfile_open_locked(struct git_pack_file *p)
{
struct stat st;
struct git_pack_header hdr;
git_oid sha1;
unsigned char *idx_sha1;
- if (p->index_version == -1 && pack_index_open(p) < 0)
+ if (pack_index_open_locked(p) < 0)
return git_odb__error_notfound("failed to open packfile", NULL, 0);
- /* if mwf opened by another thread, return now */
- if (git_mutex_lock(&p->lock) < 0)
- return packfile_error("failed to get lock for open");
-
- if (p->mwf.fd >= 0) {
- git_mutex_unlock(&p->lock);
+ if (p->mwf.fd >= 0)
return 0;
- }
/* TODO: open with noatime */
p->mwf.fd = git_futils_open_ro(p->pack_name);
if (p->mwf.fd < 0)
goto cleanup;
- if (p_fstat(p->mwf.fd, &st) < 0 ||
- git_mwindow_file_register(&p->mwf) < 0)
+ if (p_fstat(p->mwf.fd, &st) < 0) {
+ git_error_set(GIT_ERROR_OS, "could not stat packfile");
goto cleanup;
+ }
/* If we created the struct before we had the pack we lack size. */
if (!p->mwf.size) {
@@ -1052,8 +1130,7 @@ static int packfile_open(struct git_pack_file *p)
/* Verify the pack matches its index. */
if (p->num_objects != ntohl(hdr.hdr_entries) ||
- p_lseek(p->mwf.fd, p->mwf.size - GIT_OID_RAWSZ, SEEK_SET) == -1 ||
- p_read(p->mwf.fd, sha1.id, GIT_OID_RAWSZ) < 0)
+ p_pread(p->mwf.fd, sha1.id, GIT_OID_RAWSZ, p->mwf.size - GIT_OID_RAWSZ) < 0)
goto cleanup;
idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
@@ -1061,7 +1138,9 @@ static int packfile_open(struct git_pack_file *p)
if (git_oid__cmp(&sha1, (git_oid *)idx_sha1) != 0)
goto cleanup;
- git_mutex_unlock(&p->lock);
+ if (git_mwindow_file_register(&p->mwf) < 0)
+ goto cleanup;
+
return 0;
cleanup:
@@ -1071,8 +1150,6 @@ cleanup:
p_close(p->mwf.fd);
p->mwf.fd = -1;
- git_mutex_unlock(&p->lock);
-
return -1;
}
@@ -1142,13 +1219,22 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
p->mtime = (git_time_t)st.st_mtime;
p->index_version = -1;
- if (git_mutex_init(&p->lock)) {
+ if (git_mutex_init(&p->lock) < 0) {
git_error_set(GIT_ERROR_OS, "failed to initialize packfile mutex");
git__free(p);
return -1;
}
+ if (git_mutex_init(&p->mwf.lock) < 0) {
+ git_error_set(GIT_ERROR_OS, "failed to initialize packfile window mutex");
+ git_mutex_free(&p->lock);
+ git__free(p);
+ return -1;
+ }
+
if (cache_init(&p->bases) < 0) {
+ git_mutex_free(&p->mwf.lock);
+ git_mutex_free(&p->lock);
git__free(p);
return -1;
}
@@ -1164,28 +1250,29 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
*
***********************************************************/
-static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n)
+static off64_t nth_packed_object_offset_locked(struct git_pack_file *p, uint32_t n)
{
- const unsigned char *index = p->index_map.data;
- const unsigned char *end = index + p->index_map.len;
+ const unsigned char *index, *end;
+ uint32_t off32;
+
+ index = p->index_map.data;
+ end = index + p->index_map.len;
index += 4 * 256;
- if (p->index_version == 1) {
+ if (p->index_version == 1)
return ntohl(*((uint32_t *)(index + 24 * n)));
- } else {
- uint32_t off;
- index += 8 + p->num_objects * (20 + 4);
- off = ntohl(*((uint32_t *)(index + 4 * n)));
- if (!(off & 0x80000000))
- return off;
- index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
-
- /* Make sure we're not being sent out of bounds */
- if (index >= end - 8)
- return -1;
- return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
- ntohl(*((uint32_t *)(index + 4)));
- }
+ index += 8 + p->num_objects * (20 + 4);
+ off32 = ntohl(*((uint32_t *)(index + 4 * n)));
+ if (!(off32 & 0x80000000))
+ return off32;
+ index += p->num_objects * 4 + (off32 & 0x7fffffff) * 8;
+
+ /* Make sure we're not being sent out of bounds */
+ if (index >= end - 8)
+ return -1;
+
+ return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
+ ntohl(*((uint32_t *)(index + 4)));
}
static int git__memcmp4(const void *a, const void *b) {
@@ -1197,33 +1284,45 @@ int git_pack_foreach_entry(
git_odb_foreach_cb cb,
void *data)
{
- const unsigned char *index = p->index_map.data, *current;
+ const unsigned char *index, *current;
uint32_t i;
int error = 0;
+ git_array_oid_t oids = GIT_ARRAY_INIT;
+ git_oid *oid;
- if (index == NULL) {
- if ((error = pack_index_open(p)) < 0)
- return error;
+ if (git_mutex_lock(&p->lock) < 0)
+ return packfile_error("failed to get lock for git_pack_foreach_entry");
- assert(p->index_map.data);
+ if ((error = pack_index_open_locked(p)) < 0) {
+ git_mutex_unlock(&p->lock);
+ return error;
+ }
- index = p->index_map.data;
+ if (!p->index_map.data) {
+ git_error_set(GIT_ERROR_INTERNAL, "internal error: p->index_map.data == NULL");
+ git_mutex_unlock(&p->lock);
+ return -1;
}
- if (p->index_version > 1) {
+ index = p->index_map.data;
+
+ if (p->index_version > 1)
index += 8;
- }
index += 4 * 256;
if (p->oids == NULL) {
git_vector offsets, oids;
- if ((error = git_vector_init(&oids, p->num_objects, NULL)))
+ if ((error = git_vector_init(&oids, p->num_objects, NULL))) {
+ git_mutex_unlock(&p->lock);
return error;
+ }
- if ((error = git_vector_init(&offsets, p->num_objects, git__memcmp4)))
+ if ((error = git_vector_init(&offsets, p->num_objects, git__memcmp4))) {
+ git_mutex_unlock(&p->lock);
return error;
+ }
if (p->index_version > 1) {
const unsigned char *off = index + 24 * p->num_objects;
@@ -1244,21 +1343,115 @@ int git_pack_foreach_entry(
p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids);
}
- for (i = 0; i < p->num_objects; i++)
- if ((error = cb(p->oids[i], data)) != 0)
- return git_error_set_after_callback(error);
+ /* We need to copy the OIDs to another array before we relinquish the lock to avoid races. */
+ git_array_init_to_size(oids, p->num_objects);
+ if (!oids.ptr) {
+ git_mutex_unlock(&p->lock);
+ git_array_clear(oids);
+ GIT_ERROR_CHECK_ARRAY(oids);
+ }
+ for (i = 0; i < p->num_objects; i++) {
+ oid = git_array_alloc(oids);
+ if (!oid) {
+ git_mutex_unlock(&p->lock);
+ git_array_clear(oids);
+ GIT_ERROR_CHECK_ALLOC(oid);
+ }
+ git_oid_cpy(oid, p->oids[i]);
+ }
+
+ git_mutex_unlock(&p->lock);
+
+ git_array_foreach(oids, i, oid) {
+ if ((error = cb(oid, data)) != 0) {
+ git_error_set_after_callback(error);
+ break;
+ }
+ }
+
+ git_array_clear(oids);
+ return error;
+}
+
+int git_pack_foreach_entry_offset(
+ struct git_pack_file *p,
+ git_pack_foreach_entry_offset_cb cb,
+ void *data)
+{
+ const unsigned char *index;
+ off64_t current_offset;
+ const git_oid *current_oid;
+ uint32_t i;
+ int error = 0;
+
+ if (git_mutex_lock(&p->lock) < 0)
+ return packfile_error("failed to get lock for git_pack_foreach_entry_offset");
+
+ index = p->index_map.data;
+ if (index == NULL) {
+ if ((error = pack_index_open_locked(p)) < 0)
+ goto cleanup;
+
+ if (!p->index_map.data) {
+ git_error_set(GIT_ERROR_INTERNAL, "internal error: p->index_map.data == NULL");
+ goto cleanup;
+ }
+
+ index = p->index_map.data;
+ }
+
+ if (p->index_version > 1)
+ index += 8;
+
+ index += 4 * 256;
+
+ /* all offsets should have been validated by pack_index_check_locked */
+ if (p->index_version > 1) {
+ const unsigned char *offsets = index + 24 * p->num_objects;
+ const unsigned char *large_offset_ptr;
+ const unsigned char *large_offsets = index + 28 * p->num_objects;
+ const unsigned char *large_offsets_end = ((const unsigned char *)p->index_map.data) + p->index_map.len - 20;
+ for (i = 0; i < p->num_objects; i++) {
+ current_offset = ntohl(*(const uint32_t *)(offsets + 4 * i));
+ if (current_offset & 0x80000000) {
+ large_offset_ptr = large_offsets + (current_offset & 0x7fffffff) * 8;
+ if (large_offset_ptr >= large_offsets_end) {
+ error = packfile_error("invalid large offset");
+ goto cleanup;
+ }
+ current_offset = (((off64_t)ntohl(*((uint32_t *)(large_offset_ptr + 0)))) << 32) |
+ ntohl(*((uint32_t *)(large_offset_ptr + 4)));
+ }
+ current_oid = (const git_oid *)(index + 20 * i);
+ if ((error = cb(current_oid, current_offset, data)) != 0) {
+ error = git_error_set_after_callback(error);
+ goto cleanup;
+ }
+ }
+ } else {
+ for (i = 0; i < p->num_objects; i++) {
+ current_offset = ntohl(*(const uint32_t *)(index + 24 * i));
+ current_oid = (const git_oid *)(index + 24 * i + 4);
+ if ((error = cb(current_oid, current_offset, data)) != 0) {
+ error = git_error_set_after_callback(error);
+ goto cleanup;
+ }
+ }
+ }
+cleanup:
+ git_mutex_unlock(&p->lock);
return error;
}
-static int sha1_position(const void *table, size_t stride, unsigned lo,
- unsigned hi, const unsigned char *key)
+int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned lo,
+ unsigned hi, const unsigned char *oid_prefix)
{
- const unsigned char *base = table;
+ const unsigned char *base = oid_lookup_table;
while (lo < hi) {
unsigned mi = (lo + hi) / 2;
- int cmp = git_oid__hashcmp(base + mi * stride, key);
+ int cmp = git_oid__hashcmp(base + mi * stride, oid_prefix);
if (!cmp)
return mi;
@@ -1285,15 +1478,19 @@ static int pack_entry_find_offset(
int pos, found = 0;
off64_t offset;
const unsigned char *current = 0;
+ int error = 0;
*offset_out = 0;
- if (p->index_version == -1) {
- int error;
+ if (git_mutex_lock(&p->lock) < 0)
+ return packfile_error("failed to get lock for pack_entry_find_offset");
- if ((error = pack_index_open(p)) < 0)
- return error;
- assert(p->index_map.data);
+ if ((error = pack_index_open_locked(p)) < 0)
+ goto cleanup;
+
+ if (!p->index_map.data) {
+ git_error_set(GIT_ERROR_INTERNAL, "internal error: p->index_map.data == NULL");
+ goto cleanup;
}
index = p->index_map.data;
@@ -1320,7 +1517,7 @@ static int pack_entry_find_offset(
short_oid->id[0], short_oid->id[1], short_oid->id[2], lo, hi, p->num_objects);
#endif
- pos = sha1_position(index, stride, lo, hi, short_oid->id);
+ pos = git_pack__lookup_sha1(index, stride, lo, hi, short_oid->id);
if (pos >= 0) {
/* An object matching exactly the oid was found */
@@ -1347,14 +1544,19 @@ static int pack_entry_find_offset(
}
}
- if (!found)
- return git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
- if (found > 1)
- return git_odb__error_ambiguous("found multiple offsets for pack entry");
+ if (!found) {
+ error = git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
+ goto cleanup;
+ }
+ if (found > 1) {
+ error = git_odb__error_ambiguous("found multiple offsets for pack entry");
+ goto cleanup;
+ }
- if ((offset = nth_packed_object_offset(p, pos)) < 0) {
+ if ((offset = nth_packed_object_offset_locked(p, pos)) < 0) {
git_error_set(GIT_ERROR_ODB, "packfile index is corrupt");
- return -1;
+ error = -1;
+ goto cleanup;
}
*offset_out = offset;
@@ -1369,7 +1571,9 @@ static int pack_entry_find_offset(
}
#endif
- return 0;
+cleanup:
+ git_mutex_unlock(&p->lock);
+ return error;
}
int git_pack_entry_find(
@@ -1382,7 +1586,7 @@ int git_pack_entry_find(
git_oid found_oid;
int error;
- assert(p);
+ GIT_ASSERT_ARG(p);
if (len == GIT_OID_HEXSZ && p->num_bad_objects) {
unsigned i;
@@ -1395,10 +1599,26 @@ int git_pack_entry_find(
if (error < 0)
return error;
+ error = git_mutex_lock(&p->lock);
+ if (error < 0) {
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
+ return error;
+ }
+ error = git_mutex_lock(&p->mwf.lock);
+ if (error < 0) {
+ git_mutex_unlock(&p->lock);
+ git_error_set(GIT_ERROR_OS, "failed to lock packfile reader");
+ return error;
+ }
+
/* we found a unique entry in the index;
* make sure the packfile backing the index
* still exists on disk */
- if (p->mwf.fd == -1 && (error = packfile_open(p)) < 0)
+ if (p->mwf.fd == -1)
+ error = packfile_open_locked(p);
+ git_mutex_unlock(&p->mwf.lock);
+ git_mutex_unlock(&p->lock);
+ if (error < 0)
return error;
e->offset = offset;
diff --git a/src/pack.h b/src/pack.h
index 17ae72228..bf279c6b6 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -20,6 +20,14 @@
#include "oidmap.h"
#include "zstream.h"
+/**
+ * Function type for callbacks from git_pack_foreach_entry_offset.
+ */
+typedef int git_pack_foreach_entry_offset_cb(
+ const git_oid *id,
+ off64_t offset,
+ void *payload);
+
#define GIT_PACK_FILE_MODE 0444
#define PACK_SIGNATURE 0x5041434b /* "PACK" */
@@ -58,7 +66,7 @@ struct git_pack_idx_header {
typedef struct git_pack_cache_entry {
size_t last_usage; /* enough? */
- git_atomic refcount;
+ git_atomic32 refcount;
git_rawobj raw;
} git_pack_cache_entry;
@@ -85,8 +93,8 @@ typedef struct {
struct git_pack_file {
git_mwindow_file mwf;
git_map index_map;
- git_mutex lock; /* protect updates to mwf and index_map */
- git_atomic refcount;
+ git_mutex lock; /* protect updates to index_map */
+ git_atomic32 refcount;
uint32_t num_objects;
uint32_t num_bad_objects;
@@ -106,6 +114,19 @@ struct git_pack_file {
char pack_name[GIT_FLEX_ARRAY]; /* more */
};
+/**
+ * Return the position where an OID (or a prefix) would be inserted within the
+ * OID Lookup Table of an .idx file. This performs binary search between the lo
+ * and hi indices.
+ *
+ * The stride parameter is provided because .idx files version 1 store the OIDs
+ * interleaved with the 4-byte file offsets of the objects within the .pack
+ * file (stride = 24), whereas files with version 2 store them in a contiguous
+ * flat array (stride = 20).
+ */
+int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned lo,
+ unsigned hi, const unsigned char *oid_prefix);
+
struct git_pack_entry {
off64_t offset;
git_oid sha1;
@@ -120,14 +141,14 @@ typedef struct git_packfile_stream {
git_mwindow *mw;
} git_packfile_stream;
-size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_object_t type);
+int git_packfile__object_header(size_t *out, unsigned char *hdr, size_t size, git_object_t type);
int git_packfile__name(char **out, const char *path);
int git_packfile_unpack_header(
size_t *size_p,
git_object_t *type_p,
- git_mwindow_file *mwf,
+ struct git_pack_file *p,
git_mwindow **w_curs,
off64_t *curpos);
@@ -151,8 +172,7 @@ int get_delta_base(
git_object_t type,
off64_t delta_obj_offset);
-void git_packfile_close(struct git_pack_file *p, bool unlink_packfile);
-void git_packfile_free(struct git_pack_file *p);
+void git_packfile_free(struct git_pack_file *p, bool unlink_packfile);
int git_packfile_alloc(struct git_pack_file **pack_out, const char *path);
int git_pack_entry_find(
@@ -164,5 +184,16 @@ int git_pack_foreach_entry(
struct git_pack_file *p,
git_odb_foreach_cb cb,
void *data);
+/**
+ * Similar to git_pack_foreach_entry, but:
+ * - It also provides the offset of the object within the
+ * packfile.
+ * - It does not sort the objects in any order.
+ * - It retains the lock while invoking the callback.
+ */
+int git_pack_foreach_entry_offset(
+ struct git_pack_file *p,
+ git_pack_foreach_entry_offset_cb cb,
+ void *data);
#endif
diff --git a/src/patch.c b/src/patch.c
index 82181bb3d..f02c928de 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -65,7 +65,7 @@ size_t git_patch_size(
{
size_t out;
- assert(patch);
+ GIT_ASSERT_ARG(patch);
out = patch->content_size;
@@ -129,13 +129,13 @@ int git_patch_line_stats(
const git_diff_delta *git_patch_get_delta(const git_patch *patch)
{
- assert(patch);
+ GIT_ASSERT_ARG_WITH_RETVAL(patch, NULL);
return patch->delta;
}
size_t git_patch_num_hunks(const git_patch *patch)
{
- assert(patch);
+ GIT_ASSERT_ARG(patch);
return git_array_size(patch->hunks);
}
@@ -152,7 +152,7 @@ int git_patch_get_hunk(
size_t hunk_idx)
{
git_patch_hunk *hunk;
- assert(patch);
+ GIT_ASSERT_ARG(patch);
hunk = git_array_get(patch->hunks, hunk_idx);
@@ -170,7 +170,7 @@ int git_patch_get_hunk(
int git_patch_num_lines_in_hunk(const git_patch *patch, size_t hunk_idx)
{
git_patch_hunk *hunk;
- assert(patch);
+ GIT_ASSERT_ARG(patch);
if (!(hunk = git_array_get(patch->hunks, hunk_idx)))
return patch_error_outofrange("hunk");
@@ -186,7 +186,7 @@ int git_patch_get_line_in_hunk(
git_patch_hunk *hunk;
git_diff_line *line;
- assert(patch);
+ GIT_ASSERT_ARG(patch);
if (!(hunk = git_array_get(patch->hunks, hunk_idx))) {
if (out) *out = NULL;
@@ -204,9 +204,16 @@ int git_patch_get_line_in_hunk(
return 0;
}
+git_repository *git_patch_owner(const git_patch *patch)
+{
+ return patch->repo;
+}
+
int git_patch_from_diff(git_patch **out, git_diff *diff, size_t idx)
{
- assert(out && diff && diff->patch_fn);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(diff);
+ GIT_ASSERT_ARG(diff->patch_fn);
return diff->patch_fn(out, diff, idx);
}
diff --git a/src/patch_generate.c b/src/patch_generate.c
index 18256d076..38cd714a9 100644
--- a/src/patch_generate.c
+++ b/src/patch_generate.c
@@ -209,9 +209,7 @@ static int patch_generated_load(git_patch_generated *patch, git_patch_generated_
if ((error = git_diff_file_content__load(
&patch->ofile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->ofile.file))
- goto cleanup;
- if ((error = git_diff_file_content__load(
+ (error = git_diff_file_content__load(
&patch->nfile, &patch->base.diff_opts)) < 0 ||
should_skip_binary(patch, patch->nfile.file))
goto cleanup;
@@ -563,7 +561,7 @@ static int patch_from_sources(
patch_generated_with_delta *pd;
git_xdiff_output xo;
- assert(out);
+ GIT_ASSERT_ARG(out);
*out = NULL;
if ((error = patch_generated_with_delta_alloc(
@@ -842,7 +840,7 @@ static int patch_generated_line_cb(
GIT_UNUSED(hunk_);
hunk = git_array_last(patch->base.hunks);
- assert(hunk); /* programmer error if no hunk is available */
+ GIT_ASSERT(hunk); /* programmer error if no hunk is available */
line = git_array_alloc(patch->base.lines);
GIT_ERROR_CHECK_ALLOC(line);
diff --git a/src/patch_parse.c b/src/patch_parse.c
index 918575306..2cc5c5995 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -198,7 +198,7 @@ static int parse_header_git_index(
return -1;
if (git_parse_peek(&c, &ctx->parse_ctx, 0) == 0 && c == ' ') {
- uint16_t mode;
+ uint16_t mode = 0;
git_parse_advance_chars(&ctx->parse_ctx, 1);
@@ -407,6 +407,7 @@ static const parse_header_transition transitions[] = {
{ "--- " , STATE_DIFF, STATE_PATH, parse_header_git_oldpath },
{ "--- " , STATE_INDEX, STATE_PATH, parse_header_git_oldpath },
+ { "--- " , STATE_FILEMODE, STATE_PATH, parse_header_git_oldpath },
{ "+++ " , STATE_PATH, STATE_END, parse_header_git_newpath },
{ "GIT binary patch" , STATE_INDEX, STATE_END, NULL },
{ "Binary files " , STATE_INDEX, STATE_END, NULL },
@@ -1167,7 +1168,8 @@ int git_patch_parse(
size_t start, used;
int error = 0;
- assert(out && ctx);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(ctx);
*out = NULL;
diff --git a/src/path.c b/src/path.c
index 0d0b40f9c..c444b31a7 100644
--- a/src/path.c
+++ b/src/path.c
@@ -274,24 +274,6 @@ size_t git_path_basename_offset(git_buf *buffer)
return 0;
}
-const char *git_path_topdir(const char *path)
-{
- size_t len;
- ssize_t i;
-
- assert(path);
- len = strlen(path);
-
- if (!len || path[len - 1] != '/')
- return NULL;
-
- for (i = (ssize_t)len - 2; i >= 0; --i)
- if (path[i] == '/')
- break;
-
- return &path[i + 1];
-}
-
int git_path_root(const char *path)
{
int offset = 0, prefix_len;
@@ -325,7 +307,9 @@ int git_path_root(const char *path)
static void path_trim_slashes(git_buf *path)
{
int ceiling = git_path_root(path->ptr) + 1;
- assert(ceiling >= 0);
+
+ if (ceiling < 0)
+ return;
while (path->size > (size_t)ceiling) {
if (path->ptr[path->size-1] != '/')
@@ -341,7 +325,8 @@ int git_path_join_unrooted(
{
ssize_t root;
- assert(path && path_out);
+ GIT_ASSERT_ARG(path_out);
+ GIT_ASSERT_ARG(path);
root = (ssize_t)git_path_root(path);
@@ -389,7 +374,8 @@ int git_path_prettify(git_buf *path_out, const char *path, const char *base)
{
char buf[GIT_PATH_MAX];
- assert(path && path_out);
+ GIT_ASSERT_ARG(path_out);
+ GIT_ASSERT_ARG(path);
/* construct path if needed */
if (base != NULL && git_path_root(path) < 0) {
@@ -427,7 +413,7 @@ int git_path_to_dir(git_buf *path)
return git_buf_oom(path) ? -1 : 0;
}
-void git_path_string_to_dir(char* path, size_t size)
+void git_path_string_to_dir(char *path, size_t size)
{
size_t end = strlen(path);
@@ -440,7 +426,9 @@ void git_path_string_to_dir(char* path, size_t size)
int git__percent_decode(git_buf *decoded_out, const char *input)
{
int len, hi, lo, i;
- assert(decoded_out && input);
+
+ GIT_ASSERT_ARG(decoded_out);
+ GIT_ASSERT_ARG(input);
len = (int)strlen(input);
git_buf_clear(decoded_out);
@@ -501,7 +489,8 @@ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
{
int offset;
- assert(local_path_out && file_url);
+ GIT_ASSERT_ARG(local_path_out);
+ GIT_ASSERT_ARG(file_url);
if ((offset = local_file_url_prefixlen(file_url)) < 0 ||
file_url[offset] == '\0' || file_url[offset] == '/')
@@ -526,7 +515,8 @@ int git_path_walk_up(
ssize_t stop = 0, scan;
char oldc = '\0';
- assert(path && cb);
+ GIT_ASSERT_ARG(path);
+ GIT_ASSERT_ARG(cb);
if (ceiling != NULL) {
if (git__prefixcmp(path->ptr, ceiling) == 0)
@@ -581,7 +571,7 @@ int git_path_walk_up(
bool git_path_exists(const char *path)
{
- assert(path);
+ GIT_ASSERT_ARG_WITH_RETVAL(path, false);
return p_access(path, F_OK) == 0;
}
@@ -598,7 +588,7 @@ bool git_path_isfile(const char *path)
{
struct stat st;
- assert(path);
+ GIT_ASSERT_ARG_WITH_RETVAL(path, false);
if (p_stat(path, &st) < 0)
return false;
@@ -609,7 +599,7 @@ bool git_path_islink(const char *path)
{
struct stat st;
- assert(path);
+ GIT_ASSERT_ARG_WITH_RETVAL(path, false);
if (p_lstat(path, &st) < 0)
return false;
@@ -764,15 +754,13 @@ bool git_path_contains_file(git_buf *base, const char *file)
return _check_dir_contents(base, file, &git_path_isfile);
}
-int git_path_find_dir(git_buf *dir, const char *path, const char *base)
+int git_path_find_dir(git_buf *dir)
{
- int error = git_path_join_unrooted(dir, path, base, NULL);
+ int error = 0;
+ char buf[GIT_PATH_MAX];
- if (!error) {
- char buf[GIT_PATH_MAX];
- if (p_realpath(dir->ptr, buf) != NULL)
- error = git_buf_sets(dir, buf);
- }
+ if (p_realpath(dir->ptr, buf) != NULL)
+ error = git_buf_sets(dir, buf);
/* call dirname if this is not a directory */
if (!error) /* && git_path_isdir(dir->ptr) == false) */
@@ -1211,7 +1199,8 @@ int git_path_diriter_init(
if (is_win7_or_later < 0)
is_win7_or_later = git_has_win32_version(6, 1, 0);
- assert(diriter && path);
+ GIT_ASSERT_ARG(diriter);
+ GIT_ASSERT_ARG(path);
memset(diriter, 0, sizeof(git_path_diriter));
diriter->handle = INVALID_HANDLE_VALUE;
@@ -1311,9 +1300,10 @@ int git_path_diriter_filename(
size_t *out_len,
git_path_diriter *diriter)
{
- assert(out && out_len && diriter);
-
- assert(diriter->path_utf8.size > diriter->parent_utf8_len);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(out_len);
+ GIT_ASSERT_ARG(diriter);
+ GIT_ASSERT(diriter->path_utf8.size > diriter->parent_utf8_len);
*out = &diriter->path_utf8.ptr[diriter->parent_utf8_len+1];
*out_len = diriter->path_utf8.size - diriter->parent_utf8_len - 1;
@@ -1325,7 +1315,9 @@ int git_path_diriter_fullpath(
size_t *out_len,
git_path_diriter *diriter)
{
- assert(out && out_len && diriter);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(out_len);
+ GIT_ASSERT_ARG(diriter);
*out = diriter->path_utf8.ptr;
*out_len = diriter->path_utf8.size;
@@ -1334,7 +1326,8 @@ int git_path_diriter_fullpath(
int git_path_diriter_stat(struct stat *out, git_path_diriter *diriter)
{
- assert(out && diriter);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(diriter);
return git_win32__file_attribute_to_stat(out,
(WIN32_FILE_ATTRIBUTE_DATA *)&diriter->current,
@@ -1361,7 +1354,8 @@ int git_path_diriter_init(
const char *path,
unsigned int flags)
{
- assert(diriter && path);
+ GIT_ASSERT_ARG(diriter);
+ GIT_ASSERT_ARG(path);
memset(diriter, 0, sizeof(git_path_diriter));
@@ -1401,7 +1395,7 @@ int git_path_diriter_next(git_path_diriter *diriter)
bool skip_dot = !(diriter->flags & GIT_PATH_DIR_INCLUDE_DOT_AND_DOTDOT);
int error = 0;
- assert(diriter);
+ GIT_ASSERT_ARG(diriter);
errno = 0;
@@ -1444,9 +1438,10 @@ int git_path_diriter_filename(
size_t *out_len,
git_path_diriter *diriter)
{
- assert(out && out_len && diriter);
-
- assert(diriter->path.size > diriter->parent_len);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(out_len);
+ GIT_ASSERT_ARG(diriter);
+ GIT_ASSERT(diriter->path.size > diriter->parent_len);
*out = &diriter->path.ptr[diriter->parent_len+1];
*out_len = diriter->path.size - diriter->parent_len - 1;
@@ -1458,7 +1453,9 @@ int git_path_diriter_fullpath(
size_t *out_len,
git_path_diriter *diriter)
{
- assert(out && out_len && diriter);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(out_len);
+ GIT_ASSERT_ARG(diriter);
*out = diriter->path.ptr;
*out_len = diriter->path.size;
@@ -1467,7 +1464,8 @@ int git_path_diriter_fullpath(
int git_path_diriter_stat(struct stat *out, git_path_diriter *diriter)
{
- assert(out && diriter);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(diriter);
return git_path_lstat(diriter->path.ptr, out);
}
@@ -1503,7 +1501,8 @@ int git_path_dirload(
char *dup;
int error;
- assert(contents && path);
+ GIT_ASSERT_ARG(contents);
+ GIT_ASSERT_ARG(path);
if ((error = git_path_diriter_init(&iter, path, flags)) < 0)
return error;
@@ -1512,7 +1511,7 @@ int git_path_dirload(
if ((error = git_path_diriter_fullpath(&name, &name_len, &iter)) < 0)
break;
- assert(name_len > prefix_len);
+ GIT_ASSERT(name_len > prefix_len);
dup = git__strndup(name + prefix_len, name_len - prefix_len);
GIT_ERROR_CHECK_ALLOC(dup);
@@ -1561,8 +1560,8 @@ GIT_INLINE(bool) verify_dospath(
static int32_t next_hfs_char(const char **in, size_t *len)
{
while (*len) {
- int32_t codepoint;
- int cp_len = git__utf8_iterate((const uint8_t *)(*in), (int)(*len), &codepoint);
+ uint32_t codepoint;
+ int cp_len = git_utf8_iterate(&codepoint, *in, *len);
if (cp_len < 0)
return -1;
@@ -1594,7 +1593,7 @@ static int32_t next_hfs_char(const char **in, size_t *len)
* the ASCII range, which is perfectly fine, because the
* git folder name can only be composed of ascii characters
*/
- return git__tolower(codepoint);
+ return git__tolower((int)codepoint);
}
return 0; /* NULL byte -- end of string */
}
@@ -1876,7 +1875,7 @@ GIT_INLINE(unsigned int) dotgit_flags(
return flags;
}
-bool git_path_isvalid(
+bool git_path_validate(
git_repository *repo,
const char *path,
uint16_t mode,
@@ -1903,6 +1902,52 @@ bool git_path_isvalid(
return verify_component(repo, start, (c - start), mode, flags);
}
+#ifdef GIT_WIN32
+GIT_INLINE(bool) should_validate_longpaths(git_repository *repo)
+{
+ int longpaths = 0;
+
+ if (repo &&
+ git_repository__configmap_lookup(&longpaths, repo, GIT_CONFIGMAP_LONGPATHS) < 0)
+ longpaths = 0;
+
+ return (longpaths == 0);
+}
+
+#else
+
+GIT_INLINE(bool) should_validate_longpaths(git_repository *repo)
+{
+ GIT_UNUSED(repo);
+
+ return false;
+}
+#endif
+
+int git_path_validate_workdir(git_repository *repo, const char *path)
+{
+ if (should_validate_longpaths(repo))
+ return git_path_validate_filesystem(path, strlen(path));
+
+ return 0;
+}
+
+int git_path_validate_workdir_with_len(
+ git_repository *repo,
+ const char *path,
+ size_t path_len)
+{
+ if (should_validate_longpaths(repo))
+ return git_path_validate_filesystem(path, path_len);
+
+ return 0;
+}
+
+int git_path_validate_workdir_buf(git_repository *repo, git_buf *path)
+{
+ return git_path_validate_workdir_with_len(repo, path->ptr, path->size);
+}
+
int git_path_normalize_slashes(git_buf *out, const char *path)
{
int error;
@@ -2045,7 +2090,7 @@ int git_path_validate_system_file_ownership(const char *path)
git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is not valid");
ret = GIT_ERROR;
}
- free(info);
+ git__free(info);
cleanup:
if (descriptor)
diff --git a/src/path.h b/src/path.h
index ed6b93574..de6ec8ff2 100644
--- a/src/path.h
+++ b/src/path.h
@@ -67,8 +67,6 @@ extern int git_path_basename_r(git_buf *buffer, const char *path);
*/
extern size_t git_path_basename_offset(git_buf *buffer);
-extern const char *git_path_topdir(const char *path);
-
/**
* Find offset to root of path if path has one.
*
@@ -87,7 +85,7 @@ extern int git_path_to_dir(git_buf *path);
/**
* Ensure string has a trailing '/' if there is space for it.
*/
-extern void git_path_string_to_dir(char* path, size_t size);
+extern void git_path_string_to_dir(char *path, size_t size);
/**
* Taken from git.git; returns nonzero if the given path is "." or "..".
@@ -285,7 +283,7 @@ extern int git_path_prettify_dir(git_buf *path_out, const char *path, const char
* appends the trailing '/'. If the path does not exist, it is
* treated like a regular filename.
*/
-extern int git_path_find_dir(git_buf *dir, const char *path, const char *base);
+extern int git_path_find_dir(git_buf *dir);
/**
* Resolve relative references within a path.
@@ -628,21 +626,96 @@ extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or
#define GIT_PATH_REJECT_INDEX_DEFAULTS \
GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT
-/*
- * Determine whether a path is a valid git path or not - this must not contain
+/**
+ * Validate a "bare" git path. This ensures that the given path is legal
+ * to place in the index or a tree. This should be checked by mechanisms
+ * like `git_index_add` and `git_treebuilder_insert` when taking user
+ * data, and by `git_checkout` before constructing on-disk paths.
+ *
+ * This will ensure that a git path does not contain any "unsafe" components,
* a '.' or '..' component, or a component that is ".git" (in any case).
*
+ * (Note: if you take or construct an on-disk path -- a workdir path,
+ * a path to a git repository or a reference name that could be a loose
+ * ref -- you should _also_ validate that with `git_path_validate_workdir`.)
+ *
* `repo` is optional. If specified, it will be used to determine the short
* path name to reject (if `GIT_PATH_REJECT_DOS_SHORTNAME` is specified),
* in addition to the default of "git~1".
*/
-extern bool git_path_isvalid(
+extern bool git_path_validate(
git_repository *repo,
const char *path,
uint16_t mode,
unsigned int flags);
/**
+ * Validate an on-disk path, taking into account that it will have a
+ * suffix appended (eg, `.lock`).
+ */
+GIT_INLINE(int) git_path_validate_filesystem_with_suffix(
+ const char *path,
+ size_t path_len,
+ size_t suffix_len)
+{
+#ifdef GIT_WIN32
+ size_t path_chars, total_chars;
+
+ path_chars = git_utf8_char_length(path, path_len);
+
+ if (GIT_ADD_SIZET_OVERFLOW(&total_chars, path_chars, suffix_len) ||
+ total_chars > MAX_PATH) {
+ git_error_set(GIT_ERROR_FILESYSTEM, "path too long: '%s'", path);
+ return -1;
+ }
+ return 0;
+#else
+ GIT_UNUSED(path);
+ GIT_UNUSED(path_len);
+ GIT_UNUSED(suffix_len);
+ return 0;
+#endif
+}
+
+/**
+ * Validate an path on the filesystem. This ensures that the given
+ * path is valid for the operating system/platform; for example, this
+ * will ensure that the given absolute path is smaller than MAX_PATH on
+ * Windows.
+ *
+ * For paths within the working directory, you should use ensure that
+ * `core.longpaths` is obeyed. Use `git_path_validate_workdir`.
+ */
+GIT_INLINE(int) git_path_validate_filesystem(
+ const char *path,
+ size_t path_len)
+{
+ return git_path_validate_filesystem_with_suffix(path, path_len, 0);
+}
+
+/**
+ * Validate a path relative to the repo's worktree. This ensures that
+ * the given working tree path is valid for the operating system/platform.
+ * This will ensure that an absolute path is smaller than MAX_PATH on
+ * Windows, while keeping `core.longpaths` configuration settings in mind.
+ *
+ * This should be checked by mechamisms like `git_checkout` after
+ * contructing on-disk paths and before trying to write them.
+ *
+ * If the repository is null, no repository configuration is applied.
+ */
+extern int git_path_validate_workdir(
+ git_repository *repo,
+ const char *path);
+extern int git_path_validate_workdir_with_len(
+ git_repository *repo,
+ const char *path,
+ size_t path_len);
+extern int git_path_validate_workdir_buf(
+ git_repository *repo,
+ git_buf *buf);
+
+/**
* Convert any backslashes into slashes
*/
int git_path_normalize_slashes(git_buf *out, const char *path);
diff --git a/src/pathspec.c b/src/pathspec.c
index 83f776c91..c6ad16571 100644
--- a/src/pathspec.c
+++ b/src/pathspec.c
@@ -9,7 +9,6 @@
#include "git2/pathspec.h"
#include "git2/diff.h"
-#include "buf_text.h"
#include "attr_file.h"
#include "iterator.h"
#include "repository.h"
@@ -25,7 +24,7 @@ char *git_pathspec_prefix(const git_strarray *pathspec)
const char *scan;
if (!pathspec || !pathspec->count ||
- git_buf_text_common_prefix(&prefix, pathspec) < 0)
+ git_buf_common_prefix(&prefix, pathspec->strings, pathspec->count) < 0)
return NULL;
/* diff prefix will only be leading non-wildcards */
@@ -41,7 +40,7 @@ char *git_pathspec_prefix(const git_strarray *pathspec)
return NULL;
}
- git_buf_text_unescape(&prefix);
+ git_buf_unescape(&prefix);
return git_buf_detach(&prefix);
}
@@ -289,7 +288,8 @@ int git_pathspec_matches_path(
bool no_fnmatch = (flags & GIT_PATHSPEC_NO_GLOB) != 0;
bool casefold = (flags & GIT_PATHSPEC_IGNORE_CASE) != 0;
- assert(ps && path);
+ GIT_ASSERT_ARG(ps);
+ GIT_ASSERT_ARG(path);
return (0 != git_pathspec__match(
&ps->pathspec, path, no_fnmatch, casefold, NULL, NULL));
@@ -526,7 +526,7 @@ int git_pathspec_match_workdir(
git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
int error = 0;
- assert(repo);
+ GIT_ASSERT_ARG(repo);
iter_opts.flags = pathspec_match_iter_flags(flags);
@@ -548,7 +548,7 @@ int git_pathspec_match_index(
git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
int error = 0;
- assert(index);
+ GIT_ASSERT_ARG(index);
iter_opts.flags = pathspec_match_iter_flags(flags);
@@ -570,7 +570,7 @@ int git_pathspec_match_tree(
git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
int error = 0;
- assert(tree);
+ GIT_ASSERT_ARG(tree);
iter_opts.flags = pathspec_match_iter_flags(flags);
@@ -598,7 +598,7 @@ int git_pathspec_match_diff(
const git_diff_delta *delta, **match;
git_bitvec used_patterns;
- assert(diff);
+ GIT_ASSERT_ARG(diff);
if (git_bitvec_init(&used_patterns, patterns->length) < 0)
return -1;
diff --git a/src/pool.c b/src/pool.c
index cb98f1af1..16ffa398d 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -21,30 +21,27 @@ struct git_pool_page {
static void *pool_alloc_page(git_pool *pool, size_t size);
-static size_t pool_system_page_size(void)
-{
- static size_t size = 0;
+#ifndef GIT_DEBUG_POOL
- if (!size) {
- size_t page_size;
- if (git__page_size(&page_size) < 0)
- page_size = 4096;
- /* allow space for malloc overhead */
- size = (page_size - (2 * sizeof(void *)) - sizeof(git_pool_page));
- }
+static size_t system_page_size = 0;
- return size;
+int git_pool_global_init(void)
+{
+ if (git__page_size(&system_page_size) < 0)
+ system_page_size = 4096;
+ /* allow space for malloc overhead */
+ system_page_size -= (2 * sizeof(void *)) + sizeof(git_pool_page);
+ return 0;
}
-#ifndef GIT_DEBUG_POOL
int git_pool_init(git_pool *pool, size_t item_size)
{
- assert(pool);
- assert(item_size >= 1);
+ GIT_ASSERT_ARG(pool);
+ GIT_ASSERT_ARG(item_size >= 1);
memset(pool, 0, sizeof(git_pool));
pool->item_size = item_size;
- pool->page_size = pool_system_page_size();
+ pool->page_size = system_page_size;
return 0;
}
@@ -114,6 +111,11 @@ bool git_pool__ptr_in_pool(git_pool *pool, void *ptr)
#else
+int git_pool_global_init(void)
+{
+ return 0;
+}
+
static int git_pool__ptr_cmp(const void * a, const void * b)
{
if(a > b) {
@@ -129,8 +131,8 @@ static int git_pool__ptr_cmp(const void * a, const void * b)
int git_pool_init(git_pool *pool, size_t item_size)
{
- assert(pool);
- assert(item_size >= 1);
+ GIT_ASSERT_ARG(pool);
+ GIT_ASSERT_ARG(item_size >= 1);
memset(pool, 0, sizeof(git_pool));
pool->item_size = item_size;
@@ -203,7 +205,9 @@ char *git_pool_strndup(git_pool *pool, const char *str, size_t n)
{
char *ptr = NULL;
- assert(pool && str && pool->item_size == sizeof(char));
+ GIT_ASSERT_ARG_WITH_RETVAL(pool, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(str, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(pool->item_size == sizeof(char), NULL);
if (n == SIZE_MAX)
return NULL;
@@ -218,7 +222,10 @@ char *git_pool_strndup(git_pool *pool, const char *str, size_t n)
char *git_pool_strdup(git_pool *pool, const char *str)
{
- assert(pool && str && pool->item_size == sizeof(char));
+ GIT_ASSERT_ARG_WITH_RETVAL(pool, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(str, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(pool->item_size == sizeof(char), NULL);
+
return git_pool_strndup(pool, str, strlen(str));
}
@@ -232,7 +239,8 @@ char *git_pool_strcat(git_pool *pool, const char *a, const char *b)
void *ptr;
size_t len_a, len_b, total;
- assert(pool && pool->item_size == sizeof(char));
+ GIT_ASSERT_ARG_WITH_RETVAL(pool, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(pool->item_size == sizeof(char), NULL);
len_a = a ? strlen(a) : 0;
len_b = b ? strlen(b) : 0;
diff --git a/src/pool.h b/src/pool.h
index 969d0e7fe..cecb84665 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -135,4 +135,12 @@ extern uint32_t git_pool__open_pages(git_pool *pool);
#endif
extern bool git_pool__ptr_in_pool(git_pool *pool, void *ptr);
+/**
+ * This function is being called by our global setup routines to
+ * initialize the system pool size.
+ *
+ * @return 0 on success, <0 on failure
+ */
+extern int git_pool_global_init(void);
+
#endif
diff --git a/src/posix.c b/src/posix.c
index fbaa7c3ca..c40134824 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -109,6 +109,13 @@ int p_open(const char *path, volatile int flags, ...)
{
mode_t mode = 0;
+ #ifdef GIT_DEBUG_STRICT_OPEN
+ if (strstr(path, "//") != NULL) {
+ errno = EACCES;
+ return -1;
+ }
+ #endif
+
if (flags & O_CREAT) {
va_list arg_list;
@@ -129,7 +136,8 @@ int p_getcwd(char *buffer_out, size_t size)
{
char *cwd_buffer;
- assert(buffer_out && size > 0);
+ GIT_ASSERT_ARG(buffer_out);
+ GIT_ASSERT_ARG(size > 0);
cwd_buffer = getcwd(buffer_out, size);
@@ -196,7 +204,7 @@ int p_write(git_file fd, const void *buf, size_t cnt)
while (cnt) {
ssize_t r;
#ifdef GIT_WIN32
- assert((size_t)((unsigned int)cnt) == cnt);
+ GIT_ASSERT((size_t)((unsigned int)cnt) == cnt);
r = write(fd, b, (unsigned int)cnt);
#else
r = write(fd, b, cnt);
@@ -237,24 +245,43 @@ int git__mmap_alignment(size_t *alignment)
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset)
{
+ const char *ptr;
+ size_t remaining_len;
+
GIT_MMAP_VALIDATE(out, len, prot, flags);
- out->data = NULL;
- out->len = 0;
+ /* writes cannot be emulated without handling pagefaults since write happens by
+ * writing to mapped memory */
+ if (prot & GIT_PROT_WRITE) {
+ git_error_set(GIT_ERROR_OS, "trying to map %s-writeable",
+ ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED) ? "shared": "private");
+ return -1;
+ }
- if ((prot & GIT_PROT_WRITE) && ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)) {
- git_error_set(GIT_ERROR_OS, "trying to map shared-writeable");
+ if (!git__is_ssizet(len)) {
+ errno = EINVAL;
return -1;
}
+ out->len = 0;
out->data = git__malloc(len);
GIT_ERROR_CHECK_ALLOC(out->data);
- if (!git__is_ssizet(len) ||
- (p_lseek(fd, offset, SEEK_SET) < 0) ||
- (p_read(fd, out->data, len) != (ssize_t)len)) {
- git_error_set(GIT_ERROR_OS, "mmap emulation failed");
- return -1;
+ remaining_len = len;
+ ptr = (const char *)out->data;
+ while (remaining_len > 0) {
+ ssize_t nb;
+ HANDLE_EINTR(nb, p_pread(fd, (void *)ptr, remaining_len, offset));
+ if (nb <= 0) {
+ git_error_set(GIT_ERROR_OS, "mmap emulation failed");
+ git__free(out->data);
+ out->data = NULL;
+ return -1;
+ }
+
+ ptr += nb;
+ offset += nb;
+ remaining_len -= nb;
}
out->len = len;
@@ -263,9 +290,13 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset
int p_munmap(git_map *map)
{
- assert(map != NULL);
+ GIT_ASSERT_ARG(map);
git__free(map->data);
+ /* Initializing will help debug use-after-free */
+ map->len = 0;
+ map->data = NULL;
+
return 0;
}
diff --git a/src/posix.h b/src/posix.h
index eef667762..d98bc82ca 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -89,6 +89,12 @@
#define EAFNOSUPPORT (INT_MAX-1)
#endif
+/* Compiler independent macro to handle signal interrpted system calls */
+#define HANDLE_EINTR(result, x) do { \
+ result = (x); \
+ } while (result == -1 && errno == EINTR);
+
+
/* Provide a 64-bit size for offsets. */
#if defined(_MSC_VER)
@@ -119,6 +125,9 @@ typedef int git_file;
extern ssize_t p_read(git_file fd, void *buf, size_t cnt);
extern int p_write(git_file fd, const void *buf, size_t cnt);
+extern ssize_t p_pread(int fd, void *data, size_t size, off64_t offset);
+extern ssize_t p_pwrite(int fd, const void *data, size_t size, off64_t offset);
+
#define p_close(fd) close(fd)
#define p_umask(m) umask(m)
diff --git a/src/reader.c b/src/reader.c
index 90f700a00..48928940d 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -61,7 +61,8 @@ int git_reader_for_tree(git_reader **out, git_tree *tree)
{
tree_reader *reader;
- assert(out && tree);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(tree);
reader = git__calloc(1, sizeof(tree_reader));
GIT_ERROR_CHECK_ALLOC(reader);
@@ -97,8 +98,7 @@ static int workdir_reader_read(
git_oid id;
int error;
- if ((error = git_buf_joinpath(&path,
- git_repository_workdir(reader->repo), filename)) < 0)
+ if ((error = git_repository_workdir_path(&path, reader->repo, filename)) < 0)
goto done;
if ((error = p_lstat(path.ptr, &st)) < 0) {
@@ -158,7 +158,8 @@ int git_reader_for_workdir(
workdir_reader *reader;
int error;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
reader = git__calloc(1, sizeof(workdir_reader));
GIT_ERROR_CHECK_ALLOC(reader);
@@ -223,7 +224,8 @@ int git_reader_for_index(
index_reader *reader;
int error;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
reader = git__calloc(1, sizeof(index_reader));
GIT_ERROR_CHECK_ALLOC(reader);
@@ -251,7 +253,9 @@ int git_reader_read(
git_reader *reader,
const char *filename)
{
- assert(out && reader && filename);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(reader);
+ GIT_ASSERT_ARG(filename);
return reader->read(out, out_id, out_filemode, reader, filename);
}
diff --git a/src/rebase.c b/src/rebase.c
index 7c6561195..4f10c296b 100644
--- a/src/rebase.c
+++ b/src/rebase.c
@@ -186,8 +186,8 @@ static git_rebase_operation *rebase_operation_alloc(
{
git_rebase_operation *operation;
- assert((type == GIT_REBASE_OPERATION_EXEC) == !id);
- assert((type == GIT_REBASE_OPERATION_EXEC) == !!exec);
+ GIT_ASSERT_WITH_RETVAL((type == GIT_REBASE_OPERATION_EXEC) == !id, NULL);
+ GIT_ASSERT_WITH_RETVAL((type == GIT_REBASE_OPERATION_EXEC) == !!exec, NULL);
if ((operation = git_array_alloc(rebase->operations)) == NULL)
return NULL;
@@ -301,7 +301,7 @@ int git_rebase_open(
size_t state_path_len;
int error;
- assert(repo);
+ GIT_ASSERT_ARG(repo);
if ((error = rebase_check_versions(given_opts)) < 0)
return error;
@@ -701,7 +701,8 @@ int git_rebase_init(
bool inmemory = (given_opts && given_opts->inmemory);
int error;
- assert(repo && (upstream || onto));
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(upstream || onto);
*out = NULL;
@@ -912,7 +913,8 @@ int git_rebase_next(
{
int error;
- assert(out && rebase);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(rebase);
if ((error = rebase_movenext(rebase)) < 0)
return error;
@@ -931,7 +933,9 @@ int git_rebase_inmemory_index(
git_index **out,
git_rebase *rebase)
{
- assert(out && rebase && rebase->index);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(rebase);
+ GIT_ASSERT_ARG(rebase->index);
GIT_REFCOUNT_INC(rebase->index);
*out = rebase->index;
@@ -939,6 +943,54 @@ int git_rebase_inmemory_index(
return 0;
}
+#ifndef GIT_DEPRECATE_HARD
+static int create_signed(
+ git_oid *out,
+ git_rebase *rebase,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message_encoding,
+ const char *message,
+ git_tree *tree,
+ size_t parent_count,
+ const git_commit **parents)
+{
+ git_buf commit_content = GIT_BUF_INIT,
+ commit_signature = GIT_BUF_INIT,
+ signature_field = GIT_BUF_INIT;
+ int error;
+
+ git_error_clear();
+
+ if ((error = git_commit_create_buffer(&commit_content,
+ rebase->repo, author, committer, message_encoding,
+ message, tree, parent_count, parents)) < 0)
+ goto done;
+
+ error = rebase->options.signing_cb(&commit_signature,
+ &signature_field, commit_content.ptr,
+ rebase->options.payload);
+
+ if (error) {
+ if (error != GIT_PASSTHROUGH)
+ git_error_set_after_callback_function(error, "signing_cb");
+
+ goto done;
+ }
+
+ error = git_commit_create_with_signature(out, rebase->repo,
+ commit_content.ptr,
+ commit_signature.size > 0 ? commit_signature.ptr : NULL,
+ signature_field.size > 0 ? signature_field.ptr : NULL);
+
+done:
+ git_buf_dispose(&commit_signature);
+ git_buf_dispose(&signature_field);
+ git_buf_dispose(&commit_content);
+ return error;
+}
+#endif
+
static int rebase_commit__create(
git_commit **out,
git_rebase *rebase,
@@ -953,10 +1005,6 @@ static int rebase_commit__create(
git_commit *current_commit = NULL, *commit = NULL;
git_tree *parent_tree = NULL, *tree = NULL;
git_oid tree_id, commit_id;
- git_buf commit_content = GIT_BUF_INIT, commit_signature = GIT_BUF_INIT,
- signature_field = GIT_BUF_INIT;
- const char *signature_field_string = NULL,
- *commit_signature_string = NULL;
int error;
operation = git_array_get(rebase->operations, rebase->current);
@@ -987,37 +1035,32 @@ static int rebase_commit__create(
message = git_commit_message(current_commit);
}
- if ((error = git_commit_create_buffer(&commit_content, rebase->repo, author, committer,
- message_encoding, message, tree, 1, (const git_commit **)&parent_commit)) < 0)
- goto done;
+ git_error_clear();
+ error = GIT_PASSTHROUGH;
- if (rebase->options.signing_cb) {
- git_error_clear();
- error = git_error_set_after_callback_function(rebase->options.signing_cb(
- &commit_signature, &signature_field, git_buf_cstr(&commit_content),
- rebase->options.payload), "commit signing_cb failed");
- if (error == GIT_PASSTHROUGH) {
- git_buf_dispose(&commit_signature);
- git_buf_dispose(&signature_field);
- git_error_clear();
- error = GIT_OK;
- } else if (error < 0)
- goto done;
- }
+ if (rebase->options.commit_create_cb) {
+ error = rebase->options.commit_create_cb(&commit_id,
+ author, committer, message_encoding, message,
+ tree, 1, (const git_commit **)&parent_commit,
+ rebase->options.payload);
- if (git_buf_is_allocated(&commit_signature)) {
- assert(git_buf_contains_nul(&commit_signature));
- commit_signature_string = git_buf_cstr(&commit_signature);
+ git_error_set_after_callback_function(error,
+ "commit_create_cb");
}
-
- if (git_buf_is_allocated(&signature_field)) {
- assert(git_buf_contains_nul(&signature_field));
- signature_field_string = git_buf_cstr(&signature_field);
+#ifndef GIT_DEPRECATE_HARD
+ else if (rebase->options.signing_cb) {
+ error = create_signed(&commit_id, rebase, author,
+ committer, message_encoding, message, tree,
+ 1, (const git_commit **)&parent_commit);
}
+#endif
- if ((error = git_commit_create_with_signature(&commit_id, rebase->repo,
- git_buf_cstr(&commit_content), commit_signature_string,
- signature_field_string)))
+ if (error == GIT_PASSTHROUGH)
+ error = git_commit_create(&commit_id, rebase->repo, NULL,
+ author, committer, message_encoding, message,
+ tree, 1, (const git_commit **)&parent_commit);
+
+ if (error)
goto done;
if ((error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0)
@@ -1029,9 +1072,6 @@ done:
if (error < 0)
git_commit_free(commit);
- git_buf_dispose(&commit_signature);
- git_buf_dispose(&signature_field);
- git_buf_dispose(&commit_content);
git_commit_free(current_commit);
git_tree_free(parent_tree);
git_tree_free(tree);
@@ -1055,7 +1095,7 @@ static int rebase_commit_merge(
int error;
operation = git_array_get(rebase->operations, rebase->current);
- assert(operation);
+ GIT_ASSERT(operation);
if ((error = rebase_ensure_not_dirty(rebase->repo, false, true, GIT_EUNMERGED)) < 0 ||
(error = git_repository_head(&head, rebase->repo)) < 0 ||
@@ -1095,9 +1135,9 @@ static int rebase_commit_inmemory(
git_commit *commit = NULL;
int error = 0;
- assert(rebase->index);
- assert(rebase->last_commit);
- assert(rebase->current < rebase->operations.size);
+ GIT_ASSERT_ARG(rebase->index);
+ GIT_ASSERT_ARG(rebase->last_commit);
+ GIT_ASSERT_ARG(rebase->current < rebase->operations.size);
if ((error = rebase_commit__create(&commit, rebase, rebase->index,
rebase->last_commit, author, committer, message_encoding, message)) < 0)
@@ -1125,7 +1165,8 @@ int git_rebase_commit(
{
int error;
- assert(rebase && committer);
+ GIT_ASSERT_ARG(rebase);
+ GIT_ASSERT_ARG(committer);
if (rebase->inmemory)
error = rebase_commit_inmemory(
@@ -1145,7 +1186,7 @@ int git_rebase_abort(git_rebase *rebase)
git_commit *orig_head_commit = NULL;
int error;
- assert(rebase);
+ GIT_ASSERT_ARG(rebase);
if (rebase->inmemory)
return 0;
@@ -1358,7 +1399,7 @@ int git_rebase_finish(
{
int error = 0;
- assert(rebase);
+ GIT_ASSERT_ARG(rebase);
if (rebase->inmemory)
return 0;
@@ -1373,14 +1414,17 @@ int git_rebase_finish(
}
const char *git_rebase_orig_head_name(git_rebase *rebase) {
+ GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
return rebase->orig_head_name;
}
const git_oid *git_rebase_orig_head_id(git_rebase *rebase) {
+ GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
return &rebase->orig_head_id;
}
const char *git_rebase_onto_name(git_rebase *rebase) {
+ GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
return rebase->onto_name;
}
@@ -1390,21 +1434,21 @@ const git_oid *git_rebase_onto_id(git_rebase *rebase) {
size_t git_rebase_operation_entrycount(git_rebase *rebase)
{
- assert(rebase);
+ GIT_ASSERT_ARG_WITH_RETVAL(rebase, 0);
return git_array_size(rebase->operations);
}
size_t git_rebase_operation_current(git_rebase *rebase)
{
- assert(rebase);
+ GIT_ASSERT_ARG_WITH_RETVAL(rebase, 0);
return rebase->started ? rebase->current : GIT_REBASE_NO_OPERATION;
}
git_rebase_operation *git_rebase_operation_byindex(git_rebase *rebase, size_t idx)
{
- assert(rebase);
+ GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL);
return git_array_get(rebase->operations, idx);
}
diff --git a/src/refdb.c b/src/refdb.c
index fbbf5193c..ed33de92b 100644
--- a/src/refdb.c
+++ b/src/refdb.c
@@ -17,11 +17,15 @@
#include "reflog.h"
#include "posix.h"
+#define DEFAULT_NESTING_LEVEL 5
+#define MAX_NESTING_LEVEL 10
+
int git_refdb_new(git_refdb **out, git_repository *repo)
{
git_refdb *db;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
db = git__calloc(1, sizeof(*db));
GIT_ERROR_CHECK_ALLOC(db);
@@ -38,7 +42,8 @@ int git_refdb_open(git_refdb **out, git_repository *repo)
git_refdb *db;
git_refdb_backend *dir;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
*out = NULL;
@@ -86,7 +91,7 @@ int git_refdb_set_backend(git_refdb *db, git_refdb_backend *backend)
int git_refdb_compress(git_refdb *db)
{
- assert(db);
+ GIT_ASSERT_ARG(db);
if (db->backend->compress)
return db->backend->compress(db->backend);
@@ -111,7 +116,9 @@ void git_refdb_free(git_refdb *db)
int git_refdb_exists(int *exists, git_refdb *refdb, const char *ref_name)
{
- assert(exists && refdb && refdb->backend);
+ GIT_ASSERT_ARG(exists);
+ GIT_ASSERT_ARG(refdb);
+ GIT_ASSERT_ARG(refdb->backend);
return refdb->backend->exists(exists, refdb->backend, ref_name);
}
@@ -121,7 +128,10 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
git_reference *ref;
int error;
- assert(db && db->backend && out && ref_name);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(db->backend);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(ref_name);
error = db->backend->lookup(&ref, db->backend, ref_name);
if (error < 0)
@@ -134,6 +144,59 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
return 0;
}
+int git_refdb_resolve(
+ git_reference **out,
+ git_refdb *db,
+ const char *ref_name,
+ int max_nesting)
+{
+ git_reference *ref = NULL;
+ int error = 0, nesting;
+
+ *out = NULL;
+
+ if (max_nesting > MAX_NESTING_LEVEL)
+ max_nesting = MAX_NESTING_LEVEL;
+ else if (max_nesting < 0)
+ max_nesting = DEFAULT_NESTING_LEVEL;
+
+ if ((error = git_refdb_lookup(&ref, db, ref_name)) < 0)
+ goto out;
+
+ for (nesting = 0; nesting < max_nesting; nesting++) {
+ git_reference *resolved;
+
+ if (ref->type == GIT_REFERENCE_DIRECT)
+ break;
+
+ if ((error = git_refdb_lookup(&resolved, db, git_reference_symbolic_target(ref))) < 0) {
+ /* If we found a symbolic reference with a nonexistent target, return it. */
+ if (error == GIT_ENOTFOUND) {
+ error = 0;
+ *out = ref;
+ ref = NULL;
+ }
+ goto out;
+ }
+
+ git_reference_free(ref);
+ ref = resolved;
+ }
+
+ if (ref->type != GIT_REFERENCE_DIRECT && max_nesting != 0) {
+ git_error_set(GIT_ERROR_REFERENCE,
+ "cannot resolve reference (>%u levels deep)", max_nesting);
+ error = -1;
+ goto out;
+ }
+
+ *out = ref;
+ ref = NULL;
+out:
+ git_reference_free(ref);
+ return error;
+}
+
int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob)
{
int error;
@@ -178,7 +241,8 @@ void git_refdb_iterator_free(git_reference_iterator *iter)
int git_refdb_write(git_refdb *db, git_reference *ref, int force, const git_signature *who, const char *message, const git_oid *old_id, const char *old_target)
{
- assert(db && db->backend);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(db->backend);
GIT_REFCOUNT_INC(db);
ref->db = db;
@@ -197,7 +261,9 @@ int git_refdb_rename(
{
int error;
- assert(db && db->backend);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(db->backend);
+
error = db->backend->rename(out, db->backend, old_name, new_name, force, who, message);
if (error < 0)
return error;
@@ -212,7 +278,9 @@ int git_refdb_rename(
int git_refdb_delete(struct git_refdb *db, const char *ref_name, const git_oid *old_id, const char *old_target)
{
- assert(db && db->backend);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(db->backend);
+
return db->backend->del(db->backend, ref_name, old_id, old_target);
}
@@ -220,7 +288,8 @@ int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name)
{
int error;
- assert(db && db->backend);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(db->backend);
if ((error = db->backend->reflog_read(out, db->backend, name)) < 0)
return error;
@@ -231,16 +300,97 @@ int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name)
return 0;
}
+int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *ref)
+{
+ int error, logall;
+
+ error = git_repository__configmap_lookup(&logall, db->repo, GIT_CONFIGMAP_LOGALLREFUPDATES);
+ if (error < 0)
+ return error;
+
+ /* Defaults to the opposite of the repo being bare */
+ if (logall == GIT_LOGALLREFUPDATES_UNSET)
+ logall = !git_repository_is_bare(db->repo);
+
+ *out = 0;
+ switch (logall) {
+ case GIT_LOGALLREFUPDATES_FALSE:
+ *out = 0;
+ break;
+
+ case GIT_LOGALLREFUPDATES_TRUE:
+ /* Only write if it already has a log,
+ * or if it's under heads/, remotes/ or notes/
+ */
+ *out = git_refdb_has_log(db, ref->name) ||
+ !git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) ||
+ !git__strcmp(ref->name, GIT_HEAD_FILE) ||
+ !git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) ||
+ !git__prefixcmp(ref->name, GIT_REFS_NOTES_DIR);
+ break;
+
+ case GIT_LOGALLREFUPDATES_ALWAYS:
+ *out = 1;
+ break;
+ }
+
+ return 0;
+}
+
+int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_reference *ref)
+{
+ git_reference *head = NULL, *resolved = NULL;
+ const char *name;
+ int error;
+
+ *out = 0;
+
+ if (ref->type == GIT_REFERENCE_SYMBOLIC) {
+ error = 0;
+ goto out;
+ }
+
+ if ((error = git_refdb_lookup(&head, db, GIT_HEAD_FILE)) < 0)
+ goto out;
+
+ if (git_reference_type(head) == GIT_REFERENCE_DIRECT)
+ goto out;
+
+ /* Go down the symref chain until we find the branch */
+ if ((error = git_refdb_resolve(&resolved, db, git_reference_symbolic_target(head), -1)) < 0) {
+ if (error != GIT_ENOTFOUND)
+ goto out;
+ error = 0;
+ name = git_reference_symbolic_target(head);
+ } else if (git_reference_type(resolved) == GIT_REFERENCE_SYMBOLIC) {
+ name = git_reference_symbolic_target(resolved);
+ } else {
+ name = git_reference_name(resolved);
+ }
+
+ if (strcmp(name, ref->name))
+ goto out;
+
+ *out = 1;
+
+out:
+ git_reference_free(resolved);
+ git_reference_free(head);
+ return error;
+}
+
int git_refdb_has_log(git_refdb *db, const char *refname)
{
- assert(db && refname);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(refname);
return db->backend->has_log(db->backend, refname);
}
int git_refdb_ensure_log(git_refdb *db, const char *refname)
{
- assert(db && refname);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(refname);
return db->backend->ensure_log(db->backend, refname);
}
@@ -254,7 +404,9 @@ int git_refdb_init_backend(git_refdb_backend *backend, unsigned int version)
int git_refdb_lock(void **payload, git_refdb *db, const char *refname)
{
- assert(payload && db && refname);
+ GIT_ASSERT_ARG(payload);
+ GIT_ASSERT_ARG(db);
+ GIT_ASSERT_ARG(refname);
if (!db->backend->lock) {
git_error_set(GIT_ERROR_REFERENCE, "backend does not support locking");
@@ -266,7 +418,7 @@ int git_refdb_lock(void **payload, git_refdb *db, const char *refname)
int git_refdb_unlock(git_refdb *db, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message)
{
- assert(db);
+ GIT_ASSERT_ARG(db);
return db->backend->unlock(db->backend, payload, success, update_reflog, ref, sig, message);
}
diff --git a/src/refdb.h b/src/refdb.h
index 2d4ec753a..84e19b1c3 100644
--- a/src/refdb.h
+++ b/src/refdb.h
@@ -30,6 +30,31 @@ int git_refdb_lookup(
git_refdb *refdb,
const char *ref_name);
+/**
+ * Resolve the reference by following symbolic references.
+ *
+ * Given a reference name, this function will follow any symbolic references up
+ * to `max_nesting` deep and return the resolved direct reference. If any of
+ * the intermediate symbolic references points to a non-existing reference,
+ * then that symbolic reference is returned instead with an error code of `0`.
+ * If the given reference is a direct reference already, it is returned
+ * directly.
+ *
+ * If `max_nesting` is `0`, the reference will not be resolved. If it's
+ * negative, it will be set to the default resolve depth which is `5`.
+ *
+ * @param out Pointer to store the result in.
+ * @param db The refdb to use for resolving the reference.
+ * @param ref_name The reference name to lookup and resolve.
+ * @param max_nesting The maximum nesting depth.
+ * @return `0` on success, a negative error code otherwise.
+ */
+int git_refdb_resolve(
+ git_reference **out,
+ git_refdb *db,
+ const char *ref_name,
+ int max_nesting);
+
int git_refdb_rename(
git_reference **out,
git_refdb *db,
@@ -50,6 +75,50 @@ int git_refdb_delete(git_refdb *refdb, const char *ref_name, const git_oid *old_
int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name);
int git_refdb_reflog_write(git_reflog *reflog);
+/**
+ * Determine whether a reflog entry should be created for the given reference.
+ *
+ * Whether or not writing to a reference should create a reflog entry is
+ * dependent on a number of things. Most importantly, there's the
+ * "core.logAllRefUpdates" setting that controls in which situations a
+ * reference should get a corresponding reflog entry. The following values for
+ * it are understood:
+ *
+ * - "false": Do not log reference updates.
+ *
+ * - "true": Log normal reference updates. This will write entries for
+ * references in "refs/heads", "refs/remotes", "refs/notes" and
+ * "HEAD" or if the reference already has a log entry.
+ *
+ * - "always": Always create a reflog entry.
+ *
+ * If unset, the value will default to "true" for non-bare repositories and
+ * "false" for bare ones.
+ *
+ * @param out pointer to which the result will be written, `1` means a reflog
+ * entry should be written, `0` means none should be written.
+ * @param db The refdb to decide this for.
+ * @param ref The reference one wants to check.
+ * @return `0` on success, a negative error code otherwise.
+ */
+int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *ref);
+
+/**
+ * Determine whether a reflog entry should be created for HEAD if creating one
+ * for the given reference
+ *
+ * In case the given reference is being pointed to by HEAD, then creating a
+ * reflog entry for this reference also requires us to create a corresponding
+ * reflog entry for HEAD. This function can be used to determine that scenario.
+ *
+ * @param out pointer to which the result will be written, `1` means a reflog
+ * entry should be written, `0` means none should be written.
+ * @param db The refdb to decide this for.
+ * @param ref The reference one wants to check.
+ * @return `0` on success, a negative error code otherwise.
+ */
+int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_reference *ref);
+
int git_refdb_has_log(git_refdb *db, const char *refname);
int git_refdb_ensure_log(git_refdb *refdb, const char *refname);
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 28ea474c9..24cb22fb0 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -68,6 +68,35 @@ typedef struct refdb_fs_backend {
static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name);
+GIT_INLINE(int) loose_path(
+ git_buf *out,
+ const char *base,
+ const char *refname)
+{
+ if (git_buf_joinpath(out, base, refname) < 0)
+ return -1;
+
+ return git_path_validate_filesystem_with_suffix(out->ptr, out->size,
+ CONST_STRLEN(".lock"));
+}
+
+GIT_INLINE(int) reflog_path(
+ git_buf *out,
+ git_repository *repo,
+ const char *refname)
+{
+ const char *base;
+ int error;
+
+ base = (strcmp(refname, GIT_HEAD_FILE) == 0) ? repo->gitdir :
+ repo->commondir;
+
+ if ((error = git_buf_joinpath(out, base, GIT_REFLOG_DIR)) < 0)
+ return error;
+
+ return loose_path(out, out->ptr, refname);
+}
+
static int packref_cmp(const void *a_, const void *b_)
{
const struct packref *a = a_, *b = b_;
@@ -93,7 +122,7 @@ static int packed_reload(refdb_fs_backend *backend)
*/
if (error <= 0) {
if (error == GIT_ENOTFOUND) {
- git_sortedcache_clear(backend->refcache, true);
+ GIT_UNUSED(git_sortedcache_clear(backend->refcache, true));
git_error_clear();
error = 0;
}
@@ -102,7 +131,7 @@ static int packed_reload(refdb_fs_backend *backend)
/* At this point, refresh the packed refs from the loaded buffer. */
- git_sortedcache_clear(backend->refcache, false);
+ GIT_UNUSED(git_sortedcache_clear(backend->refcache, false));
scan = (char *)packedrefs.ptr;
eof = scan + packedrefs.size;
@@ -190,7 +219,7 @@ static int packed_reload(refdb_fs_backend *backend)
parse_failed:
git_error_set(GIT_ERROR_REFERENCE, "corrupted packed references file");
- git_sortedcache_clear(backend->refcache, false);
+ GIT_UNUSED(git_sortedcache_clear(backend->refcache, false));
git_sortedcache_wunlock(backend->refcache);
git_buf_dispose(&packedrefs);
@@ -223,9 +252,8 @@ static int loose_readbuffer(git_buf *buf, const char *base, const char *path)
{
int error;
- /* build full path to file */
- if ((error = git_buf_joinpath(buf, base, path)) < 0 ||
- (error = git_futils_readbuffer(buf, buf->ptr)) < 0)
+ if ((error = loose_path(buf, base, path)) < 0 ||
+ (error = git_futils_readbuffer(buf, buf->ptr)) < 0)
git_buf_dispose(buf);
return error;
@@ -254,7 +282,8 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name)
if ((error = loose_parse_oid(&oid, name, &ref_file)) < 0)
goto done;
- git_sortedcache_wlock(backend->refcache);
+ if ((error = git_sortedcache_wlock(backend->refcache)) < 0)
+ goto done;
if (!(error = git_sortedcache_upsert(
(void **)&ref, backend->refcache, name))) {
@@ -331,11 +360,11 @@ static int refdb_fs_backend__exists(
git_buf ref_path = GIT_BUF_INIT;
int error;
- assert(backend);
+ GIT_ASSERT_ARG(backend);
*exists = 0;
- if ((error = git_buf_joinpath(&ref_path, backend->gitpath, ref_name)) < 0)
+ if ((error = loose_path(&ref_path, backend->gitpath, ref_name)) < 0)
goto out;
if (git_path_isfile(ref_path.ptr)) {
@@ -472,7 +501,7 @@ static int refdb_fs_backend__lookup(
refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
int error;
- assert(backend);
+ GIT_ASSERT_ARG(backend);
if (!(error = loose_lookup(out, backend, ref_name)))
return 0;
@@ -549,7 +578,7 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter)
}
}
- if ((error = git_buf_printf(&path, "%s/", backend->commonpath)) < 0 ||
+ if ((error = git_buf_puts(&path, backend->commonpath)) < 0 ||
(error = git_buf_put(&path, ref_prefix, ref_prefix_len)) < 0) {
git_buf_dispose(&path);
return error;
@@ -678,7 +707,7 @@ static int refdb_fs_backend__iterator(
refdb_fs_iter *iter = NULL;
int error;
- assert(backend);
+ GIT_ASSERT_ARG(backend);
iter = git__calloc(1, sizeof(refdb_fs_iter));
GIT_ERROR_CHECK_ALLOC(iter);
@@ -735,7 +764,7 @@ static bool ref_is_available(
static int reference_path_available(
refdb_fs_backend *backend,
const char *new_ref,
- const char* old_ref,
+ const char *old_ref,
int force)
{
size_t i;
@@ -760,7 +789,8 @@ static int reference_path_available(
}
}
- git_sortedcache_rlock(backend->refcache);
+ if ((error = git_sortedcache_rlock(backend->refcache)) < 0)
+ return error;
for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) {
struct packref *ref = git_sortedcache_entry(backend->refcache, i);
@@ -783,9 +813,11 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
git_buf ref_path = GIT_BUF_INIT;
const char *basedir;
- assert(file && backend && name);
+ GIT_ASSERT_ARG(file);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(name);
- if (!git_path_isvalid(backend->repo, name, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
+ if (!git_path_validate(backend->repo, name, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
git_error_set(GIT_ERROR_INVALID, "invalid reference name '%s'", name);
return GIT_EINVALIDSPEC;
}
@@ -801,8 +833,8 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
if ((error = git_futils_rmdir_r(name, basedir, GIT_RMDIR_SKIP_NONEMPTY)) < 0)
return error;
- if (git_buf_joinpath(&ref_path, basedir, name) < 0)
- return -1;
+ if ((error = loose_path(&ref_path, basedir, name)) < 0)
+ return error;
filebuf_flags = GIT_FILEBUF_CREATE_LEADING_DIRS;
if (backend->fsync)
@@ -819,7 +851,8 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
static int loose_commit(git_filebuf *file, const git_reference *ref)
{
- assert(file && ref);
+ GIT_ASSERT_ARG(file);
+ GIT_ASSERT_ARG(ref);
if (ref->type == GIT_REFERENCE_DIRECT) {
char oid[GIT_OID_HEXSZ + 1];
@@ -829,7 +862,7 @@ static int loose_commit(git_filebuf *file, const git_reference *ref)
} else if (ref->type == GIT_REFERENCE_SYMBOLIC) {
git_filebuf_printf(file, GIT_SYMREF "%s\n", ref->target.symbolic);
} else {
- assert(0); /* don't let this happen */
+ GIT_ASSERT(0);
}
return git_filebuf_commit(file);
@@ -1066,7 +1099,7 @@ static int packed_write(refdb_fs_backend *backend)
for (i = 0; i < git_sortedcache_entrycount(refcache); ++i) {
struct packref *ref = git_sortedcache_entry(refcache, i);
- assert(ref);
+ GIT_ASSERT(ref);
if ((error = packed_find_peel(backend, ref)) < 0)
goto fail;
@@ -1128,44 +1161,6 @@ cleanup:
}
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *author, const char *message);
-static int has_reflog(git_repository *repo, const char *name);
-
-static int should_write_reflog(int *write, git_repository *repo, const char *name)
-{
- int error, logall;
-
- error = git_repository__configmap_lookup(&logall, repo, GIT_CONFIGMAP_LOGALLREFUPDATES);
- if (error < 0)
- return error;
-
- /* Defaults to the opposite of the repo being bare */
- if (logall == GIT_LOGALLREFUPDATES_UNSET)
- logall = !git_repository_is_bare(repo);
-
- *write = 0;
- switch (logall) {
- case GIT_LOGALLREFUPDATES_FALSE:
- *write = 0;
- break;
-
- case GIT_LOGALLREFUPDATES_TRUE:
- /* Only write if it already has a log,
- * or if it's under heads/, remotes/ or notes/
- */
- *write = has_reflog(repo, name) ||
- !git__prefixcmp(name, GIT_REFS_HEADS_DIR) ||
- !git__strcmp(name, GIT_HEAD_FILE) ||
- !git__prefixcmp(name, GIT_REFS_REMOTES_DIR) ||
- !git__prefixcmp(name, GIT_REFS_NOTES_DIR);
- break;
-
- case GIT_LOGALLREFUPDATES_ALWAYS:
- *write = 1;
- break;
- }
-
- return 0;
-}
static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const char *name,
const git_oid *old_id, const char *old_target)
@@ -1178,8 +1173,11 @@ static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const char *name,
if (!old_id && !old_target)
return 0;
- if ((error = refdb_fs_backend__lookup(&old_ref, backend, name)) < 0)
+ if ((error = refdb_fs_backend__lookup(&old_ref, backend, name)) < 0) {
+ if (error == GIT_ENOTFOUND && old_id && git_oid_is_zero(old_id))
+ return 0;
goto out;
+ }
/* If the types don't match, there's no way the values do */
if (old_id && old_ref->type != GIT_REFERENCE_DIRECT) {
@@ -1219,54 +1217,28 @@ out:
*/
static int maybe_append_head(refdb_fs_backend *backend, const git_reference *ref, const git_signature *who, const char *message)
{
- int error;
+ git_reference *head = NULL;
+ git_refdb *refdb = NULL;
+ int error, write_reflog;
git_oid old_id;
- git_reference *tmp = NULL, *head = NULL, *peeled = NULL;
- const char *name;
- if (ref->type == GIT_REFERENCE_SYMBOLIC)
- return 0;
+ if ((error = git_repository_refdb(&refdb, backend->repo)) < 0 ||
+ (error = git_refdb_should_write_head_reflog(&write_reflog, refdb, ref)) < 0)
+ goto out;
+ if (!write_reflog)
+ goto out;
/* if we can't resolve, we use {0}*40 as old id */
if (git_reference_name_to_id(&old_id, backend->repo, ref->name) < 0)
memset(&old_id, 0, sizeof(old_id));
- if ((error = git_reference_lookup(&head, backend->repo, GIT_HEAD_FILE)) < 0)
- return error;
-
- if (git_reference_type(head) == GIT_REFERENCE_DIRECT)
- goto cleanup;
-
- if ((error = git_reference_lookup(&tmp, backend->repo, GIT_HEAD_FILE)) < 0)
- goto cleanup;
-
- /* Go down the symref chain until we find the branch */
- while (git_reference_type(tmp) == GIT_REFERENCE_SYMBOLIC) {
- error = git_reference_lookup(&peeled, backend->repo, git_reference_symbolic_target(tmp));
- if (error < 0)
- break;
-
- git_reference_free(tmp);
- tmp = peeled;
- }
-
- if (error == GIT_ENOTFOUND) {
- error = 0;
- name = git_reference_symbolic_target(tmp);
- } else if (error < 0) {
- goto cleanup;
- } else {
- name = git_reference_name(tmp);
- }
-
- if (strcmp(name, ref->name))
- goto cleanup;
-
- error = reflog_append(backend, head, &old_id, git_reference_target(ref), who, message);
+ if ((error = git_reference_lookup(&head, backend->repo, GIT_HEAD_FILE)) < 0 ||
+ (error = reflog_append(backend, head, &old_id, git_reference_target(ref), who, message)) < 0)
+ goto out;
-cleanup:
- git_reference_free(tmp);
+out:
git_reference_free(head);
+ git_refdb_free(refdb);
return error;
}
@@ -1283,7 +1255,7 @@ static int refdb_fs_backend__write(
git_filebuf file = GIT_FILEBUF_INIT;
int error = 0;
- assert(backend);
+ GIT_ASSERT_ARG(backend);
if ((error = reference_path_available(backend, ref->name, NULL, force)) < 0)
return error;
@@ -1335,7 +1307,10 @@ static int refdb_fs_backend__write_tail(
}
if (update_reflog) {
- if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0)
+ git_refdb *refdb;
+
+ if ((error = git_repository_refdb__weakptr(&refdb, backend->repo)) < 0 ||
+ (error = git_refdb_should_write_reflog(&should_write, refdb, ref)) < 0)
goto on_error;
if (should_write) {
@@ -1353,7 +1328,7 @@ on_error:
return error;
}
-static void refdb_fs_backend__prune_refs(
+static int refdb_fs_backend__prune_refs(
refdb_fs_backend *backend,
const char *ref_name,
const char *prefix)
@@ -1361,10 +1336,12 @@ static void refdb_fs_backend__prune_refs(
git_buf relative_path = GIT_BUF_INIT;
git_buf base_path = GIT_BUF_INIT;
size_t commonlen;
+ int error;
- assert(backend && ref_name);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(ref_name);
- if (git_buf_sets(&relative_path, ref_name) < 0)
+ if ((error = git_buf_sets(&relative_path, ref_name)) < 0)
goto cleanup;
git_path_squash_slashes(&relative_path);
@@ -1374,20 +1351,33 @@ static void refdb_fs_backend__prune_refs(
git_buf_truncate(&relative_path, commonlen);
- if (prefix) {
- if (git_buf_join3(&base_path, '/', backend->commonpath, prefix, git_buf_cstr(&relative_path)) < 0)
- goto cleanup;
- } else {
- if (git_buf_joinpath(&base_path, backend->commonpath, git_buf_cstr(&relative_path)) < 0)
- goto cleanup;
- }
+ if (prefix)
+ error = git_buf_join3(&base_path, '/',
+ backend->commonpath, prefix,
+ git_buf_cstr(&relative_path));
+ else
+ error = git_buf_joinpath(&base_path,
+ backend->commonpath,
+ git_buf_cstr(&relative_path));
+
+ if (!error)
+ error = git_path_validate_filesystem(base_path.ptr, base_path.size);
+
+ if (error < 0)
+ goto cleanup;
+
+ error = git_futils_rmdir_r(ref_name + commonlen,
+ git_buf_cstr(&base_path),
+ GIT_RMDIR_EMPTY_PARENTS | GIT_RMDIR_SKIP_ROOT);
- git_futils_rmdir_r(ref_name + commonlen, git_buf_cstr(&base_path), GIT_RMDIR_EMPTY_PARENTS | GIT_RMDIR_SKIP_ROOT);
+ if (error == GIT_ENOTFOUND)
+ error = 0;
}
cleanup:
git_buf_dispose(&relative_path);
git_buf_dispose(&base_path);
+ return error;
}
static int refdb_fs_backend__delete(
@@ -1399,7 +1389,8 @@ static int refdb_fs_backend__delete(
git_filebuf file = GIT_FILEBUF_INIT;
int error = 0;
- assert(backend && ref_name);
+ GIT_ASSERT_ARG(backend);
+ GIT_ASSERT_ARG(ref_name);
if ((error = loose_lock(&file, backend, ref_name)) < 0)
return error;
@@ -1414,19 +1405,19 @@ static int refdb_fs_backend__delete(
static int loose_delete(refdb_fs_backend *backend, const char *ref_name)
{
- git_buf loose_path = GIT_BUF_INIT;
+ git_buf path = GIT_BUF_INIT;
int error = 0;
- if (git_buf_joinpath(&loose_path, backend->commonpath, ref_name) < 0)
- return -1;
+ if ((error = loose_path(&path, backend->commonpath, ref_name)) < 0)
+ return error;
- error = p_unlink(loose_path.ptr);
+ error = p_unlink(path.ptr);
if (error < 0 && errno == ENOENT)
error = GIT_ENOTFOUND;
else if (error != 0)
error = -1;
- git_buf_dispose(&loose_path);
+ git_buf_dispose(&path);
return error;
}
@@ -1485,7 +1476,7 @@ static int refdb_fs_backend__delete_tail(
cleanup:
git_filebuf_cleanup(file);
if (error == 0)
- refdb_fs_backend__prune_refs(backend, ref_name, "");
+ error = refdb_fs_backend__prune_refs(backend, ref_name, "");
return error;
}
@@ -1505,7 +1496,7 @@ static int refdb_fs_backend__rename(
git_filebuf file = GIT_FILEBUF_INIT;
int error;
- assert(backend);
+ GIT_ASSERT_ARG(backend);
if ((error = reference_path_available(
backend, new_name, old_name, force)) < 0 ||
@@ -1558,7 +1549,7 @@ static int refdb_fs_backend__compress(git_refdb_backend *_backend)
int error;
refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
- assert(backend);
+ GIT_ASSERT_ARG(backend);
if ((error = packed_reload(backend)) < 0 || /* load the existing packfile */
(error = packed_loadloose(backend)) < 0 || /* add all the loose refs */
@@ -1572,7 +1563,8 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend)
{
refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
- assert(backend);
+ if (!backend)
+ return;
git_sortedcache_free(backend->refcache);
git__free(backend->gitpath);
@@ -1617,8 +1609,9 @@ static char *setup_namespace(git_repository *repo, const char *in)
GIT_MKDIR_PATH, NULL) < 0)
goto done;
- /* Return root of the namespaced gitpath, i.e. without the trailing '/refs' */
+ /* Return root of the namespaced gitpath, i.e. without the trailing 'refs' */
git_buf_rtruncate_at_char(&path, '/');
+ git_buf_putc(&path, '/');
out = git_buf_detach(&path);
done:
@@ -1719,13 +1712,6 @@ static int create_new_reflog_file(const char *filepath)
return p_close(fd);
}
-GIT_INLINE(int) retrieve_reflog_path(git_buf *path, git_repository *repo, const char *name)
-{
- if (strcmp(name, GIT_HEAD_FILE) == 0)
- return git_buf_join3(path, '/', repo->gitdir, GIT_REFLOG_DIR, name);
- return git_buf_join3(path, '/', repo->commondir, GIT_REFLOG_DIR, name);
-}
-
static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *name)
{
refdb_fs_backend *backend;
@@ -1733,12 +1719,12 @@ static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *
git_buf path = GIT_BUF_INIT;
int error;
- assert(_backend && name);
+ GIT_ASSERT_ARG(_backend && name);
backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
repo = backend->repo;
- if ((error = retrieve_reflog_path(&path, repo, name)) < 0)
+ if ((error = reflog_path(&path, repo, name)) < 0)
return error;
error = create_new_reflog_file(git_buf_cstr(&path));
@@ -1752,7 +1738,7 @@ static int has_reflog(git_repository *repo, const char *name)
int ret = 0;
git_buf path = GIT_BUF_INIT;
- if (retrieve_reflog_path(&path, repo, name) < 0)
+ if (reflog_path(&path, repo, name) < 0)
goto cleanup;
ret = git_path_isfile(git_buf_cstr(&path));
@@ -1766,7 +1752,8 @@ static int refdb_reflog_fs__has_log(git_refdb_backend *_backend, const char *nam
{
refdb_fs_backend *backend;
- assert(_backend && name);
+ GIT_ASSERT_ARG(_backend);
+ GIT_ASSERT_ARG(name);
backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
@@ -1782,7 +1769,9 @@ static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend,
git_repository *repo;
refdb_fs_backend *backend;
- assert(out && _backend && name);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(_backend);
+ GIT_ASSERT_ARG(name);
backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
repo = backend->repo;
@@ -1790,7 +1779,7 @@ static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend,
if (reflog_alloc(&log, name) < 0)
return -1;
- if (retrieve_reflog_path(&log_path, repo, name) < 0)
+ if (reflog_path(&log_path, repo, name) < 0)
goto cleanup;
error = git_futils_readbuffer(&log_file, git_buf_cstr(&log_path));
@@ -1867,12 +1856,12 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
repo = backend->repo;
- if (!git_path_isvalid(backend->repo, refname, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
+ if (!git_path_validate(backend->repo, refname, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
git_error_set(GIT_ERROR_INVALID, "invalid reference name '%s'", refname);
return GIT_EINVALIDSPEC;
}
- if (retrieve_reflog_path(&log_path, repo, refname) < 0)
+ if (reflog_path(&log_path, repo, refname) < 0)
return -1;
if (!git_path_isfile(git_buf_cstr(&log_path))) {
@@ -1899,7 +1888,8 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo
git_buf log = GIT_BUF_INIT;
git_filebuf fbuf = GIT_FILEBUF_INIT;
- assert(_backend && reflog);
+ GIT_ASSERT_ARG(_backend);
+ GIT_ASSERT_ARG(reflog);
backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
@@ -1972,7 +1962,7 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
if ((error = serialize_reflog_entry(&buf, &old_id, &new_id, who, message)) < 0)
goto cleanup;
- if ((error = retrieve_reflog_path(&path, repo, ref->name)) < 0)
+ if ((error = reflog_path(&path, repo, ref->name)) < 0)
goto cleanup;
if (((error = git_futils_mkpath2file(git_buf_cstr(&path), 0777)) < 0) &&
@@ -2021,7 +2011,9 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
git_repository *repo;
refdb_fs_backend *backend;
- assert(_backend && old_name && new_name);
+ GIT_ASSERT_ARG(_backend);
+ GIT_ASSERT_ARG(old_name);
+ GIT_ASSERT_ARG(new_name);
backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
repo = backend->repo;
@@ -2033,11 +2025,11 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
if (git_buf_joinpath(&temp_path, repo->gitdir, GIT_REFLOG_DIR) < 0)
return -1;
- if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), old_name) < 0)
- return -1;
+ if ((error = loose_path(&old_path, git_buf_cstr(&temp_path), old_name)) < 0)
+ return error;
- if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path), git_buf_cstr(&normalized)) < 0)
- return -1;
+ if ((error = loose_path(&new_path, git_buf_cstr(&temp_path), git_buf_cstr(&normalized))) < 0)
+ return error;
if (!git_path_exists(git_buf_cstr(&old_path))) {
error = GIT_ENOTFOUND;
@@ -2051,8 +2043,8 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
* - a/b -> a/b/c
* - a/b/c/d -> a/b/c
*/
- if (git_buf_joinpath(&temp_path, git_buf_cstr(&temp_path), "temp_reflog") < 0)
- return -1;
+ if ((error = loose_path(&temp_path, git_buf_cstr(&temp_path), "temp_reflog")) < 0)
+ return error;
if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path), GIT_REFLOG_FILE_MODE)) < 0) {
error = -1;
@@ -2098,9 +2090,10 @@ static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name
git_buf path = GIT_BUF_INIT;
int error;
- assert(_backend && name);
+ GIT_ASSERT_ARG(_backend);
+ GIT_ASSERT_ARG(name);
- if ((error = retrieve_reflog_path(&path, backend->repo, name)) < 0)
+ if ((error = reflog_path(&path, backend->repo, name)) < 0)
goto out;
if (!git_path_exists(path.ptr))
@@ -2109,7 +2102,7 @@ static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name
if ((error = p_unlink(path.ptr)) < 0)
goto out;
- refdb_fs_backend__prune_refs(backend, name, GIT_REFLOG_DIR);
+ error = refdb_fs_backend__prune_refs(backend, name, GIT_REFLOG_DIR);
out:
git_buf_dispose(&path);
diff --git a/src/reflog.c b/src/reflog.c
index 34537aa1f..1e9c0d4f1 100644
--- a/src/reflog.c
+++ b/src/reflog.c
@@ -50,7 +50,9 @@ int git_reflog_read(git_reflog **reflog, git_repository *repo, const char *name
git_refdb *refdb;
int error;
- assert(reflog && repo && name);
+ GIT_ASSERT_ARG(reflog);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
return error;
@@ -62,7 +64,8 @@ int git_reflog_write(git_reflog *reflog)
{
git_refdb *db;
- assert(reflog && reflog->db);
+ GIT_ASSERT_ARG(reflog);
+ GIT_ASSERT_ARG(reflog->db);
db = reflog->db;
return db->backend->reflog_write(db->backend, reflog);
@@ -73,7 +76,9 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_sign
const git_reflog_entry *previous;
git_reflog_entry *entry;
- assert(reflog && new_oid && committer);
+ GIT_ASSERT_ARG(reflog);
+ GIT_ASSERT_ARG(new_oid);
+ GIT_ASSERT_ARG(committer);
entry = git__calloc(1, sizeof(git_reflog_entry));
GIT_ERROR_CHECK_ALLOC(entry);
@@ -139,13 +144,13 @@ int git_reflog_delete(git_repository *repo, const char *name)
size_t git_reflog_entrycount(git_reflog *reflog)
{
- assert(reflog);
+ GIT_ASSERT_ARG_WITH_RETVAL(reflog, 0);
return reflog->entries.length;
}
-const git_reflog_entry * git_reflog_entry_byindex(const git_reflog *reflog, size_t idx)
+const git_reflog_entry *git_reflog_entry_byindex(const git_reflog *reflog, size_t idx)
{
- assert(reflog);
+ GIT_ASSERT_ARG_WITH_RETVAL(reflog, NULL);
if (idx >= reflog->entries.length)
return NULL;
@@ -154,27 +159,27 @@ const git_reflog_entry * git_reflog_entry_byindex(const git_reflog *reflog, size
&reflog->entries, reflog_inverse_index(idx, reflog->entries.length));
}
-const git_oid * git_reflog_entry_id_old(const git_reflog_entry *entry)
+const git_oid *git_reflog_entry_id_old(const git_reflog_entry *entry)
{
- assert(entry);
+ GIT_ASSERT_ARG_WITH_RETVAL(entry, NULL);
return &entry->oid_old;
}
-const git_oid * git_reflog_entry_id_new(const git_reflog_entry *entry)
+const git_oid *git_reflog_entry_id_new(const git_reflog_entry *entry)
{
- assert(entry);
+ GIT_ASSERT_ARG_WITH_RETVAL(entry, NULL);
return &entry->oid_cur;
}
-const git_signature * git_reflog_entry_committer(const git_reflog_entry *entry)
+const git_signature *git_reflog_entry_committer(const git_reflog_entry *entry)
{
- assert(entry);
+ GIT_ASSERT_ARG_WITH_RETVAL(entry, NULL);
return entry->committer;
}
-const char * git_reflog_entry_message(const git_reflog_entry *entry)
+const char *git_reflog_entry_message(const git_reflog_entry *entry)
{
- assert(entry);
+ GIT_ASSERT_ARG_WITH_RETVAL(entry, NULL);
return entry->msg;
}
diff --git a/src/refs.c b/src/refs.c
index c5d69c18c..8acfa84a5 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -27,9 +27,6 @@
bool git_reference__enable_symbolic_ref_target_validation = true;
-#define DEFAULT_NESTING_LEVEL 5
-#define MAX_NESTING_LEVEL 10
-
enum {
GIT_PACKREF_HAS_PEEL = 1,
GIT_PACKREF_WAS_LOOSE = 2
@@ -53,7 +50,8 @@ git_reference *git_reference__alloc_symbolic(
{
git_reference *ref;
- assert(name && target);
+ GIT_ASSERT_ARG_WITH_RETVAL(name, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(target, NULL);
ref = alloc_ref(name);
if (!ref)
@@ -76,7 +74,8 @@ git_reference *git_reference__alloc(
{
git_reference *ref;
- assert(name && oid);
+ GIT_ASSERT_ARG_WITH_RETVAL(name, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(oid, NULL);
ref = alloc_ref(name);
if (!ref)
@@ -97,7 +96,8 @@ git_reference *git_reference__realloc(
size_t namelen, reflen;
git_reference *rewrite = NULL;
- assert(ptr_to_ref && name);
+ GIT_ASSERT_ARG_WITH_RETVAL(ptr_to_ref, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(name, NULL);
namelen = strlen(name);
@@ -214,97 +214,42 @@ int git_reference_lookup_resolved(
const char *name,
int max_nesting)
{
- git_refname_t scan_name;
- git_reference_t scan_type;
- int error = 0, nesting;
- git_reference *ref = NULL;
+ git_refname_t normalized;
git_refdb *refdb;
+ int error = 0;
- assert(ref_out && repo && name);
-
- *ref_out = NULL;
-
- if (max_nesting > MAX_NESTING_LEVEL)
- max_nesting = MAX_NESTING_LEVEL;
- else if (max_nesting < 0)
- max_nesting = DEFAULT_NESTING_LEVEL;
-
- scan_type = GIT_REFERENCE_SYMBOLIC;
-
- if ((error = reference_normalize_for_repo(scan_name, repo, name, true)) < 0)
- return error;
+ GIT_ASSERT_ARG(ref_out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
- if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
+ if ((error = reference_normalize_for_repo(normalized, repo, name, true)) < 0 ||
+ (error = git_repository_refdb__weakptr(&refdb, repo)) < 0 ||
+ (error = git_refdb_resolve(ref_out, refdb, normalized, max_nesting)) < 0)
return error;
- for (nesting = max_nesting;
- nesting >= 0 && scan_type == GIT_REFERENCE_SYMBOLIC;
- nesting--)
- {
- if (nesting != max_nesting) {
- strncpy(scan_name, ref->target.symbolic, sizeof(scan_name));
- git_reference_free(ref);
- }
-
- if ((error = git_refdb_lookup(&ref, refdb, scan_name)) < 0)
- return error;
-
- scan_type = ref->type;
- }
-
- if (scan_type != GIT_REFERENCE_DIRECT && max_nesting != 0) {
- git_error_set(GIT_ERROR_REFERENCE,
- "cannot resolve reference (>%u levels deep)", max_nesting);
- git_reference_free(ref);
- return -1;
+ /*
+ * The resolved reference may be a symbolic reference in case its
+ * target doesn't exist. If the user asked us to resolve (e.g.
+ * `max_nesting != 0`), then we need to return an error in case we got
+ * a symbolic reference back.
+ */
+ if (max_nesting && git_reference_type(*ref_out) == GIT_REFERENCE_SYMBOLIC) {
+ git_reference_free(*ref_out);
+ *ref_out = NULL;
+ return GIT_ENOTFOUND;
}
- *ref_out = ref;
return 0;
}
-int git_reference__read_head(
- git_reference **out,
- git_repository *repo,
- const char *path)
-{
- git_buf reference = GIT_BUF_INIT;
- char *name = NULL;
- int error;
-
- if ((error = git_futils_readbuffer(&reference, path)) < 0)
- goto out;
- git_buf_rtrim(&reference);
-
- if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)) == 0) {
- git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF));
-
- name = git_path_basename(path);
-
- if ((*out = git_reference__alloc_symbolic(name, reference.ptr)) == NULL) {
- error = -1;
- goto out;
- }
- } else {
- if ((error = git_reference_lookup(out, repo, reference.ptr)) < 0)
- goto out;
- }
-
-out:
- git__free(name);
- git_buf_dispose(&reference);
-
- return error;
-}
-
int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname)
{
- int error = 0, i;
+ int error = 0, i, valid;
bool fallbackmode = true, foundvalid = false;
git_reference *ref;
git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
- static const char* formatters[] = {
+ static const char *formatters[] = {
"%s",
GIT_REFS_DIR "%s",
GIT_REFS_TAGS_DIR "%s",
@@ -325,10 +270,11 @@ int git_reference_dwim(git_reference **out, git_repository *repo, const char *re
git_buf_clear(&refnamebuf);
- if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
+ if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0 ||
+ (error = git_reference_name_is_valid(&valid, git_buf_cstr(&refnamebuf))) < 0)
goto cleanup;
- if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
+ if (!valid) {
error = GIT_EINVALIDSPEC;
continue;
}
@@ -366,25 +312,25 @@ cleanup:
*/
git_reference_t git_reference_type(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG(ref);
return ref->type;
}
const char *git_reference_name(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG_WITH_RETVAL(ref, NULL);
return ref->name;
}
git_repository *git_reference_owner(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG_WITH_RETVAL(ref, NULL);
return ref->db->repo;
}
const git_oid *git_reference_target(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG_WITH_RETVAL(ref, NULL);
if (ref->type != GIT_REFERENCE_DIRECT)
return NULL;
@@ -394,7 +340,7 @@ const git_oid *git_reference_target(const git_reference *ref)
const git_oid *git_reference_target_peel(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG_WITH_RETVAL(ref, NULL);
if (ref->type != GIT_REFERENCE_DIRECT || git_oid_is_zero(&ref->peel))
return NULL;
@@ -404,7 +350,7 @@ const git_oid *git_reference_target_peel(const git_reference *ref)
const char *git_reference_symbolic_target(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG_WITH_RETVAL(ref, NULL);
if (ref->type != GIT_REFERENCE_SYMBOLIC)
return NULL;
@@ -429,8 +375,9 @@ static int reference__create(
git_reference *ref = NULL;
int error = 0;
- assert(repo && name);
- assert(symbolic || signature);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
+ GIT_ASSERT_ARG(symbolic || signature);
if (ref_out)
*ref_out = NULL;
@@ -444,7 +391,7 @@ static int reference__create(
return error;
if (oid != NULL) {
- assert(symbolic == NULL);
+ GIT_ASSERT(symbolic == NULL);
if (!git_object__is_valid(repo, oid, GIT_OBJECT_ANY)) {
git_error_set(GIT_ERROR_REFERENCE,
@@ -516,7 +463,7 @@ int git_reference_create_matching(
int error;
git_signature *who = NULL;
- assert(id);
+ GIT_ASSERT_ARG(id);
if ((error = git_reference__log_signature(&who, repo)) < 0)
return error;
@@ -551,7 +498,7 @@ int git_reference_symbolic_create_matching(
int error;
git_signature *who = NULL;
- assert(target);
+ GIT_ASSERT_ARG(target);
if ((error = git_reference__log_signature(&who, repo)) < 0)
return error;
@@ -592,7 +539,9 @@ int git_reference_set_target(
int error;
git_repository *repo;
- assert(out && ref && id);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(ref);
+ GIT_ASSERT_ARG(id);
repo = ref->db->repo;
@@ -619,7 +568,9 @@ int git_reference_symbolic_set_target(
{
int error;
- assert(out && ref && target);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(ref);
+ GIT_ASSERT_ARG(target);
if ((error = ensure_is_an_updatable_symbolic_reference(ref)) < 0)
return error;
@@ -631,84 +582,33 @@ int git_reference_symbolic_set_target(
typedef struct {
const char *old_name;
git_refname_t new_name;
-} rename_cb_data;
+} refs_update_head_payload;
-static int update_wt_heads(git_repository *repo, const char *path, void *payload)
+static int refs_update_head(git_repository *worktree, void *_payload)
{
- rename_cb_data *data = (rename_cb_data *) payload;
- git_reference *head = NULL;
- char *gitdir = NULL;
+ refs_update_head_payload *payload = (refs_update_head_payload *)_payload;
+ git_reference *head = NULL, *updated = NULL;
int error;
- if ((error = git_reference__read_head(&head, repo, path)) < 0) {
- git_error_set(GIT_ERROR_REFERENCE, "could not read HEAD when renaming references");
- goto out;
- }
-
- if ((gitdir = git_path_dirname(path)) == NULL) {
- error = -1;
+ if ((error = git_reference_lookup(&head, worktree, GIT_HEAD_FILE)) < 0)
goto out;
- }
if (git_reference_type(head) != GIT_REFERENCE_SYMBOLIC ||
- git__strcmp(head->target.symbolic, data->old_name) != 0) {
- error = 0;
+ git__strcmp(git_reference_symbolic_target(head), payload->old_name) != 0)
goto out;
- }
- /* Update HEAD it was pointing to the reference being renamed */
- if ((error = git_repository_create_head(gitdir, data->new_name)) < 0) {
+ /* Update HEAD if it was pointing to the reference being renamed */
+ if ((error = git_reference_symbolic_set_target(&updated, head, payload->new_name, NULL)) < 0) {
git_error_set(GIT_ERROR_REFERENCE, "failed to update HEAD after renaming reference");
goto out;
}
out:
+ git_reference_free(updated);
git_reference_free(head);
- git__free(gitdir);
-
return error;
}
-static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force,
- const git_signature *signature, const char *message)
-{
- git_repository *repo;
- git_refname_t normalized;
- bool should_head_be_updated = false;
- int error = 0;
-
- assert(ref && new_name && signature);
-
- repo = git_reference_owner(ref);
-
- if ((error = reference_normalize_for_repo(
- normalized, repo, new_name, true)) < 0)
- return error;
-
- /* Check if we have to update HEAD. */
- if ((error = git_branch_is_head(ref)) < 0)
- return error;
-
- should_head_be_updated = (error > 0);
-
- if ((error = git_refdb_rename(out, ref->db, ref->name, normalized, force, signature, message)) < 0)
- return error;
-
- /* Update HEAD if it was pointing to the reference being renamed */
- if (should_head_be_updated) {
- error = git_repository_set_head(ref->db->repo, normalized);
- } else {
- rename_cb_data payload;
- payload.old_name = ref->name;
- memcpy(&payload.new_name, &normalized, sizeof(normalized));
-
- error = git_repository_foreach_head(repo, update_wt_heads, 0, &payload);
- }
-
- return error;
-}
-
-
int git_reference_rename(
git_reference **out,
git_reference *ref,
@@ -716,17 +616,29 @@ int git_reference_rename(
int force,
const char *log_message)
{
- git_signature *who;
+ refs_update_head_payload payload;
+ git_signature *signature = NULL;
+ git_repository *repo;
int error;
- assert(out && ref);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(ref);
- if ((error = git_reference__log_signature(&who, ref->db->repo)) < 0)
- return error;
+ repo = git_reference_owner(ref);
- error = reference__rename(out, ref, new_name, force, who, log_message);
- git_signature_free(who);
+ if ((error = git_reference__log_signature(&signature, repo)) < 0 ||
+ (error = reference_normalize_for_repo(payload.new_name, repo, new_name, true)) < 0 ||
+ (error = git_refdb_rename(out, ref->db, ref->name, payload.new_name, force, signature, log_message)) < 0)
+ goto out;
+ payload.old_name = ref->name;
+
+ /* We may have to update any HEAD that was pointing to the renamed reference. */
+ if ((error = git_repository_foreach_worktree(repo, refs_update_head, &payload)) < 0)
+ goto out;
+
+out:
+ git_signature_free(signature);
return error;
}
@@ -876,7 +788,8 @@ int git_reference_list(
{
git_vector ref_list;
- assert(array && repo);
+ GIT_ASSERT_ARG(array);
+ GIT_ASSERT_ARG(repo);
array->strings = NULL;
array->count = 0;
@@ -960,7 +873,8 @@ static bool is_all_caps_and_underscore(const char *name, size_t len)
size_t i;
char c;
- assert(name && len > 0);
+ GIT_ASSERT_ARG(name);
+ GIT_ASSERT_ARG(len > 0);
for (i = 0; i < len; i++)
{
@@ -991,7 +905,7 @@ int git_reference__normalize_name(
git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
#endif
- assert(name);
+ GIT_ASSERT_ARG(name);
process_flags = flags;
current = (char *)name;
@@ -1123,7 +1037,8 @@ int git_reference_normalize_name(
goto cleanup;
}
- git_buf_copy_cstr(buffer_out, buffer_size, &buf);
+ if ((error = git_buf_copy_cstr(buffer_out, buffer_size, &buf)) < 0)
+ goto cleanup;
error = 0;
@@ -1139,7 +1054,9 @@ int git_reference_cmp(
const git_reference *ref2)
{
git_reference_t type1, type2;
- assert(ref1 && ref2);
+
+ GIT_ASSERT_ARG(ref1);
+ GIT_ASSERT_ARG(ref2);
type1 = git_reference_type(ref1);
type2 = git_reference_type(ref2);
@@ -1154,40 +1071,6 @@ int git_reference_cmp(
return git_oid__cmp(&ref1->target.oid, &ref2->target.oid);
}
-/**
- * Get the end of a chain of references. If the final one is not
- * found, we return the reference just before that.
- */
-static int get_terminal(git_reference **out, git_repository *repo, const char *ref_name, int nesting)
-{
- git_reference *ref;
- int error = 0;
-
- if (nesting > MAX_NESTING_LEVEL) {
- git_error_set(GIT_ERROR_REFERENCE, "reference chain too deep (%d)", nesting);
- return GIT_ENOTFOUND;
- }
-
- /* set to NULL to let the caller know that they're at the end of the chain */
- if ((error = git_reference_lookup(&ref, repo, ref_name)) < 0) {
- *out = NULL;
- return error;
- }
-
- if (git_reference_type(ref) == GIT_REFERENCE_DIRECT) {
- *out = ref;
- error = 0;
- } else {
- error = get_terminal(out, repo, git_reference_symbolic_target(ref), nesting + 1);
- if (error == GIT_ENOTFOUND && !*out)
- *out = ref;
- else
- git_reference_free(ref);
- }
-
- return error;
-}
-
/*
* Starting with the reference given by `ref_name`, follows symbolic
* references until a direct reference is found and updated the OID
@@ -1202,31 +1085,37 @@ int git_reference__update_terminal(
{
git_reference *ref = NULL, *ref2 = NULL;
git_signature *who = NULL;
+ git_refdb *refdb = NULL;
const git_signature *to_use;
int error = 0;
if (!sig && (error = git_reference__log_signature(&who, repo)) < 0)
- return error;
+ goto out;
to_use = sig ? sig : who;
- error = get_terminal(&ref, repo, ref_name, 0);
- /* found a dangling symref */
- if (error == GIT_ENOTFOUND && ref) {
- assert(git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC);
- git_error_clear();
+ if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
+ goto out;
+
+ if ((error = git_refdb_resolve(&ref, refdb, ref_name, -1)) < 0) {
+ if (error == GIT_ENOTFOUND) {
+ git_error_clear();
+ error = reference__create(&ref2, repo, ref_name, oid, NULL, 0, to_use,
+ log_message, NULL, NULL);
+ }
+ goto out;
+ }
+
+ /* In case the resolved reference is symbolic, then it's a dangling symref. */
+ if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) {
error = reference__create(&ref2, repo, ref->target.symbolic, oid, NULL, 0, to_use,
log_message, NULL, NULL);
- } else if (error == GIT_ENOTFOUND) {
- git_error_clear();
- error = reference__create(&ref2, repo, ref_name, oid, NULL, 0, to_use,
- log_message, NULL, NULL);
- } else if (error == 0) {
- assert(git_reference_type(ref) == GIT_REFERENCE_DIRECT);
+ } else {
error = reference__create(&ref2, repo, ref->name, oid, NULL, 1, to_use,
log_message, &ref->target.oid, NULL);
}
+out:
git_reference_free(ref2);
git_reference_free(ref);
git_signature_free(who);
@@ -1290,7 +1179,8 @@ int git_reference_has_log(git_repository *repo, const char *refname)
int error;
git_refdb *refdb;
- assert(repo && refname);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(refname);
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
return error;
@@ -1303,7 +1193,8 @@ int git_reference_ensure_log(git_repository *repo, const char *refname)
int error;
git_refdb *refdb;
- assert(repo && refname);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(refname);
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
return error;
@@ -1318,7 +1209,7 @@ int git_reference__is_branch(const char *ref_name)
int git_reference_is_branch(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG(ref);
return git_reference__is_branch(ref->name);
}
@@ -1329,7 +1220,7 @@ int git_reference__is_remote(const char *ref_name)
int git_reference_is_remote(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG(ref);
return git_reference__is_remote(ref->name);
}
@@ -1340,7 +1231,7 @@ int git_reference__is_tag(const char *ref_name)
int git_reference_is_tag(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG(ref);
return git_reference__is_tag(ref->name);
}
@@ -1351,11 +1242,11 @@ int git_reference__is_note(const char *ref_name)
int git_reference_is_note(const git_reference *ref)
{
- assert(ref);
+ GIT_ASSERT_ARG(ref);
return git_reference__is_note(ref->name);
}
-static int peel_error(int error, const git_reference *ref, const char* msg)
+static int peel_error(int error, const git_reference *ref, const char *msg)
{
git_error_set(
GIT_ERROR_INVALID,
@@ -1373,7 +1264,7 @@ int git_reference_peel(
git_object *target = NULL;
int error;
- assert(ref);
+ GIT_ASSERT_ARG(ref);
if (ref->type == GIT_REFERENCE_DIRECT) {
resolved = ref;
@@ -1415,19 +1306,30 @@ cleanup:
return error;
}
-int git_reference__is_valid_name(const char *refname, unsigned int flags)
+int git_reference__name_is_valid(
+ int *valid,
+ const char *refname,
+ unsigned int flags)
{
- if (git_reference__normalize_name(NULL, refname, flags) < 0) {
- git_error_clear();
- return false;
- }
+ int error;
- return true;
+ GIT_ASSERT(valid && refname);
+
+ *valid = 0;
+
+ error = git_reference__normalize_name(NULL, refname, flags);
+
+ if (!error)
+ *valid = 1;
+ else if (error == GIT_EINVALIDSPEC)
+ error = 0;
+
+ return error;
}
-int git_reference_is_valid_name(const char *refname)
+int git_reference_name_is_valid(int *valid, const char *refname)
{
- return git_reference__is_valid_name(refname, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL);
+ return git_reference__name_is_valid(valid, refname, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL);
}
const char *git_reference__shorthand(const char *name)
@@ -1441,7 +1343,7 @@ const char *git_reference__shorthand(const char *name)
else if (!git__prefixcmp(name, GIT_REFS_DIR))
return name + strlen(GIT_REFS_DIR);
- /* No shorthands are avaiable, so just return the name */
+ /* No shorthands are available, so just return the name. */
return name;
}
@@ -1454,7 +1356,10 @@ int git_reference__is_unborn_head(bool *unborn, const git_reference *ref, git_re
{
int error;
git_reference *tmp_ref;
- assert(unborn && ref && repo);
+
+ GIT_ASSERT_ARG(unborn);
+ GIT_ASSERT_ARG(ref);
+ GIT_ASSERT_ARG(repo);
if (ref->type == GIT_REFERENCE_DIRECT) {
*unborn = 0;
@@ -1473,3 +1378,18 @@ int git_reference__is_unborn_head(bool *unborn, const git_reference *ref, git_re
return 0;
}
+
+/* Deprecated functions */
+
+#ifndef GIT_DEPRECATE_HARD
+
+int git_reference_is_valid_name(const char *refname)
+{
+ int valid = 0;
+
+ git_reference__name_is_valid(&valid, refname, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL);
+
+ return valid;
+}
+
+#endif
diff --git a/src/refs.h b/src/refs.h
index ece66468a..376a512f8 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -45,7 +45,6 @@ extern bool git_reference__enable_symbolic_ref_target_validation;
#define GIT_REBASE_APPLY_DIR "rebase-apply/"
#define GIT_REBASE_APPLY_REBASING_FILE GIT_REBASE_APPLY_DIR "rebasing"
#define GIT_REBASE_APPLY_APPLYING_FILE GIT_REBASE_APPLY_DIR "applying"
-#define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master"
#define GIT_SEQUENCER_DIR "sequencer/"
#define GIT_SEQUENCER_HEAD_FILE GIT_SEQUENCER_DIR "head"
@@ -86,7 +85,7 @@ git_reference *git_reference__realloc(git_reference **ptr_to_ref, const char *na
int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags);
int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid, const git_signature *sig, const char *log_message);
-int git_reference__is_valid_name(const char *refname, unsigned int flags);
+int git_reference__name_is_valid(int *valid, const char *name, unsigned int flags);
int git_reference__is_branch(const char *ref_name);
int git_reference__is_remote(const char *ref_name);
int git_reference__is_tag(const char *ref_name);
@@ -116,24 +115,6 @@ int git_reference_lookup_resolved(
const char *name,
int max_deref);
-/**
- * Read reference from a file.
- *
- * This function will read in the file at `path`. If it is a
- * symref, it will return a new unresolved symbolic reference
- * with the given name pointing to the reference pointed to by
- * the file. If it is not a symbolic reference, it will return
- * the resolved reference.
- *
- * Note that because the refdb is not involved for symbolic references, they
- * won't be owned, hence you should either not make the returned reference
- * 'externally visible', or perform the lookup before returning it to the user.
- */
-int git_reference__read_head(
- git_reference **out,
- git_repository *repo,
- const char *path);
-
int git_reference__log_signature(git_signature **out, git_repository *repo);
/** Update a reference after a commit. */
diff --git a/src/refspec.c b/src/refspec.c
index 854240a84..c72721a43 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -21,9 +21,11 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
size_t llen;
int is_glob = 0;
const char *lhs, *rhs;
- int flags;
+ int valid = 0;
+ unsigned int flags;
- assert(refspec && input);
+ GIT_ASSERT_ARG(refspec);
+ GIT_ASSERT_ARG(input);
memset(refspec, 0x0, sizeof(git_refspec));
refspec->push = !is_fetch;
@@ -75,57 +77,69 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
if (is_fetch) {
/*
- * LHS
- * - empty is allowed; it means HEAD.
- * - otherwise it must be a valid looking ref.
- */
+ * LHS
+ * - empty is allowed; it means HEAD.
+ * - otherwise it must be a valid looking ref.
+ */
if (!*refspec->src)
; /* empty is ok */
- else if (!git_reference__is_valid_name(refspec->src, flags))
+ else if (git_reference__name_is_valid(&valid, refspec->src, flags) < 0)
+ goto on_error;
+ else if (!valid)
goto invalid;
+
/*
- * RHS
- * - missing is ok, and is same as empty.
- * - empty is ok; it means not to store.
- * - otherwise it must be a valid looking ref.
- */
+ * RHS
+ * - missing is ok, and is same as empty.
+ * - empty is ok; it means not to store.
+ * - otherwise it must be a valid looking ref.
+ */
if (!refspec->dst)
; /* ok */
else if (!*refspec->dst)
; /* ok */
- else if (!git_reference__is_valid_name(refspec->dst, flags))
+ else if (git_reference__name_is_valid(&valid, refspec->dst, flags) < 0)
+ goto on_error;
+ else if (!valid)
goto invalid;
} else {
/*
- * LHS
- * - empty is allowed; it means delete.
- * - when wildcarded, it must be a valid looking ref.
- * - otherwise, it must be an extended SHA-1, but
- * there is no existing way to validate this.
- */
+ * LHS
+ * - empty is allowed; it means delete.
+ * - when wildcarded, it must be a valid looking ref.
+ * - otherwise, it must be an extended SHA-1, but
+ * there is no existing way to validate this.
+ */
if (!*refspec->src)
; /* empty is ok */
else if (is_glob) {
- if (!git_reference__is_valid_name(refspec->src, flags))
+ if (git_reference__name_is_valid(&valid, refspec->src, flags) < 0)
+ goto on_error;
+ else if (!valid)
goto invalid;
}
else {
; /* anything goes, for now */
}
+
/*
- * RHS
- * - missing is allowed, but LHS then must be a
- * valid looking ref.
- * - empty is not allowed.
- * - otherwise it must be a valid looking ref.
- */
+ * RHS
+ * - missing is allowed, but LHS then must be a
+ * valid looking ref.
+ * - empty is not allowed.
+ * - otherwise it must be a valid looking ref.
+ */
if (!refspec->dst) {
- if (!git_reference__is_valid_name(refspec->src, flags))
+ if (git_reference__name_is_valid(&valid, refspec->src, flags) < 0)
+ goto on_error;
+ else if (!valid)
goto invalid;
} else if (!*refspec->dst) {
goto invalid;
} else {
- if (!git_reference__is_valid_name(refspec->dst, flags))
+ if (git_reference__name_is_valid(&valid, refspec->dst, flags) < 0)
+ goto on_error;
+ else if (!valid)
goto invalid;
}
@@ -141,11 +155,14 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
return 0;
- invalid:
- git_error_set(
- GIT_ERROR_INVALID,
- "'%s' is not a valid refspec.", input);
- git_refspec__dispose(refspec);
+invalid:
+ git_error_set(GIT_ERROR_INVALID,
+ "'%s' is not a valid refspec.", input);
+ git_refspec__dispose(refspec);
+ return GIT_EINVALIDSPEC;
+
+on_error:
+ git_refspec__dispose(refspec);
return -1;
}
@@ -164,7 +181,8 @@ void git_refspec__dispose(git_refspec *refspec)
int git_refspec_parse(git_refspec **out_refspec, const char *input, int is_fetch)
{
git_refspec *refspec;
- assert(out_refspec && input);
+ GIT_ASSERT_ARG(out_refspec);
+ GIT_ASSERT_ARG(input);
*out_refspec = NULL;
@@ -203,7 +221,7 @@ const char *git_refspec_string(const git_refspec *refspec)
int git_refspec_force(const git_refspec *refspec)
{
- assert(refspec);
+ GIT_ASSERT_ARG(refspec);
return refspec->force;
}
@@ -229,8 +247,11 @@ static int refspec_transform(
{
const char *from_star, *to_star;
size_t replacement_len, star_offset;
+ int error;
+
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
- git_buf_sanitize(out);
git_buf_clear(out);
/*
@@ -242,7 +263,7 @@ static int refspec_transform(
from_star = strchr(from, '*');
to_star = strchr(to, '*');
- assert(from_star && to_star);
+ GIT_ASSERT(from_star && to_star);
/* star offset, both in 'from' and in 'name' */
star_offset = from_star - from;
@@ -262,8 +283,14 @@ static int refspec_transform(
int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name)
{
- assert(out && spec && name);
- git_buf_sanitize(out);
+ int error;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(spec);
+ GIT_ASSERT_ARG(name);
+
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
if (!git_refspec_src_matches(spec, name)) {
git_error_set(GIT_ERROR_INVALID, "ref '%s' doesn't match the source", name);
@@ -278,8 +305,14 @@ int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *nam
int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
{
- assert(out && spec && name);
- git_buf_sanitize(out);
+ int error;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(spec);
+ GIT_ASSERT_ARG(name);
+
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
if (!git_refspec_dst_matches(spec, name)) {
git_error_set(GIT_ERROR_INVALID, "ref '%s' doesn't match the destination", name);
@@ -306,14 +339,15 @@ int git_refspec__serialize(git_buf *out, const git_refspec *refspec)
int git_refspec_is_wildcard(const git_refspec *spec)
{
- assert(spec && spec->src);
+ GIT_ASSERT_ARG(spec);
+ GIT_ASSERT_ARG(spec->src);
return (spec->src[strlen(spec->src) - 1] == '*');
}
git_direction git_refspec_direction(const git_refspec *spec)
{
- assert(spec);
+ GIT_ASSERT_ARG(spec);
return spec->push;
}
@@ -325,14 +359,16 @@ int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
git_remote_head key;
git_refspec *cur;
- const char* formatters[] = {
+ const char *formatters[] = {
GIT_REFS_DIR "%s",
GIT_REFS_TAGS_DIR "%s",
GIT_REFS_HEADS_DIR "%s",
NULL
};
- assert(out && spec && refs);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(spec);
+ GIT_ASSERT_ARG(refs);
cur = git__calloc(1, sizeof(git_refspec));
GIT_ERROR_CHECK_ALLOC(cur);
diff --git a/src/regexp.c b/src/regexp.c
index 5fe49f37e..c1b9ef4cd 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -12,7 +12,7 @@
int git_regexp_compile(git_regexp *r, const char *pattern, int flags)
{
int erroffset, cflags = 0;
- const char *error;
+ const char *error = NULL;
if (flags & GIT_REGEXP_ICASE)
cflags |= PCRE_CASELESS;
@@ -41,7 +41,7 @@ int git_regexp_match(const git_regexp *r, const char *string)
int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches)
{
- int static_ovec[9], *ovec;
+ int static_ovec[9] = {0}, *ovec;
int error;
size_t i;
diff --git a/src/remote.c b/src/remote.c
index 23054c83b..56d7e42db 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -82,9 +82,11 @@ static int download_tags_value(git_remote *remote, git_config *cfg)
static int ensure_remote_name_is_valid(const char *name)
{
- int error = 0;
+ int valid, error;
+
+ error = git_remote_name_is_valid(&valid, name);
- if (!git_remote_is_valid_name(name)) {
+ if (!error && !valid) {
git_error_set(
GIT_ERROR_CONFIG,
"'%s' is not a valid remote name.", name ? name : "(null)");
@@ -110,12 +112,8 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
if ((error = ensure_remote_name_is_valid(name)) < 0)
return error;
- if ((error = git_refspec__parse(&spec, refspec, fetch)) < 0) {
- if (git_error_last()->klass != GIT_ERROR_NOMEMORY)
- error = GIT_EINVALIDSPEC;
-
+ if ((error = git_refspec__parse(&spec, refspec, fetch)) < 0)
return error;
- }
git_refspec__dispose(&spec);
@@ -123,7 +121,7 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
return error;
/*
- * "$^" is a unmatcheable regexp: it will not match anything at all, so
+ * "$^" is an unmatchable regexp: it will not match anything at all, so
* all values will be considered new and we will not replace any
* present value.
*/
@@ -212,7 +210,8 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
const git_remote_create_options dummy_opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
int error = -1;
- assert(out && url);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(url);
if (!opts) {
opts = &dummy_opts;
@@ -461,7 +460,9 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
struct refspec_cb_data data = { NULL };
bool optional_setting_found = false, found;
- assert(out && repo && name);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
if ((error = ensure_remote_name_is_valid(name)) < 0)
return error;
@@ -583,29 +584,46 @@ static int lookup_remote_prune_config(git_remote *remote, git_config *config, co
const char *git_remote_name(const git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
return remote->name;
}
git_repository *git_remote_owner(const git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
return remote->repo;
}
const char *git_remote_url(const git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
return remote->url;
}
+int git_remote_set_instance_url(git_remote *remote, const char *url)
+{
+ char *tmp;
+
+ GIT_ASSERT_ARG(remote);
+ GIT_ASSERT_ARG(url);
+
+ if ((tmp = git__strdup(url)) == NULL)
+ return -1;
+
+ git__free(remote->url);
+ remote->url = tmp;
+
+ return 0;
+}
+
static int set_url(git_repository *repo, const char *remote, const char *pattern, const char *url)
{
git_config *cfg;
git_buf buf = GIT_BUF_INIT, canonical_url = GIT_BUF_INIT;
int error;
- assert(repo && remote);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(remote);
if ((error = ensure_remote_name_is_valid(remote)) < 0)
return error;
@@ -639,44 +657,84 @@ int git_remote_set_url(git_repository *repo, const char *remote, const char *url
const char *git_remote_pushurl(const git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
return remote->pushurl;
}
-int git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url)
+int git_remote_set_instance_pushurl(git_remote *remote, const char *url)
+{
+ char *tmp;
+
+ GIT_ASSERT_ARG(remote);
+ GIT_ASSERT_ARG(url);
+
+ if ((tmp = git__strdup(url)) == NULL)
+ return -1;
+
+ git__free(remote->pushurl);
+ remote->pushurl = tmp;
+
+ return 0;
+}
+
+int git_remote_set_pushurl(git_repository *repo, const char *remote, const char *url)
{
return set_url(repo, remote, CONFIG_PUSHURL_FMT, url);
}
-static int resolve_url(git_buf *resolved_url, const char *url, int direction, const git_remote_callbacks *callbacks)
+static int resolve_url(
+ git_buf *resolved_url,
+ const char *url,
+ int direction,
+ const git_remote_callbacks *callbacks)
{
- int status;
+#ifdef GIT_DEPRECATE_HARD
+ GIT_UNUSED(direction);
+ GIT_UNUSED(callbacks);
+#else
+ int status, error;
if (callbacks && callbacks->resolve_url) {
git_buf_clear(resolved_url);
status = callbacks->resolve_url(resolved_url, url, direction, callbacks->payload);
if (status != GIT_PASSTHROUGH) {
git_error_set_after_callback_function(status, "git_resolve_url_cb");
- git_buf_sanitize(resolved_url);
+
+ if ((error = git_buf_sanitize(resolved_url)) < 0)
+ return error;
+
return status;
}
}
+#endif
return git_buf_sets(resolved_url, url);
}
-int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks)
+int git_remote__urlfordirection(
+ git_buf *url_out,
+ struct git_remote *remote,
+ int direction,
+ const git_remote_callbacks *callbacks)
{
const char *url = NULL;
- assert(remote);
- assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
+ GIT_ASSERT_ARG(remote);
+ GIT_ASSERT_ARG(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
- if (direction == GIT_DIRECTION_FETCH) {
+ if (callbacks && callbacks->remote_ready) {
+ int status = callbacks->remote_ready(remote, direction, callbacks->payload);
+
+ if (status != 0 && status != GIT_PASSTHROUGH) {
+ git_error_set_after_callback_function(status, "git_remote_ready_cb");
+ return status;
+ }
+ }
+
+ if (direction == GIT_DIRECTION_FETCH)
url = remote->url;
- } else if (direction == GIT_DIRECTION_PUSH) {
+ else if (direction == GIT_DIRECTION_PUSH)
url = remote->pushurl ? remote->pushurl : remote->url;
- }
if (!url) {
git_error_set(GIT_ERROR_INVALID,
@@ -685,6 +743,7 @@ int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int
direction == GIT_DIRECTION_FETCH ? "fetch" : "push");
return GIT_EINVALID;
}
+
return resolve_url(url_out, url, direction, callbacks);
}
@@ -715,7 +774,7 @@ int git_remote__connect(git_remote *remote, git_direction direction, const git_r
git_credential_acquire_cb credentials = NULL;
git_transport_cb transport = NULL;
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (callbacks) {
GIT_ERROR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
@@ -780,7 +839,7 @@ int git_remote_connect(git_remote *remote, git_direction direction, const git_re
int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (!remote->transport) {
git_error_set(GIT_ERROR_NET, "this remote has never connected");
@@ -790,75 +849,147 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote
return remote->transport->ls(out, size, remote->transport);
}
-int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
+static int lookup_config(char **out, git_config *cfg, const char *name)
{
- git_config *cfg;
git_config_entry *ce = NULL;
- git_buf val = GIT_BUF_INIT;
int error;
- assert(remote);
+ if ((error = git_config__lookup_entry(&ce, cfg, name, false)) < 0)
+ return error;
- if (!proxy_url || !remote->repo)
- return -1;
+ if (ce && ce->value) {
+ *out = git__strdup(ce->value);
+ GIT_ERROR_CHECK_ALLOC(*out);
+ } else {
+ error = GIT_ENOTFOUND;
+ }
+
+ git_config_entry_free(ce);
+ return error;
+}
- *proxy_url = NULL;
+static void url_config_trim(git_net_url *url)
+{
+ size_t len = strlen(url->path);
- if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
- return error;
+ if (url->path[len - 1] == '/') {
+ len--;
+ } else {
+ while (len && url->path[len - 1] != '/')
+ len--;
+ }
+
+ url->path[len] = '\0';
+}
+
+static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
+{
+ git_config *cfg = NULL;
+ git_buf buf = GIT_BUF_INIT;
+ git_net_url lookup_url = GIT_NET_URL_INIT;
+ int error;
+
+ if ((error = git_net_url_dup(&lookup_url, url)) < 0)
+ goto done;
- /* Go through the possible sources for proxy configuration, from most specific
- * to least specific. */
+ if (remote->repo) {
+ if ((error = git_repository_config(&cfg, remote->repo)) < 0)
+ goto done;
+ } else {
+ if ((error = git_config_open_default(&cfg)) < 0)
+ goto done;
+ }
/* remote.<name>.proxy config setting */
if (remote->name && remote->name[0]) {
- git_buf buf = GIT_BUF_INIT;
+ git_buf_clear(&buf);
- if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0)
- return error;
+ if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0 ||
+ (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
+ goto done;
+ }
- error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
- git_buf_dispose(&buf);
+ while (true) {
+ git_buf_clear(&buf);
- if (error < 0)
- return error;
+ if ((error = git_buf_puts(&buf, "http.")) < 0 ||
+ (error = git_net_url_fmt(&buf, &lookup_url)) < 0 ||
+ (error = git_buf_puts(&buf, ".proxy")) < 0 ||
+ (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
+ goto done;
- if (ce && ce->value) {
- *proxy_url = git__strdup(ce->value);
- goto found;
- }
+ if (! lookup_url.path[0])
+ break;
+
+ url_config_trim(&lookup_url);
}
- /* http.proxy config setting */
- if ((error = git_config__lookup_entry(&ce, cfg, "http.proxy", false)) < 0)
- return error;
+ git_buf_clear(&buf);
- if (ce && ce->value) {
- *proxy_url = git__strdup(ce->value);
- goto found;
- }
+ error = lookup_config(out, cfg, "http.proxy");
+
+done:
+ git_config_free(cfg);
+ git_buf_dispose(&buf);
+ git_net_url_dispose(&lookup_url);
+ return error;
+}
+
+static int http_proxy_env(char **out, git_remote *remote, git_net_url *url)
+{
+ git_buf proxy_env = GIT_BUF_INIT, no_proxy_env = GIT_BUF_INIT;
+ bool use_ssl = (strcmp(url->scheme, "https") == 0);
+ int error;
+
+ GIT_UNUSED(remote);
/* http_proxy / https_proxy environment variables */
- error = git__getenv(&val, use_ssl ? "https_proxy" : "http_proxy");
+ error = git__getenv(&proxy_env, use_ssl ? "https_proxy" : "http_proxy");
/* try uppercase environment variables */
if (error == GIT_ENOTFOUND)
- error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
+ error = git__getenv(&proxy_env, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
- if (error < 0) {
- if (error == GIT_ENOTFOUND) {
- git_error_clear();
- error = 0;
- }
+ if (error)
+ goto done;
- return error;
- }
+ /* no_proxy/NO_PROXY environment variables */
+ error = git__getenv(&no_proxy_env, "no_proxy");
- *proxy_url = git_buf_detach(&val);
+ if (error == GIT_ENOTFOUND)
+ error = git__getenv(&no_proxy_env, "NO_PROXY");
-found:
- GIT_ERROR_CHECK_ALLOC(*proxy_url);
- git_config_entry_free(ce);
+ if (error && error != GIT_ENOTFOUND)
+ goto done;
+
+ if (!git_net_url_matches_pattern_list(url, no_proxy_env.ptr))
+ *out = git_buf_detach(&proxy_env);
+ else
+ error = GIT_ENOTFOUND;
+
+done:
+ git_buf_dispose(&proxy_env);
+ git_buf_dispose(&no_proxy_env);
+ return error;
+}
+
+int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url)
+{
+ int error;
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(remote);
+
+ *out = NULL;
+
+ /*
+ * Go through the possible sources for proxy configuration,
+ * Examine the various git config options first, then
+ * consult environment variables.
+ */
+ if ((error = http_proxy_config(out, remote, url)) != GIT_ENOTFOUND ||
+ (error = http_proxy_env(out, remote, url)) != GIT_ENOTFOUND)
+ return error;
return 0;
}
@@ -926,7 +1057,7 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
const git_strarray *custom_headers = NULL;
const git_proxy_options *proxy = NULL;
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (!remote->repo) {
git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
@@ -1065,7 +1196,8 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda
unsigned int i;
git_remote_head *remote_ref;
- assert(update_heads && fetchspec_src);
+ GIT_ASSERT_ARG(update_heads);
+ GIT_ASSERT_ARG(fetchspec_src);
*out = NULL;
@@ -1119,7 +1251,9 @@ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_re
const char *ref_name;
int error = 0, update;
- assert(out && spec && ref);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(spec);
+ GIT_ASSERT_ARG(ref);
*out = NULL;
@@ -1133,6 +1267,16 @@ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_re
ref_name = git_reference_name(resolved_ref);
}
+ /*
+ * The ref name may be unresolvable - perhaps it's pointing to
+ * something invalid. In this case, there is no remote head for
+ * this ref.
+ */
+ if (!ref_name) {
+ error = 0;
+ goto cleanup;
+ }
+
if ((error = ref_to_update(&update, &remote_name, remote, spec, ref_name)) < 0)
goto cleanup;
@@ -1156,7 +1300,7 @@ static int git_remote_write_fetchhead(git_remote *remote, git_refspec *spec, git
unsigned int i = 0;
int error = 0;
- assert(remote);
+ GIT_ASSERT_ARG(remote);
/* no heads, nothing to do */
if (update_heads->length == 0)
@@ -1299,7 +1443,7 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
if (error == GIT_ENOTFOUND)
continue;
- /* if we did find a source, remove it from the candiates */
+ /* If we did find a source, remove it from the candidates. */
if ((error = git_vector_set((void **) &src_name, &candidates, i, NULL)) < 0)
goto cleanup;
@@ -1362,7 +1506,7 @@ static int update_tips_for_spec(
git_vector *refs,
const char *log_message)
{
- int error = 0, autotag;
+ int error = 0, autotag, valid;
unsigned int i = 0;
git_buf refname = GIT_BUF_INIT;
git_oid old;
@@ -1372,7 +1516,7 @@ static int update_tips_for_spec(
git_refspec tagspec;
git_vector update_heads;
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
return -1;
@@ -1390,7 +1534,10 @@ static int update_tips_for_spec(
git_buf_clear(&refname);
/* Ignore malformed ref names (which also saves us from tag^{} */
- if (!git_reference_is_valid_name(head->name))
+ if (git_reference_name_is_valid(&valid, head->name) < 0)
+ goto on_error;
+
+ if (!valid)
continue;
/* If we have a tag, see if the auto-follow rules say to update it */
@@ -1439,6 +1586,11 @@ static int update_tips_for_spec(
if (error < 0 && error != GIT_ENOTFOUND)
goto on_error;
+ if (!(error || error == GIT_ENOTFOUND)
+ && !spec->force
+ && !git_graph_descendant_of(remote->repo, &head->oid, &old))
+ continue;
+
if (error == GIT_ENOTFOUND) {
memset(&old, 0, GIT_OID_RAWSZ);
@@ -1499,6 +1651,7 @@ static int next_head(const git_remote *remote, git_vector *refs,
git_remote_head *head;
git_refspec *spec, *passive_spec;
size_t i, j, k;
+ int valid;
active = &remote->active_refspecs;
passive = &remote->passive_refspecs;
@@ -1510,7 +1663,10 @@ static int next_head(const git_remote *remote, git_vector *refs,
for (; i < refs->length; i++) {
head = git_vector_get(refs, i);
- if (!git_reference_is_valid_name(head->name))
+ if (git_reference_name_is_valid(&valid, head->name) < 0)
+ return -1;
+
+ if (!valid)
continue;
for (; j < active->length; j++) {
@@ -1657,7 +1813,7 @@ int git_remote_update_tips(
goto out;
}
- /* only try to do opportunisitic updates if the refpec lists differ */
+ /* Only try to do opportunistic updates if the refpec lists differ. */
if (remote->passed_refspecs)
error = opportunistic_updates(remote, callbacks, &refs, reflog_message);
@@ -1669,7 +1825,7 @@ out:
int git_remote_connected(const git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (!remote->transport || !remote->transport->is_connected)
return 0;
@@ -1680,7 +1836,7 @@ int git_remote_connected(const git_remote *remote)
int git_remote_stop(git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (remote->transport && remote->transport->cancel)
remote->transport->cancel(remote->transport);
@@ -1690,7 +1846,7 @@ int git_remote_stop(git_remote *remote)
int git_remote_disconnect(git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (git_remote_connected(remote))
remote->transport->close(remote->transport);
@@ -1776,7 +1932,7 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
const git_indexer_progress *git_remote_stats(git_remote *remote)
{
- assert(remote);
+ GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
return &remote->stats;
}
@@ -1791,7 +1947,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_
git_config *config;
int error;
- assert(repo && remote);
+ GIT_ASSERT_ARG(repo && remote);
if ((error = ensure_remote_name_is_valid(remote)) < 0)
return error;
@@ -2055,7 +2211,7 @@ int git_remote_rename(git_strarray *out, git_repository *repo, const char *name,
git_vector problem_refspecs = GIT_VECTOR_INIT;
git_remote *remote = NULL;
- assert(out && repo && name && new_name);
+ GIT_ASSERT_ARG(out && repo && name && new_name);
if ((error = git_remote_lookup(&remote, repo, name)) < 0)
return error;
@@ -2089,24 +2245,34 @@ cleanup:
return error;
}
-int git_remote_is_valid_name(
- const char *remote_name)
+int git_remote_name_is_valid(int *valid, const char *remote_name)
{
git_buf buf = GIT_BUF_INIT;
- git_refspec refspec;
- int error = -1;
+ git_refspec refspec = {0};
+ int error;
+
+ GIT_ASSERT(valid);
+
+ *valid = 0;
if (!remote_name || *remote_name == '\0')
return 0;
- git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name);
+ if ((error = git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name)) < 0)
+ goto done;
+
error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
+ if (!error)
+ *valid = 1;
+ else if (error == GIT_EINVALIDSPEC)
+ error = 0;
+
+done:
git_buf_dispose(&buf);
git_refspec__dispose(&refspec);
- git_error_clear();
- return error == 0;
+ return error;
}
git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refname)
@@ -2221,7 +2387,7 @@ static const char *name_offset(size_t *len_out, const char *name)
prefix_len = strlen("remote.");
dot = strchr(name + prefix_len, '.');
- assert(dot);
+ GIT_ASSERT_ARG_WITH_RETVAL(dot, NULL);
*len_out = dot - name - prefix_len;
return name + prefix_len;
@@ -2251,10 +2417,13 @@ static int remove_branch_config_related_entries(
if (strcmp(remote_name, entry->value))
continue;
- branch = name_offset(&branch_len, entry->name);
+ if ((branch = name_offset(&branch_len, entry->name)) == NULL) {
+ error = -1;
+ break;
+ }
git_buf_clear(&buf);
- if (git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch) < 0)
+ if ((error = git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch)) < 0)
break;
if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
@@ -2264,7 +2433,7 @@ static int remove_branch_config_related_entries(
}
git_buf_clear(&buf);
- if (git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch) < 0)
+ if ((error = git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch)) < 0)
break;
if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
@@ -2359,7 +2528,8 @@ int git_remote_delete(git_repository *repo, const char *name)
{
int error;
- assert(repo && name);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
if ((error = remove_branch_config_related_entries(repo, name)) < 0 ||
(error = remove_remote_tracking(repo, name)) < 0 ||
@@ -2375,29 +2545,37 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
const git_remote_head *guess = NULL;
const git_oid *head_id;
size_t heads_len, i;
+ git_buf local_default = GIT_BUF_INIT;
int error;
- assert(out);
+ GIT_ASSERT_ARG(out);
if ((error = git_remote_ls(&heads, &heads_len, remote)) < 0)
- return error;
+ goto done;
- if (heads_len == 0)
- return GIT_ENOTFOUND;
+ if (heads_len == 0 || strcmp(heads[0]->name, GIT_HEAD_FILE)) {
+ error = GIT_ENOTFOUND;
+ goto done;
+ }
- if (strcmp(heads[0]->name, GIT_HEAD_FILE))
- return GIT_ENOTFOUND;
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
- git_buf_sanitize(out);
/* the first one must be HEAD so if that has the symref info, we're done */
- if (heads[0]->symref_target)
- return git_buf_puts(out, heads[0]->symref_target);
+ if (heads[0]->symref_target) {
+ error = git_buf_puts(out, heads[0]->symref_target);
+ goto done;
+ }
/*
* If there's no symref information, we have to look over them
- * and guess. We return the first match unless the master
- * branch is a candidate. Then we return the master branch.
+ * and guess. We return the first match unless the default
+ * branch is a candidate. Then we return the default branch.
*/
+
+ if ((error = git_repository_initialbranch(&local_default, remote->repo)) < 0)
+ goto done;
+
head_id = &heads[0]->oid;
for (i = 1; i < heads_len; i++) {
@@ -2412,16 +2590,22 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
continue;
}
- if (!git__strcmp(GIT_REFS_HEADS_MASTER_FILE, heads[i]->name)) {
+ if (!git__strcmp(local_default.ptr, heads[i]->name)) {
guess = heads[i];
break;
}
}
- if (!guess)
- return GIT_ENOTFOUND;
+ if (!guess) {
+ error = GIT_ENOTFOUND;
+ goto done;
+ }
+
+ error = git_buf_puts(out, guess->name);
- return git_buf_puts(out, guess->name);
+done:
+ git_buf_dispose(&local_default);
+ return error;
}
int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
@@ -2433,7 +2617,7 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
const git_remote_callbacks *cbs = NULL;
git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (!remote->repo) {
git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
@@ -2499,7 +2683,7 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
const git_strarray *custom_headers = NULL;
const git_proxy_options *proxy = NULL;
- assert(remote);
+ GIT_ASSERT_ARG(remote);
if (!remote->repo) {
git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
@@ -2514,8 +2698,6 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
proxy = &opts->proxy_opts;
}
- assert(remote);
-
if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
return error;
@@ -2542,9 +2724,9 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
git_config_entry *entry;
git_config_iterator *iter;
- assert(config);
- assert(url);
- assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
+ GIT_ASSERT_ARG_WITH_RETVAL(config, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(url, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH, NULL);
/* Add 1 to prefix/suffix length due to the additional escaped dot */
prefix_length = strlen(PREFIX) + 1;
@@ -2592,3 +2774,17 @@ char *apply_insteadof(git_config *config, const char *url, int direction)
return result.ptr;
}
+
+/* Deprecated functions */
+
+#ifndef GIT_DEPRECATE_HARD
+
+int git_remote_is_valid_name(const char *remote_name)
+{
+ int valid = 0;
+
+ git_remote_name_is_valid(&valid, remote_name);
+ return valid;
+}
+
+#endif
diff --git a/src/remote.h b/src/remote.h
index df75ed359..ce92db76a 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -15,6 +15,7 @@
#include "refspec.h"
#include "vector.h"
+#include "net.h"
#define GIT_REMOTE_ORIGIN "origin"
@@ -46,7 +47,7 @@ typedef struct git_remote_connection_opts {
int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn);
int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks);
-int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url);
+int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url);
git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refname);
git_refspec *git_remote__matching_dst_refspec(git_remote *remote, const char *refname);
diff --git a/src/repository.c b/src/repository.c
index bc5ee6ac0..5297a8840 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -70,7 +70,7 @@ static int check_extensions(git_config *config, int version);
#define GIT_FILE_CONTENT_PREFIX "gitdir:"
-#define GIT_BRANCH_MASTER "master"
+#define GIT_BRANCH_DEFAULT "master"
#define GIT_REPO_VERSION 0
#define GIT_REPO_MAX_VERSION 1
@@ -93,7 +93,7 @@ static void set_odb(git_repository *repo, git_odb *odb)
GIT_REFCOUNT_INC(odb);
}
- if ((odb = git__swap(repo->_odb, odb)) != NULL) {
+ if ((odb = git_atomic_swap(repo->_odb, odb)) != NULL) {
GIT_REFCOUNT_OWN(odb, NULL);
git_odb_free(odb);
}
@@ -106,7 +106,7 @@ static void set_refdb(git_repository *repo, git_refdb *refdb)
GIT_REFCOUNT_INC(refdb);
}
- if ((refdb = git__swap(repo->_refdb, refdb)) != NULL) {
+ if ((refdb = git_atomic_swap(repo->_refdb, refdb)) != NULL) {
GIT_REFCOUNT_OWN(refdb, NULL);
git_refdb_free(refdb);
}
@@ -119,7 +119,7 @@ static void set_config(git_repository *repo, git_config *config)
GIT_REFCOUNT_INC(config);
}
- if ((config = git__swap(repo->_config, config)) != NULL) {
+ if ((config = git_atomic_swap(repo->_config, config)) != NULL) {
GIT_REFCOUNT_OWN(config, NULL);
git_config_free(config);
}
@@ -134,7 +134,7 @@ static void set_index(git_repository *repo, git_index *index)
GIT_REFCOUNT_INC(index);
}
- if ((index = git__swap(repo->_index, index)) != NULL) {
+ if ((index = git_atomic_swap(repo->_index, index)) != NULL) {
GIT_REFCOUNT_OWN(index, NULL);
git_index_free(index);
}
@@ -142,7 +142,7 @@ static void set_index(git_repository *repo, git_index *index)
int git_repository__cleanup(git_repository *repo)
{
- assert(repo);
+ GIT_ASSERT_ARG(repo);
git_repository_submodule_cache_clear(repo);
git_cache_clear(&repo->objects);
@@ -188,6 +188,63 @@ void git_repository_free(git_repository *repo)
git__free(repo);
}
+/* Check if we have a separate commondir (e.g. we have a worktree) */
+static int lookup_commondir(bool *separate, git_buf *commondir, git_buf *repository_path)
+{
+ git_buf common_link = GIT_BUF_INIT;
+ int error;
+
+ /*
+ * If there's no commondir file, the repository path is the
+ * common path, but it needs a trailing slash.
+ */
+ if (!git_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) {
+ if ((error = git_buf_set(commondir, repository_path->ptr, repository_path->size)) == 0)
+ error = git_path_to_dir(commondir);
+
+ *separate = false;
+ goto done;
+ }
+
+ *separate = true;
+
+ if ((error = git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE)) < 0 ||
+ (error = git_futils_readbuffer(&common_link, common_link.ptr)) < 0)
+ goto done;
+
+ git_buf_rtrim(&common_link);
+ if (git_path_is_relative(common_link.ptr)) {
+ if ((error = git_buf_joinpath(commondir, repository_path->ptr, common_link.ptr)) < 0)
+ goto done;
+ } else {
+ git_buf_swap(commondir, &common_link);
+ }
+
+ git_buf_dispose(&common_link);
+
+ /* Make sure the commondir path always has a trailing slash */
+ error = git_path_prettify_dir(commondir, commondir->ptr, NULL);
+
+done:
+ return error;
+}
+
+GIT_INLINE(int) validate_repo_path(git_buf *path)
+{
+ /*
+ * The longest static path in a repository (or commondir) is the
+ * packed refs file. (Loose refs may be longer since they
+ * include the reference name, but will be validated when the
+ * path is constructed.)
+ */
+ static size_t suffix_len =
+ CONST_STRLEN("objects/pack/pack-.pack.lock") +
+ GIT_OID_HEXSZ;
+
+ return git_path_validate_filesystem_with_suffix(
+ path->ptr, path->size, suffix_len);
+}
+
/*
* Git repository open methods
*
@@ -195,48 +252,30 @@ void git_repository_free(git_repository *repo)
*/
static int is_valid_repository_path(bool *out, git_buf *repository_path, git_buf *common_path)
{
+ bool separate_commondir = false;
int error;
*out = false;
- /* Check if we have a separate commondir (e.g. we have a
- * worktree) */
- if (git_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) {
- git_buf common_link = GIT_BUF_INIT;
-
- if ((error = git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE)) < 0 ||
- (error = git_futils_readbuffer(&common_link, common_link.ptr)) < 0)
- return error;
-
- git_buf_rtrim(&common_link);
- if (git_path_is_relative(common_link.ptr)) {
- if ((error = git_buf_joinpath(common_path, repository_path->ptr, common_link.ptr)) < 0)
- return error;
- } else {
- git_buf_swap(common_path, &common_link);
- }
-
- git_buf_dispose(&common_link);
- }
- else {
- if ((error = git_buf_set(common_path, repository_path->ptr, repository_path->size)) < 0)
- return error;
- }
-
- /* Make sure the commondir path always has a trailing * slash */
- if (git_buf_rfind(common_path, '/') != (ssize_t)common_path->size - 1)
- if ((error = git_buf_putc(common_path, '/')) < 0)
- return error;
+ if ((error = lookup_commondir(&separate_commondir, common_path, repository_path)) < 0)
+ return error;
/* Ensure HEAD file exists */
if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
return 0;
+
/* Check files in common dir */
if (git_path_contains_dir(common_path, GIT_OBJECTS_DIR) == false)
return 0;
if (git_path_contains_dir(common_path, GIT_REFS_DIR) == false)
return 0;
+ /* Ensure the repo (and commondir) are valid paths */
+ if ((error = validate_repo_path(common_path)) < 0 ||
+ (separate_commondir &&
+ (error = validate_repo_path(repository_path)) < 0))
+ return error;
+
*out = true;
return 0;
}
@@ -370,7 +409,7 @@ static size_t find_ceiling_dir_offset(
const char *ceil, *sep;
size_t len, max_len = 0, min_len;
- assert(path);
+ GIT_ASSERT_ARG(path);
min_len = (size_t)(git_path_root(path) + 1);
@@ -416,7 +455,8 @@ static int read_gitfile(git_buf *path_out, const char *file_path)
git_buf file = GIT_BUF_INIT;
size_t prefix_len = strlen(GIT_FILE_CONTENT_PREFIX);
- assert(path_out && file_path);
+ GIT_ASSERT_ARG(path_out);
+ GIT_ASSERT_ARG(file_path);
if (git_futils_readbuffer(&file, file_path) < 0)
return -1;
@@ -883,7 +923,7 @@ int git_repository_open_ext(
if (config && (error = check_repositoryformatversion(&version, config)) < 0)
goto cleanup;
- if ((error = check_extensions(config, version) < 0))
+ if ((error = check_extensions(config, version)) < 0)
goto cleanup;
if ((error = load_grafts(repo)) < 0)
@@ -927,7 +967,8 @@ int git_repository_open_from_worktree(git_repository **repo_out, git_worktree *w
size_t len;
int err;
- assert(repo_out && wt);
+ GIT_ASSERT_ARG(repo_out);
+ GIT_ASSERT_ARG(wt);
*repo_out = NULL;
len = strlen(wt->gitlink_path);
@@ -971,10 +1012,12 @@ int git_repository_discover(
const char *ceiling_dirs)
{
uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
+ int error;
- assert(start_path);
+ GIT_ASSERT_ARG(start_path);
- git_buf_sanitize(out);
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
return find_repo(out, NULL, NULL, NULL, start_path, flags, ceiling_dirs);
}
@@ -991,7 +1034,7 @@ static int load_config(
git_buf config_path = GIT_BUF_INIT;
git_config *cfg = NULL;
- assert(out);
+ GIT_ASSERT_ARG(out);
if ((error = git_config_new(&cfg)) < 0)
return error;
@@ -1076,8 +1119,7 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(config, repo);
- config = git__compare_and_swap(&repo->_config, NULL, config);
- if (config != NULL) {
+ if (git_atomic_compare_and_swap(&repo->_config, NULL, config) != NULL) {
GIT_REFCOUNT_OWN(config, NULL);
git_config_free(config);
}
@@ -1115,7 +1157,9 @@ int git_repository_config_snapshot(git_config **out, git_repository *repo)
int git_repository_set_config(git_repository *repo, git_config *config)
{
- assert(repo && config);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(config);
+
set_config(repo, config);
return 0;
}
@@ -1124,9 +1168,11 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
{
int error = 0;
- assert(repo && out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(out);
- if (repo->_odb == NULL) {
+ *out = git_atomic_load(repo->_odb);
+ if (*out == NULL) {
git_buf odb_path = GIT_BUF_INIT;
git_odb *odb;
@@ -1143,16 +1189,15 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
return error;
}
- odb = git__compare_and_swap(&repo->_odb, NULL, odb);
- if (odb != NULL) {
+ if (git_atomic_compare_and_swap(&repo->_odb, NULL, odb) != NULL) {
GIT_REFCOUNT_OWN(odb, NULL);
git_odb_free(odb);
}
git_buf_dispose(&odb_path);
+ *out = git_atomic_load(repo->_odb);
}
- *out = repo->_odb;
return error;
}
@@ -1167,7 +1212,9 @@ int git_repository_odb(git_odb **out, git_repository *repo)
int git_repository_set_odb(git_repository *repo, git_odb *odb)
{
- assert(repo && odb);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(odb);
+
set_odb(repo, odb);
return 0;
}
@@ -1176,7 +1223,8 @@ int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo)
{
int error = 0;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
if (repo->_refdb == NULL) {
git_refdb *refdb;
@@ -1185,8 +1233,7 @@ int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(refdb, repo);
- refdb = git__compare_and_swap(&repo->_refdb, NULL, refdb);
- if (refdb != NULL) {
+ if (git_atomic_compare_and_swap(&repo->_refdb, NULL, refdb) != NULL) {
GIT_REFCOUNT_OWN(refdb, NULL);
git_refdb_free(refdb);
}
@@ -1208,7 +1255,9 @@ int git_repository_refdb(git_refdb **out, git_repository *repo)
int git_repository_set_refdb(git_repository *repo, git_refdb *refdb)
{
- assert(repo && refdb);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(refdb);
+
set_refdb(repo, refdb);
return 0;
}
@@ -1217,7 +1266,8 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
{
int error = 0;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
if (repo->_index == NULL) {
git_buf index_path = GIT_BUF_INIT;
@@ -1230,8 +1280,7 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
if (!error) {
GIT_REFCOUNT_OWN(index, repo);
- index = git__compare_and_swap(&repo->_index, NULL, index);
- if (index != NULL) {
+ if (git_atomic_compare_and_swap(&repo->_index, NULL, index) != NULL) {
GIT_REFCOUNT_OWN(index, NULL);
git_index_free(index);
}
@@ -1258,7 +1307,7 @@ int git_repository_index(git_index **out, git_repository *repo)
int git_repository_set_index(git_repository *repo, git_index *index)
{
- assert(repo);
+ GIT_ASSERT_ARG(repo);
set_index(repo, index);
return 0;
}
@@ -1418,15 +1467,60 @@ static int check_repositoryformatversion(int *version, git_config *config)
return 0;
}
+static const char *builtin_extensions[] = {
+ "noop"
+};
+
+static git_vector user_extensions = GIT_VECTOR_INIT;
+
static int check_valid_extension(const git_config_entry *entry, void *payload)
{
+ git_buf cfg = GIT_BUF_INIT;
+ bool reject;
+ const char *extension;
+ size_t i;
+ int error = 0;
+
GIT_UNUSED(payload);
- if (!strcmp(entry->name, "extensions.noop"))
- return 0;
+ git_vector_foreach (&user_extensions, i, extension) {
+ git_buf_clear(&cfg);
+ /*
+ * Users can specify that they don't want to support an
+ * extension with a '!' prefix.
+ */
+ if ((reject = (extension[0] == '!')) == true)
+ extension = &extension[1];
+
+ if ((error = git_buf_printf(&cfg, "extensions.%s", extension)) < 0)
+ goto done;
+
+ if (strcmp(entry->name, cfg.ptr) == 0) {
+ if (reject)
+ goto fail;
+
+ goto done;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) {
+ extension = builtin_extensions[i];
+
+ if ((error = git_buf_printf(&cfg, "extensions.%s", extension)) < 0)
+ goto done;
+
+ if (strcmp(entry->name, cfg.ptr) == 0)
+ goto done;
+ }
+
+fail:
git_error_set(GIT_ERROR_REPOSITORY, "unsupported extension name %s", entry->name);
- return -1;
+ error = -1;
+
+done:
+ git_buf_dispose(&cfg);
+ return error;
}
static int check_extensions(git_config *config, int version)
@@ -1437,6 +1531,70 @@ static int check_extensions(git_config *config, int version)
return git_config_foreach_match(config, "^extensions\\.", check_valid_extension, NULL);
}
+int git_repository__extensions(char ***out, size_t *out_len)
+{
+ git_vector extensions;
+ const char *builtin, *user;
+ char *extension;
+ size_t i, j;
+
+ if (git_vector_init(&extensions, 8, NULL) < 0)
+ return -1;
+
+ for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) {
+ bool match = false;
+
+ builtin = builtin_extensions[i];
+
+ git_vector_foreach (&user_extensions, j, user) {
+ if (user[0] == '!' && strcmp(builtin, &user[1]) == 0) {
+ match = true;
+ break;
+ }
+ }
+
+ if (match)
+ continue;
+
+ if ((extension = git__strdup(builtin)) == NULL ||
+ git_vector_insert(&extensions, extension) < 0)
+ return -1;
+ }
+
+ git_vector_foreach (&user_extensions, i, user) {
+ if (user[0] == '!')
+ continue;
+
+ if ((extension = git__strdup(user)) == NULL ||
+ git_vector_insert(&extensions, extension) < 0)
+ return -1;
+ }
+
+ *out = (char **)git_vector_detach(out_len, NULL, &extensions);
+ return 0;
+}
+
+int git_repository__set_extensions(const char **extensions, size_t len)
+{
+ char *extension;
+ size_t i;
+
+ git_repository__free_extensions();
+
+ for (i = 0; i < len; i++) {
+ if ((extension = git__strdup(extensions[i])) == NULL ||
+ git_vector_insert(&user_extensions, extension) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+void git_repository__free_extensions(void)
+{
+ git_vector_free_deep(&user_extensions);
+}
+
int git_repository_create_head(const char *git_dir, const char *ref_name)
{
git_buf ref_path = GIT_BUF_INIT;
@@ -1448,9 +1606,6 @@ int git_repository_create_head(const char *git_dir, const char *ref_name)
(error = git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE)) < 0)
goto out;
- if (!ref_name)
- ref_name = GIT_BRANCH_MASTER;
-
if (git__prefixcmp(ref_name, GIT_REFS_DIR) == 0)
fmt = "ref: %s\n";
else
@@ -1656,7 +1811,7 @@ static int repo_init_config(
if (is_reinit && (error = check_repositoryformatversion(&version, config)) < 0)
goto cleanup;
- if ((error = check_extensions(config, version) < 0))
+ if ((error = check_extensions(config, version)) < 0)
goto cleanup;
#define SET_REPO_CONFIG(TYPE, NAME, VAL) do { \
@@ -2101,6 +2256,44 @@ static int repo_init_directories(
return error;
}
+static int repo_init_head(const char *repo_dir, const char *given)
+{
+ git_config *cfg = NULL;
+ git_buf head_path = GIT_BUF_INIT, cfg_branch = GIT_BUF_INIT;
+ const char *initial_head = NULL;
+ int error;
+
+ if ((error = git_buf_joinpath(&head_path, repo_dir, GIT_HEAD_FILE)) < 0)
+ goto out;
+
+ /*
+ * A template may have set a HEAD; use that unless it's been
+ * overridden by the caller's given initial head setting.
+ */
+ if (git_path_exists(head_path.ptr) && !given)
+ goto out;
+
+ if (given) {
+ initial_head = given;
+ } else if ((error = git_config_open_default(&cfg)) >= 0 &&
+ (error = git_config_get_string_buf(&cfg_branch, cfg, "init.defaultbranch")) >= 0 &&
+ *cfg_branch.ptr) {
+ initial_head = cfg_branch.ptr;
+ }
+
+ if (!initial_head)
+ initial_head = GIT_BRANCH_DEFAULT;
+
+ error = git_repository_create_head(repo_dir, initial_head);
+
+out:
+ git_config_free(cfg);
+ git_buf_dispose(&head_path);
+ git_buf_dispose(&cfg_branch);
+
+ return error;
+}
+
static int repo_init_create_origin(git_repository *repo, const char *url)
{
int error;
@@ -2131,12 +2324,14 @@ int git_repository_init_ext(
git_repository_init_options *opts)
{
git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT,
- common_path = GIT_BUF_INIT, head_path = GIT_BUF_INIT;
+ common_path = GIT_BUF_INIT;
const char *wd;
bool is_valid;
int error;
- assert(out && given_repo && opts);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(given_repo);
+ GIT_ASSERT_ARG(opts);
GIT_ERROR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options");
@@ -2165,16 +2360,7 @@ int git_repository_init_ext(
} else {
if ((error = repo_init_structure(repo_path.ptr, wd, opts)) < 0 ||
(error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0 ||
- (error = git_buf_joinpath(&head_path, repo_path.ptr, GIT_HEAD_FILE)) < 0)
- goto out;
-
- /*
- * Only set the new HEAD if the file does not exist already via
- * a template or if the caller has explicitly supplied an
- * initial HEAD value.
- */
- if ((!git_path_exists(head_path.ptr) || opts->initial_head) &&
- (error = git_repository_create_head(repo_path.ptr, opts->initial_head)) < 0)
+ (error = repo_init_head(repo_path.ptr, opts->initial_head)) < 0)
goto out;
}
@@ -2186,7 +2372,6 @@ int git_repository_init_ext(
goto out;
out:
- git_buf_dispose(&head_path);
git_buf_dispose(&common_path);
git_buf_dispose(&repo_path);
git_buf_dispose(&wd_path);
@@ -2217,18 +2402,13 @@ int git_repository_head_detached(git_repository *repo)
return exists;
}
-static int get_worktree_file_path(git_buf *out, git_repository *repo, const char *worktree, const char *file)
-{
- git_buf_clear(out);
- return git_buf_printf(out, "%s/worktrees/%s/%s", repo->commondir, worktree, file);
-}
-
int git_repository_head_detached_for_worktree(git_repository *repo, const char *name)
{
git_reference *ref = NULL;
int error;
- assert(repo && name);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
if ((error = git_repository_head_for_worktree(&ref, repo, name)) < 0)
goto out;
@@ -2245,7 +2425,7 @@ int git_repository_head(git_reference **head_out, git_repository *repo)
git_reference *head;
int error;
- assert(head_out);
+ GIT_ASSERT_ARG(head_out);
if ((error = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0)
return error;
@@ -2263,73 +2443,85 @@ int git_repository_head(git_reference **head_out, git_repository *repo)
int git_repository_head_for_worktree(git_reference **out, git_repository *repo, const char *name)
{
- git_buf path = GIT_BUF_INIT;
+ git_repository *worktree_repo = NULL;
+ git_worktree *worktree = NULL;
git_reference *head = NULL;
int error;
- assert(out && repo && name);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
*out = NULL;
- if ((error = get_worktree_file_path(&path, repo, name, GIT_HEAD_FILE)) < 0 ||
- (error = git_reference__read_head(&head, repo, path.ptr)) < 0)
+ if ((error = git_worktree_lookup(&worktree, repo, name)) < 0 ||
+ (error = git_repository_open_from_worktree(&worktree_repo, worktree)) < 0 ||
+ (error = git_reference_lookup(&head, worktree_repo, GIT_HEAD_FILE)) < 0)
goto out;
if (git_reference_type(head) != GIT_REFERENCE_DIRECT) {
- git_reference *resolved;
-
- error = git_reference_lookup_resolved(&resolved, repo, git_reference_symbolic_target(head), -1);
- git_reference_free(head);
- head = resolved;
+ if ((error = git_reference_lookup_resolved(out, worktree_repo, git_reference_symbolic_target(head), -1)) < 0)
+ goto out;
+ } else {
+ *out = head;
+ head = NULL;
}
- *out = head;
-
out:
- if (error)
- git_reference_free(head);
-
- git_buf_dispose(&path);
-
+ git_reference_free(head);
+ git_worktree_free(worktree);
+ git_repository_free(worktree_repo);
return error;
}
-int git_repository_foreach_head(git_repository *repo,
- git_repository_foreach_head_cb cb,
- int flags, void *payload)
+int git_repository_foreach_worktree(git_repository *repo,
+ git_repository_foreach_worktree_cb cb,
+ void *payload)
{
- git_strarray worktrees = GIT_VECTOR_INIT;
- git_buf path = GIT_BUF_INIT;
- int error = 0;
+ git_strarray worktrees = {0};
+ git_repository *worktree_repo = NULL;
+ git_worktree *worktree = NULL;
+ int error;
size_t i;
+ /* apply operation to repository supplied when commondir is empty, implying there's
+ * no linked worktrees to iterate, which can occur when using custom odb/refdb
+ */
+ if (!repo->commondir)
+ return cb(repo, payload);
- if (!(flags & GIT_REPOSITORY_FOREACH_HEAD_SKIP_REPO)) {
- /* Gather HEAD of main repository */
- if ((error = git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE)) < 0 ||
- (error = cb(repo, path.ptr, payload) != 0))
- goto out;
- }
+ if ((error = git_repository_open(&worktree_repo, repo->commondir)) < 0 ||
+ (error = cb(worktree_repo, payload) != 0))
+ goto out;
- if (!(flags & GIT_REPOSITORY_FOREACH_HEAD_SKIP_WORKTREES)) {
- if ((error = git_worktree_list(&worktrees, repo)) < 0) {
- error = 0;
- goto out;
- }
+ git_repository_free(worktree_repo);
+ worktree_repo = NULL;
+
+ if ((error = git_worktree_list(&worktrees, repo)) < 0)
+ goto out;
- /* Gather HEADs of all worktrees */
- for (i = 0; i < worktrees.count; i++) {
- if (get_worktree_file_path(&path, repo, worktrees.strings[i], GIT_HEAD_FILE) < 0)
- continue;
+ for (i = 0; i < worktrees.count; i++) {
+ git_repository_free(worktree_repo);
+ worktree_repo = NULL;
+ git_worktree_free(worktree);
+ worktree = NULL;
- if ((error = cb(repo, path.ptr, payload)) != 0)
+ if ((error = git_worktree_lookup(&worktree, repo, worktrees.strings[i]) < 0) ||
+ (error = git_repository_open_from_worktree(&worktree_repo, worktree)) < 0) {
+ if (error != GIT_ENOTFOUND)
goto out;
+ error = 0;
+ continue;
}
+
+ if ((error = cb(worktree_repo, payload)) != 0)
+ goto out;
}
out:
- git_buf_dispose(&path);
git_strarray_dispose(&worktrees);
+ git_repository_free(worktree_repo);
+ git_worktree_free(worktree);
return error;
}
@@ -2352,43 +2544,79 @@ int git_repository_head_unborn(git_repository *repo)
return 0;
}
-static int at_least_one_cb(const char *refname, void *payload)
+static int repo_contains_no_reference(git_repository *repo)
{
- GIT_UNUSED(refname);
- GIT_UNUSED(payload);
- return GIT_PASSTHROUGH;
+ git_reference_iterator *iter;
+ const char *refname;
+ int error;
+
+ if ((error = git_reference_iterator_new(&iter, repo)) < 0)
+ return error;
+
+ error = git_reference_next_name(&refname, iter);
+ git_reference_iterator_free(iter);
+
+ if (error == GIT_ITEROVER)
+ return 1;
+
+ return error;
}
-static int repo_contains_no_reference(git_repository *repo)
+int git_repository_initialbranch(git_buf *out, git_repository *repo)
{
- int error = git_reference_foreach_name(repo, &at_least_one_cb, NULL);
+ git_config *config;
+ git_config_entry *entry = NULL;
+ const char *branch;
+ int valid, error;
- if (error == GIT_PASSTHROUGH)
- return 0;
+ if ((error = git_repository_config__weakptr(&config, repo)) < 0)
+ return error;
- if (!error)
- return 1;
+ if ((error = git_config_get_entry(&entry, config, "init.defaultbranch")) == 0 &&
+ *entry->value) {
+ branch = entry->value;
+ }
+ else if (!error || error == GIT_ENOTFOUND) {
+ branch = GIT_BRANCH_DEFAULT;
+ }
+ else {
+ goto done;
+ }
+
+ if ((error = git_buf_puts(out, GIT_REFS_HEADS_DIR)) < 0 ||
+ (error = git_buf_puts(out, branch)) < 0 ||
+ (error = git_reference_name_is_valid(&valid, out->ptr)) < 0)
+ goto done;
+ if (!valid) {
+ git_error_set(GIT_ERROR_INVALID, "the value of init.defaultBranch is not a valid branch name");
+ error = -1;
+ }
+
+done:
+ git_config_entry_free(entry);
return error;
}
int git_repository_is_empty(git_repository *repo)
{
git_reference *head = NULL;
- int is_empty = 0;
+ git_buf initialbranch = GIT_BUF_INIT;
+ int result = 0;
- if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0)
- return -1;
+ if ((result = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0 ||
+ (result = git_repository_initialbranch(&initialbranch, repo)) < 0)
+ goto done;
- if (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC)
- is_empty =
- (strcmp(git_reference_symbolic_target(head),
- GIT_REFS_HEADS_DIR "master") == 0) &&
- repo_contains_no_reference(repo);
+ result = (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC &&
+ strcmp(git_reference_symbolic_target(head), initialbranch.ptr) == 0 &&
+ repo_contains_no_reference(repo));
+done:
git_reference_free(head);
+ git_buf_dispose(&initialbranch);
- return is_empty;
+ return result;
}
static const char *resolved_parent_path(const git_repository *repo, git_repository_item_t item, git_repository_item_t fallback)
@@ -2441,13 +2669,13 @@ int git_repository_item_path(git_buf *out, const git_repository *repo, git_repos
const char *git_repository_path(const git_repository *repo)
{
- assert(repo);
+ GIT_ASSERT_ARG_WITH_RETVAL(repo, NULL);
return repo->gitdir;
}
const char *git_repository_workdir(const git_repository *repo)
{
- assert(repo);
+ GIT_ASSERT_ARG_WITH_RETVAL(repo, NULL);
if (repo->is_bare)
return NULL;
@@ -2455,9 +2683,25 @@ const char *git_repository_workdir(const git_repository *repo)
return repo->workdir;
}
+int git_repository_workdir_path(
+ git_buf *out, git_repository *repo, const char *path)
+{
+ int error;
+
+ if (!repo->workdir) {
+ git_error_set(GIT_ERROR_REPOSITORY, "repository has no working directory");
+ return GIT_EBAREREPO;
+ }
+
+ if (!(error = git_buf_joinpath(out, repo->workdir, path)))
+ error = git_path_validate_workdir_buf(repo, out);
+
+ return error;
+}
+
const char *git_repository_commondir(const git_repository *repo)
{
- assert(repo);
+ GIT_ASSERT_ARG_WITH_RETVAL(repo, NULL);
return repo->commondir;
}
@@ -2467,7 +2711,8 @@ int git_repository_set_workdir(
int error = 0;
git_buf path = GIT_BUF_INIT;
- assert(repo && workdir);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(workdir);
if (git_path_prettify_dir(&path, workdir, NULL) < 0)
return -1;
@@ -2507,13 +2752,13 @@ int git_repository_set_workdir(
int git_repository_is_bare(const git_repository *repo)
{
- assert(repo);
+ GIT_ASSERT_ARG(repo);
return repo->is_bare;
}
int git_repository_is_worktree(const git_repository *repo)
{
- assert(repo);
+ GIT_ASSERT_ARG(repo);
return repo->is_worktree;
}
@@ -2522,7 +2767,7 @@ int git_repository_set_bare(git_repository *repo)
int error;
git_config *config;
- assert(repo);
+ GIT_ASSERT_ARG(repo);
if (repo->is_bare)
return 0;
@@ -2590,7 +2835,8 @@ int git_repository_message(git_buf *out, git_repository *repo)
struct stat st;
int error;
- git_buf_sanitize(out);
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
return -1;
@@ -2634,31 +2880,36 @@ int git_repository_hashfile(
git_file fd = -1;
uint64_t len;
git_buf full_path = GIT_BUF_INIT;
+ const char *workdir = git_repository_workdir(repo);
- assert(out && path && repo); /* as_path can be NULL */
-
- /* At some point, it would be nice if repo could be NULL to just
- * apply filter rules defined in system and global files, but for
- * now that is not possible because git_filters_load() needs it.
- */
+ /* as_path can be NULL */
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(path);
+ GIT_ASSERT_ARG(repo);
- error = git_path_join_unrooted(
- &full_path, path, git_repository_workdir(repo), NULL);
- if (error < 0)
+ if ((error = git_path_join_unrooted(&full_path, path, workdir, NULL)) < 0 ||
+ (error = git_path_validate_workdir_buf(repo, &full_path)) < 0)
return error;
- if (!as_path)
- as_path = path;
+ /*
+ * NULL as_path means that we should derive it from the
+ * given path.
+ */
+ if (!as_path) {
+ if (workdir && !git__prefixcmp(full_path.ptr, workdir))
+ as_path = full_path.ptr + strlen(workdir);
+ else
+ as_path = "";
+ }
/* passing empty string for "as_path" indicated --no-filters */
if (strlen(as_path) > 0) {
error = git_filter_list_load(
&fl, repo, NULL, as_path,
GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT);
+
if (error < 0)
return error;
- } else {
- error = 0;
}
/* at this point, error is a count of the number of loaded filters */
@@ -2720,7 +2971,8 @@ static int detach(git_repository *repo, const git_oid *id, const char *new)
git_object *object = NULL, *peeled = NULL;
git_reference *new_head = NULL, *current = NULL;
- assert(repo && id);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(id);
if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
return error;
@@ -2749,14 +3001,15 @@ cleanup:
}
int git_repository_set_head(
- git_repository* repo,
- const char* refname)
+ git_repository *repo,
+ const char *refname)
{
git_reference *ref = NULL, *current = NULL, *new_head = NULL;
git_buf log_message = GIT_BUF_INIT;
int error;
- assert(repo && refname);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(refname);
if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
return error;
@@ -2798,8 +3051,8 @@ cleanup:
}
int git_repository_set_head_detached(
- git_repository* repo,
- const git_oid* commitish)
+ git_repository *repo,
+ const git_oid *commitish)
{
return detach(repo, commitish, NULL);
}
@@ -2808,19 +3061,20 @@ int git_repository_set_head_detached_from_annotated(
git_repository *repo,
const git_annotated_commit *commitish)
{
- assert(repo && commitish);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(commitish);
return detach(repo, git_annotated_commit_id(commitish), commitish->description);
}
-int git_repository_detach_head(git_repository* repo)
+int git_repository_detach_head(git_repository *repo)
{
git_reference *old_head = NULL, *new_head = NULL, *current = NULL;
git_object *object = NULL;
git_buf log_message = GIT_BUF_INIT;
int error;
- assert(repo);
+ GIT_ASSERT_ARG(repo);
if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
return error;
@@ -2855,7 +3109,7 @@ int git_repository_state(git_repository *repo)
git_buf repo_path = GIT_BUF_INIT;
int state = GIT_REPOSITORY_STATE_NONE;
- assert(repo);
+ GIT_ASSERT_ARG(repo);
if (git_buf_puts(&repo_path, repo->gitdir) < 0)
return -1;
@@ -2932,7 +3186,7 @@ static const char *state_files[] = {
int git_repository_state_cleanup(git_repository *repo)
{
- assert(repo);
+ GIT_ASSERT_ARG(repo);
return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
}
@@ -2998,8 +3252,8 @@ int git_repository_set_ident(git_repository *repo, const char *name, const char
GIT_ERROR_CHECK_ALLOC(tmp_email);
}
- tmp_name = git__swap(repo->ident_name, tmp_name);
- tmp_email = git__swap(repo->ident_email, tmp_email);
+ tmp_name = git_atomic_swap(repo->ident_name, tmp_name);
+ tmp_email = git_atomic_swap(repo->ident_email, tmp_email);
git__free(tmp_name);
git__free(tmp_email);
@@ -3009,28 +3263,16 @@ int git_repository_set_ident(git_repository *repo, const char *name, const char
int git_repository_submodule_cache_all(git_repository *repo)
{
- int error;
-
- assert(repo);
-
- if ((error = git_strmap_new(&repo->submodule_cache)))
- return error;
-
- error = git_submodule__map(repo, repo->submodule_cache);
- return error;
+ GIT_ASSERT_ARG(repo);
+ return git_submodule_cache_init(&repo->submodule_cache, repo);
}
int git_repository_submodule_cache_clear(git_repository *repo)
{
- git_submodule *sm;
- assert(repo);
- if (repo->submodule_cache == NULL) {
- return 0;
- }
- git_strmap_foreach_value(repo->submodule_cache, sm, {
- git_submodule_free(sm);
- });
- git_strmap_free(repo->submodule_cache);
- repo->submodule_cache = 0;
- return 0;
+ int error = 0;
+ GIT_ASSERT_ARG(repo);
+
+ error = git_submodule_cache_free(repo->submodule_cache);
+ repo->submodule_cache = NULL;
+ return error;
}
diff --git a/src/repository.h b/src/repository.h
index 5922bf02a..8da65652d 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -53,6 +53,7 @@ typedef enum {
GIT_CONFIGMAP_PROTECTHFS, /* core.protectHFS */
GIT_CONFIGMAP_PROTECTNTFS, /* core.protectNTFS */
GIT_CONFIGMAP_FSYNCOBJECTFILES, /* core.fsyncObjectFiles */
+ GIT_CONFIGMAP_LONGPATHS, /* core.longpaths */
GIT_CONFIGMAP_CACHE_MAX
} git_configmap_item;
@@ -118,6 +119,8 @@ typedef enum {
GIT_PROTECTNTFS_DEFAULT = GIT_CONFIGMAP_TRUE,
/* core.fsyncObjectFiles */
GIT_FSYNCOBJECTFILES_DEFAULT = GIT_CONFIGMAP_FALSE,
+ /* core.longpaths */
+ GIT_LONGPATHS_DEFAULT = GIT_CONFIGMAP_FALSE,
} git_configmap_value;
/* internal repository init flags */
@@ -157,9 +160,9 @@ struct git_repository {
git_grafts *grafts;
git_grafts *shallow_grafts;
- git_atomic attr_session_key;
+ git_atomic32 attr_session_key;
- git_configmap_value configmap_cache[GIT_CONFIGMAP_CACHE_MAX];
+ intptr_t configmap_cache[GIT_CONFIGMAP_CACHE_MAX];
git_strmap *submodule_cache;
};
@@ -171,34 +174,11 @@ GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo)
int git_repository_head_tree(git_tree **tree, git_repository *repo);
int git_repository_create_head(const char *git_dir, const char *ref_name);
-/*
- * Called for each HEAD.
- *
- * Can return either 0, causing the iteration over HEADs to
- * continue, or a non-0 value causing the iteration to abort. The
- * return value is passed back to the caller of
- * `git_repository_foreach_head`
- */
-typedef int (*git_repository_foreach_head_cb)(git_repository *repo, const char *path, void *payload);
-
-enum {
- /* Skip enumeration of the main repository HEAD */
- GIT_REPOSITORY_FOREACH_HEAD_SKIP_REPO = (1u << 0),
- /* Skip enumeration of worktree HEADs */
- GIT_REPOSITORY_FOREACH_HEAD_SKIP_WORKTREES = (1u << 1),
-};
+typedef int (*git_repository_foreach_worktree_cb)(git_repository *, void *);
-/*
- * Iterate over repository and all worktree HEADs.
- *
- * This function will be called for the repository HEAD and for
- * all HEADS of linked worktrees. For each HEAD, the callback is
- * executed with the given payload. The return value equals the
- * return value of the last executed callback function.
- */
-int git_repository_foreach_head(git_repository *repo,
- git_repository_foreach_head_cb cb,
- int flags, void *payload);
+int git_repository_foreach_worktree(git_repository *repo,
+ git_repository_foreach_worktree_cb cb,
+ void *payload);
/*
* Weak pointers to repository internals.
@@ -262,4 +242,22 @@ extern size_t git_repository__reserved_names_posix_len;
bool git_repository__reserved_names(
git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs);
+/*
+ * The default branch for the repository; the `init.defaultBranch`
+ * configuration option, if set, or `master` if it is not.
+ */
+int git_repository_initialbranch(git_buf *out, git_repository *repo);
+
+/*
+ * Given a relative `path`, this makes it absolute based on the
+ * repository's working directory. This will perform validation
+ * to ensure that the path is not longer than MAX_PATH on Windows
+ * (unless `core.longpaths` is set in the repo config).
+ */
+int git_repository_workdir_path(git_buf *out, git_repository *repo, const char *path);
+
+int git_repository__extensions(char ***out, size_t *out_len);
+int git_repository__set_extensions(const char **extensions, size_t len);
+void git_repository__free_extensions(void);
+
#endif
diff --git a/src/reset.c b/src/reset.c
index ca6a5bd73..f21a620c6 100644
--- a/src/reset.c
+++ b/src/reset.c
@@ -22,7 +22,7 @@
int git_reset_default(
git_repository *repo,
const git_object *target,
- const git_strarray* pathspecs)
+ const git_strarray *pathspecs)
{
git_object *commit = NULL;
git_tree *tree = NULL;
@@ -33,7 +33,7 @@ int git_reset_default(
int error;
git_index *index = NULL;
- assert(pathspecs != NULL && pathspecs->count > 0);
+ GIT_ASSERT_ARG(pathspecs && pathspecs->count > 0);
memset(&entry, 0, sizeof(git_index_entry));
@@ -62,10 +62,10 @@ int git_reset_default(
for (i = 0, max_i = git_diff_num_deltas(diff); i < max_i; ++i) {
const git_diff_delta *delta = git_diff_get_delta(diff, i);
- assert(delta->status == GIT_DELTA_ADDED ||
- delta->status == GIT_DELTA_MODIFIED ||
- delta->status == GIT_DELTA_CONFLICTED ||
- delta->status == GIT_DELTA_DELETED);
+ GIT_ASSERT(delta->status == GIT_DELTA_ADDED ||
+ delta->status == GIT_DELTA_MODIFIED ||
+ delta->status == GIT_DELTA_CONFLICTED ||
+ delta->status == GIT_DELTA_DELETED);
error = git_index_conflict_remove(index, delta->old_file.path);
if (error < 0) {
@@ -113,7 +113,8 @@ static int reset(
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
git_buf log_message = GIT_BUF_INIT;
- assert(repo && target);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(target);
if (checkout_opts)
opts = *checkout_opts;
diff --git a/src/revert.c b/src/revert.c
index b84bc7d79..683f0d70d 100644
--- a/src/revert.c
+++ b/src/revert.c
@@ -129,7 +129,10 @@ int git_revert_commit(
git_tree *parent_tree = NULL, *our_tree = NULL, *revert_tree = NULL;
int parent = 0, error = 0;
- assert(out && repo && revert_commit && our_commit);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(revert_commit);
+ GIT_ASSERT_ARG(our_commit);
if (git_commit_parentcount(revert_commit) > 1) {
if (!mainline)
@@ -180,7 +183,8 @@ int git_revert(
git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
int error;
- assert(repo && commit);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(commit);
GIT_ERROR_CHECK_VERSION(given_opts, GIT_REVERT_OPTIONS_VERSION, "git_revert_options");
diff --git a/src/revparse.c b/src/revparse.c
index 1cc8b97f5..b4d5d4759 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -14,7 +14,7 @@
#include "git2.h"
-static int maybe_sha_or_abbrev(git_object** out, git_repository *repo, const char *spec, size_t speclen)
+static int maybe_sha_or_abbrev(git_object **out, git_repository *repo, const char *spec, size_t speclen)
{
git_oid oid;
@@ -24,7 +24,7 @@ static int maybe_sha_or_abbrev(git_object** out, git_repository *repo, const cha
return git_object_lookup_prefix(out, repo, &oid, speclen, GIT_OBJECT_ANY);
}
-static int maybe_sha(git_object** out, git_repository *repo, const char *spec)
+static int maybe_sha(git_object **out, git_repository *repo, const char *spec)
{
size_t speclen = strlen(spec);
@@ -34,7 +34,7 @@ static int maybe_sha(git_object** out, git_repository *repo, const char *spec)
return maybe_sha_or_abbrev(out, repo, spec, speclen);
}
-static int maybe_abbrev(git_object** out, git_repository *repo, const char *spec)
+static int maybe_abbrev(git_object **out, git_repository *repo, const char *spec)
{
size_t speclen = strlen(spec);
@@ -310,14 +310,14 @@ cleanup:
return error;
}
-static int handle_at_syntax(git_object **out, git_reference **ref, const char *spec, size_t identifier_len, git_repository* repo, const char *curly_braces_content)
+static int handle_at_syntax(git_object **out, git_reference **ref, const char *spec, size_t identifier_len, git_repository *repo, const char *curly_braces_content)
{
bool is_numeric;
int parsed = 0, error = -1;
git_buf identifier = GIT_BUF_INIT;
git_time_t timestamp;
- assert(*out == NULL);
+ GIT_ASSERT(*out == NULL);
if (git_buf_put(&identifier, spec, identifier_len) < 0)
return -1;
@@ -524,7 +524,7 @@ static int extract_curly_braces_content(git_buf *buf, const char *spec, size_t *
{
git_buf_clear(buf);
- assert(spec[*pos] == '^' || spec[*pos] == '@');
+ GIT_ASSERT_ARG(spec[*pos] == '^' || spec[*pos] == '@');
(*pos)++;
@@ -550,7 +550,7 @@ static int extract_path(git_buf *buf, const char *spec, size_t *pos)
{
git_buf_clear(buf);
- assert(spec[*pos] == ':');
+ GIT_ASSERT_ARG(spec[*pos] == ':');
(*pos)++;
@@ -568,7 +568,7 @@ static int extract_how_many(int *n, const char *spec, size_t *pos)
int parsed, accumulated;
char kind = spec[*pos];
- assert(spec[*pos] == '^' || spec[*pos] == '~');
+ GIT_ASSERT_ARG(spec[*pos] == '^' || spec[*pos] == '~');
accumulated = 0;
@@ -676,7 +676,10 @@ static int revparse(
bool should_return_reference = true;
- assert(object_out && reference_out && repo && spec);
+ GIT_ASSERT_ARG(object_out);
+ GIT_ASSERT_ARG(reference_out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(spec);
*object_out = NULL;
*reference_out = NULL;
@@ -882,14 +885,16 @@ int git_revparse(
const char *dotdot;
int error = 0;
- assert(revspec && repo && spec);
+ GIT_ASSERT_ARG(revspec);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(spec);
memset(revspec, 0x0, sizeof(*revspec));
if ((dotdot = strstr(spec, "..")) != NULL) {
char *lstr;
const char *rstr;
- revspec->flags = GIT_REVPARSE_RANGE;
+ revspec->flags = GIT_REVSPEC_RANGE;
/*
* Following git.git, don't allow '..' because it makes command line
@@ -905,7 +910,7 @@ int git_revparse(
lstr = git__substrdup(spec, dotdot - spec);
rstr = dotdot + 2;
if (dotdot[2] == '.') {
- revspec->flags |= GIT_REVPARSE_MERGE_BASE;
+ revspec->flags |= GIT_REVSPEC_MERGE_BASE;
rstr++;
}
@@ -923,7 +928,7 @@ int git_revparse(
git__free((void*)lstr);
} else {
- revspec->flags = GIT_REVPARSE_SINGLE;
+ revspec->flags = GIT_REVSPEC_SINGLE;
error = git_revparse_single(&revspec->from, repo, spec);
}
diff --git a/src/revwalk.c b/src/revwalk.c
index 1efb938bd..a686a9f6f 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -99,7 +99,8 @@ int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
{
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
- assert(walk && oid);
+ GIT_ASSERT_ARG(walk);
+ GIT_ASSERT_ARG(oid);
return git_revwalk__push_commit(walk, oid, &opts);
}
@@ -108,7 +109,9 @@ int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
{
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
- assert(walk && oid);
+
+ GIT_ASSERT_ARG(walk);
+ GIT_ASSERT_ARG(oid);
opts.uninteresting = 1;
return git_revwalk__push_commit(walk, oid, &opts);
@@ -133,7 +136,8 @@ int git_revwalk__push_glob(git_revwalk *walk, const char *glob, const git_revwal
git_reference_iterator *iter;
size_t wildcard;
- assert(walk && glob);
+ GIT_ASSERT_ARG(walk);
+ GIT_ASSERT_ARG(glob);
if (given_opts)
memcpy(&opts, given_opts, sizeof(opts));
@@ -172,7 +176,9 @@ out:
int git_revwalk_push_glob(git_revwalk *walk, const char *glob)
{
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
- assert(walk && glob);
+
+ GIT_ASSERT_ARG(walk);
+ GIT_ASSERT_ARG(glob);
return git_revwalk__push_glob(walk, glob, &opts);
}
@@ -180,7 +186,9 @@ int git_revwalk_push_glob(git_revwalk *walk, const char *glob)
int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
{
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
- assert(walk && glob);
+
+ GIT_ASSERT_ARG(walk);
+ GIT_ASSERT_ARG(glob);
opts.uninteresting = 1;
return git_revwalk__push_glob(walk, glob, &opts);
@@ -189,7 +197,8 @@ int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
int git_revwalk_push_head(git_revwalk *walk)
{
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
- assert(walk);
+
+ GIT_ASSERT_ARG(walk);
return git_revwalk__push_ref(walk, GIT_HEAD_FILE, &opts);
}
@@ -197,7 +206,8 @@ int git_revwalk_push_head(git_revwalk *walk)
int git_revwalk_hide_head(git_revwalk *walk)
{
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
- assert(walk);
+
+ GIT_ASSERT_ARG(walk);
opts.uninteresting = 1;
return git_revwalk__push_ref(walk, GIT_HEAD_FILE, &opts);
@@ -206,7 +216,9 @@ int git_revwalk_hide_head(git_revwalk *walk)
int git_revwalk_push_ref(git_revwalk *walk, const char *refname)
{
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
- assert(walk && refname);
+
+ GIT_ASSERT_ARG(walk);
+ GIT_ASSERT_ARG(refname);
return git_revwalk__push_ref(walk, refname, &opts);
}
@@ -226,7 +238,7 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
goto out;
}
- if (revspec.flags & GIT_REVPARSE_MERGE_BASE) {
+ if (revspec.flags & GIT_REVSPEC_MERGE_BASE) {
/* TODO: support "<commit>...<commit>" */
git_error_set(GIT_ERROR_INVALID, "symmetric differences not implemented in revwalk");
error = GIT_EINVALIDSPEC;
@@ -249,7 +261,10 @@ out:
int git_revwalk_hide_ref(git_revwalk *walk, const char *refname)
{
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
- assert(walk && refname);
+
+ GIT_ASSERT_ARG(walk);
+ GIT_ASSERT_ARG(refname);
+
opts.uninteresting = 1;
return git_revwalk__push_ref(walk, refname, &opts);
}
@@ -694,13 +709,14 @@ void git_revwalk_free(git_revwalk *walk)
git_repository *git_revwalk_repository(git_revwalk *walk)
{
- assert(walk);
+ GIT_ASSERT_ARG_WITH_RETVAL(walk, NULL);
+
return walk->repo;
}
int git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode)
{
- assert(walk);
+ GIT_ASSERT_ARG(walk);
if (walk->walking)
git_revwalk_reset(walk);
@@ -732,7 +748,8 @@ int git_revwalk_next(git_oid *oid, git_revwalk *walk)
int error;
git_commit_list_node *next;
- assert(walk && oid);
+ GIT_ASSERT_ARG(walk);
+ GIT_ASSERT_ARG(oid);
if (!walk->walking) {
if ((error = prepare_walk(walk)) < 0)
@@ -757,7 +774,7 @@ int git_revwalk_reset(git_revwalk *walk)
{
git_commit_list_node *commit;
- assert(walk);
+ GIT_ASSERT_ARG(walk);
git_oidmap_foreach_value(walk->commits, commit, {
commit->seen = 0;
@@ -787,7 +804,7 @@ int git_revwalk_add_hide_cb(
git_revwalk_hide_cb hide_cb,
void *payload)
{
- assert(walk);
+ GIT_ASSERT_ARG(walk);
if (walk->walking)
git_revwalk_reset(walk);
diff --git a/src/runtime.c b/src/runtime.c
new file mode 100644
index 000000000..c05dee8b9
--- /dev/null
+++ b/src/runtime.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "common.h"
+#include "runtime.h"
+
+static git_runtime_shutdown_fn shutdown_callback[32];
+static git_atomic32 shutdown_callback_count;
+
+static git_atomic32 init_count;
+
+static int init_common(git_runtime_init_fn init_fns[], size_t cnt)
+{
+ size_t i;
+ int ret;
+
+ /* Initialize subsystems that have global state */
+ for (i = 0; i < cnt; i++) {
+ if ((ret = init_fns[i]()) != 0)
+ break;
+ }
+
+ GIT_MEMORY_BARRIER;
+
+ return ret;
+}
+
+static void shutdown_common(void)
+{
+ git_runtime_shutdown_fn cb;
+ int pos;
+
+ for (pos = git_atomic32_get(&shutdown_callback_count);
+ pos > 0;
+ pos = git_atomic32_dec(&shutdown_callback_count)) {
+ cb = git_atomic_swap(shutdown_callback[pos - 1], NULL);
+
+ if (cb != NULL)
+ cb();
+ }
+}
+
+int git_runtime_shutdown_register(git_runtime_shutdown_fn callback)
+{
+ int count = git_atomic32_inc(&shutdown_callback_count);
+
+ if (count > (int)ARRAY_SIZE(shutdown_callback) || count == 0) {
+ git_error_set(GIT_ERROR_INVALID,
+ "too many shutdown callbacks registered");
+ git_atomic32_dec(&shutdown_callback_count);
+ return -1;
+ }
+
+ shutdown_callback[count - 1] = callback;
+
+ return 0;
+}
+
+#if defined(GIT_THREADS) && defined(GIT_WIN32)
+
+/*
+ * On Win32, we use a spinlock to provide locking semantics. This is
+ * lighter-weight than a proper critical section.
+ */
+static volatile LONG init_spinlock = 0;
+
+GIT_INLINE(int) init_lock(void)
+{
+ while (InterlockedCompareExchange(&init_spinlock, 1, 0)) { Sleep(0); }
+ return 0;
+}
+
+GIT_INLINE(int) init_unlock(void)
+{
+ InterlockedExchange(&init_spinlock, 0);
+ return 0;
+}
+
+#elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
+
+/*
+ * On POSIX, we need to use a proper mutex for locking. We might prefer
+ * a spinlock here, too, but there's no static initializer for a
+ * pthread_spinlock_t.
+ */
+static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+GIT_INLINE(int) init_lock(void)
+{
+ return pthread_mutex_lock(&init_mutex) == 0 ? 0 : -1;
+}
+
+GIT_INLINE(int) init_unlock(void)
+{
+ return pthread_mutex_unlock(&init_mutex) == 0 ? 0 : -1;
+}
+
+#elif defined(GIT_THREADS)
+# error unknown threading model
+#else
+
+# define init_lock() git__noop()
+# define init_unlock() git__noop()
+
+#endif
+
+int git_runtime_init(git_runtime_init_fn init_fns[], size_t cnt)
+{
+ int ret;
+
+ if (init_lock() < 0)
+ return -1;
+
+ /* Only do work on a 0 -> 1 transition of the refcount */
+ if ((ret = git_atomic32_inc(&init_count)) == 1) {
+ if (init_common(init_fns, cnt) < 0)
+ ret = -1;
+ }
+
+ if (init_unlock() < 0)
+ return -1;
+
+ return ret;
+}
+
+int git_runtime_init_count(void)
+{
+ int ret;
+
+ if (init_lock() < 0)
+ return -1;
+
+ ret = git_atomic32_get(&init_count);
+
+ if (init_unlock() < 0)
+ return -1;
+
+ return ret;
+}
+
+int git_runtime_shutdown(void)
+{
+ int ret;
+
+ /* Enter the lock */
+ if (init_lock() < 0)
+ return -1;
+
+ /* Only do work on a 1 -> 0 transition of the refcount */
+ if ((ret = git_atomic32_dec(&init_count)) == 0)
+ shutdown_common();
+
+ /* Exit the lock */
+ if (init_unlock() < 0)
+ return -1;
+
+ return ret;
+}
diff --git a/src/runtime.h b/src/runtime.h
new file mode 100644
index 000000000..24ac58ee9
--- /dev/null
+++ b/src/runtime.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_runtime_h__
+#define INCLUDE_runtime_h__
+
+#include "common.h"
+
+typedef int (*git_runtime_init_fn)(void);
+typedef void (*git_runtime_shutdown_fn)(void);
+
+/**
+ * Start up a new runtime. If this is the first time that this
+ * function is called within the context of the current library
+ * or executable, then the given `init_fns` will be invoked. If
+ * it is not the first time, they will be ignored.
+ *
+ * The given initialization functions _may_ register shutdown
+ * handlers using `git_runtime_shutdown_register` to be notified
+ * when the runtime is shutdown.
+ *
+ * @param init_fns The list of initialization functions to call
+ * @param cnt The number of init_fns
+ * @return The number of initializations performed (including this one) or an error
+ */
+int git_runtime_init(git_runtime_init_fn init_fns[], size_t cnt);
+
+/*
+ * Returns the number of initializations active (the number of calls to
+ * `git_runtime_init` minus the number of calls sto `git_runtime_shutdown`).
+ * If 0, the runtime is not currently initialized.
+ *
+ * @return The number of initializations performed or an error
+ */
+int git_runtime_init_count(void);
+
+/**
+ * Shut down the runtime. If this is the last shutdown call,
+ * such that there are no remaining `init` calls, then any
+ * shutdown hooks that have been registered will be invoked.
+ *
+ * The number of outstanding initializations will be returned.
+ * If this number is 0, then the runtime is shutdown.
+ *
+ * @return The number of outstanding initializations (after this one) or an error
+ */
+int git_runtime_shutdown(void);
+
+/**
+ * Register a shutdown handler for this runtime. This should be done
+ * by a function invoked by `git_runtime_init` to ensure that the
+ * appropriate locks are taken.
+ *
+ * @param callback The shutdown handler callback
+ * @return 0 or an error code
+ */
+int git_runtime_shutdown_register(git_runtime_shutdown_fn callback);
+
+#endif
diff --git a/src/settings.h b/src/settings.h
new file mode 100644
index 000000000..dc42ce939
--- /dev/null
+++ b/src/settings.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+extern int git_settings_global_init(void);
+
+extern const char *git_libgit2__user_agent(void);
+extern const char *git_libgit2__ssl_ciphers(void);
diff --git a/src/signature.c b/src/signature.c
index f4c8a104a..1efda212a 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -65,7 +65,8 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema
{
git_signature *p = NULL;
- assert(name && email);
+ GIT_ASSERT_ARG(name);
+ GIT_ASSERT_ARG(email);
*sig_out = NULL;
@@ -279,7 +280,8 @@ int git_signature_from_buffer(git_signature **out, const char *buf)
const char *buf_end;
int error;
- assert(out && buf);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(buf);
*out = NULL;
@@ -302,8 +304,6 @@ void git_signature__writebuf(git_buf *buf, const char *header, const git_signatu
int offset, hours, mins;
char sign;
- assert(buf && sig);
-
offset = sig->when.offset;
sign = (sig->when.offset < 0 || sig->when.sign == '-') ? '-' : '+';
@@ -320,7 +320,8 @@ void git_signature__writebuf(git_buf *buf, const char *header, const git_signatu
bool git_signature__equal(const git_signature *one, const git_signature *two)
{
- assert(one && two);
+ GIT_ASSERT_ARG(one);
+ GIT_ASSERT_ARG(two);
return
git__strcmp(one->name, two->name) == 0 &&
diff --git a/src/sortedcache.h b/src/sortedcache.h
index e553d01dd..0e1f63ceb 100644
--- a/src/sortedcache.h
+++ b/src/sortedcache.h
@@ -12,7 +12,7 @@
#include "util.h"
#include "futils.h"
#include "vector.h"
-#include "thread-utils.h"
+#include "thread.h"
#include "pool.h"
#include "strmap.h"
@@ -58,7 +58,7 @@ typedef struct {
* may be NULL. The cache makes it easy to load this and check
* if it has been modified since the last load and/or write.
*/
-int git_sortedcache_new(
+GIT_WARN_UNUSED_RESULT int git_sortedcache_new(
git_sortedcache **out,
size_t item_path_offset, /* use offsetof(struct, path-field) macro */
git_sortedcache_free_item_fn free_item,
@@ -71,7 +71,7 @@ int git_sortedcache_new(
* - `copy_item` can be NULL to just use memcpy
* - if `lock`, grabs read lock on `src` during copy and releases after
*/
-int git_sortedcache_copy(
+GIT_WARN_UNUSED_RESULT int git_sortedcache_copy(
git_sortedcache **out,
git_sortedcache *src,
bool lock,
@@ -100,7 +100,7 @@ const char *git_sortedcache_path(git_sortedcache *sc);
*/
/* Lock sortedcache for write */
-int git_sortedcache_wlock(git_sortedcache *sc);
+GIT_WARN_UNUSED_RESULT int git_sortedcache_wlock(git_sortedcache *sc);
/* Unlock sorted cache when done with write */
void git_sortedcache_wunlock(git_sortedcache *sc);
@@ -120,7 +120,8 @@ void git_sortedcache_wunlock(git_sortedcache *sc);
*
* @return 0 if up-to-date, 1 if out-of-date, <0 on error
*/
-int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf);
+GIT_WARN_UNUSED_RESULT int git_sortedcache_lockandload(
+ git_sortedcache *sc, git_buf *buf);
/* Refresh file timestamp after write completes
* You should already be holding the write lock when you call this.
@@ -132,12 +133,13 @@ void git_sortedcache_updated(git_sortedcache *sc);
* If `wlock` is true, grabs write lock and releases when done, otherwise
* you should already be holding a write lock when you call this.
*/
-int git_sortedcache_clear(git_sortedcache *sc, bool wlock);
+GIT_WARN_UNUSED_RESULT int git_sortedcache_clear(
+ git_sortedcache *sc, bool wlock);
/* Find and/or insert item, returning pointer to item data.
* You should already be holding the write lock when you call this.
*/
-int git_sortedcache_upsert(
+GIT_WARN_UNUSED_RESULT int git_sortedcache_upsert(
void **out, git_sortedcache *sc, const char *key);
/* Removes entry at pos from cache
@@ -155,7 +157,7 @@ int git_sortedcache_remove(git_sortedcache *sc, size_t pos);
*/
/* Lock sortedcache for read */
-int git_sortedcache_rlock(git_sortedcache *sc);
+GIT_WARN_UNUSED_RESULT int git_sortedcache_rlock(git_sortedcache *sc);
/* Unlock sorted cache when done with read */
void git_sortedcache_runlock(git_sortedcache *sc);
diff --git a/src/stash.c b/src/stash.c
index 0d5dc4351..49ea26fdd 100644
--- a/src/stash.c
+++ b/src/stash.c
@@ -56,7 +56,7 @@ static int append_abbreviated_oid(git_buf *out, const git_oid *b_commit)
return git_buf_oom(out) ? -1 : 0;
}
-static int append_commit_description(git_buf *out, git_commit* commit)
+static int append_commit_description(git_buf *out, git_commit *commit)
{
const char *summary = git_commit_summary(commit);
GIT_ERROR_CHECK_ALLOC(summary);
@@ -546,7 +546,9 @@ int git_stash_save(
git_buf msg = GIT_BUF_INIT;
int error;
- assert(out && repo && stasher);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(stasher);
if ((error = git_repository__ensure_not_bare(repo, "stash save")) < 0)
return error;
diff --git a/src/status.c b/src/status.c
index eca1f4912..c98564643 100644
--- a/src/status.c
+++ b/src/status.c
@@ -391,14 +391,14 @@ done:
size_t git_status_list_entrycount(git_status_list *status)
{
- assert(status);
+ GIT_ASSERT_ARG_WITH_RETVAL(status, 0);
return status->paired.length;
}
const git_status_entry *git_status_byindex(git_status_list *status, size_t i)
{
- assert(status);
+ GIT_ASSERT_ARG_WITH_RETVAL(status, NULL);
return git_vector_get(&status->paired, i);
}
@@ -492,7 +492,9 @@ int git_status_file(
struct status_file_info sfi = {0};
git_index *index;
- assert(status_flags && repo && path);
+ GIT_ASSERT_ARG(status_flags);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(path);
if ((error = git_repository_index__weakptr(&index, repo)) < 0)
return error;
@@ -558,7 +560,8 @@ int git_status_init_options(git_status_options *opts, unsigned int version)
int git_status_list_get_perfdata(
git_diff_perfdata *out, const git_status_list *status)
{
- assert(out);
+ GIT_ASSERT_ARG(out);
+
GIT_ERROR_CHECK_VERSION(out, GIT_DIFF_PERFDATA_VERSION, "git_diff_perfdata");
out->stat_calls = 0;
diff --git a/src/strarray.c b/src/strarray.c
index 54fe9fbfb..2f9b77cc2 100644
--- a/src/strarray.c
+++ b/src/strarray.c
@@ -13,7 +13,8 @@ int git_strarray_copy(git_strarray *tgt, const git_strarray *src)
{
size_t i;
- assert(tgt && src);
+ GIT_ASSERT_ARG(tgt);
+ GIT_ASSERT_ARG(src);
memset(tgt, 0, sizeof(*tgt));
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
index cbe2f681a..b3a35ab02 100644
--- a/src/streams/mbedtls.c
+++ b/src/streams/mbedtls.c
@@ -11,7 +11,7 @@
#include <ctype.h>
-#include "global.h"
+#include "runtime.h"
#include "stream.h"
#include "streams/socket.h"
#include "netops.h"
@@ -68,8 +68,6 @@ static void shutdown_ssl(void)
}
}
-int git_mbedtls__set_cert_location(const char *path, int is_dir);
-
int git_mbedtls_stream_global_init(void)
{
int loaded = 0;
@@ -148,13 +146,11 @@ int git_mbedtls_stream_global_init(void)
/* load default certificates */
if (crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
- loaded = (git_mbedtls__set_cert_location(crtpath, 0) == 0);
+ loaded = (git_mbedtls__set_cert_location(crtpath, NULL) == 0);
if (!loaded && crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
- loaded = (git_mbedtls__set_cert_location(crtpath, 1) == 0);
-
- git__on_shutdown(shutdown_ssl);
+ loaded = (git_mbedtls__set_cert_location(NULL, crtpath) == 0);
- return 0;
+ return git_runtime_shutdown_register(shutdown_ssl);
cleanup:
mbedtls_ctr_drbg_free(ctr_drbg);
@@ -183,8 +179,8 @@ static int ssl_set_error(mbedtls_ssl_context *ssl, int error)
char errbuf[512];
int ret = -1;
- assert(error != MBEDTLS_ERR_SSL_WANT_READ);
- assert(error != MBEDTLS_ERR_SSL_WANT_WRITE);
+ GIT_ASSERT(error != MBEDTLS_ERR_SSL_WANT_READ);
+ GIT_ASSERT(error != MBEDTLS_ERR_SSL_WANT_WRITE);
if (error != 0)
mbedtls_strerror( error, errbuf, 512 );
@@ -425,7 +421,9 @@ int git_mbedtls_stream_new(
git_stream *stream;
int error;
- assert(out && host && port);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(host);
+ GIT_ASSERT_ARG(port);
if ((error = git_socket_stream_new(&stream, host, port)) < 0)
return error;
@@ -438,23 +436,22 @@ int git_mbedtls_stream_new(
return error;
}
-int git_mbedtls__set_cert_location(const char *path, int is_dir)
+int git_mbedtls__set_cert_location(const char *file, const char *path)
{
int ret = 0;
char errbuf[512];
mbedtls_x509_crt *cacert;
- assert(path != NULL);
+ GIT_ASSERT_ARG(file || path);
cacert = git__malloc(sizeof(mbedtls_x509_crt));
GIT_ERROR_CHECK_ALLOC(cacert);
mbedtls_x509_crt_init(cacert);
- if (is_dir) {
+ if (file)
+ ret = mbedtls_x509_crt_parse_file(cacert, file);
+ if (ret >= 0 && path)
ret = mbedtls_x509_crt_parse_path(cacert, path);
- } else {
- ret = mbedtls_x509_crt_parse_file(cacert, path);
- }
/* mbedtls_x509_crt_parse_path returns the number of invalid certs on success */
if (ret < 0) {
mbedtls_x509_crt_free(cacert);
diff --git a/src/streams/mbedtls.h b/src/streams/mbedtls.h
index 7de94b9fb..bcca6dd40 100644
--- a/src/streams/mbedtls.h
+++ b/src/streams/mbedtls.h
@@ -14,7 +14,7 @@
extern int git_mbedtls_stream_global_init(void);
#ifdef GIT_MBEDTLS
-extern int git_mbedtls__set_cert_location(const char *path, int is_dir);
+extern int git_mbedtls__set_cert_location(const char *file, const char *path);
extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port);
extern int git_mbedtls_stream_wrap(git_stream **out, git_stream *in, const char *host);
diff --git a/src/streams/openssl.c b/src/streams/openssl.c
index 6a490d17d..89c96780c 100644
--- a/src/streams/openssl.c
+++ b/src/streams/openssl.c
@@ -6,12 +6,16 @@
*/
#include "streams/openssl.h"
+#include "streams/openssl_legacy.h"
+#include "streams/openssl_dynamic.h"
#ifdef GIT_OPENSSL
#include <ctype.h>
-#include "global.h"
+#include "common.h"
+#include "runtime.h"
+#include "settings.h"
#include "posix.h"
#include "stream.h"
#include "streams/socket.h"
@@ -25,156 +29,17 @@
# include <netinet/in.h>
#endif
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/x509v3.h>
-#include <openssl/bio.h>
+#ifndef GIT_OPENSSL_DYNAMIC
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+# include <openssl/bio.h>
+#endif
SSL_CTX *git__ssl_ctx;
#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
-#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || \
- (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
-# define OPENSSL_LEGACY_API
-#endif
-
-/*
- * OpenSSL 1.1 made BIO opaque so we have to use functions to interact with it
- * which do not exist in previous versions. We define these inline functions so
- * we can program against the interface instead of littering the implementation
- * with ifdefs. We do the same for OPENSSL_init_ssl.
- */
-#if defined(OPENSSL_LEGACY_API)
-static int OPENSSL_init_ssl(int opts, void *settings)
-{
- GIT_UNUSED(opts);
- GIT_UNUSED(settings);
- SSL_load_error_strings();
- OpenSSL_add_ssl_algorithms();
- return 0;
-}
-
-static BIO_METHOD* BIO_meth_new(int type, const char *name)
-{
- BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
- if (!meth) {
- return NULL;
- }
-
- meth->type = type;
- meth->name = name;
-
- return meth;
-}
-
-static void BIO_meth_free(BIO_METHOD *biom)
-{
- git__free(biom);
-}
-
-static int BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
-{
- biom->bwrite = write;
- return 1;
-}
-
-static int BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
-{
- biom->bread = read;
- return 1;
-}
-
-static int BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
-{
- biom->bputs = puts;
- return 1;
-}
-
-static int BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
-
-{
- biom->bgets = gets;
- return 1;
-}
-
-static int BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
-{
- biom->ctrl = ctrl;
- return 1;
-}
-
-static int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
-{
- biom->create = create;
- return 1;
-}
-
-static int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
-{
- biom->destroy = destroy;
- return 1;
-}
-
-static int BIO_get_new_index(void)
-{
- /* This exists as of 1.1 so before we'd just have 0 */
- return 0;
-}
-
-static void BIO_set_init(BIO *b, int init)
-{
- b->init = init;
-}
-
-static void BIO_set_data(BIO *a, void *ptr)
-{
- a->ptr = ptr;
-}
-
-static void *BIO_get_data(BIO *a)
-{
- return a->ptr;
-}
-
-static const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
-{
- return ASN1_STRING_data((ASN1_STRING *)x);
-}
-
-# if defined(GIT_THREADS)
-static git_mutex *openssl_locks;
-
-static void openssl_locking_function(
- int mode, int n, const char *file, int line)
-{
- int lock;
-
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- lock = mode & CRYPTO_LOCK;
-
- if (lock) {
- (void)git_mutex_lock(&openssl_locks[n]);
- } else {
- git_mutex_unlock(&openssl_locks[n]);
- }
-}
-
-static void shutdown_ssl_locking(void)
-{
- int num_locks, i;
-
- num_locks = CRYPTO_num_locks();
- CRYPTO_set_locking_callback(NULL);
-
- for (i = 0; i < num_locks; ++i)
- git_mutex_free(&openssl_locks[i]);
- git__free(openssl_locks);
-}
-# endif /* GIT_THREADS */
-#endif /* OPENSSL_LEGACY_API */
static BIO_METHOD *git_stream_bio_method;
static int init_bio_method(void);
@@ -197,46 +62,47 @@ static void shutdown_ssl(void)
}
#ifdef VALGRIND
-#ifdef OPENSSL_LEGACY_API
-static void *git_openssl_malloc(size_t bytes)
-{
- return git__calloc(1, bytes);
-}
+# if !defined(GIT_OPENSSL_LEGACY) && !defined(GIT_OPENSSL_DYNAMIC)
-static void *git_openssl_realloc(void *mem, size_t size)
-{
- return git__realloc(mem, size);
-}
-
-static void git_openssl_free(void *mem)
-{
- return git__free(mem);
-}
-#else
static void *git_openssl_malloc(size_t bytes, const char *file, int line)
{
GIT_UNUSED(file);
GIT_UNUSED(line);
return git__calloc(1, bytes);
}
-
+
static void *git_openssl_realloc(void *mem, size_t size, const char *file, int line)
{
GIT_UNUSED(file);
GIT_UNUSED(line);
return git__realloc(mem, size);
}
-
+
static void git_openssl_free(void *mem, const char *file, int line)
{
GIT_UNUSED(file);
GIT_UNUSED(line);
- return git__free(mem);
+ git__free(mem);
+}
+# else /* !GIT_OPENSSL_LEGACY && !GIT_OPENSSL_DYNAMIC */
+static void *git_openssl_malloc(size_t bytes)
+{
+ return git__calloc(1, bytes);
}
-#endif
-#endif
-int git_openssl_stream_global_init(void)
+static void *git_openssl_realloc(void *mem, size_t size)
+{
+ return git__realloc(mem, size);
+}
+
+static void git_openssl_free(void *mem)
+{
+ git__free(mem);
+}
+# endif /* !GIT_OPENSSL_LEGACY && !GIT_OPENSSL_DYNAMIC */
+#endif /* VALGRIND */
+
+static int openssl_init(void)
{
long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
const char *ciphers = git_libgit2__ssl_ciphers();
@@ -250,13 +116,18 @@ int git_openssl_stream_global_init(void)
#endif
#ifdef VALGRIND
- /* Swap in our own allocator functions that initialize allocated memory */
- if (!allocators_initialized &&
+ /*
+ * Swap in our own allocator functions that initialize
+ * allocated memory to avoid spurious valgrind warnings.
+ * Don't error on failure; many builds of OpenSSL do not
+ * allow you to set these functions.
+ */
+ if (!allocators_initialized) {
CRYPTO_set_mem_functions(git_openssl_malloc,
git_openssl_realloc,
- git_openssl_free) != 1)
- goto error;
- allocators_initialized = true;
+ git_openssl_free);
+ allocators_initialized = true;
+ }
#endif
OPENSSL_init_ssl(0, NULL);
@@ -285,9 +156,7 @@ int git_openssl_stream_global_init(void)
if (init_bio_method() < 0)
goto error;
- git__on_shutdown(shutdown_ssl);
-
- return 0;
+ return git_runtime_shutdown_register(shutdown_ssl);
error:
git_error_set(GIT_ERROR_NET, "could not initialize openssl: %s",
@@ -297,42 +166,60 @@ error:
return -1;
}
-#if defined(GIT_THREADS) && defined(OPENSSL_LEGACY_API)
-static void threadid_cb(CRYPTO_THREADID *threadid)
+/*
+ * When we use dynamic loading, we defer OpenSSL initialization until
+ * it's first used. `openssl_ensure_initialized` will do the work
+ * under a mutex.
+ */
+git_mutex openssl_mutex;
+bool openssl_initialized;
+
+int git_openssl_stream_global_init(void)
{
- GIT_UNUSED(threadid);
- CRYPTO_THREADID_set_numeric(threadid, git_thread_currentid());
-}
+#ifndef GIT_OPENSSL_DYNAMIC
+ return openssl_init();
+#else
+ if (git_mutex_init(&openssl_mutex) != 0)
+ return -1;
+
+ return 0;
#endif
+}
-int git_openssl_set_locking(void)
+static int openssl_ensure_initialized(void)
{
-#if defined(GIT_THREADS) && defined(OPENSSL_LEGACY_API)
- int num_locks, i;
+#ifdef GIT_OPENSSL_DYNAMIC
+ int error = 0;
- CRYPTO_THREADID_set_callback(threadid_cb);
+ if (git_mutex_lock(&openssl_mutex) != 0)
+ return -1;
- num_locks = CRYPTO_num_locks();
- openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
- GIT_ERROR_CHECK_ALLOC(openssl_locks);
+ if (!openssl_initialized) {
+ if ((error = git_openssl_stream_dynamic_init()) == 0)
+ error = openssl_init();
- for (i = 0; i < num_locks; i++) {
- if (git_mutex_init(&openssl_locks[i]) != 0) {
- git_error_set(GIT_ERROR_SSL, "failed to initialize openssl locks");
- return -1;
- }
+ openssl_initialized = true;
}
- CRYPTO_set_locking_callback(openssl_locking_function);
- git__on_shutdown(shutdown_ssl_locking);
+ error |= git_mutex_unlock(&openssl_mutex);
+ return error;
+
+#else
return 0;
-#elif !defined(OPENSSL_LEGACY_API)
+#endif
+}
+
+#if !defined(GIT_OPENSSL_LEGACY) && !defined(GIT_OPENSSL_DYNAMIC)
+int git_openssl_set_locking(void)
+{
+# ifdef GIT_THREADS
return 0;
-#else
+# else
git_error_set(GIT_ERROR_THREAD, "libgit2 was not built with threads");
return -1;
-#endif
+# endif
}
+#endif
static int bio_create(BIO *b)
@@ -415,8 +302,8 @@ static int ssl_set_error(SSL *ssl, int error)
err = SSL_get_error(ssl, error);
- assert(err != SSL_ERROR_WANT_READ);
- assert(err != SSL_ERROR_WANT_WRITE);
+ GIT_ASSERT(err != SSL_ERROR_WANT_READ);
+ GIT_ASSERT(err != SSL_ERROR_WANT_WRITE);
switch (err) {
case SSL_ERROR_WANT_CONNECT:
@@ -758,7 +645,9 @@ static int openssl_stream_wrap(
{
openssl_stream *st;
- assert(out && in && host);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(in);
+ GIT_ASSERT_ARG(host);
st = git__calloc(1, sizeof(openssl_stream));
GIT_ERROR_CHECK_ALLOC(st);
@@ -793,6 +682,9 @@ static int openssl_stream_wrap(
int git_openssl_stream_wrap(git_stream **out, git_stream *in, const char *host)
{
+ if (openssl_ensure_initialized() < 0)
+ return -1;
+
return openssl_stream_wrap(out, in, host, 0);
}
@@ -801,7 +693,12 @@ int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
git_stream *stream = NULL;
int error;
- assert(out && host && port);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(host);
+ GIT_ASSERT_ARG(port);
+
+ if (openssl_ensure_initialized() < 0)
+ return -1;
if ((error = git_socket_stream_new(&stream, host, port)) < 0)
return error;
@@ -816,6 +713,9 @@ int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
int git_openssl__set_cert_location(const char *file, const char *path)
{
+ if (openssl_ensure_initialized() < 0)
+ return -1;
+
if (SSL_CTX_load_verify_locations(git__ssl_ctx, file, path) == 0) {
char errmsg[256];
diff --git a/src/streams/openssl.h b/src/streams/openssl.h
index 826d1efbc..89fb60a82 100644
--- a/src/streams/openssl.h
+++ b/src/streams/openssl.h
@@ -8,14 +8,22 @@
#define INCLUDE_streams_openssl_h__
#include "common.h"
+#include "streams/openssl_legacy.h"
+#include "streams/openssl_dynamic.h"
#include "git2/sys/stream.h"
extern int git_openssl_stream_global_init(void);
+#if defined(GIT_OPENSSL) && !defined(GIT_OPENSSL_DYNAMIC)
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+# include <openssl/bio.h>
+# endif
+
#ifdef GIT_OPENSSL
extern int git_openssl__set_cert_location(const char *file, const char *path);
-
extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
extern int git_openssl_stream_wrap(git_stream **out, git_stream *in, const char *host);
#endif
diff --git a/src/streams/openssl_dynamic.c b/src/streams/openssl_dynamic.c
new file mode 100644
index 000000000..da16b6ed7
--- /dev/null
+++ b/src/streams/openssl_dynamic.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "streams/openssl.h"
+#include "streams/openssl_dynamic.h"
+
+#if defined(GIT_OPENSSL) && defined(GIT_OPENSSL_DYNAMIC)
+
+#include "runtime.h"
+
+#include <dlfcn.h>
+
+unsigned char *(*ASN1_STRING_data)(ASN1_STRING *x);
+const unsigned char *(*ASN1_STRING_get0_data)(const ASN1_STRING *x);
+int (*ASN1_STRING_length)(const ASN1_STRING *x);
+int (*ASN1_STRING_to_UTF8)(unsigned char **out, const ASN1_STRING *in);
+int (*ASN1_STRING_type)(const ASN1_STRING *x);
+
+void *(*BIO_get_data)(BIO *a);
+int (*BIO_get_new_index)(void);
+int (*OPENSSL_init_ssl)(uint64_t opts, const void *settings);
+void (*BIO_meth_free)(BIO_METHOD *biom);
+int (*BIO_meth_set_create)(BIO_METHOD *biom, int (*create) (BIO *));
+int (*BIO_meth_set_ctrl)(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *));
+int (*BIO_meth_set_destroy)(BIO_METHOD *biom, int (*destroy) (BIO *));
+int (*BIO_meth_set_gets)(BIO_METHOD *biom, int (*gets) (BIO *, char *, int));
+int (*BIO_meth_set_puts)(BIO_METHOD *biom, int (*puts) (BIO *, const char *));
+int (*BIO_meth_set_read)(BIO_METHOD *biom, int (*read) (BIO *, char *, int));
+int (*BIO_meth_set_write)(BIO_METHOD *biom, int (*write) (BIO *, const char *, int));
+BIO_METHOD *(*BIO_meth_new)(int type, const char *name);
+BIO *(*BIO_new)(const BIO_METHOD *type);
+void (*BIO_set_data)(BIO *a, void *ptr);
+void (*BIO_set_init)(BIO *a, int init);
+
+void (*CRYPTO_free)(void *ptr, const char *file, int line);
+void *(*CRYPTO_malloc)(size_t num, const char *file, int line);
+int (*CRYPTO_num_locks)(void);
+void (*CRYPTO_set_locking_callback)(void (*func)(int mode, int type, const char *file, int line));
+int (*CRYPTO_set_mem_functions)(void *(*m)(size_t bytes), void *(*r)(void *mem, size_t size), void (*f)(void *mem));
+int (*CRYPTO_THREADID_set_callback)(void (*func)(CRYPTO_THREADID *id));
+void (*CRYPTO_THREADID_set_numeric)(CRYPTO_THREADID *id, unsigned long val);
+
+char *(*ERR_error_string)(unsigned long e, char *buf);
+void (*ERR_error_string_n)(unsigned long e, char *buf, size_t len);
+unsigned long (*ERR_get_error)(void);
+
+int (*SSL_connect)(SSL *ssl);
+long (*SSL_ctrl)(SSL *ssl, int cmd, long arg, void *parg);
+void (*SSL_free)(SSL *ssl);
+int (*SSL_get_error)(SSL *ssl, int ret);
+X509 *(*SSL_get_peer_certificate)(const SSL *ssl);
+long (*SSL_get_verify_result)(const SSL *ssl);
+int (*SSL_library_init)(void);
+void (*SSL_load_error_strings)(void);
+SSL *(*SSL_new)(SSL_CTX *ctx);
+int (*SSL_read)(SSL *ssl, const void *buf, int num);
+void (*SSL_set_bio)(SSL *ssl, BIO *rbio, BIO *wbio);
+int (*SSL_shutdown)(SSL *ssl);
+int (*SSL_write)(SSL *ssl, const void *buf, int num);
+
+long (*SSL_CTX_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg);
+void (*SSL_CTX_free)(SSL_CTX *ctx);
+SSL_CTX *(*SSL_CTX_new)(const SSL_METHOD *method);
+int (*SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str);
+int (*SSL_CTX_set_default_verify_paths)(SSL_CTX *ctx);
+long (*SSL_CTX_set_options)(SSL_CTX *ctx, long options);
+void (*SSL_CTX_set_verify)(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
+int (*SSL_CTX_load_verify_locations)(SSL_CTX *ctx, const char *CAfile, const char *CApath);
+
+const SSL_METHOD *(*SSLv23_method)(void);
+const SSL_METHOD *(*TLS_method)(void);
+
+ASN1_STRING *(*X509_NAME_ENTRY_get_data)(const X509_NAME_ENTRY *ne);
+X509_NAME_ENTRY *(*X509_NAME_get_entry)(X509_NAME *name, int loc);
+int (*X509_NAME_get_index_by_NID)(X509_NAME *name, int nid, int lastpos);
+void (*X509_free)(X509 *a);
+void *(*X509_get_ext_d2i)(const X509 *x, int nid, int *crit, int *idx);
+X509_NAME *(*X509_get_subject_name)(const X509 *x);
+
+int (*i2d_X509)(X509 *a, unsigned char **ppout);
+
+int (*OPENSSL_sk_num)(const void *sk);
+void *(*OPENSSL_sk_value)(const void *sk, int i);
+void (*OPENSSL_sk_free)(void *sk);
+
+int (*sk_num)(const void *sk);
+void *(*sk_value)(const void *sk, int i);
+void (*sk_free)(void *sk);
+
+void *openssl_handle;
+
+GIT_INLINE(void *) openssl_sym(int *err, const char *name, bool required)
+{
+ void *symbol;
+
+ /* if we've seen an err, noop to retain it */
+ if (*err)
+ return NULL;
+
+
+ if ((symbol = dlsym(openssl_handle, name)) == NULL && required) {
+ const char *msg = dlerror();
+ git_error_set(GIT_ERROR_SSL, "could not load ssl function '%s': %s", name, msg ? msg : "unknown error");
+ *err = -1;
+ }
+
+ return symbol;
+}
+
+static void dynamic_shutdown(void)
+{
+ dlclose(openssl_handle);
+ openssl_handle = NULL;
+}
+
+int git_openssl_stream_dynamic_init(void)
+{
+ int err = 0;
+
+ if ((openssl_handle = dlopen("libssl.so.1.1", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.1.1.dylib", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.so.1.0.0", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.1.0.0.dylib", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.so.10", RTLD_NOW)) == NULL) {
+ git_error_set(GIT_ERROR_SSL, "could not load ssl libraries");
+ return -1;
+ }
+
+ ASN1_STRING_data = (unsigned char *(*)(ASN1_STRING *x))openssl_sym(&err, "ASN1_STRING_data", false);
+ ASN1_STRING_get0_data = (const unsigned char *(*)(const ASN1_STRING *x))openssl_sym(&err, "ASN1_STRING_get0_data", false);
+ ASN1_STRING_length = (int (*)(const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_length", true);
+ ASN1_STRING_to_UTF8 = (int (*)(unsigned char **, const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_to_UTF8", true);
+ ASN1_STRING_type = (int (*)(const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_type", true);
+
+ BIO_get_data = (void *(*)(BIO *))openssl_sym(&err, "BIO_get_data", false);
+ BIO_get_new_index = (int (*)(void))openssl_sym(&err, "BIO_get_new_index", false);
+ BIO_meth_free = (void (*)(BIO_METHOD *))openssl_sym(&err, "BIO_meth_free", false);
+ BIO_meth_new = (BIO_METHOD *(*)(int, const char *))openssl_sym(&err, "BIO_meth_new", false);
+ BIO_meth_set_create = (int (*)(BIO_METHOD *, int (*)(BIO *)))openssl_sym(&err, "BIO_meth_set_create", false);
+ BIO_meth_set_ctrl = (int (*)(BIO_METHOD *, long (*)(BIO *, int, long, void *)))openssl_sym(&err, "BIO_meth_set_ctrl", false);
+ BIO_meth_set_destroy = (int (*)(BIO_METHOD *, int (*)(BIO *)))openssl_sym(&err, "BIO_meth_set_destroy", false);
+ BIO_meth_set_gets = (int (*)(BIO_METHOD *, int (*)(BIO *, char *, int)))openssl_sym(&err, "BIO_meth_set_gets", false);
+ BIO_meth_set_puts = (int (*)(BIO_METHOD *, int (*)(BIO *, const char *)))openssl_sym(&err, "BIO_meth_set_puts", false);
+ BIO_meth_set_read = (int (*)(BIO_METHOD *, int (*)(BIO *, char *, int)))openssl_sym(&err, "BIO_meth_set_read", false);
+ BIO_meth_set_write = (int (*)(BIO_METHOD *, int (*)(BIO *, const char *, int)))openssl_sym(&err, "BIO_meth_set_write", false);
+ BIO_new = (BIO *(*)(const BIO_METHOD *))openssl_sym(&err, "BIO_new", true);
+ BIO_set_data = (void (*)(BIO *a, void *))openssl_sym(&err, "BIO_set_data", false);
+ BIO_set_init = (void (*)(BIO *a, int))openssl_sym(&err, "BIO_set_init", false);
+
+ CRYPTO_free = (void (*)(void *, const char *, int))openssl_sym(&err, "CRYPTO_free", true);
+ CRYPTO_malloc = (void *(*)(size_t, const char *, int))openssl_sym(&err, "CRYPTO_malloc", true);
+ CRYPTO_num_locks = (int (*)(void))openssl_sym(&err, "CRYPTO_num_locks", false);
+ CRYPTO_set_locking_callback = (void (*)(void (*)(int, int, const char *, int)))openssl_sym(&err, "CRYPTO_set_locking_callback", false);
+ CRYPTO_set_mem_functions = (int (*)(void *(*)(size_t), void *(*)(void *, size_t), void (*f)(void *)))openssl_sym(&err, "CRYPTO_set_mem_functions", true);
+
+ CRYPTO_THREADID_set_callback = (int (*)(void (*)(CRYPTO_THREADID *)))openssl_sym(&err, "CRYPTO_THREADID_set_callback", false);
+ CRYPTO_THREADID_set_numeric = (void (*)(CRYPTO_THREADID *, unsigned long))openssl_sym(&err, "CRYPTO_THREADID_set_numeric", false);
+
+ ERR_error_string = (char *(*)(unsigned long, char *))openssl_sym(&err, "ERR_error_string", true);
+ ERR_error_string_n = (void (*)(unsigned long, char *, size_t))openssl_sym(&err, "ERR_error_string_n", true);
+ ERR_get_error = (unsigned long (*)(void))openssl_sym(&err, "ERR_get_error", true);
+
+ OPENSSL_init_ssl = (int (*)(uint64_t opts, const void *settings))openssl_sym(&err, "OPENSSL_init_ssl", false);
+ OPENSSL_sk_num = (int (*)(const void *))openssl_sym(&err, "OPENSSL_sk_num", false);
+ OPENSSL_sk_value = (void *(*)(const void *sk, int i))openssl_sym(&err, "OPENSSL_sk_value", false);
+ OPENSSL_sk_free = (void (*)(void *))openssl_sym(&err, "OPENSSL_sk_free", false);
+
+ sk_num = (int (*)(const void *))openssl_sym(&err, "sk_num", false);
+ sk_value = (void *(*)(const void *sk, int i))openssl_sym(&err, "sk_value", false);
+ sk_free = (void (*)(void *))openssl_sym(&err, "sk_free", false);
+
+ SSL_connect = (int (*)(SSL *))openssl_sym(&err, "SSL_connect", true);
+ SSL_ctrl = (long (*)(SSL *, int, long, void *))openssl_sym(&err, "SSL_ctrl", true);
+ SSL_get_peer_certificate = (X509 *(*)(const SSL *))openssl_sym(&err, "SSL_get_peer_certificate", true);
+ SSL_library_init = (int (*)(void))openssl_sym(&err, "SSL_library_init", false);
+ SSL_free = (void (*)(SSL *))openssl_sym(&err, "SSL_free", true);
+ SSL_get_error = (int (*)(SSL *, int))openssl_sym(&err, "SSL_get_error", true);
+ SSL_get_verify_result = (long (*)(const SSL *ssl))openssl_sym(&err, "SSL_get_verify_result", true);
+ SSL_load_error_strings = (void (*)(void))openssl_sym(&err, "SSL_load_error_strings", false);
+ SSL_new = (SSL *(*)(SSL_CTX *))openssl_sym(&err, "SSL_new", true);
+ SSL_read = (int (*)(SSL *, const void *, int))openssl_sym(&err, "SSL_read", true);
+ SSL_set_bio = (void (*)(SSL *, BIO *, BIO *))openssl_sym(&err, "SSL_set_bio", true);
+ SSL_shutdown = (int (*)(SSL *ssl))openssl_sym(&err, "SSL_shutdown", true);
+ SSL_write = (int (*)(SSL *, const void *, int))openssl_sym(&err, "SSL_write", true);
+
+ SSL_CTX_ctrl = (long (*)(SSL_CTX *, int, long, void *))openssl_sym(&err, "SSL_CTX_ctrl", true);
+ SSL_CTX_free = (void (*)(SSL_CTX *))openssl_sym(&err, "SSL_CTX_free", true);
+ SSL_CTX_new = (SSL_CTX *(*)(const SSL_METHOD *))openssl_sym(&err, "SSL_CTX_new", true);
+ SSL_CTX_set_cipher_list = (int (*)(SSL_CTX *, const char *))openssl_sym(&err, "SSL_CTX_set_cipher_list", true);
+ SSL_CTX_set_default_verify_paths = (int (*)(SSL_CTX *ctx))openssl_sym(&err, "SSL_CTX_set_default_verify_paths", true);
+ SSL_CTX_set_options = (long (*)(SSL_CTX *, long))openssl_sym(&err, "SSL_CTX_set_options", false);
+ SSL_CTX_set_verify = (void (*)(SSL_CTX *, int, int (*)(int, X509_STORE_CTX *)))openssl_sym(&err, "SSL_CTX_set_verify", true);
+ SSL_CTX_load_verify_locations = (int (*)(SSL_CTX *, const char *, const char *))openssl_sym(&err, "SSL_CTX_load_verify_locations", true);
+
+ SSLv23_method = (const SSL_METHOD *(*)(void))openssl_sym(&err, "SSLv23_method", false);
+ TLS_method = (const SSL_METHOD *(*)(void))openssl_sym(&err, "TLS_method", false);
+
+ X509_NAME_ENTRY_get_data = (ASN1_STRING *(*)(const X509_NAME_ENTRY *))openssl_sym(&err, "X509_NAME_ENTRY_get_data", true);
+ X509_NAME_get_entry = (X509_NAME_ENTRY *(*)(X509_NAME *, int))openssl_sym(&err, "X509_NAME_get_entry", true);
+ X509_NAME_get_index_by_NID = (int (*)(X509_NAME *, int, int))openssl_sym(&err, "X509_NAME_get_index_by_NID", true);
+ X509_free = (void (*)(X509 *))openssl_sym(&err, "X509_free", true);
+ X509_get_ext_d2i = (void *(*)(const X509 *x, int nid, int *crit, int *idx))openssl_sym(&err, "X509_get_ext_d2i", true);
+ X509_get_subject_name = (X509_NAME *(*)(const X509 *))openssl_sym(&err, "X509_get_subject_name", true);
+
+ i2d_X509 = (int (*)(X509 *a, unsigned char **ppout))openssl_sym(&err, "i2d_X509", true);
+
+ if (err)
+ goto on_error;
+
+ /* Add legacy functionality */
+ if (!OPENSSL_init_ssl) {
+ OPENSSL_init_ssl = OPENSSL_init_ssl__legacy;
+
+ if (!SSL_library_init ||
+ !SSL_load_error_strings ||
+ !CRYPTO_num_locks ||
+ !CRYPTO_set_locking_callback ||
+ !CRYPTO_THREADID_set_callback ||
+ !CRYPTO_THREADID_set_numeric) {
+ git_error_set(GIT_ERROR_SSL, "could not load legacy openssl initialization functions");
+ goto on_error;
+ }
+ }
+
+ if (!SSL_CTX_set_options)
+ SSL_CTX_set_options = SSL_CTX_set_options__legacy;
+
+ if (TLS_method)
+ SSLv23_method = TLS_method;
+
+ if (!BIO_meth_new) {
+ BIO_meth_new = BIO_meth_new__legacy;
+ BIO_meth_new = BIO_meth_new__legacy;
+ BIO_meth_free = BIO_meth_free__legacy;
+ BIO_meth_set_write = BIO_meth_set_write__legacy;
+ BIO_meth_set_read = BIO_meth_set_read__legacy;
+ BIO_meth_set_puts = BIO_meth_set_puts__legacy;
+ BIO_meth_set_gets = BIO_meth_set_gets__legacy;
+ BIO_meth_set_ctrl = BIO_meth_set_ctrl__legacy;
+ BIO_meth_set_create = BIO_meth_set_create__legacy;
+ BIO_meth_set_destroy = BIO_meth_set_destroy__legacy;
+ BIO_get_new_index = BIO_get_new_index__legacy;
+ BIO_set_data = BIO_set_data__legacy;
+ BIO_set_init = BIO_set_init__legacy;
+ BIO_get_data = BIO_get_data__legacy;
+ }
+
+ if (!ASN1_STRING_get0_data) {
+ if (!ASN1_STRING_data) {
+ git_error_set(GIT_ERROR_SSL, "could not load legacy openssl string function");
+ goto on_error;
+ }
+
+ ASN1_STRING_get0_data = ASN1_STRING_get0_data__legacy;
+ }
+
+ if ((!OPENSSL_sk_num && !sk_num) ||
+ (!OPENSSL_sk_value && !sk_value) ||
+ (!OPENSSL_sk_free && !sk_free)) {
+ git_error_set(GIT_ERROR_SSL, "could not load legacy openssl stack functions");
+ goto on_error;
+ }
+
+ if (git_runtime_shutdown_register(dynamic_shutdown) != 0)
+ goto on_error;
+
+ return 0;
+
+on_error:
+ dlclose(openssl_handle);
+ return -1;
+}
+
+
+int sk_GENERAL_NAME_num(const GENERAL_NAME *sk)
+{
+ if (OPENSSL_sk_num)
+ return OPENSSL_sk_num(sk);
+ else if (sk_num)
+ return sk_num(sk);
+
+ GIT_ASSERT_WITH_RETVAL(false, 0);
+ return 0;
+}
+
+GENERAL_NAME *sk_GENERAL_NAME_value(const GENERAL_NAME *sk, int i)
+{
+ if (OPENSSL_sk_value)
+ return OPENSSL_sk_value(sk, i);
+ else if (sk_value)
+ return sk_value(sk, i);
+
+ GIT_ASSERT_WITH_RETVAL(false, NULL);
+ return NULL;
+}
+
+void GENERAL_NAMES_free(GENERAL_NAME *sk)
+{
+ if (OPENSSL_sk_free)
+ OPENSSL_sk_free(sk);
+ else if (sk_free)
+ sk_free(sk);
+}
+
+#endif /* GIT_OPENSSL && GIT_OPENSSL_DYNAMIC */
diff --git a/src/streams/openssl_dynamic.h b/src/streams/openssl_dynamic.h
new file mode 100644
index 000000000..12d927a61
--- /dev/null
+++ b/src/streams/openssl_dynamic.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#ifndef INCLUDE_streams_openssl_dynamic_h__
+#define INCLUDE_streams_openssl_dynamic_h__
+
+#ifdef GIT_OPENSSL_DYNAMIC
+
+# define BIO_CTRL_FLUSH 11
+
+# define BIO_TYPE_SOURCE_SINK 0x0400
+
+# define CRYPTO_LOCK 1
+
+# define GEN_DNS 2
+# define GEN_IPADD 7
+
+# define NID_commonName 13
+# define NID_subject_alt_name 85
+
+# define SSL_VERIFY_NONE 0x00
+
+# define SSL_CTRL_OPTIONS 32
+# define SSL_CTRL_MODE 33
+# define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
+
+# define SSL_ERROR_NONE 0
+# define SSL_ERROR_SSL 1
+# define SSL_ERROR_WANT_READ 2
+# define SSL_ERROR_WANT_WRITE 3
+# define SSL_ERROR_WANT_X509_LOOKUP 4
+# define SSL_ERROR_SYSCALL 5
+# define SSL_ERROR_ZERO_RETURN 6
+# define SSL_ERROR_WANT_CONNECT 7
+# define SSL_ERROR_WANT_ACCEPT 8
+
+# define SSL_OP_NO_COMPRESSION 0x00020000L
+# define SSL_OP_NO_SSLv2 0x01000000L
+# define SSL_OP_NO_SSLv3 0x02000000L
+
+# define SSL_MODE_AUTO_RETRY 0x00000004L
+
+# define TLSEXT_NAMETYPE_host_name 0
+
+# define V_ASN1_UTF8STRING 12
+
+# define X509_V_OK 0
+
+/* Most of the OpenSSL types are mercifully opaque, so we can treat them like `void *` */
+typedef struct bio_st BIO;
+typedef struct bio_method_st BIO_METHOD;
+typedef void bio_info_cb;
+typedef void * CRYPTO_EX_DATA;
+typedef void CRYPTO_THREADID;
+typedef void GENERAL_NAMES;
+typedef void SSL;
+typedef void SSL_CTX;
+typedef void SSL_METHOD;
+typedef void X509;
+typedef void X509_NAME;
+typedef void X509_NAME_ENTRY;
+typedef void X509_STORE_CTX;
+
+typedef struct {
+ int length;
+ int type;
+ unsigned char *data;
+ long flags;
+} ASN1_STRING;
+
+typedef struct {
+ int type;
+ union {
+ char *ptr;
+ ASN1_STRING *ia5;
+ } d;
+} GENERAL_NAME;
+
+struct bio_st {
+ BIO_METHOD *method;
+ /* bio, mode, argp, argi, argl, ret */
+ long (*callback) (struct bio_st *, int, const char *, int, long, long);
+ char *cb_arg; /* first argument for the callback */
+ int init;
+ int shutdown;
+ int flags; /* extra storage */
+ int retry_reason;
+ int num;
+ void *ptr;
+ struct bio_st *next_bio; /* used by filter BIOs */
+ struct bio_st *prev_bio; /* used by filter BIOs */
+ int references;
+ unsigned long num_read;
+ unsigned long num_write;
+ CRYPTO_EX_DATA ex_data;
+};
+
+struct bio_method_st {
+ int type;
+ const char *name;
+ int (*bwrite) (BIO *, const char *, int);
+ int (*bread) (BIO *, char *, int);
+ int (*bputs) (BIO *, const char *);
+ int (*bgets) (BIO *, char *, int);
+ long (*ctrl) (BIO *, int, long, void *);
+ int (*create) (BIO *);
+ int (*destroy) (BIO *);
+ long (*callback_ctrl) (BIO *, int, bio_info_cb *);
+};
+
+extern unsigned char *(*ASN1_STRING_data)(ASN1_STRING *x);
+extern const unsigned char *(*ASN1_STRING_get0_data)(const ASN1_STRING *x);
+extern int (*ASN1_STRING_length)(const ASN1_STRING *x);
+extern int (*ASN1_STRING_to_UTF8)(unsigned char **out, const ASN1_STRING *in);
+extern int (*ASN1_STRING_type)(const ASN1_STRING *x);
+
+extern void *(*BIO_get_data)(BIO *a);
+extern int (*BIO_get_new_index)(void);
+extern int (*OPENSSL_init_ssl)(uint64_t opts, const void *settings);
+extern void (*BIO_meth_free)(BIO_METHOD *biom);
+extern int (*BIO_meth_set_create)(BIO_METHOD *biom, int (*create) (BIO *));
+extern int (*BIO_meth_set_ctrl)(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *));
+extern int (*BIO_meth_set_destroy)(BIO_METHOD *biom, int (*destroy) (BIO *));
+extern int (*BIO_meth_set_gets)(BIO_METHOD *biom, int (*gets) (BIO *, char *, int));
+extern int (*BIO_meth_set_puts)(BIO_METHOD *biom, int (*puts) (BIO *, const char *));
+extern int (*BIO_meth_set_read)(BIO_METHOD *biom, int (*read) (BIO *, char *, int));
+extern int (*BIO_meth_set_write)(BIO_METHOD *biom, int (*write) (BIO *, const char *, int));
+extern BIO_METHOD *(*BIO_meth_new)(int type, const char *name);
+extern BIO *(*BIO_new)(const BIO_METHOD *type);
+extern void (*BIO_set_data)(BIO *a, void *ptr);
+extern void (*BIO_set_init)(BIO *a, int init);
+
+extern void (*CRYPTO_free)(void *ptr, const char *file, int line);
+extern void *(*CRYPTO_malloc)(size_t num, const char *file, int line);
+extern int (*CRYPTO_num_locks)(void);
+extern void (*CRYPTO_set_locking_callback)(void (*func)(int mode, int type, const char *file, int line));
+extern int (*CRYPTO_set_mem_functions)(void *(*m)(size_t bytes), void *(*r)(void *mem, size_t size), void (*f)(void *mem));
+extern int (*CRYPTO_THREADID_set_callback)(void (*func)(CRYPTO_THREADID *id));
+extern void (*CRYPTO_THREADID_set_numeric)(CRYPTO_THREADID *id, unsigned long val);
+
+extern char *(*ERR_error_string)(unsigned long e, char *buf);
+extern void (*ERR_error_string_n)(unsigned long e, char *buf, size_t len);
+extern unsigned long (*ERR_get_error)(void);
+
+# define OPENSSL_malloc(num) CRYPTO_malloc(num, __FILE__, __LINE__)
+# define OPENSSL_free(addr) CRYPTO_free(addr, __FILE__, __LINE__)
+
+extern int (*SSL_connect)(SSL *ssl);
+extern long (*SSL_ctrl)(SSL *ssl, int cmd, long arg, void *parg);
+extern void (*SSL_free)(SSL *ssl);
+extern int (*SSL_get_error)(SSL *ssl, int ret);
+extern X509 *(*SSL_get_peer_certificate)(const SSL *ssl);
+extern long (*SSL_get_verify_result)(const SSL *ssl);
+extern int (*SSL_library_init)(void);
+extern void (*SSL_load_error_strings)(void);
+extern SSL *(*SSL_new)(SSL_CTX *ctx);
+extern int (*SSL_read)(SSL *ssl, const void *buf, int num);
+extern void (*SSL_set_bio)(SSL *ssl, BIO *rbio, BIO *wbio);
+extern int (*SSL_shutdown)(SSL *ssl);
+extern int (*SSL_write)(SSL *ssl, const void *buf, int num);
+
+# define SSL_set_tlsext_host_name(s, name) SSL_ctrl((s), SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (char *)(name));
+
+extern long (*SSL_CTX_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg);
+extern void (*SSL_CTX_free)(SSL_CTX *ctx);
+extern SSL_CTX *(*SSL_CTX_new)(const SSL_METHOD *method);
+extern int (*SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str);
+extern int (*SSL_CTX_set_default_verify_paths)(SSL_CTX *ctx);
+extern long (*SSL_CTX_set_options)(SSL_CTX *ctx, long options);
+extern void (*SSL_CTX_set_verify)(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
+extern int (*SSL_CTX_load_verify_locations)(SSL_CTX *ctx, const char *CAfile, const char *CApath);
+
+# define SSL_CTX_set_mode(ctx, mode) SSL_CTX_ctrl((ctx), SSL_CTRL_MODE, (mode), NULL);
+
+extern const SSL_METHOD *(*SSLv23_method)(void);
+extern const SSL_METHOD *(*TLS_method)(void);
+
+extern ASN1_STRING *(*X509_NAME_ENTRY_get_data)(const X509_NAME_ENTRY *ne);
+extern X509_NAME_ENTRY *(*X509_NAME_get_entry)(X509_NAME *name, int loc);
+extern int (*X509_NAME_get_index_by_NID)(X509_NAME *name, int nid, int lastpos);
+extern void (*X509_free)(X509 *a);
+extern void *(*X509_get_ext_d2i)(const X509 *x, int nid, int *crit, int *idx);
+extern X509_NAME *(*X509_get_subject_name)(const X509 *x);
+
+extern int (*i2d_X509)(X509 *a, unsigned char **ppout);
+
+extern int (*OPENSSL_sk_num)(const void *sk);
+extern void *(*OPENSSL_sk_value)(const void *sk, int i);
+extern void (*OPENSSL_sk_free)(void *sk);
+
+extern int (*sk_num)(const void *sk);
+extern void *(*sk_value)(const void *sk, int i);
+extern void (*sk_free)(void *sk);
+
+extern int sk_GENERAL_NAME_num(const GENERAL_NAME *sk);
+extern GENERAL_NAME *sk_GENERAL_NAME_value(const GENERAL_NAME *sk, int i);
+extern void GENERAL_NAMES_free(GENERAL_NAME *sk);
+
+extern int git_openssl_stream_dynamic_init(void);
+
+#endif /* GIT_OPENSSL_DYNAMIC */
+
+#endif
diff --git a/src/streams/openssl_legacy.c b/src/streams/openssl_legacy.c
new file mode 100644
index 000000000..e61e6efbb
--- /dev/null
+++ b/src/streams/openssl_legacy.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "streams/openssl.h"
+#include "streams/openssl_legacy.h"
+
+#include "runtime.h"
+#include "git2/sys/openssl.h"
+
+#if defined(GIT_OPENSSL) && !defined(GIT_OPENSSL_DYNAMIC)
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+# include <openssl/bio.h>
+#endif
+
+#if defined(GIT_OPENSSL_LEGACY) || defined(GIT_OPENSSL_DYNAMIC)
+
+/*
+ * OpenSSL 1.1 made BIO opaque so we have to use functions to interact with it
+ * which do not exist in previous versions. We define these inline functions so
+ * we can program against the interface instead of littering the implementation
+ * with ifdefs. We do the same for OPENSSL_init_ssl.
+ */
+
+int OPENSSL_init_ssl__legacy(uint64_t opts, const void *settings)
+{
+ GIT_UNUSED(opts);
+ GIT_UNUSED(settings);
+ SSL_load_error_strings();
+ SSL_library_init();
+ return 0;
+}
+
+BIO_METHOD *BIO_meth_new__legacy(int type, const char *name)
+{
+ BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
+ if (!meth) {
+ return NULL;
+ }
+
+ meth->type = type;
+ meth->name = name;
+
+ return meth;
+}
+
+void BIO_meth_free__legacy(BIO_METHOD *biom)
+{
+ git__free(biom);
+}
+
+int BIO_meth_set_write__legacy(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
+{
+ biom->bwrite = write;
+ return 1;
+}
+
+int BIO_meth_set_read__legacy(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
+{
+ biom->bread = read;
+ return 1;
+}
+
+int BIO_meth_set_puts__legacy(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
+{
+ biom->bputs = puts;
+ return 1;
+}
+
+int BIO_meth_set_gets__legacy(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
+
+{
+ biom->bgets = gets;
+ return 1;
+}
+
+int BIO_meth_set_ctrl__legacy(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
+{
+ biom->ctrl = ctrl;
+ return 1;
+}
+
+int BIO_meth_set_create__legacy(BIO_METHOD *biom, int (*create) (BIO *))
+{
+ biom->create = create;
+ return 1;
+}
+
+int BIO_meth_set_destroy__legacy(BIO_METHOD *biom, int (*destroy) (BIO *))
+{
+ biom->destroy = destroy;
+ return 1;
+}
+
+int BIO_get_new_index__legacy(void)
+{
+ /* This exists as of 1.1 so before we'd just have 0 */
+ return 0;
+}
+
+void BIO_set_init__legacy(BIO *b, int init)
+{
+ b->init = init;
+}
+
+void BIO_set_data__legacy(BIO *a, void *ptr)
+{
+ a->ptr = ptr;
+}
+
+void *BIO_get_data__legacy(BIO *a)
+{
+ return a->ptr;
+}
+
+const unsigned char *ASN1_STRING_get0_data__legacy(const ASN1_STRING *x)
+{
+ return ASN1_STRING_data((ASN1_STRING *)x);
+}
+
+long SSL_CTX_set_options__legacy(SSL_CTX *ctx, long op)
+{
+ return SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, op, NULL);
+}
+
+# if defined(GIT_THREADS)
+static git_mutex *openssl_locks;
+
+static void openssl_locking_function(int mode, int n, const char *file, int line)
+{
+ int lock;
+
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ lock = mode & CRYPTO_LOCK;
+
+ if (lock)
+ (void)git_mutex_lock(&openssl_locks[n]);
+ else
+ git_mutex_unlock(&openssl_locks[n]);
+}
+
+static void shutdown_ssl_locking(void)
+{
+ int num_locks, i;
+
+ num_locks = CRYPTO_num_locks();
+ CRYPTO_set_locking_callback(NULL);
+
+ for (i = 0; i < num_locks; ++i)
+ git_mutex_free(&openssl_locks[i]);
+ git__free(openssl_locks);
+}
+
+static void threadid_cb(CRYPTO_THREADID *threadid)
+{
+ GIT_UNUSED(threadid);
+ CRYPTO_THREADID_set_numeric(threadid, git_thread_currentid());
+}
+
+int git_openssl_set_locking(void)
+{
+ int num_locks, i;
+
+#ifndef GIT_THREADS
+ git_error_set(GIT_ERROR_THREAD, "libgit2 was not built with threads");
+ return -1;
+#endif
+
+#ifdef GIT_OPENSSL_DYNAMIC
+ /*
+ * This function is required on legacy versions of OpenSSL; when building
+ * with dynamically-loaded OpenSSL, we detect whether we loaded it or not.
+ */
+ if (!CRYPTO_set_locking_callback)
+ return 0;
+#endif
+
+ CRYPTO_THREADID_set_callback(threadid_cb);
+
+ num_locks = CRYPTO_num_locks();
+ openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
+ GIT_ERROR_CHECK_ALLOC(openssl_locks);
+
+ for (i = 0; i < num_locks; i++) {
+ if (git_mutex_init(&openssl_locks[i]) != 0) {
+ git_error_set(GIT_ERROR_SSL, "failed to initialize openssl locks");
+ return -1;
+ }
+ }
+
+ CRYPTO_set_locking_callback(openssl_locking_function);
+ return git_runtime_shutdown_register(shutdown_ssl_locking);
+}
+#endif /* GIT_THREADS */
+
+#endif /* GIT_OPENSSL_LEGACY || GIT_OPENSSL_DYNAMIC */
diff --git a/src/streams/openssl_legacy.h b/src/streams/openssl_legacy.h
new file mode 100644
index 000000000..e6dae9572
--- /dev/null
+++ b/src/streams/openssl_legacy.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_streams_openssl_legacy_h__
+#define INCLUDE_streams_openssl_legacy_h__
+
+#include "streams/openssl_dynamic.h"
+
+#if defined(GIT_OPENSSL) && !defined(GIT_OPENSSL_DYNAMIC)
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+# include <openssl/bio.h>
+
+# if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
+# define GIT_OPENSSL_LEGACY
+# endif
+#endif
+
+#if defined(GIT_OPENSSL_LEGACY) && !defined(GIT_OPENSSL_DYNAMIC)
+# define OPENSSL_init_ssl OPENSSL_init_ssl__legacy
+# define BIO_meth_new BIO_meth_new__legacy
+# define BIO_meth_free BIO_meth_free__legacy
+# define BIO_meth_set_write BIO_meth_set_write__legacy
+# define BIO_meth_set_read BIO_meth_set_read__legacy
+# define BIO_meth_set_puts BIO_meth_set_puts__legacy
+# define BIO_meth_set_gets BIO_meth_set_gets__legacy
+# define BIO_meth_set_ctrl BIO_meth_set_ctrl__legacy
+# define BIO_meth_set_create BIO_meth_set_create__legacy
+# define BIO_meth_set_destroy BIO_meth_set_destroy__legacy
+# define BIO_get_new_index BIO_get_new_index__legacy
+# define BIO_set_data BIO_set_data__legacy
+# define BIO_set_init BIO_set_init__legacy
+# define BIO_get_data BIO_get_data__legacy
+# define ASN1_STRING_get0_data ASN1_STRING_get0_data__legacy
+#endif
+
+#if defined(GIT_OPENSSL_LEGACY) || defined(GIT_OPENSSL_DYNAMIC)
+
+extern int OPENSSL_init_ssl__legacy(uint64_t opts, const void *settings);
+extern BIO_METHOD *BIO_meth_new__legacy(int type, const char *name);
+extern void BIO_meth_free__legacy(BIO_METHOD *biom);
+extern int BIO_meth_set_write__legacy(BIO_METHOD *biom, int (*write) (BIO *, const char *, int));
+extern int BIO_meth_set_read__legacy(BIO_METHOD *biom, int (*read) (BIO *, char *, int));
+extern int BIO_meth_set_puts__legacy(BIO_METHOD *biom, int (*puts) (BIO *, const char *));
+extern int BIO_meth_set_gets__legacy(BIO_METHOD *biom, int (*gets) (BIO *, char *, int));
+extern int BIO_meth_set_ctrl__legacy(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *));
+extern int BIO_meth_set_create__legacy(BIO_METHOD *biom, int (*create) (BIO *));
+extern int BIO_meth_set_destroy__legacy(BIO_METHOD *biom, int (*destroy) (BIO *));
+extern int BIO_get_new_index__legacy(void);
+extern void BIO_set_data__legacy(BIO *a, void *ptr);
+extern void BIO_set_init__legacy(BIO *b, int init);
+extern void *BIO_get_data__legacy(BIO *a);
+extern const unsigned char *ASN1_STRING_get0_data__legacy(const ASN1_STRING *x);
+extern long SSL_CTX_set_options__legacy(SSL_CTX *ctx, long op);
+
+#endif
+
+#endif
diff --git a/src/streams/registry.c b/src/streams/registry.c
index 284431207..e60e1cd63 100644
--- a/src/streams/registry.c
+++ b/src/streams/registry.c
@@ -9,7 +9,7 @@
#include "streams/registry.h"
-#include "global.h"
+#include "runtime.h"
#include "streams/tls.h"
#include "streams/mbedtls.h"
#include "streams/openssl.h"
@@ -33,8 +33,7 @@ int git_stream_registry_global_init(void)
if (git_rwlock_init(&stream_registry.lock) < 0)
return -1;
- git__on_shutdown(shutdown_stream_registry);
- return 0;
+ return git_runtime_shutdown_register(shutdown_stream_registry);
}
GIT_INLINE(void) stream_registration_cpy(
@@ -52,7 +51,7 @@ int git_stream_registry_lookup(git_stream_registration *out, git_stream_t type)
git_stream_registration *target;
int error = GIT_ENOTFOUND;
- assert(out);
+ GIT_ASSERT_ARG(out);
switch(type) {
case GIT_STREAM_STANDARD:
@@ -62,7 +61,7 @@ int git_stream_registry_lookup(git_stream_registration *out, git_stream_t type)
target = &stream_registry.tls_callbacks;
break;
default:
- assert(0);
+ git_error_set(GIT_ERROR_INVALID, "invalid stream type");
return -1;
}
@@ -82,7 +81,7 @@ int git_stream_registry_lookup(git_stream_registration *out, git_stream_t type)
int git_stream_register(git_stream_t type, git_stream_registration *registration)
{
- assert(!registration || registration->init);
+ GIT_ASSERT(!registration || registration->init);
GIT_ERROR_CHECK_VERSION(registration, GIT_STREAM_VERSION, "stream_registration");
diff --git a/src/streams/socket.c b/src/streams/socket.c
index 33f7883cd..9415fe892 100644
--- a/src/streams/socket.c
+++ b/src/streams/socket.c
@@ -183,7 +183,9 @@ static int default_socket_stream_new(
{
git_socket_stream *st;
- assert(out && host && port);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(host);
+ GIT_ASSERT_ARG(port);
st = git__calloc(1, sizeof(git_socket_stream));
GIT_ERROR_CHECK_ALLOC(st);
@@ -217,7 +219,9 @@ int git_socket_stream_new(
git_stream_registration custom = {0};
int error;
- assert(out && host && port);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(host);
+ GIT_ASSERT_ARG(port);
if ((error = git_stream_registry_lookup(&custom, GIT_STREAM_STANDARD)) == 0)
init = custom.init;
diff --git a/src/streams/stransport.c b/src/streams/stransport.c
index a79d3cbf0..3f31d2541 100644
--- a/src/streams/stransport.c
+++ b/src/streams/stransport.c
@@ -167,7 +167,7 @@ static ssize_t stransport_write(git_stream *stream, const char *data, size_t len
if ((ret = SSLWrite(st->ctx, data, data_len, &processed)) != noErr)
return stransport_error(ret);
- assert(processed < SSIZE_MAX);
+ GIT_ASSERT(processed < SSIZE_MAX);
return (ssize_t)processed;
}
@@ -251,7 +251,9 @@ static int stransport_wrap(
stransport_stream *st;
OSStatus ret;
- assert(out && in && host);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(in);
+ GIT_ASSERT_ARG(host);
st = git__calloc(1, sizeof(stransport_stream));
GIT_ERROR_CHECK_ALLOC(st);
@@ -305,7 +307,8 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
git_stream *stream = NULL;
int error;
- assert(out && host);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(host);
error = git_socket_stream_new(&stream, host, port);
diff --git a/src/streams/tls.c b/src/streams/tls.c
index 6a251717b..e063a33f9 100644
--- a/src/streams/tls.c
+++ b/src/streams/tls.c
@@ -8,7 +8,6 @@
#include "git2/errors.h"
#include "common.h"
-#include "global.h"
#include "streams/registry.h"
#include "streams/tls.h"
#include "streams/mbedtls.h"
@@ -21,7 +20,9 @@ int git_tls_stream_new(git_stream **out, const char *host, const char *port)
git_stream_registration custom = {0};
int error;
- assert(out && host && port);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(host);
+ GIT_ASSERT_ARG(port);
if ((error = git_stream_registry_lookup(&custom, GIT_STREAM_TLS)) == 0) {
init = custom.init;
@@ -50,7 +51,8 @@ int git_tls_stream_wrap(git_stream **out, git_stream *in, const char *host)
int (*wrap)(git_stream **, git_stream *, const char *) = NULL;
git_stream_registration custom = {0};
- assert(out && in);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(in);
if (git_stream_registry_lookup(&custom, GIT_STREAM_TLS) == 0) {
wrap = custom.wrap;
diff --git a/src/submodule.c b/src/submodule.c
index c32b9770a..7cbb9fa3a 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -12,7 +12,6 @@
#include "git2/types.h"
#include "git2/index.h"
#include "buffer.h"
-#include "buf_text.h"
#include "vector.h"
#include "posix.h"
#include "config_backend.h"
@@ -249,24 +248,62 @@ out:
return error;
}
+int git_submodule_cache_init(git_strmap **out, git_repository *repo)
+{
+ int error = 0;
+ git_strmap *cache = NULL;
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ if ((error = git_strmap_new(&cache)) < 0)
+ return error;
+ if ((error = git_submodule__map(repo, cache)) < 0) {
+ git_submodule_cache_free(cache);
+ return error;
+ }
+ *out = cache;
+ return error;
+}
+
+int git_submodule_cache_free(git_strmap *cache)
+{
+ git_submodule *sm = NULL;
+ if (cache == NULL)
+ return 0;
+ git_strmap_foreach_value(cache, sm, {
+ git_submodule_free(sm);
+ });
+ git_strmap_free(cache);
+ return 0;
+}
+
int git_submodule_lookup(
git_submodule **out, /* NULL if user only wants to test existence */
git_repository *repo,
const char *name) /* trailing slash is allowed */
{
+ return git_submodule__lookup_with_cache(out, repo, name, repo->submodule_cache);
+}
+
+int git_submodule__lookup_with_cache(
+ git_submodule **out, /* NULL if user only wants to test existence */
+ git_repository *repo,
+ const char *name, /* trailing slash is allowed */
+ git_strmap *cache)
+{
int error;
unsigned int location;
git_submodule *sm;
- assert(repo && name);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
if (repo->is_bare) {
git_error_set(GIT_ERROR_SUBMODULE, "cannot get submodules without a working tree");
return -1;
}
- if (repo->submodule_cache != NULL) {
- if ((sm = git_strmap_get(repo->submodule_cache, name)) != NULL) {
+ if (cache != NULL) {
+ if ((sm = git_strmap_get(cache, name)) != NULL) {
if (out) {
*out = sm;
GIT_REFCOUNT_INC(*out);
@@ -342,8 +379,10 @@ int git_submodule_lookup(
/* If it's not configured, we still check if there's a repo at the path */
if (git_repository_workdir(repo)) {
git_buf path = GIT_BUF_INIT;
- if (git_buf_join3(&path,
- '/', git_repository_workdir(repo), name, DOT_GIT) < 0)
+ if (git_buf_join3(&path, '/',
+ git_repository_workdir(repo),
+ name, DOT_GIT) < 0 ||
+ git_path_validate_workdir_buf(NULL, &path) < 0)
return -1;
if (git_path_exists(path.ptr))
@@ -380,7 +419,7 @@ int git_submodule_name_is_valid(git_repository *repo, const char *name, int flag
git_buf_attach_notowned(&buf, name, strlen(name));
}
- isvalid = git_path_isvalid(repo, buf.ptr, 0, flags);
+ isvalid = git_path_validate(repo, buf.ptr, 0, flags);
git_buf_dispose(&buf);
return isvalid;
@@ -515,12 +554,13 @@ int git_submodule__map(git_repository *repo, git_strmap *map)
int error = 0;
git_index *idx = NULL;
git_tree *head = NULL;
- const char *wd = NULL;
git_buf path = GIT_BUF_INIT;
git_submodule *sm;
git_config *mods = NULL;
+ bool has_workdir;
- assert(repo && map);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(map);
/* get sources that we will need to check */
if (git_repository_index(&idx, repo) < 0)
@@ -528,12 +568,14 @@ int git_submodule__map(git_repository *repo, git_strmap *map)
if (git_repository_head_tree(&head, repo) < 0)
git_error_clear();
- wd = git_repository_workdir(repo);
- if (wd && (error = git_buf_joinpath(&path, wd, GIT_MODULES_FILE)) < 0)
+ has_workdir = git_repository_workdir(repo) != NULL;
+
+ if (has_workdir &&
+ (error = git_repository_workdir_path(&path, repo, GIT_MODULES_FILE)) < 0)
goto cleanup;
/* add submodule information from .gitmodules */
- if (wd) {
+ if (has_workdir) {
lfc_data data = { 0 };
data.map = map;
data.repo = repo;
@@ -560,7 +602,7 @@ int git_submodule__map(git_repository *repo, git_strmap *map)
goto cleanup;
}
/* shallow scan submodules in work tree as needed */
- if (wd) {
+ if (has_workdir) {
git_strmap_foreach_value(map, sm, {
submodule_load_from_wd_lite(sm);
});
@@ -644,7 +686,7 @@ static int submodule_repo_init(
git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT;
git_repository *subrepo = NULL;
- error = git_buf_joinpath(&workdir, git_repository_workdir(parent_repo), path);
+ error = git_repository_workdir_path(&workdir, parent_repo, path);
if (error < 0)
goto cleanup;
@@ -698,7 +740,9 @@ int git_submodule_add_setup(
git_repository *subrepo = NULL;
bool path_occupied;
- assert(repo && url && path);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(url);
+ GIT_ASSERT_ARG(path);
/* see if there is already an entry for this submodule */
@@ -749,7 +793,7 @@ int git_submodule_add_setup(
/* init submodule repository and add origin remote as needed */
- error = git_buf_joinpath(&name, git_repository_workdir(repo), path);
+ error = git_repository_workdir_path(&name, repo, path);
if (error < 0)
goto cleanup;
@@ -799,7 +843,8 @@ int git_submodule_repo_init(
git_config *cfg = NULL;
git_buf buf = GIT_BUF_INIT;
- assert(out && sm);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(sm);
/* get the configured remote url of the submodule */
if ((error = git_buf_printf(&buf, "submodule.%s.url", sm->name)) < 0 ||
@@ -840,7 +885,7 @@ int git_submodule_clone(git_repository **out, git_submodule *submodule, const gi
git_submodule_update_options sub_opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
- assert(submodule);
+ GIT_ASSERT_ARG(submodule);
if (given_opts)
memcpy(&sub_opts, given_opts, sizeof(sub_opts));
@@ -854,10 +899,9 @@ int git_submodule_clone(git_repository **out, git_submodule *submodule, const gi
opts.remote_cb = clone_return_origin;
opts.remote_cb_payload = submodule;
- git_buf_puts(&rel_path, git_repository_workdir(git_submodule_owner(submodule)));
- git_buf_joinpath(&rel_path, git_buf_cstr(&rel_path), git_submodule_path(submodule));
-
- GIT_ERROR_CHECK_ALLOC_BUF(&rel_path);
+ error = git_repository_workdir_path(&rel_path, git_submodule_owner(submodule), git_submodule_path(submodule));
+ if (error < 0)
+ goto cleanup;
error = git_clone__submodule(&clone, git_submodule_url(submodule), git_buf_cstr(&rel_path), &opts);
if (error < 0)
@@ -879,7 +923,7 @@ int git_submodule_add_finalize(git_submodule *sm)
int error;
git_index *index;
- assert(sm);
+ GIT_ASSERT_ARG(sm);
if ((error = git_repository_index__weakptr(&index, sm->repo)) < 0 ||
(error = git_index_add_bypath(index, GIT_MODULES_FILE)) < 0)
@@ -898,15 +942,14 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
git_index_entry entry;
struct stat st;
- assert(sm);
+ GIT_ASSERT_ARG(sm);
/* force reload of wd OID by git_submodule_open */
sm->flags = sm->flags & ~GIT_SUBMODULE_STATUS__WD_OID_VALID;
if ((error = git_repository_index__weakptr(&index, sm->repo)) < 0 ||
- (error = git_buf_joinpath(
- &path, git_repository_workdir(sm->repo), sm->path)) < 0 ||
- (error = git_submodule_open(&sm_repo, sm)) < 0)
+ (error = git_repository_workdir_path(&path, sm->repo, sm->path)) < 0 ||
+ (error = git_submodule_open(&sm_repo, sm)) < 0)
goto cleanup;
/* read stat information for submodule working directory */
@@ -969,25 +1012,25 @@ static const char *submodule_update_to_str(git_submodule_update_t update)
git_repository *git_submodule_owner(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
return submodule->repo;
}
const char *git_submodule_name(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
return submodule->name;
}
const char *git_submodule_path(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
return submodule->path;
}
const char *git_submodule_url(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
return submodule->url;
}
@@ -996,9 +1039,12 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur
int error = 0;
git_buf normalized = GIT_BUF_INIT;
- assert(out && repo && url);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(url);
- git_buf_sanitize(out);
+ if ((error = git_buf_sanitize(out)) < 0)
+ return error;
/* We do this in all platforms in case someone on Windows created the .gitmodules */
if (strchr(url, '\\')) {
@@ -1066,28 +1112,30 @@ static int write_mapped_var(git_repository *repo, const char *name, git_configma
const char *git_submodule_branch(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
return submodule->branch;
}
int git_submodule_set_branch(git_repository *repo, const char *name, const char *branch)
{
-
- assert(repo && name);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
return write_var(repo, name, "branch", branch);
}
int git_submodule_set_url(git_repository *repo, const char *name, const char *url)
{
- assert(repo && name && url);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
+ GIT_ASSERT_ARG(url);
return write_var(repo, name, "url", url);
}
const git_oid *git_submodule_index_id(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
if (submodule->flags & GIT_SUBMODULE_STATUS__INDEX_OID_VALID)
return &submodule->index_oid;
@@ -1097,7 +1145,7 @@ const git_oid *git_submodule_index_id(git_submodule *submodule)
const git_oid *git_submodule_head_id(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
if (submodule->flags & GIT_SUBMODULE_STATUS__HEAD_OID_VALID)
return &submodule->head_oid;
@@ -1107,7 +1155,7 @@ const git_oid *git_submodule_head_id(git_submodule *submodule)
const git_oid *git_submodule_wd_id(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, NULL);
/* load unless we think we have a valid oid */
if (!(submodule->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID)) {
@@ -1128,28 +1176,32 @@ const git_oid *git_submodule_wd_id(git_submodule *submodule)
git_submodule_ignore_t git_submodule_ignore(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, GIT_SUBMODULE_IGNORE_UNSPECIFIED);
+
return (submodule->ignore < GIT_SUBMODULE_IGNORE_NONE) ?
GIT_SUBMODULE_IGNORE_NONE : submodule->ignore;
}
int git_submodule_set_ignore(git_repository *repo, const char *name, git_submodule_ignore_t ignore)
{
- assert(repo && name);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
return write_mapped_var(repo, name, _sm_ignore_map, ARRAY_SIZE(_sm_ignore_map), "ignore", ignore);
}
git_submodule_update_t git_submodule_update_strategy(git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, GIT_SUBMODULE_UPDATE_NONE);
+
return (submodule->update < GIT_SUBMODULE_UPDATE_CHECKOUT) ?
GIT_SUBMODULE_UPDATE_CHECKOUT : submodule->update;
}
int git_submodule_set_update(git_repository *repo, const char *name, git_submodule_update_t update)
{
- assert(repo && name);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
return write_mapped_var(repo, name, _sm_update_map, ARRAY_SIZE(_sm_update_map), "update", update);
}
@@ -1157,13 +1209,14 @@ int git_submodule_set_update(git_repository *repo, const char *name, git_submodu
git_submodule_recurse_t git_submodule_fetch_recurse_submodules(
git_submodule *submodule)
{
- assert(submodule);
+ GIT_ASSERT_ARG_WITH_RETVAL(submodule, GIT_SUBMODULE_RECURSE_NO);
return submodule->fetch_recurse;
}
int git_submodule_set_fetch_recurse_submodules(git_repository *repo, const char *name, git_submodule_recurse_t recurse)
{
- assert(repo && name);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
return write_mapped_var(repo, name, _sm_recurse_map, ARRAY_SIZE(_sm_recurse_map), "fetchRecurseSubmodules", recurse);
}
@@ -1185,7 +1238,7 @@ static int submodule_repo_create(
GIT_REPOSITORY_INIT_RELATIVE_GITLINK;
/* Workdir: path to sub-repo working directory */
- error = git_buf_joinpath(&workdir, git_repository_workdir(parent_repo), path);
+ error = git_repository_workdir_path(&workdir, parent_repo, path);
if (error < 0)
goto cleanup;
@@ -1260,7 +1313,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
git_clone_options clone_options = GIT_CLONE_OPTIONS_INIT;
- assert(sm);
+ GIT_ASSERT_ARG(sm);
if (_update_options)
memcpy(&update_options, _update_options, sizeof(git_submodule_update_options));
@@ -1473,7 +1526,8 @@ static int git_submodule__open(
unsigned int flags = GIT_REPOSITORY_OPEN_NO_SEARCH;
const char *wd;
- assert(sm && subrepo);
+ GIT_ASSERT_ARG(sm);
+ GIT_ASSERT_ARG(subrepo);
if (git_repository__ensure_not_bare(
sm->repo, "open submodule repository") < 0)
@@ -1481,8 +1535,7 @@ static int git_submodule__open(
wd = git_repository_workdir(sm->repo);
- if (git_buf_joinpath(&path, wd, sm->path) < 0 ||
- git_buf_joinpath(&path, path.ptr, DOT_GIT) < 0)
+ if (git_buf_join3(&path, '/', wd, sm->path, DOT_GIT) < 0)
return -1;
sm->flags = sm->flags &
@@ -1609,7 +1662,7 @@ int git_submodule_reload(git_submodule *sm, int force)
GIT_UNUSED(force);
- assert(sm);
+ GIT_ASSERT_ARG(sm);
if ((error = git_submodule_name_is_valid(sm->repo, sm->name, 0)) <= 0)
/* This should come with a warning, but we've no API for that */
@@ -1726,7 +1779,9 @@ int git_submodule_status(unsigned int *status, git_repository *repo, const char
git_submodule *sm;
int error;
- assert(status && repo && name);
+ GIT_ASSERT_ARG(status);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
if ((error = git_submodule_lookup(&sm, repo, name)) < 0)
return error;
@@ -1739,7 +1794,8 @@ int git_submodule_status(unsigned int *status, git_repository *repo, const char
int git_submodule_location(unsigned int *location, git_submodule *sm)
{
- assert(location && sm);
+ GIT_ASSERT_ARG(location);
+ GIT_ASSERT_ARG(sm);
return git_submodule__status(
location, NULL, NULL, NULL, sm, GIT_SUBMODULE_IGNORE_ALL);
@@ -1798,6 +1854,17 @@ static void submodule_release(git_submodule *sm)
git__free(sm);
}
+int git_submodule_dup(git_submodule **out, git_submodule *source)
+{
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(source);
+
+ GIT_REFCOUNT_INC(source);
+
+ *out = source;
+ return 0;
+}
+
void git_submodule_free(git_submodule *sm)
{
if (!sm)
@@ -2024,7 +2091,7 @@ static int submodule_load_from_wd_lite(git_submodule *sm)
{
git_buf path = GIT_BUF_INIT;
- if (git_buf_joinpath(&path, git_repository_workdir(sm->repo), sm->path) < 0)
+ if (git_repository_workdir_path(&path, sm->repo, sm->path) < 0)
return -1;
if (git_path_isdir(path.ptr))
@@ -2044,15 +2111,14 @@ static int submodule_load_from_wd_lite(git_submodule *sm)
*/
static int gitmodules_snapshot(git_config **snap, git_repository *repo)
{
- const char *workdir = git_repository_workdir(repo);
git_config *mods = NULL;
git_buf path = GIT_BUF_INIT;
int error;
- if (!workdir)
+ if (git_repository_workdir(repo) == NULL)
return GIT_ENOTFOUND;
- if ((error = git_buf_joinpath(&path, workdir, GIT_MODULES_FILE)) < 0)
+ if ((error = git_repository_workdir_path(&path, repo, GIT_MODULES_FILE)) < 0)
return error;
if ((error = git_config_open_ondisk(&mods, path.ptr)) < 0)
@@ -2076,12 +2142,11 @@ static git_config_backend *open_gitmodules(
git_repository *repo,
int okay_to_create)
{
- const char *workdir = git_repository_workdir(repo);
git_buf path = GIT_BUF_INIT;
git_config_backend *mods = NULL;
- if (workdir != NULL) {
- if (git_buf_joinpath(&path, workdir, GIT_MODULES_FILE) != 0)
+ if (git_repository_workdir(repo) != NULL) {
+ if (git_repository_workdir_path(&path, repo, GIT_MODULES_FILE) != 0)
return NULL;
if (okay_to_create || git_path_isfile(path.ptr)) {
@@ -2194,8 +2259,9 @@ static int get_url_base(git_buf *url, git_repository *repo)
if ((error = git_worktree_open_from_repository(&wt, repo)) < 0)
goto out;
error = git_buf_sets(url, wt->parent_path);
- } else
+ } else {
error = git_buf_sets(url, git_repository_workdir(repo));
+ }
out:
git_remote_free(remote);
diff --git a/src/submodule.h b/src/submodule.h
index 57d95c3fc..b01ff68a2 100644
--- a/src/submodule.h
+++ b/src/submodule.h
@@ -101,12 +101,6 @@ struct git_submodule {
git_oid wd_oid;
};
-/* Force revalidation of submodule data cache (alloc as needed) */
-extern int git_submodule_cache_refresh(git_repository *repo);
-
-/* Release all submodules */
-extern void git_submodule_cache_free(git_repository *repo);
-
/* Additional flags on top of public GIT_SUBMODULE_STATUS values */
enum {
GIT_SUBMODULE_STATUS__WD_SCANNED = (1u << 20),
@@ -122,9 +116,15 @@ enum {
#define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \
((S) & ~(0xFFFFFFFFu << 20))
-/* Internal lookup does not attempt to refresh cached data */
-extern int git_submodule__lookup(
- git_submodule **out, git_repository *repo, const char *path);
+/* Initialize an external submodule cache for the provided repo. */
+extern int git_submodule_cache_init(git_strmap **out, git_repository *repo);
+
+/* Release the resources of the submodule cache. */
+extern int git_submodule_cache_free(git_strmap *cache);
+
+/* Submodule lookup with an explicit cache */
+extern int git_submodule__lookup_with_cache(
+ git_submodule **out, git_repository *repo, const char *path, git_strmap *cache);
/* Internal status fn returns status and optionally the various OIDs */
extern int git_submodule__status(
diff --git a/src/sysdir.c b/src/sysdir.c
index bcef97c03..dcbd48bc3 100644
--- a/src/sysdir.c
+++ b/src/sysdir.c
@@ -7,7 +7,7 @@
#include "sysdir.h"
-#include "global.h"
+#include "runtime.h"
#include "buffer.h"
#include "path.h"
#include <ctype.h>
@@ -45,7 +45,7 @@ static int get_passwd_home(git_buf *out, uid_t uid)
long buflen;
int error;
- assert(out);
+ GIT_ASSERT_ARG(out);
if ((buflen = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1)
buflen = 1024;
@@ -189,9 +189,7 @@ int git_sysdir_global_init(void)
for (i = 0; !error && i < ARRAY_SIZE(git_sysdir__dirs); i++)
error = git_sysdir__dirs[i].guess(&git_sysdir__dirs[i].buf);
- git__on_shutdown(git_sysdir_global_shutdown);
-
- return error;
+ return git_runtime_shutdown_register(git_sysdir_global_shutdown);
}
static int git_sysdir_check_selector(git_sysdir_t which)
@@ -206,7 +204,7 @@ static int git_sysdir_check_selector(git_sysdir_t which)
int git_sysdir_get(const git_buf **out, git_sysdir_t which)
{
- assert(out);
+ GIT_ASSERT_ARG(out);
*out = NULL;
@@ -298,8 +296,11 @@ static int git_sysdir_find_in_dirlist(
}
done:
+ if (name)
+ git_error_set(GIT_ERROR_OS, "the %s file '%s' doesn't exist", label, name);
+ else
+ git_error_set(GIT_ERROR_OS, "the %s directory doesn't exist", label);
git_buf_dispose(path);
- git_error_set(GIT_ERROR_OS, "the %s file '%s' doesn't exist", label, name);
return GIT_ENOTFOUND;
}
diff --git a/src/tag.c b/src/tag.c
index 037dc6664..ee91e5091 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -27,25 +27,25 @@ void git_tag__free(void *_tag)
int git_tag_target(git_object **target, const git_tag *t)
{
- assert(t);
+ GIT_ASSERT_ARG(t);
return git_object_lookup(target, t->object.repo, &t->target, t->type);
}
const git_oid *git_tag_target_id(const git_tag *t)
{
- assert(t);
+ GIT_ASSERT_ARG_WITH_RETVAL(t, NULL);
return &t->target;
}
git_object_t git_tag_target_type(const git_tag *t)
{
- assert(t);
+ GIT_ASSERT_ARG_WITH_RETVAL(t, GIT_OBJECT_INVALID);
return t->type;
}
const char *git_tag_name(const git_tag *t)
{
- assert(t);
+ GIT_ASSERT_ARG_WITH_RETVAL(t, NULL);
return t->tag_name;
}
@@ -56,7 +56,7 @@ const git_signature *git_tag_tagger(const git_tag *t)
const char *git_tag_message(const git_tag *t)
{
- assert(t);
+ GIT_ASSERT_ARG_WITH_RETVAL(t, NULL);
return t->message;
}
@@ -259,8 +259,10 @@ static int git_tag_create__internal(
int error;
- assert(repo && tag_name && target);
- assert(!create_tag_annotation || (tagger && message));
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(tag_name);
+ GIT_ASSERT_ARG(target);
+ GIT_ASSERT_ARG(!create_tag_annotation || (tagger && message));
if (git_object_owner(target) != repo) {
git_error_set(GIT_ERROR_INVALID, "the given target does not belong to this repository");
@@ -313,7 +315,12 @@ int git_tag_annotation_create(
const git_signature *tagger,
const char *message)
{
- assert(oid && repo && tag_name && target && tagger && message);
+ GIT_ASSERT_ARG(oid);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(tag_name);
+ GIT_ASSERT_ARG(target);
+ GIT_ASSERT_ARG(tagger);
+ GIT_ASSERT_ARG(message);
return write_tag_annotation(oid, repo, tag_name, target, tagger, message);
}
@@ -339,7 +346,8 @@ int git_tag_create_from_buffer(git_oid *oid, git_repository *repo, const char *b
git_reference *new_ref = NULL;
git_buf ref_name = GIT_BUF_INIT;
- assert(oid && buffer);
+ GIT_ASSERT_ARG(oid);
+ GIT_ASSERT_ARG(buffer);
memset(&tag, 0, sizeof(tag));
@@ -454,7 +462,8 @@ int git_tag_foreach(git_repository *repo, git_tag_foreach_cb cb, void *cb_data)
{
tag_cb_data data;
- assert(repo && cb);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(cb);
data.cb = cb;
data.cb_data = cb_data;
@@ -493,7 +502,9 @@ int git_tag_list_match(git_strarray *tag_names, const char *pattern, git_reposit
tag_filter_data filter;
git_vector taglist;
- assert(tag_names && repo && pattern);
+ GIT_ASSERT_ARG(tag_names);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(pattern);
if ((error = git_vector_init(&taglist, 8, NULL)) < 0)
return error;
@@ -522,6 +533,31 @@ int git_tag_peel(git_object **tag_target, const git_tag *tag)
return git_object_peel(tag_target, (const git_object *)tag, GIT_OBJECT_ANY);
}
+int git_tag_name_is_valid(int *valid, const char *name)
+{
+ git_buf ref_name = GIT_BUF_INIT;
+ int error = 0;
+
+ GIT_ASSERT(valid);
+
+ /*
+ * Discourage tag name starting with dash,
+ * https://github.com/git/git/commit/4f0accd638b8d2
+ */
+ if (!name || name[0] == '-')
+ goto done;
+
+ if ((error = git_buf_puts(&ref_name, GIT_REFS_TAGS_DIR)) < 0 ||
+ (error = git_buf_puts(&ref_name, name)) < 0)
+ goto done;
+
+ error = git_reference_name_is_valid(valid, ref_name.ptr);
+
+done:
+ git_buf_dispose(&ref_name);
+ return error;
+}
+
/* Deprecated Functions */
#ifndef GIT_DEPRECATE_HARD
diff --git a/src/thread-utils.c b/src/thread-utils.c
deleted file mode 100644
index e5ec6a843..000000000
--- a/src/thread-utils.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "common.h"
-#include "thread-utils.h"
-
-#ifdef _WIN32
-#ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-#endif
-# include <windows.h>
-#elif defined(hpux) || defined(__hpux) || defined(_hpux)
-# include <sys/pstat.h>
-#endif
-
-/*
- * By doing this in two steps we can at least get
- * the function to be somewhat coherent, even
- * with this disgusting nest of #ifdefs.
- */
-#ifndef _SC_NPROCESSORS_ONLN
-# ifdef _SC_NPROC_ONLN
-# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
-# elif defined _SC_CRAY_NCPU
-# define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU
-# endif
-#endif
-
-int git_online_cpus(void)
-{
-#ifdef _SC_NPROCESSORS_ONLN
- long ncpus;
-#endif
-
-#ifdef _WIN32
- SYSTEM_INFO info;
- GetSystemInfo(&info);
-
- if ((int)info.dwNumberOfProcessors > 0)
- return (int)info.dwNumberOfProcessors;
-#elif defined(hpux) || defined(__hpux) || defined(_hpux)
- struct pst_dynamic psd;
-
- if (!pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0))
- return (int)psd.psd_proc_cnt;
-#endif
-
-#ifdef _SC_NPROCESSORS_ONLN
- if ((ncpus = (long)sysconf(_SC_NPROCESSORS_ONLN)) > 0)
- return (int)ncpus;
-#endif
-
- return 1;
-}
diff --git a/src/thread-utils.h b/src/thread-utils.h
deleted file mode 100644
index 035de699f..000000000
--- a/src/thread-utils.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef INCLUDE_thread_utils_h__
-#define INCLUDE_thread_utils_h__
-
-#if defined(__GNUC__) && defined(GIT_THREADS)
-# if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1))
-# error Atomic primitives do not exist on this version of gcc; configure libgit2 with -DTHREADSAFE=OFF
-# endif
-#endif
-
-/* Common operations even if threading has been disabled */
-typedef struct {
-#if defined(GIT_WIN32)
- volatile long val;
-#else
- volatile int val;
-#endif
-} git_atomic;
-
-#ifdef GIT_ARCH_64
-
-typedef struct {
-#if defined(GIT_WIN32)
- __int64 val;
-#else
- int64_t val;
-#endif
-} git_atomic64;
-
-typedef git_atomic64 git_atomic_ssize;
-
-#define git_atomic_ssize_add git_atomic64_add
-
-#else
-
-typedef git_atomic git_atomic_ssize;
-
-#define git_atomic_ssize_add git_atomic_add
-
-#endif
-
-#ifdef GIT_THREADS
-
-#ifdef GIT_WIN32
-# include "win32/thread.h"
-#else
-# include "unix/pthread.h"
-#endif
-
-GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
-{
-#if defined(GIT_WIN32)
- InterlockedExchange(&a->val, (LONG)val);
-#elif defined(__GNUC__)
- __sync_lock_test_and_set(&a->val, val);
-#else
-# error "Unsupported architecture for atomic operations"
-#endif
-}
-
-GIT_INLINE(int) git_atomic_inc(git_atomic *a)
-{
-#if defined(GIT_WIN32)
- return InterlockedIncrement(&a->val);
-#elif defined(__GNUC__)
- return __sync_add_and_fetch(&a->val, 1);
-#else
-# error "Unsupported architecture for atomic operations"
-#endif
-}
-
-GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
-{
-#if defined(GIT_WIN32)
- return InterlockedExchangeAdd(&a->val, addend);
-#elif defined(__GNUC__)
- return __sync_add_and_fetch(&a->val, addend);
-#else
-# error "Unsupported architecture for atomic operations"
-#endif
-}
-
-GIT_INLINE(int) git_atomic_dec(git_atomic *a)
-{
-#if defined(GIT_WIN32)
- return InterlockedDecrement(&a->val);
-#elif defined(__GNUC__)
- return __sync_sub_and_fetch(&a->val, 1);
-#else
-# error "Unsupported architecture for atomic operations"
-#endif
-}
-
-GIT_INLINE(void *) git___compare_and_swap(
- void * volatile *ptr, void *oldval, void *newval)
-{
- volatile void *foundval;
-#if defined(GIT_WIN32)
- foundval = InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval);
-#elif defined(__GNUC__)
- foundval = __sync_val_compare_and_swap(ptr, oldval, newval);
-#else
-# error "Unsupported architecture for atomic operations"
-#endif
- return (foundval == oldval) ? oldval : newval;
-}
-
-GIT_INLINE(volatile void *) git___swap(
- void * volatile *ptr, void *newval)
-{
-#if defined(GIT_WIN32)
- return InterlockedExchangePointer(ptr, newval);
-#else
- return __sync_lock_test_and_set(ptr, newval);
-#endif
-}
-
-#ifdef GIT_ARCH_64
-
-GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
-{
-#if defined(GIT_WIN32)
- return InterlockedExchangeAdd64(&a->val, addend);
-#elif defined(__GNUC__)
- return __sync_add_and_fetch(&a->val, addend);
-#else
-# error "Unsupported architecture for atomic operations"
-#endif
-}
-
-#endif
-
-#else
-
-#define git_thread unsigned int
-#define git_thread_create(thread, start_routine, arg) 0
-#define git_thread_join(id, status) (void)0
-
-/* Pthreads Mutex */
-#define git_mutex unsigned int
-GIT_INLINE(int) git_mutex_init(git_mutex *mutex) \
- { GIT_UNUSED(mutex); return 0; }
-GIT_INLINE(int) git_mutex_lock(git_mutex *mutex) \
- { GIT_UNUSED(mutex); return 0; }
-#define git_mutex_unlock(a) (void)0
-#define git_mutex_free(a) (void)0
-
-/* Pthreads condition vars */
-#define git_cond unsigned int
-#define git_cond_init(c, a) (void)0
-#define git_cond_free(c) (void)0
-#define git_cond_wait(c, l) (void)0
-#define git_cond_signal(c) (void)0
-#define git_cond_broadcast(c) (void)0
-
-/* Pthreads rwlock */
-#define git_rwlock unsigned int
-#define git_rwlock_init(a) 0
-#define git_rwlock_rdlock(a) 0
-#define git_rwlock_rdunlock(a) (void)0
-#define git_rwlock_wrlock(a) 0
-#define git_rwlock_wrunlock(a) (void)0
-#define git_rwlock_free(a) (void)0
-#define GIT_RWLOCK_STATIC_INIT 0
-
-
-GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
-{
- a->val = val;
-}
-
-GIT_INLINE(int) git_atomic_inc(git_atomic *a)
-{
- return ++a->val;
-}
-
-GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
-{
- a->val += addend;
- return a->val;
-}
-
-GIT_INLINE(int) git_atomic_dec(git_atomic *a)
-{
- return --a->val;
-}
-
-GIT_INLINE(void *) git___compare_and_swap(
- void * volatile *ptr, void *oldval, void *newval)
-{
- if (*ptr == oldval)
- *ptr = newval;
- else
- oldval = newval;
- return oldval;
-}
-
-GIT_INLINE(volatile void *) git___swap(
- void * volatile *ptr, void *newval)
-{
- volatile void *old = *ptr;
- *ptr = newval;
- return old;
-}
-
-#ifdef GIT_ARCH_64
-
-GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
-{
- a->val += addend;
- return a->val;
-}
-
-#endif
-
-#endif
-
-GIT_INLINE(int) git_atomic_get(git_atomic *a)
-{
- return (int)a->val;
-}
-
-/* Atomically replace oldval with newval
- * @return oldval if it was replaced or newval if it was not
- */
-#define git__compare_and_swap(P,O,N) \
- git___compare_and_swap((void * volatile *)P, O, N)
-
-#define git__swap(ptr, val) (void *)git___swap((void * volatile *)&ptr, val)
-
-extern int git_online_cpus(void);
-
-#if defined(GIT_THREADS) && defined(_MSC_VER)
-# define GIT_MEMORY_BARRIER MemoryBarrier()
-#elif defined(GIT_THREADS)
-# define GIT_MEMORY_BARRIER __sync_synchronize()
-#else
-# define GIT_MEMORY_BARRIER /* noop */
-#endif
-
-#endif
diff --git a/src/thread.c b/src/thread.c
new file mode 100644
index 000000000..3171771d7
--- /dev/null
+++ b/src/thread.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "common.h"
+
+#if !defined(GIT_THREADS)
+
+#define TLSDATA_MAX 16
+
+typedef struct {
+ void *value;
+ void (GIT_SYSTEM_CALL *destroy_fn)(void *);
+} tlsdata_value;
+
+static tlsdata_value tlsdata_values[TLSDATA_MAX];
+static int tlsdata_cnt = 0;
+
+int git_tlsdata_init(git_tlsdata_key *key, void (GIT_SYSTEM_CALL *destroy_fn)(void *))
+{
+ if (tlsdata_cnt >= TLSDATA_MAX)
+ return -1;
+
+ tlsdata_values[tlsdata_cnt].value = NULL;
+ tlsdata_values[tlsdata_cnt].destroy_fn = destroy_fn;
+
+ *key = tlsdata_cnt;
+ tlsdata_cnt++;
+
+ return 0;
+}
+
+int git_tlsdata_set(git_tlsdata_key key, void *value)
+{
+ if (key < 0 || key > tlsdata_cnt)
+ return -1;
+
+ tlsdata_values[key].value = value;
+ return 0;
+}
+
+void *git_tlsdata_get(git_tlsdata_key key)
+{
+ if (key < 0 || key > tlsdata_cnt)
+ return NULL;
+
+ return tlsdata_values[key].value;
+}
+
+int git_tlsdata_dispose(git_tlsdata_key key)
+{
+ void *value;
+ void (*destroy_fn)(void *) = NULL;
+
+ if (key < 0 || key > tlsdata_cnt)
+ return -1;
+
+ value = tlsdata_values[key].value;
+ destroy_fn = tlsdata_values[key].destroy_fn;
+
+ tlsdata_values[key].value = NULL;
+ tlsdata_values[key].destroy_fn = NULL;
+
+ if (value && destroy_fn)
+ destroy_fn(value);
+
+ return 0;
+}
+
+#elif defined(GIT_WIN32)
+
+int git_tlsdata_init(git_tlsdata_key *key, void (GIT_SYSTEM_CALL *destroy_fn)(void *))
+{
+ DWORD fls_index = FlsAlloc(destroy_fn);
+
+ if (fls_index == FLS_OUT_OF_INDEXES)
+ return -1;
+
+ *key = fls_index;
+ return 0;
+}
+
+int git_tlsdata_set(git_tlsdata_key key, void *value)
+{
+ if (!FlsSetValue(key, value))
+ return -1;
+
+ return 0;
+}
+
+void *git_tlsdata_get(git_tlsdata_key key)
+{
+ return FlsGetValue(key);
+}
+
+int git_tlsdata_dispose(git_tlsdata_key key)
+{
+ if (!FlsFree(key))
+ return -1;
+
+ return 0;
+}
+
+#elif defined(_POSIX_THREADS)
+
+int git_tlsdata_init(git_tlsdata_key *key, void (GIT_SYSTEM_CALL *destroy_fn)(void *))
+{
+ if (pthread_key_create(key, destroy_fn) != 0)
+ return -1;
+
+ return 0;
+}
+
+int git_tlsdata_set(git_tlsdata_key key, void *value)
+{
+ if (pthread_setspecific(key, value) != 0)
+ return -1;
+
+ return 0;
+}
+
+void *git_tlsdata_get(git_tlsdata_key key)
+{
+ return pthread_getspecific(key);
+}
+
+int git_tlsdata_dispose(git_tlsdata_key key)
+{
+ if (pthread_key_delete(key) != 0)
+ return -1;
+
+ return 0;
+}
+
+#else
+# error unknown threading model
+#endif
diff --git a/src/thread.h b/src/thread.h
new file mode 100644
index 000000000..4b091c0a2
--- /dev/null
+++ b/src/thread.h
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_thread_h__
+#define INCLUDE_thread_h__
+
+#if defined(GIT_THREADS)
+
+#if defined(__clang__)
+
+# if (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 1))
+# error Atomic primitives do not exist on this version of clang; configure libgit2 with -DTHREADSAFE=OFF
+# else
+# define GIT_BUILTIN_ATOMIC
+# endif
+
+#elif defined(__GNUC__)
+
+# if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1))
+# error Atomic primitives do not exist on this version of gcc; configure libgit2 with -DTHREADSAFE=OFF
+# elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+# define GIT_BUILTIN_ATOMIC
+# else
+# define GIT_BUILTIN_SYNC
+# endif
+
+#endif
+
+#endif /* GIT_THREADS */
+
+/* Common operations even if threading has been disabled */
+typedef struct {
+#if defined(GIT_WIN32)
+ volatile long val;
+#else
+ volatile int val;
+#endif
+} git_atomic32;
+
+#ifdef GIT_ARCH_64
+
+typedef struct {
+#if defined(GIT_WIN32)
+ volatile __int64 val;
+#else
+ volatile int64_t val;
+#endif
+} git_atomic64;
+
+typedef git_atomic64 git_atomic_ssize;
+
+#define git_atomic_ssize_set git_atomic64_set
+#define git_atomic_ssize_add git_atomic64_add
+#define git_atomic_ssize_get git_atomic64_get
+
+#else
+
+typedef git_atomic32 git_atomic_ssize;
+
+#define git_atomic_ssize_set git_atomic32_set
+#define git_atomic_ssize_add git_atomic32_add
+#define git_atomic_ssize_get git_atomic32_get
+
+#endif
+
+#ifdef GIT_THREADS
+
+#ifdef GIT_WIN32
+# include "win32/thread.h"
+#else
+# include "unix/pthread.h"
+#endif
+
+/*
+ * Atomically sets the contents of *a to be val.
+ */
+GIT_INLINE(void) git_atomic32_set(git_atomic32 *a, int val)
+{
+#if defined(GIT_WIN32)
+ InterlockedExchange(&a->val, (LONG)val);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ __atomic_store_n(&a->val, val, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ __sync_lock_test_and_set(&a->val, val);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+/*
+ * Atomically increments the contents of *a by 1, and stores the result back into *a.
+ * @return the result of the operation.
+ */
+GIT_INLINE(int) git_atomic32_inc(git_atomic32 *a)
+{
+#if defined(GIT_WIN32)
+ return InterlockedIncrement(&a->val);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ return __atomic_add_fetch(&a->val, 1, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ return __sync_add_and_fetch(&a->val, 1);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+/*
+ * Atomically adds the contents of *a and addend, and stores the result back into *a.
+ * @return the result of the operation.
+ */
+GIT_INLINE(int) git_atomic32_add(git_atomic32 *a, int32_t addend)
+{
+#if defined(GIT_WIN32)
+ return InterlockedAdd(&a->val, addend);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ return __atomic_add_fetch(&a->val, addend, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ return __sync_add_and_fetch(&a->val, addend);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+/*
+ * Atomically decrements the contents of *a by 1, and stores the result back into *a.
+ * @return the result of the operation.
+ */
+GIT_INLINE(int) git_atomic32_dec(git_atomic32 *a)
+{
+#if defined(GIT_WIN32)
+ return InterlockedDecrement(&a->val);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ return __atomic_sub_fetch(&a->val, 1, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ return __sync_sub_and_fetch(&a->val, 1);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+/*
+ * Atomically gets the contents of *a.
+ * @return the contents of *a.
+ */
+GIT_INLINE(int) git_atomic32_get(git_atomic32 *a)
+{
+#if defined(GIT_WIN32)
+ return (int)InterlockedCompareExchange(&a->val, 0, 0);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ return __atomic_load_n(&a->val, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ return __sync_val_compare_and_swap(&a->val, 0, 0);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+GIT_INLINE(void *) git_atomic__compare_and_swap(
+ void * volatile *ptr, void *oldval, void *newval)
+{
+#if defined(GIT_WIN32)
+ return InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ void *foundval = oldval;
+ __atomic_compare_exchange(ptr, &foundval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ return foundval;
+#elif defined(GIT_BUILTIN_SYNC)
+ return __sync_val_compare_and_swap(ptr, oldval, newval);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+GIT_INLINE(volatile void *) git_atomic__swap(
+ void * volatile *ptr, void *newval)
+{
+#if defined(GIT_WIN32)
+ return InterlockedExchangePointer(ptr, newval);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ void * volatile foundval = NULL;
+ __atomic_exchange(ptr, &newval, &foundval, __ATOMIC_SEQ_CST);
+ return foundval;
+#elif defined(GIT_BUILTIN_SYNC)
+ return (volatile void *)__sync_lock_test_and_set(ptr, newval);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+GIT_INLINE(volatile void *) git_atomic__load(void * volatile *ptr)
+{
+#if defined(GIT_WIN32)
+ void *newval = NULL, *oldval = NULL;
+ return (volatile void *)InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ return (volatile void *)__atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ return (volatile void *)__sync_val_compare_and_swap(ptr, 0, 0);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+#ifdef GIT_ARCH_64
+
+/*
+ * Atomically adds the contents of *a and addend, and stores the result back into *a.
+ * @return the result of the operation.
+ */
+GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
+{
+#if defined(GIT_WIN32)
+ return InterlockedAdd64(&a->val, addend);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ return __atomic_add_fetch(&a->val, addend, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ return __sync_add_and_fetch(&a->val, addend);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+/*
+ * Atomically sets the contents of *a to be val.
+ */
+GIT_INLINE(void) git_atomic64_set(git_atomic64 *a, int64_t val)
+{
+#if defined(GIT_WIN32)
+ InterlockedExchange64(&a->val, val);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ __atomic_store_n(&a->val, val, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ __sync_lock_test_and_set(&a->val, val);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+/*
+ * Atomically gets the contents of *a.
+ * @return the contents of *a.
+ */
+GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
+{
+#if defined(GIT_WIN32)
+ return (int64_t)InterlockedCompareExchange64(&a->val, 0, 0);
+#elif defined(GIT_BUILTIN_ATOMIC)
+ return __atomic_load_n(&a->val, __ATOMIC_SEQ_CST);
+#elif defined(GIT_BUILTIN_SYNC)
+ return __sync_val_compare_and_swap(&a->val, 0, 0);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+#endif
+
+#else
+
+#define git_threads_global_init git__noop
+
+#define git_thread unsigned int
+#define git_thread_create(thread, start_routine, arg) git__noop()
+#define git_thread_join(id, status) git__noop()
+
+/* Pthreads Mutex */
+#define git_mutex unsigned int
+#define git_mutex_init(a) git__noop()
+#define git_mutex_init(a) git__noop()
+#define git_mutex_lock(a) git__noop()
+#define git_mutex_unlock(a) git__noop()
+#define git_mutex_free(a) git__noop()
+
+/* Pthreads condition vars */
+#define git_cond unsigned int
+#define git_cond_init(c) git__noop()
+#define git_cond_free(c) git__noop()
+#define git_cond_wait(c, l) git__noop()
+#define git_cond_signal(c) git__noop()
+#define git_cond_broadcast(c) git__noop()
+
+/* Pthreads rwlock */
+#define git_rwlock unsigned int
+#define git_rwlock_init(a) git__noop()
+#define git_rwlock_rdlock(a) git__noop()
+#define git_rwlock_rdunlock(a) git__noop()
+#define git_rwlock_wrlock(a) git__noop()
+#define git_rwlock_wrunlock(a) git__noop()
+#define git_rwlock_free(a) git__noop()
+#define GIT_RWLOCK_STATIC_INIT 0
+
+
+GIT_INLINE(void) git_atomic32_set(git_atomic32 *a, int val)
+{
+ a->val = val;
+}
+
+GIT_INLINE(int) git_atomic32_inc(git_atomic32 *a)
+{
+ return ++a->val;
+}
+
+GIT_INLINE(int) git_atomic32_add(git_atomic32 *a, int32_t addend)
+{
+ a->val += addend;
+ return a->val;
+}
+
+GIT_INLINE(int) git_atomic32_dec(git_atomic32 *a)
+{
+ return --a->val;
+}
+
+GIT_INLINE(int) git_atomic32_get(git_atomic32 *a)
+{
+ return (int)a->val;
+}
+
+GIT_INLINE(void *) git_atomic__compare_and_swap(
+ void * volatile *ptr, void *oldval, void *newval)
+{
+ void *foundval = *ptr;
+ if (foundval == oldval)
+ *ptr = newval;
+ return foundval;
+}
+
+GIT_INLINE(volatile void *) git_atomic__swap(
+ void * volatile *ptr, void *newval)
+{
+ volatile void *old = *ptr;
+ *ptr = newval;
+ return old;
+}
+
+GIT_INLINE(volatile void *) git_atomic__load(void * volatile *ptr)
+{
+ return *ptr;
+}
+
+#ifdef GIT_ARCH_64
+
+GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
+{
+ a->val += addend;
+ return a->val;
+}
+
+GIT_INLINE(void) git_atomic64_set(git_atomic64 *a, int64_t val)
+{
+ a->val = val;
+}
+
+GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
+{
+ return (int64_t)a->val;
+}
+
+#endif
+
+#endif
+
+/*
+ * Atomically replace the contents of *ptr (if they are equal to oldval) with
+ * newval. ptr must point to a pointer or a value that is the same size as a
+ * pointer. This is semantically compatible with:
+ *
+ * #define git_atomic_compare_and_swap(ptr, oldval, newval) \
+ * ({ \
+ * void *foundval = *ptr; \
+ * if (foundval == oldval) \
+ * *ptr = newval; \
+ * foundval; \
+ * })
+ *
+ * @return the original contents of *ptr.
+ */
+#define git_atomic_compare_and_swap(ptr, oldval, newval) \
+ git_atomic__compare_and_swap((void * volatile *)ptr, oldval, newval)
+
+/*
+ * Atomically replace the contents of v with newval. v must be the same size as
+ * a pointer. This is semantically compatible with:
+ *
+ * #define git_atomic_swap(v, newval) \
+ * ({ \
+ * volatile void *old = v; \
+ * v = newval; \
+ * old; \
+ * })
+ *
+ * @return the original contents of v.
+ */
+#define git_atomic_swap(v, newval) \
+ (void *)git_atomic__swap((void * volatile *)&(v), newval)
+
+/*
+ * Atomically reads the contents of v. v must be the same size as a pointer.
+ * This is semantically compatible with:
+ *
+ * #define git_atomic_load(v) v
+ *
+ * @return the contents of v.
+ */
+#define git_atomic_load(v) \
+ (void *)git_atomic__load((void * volatile *)&(v))
+
+#if defined(GIT_THREADS)
+
+# if defined(GIT_WIN32)
+# define GIT_MEMORY_BARRIER MemoryBarrier()
+# elif defined(GIT_BUILTIN_ATOMIC)
+# define GIT_MEMORY_BARRIER __atomic_thread_fence(__ATOMIC_SEQ_CST)
+# elif defined(GIT_BUILTIN_SYNC)
+# define GIT_MEMORY_BARRIER __sync_synchronize()
+# endif
+
+#else
+
+# define GIT_MEMORY_BARRIER /* noop */
+
+#endif
+
+/* Thread-local data */
+
+#if !defined(GIT_THREADS)
+# define git_tlsdata_key int
+#elif defined(GIT_WIN32)
+# define git_tlsdata_key DWORD
+#elif defined(_POSIX_THREADS)
+# define git_tlsdata_key pthread_key_t
+#else
+# error unknown threading model
+#endif
+
+/**
+ * Create a thread-local data key. The destroy function will be
+ * called upon thread exit. On some platforms, it may be called
+ * when all threads have deleted their keys.
+ *
+ * Note that the tlsdata functions do not set an error message on
+ * failure; this is because the error handling in libgit2 is itself
+ * handled by thread-local data storage.
+ *
+ * @param key the tlsdata key
+ * @param destroy_fn function pointer called upon thread exit
+ * @return 0 on success, non-zero on failure
+ */
+int git_tlsdata_init(git_tlsdata_key *key, void (GIT_SYSTEM_CALL *destroy_fn)(void *));
+
+/**
+ * Set a the thread-local value for the given key.
+ *
+ * @param key the tlsdata key to store data on
+ * @param value the pointer to store
+ * @return 0 on success, non-zero on failure
+ */
+int git_tlsdata_set(git_tlsdata_key key, void *value);
+
+/**
+ * Get the thread-local value for the given key.
+ *
+ * @param key the tlsdata key to retrieve the value of
+ * @return the pointer stored with git_tlsdata_set
+ */
+void *git_tlsdata_get(git_tlsdata_key key);
+
+/**
+ * Delete the given thread-local key.
+ *
+ * @param key the tlsdata key to dispose
+ * @return 0 on success, non-zero on failure
+ */
+int git_tlsdata_dispose(git_tlsdata_key key);
+
+#endif
diff --git a/src/threadstate.c b/src/threadstate.c
new file mode 100644
index 000000000..e2c08975f
--- /dev/null
+++ b/src/threadstate.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "threadstate.h"
+#include "runtime.h"
+
+/**
+ * Handle the thread-local state
+ *
+ * `git_threadstate_global_init` will be called as part
+ * of `git_libgit2_init` (which itself must be called
+ * before calling any other function in the library).
+ *
+ * This function allocates a TLS index to store the per-
+ * thread state.
+ *
+ * Any internal method that requires thread-local state
+ * will then call `git_threadstate_get()` which returns a
+ * pointer to the thread-local state structure; this
+ * structure is lazily allocated on each thread.
+ *
+ * This mechanism will register a shutdown handler
+ * (`git_threadstate_global_shutdown`) which will free the
+ * TLS index. This shutdown handler will be called by
+ * `git_libgit2_shutdown`.
+ */
+
+static git_tlsdata_key tls_key;
+
+static void threadstate_dispose(git_threadstate *threadstate)
+{
+ if (!threadstate)
+ return;
+
+ if (threadstate->error_t.message != git_buf__initbuf)
+ git__free(threadstate->error_t.message);
+ threadstate->error_t.message = NULL;
+}
+
+static void GIT_SYSTEM_CALL threadstate_free(void *threadstate)
+{
+ threadstate_dispose(threadstate);
+ git__free(threadstate);
+}
+
+static void git_threadstate_global_shutdown(void)
+{
+ git_threadstate *threadstate;
+
+ threadstate = git_tlsdata_get(tls_key);
+ git_tlsdata_set(tls_key, NULL);
+
+ threadstate_dispose(threadstate);
+ git__free(threadstate);
+
+ git_tlsdata_dispose(tls_key);
+}
+
+int git_threadstate_global_init(void)
+{
+ if (git_tlsdata_init(&tls_key, &threadstate_free) != 0)
+ return -1;
+
+ return git_runtime_shutdown_register(git_threadstate_global_shutdown);
+}
+
+git_threadstate *git_threadstate_get(void)
+{
+ git_threadstate *threadstate;
+
+ if ((threadstate = git_tlsdata_get(tls_key)) != NULL)
+ return threadstate;
+
+ if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
+ git_buf_init(&threadstate->error_buf, 0) < 0)
+ return NULL;
+
+ git_tlsdata_set(tls_key, threadstate);
+ return threadstate;
+}
diff --git a/src/threadstate.h b/src/threadstate.h
new file mode 100644
index 000000000..51810a939
--- /dev/null
+++ b/src/threadstate.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_threadstate_h__
+#define INCLUDE_threadstate_h__
+
+#include "common.h"
+
+typedef struct {
+ git_error *last_error;
+ git_error error_t;
+ git_buf error_buf;
+ char oid_fmt[GIT_OID_HEXSZ+1];
+} git_threadstate;
+
+extern int git_threadstate_global_init(void);
+extern git_threadstate *git_threadstate_get(void);
+
+#define GIT_THREADSTATE (git_threadstate_get())
+
+#endif
diff --git a/src/trace.c b/src/trace.c
index ec6a90aad..efc7b01a2 100644
--- a/src/trace.c
+++ b/src/trace.c
@@ -8,7 +8,7 @@
#include "trace.h"
#include "buffer.h"
-#include "global.h"
+#include "runtime.h"
#include "git2/trace.h"
#ifdef GIT_TRACE
@@ -20,7 +20,7 @@ struct git_trace_data git_trace__data = {0};
int git_trace_set(git_trace_level_t level, git_trace_cb callback)
{
#ifdef GIT_TRACE
- assert(level == 0 || callback != NULL);
+ GIT_ASSERT_ARG(level == 0 || callback != NULL);
git_trace__data.level = level;
git_trace__data.callback = callback;
diff --git a/src/trace.h b/src/trace.h
index e15118ef5..a233aa225 100644
--- a/src/trace.h
+++ b/src/trace.h
@@ -23,28 +23,32 @@ extern struct git_trace_data git_trace__data;
GIT_INLINE(void) git_trace__write_fmt(
git_trace_level_t level,
- const char *fmt, ...)
+ const char *fmt,
+ va_list ap)
{
git_trace_cb callback = git_trace__data.callback;
git_buf message = GIT_BUF_INIT;
- va_list ap;
- va_start(ap, fmt);
git_buf_vprintf(&message, fmt, ap);
- va_end(ap);
callback(level, git_buf_cstr(&message));
git_buf_dispose(&message);
}
-#define git_trace_level() (git_trace__data.level)
-#define git_trace(l, ...) { \
- if (git_trace__data.level >= l && \
- git_trace__data.callback != NULL) { \
- git_trace__write_fmt(l, __VA_ARGS__); \
- } \
- }
+#define git_trace_level() (git_trace__data.level)
+
+GIT_INLINE(void) git_trace(git_trace_level_t level, const char *fmt, ...)
+{
+ if (git_trace__data.level >= level &&
+ git_trace__data.callback != NULL) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ git_trace__write_fmt(level, fmt, ap);
+ va_end(ap);
+ }
+}
#else
@@ -56,8 +60,8 @@ GIT_INLINE(void) git_trace__null(
GIT_UNUSED(fmt);
}
-#define git_trace_level() ((git_trace_level_t)0)
-#define git_trace git_trace__null
+#define git_trace_level() ((git_trace_level_t)0)
+#define git_trace git_trace__null
#endif
diff --git a/src/trailer.c b/src/trailer.c
index ca81fd020..61cdd1ba1 100644
--- a/src/trailer.c
+++ b/src/trailer.c
@@ -258,7 +258,7 @@ static size_t find_trailer_end(const char *buf, size_t len)
return len - ignore_non_trailer(buf, len);
}
-static char *extract_trailer_block(const char *message, size_t* len)
+static char *extract_trailer_block(const char *message, size_t *len)
{
size_t patch_start = find_patch_start(message);
size_t trailer_end = find_trailer_end(message, patch_start);
diff --git a/src/transaction.c b/src/transaction.c
index 81af8d831..98fa1ba90 100644
--- a/src/transaction.c
+++ b/src/transaction.c
@@ -57,7 +57,9 @@ struct git_transaction {
int git_transaction_config_new(git_transaction **out, git_config *cfg)
{
git_transaction *tx;
- assert(out && cfg);
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(cfg);
tx = git__calloc(1, sizeof(git_transaction));
GIT_ERROR_CHECK_ALLOC(tx);
@@ -74,7 +76,8 @@ int git_transaction_new(git_transaction **out, git_repository *repo)
git_pool pool;
git_transaction *tx = NULL;
- assert(out && repo);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
if ((error = git_pool_init(&pool, 1)) < 0)
goto on_error;
@@ -109,7 +112,8 @@ int git_transaction_lock_ref(git_transaction *tx, const char *refname)
int error;
transaction_node *node;
- assert(tx && refname);
+ GIT_ASSERT_ARG(tx);
+ GIT_ASSERT_ARG(refname);
node = git_pool_mallocz(&tx->pool, sizeof(transaction_node));
GIT_ERROR_CHECK_ALLOC(node);
@@ -176,7 +180,9 @@ int git_transaction_set_target(git_transaction *tx, const char *refname, const g
int error;
transaction_node *node;
- assert(tx && refname && target);
+ GIT_ASSERT_ARG(tx);
+ GIT_ASSERT_ARG(refname);
+ GIT_ASSERT_ARG(target);
if ((error = find_locked(&node, tx, refname)) < 0)
return error;
@@ -195,7 +201,9 @@ int git_transaction_set_symbolic_target(git_transaction *tx, const char *refname
int error;
transaction_node *node;
- assert(tx && refname && target);
+ GIT_ASSERT_ARG(tx);
+ GIT_ASSERT_ARG(refname);
+ GIT_ASSERT_ARG(target);
if ((error = find_locked(&node, tx, refname)) < 0)
return error;
@@ -272,7 +280,9 @@ int git_transaction_set_reflog(git_transaction *tx, const char *refname, const g
int error;
transaction_node *node;
- assert(tx && refname && reflog);
+ GIT_ASSERT_ARG(tx);
+ GIT_ASSERT_ARG(refname);
+ GIT_ASSERT_ARG(reflog);
if ((error = find_locked(&node, tx, refname)) < 0)
return error;
@@ -320,7 +330,7 @@ int git_transaction_commit(git_transaction *tx)
transaction_node *node;
int error = 0;
- assert(tx);
+ GIT_ASSERT_ARG(tx);
if (tx->type == TRANSACTION_CONFIG) {
error = git_config_unlock(tx->cfg, true);
@@ -355,7 +365,8 @@ void git_transaction_free(git_transaction *tx)
transaction_node *node;
git_pool pool;
- assert(tx);
+ if (!tx)
+ return;
if (tx->type == TRANSACTION_CONFIG) {
if (tx->cfg) {
diff --git a/src/transport.c b/src/transport.c
index 227ee7dee..e128aa6c7 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -148,8 +148,8 @@ int git_transport_register(
size_t i;
int error = 0;
- assert(scheme);
- assert(cb);
+ GIT_ASSERT_ARG(scheme);
+ GIT_ASSERT_ARG(cb);
if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
goto on_error;
@@ -186,7 +186,7 @@ int git_transport_unregister(const char *scheme)
size_t i;
int error = 0;
- assert(scheme);
+ GIT_ASSERT_ARG(scheme);
if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
goto done;
diff --git a/src/transports/auth.c b/src/transports/auth.c
index 4aa3df021..51763e359 100644
--- a/src/transports/auth.c
+++ b/src/transports/auth.c
@@ -18,7 +18,7 @@ static int basic_next_token(
{
git_credential_userpass_plaintext *cred;
git_buf raw = GIT_BUF_INIT;
- int error = -1;
+ int error = GIT_EAUTH;
GIT_UNUSED(ctx);
diff --git a/src/transports/auth_negotiate.c b/src/transports/auth_negotiate.c
index 8a614b81a..31469933e 100644
--- a/src/transports/auth_negotiate.c
+++ b/src/transports/auth_negotiate.c
@@ -65,7 +65,9 @@ static int negotiate_set_challenge(
{
http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
- assert(ctx && ctx->configured && challenge);
+ GIT_ASSERT_ARG(ctx);
+ GIT_ASSERT_ARG(challenge);
+ GIT_ASSERT(ctx->configured);
git__free(ctx->challenge);
@@ -108,7 +110,12 @@ static int negotiate_next_token(
size_t challenge_len;
int error = 0;
- assert(buf && ctx && ctx->configured && cred && cred->credtype == GIT_CREDENTIAL_DEFAULT);
+ GIT_ASSERT_ARG(buf);
+ GIT_ASSERT_ARG(ctx);
+ GIT_ASSERT_ARG(cred);
+
+ GIT_ASSERT(ctx->configured);
+ GIT_ASSERT(cred->credtype == GIT_CREDENTIAL_DEFAULT);
if (ctx->complete)
return 0;
@@ -202,7 +209,7 @@ static int negotiate_is_complete(git_http_auth_context *c)
{
http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
return (ctx->complete == 1);
}
@@ -260,7 +267,7 @@ static int negotiate_init_context(
if (!ctx->oid) {
git_error_set(GIT_ERROR_NET, "negotiate authentication is not supported");
- return -1;
+ return GIT_EAUTH;
}
git_buf_puts(&ctx->target, "HTTP@");
diff --git a/src/transports/auth_ntlm.c b/src/transports/auth_ntlm.c
index d134a3db6..742db75b3 100644
--- a/src/transports/auth_ntlm.c
+++ b/src/transports/auth_ntlm.c
@@ -14,7 +14,7 @@
#ifdef GIT_NTLM
-#include "ntlm.h"
+#include "ntlmclient.h"
typedef struct {
git_http_auth_context parent;
@@ -29,7 +29,8 @@ static int ntlm_set_challenge(
{
http_auth_ntlm_context *ctx = (http_auth_ntlm_context *)c;
- assert(ctx && challenge);
+ GIT_ASSERT_ARG(ctx);
+ GIT_ASSERT_ARG(challenge);
git__free(ctx->challenge);
@@ -46,7 +47,7 @@ static int ntlm_set_credentials(http_auth_ntlm_context *ctx, git_credential *_cr
char *domain = NULL, *domainuser = NULL;
int error = 0;
- assert(_cred->credtype == GIT_CREDENTIAL_USERPASS_PLAINTEXT);
+ GIT_ASSERT(_cred->credtype == GIT_CREDENTIAL_USERPASS_PLAINTEXT);
cred = (git_credential_userpass_plaintext *)_cred;
if ((sep = strchr(cred->username, '\\')) != NULL) {
@@ -84,9 +85,12 @@ static int ntlm_next_token(
git_buf input_buf = GIT_BUF_INIT;
const unsigned char *msg;
size_t challenge_len, msg_len;
- int error = -1;
+ int error = GIT_EAUTH;
- assert(buf && ctx && ctx->ntlm);
+ GIT_ASSERT_ARG(buf);
+ GIT_ASSERT_ARG(ctx);
+
+ GIT_ASSERT(ctx->ntlm);
challenge_len = ctx->challenge ? strlen(ctx->challenge) : 0;
@@ -162,7 +166,7 @@ static int ntlm_is_complete(git_http_auth_context *c)
{
http_auth_ntlm_context *ctx = (http_auth_ntlm_context *)c;
- assert(ctx);
+ GIT_ASSERT_ARG(ctx);
return (ctx->complete == true);
}
diff --git a/src/transports/credential.c b/src/transports/credential.c
index 7b2836445..6e00b0282 100644
--- a/src/transports/credential.c
+++ b/src/transports/credential.c
@@ -85,7 +85,9 @@ int git_credential_userpass_plaintext_new(
{
git_credential_userpass_plaintext *c;
- assert(cred && username && password);
+ GIT_ASSERT_ARG(cred);
+ GIT_ASSERT_ARG(username);
+ GIT_ASSERT_ARG(password);
c = git__malloc(sizeof(git_credential_userpass_plaintext));
GIT_ERROR_CHECK_ALLOC(c);
@@ -233,7 +235,9 @@ static int git_credential_ssh_key_type_new(
{
git_credential_ssh_key *c;
- assert(username && cred && privatekey);
+ GIT_ASSERT_ARG(username);
+ GIT_ASSERT_ARG(cred);
+ GIT_ASSERT_ARG(privatekey);
c = git__calloc(1, sizeof(git_credential_ssh_key));
GIT_ERROR_CHECK_ALLOC(c);
@@ -269,7 +273,9 @@ int git_credential_ssh_interactive_new(
{
git_credential_ssh_interactive *c;
- assert(out && username && prompt_callback);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(username);
+ GIT_ASSERT_ARG(prompt_callback);
c = git__calloc(1, sizeof(git_credential_ssh_interactive));
GIT_ERROR_CHECK_ALLOC(c);
@@ -290,7 +296,8 @@ int git_credential_ssh_interactive_new(
int git_credential_ssh_key_from_agent(git_credential **cred, const char *username) {
git_credential_ssh_key *c;
- assert(username && cred);
+ GIT_ASSERT_ARG(username);
+ GIT_ASSERT_ARG(cred);
c = git__calloc(1, sizeof(git_credential_ssh_key));
GIT_ERROR_CHECK_ALLOC(c);
@@ -317,7 +324,8 @@ int git_credential_ssh_custom_new(
{
git_credential_ssh_custom *c;
- assert(username && cred);
+ GIT_ASSERT_ARG(username);
+ GIT_ASSERT_ARG(cred);
c = git__calloc(1, sizeof(git_credential_ssh_custom));
GIT_ERROR_CHECK_ALLOC(c);
@@ -347,7 +355,7 @@ int git_credential_default_new(git_credential **cred)
{
git_credential_default *c;
- assert(cred);
+ GIT_ASSERT_ARG(cred);
c = git__calloc(1, sizeof(git_credential_default));
GIT_ERROR_CHECK_ALLOC(c);
@@ -364,7 +372,7 @@ int git_credential_username_new(git_credential **cred, const char *username)
git_credential_username *c;
size_t len, allocsize;
- assert(cred);
+ GIT_ASSERT_ARG(cred);
len = strlen(username);
diff --git a/src/transports/git.c b/src/transports/git.c
index e48b7f961..7c93155a8 100644
--- a/src/transports/git.c
+++ b/src/transports/git.c
@@ -327,7 +327,7 @@ static int _git_close(git_smart_subtransport *subtransport)
{
git_subtransport *t = (git_subtransport *) subtransport;
- assert(!t->current_stream);
+ GIT_ASSERT(!t->current_stream);
GIT_UNUSED(t);
@@ -338,8 +338,6 @@ static void _git_free(git_smart_subtransport *subtransport)
{
git_subtransport *t = (git_subtransport *) subtransport;
- assert(!t->current_stream);
-
git__free(t);
}
diff --git a/src/transports/http.c b/src/transports/http.c
index 66731b0ce..914335aba 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -14,7 +14,6 @@
#include "buffer.h"
#include "net.h"
#include "netops.h"
-#include "global.h"
#include "remote.h"
#include "git2/sys/credential.h"
#include "smart.h"
@@ -105,6 +104,11 @@ static int apply_url_credentials(
const char *username,
const char *password)
{
+ GIT_ASSERT_ARG(username);
+
+ if (!password)
+ password = "";
+
if (allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT)
return git_credential_userpass_plaintext_new(cred, username, password);
@@ -139,8 +143,7 @@ static int handle_auth(
/* Start with URL-specified credentials, if there were any. */
if ((allowed_credtypes & GIT_CREDENTIAL_USERPASS_PLAINTEXT) &&
!server->url_cred_presented &&
- server->url.username &&
- server->url.password) {
+ server->url.username) {
error = apply_url_credentials(&server->cred, allowed_credtypes, server->url.username, server->url.password);
server->url_cred_presented = 1;
@@ -159,7 +162,7 @@ static int handle_auth(
if (error > 0) {
git_error_set(GIT_ERROR_HTTP, "%s authentication required but no callback set", server_type);
- error = -1;
+ error = GIT_EAUTH;
}
if (!error)
@@ -176,7 +179,7 @@ GIT_INLINE(int) handle_remote_auth(
if (response->server_auth_credtypes == 0) {
git_error_set(GIT_ERROR_HTTP, "server requires authentication that we do not support");
- return -1;
+ return GIT_EAUTH;
}
/* Otherwise, prompt for credentials. */
@@ -198,7 +201,7 @@ GIT_INLINE(int) handle_proxy_auth(
if (response->proxy_auth_credtypes == 0) {
git_error_set(GIT_ERROR_HTTP, "proxy requires authentication that we do not support");
- return -1;
+ return GIT_EAUTH;
}
/* Otherwise, prompt for credentials. */
@@ -256,7 +259,7 @@ static int handle_response(
} else if (response->status == GIT_HTTP_STATUS_UNAUTHORIZED ||
response->status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
git_error_set(GIT_ERROR_HTTP, "unexpected authentication failure");
- return -1;
+ return GIT_EAUTH;
}
if (response->status != GIT_HTTP_STATUS_OK) {
@@ -287,7 +290,6 @@ static int lookup_proxy(
{
const char *proxy;
git_remote *remote;
- bool use_ssl;
char *config = NULL;
int error = 0;
@@ -301,9 +303,8 @@ static int lookup_proxy(
case GIT_PROXY_AUTO:
remote = transport->owner->owner;
- use_ssl = !strcmp(transport->server.url.scheme, "https");
- error = git_remote__get_http_proxy(remote, use_ssl, &config);
+ error = git_remote__http_proxy(&config, remote, &transport->server.url);
if (error || !config)
goto done;
@@ -413,11 +414,11 @@ static int http_stream_read(
if (stream->state == HTTP_STATE_SENDING_REQUEST) {
git_error_set(GIT_ERROR_HTTP, "too many redirects or authentication replays");
- error = -1;
+ error = GIT_ERROR; /* not GIT_EAUTH, because the exact cause is unclear */
goto done;
}
- assert (stream->state == HTTP_STATE_RECEIVING_RESPONSE);
+ GIT_ASSERT(stream->state == HTTP_STATE_RECEIVING_RESPONSE);
error = git_http_client_read_body(transport->http_client, buffer, buffer_size);
@@ -551,11 +552,11 @@ static int http_stream_write(
if (stream->state == HTTP_STATE_NONE) {
git_error_set(GIT_ERROR_HTTP,
"too many redirects or authentication replays");
- error = -1;
+ error = GIT_ERROR; /* not GIT_EAUTH because the exact cause is unclear */
goto done;
}
- assert(stream->state == HTTP_STATE_SENDING_REQUEST);
+ GIT_ASSERT(stream->state == HTTP_STATE_SENDING_REQUEST);
error = git_http_client_send_body(transport->http_client, buffer, len);
@@ -589,7 +590,7 @@ static int http_stream_read_response(
(error = handle_response(&complete, stream, &response, false)) < 0)
goto done;
- assert(complete);
+ GIT_ASSERT(complete);
stream->state = HTTP_STATE_RECEIVING_RESPONSE;
}
@@ -638,7 +639,8 @@ static int http_action(
const http_service *service;
int error;
- assert(out && t);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(t);
*out = NULL;
@@ -721,7 +723,7 @@ int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *own
GIT_UNUSED(param);
- assert(out);
+ GIT_ASSERT_ARG(out);
transport = git__calloc(sizeof(http_subtransport), 1);
GIT_ERROR_CHECK_ALLOC(transport);
diff --git a/src/transports/http.h b/src/transports/http.h
index c02109cec..5c360b883 100644
--- a/src/transports/http.h
+++ b/src/transports/http.h
@@ -9,6 +9,7 @@
#define INCLUDE_transports_http_h__
#include "buffer.h"
+#include "settings.h"
#include "httpclient.h"
#define GIT_HTTP_REPLAY_MAX 15
diff --git a/src/transports/httpclient.c b/src/transports/httpclient.c
index dda267833..5b8949a04 100644
--- a/src/transports/httpclient.c
+++ b/src/transports/httpclient.c
@@ -10,7 +10,6 @@
#include "http_parser.h"
#include "vector.h"
#include "trace.h"
-#include "global.h"
#include "httpclient.h"
#include "http.h"
#include "auth.h"
@@ -146,7 +145,8 @@ bool git_http_response_is_redirect(git_http_response *response)
void git_http_response_dispose(git_http_response *response)
{
- assert(response);
+ if (!response)
+ return;
git__free(response->content_type);
git__free(response->location);
@@ -400,7 +400,7 @@ static int on_body(http_parser *parser, const char *buf, size_t len)
return 0;
}
- assert(ctx->output_size >= ctx->output_written);
+ GIT_ASSERT(ctx->output_size >= ctx->output_written);
max_len = min(ctx->output_size - ctx->output_written, len);
max_len = min(max_len, INT_MAX);
@@ -597,7 +597,7 @@ static int apply_credentials(
free_auth_context(server);
} else if (!token.size) {
git_error_set(GIT_ERROR_HTTP, "failed to respond to authentication challenge");
- error = -1;
+ error = GIT_EAUTH;
goto done;
}
@@ -631,6 +631,26 @@ GIT_INLINE(int) apply_proxy_credentials(
request->proxy_credentials);
}
+static int puts_host_and_port(git_buf *buf, git_net_url *url, bool force_port)
+{
+ bool ipv6 = git_net_url_is_ipv6(url);
+
+ if (ipv6)
+ git_buf_putc(buf, '[');
+
+ git_buf_puts(buf, url->host);
+
+ if (ipv6)
+ git_buf_putc(buf, ']');
+
+ if (force_port || !git_net_url_is_default_port(url)) {
+ git_buf_putc(buf, ':');
+ git_buf_puts(buf, url->port);
+ }
+
+ return git_buf_oom(buf) ? -1 : 0;
+}
+
static int generate_connect_request(
git_http_client *client,
git_http_request *request)
@@ -641,14 +661,17 @@ static int generate_connect_request(
git_buf_clear(&client->request_msg);
buf = &client->request_msg;
- git_buf_printf(buf, "CONNECT %s:%s HTTP/1.1\r\n",
- client->server.url.host, client->server.url.port);
+ git_buf_puts(buf, "CONNECT ");
+ puts_host_and_port(buf, &client->server.url, true);
+ git_buf_puts(buf, " HTTP/1.1\r\n");
git_buf_puts(buf, "User-Agent: ");
git_http__user_agent(buf);
git_buf_puts(buf, "\r\n");
- git_buf_printf(buf, "Host: %s\r\n", client->proxy.url.host);
+ git_buf_puts(buf, "Host: ");
+ puts_host_and_port(buf, &client->server.url, true);
+ git_buf_puts(buf, "\r\n");
if ((error = apply_proxy_credentials(buf, client, request) < 0))
return -1;
@@ -658,6 +681,11 @@ static int generate_connect_request(
return git_buf_oom(buf) ? -1 : 0;
}
+static bool use_connect_proxy(git_http_client *client)
+{
+ return client->proxy.url.host && !strcmp(client->server.url.scheme, "https");
+}
+
static int generate_request(
git_http_client *client,
git_http_request *request)
@@ -666,7 +694,8 @@ static int generate_request(
size_t i;
int error;
- assert(client && request);
+ GIT_ASSERT_ARG(client);
+ GIT_ASSERT_ARG(request);
git_buf_clear(&client->request_msg);
buf = &client->request_msg;
@@ -686,11 +715,8 @@ static int generate_request(
git_http__user_agent(buf);
git_buf_puts(buf, "\r\n");
- git_buf_printf(buf, "Host: %s", request->url->host);
-
- if (!git_net_url_is_default_port(request->url))
- git_buf_printf(buf, ":%s", request->url->port);
-
+ git_buf_puts(buf, "Host: ");
+ puts_host_and_port(buf, request->url, false);
git_buf_puts(buf, "\r\n");
if (request->accept)
@@ -713,7 +739,8 @@ static int generate_request(
git_buf_printf(buf, "Expect: 100-continue\r\n");
if ((error = apply_server_credentials(buf, client, request)) < 0 ||
- (error = apply_proxy_credentials(buf, client, request)) < 0)
+ (!use_connect_proxy(client) &&
+ (error = apply_proxy_credentials(buf, client, request)) < 0))
return error;
if (request->custom_headers) {
@@ -843,7 +870,10 @@ static int setup_hosts(
{
int ret, diff = 0;
- assert(client && request && request->url);
+ GIT_ASSERT_ARG(client);
+ GIT_ASSERT_ARG(request);
+
+ GIT_ASSERT(request->url);
if ((ret = server_setup_from_url(&client->server, request->url)) < 0)
return ret;
@@ -898,7 +928,7 @@ static int proxy_connect(
int error;
if (!client->proxy_connected || !client->keepalive) {
- git_trace(GIT_TRACE_DEBUG, "Connecting to proxy %s:%s",
+ git_trace(GIT_TRACE_DEBUG, "Connecting to proxy %s port %s",
client->proxy.url.host, client->proxy.url.port);
if ((error = server_create_stream(&client->proxy)) < 0 ||
@@ -923,7 +953,7 @@ static int proxy_connect(
(error = git_http_client_skip_body(client)) < 0)
goto done;
- assert(client->state == DONE);
+ GIT_ASSERT(client->state == DONE);
if (response.status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
save_early_response(client, &response);
@@ -1003,8 +1033,7 @@ static int http_client_connect(
reset_parser(client);
/* Reconnect to the proxy if necessary. */
- use_proxy = client->proxy.url.host &&
- !strcmp(client->server.url.scheme, "https");
+ use_proxy = use_connect_proxy(client);
if (use_proxy) {
if (!client->proxy_connected || !client->keepalive ||
@@ -1019,7 +1048,7 @@ static int http_client_connect(
goto on_error;
}
- git_trace(GIT_TRACE_DEBUG, "Connecting to remote %s:%s",
+ git_trace(GIT_TRACE_DEBUG, "Connecting to remote %s port %s",
client->server.url.host, client->server.url.port);
if ((error = server_connect(client)) < 0)
@@ -1120,11 +1149,6 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
return -1;
}
- if (parser->upgrade) {
- git_error_set(GIT_ERROR_HTTP, "server requested upgrade");
- return -1;
- }
-
if (ctx->parse_status == PARSE_STATUS_ERROR) {
client->connected = 0;
return ctx->error ? ctx->error : -1;
@@ -1143,7 +1167,7 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
* final byte when paused in a callback. Consume that byte.
* https://github.com/nodejs/http-parser/issues/97
*/
- assert(client->read_buf.size > parsed_len);
+ GIT_ASSERT(client->read_buf.size > parsed_len);
http_parser_pause(parser, 0);
@@ -1221,7 +1245,8 @@ int git_http_client_send_request(
git_http_response response = {0};
int error = -1;
- assert(client && request);
+ GIT_ASSERT_ARG(client);
+ GIT_ASSERT_ARG(request);
/* If the client did not finish reading, clean up the stream. */
if (client->state == READING_BODY)
@@ -1292,7 +1317,7 @@ int git_http_client_send_body(
git_buf hdr = GIT_BUF_INIT;
int error;
- assert(client);
+ GIT_ASSERT_ARG(client);
/* If we're waiting for proxy auth, don't sending more requests. */
if (client->state == HAS_EARLY_RESPONSE)
@@ -1309,7 +1334,7 @@ int git_http_client_send_body(
server = &client->server;
if (client->request_body_len) {
- assert(buffer_len <= client->request_body_remain);
+ GIT_ASSERT(buffer_len <= client->request_body_remain);
if ((error = stream_write(server, buffer, buffer_len)) < 0)
goto done;
@@ -1332,7 +1357,8 @@ static int complete_request(git_http_client *client)
{
int error = 0;
- assert(client && client->state == SENDING_BODY);
+ GIT_ASSERT_ARG(client);
+ GIT_ASSERT(client->state == SENDING_BODY);
if (client->request_body_len && client->request_body_remain) {
git_error_set(GIT_ERROR_HTTP, "truncated write");
@@ -1352,7 +1378,8 @@ int git_http_client_read_response(
http_parser_context parser_context = {0};
int error;
- assert(response && client);
+ GIT_ASSERT_ARG(response);
+ GIT_ASSERT_ARG(client);
if (client->state == SENDING_BODY) {
if ((error = complete_request(client)) < 0)
@@ -1374,8 +1401,11 @@ int git_http_client_read_response(
git_http_response_dispose(response);
- git_vector_free_deep(&client->server.auth_challenges);
- git_vector_free_deep(&client->proxy.auth_challenges);
+ if (client->current_server == PROXY) {
+ git_vector_free_deep(&client->proxy.auth_challenges);
+ } else if(client->current_server == SERVER) {
+ git_vector_free_deep(&client->server.auth_challenges);
+ }
client->state = READING_RESPONSE;
client->keepalive = 0;
@@ -1389,7 +1419,7 @@ int git_http_client_read_response(
goto done;
}
- assert(client->state == READING_BODY || client->state == DONE);
+ GIT_ASSERT(client->state == READING_BODY || client->state == DONE);
done:
git_buf_dispose(&parser_context.parse_header_name);
@@ -1442,7 +1472,7 @@ int git_http_client_read_body(
break;
}
- assert(parser_context.output_written <= INT_MAX);
+ GIT_ASSERT(parser_context.output_written <= INT_MAX);
error = (int)parser_context.output_written;
done:
@@ -1478,7 +1508,7 @@ int git_http_client_skip_body(git_http_client *client)
"unexpected data handled in callback");
error = -1;
}
- } while (!error);
+ } while (error >= 0 && client->state != DONE);
if (error < 0)
client->connected = 0;
@@ -1496,7 +1526,7 @@ int git_http_client_new(
{
git_http_client *client;
- assert(out);
+ GIT_ASSERT_ARG(out);
client = git__calloc(1, sizeof(git_http_client));
GIT_ERROR_CHECK_ALLOC(client);
diff --git a/src/transports/httpclient.h b/src/transports/httpclient.h
index 2a83bee3e..6d0ef9edb 100644
--- a/src/transports/httpclient.h
+++ b/src/transports/httpclient.h
@@ -90,7 +90,7 @@ extern int git_http_client_new(
/*
* Sends a request to the host specified by the request URL. If the
- * method is POST, either the the content_length or the chunked flag must
+ * method is POST, either the content_length or the chunked flag must
* be specified. The body should be provided in subsequent calls to
* git_http_client_send_body.
*
diff --git a/src/transports/local.c b/src/transports/local.c
index 210de9f74..bb31b1345 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -36,7 +36,7 @@ typedef struct {
char *url;
int direction;
int flags;
- git_atomic cancelled;
+ git_atomic32 cancelled;
git_repository *repo;
git_transport_message_cb progress_cb;
git_transport_message_cb error_cb;
@@ -158,7 +158,7 @@ static int store_refs(transport_local *t)
git_remote_head *head;
git_strarray ref_names = {0};
- assert(t);
+ GIT_ASSERT_ARG(t);
if (git_reference_list(&ref_names, t->repo) < 0)
goto on_error;
@@ -671,7 +671,7 @@ static void local_cancel(git_transport *transport)
{
transport_local *t = (transport_local *)transport;
- git_atomic_set(&t->cancelled, 1);
+ git_atomic32_set(&t->cancelled, 1);
}
static int local_close(git_transport *transport)
diff --git a/src/transports/smart.c b/src/transports/smart.c
index 5f5919407..587f14358 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -18,7 +18,7 @@ static int git_smart__recv_cb(gitno_buffer *buf)
size_t old_len, bytes_read;
int error;
- assert(t->current_stream);
+ GIT_ASSERT(t->current_stream);
old_len = buf->offset;
@@ -30,7 +30,7 @@ static int git_smart__recv_cb(gitno_buffer *buf)
if (t->packetsize_cb && !t->cancelled.val) {
error = t->packetsize_cb(bytes_read, t->packetsize_payload);
if (error) {
- git_atomic_set(&t->cancelled, 1);
+ git_atomic32_set(&t->cancelled, 1);
return GIT_EUSER;
}
}
@@ -226,6 +226,8 @@ static int git_smart__connect(
t->url = git__strdup(url);
GIT_ERROR_CHECK_ALLOC(t->url);
+ git_proxy_options_clear(&t->proxy);
+
if (git_proxy_options_dup(&t->proxy, proxy) < 0)
return -1;
@@ -346,7 +348,7 @@ int git_smart__negotiation_step(git_transport *transport, void *data, size_t len
return error;
/* If this is a stateful implementation, the stream we get back should be the same */
- assert(t->rpc || t->current_stream == stream);
+ GIT_ASSERT(t->rpc || t->current_stream == stream);
/* Save off the current stream (i.e. socket) that we are working with */
t->current_stream = stream;
@@ -375,7 +377,7 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream
return error;
/* If this is a stateful implementation, the stream we get back should be the same */
- assert(t->rpc || t->current_stream == *stream);
+ GIT_ASSERT(t->rpc || t->current_stream == *stream);
/* Save off the current stream (i.e. socket) that we are working with */
t->current_stream = *stream;
@@ -389,7 +391,7 @@ static void git_smart__cancel(git_transport *transport)
{
transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
- git_atomic_set(&t->cancelled, 1);
+ git_atomic32_set(&t->cancelled, 1);
}
static int git_smart__is_connected(git_transport *transport)
@@ -481,7 +483,9 @@ int git_transport_smart_certificate_check(git_transport *transport, git_cert *ce
{
transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
- assert(transport && cert && hostname);
+ GIT_ASSERT_ARG(transport);
+ GIT_ASSERT_ARG(cert);
+ GIT_ASSERT_ARG(hostname);
if (!t->certificate_check_cb)
return GIT_PASSTHROUGH;
@@ -493,7 +497,8 @@ int git_transport_smart_credentials(git_credential **out, git_transport *transpo
{
transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
- assert(out && transport);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(transport);
if (!t->cred_acquire_cb)
return GIT_PASSTHROUGH;
diff --git a/src/transports/smart.h b/src/transports/smart.h
index 18e0b7e9f..a05d4c9e3 100644
--- a/src/transports/smart.h
+++ b/src/transports/smart.h
@@ -153,7 +153,7 @@ typedef struct {
git_vector refs;
git_vector heads;
git_vector common;
- git_atomic cancelled;
+ git_atomic32 cancelled;
packetsize_cb packetsize_cb;
void *packetsize_payload;
unsigned rpc : 1,
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index c01656dc4..91de163e9 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -64,7 +64,9 @@ int git_smart__store_refs(transport_smart *t, int flushes)
continue;
}
- gitno_consume(buf, line_end);
+ if (gitno_consume(buf, line_end) < 0)
+ return -1;
+
if (pkt->type == GIT_PKT_ERR) {
git_error_set(GIT_ERROR_NET, "remote error: %s", ((git_pkt_err *)pkt)->error);
git__free(pkt);
@@ -236,7 +238,9 @@ static int recv_pkt(git_pkt **out_pkt, git_pkt_type *out_type, gitno_buffer *buf
}
} while (error);
- gitno_consume(buf, line_end);
+ if (gitno_consume(buf, line_end) < 0)
+ return -1;
+
if (out_type != NULL)
*out_type = pkt->type;
if (out_pkt != NULL)
@@ -531,7 +535,7 @@ int git_smart__download_pack(
/* We might have something in the buffer already from negotiate_fetch */
if (t->buffer.offset > 0 && !t->cancelled.val)
if (t->packetsize_cb(t->buffer.offset, t->packetsize_payload))
- git_atomic_set(&t->cancelled, 1);
+ git_atomic32_set(&t->cancelled, 1);
}
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
@@ -791,7 +795,8 @@ static int parse_report(transport_smart *transport, git_push *push)
continue;
}
- gitno_consume(buf, line_end);
+ if (gitno_consume(buf, line_end) < 0)
+ return -1;
error = 0;
@@ -970,9 +975,10 @@ static int stream_thunk(void *buf, size_t size, void *data)
if (payload->cb) {
double current_time = git__timer();
+ double elapsed = current_time - payload->last_progress_report_time;
payload->last_bytes += size;
- if ((current_time - payload->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) {
+ if (elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
payload->last_progress_report_time = current_time;
error = payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload);
}
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 68b3cbeda..1b00be79c 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -11,7 +11,7 @@
#include <libssh2.h>
#endif
-#include "global.h"
+#include "runtime.h"
#include "git2.h"
#include "buffer.h"
#include "net.h"
@@ -238,7 +238,7 @@ static int ssh_stream_alloc(
{
ssh_stream *s;
- assert(stream);
+ GIT_ASSERT_ARG(stream);
s = git__calloc(sizeof(ssh_stream), 1);
GIT_ERROR_CHECK_ALLOC(s);
@@ -404,8 +404,8 @@ static int _git_ssh_authenticate_session(
case GIT_CREDENTIAL_SSH_MEMORY: {
git_credential_ssh_key *c = (git_credential_ssh_key *)cred;
- assert(c->username);
- assert(c->privatekey);
+ GIT_ASSERT(c->username);
+ GIT_ASSERT(c->privatekey);
rc = libssh2_userauth_publickey_frommemory(
session,
@@ -461,13 +461,13 @@ static int request_creds(git_credential **out, ssh_subtransport *t, const char *
if (no_callback) {
git_error_set(GIT_ERROR_SSH, "authentication required but no callback set");
- return -1;
+ return GIT_EAUTH;
}
if (!(cred->credtype & auth_methods)) {
cred->free(cred);
- git_error_set(GIT_ERROR_SSH, "callback returned unsupported credentials type");
- return -1;
+ git_error_set(GIT_ERROR_SSH, "authentication callback returned unsupported credentials type");
+ return GIT_EAUTH;
}
*out = cred;
@@ -476,14 +476,14 @@ static int request_creds(git_credential **out, ssh_subtransport *t, const char *
}
static int _git_ssh_session_create(
- LIBSSH2_SESSION** session,
+ LIBSSH2_SESSION **session,
git_stream *io)
{
int rc = 0;
- LIBSSH2_SESSION* s;
+ LIBSSH2_SESSION *s;
git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent);
- assert(session);
+ GIT_ASSERT_ARG(session);
s = libssh2_session_init();
if (!s) {
@@ -521,8 +521,8 @@ static int _git_ssh_setup_conn(
size_t i;
ssh_stream *s;
git_credential *cred = NULL;
- LIBSSH2_SESSION* session=NULL;
- LIBSSH2_CHANNEL* channel=NULL;
+ LIBSSH2_SESSION *session=NULL;
+ LIBSSH2_CHANNEL *channel=NULL;
t->current_stream = NULL;
@@ -563,9 +563,46 @@ post_extract:
if (t->owner->certificate_check_cb != NULL) {
git_cert_hostkey cert = {{ 0 }}, *cert_ptr;
const char *key;
+ size_t cert_len;
+ int cert_type;
cert.parent.cert_type = GIT_CERT_HOSTKEY_LIBSSH2;
+ key = libssh2_session_hostkey(session, &cert_len, &cert_type);
+ if (key != NULL) {
+ cert.type |= GIT_CERT_SSH_RAW;
+ cert.hostkey = key;
+ cert.hostkey_len = cert_len;
+ switch (cert_type) {
+ case LIBSSH2_HOSTKEY_TYPE_RSA:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_RSA;
+ break;
+ case LIBSSH2_HOSTKEY_TYPE_DSS:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_DSS;
+ break;
+
+#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
+ case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256;
+ break;
+ case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384;
+ break;
+ case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521;
+ break;
+#endif
+
+#ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
+ case LIBSSH2_HOSTKEY_TYPE_ED25519:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ED25519;
+ break;
+#endif
+ default:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_UNKNOWN;
+ }
+ }
+
#ifdef LIBSSH2_HOSTKEY_HASH_SHA256
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA256);
if (key != NULL) {
@@ -772,7 +809,7 @@ static int _ssh_close(git_smart_subtransport *subtransport)
{
ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent);
- assert(!t->current_stream);
+ GIT_ASSERT(!t->current_stream);
GIT_UNUSED(t);
@@ -783,8 +820,6 @@ static void _ssh_free(git_smart_subtransport *subtransport)
{
ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent);
- assert(!t->current_stream);
-
git__free(t->cmd_uploadpack);
git__free(t->cmd_receivepack);
git__free(t);
@@ -805,7 +840,7 @@ static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *use
/* either error, or the remote accepts NONE auth, which is bizarre, let's punt */
if (list == NULL && !libssh2_userauth_authenticated(session)) {
ssh_error(session, "Failed to retrieve list of SSH authentication methods");
- return -1;
+ return GIT_EAUTH;
}
ptr = list;
@@ -849,7 +884,7 @@ int git_smart_subtransport_ssh(
#ifdef GIT_SSH
ssh_subtransport *t;
- assert(out);
+ GIT_ASSERT_ARG(out);
GIT_UNUSED(param);
@@ -867,7 +902,7 @@ int git_smart_subtransport_ssh(
GIT_UNUSED(owner);
GIT_UNUSED(param);
- assert(out);
+ GIT_ASSERT_ARG(out);
*out = NULL;
git_error_set(GIT_ERROR_INVALID, "cannot create SSH transport. Library was built without SSH support");
@@ -911,7 +946,7 @@ int git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *p
GIT_UNUSED(owner);
GIT_UNUSED(payload);
- assert(out);
+ GIT_ASSERT_ARG(out);
*out = NULL;
git_error_set(GIT_ERROR_INVALID, "cannot create SSH transport. Library was built without SSH support");
@@ -934,8 +969,7 @@ int git_transport_ssh_global_init(void)
return -1;
}
- git__on_shutdown(shutdown_ssh);
- return 0;
+ return git_runtime_shutdown_register(shutdown_ssh);
#else
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index ee8cb1543..f4801a451 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -17,7 +17,6 @@
#include "smart.h"
#include "remote.h"
#include "repository.h"
-#include "global.h"
#include "http.h"
#include "git2/sys/credential.h"
@@ -41,14 +40,22 @@
#define WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH 0
#endif
-#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS_1_1
+#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1
# define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 0x00000200
#endif
-#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS_1_2
+#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
# define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 0x00000800
#endif
+#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3
+# define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 0x00002000
+#endif
+
+#ifndef WINHTTP_NO_CLIENT_CERT_CONTEXT
+# define WINHTTP_NO_CLIENT_CERT_CONTEXT NULL
+#endif
+
#ifndef HTTP_STATUS_PERMANENT_REDIRECT
# define HTTP_STATUS_PERMANENT_REDIRECT 308
#endif
@@ -108,7 +115,8 @@ typedef struct {
DWORD post_body_len;
unsigned sent_request : 1,
received_response : 1,
- chunked : 1;
+ chunked : 1,
+ status_sending_request_reached: 1;
} winhttp_stream;
typedef struct {
@@ -146,7 +154,7 @@ static int apply_userpass_credentials(HINTERNET request, DWORD target, int mecha
native_scheme = WINHTTP_AUTH_SCHEME_BASIC;
} else {
git_error_set(GIT_ERROR_HTTP, "invalid authentication scheme");
- error = -1;
+ error = GIT_EAUTH;
goto done;
}
@@ -185,7 +193,7 @@ static int apply_default_credentials(HINTERNET request, DWORD target, int mechan
native_scheme = WINHTTP_AUTH_SCHEME_NTLM;
} else {
git_error_set(GIT_ERROR_HTTP, "invalid authentication scheme");
- return -1;
+ return GIT_EAUTH;
}
/*
@@ -242,7 +250,7 @@ static int acquire_fallback_cred(
hCoInitResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hCoInitResult) || hCoInitResult == RPC_E_CHANGED_MODE) {
- IInternetSecurityManager* pISM;
+ IInternetSecurityManager *pISM;
/* And if the target URI is in the My Computer, Intranet, or Trusted zones */
if (SUCCEEDED(CoCreateInstance(&CLSID_InternetSecurityManager, NULL,
@@ -265,7 +273,7 @@ static int acquire_fallback_cred(
pISM->lpVtbl->Release(pISM);
}
- /* Only unitialize if the call to CoInitializeEx was successful. */
+ /* Only uninitialize if the call to CoInitializeEx was successful. */
if (SUCCEEDED(hCoInitResult))
CoUninitialize();
}
@@ -421,7 +429,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
proxy_opts = &t->owner->proxy;
if (proxy_opts->type == GIT_PROXY_AUTO) {
/* Set proxy if necessary */
- if (git_remote__get_http_proxy(t->owner->owner, (strcmp(t->server.url.scheme, "https") == 0), &proxy_url) < 0)
+ if (git_remote__http_proxy(&proxy_url, t->owner->owner, &t->server.url) < 0)
goto on_error;
}
else if (proxy_opts->type == GIT_PROXY_SPECIFIED) {
@@ -448,8 +456,14 @@ static int winhttp_stream_connect(winhttp_stream *s)
git_buf_puts(&processed_url, t->proxy.url.scheme);
git_buf_PUTS(&processed_url, "://");
+ if (git_net_url_is_ipv6(&t->proxy.url))
+ git_buf_putc(&processed_url, '[');
+
git_buf_puts(&processed_url, t->proxy.url.host);
+ if (git_net_url_is_ipv6(&t->proxy.url))
+ git_buf_putc(&processed_url, ']');
+
if (!git_net_url_is_default_port(&t->proxy.url))
git_buf_printf(&processed_url, ":%s", t->proxy.url.port);
@@ -602,7 +616,7 @@ static int parse_unauthorized_response(
*/
if (!WinHttpQueryAuthSchemes(request, &supported, &first, &target)) {
git_error_set(GIT_ERROR_OS, "failed to parse supported auth schemes");
- return -1;
+ return GIT_EAUTH;
}
if (WINHTTP_AUTH_SCHEME_NTLM & supported) {
@@ -704,46 +718,54 @@ static void CALLBACK winhttp_status(
DWORD status;
GIT_UNUSED(connection);
- GIT_UNUSED(ctx);
GIT_UNUSED(info_len);
- if (code != WINHTTP_CALLBACK_STATUS_SECURE_FAILURE)
- return;
-
- status = *((DWORD *)info);
-
- if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID))
- git_error_set(GIT_ERROR_HTTP, "SSL certificate issued for different common name");
- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID))
- git_error_set(GIT_ERROR_HTTP, "SSL certificate has expired");
- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA))
- git_error_set(GIT_ERROR_HTTP, "SSL certificate signed by unknown CA");
- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT))
- git_error_set(GIT_ERROR_HTTP, "SSL certificate is invalid");
- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED))
- git_error_set(GIT_ERROR_HTTP, "certificate revocation check failed");
- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED))
- git_error_set(GIT_ERROR_HTTP, "SSL certificate was revoked");
- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR))
- git_error_set(GIT_ERROR_HTTP, "security libraries could not be loaded");
- else
- git_error_set(GIT_ERROR_HTTP, "unknown security error %lu", status);
+ switch (code) {
+ case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
+ status = *((DWORD *)info);
+
+ if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID))
+ git_error_set(GIT_ERROR_HTTP, "SSL certificate issued for different common name");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID))
+ git_error_set(GIT_ERROR_HTTP, "SSL certificate has expired");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA))
+ git_error_set(GIT_ERROR_HTTP, "SSL certificate signed by unknown CA");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT))
+ git_error_set(GIT_ERROR_HTTP, "SSL certificate is invalid");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED))
+ git_error_set(GIT_ERROR_HTTP, "certificate revocation check failed");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED))
+ git_error_set(GIT_ERROR_HTTP, "SSL certificate was revoked");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR))
+ git_error_set(GIT_ERROR_HTTP, "security libraries could not be loaded");
+ else
+ git_error_set(GIT_ERROR_HTTP, "unknown security error %lu", status);
+
+ break;
+
+ case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST:
+ ((winhttp_stream *) ctx)->status_sending_request_reached = 1;
+
+ break;
+ }
}
static int winhttp_connect(
winhttp_subtransport *t)
{
- wchar_t *wide_host;
+ wchar_t *wide_host = NULL;
int32_t port;
- wchar_t *wide_ua;
- git_buf ua = GIT_BUF_INIT;
+ wchar_t *wide_ua = NULL;
+ git_buf ipv6 = GIT_BUF_INIT, ua = GIT_BUF_INIT;
+ const char *host;
int error = -1;
int default_timeout = TIMEOUT_INFINITE;
int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
DWORD protocols =
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
- WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
+ WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 |
+ WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3;
t->session = NULL;
t->connection = NULL;
@@ -751,29 +773,33 @@ static int winhttp_connect(
/* Prepare port */
if (git__strntol32(&port, t->server.url.port,
strlen(t->server.url.port), NULL, 10) < 0)
- return -1;
+ goto on_error;
+
+ /* IPv6? Add braces around the host. */
+ if (git_net_url_is_ipv6(&t->server.url)) {
+ if (git_buf_printf(&ipv6, "[%s]", t->server.url.host) < 0)
+ goto on_error;
+
+ host = ipv6.ptr;
+ } else {
+ host = t->server.url.host;
+ }
/* Prepare host */
- if (git__utf8_to_16_alloc(&wide_host, t->server.url.host) < 0) {
+ if (git__utf8_to_16_alloc(&wide_host, host) < 0) {
git_error_set(GIT_ERROR_OS, "unable to convert host to wide characters");
- return -1;
+ goto on_error;
}
- if ((error = git_http__user_agent(&ua)) < 0) {
- git__free(wide_host);
- return error;
- }
+ if (git_http__user_agent(&ua) < 0)
+ goto on_error;
if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) {
git_error_set(GIT_ERROR_OS, "unable to convert host to wide characters");
- git__free(wide_host);
- git_buf_dispose(&ua);
- return -1;
+ goto on_error;
}
- git_buf_dispose(&ua);
-
/* Establish session */
t->session = WinHttpOpen(
wide_ua,
@@ -788,14 +814,20 @@ static int winhttp_connect(
}
/*
- * Do a best-effort attempt to enable TLS 1.2 but allow this to
- * fail; if TLS 1.2 support is not available for some reason,
+ * Do a best-effort attempt to enable TLS 1.3 and 1.2 but allow this to
+ * fail; if TLS 1.2 or 1.3 support is not available for some reason,
* ignore the failure (it will keep the default protocols).
*/
- WinHttpSetOption(t->session,
+ if (WinHttpSetOption(t->session,
WINHTTP_OPTION_SECURE_PROTOCOLS,
&protocols,
- sizeof(protocols));
+ sizeof(protocols)) == FALSE) {
+ protocols &= ~WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3;
+ WinHttpSetOption(t->session,
+ WINHTTP_OPTION_SECURE_PROTOCOLS,
+ &protocols,
+ sizeof(protocols));
+ }
if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
git_error_set(GIT_ERROR_OS, "failed to set timeouts for WinHTTP");
@@ -815,7 +847,12 @@ static int winhttp_connect(
goto on_error;
}
- if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) {
+ if (WinHttpSetStatusCallback(
+ t->connection,
+ winhttp_status,
+ WINHTTP_CALLBACK_FLAG_SECURE_FAILURE | WINHTTP_CALLBACK_FLAG_SEND_REQUEST,
+ 0
+ ) == WINHTTP_INVALID_STATUS_CALLBACK) {
git_error_set(GIT_ERROR_OS, "failed to set status callback");
goto on_error;
}
@@ -826,6 +863,8 @@ on_error:
if (error < 0)
winhttp_close_connection(t);
+ git_buf_dispose(&ua);
+ git_buf_dispose(&ipv6);
git__free(wide_host);
git__free(wide_ua);
@@ -847,12 +886,12 @@ static int do_send_request(winhttp_stream *s, size_t len, bool chunked)
success = WinHttpSendRequest(s->request,
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
WINHTTP_NO_REQUEST_DATA, 0,
- WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0);
+ WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, (DWORD_PTR)s);
} else {
success = WinHttpSendRequest(s->request,
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
WINHTTP_NO_REQUEST_DATA, 0,
- (DWORD)len, 0);
+ (DWORD)len, (DWORD_PTR)s);
}
if (success || GetLastError() != (DWORD)SEC_E_BUFFER_TOO_SMALL)
@@ -864,42 +903,71 @@ static int do_send_request(winhttp_stream *s, size_t len, bool chunked)
static int send_request(winhttp_stream *s, size_t len, bool chunked)
{
- int request_failed = 0, cert_valid = 1, error = 0;
- DWORD ignore_flags;
+ int request_failed = 1, error, attempts = 0;
+ DWORD ignore_flags, send_request_error;
git_error_clear();
- if ((error = do_send_request(s, len, chunked)) < 0) {
- if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
- git_error_set(GIT_ERROR_OS, "failed to send request");
- return -1;
- }
- request_failed = 1;
- cert_valid = 0;
- }
+ while (request_failed && attempts++ < 3) {
+ int cert_valid = 1;
+ int client_cert_requested = 0;
+ request_failed = 0;
+ if ((error = do_send_request(s, len, chunked)) < 0) {
+ send_request_error = GetLastError();
+ request_failed = 1;
+ switch (send_request_error) {
+ case ERROR_WINHTTP_SECURE_FAILURE:
+ cert_valid = 0;
+ break;
+ case ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED:
+ client_cert_requested = 1;
+ break;
+ default:
+ git_error_set(GIT_ERROR_OS, "failed to send request");
+ return -1;
+ }
+ }
- git_error_clear();
- if ((error = certificate_check(s, cert_valid)) < 0) {
- if (!git_error_last())
- git_error_set(GIT_ERROR_OS, "user cancelled certificate check");
+ /*
+ * Only check the certificate if we were able to reach the sending request phase, or
+ * received a secure failure error. Otherwise, the server certificate won't be available
+ * since the request wasn't able to complete (e.g. proxy auth required)
+ */
+ if (!cert_valid ||
+ (!request_failed && s->status_sending_request_reached)) {
+ git_error_clear();
+ if ((error = certificate_check(s, cert_valid)) < 0) {
+ if (!git_error_last())
+ git_error_set(GIT_ERROR_OS, "user cancelled certificate check");
- return error;
- }
+ return error;
+ }
+ }
- /* if neither the request nor the certificate check returned errors, we're done */
- if (!request_failed)
- return 0;
+ /* if neither the request nor the certificate check returned errors, we're done */
+ if (!request_failed)
+ return 0;
- ignore_flags = no_check_cert_flags;
+ if (!cert_valid) {
+ ignore_flags = no_check_cert_flags;
+ if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
+ git_error_set(GIT_ERROR_OS, "failed to set security options");
+ return -1;
+ }
+ }
- if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
- git_error_set(GIT_ERROR_OS, "failed to set security options");
- return -1;
+ if (client_cert_requested) {
+ /*
+ * Client certificates are not supported, explicitly tell the server that
+ * (it's possible a client certificate was requested but is not required)
+ */
+ if (!WinHttpSetOption(s->request, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0)) {
+ git_error_set(GIT_ERROR_OS, "failed to set client cert context");
+ return -1;
+ }
+ }
}
- if ((error = do_send_request(s, len, chunked)) < 0)
- git_error_set(GIT_ERROR_OS, "failed to send request with unchecked certificate");
-
return error;
}
@@ -972,7 +1040,7 @@ replay:
/* Enforce a reasonable cap on the number of replays */
if (replay_count++ >= GIT_HTTP_REPLAY_MAX) {
git_error_set(GIT_ERROR_HTTP, "too many redirects or authentication replays");
- return -1;
+ return GIT_ERROR; /* not GIT_EAUTH because the exact cause is not clear */
}
/* Connect if necessary */
@@ -993,7 +1061,7 @@ replay:
}
if (s->chunked) {
- assert(s->verb == post_verb);
+ GIT_ASSERT(s->verb == post_verb);
/* Flush, if necessary */
if (s->chunk_buffer_len > 0 &&
@@ -1044,7 +1112,7 @@ replay:
}
len -= bytes_read;
- assert(bytes_read == bytes_written);
+ GIT_ASSERT(bytes_read == bytes_written);
}
git__free(buffer);
@@ -1156,7 +1224,7 @@ replay:
if (error < 0) {
return error;
} else if (!error) {
- assert(t->server.cred);
+ GIT_ASSERT(t->server.cred);
winhttp_stream_close(s);
goto replay;
}
@@ -1170,7 +1238,7 @@ replay:
if (error < 0) {
return error;
} else if (!error) {
- assert(t->proxy.cred);
+ GIT_ASSERT(t->proxy.cred);
winhttp_stream_close(s);
goto replay;
}
@@ -1256,7 +1324,7 @@ static int winhttp_stream_write_single(
return -1;
}
- assert((DWORD)len == bytes_written);
+ GIT_ASSERT((DWORD)len == bytes_written);
return 0;
}
@@ -1355,7 +1423,7 @@ static int winhttp_stream_write_buffered(
return -1;
}
- assert((DWORD)len == bytes_written);
+ GIT_ASSERT((DWORD)len == bytes_written);
s->post_body_len += bytes_written;
@@ -1562,7 +1630,7 @@ static int winhttp_action(
break;
default:
- assert(0);
+ GIT_ASSERT(0);
}
if (!ret)
diff --git a/src/tree.c b/src/tree.c
index 48468dff6..b1df79eac 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -54,7 +54,7 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
static int valid_entry_name(git_repository *repo, const char *filename)
{
return *filename != '\0' &&
- git_path_isvalid(repo, filename, 0,
+ git_path_validate(repo, filename, 0,
GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT | GIT_PATH_REJECT_SLASH);
}
@@ -228,7 +228,7 @@ int git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source)
{
git_tree_entry *cpy;
- assert(source);
+ GIT_ASSERT_ARG(source);
cpy = alloc_entry(source->filename, source->filename_len, source->oid);
if (cpy == NULL)
@@ -261,19 +261,19 @@ git_filemode_t git_tree_entry_filemode_raw(const git_tree_entry *entry)
const char *git_tree_entry_name(const git_tree_entry *entry)
{
- assert(entry);
+ GIT_ASSERT_ARG_WITH_RETVAL(entry, NULL);
return entry->filename;
}
const git_oid *git_tree_entry_id(const git_tree_entry *entry)
{
- assert(entry);
+ GIT_ASSERT_ARG_WITH_RETVAL(entry, NULL);
return entry->oid;
}
git_object_t git_tree_entry_type(const git_tree_entry *entry)
{
- assert(entry);
+ GIT_ASSERT_ARG_WITH_RETVAL(entry, GIT_OBJECT_INVALID);
if (S_ISGITLINK(entry->attr))
return GIT_OBJECT_COMMIT;
@@ -288,7 +288,9 @@ int git_tree_entry_to_object(
git_repository *repo,
const git_tree_entry *entry)
{
- assert(entry && object_out);
+ GIT_ASSERT_ARG(entry);
+ GIT_ASSERT_ARG(object_out);
+
return git_object_lookup(object_out, repo, entry->oid, GIT_OBJECT_ANY);
}
@@ -306,7 +308,8 @@ static const git_tree_entry *entry_fromname(
const git_tree_entry *git_tree_entry_byname(
const git_tree *tree, const char *filename)
{
- assert(tree && filename);
+ GIT_ASSERT_ARG_WITH_RETVAL(tree, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(filename, NULL);
return entry_fromname(tree, filename, strlen(filename));
}
@@ -314,7 +317,7 @@ const git_tree_entry *git_tree_entry_byname(
const git_tree_entry *git_tree_entry_byindex(
const git_tree *tree, size_t idx)
{
- assert(tree);
+ GIT_ASSERT_ARG_WITH_RETVAL(tree, NULL);
return git_array_get(tree->entries, idx);
}
@@ -324,7 +327,7 @@ const git_tree_entry *git_tree_entry_byid(
size_t i;
const git_tree_entry *e;
- assert(tree);
+ GIT_ASSERT_ARG_WITH_RETVAL(tree, NULL);
git_array_foreach(tree->entries, i, e) {
if (memcmp(&e->oid->id, &id->id, sizeof(id->id)) == 0)
@@ -336,13 +339,13 @@ const git_tree_entry *git_tree_entry_byid(
size_t git_tree_entrycount(const git_tree *tree)
{
- assert(tree);
+ GIT_ASSERT_ARG_WITH_RETVAL(tree, 0);
return tree->entries.size;
}
size_t git_treebuilder_entrycount(git_treebuilder *bld)
{
- assert(bld);
+ GIT_ASSERT_ARG_WITH_RETVAL(bld, 0);
return git_strmap_size(bld->map);
}
@@ -489,6 +492,56 @@ static int check_entry(git_repository *repo, const char *filename, const git_oid
return 0;
}
+static int git_treebuilder__write_with_buffer(
+ git_oid *oid,
+ git_treebuilder *bld,
+ git_buf *buf)
+{
+ int error = 0;
+ size_t i, entrycount;
+ git_odb *odb;
+ git_tree_entry *entry;
+ git_vector entries = GIT_VECTOR_INIT;
+
+ git_buf_clear(buf);
+
+ entrycount = git_strmap_size(bld->map);
+ if ((error = git_vector_init(&entries, entrycount, entry_sort_cmp)) < 0)
+ goto out;
+
+ if (buf->asize == 0 &&
+ (error = git_buf_grow(buf, entrycount * 72)) < 0)
+ goto out;
+
+ git_strmap_foreach_value(bld->map, entry, {
+ if ((error = git_vector_insert(&entries, entry)) < 0)
+ goto out;
+ });
+
+ git_vector_sort(&entries);
+
+ for (i = 0; i < entries.length && !error; ++i) {
+ entry = git_vector_get(&entries, i);
+
+ git_buf_printf(buf, "%o ", entry->attr);
+ git_buf_put(buf, entry->filename, entry->filename_len + 1);
+ git_buf_put(buf, (char *)entry->oid->id, GIT_OID_RAWSZ);
+
+ if (git_buf_oom(buf)) {
+ error = -1;
+ goto out;
+ }
+ }
+
+ if ((error = git_repository_odb__weakptr(&odb, bld->repo)) == 0)
+ error = git_odb_write(oid, odb, buf->ptr, buf->size, GIT_OBJECT_TREE);
+
+out:
+ git_vector_free(&entries);
+
+ return error;
+}
+
static int append_entry(
git_treebuilder *bld,
const char *filename,
@@ -607,7 +660,7 @@ static int write_tree(
}
}
- if (git_treebuilder_write_with_buffer(oid, bld, shared_buf) < 0)
+ if (git_treebuilder__write_with_buffer(oid, bld, shared_buf) < 0)
goto on_error;
git_treebuilder_free(bld);
@@ -626,7 +679,9 @@ int git_tree__write_index(
git_buf shared_buf = GIT_BUF_INIT;
bool old_ignore_case = false;
- assert(oid && index && repo);
+ GIT_ASSERT_ARG(oid);
+ GIT_ASSERT_ARG(index);
+ GIT_ASSERT_ARG(repo);
if (git_index_has_conflicts(index)) {
git_error_set(GIT_ERROR_INDEX,
@@ -680,7 +735,8 @@ int git_treebuilder_new(
git_treebuilder *bld;
size_t i;
- assert(builder_p && repo);
+ GIT_ASSERT_ARG(builder_p);
+ GIT_ASSERT_ARG(repo);
bld = git__calloc(1, sizeof(git_treebuilder));
GIT_ERROR_CHECK_ALLOC(bld);
@@ -723,7 +779,9 @@ int git_treebuilder_insert(
git_tree_entry *entry;
int error;
- assert(bld && id && filename);
+ GIT_ASSERT_ARG(bld);
+ GIT_ASSERT_ARG(id);
+ GIT_ASSERT_ARG(filename);
if ((error = check_entry(bld->repo, filename, id, filemode)) < 0)
return error;
@@ -751,7 +809,9 @@ int git_treebuilder_insert(
static git_tree_entry *treebuilder_get(git_treebuilder *bld, const char *filename)
{
- assert(bld && filename);
+ GIT_ASSERT_ARG_WITH_RETVAL(bld, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(filename, NULL);
+
return git_strmap_get(bld->map, filename);
}
@@ -775,63 +835,10 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
int git_treebuilder_write(git_oid *oid, git_treebuilder *bld)
{
- int error;
- git_buf buffer = GIT_BUF_INIT;
-
- error = git_treebuilder_write_with_buffer(oid, bld, &buffer);
-
- git_buf_dispose(&buffer);
- return error;
-}
-
-int git_treebuilder_write_with_buffer(git_oid *oid, git_treebuilder *bld, git_buf *tree)
-{
- int error = 0;
- size_t i, entrycount;
- git_odb *odb;
- git_tree_entry *entry;
- git_vector entries = GIT_VECTOR_INIT;
-
- assert(bld);
- assert(tree);
-
- git_buf_clear(tree);
-
- entrycount = git_strmap_size(bld->map);
- if ((error = git_vector_init(&entries, entrycount, entry_sort_cmp)) < 0)
- goto out;
-
- if (tree->asize == 0 &&
- (error = git_buf_grow(tree, entrycount * 72)) < 0)
- goto out;
-
- git_strmap_foreach_value(bld->map, entry, {
- if ((error = git_vector_insert(&entries, entry)) < 0)
- goto out;
- });
-
- git_vector_sort(&entries);
+ GIT_ASSERT_ARG(oid);
+ GIT_ASSERT_ARG(bld);
- for (i = 0; i < entries.length && !error; ++i) {
- entry = git_vector_get(&entries, i);
-
- git_buf_printf(tree, "%o ", entry->attr);
- git_buf_put(tree, entry->filename, entry->filename_len + 1);
- git_buf_put(tree, (char *)entry->oid->id, GIT_OID_RAWSZ);
-
- if (git_buf_oom(tree)) {
- error = -1;
- goto out;
- }
- }
-
- if ((error = git_repository_odb__weakptr(&odb, bld->repo)) == 0)
- error = git_odb_write(oid, odb, tree->ptr, tree->size, GIT_OBJECT_TREE);
-
-out:
- git_vector_free(&entries);
-
- return error;
+ return git_treebuilder__write_with_buffer(oid, bld, &bld->write_cache);
}
int git_treebuilder_filter(
@@ -842,7 +849,8 @@ int git_treebuilder_filter(
const char *filename;
git_tree_entry *entry;
- assert(bld && filter);
+ GIT_ASSERT_ARG(bld);
+ GIT_ASSERT_ARG(filter);
git_strmap_foreach(bld->map, filename, entry, {
if (filter(entry, payload)) {
@@ -858,7 +866,7 @@ int git_treebuilder_clear(git_treebuilder *bld)
{
git_tree_entry *e;
- assert(bld);
+ GIT_ASSERT_ARG(bld);
git_strmap_foreach_value(bld->map, e, git_tree_entry_free(e));
git_strmap_clear(bld->map);
@@ -871,6 +879,7 @@ void git_treebuilder_free(git_treebuilder *bld)
if (bld == NULL)
return;
+ git_buf_dispose(&bld->write_cache);
git_treebuilder_clear(bld);
git_strmap_free(bld->map);
git__free(bld);
@@ -1174,10 +1183,10 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
for (j = 0; j < steps_up; j++) {
tree_stack_entry *current, *popped = git_array_pop(stack);
- assert(popped);
+ GIT_ASSERT(popped);
current = git_array_last(stack);
- assert(current);
+ GIT_ASSERT(current);
if ((error = create_popped_tree(current, popped, &component)) < 0)
goto cleanup;
@@ -1242,8 +1251,9 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
}
case GIT_TREE_UPDATE_REMOVE:
{
+ tree_stack_entry *last = git_array_last(stack);
char *basename = git_path_basename(update->path);
- error = git_treebuilder_remove(git_array_last(stack)->bld, basename);
+ error = git_treebuilder_remove(last->bld, basename);
git__free(basename);
break;
}
@@ -1295,3 +1305,16 @@ cleanup:
git_vector_free(&entries);
return error;
}
+
+/* Deprecated Functions */
+
+#ifndef GIT_DEPRECATE_HARD
+
+int git_treebuilder_write_with_buffer(git_oid *oid, git_treebuilder *bld, git_buf *buf)
+{
+ GIT_UNUSED(buf);
+
+ return git_treebuilder_write(oid, bld);
+}
+
+#endif
diff --git a/src/tree.h b/src/tree.h
index 973ba15d0..2f3027b5a 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -32,6 +32,7 @@ struct git_tree {
struct git_treebuilder {
git_repository *repo;
git_strmap *map;
+ git_buf write_cache;
};
GIT_INLINE(bool) git_tree_entry__is_tree(const struct git_tree_entry *e)
diff --git a/src/tsort.c b/src/tsort.c
index 8d1ed9787..045efad23 100644
--- a/src/tsort.c
+++ b/src/tsort.c
@@ -29,8 +29,6 @@ static int binsearch(
int l, c, r;
void *lx, *cx;
- assert(size > 0);
-
l = 0;
r = (int)size - 1;
c = r >> 1;
diff --git a/src/unix/map.c b/src/unix/map.c
index 7f9076e19..88f283ce8 100644
--- a/src/unix/map.c
+++ b/src/unix/map.c
@@ -66,8 +66,10 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset
int p_munmap(git_map *map)
{
- assert(map != NULL);
+ GIT_ASSERT_ARG(map);
munmap(map->data, map->len);
+ map->data = NULL;
+ map->len = 0;
return 0;
}
diff --git a/src/unix/posix.h b/src/unix/posix.h
index 4fa725013..7b3325e78 100644
--- a/src/unix/posix.h
+++ b/src/unix/posix.h
@@ -62,11 +62,23 @@ GIT_INLINE(int) p_fsync(int fd)
#define p_snprintf snprintf
#define p_mkstemp(p) mkstemp(p)
#define p_chdir(p) chdir(p)
-#define p_chmod(p,m) chmod(p, m)
#define p_rmdir(p) rmdir(p)
#define p_access(p,m) access(p,m)
#define p_ftruncate(fd, sz) ftruncate(fd, sz)
+/*
+ * Pre-Android 5 did not implement a virtual filesystem atop FAT
+ * partitions for Unix permissions, which causes chmod to fail. However,
+ * Unix permissions have no effect on Android anyway as file permissions
+ * are not actually managed this way, so treating it as a no-op across
+ * all Android is safe.
+ */
+#ifdef __ANDROID__
+# define p_chmod(p,m) 0
+#else
+# define p_chmod(p,m) chmod(p, m)
+#endif
+
/* see win32/posix.h for explanation about why this exists */
#define p_lstat_posixly(p,b) lstat(p,b)
@@ -89,4 +101,7 @@ GIT_INLINE(int) p_futimes(int f, const struct p_timeval t[2])
# define p_futimes futimes
#endif
+#define p_pread(f, d, s, o) pread(f, d, s, o)
+#define p_pwrite(f, d, s, o) pwrite(f, d, s, o)
+
#endif
diff --git a/src/unix/pthread.h b/src/unix/pthread.h
index 233561b4e..55f4ae227 100644
--- a/src/unix/pthread.h
+++ b/src/unix/pthread.h
@@ -12,7 +12,8 @@ typedef struct {
pthread_t thread;
} git_thread;
-#define git_threads_init() (void)0
+GIT_INLINE(int) git_threads_global_init(void) { return 0; }
+
#define git_thread_create(git_thread_ptr, start_routine, arg) \
pthread_create(&(git_thread_ptr)->thread, NULL, start_routine, arg)
#define git_thread_join(git_thread_ptr, status) \
diff --git a/src/utf8.c b/src/utf8.c
new file mode 100644
index 000000000..77065cb71
--- /dev/null
+++ b/src/utf8.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "utf8.h"
+
+#include "common.h"
+
+/*
+ * git_utf8_iterate is taken from the utf8proc project,
+ * http://www.public-software-group.org/utf8proc
+ *
+ * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the ""Software""),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+static const uint8_t utf8proc_utf8class[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int utf8_charlen(const uint8_t *str, size_t str_len)
+{
+ uint8_t length;
+ size_t i;
+
+ length = utf8proc_utf8class[str[0]];
+ if (!length)
+ return -1;
+
+ if (str_len > 0 && length > str_len)
+ return -1;
+
+ for (i = 1; i < length; i++) {
+ if ((str[i] & 0xC0) != 0x80)
+ return -1;
+ }
+
+ return (int)length;
+}
+
+int git_utf8_iterate(uint32_t *out, const char *_str, size_t str_len)
+{
+ const uint8_t *str = (const uint8_t *)_str;
+ uint32_t uc = 0;
+ int length;
+
+ *out = 0;
+
+ if ((length = utf8_charlen(str, str_len)) < 0)
+ return -1;
+
+ switch (length) {
+ case 1:
+ uc = str[0];
+ break;
+ case 2:
+ uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F);
+ if (uc < 0x80) uc = -1;
+ break;
+ case 3:
+ uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6)
+ + (str[2] & 0x3F);
+ if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) ||
+ (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1;
+ break;
+ case 4:
+ uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12)
+ + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F);
+ if (uc < 0x10000 || uc >= 0x110000) uc = -1;
+ break;
+ default:
+ return -1;
+ }
+
+ if ((uc & 0xFFFF) >= 0xFFFE)
+ return -1;
+
+ *out = uc;
+ return length;
+}
+
+size_t git_utf8_char_length(const char *_str, size_t str_len)
+{
+ const uint8_t *str = (const uint8_t *)_str;
+ size_t offset = 0, count = 0;
+
+ while (offset < str_len) {
+ int length = utf8_charlen(str + offset, str_len - offset);
+
+ if (length < 0)
+ length = 1;
+
+ offset += length;
+ count++;
+ }
+
+ return count;
+}
+
+size_t git_utf8_valid_buf_length(const char *_str, size_t str_len)
+{
+ const uint8_t *str = (const uint8_t *)_str;
+ size_t offset = 0;
+
+ while (offset < str_len) {
+ int length = utf8_charlen(str + offset, str_len - offset);
+
+ if (length < 0)
+ break;
+
+ offset += length;
+ }
+
+ return offset;
+}
diff --git a/src/utf8.h b/src/utf8.h
new file mode 100644
index 000000000..dff91b294
--- /dev/null
+++ b/src/utf8.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_utf8_h__
+#define INCLUDE_utf8_h__
+
+#include "common.h"
+
+/*
+ * Iterate through an UTF-8 string, yielding one codepoint at a time.
+ *
+ * @param out pointer where to store the current codepoint
+ * @param str current position in the string
+ * @param str_len size left in the string
+ * @return length in bytes of the read codepoint; -1 if the codepoint was invalid
+ */
+extern int git_utf8_iterate(uint32_t *out, const char *str, size_t str_len);
+
+/**
+ * Returns the number of characters in the given string.
+ *
+ * This function will count invalid codepoints; if any given byte is
+ * not part of a valid UTF-8 codepoint, then it will be counted toward
+ * the length in characters.
+ *
+ * In other words:
+ * 0x24 (U+0024 "$") has length 1
+ * 0xc2 0xa2 (U+00A2 "¢") has length 1
+ * 0x24 0xc2 0xa2 (U+0024 U+00A2 "$¢") has length 2
+ * 0xf0 0x90 0x8d 0x88 (U+10348 "ðˆ") has length 1
+ * 0x24 0xc0 0xc1 0x34 (U+0024 <invalid> <invalid> "4) has length 4
+ *
+ * @param str string to scan
+ * @param str_len size of the string
+ * @return length in characters of the string
+ */
+extern size_t git_utf8_char_length(const char *str, size_t str_len);
+
+/**
+ * Iterate through an UTF-8 string and stops after finding any invalid UTF-8
+ * codepoints.
+ *
+ * @param str string to scan
+ * @param str_len size of the string
+ * @return length in bytes of the string that contains valid data
+ */
+extern size_t git_utf8_valid_buf_length(const char *str, size_t str_len);
+
+#endif
diff --git a/src/util.c b/src/util.c
index 2efb212bc..9b0c45ce8 100644
--- a/src/util.c
+++ b/src/util.c
@@ -13,6 +13,11 @@
# include "win32/utf-conv.h"
# include "win32/w32_buffer.h"
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+
# ifdef HAVE_QSORT_S
# include <search.h>
# endif
@@ -22,11 +27,15 @@
# include <Shlwapi.h>
#endif
+#if defined(hpux) || defined(__hpux) || defined(_hpux)
+# include <sys/pstat.h>
+#endif
+
int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
{
const char *p;
- int64_t n, nn;
- int c, ovfl, v, neg, ndig;
+ int64_t n, nn, v;
+ int c, ovfl, neg, ndig;
p = nptr;
neg = 0;
@@ -101,19 +110,11 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
if (v >= base)
break;
v = neg ? -v : v;
- if (n > INT64_MAX / base || n < INT64_MIN / base) {
- ovfl = 1;
- /* Keep on iterating until the end of this number */
- continue;
- }
- nn = n * base;
- if ((v > 0 && nn > INT64_MAX - v) ||
- (v < 0 && nn < INT64_MIN - v)) {
+ if (git__multiply_int64_overflow(&nn, n, base) || git__add_int64_overflow(&n, nn, v)) {
ovfl = 1;
/* Keep on iterating until the end of this number */
continue;
}
- n = nn + v;
}
Return:
@@ -678,7 +679,7 @@ typedef struct {
void *payload;
} git__qsort_r_glue;
-static int GIT_STDLIB_CALL git__qsort_r_glue_cmp(
+static int GIT_LIBGIT2_CALL git__qsort_r_glue_cmp(
void *payload, const void *a, const void *b)
{
git__qsort_r_glue *glue = payload;
@@ -733,123 +734,6 @@ void git__qsort_r(
#endif
}
-/*
- * git__utf8_iterate is taken from the utf8proc project,
- * http://www.public-software-group.org/utf8proc
- *
- * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the ""Software""),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-static const int8_t utf8proc_utf8class[256] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static int util_utf8_charlen(const uint8_t *str, size_t str_len)
-{
- size_t length, i;
-
- length = utf8proc_utf8class[str[0]];
- if (!length)
- return -1;
-
- if (str_len > 0 && length > str_len)
- return -1;
-
- for (i = 1; i < length; i++) {
- if ((str[i] & 0xC0) != 0x80)
- return -1;
- }
-
- return (int)length;
-}
-
-int git__utf8_iterate(const uint8_t *str, int str_len, int32_t *dst)
-{
- int length;
- int32_t uc = -1;
-
- *dst = -1;
- length = util_utf8_charlen(str, str_len);
- if (length < 0)
- return -1;
-
- switch (length) {
- case 1:
- uc = str[0];
- break;
- case 2:
- uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F);
- if (uc < 0x80) uc = -1;
- break;
- case 3:
- uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6)
- + (str[2] & 0x3F);
- if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) ||
- (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1;
- break;
- case 4:
- uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12)
- + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F);
- if (uc < 0x10000 || uc >= 0x110000) uc = -1;
- break;
- }
-
- if (uc < 0 || ((uc & 0xFFFF) >= 0xFFFE))
- return -1;
-
- *dst = uc;
- return length;
-}
-
-size_t git__utf8_valid_buf_length(const uint8_t *str, size_t str_len)
-{
- size_t offset = 0;
-
- while (offset < str_len) {
- int length = util_utf8_charlen(str + offset, str_len - offset);
-
- if (length < 0)
- break;
-
- offset += length;
- }
-
- return offset;
-}
-
#ifdef GIT_WIN32
int git__getenv(git_buf *out, const char *name)
{
@@ -871,7 +755,7 @@ int git__getenv(git_buf *out, const char *name)
if (value_len)
error = git_buf_put_w(out, wide_value, value_len);
- else if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+ else if (GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_ENVVAR_NOT_FOUND)
error = GIT_ENOTFOUND;
else
git_error_set(GIT_ERROR_OS, "could not read environment variable '%s'", name);
@@ -893,3 +777,43 @@ int git__getenv(git_buf *out, const char *name)
return git_buf_puts(out, val);
}
#endif
+
+/*
+ * By doing this in two steps we can at least get
+ * the function to be somewhat coherent, even
+ * with this disgusting nest of #ifdefs.
+ */
+#ifndef _SC_NPROCESSORS_ONLN
+# ifdef _SC_NPROC_ONLN
+# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
+# elif defined _SC_CRAY_NCPU
+# define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU
+# endif
+#endif
+
+int git__online_cpus(void)
+{
+#ifdef _SC_NPROCESSORS_ONLN
+ long ncpus;
+#endif
+
+#ifdef _WIN32
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+
+ if ((int)info.dwNumberOfProcessors > 0)
+ return (int)info.dwNumberOfProcessors;
+#elif defined(hpux) || defined(__hpux) || defined(_hpux)
+ struct pst_dynamic psd;
+
+ if (!pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0))
+ return (int)psd.psd_proc_cnt;
+#endif
+
+#ifdef _SC_NPROCESSORS_ONLN
+ if ((ncpus = (long)sysconf(_SC_NPROCESSORS_ONLN)) > 0)
+ return (int)ncpus;
+#endif
+
+ return 1;
+}
diff --git a/src/util.h b/src/util.h
index b49850d23..e8074fcb9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -18,11 +18,11 @@
#include "buffer.h"
#include "common.h"
#include "strnlen.h"
-#include "thread-utils.h"
+#include "thread.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
-#define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
+#define MSB(x, bits) ((x) & (~UINT64_C(0) << (bitsizeof(x) - (bits))))
#ifndef min
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif
@@ -34,7 +34,7 @@
# define GIT_CONTAINER_OF(ptr, type, member) \
__builtin_choose_expr( \
__builtin_offsetof(type, member) == 0 && \
- __builtin_types_compatible_p(typeof(&((type *) 0)->member), typeof(ptr)), \
+ __builtin_types_compatible_p(__typeof__(&((type *) 0)->member), __typeof__(ptr)), \
((type *) (ptr)), \
(void)0)
#else
@@ -168,30 +168,41 @@ extern int git__strncasecmp(const char *a, const char *b, size_t sz);
extern int git__strcasesort_cmp(const char *a, const char *b);
+/*
+ * Compare some NUL-terminated `a` to a possibly non-NUL terminated
+ * `b` of length `b_len`; like `strncmp` but ensuring that
+ * `strlen(a) == b_len` as well.
+ */
+GIT_INLINE(int) git__strlcmp(const char *a, const char *b, size_t b_len)
+{
+ int cmp = strncmp(a, b, b_len);
+ return cmp ? cmp : (int)a[b_len];
+}
+
typedef struct {
- git_atomic refcount;
+ git_atomic32 refcount;
void *owner;
} git_refcount;
typedef void (*git_refcount_freeptr)(void *r);
#define GIT_REFCOUNT_INC(r) { \
- git_atomic_inc(&(r)->rc.refcount); \
+ git_atomic32_inc(&(r)->rc.refcount); \
}
#define GIT_REFCOUNT_DEC(_r, do_free) { \
git_refcount *r = &(_r)->rc; \
- int val = git_atomic_dec(&r->refcount); \
+ int val = git_atomic32_dec(&r->refcount); \
if (val <= 0 && r->owner == NULL) { do_free(_r); } \
}
#define GIT_REFCOUNT_OWN(r, o) { \
- (r)->rc.owner = o; \
+ (void)git_atomic_swap((r)->rc.owner, o); \
}
-#define GIT_REFCOUNT_OWNER(r) ((r)->rc.owner)
+#define GIT_REFCOUNT_OWNER(r) git_atomic_load((r)->rc.owner)
-#define GIT_REFCOUNT_VAL(r) git_atomic_get((r)->rc.refcount)
+#define GIT_REFCOUNT_VAL(r) git_atomic32_get((r)->rc.refcount)
static signed char from_hex[] = {
@@ -317,27 +328,6 @@ extern int git__date_rfc2822_fmt(char *out, size_t len, const git_time *date);
extern size_t git__unescape(char *str);
/*
- * Iterate through an UTF-8 string, yielding one
- * codepoint at a time.
- *
- * @param str current position in the string
- * @param str_len size left in the string; -1 if the string is NULL-terminated
- * @param dst pointer where to store the current codepoint
- * @return length in bytes of the read codepoint; -1 if the codepoint was invalid
- */
-extern int git__utf8_iterate(const uint8_t *str, int str_len, int32_t *dst);
-
-/*
- * Iterate through an UTF-8 string and stops after finding any invalid UTF-8
- * codepoints.
- *
- * @param str string to scan
- * @param str_len size of the string
- * @return length in bytes of the string that contains valid data
- */
-extern size_t git__utf8_valid_buf_length(const uint8_t *str, size_t str_len);
-
-/*
* Safely zero-out memory, making sure that the compiler
* doesn't optimize away the operation.
*/
@@ -380,7 +370,7 @@ GIT_INLINE(double) git__timer(void)
return (double)time * scaling_factor / 1.0E9;
}
-#elif defined(AMIGA)
+#elif defined(__amigaos4__)
#include <proto/timer.h>
@@ -397,23 +387,27 @@ GIT_INLINE(double) git__timer(void)
GIT_INLINE(double) git__timer(void)
{
- struct timespec tp;
+ struct timeval tv;
- if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
+#ifdef CLOCK_MONOTONIC
+ struct timespec tp;
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
return (double) tp.tv_sec + (double) tp.tv_nsec / 1.0E9;
- } else {
- /* Fall back to using gettimeofday */
- struct timeval tv;
- struct timezone tz;
- gettimeofday(&tv, &tz);
- return (double)tv.tv_sec + (double)tv.tv_usec / 1.0E6;
- }
+#endif
+
+ /* Fall back to using gettimeofday */
+ gettimeofday(&tv, NULL);
+ return (double)tv.tv_sec + (double)tv.tv_usec / 1.0E6;
}
#endif
extern int git__getenv(git_buf *out, const char *name);
+extern int git__online_cpus(void);
+
+GIT_INLINE(int) git__noop(void) { return 0; }
+
#include "alloc.h"
#endif
diff --git a/src/vector.c b/src/vector.c
index b51e7644b..4a4bc8c0e 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -53,7 +53,8 @@ int git_vector_size_hint(git_vector *v, size_t size_hint)
int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp)
{
- assert(v && src);
+ GIT_ASSERT_ARG(v);
+ GIT_ASSERT_ARG(src);
v->_alloc_size = 0;
v->contents = NULL;
@@ -77,7 +78,8 @@ int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp)
void git_vector_free(git_vector *v)
{
- assert(v);
+ if (!v)
+ return;
git__free(v->contents);
v->contents = NULL;
@@ -90,7 +92,8 @@ void git_vector_free_deep(git_vector *v)
{
size_t i;
- assert(v);
+ if (!v)
+ return;
for (i = 0; i < v->length; ++i) {
git__free(v->contents[i]);
@@ -102,7 +105,7 @@ void git_vector_free_deep(git_vector *v)
int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp)
{
- assert(v);
+ GIT_ASSERT_ARG(v);
v->_alloc_size = 0;
v->_cmp = cmp;
@@ -131,7 +134,7 @@ void **git_vector_detach(size_t *size, size_t *asize, git_vector *v)
int git_vector_insert(git_vector *v, void *element)
{
- assert(v);
+ GIT_ASSERT_ARG(v);
if (v->length >= v->_alloc_size &&
resize_vector(v, compute_new_size(v)) < 0)
@@ -150,7 +153,8 @@ int git_vector_insert_sorted(
int result;
size_t pos;
- assert(v && v->_cmp);
+ GIT_ASSERT_ARG(v);
+ GIT_ASSERT(v->_cmp);
if (!git_vector_is_sorted(v))
git_vector_sort(v);
@@ -180,8 +184,6 @@ int git_vector_insert_sorted(
void git_vector_sort(git_vector *v)
{
- assert(v);
-
if (git_vector_is_sorted(v) || !v->_cmp)
return;
@@ -196,7 +198,9 @@ int git_vector_bsearch2(
git_vector_cmp key_lookup,
const void *key)
{
- assert(v && key && key_lookup);
+ GIT_ASSERT_ARG(v);
+ GIT_ASSERT_ARG(key);
+ GIT_ASSERT(key_lookup);
/* need comparison function to sort the vector */
if (!v->_cmp)
@@ -212,7 +216,9 @@ int git_vector_search2(
{
size_t i;
- assert(v && key && key_lookup);
+ GIT_ASSERT_ARG(v);
+ GIT_ASSERT_ARG(key);
+ GIT_ASSERT(key_lookup);
for (i = 0; i < v->length; ++i) {
if (key_lookup(key, v->contents[i]) == 0) {
@@ -240,7 +246,7 @@ int git_vector_remove(git_vector *v, size_t idx)
{
size_t shift_count;
- assert(v);
+ GIT_ASSERT_ARG(v);
if (idx >= v->length)
return GIT_ENOTFOUND;
@@ -303,7 +309,6 @@ void git_vector_remove_matching(
void git_vector_clear(git_vector *v)
{
- assert(v);
v->length = 0;
git_vector_set_sorted(v, 1);
}
@@ -312,8 +317,6 @@ void git_vector_swap(git_vector *a, git_vector *b)
{
git_vector t;
- assert(a && b);
-
if (a != b) {
memcpy(&t, a, sizeof(t));
memcpy(a, b, sizeof(t));
@@ -340,7 +343,8 @@ int git_vector_insert_null(git_vector *v, size_t idx, size_t insert_len)
{
size_t new_length;
- assert(insert_len > 0 && idx <= v->length);
+ GIT_ASSERT_ARG(insert_len > 0);
+ GIT_ASSERT_ARG(idx <= v->length);
GIT_ERROR_CHECK_ALLOC_ADD(&new_length, v->length, insert_len);
@@ -359,13 +363,13 @@ int git_vector_remove_range(git_vector *v, size_t idx, size_t remove_len)
{
size_t new_length = v->length - remove_len;
size_t end_idx = 0;
-
- assert(remove_len > 0);
+
+ GIT_ASSERT_ARG(remove_len > 0);
if (git__add_sizet_overflow(&end_idx, idx, remove_len))
- assert(0);
+ GIT_ASSERT(0);
- assert(end_idx <= v->length);
+ GIT_ASSERT(end_idx <= v->length);
if (end_idx < v->length)
memmove(&v->contents[idx], &v->contents[end_idx],
diff --git a/src/vector.h b/src/vector.h
index cc4c314d5..3dcec3d13 100644
--- a/src/vector.h
+++ b/src/vector.h
@@ -26,11 +26,13 @@ typedef struct git_vector {
#define GIT_VECTOR_INIT {0}
-int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp);
+GIT_WARN_UNUSED_RESULT int git_vector_init(
+ git_vector *v, size_t initial_size, git_vector_cmp cmp);
void git_vector_free(git_vector *v);
void git_vector_free_deep(git_vector *v); /* free each entry and self */
void git_vector_clear(git_vector *v);
-int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp);
+GIT_WARN_UNUSED_RESULT int git_vector_dup(
+ git_vector *v, const git_vector *src, git_vector_cmp cmp);
void git_vector_swap(git_vector *a, git_vector *b);
int git_vector_size_hint(git_vector *v, size_t size_hint);
diff --git a/src/win32/findfile.c b/src/win32/findfile.c
index 7f077e154..40d2d518a 100644
--- a/src/win32/findfile.c
+++ b/src/win32/findfile.c
@@ -49,11 +49,13 @@ static int win32_path_to_8(git_buf *dest, const wchar_t *src)
return git_buf_sets(dest, utf8_path);
}
-static wchar_t* win32_walkpath(wchar_t *path, wchar_t *buf, size_t buflen)
+static wchar_t *win32_walkpath(wchar_t *path, wchar_t *buf, size_t buflen)
{
wchar_t term, *base = path;
- assert(path && buf && buflen);
+ GIT_ASSERT_ARG_WITH_RETVAL(path, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(buf, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(buflen, NULL);
term = (*path == L'"') ? *path++ : L';';
@@ -109,7 +111,7 @@ static int win32_find_git_in_registry(
HKEY hKey;
int error = GIT_ENOTFOUND;
- assert(buf);
+ GIT_ASSERT_ARG(buf);
if (!RegOpenKeyExW(hive, key, 0, KEY_READ, &hKey)) {
DWORD dwType, cbData;
diff --git a/src/win32/git2.rc b/src/win32/git2.rc
index 3571bc683..d273afd70 100644
--- a/src/win32/git2.rc
+++ b/src/win32/git2.rc
@@ -2,14 +2,29 @@
#include "../../include/git2/version.h"
#ifndef LIBGIT2_FILENAME
-# define LIBGIT2_FILENAME "git2"
+# ifdef __GNUC__
+# define LIBGIT2_FILENAME git2
+# else
+# define LIBGIT2_FILENAME "git2"
+# endif
#endif
#ifndef LIBGIT2_COMMENTS
# define LIBGIT2_COMMENTS "For more information visit http://libgit2.github.com/"
#endif
+#ifdef __GNUC__
+# define _STR(x) #x
+# define STR(x) _STR(x)
+#else
+# define STR(x) x
+#endif
+
+#ifdef __GNUC__
+VS_VERSION_INFO VERSIONINFO
+#else
VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
+#endif
FILEVERSION LIBGIT2_VER_MAJOR,LIBGIT2_VER_MINOR,LIBGIT2_VER_REVISION,LIBGIT2_VER_PATCH
PRODUCTVERSION LIBGIT2_VER_MAJOR,LIBGIT2_VER_MINOR,LIBGIT2_VER_REVISION,LIBGIT2_VER_PATCH
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
@@ -29,9 +44,9 @@ BEGIN
BEGIN
VALUE "FileDescription", "libgit2 - the Git linkable library\0"
VALUE "FileVersion", LIBGIT2_VERSION "\0"
- VALUE "InternalName", LIBGIT2_FILENAME ".dll\0"
+ VALUE "InternalName", STR(LIBGIT2_FILENAME) ".dll\0"
VALUE "LegalCopyright", "Copyright (C) the libgit2 contributors. All rights reserved.\0"
- VALUE "OriginalFilename", LIBGIT2_FILENAME ".dll\0"
+ VALUE "OriginalFilename", STR(LIBGIT2_FILENAME) ".dll\0"
VALUE "ProductName", "libgit2\0"
VALUE "ProductVersion", LIBGIT2_VERSION "\0"
VALUE "Comments", LIBGIT2_COMMENTS "\0"
diff --git a/src/win32/map.c b/src/win32/map.c
index e2ce737de..2aabc9b15 100644
--- a/src/win32/map.c
+++ b/src/win32/map.c
@@ -117,7 +117,7 @@ int p_munmap(git_map *map)
{
int error = 0;
- assert(map != NULL);
+ GIT_ASSERT_ARG(map);
if (map->data) {
if (!UnmapViewOfFile(map->data)) {
diff --git a/src/win32/msvc-compat.h b/src/win32/msvc-compat.h
index 4cf471f1d..03f9f36dc 100644
--- a/src/win32/msvc-compat.h
+++ b/src/win32/msvc-compat.h
@@ -23,6 +23,14 @@ typedef SSIZE_T ssize_t;
#endif
-#define GIT_STDLIB_CALL __cdecl
+/*
+ * Offer GIT_LIBGIT2_CALL for our calling conventions (__cdecl, always).
+ * This is useful for providing callbacks to userspace code.
+ *
+ * Offer GIT_SYSTEM_CALL for the system calling conventions (__stdcall on
+ * Win32). Useful for providing callbacks to system libraries.
+ */
+#define GIT_LIBGIT2_CALL __cdecl
+#define GIT_SYSTEM_CALL NTAPI
#endif
diff --git a/src/win32/path_w32.c b/src/win32/path_w32.c
index 9faddcf3b..e6640c85e 100644
--- a/src/win32/path_w32.c
+++ b/src/win32/path_w32.c
@@ -170,7 +170,7 @@ static int win32_path_cwd(wchar_t *out, size_t len)
* '\'s, but we we add a 'UNC' specifier to the path, plus
* a trailing directory separator, plus a NUL.
*/
- if (cwd_len > MAX_PATH - 4) {
+ if (cwd_len > GIT_WIN_PATH_MAX - 4) {
errno = ENAMETOOLONG;
return -1;
}
@@ -187,7 +187,7 @@ static int win32_path_cwd(wchar_t *out, size_t len)
* working directory. (One character for the directory separator,
* one for the null.
*/
- else if (cwd_len > MAX_PATH - 2) {
+ else if (cwd_len > GIT_WIN_PATH_MAX - 2) {
errno = ENAMETOOLONG;
return -1;
}
@@ -205,13 +205,13 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
/* See if this is an absolute path (beginning with a drive letter) */
if (git_path_is_absolute(src)) {
- if (git__utf8_to_16(dest, MAX_PATH, src) < 0)
+ if (git__utf8_to_16(dest, GIT_WIN_PATH_MAX, src) < 0)
goto on_error;
}
/* File-prefixed NT-style paths beginning with \\?\ */
else if (path__is_nt_namespace(src)) {
/* Skip the NT prefix, the destination already contains it */
- if (git__utf8_to_16(dest, MAX_PATH, src + PATH__NT_NAMESPACE_LEN) < 0)
+ if (git__utf8_to_16(dest, GIT_WIN_PATH_MAX, src + PATH__NT_NAMESPACE_LEN) < 0)
goto on_error;
}
/* UNC paths */
@@ -220,12 +220,12 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
dest += 4;
/* Skip the leading "\\" */
- if (git__utf8_to_16(dest, MAX_PATH - 2, src + 2) < 0)
+ if (git__utf8_to_16(dest, GIT_WIN_PATH_MAX - 2, src + 2) < 0)
goto on_error;
}
/* Absolute paths omitting the drive letter */
else if (path__startswith_slash(src)) {
- if (path__cwd(dest, MAX_PATH) < 0)
+ if (path__cwd(dest, GIT_WIN_PATH_MAX) < 0)
goto on_error;
if (!git_path_is_absolute(dest)) {
@@ -234,19 +234,19 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
}
/* Skip the drive letter specification ("C:") */
- if (git__utf8_to_16(dest + 2, MAX_PATH - 2, src) < 0)
+ if (git__utf8_to_16(dest + 2, GIT_WIN_PATH_MAX - 2, src) < 0)
goto on_error;
}
/* Relative paths */
else {
int cwd_len;
- if ((cwd_len = win32_path_cwd(dest, MAX_PATH)) < 0)
+ if ((cwd_len = win32_path_cwd(dest, GIT_WIN_PATH_MAX)) < 0)
goto on_error;
dest[cwd_len++] = L'\\';
- if (git__utf8_to_16(dest + cwd_len, MAX_PATH - cwd_len, src) < 0)
+ if (git__utf8_to_16(dest + cwd_len, GIT_WIN_PATH_MAX - cwd_len, src) < 0)
goto on_error;
}
@@ -273,7 +273,7 @@ int git_win32_path_relative_from_utf8(git_win32_path out, const char *src)
return git_win32_path_from_utf8(out, src);
}
- if ((len = git__utf8_to_16(dest, MAX_PATH, src)) < 0)
+ if ((len = git__utf8_to_16(dest, GIT_WIN_PATH_MAX, src)) < 0)
return -1;
for (p = dest; p < (dest + len); p++) {
@@ -381,14 +381,14 @@ int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path)
switch (reparse_buf->ReparseTag) {
case IO_REPARSE_TAG_SYMLINK:
- target = reparse_buf->SymbolicLinkReparseBuffer.PathBuffer +
- (reparse_buf->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
- target_len = reparse_buf->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
+ target = reparse_buf->ReparseBuffer.SymbolicLink.PathBuffer +
+ (reparse_buf->ReparseBuffer.SymbolicLink.SubstituteNameOffset / sizeof(WCHAR));
+ target_len = reparse_buf->ReparseBuffer.SymbolicLink.SubstituteNameLength / sizeof(WCHAR);
break;
case IO_REPARSE_TAG_MOUNT_POINT:
- target = reparse_buf->MountPointReparseBuffer.PathBuffer +
- (reparse_buf->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
- target_len = reparse_buf->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
+ target = reparse_buf->ReparseBuffer.MountPoint.PathBuffer +
+ (reparse_buf->ReparseBuffer.MountPoint.SubstituteNameOffset / sizeof(WCHAR));
+ target_len = reparse_buf->ReparseBuffer.MountPoint.SubstituteNameLength / sizeof(WCHAR);
break;
default:
errno = EINVAL;
@@ -492,14 +492,12 @@ size_t git_win32_path_remove_namespace(wchar_t *str, size_t len)
prefix_len = CONST_STRLEN(unc_prefix);
}
- if (remainder) {
- /*
- * Sanity check that the new string isn't longer than the old one.
- * (This could only happen due to programmer error introducing a
- * prefix longer than the namespace it replaces.)
- */
- assert(len >= remainder_len + prefix_len);
-
+ /*
+ * Sanity check that the new string isn't longer than the old one.
+ * (This could only happen due to programmer error introducing a
+ * prefix longer than the namespace it replaces.)
+ */
+ if (remainder && len >= remainder_len + prefix_len) {
if (prefix)
memmove(str, prefix, prefix_len * sizeof(wchar_t));
diff --git a/src/win32/path_w32.h b/src/win32/path_w32.h
index dab8b96fa..4fadf8d08 100644
--- a/src/win32/path_w32.h
+++ b/src/win32/path_w32.h
@@ -8,7 +8,6 @@
#define INCLUDE_win32_path_w32_h__
#include "common.h"
-#include "vector.h"
/**
* Create a Win32 path (in UCS-2 format) from a UTF-8 string. If the given
diff --git a/src/win32/posix.h b/src/win32/posix.h
index f115088b4..87c6b436a 100644
--- a/src/win32/posix.h
+++ b/src/win32/posix.h
@@ -23,7 +23,7 @@ typedef SOCKET GIT_SOCKET;
extern int p_fstat(int fd, struct stat *buf);
extern int p_lstat(const char *file_name, struct stat *buf);
-extern int p_stat(const char* path, struct stat *buf);
+extern int p_stat(const char *path, struct stat *buf);
extern int p_utimes(const char *filename, const struct p_timeval times[2]);
extern int p_futimes(int fd, const struct p_timeval times[2]);
@@ -38,15 +38,15 @@ extern char *p_realpath(const char *orig_path, char *buffer);
extern int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags);
extern int p_send(GIT_SOCKET socket, const void *buffer, size_t length, int flags);
-extern int p_inet_pton(int af, const char* src, void* dst);
+extern int p_inet_pton(int af, const char *src, void* dst);
extern int p_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr);
extern int p_snprintf(char *buffer, size_t count, const char *format, ...) GIT_FORMAT_PRINTF(3, 4);
extern int p_mkstemp(char *tmp_path);
-extern int p_chdir(const char* path);
-extern int p_chmod(const char* path, mode_t mode);
-extern int p_rmdir(const char* path);
-extern int p_access(const char* path, mode_t mode);
+extern int p_chdir(const char *path);
+extern int p_chmod(const char *path, mode_t mode);
+extern int p_rmdir(const char *path);
+extern int p_access(const char *path, mode_t mode);
extern int p_ftruncate(int fd, off64_t size);
/* p_lstat is almost but not quite POSIX correct. Specifically, the use of
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index cacf986e8..8af07e6fa 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -14,7 +14,6 @@
#include "utf-conv.h"
#include "repository.h"
#include "reparse.h"
-#include "global.h"
#include "buffer.h"
#include <errno.h>
#include <io.h>
@@ -544,6 +543,13 @@ int p_open(const char *path, int flags, ...)
mode_t mode = 0;
struct open_opts opts = {0};
+ #ifdef GIT_DEBUG_STRICT_OPEN
+ if (strstr(path, "//") != NULL) {
+ errno = EACCES;
+ return -1;
+ }
+ #endif
+
if (git_win32_path_from_utf8(wpath, path) < 0)
return -1;
@@ -642,6 +648,8 @@ int p_getcwd(char *buffer_out, size_t size)
if (!cwd)
return -1;
+ git_win32_path_remove_namespace(cwd, wcslen(cwd));
+
/* Convert the working directory back to UTF-8 */
if (git__utf16_to_8(buffer_out, size, cwd) < 0) {
DWORD code = GetLastError();
@@ -654,6 +662,7 @@ int p_getcwd(char *buffer_out, size_t size)
return -1;
}
+ git_path_mkposix(buffer_out);
return 0;
}
@@ -684,7 +693,7 @@ static int getfinalpath_w(
return (int)git_win32_path_remove_namespace(dest, dwChars);
}
-static int follow_and_lstat_link(git_win32_path path, struct stat* buf)
+static int follow_and_lstat_link(git_win32_path path, struct stat *buf)
{
git_win32_path target_w;
@@ -710,7 +719,7 @@ int p_fstat(int fd, struct stat *buf)
return 0;
}
-int p_stat(const char* path, struct stat* buf)
+int p_stat(const char *path, struct stat *buf)
{
git_win32_path path_w;
int len;
@@ -727,7 +736,7 @@ int p_stat(const char* path, struct stat* buf)
return 0;
}
-int p_chdir(const char* path)
+int p_chdir(const char *path)
{
git_win32_path buf;
@@ -737,7 +746,7 @@ int p_chdir(const char* path)
return _wchdir(buf);
}
-int p_chmod(const char* path, mode_t mode)
+int p_chmod(const char *path, mode_t mode)
{
git_win32_path buf;
@@ -747,7 +756,7 @@ int p_chmod(const char* path, mode_t mode)
return _wchmod(buf, mode);
}
-int p_rmdir(const char* path)
+int p_rmdir(const char *path)
{
git_win32_path buf;
int error;
@@ -867,7 +876,7 @@ int p_mkstemp(char *tmp_path)
return p_open(tmp_path, O_RDWR | O_CREAT | O_EXCL, 0744); /* -V536 */
}
-int p_access(const char* path, mode_t mode)
+int p_access(const char *path, mode_t mode)
{
git_win32_path buf;
@@ -982,3 +991,73 @@ int p_inet_pton(int af, const char *src, void *dst)
errno = EINVAL;
return -1;
}
+
+ssize_t p_pread(int fd, void *data, size_t size, off64_t offset)
+{
+ HANDLE fh;
+ DWORD rsize = 0;
+ OVERLAPPED ov = {0};
+ LARGE_INTEGER pos = {0};
+ off64_t final_offset = 0;
+
+ /* Fail if the final offset would have overflowed to match POSIX semantics. */
+ if (!git__is_ssizet(size) || git__add_int64_overflow(&final_offset, offset, (int64_t)size)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Truncate large writes to the maximum allowable size: the caller
+ * needs to always call this in a loop anyways.
+ */
+ if (size > INT32_MAX) {
+ size = INT32_MAX;
+ }
+
+ pos.QuadPart = offset;
+ ov.Offset = pos.LowPart;
+ ov.OffsetHigh = pos.HighPart;
+ fh = (HANDLE)_get_osfhandle(fd);
+
+ if (ReadFile(fh, data, (DWORD)size, &rsize, &ov)) {
+ return (ssize_t)rsize;
+ }
+
+ set_errno();
+ return -1;
+}
+
+ssize_t p_pwrite(int fd, const void *data, size_t size, off64_t offset)
+{
+ HANDLE fh;
+ DWORD wsize = 0;
+ OVERLAPPED ov = {0};
+ LARGE_INTEGER pos = {0};
+ off64_t final_offset = 0;
+
+ /* Fail if the final offset would have overflowed to match POSIX semantics. */
+ if (!git__is_ssizet(size) || git__add_int64_overflow(&final_offset, offset, (int64_t)size)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Truncate large writes to the maximum allowable size: the caller
+ * needs to always call this in a loop anyways.
+ */
+ if (size > INT32_MAX) {
+ size = INT32_MAX;
+ }
+
+ pos.QuadPart = offset;
+ ov.Offset = pos.LowPart;
+ ov.OffsetHigh = pos.HighPart;
+ fh = (HANDLE)_get_osfhandle(fd);
+
+ if (WriteFile(fh, data, (DWORD)size, &wsize, &ov)) {
+ return (ssize_t)wsize;
+ }
+
+ set_errno();
+ return -1;
+}
diff --git a/src/win32/precompiled.h b/src/win32/precompiled.h
index 314383d31..806b1698a 100644
--- a/src/win32/precompiled.h
+++ b/src/win32/precompiled.h
@@ -1,6 +1,5 @@
#include "common.h"
-#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
diff --git a/src/win32/reparse.h b/src/win32/reparse.h
index 5f7408a1b..23312319f 100644
--- a/src/win32/reparse.h
+++ b/src/win32/reparse.h
@@ -26,18 +26,18 @@ typedef struct _GIT_REPARSE_DATA_BUFFER {
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
- } SymbolicLinkReparseBuffer;
+ } SymbolicLink;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
- } MountPointReparseBuffer;
+ } MountPoint;
struct {
UCHAR DataBuffer[1];
- } GenericReparseBuffer;
- };
+ } Generic;
+ } ReparseBuffer;
} GIT_REPARSE_DATA_BUFFER;
#define REPARSE_DATA_HEADER_SIZE 8
diff --git a/src/win32/thread.c b/src/win32/thread.c
index 42dba7f97..f5cacd320 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -6,8 +6,7 @@
*/
#include "thread.h"
-
-#include "../global.h"
+#include "runtime.h"
#define CLEAN_THREAD_EXIT 0x6F012842
@@ -19,6 +18,8 @@ static win32_srwlock_fn win32_srwlock_release_shared;
static win32_srwlock_fn win32_srwlock_acquire_exclusive;
static win32_srwlock_fn win32_srwlock_release_exclusive;
+static DWORD fls_index;
+
/* The thread procedure stub used to invoke the caller's procedure
* and capture the return value for later collection. Windows will
* only hold a DWORD, but we need to be able to store an entire
@@ -28,14 +29,19 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
git_thread *thread = lpParameter;
/* Set the current thread for `git_thread_exit` */
- GIT_GLOBAL->current_thread = thread;
+ FlsSetValue(fls_index, thread);
thread->result = thread->proc(thread->param);
return CLEAN_THREAD_EXIT;
}
-int git_threads_init(void)
+static void git_threads_global_shutdown(void)
+{
+ FlsFree(fls_index);
+}
+
+int git_threads_global_init(void)
{
HMODULE hModule = GetModuleHandleW(L"kernel32");
@@ -52,7 +58,10 @@ int git_threads_init(void)
GetProcAddress(hModule, "ReleaseSRWLockExclusive");
}
- return 0;
+ if ((fls_index = FlsAlloc(NULL)) == FLS_OUT_OF_INDEXES)
+ return -1;
+
+ return git_runtime_shutdown_register(git_threads_global_shutdown);
}
int git_thread_create(
@@ -85,10 +94,7 @@ int git_thread_join(
/* Check for the thread having exited uncleanly. If exit was unclean,
* then we don't have a return value to give back to the caller. */
- if (exit != CLEAN_THREAD_EXIT) {
- assert(false);
- thread->result = NULL;
- }
+ GIT_ASSERT(exit == CLEAN_THREAD_EXIT);
if (value_ptr)
*value_ptr = thread->result;
@@ -99,8 +105,11 @@ int git_thread_join(
void git_thread_exit(void *value)
{
- assert(GIT_GLOBAL->current_thread);
- GIT_GLOBAL->current_thread->result = value;
+ git_thread *thread = FlsGetValue(fls_index);
+
+ if (thread)
+ thread->result = value;
+
ExitThread(CLEAN_THREAD_EXIT);
}
@@ -137,7 +146,7 @@ int git_cond_init(git_cond *cond)
{
/* This is an auto-reset event. */
*cond = CreateEventW(NULL, FALSE, FALSE, NULL);
- assert(*cond);
+ GIT_ASSERT(*cond);
/* If we can't create the event, claim that the reason was out-of-memory.
* The actual reason can be fetched with GetLastError(). */
@@ -152,7 +161,7 @@ int git_cond_free(git_cond *cond)
return EINVAL;
closed = CloseHandle(*cond);
- assert(closed);
+ GIT_ASSERT(closed);
GIT_UNUSED(closed);
*cond = NULL;
@@ -174,7 +183,7 @@ int git_cond_wait(git_cond *cond, git_mutex *mutex)
return error;
wait_result = WaitForSingleObject(*cond, INFINITE);
- assert(WAIT_OBJECT_0 == wait_result);
+ GIT_ASSERT(WAIT_OBJECT_0 == wait_result);
GIT_UNUSED(wait_result);
return git_mutex_lock(mutex);
@@ -188,7 +197,7 @@ int git_cond_signal(git_cond *cond)
return EINVAL;
signaled = SetEvent(*cond);
- assert(signaled);
+ GIT_ASSERT(signaled);
GIT_UNUSED(signaled);
return 0;
diff --git a/src/win32/thread.h b/src/win32/thread.h
index 41cbf015b..8305036b4 100644
--- a/src/win32/thread.h
+++ b/src/win32/thread.h
@@ -35,7 +35,7 @@ typedef struct {
} native;
} git_rwlock;
-int git_threads_init(void);
+int git_threads_global_init(void);
int git_thread_create(git_thread *GIT_RESTRICT,
void *(*) (void *),
diff --git a/src/win32/w32_buffer.c b/src/win32/w32_buffer.c
index b78a7e6f3..f270a1e6a 100644
--- a/src/win32/w32_buffer.c
+++ b/src/win32/w32_buffer.c
@@ -32,13 +32,13 @@ int git_buf_put_w(git_buf *buf, const wchar_t *string_w, size_t len_w)
return -1;
}
- assert(string_w);
+ GIT_ASSERT(string_w);
/* Measure the string necessary for conversion */
if ((utf8_len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, string_w, (int)len_w, NULL, 0, NULL, NULL)) == 0)
return 0;
- assert(utf8_len > 0);
+ GIT_ASSERT(utf8_len > 0);
GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, (size_t)utf8_len);
GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
@@ -50,7 +50,7 @@ int git_buf_put_w(git_buf *buf, const wchar_t *string_w, size_t len_w)
CP_UTF8, WC_ERR_INVALID_CHARS, string_w, (int)len_w, &buf->ptr[buf->size], utf8_len, NULL, NULL)) == 0)
return handle_wc_error();
- assert(utf8_write_len == utf8_len);
+ GIT_ASSERT(utf8_write_len == utf8_len);
buf->size += utf8_write_len;
buf->ptr[buf->size] = '\0';
diff --git a/src/win32/w32_common.h b/src/win32/w32_common.h
index f9e74b947..c20b3e85e 100644
--- a/src/win32/w32_common.h
+++ b/src/win32/w32_common.h
@@ -8,24 +8,33 @@
#ifndef INCLUDE_win32_w32_common_h__
#define INCLUDE_win32_w32_common_h__
+#include <git2/common.h>
+
+/*
+ * 4096 is the max allowed Git path. `MAX_PATH` (260) is the typical max allowed
+ * Windows path length, however win32 Unicode APIs generally allow up to 32,767
+ * if prefixed with "\\?\" (i.e. converted to an NT-style name).
+ */
+#define GIT_WIN_PATH_MAX GIT_PATH_MAX
+
/*
- * Provides a large enough buffer to support Windows paths: MAX_PATH is
- * 260, corresponding to a maximum path length of 259 characters plus a
- * NULL terminator. Prefixing with "\\?\" adds 4 characters, but if the
- * original was a UNC path, then we turn "\\server\share" into
+ * Provides a large enough buffer to support Windows Git paths:
+ * GIT_WIN_PATH_MAX is 4096, corresponding to a maximum path length of 4095
+ * characters plus a NULL terminator. Prefixing with "\\?\" adds 4 characters,
+ * but if the original was a UNC path, then we turn "\\server\share" into
* "\\?\UNC\server\share". So we replace the first two characters with
- * 8 characters, a net gain of 6, so the maximum length is MAX_PATH+6.
+ * 8 characters, a net gain of 6, so the maximum length is GIT_WIN_PATH_MAX+6.
*/
-#define GIT_WIN_PATH_UTF16 MAX_PATH+6
+#define GIT_WIN_PATH_UTF16 GIT_WIN_PATH_MAX+6
-/* Maximum size of a UTF-8 Win32 path. We remove the "\\?\" or "\\?\UNC\"
- * prefixes for presentation, bringing us back to 259 (non-NULL)
+/* Maximum size of a UTF-8 Win32 Git path. We remove the "\\?\" or "\\?\UNC\"
+ * prefixes for presentation, bringing us back to 4095 (non-NULL)
* characters. UTF-8 does have 4-byte sequences, but they are encoded in
* UTF-16 using surrogate pairs, which takes up the space of two characters.
* Two characters in the range U+0800 -> U+FFFF take up more space in UTF-8
* (6 bytes) than one surrogate pair (4 bytes).
*/
-#define GIT_WIN_PATH_UTF8 (259 * 3 + 1)
+#define GIT_WIN_PATH_UTF8 ((GIT_WIN_PATH_MAX - 1) * 3 + 1)
/*
* The length of a Windows "shortname", for 8.3 compatibility.
diff --git a/src/win32/w32_crtdbg_stacktrace.h b/src/win32/w32_crtdbg_stacktrace.h
deleted file mode 100644
index d65154bab..000000000
--- a/src/win32/w32_crtdbg_stacktrace.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef INCLUDE_win32_w32_crtdbg_stacktrace_h__
-#define INCLUDE_win32_w32_crtdbg_stacktrace_h__
-
-#include "common.h"
-
-#if defined(GIT_MSVC_CRTDBG)
-
-#include <stdlib.h>
-#include <crtdbg.h>
-
-#include "git2/errors.h"
-#include "strnlen.h"
-
-/* MSVC CRTDBG memory leak reporting.
- *
- * We DO NOT use the "_CRTDBG_MAP_ALLOC" macro described in the MSVC
- * documentation because all allocs/frees in libgit2 already go through
- * the "git__" routines defined in this file. Simply using the normal
- * reporting mechanism causes all leaks to be attributed to a routine
- * here in util.h (ie, the actual call to calloc()) rather than the
- * caller of git__calloc().
- *
- * Therefore, we declare a set of "git__crtdbg__" routines to replace
- * the corresponding "git__" routines and re-define the "git__" symbols
- * as macros. This allows us to get and report the file:line info of
- * the real caller.
- *
- * We DO NOT replace the "git__free" routine because it needs to remain
- * a function pointer because it is used as a function argument when
- * setting up various structure "destructors".
- *
- * We also DO NOT use the "_CRTDBG_MAP_ALLOC" macro because it causes
- * "free" to be remapped to "_free_dbg" and this causes problems for
- * structures which define a field named "free".
- *
- * Finally, CRTDBG must be explicitly enabled and configured at program
- * startup. See tests/main.c for an example.
- */
-
-/**
- * Initialize our memory leak tracking and de-dup data structures.
- * This should ONLY be called by git_libgit2_init().
- */
-void git_win32__crtdbg_stacktrace_init(void);
-
-/**
- * Shutdown our memory leak tracking and dump summary data.
- * This should ONLY be called by git_libgit2_shutdown().
- *
- * We explicitly call _CrtDumpMemoryLeaks() during here so
- * that we can compute summary data for the leaks. We print
- * the stacktrace of each unique leak.
- *
- * This cleanup does not happen if the app calls exit()
- * without calling the libgit2 shutdown code.
- *
- * This info we print here is independent of any automatic
- * reporting during exit() caused by _CRTDBG_LEAK_CHECK_DF.
- * Set it in your app if you also want traditional reporting.
- */
-void git_win32__crtdbg_stacktrace_cleanup(void);
-
-/**
- * Checkpoint options.
- */
-typedef enum git_win32__crtdbg_stacktrace_options {
- /**
- * Set checkpoint marker.
- */
- GIT_WIN32__CRTDBG_STACKTRACE__SET_MARK = (1 << 0),
-
- /**
- * Dump leaks since last checkpoint marker.
- * May not be combined with __LEAKS_TOTAL.
- *
- * Note that this may generate false positives for global TLS
- * error state and other global caches that aren't cleaned up
- * until the thread/process terminates. So when using this
- * around a region of interest, also check the final (at exit)
- * dump before digging into leaks reported here.
- */
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK = (1 << 1),
-
- /**
- * Dump leaks since init. May not be combined
- * with __LEAKS_SINCE_MARK.
- */
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_TOTAL = (1 << 2),
-
- /**
- * Suppress printing during dumps.
- * Just return leak count.
- */
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET = (1 << 3),
-
-} git_win32__crtdbg_stacktrace_options;
-
-/**
- * Checkpoint memory state and/or dump unique stack traces of
- * current memory leaks.
- *
- * @return number of unique leaks (relative to requested starting
- * point) or error.
- */
-GIT_EXTERN(int) git_win32__crtdbg_stacktrace__dump(
- git_win32__crtdbg_stacktrace_options opt,
- const char *label);
-
-/**
- * Construct stacktrace and append it to the global buffer.
- * Return pointer to start of this string. On any error or
- * lack of buffer space, just return the given file buffer
- * so it will behave as usual.
- *
- * This should ONLY be called by our internal memory allocations
- * routines.
- */
-const char *git_win32__crtdbg_stacktrace(int skip, const char *file);
-
-#endif
-#endif
diff --git a/src/win32/w32_crtdbg_stacktrace.c b/src/win32/w32_leakcheck.c
index cdb5ac1a5..5c8425be3 100644
--- a/src/win32/w32_crtdbg_stacktrace.c
+++ b/src/win32/w32_leakcheck.c
@@ -5,12 +5,203 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "w32_crtdbg_stacktrace.h"
+#include "w32_leakcheck.h"
-#if defined(GIT_MSVC_CRTDBG)
-#include "w32_stack.h"
+#if defined(GIT_WIN32_LEAKCHECK)
-#define CRTDBG_STACKTRACE__UID_LEN (15)
+#include "Windows.h"
+#include "Dbghelp.h"
+#include "win32/posix.h"
+#include "hash.h"
+#include "runtime.h"
+
+/* Stack frames (for stack tracing, below) */
+
+static bool g_win32_stack_initialized = false;
+static HANDLE g_win32_stack_process = INVALID_HANDLE_VALUE;
+static git_win32_leakcheck_stack_aux_cb_alloc g_aux_cb_alloc = NULL;
+static git_win32_leakcheck_stack_aux_cb_lookup g_aux_cb_lookup = NULL;
+
+int git_win32_leakcheck_stack_set_aux_cb(
+ git_win32_leakcheck_stack_aux_cb_alloc cb_alloc,
+ git_win32_leakcheck_stack_aux_cb_lookup cb_lookup)
+{
+ g_aux_cb_alloc = cb_alloc;
+ g_aux_cb_lookup = cb_lookup;
+
+ return 0;
+}
+
+/**
+ * Load symbol table data. This should be done in the primary
+ * thread at startup (under a lock if there are other threads
+ * active).
+ */
+void git_win32_leakcheck_stack_init(void)
+{
+ if (!g_win32_stack_initialized) {
+ g_win32_stack_process = GetCurrentProcess();
+ SymSetOptions(SYMOPT_LOAD_LINES);
+ SymInitialize(g_win32_stack_process, NULL, TRUE);
+ g_win32_stack_initialized = true;
+ }
+}
+
+/**
+ * Cleanup symbol table data. This should be done in the
+ * primary thead at shutdown (under a lock if there are other
+ * threads active).
+ */
+void git_win32_leakcheck_stack_cleanup(void)
+{
+ if (g_win32_stack_initialized) {
+ SymCleanup(g_win32_stack_process);
+ g_win32_stack_process = INVALID_HANDLE_VALUE;
+ g_win32_stack_initialized = false;
+ }
+}
+
+int git_win32_leakcheck_stack_capture(git_win32_leakcheck_stack_raw_data *pdata, int skip)
+{
+ if (!g_win32_stack_initialized) {
+ git_error_set(GIT_ERROR_INVALID, "git_win32_stack not initialized.");
+ return GIT_ERROR;
+ }
+
+ memset(pdata, 0, sizeof(*pdata));
+ pdata->nr_frames = RtlCaptureStackBackTrace(
+ skip+1, GIT_WIN32_LEAKCHECK_STACK_MAX_FRAMES, pdata->frames, NULL);
+
+ /* If an "aux" data provider was registered, ask it to capture
+ * whatever data it needs and give us an "aux_id" to it so that
+ * we can refer to it later when reporting.
+ */
+ if (g_aux_cb_alloc)
+ (g_aux_cb_alloc)(&pdata->aux_id);
+
+ return 0;
+}
+
+int git_win32_leakcheck_stack_compare(
+ git_win32_leakcheck_stack_raw_data *d1,
+ git_win32_leakcheck_stack_raw_data *d2)
+{
+ return memcmp(d1, d2, sizeof(*d1));
+}
+
+int git_win32_leakcheck_stack_format(
+ char *pbuf, size_t buf_len,
+ const git_win32_leakcheck_stack_raw_data *pdata,
+ const char *prefix, const char *suffix)
+{
+#define MY_MAX_FILENAME 255
+
+ /* SYMBOL_INFO has char FileName[1] at the end. The docs say to
+ * to malloc it with extra space for your desired max filename.
+ */
+ struct {
+ SYMBOL_INFO symbol;
+ char extra[MY_MAX_FILENAME + 1];
+ } s;
+
+ IMAGEHLP_LINE64 line;
+ size_t buf_used = 0;
+ unsigned int k;
+ char detail[MY_MAX_FILENAME * 2]; /* filename plus space for function name and formatting */
+ size_t detail_len;
+
+ if (!g_win32_stack_initialized) {
+ git_error_set(GIT_ERROR_INVALID, "git_win32_stack not initialized.");
+ return GIT_ERROR;
+ }
+
+ if (!prefix)
+ prefix = "\t";
+ if (!suffix)
+ suffix = "\n";
+
+ memset(pbuf, 0, buf_len);
+
+ memset(&s, 0, sizeof(s));
+ s.symbol.MaxNameLen = MY_MAX_FILENAME;
+ s.symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
+
+ memset(&line, 0, sizeof(line));
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+ for (k=0; k < pdata->nr_frames; k++) {
+ DWORD64 frame_k = (DWORD64)pdata->frames[k];
+ DWORD dwUnused;
+
+ if (SymFromAddr(g_win32_stack_process, frame_k, 0, &s.symbol) &&
+ SymGetLineFromAddr64(g_win32_stack_process, frame_k, &dwUnused, &line)) {
+ const char *pslash;
+ const char *pfile;
+
+ pslash = strrchr(line.FileName, '\\');
+ pfile = ((pslash) ? (pslash+1) : line.FileName);
+ p_snprintf(detail, sizeof(detail), "%s%s:%d> %s%s",
+ prefix, pfile, line.LineNumber, s.symbol.Name, suffix);
+ } else {
+ /* This happens when we cross into another module.
+ * For example, in CLAR tests, this is typically
+ * the CRT startup code. Just print an unknown
+ * frame and continue.
+ */
+ p_snprintf(detail, sizeof(detail), "%s??%s", prefix, suffix);
+ }
+ detail_len = strlen(detail);
+
+ if (buf_len < (buf_used + detail_len + 1)) {
+ /* we don't have room for this frame in the buffer, so just stop. */
+ break;
+ }
+
+ memcpy(&pbuf[buf_used], detail, detail_len);
+ buf_used += detail_len;
+ }
+
+ /* "aux_id" 0 is reserved to mean no aux data. This is needed to handle
+ * allocs that occur before the aux callbacks were registered.
+ */
+ if (pdata->aux_id > 0) {
+ p_snprintf(detail, sizeof(detail), "%saux_id: %d%s",
+ prefix, pdata->aux_id, suffix);
+ detail_len = strlen(detail);
+ if ((buf_used + detail_len + 1) < buf_len) {
+ memcpy(&pbuf[buf_used], detail, detail_len);
+ buf_used += detail_len;
+ }
+
+ /* If an "aux" data provider is still registered, ask it to append its detailed
+ * data to the end of ours using the "aux_id" it gave us when this de-duped
+ * item was created.
+ */
+ if (g_aux_cb_lookup)
+ (g_aux_cb_lookup)(pdata->aux_id, &pbuf[buf_used], (buf_len - buf_used - 1));
+ }
+
+ return GIT_OK;
+}
+
+int git_win32_leakcheck_stack(
+ char * pbuf, size_t buf_len,
+ int skip,
+ const char *prefix, const char *suffix)
+{
+ git_win32_leakcheck_stack_raw_data data;
+ int error;
+
+ if ((error = git_win32_leakcheck_stack_capture(&data, skip)) < 0)
+ return error;
+ if ((error = git_win32_leakcheck_stack_format(pbuf, buf_len, &data, prefix, suffix)) < 0)
+ return error;
+ return 0;
+}
+
+/* Strack tracing */
+
+#define STACKTRACE_UID_LEN (15)
/**
* The stacktrace of an allocation can be distilled
@@ -20,20 +211,20 @@
* give to the CRT malloc routines.
*/
typedef struct {
- char uid[CRTDBG_STACKTRACE__UID_LEN + 1];
-} git_win32__crtdbg_stacktrace__uid;
+ char uid[STACKTRACE_UID_LEN + 1];
+} git_win32_leakcheck_stacktrace_uid;
/**
* All mallocs with the same stacktrace will be de-duped
* and aggregated into this row.
*/
typedef struct {
- git_win32__crtdbg_stacktrace__uid uid; /* must be first */
- git_win32__stack__raw_data raw_data;
+ git_win32_leakcheck_stacktrace_uid uid; /* must be first */
+ git_win32_leakcheck_stack_raw_data raw_data;
unsigned int count_allocs; /* times this alloc signature seen since init */
unsigned int count_allocs_at_last_checkpoint; /* times since last mark */
unsigned int transient_count_leaks; /* sum of leaks */
-} git_win32__crtdbg_stacktrace__row;
+} git_win32_leakcheck_stacktrace_row;
static CRITICAL_SECTION g_crtdbg_stacktrace_cs;
@@ -57,9 +248,9 @@ static CRITICAL_SECTION g_crtdbg_stacktrace_cs;
* it and try again.
*/
-#define MY_ROW_LIMIT (1024 * 1024)
-static git_win32__crtdbg_stacktrace__row g_cs_rows[MY_ROW_LIMIT];
-static git_win32__crtdbg_stacktrace__row *g_cs_index[MY_ROW_LIMIT];
+#define MY_ROW_LIMIT (2 * 1024 * 1024)
+static git_win32_leakcheck_stacktrace_row g_cs_rows[MY_ROW_LIMIT];
+static git_win32_leakcheck_stacktrace_row *g_cs_index[MY_ROW_LIMIT];
static unsigned int g_cs_end = MY_ROW_LIMIT;
static unsigned int g_cs_ins = 0; /* insertion point == unique allocs seen */
@@ -76,18 +267,18 @@ static bool g_transient_leaks_since_mark = false; /* payload for hook */
*/
static int row_cmp(const void *v1, const void *v2)
{
- git_win32__stack__raw_data *d1 = (git_win32__stack__raw_data*)v1;
- git_win32__crtdbg_stacktrace__row *r2 = (git_win32__crtdbg_stacktrace__row *)v2;
+ git_win32_leakcheck_stack_raw_data *d1 = (git_win32_leakcheck_stack_raw_data*)v1;
+ git_win32_leakcheck_stacktrace_row *r2 = (git_win32_leakcheck_stacktrace_row *)v2;
- return (git_win32__stack_compare(d1, &r2->raw_data));
+ return (git_win32_leakcheck_stack_compare(d1, &r2->raw_data));
}
/**
* Unique insert the new data into the row and index tables.
* We have to sort by the stackframe data itself, not the uid.
*/
-static git_win32__crtdbg_stacktrace__row * insert_unique(
- const git_win32__stack__raw_data *pdata)
+static git_win32_leakcheck_stacktrace_row * insert_unique(
+ const git_win32_leakcheck_stack_raw_data *pdata)
{
size_t pos;
if (git__bsearch(g_cs_index, g_cs_ins, pdata, row_cmp, &pos) < 0) {
@@ -206,7 +397,7 @@ static void dump_summary(const char *label)
g_cs_rows[k].count_allocs);
my_output(buf);
- if (git_win32__stack_format(
+ if (git_win32_leakcheck_stack_format(
buf, sizeof(buf), &g_cs_rows[k].raw_data,
NULL, NULL) >= 0) {
my_output(buf);
@@ -219,7 +410,11 @@ static void dump_summary(const char *label)
fflush(stderr);
}
-void git_win32__crtdbg_stacktrace_init(void)
+/**
+ * Initialize our memory leak tracking and de-dup data structures.
+ * This should ONLY be called by git_libgit2_init().
+ */
+void git_win32_leakcheck_stacktrace_init(void)
{
InitializeCriticalSection(&g_crtdbg_stacktrace_cs);
@@ -238,8 +433,8 @@ void git_win32__crtdbg_stacktrace_init(void)
LeaveCriticalSection(&g_crtdbg_stacktrace_cs);
}
-int git_win32__crtdbg_stacktrace__dump(
- git_win32__crtdbg_stacktrace_options opt,
+int git_win32_leakcheck_stacktrace_dump(
+ git_win32_leakcheck_stacktrace_options opt,
const char *label)
{
_CRT_REPORT_HOOK old;
@@ -248,10 +443,10 @@ int git_win32__crtdbg_stacktrace__dump(
#define IS_BIT_SET(o,b) (((o) & (b)) != 0)
- bool b_set_mark = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__SET_MARK);
- bool b_leaks_since_mark = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK);
- bool b_leaks_total = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_TOTAL);
- bool b_quiet = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__QUIET);
+ bool b_set_mark = IS_BIT_SET(opt, GIT_WIN32_LEAKCHECK_STACKTRACE_SET_MARK);
+ bool b_leaks_since_mark = IS_BIT_SET(opt, GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK);
+ bool b_leaks_total = IS_BIT_SET(opt, GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_TOTAL);
+ bool b_quiet = IS_BIT_SET(opt, GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET);
if (b_leaks_since_mark && b_leaks_total) {
git_error_set(GIT_ERROR_INVALID, "cannot combine LEAKS_SINCE_MARK and LEAKS_TOTAL.");
@@ -301,29 +496,44 @@ int git_win32__crtdbg_stacktrace__dump(
return r;
}
-void git_win32__crtdbg_stacktrace_cleanup(void)
+/**
+ * Shutdown our memory leak tracking and dump summary data.
+ * This should ONLY be called by git_libgit2_shutdown().
+ *
+ * We explicitly call _CrtDumpMemoryLeaks() during here so
+ * that we can compute summary data for the leaks. We print
+ * the stacktrace of each unique leak.
+ *
+ * This cleanup does not happen if the app calls exit()
+ * without calling the libgit2 shutdown code.
+ *
+ * This info we print here is independent of any automatic
+ * reporting during exit() caused by _CRTDBG_LEAK_CHECK_DF.
+ * Set it in your app if you also want traditional reporting.
+ */
+void git_win32_leakcheck_stacktrace_cleanup(void)
{
- /* At shutdown/cleanup, dump cummulative leak info
+ /* At shutdown/cleanup, dump cumulative leak info
* with everything since startup. This might generate
* extra noise if the caller has been doing checkpoint
* dumps, but it might also eliminate some false
* positives for resources previously reported during
* checkpoints.
*/
- git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_TOTAL,
+ git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_TOTAL,
"CLEANUP");
DeleteCriticalSection(&g_crtdbg_stacktrace_cs);
}
-const char *git_win32__crtdbg_stacktrace(int skip, const char *file)
+const char *git_win32_leakcheck_stacktrace(int skip, const char *file)
{
- git_win32__stack__raw_data new_data;
- git_win32__crtdbg_stacktrace__row *row;
+ git_win32_leakcheck_stack_raw_data new_data;
+ git_win32_leakcheck_stacktrace_row *row;
const char * result = file;
- if (git_win32__stack_capture(&new_data, skip+1) < 0)
+ if (git_win32_leakcheck_stack_capture(&new_data, skip+1) < 0)
return result;
EnterCriticalSection(&g_crtdbg_stacktrace_cs);
@@ -342,4 +552,30 @@ const char *git_win32__crtdbg_stacktrace(int skip, const char *file)
return result;
}
+static void git_win32_leakcheck_global_shutdown(void)
+{
+ git_win32_leakcheck_stacktrace_cleanup();
+ git_win32_leakcheck_stack_cleanup();
+}
+
+bool git_win32_leakcheck_has_leaks(void)
+{
+ return (g_transient_count_total_leaks > 0);
+}
+
+int git_win32_leakcheck_global_init(void)
+{
+ git_win32_leakcheck_stacktrace_init();
+ git_win32_leakcheck_stack_init();
+
+ return git_runtime_shutdown_register(git_win32_leakcheck_global_shutdown);
+}
+
+#else
+
+int git_win32_leakcheck_global_init(void)
+{
+ return 0;
+}
+
#endif
diff --git a/src/win32/w32_leakcheck.h b/src/win32/w32_leakcheck.h
new file mode 100644
index 000000000..cb45e3675
--- /dev/null
+++ b/src/win32/w32_leakcheck.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#ifndef INCLUDE_win32_leakcheck_h__
+#define INCLUDE_win32_leakcheck_h__
+
+#include "common.h"
+
+/* Initialize the win32 leak checking system. */
+int git_win32_leakcheck_global_init(void);
+
+#if defined(GIT_WIN32_LEAKCHECK)
+
+#include <stdlib.h>
+#include <crtdbg.h>
+
+#include "git2/errors.h"
+#include "strnlen.h"
+
+bool git_win32_leakcheck_has_leaks(void);
+
+/* Stack frames (for stack tracing, below) */
+
+/**
+ * This type defines a callback to be used to augment a C stacktrace
+ * with "aux" data. This can be used, for example, to allow LibGit2Sharp
+ * (or other interpreted consumer libraries) to give us C# stacktrace
+ * data for the PInvoke.
+ *
+ * This callback will be called during crtdbg-instrumented allocs.
+ *
+ * @param aux_id [out] A returned "aux_id" representing a unique
+ * (de-duped at the C# layer) stacktrace. "aux_id" 0 is reserved
+ * to mean no aux stacktrace data.
+ */
+typedef void (*git_win32_leakcheck_stack_aux_cb_alloc)(unsigned int *aux_id);
+
+/**
+ * This type defines a callback to be used to augment the output of
+ * a stacktrace. This will be used to request the C# layer format
+ * the C# stacktrace associated with "aux_id" into the provided
+ * buffer.
+ *
+ * This callback will be called during leak reporting.
+ *
+ * @param aux_id The "aux_id" key associated with a stacktrace.
+ * @param aux_msg A buffer where a formatted message should be written.
+ * @param aux_msg_len The size of the buffer.
+ */
+typedef void (*git_win32_leakcheck_stack_aux_cb_lookup)(unsigned int aux_id, char *aux_msg, size_t aux_msg_len);
+
+/**
+ * Register an "aux" data provider to augment our C stacktrace data.
+ *
+ * This can be used, for example, to allow LibGit2Sharp (or other
+ * interpreted consumer libraries) to give us the C# stacktrace of
+ * the PInvoke.
+ *
+ * If you choose to use this feature, it should be registered during
+ * initialization and not changed for the duration of the process.
+ */
+int git_win32_leakcheck_stack_set_aux_cb(
+ git_win32_leakcheck_stack_aux_cb_alloc cb_alloc,
+ git_win32_leakcheck_stack_aux_cb_lookup cb_lookup);
+
+/**
+ * Maximum number of stackframes to record for a
+ * single stacktrace.
+ */
+#define GIT_WIN32_LEAKCHECK_STACK_MAX_FRAMES 30
+
+/**
+ * Wrapper containing the raw unprocessed stackframe
+ * data for a single stacktrace and any "aux_id".
+ *
+ * I put the aux_id first so leaks will be sorted by it.
+ * So, for example, if a specific callstack in C# leaks
+ * a repo handle, all of the pointers within the associated
+ * repo pointer will be grouped together.
+ */
+typedef struct {
+ unsigned int aux_id;
+ unsigned int nr_frames;
+ void *frames[GIT_WIN32_LEAKCHECK_STACK_MAX_FRAMES];
+} git_win32_leakcheck_stack_raw_data;
+
+/**
+ * Capture raw stack trace data for the current process/thread.
+ *
+ * @param skip Number of initial frames to skip. Pass 0 to
+ * begin with the caller of this routine. Pass 1 to begin
+ * with its caller. And so on.
+ */
+int git_win32_leakcheck_stack_capture(git_win32_leakcheck_stack_raw_data *pdata, int skip);
+
+/**
+ * Compare 2 raw stacktraces with the usual -1,0,+1 result.
+ * This includes any "aux_id" values in the comparison, so that
+ * our de-dup is also "aux" context relative.
+ */
+int git_win32_leakcheck_stack_compare(
+ git_win32_leakcheck_stack_raw_data *d1,
+ git_win32_leakcheck_stack_raw_data *d2);
+
+/**
+ * Format raw stacktrace data into buffer WITHOUT using any mallocs.
+ *
+ * @param prefix String written before each frame; defaults to "\t".
+ * @param suffix String written after each frame; defaults to "\n".
+ */
+int git_win32_leakcheck_stack_format(
+ char *pbuf, size_t buf_len,
+ const git_win32_leakcheck_stack_raw_data *pdata,
+ const char *prefix, const char *suffix);
+
+/**
+ * Convenience routine to capture and format stacktrace into
+ * a buffer WITHOUT using any mallocs. This is primarily a
+ * wrapper for testing.
+ *
+ * @param skip Number of initial frames to skip. Pass 0 to
+ * begin with the caller of this routine. Pass 1 to begin
+ * with its caller. And so on.
+ * @param prefix String written before each frame; defaults to "\t".
+ * @param suffix String written after each frame; defaults to "\n".
+ */
+int git_win32_leakcheck_stack(
+ char * pbuf, size_t buf_len,
+ int skip,
+ const char *prefix, const char *suffix);
+
+/* Stack tracing */
+
+/* MSVC CRTDBG memory leak reporting.
+ *
+ * We DO NOT use the "_CRTDBG_MAP_ALLOC" macro described in the MSVC
+ * documentation because all allocs/frees in libgit2 already go through
+ * the "git__" routines defined in this file. Simply using the normal
+ * reporting mechanism causes all leaks to be attributed to a routine
+ * here in util.h (ie, the actual call to calloc()) rather than the
+ * caller of git__calloc().
+ *
+ * Therefore, we declare a set of "git__crtdbg__" routines to replace
+ * the corresponding "git__" routines and re-define the "git__" symbols
+ * as macros. This allows us to get and report the file:line info of
+ * the real caller.
+ *
+ * We DO NOT replace the "git__free" routine because it needs to remain
+ * a function pointer because it is used as a function argument when
+ * setting up various structure "destructors".
+ *
+ * We also DO NOT use the "_CRTDBG_MAP_ALLOC" macro because it causes
+ * "free" to be remapped to "_free_dbg" and this causes problems for
+ * structures which define a field named "free".
+ *
+ * Finally, CRTDBG must be explicitly enabled and configured at program
+ * startup. See tests/main.c for an example.
+ */
+
+/**
+ * Checkpoint options.
+ */
+typedef enum git_win32_leakcheck_stacktrace_options {
+ /**
+ * Set checkpoint marker.
+ */
+ GIT_WIN32_LEAKCHECK_STACKTRACE_SET_MARK = (1 << 0),
+
+ /**
+ * Dump leaks since last checkpoint marker.
+ * May not be combined with _LEAKS_TOTAL.
+ *
+ * Note that this may generate false positives for global TLS
+ * error state and other global caches that aren't cleaned up
+ * until the thread/process terminates. So when using this
+ * around a region of interest, also check the final (at exit)
+ * dump before digging into leaks reported here.
+ */
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK = (1 << 1),
+
+ /**
+ * Dump leaks since init. May not be combined
+ * with _LEAKS_SINCE_MARK.
+ */
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_TOTAL = (1 << 2),
+
+ /**
+ * Suppress printing during dumps.
+ * Just return leak count.
+ */
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET = (1 << 3),
+
+} git_win32_leakcheck_stacktrace_options;
+
+/**
+ * Checkpoint memory state and/or dump unique stack traces of
+ * current memory leaks.
+ *
+ * @return number of unique leaks (relative to requested starting
+ * point) or error.
+ */
+int git_win32_leakcheck_stacktrace_dump(
+ git_win32_leakcheck_stacktrace_options opt,
+ const char *label);
+
+/**
+ * Construct stacktrace and append it to the global buffer.
+ * Return pointer to start of this string. On any error or
+ * lack of buffer space, just return the given file buffer
+ * so it will behave as usual.
+ *
+ * This should ONLY be called by our internal memory allocations
+ * routines.
+ */
+const char *git_win32_leakcheck_stacktrace(int skip, const char *file);
+
+#endif
+#endif
diff --git a/src/win32/w32_stack.c b/src/win32/w32_stack.c
deleted file mode 100644
index 78c78dbbd..000000000
--- a/src/win32/w32_stack.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "w32_stack.h"
-
-#if defined(GIT_MSVC_CRTDBG)
-#include "Windows.h"
-#include "Dbghelp.h"
-#include "win32/posix.h"
-#include "hash.h"
-
-static bool g_win32_stack_initialized = false;
-static HANDLE g_win32_stack_process = INVALID_HANDLE_VALUE;
-static git_win32__stack__aux_cb_alloc g_aux_cb_alloc = NULL;
-static git_win32__stack__aux_cb_lookup g_aux_cb_lookup = NULL;
-
-int git_win32__stack__set_aux_cb(
- git_win32__stack__aux_cb_alloc cb_alloc,
- git_win32__stack__aux_cb_lookup cb_lookup)
-{
- g_aux_cb_alloc = cb_alloc;
- g_aux_cb_lookup = cb_lookup;
-
- return 0;
-}
-
-void git_win32__stack_init(void)
-{
- if (!g_win32_stack_initialized) {
- g_win32_stack_process = GetCurrentProcess();
- SymSetOptions(SYMOPT_LOAD_LINES);
- SymInitialize(g_win32_stack_process, NULL, TRUE);
- g_win32_stack_initialized = true;
- }
-}
-
-void git_win32__stack_cleanup(void)
-{
- if (g_win32_stack_initialized) {
- SymCleanup(g_win32_stack_process);
- g_win32_stack_process = INVALID_HANDLE_VALUE;
- g_win32_stack_initialized = false;
- }
-}
-
-int git_win32__stack_capture(git_win32__stack__raw_data *pdata, int skip)
-{
- if (!g_win32_stack_initialized) {
- git_error_set(GIT_ERROR_INVALID, "git_win32_stack not initialized.");
- return GIT_ERROR;
- }
-
- memset(pdata, 0, sizeof(*pdata));
- pdata->nr_frames = RtlCaptureStackBackTrace(
- skip+1, GIT_WIN32__STACK__MAX_FRAMES, pdata->frames, NULL);
-
- /* If an "aux" data provider was registered, ask it to capture
- * whatever data it needs and give us an "aux_id" to it so that
- * we can refer to it later when reporting.
- */
- if (g_aux_cb_alloc)
- (g_aux_cb_alloc)(&pdata->aux_id);
-
- return 0;
-}
-
-int git_win32__stack_compare(
- git_win32__stack__raw_data *d1,
- git_win32__stack__raw_data *d2)
-{
- return memcmp(d1, d2, sizeof(*d1));
-}
-
-int git_win32__stack_format(
- char *pbuf, size_t buf_len,
- const git_win32__stack__raw_data *pdata,
- const char *prefix, const char *suffix)
-{
-#define MY_MAX_FILENAME 255
-
- /* SYMBOL_INFO has char FileName[1] at the end. The docs say to
- * to malloc it with extra space for your desired max filename.
- */
- struct {
- SYMBOL_INFO symbol;
- char extra[MY_MAX_FILENAME + 1];
- } s;
-
- IMAGEHLP_LINE64 line;
- size_t buf_used = 0;
- unsigned int k;
- char detail[MY_MAX_FILENAME * 2]; /* filename plus space for function name and formatting */
- size_t detail_len;
-
- if (!g_win32_stack_initialized) {
- git_error_set(GIT_ERROR_INVALID, "git_win32_stack not initialized.");
- return GIT_ERROR;
- }
-
- if (!prefix)
- prefix = "\t";
- if (!suffix)
- suffix = "\n";
-
- memset(pbuf, 0, buf_len);
-
- memset(&s, 0, sizeof(s));
- s.symbol.MaxNameLen = MY_MAX_FILENAME;
- s.symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
-
- memset(&line, 0, sizeof(line));
- line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-
- for (k=0; k < pdata->nr_frames; k++) {
- DWORD64 frame_k = (DWORD64)pdata->frames[k];
- DWORD dwUnused;
-
- if (SymFromAddr(g_win32_stack_process, frame_k, 0, &s.symbol) &&
- SymGetLineFromAddr64(g_win32_stack_process, frame_k, &dwUnused, &line)) {
- const char *pslash;
- const char *pfile;
-
- pslash = strrchr(line.FileName, '\\');
- pfile = ((pslash) ? (pslash+1) : line.FileName);
- p_snprintf(detail, sizeof(detail), "%s%s:%d> %s%s",
- prefix, pfile, line.LineNumber, s.symbol.Name, suffix);
- } else {
- /* This happens when we cross into another module.
- * For example, in CLAR tests, this is typically
- * the CRT startup code. Just print an unknown
- * frame and continue.
- */
- p_snprintf(detail, sizeof(detail), "%s??%s", prefix, suffix);
- }
- detail_len = strlen(detail);
-
- if (buf_len < (buf_used + detail_len + 1)) {
- /* we don't have room for this frame in the buffer, so just stop. */
- break;
- }
-
- memcpy(&pbuf[buf_used], detail, detail_len);
- buf_used += detail_len;
- }
-
- /* "aux_id" 0 is reserved to mean no aux data. This is needed to handle
- * allocs that occur before the aux callbacks were registered.
- */
- if (pdata->aux_id > 0) {
- p_snprintf(detail, sizeof(detail), "%saux_id: %d%s",
- prefix, pdata->aux_id, suffix);
- detail_len = strlen(detail);
- if ((buf_used + detail_len + 1) < buf_len) {
- memcpy(&pbuf[buf_used], detail, detail_len);
- buf_used += detail_len;
- }
-
- /* If an "aux" data provider is still registered, ask it to append its detailed
- * data to the end of ours using the "aux_id" it gave us when this de-duped
- * item was created.
- */
- if (g_aux_cb_lookup)
- (g_aux_cb_lookup)(pdata->aux_id, &pbuf[buf_used], (buf_len - buf_used - 1));
- }
-
- return GIT_OK;
-}
-
-int git_win32__stack(
- char * pbuf, size_t buf_len,
- int skip,
- const char *prefix, const char *suffix)
-{
- git_win32__stack__raw_data data;
- int error;
-
- if ((error = git_win32__stack_capture(&data, skip)) < 0)
- return error;
- if ((error = git_win32__stack_format(pbuf, buf_len, &data, prefix, suffix)) < 0)
- return error;
- return 0;
-}
-
-#endif
diff --git a/src/win32/w32_stack.h b/src/win32/w32_stack.h
deleted file mode 100644
index c2565c228..000000000
--- a/src/win32/w32_stack.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#ifndef INCLUDE_win32_w32_stack_h__
-#define INCLUDE_win32_w32_stack_h__
-
-#include "common.h"
-
-#if defined(GIT_MSVC_CRTDBG)
-
-/**
- * This type defines a callback to be used to augment a C stacktrace
- * with "aux" data. This can be used, for example, to allow LibGit2Sharp
- * (or other interpreted consumer libraries) to give us C# stacktrace
- * data for the PInvoke.
- *
- * This callback will be called during crtdbg-instrumented allocs.
- *
- * @param aux_id [out] A returned "aux_id" representing a unique
- * (de-duped at the C# layer) stacktrace. "aux_id" 0 is reserved
- * to mean no aux stacktrace data.
- */
-typedef void (*git_win32__stack__aux_cb_alloc)(unsigned int *aux_id);
-
-/**
- * This type defines a callback to be used to augment the output of
- * a stacktrace. This will be used to request the C# layer format
- * the C# stacktrace associated with "aux_id" into the provided
- * buffer.
- *
- * This callback will be called during leak reporting.
- *
- * @param aux_id The "aux_id" key associated with a stacktrace.
- * @param aux_msg A buffer where a formatted message should be written.
- * @param aux_msg_len The size of the buffer.
- */
-typedef void (*git_win32__stack__aux_cb_lookup)(unsigned int aux_id, char *aux_msg, size_t aux_msg_len);
-
-/**
- * Register an "aux" data provider to augment our C stacktrace data.
- *
- * This can be used, for example, to allow LibGit2Sharp (or other
- * interpreted consumer libraries) to give us the C# stacktrace of
- * the PInvoke.
- *
- * If you choose to use this feature, it should be registered during
- * initialization and not changed for the duration of the process.
- */
-GIT_EXTERN(int) git_win32__stack__set_aux_cb(
- git_win32__stack__aux_cb_alloc cb_alloc,
- git_win32__stack__aux_cb_lookup cb_lookup);
-
-/**
- * Maximum number of stackframes to record for a
- * single stacktrace.
- */
-#define GIT_WIN32__STACK__MAX_FRAMES 30
-
-/**
- * Wrapper containing the raw unprocessed stackframe
- * data for a single stacktrace and any "aux_id".
- *
- * I put the aux_id first so leaks will be sorted by it.
- * So, for example, if a specific callstack in C# leaks
- * a repo handle, all of the pointers within the associated
- * repo pointer will be grouped together.
- */
-typedef struct {
- unsigned int aux_id;
- unsigned int nr_frames;
- void *frames[GIT_WIN32__STACK__MAX_FRAMES];
-} git_win32__stack__raw_data;
-
-
-/**
- * Load symbol table data. This should be done in the primary
- * thread at startup (under a lock if there are other threads
- * active).
- */
-void git_win32__stack_init(void);
-
-/**
- * Cleanup symbol table data. This should be done in the
- * primary thead at shutdown (under a lock if there are other
- * threads active).
- */
-void git_win32__stack_cleanup(void);
-
-
-/**
- * Capture raw stack trace data for the current process/thread.
- *
- * @param skip Number of initial frames to skip. Pass 0 to
- * begin with the caller of this routine. Pass 1 to begin
- * with its caller. And so on.
- */
-int git_win32__stack_capture(git_win32__stack__raw_data *pdata, int skip);
-
-/**
- * Compare 2 raw stacktraces with the usual -1,0,+1 result.
- * This includes any "aux_id" values in the comparison, so that
- * our de-dup is also "aux" context relative.
- */
-int git_win32__stack_compare(
- git_win32__stack__raw_data *d1,
- git_win32__stack__raw_data *d2);
-
-/**
- * Format raw stacktrace data into buffer WITHOUT using any mallocs.
- *
- * @param prefix String written before each frame; defaults to "\t".
- * @param suffix String written after each frame; defaults to "\n".
- */
-int git_win32__stack_format(
- char *pbuf, size_t buf_len,
- const git_win32__stack__raw_data *pdata,
- const char *prefix, const char *suffix);
-
-/**
- * Convenience routine to capture and format stacktrace into
- * a buffer WITHOUT using any mallocs. This is primarily a
- * wrapper for testing.
- *
- * @param skip Number of initial frames to skip. Pass 0 to
- * begin with the caller of this routine. Pass 1 to begin
- * with its caller. And so on.
- * @param prefix String written before each frame; defaults to "\t".
- * @param suffix String written after each frame; defaults to "\n".
- */
-int git_win32__stack(
- char * pbuf, size_t buf_len,
- int skip,
- const char *prefix, const char *suffix);
-
-#endif /* GIT_MSVC_CRTDBG */
-#endif
diff --git a/src/win32/w32_util.h b/src/win32/w32_util.h
index d7f9d3da6..1321d30e6 100644
--- a/src/win32/w32_util.h
+++ b/src/win32/w32_util.h
@@ -74,8 +74,8 @@ GIT_INLINE(void) git_win32__filetime_to_timespec(
const FILETIME *ft,
struct timespec *ts)
{
- long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
- winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
+ int64_t winTime = ((int64_t)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
+ winTime -= INT64_C(116444736000000000); /* Windows to Unix Epoch conversion */
ts->tv_sec = (time_t)(winTime / 10000000);
#ifdef GIT_USE_NSEC
ts->tv_nsec = (winTime % 10000000) * 100;
@@ -87,11 +87,11 @@ GIT_INLINE(void) git_win32__filetime_to_timespec(
GIT_INLINE(void) git_win32__timeval_to_filetime(
FILETIME *ft, const struct p_timeval tv)
{
- long long ticks = (tv.tv_sec * 10000000LL) +
- (tv.tv_usec * 10LL) + 116444736000000000LL;
+ int64_t ticks = (tv.tv_sec * INT64_C(10000000)) +
+ (tv.tv_usec * INT64_C(10)) + INT64_C(116444736000000000);
- ft->dwHighDateTime = ((ticks >> 32) & 0xffffffffLL);
- ft->dwLowDateTime = (ticks & 0xffffffffLL);
+ ft->dwHighDateTime = ((ticks >> 32) & INT64_C(0xffffffff));
+ ft->dwLowDateTime = (ticks & INT64_C(0xffffffff));
}
GIT_INLINE(void) git_win32__stat_init(
diff --git a/src/worktree.c b/src/worktree.c
index fda9b0b71..fe8db7743 100644
--- a/src/worktree.c
+++ b/src/worktree.c
@@ -37,12 +37,13 @@ int git_worktree_list(git_strarray *wts, git_repository *repo)
size_t i, len;
int error;
- assert(wts && repo);
+ GIT_ASSERT_ARG(wts);
+ GIT_ASSERT_ARG(repo);
wts->count = 0;
wts->strings = NULL;
- if ((error = git_buf_printf(&path, "%s/worktrees/", repo->commondir)) < 0)
+ if ((error = git_buf_joinpath(&path, repo->commondir, "worktrees/")) < 0)
goto exit;
if (!git_path_exists(path.ptr) || git_path_is_empty_dir(path.ptr))
goto exit;
@@ -73,7 +74,8 @@ char *git_worktree__read_link(const char *base, const char *file)
{
git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
- assert(base && file);
+ GIT_ASSERT_ARG_WITH_RETVAL(base, NULL);
+ GIT_ASSERT_ARG_WITH_RETVAL(file, NULL);
if (git_buf_joinpath(&path, base, file) < 0)
goto err;
@@ -106,7 +108,9 @@ static int write_wtfile(const char *base, const char *file, const git_buf *buf)
git_buf path = GIT_BUF_INIT;
int err;
- assert(base && file && buf);
+ GIT_ASSERT_ARG(base);
+ GIT_ASSERT_ARG(file);
+ GIT_ASSERT_ARG(buf);
if ((err = git_buf_joinpath(&path, base, file)) < 0)
goto out;
@@ -131,6 +135,9 @@ static int open_worktree_dir(git_worktree **out, const char *parent, const char
goto out;
}
+ if ((error = git_path_validate_workdir(NULL, dir)) < 0)
+ goto out;
+
if ((wt = git__calloc(1, sizeof(*wt))) == NULL) {
error = -1;
goto out;
@@ -170,11 +177,12 @@ int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *na
git_worktree *wt = NULL;
int error;
- assert(repo && name);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
*out = NULL;
- if ((error = git_buf_printf(&path, "%s/worktrees/%s", repo->commondir, name)) < 0)
+ if ((error = git_buf_join3(&path, '/', repo->commondir, "worktrees", name)) < 0)
goto out;
if ((error = (open_worktree_dir(out, git_repository_workdir(repo), path.ptr, name))) < 0)
@@ -237,7 +245,7 @@ void git_worktree_free(git_worktree *wt)
int git_worktree_validate(const git_worktree *wt)
{
- assert(wt);
+ GIT_ASSERT_ARG(wt);
if (!is_worktree_dir(wt->gitdir_path)) {
git_error_set(GIT_ERROR_WORKTREE,
@@ -260,6 +268,13 @@ int git_worktree_validate(const git_worktree *wt)
return GIT_ERROR;
}
+ if (!git_path_exists(wt->worktree_path)) {
+ git_error_set(GIT_ERROR_WORKTREE,
+ "worktree directory '%s' does not exist",
+ wt->worktree_path);
+ return GIT_ERROR;
+ }
+
return 0;
}
@@ -297,7 +312,10 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
if (opts)
memcpy(&wtopts, opts, sizeof(wtopts));
- assert(out && repo && name && worktree);
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(repo);
+ GIT_ASSERT_ARG(name);
+ GIT_ASSERT_ARG(worktree);
*out = NULL;
@@ -410,7 +428,7 @@ int git_worktree_lock(git_worktree *wt, const char *reason)
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
int error;
- assert(wt);
+ GIT_ASSERT_ARG(wt);
if ((error = git_worktree_is_locked(NULL, wt)) < 0)
goto out;
@@ -441,7 +459,7 @@ int git_worktree_unlock(git_worktree *wt)
git_buf path = GIT_BUF_INIT;
int error;
- assert(wt);
+ GIT_ASSERT_ARG(wt);
if ((error = git_worktree_is_locked(NULL, wt)) < 0)
return error;
@@ -468,7 +486,7 @@ int git_worktree_is_locked(git_buf *reason, const git_worktree *wt)
git_buf path = GIT_BUF_INIT;
int error, locked;
- assert(wt);
+ GIT_ASSERT_ARG(wt);
if (reason)
git_buf_clear(reason);
@@ -489,13 +507,13 @@ out:
const char *git_worktree_name(const git_worktree *wt)
{
- assert(wt);
+ GIT_ASSERT_ARG_WITH_RETVAL(wt, NULL);
return wt->name;
}
const char *git_worktree_path(const git_worktree *wt)
{
- assert(wt);
+ GIT_ASSERT_ARG_WITH_RETVAL(wt, NULL);
return wt->worktree_path;
}
@@ -574,7 +592,7 @@ int git_worktree_prune(git_worktree *wt,
}
/* Delete gitdir in parent repository */
- if ((err = git_buf_printf(&path, "%s/worktrees/%s", wt->commondir_path, wt->name)) < 0)
+ if ((err = git_buf_join3(&path, '/', wt->commondir_path, "worktrees", wt->name)) < 0)
goto out;
if (!git_path_exists(path.ptr))
{
diff --git a/src/zstream.c b/src/zstream.c
index 975ead2f6..a5675676e 100644
--- a/src/zstream.c
+++ b/src/zstream.c
@@ -156,7 +156,7 @@ int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream)
}
/* either we finished the input or we did not flush the data */
- assert(zstream->in_len > 0 || zstream->flush == Z_FINISH);
+ GIT_ASSERT(zstream->in_len > 0 || zstream->flush == Z_FINISH);
/* set out_size to number of bytes actually written to output */
*out_len = *out_len - out_remain;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 6f8a18ec0..49999f481 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,3 +1,4 @@
+SET(Python_ADDITIONAL_VERSIONS 3 2.7)
FIND_PACKAGE(PythonInterp)
IF(NOT PYTHONINTERP_FOUND)
@@ -9,6 +10,7 @@ SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/resources/")
SET(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
ADD_DEFINITIONS(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\")
ADD_DEFINITIONS(-DCLAR_TMPDIR=\"libgit2_tests\")
+ADD_DEFINITIONS(-DCLAR_WIN32_LONGPATHS)
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
# Ensure that we do not use deprecated functions internally
@@ -62,7 +64,8 @@ ENDFUNCTION(ADD_CLAR_TEST)
ADD_CLAR_TEST(offline -v -xonline)
ADD_CLAR_TEST(invasive -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
-ADD_CLAR_TEST(online -v -sonline)
+ADD_CLAR_TEST(online -v -sonline -xonline::customcert)
+ADD_CLAR_TEST(online_customcert -v -sonline::customcert)
ADD_CLAR_TEST(gitdaemon -v -sonline::push)
ADD_CLAR_TEST(ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh)
ADD_CLAR_TEST(proxy -v -sonline::clone::proxy)
diff --git a/tests/apply/apply_helpers.h b/tests/apply/apply_helpers.h
index 2d0019abf..82094773e 100644
--- a/tests/apply/apply_helpers.h
+++ b/tests/apply/apply_helpers.h
@@ -474,6 +474,15 @@
"-asparagus which had been laid by, boil it until these last articles are\n" \
"-sufficiently done, thicken with flour, butter and milk, and serve it up.\n"
+#define DIFF_ADD_INVALID_FILENAME \
+ "diff --git a/.git/hello_world.txt b/.git/hello_world.txt\n" \
+ "new file mode 100644\n" \
+ "index 0000000..f75ba05\n" \
+ "--- /dev/null\n" \
+ "+++ b/.git/hello_world.txt\n" \
+ "@@ -0,0 +1 @@\n" \
+ "+Hello, world.\n"
+
void validate_apply_workdir(
git_repository *repo,
struct merge_index_entry *workdir_entries,
diff --git a/tests/apply/both.c b/tests/apply/both.c
index 400df5e38..108963270 100644
--- a/tests/apply/both.c
+++ b/tests/apply/both.c
@@ -734,3 +734,14 @@ void test_apply_both__cant_remove_file_twice(void)
git_diff_free(diff);
}
+
+void test_apply_both__cant_add_invalid_filename(void)
+{
+ git_diff *diff;
+
+ cl_git_pass(git_diff_from_buffer(&diff, DIFF_ADD_INVALID_FILENAME,
+ strlen(DIFF_ADD_INVALID_FILENAME)));
+ cl_git_fail(git_apply(repo, diff, GIT_APPLY_LOCATION_BOTH, NULL));
+
+ git_diff_free(diff);
+}
diff --git a/tests/apply/fromdiff.c b/tests/apply/fromdiff.c
index e9329f6d3..69dfe0987 100644
--- a/tests/apply/fromdiff.c
+++ b/tests/apply/fromdiff.c
@@ -3,7 +3,6 @@
#include "apply.h"
#include "repository.h"
-#include "buf_text.h"
#include "../patch/patch_common.h"
diff --git a/tests/apply/fromfile.c b/tests/apply/fromfile.c
index 477e283ad..ae519eab0 100644
--- a/tests/apply/fromfile.c
+++ b/tests/apply/fromfile.c
@@ -5,7 +5,6 @@
#include "patch.h"
#include "patch_parse.h"
#include "repository.h"
-#include "buf_text.h"
#include "../patch/patch_common.h"
diff --git a/tests/apply/partial.c b/tests/apply/partial.c
index 466a92717..548faaadb 100644
--- a/tests/apply/partial.c
+++ b/tests/apply/partial.c
@@ -3,7 +3,6 @@
#include "apply.h"
#include "repository.h"
-#include "buf_text.h"
#include "../patch/patch_common.h"
diff --git a/tests/attr/lookup.c b/tests/attr/lookup.c
index 6063468cb..f19f38fbb 100644
--- a/tests/attr/lookup.c
+++ b/tests/attr/lookup.c
@@ -236,6 +236,7 @@ void test_attr_lookup__check_attr_examples(void)
void test_attr_lookup__from_buffer(void)
{
git_attr_file *file;
+ git_attr_file_source source = {0};
struct attr_expected cases[] = {
{ "abc", "foo", EXPECT_TRUE, NULL },
@@ -250,7 +251,7 @@ void test_attr_lookup__from_buffer(void)
{ NULL, NULL, 0, NULL }
};
- cl_git_pass(git_attr_file__new(&file, NULL, 0));
+ cl_git_pass(git_attr_file__new(&file, NULL, &source));
cl_git_pass(git_attr_file__parse_buffer(NULL, file, "a* foo\nabc bar\n* baz", true));
diff --git a/tests/attr/repo.c b/tests/attr/repo.c
index 36beeb095..eabc033eb 100644
--- a/tests/attr/repo.c
+++ b/tests/attr/repo.c
@@ -71,11 +71,11 @@ void test_attr_repo__get_one(void)
}
cl_assert(git_attr_cache__is_cached(
- g_repo, GIT_ATTR_FILE__FROM_FILE, ".git/info/attributes"));
+ g_repo, GIT_ATTR_FILE_SOURCE_FILE, ".git/info/attributes"));
cl_assert(git_attr_cache__is_cached(
- g_repo, GIT_ATTR_FILE__FROM_FILE, ".gitattributes"));
+ g_repo, GIT_ATTR_FILE_SOURCE_FILE, ".gitattributes"));
cl_assert(git_attr_cache__is_cached(
- g_repo, GIT_ATTR_FILE__FROM_FILE, "sub/.gitattributes"));
+ g_repo, GIT_ATTR_FILE_SOURCE_FILE, "sub/.gitattributes"));
}
void test_attr_repo__get_one_start_deep(void)
@@ -92,11 +92,11 @@ void test_attr_repo__get_one_start_deep(void)
}
cl_assert(git_attr_cache__is_cached(
- g_repo, GIT_ATTR_FILE__FROM_FILE, ".git/info/attributes"));
+ g_repo, GIT_ATTR_FILE_SOURCE_FILE, ".git/info/attributes"));
cl_assert(git_attr_cache__is_cached(
- g_repo, GIT_ATTR_FILE__FROM_FILE, ".gitattributes"));
+ g_repo, GIT_ATTR_FILE_SOURCE_FILE, ".gitattributes"));
cl_assert(git_attr_cache__is_cached(
- g_repo, GIT_ATTR_FILE__FROM_FILE, "sub/.gitattributes"));
+ g_repo, GIT_ATTR_FILE_SOURCE_FILE, "sub/.gitattributes"));
}
void test_attr_repo__get_many(void)
@@ -341,7 +341,7 @@ void test_attr_repo__sysdir_with_session(void)
g_repo = cl_git_sandbox_reopen();
cl_git_pass(git_attr_session__init(&session, g_repo));
- cl_git_pass(git_attr_get_many_with_session(values, g_repo, &session, 0, "file", ARRAY_SIZE(attrs), attrs));
+ cl_git_pass(git_attr_get_many_with_session(values, g_repo, &session, NULL, "file", ARRAY_SIZE(attrs), attrs));
cl_assert_equal_s(values[0], "1");
cl_assert_equal_s(values[1], "2");
diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c
index 380d25101..3241a3eb7 100644
--- a/tests/checkout/tree.c
+++ b/tests/checkout/tree.c
@@ -917,7 +917,7 @@ void test_checkout_tree__extremely_long_file_name(void)
{
/* A utf-8 string with 83 characters, but 249 bytes. */
const char *longname = "\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97";
- char path[1024];
+ char path[1024] = {0};
g_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
cl_git_pass(git_revparse_single(&g_object, g_repo, "long-file-name"));
@@ -1636,3 +1636,49 @@ void test_checkout_tree__no_index_refresh(void)
modify_index_and_checkout_tree(&opts);
assert_status_entrycount(g_repo, 0);
}
+
+void test_checkout_tree__dry_run(void)
+{
+ git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
+ git_oid oid;
+ git_object *obj = NULL;
+ checkout_counts ct;
+
+ /* first let's get things into a known state - by checkout out the HEAD */
+
+ assert_on_branch(g_repo, "master");
+
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+ cl_git_pass(git_checkout_head(g_repo, &opts));
+
+ cl_assert(!git_path_isdir("testrepo/a"));
+
+ check_file_contents_nocr("testrepo/branch_file.txt", "hi\nbye!\n");
+
+ /* now checkout branch but with dry run enabled */
+
+ memset(&ct, 0, sizeof(ct));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_DRY_RUN;
+ opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL;
+ opts.notify_cb = checkout_count_callback;
+ opts.notify_payload = &ct;
+
+ cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir"));
+ cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJECT_ANY));
+
+ cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
+
+ assert_on_branch(g_repo, "dir");
+
+ /* these normally would have been created and updated, but with
+ * DRY_RUN they will be unchanged.
+ */
+ cl_assert(!git_path_isdir("testrepo/a"));
+ check_file_contents_nocr("testrepo/branch_file.txt", "hi\nbye!\n");
+
+ /* check that notify callback was invoked */
+ cl_assert_equal_i(ct.n_updates, 2);
+
+ git_object_free(obj);
+}
diff --git a/tests/clar/fs.h b/tests/clar/fs.h
index 87d345132..44ede4572 100644
--- a/tests/clar/fs.h
+++ b/tests/clar/fs.h
@@ -8,6 +8,12 @@
#ifdef _WIN32
+#ifdef CLAR_WIN32_LONGPATHS
+# define CLAR_MAX_PATH 4096
+#else
+# define CLAR_MAX_PATH MAX_PATH
+#endif
+
#define RM_RETRY_COUNT 5
#define RM_RETRY_DELAY 10
@@ -48,21 +54,48 @@ fs_rmdir_rmdir(WCHAR *_wpath)
return 0;
}
+static void translate_path(WCHAR *path, size_t path_size)
+{
+ size_t path_len, i;
+
+ if (wcsncmp(path, L"\\\\?\\", 4) == 0)
+ return;
+
+ path_len = wcslen(path);
+ cl_assert(path_size > path_len + 4);
+
+ for (i = path_len; i > 0; i--) {
+ WCHAR c = path[i - 1];
+
+ if (c == L'/')
+ path[i + 3] = L'\\';
+ else
+ path[i + 3] = path[i - 1];
+ }
+
+ path[0] = L'\\';
+ path[1] = L'\\';
+ path[2] = L'?';
+ path[3] = L'\\';
+ path[path_len + 4] = L'\0';
+}
+
static void
fs_rmdir_helper(WCHAR *_wsource)
{
- WCHAR buffer[MAX_PATH];
+ WCHAR buffer[CLAR_MAX_PATH];
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
size_t buffer_prefix_len;
/* Set up the buffer and capture the length */
- wcscpy_s(buffer, MAX_PATH, _wsource);
- wcscat_s(buffer, MAX_PATH, L"\\");
+ wcscpy_s(buffer, CLAR_MAX_PATH, _wsource);
+ translate_path(buffer, CLAR_MAX_PATH);
+ wcscat_s(buffer, CLAR_MAX_PATH, L"\\");
buffer_prefix_len = wcslen(buffer);
/* FindFirstFile needs a wildcard to match multiple items */
- wcscat_s(buffer, MAX_PATH, L"*");
+ wcscat_s(buffer, CLAR_MAX_PATH, L"*");
find_handle = FindFirstFileW(buffer, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);
@@ -72,7 +105,7 @@ fs_rmdir_helper(WCHAR *_wsource)
if (fs__dotordotdot(find_data.cFileName))
continue;
- wcscpy_s(buffer + buffer_prefix_len, MAX_PATH - buffer_prefix_len, find_data.cFileName);
+ wcscpy_s(buffer + buffer_prefix_len, CLAR_MAX_PATH - buffer_prefix_len, find_data.cFileName);
if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
fs_rmdir_helper(buffer);
@@ -123,7 +156,7 @@ fs_rm_wait(WCHAR *_wpath)
static void
fs_rm(const char *_source)
{
- WCHAR wsource[MAX_PATH];
+ WCHAR wsource[CLAR_MAX_PATH];
DWORD attrs;
/* The input path is UTF-8. Convert it to wide characters
@@ -133,7 +166,9 @@ fs_rm(const char *_source)
_source,
-1, /* Indicates NULL termination */
wsource,
- MAX_PATH));
+ CLAR_MAX_PATH));
+
+ translate_path(wsource, CLAR_MAX_PATH);
/* Does the item exist? If not, we have no work to do */
attrs = GetFileAttributesW(wsource);
@@ -158,21 +193,23 @@ fs_rm(const char *_source)
static void
fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
{
- WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH];
+ WCHAR buf_source[CLAR_MAX_PATH], buf_dest[CLAR_MAX_PATH];
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
size_t buf_source_prefix_len, buf_dest_prefix_len;
- wcscpy_s(buf_source, MAX_PATH, _wsource);
- wcscat_s(buf_source, MAX_PATH, L"\\");
+ wcscpy_s(buf_source, CLAR_MAX_PATH, _wsource);
+ wcscat_s(buf_source, CLAR_MAX_PATH, L"\\");
+ translate_path(buf_source, CLAR_MAX_PATH);
buf_source_prefix_len = wcslen(buf_source);
- wcscpy_s(buf_dest, MAX_PATH, _wdest);
- wcscat_s(buf_dest, MAX_PATH, L"\\");
+ wcscpy_s(buf_dest, CLAR_MAX_PATH, _wdest);
+ wcscat_s(buf_dest, CLAR_MAX_PATH, L"\\");
+ translate_path(buf_dest, CLAR_MAX_PATH);
buf_dest_prefix_len = wcslen(buf_dest);
/* Get an enumerator for the items in the source. */
- wcscat_s(buf_source, MAX_PATH, L"*");
+ wcscat_s(buf_source, CLAR_MAX_PATH, L"*");
find_handle = FindFirstFileW(buf_source, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);
@@ -185,8 +222,8 @@ fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
if (fs__dotordotdot(find_data.cFileName))
continue;
- wcscpy_s(buf_source + buf_source_prefix_len, MAX_PATH - buf_source_prefix_len, find_data.cFileName);
- wcscpy_s(buf_dest + buf_dest_prefix_len, MAX_PATH - buf_dest_prefix_len, find_data.cFileName);
+ wcscpy_s(buf_source + buf_source_prefix_len, CLAR_MAX_PATH - buf_source_prefix_len, find_data.cFileName);
+ wcscpy_s(buf_dest + buf_dest_prefix_len, CLAR_MAX_PATH - buf_dest_prefix_len, find_data.cFileName);
if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
fs_copydir_helper(buf_source, buf_dest);
@@ -205,7 +242,7 @@ fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
static void
fs_copy(const char *_source, const char *_dest)
{
- WCHAR wsource[MAX_PATH], wdest[MAX_PATH];
+ WCHAR wsource[CLAR_MAX_PATH], wdest[CLAR_MAX_PATH];
DWORD source_attrs, dest_attrs;
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
@@ -217,14 +254,17 @@ fs_copy(const char *_source, const char *_dest)
_source,
-1,
wsource,
- MAX_PATH));
+ CLAR_MAX_PATH));
cl_assert(MultiByteToWideChar(CP_UTF8,
MB_ERR_INVALID_CHARS,
_dest,
-1,
wdest,
- MAX_PATH));
+ CLAR_MAX_PATH));
+
+ translate_path(wsource, CLAR_MAX_PATH);
+ translate_path(wdest, CLAR_MAX_PATH);
/* Check the source for existence */
source_attrs = GetFileAttributesW(wsource);
@@ -238,8 +278,8 @@ fs_copy(const char *_source, const char *_dest)
* Use FindFirstFile to parse the path */
find_handle = FindFirstFileW(wsource, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);
- wcscat_s(wdest, MAX_PATH, L"\\");
- wcscat_s(wdest, MAX_PATH, find_data.cFileName);
+ wcscat_s(wdest, CLAR_MAX_PATH, L"\\");
+ wcscat_s(wdest, CLAR_MAX_PATH, find_data.cFileName);
FindClose(find_handle);
/* Check the new target for existence */
@@ -273,7 +313,7 @@ cl_fs_cleanup(void)
# include <sys/sendfile.h>
#endif
-#if defined(__APPLE__) || defined(__FreeBSD__)
+#if defined(__APPLE__)
# include <copyfile.h>
#endif
@@ -356,7 +396,7 @@ fs_copyfile_helper(const char *source, size_t source_len, const char *dest, int
cl_must_pass((in = open(source, O_RDONLY)));
cl_must_pass((out = open(dest, O_WRONLY|O_CREAT|O_TRUNC, dest_mode)));
-#if USE_FCOPYFILE && (defined(__APPLE__) || defined(__FreeBSD__))
+#if USE_FCOPYFILE && defined(__APPLE__)
((void)(source_len)); /* unused */
cl_must_pass(fcopyfile(in, out, 0, COPYFILE_DATA));
#elif USE_SENDFILE && defined(__linux__)
@@ -396,7 +436,7 @@ static void
fs_copy(const char *source, const char *_dest)
{
char *dbuf = NULL;
- const char *dest;
+ const char *dest = NULL;
struct stat source_st, dest_st;
cl_must_pass_(lstat(source, &source_st), "Failed to stat copy source");
diff --git a/tests/clar/sandbox.h b/tests/clar/sandbox.h
index 2114819e4..0ba147962 100644
--- a/tests/clar/sandbox.h
+++ b/tests/clar/sandbox.h
@@ -2,7 +2,7 @@
#include <sys/syslimits.h>
#endif
-static char _clar_path[4096];
+static char _clar_path[4096 + 1];
static int
is_valid_tmp_path(const char *path)
@@ -39,7 +39,8 @@ find_tmp_path(char *buffer, size_t length)
if (length >= PATH_MAX && realpath(env, buffer) != NULL)
return 0;
#endif
- strncpy(buffer, env, length);
+ strncpy(buffer, env, length - 1);
+ buffer[length - 1] = '\0';
return 0;
}
}
@@ -50,7 +51,8 @@ find_tmp_path(char *buffer, size_t length)
if (length >= PATH_MAX && realpath("/tmp", buffer) != NULL)
return 0;
#endif
- strncpy(buffer, "/tmp", length);
+ strncpy(buffer, "/tmp", length - 1);
+ buffer[length - 1] = '\0';
return 0;
}
@@ -65,7 +67,8 @@ find_tmp_path(char *buffer, size_t length)
/* This system doesn't like us, try to use the current directory */
if (is_valid_tmp_path(".")) {
- strncpy(buffer, ".", length);
+ strncpy(buffer, ".", length - 1);
+ buffer[length - 1] = '\0';
return 0;
}
diff --git a/tests/clar_libgit2.c b/tests/clar_libgit2.c
index 65b8923f5..c4550c32a 100644
--- a/tests/clar_libgit2.c
+++ b/tests/clar_libgit2.c
@@ -275,7 +275,7 @@ const char* cl_git_fixture_url(const char *fixturename)
const char* cl_git_path_url(const char *path)
{
- static char url[4096];
+ static char url[4096 + 1];
const char *in_buf;
git_buf path_buf = GIT_BUF_INIT;
@@ -311,9 +311,10 @@ const char* cl_git_path_url(const char *path)
in_buf++;
}
- cl_assert(url_buf.size < 4096);
+ cl_assert(url_buf.size < sizeof(url) - 1);
- strncpy(url, git_buf_cstr(&url_buf), 4096);
+ strncpy(url, git_buf_cstr(&url_buf), sizeof(url) - 1);
+ url[sizeof(url) - 1] = '\0';
git_buf_dispose(&url_buf);
git_buf_dispose(&path_buf);
return url;
diff --git a/tests/clar_libgit2_trace.c b/tests/clar_libgit2_trace.c
index d4d8d2c37..8eb6d4e8d 100644
--- a/tests/clar_libgit2_trace.c
+++ b/tests/clar_libgit2_trace.c
@@ -164,7 +164,7 @@ void _cl_trace_cb__event_handler(
switch (ev) {
case CL_TRACE__SUITE_BEGIN:
git_trace(GIT_TRACE_TRACE, "\n\n%s\n%s: Begin Suite", HR, suite_name);
-#if 0 && defined(GIT_MSVC_CRTDBG)
+#if 0 && defined(GIT_WIN32_LEAKCHECK)
git_win32__crtdbg_stacktrace__dump(
GIT_WIN32__CRTDBG_STACKTRACE__SET_MARK,
suite_name);
@@ -172,7 +172,7 @@ void _cl_trace_cb__event_handler(
break;
case CL_TRACE__SUITE_END:
-#if 0 && defined(GIT_MSVC_CRTDBG)
+#if 0 && defined(GIT_WIN32_LEAKCHECK)
/* As an example of checkpointing, dump leaks within this suite.
* This may generate false positives for things like the global
* TLS error state and maybe the odb cache since they aren't
diff --git a/tests/clone/empty.c b/tests/clone/empty.c
index 8e59d2b8c..94847bc73 100644
--- a/tests/clone/empty.c
+++ b/tests/clone/empty.c
@@ -2,6 +2,7 @@
#include "git2/clone.h"
#include "repository.h"
+#include "repo/repo_helpers.h"
static git_clone_options g_options;
static git_repository *g_repo;
@@ -22,6 +23,7 @@ void test_clone_empty__initialize(void)
void test_clone_empty__cleanup(void)
{
+ cl_fixture_cleanup("tmp_global_path");
cl_git_sandbox_cleanup();
}
@@ -66,6 +68,21 @@ void test_clone_empty__can_clone_an_empty_local_repo_barely(void)
expected_tracked_branch_name));
}
+void test_clone_empty__respects_initialbranch_config(void)
+{
+ git_buf buf = GIT_BUF_INIT;
+
+ create_tmp_global_config("tmp_global_path", "init.defaultbranch", "my_default_branch");
+
+ cl_set_cleanup(&cleanup_repository, "./empty");
+
+ g_options.bare = true;
+ cl_git_pass(git_clone(&g_repo_cloned, "./empty_bare.git", "./empty", &g_options));
+ cl_git_pass(git_branch_upstream_name(&buf, g_repo_cloned, "refs/heads/my_default_branch"));
+ cl_assert_equal_s("refs/remotes/origin/my_default_branch", buf.ptr);
+ git_buf_dispose(&buf);
+}
+
void test_clone_empty__can_clone_an_empty_local_repo(void)
{
cl_set_cleanup(&cleanup_repository, "./empty");
diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c
index 7ca49085c..ec12fee18 100644
--- a/tests/clone/nonetwork.c
+++ b/tests/clone/nonetwork.c
@@ -158,6 +158,8 @@ void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void)
void test_clone_nonetwork__can_checkout_given_branch(void)
{
+ git_reference *remote_head;
+
g_options.checkout_branch = "test";
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
@@ -167,6 +169,12 @@ void test_clone_nonetwork__can_checkout_given_branch(void)
cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test");
cl_assert(git_path_exists("foo/readme.txt"));
+
+ cl_git_pass(git_reference_lookup(&remote_head, g_repo, "refs/remotes/origin/HEAD"));
+ cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(remote_head));
+ cl_assert_equal_s("refs/remotes/origin/master", git_reference_symbolic_target(remote_head));
+
+ git_reference_free(remote_head);
}
static int clone_cancel_fetch_transfer_progress_cb(
diff --git a/tests/config/include.c b/tests/config/include.c
index e2b0fc96c..b702d6211 100644
--- a/tests/config/include.c
+++ b/tests/config/include.c
@@ -178,6 +178,30 @@ void test_config_include__rewriting_include_refreshes_values(void)
cl_git_pass(p_unlink("second"));
}
+void test_config_include__rewriting_include_twice_refreshes_values(void)
+{
+ cl_git_mkfile("top-level", "[include]\npath = included");
+ cl_git_mkfile("included", "[foo]\nbar = first-value");
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
+ cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
+
+ git_buf_clear(&buf);
+ cl_git_mkfile("included", "[foo]\nother = value2");
+ cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
+ cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.other"));
+ cl_assert_equal_s(buf.ptr, "value2");
+
+ git_buf_clear(&buf);
+ cl_git_mkfile("included", "[foo]\nanother = bar");
+ cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.other"));
+ cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.another"));
+ cl_assert_equal_s(buf.ptr, "bar");
+
+ cl_git_pass(p_unlink("top-level"));
+ cl_git_pass(p_unlink("included"));
+}
+
void test_config_include__included_variables_cannot_be_deleted(void)
{
cl_git_mkfile("top-level", "[include]\npath = included\n");
diff --git a/tests/config/read.c b/tests/config/read.c
index ba97302f7..8d1bb8b0a 100644
--- a/tests/config/read.c
+++ b/tests/config/read.c
@@ -213,6 +213,13 @@ void test_config_read__symbol_headers(void)
git_config_free(cfg);
}
+void test_config_read__multiline_multiple_quoted_comment_chars(void)
+{
+ git_config *cfg;
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config21")));
+ git_config_free(cfg);
+}
+
void test_config_read__header_in_last_line(void)
{
git_config *cfg;
@@ -928,3 +935,79 @@ void test_config_read__nosection(void)
git_buf_dispose(&buf);
git_config_free(cfg);
}
+
+enum {
+ MAP_TRUE = 0,
+ MAP_FALSE = 1,
+ MAP_ALWAYS = 2
+};
+
+static git_configmap _test_map1[] = {
+ {GIT_CONFIGMAP_STRING, "always", MAP_ALWAYS},
+ {GIT_CONFIGMAP_FALSE, NULL, MAP_FALSE},
+ {GIT_CONFIGMAP_TRUE, NULL, MAP_TRUE},
+};
+
+static git_configmap _test_map2[] = {
+ {GIT_CONFIGMAP_INT32, NULL, 0},
+};
+
+void test_config_read__get_mapped(void)
+{
+ git_config *cfg;
+ int val;
+ int known_good;
+
+ cl_set_cleanup(&clean_test_config, NULL);
+ cl_git_mkfile("./testconfig", "[header]\n"
+ " key1 = 1\n"
+ " key2 = true\n"
+ " key3\n"
+ " key4 = always\n"
+ " key5 = false\n"
+ " key6 = 0\n"
+ " key7 = never\n"
+ " key8 = On\n"
+ " key9 = off\n");
+ cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
+
+ /* check parsing bool and string */
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key1", _test_map1, ARRAY_SIZE(_test_map1)));
+ cl_assert_equal_i(val, MAP_TRUE);
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key2", _test_map1, ARRAY_SIZE(_test_map1)));
+ cl_assert_equal_i(val, MAP_TRUE);
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key3", _test_map1, ARRAY_SIZE(_test_map1)));
+ cl_assert_equal_i(val, MAP_TRUE);
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key8", _test_map1, ARRAY_SIZE(_test_map1)));
+ cl_assert_equal_i(val, MAP_TRUE);
+
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key4", _test_map1, ARRAY_SIZE(_test_map1)));
+ cl_assert_equal_i(val, MAP_ALWAYS);
+
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key5", _test_map1, ARRAY_SIZE(_test_map1)));
+ cl_assert_equal_i(val, MAP_FALSE);
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key6", _test_map1, ARRAY_SIZE(_test_map1)));
+ cl_assert_equal_i(val, MAP_FALSE);
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key9", _test_map1, ARRAY_SIZE(_test_map1)));
+ cl_assert_equal_i(val, MAP_FALSE);
+
+ cl_git_fail(git_config_get_mapped(&val, cfg, "header.key7", _test_map1, ARRAY_SIZE(_test_map1)));
+
+ /* check parsing int values */
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key1", _test_map2, ARRAY_SIZE(_test_map2)));
+ cl_git_pass(git_config_get_int32(&known_good, cfg, "header.key1"));
+ cl_assert_equal_i(val, known_good);
+ cl_git_pass(git_config_get_mapped(&val, cfg, "header.key6", _test_map2, ARRAY_SIZE(_test_map2)));
+ cl_git_pass(git_config_get_int32(&known_good, cfg, "header.key6"));
+ cl_assert_equal_i(val, known_good);
+
+ cl_git_fail(git_config_get_mapped(&val, cfg, "header.key2", _test_map2, ARRAY_SIZE(_test_map2)));
+ cl_git_fail(git_config_get_mapped(&val, cfg, "header.key3", _test_map2, ARRAY_SIZE(_test_map2)));
+ cl_git_fail(git_config_get_mapped(&val, cfg, "header.key4", _test_map2, ARRAY_SIZE(_test_map2)));
+ cl_git_fail(git_config_get_mapped(&val, cfg, "header.key5", _test_map2, ARRAY_SIZE(_test_map2)));
+ cl_git_fail(git_config_get_mapped(&val, cfg, "header.key7", _test_map2, ARRAY_SIZE(_test_map2)));
+ cl_git_fail(git_config_get_mapped(&val, cfg, "header.key8", _test_map2, ARRAY_SIZE(_test_map2)));
+ cl_git_fail(git_config_get_mapped(&val, cfg, "header.key9", _test_map2, ARRAY_SIZE(_test_map2)));
+
+ git_config_free(cfg);
+}
diff --git a/tests/config/stress.c b/tests/config/stress.c
index 28c3c4ac0..577452e8d 100644
--- a/tests/config/stress.c
+++ b/tests/config/stress.c
@@ -59,6 +59,11 @@ void test_config_stress__comments(void)
assert_config_value(config, "some.section.multi", "hi, this is a ; multiline comment # with ;\n special chars and other stuff !@#");
assert_config_value(config, "some.section.multi2", "good, this is a ; multiline comment # with ;\n special chars and other stuff !@#");
assert_config_value(config, "some.section.back", "this is \ba phrase");
+ assert_config_value(config, "some.section.dollar", "some $sign");
+ assert_config_value(config, "some.section.multiquotes", "!ls x ls # comment2 $HOME");
+ assert_config_value(config, "some.section.multiquotes2", "!ls x ls \"# comment2 $HOME\"");
+ assert_config_value(config, "some.section.multiquotes3", "hi # ho there are # more quotes");
+ assert_config_value(config, "some.section.quotecomment", "hi # ho there are # more");
git_config_free(config);
}
diff --git a/tests/core/buffer.c b/tests/core/buffer.c
index 4e895afd9..2af4a8712 100644
--- a/tests/core/buffer.c
+++ b/tests/core/buffer.c
@@ -1,6 +1,5 @@
#include "clar_libgit2.h"
#include "buffer.h"
-#include "buf_text.h"
#include "git2/sys/hashsig.h"
#include "futils.h"
@@ -633,7 +632,6 @@ void test_core_buffer__join3(void)
void test_core_buffer__11(void)
{
git_buf a = GIT_BUF_INIT;
- git_strarray t;
char *t1[] = { "nothing", "in", "common" };
char *t2[] = { "something", "something else", "some other" };
char *t3[] = { "something", "some fun", "no fun" };
@@ -642,39 +640,25 @@ void test_core_buffer__11(void)
char *t6[] = { "no", "nope", "" };
char *t7[] = { "", "doesn't matter" };
- t.strings = t1;
- t.count = 3;
- cl_git_pass(git_buf_text_common_prefix(&a, &t));
+ cl_git_pass(git_buf_common_prefix(&a, t1, 3));
cl_assert_equal_s(a.ptr, "");
- t.strings = t2;
- t.count = 3;
- cl_git_pass(git_buf_text_common_prefix(&a, &t));
+ cl_git_pass(git_buf_common_prefix(&a, t2, 3));
cl_assert_equal_s(a.ptr, "some");
- t.strings = t3;
- t.count = 3;
- cl_git_pass(git_buf_text_common_prefix(&a, &t));
+ cl_git_pass(git_buf_common_prefix(&a, t3, 3));
cl_assert_equal_s(a.ptr, "");
- t.strings = t4;
- t.count = 3;
- cl_git_pass(git_buf_text_common_prefix(&a, &t));
+ cl_git_pass(git_buf_common_prefix(&a, t4, 3));
cl_assert_equal_s(a.ptr, "happ");
- t.strings = t5;
- t.count = 3;
- cl_git_pass(git_buf_text_common_prefix(&a, &t));
+ cl_git_pass(git_buf_common_prefix(&a, t5, 3));
cl_assert_equal_s(a.ptr, "happ");
- t.strings = t6;
- t.count = 3;
- cl_git_pass(git_buf_text_common_prefix(&a, &t));
+ cl_git_pass(git_buf_common_prefix(&a, t6, 3));
cl_assert_equal_s(a.ptr, "");
- t.strings = t7;
- t.count = 3;
- cl_git_pass(git_buf_text_common_prefix(&a, &t));
+ cl_git_pass(git_buf_common_prefix(&a, t7, 3));
cl_assert_equal_s(a.ptr, "");
git_buf_dispose(&a);
@@ -709,19 +693,19 @@ void test_core_buffer__puts_escaped(void)
git_buf a = GIT_BUF_INIT;
git_buf_clear(&a);
- cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "", ""));
+ cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "", ""));
cl_assert_equal_s("this is a test", a.ptr);
git_buf_clear(&a);
- cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "t", "\\"));
+ cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "t", "\\"));
cl_assert_equal_s("\\this is a \\tes\\t", a.ptr);
git_buf_clear(&a);
- cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "i ", "__"));
+ cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "i ", "__"));
cl_assert_equal_s("th__is__ __is__ a__ test", a.ptr);
git_buf_clear(&a);
- cl_git_pass(git_buf_text_puts_escape_regex(&a, "^match\\s*[A-Z]+.*"));
+ cl_git_pass(git_buf_puts_escape_regex(&a, "^match\\s*[A-Z]+.*"));
cl_assert_equal_s("\\^match\\\\s\\*\\[A-Z\\]\\+\\.\\*", a.ptr);
git_buf_dispose(&a);
@@ -731,7 +715,7 @@ static void assert_unescape(char *expected, char *to_unescape) {
git_buf buf = GIT_BUF_INIT;
cl_git_pass(git_buf_sets(&buf, to_unescape));
- git_buf_text_unescape(&buf);
+ git_buf_unescape(&buf);
cl_assert_equal_s(expected, buf.ptr);
cl_assert_equal_sz(strlen(expected), buf.size);
@@ -864,20 +848,20 @@ void test_core_buffer__classify_with_utf8(void)
git_buf b;
b.ptr = data0; b.size = b.asize = data0len;
- cl_assert(!git_buf_text_is_binary(&b));
- cl_assert(!git_buf_text_contains_nul(&b));
+ cl_assert(!git_buf_is_binary(&b));
+ cl_assert(!git_buf_contains_nul(&b));
b.ptr = data1; b.size = b.asize = data1len;
- cl_assert(!git_buf_text_is_binary(&b));
- cl_assert(!git_buf_text_contains_nul(&b));
+ cl_assert(!git_buf_is_binary(&b));
+ cl_assert(!git_buf_contains_nul(&b));
b.ptr = data2; b.size = b.asize = data2len;
- cl_assert(git_buf_text_is_binary(&b));
- cl_assert(git_buf_text_contains_nul(&b));
+ cl_assert(git_buf_is_binary(&b));
+ cl_assert(git_buf_contains_nul(&b));
b.ptr = data3; b.size = b.asize = data3len;
- cl_assert(!git_buf_text_is_binary(&b));
- cl_assert(!git_buf_text_contains_nul(&b));
+ cl_assert(!git_buf_is_binary(&b));
+ cl_assert(!git_buf_contains_nul(&b));
}
#define SIMILARITY_TEST_DATA_1 \
@@ -1074,80 +1058,80 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "lf\nlf\nlf\nlf\n");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf("lf\r\nlf\r\nlf\r\nlf\r\n", tgt);
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf(src.ptr, tgt);
git_buf_sets(&src, "\nlf\nlf\nlf\nlf\nlf");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf("\r\nlf\r\nlf\r\nlf\r\nlf\r\nlf", tgt);
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf(src.ptr, tgt);
/* CRLF source */
git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf("crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n", tgt);
git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf("crlf\ncrlf\ncrlf\ncrlf\n", tgt);
git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf("\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf", tgt);
git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf("\ncrlf\ncrlf\ncrlf\ncrlf\ncrlf", tgt);
/* CRLF in LF text */
git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf("\r\nlf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\ncrlf\r\n", tgt);
git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf("\nlf\nlf\ncrlf\nlf\nlf\ncrlf\n", tgt);
/* LF in CRLF text */
git_buf_sets(&src, "\ncrlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf("\r\ncrlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf", tgt);
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf("\ncrlf\ncrlf\nlf\ncrlf\ncrlf", tgt);
/* bare CR test */
git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf("\rcrlf\r\nlf\r\nlf\r\ncr\rcrlf\r\nlf\r\ncr\r", tgt);
git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt);
git_buf_sets(&src, "\rcr\r");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf(src.ptr, tgt);
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf("\rcr\r", tgt);
git_buf_dispose(&src);
@@ -1156,37 +1140,37 @@ void test_core_buffer__lf_and_crlf_conversions(void)
/* blob correspondence tests */
git_buf_sets(&src, ALL_CRLF_TEXT_RAW);
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt);
git_buf_sets(&src, ALL_CRLF_TEXT_RAW);
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf(ALL_CRLF_TEXT_AS_LF, tgt);
git_buf_dispose(&src);
git_buf_dispose(&tgt);
git_buf_sets(&src, ALL_LF_TEXT_RAW);
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf(ALL_LF_TEXT_AS_CRLF, tgt);
git_buf_sets(&src, ALL_LF_TEXT_RAW);
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf(ALL_LF_TEXT_AS_LF, tgt);
git_buf_dispose(&src);
git_buf_dispose(&tgt);
git_buf_sets(&src, MORE_CRLF_TEXT_RAW);
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt);
git_buf_sets(&src, MORE_CRLF_TEXT_RAW);
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf(MORE_CRLF_TEXT_AS_LF, tgt);
git_buf_dispose(&src);
git_buf_dispose(&tgt);
git_buf_sets(&src, MORE_LF_TEXT_RAW);
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
+ cl_git_pass(git_buf_lf_to_crlf(&tgt, &src));
check_buf(MORE_LF_TEXT_AS_CRLF, tgt);
git_buf_sets(&src, MORE_LF_TEXT_RAW);
- cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
+ cl_git_pass(git_buf_crlf_to_lf(&tgt, &src));
check_buf(MORE_LF_TEXT_AS_LF, tgt);
git_buf_dispose(&src);
git_buf_dispose(&tgt);
diff --git a/tests/core/encoding.c b/tests/core/encoding.c
index a677afe2e..6cec24679 100644
--- a/tests/core/encoding.c
+++ b/tests/core/encoding.c
@@ -14,7 +14,7 @@ void test_core_encoding__decode(void)
cl_assert(size == 4);
buf = (unsigned char *)"\xaa\xaa\xfe\xdc\xbaXY";
- cl_assert(git_decode_varint(buf, &size) == 1489279344088ULL);
+ cl_assert(git_decode_varint(buf, &size) == UINT64_C(1489279344088));
cl_assert(size == 6);
buf = (unsigned char *)"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xfe\xdc\xbaXY";
@@ -35,8 +35,8 @@ void test_core_encoding__encode(void)
cl_assert(git_encode_varint(buf, 100, 267869656) == 4);
cl_assert(!memcmp(buf, "\xfe\xdc\xbaX", 4));
- cl_assert(git_encode_varint(buf, 100, 1489279344088ULL) == 6);
+ cl_assert(git_encode_varint(buf, 100, UINT64_C(1489279344088)) == 6);
cl_assert(!memcmp(buf, "\xaa\xaa\xfe\xdc\xbaX", 6));
- cl_assert(git_encode_varint(buf, 1, 1489279344088ULL) == -1);
+ cl_assert(git_encode_varint(buf, 1, UINT64_C(1489279344088)) == -1);
}
diff --git a/tests/core/integer.c b/tests/core/integer.c
new file mode 100644
index 000000000..18364ba62
--- /dev/null
+++ b/tests/core/integer.c
@@ -0,0 +1,253 @@
+#include "clar_libgit2.h"
+
+void test_core_integer__multiply_int64_no_overflow(void)
+{
+#if !defined(git__multiply_int64_overflow)
+ int64_t result = 0;
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(-0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(-0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(0x7fffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(-0x7fffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x0), INT64_C(-0x8000000000000000)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(0x1));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x1));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(0x2));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(-0x2));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0x7ffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(-0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(-0x7ffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(0x800000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(-0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(-0x800000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(0x7fffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0x7fffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(-0x7fffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(-0x7fffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x1));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(0x1));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(-0x2));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(0x2));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(-0x7ffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(-0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0x7ffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(-0x800000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(-0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(0x800000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(0x7fffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(-0x7fffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(-0x7fffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0x7fffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(0x2));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x2));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(0x4));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(-0x4));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0xffffffffffffffe));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(-0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(-0xffffffffffffffe));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(0x1000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(-0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(-0x1000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x2));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(0x2));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(-0x4));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(0x4));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(-0xffffffffffffffe));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(-0x7ffffffffffffff)));
+ cl_assert_equal_i(result, INT64_C(0xffffffffffffffe));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(-0x1000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(-0x800000000000000)));
+ cl_assert_equal_i(result, INT64_C(0x1000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(-0x4000000000000000)));
+ cl_assert_equal_i(result, INT64_C(-0x8000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(0x7ffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x7ffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(0xffffffffffffffe));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(-0xffffffffffffffe));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x7ffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(0x7ffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(-0xffffffffffffffe));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(0xffffffffffffffe));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(0x800000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x800000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(0x1000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(-0x1000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x800000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(0x800000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(-0x1000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(-0x2)));
+ cl_assert_equal_i(result, INT64_C(0x1000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(0x7fffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x7fffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x4000000000000000), INT64_C(0x2)));
+ cl_assert_equal_i(result, INT64_C(-0x8000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x7fffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(0x7fffffffffffffff));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(0x0)));
+ cl_assert_equal_i(result, INT64_C(0x0));
+#endif
+}
+
+void test_core_integer__multiply_int64_overflow(void)
+{
+#if !defined(git__multiply_int64_overflow)
+ int64_t result = 0;
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(0x4000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x2), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x2), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(-0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(-0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7ffffffffffffff), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(-0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(-0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7ffffffffffffff), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(-0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(-0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x800000000000000), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(-0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(-0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x800000000000000), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x4000000000000000), INT64_C(0x2)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(0x2)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(-0x2)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(-0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(-0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x7fffffffffffffff), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(0x2)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(-0x2)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(-0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(-0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x7fffffffffffffff), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(0x2)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(-0x2)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(-0x7ffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(-0x800000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(-0x7fffffffffffffff)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(-0x8000000000000000)));
+#endif
+}
+
+void test_core_integer__multiply_int64_edge_cases(void)
+{
+#if !defined(git__multiply_int64_overflow)
+ int64_t result = 0;
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(-0x1)));
+ cl_assert_equal_i(result, INT64_C(-0x8000000000000000));
+ cl_assert(!git__multiply_int64_overflow(&result, INT64_C(-0x1), INT64_C(-0x8000000000000000)));
+ cl_assert_equal_i(result, INT64_C(-0x8000000000000000));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(0x1), INT64_C(-0x8000000000000000)));
+ cl_assert(git__multiply_int64_overflow(&result, INT64_C(-0x8000000000000000), INT64_C(0x1)));
+#endif
+}
diff --git a/tests/core/link.c b/tests/core/link.c
index 1e5ed454c..0493edf1d 100644
--- a/tests/core/link.c
+++ b/tests/core/link.c
@@ -123,7 +123,7 @@ static void do_junction(const char *old, const char *new)
reparse_buf = LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, reparse_buflen);
cl_assert(reparse_buf);
- subst_utf16 = reparse_buf->MountPointReparseBuffer.PathBuffer;
+ subst_utf16 = reparse_buf->ReparseBuffer.MountPoint.PathBuffer;
print_utf16 = subst_utf16 + subst_utf16_len + 1;
ret = git__utf8_to_16(subst_utf16, subst_utf16_len + 1,
@@ -135,10 +135,10 @@ static void do_junction(const char *old, const char *new)
cl_assert_equal_i(print_utf16_len, ret);
reparse_buf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
- reparse_buf->MountPointReparseBuffer.SubstituteNameOffset = 0;
- reparse_buf->MountPointReparseBuffer.SubstituteNameLength = subst_byte_len;
- reparse_buf->MountPointReparseBuffer.PrintNameOffset = (USHORT)(subst_byte_len + sizeof(WCHAR));
- reparse_buf->MountPointReparseBuffer.PrintNameLength = print_byte_len;
+ reparse_buf->ReparseBuffer.MountPoint.SubstituteNameOffset = 0;
+ reparse_buf->ReparseBuffer.MountPoint.SubstituteNameLength = subst_byte_len;
+ reparse_buf->ReparseBuffer.MountPoint.PrintNameOffset = (USHORT)(subst_byte_len + sizeof(WCHAR));
+ reparse_buf->ReparseBuffer.MountPoint.PrintNameLength = print_byte_len;
reparse_buf->ReparseDataLength = reparse_buflen - REPARSE_DATA_HEADER_SIZE;
cl_win32_pass(DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT,
diff --git a/tests/core/opts.c b/tests/core/opts.c
index 72408cbe8..e8f65d510 100644
--- a/tests/core/opts.c
+++ b/tests/core/opts.c
@@ -1,6 +1,11 @@
#include "clar_libgit2.h"
#include "cache.h"
+void test_core_opts__cleanup(void)
+{
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, NULL, 0));
+}
+
void test_core_opts__readwrite(void)
{
size_t old_val = 0;
@@ -23,3 +28,44 @@ void test_core_opts__invalid_option(void)
cl_git_fail(git_libgit2_opts(-1, "foobar"));
}
+void test_core_opts__extensions_query(void)
+{
+ git_strarray out = { 0 };
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
+
+ cl_assert_equal_sz(out.count, 1);
+ cl_assert_equal_s("noop", out.strings[0]);
+
+ git_strarray_dispose(&out);
+}
+
+void test_core_opts__extensions_add(void)
+{
+ const char *in[] = { "foo" };
+ git_strarray out = { 0 };
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
+
+ cl_assert_equal_sz(out.count, 2);
+ cl_assert_equal_s("noop", out.strings[0]);
+ cl_assert_equal_s("foo", out.strings[1]);
+
+ git_strarray_dispose(&out);
+}
+
+void test_core_opts__extensions_remove(void)
+{
+ const char *in[] = { "bar", "!negate", "!noop", "baz" };
+ git_strarray out = { 0 };
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
+
+ cl_assert_equal_sz(out.count, 2);
+ cl_assert_equal_s("bar", out.strings[0]);
+ cl_assert_equal_s("baz", out.strings[1]);
+
+ git_strarray_dispose(&out);
+}
diff --git a/tests/core/path.c b/tests/core/path.c
index 2e5a4ab24..eac3573fe 100644
--- a/tests/core/path.c
+++ b/tests/core/path.c
@@ -32,15 +32,6 @@ check_basename(const char *A, const char *B)
}
static void
-check_topdir(const char *A, const char *B)
-{
- const char *dir;
-
- cl_assert((dir = git_path_topdir(A)) != NULL);
- cl_assert_equal_s(B, dir);
-}
-
-static void
check_joinpath(const char *path_a, const char *path_b, const char *expected_path)
{
git_buf joined_path = GIT_BUF_INIT;
@@ -119,23 +110,6 @@ void test_core_path__01_basename(void)
check_basename(REP1024("/abc"), "abc");
}
-/* get the latest component in a path */
-void test_core_path__02_topdir(void)
-{
- check_topdir(".git/", ".git/");
- check_topdir("/.git/", ".git/");
- check_topdir("usr/local/.git/", ".git/");
- check_topdir("./.git/", ".git/");
- check_topdir("/usr/.git/", ".git/");
- check_topdir("/", "/");
- check_topdir("a/", "a/");
-
- cl_assert(git_path_topdir("/usr/.git") == NULL);
- cl_assert(git_path_topdir(".") == NULL);
- cl_assert(git_path_topdir("") == NULL);
- cl_assert(git_path_topdir("a") == NULL);
-}
-
/* properly join path components */
void test_core_path__05_joins(void)
{
@@ -285,7 +259,7 @@ void test_core_path__08_self_join(void)
cl_git_pass(git_buf_joinpath(&path, path.ptr + 4, "somethinglongenoughtorealloc"));
cl_assert_equal_s(path.ptr, "/baz/somethinglongenoughtorealloc");
cl_assert(asize < path.asize);
-
+
git_buf_dispose(&path);
}
diff --git a/tests/core/sha1.c b/tests/core/sha1.c
index f81d40854..196b00352 100644
--- a/tests/core/sha1.c
+++ b/tests/core/sha1.c
@@ -52,7 +52,7 @@ void test_core_sha1__detect_collision_attack(void)
git_oid oid, expected;
#ifdef GIT_SHA1_COLLISIONDETECT
- GIT_UNUSED(expected);
+ GIT_UNUSED(&expected);
cl_git_fail(sha1_file(&oid, FIXTURE_DIR "/shattered-1.pdf"));
cl_assert_equal_s("SHA1 collision attack detected", git_error_last()->message);
#else
diff --git a/tests/core/sortedcache.c b/tests/core/sortedcache.c
index 35e92ece9..d5bbcea19 100644
--- a/tests/core/sortedcache.c
+++ b/tests/core/sortedcache.c
@@ -54,7 +54,7 @@ void test_core_sortedcache__name_only(void)
cl_assert_equal_i(
GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "abc"));
- git_sortedcache_clear(sc, true);
+ cl_git_pass(git_sortedcache_clear(sc, true));
cl_assert_equal_sz(0, git_sortedcache_entrycount(sc));
cl_assert(git_sortedcache_entry(sc, 0) == NULL);
@@ -154,7 +154,7 @@ void test_core_sortedcache__in_memory(void)
cl_assert_equal_i(0, free_count);
- git_sortedcache_clear(sc, true);
+ cl_git_pass(git_sortedcache_clear(sc, true));
cl_assert_equal_i(5, free_count);
@@ -247,7 +247,7 @@ static void sortedcache_test_reload(git_sortedcache *sc)
cl_assert(git_sortedcache_lockandload(sc, &buf) > 0);
- git_sortedcache_clear(sc, false); /* clear once we already have lock */
+ cl_git_pass(git_sortedcache_clear(sc, false)); /* clear once we already have lock */
for (scan = buf.ptr; *scan; scan = after + 1) {
int val = strtol(scan, &after, 0);
diff --git a/tests/core/string.c b/tests/core/string.c
index 85db0c662..928dfbcc1 100644
--- a/tests/core/string.c
+++ b/tests/core/string.c
@@ -123,3 +123,14 @@ void test_core_string__strcasecmp(void)
cl_assert(git__strcasecmp("et", "e\342\202\254ghi=") < 0);
cl_assert(git__strcasecmp("\303\215", "\303\255") < 0);
}
+
+void test_core_string__strlcmp(void)
+{
+ const char foo[3] = { 'f', 'o', 'o' };
+
+ cl_assert(git__strlcmp("foo", "foo", 3) == 0);
+ cl_assert(git__strlcmp("foo", foo, 3) == 0);
+ cl_assert(git__strlcmp("foo", "foobar", 3) == 0);
+ cl_assert(git__strlcmp("foobar", "foo", 3) > 0);
+ cl_assert(git__strlcmp("foo", "foobar", 6) < 0);
+}
diff --git a/tests/core/strtol.c b/tests/core/strtol.c
index 25dbe467c..851b91b0a 100644
--- a/tests/core/strtol.c
+++ b/tests/core/strtol.c
@@ -30,8 +30,9 @@ void test_core_strtol__int32(void)
{
assert_l32_parses("123", 123, 10);
assert_l32_parses(" +123 ", 123, 10);
+ assert_l32_parses(" -123 ", -123, 10);
assert_l32_parses(" +2147483647 ", 2147483647, 10);
- assert_l32_parses(" -2147483648 ", -2147483648LL, 10);
+ assert_l32_parses(" -2147483648 ", INT64_C(-2147483648), 10);
assert_l32_parses("A", 10, 16);
assert_l32_parses("1x1", 1, 10);
@@ -46,10 +47,11 @@ void test_core_strtol__int64(void)
{
assert_l64_parses("123", 123, 10);
assert_l64_parses(" +123 ", 123, 10);
+ assert_l64_parses(" -123 ", -123, 10);
assert_l64_parses(" +2147483647 ", 2147483647, 10);
- assert_l64_parses(" -2147483648 ", -2147483648LL, 10);
- assert_l64_parses(" 2147483657 ", 2147483657LL, 10);
- assert_l64_parses(" -2147483657 ", -2147483657LL, 10);
+ assert_l64_parses(" -2147483648 ", INT64_C(-2147483648), 10);
+ assert_l64_parses(" 2147483657 ", INT64_C(2147483657), 10);
+ assert_l64_parses(" -2147483657 ", INT64_C(-2147483657), 10);
assert_l64_parses(" 9223372036854775807 ", INT64_MAX, 10);
assert_l64_parses(" -9223372036854775808 ", INT64_MIN, 10);
assert_l64_parses(" 0x7fffffffffffffff ", INT64_MAX, 16);
diff --git a/tests/core/structinit.c b/tests/core/structinit.c
index 192096be3..d24da874d 100644
--- a/tests/core/structinit.c
+++ b/tests/core/structinit.c
@@ -1,4 +1,5 @@
#include "clar_libgit2.h"
+#include <git2/sys/commit_graph.h>
#include <git2/sys/config.h>
#include <git2/sys/filter.h>
#include <git2/sys/odb_backend.h>
@@ -82,6 +83,11 @@ void test_core_structinit__compare(void)
git_blame_options, GIT_BLAME_OPTIONS_VERSION, \
GIT_BLAME_OPTIONS_INIT, git_blame_options_init);
+ /* blob_filter_options */
+ CHECK_MACRO_FUNC_INIT_EQUAL( \
+ git_blob_filter_options, GIT_BLOB_FILTER_OPTIONS_VERSION, \
+ GIT_BLOB_FILTER_OPTIONS_INIT, git_blob_filter_options_init);
+
/* checkout */
CHECK_MACRO_FUNC_INIT_EQUAL( \
git_checkout_options, GIT_CHECKOUT_OPTIONS_VERSION, \
@@ -92,6 +98,13 @@ void test_core_structinit__compare(void)
git_clone_options, GIT_CLONE_OPTIONS_VERSION, \
GIT_CLONE_OPTIONS_INIT, git_clone_options_init);
+ /* commit_graph_writer */
+ CHECK_MACRO_FUNC_INIT_EQUAL( \
+ git_commit_graph_writer_options, \
+ GIT_COMMIT_GRAPH_WRITER_OPTIONS_VERSION, \
+ GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT, \
+ git_commit_graph_writer_options_init);
+
/* diff */
CHECK_MACRO_FUNC_INIT_EQUAL( \
git_diff_options, GIT_DIFF_OPTIONS_VERSION, \
diff --git a/tests/core/useragent.c b/tests/core/useragent.c
index c6c5220b2..2ce935bf5 100644
--- a/tests/core/useragent.c
+++ b/tests/core/useragent.c
@@ -1,5 +1,5 @@
#include "clar_libgit2.h"
-#include "global.h"
+#include "settings.h"
void test_core_useragent__get(void)
{
diff --git a/tests/core/utf8.c b/tests/core/utf8.c
new file mode 100644
index 000000000..021828e9e
--- /dev/null
+++ b/tests/core/utf8.c
@@ -0,0 +1,19 @@
+#include "clar_libgit2.h"
+
+void test_core_utf8__char_length(void)
+{
+ cl_assert_equal_i(0, git_utf8_char_length("", 0));
+ cl_assert_equal_i(1, git_utf8_char_length("$", 1));
+ cl_assert_equal_i(5, git_utf8_char_length("abcde", 5));
+ cl_assert_equal_i(1, git_utf8_char_length("\xc2\xa2", 2));
+ cl_assert_equal_i(2, git_utf8_char_length("\x24\xc2\xa2", 3));
+ cl_assert_equal_i(1, git_utf8_char_length("\xf0\x90\x8d\x88", 4));
+
+ /* uncontinued character counted as single characters */
+ cl_assert_equal_i(2, git_utf8_char_length("\x24\xc2", 2));
+ cl_assert_equal_i(3, git_utf8_char_length("\x24\xc2\xc2\xa2", 4));
+
+ /* invalid characters are counted as single characters */
+ cl_assert_equal_i(4, git_utf8_char_length("\x24\xc0\xc0\x34", 4));
+ cl_assert_equal_i(4, git_utf8_char_length("\x24\xf5\xfd\xc2", 4));
+}
diff --git a/tests/core/vector.c b/tests/core/vector.c
index a7e1a0325..08cd2c19b 100644
--- a/tests/core/vector.c
+++ b/tests/core/vector.c
@@ -8,7 +8,7 @@ void test_core_vector__0(void)
{
git_vector x;
int i;
- git_vector_init(&x, 1, NULL);
+ cl_git_pass(git_vector_init(&x, 1, NULL));
for (i = 0; i < 10; ++i) {
git_vector_insert(&x, (void*) 0xabc);
}
@@ -21,7 +21,7 @@ void test_core_vector__1(void)
{
git_vector x;
/* make initial capacity exact for our insertions. */
- git_vector_init(&x, 3, NULL);
+ cl_git_pass(git_vector_init(&x, 3, NULL));
git_vector_insert(&x, (void*) 0xabc);
git_vector_insert(&x, (void*) 0xdef);
git_vector_insert(&x, (void*) 0x123);
@@ -76,7 +76,7 @@ void test_core_vector__3(void)
{
git_vector x;
intptr_t i;
- git_vector_init(&x, 1, &compare_them);
+ cl_git_pass(git_vector_init(&x, 1, &compare_them));
for (i = 0; i < 10; i += 2) {
git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
@@ -99,7 +99,7 @@ void test_core_vector__4(void)
{
git_vector x;
intptr_t i;
- git_vector_init(&x, 1, &compare_them);
+ cl_git_pass(git_vector_init(&x, 1, &compare_them));
for (i = 0; i < 10; i += 2) {
git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
@@ -163,7 +163,7 @@ void test_core_vector__5(void)
git_vector x;
int i;
- git_vector_init(&x, 1, &compare_structs);
+ cl_git_pass(git_vector_init(&x, 1, &compare_structs));
for (i = 0; i < 10; i += 2)
git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
@@ -205,7 +205,7 @@ void test_core_vector__remove_matching(void)
size_t i;
void *compare;
- git_vector_init(&x, 1, NULL);
+ cl_git_pass(git_vector_init(&x, 1, NULL));
git_vector_insert(&x, (void*) 0x001);
cl_assert(x.length == 1);
diff --git a/tests/diff/format_email.c b/tests/diff/format_email.c
index 28f840ab0..ea7aa070f 100644
--- a/tests/diff/format_email.c
+++ b/tests/diff/format_email.c
@@ -18,6 +18,7 @@ void test_diff_format_email__cleanup(void)
cl_git_sandbox_cleanup();
}
+#ifndef GIT_DEPRECATE_HARD
static void assert_email_match(
const char *expected,
const char *oidstr,
@@ -51,9 +52,11 @@ static void assert_email_match(
git_commit_free(commit);
git_buf_dispose(&buf);
}
+#endif
void test_diff_format_email__simple(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
const char *email =
"From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \
@@ -96,10 +99,12 @@ void test_diff_format_email__simple(void)
assert_email_match(
email, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+#endif
}
void test_diff_format_email__with_message(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
const char *email = "From 627e7e12d87e07a83fad5b6bfa25e86ead4a5270 Mon Sep 17 00:00:00 2001\n" \
"From: Patrick Steinhardt <ps@pks.im>\n" \
@@ -136,11 +141,13 @@ void test_diff_format_email__with_message(void)
assert_email_match(
email, "627e7e12d87e07a83fad5b6bfa25e86ead4a5270", &opts);
+#endif
}
void test_diff_format_email__multiple(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_oid oid;
git_commit *commit = NULL;
git_diff *diff = NULL;
@@ -256,10 +263,12 @@ void test_diff_format_email__multiple(void)
git_diff_free(diff);
git_commit_free(commit);
git_buf_dispose(&buf);
+#endif
}
void test_diff_format_email__exclude_marker(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
const char *email =
"From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \
@@ -304,10 +313,12 @@ void test_diff_format_email__exclude_marker(void)
assert_email_match(
email, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+#endif
}
void test_diff_format_email__invalid_no(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_oid oid;
git_commit *commit = NULL;
git_diff *diff = NULL;
@@ -327,15 +338,16 @@ void test_diff_format_email__invalid_no(void)
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
cl_git_fail(git_diff_format_email(&buf, diff, &opts));
cl_git_fail(git_diff_commit_as_email(&buf, repo, commit, 2, 1, 0, NULL));
- cl_git_fail(git_diff_commit_as_email(&buf, repo, commit, 0, 0, 0, NULL));
git_diff_free(diff);
git_commit_free(commit);
git_buf_dispose(&buf);
+#endif
}
void test_diff_format_email__mode_change(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
const char *email =
"From 7ade76dd34bba4733cf9878079f9fd4a456a9189 Mon Sep 17 00:00:00 2001\n" \
@@ -357,10 +369,12 @@ void test_diff_format_email__mode_change(void)
assert_email_match(
email, "7ade76dd34bba4733cf9878079f9fd4a456a9189", &opts);
+#endif
}
void test_diff_format_email__rename_add_remove(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
const char *email =
"From 6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d Mon Sep 17 00:00:00 2001\n" \
@@ -427,10 +441,12 @@ void test_diff_format_email__rename_add_remove(void)
assert_email_match(
email, "6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d", &opts);
+#endif
}
void test_diff_format_email__multiline_summary(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
const char *email =
"From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \
@@ -475,10 +491,12 @@ void test_diff_format_email__multiline_summary(void)
assert_email_match(
email, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+#endif
}
void test_diff_format_email__binary(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
const char *email =
"From 8d7523f6fcb2404257889abe0d96f093d9f524f9 Mon Sep 17 00:00:00 2001\n" \
@@ -487,7 +505,7 @@ void test_diff_format_email__binary(void)
"Subject: [PATCH] Modified binary file\n" \
"\n" \
"---\n" \
- " binary.bin | Bin 3 -> 0 bytes\n" \
+ " binary.bin | Bin 3 -> 5 bytes\n" \
" 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
"\n" \
"diff --git a/binary.bin b/binary.bin\n" \
@@ -496,11 +514,11 @@ void test_diff_format_email__binary(void)
"--\n" \
"libgit2 " LIBGIT2_VERSION "\n" \
"\n";
- /* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */
opts.summary = "Modified binary file";
assert_email_match(
email, "8d7523f6fcb2404257889abe0d96f093d9f524f9", &opts);
+#endif
}
diff --git a/tests/diff/parse.c b/tests/diff/parse.c
index 56f2253aa..6b6e6645e 100644
--- a/tests/diff/parse.c
+++ b/tests/diff/parse.c
@@ -107,6 +107,29 @@ void test_diff_parse__no_extended_headers(void)
git_diff_free(diff);
}
+void test_diff_parse__add_delete_no_index(void)
+{
+ const char *content =
+ "diff --git a/file.txt b/file.txt\n"
+ "new file mode 100644\n"
+ "--- /dev/null\n"
+ "+++ b/file.txt\n"
+ "@@ -0,0 +1,2 @@\n"
+ "+one\n"
+ "+two\n"
+ "diff --git a/otherfile.txt b/otherfile.txt\n"
+ "deleted file mode 100644\n"
+ "--- a/otherfile.txt\n"
+ "+++ /dev/null\n"
+ "@@ -1,1 +0,0 @@\n"
+ "-three\n";
+ git_diff *diff;
+
+ cl_git_pass(git_diff_from_buffer(
+ &diff, content, strlen(content)));
+ git_diff_free(diff);
+}
+
void test_diff_parse__invalid_patches_fails(void)
{
test_parse_invalid_diff(PATCH_CORRUPT_MISSING_NEW_FILE);
diff --git a/tests/diff/patch.c b/tests/diff/patch.c
index 7eb353627..d288bba58 100644
--- a/tests/diff/patch.c
+++ b/tests/diff/patch.c
@@ -4,7 +4,6 @@
#include "diff_helpers.h"
#include "diff.h"
#include "repository.h"
-#include "buf_text.h"
static git_repository *g_repo = NULL;
diff --git a/tests/diff/rename.c b/tests/diff/rename.c
index df32eebf2..bd25d29aa 100644
--- a/tests/diff/rename.c
+++ b/tests/diff/rename.c
@@ -1,6 +1,5 @@
#include "clar_libgit2.h"
#include "diff_helpers.h"
-#include "buf_text.h"
static git_repository *g_repo = NULL;
@@ -22,6 +21,8 @@ void test_diff_rename__cleanup(void)
#define RENAME_MODIFICATION_COMMIT "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"
#define REWRITE_DELETE_COMMIT "84d8efa38af7ace2b302de0adbda16b1f1cd2e1b"
#define DELETE_RENAME_COMMIT "be053a189b0bbde545e0a3f59ce00b46ad29ce0d"
+#define BREAK_REWRITE_BASE_COMMIT "db98035f715427eef1f5e17f03e1801c05301e9e"
+#define BREAK_REWRITE_COMMIT "7e7bfb88ba9bc65fd700fee1819cf1c317aafa56"
/*
* Renames repo has:
@@ -513,7 +514,7 @@ void test_diff_rename__working_directory_changes(void)
cl_git_pass(
git_futils_readbuffer(&old_content, "renames/songof7cities.txt"));
cl_git_pass(
- git_buf_text_lf_to_crlf(&content, &old_content));
+ git_buf_lf_to_crlf(&content, &old_content));
cl_git_pass(
git_futils_writebuffer(&content, "renames/songof7cities.txt", 0, 0));
@@ -1978,3 +1979,56 @@ void test_diff_rename__delete_and_rename(void)
git_tree_free(old_tree);
git_tree_free(new_tree);
}
+
+/*
+ * The break_rewrite branch contains a testcase reduced from
+ * a real-world scenario, rather than being "constructed" like
+ * the above tests seem to be. There are two commits layered
+ * on top of the repo's initial commit; the base commit which
+ * clears out the files from the initial commit and installs
+ * four files. And then there's the modification commit which
+ * mutates the files in such a way as to trigger the bug in
+ * libgit2.
+ * commit db98035f715427eef1f5e17f03e1801c05301e9e
+ * serving.txt (deleted)
+ * sevencities.txt (deleted)
+ * AAA (313 lines)
+ * BBB (314 lines)
+ * CCC (704 lines)
+ * DDD (314 lines, identical to BBB)
+ * commit 7e7bfb88ba9bc65fd700fee1819cf1c317aafa56
+ * This deletes CCC and makes slight modifications
+ * to AAA, BBB, and DDD. The find_best_matches loop
+ * for git_diff_find_similar computes the following:
+ * CCC moved to AAA (similarity 91)
+ * CCC copied to AAA (similarity 91)
+ * DDD moved to BBB (similarity 52)
+ * CCC copied to BBB (similarity 90)
+ * BBB moved to DDD (similarity 52)
+ * CCC copied to DDD (similarity 90)
+ * The code to rewrite the diffs by resolving these
+ * copies/renames would resolve the BBB <-> DDD moves
+ * but then still leave BBB as a rename target for
+ * the deleted file CCC. Since the split flag on BBB
+ * was cleared, this would trigger an error.
+ */
+void test_diff_rename__break_rewrite(void)
+{
+ const char *old_sha = BREAK_REWRITE_BASE_COMMIT;
+ const char *new_sha = BREAK_REWRITE_COMMIT;
+ git_tree *old_tree, *new_tree;
+ git_diff *diff;
+ git_diff_find_options find_opts = GIT_DIFF_FIND_OPTIONS_INIT;
+
+ old_tree = resolve_commit_oid_to_tree(g_repo, old_sha);
+ new_tree = resolve_commit_oid_to_tree(g_repo, new_sha);
+
+ find_opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES | GIT_DIFF_BREAK_REWRITES | GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY;
+
+ cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, old_tree, new_tree, NULL));
+ cl_git_pass(git_diff_find_similar(diff, &find_opts));
+
+ git_diff_free(diff);
+ git_tree_free(old_tree);
+ git_tree_free(new_tree);
+}
diff --git a/tests/diff/stats.c b/tests/diff/stats.c
index 150355686..54572672c 100644
--- a/tests/diff/stats.c
+++ b/tests/diff/stats.c
@@ -298,9 +298,8 @@ void test_diff_stats__binary(void)
{
git_buf buf = GIT_BUF_INIT;
const char *stat =
- " binary.bin | Bin 3 -> 0 bytes\n"
+ " binary.bin | Bin 3 -> 5 bytes\n"
" 1 file changed, 0 insertions(+), 0 deletions(-)\n";
- /* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */
diff_stats_from_commit_oid(
&_stats, "8d7523f6fcb2404257889abe0d96f093d9f524f9", false);
@@ -343,3 +342,38 @@ void test_diff_stats__mode_change(void)
cl_assert_equal_s(stat, git_buf_cstr(&buf));
git_buf_dispose(&buf);
}
+
+void test_diff_stats__new_file(void)
+{
+ git_diff *diff;
+ git_buf buf = GIT_BUF_INIT;
+
+ const char *input =
+ "---\n"
+ " Gurjeet Singh | 1 +\n"
+ " 1 file changed, 1 insertion(+)\n"
+ " create mode 100644 Gurjeet Singh\n"
+ "\n"
+ "diff --git a/Gurjeet Singh b/Gurjeet Singh\n"
+ "new file mode 100644\n"
+ "index 0000000..6d0ecfd\n"
+ "--- /dev/null\n"
+ "+++ b/Gurjeet Singh \n"
+ "@@ -0,0 +1 @@\n"
+ "+I'm about to try git send-email\n"
+ "-- \n"
+ "2.21.0\n";
+
+ const char *stat =
+ " Gurjeet Singh | 1 +\n"
+ " 1 file changed, 1 insertion(+)\n"
+ " create mode 100644 Gurjeet Singh\n";
+
+ cl_git_pass(git_diff_from_buffer(&diff, input, strlen(input)));
+ cl_git_pass(git_diff_get_stats(&_stats, diff));
+ cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY, 0));
+ cl_assert_equal_s(stat, git_buf_cstr(&buf));
+
+ git_buf_dispose(&buf);
+ git_diff_free(diff);
+}
diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c
index f2404958e..00c52ff1b 100644
--- a/tests/diff/workdir.c
+++ b/tests/diff/workdir.c
@@ -2203,3 +2203,38 @@ void test_diff_workdir__order(void)
git_diff_free(diff);
git_tree_free(tree);
}
+
+void test_diff_workdir__ignore_blank_lines(void)
+{
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_diff *diff;
+ git_patch *patch;
+ git_buf buf = GIT_BUF_INIT;
+
+ g_repo = cl_git_sandbox_init("rebase");
+ cl_git_rewritefile("rebase/gravy.txt", "GRAVY SOUP.\n\n\nGet eight pounds of coarse lean beef--wash it clean and lay it in your\n\npot, put in the same ingredients as for the shin soup, with the same\nquantity of water, and follow the process directed for that. Strain the\nsoup through a sieve, and serve it up clear, with nothing more than\ntoasted bread in it; two table-spoonsful of mushroom catsup will add a\nfine flavour to the soup!\n");
+
+ /* Perform the diff normally */
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+ cl_git_pass(git_patch_from_diff(&patch, diff, 0));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+
+ cl_assert_equal_s("diff --git a/gravy.txt b/gravy.txt\nindex c4e6cca..3c617e6 100644\n--- a/gravy.txt\n+++ b/gravy.txt\n@@ -1,8 +1,10 @@\n GRAVY SOUP.\n \n+\n Get eight pounds of coarse lean beef--wash it clean and lay it in your\n+\n pot, put in the same ingredients as for the shin soup, with the same\n quantity of water, and follow the process directed for that. Strain the\n soup through a sieve, and serve it up clear, with nothing more than\n toasted bread in it; two table-spoonsful of mushroom catsup will add a\n-fine flavour to the soup.\n+fine flavour to the soup!\n", buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_patch_free(patch);
+ git_diff_free(diff);
+
+ /* Perform the diff ignoring blank lines */
+ opts.flags |= GIT_DIFF_IGNORE_BLANK_LINES;
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+ cl_git_pass(git_patch_from_diff(&patch, diff, 0));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+
+ cl_assert_equal_s("diff --git a/gravy.txt b/gravy.txt\nindex c4e6cca..3c617e6 100644\n--- a/gravy.txt\n+++ b/gravy.txt\n@@ -5,4 +7,4 @@ pot, put in the same ingredients as for the shin soup, with the same\n quantity of water, and follow the process directed for that. Strain the\n soup through a sieve, and serve it up clear, with nothing more than\n toasted bread in it; two table-spoonsful of mushroom catsup will add a\n-fine flavour to the soup.\n+fine flavour to the soup!\n", buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_patch_free(patch);
+ git_diff_free(diff);
+}
diff --git a/tests/email/create.c b/tests/email/create.c
new file mode 100644
index 000000000..ccf79c2aa
--- /dev/null
+++ b/tests/email/create.c
@@ -0,0 +1,363 @@
+#include "clar.h"
+#include "clar_libgit2.h"
+
+#include "buffer.h"
+#include "diff_generate.h"
+
+static git_repository *repo;
+
+void test_email_create__initialize(void)
+{
+ repo = cl_git_sandbox_init("diff_format_email");
+}
+
+void test_email_create__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+static void email_for_commit(
+ git_buf *out,
+ const char *commit_id,
+ git_email_create_options *opts)
+{
+ git_oid oid;
+ git_commit *commit = NULL;
+ git_diff *diff = NULL;
+
+ git_oid_fromstr(&oid, commit_id);
+
+ cl_git_pass(git_commit_lookup(&commit, repo, &oid));
+
+ cl_git_pass(git_email_create_from_commit(out, commit, opts));
+
+ git_diff_free(diff);
+ git_commit_free(commit);
+}
+
+static void assert_email_match(
+ const char *expected,
+ const char *commit_id,
+ git_email_create_options *opts)
+{
+ git_buf buf = GIT_BUF_INIT;
+
+ email_for_commit(&buf, commit_id, opts);
+ cl_assert_equal_s(expected, git_buf_cstr(&buf));
+
+ git_buf_dispose(&buf);
+}
+
+static void assert_subject_match(
+ const char *expected,
+ const char *commit_id,
+ git_email_create_options *opts)
+{
+ git_buf buf = GIT_BUF_INIT;
+ const char *loc;
+
+ email_for_commit(&buf, commit_id, opts);
+
+ cl_assert((loc = strstr(buf.ptr, "\nSubject: ")) != NULL);
+ git_buf_consume(&buf, (loc + 10));
+ git_buf_truncate_at_char(&buf, '\n');
+
+ cl_assert_equal_s(expected, git_buf_cstr(&buf));
+
+ git_buf_dispose(&buf);
+}
+
+void test_email_create__commit(void)
+{
+ const char *expected =
+ "From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \
+ "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+ "Date: Wed, 9 Apr 2014 20:57:01 +0200\n" \
+ "Subject: [PATCH] Modify some content\n" \
+ "\n" \
+ "---\n" \
+ " file1.txt | 8 +++++---\n" \
+ " 1 file changed, 5 insertions(+), 3 deletions(-)\n" \
+ "\n" \
+ "diff --git a/file1.txt b/file1.txt\n" \
+ "index 94aaae8..af8f41d 100644\n" \
+ "--- a/file1.txt\n" \
+ "+++ b/file1.txt\n" \
+ "@@ -1,15 +1,17 @@\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ "+_file1.txt_\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ "+\n" \
+ "+\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "+_file1.txt_\n" \
+ "+_file1.txt_\n" \
+ " file1.txt\n" \
+ "--\n" \
+ "libgit2 " LIBGIT2_VERSION "\n" \
+ "\n";
+
+ assert_email_match(
+ expected, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", NULL);
+}
+
+void test_email_create__rename(void)
+{
+ const char *expected =
+ "From 6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d Mon Sep 17 00:00:00 2001\n" \
+ "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+ "Date: Wed, 9 Apr 2014 21:15:56 +0200\n" \
+ "Subject: [PATCH] Renamed file1.txt -> file1.txt.renamed\n" \
+ "\n" \
+ "---\n" \
+ " file1.txt => file1.txt.renamed | 4 ++--\n" \
+ " 1 file changed, 2 insertions(+), 2 deletions(-)\n" \
+ "\n" \
+ "diff --git a/file1.txt b/file1.txt.renamed\n" \
+ "similarity index 86%\n" \
+ "rename from file1.txt\n" \
+ "rename to file1.txt.renamed\n" \
+ "index af8f41d..a97157a 100644\n" \
+ "--- a/file1.txt\n" \
+ "+++ b/file1.txt.renamed\n" \
+ "@@ -3,13 +3,13 @@ file1.txt\n" \
+ " _file1.txt_\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ "-file1.txt\n" \
+ "+file1.txt_renamed\n" \
+ " file1.txt\n" \
+ " \n" \
+ " \n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ "-file1.txt\n" \
+ "+file1.txt_renamed\n" \
+ " file1.txt\n" \
+ " file1.txt\n" \
+ " _file1.txt_\n" \
+ "--\n" \
+ "libgit2 " LIBGIT2_VERSION "\n" \
+ "\n";
+
+ assert_email_match(expected, "6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d", NULL);
+}
+
+void test_email_create__rename_as_add_delete(void)
+{
+ const char *expected =
+ "From 6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d Mon Sep 17 00:00:00 2001\n" \
+ "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+ "Date: Wed, 9 Apr 2014 21:15:56 +0200\n" \
+ "Subject: [PATCH] Renamed file1.txt -> file1.txt.renamed\n" \
+ "\n" \
+ "---\n" \
+ " file1.txt | 17 -----------------\n" \
+ " file1.txt.renamed | 17 +++++++++++++++++\n" \
+ " 2 files changed, 17 insertions(+), 17 deletions(-)\n" \
+ " delete mode 100644 file1.txt\n" \
+ " create mode 100644 file1.txt.renamed\n" \
+ "\n" \
+ "diff --git a/file1.txt b/file1.txt\n" \
+ "deleted file mode 100644\n" \
+ "index af8f41d..0000000\n" \
+ "--- a/file1.txt\n" \
+ "+++ /dev/null\n" \
+ "@@ -1,17 +0,0 @@\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-_file1.txt_\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-\n" \
+ "-\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-file1.txt\n" \
+ "-_file1.txt_\n" \
+ "-_file1.txt_\n" \
+ "-file1.txt\n" \
+ "diff --git a/file1.txt.renamed b/file1.txt.renamed\n" \
+ "new file mode 100644\n" \
+ "index 0000000..a97157a\n" \
+ "--- /dev/null\n" \
+ "+++ b/file1.txt.renamed\n" \
+ "@@ -0,0 +1,17 @@\n" \
+ "+file1.txt\n" \
+ "+file1.txt\n" \
+ "+_file1.txt_\n" \
+ "+file1.txt\n" \
+ "+file1.txt\n" \
+ "+file1.txt_renamed\n" \
+ "+file1.txt\n" \
+ "+\n" \
+ "+\n" \
+ "+file1.txt\n" \
+ "+file1.txt\n" \
+ "+file1.txt_renamed\n" \
+ "+file1.txt\n" \
+ "+file1.txt\n" \
+ "+_file1.txt_\n" \
+ "+_file1.txt_\n" \
+ "+file1.txt\n" \
+ "--\n" \
+ "libgit2 " LIBGIT2_VERSION "\n" \
+ "\n";
+
+ git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+ opts.flags |= GIT_EMAIL_CREATE_NO_RENAMES;
+
+ assert_email_match(expected, "6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d", &opts);
+}
+
+void test_email_create__binary(void)
+{
+ const char *expected =
+ "From 8d7523f6fcb2404257889abe0d96f093d9f524f9 Mon Sep 17 00:00:00 2001\n" \
+ "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+ "Date: Sun, 13 Apr 2014 18:10:18 +0200\n" \
+ "Subject: [PATCH] Modified binary file\n" \
+ "\n" \
+ "---\n" \
+ " binary.bin | Bin 3 -> 5 bytes\n" \
+ " 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
+ "\n" \
+ "diff --git a/binary.bin b/binary.bin\n" \
+ "index bd474b2519cc15eab801ff851cc7d50f0dee49a1..9ac35ff15cd8864aeafd889e4826a3150f0b06c4 100644\n" \
+ "GIT binary patch\n" \
+ "literal 5\n" \
+ "Mc${NkU}WL~000&M4gdfE\n" \
+ "\n" \
+ "literal 3\n" \
+ "Kc${Nk-~s>u4FC%O\n" \
+ "\n" \
+ "--\n" \
+ "libgit2 " LIBGIT2_VERSION "\n" \
+ "\n";
+
+ assert_email_match(expected, "8d7523f6fcb2404257889abe0d96f093d9f524f9", NULL);
+}
+
+void test_email_create__binary_not_included(void)
+{
+ const char *expected =
+ "From 8d7523f6fcb2404257889abe0d96f093d9f524f9 Mon Sep 17 00:00:00 2001\n" \
+ "From: Jacques Germishuys <jacquesg@striata.com>\n" \
+ "Date: Sun, 13 Apr 2014 18:10:18 +0200\n" \
+ "Subject: [PATCH] Modified binary file\n" \
+ "\n" \
+ "---\n" \
+ " binary.bin | Bin 3 -> 5 bytes\n" \
+ " 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
+ "\n" \
+ "diff --git a/binary.bin b/binary.bin\n" \
+ "index bd474b2..9ac35ff 100644\n" \
+ "Binary files a/binary.bin and b/binary.bin differ\n" \
+ "--\n" \
+ "libgit2 " LIBGIT2_VERSION "\n" \
+ "\n";
+
+ git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+ opts.diff_opts.flags &= ~GIT_DIFF_SHOW_BINARY;
+
+ assert_email_match(expected, "8d7523f6fcb2404257889abe0d96f093d9f524f9", &opts);
+}
+
+void test_email_create__custom_summary_and_body(void)
+{
+ const char *expected = "From 627e7e12d87e07a83fad5b6bfa25e86ead4a5270 Mon Sep 17 00:00:00 2001\n" \
+ "From: Patrick Steinhardt <ps@pks.im>\n" \
+ "Date: Tue, 24 Nov 2015 13:34:39 +0100\n" \
+ "Subject: [PPPPPATCH 2/4] This is a subject\n" \
+ "\n" \
+ "Modify content of file3.txt by appending a new line. Make this\n" \
+ "commit message somewhat longer to test behavior with newlines\n" \
+ "embedded in the message body.\n" \
+ "\n" \
+ "Also test if new paragraphs are included correctly.\n" \
+ "---\n" \
+ " file3.txt | 1 +\n" \
+ " 1 file changed, 1 insertion(+)\n" \
+ "\n" \
+ "diff --git a/file3.txt b/file3.txt\n" \
+ "index 9a2d780..7309653 100644\n" \
+ "--- a/file3.txt\n" \
+ "+++ b/file3.txt\n" \
+ "@@ -3,3 +3,4 @@ file3!\n" \
+ " file3\n" \
+ " file3\n" \
+ " file3\n" \
+ "+file3\n" \
+ "--\n" \
+ "libgit2 " LIBGIT2_VERSION "\n" \
+ "\n";
+
+ const char *summary = "This is a subject\nwith\nnewlines";
+ const char *body = "Modify content of file3.txt by appending a new line. Make this\n" \
+ "commit message somewhat longer to test behavior with newlines\n" \
+ "embedded in the message body.\n" \
+ "\n" \
+ "Also test if new paragraphs are included correctly.";
+
+ git_oid oid;
+ git_commit *commit = NULL;
+ git_diff *diff = NULL;
+ git_buf buf = GIT_BUF_INIT;
+ git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+
+ opts.subject_prefix = "PPPPPATCH";
+
+ git_oid_fromstr(&oid, "627e7e12d87e07a83fad5b6bfa25e86ead4a5270");
+ cl_git_pass(git_commit_lookup(&commit, repo, &oid));
+ cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
+ cl_git_pass(git_email_create_from_diff(&buf, diff, 2, 4, &oid, summary, body, git_commit_author(commit), &opts));
+
+ cl_assert_equal_s(expected, git_buf_cstr(&buf));
+
+ git_diff_free(diff);
+ git_commit_free(commit);
+ git_buf_dispose(&buf);
+}
+
+void test_email_create__commit_subjects(void)
+{
+ git_email_create_options opts = GIT_EMAIL_CREATE_OPTIONS_INIT;
+
+ assert_subject_match("[PATCH] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+ opts.reroll_number = 42;
+ assert_subject_match("[PATCH v42] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+ opts.flags |= GIT_EMAIL_CREATE_ALWAYS_NUMBER;
+ assert_subject_match("[PATCH v42 1/1] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+ opts.start_number = 9;
+ assert_subject_match("[PATCH v42 9/9] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+ opts.subject_prefix = "";
+ assert_subject_match("[v42 9/9] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+ opts.reroll_number = 0;
+ assert_subject_match("[9/9] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+ opts.start_number = 0;
+ assert_subject_match("[1/1] Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+
+ opts.flags = GIT_EMAIL_CREATE_OMIT_NUMBERS;
+ assert_subject_match("Modify some content", "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts);
+}
diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c
index 6cea6d166..6881af40a 100644
--- a/tests/fetchhead/nonetwork.c
+++ b/tests/fetchhead/nonetwork.c
@@ -82,7 +82,7 @@ void test_fetchhead_nonetwork__write(void)
int equals = 0;
size_t i;
- git_vector_init(&fetchhead_vector, 6, NULL);
+ cl_git_pass(git_vector_init(&fetchhead_vector, 6, NULL));
cl_set_cleanup(&cleanup_repository, "./test1");
cl_git_pass(git_repository_init(&g_repo, "./test1", 0));
@@ -319,6 +319,16 @@ static int assert_master_for_merge(const char *ref, const char *url, const git_o
return 0;
}
+static int assert_none_for_merge(const char *ref, const char *url, const git_oid *id, unsigned int is_merge, void *data)
+{
+ GIT_UNUSED(ref);
+ GIT_UNUSED(url);
+ GIT_UNUSED(id);
+ GIT_UNUSED(data);
+
+ return is_merge ? -1 : 0;
+}
+
void test_fetchhead_nonetwork__unborn_with_upstream(void)
{
git_repository *repo;
@@ -366,6 +376,25 @@ void test_fetchhead_nonetwork__fetch_into_repo_with_symrefs(void)
cl_git_sandbox_cleanup();
}
+void test_fetchhead_nonetwork__fetch_into_repo_with_invalid_head(void)
+{
+ git_remote *remote;
+ char *strings[] = { "refs/heads/*:refs/remotes/origin/*" };
+ git_strarray refspecs = { strings, 1 };
+
+ cl_set_cleanup(&cleanup_repository, "./test1");
+ cl_git_pass(git_repository_init(&g_repo, "./test1", 0));
+
+ /* HEAD pointing to nonexistent branch */
+ cl_git_rewritefile("./test1/.git/HEAD", "ref: refs/heads/\n");
+
+ cl_git_pass(git_remote_create_anonymous(&remote, g_repo, cl_fixture("testrepo.git")));
+ cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, NULL));
+ cl_git_pass(git_repository_fetchhead_foreach(g_repo, assert_none_for_merge, NULL));
+
+ git_remote_free(remote);
+}
+
void test_fetchhead_nonetwork__quote_in_branch_name(void)
{
cl_set_cleanup(&cleanup_repository, "./test1");
diff --git a/tests/filter/bare.c b/tests/filter/bare.c
index 430931ee8..8402638ce 100644
--- a/tests/filter/bare.c
+++ b/tests/filter/bare.c
@@ -10,7 +10,7 @@ void test_filter_bare__initialize(void)
cl_git_pass(git_repository_open(&g_repo, "crlf.git"));
filter_opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES;
- filter_opts.flags |= GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD;
+ filter_opts.flags |= GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD;
}
void test_filter_bare__cleanup(void)
@@ -132,3 +132,57 @@ void test_filter_bare__sanitizes(void)
git_blob_free(blob);
}
+void test_filter_bare__from_specific_commit_one(void)
+{
+ git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
+ git_blob *blob;
+ git_buf buf = { 0 };
+
+ opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES;
+ opts.flags |= GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT;
+ cl_git_pass(git_oid_fromstr(&opts.attr_commit_id, "b8986fec0f7bde90f78ac72706e782d82f24f2f0"));
+
+ cl_git_pass(git_revparse_single(
+ (git_object **)&blob, g_repo, "055c872")); /* ident */
+
+ cl_assert_equal_s("$Id$\n", git_blob_rawcontent(blob));
+
+ cl_git_pass(git_blob_filter(&buf, blob, "ident.bin", &opts));
+ cl_assert_equal_s("$Id$\n", buf.ptr);
+
+ cl_git_pass(git_blob_filter(&buf, blob, "ident.identlf", &opts));
+ cl_assert_equal_s("$Id: 055c8729cdcc372500a08db659c045e16c4409fb $\n", buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_blob_free(blob);
+}
+
+void test_filter_bare__from_specific_commit_with_no_attributes_file(void)
+{
+ git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
+ git_blob *blob;
+ git_buf buf = { 0 };
+
+ opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES;
+ opts.flags |= GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT;
+ cl_git_pass(git_oid_fromstr(&opts.attr_commit_id, "5afb6a14a864e30787857dd92af837e8cdd2cb1b"));
+
+ cl_git_pass(git_revparse_single(
+ (git_object **)&blob, g_repo, "799770d")); /* all-lf */
+
+ cl_assert_equal_s(ALL_LF_TEXT_RAW, git_blob_rawcontent(blob));
+
+ cl_git_pass(git_blob_filter(&buf, blob, "file.bin", &opts));
+ cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
+
+ /* we never convert CRLF -> LF on platforms that have LF */
+ cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &opts));
+ cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
+
+ /* we never convert CRLF -> LF on platforms that have LF */
+ cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &opts));
+ cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_blob_free(blob);
+}
diff --git a/tests/filter/crlf.c b/tests/filter/crlf.c
index a266005d4..bc9c7f289 100644
--- a/tests/filter/crlf.c
+++ b/tests/filter/crlf.c
@@ -23,7 +23,9 @@ void test_filter_crlf__to_worktree(void)
{
git_filter_list *fl;
git_filter *crlf;
- git_buf in = { 0 }, out = { 0 };
+ git_buf out = GIT_BUF_INIT;
+ const char *in;
+ size_t in_len;
cl_git_pass(git_filter_list_new(
&fl, g_repo, GIT_FILTER_TO_WORKTREE, 0));
@@ -33,10 +35,10 @@ void test_filter_crlf__to_worktree(void)
cl_git_pass(git_filter_list_push(fl, crlf, NULL));
- in.ptr = "Some text\nRight here\n";
- in.size = strlen(in.ptr);
+ in = "Some text\nRight here\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Some text\r\nRight here\r\n", out.ptr);
@@ -48,7 +50,9 @@ void test_filter_crlf__to_odb(void)
{
git_filter_list *fl;
git_filter *crlf;
- git_buf in = { 0 }, out = { 0 };
+ git_buf out = GIT_BUF_INIT;
+ const char *in;
+ size_t in_len;
cl_git_pass(git_filter_list_new(
&fl, g_repo, GIT_FILTER_TO_ODB, 0));
@@ -58,10 +62,10 @@ void test_filter_crlf__to_odb(void)
cl_git_pass(git_filter_list_push(fl, crlf, NULL));
- in.ptr = "Some text\r\nRight here\r\n";
- in.size = strlen(in.ptr);
+ in = "Some text\r\nRight here\r\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Some text\nRight here\n", out.ptr);
@@ -73,7 +77,9 @@ void test_filter_crlf__with_safecrlf(void)
{
git_filter_list *fl;
git_filter *crlf;
- git_buf in = {0}, out = GIT_BUF_INIT;
+ git_buf out = GIT_BUF_INIT;
+ const char *in;
+ size_t in_len;
cl_repo_set_bool(g_repo, "core.safecrlf", true);
@@ -86,31 +92,31 @@ void test_filter_crlf__with_safecrlf(void)
cl_git_pass(git_filter_list_push(fl, crlf, NULL));
/* Normalized \r\n succeeds with safecrlf */
- in.ptr = "Normal\r\nCRLF\r\nline-endings.\r\n";
- in.size = strlen(in.ptr);
+ in = "Normal\r\nCRLF\r\nline-endings.\r\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Normal\nCRLF\nline-endings.\n", out.ptr);
/* Mix of line endings fails with safecrlf */
- in.ptr = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
- in.size = strlen(in.ptr);
+ in = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
+ in_len = strlen(in);
- cl_git_fail(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_fail(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_i(git_error_last()->klass, GIT_ERROR_FILTER);
/* Normalized \n fails for autocrlf=true when safecrlf=true */
- in.ptr = "Normal\nLF\nonly\nline-endings.\n";
- in.size = strlen(in.ptr);
+ in = "Normal\nLF\nonly\nline-endings.\n";
+ in_len = strlen(in);
- cl_git_fail(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_fail(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_i(git_error_last()->klass, GIT_ERROR_FILTER);
/* String with \r but without \r\n does not fail with safecrlf */
- in.ptr = "Normal\nCR only\rand some more\nline-endings.\n";
- in.size = strlen(in.ptr);
+ in = "Normal\nCR only\rand some more\nline-endings.\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Normal\nCR only\rand some more\nline-endings.\n", out.ptr);
git_filter_list_free(fl);
@@ -121,7 +127,9 @@ void test_filter_crlf__with_safecrlf_and_unsafe_allowed(void)
{
git_filter_list *fl;
git_filter *crlf;
- git_buf in = {0}, out = GIT_BUF_INIT;
+ git_buf out = GIT_BUF_INIT;
+ const char *in;
+ size_t in_len;
cl_repo_set_bool(g_repo, "core.safecrlf", true);
@@ -134,25 +142,25 @@ void test_filter_crlf__with_safecrlf_and_unsafe_allowed(void)
cl_git_pass(git_filter_list_push(fl, crlf, NULL));
/* Normalized \r\n succeeds with safecrlf */
- in.ptr = "Normal\r\nCRLF\r\nline-endings.\r\n";
- in.size = strlen(in.ptr);
+ in = "Normal\r\nCRLF\r\nline-endings.\r\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Normal\nCRLF\nline-endings.\n", out.ptr);
/* Mix of line endings fails with safecrlf, but allowed to pass */
- in.ptr = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
- in.size = strlen(in.ptr);
+ in = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
/* TODO: check for warning */
cl_assert_equal_s("Mixed\nup\nLF\nand\nCRLF\nline-endings.\n", out.ptr);
/* Normalized \n fails with safecrlf, but allowed to pass */
- in.ptr = "Normal\nLF\nonly\nline-endings.\n";
- in.size = strlen(in.ptr);
+ in = "Normal\nLF\nonly\nline-endings.\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
/* TODO: check for warning */
cl_assert_equal_s("Normal\nLF\nonly\nline-endings.\n", out.ptr);
@@ -164,7 +172,9 @@ void test_filter_crlf__no_safecrlf(void)
{
git_filter_list *fl;
git_filter *crlf;
- git_buf in = {0}, out = GIT_BUF_INIT;
+ git_buf out = GIT_BUF_INIT;
+ const char *in;
+ size_t in_len;
cl_git_pass(git_filter_list_new(
&fl, g_repo, GIT_FILTER_TO_ODB, 0));
@@ -175,24 +185,24 @@ void test_filter_crlf__no_safecrlf(void)
cl_git_pass(git_filter_list_push(fl, crlf, NULL));
/* Normalized \r\n succeeds with safecrlf */
- in.ptr = "Normal\r\nCRLF\r\nline-endings.\r\n";
- in.size = strlen(in.ptr);
+ in = "Normal\r\nCRLF\r\nline-endings.\r\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Normal\nCRLF\nline-endings.\n", out.ptr);
/* Mix of line endings fails with safecrlf */
- in.ptr = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
- in.size = strlen(in.ptr);
+ in = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Mixed\nup\nLF\nand\nCRLF\nline-endings.\n", out.ptr);
/* Normalized \n fails with safecrlf */
- in.ptr = "Normal\nLF\nonly\nline-endings.\n";
- in.size = strlen(in.ptr);
+ in = "Normal\nLF\nonly\nline-endings.\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Normal\nLF\nonly\nline-endings.\n", out.ptr);
git_filter_list_free(fl);
@@ -203,7 +213,9 @@ void test_filter_crlf__safecrlf_warn(void)
{
git_filter_list *fl;
git_filter *crlf;
- git_buf in = {0}, out = GIT_BUF_INIT;
+ git_buf out = GIT_BUF_INIT;
+ const char *in;
+ size_t in_len;
cl_repo_set_string(g_repo, "core.safecrlf", "warn");
@@ -216,26 +228,26 @@ void test_filter_crlf__safecrlf_warn(void)
cl_git_pass(git_filter_list_push(fl, crlf, NULL));
/* Normalized \r\n succeeds with safecrlf=warn */
- in.ptr = "Normal\r\nCRLF\r\nline-endings.\r\n";
- in.size = strlen(in.ptr);
+ in = "Normal\r\nCRLF\r\nline-endings.\r\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_s("Normal\nCRLF\nline-endings.\n", out.ptr);
/* Mix of line endings succeeds with safecrlf=warn */
- in.ptr = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
- in.size = strlen(in.ptr);
+ in = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
/* TODO: check for warning */
cl_assert_equal_s("Mixed\nup\nLF\nand\nCRLF\nline-endings.\n", out.ptr);
/* Normalized \n is reversible, so does not fail with safecrlf=warn */
- in.ptr = "Normal\nLF\nonly\nline-endings.\n";
- in.size = strlen(in.ptr);
+ in = "Normal\nLF\nonly\nline-endings.\n";
+ in_len = strlen(in);
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
- cl_assert_equal_s(in.ptr, out.ptr);
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
+ cl_assert_equal_s(in, out.ptr);
git_filter_list_free(fl);
git_buf_dispose(&out);
diff --git a/tests/filter/custom.c b/tests/filter/custom.c
index fe2025fc2..57cef33ce 100644
--- a/tests/filter/custom.c
+++ b/tests/filter/custom.c
@@ -2,7 +2,6 @@
#include "posix.h"
#include "blob.h"
#include "filter.h"
-#include "buf_text.h"
#include "git2/sys/filter.h"
#include "git2/sys/repository.h"
#include "custom_helpers.h"
@@ -95,13 +94,17 @@ static void register_custom_filters(void)
void test_filter_custom__to_odb(void)
{
git_filter_list *fl;
- git_buf out = { 0 };
- git_buf in = GIT_BUF_INIT_CONST(workdir_data, strlen(workdir_data));
+ git_buf out = GIT_BUF_INIT;
+ const char *in;
+ size_t in_len;
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "herofile", GIT_FILTER_TO_ODB, 0));
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ in = workdir_data;
+ in_len = strlen(workdir_data);
+
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_i(BITFLIPPED_AND_REVERSED_DATA_LEN, out.size);
@@ -115,14 +118,17 @@ void test_filter_custom__to_odb(void)
void test_filter_custom__to_workdir(void)
{
git_filter_list *fl;
- git_buf out = { 0 };
- git_buf in = GIT_BUF_INIT_CONST(
- bitflipped_and_reversed_data, BITFLIPPED_AND_REVERSED_DATA_LEN);
+ git_buf out = GIT_BUF_INIT;
+ const char *in;
+ size_t in_len;
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE, 0));
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ in = (char *)bitflipped_and_reversed_data;
+ in_len = BITFLIPPED_AND_REVERSED_DATA_LEN;
+
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, in, in_len));
cl_assert_equal_i(strlen(workdir_data), out.size);
@@ -246,12 +252,16 @@ void test_filter_custom__erroneous_filter_fails(void)
{
git_filter_list *filters;
git_buf out = GIT_BUF_INIT;
- git_buf in = GIT_BUF_INIT_CONST(workdir_data, strlen(workdir_data));
+ const char *in;
+ size_t in_len;
cl_git_pass(git_filter_list_load(
&filters, g_repo, NULL, "villain", GIT_FILTER_TO_WORKTREE, 0));
- cl_git_fail(git_filter_list_apply_to_data(&out, filters, &in));
+ in = workdir_data;
+ in_len = strlen(workdir_data);
+
+ cl_git_fail(git_filter_list_apply_to_buffer(&out, filters, in, in_len));
git_filter_list_free(filters);
git_buf_dispose(&out);
diff --git a/tests/filter/custom_helpers.c b/tests/filter/custom_helpers.c
index d7f2afe7a..ee3b6353b 100644
--- a/tests/filter/custom_helpers.c
+++ b/tests/filter/custom_helpers.c
@@ -1,7 +1,6 @@
#include "clar_libgit2.h"
#include "posix.h"
#include "filter.h"
-#include "buf_text.h"
#include "git2/sys/filter.h"
#define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff)
@@ -38,6 +37,17 @@ int bitflip_filter_apply(
return 0;
}
+static int bitflip_filter_stream(
+ git_writestream **out,
+ git_filter *self,
+ void **payload,
+ const git_filter_source *src,
+ git_writestream *next)
+{
+ return git_filter_buffered_stream_new(out,
+ self, bitflip_filter_apply, NULL, payload, src, next);
+}
+
static void bitflip_filter_free(git_filter *f)
{
git__free(f);
@@ -51,7 +61,7 @@ git_filter *create_bitflip_filter(void)
filter->version = GIT_FILTER_VERSION;
filter->attributes = "+bitflip";
filter->shutdown = bitflip_filter_free;
- filter->apply = bitflip_filter_apply;
+ filter->stream = bitflip_filter_stream;
return filter;
}
@@ -89,6 +99,17 @@ int reverse_filter_apply(
return 0;
}
+static int reverse_filter_stream(
+ git_writestream **out,
+ git_filter *self,
+ void **payload,
+ const git_filter_source *src,
+ git_writestream *next)
+{
+ return git_filter_buffered_stream_new(out,
+ self, reverse_filter_apply, NULL, payload, src, next);
+}
+
static void reverse_filter_free(git_filter *f)
{
git__free(f);
@@ -102,7 +123,7 @@ git_filter *create_reverse_filter(const char *attrs)
filter->version = GIT_FILTER_VERSION;
filter->attributes = attrs;
filter->shutdown = reverse_filter_free;
- filter->apply = reverse_filter_apply;
+ filter->stream = reverse_filter_stream;
return filter;
}
diff --git a/tests/filter/stream.c b/tests/filter/stream.c
index 226092c3f..b6a4c3ca1 100644
--- a/tests/filter/stream.c
+++ b/tests/filter/stream.c
@@ -2,7 +2,6 @@
#include "posix.h"
#include "blob.h"
#include "filter.h"
-#include "buf_text.h"
#include "git2/sys/filter.h"
#include "git2/sys/repository.h"
diff --git a/tests/filter/wildcard.c b/tests/filter/wildcard.c
index 3c25ea266..0c9c13b1e 100644
--- a/tests/filter/wildcard.c
+++ b/tests/filter/wildcard.c
@@ -2,7 +2,6 @@
#include "posix.h"
#include "blob.h"
#include "filter.h"
-#include "buf_text.h"
#include "git2/sys/filter.h"
#include "git2/sys/repository.h"
#include "custom_helpers.h"
@@ -94,6 +93,17 @@ static int wildcard_filter_apply(
return GIT_PASSTHROUGH;
}
+static int wildcard_filter_stream(
+ git_writestream **out,
+ git_filter *self,
+ void **payload,
+ const git_filter_source *src,
+ git_writestream *next)
+{
+ return git_filter_buffered_stream_new(out,
+ self, wildcard_filter_apply, NULL, payload, src, next);
+}
+
static void wildcard_filter_cleanup(git_filter *self, void *payload)
{
GIT_UNUSED(self);
@@ -113,7 +123,7 @@ static git_filter *create_wildcard_filter(void)
filter->version = GIT_FILTER_VERSION;
filter->attributes = "filter=*";
filter->check = wildcard_filter_check;
- filter->apply = wildcard_filter_apply;
+ filter->stream = wildcard_filter_stream;
filter->cleanup = wildcard_filter_cleanup;
filter->shutdown = wildcard_filter_free;
@@ -123,13 +133,12 @@ static git_filter *create_wildcard_filter(void)
void test_filter_wildcard__reverse(void)
{
git_filter_list *fl;
- git_buf in = GIT_BUF_INIT, out = GIT_BUF_INIT;
+ git_buf out = GIT_BUF_INIT;
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "hero-reverse-foo", GIT_FILTER_TO_ODB, 0));
- cl_git_pass(git_buf_put(&in, (char *)input, DATA_LEN));
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, (char *)input, DATA_LEN));
cl_assert_equal_i(DATA_LEN, out.size);
@@ -138,19 +147,17 @@ void test_filter_wildcard__reverse(void)
git_filter_list_free(fl);
git_buf_dispose(&out);
- git_buf_dispose(&in);
}
void test_filter_wildcard__flip(void)
{
git_filter_list *fl;
- git_buf in = GIT_BUF_INIT, out = GIT_BUF_INIT;
+ git_buf out = GIT_BUF_INIT;
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "hero-flip-foo", GIT_FILTER_TO_ODB, 0));
- cl_git_pass(git_buf_put(&in, (char *)input, DATA_LEN));
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, (char *)input, DATA_LEN));
cl_assert_equal_i(DATA_LEN, out.size);
@@ -159,19 +166,17 @@ void test_filter_wildcard__flip(void)
git_filter_list_free(fl);
git_buf_dispose(&out);
- git_buf_dispose(&in);
}
void test_filter_wildcard__none(void)
{
git_filter_list *fl;
- git_buf in = GIT_BUF_INIT, out = GIT_BUF_INIT;
+ git_buf out = GIT_BUF_INIT;
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "none-foo", GIT_FILTER_TO_ODB, 0));
- cl_git_pass(git_buf_put(&in, (char *)input, DATA_LEN));
- cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
+ cl_git_pass(git_filter_list_apply_to_buffer(&out, fl, (char *)input, DATA_LEN));
cl_assert_equal_i(DATA_LEN, out.size);
@@ -180,5 +185,4 @@ void test_filter_wildcard__none(void)
git_filter_list_free(fl);
git_buf_dispose(&out);
- git_buf_dispose(&in);
}
diff --git a/tests/graph/commit_graph.c b/tests/graph/commit_graph.c
new file mode 100644
index 000000000..5926dca6f
--- /dev/null
+++ b/tests/graph/commit_graph.c
@@ -0,0 +1,125 @@
+#include "clar_libgit2.h"
+
+#include <git2.h>
+#include <git2/sys/commit_graph.h>
+
+#include "commit_graph.h"
+#include "futils.h"
+
+void test_graph_commit_graph__parse(void)
+{
+ git_repository *repo;
+ struct git_commit_graph_file *file;
+ struct git_commit_graph_entry e, parent;
+ git_oid id;
+ git_buf commit_graph_path = GIT_BUF_INIT;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+ cl_git_pass(git_buf_joinpath(&commit_graph_path, git_repository_path(repo), "objects/info/commit-graph"));
+ cl_git_pass(git_commit_graph_file_open(&file, git_buf_cstr(&commit_graph_path)));
+ cl_assert_equal_i(git_commit_graph_file_needs_refresh(file, git_buf_cstr(&commit_graph_path)), 0);
+
+ cl_git_pass(git_oid_fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5"));
+ cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
+ cl_assert_equal_oid(&e.sha1, &id);
+ cl_git_pass(git_oid_fromstr(&id, "418382dff1ffb8bdfba833f4d8bbcde58b1e7f47"));
+ cl_assert_equal_oid(&e.tree_oid, &id);
+ cl_assert_equal_i(e.generation, 1);
+ cl_assert_equal_i(e.commit_time, UINT64_C(1273610423));
+ cl_assert_equal_i(e.parent_count, 0);
+
+ cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
+ cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
+ cl_assert_equal_oid(&e.sha1, &id);
+ cl_assert_equal_i(e.generation, 5);
+ cl_assert_equal_i(e.commit_time, UINT64_C(1274813907));
+ cl_assert_equal_i(e.parent_count, 2);
+
+ cl_git_pass(git_oid_fromstr(&id, "9fd738e8f7967c078dceed8190330fc8648ee56a"));
+ cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 0));
+ cl_assert_equal_oid(&parent.sha1, &id);
+ cl_assert_equal_i(parent.generation, 4);
+
+ cl_git_pass(git_oid_fromstr(&id, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
+ cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 1));
+ cl_assert_equal_oid(&parent.sha1, &id);
+ cl_assert_equal_i(parent.generation, 3);
+
+ git_commit_graph_file_free(file);
+ git_repository_free(repo);
+ git_buf_dispose(&commit_graph_path);
+}
+
+void test_graph_commit_graph__parse_octopus_merge(void)
+{
+ git_repository *repo;
+ struct git_commit_graph_file *file;
+ struct git_commit_graph_entry e, parent;
+ git_oid id;
+ git_buf commit_graph_path = GIT_BUF_INIT;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("merge-recursive/.gitted")));
+ cl_git_pass(git_buf_joinpath(&commit_graph_path, git_repository_path(repo), "objects/info/commit-graph"));
+ cl_git_pass(git_commit_graph_file_open(&file, git_buf_cstr(&commit_graph_path)));
+
+ cl_git_pass(git_oid_fromstr(&id, "d71c24b3b113fd1d1909998c5bfe33b86a65ee03"));
+ cl_git_pass(git_commit_graph_entry_find(&e, file, &id, GIT_OID_HEXSZ));
+ cl_assert_equal_oid(&e.sha1, &id);
+ cl_git_pass(git_oid_fromstr(&id, "348f16ffaeb73f319a75cec5b16a0a47d2d5e27c"));
+ cl_assert_equal_oid(&e.tree_oid, &id);
+ cl_assert_equal_i(e.generation, 7);
+ cl_assert_equal_i(e.commit_time, UINT64_C(1447083009));
+ cl_assert_equal_i(e.parent_count, 3);
+
+ cl_git_pass(git_oid_fromstr(&id, "ad2ace9e15f66b3d1138922e6ffdc3ea3f967fa6"));
+ cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 0));
+ cl_assert_equal_oid(&parent.sha1, &id);
+ cl_assert_equal_i(parent.generation, 6);
+
+ cl_git_pass(git_oid_fromstr(&id, "483065df53c0f4a02cdc6b2910b05d388fc17ffb"));
+ cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 1));
+ cl_assert_equal_oid(&parent.sha1, &id);
+ cl_assert_equal_i(parent.generation, 2);
+
+ cl_git_pass(git_oid_fromstr(&id, "815b5a1c80ca749d705c7aa0cb294a00cbedd340"));
+ cl_git_pass(git_commit_graph_entry_parent(&parent, file, &e, 2));
+ cl_assert_equal_oid(&parent.sha1, &id);
+ cl_assert_equal_i(parent.generation, 6);
+
+ git_commit_graph_file_free(file);
+ git_repository_free(repo);
+ git_buf_dispose(&commit_graph_path);
+}
+
+void test_graph_commit_graph__writer(void)
+{
+ git_repository *repo;
+ git_commit_graph_writer *w = NULL;
+ git_revwalk *walk;
+ git_commit_graph_writer_options opts = GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT;
+ git_buf cgraph = GIT_BUF_INIT, expected_cgraph = GIT_BUF_INIT, path = GIT_BUF_INIT;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+ cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/info"));
+ cl_git_pass(git_commit_graph_writer_new(&w, git_buf_cstr(&path)));
+
+ /* This is equivalent to `git commit-graph write --reachable`. */
+ cl_git_pass(git_revwalk_new(&walk, repo));
+ cl_git_pass(git_revwalk_push_glob(walk, "refs/*"));
+ cl_git_pass(git_commit_graph_writer_add_revwalk(w, walk));
+ git_revwalk_free(walk);
+
+ cl_git_pass(git_commit_graph_writer_dump(&cgraph, w, &opts));
+ cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/info/commit-graph"));
+ cl_git_pass(git_futils_readbuffer(&expected_cgraph, git_buf_cstr(&path)));
+
+ cl_assert_equal_i(git_buf_len(&cgraph), git_buf_len(&expected_cgraph));
+ cl_assert_equal_i(memcmp(git_buf_cstr(&cgraph), git_buf_cstr(&expected_cgraph), git_buf_len(&cgraph)), 0);
+
+ git_buf_dispose(&cgraph);
+ git_buf_dispose(&expected_cgraph);
+ git_buf_dispose(&path);
+ git_commit_graph_writer_free(w);
+ git_repository_free(repo);
+}
diff --git a/tests/graph/reachable_from_any.c b/tests/graph/reachable_from_any.c
new file mode 100644
index 000000000..5c8416499
--- /dev/null
+++ b/tests/graph/reachable_from_any.c
@@ -0,0 +1,236 @@
+#include "clar_libgit2.h"
+
+#include <git2.h>
+
+#include "commit_graph.h"
+#include "bitvec.h"
+#include "vector.h"
+
+static git_repository *repo;
+
+#define TEST_REPO_PATH "merge-recursive"
+
+void test_graph_reachable_from_any__initialize(void)
+{
+ git_oid oid;
+ git_commit *commit;
+
+ repo = cl_git_sandbox_init(TEST_REPO_PATH);
+
+ git_oid_fromstr(&oid, "539bd011c4822c560c1d17cab095006b7a10f707");
+ cl_git_pass(git_commit_lookup(&commit, repo, &oid));
+ cl_git_pass(git_reset(repo, (git_object *)commit, GIT_RESET_HARD, NULL));
+ git_commit_free(commit);
+}
+
+void test_graph_reachable_from_any__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+void test_graph_reachable_from_any__returns_correct_result(void)
+{
+ git_object *branchA1, *branchA2, *branchB1, *branchB2, *branchC1, *branchC2, *branchH1,
+ *branchH2;
+ git_oid descendants[7];
+
+ cl_git_pass(git_revparse_single(&branchA1, repo, "branchA-1"));
+ cl_git_pass(git_revparse_single(&branchA2, repo, "branchA-2"));
+ cl_git_pass(git_revparse_single(&branchB1, repo, "branchB-1"));
+ cl_git_pass(git_revparse_single(&branchB2, repo, "branchB-2"));
+ cl_git_pass(git_revparse_single(&branchC1, repo, "branchC-1"));
+ cl_git_pass(git_revparse_single(&branchC2, repo, "branchC-2"));
+ cl_git_pass(git_revparse_single(&branchH1, repo, "branchH-1"));
+ cl_git_pass(git_revparse_single(&branchH2, repo, "branchH-2"));
+
+ cl_assert_equal_i(
+ git_graph_reachable_from_any(
+ repo, git_object_id(branchH1), git_object_id(branchA1), 1),
+ 0);
+ cl_assert_equal_i(
+ git_graph_reachable_from_any(
+ repo, git_object_id(branchH1), git_object_id(branchA2), 1),
+ 0);
+
+ cl_git_pass(git_oid_cpy(&descendants[0], git_object_id(branchA1)));
+ cl_git_pass(git_oid_cpy(&descendants[1], git_object_id(branchA2)));
+ cl_git_pass(git_oid_cpy(&descendants[2], git_object_id(branchB1)));
+ cl_git_pass(git_oid_cpy(&descendants[3], git_object_id(branchB2)));
+ cl_git_pass(git_oid_cpy(&descendants[4], git_object_id(branchC1)));
+ cl_git_pass(git_oid_cpy(&descendants[5], git_object_id(branchC2)));
+ cl_git_pass(git_oid_cpy(&descendants[6], git_object_id(branchH2)));
+ cl_assert_equal_i(
+ git_graph_reachable_from_any(repo, git_object_id(branchH2), descendants, 6),
+ 0);
+ cl_assert_equal_i(
+ git_graph_reachable_from_any(repo, git_object_id(branchH2), descendants, 7),
+ 1);
+
+ git_object_free(branchA1);
+ git_object_free(branchA2);
+ git_object_free(branchB1);
+ git_object_free(branchB2);
+ git_object_free(branchC1);
+ git_object_free(branchC2);
+ git_object_free(branchH1);
+ git_object_free(branchH2);
+}
+
+struct exhaustive_state {
+ git_odb *db;
+ git_vector commits;
+};
+
+/** Get all commits from the repository. */
+static int exhaustive_commits(const git_oid *id, void *payload)
+{
+ struct exhaustive_state *mc = (struct exhaustive_state *)payload;
+ size_t header_len;
+ git_object_t header_type;
+ int error = 0;
+
+ error = git_odb_read_header(&header_len, &header_type, mc->db, id);
+ if (error < 0)
+ return error;
+
+ if (header_type == GIT_OBJECT_COMMIT) {
+ git_commit *commit = NULL;
+
+ cl_git_pass(git_commit_lookup(&commit, repo, id));
+ cl_git_pass(git_vector_insert(&mc->commits, commit));
+ }
+
+ return 0;
+}
+
+/** Compare the `git_oid`s of two `git_commit` objects. */
+static int commit_id_cmp(const void *a, const void *b)
+{
+ return git_oid_cmp(
+ git_commit_id((const git_commit *)a), git_commit_id((const git_commit *)b));
+}
+
+/** Find a `git_commit` whose ID matches the provided `git_oid` key. */
+static int id_commit_id_cmp(const void *key, const void *commit)
+{
+ return git_oid_cmp((const git_oid *)key, git_commit_id((const git_commit *)commit));
+}
+
+void test_graph_reachable_from_any__exhaustive(void)
+{
+ struct exhaustive_state mc = {
+ .db = NULL,
+ .commits = GIT_VECTOR_INIT,
+ };
+ size_t child_idx, commit_count;
+ size_t n_descendants;
+ git_commit *child_commit;
+ git_bitvec reachable;
+
+ cl_git_pass(git_repository_odb(&mc.db, repo));
+ cl_git_pass(git_odb_foreach(mc.db, &exhaustive_commits, &mc));
+ git_vector_set_cmp(&mc.commits, commit_id_cmp);
+ git_vector_sort(&mc.commits);
+ cl_git_pass(git_bitvec_init(
+ &reachable,
+ git_vector_length(&mc.commits) * git_vector_length(&mc.commits)));
+
+ commit_count = git_vector_length(&mc.commits);
+ git_vector_foreach (&mc.commits, child_idx, child_commit) {
+ unsigned int parent_i;
+
+ /* We treat each commit as being able to reach itself. */
+ git_bitvec_set(&reachable, child_idx * commit_count + child_idx, true);
+
+ for (parent_i = 0; parent_i < git_commit_parentcount(child_commit); ++parent_i) {
+ size_t parent_idx = -1;
+ cl_git_pass(git_vector_bsearch2(
+ &parent_idx,
+ &mc.commits,
+ id_commit_id_cmp,
+ git_commit_parent_id(child_commit, parent_i)));
+
+ /* We have established that parent_idx is reachable from child_idx */
+ git_bitvec_set(&reachable, parent_idx * commit_count + child_idx, true);
+ }
+ }
+
+ /* Floyd-Warshall */
+ {
+ size_t i, j, k;
+ for (k = 0; k < commit_count; ++k) {
+ for (i = 0; i < commit_count; ++i) {
+ if (!git_bitvec_get(&reachable, i * commit_count + k))
+ continue;
+ for (j = 0; j < commit_count; ++j) {
+ if (!git_bitvec_get(&reachable, k * commit_count + j))
+ continue;
+ git_bitvec_set(&reachable, i * commit_count + j, true);
+ }
+ }
+ }
+ }
+
+ /* Try 1000 subsets of 1 through 10 entries each. */
+ srand(0x223ddc4b);
+ for (n_descendants = 1; n_descendants < 10; ++n_descendants) {
+ size_t test_iteration;
+ git_oid descendants[10];
+
+ for (test_iteration = 0; test_iteration < 1000; ++test_iteration) {
+ size_t descendant_i;
+ size_t child_idx, parent_idx;
+ int expected_reachable = false, actual_reachable;
+ git_commit *child_commit, *parent_commit;
+
+ parent_idx = rand() % commit_count;
+ parent_commit = (git_commit *)git_vector_get(&mc.commits, parent_idx);
+ for (descendant_i = 0; descendant_i < n_descendants; ++descendant_i) {
+ child_idx = rand() % commit_count;
+ child_commit = (git_commit *)git_vector_get(&mc.commits, child_idx);
+ expected_reachable |= git_bitvec_get(
+ &reachable, parent_idx * commit_count + child_idx);
+ git_oid_cpy(&descendants[descendant_i],
+ git_commit_id(child_commit));
+ }
+
+ actual_reachable = git_graph_reachable_from_any(
+ repo,
+ git_commit_id(parent_commit),
+ descendants,
+ n_descendants);
+ if (actual_reachable != expected_reachable) {
+ git_buf error_message_buf = GIT_BUF_INIT;
+ char parent_oidbuf[9] = {0}, child_oidbuf[9] = {0};
+
+ cl_git_pass(git_oid_nfmt(
+ parent_oidbuf, 8, git_commit_id(parent_commit)));
+ git_buf_printf(&error_message_buf,
+ "git_graph_reachable_from_any(\"%s\", %zu, "
+ "{",
+ parent_oidbuf,
+ n_descendants);
+ for (descendant_i = 0; descendant_i < n_descendants;
+ ++descendant_i) {
+ cl_git_pass(
+ git_oid_nfmt(child_oidbuf,
+ 8,
+ &descendants[descendant_i]));
+ git_buf_printf(&error_message_buf, " \"%s\"", child_oidbuf);
+ }
+ git_buf_printf(&error_message_buf,
+ " }) = %d, expected = %d",
+ actual_reachable,
+ expected_reachable);
+ cl_check_(actual_reachable == expected_reachable,
+ git_buf_cstr(&error_message_buf));
+ }
+ }
+ }
+
+ git_vector_foreach (&mc.commits, child_idx, child_commit)
+ git_commit_free(child_commit);
+ git_bitvec_free(&reachable);
+ git_vector_free(&mc.commits);
+ git_odb_free(mc.db);
+}
diff --git a/tests/ignore/path.c b/tests/ignore/path.c
index 5d53c9df9..d55bdc5dd 100644
--- a/tests/ignore/path.c
+++ b/tests/ignore/path.c
@@ -575,3 +575,11 @@ void test_ignore_path__negative_prefix_rule(void)
assert_is_ignored(true, "ff");
assert_is_ignored(false, "f");
}
+
+void test_ignore_path__negative_more_specific(void)
+{
+ cl_git_rewritefile("attr/.gitignore", "*.txt\n!/dir/test.txt\n");
+ assert_is_ignored(true, "test.txt");
+ assert_is_ignored(false, "dir/test.txt");
+ assert_is_ignored(true, "outer/dir/test.txt");
+}
diff --git a/tests/ignore/status.c b/tests/ignore/status.c
index 188fbe469..83e821bdd 100644
--- a/tests/ignore/status.c
+++ b/tests/ignore/status.c
@@ -70,9 +70,9 @@ void test_ignore_status__0(void)
/* confirm that ignore files were cached */
cl_assert(git_attr_cache__is_cached(
- g_repo, GIT_ATTR_FILE__FROM_FILE, ".git/info/exclude"));
+ g_repo, GIT_ATTR_FILE_SOURCE_FILE, ".git/info/exclude"));
cl_assert(git_attr_cache__is_cached(
- g_repo, GIT_ATTR_FILE__FROM_FILE, ".gitignore"));
+ g_repo, GIT_ATTR_FILE_SOURCE_FILE, ".gitignore"));
}
diff --git a/tests/index/addall.c b/tests/index/addall.c
index d1ef31daf..6f95f6386 100644
--- a/tests/index/addall.c
+++ b/tests/index/addall.c
@@ -318,11 +318,9 @@ void test_index_addall__files_in_folders(void)
void test_index_addall__hidden_files(void)
{
+#ifdef GIT_WIN32
git_index *index;
- GIT_UNUSED(index);
-
-#ifdef GIT_WIN32
addall_create_test_repo(true);
cl_git_pass(git_repository_index(&index, g_repo));
diff --git a/tests/index/bypath.c b/tests/index/bypath.c
index 21d3d3ed0..b32a0a789 100644
--- a/tests/index/bypath.c
+++ b/tests/index/bypath.c
@@ -49,13 +49,10 @@ void test_index_bypath__add_submodule_unregistered(void)
void test_index_bypath__add_hidden(void)
{
+#ifdef GIT_WIN32
const git_index_entry *entry;
bool hidden;
- GIT_UNUSED(entry);
- GIT_UNUSED(hidden);
-
-#ifdef GIT_WIN32
cl_git_mkfile("submod2/hidden_file", "you can't see me");
cl_git_pass(git_win32__hidden(&hidden, "submod2/hidden_file"));
diff --git a/tests/iterator/workdir.c b/tests/iterator/workdir.c
index 547fb7d95..82ee363f9 100644
--- a/tests/iterator/workdir.c
+++ b/tests/iterator/workdir.c
@@ -1024,7 +1024,7 @@ static void create_paths(const char *root, int depth)
int i;
cl_git_pass(git_buf_puts(&fullpath, root));
- cl_git_pass(git_buf_putc(&fullpath, '/'));
+ cl_git_pass(git_path_to_dir(&fullpath));
root_len = fullpath.size;
diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c
index e2ab05c99..ba3b3a2f6 100644
--- a/tests/mailmap/parsing.c
+++ b/tests/mailmap/parsing.c
@@ -2,7 +2,6 @@
#include "repository.h"
#include "git2/sys/repository.h"
#include "mailmap_testdata.h"
-#include "buf_text.h"
static git_repository *g_repo;
static git_mailmap *g_mailmap;
@@ -109,7 +108,7 @@ void test_mailmap_parsing__windows_string(void)
/* Parse with windows-style line endings */
git_buf_attach_notowned(&unixbuf, string_mailmap, strlen(string_mailmap));
- cl_git_pass(git_buf_text_lf_to_crlf(&winbuf, &unixbuf));
+ cl_git_pass(git_buf_lf_to_crlf(&winbuf, &unixbuf));
cl_git_pass(git_mailmap_from_buffer(&g_mailmap, winbuf.ptr, winbuf.size));
git_buf_dispose(&winbuf);
diff --git a/tests/main.c b/tests/main.c
index 00b2bae02..56751c288 100644
--- a/tests/main.c
+++ b/tests/main.c
@@ -1,6 +1,10 @@
#include "clar_libgit2.h"
#include "clar_libgit2_trace.h"
+#ifdef GIT_WIN32_LEAKCHECK
+# include "win32/w32_leakcheck.h"
+#endif
+
#ifdef _WIN32
int __cdecl main(int argc, char *argv[])
#else
@@ -14,7 +18,9 @@ int main(int argc, char *argv[])
res = git_libgit2_init();
if (res < 0) {
- fprintf(stderr, "failed to init libgit2");
+ const git_error *err = git_error_last();
+ const char *msg = err ? err->message : "unknown failure";
+ fprintf(stderr, "failed to init libgit2: %s\n", msg);
return res;
}
@@ -29,6 +35,11 @@ int main(int argc, char *argv[])
cl_global_trace_disable();
git_libgit2_shutdown();
+#ifdef GIT_WIN32_LEAKCHECK
+ if (git_win32_leakcheck_has_leaks())
+ res = res || 1;
+#endif
+
at_exit_cmd = getenv("CLAR_AT_EXIT");
if (at_exit_cmd != NULL) {
int at_exit = system(at_exit_cmd);
diff --git a/tests/merge/workdir/setup.c b/tests/merge/workdir/setup.c
index ad29fcd94..0b85f2712 100644
--- a/tests/merge/workdir/setup.c
+++ b/tests/merge/workdir/setup.c
@@ -49,7 +49,7 @@ static bool test_file_contents(const char *filename, const char *expected)
git_buf file_path_buf = GIT_BUF_INIT, file_buf = GIT_BUF_INIT;
bool equals;
- git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename);
+ git_buf_joinpath(&file_path_buf, git_repository_path(repo), filename);
cl_git_pass(git_futils_readbuffer(&file_buf, file_path_buf.ptr));
equals = (strcmp(file_buf.ptr, expected) == 0);
@@ -64,7 +64,7 @@ static void write_file_contents(const char *filename, const char *output)
{
git_buf file_path_buf = GIT_BUF_INIT;
- git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo),
+ git_buf_joinpath(&file_path_buf, git_repository_path(repo),
filename);
cl_git_rewritefile(file_path_buf.ptr, output);
diff --git a/tests/network/refspecs.c b/tests/network/refspecs.c
index 5c8eb1502..d9e0d9e8d 100644
--- a/tests/network/refspecs.c
+++ b/tests/network/refspecs.c
@@ -13,7 +13,7 @@ static void assert_refspec(unsigned int direction, const char *input, bool is_ex
if (is_expected_to_be_valid)
cl_assert_equal_i(0, error);
else
- cl_assert_equal_i(GIT_ERROR, error);
+ cl_assert_equal_i(GIT_EINVALIDSPEC, error);
}
void test_network_refspecs__parsing(void)
diff --git a/tests/network/remote/isvalidname.c b/tests/network/remote/isvalidname.c
index c26fbd0a5..a3080f67c 100644
--- a/tests/network/remote/isvalidname.c
+++ b/tests/network/remote/isvalidname.c
@@ -1,17 +1,24 @@
#include "clar_libgit2.h"
+static int is_valid_name(const char *name)
+{
+ int valid = 0;
+ cl_git_pass(git_remote_name_is_valid(&valid, name));
+ return valid;
+}
+
void test_network_remote_isvalidname__can_detect_invalid_formats(void)
{
- cl_assert_equal_i(false, git_remote_is_valid_name("/"));
- cl_assert_equal_i(false, git_remote_is_valid_name("//"));
- cl_assert_equal_i(false, git_remote_is_valid_name(".lock"));
- cl_assert_equal_i(false, git_remote_is_valid_name("a.lock"));
- cl_assert_equal_i(false, git_remote_is_valid_name("/no/leading/slash"));
- cl_assert_equal_i(false, git_remote_is_valid_name("no/trailing/slash/"));
+ cl_assert_equal_i(false, is_valid_name("/"));
+ cl_assert_equal_i(false, is_valid_name("//"));
+ cl_assert_equal_i(false, is_valid_name(".lock"));
+ cl_assert_equal_i(false, is_valid_name("a.lock"));
+ cl_assert_equal_i(false, is_valid_name("/no/leading/slash"));
+ cl_assert_equal_i(false, is_valid_name("no/trailing/slash/"));
}
void test_network_remote_isvalidname__wont_hopefully_choke_on_valid_formats(void)
{
- cl_assert_equal_i(true, git_remote_is_valid_name("webmatrix"));
- cl_assert_equal_i(true, git_remote_is_valid_name("yishaigalatzer/rules"));
+ cl_assert_equal_i(true, is_valid_name("webmatrix"));
+ cl_assert_equal_i(true, is_valid_name("yishaigalatzer/rules"));
}
diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c
index 0694a6f66..ed6a89075 100644
--- a/tests/network/remote/remotes.c
+++ b/tests/network/remote/remotes.c
@@ -56,6 +56,49 @@ void test_network_remote_remotes__parsing(void)
git_buf_dispose(&url);
}
+static int remote_ready_callback(git_remote *remote, int direction, void *payload)
+{
+ if (direction == GIT_DIRECTION_PUSH) {
+ const char *url = git_remote_pushurl(remote);
+
+ cl_assert_equal_p(url, NULL);;
+ cl_assert_equal_s(payload, "payload");
+ return git_remote_set_instance_pushurl(remote, "push_url");
+ }
+
+ if (direction == GIT_DIRECTION_FETCH) {
+ const char *url = git_remote_url(remote);
+
+ cl_assert_equal_s(url, "git://github.com/libgit2/libgit2");
+ cl_assert_equal_s(payload, "payload");
+ return git_remote_set_instance_url(remote, "fetch_url");
+ }
+
+ return -1;
+}
+
+void test_network_remote_remotes__remote_ready(void)
+{
+ git_buf url = GIT_BUF_INIT;
+
+ git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
+ callbacks.remote_ready = remote_ready_callback;
+ callbacks.payload = "payload";
+
+ cl_assert_equal_s(git_remote_name(_remote), "test");
+ cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2");
+ cl_assert(git_remote_pushurl(_remote) == NULL);
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, &callbacks));
+ cl_assert_equal_s(url.ptr, "fetch_url");
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, &callbacks));
+ cl_assert_equal_s(url.ptr, "push_url");
+
+ git_buf_dispose(&url);
+}
+
+#ifndef GIT_DEPRECATE_HARD
static int urlresolve_callback(git_buf *url_resolved, const char *url, int direction, void *payload)
{
cl_assert(strcmp(url, "git://github.com/libgit2/libgit2") == 0);
@@ -69,9 +112,11 @@ static int urlresolve_callback(git_buf *url_resolved, const char *url, int direc
return GIT_OK;
}
+#endif
void test_network_remote_remotes__urlresolve(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_buf url = GIT_BUF_INIT;
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
@@ -89,8 +134,10 @@ void test_network_remote_remotes__urlresolve(void)
cl_assert_equal_s(url.ptr, "pushresolve");
git_buf_dispose(&url);
+#endif
}
+#ifndef GIT_DEPRECATE_HARD
static int urlresolve_passthrough_callback(git_buf *url_resolved, const char *url, int direction, void *payload)
{
GIT_UNUSED(url_resolved);
@@ -99,9 +146,11 @@ static int urlresolve_passthrough_callback(git_buf *url_resolved, const char *ur
GIT_UNUSED(payload);
return GIT_PASSTHROUGH;
}
+#endif
void test_network_remote_remotes__urlresolve_passthrough(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_buf url = GIT_BUF_INIT;
const char *orig_url = "git://github.com/libgit2/libgit2";
@@ -119,6 +168,52 @@ void test_network_remote_remotes__urlresolve_passthrough(void)
cl_assert_equal_s(url.ptr, orig_url);
git_buf_dispose(&url);
+#endif
+}
+
+void test_network_remote_remotes__instance_url(void)
+{
+ git_buf url = GIT_BUF_INIT;
+ const char *orig_url = "git://github.com/libgit2/libgit2";
+
+ cl_assert_equal_s(git_remote_name(_remote), "test");
+ cl_assert_equal_s(git_remote_url(_remote), orig_url);
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
+ cl_assert_equal_s(url.ptr, orig_url);
+ git_buf_clear(&url);
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
+ cl_assert_equal_s(url.ptr, orig_url);
+ git_buf_clear(&url);
+
+ /* Setting the instance url updates the fetch and push URLs */
+ git_remote_set_instance_url(_remote, "https://github.com/new/remote/url");
+ cl_assert_equal_s(git_remote_url(_remote), "https://github.com/new/remote/url");
+ cl_assert_equal_p(git_remote_pushurl(_remote), NULL);
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
+ cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
+ git_buf_clear(&url);
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
+ cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
+ git_buf_clear(&url);
+
+ /* Setting the instance push url updates only the push URL */
+ git_remote_set_instance_pushurl(_remote, "https://github.com/new/push/url");
+ cl_assert_equal_s(git_remote_url(_remote), "https://github.com/new/remote/url");
+ cl_assert_equal_s(git_remote_pushurl(_remote), "https://github.com/new/push/url");
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL));
+ cl_assert_equal_s(url.ptr, "https://github.com/new/remote/url");
+ git_buf_clear(&url);
+
+ cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL));
+ cl_assert_equal_s(url.ptr, "https://github.com/new/push/url");
+ git_buf_clear(&url);
+
+ git_buf_dispose(&url);
}
void test_network_remote_remotes__pushurl(void)
diff --git a/tests/network/joinpath.c b/tests/network/url/joinpath.c
index da8393b91..bf4557138 100644
--- a/tests/network/joinpath.c
+++ b/tests/network/url/joinpath.c
@@ -4,19 +4,19 @@
static git_net_url source, target;
-void test_network_joinpath__initialize(void)
+void test_network_url_joinpath__initialize(void)
{
memset(&source, 0, sizeof(source));
memset(&target, 0, sizeof(target));
}
-void test_network_joinpath__cleanup(void)
+void test_network_url_joinpath__cleanup(void)
{
git_net_url_dispose(&source);
git_net_url_dispose(&target);
}
-void test_network_joinpath__target_paths_and_queries(void)
+void test_network_url_joinpath__target_paths_and_queries(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com/a/b"));
@@ -31,7 +31,7 @@ void test_network_joinpath__target_paths_and_queries(void)
git_net_url_dispose(&target);
}
-void test_network_joinpath__source_query_removed(void)
+void test_network_url_joinpath__source_query_removed(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com/a/b?query&one&two"));
@@ -46,7 +46,7 @@ void test_network_joinpath__source_query_removed(void)
git_net_url_dispose(&target);
}
-void test_network_joinpath__source_lacks_path(void)
+void test_network_url_joinpath__source_lacks_path(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com"));
@@ -91,7 +91,7 @@ void test_network_joinpath__source_lacks_path(void)
git_net_url_dispose(&target);
}
-void test_network_joinpath__source_is_slash(void)
+void test_network_url_joinpath__source_is_slash(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com/"));
@@ -137,7 +137,7 @@ void test_network_joinpath__source_is_slash(void)
}
-void test_network_joinpath__source_has_query(void)
+void test_network_url_joinpath__source_has_query(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com?query"));
@@ -183,7 +183,7 @@ void test_network_joinpath__source_has_query(void)
}
-void test_network_joinpath__empty_query_ignored(void)
+void test_network_url_joinpath__empty_query_ignored(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com/foo"));
diff --git a/tests/network/url/parse.c b/tests/network/url/parse.c
new file mode 100644
index 000000000..edfd6abec
--- /dev/null
+++ b/tests/network/url/parse.c
@@ -0,0 +1,557 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+static git_net_url conndata;
+
+void test_network_url_parse__initialize(void)
+{
+ memset(&conndata, 0, sizeof(conndata));
+}
+
+void test_network_url_parse__cleanup(void)
+{
+ git_net_url_dispose(&conndata);
+}
+
+/* Hostname */
+
+void test_network_url_parse__hostname_trivial(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__hostname_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__hostname_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__hostname_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__hostname_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__hostname_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@hostname.com:1234/"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "hostname.com");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__hostname_user(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__hostname_user_pass(void)
+{
+ /* user:pass@hostname.tld/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__hostname_port(void)
+{
+ /* hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__hostname_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__hostname_user_port(void)
+{
+ /* user@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__hostname_user_pass_port(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+/* IPv4 addresses */
+
+void test_network_url_parse__ipv4_trivial(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv4_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv4_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv4_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv4_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv4_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@192.168.1.1:1234/"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv4_user(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv4_user_pass(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv4_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv4_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv4_user_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv4_user_pass_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+/* IPv6 addresses */
+
+void test_network_url_parse__ipv6_trivial(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv6_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv6_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv6_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv6_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv6_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001]:1234/"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv6_user(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv6_user_pass(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv6_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv6_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_network_url_parse__ipv6_user_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv6_user_pass_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_network_url_parse__ipv6_invalid_addresses(void)
+{
+ /* Opening bracket missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@fe80::dcad:beff:fe00:0001]:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@fe80::dcad:beff:fe00:0001]:9191/resource"));
+
+ /* Closing bracket missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://[fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@[fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@[fe80::dcad:beff:fe00:0001:9191/resource"));
+ /* Both brackets missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@fe80::dcad:beff:fe00:0001:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@fe80::dcad:beff:fe00:0001:9191/resource"));
+
+ /* Invalid chracter inside address */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://[fe8o::dcad:beff:fe00:0001]/resource"));
+}
diff --git a/tests/network/url/pattern.c b/tests/network/url/pattern.c
new file mode 100644
index 000000000..5e4495f70
--- /dev/null
+++ b/tests/network/url/pattern.c
@@ -0,0 +1,103 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+struct url_pattern {
+ const char *url;
+ const char *pattern;
+ bool matches;
+};
+
+void test_network_url_pattern__single(void)
+{
+ git_net_url url;
+ size_t i;
+
+ struct url_pattern url_patterns[] = {
+ /* Wildcard matches */
+ { "https://example.com/", "", false },
+ { "https://example.com/", "*", true },
+
+ /* Literal and wildcard matches */
+ { "https://example.com/", "example.com", true },
+ { "https://example.com/", ".example.com", true },
+ { "https://example.com/", "*.example.com", true },
+ { "https://www.example.com/", "www.example.com", true },
+ { "https://www.example.com/", ".example.com", true },
+ { "https://www.example.com/", "*.example.com", true },
+
+ /* Literal and wildcard failures */
+ { "https://example.com/", "example.org", false },
+ { "https://example.com/", ".example.org", false },
+ { "https://example.com/", "*.example.org", false },
+ { "https://foo.example.com/", "www.example.com", false },
+
+ /*
+ * A port in the pattern is optional; if no port is
+ * present, it matches *all* ports.
+ */
+ { "https://example.com/", "example.com:443", true },
+ { "https://example.com/", "example.com:80", false },
+ { "https://example.com:1443/", "example.com", true },
+
+ /* Failures with similar prefix/suffix */
+ { "https://texample.com/", "example.com", false },
+ { "https://example.com/", "mexample.com", false },
+ { "https://example.com:44/", "example.com:443", false },
+ { "https://example.com:443/", "example.com:44", false },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(url_patterns); i++) {
+ cl_git_pass(git_net_url_parse(&url, url_patterns[i].url));
+ cl_assert_(git_net_url_matches_pattern(&url, url_patterns[i].pattern) == url_patterns[i].matches, url_patterns[i].pattern);
+ git_net_url_dispose(&url);
+ }
+}
+
+void test_network_url_pattern__list(void)
+{
+ git_net_url url;
+ size_t i;
+
+ struct url_pattern url_patterns[] = {
+ /* Wildcard matches */
+ { "https://example.com/", "", false },
+ { "https://example.com/", "*", true },
+ { "https://example.com/", ",example.com,", true },
+ { "https://example.com/", "foo,,example.com,,bar", true },
+ { "https://example.com/", "foo,,zzz,,*,,bar", true },
+
+ /* Literals */
+ { "https://example.com/", "example.com", true },
+ { "https://example.com/", "foo.bar,example.com", true },
+ { "https://example.com/", "foo.bar", false },
+ { "https://example.com/", "foo.bar,example.org", false },
+ { "https://www.example.com/", "foo.example.com,www.example.com,bar.example.com", true },
+ { "https://www.example.com/", "foo.example.com,baz.example.com,bar.example.com", false },
+ { "https://foo.example.com/", "www.example.com", false },
+ { "https://foo.example.com/", "bar.example.com,www.example.com,", false },
+
+ /* Wildcards */
+ { "https://example.com/", ".example.com", true },
+ { "https://example.com/", "*.example.com", true },
+ { "https://example.com/", "foo.com,bar.com,.example.com", true },
+ { "https://example.com/", ".foo.com,.bar.com,.example.com", true },
+ { "https://example.com/", ".foo.com,.bar.com,asdf.com", false },
+ { "https://example.com/", "*.foo,*.bar,*.example.com,*.asdf", true },
+ { "https://example.com/", "*.foo,*.bar,*.asdf", false },
+
+
+ /* Ports! */
+ { "https://example.com/", "example.com:443", true },
+ { "https://example.com/", "example.com:42,example.com:443,example.com:99", true },
+ { "https://example.com/", "example.com:42,example.com:80,example.org:443", false },
+ { "https://example.com:1443/", "example.com", true },
+ { "https://example.com:44/", "example.com:443", false },
+ { "https://example.com:443/", "example.com:44", false },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(url_patterns); i++) {
+ cl_git_pass(git_net_url_parse(&url, url_patterns[i].url));
+ cl_assert_(git_net_url_matches_pattern_list(&url, url_patterns[i].pattern) == url_patterns[i].matches, url_patterns[i].pattern);
+ git_net_url_dispose(&url);
+ }
+}
diff --git a/tests/network/redirect.c b/tests/network/url/redirect.c
index 7ce1310db..2c0b614d9 100644
--- a/tests/network/redirect.c
+++ b/tests/network/url/redirect.c
@@ -4,17 +4,17 @@
static git_net_url conndata;
-void test_network_redirect__initialize(void)
+void test_network_url_redirect__initialize(void)
{
memset(&conndata, 0, sizeof(conndata));
}
-void test_network_redirect__cleanup(void)
+void test_network_url_redirect__cleanup(void)
{
git_net_url_dispose(&conndata);
}
-void test_network_redirect__redirect_http(void)
+void test_network_url_redirect__redirect_http(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"http://example.com/foo/bar/baz"));
@@ -28,7 +28,7 @@ void test_network_redirect__redirect_http(void)
cl_assert_equal_p(conndata.password, NULL);
}
-void test_network_redirect__redirect_ssl(void)
+void test_network_url_redirect__redirect_ssl(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://example.com/foo/bar/baz"));
@@ -42,7 +42,7 @@ void test_network_redirect__redirect_ssl(void)
cl_assert_equal_p(conndata.password, NULL);
}
-void test_network_redirect__redirect_leaves_root_path(void)
+void test_network_url_redirect__redirect_leaves_root_path(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://example.com/foo/bar/baz"));
@@ -56,7 +56,7 @@ void test_network_redirect__redirect_leaves_root_path(void)
cl_assert_equal_p(conndata.password, NULL);
}
-void test_network_redirect__redirect_encoded_username_password(void)
+void test_network_url_redirect__redirect_encoded_username_password(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz"));
@@ -70,7 +70,7 @@ void test_network_redirect__redirect_encoded_username_password(void)
cl_assert_equal_s(conndata.password, "pass@word%zyx%v");
}
-void test_network_redirect__redirect_cross_host_denied(void)
+void test_network_url_redirect__redirect_cross_host_denied(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://bar.com/bar/baz"));
cl_git_fail_with(git_net_url_apply_redirect(&conndata,
@@ -78,7 +78,7 @@ void test_network_redirect__redirect_cross_host_denied(void)
-1);
}
-void test_network_redirect__redirect_http_downgrade_denied(void)
+void test_network_url_redirect__redirect_http_downgrade_denied(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/baz"));
cl_git_fail_with(git_net_url_apply_redirect(&conndata,
@@ -86,7 +86,7 @@ void test_network_redirect__redirect_http_downgrade_denied(void)
-1);
}
-void test_network_redirect__redirect_relative(void)
+void test_network_url_redirect__redirect_relative(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://foo.com/bar/baz/biff"));
cl_git_pass(git_net_url_apply_redirect(&conndata,
@@ -99,7 +99,7 @@ void test_network_redirect__redirect_relative(void)
cl_assert_equal_p(conndata.password, NULL);
}
-void test_network_redirect__redirect_relative_ssl(void)
+void test_network_url_redirect__redirect_relative_ssl(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/baz/biff"));
cl_git_pass(git_net_url_apply_redirect(&conndata,
@@ -112,7 +112,7 @@ void test_network_redirect__redirect_relative_ssl(void)
cl_assert_equal_p(conndata.password, NULL);
}
-void test_network_redirect__service_query_no_query_params_in_location(void)
+void test_network_url_redirect__service_query_no_query_params_in_location(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/info/refs?service=git-upload-pack"));
cl_git_pass(git_net_url_apply_redirect(&conndata,
@@ -120,7 +120,7 @@ void test_network_redirect__service_query_no_query_params_in_location(void)
cl_assert_equal_s(conndata.path, "/baz");
}
-void test_network_redirect__service_query_with_query_params_in_location(void)
+void test_network_url_redirect__service_query_with_query_params_in_location(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/info/refs?service=git-upload-pack"));
cl_git_pass(git_net_url_apply_redirect(&conndata,
diff --git a/tests/network/urlparse.c b/tests/network/urlparse.c
deleted file mode 100644
index 15707885a..000000000
--- a/tests/network/urlparse.c
+++ /dev/null
@@ -1,168 +0,0 @@
-#include "clar_libgit2.h"
-#include "net.h"
-
-static git_net_url conndata;
-
-void test_network_urlparse__initialize(void)
-{
- memset(&conndata, 0, sizeof(conndata));
-}
-
-void test_network_urlparse__cleanup(void)
-{
- git_net_url_dispose(&conndata);
-}
-
-void test_network_urlparse__trivial(void)
-{
- cl_git_pass(git_net_url_parse(&conndata, "http://example.com/resource"));
- cl_assert_equal_s(conndata.scheme, "http");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "80");
- cl_assert_equal_s(conndata.path, "/resource");
- cl_assert_equal_p(conndata.username, NULL);
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
-}
-
-void test_network_urlparse__root(void)
-{
- cl_git_pass(git_net_url_parse(&conndata, "http://example.com/"));
- cl_assert_equal_s(conndata.scheme, "http");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "80");
- cl_assert_equal_s(conndata.path, "/");
- cl_assert_equal_p(conndata.username, NULL);
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
-}
-
-void test_network_urlparse__implied_root(void)
-{
- cl_git_pass(git_net_url_parse(&conndata, "http://example.com"));
- cl_assert_equal_s(conndata.scheme, "http");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "80");
- cl_assert_equal_s(conndata.path, "/");
- cl_assert_equal_p(conndata.username, NULL);
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
-}
-
-void test_network_urlparse__implied_root_custom_port(void)
-{
- cl_git_pass(git_net_url_parse(&conndata, "http://example.com:42"));
- cl_assert_equal_s(conndata.scheme, "http");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "42");
- cl_assert_equal_s(conndata.path, "/");
- cl_assert_equal_p(conndata.username, NULL);
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
-}
-
-void test_network_urlparse__implied_root_empty_port(void)
-{
- cl_git_pass(git_net_url_parse(&conndata, "http://example.com:"));
- cl_assert_equal_s(conndata.scheme, "http");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "80");
- cl_assert_equal_s(conndata.path, "/");
- cl_assert_equal_p(conndata.username, NULL);
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
-}
-
-void test_network_urlparse__encoded_password(void)
-{
- cl_git_pass(git_net_url_parse(&conndata,
- "https://user:pass%2fis%40bad@hostname.com:1234/"));
- cl_assert_equal_s(conndata.scheme, "https");
- cl_assert_equal_s(conndata.host, "hostname.com");
- cl_assert_equal_s(conndata.port, "1234");
- cl_assert_equal_s(conndata.path, "/");
- cl_assert_equal_s(conndata.username, "user");
- cl_assert_equal_s(conndata.password, "pass/is@bad");
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
-}
-
-void test_network_urlparse__user(void)
-{
- cl_git_pass(git_net_url_parse(&conndata,
- "https://user@example.com/resource"));
- cl_assert_equal_s(conndata.scheme, "https");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "443");
- cl_assert_equal_s(conndata.path, "/resource");
- cl_assert_equal_s(conndata.username, "user");
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
-}
-
-void test_network_urlparse__user_pass(void)
-{
- /* user:pass@hostname.tld/resource */
- cl_git_pass(git_net_url_parse(&conndata,
- "https://user:pass@example.com/resource"));
- cl_assert_equal_s(conndata.scheme, "https");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "443");
- cl_assert_equal_s(conndata.path, "/resource");
- cl_assert_equal_s(conndata.username, "user");
- cl_assert_equal_s(conndata.password, "pass");
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
-}
-
-void test_network_urlparse__port(void)
-{
- /* hostname.tld:port/resource */
- cl_git_pass(git_net_url_parse(&conndata,
- "https://example.com:9191/resource"));
- cl_assert_equal_s(conndata.scheme, "https");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "9191");
- cl_assert_equal_s(conndata.path, "/resource");
- cl_assert_equal_p(conndata.username, NULL);
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
-}
-
-void test_network_urlparse__empty_port(void)
-{
- cl_git_pass(git_net_url_parse(&conndata, "http://example.com:/resource"));
- cl_assert_equal_s(conndata.scheme, "http");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "80");
- cl_assert_equal_s(conndata.path, "/resource");
- cl_assert_equal_p(conndata.username, NULL);
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
-}
-
-void test_network_urlparse__user_port(void)
-{
- /* user@hostname.tld:port/resource */
- cl_git_pass(git_net_url_parse(&conndata,
- "https://user@example.com:9191/resource"));
- cl_assert_equal_s(conndata.scheme, "https");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "9191");
- cl_assert_equal_s(conndata.path, "/resource");
- cl_assert_equal_s(conndata.username, "user");
- cl_assert_equal_p(conndata.password, NULL);
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
-}
-
-void test_network_urlparse__user_pass_port(void)
-{
- /* user:pass@hostname.tld:port/resource */
- cl_git_pass(git_net_url_parse(&conndata,
- "https://user:pass@example.com:9191/resource"));
- cl_assert_equal_s(conndata.scheme, "https");
- cl_assert_equal_s(conndata.host, "example.com");
- cl_assert_equal_s(conndata.port, "9191");
- cl_assert_equal_s(conndata.path, "/resource");
- cl_assert_equal_s(conndata.username, "user");
- cl_assert_equal_s(conndata.password, "pass");
- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
-}
diff --git a/tests/object/blob/filter.c b/tests/object/blob/filter.c
index 0f0f4845f..a8e3d3097 100644
--- a/tests/object/blob/filter.c
+++ b/tests/object/blob/filter.c
@@ -1,7 +1,6 @@
#include "clar_libgit2.h"
#include "posix.h"
#include "blob.h"
-#include "buf_text.h"
static git_repository *g_repo = NULL;
@@ -44,9 +43,9 @@ static git_buf_text_stats g_crlf_filtered_stats[CRLF_NUM_TEST_OBJECTS] = {
{ 0, 0, 2, 2, 2, 6, 0 },
{ 0, 0, 4, 4, 1, 31, 0 },
{ 0, 1, 1, 2, 1, 9, 5 },
- { GIT_BOM_UTF8, 0, 0, 1, 0, 16, 0 },
- { GIT_BOM_UTF8, 0, 2, 2, 2, 27, 0 },
- { GIT_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 },
+ { GIT_BUF_BOM_UTF8, 0, 0, 1, 0, 16, 0 },
+ { GIT_BUF_BOM_UTF8, 0, 2, 2, 2, 27, 0 },
+ { GIT_BUF_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 },
};
void test_object_blob_filter__initialize(void)
@@ -97,7 +96,7 @@ void test_object_blob_filter__stats(void)
for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) {
cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i]));
cl_git_pass(git_blob__getbuf(&buf, blob));
- git_buf_text_gather_stats(&stats, &buf, false);
+ git_buf_gather_text_stats(&stats, &buf, false);
cl_assert_equal_i(
0, memcmp(&g_crlf_filtered_stats[i], &stats, sizeof(stats)));
git_blob_free(blob);
diff --git a/tests/object/tag/list.c b/tests/object/tag/list.c
index 8a1a2d26d..d15f09205 100644
--- a/tests/object/tag/list.c
+++ b/tests/object/tag/list.c
@@ -20,7 +20,7 @@ static void ensure_tag_pattern_match(git_repository *repo,
int already_found[MAX_USED_TAGS] = { 0 };
git_strarray tag_list;
int error = 0;
- size_t sucessfully_found = 0;
+ size_t successfully_found = 0;
size_t i, j;
cl_assert(data->expected_matches <= MAX_USED_TAGS);
@@ -42,12 +42,12 @@ static void ensure_tag_pattern_match(git_repository *repo,
if (!already_found[j] && !strcmp(data->expected_results[j], tag_list.strings[i]))
{
already_found[j] = 1;
- sucessfully_found++;
+ successfully_found++;
break;
}
}
}
- cl_assert_equal_i((int)sucessfully_found, (int)data->expected_matches);
+ cl_assert_equal_i((int)successfully_found, (int)data->expected_matches);
exit:
git_strarray_dispose(&tag_list);
diff --git a/tests/odb/foreach.c b/tests/odb/foreach.c
index 7a45a57ae..02112380b 100644
--- a/tests/odb/foreach.c
+++ b/tests/odb/foreach.c
@@ -127,7 +127,7 @@ void test_odb_foreach__files_in_objects_dir(void)
cl_fixture_sandbox("testrepo.git");
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
- cl_git_pass(git_buf_printf(&buf, "%s/objects/somefile", git_repository_path(repo)));
+ cl_git_pass(git_buf_joinpath(&buf, git_repository_path(repo), "objects/somefile"));
cl_git_mkfile(buf.ptr, "");
git_buf_dispose(&buf);
diff --git a/tests/odb/sorting.c b/tests/odb/sorting.c
index 6af8b0d1b..e027230fa 100644
--- a/tests/odb/sorting.c
+++ b/tests/odb/sorting.c
@@ -1,5 +1,6 @@
#include "clar_libgit2.h"
#include "git2/sys/odb_backend.h"
+#include "odb.h"
typedef struct {
git_odb_backend base;
@@ -43,6 +44,11 @@ void test_odb_sorting__cleanup(void)
{
git_odb_free(_odb);
_odb = NULL;
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_LOOSE_PRIORITY,
+ GIT_ODB_DEFAULT_LOOSE_PRIORITY));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_PACKED_PRIORITY,
+ GIT_ODB_DEFAULT_PACKED_PRIORITY));
}
void test_odb_sorting__basic_backends_sorting(void)
@@ -68,3 +74,26 @@ void test_odb_sorting__alternate_backends_sorting(void)
check_backend_sorting(_odb);
}
+
+void test_odb_sorting__override_default_backend_priority(void)
+{
+ git_odb *new_odb;
+ git_odb_backend *loose, *packed, *backend;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_LOOSE_PRIORITY, 5));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_PACKED_PRIORITY, 3));
+ git_odb_backend_pack(&packed, "./testrepo.git/objects");
+ git_odb_backend_loose(&loose, "./testrepo.git/objects", -1, 0, 0, 0);
+
+ cl_git_pass(git_odb_open(&new_odb, cl_fixture("testrepo.git/objects")));
+ cl_assert_equal_sz(2, git_odb_num_backends(new_odb));
+
+ cl_git_pass(git_odb_get_backend(&backend, new_odb, 0));
+ cl_assert_equal_p(loose->read, backend->read);
+
+ cl_git_pass(git_odb_get_backend(&backend, new_odb, 1));
+ cl_assert_equal_p(packed->read, backend->read);
+
+ git_odb_free(new_odb);
+ loose->free(loose);
+ packed->free(packed);
+}
diff --git a/tests/online/badssl.c b/tests/online/badssl.c
index 6524fcd8e..6735e9cdb 100644
--- a/tests/online/badssl.c
+++ b/tests/online/badssl.c
@@ -67,14 +67,9 @@ void test_online_badssl__old_cipher(void)
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
opts.fetch_opts.callbacks.certificate_check = cert_check_assert_invalid;
- /* FIXME: we don't actually reject RC4 anywhere, figure out what to tweak */
- cl_skip();
-
if (!g_has_ssl)
cl_skip();
- cl_git_fail_with(GIT_ECERTIFICATE,
- git_clone(&g_repo, "https://rc4.badssl.com/fake.git", "./fake", NULL));
- cl_git_fail_with(GIT_ECERTIFICATE,
- git_clone(&g_repo, "https://rc4.badssl.com/fake.git", "./fake", &opts));
+ cl_git_fail(git_clone(&g_repo, "https://rc4.badssl.com/fake.git", "./fake", NULL));
+ cl_git_fail(git_clone(&g_repo, "https://rc4.badssl.com/fake.git", "./fake", &opts));
}
diff --git a/tests/online/clone.c b/tests/online/clone.c
index 9107956bd..7d43c6a09 100644
--- a/tests/online/clone.c
+++ b/tests/online/clone.c
@@ -36,6 +36,7 @@ static char *_remote_expectcontinue = NULL;
static int _orig_proxies_need_reset = 0;
static char *_orig_http_proxy = NULL;
static char *_orig_https_proxy = NULL;
+static char *_orig_no_proxy = NULL;
static int ssl_cert(git_cert *cert, int valid, const char *host, void *payload)
{
@@ -110,10 +111,14 @@ void test_online_clone__cleanup(void)
if (_orig_proxies_need_reset) {
cl_setenv("HTTP_PROXY", _orig_http_proxy);
cl_setenv("HTTPS_PROXY", _orig_https_proxy);
+ cl_setenv("NO_PROXY", _orig_no_proxy);
git__free(_orig_http_proxy);
git__free(_orig_https_proxy);
+ git__free(_orig_no_proxy);
}
+
+ git_libgit2_opts(GIT_OPT_SET_SSL_CERT_LOCATIONS, NULL, NULL);
}
void test_online_clone__network_full(void)
@@ -176,7 +181,7 @@ static int fetch_progress(const git_indexer_progress *stats, void *payload)
void test_online_clone__can_checkout_a_cloned_repo(void)
{
git_buf path = GIT_BUF_INIT;
- git_reference *head;
+ git_reference *head, *remote_head;
bool checkout_progress_cb_was_called = false,
fetch_progress_cb_was_called = false;
@@ -195,9 +200,14 @@ void test_online_clone__can_checkout_a_cloned_repo(void)
cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(head));
cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));
+ cl_git_pass(git_reference_lookup(&remote_head, g_repo, "refs/remotes/origin/HEAD"));
+ cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(remote_head));
+ cl_assert_equal_s("refs/remotes/origin/master", git_reference_symbolic_target(remote_head));
+
cl_assert_equal_i(true, checkout_progress_cb_was_called);
cl_assert_equal_i(true, fetch_progress_cb_was_called);
+ git_reference_free(remote_head);
git_reference_free(head);
git_buf_dispose(&path);
}
@@ -847,6 +857,7 @@ void test_online_clone__proxy_credentials_in_environment(void)
_orig_http_proxy = cl_getenv("HTTP_PROXY");
_orig_https_proxy = cl_getenv("HTTPS_PROXY");
+ _orig_no_proxy = cl_getenv("NO_PROXY");
_orig_proxies_need_reset = 1;
g_options.fetch_opts.proxy_opts.type = GIT_PROXY_AUTO;
@@ -858,12 +869,35 @@ void test_online_clone__proxy_credentials_in_environment(void)
cl_setenv("HTTP_PROXY", url.ptr);
cl_setenv("HTTPS_PROXY", url.ptr);
+ cl_setenv("NO_PROXY", NULL);
cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
git_buf_dispose(&url);
}
+void test_online_clone__proxy_credentials_in_url_https(void)
+{
+ git_buf url = GIT_BUF_INIT;
+
+ if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
+ cl_skip();
+
+ cl_git_pass(git_buf_printf(&url, "%s://%s:%s@%s/",
+ _remote_proxy_scheme ? _remote_proxy_scheme : "http",
+ _remote_proxy_user, _remote_proxy_pass, _remote_proxy_host));
+
+ g_options.fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED;
+ g_options.fetch_opts.proxy_opts.url = url.ptr;
+ g_options.fetch_opts.proxy_opts.certificate_check = proxy_cert_cb;
+ g_options.fetch_opts.callbacks.certificate_check = ssl_cert;
+ called_proxy_creds = 0;
+ cl_git_pass(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options));
+ cl_assert(called_proxy_creds == 0);
+
+ git_buf_dispose(&url);
+}
+
void test_online_clone__proxy_auto_not_detected(void)
{
g_options.fetch_opts.proxy_opts.type = GIT_PROXY_AUTO;
diff --git a/tests/online/customcert.c b/tests/online/customcert.c
new file mode 100644
index 000000000..c7a0de1a1
--- /dev/null
+++ b/tests/online/customcert.c
@@ -0,0 +1,79 @@
+#include "clar_libgit2.h"
+
+#include "path.h"
+#include "git2/clone.h"
+#include "git2/cred_helpers.h"
+#include "remote.h"
+#include "futils.h"
+#include "refs.h"
+
+/*
+ * Certificate one is in the `certs` folder; certificate two is in the
+ * `self-signed.pem` file.
+ */
+#define CUSTOM_CERT_ONE_URL "https://test.libgit2.org:1443/anonymous/test.git"
+#define CUSTOM_CERT_ONE_PATH "certs"
+
+#define CUSTOM_CERT_TWO_URL "https://test.libgit2.org:2443/anonymous/test.git"
+#define CUSTOM_CERT_TWO_FILE "self-signed.pem"
+
+#if (GIT_OPENSSL || GIT_MBEDTLS)
+static git_repository *g_repo;
+static int initialized = false;
+#endif
+
+void test_online_customcert__initialize(void)
+{
+#if (GIT_OPENSSL || GIT_MBEDTLS)
+ g_repo = NULL;
+
+ if (!initialized) {
+ git_buf path = GIT_BUF_INIT, file = GIT_BUF_INIT;
+ char cwd[GIT_PATH_MAX];
+
+ cl_fixture_sandbox(CUSTOM_CERT_ONE_PATH);
+ cl_fixture_sandbox(CUSTOM_CERT_TWO_FILE);
+
+ cl_must_pass(p_getcwd(cwd, GIT_PATH_MAX));
+ cl_git_pass(git_buf_joinpath(&path, cwd, CUSTOM_CERT_ONE_PATH));
+ cl_git_pass(git_buf_joinpath(&file, cwd, CUSTOM_CERT_TWO_FILE));
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SSL_CERT_LOCATIONS,
+ file.ptr, path.ptr));
+ initialized = true;
+
+ git_buf_dispose(&file);
+ git_buf_dispose(&path);
+ }
+#endif
+}
+
+void test_online_customcert__cleanup(void)
+{
+#if (GIT_OPENSSL || GIT_MBEDTLS)
+ if (g_repo) {
+ git_repository_free(g_repo);
+ g_repo = NULL;
+ }
+
+ cl_fixture_cleanup("./cloned");
+ cl_fixture_cleanup(CUSTOM_CERT_ONE_PATH);
+ cl_fixture_cleanup(CUSTOM_CERT_TWO_FILE);
+#endif
+}
+
+void test_online_customcert__file(void)
+{
+#if (GIT_OPENSSL || GIT_MBEDTLS)
+ cl_git_pass(git_clone(&g_repo, CUSTOM_CERT_ONE_URL, "./cloned", NULL));
+ cl_assert(git_path_exists("./cloned/master.txt"));
+#endif
+}
+
+void test_online_customcert__path(void)
+{
+#if (GIT_OPENSSL || GIT_MBEDTLS)
+ cl_git_pass(git_clone(&g_repo, CUSTOM_CERT_TWO_URL, "./cloned", NULL));
+ cl_assert(git_path_exists("./cloned/master.txt"));
+#endif
+}
diff --git a/tests/online/fetch.c b/tests/online/fetch.c
index f939a16b8..67dfd69ed 100644
--- a/tests/online/fetch.c
+++ b/tests/online/fetch.c
@@ -3,9 +3,19 @@
static git_repository *_repo;
static int counter;
+static char *_remote_proxy_scheme = NULL;
+static char *_remote_proxy_host = NULL;
+static char *_remote_proxy_user = NULL;
+static char *_remote_proxy_pass = NULL;
+
void test_online_fetch__initialize(void)
{
cl_git_pass(git_repository_init(&_repo, "./fetch", 0));
+
+ _remote_proxy_scheme = cl_getenv("GITTEST_REMOTE_PROXY_SCHEME");
+ _remote_proxy_host = cl_getenv("GITTEST_REMOTE_PROXY_HOST");
+ _remote_proxy_user = cl_getenv("GITTEST_REMOTE_PROXY_USER");
+ _remote_proxy_pass = cl_getenv("GITTEST_REMOTE_PROXY_PASS");
}
void test_online_fetch__cleanup(void)
@@ -14,6 +24,11 @@ void test_online_fetch__cleanup(void)
_repo = NULL;
cl_fixture_cleanup("./fetch");
+
+ git__free(_remote_proxy_scheme);
+ git__free(_remote_proxy_host);
+ git__free(_remote_proxy_user);
+ git__free(_remote_proxy_pass);
}
static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *data)
@@ -207,3 +222,28 @@ void test_online_fetch__twice(void)
git_remote_free(remote);
}
+
+void test_online_fetch__proxy(void)
+{
+ git_remote *remote;
+ git_buf url = GIT_BUF_INIT;
+ git_fetch_options fetch_opts;
+
+ if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
+ cl_skip();
+
+ cl_git_pass(git_buf_printf(&url, "%s://%s:%s@%s/",
+ _remote_proxy_scheme ? _remote_proxy_scheme : "http",
+ _remote_proxy_user, _remote_proxy_pass, _remote_proxy_host));
+
+ cl_git_pass(git_fetch_options_init(&fetch_opts, GIT_FETCH_OPTIONS_VERSION));
+ fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED;
+ fetch_opts.proxy_opts.url = url.ptr;
+
+ cl_git_pass(git_remote_create(&remote, _repo, "test", "https://github.com/libgit2/TestGitRepository.git"));
+ cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, &fetch_opts.proxy_opts, NULL));
+ cl_git_pass(git_remote_fetch(remote, NULL, &fetch_opts, NULL));
+
+ git_remote_free(remote);
+ git_buf_dispose(&url);
+}
diff --git a/tests/online/push_util.c b/tests/online/push_util.c
index fe9af2c43..b39f78114 100644
--- a/tests/online/push_util.c
+++ b/tests/online/push_util.c
@@ -58,12 +58,14 @@ int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid *
int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, size_t heads_len)
{
git_buf del_spec = GIT_BUF_INIT;
+ int valid;
size_t i;
for (i = 0; i < heads_len; i++) {
const git_remote_head *head = heads[i];
/* Ignore malformed ref names (which also saves us from tag^{} */
- if (!git_reference_is_valid_name(head->name))
+ cl_git_pass(git_reference_name_is_valid(&valid, head->name));
+ if (!valid)
return 0;
/* Create a refspec that deletes a branch in the remote */
diff --git a/tests/online/push_util.h b/tests/online/push_util.h
index d829bbc4a..5f669feaf 100644
--- a/tests/online/push_util.h
+++ b/tests/online/push_util.h
@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO;
* @param data pointer to a record_callbacks_data instance
*/
#define RECORD_CALLBACKS_INIT(data) \
- { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, NULL, data, NULL }
+ { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, NULL, NULL, data, NULL }
typedef struct {
char *name;
diff --git a/tests/pack/filelimit.c b/tests/pack/filelimit.c
new file mode 100644
index 000000000..5e0b77e9b
--- /dev/null
+++ b/tests/pack/filelimit.c
@@ -0,0 +1,136 @@
+#include "clar_libgit2.h"
+#include "mwindow.h"
+
+#include <git2.h>
+#include "git2/sys/commit.h"
+#include "git2/sys/mempack.h"
+
+static size_t expected_open_mwindow_files = 0;
+static size_t original_mwindow_file_limit = 0;
+
+extern git_mutex git__mwindow_mutex;
+extern git_mwindow_ctl git_mwindow__mem_ctl;
+
+void test_pack_filelimit__initialize_tiny(void)
+{
+ expected_open_mwindow_files = 1;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, expected_open_mwindow_files));
+}
+
+void test_pack_filelimit__initialize_medium(void)
+{
+ expected_open_mwindow_files = 10;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, expected_open_mwindow_files));
+}
+
+void test_pack_filelimit__initialize_unlimited(void)
+{
+ expected_open_mwindow_files = 15;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, 0));
+}
+
+void test_pack_filelimit__cleanup(void)
+{
+ git_buf path = GIT_BUF_INIT;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, original_mwindow_file_limit));
+
+ cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "repo.git"));
+ cl_fixture_cleanup(path.ptr);
+ git_buf_dispose(&path);
+}
+
+/*
+ * Create a packfile with one commit, one tree, and two blobs. The first blob
+ * (README.md) has the same content in all commits, but the second one
+ * (file.txt) has a different content in each commit.
+ */
+void create_packfile_commit(
+ git_repository *repo,
+ git_oid *out_commit_id,
+ git_oid *parent_id,
+ size_t commit_index,
+ size_t commit_count)
+{
+ git_buf file_contents = GIT_BUF_INIT;
+ git_treebuilder *treebuilder;
+ git_packbuilder *packbuilder;
+ git_signature *s;
+ git_oid oid, tree_id, commit_id;
+ const git_oid *parents[] = { parent_id };
+ size_t parent_count = parent_id ? 1 : 0;
+
+ cl_git_pass(git_treebuilder_new(&treebuilder, repo, NULL));
+
+ cl_git_pass(git_blob_create_from_buffer(&oid, repo, "", 0));
+ cl_git_pass(git_treebuilder_insert(NULL, treebuilder, "README.md", &oid, 0100644));
+
+ cl_git_pass(git_buf_printf(&file_contents, "Commit %zd/%zd", commit_index, commit_count));
+ cl_git_pass(git_blob_create_from_buffer(&oid, repo, file_contents.ptr, file_contents.size));
+ cl_git_pass(git_treebuilder_insert(NULL, treebuilder, "file.txt", &oid, 0100644));
+
+ cl_git_pass(git_treebuilder_write(&tree_id, treebuilder));
+ cl_git_pass(git_signature_now(&s, "alice", "alice@example.com"));
+ cl_git_pass(git_commit_create_from_ids(&commit_id, repo, "refs/heads/master", s, s,
+ NULL, file_contents.ptr, &tree_id, parent_count, parents));
+
+ cl_git_pass(git_packbuilder_new(&packbuilder, repo));
+ cl_git_pass(git_packbuilder_insert_commit(packbuilder, &commit_id));
+ cl_git_pass(git_packbuilder_write(packbuilder, NULL, 0, NULL, NULL));
+
+ cl_git_pass(git_oid_cpy(out_commit_id, &commit_id));
+
+ git_buf_dispose(&file_contents);
+ git_treebuilder_free(treebuilder);
+ git_packbuilder_free(packbuilder);
+ git_signature_free(s);
+}
+
+void test_pack_filelimit__open_repo_with_multiple_packfiles(void)
+{
+ git_buf path = GIT_BUF_INIT;
+ git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
+ git_repository *repo;
+ git_revwalk *walk;
+ git_oid id, *parent_id = NULL;
+ size_t i;
+ const size_t commit_count = 16;
+ unsigned int open_windows;
+
+ /*
+ * Create a repository and populate it with 16 commits, each in its own
+ * packfile.
+ */
+ cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "repo.git"));
+ cl_git_pass(git_repository_init(&repo, path.ptr, true));
+ for (i = 0; i < commit_count; ++i) {
+ create_packfile_commit(repo, &id, parent_id, i + 1, commit_count);
+ parent_id = &id;
+ }
+
+ cl_git_pass(git_revwalk_new(&walk, repo));
+ cl_git_pass(git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL));
+ cl_git_pass(git_revwalk_push_ref(walk, "refs/heads/master"));
+
+ /* Walking the repository requires eventually opening each of the packfiles. */
+ i = 0;
+ while (git_revwalk_next(&id, walk) == 0)
+ ++i;
+ cl_assert_equal_i(commit_count, i);
+
+ cl_git_pass(git_mutex_lock(&git__mwindow_mutex));
+ /*
+ * Adding an assert while holding a lock will cause the whole process to
+ * deadlock. Copy the value and do the assert after releasing the lock.
+ */
+ open_windows = ctl->open_windows;
+ cl_git_pass(git_mutex_unlock(&git__mwindow_mutex));
+
+ cl_assert_equal_i(expected_open_mwindow_files, open_windows);
+
+ git_buf_dispose(&path);
+ git_revwalk_free(walk);
+ git_repository_free(repo);
+}
diff --git a/tests/pack/midx.c b/tests/pack/midx.c
new file mode 100644
index 000000000..d5b91d28b
--- /dev/null
+++ b/tests/pack/midx.c
@@ -0,0 +1,110 @@
+#include "clar_libgit2.h"
+
+#include <git2.h>
+#include <git2/sys/midx.h>
+
+#include "futils.h"
+#include "midx.h"
+
+void test_pack_midx__parse(void)
+{
+ git_repository *repo;
+ struct git_midx_file *idx;
+ struct git_midx_entry e;
+ git_oid id;
+ git_buf midx_path = GIT_BUF_INIT;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+ cl_git_pass(git_buf_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index"));
+ cl_git_pass(git_midx_open(&idx, git_buf_cstr(&midx_path)));
+ cl_assert_equal_i(git_midx_needs_refresh(idx, git_buf_cstr(&midx_path)), 0);
+
+ cl_git_pass(git_oid_fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5"));
+ cl_git_pass(git_midx_entry_find(&e, idx, &id, GIT_OID_HEXSZ));
+ cl_assert_equal_oid(&e.sha1, &id);
+ cl_assert_equal_s(
+ (const char *)git_vector_get(&idx->packfile_names, e.pack_index),
+ "pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx");
+
+ git_midx_free(idx);
+ git_repository_free(repo);
+ git_buf_dispose(&midx_path);
+}
+
+void test_pack_midx__lookup(void)
+{
+ git_repository *repo;
+ git_commit *commit;
+ git_oid id;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+ cl_git_pass(git_oid_fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5"));
+ cl_git_pass(git_commit_lookup_prefix(&commit, repo, &id, GIT_OID_HEXSZ));
+ cl_assert_equal_s(git_commit_message(commit), "packed commit one\n");
+
+ git_commit_free(commit);
+ git_repository_free(repo);
+}
+
+void test_pack_midx__writer(void)
+{
+ git_repository *repo;
+ git_midx_writer *w = NULL;
+ git_buf midx = GIT_BUF_INIT, expected_midx = GIT_BUF_INIT, path = GIT_BUF_INIT;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+ cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/pack"));
+ cl_git_pass(git_midx_writer_new(&w, git_buf_cstr(&path)));
+
+ cl_git_pass(git_midx_writer_add(w, "pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx"));
+ cl_git_pass(git_midx_writer_add(w, "pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx"));
+ cl_git_pass(git_midx_writer_add(w, "pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx"));
+
+ cl_git_pass(git_midx_writer_dump(&midx, w));
+ cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/pack/multi-pack-index"));
+ cl_git_pass(git_futils_readbuffer(&expected_midx, git_buf_cstr(&path)));
+
+ cl_assert_equal_i(git_buf_len(&midx), git_buf_len(&expected_midx));
+ cl_assert_equal_strn(git_buf_cstr(&midx), git_buf_cstr(&expected_midx), git_buf_len(&midx));
+
+ git_buf_dispose(&midx);
+ git_buf_dispose(&expected_midx);
+ git_buf_dispose(&path);
+ git_midx_writer_free(w);
+ git_repository_free(repo);
+}
+
+void test_pack_midx__odb_create(void)
+{
+ git_repository *repo;
+ git_odb *odb;
+ git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
+ git_buf midx = GIT_BUF_INIT, expected_midx = GIT_BUF_INIT, midx_path = GIT_BUF_INIT;
+ struct stat st;
+
+ opts.bare = true;
+ opts.local = GIT_CLONE_LOCAL;
+ cl_git_pass(git_clone(&repo, cl_fixture("testrepo/.gitted"), "./clone.git", &opts));
+ cl_git_pass(git_buf_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index"));
+ cl_git_fail(p_stat(git_buf_cstr(&midx_path), &st));
+
+ cl_git_pass(git_repository_odb(&odb, repo));
+ cl_git_pass(git_odb_write_multi_pack_index(odb));
+ git_odb_free(odb);
+
+ cl_git_pass(p_stat(git_buf_cstr(&midx_path), &st));
+
+ cl_git_pass(git_futils_readbuffer(&expected_midx, cl_fixture("testrepo.git/objects/pack/multi-pack-index")));
+ cl_git_pass(git_futils_readbuffer(&midx, git_buf_cstr(&midx_path)));
+ cl_assert_equal_i(git_buf_len(&midx), git_buf_len(&expected_midx));
+ cl_assert_equal_strn(git_buf_cstr(&midx), git_buf_cstr(&expected_midx), git_buf_len(&midx));
+
+ git_repository_free(repo);
+ git_buf_dispose(&midx);
+ git_buf_dispose(&midx_path);
+ git_buf_dispose(&expected_midx);
+
+ cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
+} \ No newline at end of file
diff --git a/tests/pack/threadsafety.c b/tests/pack/threadsafety.c
new file mode 100644
index 000000000..fd6a61fbd
--- /dev/null
+++ b/tests/pack/threadsafety.c
@@ -0,0 +1,62 @@
+#include "clar_libgit2.h"
+#include "pool.h"
+
+#include <git2.h>
+#include "git2/sys/commit.h"
+#include "git2/sys/mempack.h"
+
+static size_t original_mwindow_file_limit = 0;
+
+void test_pack_threadsafety__initialize(void)
+{
+ size_t open_mwindow_files = 1;
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, open_mwindow_files));
+}
+
+void test_pack_threadsafety__cleanup(void)
+{
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, original_mwindow_file_limit));
+}
+
+#ifdef GIT_THREADS
+static void *get_status(void *arg)
+{
+ const char *repo_path = (const char *)arg;
+ git_repository *repo;
+ git_status_list *status;
+
+ cl_git_pass(git_repository_open(&repo, repo_path));
+ cl_git_pass(git_status_list_new(&status, repo, NULL));
+ git_status_list_free(status);
+ git_repository_free(repo);
+
+ return NULL;
+}
+#endif
+
+void test_pack_threadsafety__open_repo_in_multiple_threads(void)
+{
+#ifdef GIT_THREADS
+ const char *repo_path = cl_fixture("../..");
+ git_repository *repo;
+ git_thread threads[8];
+ size_t i;
+
+ /* If we can't open the libgit2 repo or if it isn't a full repo
+ * with proper history, just skip this test */
+ if (git_repository_open(&repo, repo_path) < 0)
+ cl_skip();
+ if (git_repository_is_shallow(repo))
+ cl_skip();
+ git_repository_free(repo);
+
+ for (i = 0; i < ARRAY_SIZE(threads); i++)
+ git_thread_create(&threads[i], get_status, (void *)repo_path);
+ for (i = 0; i < ARRAY_SIZE(threads); i++)
+ git_thread_join(&threads[i], NULL);
+#else
+ cl_skip();
+#endif
+}
diff --git a/tests/path/core.c b/tests/path/core.c
index 48b518c8d..c875a862c 100644
--- a/tests/path/core.c
+++ b/tests/path/core.c
@@ -1,6 +1,11 @@
#include "clar_libgit2.h"
#include "path.h"
+void test_path_core__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
static void test_make_relative(
const char *expected_path,
const char *path,
@@ -44,266 +49,322 @@ void test_path_core__make_relative(void)
test_make_relative("/path/to/foo.c", "/path/to/foo.c", "d:/path/to", GIT_ENOTFOUND);
test_make_relative("d:/path/to/foo.c", "d:/path/to/foo.c", "/path/to", GIT_ENOTFOUND);
-
+
test_make_relative("/path/to/foo.c", "/path/to/foo.c", "not-a-rooted-path", GIT_ENOTFOUND);
test_make_relative("not-a-rooted-path", "not-a-rooted-path", "/path/to", GIT_ENOTFOUND);
-
+
test_make_relative("/path", "/path", "pathtofoo", GIT_ENOTFOUND);
test_make_relative("path", "path", "pathtofoo", GIT_ENOTFOUND);
}
void test_path_core__isvalid_standard(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/file.txt", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/.file", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar/file.txt", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar/.file", 0, 0));
}
void test_path_core__isvalid_empty_dir_component(void)
{
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo//bar", 0, 0));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo//bar", 0, 0));
/* leading slash */
- cl_assert_equal_b(false, git_path_isvalid(NULL, "/", 0, 0));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "/foo", 0, 0));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "/foo/bar", 0, 0));
+ cl_assert_equal_b(false, git_path_validate(NULL, "/", 0, 0));
+ cl_assert_equal_b(false, git_path_validate(NULL, "/foo", 0, 0));
+ cl_assert_equal_b(false, git_path_validate(NULL, "/foo/bar", 0, 0));
/* trailing slash */
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/", 0, 0));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar/", 0, 0));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/", 0, 0));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar/", 0, 0));
}
void test_path_core__isvalid_dot_and_dotdot(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "./foo", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "./foo", 0, 0));
-
- cl_assert_equal_b(true, git_path_isvalid(NULL, "..", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "../foo", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/..", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "../foo", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".", 0, GIT_PATH_REJECT_TRAVERSAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "./foo", 0, GIT_PATH_REJECT_TRAVERSAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.", 0, GIT_PATH_REJECT_TRAVERSAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "./foo", 0, GIT_PATH_REJECT_TRAVERSAL));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "..", 0, GIT_PATH_REJECT_TRAVERSAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "../foo", 0, GIT_PATH_REJECT_TRAVERSAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/..", 0, GIT_PATH_REJECT_TRAVERSAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "../foo", 0, GIT_PATH_REJECT_TRAVERSAL));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "./foo", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/.", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "./foo", 0, 0));
+
+ cl_assert_equal_b(true, git_path_validate(NULL, "..", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "../foo", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/..", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "../foo", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, ".", 0, GIT_PATH_REJECT_TRAVERSAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "./foo", 0, GIT_PATH_REJECT_TRAVERSAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/.", 0, GIT_PATH_REJECT_TRAVERSAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "./foo", 0, GIT_PATH_REJECT_TRAVERSAL));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "..", 0, GIT_PATH_REJECT_TRAVERSAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "../foo", 0, GIT_PATH_REJECT_TRAVERSAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/..", 0, GIT_PATH_REJECT_TRAVERSAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "../foo", 0, GIT_PATH_REJECT_TRAVERSAL));
}
void test_path_core__isvalid_dot_git(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".git", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".git/foo", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.git", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.git/bar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.GIT/bar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/.Git", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".git/foo", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.git/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.GIT/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar/.Git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
-
- cl_assert_equal_b(true, git_path_isvalid(NULL, "!git", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/!git", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "!git/bar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".tig", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.tig", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".tig/bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".git", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".git/foo", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/.git", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/.git/bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/.GIT/bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar/.Git", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".git/foo", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/.git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/.git/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/.GIT/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar/.Git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
+
+ cl_assert_equal_b(true, git_path_validate(NULL, "!git", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/!git", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "!git/bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".tig", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/.tig", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".tig/bar", 0, 0));
}
void test_path_core__isvalid_backslash(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo\\file.txt", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar\\file.txt", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar\\", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo\\file.txt", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar\\file.txt", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar\\", 0, 0));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo\\file.txt", 0, GIT_PATH_REJECT_BACKSLASH));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar\\file.txt", 0, GIT_PATH_REJECT_BACKSLASH));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar\\", 0, GIT_PATH_REJECT_BACKSLASH));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo\\file.txt", 0, GIT_PATH_REJECT_BACKSLASH));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar\\file.txt", 0, GIT_PATH_REJECT_BACKSLASH));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar\\", 0, GIT_PATH_REJECT_BACKSLASH));
}
void test_path_core__isvalid_trailing_dot(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo.", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo...", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar.", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo./bar", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo.", 0, GIT_PATH_REJECT_TRAILING_DOT));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo...", 0, GIT_PATH_REJECT_TRAILING_DOT));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar.", 0, GIT_PATH_REJECT_TRAILING_DOT));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo./bar", 0, GIT_PATH_REJECT_TRAILING_DOT));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo.", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo...", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar.", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo./bar", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo.", 0, GIT_PATH_REJECT_TRAILING_DOT));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo...", 0, GIT_PATH_REJECT_TRAILING_DOT));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar.", 0, GIT_PATH_REJECT_TRAILING_DOT));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo./bar", 0, GIT_PATH_REJECT_TRAILING_DOT));
}
void test_path_core__isvalid_trailing_space(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo ", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo ", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar ", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, " ", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo /bar", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
- cl_assert_equal_b(false, git_path_isvalid(NULL, " ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo /bar", 0, GIT_PATH_REJECT_TRAILING_SPACE));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo ", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo ", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar ", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, " ", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo /bar", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
+ cl_assert_equal_b(false, git_path_validate(NULL, " ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo /bar", 0, GIT_PATH_REJECT_TRAILING_SPACE));
}
void test_path_core__isvalid_trailing_colon(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo:", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar:", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ":", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "foo:/bar", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo:", 0, GIT_PATH_REJECT_TRAILING_COLON));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar:", 0, GIT_PATH_REJECT_TRAILING_COLON));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ":", 0, GIT_PATH_REJECT_TRAILING_COLON));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "foo:/bar", 0, GIT_PATH_REJECT_TRAILING_COLON));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo:", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo/bar:", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, ":", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "foo:/bar", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo:", 0, GIT_PATH_REJECT_TRAILING_COLON));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo/bar:", 0, GIT_PATH_REJECT_TRAILING_COLON));
+ cl_assert_equal_b(false, git_path_validate(NULL, ":", 0, GIT_PATH_REJECT_TRAILING_COLON));
+ cl_assert_equal_b(false, git_path_validate(NULL, "foo:/bar", 0, GIT_PATH_REJECT_TRAILING_COLON));
}
void test_path_core__isvalid_dotgit_ntfs(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".git", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".git ", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".git.", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".git.. .", 0, 0));
-
- cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1 ", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1.", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1.. .", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".git ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".git.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".git.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1 ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".git", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".git ", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".git.", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".git.. .", 0, 0));
+
+ cl_assert_equal_b(true, git_path_validate(NULL, "git~1", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "git~1 ", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "git~1.", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "git~1.. .", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".git ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".git.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".git.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "git~1", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "git~1 ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "git~1.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "git~1.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
}
void test_path_core__isvalid_dos_paths(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux:", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.asdf", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.asdf\\zippy", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux:asdf\\foobar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "con", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "prn", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "nul", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "aux", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "aux:", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.asdf", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.asdf\\zippy", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "aux:asdf\\foobar", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "con", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "prn", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "nul", 0, GIT_PATH_REJECT_DOS_PATHS));
-
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux1", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux1", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "auxn", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "aux\\foo", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux.", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux:", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux.asdf", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux.asdf\\zippy", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux:asdf\\foobar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "con", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "prn", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "nul", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "aux", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "aux.", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "aux:", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "aux.asdf", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "aux.asdf\\zippy", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "aux:asdf\\foobar", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "con", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "prn", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "nul", 0, GIT_PATH_REJECT_DOS_PATHS));
+
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux1", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux1", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "auxn", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "aux\\foo", 0, GIT_PATH_REJECT_DOS_PATHS));
}
void test_path_core__isvalid_dos_paths_withnum(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com1", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com1:", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.asdf", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.asdf\\zippy", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com1:asdf\\foobar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com1\\foo", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt1", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "com1", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "com1:", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.asdf", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.asdf\\zippy", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "com1:asdf\\foobar", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "com1/foo", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "lpt1", 0, GIT_PATH_REJECT_DOS_PATHS));
-
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com0", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com0", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com10", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com10", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "comn", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "com1\\foo", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt0", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt10", 0, GIT_PATH_REJECT_DOS_PATHS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "lptn", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com1", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com1.", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com1:", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com1.asdf", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com1.asdf\\zippy", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com1:asdf\\foobar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com1\\foo", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "lpt1", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "com1", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "com1.", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "com1:", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "com1.asdf", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "com1.asdf\\zippy", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "com1:asdf\\foobar", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "com1/foo", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "lpt1", 0, GIT_PATH_REJECT_DOS_PATHS));
+
+ cl_assert_equal_b(true, git_path_validate(NULL, "com0", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com0", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com10", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com10", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "comn", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "com1\\foo", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "lpt0", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "lpt10", 0, GIT_PATH_REJECT_DOS_PATHS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "lptn", 0, GIT_PATH_REJECT_DOS_PATHS));
}
void test_path_core__isvalid_nt_chars(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\001foo", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\037bar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf<bar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf>foo", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf:foo", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\"bar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf|foo", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf?bar", 0, 0));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf*bar", 0, 0));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\001foo", 0, GIT_PATH_REJECT_NT_CHARS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\037bar", 0, GIT_PATH_REJECT_NT_CHARS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf<bar", 0, GIT_PATH_REJECT_NT_CHARS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf>foo", 0, GIT_PATH_REJECT_NT_CHARS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf:foo", 0, GIT_PATH_REJECT_NT_CHARS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\"bar", 0, GIT_PATH_REJECT_NT_CHARS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf|foo", 0, GIT_PATH_REJECT_NT_CHARS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf?bar", 0, GIT_PATH_REJECT_NT_CHARS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf*bar", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf\001foo", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf\037bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf<bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf>foo", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf:foo", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf\"bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf|foo", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf?bar", 0, 0));
+ cl_assert_equal_b(true, git_path_validate(NULL, "asdf*bar", 0, 0));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf\001foo", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf\037bar", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf<bar", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf>foo", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf:foo", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf\"bar", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf|foo", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf?bar", 0, GIT_PATH_REJECT_NT_CHARS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "asdf*bar", 0, GIT_PATH_REJECT_NT_CHARS));
}
void test_path_core__isvalid_dotgit_with_hfs_ignorables(void)
{
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".gi\xe2\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".g\xe2\x80\x8eIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".\xe2\x80\x8fgIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x80\xaa.gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-
- cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x80\xab.\xe2\x80\xacG\xe2\x80\xadI\xe2\x80\xaet", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x81\xab.\xe2\x80\xaaG\xe2\x81\xabI\xe2\x80\xact", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x81\xad.\xe2\x80\xaeG\xef\xbb\xbfIT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
-
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".g", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, " .git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "..git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\xe2\x80\x8dT.", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".g\xe2\x80It", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".\xe2gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, "\xe2\x80\xaa.gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".g\xe2i\x80T\x8e", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".git\xe2\x80\xbf", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".git\xe2\xab\x81", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".gi\xe2\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".g\xe2\x80\x8eIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".\xe2\x80\x8fgIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "\xe2\x80\xaa.gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+
+ cl_assert_equal_b(false, git_path_validate(NULL, "\xe2\x80\xab.\xe2\x80\xacG\xe2\x80\xadI\xe2\x80\xaet", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "\xe2\x81\xab.\xe2\x80\xaaG\xe2\x81\xabI\xe2\x80\xact", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, "\xe2\x81\xad.\xe2\x80\xaeG\xef\xbb\xbfIT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+
+ cl_assert_equal_b(true, git_path_validate(NULL, ".", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".g", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, " .git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "..git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".gi\xe2\x80\x8dT.", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".g\xe2\x80It", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".\xe2gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, "\xe2\x80\xaa.gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".gi\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".gi\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".g\xe2i\x80T\x8e", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".git\xe2\x80\xbf", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".git\xe2\xab\x81", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
+}
+
+void test_path_core__validate_workdir(void)
+{
+ cl_must_pass(git_path_validate_workdir(NULL, "/foo/bar"));
+ cl_must_pass(git_path_validate_workdir(NULL, "C:\\Foo\\Bar"));
+ cl_must_pass(git_path_validate_workdir(NULL, "\\\\?\\C:\\Foo\\Bar"));
+ cl_must_pass(git_path_validate_workdir(NULL, "\\\\?\\C:\\Foo\\Bar"));
+ cl_must_pass(git_path_validate_workdir(NULL, "\\\\?\\UNC\\server\\C$\\folder"));
+
+#ifdef GIT_WIN32
+ /*
+ * In the absense of a repo configuration, 259 character paths
+ * succeed. >= 260 character paths fail.
+ */
+ cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\ok.txt"));
+ cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\260.txt"));
+ cl_must_fail(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\longer_than_260.txt"));
+
+ /* count characters, not bytes */
+ cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\260.txt"));
+ cl_must_fail(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\long.txt"));
+#else
+ cl_must_pass(git_path_validate_workdir(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/ok.txt"));
+ cl_must_pass(git_path_validate_workdir(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/260.txt"));
+ cl_must_pass(git_path_validate_workdir(NULL, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
+ cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\260.txt"));
+ cl_must_pass(git_path_validate_workdir(NULL, "C:\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\aaaaaaaaa\\\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\xc2\xa2\\long.txt"));
+#endif
+}
+
+void test_path_core__validate_workdir_with_core_longpath(void)
+{
+#ifdef GIT_WIN32
+ git_repository *repo;
+ git_config *config;
+
+ repo = cl_git_sandbox_init("empty_bare.git");
+
+ cl_git_pass(git_repository_open(&repo, "empty_bare.git"));
+ cl_git_pass(git_repository_config(&config, repo));
+
+ /* fail by default */
+ cl_must_fail(git_path_validate_workdir(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
+
+ /* set core.longpaths explicitly on */
+ cl_git_pass(git_config_set_bool(config, "core.longpaths", 1));
+ cl_must_pass(git_path_validate_workdir(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
+
+ /* set core.longpaths explicitly off */
+ cl_git_pass(git_config_set_bool(config, "core.longpaths", 0));
+ cl_must_fail(git_path_validate_workdir(repo, "/c/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/aaaaaaaaa/longer_than_260.txt"));
+
+ git_config_free(config);
+ git_repository_free(repo);
+#endif
}
static void test_join_unrooted(
diff --git a/tests/path/dotgit.c b/tests/path/dotgit.c
index ceb7330d2..2f9fcae4f 100644
--- a/tests/path/dotgit.c
+++ b/tests/path/dotgit.c
@@ -113,8 +113,8 @@ void test_path_dotgit__dotgit_modules(void)
void test_path_dotgit__dotgit_modules_symlink(void)
{
- cl_assert_equal_b(true, git_path_isvalid(NULL, ".gitmodules", 0, GIT_PATH_REJECT_DOT_GIT_HFS|GIT_PATH_REJECT_DOT_GIT_NTFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_HFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
- cl_assert_equal_b(false, git_path_isvalid(NULL, ".gitmodules . .::$DATA", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(true, git_path_validate(NULL, ".gitmodules", 0, GIT_PATH_REJECT_DOT_GIT_HFS|GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_HFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
+ cl_assert_equal_b(false, git_path_validate(NULL, ".gitmodules . .::$DATA", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
}
diff --git a/tests/path/win32.c b/tests/path/win32.c
index b416e9e60..46b5c9f70 100644
--- a/tests/path/win32.c
+++ b/tests/path/win32.c
@@ -78,13 +78,11 @@ void test_path_win32__honors_max_path(void)
#ifdef GIT_WIN32
git_win32_path path_utf16;
- test_utf8_to_utf16("C:\\This path is 259 chars and is the max length in windows\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij",
- L"\\\\?\\C:\\This path is 259 chars and is the max length in windows\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij");
- test_utf8_to_utf16("\\\\unc\\paths may also be 259 characters including the server\\123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij",
- L"\\\\?\\UNC\\unc\\paths may also be 259 characters including the server\\123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij");
+ test_utf8_to_utf16("C:\\This path is 261 characters which is fine for our path handling functions which cope with paths longer than MAX_PATH\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghijk",
+ L"\\\\?\\C:\\This path is 261 characters which is fine for our path handling functions which cope with paths longer than MAX_PATH\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghijk");
+
+ cl_check_fail(git_win32_path_from_utf8(path_utf16, "C:\\This path is 4097 chars and exceeds our maximum path length on Windows which is limited to 4096 characters\\alas\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij01"));
- cl_check_fail(git_win32_path_from_utf8(path_utf16, "C:\\This path is 260 chars and is sadly too long for windows\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij"));
- cl_check_fail(git_win32_path_from_utf8(path_utf16, "\\\\unc\\paths are also bound by 260 character restrictions\\including the server name portion\\bcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij"));
#endif
}
diff --git a/tests/rebase/sign.c b/tests/rebase/sign.c
index fa4776661..06c18937a 100644
--- a/tests/rebase/sign.c
+++ b/tests/rebase/sign.c
@@ -18,7 +18,239 @@ void test_rebase_sign__cleanup(void)
cl_git_sandbox_cleanup();
}
-static const char *expected_commit_content = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\
+static int create_cb_passthrough(
+ git_oid *out,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message_encoding,
+ const char *message,
+ const git_tree *tree,
+ size_t parent_count,
+ const git_commit *parents[],
+ void *payload)
+{
+ GIT_UNUSED(out);
+ GIT_UNUSED(author);
+ GIT_UNUSED(committer);
+ GIT_UNUSED(message_encoding);
+ GIT_UNUSED(message);
+ GIT_UNUSED(tree);
+ GIT_UNUSED(parent_count);
+ GIT_UNUSED(parents);
+ GIT_UNUSED(payload);
+
+ return GIT_PASSTHROUGH;
+}
+
+/* git checkout gravy ; git rebase --merge veal */
+void test_rebase_sign__passthrough_create_cb(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ git_annotated_commit *branch_head, *upstream_head;
+ git_rebase_operation *rebase_operation;
+ git_oid commit_id, expected_id;
+ git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT;
+ git_commit *commit;
+ const char *expected_commit_raw_header = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\
+parent f87d14a4a236582a0278a916340a793714256864\n\
+author Edward Thomson <ethomson@edwardthomson.com> 1405625055 -0400\n\
+committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n";
+
+ rebase_opts.commit_create_cb = create_cb_passthrough;
+
+ cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
+ cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
+
+ cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
+ cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
+
+ cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &rebase_opts));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL));
+
+ git_oid_fromstr(&expected_id, "129183968a65abd6c52da35bff43325001bfc630");
+ cl_assert_equal_oid(&expected_id, &commit_id);
+
+ cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
+ cl_assert_equal_s(expected_commit_raw_header, git_commit_raw_header(commit));
+
+ cl_git_fail_with(GIT_ITEROVER, git_rebase_next(&rebase_operation, rebase));
+
+ git_reference_free(branch_ref);
+ git_reference_free(upstream_ref);
+ git_annotated_commit_free(branch_head);
+ git_annotated_commit_free(upstream_head);
+ git_commit_free(commit);
+ git_rebase_free(rebase);
+}
+
+int create_cb_signed_gpg(
+ git_oid *out,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message_encoding,
+ const char *message,
+ const git_tree *tree,
+ size_t parent_count,
+ const git_commit *parents[],
+ void *payload)
+{
+ git_buf commit_content = GIT_BUF_INIT;
+ const char *gpg_signature = "-----BEGIN PGP SIGNATURE-----\n\
+\n\
+iQIzBAEBCgAdFiEEgVlDEfSlmKn0fvGgK++h5T2/ctIFAlwZcrAACgkQK++h5T2/\n\
+ctIPVhAA42RyZhMdKl5Bm0KtQco2scsukIg2y7tjSwhti91zDu3HQgpusjjo0fQx\n\
+ZzB+OrmlvQ9CDcGpZ0THIzXD8GRJoDMPqdrvZVrBWkGcHvw7/YPA8skzsjkauJ8W\n\
+7lzF5LCuHSS6OUmPT/+5hEHPin5PB3zhfszyC+Q7aujnIuPJMrKiMnUa+w1HWifM\n\
+km49OOygQ9S6NQoVuEQede22+c76DlDL7yFghGoo1f0sKCE/9LW6SEnwI/bWv9eo\n\
+nom5vOPrvQeJiYCQk+2DyWo8RdSxINtY+G9bPE4RXm+6ZgcXECPm9TYDIWpL36fC\n\
+jvtGLs98woWFElOziBMp5Tb630GMcSI+q5ivHfJ3WS5NKLYLHBNK4iSFN0/dgAnB\n\
+dj6GcKXKWnIBWn6ZM4o40pcM5KSRUUCLtA0ZmjJH4c4zx3X5fUxd+enwkf3e9VZO\n\
+fNKC/+xfq6NfoPUPK9+UnchHpJaJw7RG5tZS+sWCz2xpQ1y3/o49xImNyM3wnpvB\n\
+cRAZabqIHpZa9/DIUkELOtCzln6niqkjRgg3M/YCCNznwV+0RNgz87VtyTPerdef\n\
+xrqn0+ROMF6ebVqIs6PPtuPkxnAJu7TMKXVB5rFnAewS24e6cIGFzeIA7810py3l\n\
+cttVRsdOoego+fiy08eFE+aJIeYiINRGhqOBTsuqG4jIdpdKxPE=\n\
+=KbsY\n\
+-----END PGP SIGNATURE-----";
+
+ git_repository *repo = (git_repository *)payload;
+ int error;
+
+ if ((error = git_commit_create_buffer(&commit_content,
+ repo, author, committer, message_encoding, message,
+ tree, parent_count, parents)) < 0)
+ goto done;
+
+ error = git_commit_create_with_signature(out, repo,
+ commit_content.ptr,
+ gpg_signature,
+ NULL);
+
+done:
+ git_buf_dispose(&commit_content);
+ return error;
+}
+
+/* git checkout gravy ; git rebase --merge veal */
+void test_rebase_sign__create_gpg_signed(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ git_annotated_commit *branch_head, *upstream_head;
+ git_rebase_operation *rebase_operation;
+ git_oid commit_id, expected_id;
+ git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT;
+ git_commit *commit;
+ const char *expected_commit_raw_header = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\
+parent f87d14a4a236582a0278a916340a793714256864\n\
+author Edward Thomson <ethomson@edwardthomson.com> 1405625055 -0400\n\
+committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n\
+gpgsig -----BEGIN PGP SIGNATURE-----\n\
+ \n\
+ iQIzBAEBCgAdFiEEgVlDEfSlmKn0fvGgK++h5T2/ctIFAlwZcrAACgkQK++h5T2/\n\
+ ctIPVhAA42RyZhMdKl5Bm0KtQco2scsukIg2y7tjSwhti91zDu3HQgpusjjo0fQx\n\
+ ZzB+OrmlvQ9CDcGpZ0THIzXD8GRJoDMPqdrvZVrBWkGcHvw7/YPA8skzsjkauJ8W\n\
+ 7lzF5LCuHSS6OUmPT/+5hEHPin5PB3zhfszyC+Q7aujnIuPJMrKiMnUa+w1HWifM\n\
+ km49OOygQ9S6NQoVuEQede22+c76DlDL7yFghGoo1f0sKCE/9LW6SEnwI/bWv9eo\n\
+ nom5vOPrvQeJiYCQk+2DyWo8RdSxINtY+G9bPE4RXm+6ZgcXECPm9TYDIWpL36fC\n\
+ jvtGLs98woWFElOziBMp5Tb630GMcSI+q5ivHfJ3WS5NKLYLHBNK4iSFN0/dgAnB\n\
+ dj6GcKXKWnIBWn6ZM4o40pcM5KSRUUCLtA0ZmjJH4c4zx3X5fUxd+enwkf3e9VZO\n\
+ fNKC/+xfq6NfoPUPK9+UnchHpJaJw7RG5tZS+sWCz2xpQ1y3/o49xImNyM3wnpvB\n\
+ cRAZabqIHpZa9/DIUkELOtCzln6niqkjRgg3M/YCCNznwV+0RNgz87VtyTPerdef\n\
+ xrqn0+ROMF6ebVqIs6PPtuPkxnAJu7TMKXVB5rFnAewS24e6cIGFzeIA7810py3l\n\
+ cttVRsdOoego+fiy08eFE+aJIeYiINRGhqOBTsuqG4jIdpdKxPE=\n\
+ =KbsY\n\
+ -----END PGP SIGNATURE-----\n";
+
+ rebase_opts.commit_create_cb = create_cb_signed_gpg;
+ rebase_opts.payload = repo;
+
+ cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
+ cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
+
+ cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
+ cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
+
+ cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &rebase_opts));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL));
+
+ git_oid_fromstr(&expected_id, "bf78348e45c8286f52b760f1db15cb6da030f2ef");
+ cl_assert_equal_oid(&expected_id, &commit_id);
+
+ cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
+ cl_assert_equal_s(expected_commit_raw_header, git_commit_raw_header(commit));
+
+ cl_git_fail_with(GIT_ITEROVER, git_rebase_next(&rebase_operation, rebase));
+
+ git_reference_free(branch_ref);
+ git_reference_free(upstream_ref);
+ git_annotated_commit_free(branch_head);
+ git_annotated_commit_free(upstream_head);
+ git_commit_free(commit);
+ git_rebase_free(rebase);
+}
+
+static int create_cb_error(
+ git_oid *out,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message_encoding,
+ const char *message,
+ const git_tree *tree,
+ size_t parent_count,
+ const git_commit *parents[],
+ void *payload)
+{
+ GIT_UNUSED(out);
+ GIT_UNUSED(author);
+ GIT_UNUSED(committer);
+ GIT_UNUSED(message_encoding);
+ GIT_UNUSED(message);
+ GIT_UNUSED(tree);
+ GIT_UNUSED(parent_count);
+ GIT_UNUSED(parents);
+ GIT_UNUSED(payload);
+
+ return GIT_EUSER;
+}
+
+/* git checkout gravy ; git rebase --merge veal */
+void test_rebase_sign__create_propagates_error(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ git_annotated_commit *branch_head, *upstream_head;
+ git_oid commit_id;
+ git_rebase_operation *rebase_operation;
+ git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT;
+
+ rebase_opts.commit_create_cb = create_cb_error;
+
+ cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
+ cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
+
+ cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
+ cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));
+
+ cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &rebase_opts));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase));
+ cl_git_fail_with(GIT_EUSER, git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL));
+
+ git_reference_free(branch_ref);
+ git_reference_free(upstream_ref);
+ git_annotated_commit_free(branch_head);
+ git_annotated_commit_free(upstream_head);
+ git_rebase_free(rebase);
+}
+
+#ifndef GIT_DEPRECATE_HARD
+static const char *expected_commit_content = "\
+tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\
parent f87d14a4a236582a0278a916340a793714256864\n\
author Edward Thomson <ethomson@edwardthomson.com> 1405625055 -0400\n\
committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n\
@@ -37,10 +269,12 @@ int signing_cb_passthrough(
cl_assert_equal_p(NULL, payload);
return GIT_PASSTHROUGH;
}
+#endif /* !GIT_DEPRECATE_HARD */
/* git checkout gravy ; git rebase --merge veal */
void test_rebase_sign__passthrough_signing_cb(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref;
git_annotated_commit *branch_head, *upstream_head;
@@ -80,15 +314,18 @@ committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n";
git_annotated_commit_free(upstream_head);
git_commit_free(commit);
git_rebase_free(rebase);
+#endif /* !GIT_DEPRECATE_HARD */
}
+#ifndef GIT_DEPRECATE_HARD
int signing_cb_gpg(
git_buf *signature,
git_buf *signature_field,
const char *commit_content,
void *payload)
{
- const char *gpg_signature = "-----BEGIN PGP SIGNATURE-----\n\
+ const char *gpg_signature = "\
+-----BEGIN PGP SIGNATURE-----\n\
\n\
iQIzBAEBCgAdFiEEgVlDEfSlmKn0fvGgK++h5T2/ctIFAlwZcrAACgkQK++h5T2/\n\
ctIPVhAA42RyZhMdKl5Bm0KtQco2scsukIg2y7tjSwhti91zDu3HQgpusjjo0fQx\n\
@@ -113,10 +350,12 @@ cttVRsdOoego+fiy08eFE+aJIeYiINRGhqOBTsuqG4jIdpdKxPE=\n\
cl_git_pass(git_buf_set(signature, gpg_signature, strlen(gpg_signature) + 1));
return GIT_OK;
}
+#endif /* !GIT_DEPRECATE_HARD */
/* git checkout gravy ; git rebase --merge veal */
void test_rebase_sign__gpg_with_no_field(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref;
git_annotated_commit *branch_head, *upstream_head;
@@ -124,7 +363,8 @@ void test_rebase_sign__gpg_with_no_field(void)
git_oid commit_id, expected_id;
git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT;
git_commit *commit;
- const char *expected_commit_raw_header = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\
+ const char *expected_commit_raw_header = "\
+tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\
parent f87d14a4a236582a0278a916340a793714256864\n\
author Edward Thomson <ethomson@edwardthomson.com> 1405625055 -0400\n\
committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n\
@@ -172,9 +412,11 @@ gpgsig -----BEGIN PGP SIGNATURE-----\n\
git_annotated_commit_free(upstream_head);
git_commit_free(commit);
git_rebase_free(rebase);
+#endif /* !GIT_DEPRECATE_HARD */
}
+#ifndef GIT_DEPRECATE_HARD
int signing_cb_magic_field(
git_buf *signature,
git_buf *signature_field,
@@ -196,10 +438,12 @@ int signing_cb_magic_field(
return GIT_OK;
}
+#endif /* !GIT_DEPRECATE_HARD */
/* git checkout gravy ; git rebase --merge veal */
void test_rebase_sign__custom_signature_field(void)
{
+#ifndef GIT_DEPRECATE_HARD
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref;
git_annotated_commit *branch_head, *upstream_head;
@@ -207,7 +451,8 @@ void test_rebase_sign__custom_signature_field(void)
git_oid commit_id, expected_id;
git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT;
git_commit *commit;
- const char *expected_commit_raw_header = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\
+ const char *expected_commit_raw_header = "\
+tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\
parent f87d14a4a236582a0278a916340a793714256864\n\
author Edward Thomson <ethomson@edwardthomson.com> 1405625055 -0400\n\
committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n\
@@ -240,4 +485,5 @@ magicsig magic word: pretty please\n";
git_annotated_commit_free(upstream_head);
git_commit_free(commit);
git_rebase_free(rebase);
+#endif /* !GIT_DEPRECATE_HARD */
}
diff --git a/tests/refs/basic.c b/tests/refs/basic.c
index ed0c0bde6..9e4c22964 100644
--- a/tests/refs/basic.c
+++ b/tests/refs/basic.c
@@ -42,3 +42,44 @@ void test_refs_basic__reference_realloc(void)
git_reference_free(new_ref);
git_reference_free(ref);
}
+
+void test_refs_basic__longpaths(void)
+{
+#ifdef GIT_WIN32
+ const char *base;
+ size_t base_len, extra_len;
+ ssize_t remain_len, i;
+ git_buf refname = GIT_BUF_INIT;
+ git_reference *one = NULL, *two = NULL;
+ git_oid id;
+
+ cl_git_pass(git_oid_fromstr(&id, "099fabac3a9ea935598528c27f866e34089c2eff"));
+
+ base = git_repository_path(g_repo);
+ base_len = git_utf8_char_length(base, strlen(base));
+ extra_len = CONST_STRLEN("logs/refs/heads/") + CONST_STRLEN(".lock");
+
+ remain_len = (ssize_t)MAX_PATH - (base_len + extra_len);
+ cl_assert(remain_len > 0);
+
+ cl_git_pass(git_buf_puts(&refname, "refs/heads/"));
+
+ for (i = 0; i < remain_len; i++) {
+ cl_git_pass(git_buf_putc(&refname, 'a'));
+ }
+
+ /*
+ * The full path to the reflog lockfile is 260 characters,
+ * this is permitted.
+ */
+ cl_git_pass(git_reference_create(&one, g_repo, refname.ptr, &id, 0, NULL));
+
+ /* Adding one more character gives us a path that is too long. */
+ cl_git_pass(git_buf_putc(&refname, 'z'));
+ cl_git_fail(git_reference_create(&two, g_repo, refname.ptr, &id, 0, NULL));
+
+ git_reference_free(one);
+ git_reference_free(two);
+ git_buf_dispose(&refname);
+#endif
+}
diff --git a/tests/refs/branches/name.c b/tests/refs/branches/name.c
index 176f836a4..290916eec 100644
--- a/tests/refs/branches/name.c
+++ b/tests/refs/branches/name.c
@@ -43,3 +43,20 @@ void test_refs_branches_name__error_when_ref_is_no_branch(void)
cl_git_pass(git_reference_lookup(&ref,repo,"refs/notes/fanout"));
cl_git_fail(git_branch_name(&name,ref));
}
+
+static int name_is_valid(const char *name)
+{
+ int valid;
+ cl_git_pass(git_branch_name_is_valid(&valid, name));
+ return valid;
+}
+
+void test_refs_branches_is_name_valid(void)
+{
+ cl_assert_equal_i(true, name_is_valid("master"));
+ cl_assert_equal_i(true, name_is_valid("test/master"));
+
+ cl_assert_equal_i(false, name_is_valid(""));
+ cl_assert_equal_i(false, name_is_valid("HEAD"));
+ cl_assert_equal_i(false, name_is_valid("-dash"));
+}
diff --git a/tests/refs/branches/upstream.c b/tests/refs/branches/upstream.c
index 928a9ff7b..919705e07 100644
--- a/tests/refs/branches/upstream.c
+++ b/tests/refs/branches/upstream.c
@@ -71,6 +71,31 @@ void test_refs_branches_upstream__upstream_remote(void)
git_buf_dispose(&buf);
}
+void test_refs_branches_upstream__upstream_merge(void)
+{
+ git_reference *branch;
+ git_repository *repository;
+ git_buf buf = GIT_BUF_INIT;
+
+ repository = cl_git_sandbox_init("testrepo.git");
+
+ /* check repository */
+ cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/test"));
+ cl_git_pass(git_branch_set_upstream(branch, "test/master"));
+
+ assert_config_entry_value(repository, "branch.test.remote", "test");
+ assert_config_entry_value(repository, "branch.test.merge", "refs/heads/master");
+
+ git_reference_free(branch);
+
+ /* check merge branch */
+ cl_git_pass(git_branch_upstream_merge(&buf, repository, "refs/heads/test"));
+ cl_assert_equal_s("refs/heads/master", buf.ptr);
+ git_buf_dispose(&buf);
+
+ cl_git_sandbox_cleanup();
+}
+
void test_refs_branches_upstream__upstream_remote_empty_value(void)
{
git_repository *repository;
diff --git a/tests/refs/isvalidname.c b/tests/refs/isvalidname.c
index 65c70ba4d..063f0f798 100644
--- a/tests/refs/isvalidname.c
+++ b/tests/refs/isvalidname.c
@@ -1,31 +1,38 @@
#include "clar_libgit2.h"
+static bool is_valid_name(const char *name)
+{
+ int valid;
+ cl_git_pass(git_reference_name_is_valid(&valid, name));
+ return valid;
+}
+
void test_refs_isvalidname__can_detect_invalid_formats(void)
{
- cl_assert_equal_i(false, git_reference_is_valid_name("refs/tags/0.17.0^{}"));
- cl_assert_equal_i(false, git_reference_is_valid_name("TWO/LEVELS"));
- cl_assert_equal_i(false, git_reference_is_valid_name("ONE.LEVEL"));
- cl_assert_equal_i(false, git_reference_is_valid_name("HEAD/"));
- cl_assert_equal_i(false, git_reference_is_valid_name("NO_TRAILING_UNDERSCORE_"));
- cl_assert_equal_i(false, git_reference_is_valid_name("_NO_LEADING_UNDERSCORE"));
- cl_assert_equal_i(false, git_reference_is_valid_name("HEAD/aa"));
- cl_assert_equal_i(false, git_reference_is_valid_name("lower_case"));
- cl_assert_equal_i(false, git_reference_is_valid_name("/stupid/name/master"));
- cl_assert_equal_i(false, git_reference_is_valid_name("/"));
- cl_assert_equal_i(false, git_reference_is_valid_name("//"));
- cl_assert_equal_i(false, git_reference_is_valid_name(""));
- cl_assert_equal_i(false, git_reference_is_valid_name("refs/heads/sub.lock/webmatrix"));
+ cl_assert_equal_i(false, is_valid_name("refs/tags/0.17.0^{}"));
+ cl_assert_equal_i(false, is_valid_name("TWO/LEVELS"));
+ cl_assert_equal_i(false, is_valid_name("ONE.LEVEL"));
+ cl_assert_equal_i(false, is_valid_name("HEAD/"));
+ cl_assert_equal_i(false, is_valid_name("NO_TRAILING_UNDERSCORE_"));
+ cl_assert_equal_i(false, is_valid_name("_NO_LEADING_UNDERSCORE"));
+ cl_assert_equal_i(false, is_valid_name("HEAD/aa"));
+ cl_assert_equal_i(false, is_valid_name("lower_case"));
+ cl_assert_equal_i(false, is_valid_name("/stupid/name/master"));
+ cl_assert_equal_i(false, is_valid_name("/"));
+ cl_assert_equal_i(false, is_valid_name("//"));
+ cl_assert_equal_i(false, is_valid_name(""));
+ cl_assert_equal_i(false, is_valid_name("refs/heads/sub.lock/webmatrix"));
}
void test_refs_isvalidname__wont_hopefully_choke_on_valid_formats(void)
{
- cl_assert_equal_i(true, git_reference_is_valid_name("refs/tags/0.17.0"));
- cl_assert_equal_i(true, git_reference_is_valid_name("refs/LEVELS"));
- cl_assert_equal_i(true, git_reference_is_valid_name("HEAD"));
- cl_assert_equal_i(true, git_reference_is_valid_name("ONE_LEVEL"));
- cl_assert_equal_i(true, git_reference_is_valid_name("refs/stash"));
- cl_assert_equal_i(true, git_reference_is_valid_name("refs/remotes/origin/bim_with_3d@11296"));
- cl_assert_equal_i(true, git_reference_is_valid_name("refs/master{yesterday"));
- cl_assert_equal_i(true, git_reference_is_valid_name("refs/master}yesterday"));
- cl_assert_equal_i(true, git_reference_is_valid_name("refs/master{yesterday}"));
+ cl_assert_equal_i(true, is_valid_name("refs/tags/0.17.0"));
+ cl_assert_equal_i(true, is_valid_name("refs/LEVELS"));
+ cl_assert_equal_i(true, is_valid_name("HEAD"));
+ cl_assert_equal_i(true, is_valid_name("ONE_LEVEL"));
+ cl_assert_equal_i(true, is_valid_name("refs/stash"));
+ cl_assert_equal_i(true, is_valid_name("refs/remotes/origin/bim_with_3d@11296"));
+ cl_assert_equal_i(true, is_valid_name("refs/master{yesterday"));
+ cl_assert_equal_i(true, is_valid_name("refs/master}yesterday"));
+ cl_assert_equal_i(true, is_valid_name("refs/master{yesterday}"));
}
diff --git a/tests/refs/races.c b/tests/refs/races.c
index 04a1bc17b..476789358 100644
--- a/tests/refs/races.c
+++ b/tests/refs/races.c
@@ -22,6 +22,24 @@ void test_refs_races__cleanup(void)
cl_git_sandbox_cleanup();
}
+void test_refs_races__create_matching_zero_old(void)
+{
+ git_reference *ref;
+ git_oid id, zero_id;
+
+ git_oid_fromstr(&id, commit_id);
+ git_oid_fromstr(&zero_id, "0000000000000000000000000000000000000000");
+
+ cl_git_fail(git_reference_create_matching(&ref, g_repo, refname, &id, 1, &zero_id, NULL));
+ git_reference_free(ref);
+
+ cl_git_pass(git_reference_create_matching(&ref, g_repo, other_refname, &id, 1, &zero_id, NULL));
+ git_reference_free(ref);
+
+ cl_git_fail(git_reference_create_matching(&ref, g_repo, other_refname, &id, 1, &zero_id, NULL));
+ git_reference_free(ref);
+}
+
void test_refs_races__create_matching(void)
{
git_reference *ref, *ref2, *ref3;
diff --git a/tests/refs/reflog/messages.c b/tests/refs/reflog/messages.c
index 43f59a84b..53b8c6f3e 100644
--- a/tests/refs/reflog/messages.c
+++ b/tests/refs/reflog/messages.c
@@ -24,11 +24,8 @@ void test_refs_reflog_messages__cleanup(void)
void test_refs_reflog_messages__setting_head_updates_reflog(void)
{
git_object *tag;
- git_signature *sig;
git_annotated_commit *annotated;
- cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
-
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); /* 4 */
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/unborn"));
cl_git_pass(git_revparse_single(&tag, g_repo, "tags/test"));
@@ -68,7 +65,6 @@ void test_refs_reflog_messages__setting_head_updates_reflog(void)
git_annotated_commit_free(annotated);
git_object_free(tag);
- git_signature_free(sig);
}
void test_refs_reflog_messages__setting_head_to_same_target_ignores_reflog(void)
@@ -87,12 +83,9 @@ void test_refs_reflog_messages__setting_head_to_same_target_ignores_reflog(void)
void test_refs_reflog_messages__detaching_writes_reflog(void)
{
- git_signature *sig;
git_oid id;
const char *msg;
- cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
-
msg = "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d";
git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d");
cl_git_pass(git_repository_set_head_detached(g_repo, &id));
@@ -107,8 +100,6 @@ void test_refs_reflog_messages__detaching_writes_reflog(void)
"e90810b8df3e80c413d903f631643c716887138d",
"258f0e2a959a364e40ed6603d5d44fbb24765b10",
NULL, msg);
-
- git_signature_free(sig);
}
void test_refs_reflog_messages__orphan_branch_does_not_count(void)
diff --git a/tests/refs/revparse.c b/tests/refs/revparse.c
index 3c4ed9af5..bc6e0a4c4 100644
--- a/tests/refs/revparse.c
+++ b/tests/refs/revparse.c
@@ -50,7 +50,7 @@ static void test_id_inrepo(
const char *spec,
const char *expected_left,
const char *expected_right,
- git_revparse_mode_t expected_flags,
+ git_revspec_t expected_flags,
git_repository *repo)
{
git_revspec revspec;
@@ -90,7 +90,7 @@ static void test_object_and_ref(const char *spec, const char *expected_oid, cons
static void test_rangelike(const char *rangelike,
const char *expected_left,
const char *expected_right,
- git_revparse_mode_t expected_revparseflags)
+ git_revspec_t expected_revparseflags)
{
char objstr[64] = {0};
git_revspec revspec;
@@ -117,7 +117,7 @@ static void test_id(
const char *spec,
const char *expected_left,
const char *expected_right,
- git_revparse_mode_t expected_flags)
+ git_revspec_t expected_flags)
{
test_id_inrepo(spec, expected_left, expected_right, expected_flags, g_repo);
}
@@ -735,53 +735,53 @@ void test_refs_revparse__range(void)
test_rangelike("be3563a^1..be3563a",
"9fd738e8f7967c078dceed8190330fc8648ee56a",
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644",
- GIT_REVPARSE_RANGE);
+ GIT_REVSPEC_RANGE);
test_rangelike("be3563a^1...be3563a",
"9fd738e8f7967c078dceed8190330fc8648ee56a",
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644",
- GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+ GIT_REVSPEC_RANGE | GIT_REVSPEC_MERGE_BASE);
test_rangelike("be3563a^1.be3563a", NULL, NULL, 0);
}
void test_refs_revparse__parses_range_operator(void)
{
- test_id("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVPARSE_SINGLE);
+ test_id("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVSPEC_SINGLE);
test_id("HEAD~3..HEAD",
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
- GIT_REVPARSE_RANGE);
+ GIT_REVSPEC_RANGE);
test_id("HEAD~3...HEAD",
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
- GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+ GIT_REVSPEC_RANGE | GIT_REVSPEC_MERGE_BASE);
test_id("HEAD~3..",
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
- GIT_REVPARSE_RANGE);
+ GIT_REVSPEC_RANGE);
test_id("HEAD~3...",
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
- GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+ GIT_REVSPEC_RANGE | GIT_REVSPEC_MERGE_BASE);
test_id("..HEAD~3",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
- GIT_REVPARSE_RANGE);
+ GIT_REVSPEC_RANGE);
test_id("...HEAD~3",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
- GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+ GIT_REVSPEC_RANGE | GIT_REVSPEC_MERGE_BASE);
test_id("...",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
- GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+ GIT_REVSPEC_RANGE | GIT_REVSPEC_MERGE_BASE);
test_invalid_revspec("..");
}
diff --git a/tests/refs/tags/name.c b/tests/refs/tags/name.c
new file mode 100644
index 000000000..0ca5df7d6
--- /dev/null
+++ b/tests/refs/tags/name.c
@@ -0,0 +1,17 @@
+#include "clar_libgit2.h"
+
+static int name_is_valid(const char *name)
+{
+ int valid;
+ cl_git_pass(git_tag_name_is_valid(&valid, name));
+ return valid;
+}
+
+void test_refs_tags_is_name_valid(void)
+{
+ cl_assert_equal_i(true, name_is_valid("sometag"));
+ cl_assert_equal_i(true, name_is_valid("test/sometag"));
+
+ cl_assert_equal_i(false, name_is_valid(""));
+ cl_assert_equal_i(false, name_is_valid("-dash"));
+}
diff --git a/tests/remote/fetch.c b/tests/remote/fetch.c
new file mode 100644
index 000000000..7e825ca16
--- /dev/null
+++ b/tests/remote/fetch.c
@@ -0,0 +1,169 @@
+#include "../clar_libgit2.h"
+
+#include "remote.h"
+#include "repository.h"
+
+static git_repository *repo1;
+static git_repository *repo2;
+static char* repo1_path;
+static char* repo2_path;
+
+static const char *REPO1_REFNAME = "refs/heads/main";
+static const char *REPO2_REFNAME = "refs/remotes/repo1/main";
+static char *FORCE_FETCHSPEC = "+refs/heads/main:refs/remotes/repo1/main";
+static char *NON_FORCE_FETCHSPEC = "refs/heads/main:refs/remotes/repo1/main";
+
+void test_remote_fetch__initialize(void) {
+ git_config *c;
+ git_buf repo1_path_buf = GIT_BUF_INIT;
+ git_buf repo2_path_buf = GIT_BUF_INIT;
+ const char *sandbox = clar_sandbox_path();
+
+ cl_git_pass(git_buf_joinpath(&repo1_path_buf, sandbox, "fetchtest_repo1"));
+ repo1_path = git_buf_detach(&repo1_path_buf);
+ cl_git_pass(git_repository_init(&repo1, repo1_path, true));
+
+ cl_git_pass(git_buf_joinpath(&repo2_path_buf, sandbox, "fetchtest_repo2"));
+ repo2_path = git_buf_detach(&repo2_path_buf);
+ cl_git_pass(git_repository_init(&repo2, repo2_path, true));
+
+ cl_git_pass(git_repository_config(&c, repo1));
+ cl_git_pass(git_config_set_string(c, "user.email", "some@email"));
+ cl_git_pass(git_config_set_string(c, "user.name", "some@name"));
+ git_config_free(c);
+ git_buf_dispose(&repo1_path_buf);
+ git_buf_dispose(&repo2_path_buf);
+}
+
+void test_remote_fetch__cleanup(void) {
+ git_repository_free(repo1);
+ git_repository_free(repo2);
+
+ cl_git_pass(git_futils_rmdir_r(repo1_path, NULL, GIT_RMDIR_REMOVE_FILES));
+ free(repo1_path);
+
+ cl_git_pass(git_futils_rmdir_r(repo2_path, NULL, GIT_RMDIR_REMOVE_FILES));
+ free(repo2_path);
+}
+
+
+/**
+ * This checks that the '+' flag on fetchspecs is respected. We create a
+ * repository that has a reference to two commits, one a child of the other.
+ * We fetch this repository into a second repository. Then we reset the
+ * reference in the first repository and run the fetch again. If the '+' flag
+ * is used then the reference in the second repository will change, but if it
+ * is not then it should stay the same.
+ *
+ * @param commit1id A pointer to an OID which will be populated with the first
+ * commit.
+ * @param commit2id A pointer to an OID which will be populated with the second
+ * commit, which is a descendant of the first.
+ * @param force Whether to use a spec with '+' prefixed to force the refs
+ * to update
+ */
+void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
+ bool force) {
+ char *refspec_strs = {
+ force ? FORCE_FETCHSPEC : NON_FORCE_FETCHSPEC,
+ };
+ git_strarray refspecs = {
+ .count = 1,
+ .strings = &refspec_strs,
+ };
+
+ /* create two commits in repo 1 and a reference to them */
+ {
+ git_oid empty_tree_id;
+ git_tree *empty_tree;
+ git_signature *sig;
+ git_treebuilder *tb;
+ cl_git_pass(git_treebuilder_new(&tb, repo1, NULL));
+ cl_git_pass(git_treebuilder_write(&empty_tree_id, tb));
+ cl_git_pass(git_tree_lookup(&empty_tree, repo1, &empty_tree_id));
+ cl_git_pass(git_signature_default(&sig, repo1));
+ cl_git_pass(git_commit_create(commit1id, repo1, REPO1_REFNAME, sig,
+ sig, NULL, "one", empty_tree, 0, NULL));
+ cl_git_pass(git_commit_create_v(commit2id, repo1, REPO1_REFNAME, sig,
+ sig, NULL, "two", empty_tree, 1, commit1id));
+
+ git_tree_free(empty_tree);
+ git_signature_free(sig);
+ git_treebuilder_free(tb);
+ }
+
+ /* fetch the reference via the remote */
+ {
+ git_remote *remote;
+
+ cl_git_pass(git_remote_create_anonymous(&remote, repo2,
+ git_repository_path(repo1)));
+ cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, "some message"));
+
+ git_remote_free(remote);
+ }
+
+ /* assert that repo2 references the second commit */
+ {
+ const git_oid *target;
+ git_reference *ref;
+ cl_git_pass(git_reference_lookup(&ref, repo2, REPO2_REFNAME));
+ target = git_reference_target(ref);
+ cl_assert_equal_b(git_oid_cmp(target, commit2id), 0);
+ git_reference_free(ref);
+ }
+
+ /* set the reference in repo1 to point to the older commit */
+ {
+ git_reference *ref;
+ git_reference *ref2;
+ cl_git_pass(git_reference_lookup(&ref, repo1, REPO1_REFNAME));
+ cl_git_pass(git_reference_set_target(&ref2, ref, commit1id,
+ "rollback"));
+ git_reference_free(ref);
+ git_reference_free(ref2);
+ }
+
+ /* fetch the reference again */
+ {
+ git_remote *remote;
+
+ cl_git_pass(git_remote_create_anonymous(&remote, repo2,
+ git_repository_path(repo1)));
+ cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, "some message"));
+
+ git_remote_free(remote);
+ }
+}
+
+void test_remote_fetch__dont_update_refs_if_not_descendant_and_not_force(void) {
+ const git_oid *target;
+ git_oid commit1id;
+ git_oid commit2id;
+ git_reference *ref;
+
+ do_time_travelling_fetch(&commit1id, &commit2id, false);
+
+ /* assert that the reference in repo2 has not changed */
+ cl_git_pass(git_reference_lookup(&ref, repo2, REPO2_REFNAME));
+ target = git_reference_target(ref);
+ cl_assert_equal_b(git_oid_cmp(target, &commit2id), 0);
+
+ git_reference_free(ref);
+}
+
+void test_remote_fetch__do_update_refs_if_not_descendant_and_force(void) {
+ const git_oid *target;
+ git_oid commit1id;
+ git_oid commit2id;
+ git_reference *ref;
+
+ do_time_travelling_fetch(&commit1id, &commit2id, true);
+
+ /* assert that the reference in repo2 has changed */
+ cl_git_pass(git_reference_lookup(&ref, repo2, REPO2_REFNAME));
+ target = git_reference_target(ref);
+ cl_assert_equal_b(git_oid_cmp(target, &commit1id), 0);
+
+ git_reference_free(ref);
+}
diff --git a/tests/remote/httpproxy.c b/tests/remote/httpproxy.c
new file mode 100644
index 000000000..8cd4371f5
--- /dev/null
+++ b/tests/remote/httpproxy.c
@@ -0,0 +1,188 @@
+#include "clar_libgit2.h"
+#include "futils.h"
+#include "net.h"
+#include "remote.h"
+
+static git_repository *repo;
+static git_net_url url = GIT_NET_URL_INIT;
+
+static int orig_proxies_need_reset = 0;
+static char *orig_http_proxy = NULL;
+static char *orig_https_proxy = NULL;
+static char *orig_no_proxy = NULL;
+
+void test_remote_httpproxy__initialize(void)
+{
+ git_remote *remote;
+
+ repo = cl_git_sandbox_init("testrepo");
+ cl_git_pass(git_remote_create(&remote, repo, "lg2", "https://github.com/libgit2/libgit2"));
+ cl_git_pass(git_net_url_parse(&url, "https://github.com/libgit2/libgit2"));
+
+ git_remote_free(remote);
+
+ orig_proxies_need_reset = 0;
+}
+
+void test_remote_httpproxy__cleanup(void)
+{
+ if (orig_proxies_need_reset) {
+ cl_setenv("HTTP_PROXY", orig_http_proxy);
+ cl_setenv("HTTPS_PROXY", orig_https_proxy);
+ cl_setenv("NO_PROXY", orig_no_proxy);
+
+ git__free(orig_http_proxy);
+ git__free(orig_https_proxy);
+ git__free(orig_no_proxy);
+ }
+
+ git_net_url_dispose(&url);
+ cl_git_sandbox_cleanup();
+}
+
+void assert_proxy_is(const char *expected)
+{
+ git_remote *remote;
+ char *proxy;
+
+ cl_git_pass(git_remote_lookup(&remote, repo, "lg2"));
+ cl_git_pass(git_remote__http_proxy(&proxy, remote, &url));
+
+ if (expected)
+ cl_assert_equal_s(proxy, expected);
+ else
+ cl_assert_equal_p(proxy, expected);
+
+ git_remote_free(remote);
+ git__free(proxy);
+}
+
+void assert_config_match(const char *config, const char *expected)
+{
+ git_remote *remote;
+ char *proxy;
+
+ if (config)
+ cl_repo_set_string(repo, config, expected);
+
+ cl_git_pass(git_remote_lookup(&remote, repo, "lg2"));
+ cl_git_pass(git_remote__http_proxy(&proxy, remote, &url));
+
+ if (expected)
+ cl_assert_equal_s(proxy, expected);
+ else
+ cl_assert_equal_p(proxy, expected);
+
+ git_remote_free(remote);
+ git__free(proxy);
+}
+
+void test_remote_httpproxy__config_overrides(void)
+{
+ /*
+ * http.proxy should be honored, then http.<url>.proxy should
+ * be honored in increasing specificity of the url. finally,
+ * remote.<name>.proxy is the most specific.
+ */
+ assert_config_match(NULL, NULL);
+ assert_config_match("http.proxy", "http://localhost:1/");
+ assert_config_match("http.https://github.com.proxy", "http://localhost:2/");
+ assert_config_match("http.https://github.com/.proxy", "http://localhost:3/");
+ assert_config_match("http.https://github.com/libgit2.proxy", "http://localhost:4/");
+ assert_config_match("http.https://github.com/libgit2/.proxy", "http://localhost:5/");
+ assert_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:6/");
+ assert_config_match("remote.lg2.proxy", "http://localhost:7/");
+}
+
+void test_remote_httpproxy__config_empty_overrides(void)
+{
+ /*
+ * with greater specificity, an empty config entry overrides
+ * a set one
+ */
+ assert_config_match("http.proxy", "http://localhost:1/");
+ assert_config_match("http.https://github.com.proxy", "");
+ assert_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:2/");
+ assert_config_match("remote.lg2.proxy", "");
+}
+
+void assert_global_config_match(const char *config, const char *expected)
+{
+ git_remote *remote;
+ char *proxy;
+ git_config* cfg;
+
+ if (config) {
+ cl_git_pass(git_config_open_default(&cfg));
+ git_config_set_string(cfg, config, expected);
+ git_config_free(cfg);
+ }
+
+ cl_git_pass(git_remote_create_detached(&remote, "https://github.com/libgit2/libgit2"));
+ cl_git_pass(git_remote__http_proxy(&proxy, remote, &url));
+
+ if (expected)
+ cl_assert_equal_s(proxy, expected);
+ else
+ cl_assert_equal_p(proxy, expected);
+
+ git_remote_free(remote);
+ git__free(proxy);
+}
+
+void test_remote_httpproxy__config_overrides_detached_remote(void)
+{
+ cl_fake_home();
+
+ assert_global_config_match(NULL, NULL);
+ assert_global_config_match("http.proxy", "http://localhost:1/");
+ assert_global_config_match("http.https://github.com.proxy", "http://localhost:2/");
+ assert_global_config_match("http.https://github.com/.proxy", "http://localhost:3/");
+ assert_global_config_match("http.https://github.com/libgit2.proxy", "http://localhost:4/");
+ assert_global_config_match("http.https://github.com/libgit2/.proxy", "http://localhost:5/");
+ assert_global_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:6/");
+
+ cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES));
+}
+
+void test_remote_httpproxy__env(void)
+{
+ orig_http_proxy = cl_getenv("HTTP_PROXY");
+ orig_https_proxy = cl_getenv("HTTPS_PROXY");
+ orig_no_proxy = cl_getenv("NO_PROXY");
+ orig_proxies_need_reset = 1;
+
+ /* Clear everything for a fresh start */
+ cl_setenv("HTTP_PROXY", NULL);
+ cl_setenv("HTTPS_PROXY", NULL);
+ cl_setenv("NO_PROXY", NULL);
+
+ /* HTTP proxy is ignored for HTTPS */
+ cl_setenv("HTTP_PROXY", "http://localhost:9/");
+ assert_proxy_is(NULL);
+
+ /* HTTPS proxy is honored for HTTPS */
+ cl_setenv("HTTPS_PROXY", "http://localhost:10/");
+ assert_proxy_is("http://localhost:10/");
+
+ /* NO_PROXY is honored */
+ cl_setenv("NO_PROXY", "github.com:443");
+ assert_proxy_is(NULL);
+
+ cl_setenv("NO_PROXY", "github.com:80");
+ assert_proxy_is("http://localhost:10/");
+
+ cl_setenv("NO_PROXY", "github.com");
+ assert_proxy_is(NULL);
+
+ cl_setenv("NO_PROXY", "github.dev,github.com,github.foo");
+ assert_proxy_is(NULL);
+
+ cl_setenv("HTTPS_PROXY", "");
+ assert_proxy_is(NULL);
+
+ /* configuration overrides environment variables */
+ cl_setenv("HTTPS_PROXY", "http://localhost:10/");
+ cl_setenv("NO_PROXY", "github.none");
+ assert_config_match("http.https://github.com.proxy", "http://localhost:11/");
+}
diff --git a/tests/repo/extensions.c b/tests/repo/extensions.c
new file mode 100644
index 000000000..e7772acd5
--- /dev/null
+++ b/tests/repo/extensions.c
@@ -0,0 +1,72 @@
+#include "clar_libgit2.h"
+#include "futils.h"
+#include "sysdir.h"
+#include <ctype.h>
+
+git_repository *repo;
+
+void test_repo_extensions__initialize(void)
+{
+ git_config *config;
+
+ repo = cl_git_sandbox_init("empty_bare.git");
+
+ cl_git_pass(git_repository_config(&config, repo));
+ cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 1));
+ git_config_free(config);
+}
+
+void test_repo_extensions__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, NULL, 0));
+}
+
+void test_repo_extensions__builtin(void)
+{
+ git_repository *extended;
+
+ cl_repo_set_string(repo, "extensions.noop", "foobar");
+
+ cl_git_pass(git_repository_open(&extended, "empty_bare.git"));
+ cl_assert(git_repository_path(extended) != NULL);
+ cl_assert(git__suffixcmp(git_repository_path(extended), "/") == 0);
+ git_repository_free(extended);
+}
+
+void test_repo_extensions__negate_builtin(void)
+{
+ const char *in[] = { "foo", "!noop", "baz" };
+ git_repository *extended;
+
+ cl_repo_set_string(repo, "extensions.noop", "foobar");
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
+
+ cl_git_fail(git_repository_open(&extended, "empty_bare.git"));
+ git_repository_free(extended);
+}
+
+void test_repo_extensions__unsupported(void)
+{
+ git_repository *extended = NULL;
+
+ cl_repo_set_string(repo, "extensions.unknown", "foobar");
+
+ cl_git_fail(git_repository_open(&extended, "empty_bare.git"));
+ git_repository_free(extended);
+}
+
+void test_repo_extensions__adds_extension(void)
+{
+ const char *in[] = { "foo", "!noop", "newextension", "baz" };
+ git_repository *extended;
+
+ cl_repo_set_string(repo, "extensions.newextension", "foobar");
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
+
+ cl_git_pass(git_repository_open(&extended, "empty_bare.git"));
+ cl_assert(git_repository_path(extended) != NULL);
+ cl_assert(git__suffixcmp(git_repository_path(extended), "/") == 0);
+ git_repository_free(extended);
+}
diff --git a/tests/repo/getters.c b/tests/repo/getters.c
index b8ede126c..d401bb832 100644
--- a/tests/repo/getters.c
+++ b/tests/repo/getters.c
@@ -1,4 +1,5 @@
#include "clar_libgit2.h"
+#include "repo/repo_helpers.h"
void test_repo_getters__is_empty_correctly_deals_with_pristine_looking_repos(void)
{
@@ -23,6 +24,18 @@ void test_repo_getters__is_empty_can_detect_used_repositories(void)
git_repository_free(repo);
}
+void test_repo_getters__is_empty_can_detect_repositories_with_defaultbranch_config_empty(void)
+{
+ git_repository *repo;
+
+ create_tmp_global_config("tmp_global_path", "init.defaultBranch", "");
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+ cl_assert_equal_i(false, git_repository_is_empty(repo));
+
+ git_repository_free(repo);
+}
+
void test_repo_getters__retrieving_the_odb_honors_the_refcount(void)
{
git_odb *odb;
diff --git a/tests/repo/hashfile.c b/tests/repo/hashfile.c
index 0fb4e6772..bffb51bb5 100644
--- a/tests/repo/hashfile.c
+++ b/tests/repo/hashfile.c
@@ -10,6 +10,7 @@ void test_repo_hashfile__initialize(void)
void test_repo_hashfile__cleanup(void)
{
+ cl_fixture_cleanup("absolute");
cl_git_sandbox_cleanup();
_repo = NULL;
}
@@ -38,10 +39,18 @@ void test_repo_hashfile__simple(void)
git_buf_dispose(&full);
}
-void test_repo_hashfile__filtered(void)
+void test_repo_hashfile__filtered_in_workdir(void)
{
+ git_buf root = GIT_BUF_INIT, txt = GIT_BUF_INIT, bin = GIT_BUF_INIT;
+ char cwd[GIT_PATH_MAX];
git_oid a, b;
+ cl_must_pass(p_getcwd(cwd, GIT_PATH_MAX));
+ cl_must_pass(p_mkdir("absolute", 0777));
+ cl_git_pass(git_buf_joinpath(&root, cwd, "status"));
+ cl_git_pass(git_buf_joinpath(&txt, root.ptr, "testfile.txt"));
+ cl_git_pass(git_buf_joinpath(&bin, root.ptr, "testfile.bin"));
+
cl_repo_set_bool(_repo, "core.autocrlf", true);
cl_git_append2file("status/.gitattributes", "*.txt text\n*.bin binary\n\n");
@@ -55,21 +64,41 @@ void test_repo_hashfile__filtered(void)
cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_BLOB, NULL));
cl_assert(git_oid_cmp(&a, &b));
+ /* not equal hashes because of filtering when specified by absolute path */
+ cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, NULL));
+ cl_assert(git_oid_cmp(&a, &b));
+
/* equal hashes because filter is binary */
cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB));
cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJECT_BLOB, NULL));
cl_assert_equal_oid(&a, &b);
+ /* equal hashes because filter is binary when specified by absolute path */
+ cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, NULL));
+ cl_assert_equal_oid(&a, &b);
+
/* equal hashes when 'as_file' points to binary filtering */
cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB));
cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_BLOB, "foo.bin"));
cl_assert_equal_oid(&a, &b);
+ /* equal hashes when 'as_file' points to binary filtering (absolute path) */
+ cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, "foo.bin"));
+ cl_assert_equal_oid(&a, &b);
+
/* not equal hashes when 'as_file' points to text filtering */
cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB));
cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJECT_BLOB, "foo.txt"));
cl_assert(git_oid_cmp(&a, &b));
+ /* not equal hashes when 'as_file' points to text filtering */
+ cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, "foo.txt"));
+ cl_assert(git_oid_cmp(&a, &b));
+
/* equal hashes when 'as_file' is empty and turns off filtering */
cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB));
cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_BLOB, ""));
@@ -79,7 +108,65 @@ void test_repo_hashfile__filtered(void)
cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJECT_BLOB, ""));
cl_assert_equal_oid(&a, &b);
+ cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, ""));
+ cl_assert_equal_oid(&a, &b);
+
+ cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, ""));
+ cl_assert_equal_oid(&a, &b);
+
/* some hash type failures */
cl_git_fail(git_odb_hashfile(&a, "status/testfile.txt", 0));
cl_git_fail(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_ANY, NULL));
+
+ git_buf_dispose(&txt);
+ git_buf_dispose(&bin);
+ git_buf_dispose(&root);
+}
+
+void test_repo_hashfile__filtered_outside_workdir(void)
+{
+ git_buf root = GIT_BUF_INIT, txt = GIT_BUF_INIT, bin = GIT_BUF_INIT;
+ char cwd[GIT_PATH_MAX];
+ git_oid a, b;
+
+ cl_must_pass(p_getcwd(cwd, GIT_PATH_MAX));
+ cl_must_pass(p_mkdir("absolute", 0777));
+ cl_git_pass(git_buf_joinpath(&root, cwd, "absolute"));
+ cl_git_pass(git_buf_joinpath(&txt, root.ptr, "testfile.txt"));
+ cl_git_pass(git_buf_joinpath(&bin, root.ptr, "testfile.bin"));
+
+ cl_repo_set_bool(_repo, "core.autocrlf", true);
+ cl_git_append2file("status/.gitattributes", "*.txt text\n*.bin binary\n\n");
+
+ /* create some sample content with CRLF in it */
+ cl_git_mkfile("absolute/testfile.txt", "content\r\n");
+ cl_git_mkfile("absolute/testfile.bin", "other\r\nstuff\r\n");
+
+ /* not equal hashes because of filtering */
+ cl_git_pass(git_odb_hashfile(&a, "absolute/testfile.txt", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, "testfile.txt"));
+ cl_assert(git_oid_cmp(&a, &b));
+
+ /* equal hashes because filter is binary */
+ cl_git_pass(git_odb_hashfile(&a, "absolute/testfile.bin", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, "testfile.bin"));
+ cl_assert_equal_oid(&a, &b);
+
+ /*
+ * equal hashes because no filtering occurs for absolute paths outside the working
+ * directory unless as_path is specified
+ */
+ cl_git_pass(git_odb_hashfile(&a, "absolute/testfile.txt", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, NULL));
+ cl_assert_equal_oid(&a, &b);
+
+ cl_git_pass(git_odb_hashfile(&a, "absolute/testfile.bin", GIT_OBJECT_BLOB));
+ cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, NULL));
+ cl_assert_equal_oid(&a, &b);
+
+ git_buf_dispose(&txt);
+ git_buf_dispose(&bin);
+ git_buf_dispose(&root);
}
diff --git a/tests/repo/init.c b/tests/repo/init.c
index 5a95229e6..1aa326f7f 100644
--- a/tests/repo/init.c
+++ b/tests/repo/init.c
@@ -11,30 +11,30 @@ enum repo_mode {
BARE_REPOSITORY = 1
};
-static git_repository *_repo = NULL;
-static git_buf _global_path = GIT_BUF_INIT;
+static git_repository *g_repo = NULL;
+static git_buf g_global_path = GIT_BUF_INIT;
void test_repo_init__initialize(void)
{
- _repo = NULL;
+ g_repo = NULL;
git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
- &_global_path);
+ &g_global_path);
}
void test_repo_init__cleanup(void)
{
git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
- _global_path.ptr);
- git_buf_dispose(&_global_path);
+ g_global_path.ptr);
+ git_buf_dispose(&g_global_path);
cl_fixture_cleanup("tmp_global_path");
}
static void cleanup_repository(void *path)
{
- git_repository_free(_repo);
- _repo = NULL;
+ git_repository_free(g_repo);
+ g_repo = NULL;
cl_fixture_cleanup((const char *)path);
}
@@ -49,9 +49,9 @@ static void ensure_repository_init(
cl_assert(!git_path_isdir(working_directory));
- cl_git_pass(git_repository_init(&_repo, working_directory, is_bare));
+ cl_git_pass(git_repository_init(&g_repo, working_directory, is_bare));
- workdir = git_repository_workdir(_repo);
+ workdir = git_repository_workdir(g_repo);
if (workdir != NULL || expected_working_directory != NULL) {
cl_assert(
git__suffixcmp(workdir, expected_working_directory) == 0
@@ -59,19 +59,19 @@ static void ensure_repository_init(
}
cl_assert(
- git__suffixcmp(git_repository_path(_repo), expected_path_repository) == 0
+ git__suffixcmp(git_repository_path(g_repo), expected_path_repository) == 0
);
- cl_assert(git_repository_is_bare(_repo) == is_bare);
+ cl_assert(git_repository_is_bare(g_repo) == is_bare);
#ifdef GIT_WIN32
if (!is_bare) {
- DWORD fattrs = GetFileAttributes(git_repository_path(_repo));
+ DWORD fattrs = GetFileAttributes(git_repository_path(g_repo));
cl_assert((fattrs & FILE_ATTRIBUTE_HIDDEN) != 0);
}
#endif
- cl_assert(git_repository_is_empty(_repo));
+ cl_assert(git_repository_is_empty(g_repo));
}
void test_repo_init__standard_repo(void)
@@ -112,13 +112,14 @@ void test_repo_init__bare_repo_escaping_current_workdir(void)
cl_git_pass(chdir(git_buf_cstr(&path_repository)));
/* Initialize a bare repo with a relative path escaping out of the current working directory */
- cl_git_pass(git_repository_init(&_repo, "../d/e.git", 1));
- cl_git_pass(git__suffixcmp(git_repository_path(_repo), "/a/b/d/e.git/"));
+ cl_git_pass(git_repository_init(&g_repo, "../d/e.git", 1));
+ cl_git_pass(git__suffixcmp(git_repository_path(g_repo), "/a/b/d/e.git/"));
- git_repository_free(_repo);
+ git_repository_free(g_repo);
+ g_repo = NULL;
/* Open a bare repo with a relative path escaping out of the current working directory */
- cl_git_pass(git_repository_open(&_repo, "../d/e.git"));
+ cl_git_pass(git_repository_open(&g_repo, "../d/e.git"));
cl_git_pass(chdir(git_buf_cstr(&path_current_workdir)));
@@ -133,11 +134,12 @@ void test_repo_init__reinit_bare_repo(void)
cl_set_cleanup(&cleanup_repository, "reinit.git");
/* Initialize the repository */
- cl_git_pass(git_repository_init(&_repo, "reinit.git", 1));
- git_repository_free(_repo);
+ cl_git_pass(git_repository_init(&g_repo, "reinit.git", 1));
+ git_repository_free(g_repo);
+ g_repo = NULL;
/* Reinitialize the repository */
- cl_git_pass(git_repository_init(&_repo, "reinit.git", 1));
+ cl_git_pass(git_repository_init(&g_repo, "reinit.git", 1));
}
void test_repo_init__reinit_too_recent_bare_repo(void)
@@ -145,8 +147,8 @@ void test_repo_init__reinit_too_recent_bare_repo(void)
git_config *config;
/* Initialize the repository */
- cl_git_pass(git_repository_init(&_repo, "reinit.git", 1));
- git_repository_config(&config, _repo);
+ cl_git_pass(git_repository_init(&g_repo, "reinit.git", 1));
+ git_repository_config(&config, g_repo);
/*
* Hack the config of the repository to make it look like it has
@@ -155,10 +157,11 @@ void test_repo_init__reinit_too_recent_bare_repo(void)
cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 42));
git_config_free(config);
- git_repository_free(_repo);
+ git_repository_free(g_repo);
+ g_repo = NULL;
/* Try to reinitialize the repository */
- cl_git_fail(git_repository_init(&_repo, "reinit.git", 1));
+ cl_git_fail(git_repository_init(&g_repo, "reinit.git", 1));
cl_fixture_cleanup("reinit.git");
}
@@ -172,15 +175,15 @@ void test_repo_init__additional_templates(void)
ensure_repository_init("tester", 0, "tester/.git/", "tester/");
cl_git_pass(
- git_buf_joinpath(&path, git_repository_path(_repo), "description"));
+ git_buf_joinpath(&path, git_repository_path(g_repo), "description"));
cl_assert(git_path_isfile(git_buf_cstr(&path)));
cl_git_pass(
- git_buf_joinpath(&path, git_repository_path(_repo), "info/exclude"));
+ git_buf_joinpath(&path, git_repository_path(g_repo), "info/exclude"));
cl_assert(git_path_isfile(git_buf_cstr(&path)));
cl_git_pass(
- git_buf_joinpath(&path, git_repository_path(_repo), "hooks"));
+ git_buf_joinpath(&path, git_repository_path(g_repo), "hooks"));
cl_assert(git_path_isdir(git_buf_cstr(&path)));
/* won't confirm specific contents of hooks dir since it may vary */
@@ -197,9 +200,9 @@ static void assert_config_entry_on_init_bytype(
cl_set_cleanup(&cleanup_repository, "config_entry");
- cl_git_pass(git_repository_init(&_repo, repo_path, is_bare));
+ cl_git_pass(git_repository_init(&g_repo, repo_path, is_bare));
- cl_git_pass(git_repository_config(&config, _repo));
+ cl_git_pass(git_repository_config(&config, g_repo));
error = git_config_get_bool(&current_value, config, config_key);
git_config_free(config);
@@ -215,7 +218,8 @@ static void assert_config_entry_on_init(
const char *config_key, int expected_value)
{
assert_config_entry_on_init_bytype(config_key, expected_value, true);
- git_repository_free(_repo);
+ git_repository_free(g_repo);
+ g_repo = NULL;
assert_config_entry_on_init_bytype(config_key, expected_value, false);
}
@@ -262,10 +266,10 @@ void test_repo_init__symlinks_win32_enabled_by_global_config(void)
* Create a new repository (can't use `assert_config_on_init` since we
* want to examine configuration levels with more granularity.)
*/
- cl_git_pass(git_repository_init(&_repo, "config_entry/test.non.bare.git", false));
+ cl_git_pass(git_repository_init(&g_repo, "config_entry/test.non.bare.git", false));
/* Ensure that core.symlinks remains set (via the global config). */
- cl_git_pass(git_repository_config(&config, _repo));
+ cl_git_pass(git_repository_config(&config, g_repo));
cl_git_pass(git_config_get_bool(&val, config, "core.symlinks"));
cl_assert_equal_i(1, val);
@@ -278,6 +282,9 @@ void test_repo_init__symlinks_win32_enabled_by_global_config(void)
git_config_free(repo_config);
git_config_free(config);
+
+ git_repository_free(g_repo);
+ g_repo = NULL;
#endif
}
@@ -324,18 +331,18 @@ void test_repo_init__reinit_doesnot_overwrite_ignorecase(void)
/* Init a new repo */
cl_set_cleanup(&cleanup_repository, "not.overwrite.git");
- cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1));
+ cl_git_pass(git_repository_init(&g_repo, "not.overwrite.git", 1));
/* Change the "core.ignorecase" config value to something unlikely */
- git_repository_config(&config, _repo);
+ git_repository_config(&config, g_repo);
git_config_set_int32(config, "core.ignorecase", 42);
git_config_free(config);
- git_repository_free(_repo);
- _repo = NULL;
+ git_repository_free(g_repo);
+ g_repo = NULL;
/* Reinit the repository */
- cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1));
- git_repository_config(&config, _repo);
+ cl_git_pass(git_repository_init(&g_repo, "not.overwrite.git", 1));
+ git_repository_config(&config, g_repo);
/* Ensure the "core.ignorecase" config value hasn't been updated */
cl_git_pass(git_config_get_int32(&current_value, config, "core.ignorecase"));
@@ -350,26 +357,26 @@ void test_repo_init__reinit_overwrites_filemode(void)
/* Init a new repo */
cl_set_cleanup(&cleanup_repository, "overwrite.git");
- cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1));
+ cl_git_pass(git_repository_init(&g_repo, "overwrite.git", 1));
/* Change the "core.filemode" config value to something unlikely */
- cl_repo_set_bool(_repo, "core.filemode", !expected);
+ cl_repo_set_bool(g_repo, "core.filemode", !expected);
- git_repository_free(_repo);
- _repo = NULL;
+ git_repository_free(g_repo);
+ g_repo = NULL;
/* Reinit the repository */
- cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1));
+ cl_git_pass(git_repository_init(&g_repo, "overwrite.git", 1));
/* Ensure the "core.filemode" config value has been reset */
- current_value = cl_repo_get_bool(_repo, "core.filemode");
+ current_value = cl_repo_get_bool(g_repo, "core.filemode");
cl_assert_equal_i(expected, current_value);
}
void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void)
{
assert_config_entry_on_init_bytype("core.logallrefupdates", GIT_ENOTFOUND, true);
- git_repository_free(_repo);
+ git_repository_free(g_repo);
assert_config_entry_on_init_bytype("core.logallrefupdates", true, false);
}
@@ -378,16 +385,16 @@ void test_repo_init__extended_0(void)
git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
/* without MKDIR this should fail */
- cl_git_fail(git_repository_init_ext(&_repo, "extended", &opts));
+ cl_git_fail(git_repository_init_ext(&g_repo, "extended", &opts));
/* make the directory first, then it should succeed */
cl_git_pass(git_futils_mkdir("extended", 0775, 0));
- cl_git_pass(git_repository_init_ext(&_repo, "extended", &opts));
+ cl_git_pass(git_repository_init_ext(&g_repo, "extended", &opts));
- cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/extended/"));
- cl_assert(!git__suffixcmp(git_repository_path(_repo), "/extended/.git/"));
- cl_assert(!git_repository_is_bare(_repo));
- cl_assert(git_repository_is_empty(_repo));
+ cl_assert(!git__suffixcmp(git_repository_workdir(g_repo), "/extended/"));
+ cl_assert(!git__suffixcmp(git_repository_path(g_repo), "/extended/.git/"));
+ cl_assert(!git_repository_is_bare(g_repo));
+ cl_assert(git_repository_is_empty(g_repo));
cleanup_repository("extended");
}
@@ -407,33 +414,33 @@ void test_repo_init__extended_1(void)
opts.initial_head = "development";
opts.origin_url = "https://github.com/libgit2/libgit2.git";
- cl_git_pass(git_repository_init_ext(&_repo, "root/b/c.git", &opts));
+ cl_git_pass(git_repository_init_ext(&g_repo, "root/b/c.git", &opts));
- cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/c_wd/"));
- cl_assert(!git__suffixcmp(git_repository_path(_repo), "/c.git/"));
+ cl_assert(!git__suffixcmp(git_repository_workdir(g_repo), "/c_wd/"));
+ cl_assert(!git__suffixcmp(git_repository_path(g_repo), "/c.git/"));
cl_assert(git_path_isfile("root/b/c_wd/.git"));
- cl_assert(!git_repository_is_bare(_repo));
+ cl_assert(!git_repository_is_bare(g_repo));
/* repo will not be counted as empty because we set head to "development" */
- cl_assert(!git_repository_is_empty(_repo));
+ cl_assert(!git_repository_is_empty(g_repo));
- cl_git_pass(git_path_lstat(git_repository_path(_repo), &st));
+ cl_git_pass(git_path_lstat(git_repository_path(g_repo), &st));
cl_assert(S_ISDIR(st.st_mode));
if (cl_is_chmod_supported())
cl_assert((S_ISGID & st.st_mode) == S_ISGID);
else
cl_assert((S_ISGID & st.st_mode) == 0);
- cl_git_pass(git_reference_lookup(&ref, _repo, "HEAD"));
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD"));
cl_assert(git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC);
cl_assert_equal_s("refs/heads/development", git_reference_symbolic_target(ref));
git_reference_free(ref);
- cl_git_pass(git_remote_lookup(&remote, _repo, "origin"));
+ cl_git_pass(git_remote_lookup(&remote, g_repo, "origin"));
cl_assert_equal_s("origin", git_remote_name(remote));
cl_assert_equal_s(opts.origin_url, git_remote_url(remote));
git_remote_free(remote);
- git_repository_free(_repo);
+ git_repository_free(g_repo);
cl_fixture_cleanup("root");
}
@@ -449,17 +456,17 @@ void test_repo_init__relative_gitdir(void)
GIT_REPOSITORY_INIT_NO_DOTGIT_DIR;
/* make the directory first, then it should succeed */
- cl_git_pass(git_repository_init_ext(&_repo, "root/b/my_repository", &opts));
+ cl_git_pass(git_repository_init_ext(&g_repo, "root/b/my_repository", &opts));
- cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "root/b/c_wd/"));
- cl_assert(!git__suffixcmp(git_repository_path(_repo), "root/b/my_repository/"));
- cl_assert(!git_repository_is_bare(_repo));
- cl_assert(git_repository_is_empty(_repo));
+ cl_assert(!git__suffixcmp(git_repository_workdir(g_repo), "root/b/c_wd/"));
+ cl_assert(!git__suffixcmp(git_repository_path(g_repo), "root/b/my_repository/"));
+ cl_assert(!git_repository_is_bare(g_repo));
+ cl_assert(git_repository_is_empty(g_repo));
/* Verify that the gitlink and worktree entries are relative */
/* Verify worktree */
- assert_config_entry_value(_repo, "core.worktree", "../c_wd/");
+ assert_config_entry_value(g_repo, "core.worktree", "../c_wd/");
/* Verify gitlink */
cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git"));
@@ -485,18 +492,18 @@ void test_repo_init__relative_gitdir_2(void)
GIT_REPOSITORY_INIT_NO_DOTGIT_DIR;
/* make the directory first, then it should succeed */
- cl_git_pass(git_repository_init_ext(&_repo, "root/b/my_repository", &opts));
+ cl_git_pass(git_repository_init_ext(&g_repo, "root/b/my_repository", &opts));
git_buf_dispose(&full_path);
- cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "root/b/c_wd/"));
- cl_assert(!git__suffixcmp(git_repository_path(_repo), "root/b/my_repository/"));
- cl_assert(!git_repository_is_bare(_repo));
- cl_assert(git_repository_is_empty(_repo));
+ cl_assert(!git__suffixcmp(git_repository_workdir(g_repo), "root/b/c_wd/"));
+ cl_assert(!git__suffixcmp(git_repository_path(g_repo), "root/b/my_repository/"));
+ cl_assert(!git_repository_is_bare(g_repo));
+ cl_assert(git_repository_is_empty(g_repo));
/* Verify that the gitlink and worktree entries are relative */
/* Verify worktree */
- assert_config_entry_value(_repo, "core.worktree", "../c_wd/");
+ assert_config_entry_value(g_repo, "core.worktree", "../c_wd/");
/* Verify gitlink */
cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git"));
@@ -513,11 +520,11 @@ void test_repo_init__can_reinit_an_initialized_repository(void)
cl_set_cleanup(&cleanup_repository, "extended");
cl_git_pass(git_futils_mkdir("extended", 0775, 0));
- cl_git_pass(git_repository_init(&_repo, "extended", false));
+ cl_git_pass(git_repository_init(&g_repo, "extended", false));
cl_git_pass(git_repository_init(&reinit, "extended", false));
- cl_assert_equal_s(git_repository_path(_repo), git_repository_path(reinit));
+ cl_assert_equal_s(git_repository_path(g_repo), git_repository_path(reinit));
git_repository_free(reinit);
}
@@ -529,10 +536,10 @@ void test_repo_init__init_with_initial_commit(void)
cl_set_cleanup(&cleanup_repository, "committed");
/* Initialize the repository */
- cl_git_pass(git_repository_init(&_repo, "committed", 0));
+ cl_git_pass(git_repository_init(&g_repo, "committed", 0));
/* Index will be automatically created when requested for a new repo */
- cl_git_pass(git_repository_index(&index, _repo));
+ cl_git_pass(git_repository_index(&index, g_repo));
/* Create a file so we can commit it
*
@@ -558,7 +565,7 @@ void test_repo_init__init_with_initial_commit(void)
/* Make sure we're ready to use git_signature_default :-) */
{
git_config *cfg, *local;
- cl_git_pass(git_repository_config(&cfg, _repo));
+ cl_git_pass(git_repository_config(&cfg, g_repo));
cl_git_pass(git_config_open_level(&local, cfg, GIT_CONFIG_LEVEL_LOCAL));
cl_git_pass(git_config_set_string(local, "user.name", "Test User"));
cl_git_pass(git_config_set_string(local, "user.email", "t@example.com"));
@@ -572,12 +579,12 @@ void test_repo_init__init_with_initial_commit(void)
git_oid tree_id, commit_id;
git_tree *tree;
- cl_git_pass(git_signature_default(&sig, _repo));
+ cl_git_pass(git_signature_default(&sig, g_repo));
cl_git_pass(git_index_write_tree(&tree_id, index));
- cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));
+ cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id));
cl_git_pass(git_commit_create_v(
- &commit_id, _repo, "HEAD", sig, sig,
+ &commit_id, g_repo, "HEAD", sig, sig,
NULL, "First", tree, 0));
git_tree_free(tree);
@@ -665,3 +672,67 @@ void test_repo_init__unwriteable_directory(void)
clar__skip();
#endif
}
+
+void test_repo_init__defaultbranch_config(void)
+{
+ git_reference *head;
+
+ cl_set_cleanup(&cleanup_repository, "repo");
+
+ create_tmp_global_config("tmp_global_path", "init.defaultbranch", "my_default_branch");
+
+ cl_git_pass(git_repository_init(&g_repo, "repo", 0));
+ cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
+
+ cl_assert_equal_s("refs/heads/my_default_branch", git_reference_symbolic_target(head));
+
+ git_reference_free(head);
+}
+
+void test_repo_init__defaultbranch_config_empty(void)
+{
+ git_reference *head;
+
+ cl_set_cleanup(&cleanup_repository, "repo");
+
+ create_tmp_global_config("tmp_global_path", "init.defaultbranch", "");
+
+ cl_git_pass(git_repository_init(&g_repo, "repo", 0));
+ cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
+
+ cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));
+
+ git_reference_free(head);
+}
+
+void test_repo_init__longpath(void)
+{
+#ifdef GIT_WIN32
+ size_t padding = CONST_STRLEN("objects/pack/pack-.pack.lock") + GIT_OID_HEXSZ;
+ size_t max, i;
+ git_buf path = GIT_BUF_INIT;
+ git_repository *one = NULL, *two = NULL;
+
+ /*
+ * Files within repositories need to fit within MAX_PATH;
+ * that means a repo path must be at most (MAX_PATH - 18).
+ */
+ cl_git_pass(git_buf_puts(&path, clar_sandbox_path()));
+ cl_git_pass(git_buf_putc(&path, '/'));
+
+ max = ((MAX_PATH) - path.size) - padding;
+
+ for (i = 0; i < max - 1; i++)
+ cl_git_pass(git_buf_putc(&path, 'a'));
+
+ cl_git_pass(git_repository_init(&one, path.ptr, 1));
+
+ /* Paths longer than this are rejected */
+ cl_git_pass(git_buf_putc(&path, 'z'));
+ cl_git_fail(git_repository_init(&two, path.ptr, 1));
+
+ git_repository_free(one);
+ git_repository_free(two);
+ git_buf_dispose(&path);
+#endif
+}
diff --git a/tests/repo/open.c b/tests/repo/open.c
index 881a23d34..bd60c12c2 100644
--- a/tests/repo/open.c
+++ b/tests/repo/open.c
@@ -42,48 +42,6 @@ void test_repo_open__format_version_1(void)
git_repository_free(repo);
}
-void test_repo_open__format_version_1_with_valid_extension(void)
-{
- git_repository *repo;
- git_config *config;
-
- repo = cl_git_sandbox_init("empty_bare.git");
-
- cl_git_pass(git_repository_open(&repo, "empty_bare.git"));
- cl_git_pass(git_repository_config(&config, repo));
-
- cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 1));
- cl_git_pass(git_config_set_int32(config, "extensions.noop", 1));
-
- git_config_free(config);
- git_repository_free(repo);
-
- cl_git_pass(git_repository_open(&repo, "empty_bare.git"));
- cl_assert(git_repository_path(repo) != NULL);
- cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0);
- git_repository_free(repo);
-}
-
-void test_repo_open__format_version_1_with_invalid_extension(void)
-{
- git_repository *repo;
- git_config *config;
-
- repo = cl_git_sandbox_init("empty_bare.git");
-
- cl_git_pass(git_repository_open(&repo, "empty_bare.git"));
- cl_git_pass(git_repository_config(&config, repo));
-
- cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 1));
- cl_git_pass(git_config_set_int32(config, "extensions.invalid", 1));
-
- git_config_free(config);
- git_repository_free(repo);
-
- cl_git_fail(git_repository_open(&repo, "empty_bare.git"));
- git_repository_free(repo);
-}
-
void test_repo_open__standard_empty_repo_through_gitdir(void)
{
git_repository *repo;
diff --git a/tests/resources/certs/61f2ddb6.0 b/tests/resources/certs/61f2ddb6.0
new file mode 100644
index 000000000..7d9ef6fce
--- /dev/null
+++ b/tests/resources/certs/61f2ddb6.0
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFWzCCA0MCFESY816VkhBPUOsdp7djKW5q4ZVzMA0GCSqGSIb3DQEBCwUAMGox
+CzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlD
+YW1icmlkZ2UxFDASBgNVBAoMC2xpYmdpdDIub3JnMRkwFwYDVQQDDBB0ZXN0Lmxp
+YmdpdDIub3JnMB4XDTIxMDgyNTE4NTExMVoXDTMxMDgyMzE4NTExMVowajELMAkG
+A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJy
+aWRnZTEUMBIGA1UECgwLbGliZ2l0Mi5vcmcxGTAXBgNVBAMMEHRlc3QubGliZ2l0
+Mi5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvaRUaM3IJh9N
+G6Yc7tHioUsIGU0MkzSvy/X6O/vONnuuioiJQyPIvfRSvZR2iQj8THTypDGhWn3r
+6h2wk5eOUGwJH2N9FrrlEBdpsMc7SKdiJXwTI30mkK3/qru8NzE71dgCkYp1xhKw
+edTkAFK+PkvyVLFL7K35cx8Bxfamyssdb+qGWa7g4P27CWUdvQgmurrzzPIMZiLD
+/cI1Kwer/N7nTY/6CSs9dcHTlanyZdf+mQ50+//vI4F6+OduGHJkxRF48jLUz1rz
+P3WGRMRbHjCmvWpX/9DLgqGk7XTy0hNgNUCit6kawwcv5y7SP/ii86MkynAHn5i8
+d+zhXjdrSSy8i0IbRJafnxmtrsmjGeIzraJSRqMlv7KKWEBz+alm6vlePnRUbWB7
+0po5uSsRPya6kJJCzMjIfKq1dgXq33m9jCG2wU+L4fEHVlEkFGXYTspMlIBNUjTc
+c45+e1EpamF8aHm32PP8gTF8fGZzQjOXmNW5g7t0joWMGZ+Ao2jYc1pG3SOARi36
+azrmB5/XJqbbfVZEzIue01fO/5R8RgabOP1qWUjH2KLb8zTDok+CW0ULNseU+MKf
+PHXG2OjxcR0vTqop2V6JlKTXXx3/TOD16/+mSrrPzNDejLrkvAH9oN38YpMBM8eg
+vfivHNRm0jjdGbv2OOPEBLEf1cNimQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBZ
+znFta24sWoqdgKXKAK5RHAh/HyOvTInwcXi9RU4XjYlbqNVs0ODR74VRZINoyAL2
+bo+x/iUuAp9+b8fjr79fpVof3nSMU7UtMcT1nvzVmaUYSkKQ0f/9vK4yg0kao1bV
+WwhIc0slKgOJjEicPVs3kd+duv5vakQeUajLPGM8SiS1F/nF67rIuZLdJn2Qp+im
+w5Q3Pjgqw5VrJxyk3AaUcntKHpWy1POLyNV79tXra6BxbtQVlRS0+h1MHELARDFx
+1ZtgyAe5YbWM7WrIiFKD4mmKZu4GMnJDXVpfUub5g0U/e7L/gg6Z1UyYZuln6axw
+RojuAHo1uAWFUsjhWLYV/7P/l/dC+7gFjvSsUqb1+U7jXObzfKjXo/FwYcy4VsVv
+xNbglbhdVjAo/YBTJuf3L0UZjSbxvQIYS+v8u1ECeWE6SH6cHRzryeo5wO4h8NJR
+n30xsvocHFbs4LWy5BVfMUo6wGUy0Y+1gSwSqVMv3JPuLwxUsv0HPdeC00Ab9cHq
+kYXPNZXg3a6orTDa4hJLdAm2V/fn/2KKJYlNj7iCL664QgoCHl7LFyLMiwFVCu5h
+4JjGL3Q+8MondaLZlq5YDmvtj979AyM/7qL4XAE2oofQ4J5dqnKKpMkWdAM/fI/9
+N5DK/4zMXJWgIED0yo2SSZHQmuqZplacOhmfjjZigQ==
+-----END CERTIFICATE-----
diff --git a/tests/resources/certs/db4f60b0.0 b/tests/resources/certs/db4f60b0.0
new file mode 100644
index 000000000..7d9ef6fce
--- /dev/null
+++ b/tests/resources/certs/db4f60b0.0
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFWzCCA0MCFESY816VkhBPUOsdp7djKW5q4ZVzMA0GCSqGSIb3DQEBCwUAMGox
+CzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlD
+YW1icmlkZ2UxFDASBgNVBAoMC2xpYmdpdDIub3JnMRkwFwYDVQQDDBB0ZXN0Lmxp
+YmdpdDIub3JnMB4XDTIxMDgyNTE4NTExMVoXDTMxMDgyMzE4NTExMVowajELMAkG
+A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJy
+aWRnZTEUMBIGA1UECgwLbGliZ2l0Mi5vcmcxGTAXBgNVBAMMEHRlc3QubGliZ2l0
+Mi5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvaRUaM3IJh9N
+G6Yc7tHioUsIGU0MkzSvy/X6O/vONnuuioiJQyPIvfRSvZR2iQj8THTypDGhWn3r
+6h2wk5eOUGwJH2N9FrrlEBdpsMc7SKdiJXwTI30mkK3/qru8NzE71dgCkYp1xhKw
+edTkAFK+PkvyVLFL7K35cx8Bxfamyssdb+qGWa7g4P27CWUdvQgmurrzzPIMZiLD
+/cI1Kwer/N7nTY/6CSs9dcHTlanyZdf+mQ50+//vI4F6+OduGHJkxRF48jLUz1rz
+P3WGRMRbHjCmvWpX/9DLgqGk7XTy0hNgNUCit6kawwcv5y7SP/ii86MkynAHn5i8
+d+zhXjdrSSy8i0IbRJafnxmtrsmjGeIzraJSRqMlv7KKWEBz+alm6vlePnRUbWB7
+0po5uSsRPya6kJJCzMjIfKq1dgXq33m9jCG2wU+L4fEHVlEkFGXYTspMlIBNUjTc
+c45+e1EpamF8aHm32PP8gTF8fGZzQjOXmNW5g7t0joWMGZ+Ao2jYc1pG3SOARi36
+azrmB5/XJqbbfVZEzIue01fO/5R8RgabOP1qWUjH2KLb8zTDok+CW0ULNseU+MKf
+PHXG2OjxcR0vTqop2V6JlKTXXx3/TOD16/+mSrrPzNDejLrkvAH9oN38YpMBM8eg
+vfivHNRm0jjdGbv2OOPEBLEf1cNimQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBZ
+znFta24sWoqdgKXKAK5RHAh/HyOvTInwcXi9RU4XjYlbqNVs0ODR74VRZINoyAL2
+bo+x/iUuAp9+b8fjr79fpVof3nSMU7UtMcT1nvzVmaUYSkKQ0f/9vK4yg0kao1bV
+WwhIc0slKgOJjEicPVs3kd+duv5vakQeUajLPGM8SiS1F/nF67rIuZLdJn2Qp+im
+w5Q3Pjgqw5VrJxyk3AaUcntKHpWy1POLyNV79tXra6BxbtQVlRS0+h1MHELARDFx
+1ZtgyAe5YbWM7WrIiFKD4mmKZu4GMnJDXVpfUub5g0U/e7L/gg6Z1UyYZuln6axw
+RojuAHo1uAWFUsjhWLYV/7P/l/dC+7gFjvSsUqb1+U7jXObzfKjXo/FwYcy4VsVv
+xNbglbhdVjAo/YBTJuf3L0UZjSbxvQIYS+v8u1ECeWE6SH6cHRzryeo5wO4h8NJR
+n30xsvocHFbs4LWy5BVfMUo6wGUy0Y+1gSwSqVMv3JPuLwxUsv0HPdeC00Ab9cHq
+kYXPNZXg3a6orTDa4hJLdAm2V/fn/2KKJYlNj7iCL664QgoCHl7LFyLMiwFVCu5h
+4JjGL3Q+8MondaLZlq5YDmvtj979AyM/7qL4XAE2oofQ4J5dqnKKpMkWdAM/fI/9
+N5DK/4zMXJWgIED0yo2SSZHQmuqZplacOhmfjjZigQ==
+-----END CERTIFICATE-----
diff --git a/tests/resources/config/config12 b/tests/resources/config/config12
index 6917880b5..2e92762df 100644
--- a/tests/resources/config/config12
+++ b/tests/resources/config/config12
@@ -11,3 +11,13 @@ and other stuff !@#"
multiline comment # with ;\n special chars \
and other stuff !@#" #^^^
back = "this is \ba phrase"
+ dollar = some $sign
+ multiquotes = !ls "x" \
+ ls "# comment2" \
+ $HOME
+ multiquotes2 = !ls "x" \
+ ls "\"# comment2" \
+ $HOME\"
+ multiquotes3 = hi "# ho" there "are #" more \
+quotes
+ quotecomment = hi "# ho" there "are #" more # and a real comment
diff --git a/tests/resources/config/config21 b/tests/resources/config/config21
new file mode 100644
index 000000000..aa5eb4115
--- /dev/null
+++ b/tests/resources/config/config21
@@ -0,0 +1,5 @@
+[alias]
+ m = '\
+ ";" \
+ ";" \
+ '
diff --git a/tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fb b/tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fb
new file mode 100644
index 000000000..44076ca39
--- /dev/null
+++ b/tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fb
Binary files differ
diff --git a/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d b/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d
new file mode 100644
index 000000000..ca97967b8
--- /dev/null
+++ b/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d
Binary files differ
diff --git a/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c b/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c
new file mode 100644
index 000000000..0576e6229
--- /dev/null
+++ b/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c
Binary files differ
diff --git a/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0 b/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0
new file mode 100644
index 000000000..7501c88e6
--- /dev/null
+++ b/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0
Binary files differ
diff --git a/tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f0 b/tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f0
new file mode 100644
index 000000000..d745d20e6
--- /dev/null
+++ b/tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f0
@@ -0,0 +1,3 @@
+x¥M
+Â0…]çs%3ÓDtá ¼À$™bÁ6¥F¼¾Q¼»÷ï¥2McònSWU`Ž6*ö¾C¡žĽGì¢w®×,‰|SŒÉ,²ê\‰¦à˜Ù#‹ôYö®8t); qÈÁȳÞÊ
+—ü’5ÃõV¦G™á -ý¨“~‹ŸÛ¥2=ù`ÑÁÖ²µ¦¥mlÕ?1æœ3È cn¶ ºHã]aïjÞ@U \ No newline at end of file
diff --git a/tests/resources/crlf.git/refs/heads/ident b/tests/resources/crlf.git/refs/heads/ident
new file mode 100644
index 000000000..8732f0cb9
--- /dev/null
+++ b/tests/resources/crlf.git/refs/heads/ident
@@ -0,0 +1 @@
+b8986fec0f7bde90f78ac72706e782d82f24f2f0
diff --git a/tests/resources/crlf.git/refs/heads/no-ident b/tests/resources/crlf.git/refs/heads/no-ident
new file mode 100644
index 000000000..fa9a6737b
--- /dev/null
+++ b/tests/resources/crlf.git/refs/heads/no-ident
@@ -0,0 +1 @@
+1ec507638b806aba45d6142082885f2a9e88322d
diff --git a/tests/resources/merge-recursive/.gitted/objects/info/commit-graph b/tests/resources/merge-recursive/.gitted/objects/info/commit-graph
new file mode 100644
index 000000000..da055f180
--- /dev/null
+++ b/tests/resources/merge-recursive/.gitted/objects/info/commit-graph
Binary files differ
diff --git a/tests/resources/renames/.gitted/ORIG_HEAD b/tests/resources/renames/.gitted/ORIG_HEAD
new file mode 100644
index 000000000..642c3198d
--- /dev/null
+++ b/tests/resources/renames/.gitted/ORIG_HEAD
@@ -0,0 +1 @@
+19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13
diff --git a/tests/resources/renames/.gitted/index b/tests/resources/renames/.gitted/index
index 72363c0f5..5882a8d60 100644
--- a/tests/resources/renames/.gitted/index
+++ b/tests/resources/renames/.gitted/index
Binary files differ
diff --git a/tests/resources/renames/.gitted/logs/HEAD b/tests/resources/renames/.gitted/logs/HEAD
index e69792263..e6da6784e 100644
--- a/tests/resources/renames/.gitted/logs/HEAD
+++ b/tests/resources/renames/.gitted/logs/HEAD
@@ -2,3 +2,8 @@
31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 2bc7f351d20b53f1c72c16c4b036e491c478c49a Russell Belfer <rb@github.com> 1351024817 -0700 commit: copy and rename with no change
2bc7f351d20b53f1c72c16c4b036e491c478c49a 1c068dee5790ef1580cfc4cd670915b48d790084 Russell Belfer <rb@github.com> 1361485758 -0800 commit: rewrites, copies with changes, etc.
1c068dee5790ef1580cfc4cd670915b48d790084 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 Russell Belfer <rb@github.com> 1361486360 -0800 commit: more renames and smallish modifications
+19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 Kartikaya Gupta <kats@pancake.staktrace.com> 1618486966 -0400 checkout: moving from master to break_rewrite
+31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 db98035f715427eef1f5e17f03e1801c05301e9e Kartikaya Gupta <kats@pancake.staktrace.com> 1618487039 -0400 commit: This test needs to start with a minimum of four files
+db98035f715427eef1f5e17f03e1801c05301e9e 7e7bfb88ba9bc65fd700fee1819cf1c317aafa56 Kartikaya Gupta <kats@pancake.staktrace.com> 1618487097 -0400 commit: Copy/modify files around
+7e7bfb88ba9bc65fd700fee1819cf1c317aafa56 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 Kartikaya Gupta <kats@pancake.staktrace.com> 1618487105 -0400 checkout: moving from break_rewrite to master
+19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 Kartikaya Gupta <kats@pancake.staktrace.com> 1618487271 -0400 reset: moving to HEAD
diff --git a/tests/resources/renames/.gitted/objects/41/2a2eaf2c13103ea976b3b02c17abee7a358432 b/tests/resources/renames/.gitted/objects/41/2a2eaf2c13103ea976b3b02c17abee7a358432
new file mode 100644
index 000000000..d0d3334bf
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/41/2a2eaf2c13103ea976b3b02c17abee7a358432
Binary files differ
diff --git a/tests/resources/renames/.gitted/objects/5a/71babaaac78a758b52576a60cea3c218c8b546 b/tests/resources/renames/.gitted/objects/5a/71babaaac78a758b52576a60cea3c218c8b546
new file mode 100644
index 000000000..e685bfaff
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/5a/71babaaac78a758b52576a60cea3c218c8b546
Binary files differ
diff --git a/tests/resources/renames/.gitted/objects/7e/7bfb88ba9bc65fd700fee1819cf1c317aafa56 b/tests/resources/renames/.gitted/objects/7e/7bfb88ba9bc65fd700fee1819cf1c317aafa56
new file mode 100644
index 000000000..e53c843dd
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/7e/7bfb88ba9bc65fd700fee1819cf1c317aafa56
@@ -0,0 +1,2 @@
+x¥ŽKn„0³ö)ú™éö)Š"e1‹9EcÚ
+bÀÈ4 nî0ËWR•^®Ë2)ØŽ>´‰€'ËV¸ØLŽÐ ÷±܀׎<ˆDv!ygÍÆMV…qèºP"o£H¡„b¹TJHƒC’^ úW<¹é4óÉð86eøšY÷Ÿ×̳ÜvåYg¹åº|u”|ŠØGøDh.z½Uy·c~ëvÞ—:Nå„2½dnõXGó ©T´ \ No newline at end of file
diff --git a/tests/resources/renames/.gitted/objects/bf/102db0c9c0c1513909a90e0611b5dddfc87c93 b/tests/resources/renames/.gitted/objects/bf/102db0c9c0c1513909a90e0611b5dddfc87c93
new file mode 100644
index 000000000..69ddd683b
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/bf/102db0c9c0c1513909a90e0611b5dddfc87c93
@@ -0,0 +1,2 @@
+x+)JMU042a040031Qpttd83ƒÿ×Ñ–fÓ®œ-°[yéï³ÚËéPi'''†¨Â]»Vï*í
+ÏJ8·øĉ­nPiggg†×›·¯—U=á©«Ÿ”¡vR%bû¹¿ Pi¬º¼:6Ž \ No newline at end of file
diff --git a/tests/resources/renames/.gitted/objects/cc/980ffac5f1393696d4cd703ea9d2fde67dd367 b/tests/resources/renames/.gitted/objects/cc/980ffac5f1393696d4cd703ea9d2fde67dd367
new file mode 100644
index 000000000..ac7a005e6
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/cc/980ffac5f1393696d4cd703ea9d2fde67dd367
Binary files differ
diff --git a/tests/resources/renames/.gitted/objects/db/98035f715427eef1f5e17f03e1801c05301e9e b/tests/resources/renames/.gitted/objects/db/98035f715427eef1f5e17f03e1801c05301e9e
new file mode 100644
index 000000000..48bc2e186
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/db/98035f715427eef1f5e17f03e1801c05301e9e
Binary files differ
diff --git a/tests/resources/renames/.gitted/objects/eb/b3b7af1d25c8492d2f626826c92458b7cefd60 b/tests/resources/renames/.gitted/objects/eb/b3b7af1d25c8492d2f626826c92458b7cefd60
new file mode 100644
index 000000000..813e7ad90
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/eb/b3b7af1d25c8492d2f626826c92458b7cefd60
Binary files differ
diff --git a/tests/resources/renames/.gitted/objects/ed/2a95c4a6c295b9afcea50baff63ec544ccf600 b/tests/resources/renames/.gitted/objects/ed/2a95c4a6c295b9afcea50baff63ec544ccf600
new file mode 100644
index 000000000..4f439e293
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/ed/2a95c4a6c295b9afcea50baff63ec544ccf600
Binary files differ
diff --git a/tests/resources/renames/.gitted/objects/f6/7e2f70efe89665e829ea0d77c46965ad1307e4 b/tests/resources/renames/.gitted/objects/f6/7e2f70efe89665e829ea0d77c46965ad1307e4
new file mode 100644
index 000000000..1cad2134d
--- /dev/null
+++ b/tests/resources/renames/.gitted/objects/f6/7e2f70efe89665e829ea0d77c46965ad1307e4
Binary files differ
diff --git a/tests/resources/renames/.gitted/refs/heads/break_rewrite b/tests/resources/renames/.gitted/refs/heads/break_rewrite
new file mode 100644
index 000000000..d170915c1
--- /dev/null
+++ b/tests/resources/renames/.gitted/refs/heads/break_rewrite
@@ -0,0 +1 @@
+7e7bfb88ba9bc65fd700fee1819cf1c317aafa56
diff --git a/tests/resources/revert-rename.git/HEAD b/tests/resources/revert-rename.git/HEAD
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/tests/resources/revert-rename.git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/revert-rename.git/config b/tests/resources/revert-rename.git/config
new file mode 100644
index 000000000..a4ef456cb
--- /dev/null
+++ b/tests/resources/revert-rename.git/config
@@ -0,0 +1,5 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = true
+ logallrefupdates = true
diff --git a/tests/resources/revert-rename.git/index b/tests/resources/revert-rename.git/index
new file mode 100644
index 000000000..232325dfb
--- /dev/null
+++ b/tests/resources/revert-rename.git/index
Binary files differ
diff --git a/tests/resources/revert-rename.git/objects/info/packs b/tests/resources/revert-rename.git/objects/info/packs
new file mode 100644
index 000000000..5d971426e
--- /dev/null
+++ b/tests/resources/revert-rename.git/objects/info/packs
@@ -0,0 +1,2 @@
+P pack-4363774fb90141e8aa7a326ace0566366114e869.pack
+
diff --git a/tests/resources/revert-rename.git/objects/pack/pack-4363774fb90141e8aa7a326ace0566366114e869.idx b/tests/resources/revert-rename.git/objects/pack/pack-4363774fb90141e8aa7a326ace0566366114e869.idx
new file mode 100644
index 000000000..3fb48ea94
--- /dev/null
+++ b/tests/resources/revert-rename.git/objects/pack/pack-4363774fb90141e8aa7a326ace0566366114e869.idx
Binary files differ
diff --git a/tests/resources/revert-rename.git/objects/pack/pack-4363774fb90141e8aa7a326ace0566366114e869.pack b/tests/resources/revert-rename.git/objects/pack/pack-4363774fb90141e8aa7a326ace0566366114e869.pack
new file mode 100644
index 000000000..e078ec2aa
--- /dev/null
+++ b/tests/resources/revert-rename.git/objects/pack/pack-4363774fb90141e8aa7a326ace0566366114e869.pack
Binary files differ
diff --git a/tests/resources/revert-rename.git/packed-refs b/tests/resources/revert-rename.git/packed-refs
new file mode 100644
index 000000000..e062909d4
--- /dev/null
+++ b/tests/resources/revert-rename.git/packed-refs
@@ -0,0 +1,2 @@
+# pack-refs with: peeled fully-peeled sorted
+ecef6a85173b6f446873a13f7b5a7b54a85cd912 refs/heads/master
diff --git a/tests/resources/revert-rename.git/refs/heads/master b/tests/resources/revert-rename.git/refs/heads/master
new file mode 100644
index 000000000..3771102fb
--- /dev/null
+++ b/tests/resources/revert-rename.git/refs/heads/master
@@ -0,0 +1 @@
+ecef6a85173b6f446873a13f7b5a7b54a85cd912
diff --git a/tests/resources/self-signed.pem b/tests/resources/self-signed.pem
new file mode 100644
index 000000000..e13417e48
--- /dev/null
+++ b/tests/resources/self-signed.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjsCFAb11im6DYQyGJ0GNQCIehXtegq6MA0GCSqGSIb3DQEBCwUAMGYx
+CzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlD
+YW1icmlkZ2UxEDAOBgNVBAoMB2xpYmdpdDIxGTAXBgNVBAMMEHRlc3QubGliZ2l0
+Mi5vcmcwHhcNMjEwODMwMDAyMTQyWhcNMzEwODI4MDAyMTQyWjBmMQswCQYDVQQG
+EwJVUzEWMBQGA1UECAwNTWFzc2FjaHVzZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdl
+MRAwDgYDVQQKDAdsaWJnaXQyMRkwFwYDVQQDDBB0ZXN0LmxpYmdpdDIub3JnMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtqe6b1vnMni+z8Z+a2bGtykI
+ITvBged15rn+0qG6Fz+sn9bYG+ceFupztFfoN3cVpUgQDBTzr3CaAx036BlV0z8i
+CrG0Oh/XGL+9TITQLumEe4iGi8NoMSujBAyXPSNgmpzDmCTGrNFfmq3HzUtO8t3x
+i8OT7d9qCVjFimLvZbgnfHGQ38xvt1XyPgYIVqDQczmMEZ5BdYWB0A1VmnWuP2dH
+BgjwPEC3HwMmm1+PL0VoPTdvE5Su092Qdt8QsiA56466DQyll1d/omnOJfrK7z0N
+OnfDmnDpARSTy6vDofEAYUQoc3dyvBUk8IIzv2UDcR7fTVvYqseQReIOTEnXmQID
+AQABMA0GCSqGSIb3DQEBCwUAA4IBAQBmUEq+JhwWTbB5ODGOKrMG1fKJ+sf6ZH6M
+c4BgLEcdoi/nOTfPuw+ols72LuhH7NKaEcqxWev0jGF0WKqMcM8AGVbywZJ3mBWo
+sKdh6rAGFNkikW4TzhjtDfFbMR45Didl28Be7ieHQL4CQ0Lse3RMOxp250WpiEYV
+W2hIKMwIqOLKGShVD7lI+eHlv+QSH4yOYKHfRHve8s82Tac5OXinc8CJm9ySOtkO
+MfLgfkHtHdFBnV6OVbf4p/596MfMXdwT/bBxT6WPkDGc1AYhoDlmLFTpRgHIDCSK
+2wgV+qHppl7Kn+p3mFQ9sW/1IaRd+jNZOrgZ8Uu5tJ00OaqR/LVG
+-----END CERTIFICATE-----
diff --git a/tests/resources/testrepo.git/objects/info/commit-graph b/tests/resources/testrepo.git/objects/info/commit-graph
new file mode 100644
index 000000000..2ef31d83e
--- /dev/null
+++ b/tests/resources/testrepo.git/objects/info/commit-graph
Binary files differ
diff --git a/tests/resources/testrepo.git/objects/pack/multi-pack-index b/tests/resources/testrepo.git/objects/pack/multi-pack-index
new file mode 100644
index 000000000..95102aeb4
--- /dev/null
+++ b/tests/resources/testrepo.git/objects/pack/multi-pack-index
Binary files differ
diff --git a/tests/revert/rename.c b/tests/revert/rename.c
new file mode 100644
index 000000000..0d713c60f
--- /dev/null
+++ b/tests/revert/rename.c
@@ -0,0 +1,49 @@
+#include "clar.h"
+#include "clar_libgit2.h"
+
+#include "git2/revert.h"
+#include "../merge/merge_helpers.h"
+
+#define TEST_REPO_PATH "revert-rename.git"
+
+static git_repository *repo;
+
+/* Fixture setup and teardown */
+void test_revert_rename__initialize(void)
+{
+ repo = cl_git_sandbox_init(TEST_REPO_PATH);
+}
+
+void test_revert_rename__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+/* Attempt a revert when there is a file rename AND change of file mode,
+ * but the file contents remain the same. Check that the file mode doesn't
+ * change following the revert.
+ */
+void test_revert_rename__automerge(void)
+{
+ git_commit *head_commit, *revert_commit;
+ git_oid revert_oid;
+ git_index *index;
+ git_reference *head_ref;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "f0f64c618e1646d2948a456ed7c4bcfad5536d68", 0, "goodmode" }};
+
+ cl_git_pass(git_repository_head(&head_ref, repo));
+ cl_git_pass(git_reference_peel((git_object **)&head_commit, head_ref, GIT_OBJECT_COMMIT));
+
+ cl_git_pass(git_oid_fromstr(&revert_oid, "7b4d7c3789b3581973c04087cb774c3c3576de2f"));
+ cl_git_pass(git_commit_lookup(&revert_commit, repo, &revert_oid));
+
+ cl_git_pass(git_revert_commit(&index, repo, revert_commit, head_commit, 0, NULL));
+ cl_assert(merge_test_index(index, merge_index_entries, 1));
+
+ git_commit_free(revert_commit);
+ git_commit_free(head_commit);
+ git_index_free(index);
+ git_reference_free(head_ref);
+}
diff --git a/tests/revwalk/basic.c b/tests/revwalk/basic.c
index ee70ec635..2c8d885e2 100644
--- a/tests/revwalk/basic.c
+++ b/tests/revwalk/basic.c
@@ -530,7 +530,7 @@ void test_revwalk_basic__big_timestamp(void)
cl_git_pass(git_reference_peel((git_object **) &tip, head, GIT_OBJECT_COMMIT));
/* Commit with a far-ahead timestamp, we should be able to parse it in the revwalk */
- cl_git_pass(git_signature_new(&sig, "Joe", "joe@example.com", 2399662595ll, 0));
+ cl_git_pass(git_signature_new(&sig, "Joe", "joe@example.com", INT64_C(2399662595), 0));
cl_git_pass(git_commit_tree(&tree, tip));
cl_git_pass(git_commit_create(&id, _repo, "HEAD", sig, sig, NULL, "some message", tree, 1,
diff --git a/tests/revwalk/mergebase.c b/tests/revwalk/mergebase.c
index bee0b926e..0378c869b 100644
--- a/tests/revwalk/mergebase.c
+++ b/tests/revwalk/mergebase.c
@@ -150,7 +150,7 @@ void test_revwalk_mergebase__multiple_merge_bases(void)
cl_assert_equal_oid(&expected1, &result.ids[0]);
cl_assert_equal_oid(&expected2, &result.ids[1]);
- git_oidarray_free(&result);
+ git_oidarray_dispose(&result);
}
void test_revwalk_mergebase__multiple_merge_bases_many_commits(void)
@@ -170,7 +170,7 @@ void test_revwalk_mergebase__multiple_merge_bases_many_commits(void)
cl_assert_equal_oid(&expected1, &result.ids[0]);
cl_assert_equal_oid(&expected2, &result.ids[1]);
- git_oidarray_free(&result);
+ git_oidarray_dispose(&result);
git__free(input);
}
@@ -186,7 +186,7 @@ void test_revwalk_mergebase__no_off_by_one_missing(void)
static void assert_mergebase_many(const char *expected_sha, int count, ...)
{
va_list ap;
- int i;
+ int i;
git_oid *oids;
git_oid oid, expected;
char *partial_oid;
@@ -376,9 +376,9 @@ void test_revwalk_mergebase__octopus_merge_branch(void)
* * commit 8496071c1b46c854b31185ea97743be6a8774479
* Author: Scott Chacon <schacon@gmail.com>
* Date: Sat May 8 16:13:06 2010 -0700
- *
+ *
* testing
- *
+ *
* * commit 41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9
* | Author: Scott Chacon <schacon@gmail.com>
* | Date: Tue May 11 13:40:41 2010 -0700
@@ -388,7 +388,7 @@ void test_revwalk_mergebase__octopus_merge_branch(void)
* * commit 5001298e0c09ad9c34e4249bc5801c75e9754fa5
* Author: Scott Chacon <schacon@gmail.com>
* Date: Tue May 11 13:40:23 2010 -0700
- *
+ *
* packed commit one
*/
@@ -398,94 +398,94 @@ void test_revwalk_mergebase__octopus_merge_branch(void)
* |\ Merge: c37a783 2224e19
* | | Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 20:31:04 2012 -0800
- * | |
+ * | |
* | | Merge branch 'first-branch' into second-branch
- * | |
+ * | |
* | * commit 2224e191514cb4bd8c566d80dac22dfcb1e9bb83
* | | Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 20:28:51 2012 -0800
- * | |
+ * | |
* | | j
- * | |
+ * | |
* | * commit a41a49f8f5cd9b6cb14a076bf8394881ed0b4d19
* | | Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 20:28:39 2012 -0800
- * | |
+ * | |
* | | i
- * | |
+ * | |
* | * commit 82bf9a1a10a4b25c1f14c9607b60970705e92545
* | | Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 20:28:28 2012 -0800
- * | |
+ * | |
* | | h
- * | |
+ * | |
* * | commit c37a783c20d92ac92362a78a32860f7eebf938ef
* | | Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 20:30:57 2012 -0800
- * | |
+ * | |
* | | n
- * | |
+ * | |
* * | commit 8b82fb1794cb1c8c7f172ec730a4c2db0ae3e650
* | | Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 20:30:43 2012 -0800
- * | |
+ * | |
* | | m
- * | |
+ * | |
* * | commit 6ab5d28acbf3c3bdff276f7ccfdf29c1520e542f
* | | Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 20:30:38 2012 -0800
- * | |
+ * | |
* | | l
- * | |
+ * | |
* * | commit 7b8c336c45fc6895c1c60827260fe5d798e5d247
* | | Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 20:30:24 2012 -0800
- * | |
+ * | |
* | | k
- * | |
+ * | |
* | | * commit 1c30b88f5f3ee66d78df6520a7de9e89b890818b
* | | | Author: Scott J. Goldman <scottjg@github.com>
* | | | Date: Tue Nov 27 20:28:10 2012 -0800
- * | | |
+ * | | |
* | | | e
- * | | |
+ * | | |
* | | * commit 42b7311aa626e712891940c1ec5d5cba201946a4
* | | | Author: Scott J. Goldman <scottjg@github.com>
* | | | Date: Tue Nov 27 20:28:06 2012 -0800
- * | | |
+ * | | |
* | | | d
- * | | |
+ * | | |
* | | * commit a953a018c5b10b20c86e69fef55ebc8ad4c5a417
* | | |\ Merge: bd1732c cdf97fd
* | | |/ Author: Scott J. Goldman <scottjg@github.com>
* | |/| Date: Tue Nov 27 20:26:43 2012 -0800
- * | | |
+ * | | |
* | | | Merge branch 'first-branch'
- * | | |
+ * | | |
* | * | commit cdf97fd3bb48eb3827638bb33d208f5fd32d0aa6
* | | | Author: Scott J. Goldman <scottjg@github.com>
* | | | Date: Tue Nov 27 20:24:46 2012 -0800
- * | | |
+ * | | |
* | | | g
- * | | |
+ * | | |
* | * | commit ef0488f0b722f0be8bcb90a7730ac7efafd1d694
* | | | Author: Scott J. Goldman <scottjg@github.com>
* | | | Date: Tue Nov 27 20:24:39 2012 -0800
- * | | |
+ * | | |
* | | | f
- * | | |
+ * | | |
* | | * commit bd1732c43c68d712ad09e1d872b9be6d4b9efdc4
* | |/ Author: Scott J. Goldman <scottjg@github.com>
* | | Date: Tue Nov 27 17:43:58 2012 -0800
- * | |
+ * | |
* | | c
- * | |
+ * | |
* | * commit 0c8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29
* |/ Author: Scott J. Goldman <scottjg@github.com>
* | Date: Tue Nov 27 17:43:48 2012 -0800
- * |
+ * |
* | b
- * |
+ * |
* * commit 1f4c0311a24b63f6fc209a59a1e404942d4a5006
* Author: Scott J. Goldman <scottjg@github.com>
* Date: Tue Nov 27 17:43:41 2012 -0800
@@ -509,6 +509,6 @@ void test_revwalk_mergebase__remove_redundant(void)
cl_assert_equal_i(1, result.count);
cl_assert_equal_oid(&base, &result.ids[0]);
- git_oidarray_free(&result);
+ git_oidarray_dispose(&result);
git_repository_free(repo);
}
diff --git a/tests/status/worktree.c b/tests/status/worktree.c
index 7711b2da4..d9fce4404 100644
--- a/tests/status/worktree.c
+++ b/tests/status/worktree.c
@@ -605,6 +605,45 @@ void test_status_worktree__filemode_changes(void)
cl_assert_equal_i(0, counts.wrong_sorted_path);
}
+void test_status_worktree__filemode_non755(void)
+{
+ git_repository *repo = cl_git_sandbox_init("filemodes");
+ status_entry_counts counts;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+ git_buf executable_path = GIT_BUF_INIT;
+ git_buf nonexecutable_path = GIT_BUF_INIT;
+
+ if (!cl_is_chmod_supported())
+ return;
+
+ opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
+ GIT_STATUS_OPT_INCLUDE_IGNORED |
+ GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
+
+ git_buf_joinpath(&executable_path, git_repository_workdir(repo), "exec_on");
+ cl_must_pass(p_chmod(git_buf_cstr(&executable_path), 0744));
+ git_buf_dispose(&executable_path);
+
+ git_buf_joinpath(&nonexecutable_path, git_repository_workdir(repo), "exec_off");
+
+ cl_must_pass(p_chmod(git_buf_cstr(&nonexecutable_path), 0655));
+ git_buf_dispose(&nonexecutable_path);
+
+ memset(&counts, 0, sizeof(counts));
+ counts.expected_entry_count = filemode_count;
+ counts.expected_paths = filemode_paths;
+ counts.expected_statuses = filemode_statuses;
+
+ cl_git_pass(
+ git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)
+ );
+
+ cl_assert_equal_i(counts.expected_entry_count, counts.entry_count);
+ cl_assert_equal_i(0, counts.wrong_status_flags_count);
+ cl_assert_equal_i(0, counts.wrong_sorted_path);
+}
+
+
static int cb_status__interrupt(const char *p, unsigned int s, void *payload)
{
volatile int *count = (int *)payload;
@@ -949,7 +988,7 @@ void test_status_worktree__sorting_by_case(void)
void test_status_worktree__long_filenames(void)
{
- char path[260*4+1];
+ char path[260*4+1] = {0};
const char *expected_paths[] = {path};
const unsigned int expected_statuses[] = {GIT_STATUS_WT_NEW};
diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c
index 6f7506d2c..f49ebb4bd 100644
--- a/tests/submodule/lookup.c
+++ b/tests/submodule/lookup.c
@@ -42,6 +42,46 @@ void test_submodule_lookup__simple_lookup(void)
assert_submodule_exists(g_repo, "sm_added_and_uncommited/");
}
+void test_submodule_lookup__can_be_dupped(void)
+{
+ git_submodule *sm;
+ git_submodule *sm_duplicate;
+ const char *oid = "480095882d281ed676fe5b863569520e54a7d5c0";
+
+ /* Check original */
+ cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
+ cl_assert(git_submodule_owner(sm) == g_repo);
+ cl_assert_equal_s("sm_unchanged", git_submodule_name(sm));
+ cl_assert(git__suffixcmp(git_submodule_path(sm), "sm_unchanged") == 0);
+ cl_assert(git__suffixcmp(git_submodule_url(sm), "/submod2_target") == 0);
+
+ cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0);
+ cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0);
+ cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0);
+
+ cl_assert(git_submodule_ignore(sm) == GIT_SUBMODULE_IGNORE_NONE);
+ cl_assert(git_submodule_update_strategy(sm) == GIT_SUBMODULE_UPDATE_CHECKOUT);
+
+ /* Duplicate and free original */
+ cl_assert(git_submodule_dup(&sm_duplicate, sm) == 0);
+ git_submodule_free(sm);
+
+ /* Check duplicate */
+ cl_assert(git_submodule_owner(sm_duplicate) == g_repo);
+ cl_assert_equal_s("sm_unchanged", git_submodule_name(sm_duplicate));
+ cl_assert(git__suffixcmp(git_submodule_path(sm_duplicate), "sm_unchanged") == 0);
+ cl_assert(git__suffixcmp(git_submodule_url(sm_duplicate), "/submod2_target") == 0);
+
+ cl_assert(git_oid_streq(git_submodule_index_id(sm_duplicate), oid) == 0);
+ cl_assert(git_oid_streq(git_submodule_head_id(sm_duplicate), oid) == 0);
+ cl_assert(git_oid_streq(git_submodule_wd_id(sm_duplicate), oid) == 0);
+
+ cl_assert(git_submodule_ignore(sm_duplicate) == GIT_SUBMODULE_IGNORE_NONE);
+ cl_assert(git_submodule_update_strategy(sm_duplicate) == GIT_SUBMODULE_UPDATE_CHECKOUT);
+
+ git_submodule_free(sm_duplicate);
+}
+
void test_submodule_lookup__accessors(void)
{
git_submodule *sm;
diff --git a/tests/threads/atomic.c b/tests/threads/atomic.c
new file mode 100644
index 000000000..4d04a777a
--- /dev/null
+++ b/tests/threads/atomic.c
@@ -0,0 +1,125 @@
+#include "clar_libgit2.h"
+
+void test_threads_atomic__atomic32_set(void)
+{
+ git_atomic32 v = {0};
+ git_atomic32_set(&v, 1);
+ cl_assert_equal_i(v.val, 1);
+}
+
+void test_threads_atomic__atomic32_get(void)
+{
+ git_atomic32 v = {1};
+ cl_assert_equal_i(git_atomic32_get(&v), 1);
+}
+
+void test_threads_atomic__atomic32_inc(void)
+{
+ git_atomic32 v = {0};
+ cl_assert_equal_i(git_atomic32_inc(&v), 1);
+ cl_assert_equal_i(v.val, 1);
+}
+
+void test_threads_atomic__atomic32_add(void)
+{
+ git_atomic32 v = {0};
+ cl_assert_equal_i(git_atomic32_add(&v, 1), 1);
+ cl_assert_equal_i(v.val, 1);
+}
+
+void test_threads_atomic__atomic32_dec(void)
+{
+ git_atomic32 v = {1};
+ cl_assert_equal_i(git_atomic32_dec(&v), 0);
+ cl_assert_equal_i(v.val, 0);
+}
+
+void test_threads_atomic__atomic64_set(void)
+{
+#ifndef GIT_ARCH_64
+ cl_skip();
+#else
+ git_atomic64 v = {0};
+ git_atomic64_set(&v, 1);
+ cl_assert_equal_i(v.val, 1);
+#endif
+}
+
+void test_threads_atomic__atomic64_get(void)
+{
+#ifndef GIT_ARCH_64
+ cl_skip();
+#else
+ git_atomic64 v = {1};
+ cl_assert_equal_i(git_atomic64_get(&v), 1);
+#endif
+}
+
+void test_threads_atomic__atomic64_add(void)
+{
+#ifndef GIT_ARCH_64
+ cl_skip();
+#else
+ git_atomic64 v = {0};
+ cl_assert_equal_i(git_atomic64_add(&v, 1), 1);
+ cl_assert_equal_i(v.val, 1);
+#endif
+}
+
+void test_threads_atomic__cas_pointer(void)
+{
+ int *value = NULL;
+ int newvalue1 = 1, newvalue2 = 2;
+
+ /* value is updated */
+ cl_assert_equal_p(git_atomic_compare_and_swap(&value, NULL, &newvalue1), NULL);
+ cl_assert_equal_p(value, &newvalue1);
+
+ /* value is not updated */
+ cl_assert_equal_p(git_atomic_compare_and_swap(&value, NULL, &newvalue2), &newvalue1);
+ cl_assert_equal_p(value, &newvalue1);
+}
+
+void test_threads_atomic__cas_intptr(void)
+{
+ intptr_t value = 0;
+ intptr_t oldvalue;
+ intptr_t newvalue;
+
+ /* value is updated */
+ oldvalue = 0;
+ newvalue = 1;
+ cl_assert_equal_i((intptr_t)git_atomic_compare_and_swap(&value, (void *)oldvalue, (void *)newvalue), 0);
+ cl_assert_equal_i(value, 1);
+
+ /* value is not updated */
+ oldvalue = 0;
+ newvalue = 2;
+ cl_assert_equal_i((intptr_t)git_atomic_compare_and_swap(&value, (void *)oldvalue, (void *)newvalue), 1);
+ cl_assert_equal_i(value, 1);
+}
+
+void test_threads_atomic__swap(void)
+{
+ int *value = NULL;
+ int newvalue = 1;
+
+ cl_assert_equal_p(git_atomic_swap(value, &newvalue), NULL);
+ cl_assert_equal_p(value, &newvalue);
+
+ cl_assert_equal_p(git_atomic_swap(value, NULL), &newvalue);
+ cl_assert_equal_p(value, NULL);
+}
+
+void test_threads_atomic__load_ptr(void)
+{
+ int value = 1;
+ int *ptr = &value;
+ cl_assert_equal_p(git_atomic_load(ptr), &value);
+}
+
+void test_threads_atomic__load_intptr(void)
+{
+ intptr_t value = 1;
+ cl_assert_equal_i((intptr_t)git_atomic_load(value), 1);
+}
diff --git a/tests/threads/basic.c b/tests/threads/basic.c
index ed4fd2f9b..2d7ddc26b 100644
--- a/tests/threads/basic.c
+++ b/tests/threads/basic.c
@@ -54,6 +54,12 @@ static void *return_normally(void *param)
{
return param;
}
+
+static void *exit_abruptly(void *param)
+{
+ git_thread_exit(param);
+ return NULL;
+}
#endif
void test_threads_basic__exit(void)
@@ -70,7 +76,7 @@ void test_threads_basic__exit(void)
cl_assert_equal_sz(424242, (size_t)result);
/* Ensure that the return value of `git_thread_exit` is returned. */
- cl_git_pass(git_thread_create(&thread, return_normally, (void *)232323));
+ cl_git_pass(git_thread_create(&thread, exit_abruptly, (void *)232323));
cl_git_pass(git_thread_join(&thread, &result));
cl_assert_equal_sz(232323, (size_t)result);
#endif
diff --git a/tests/threads/diff.c b/tests/threads/diff.c
index 699642790..04c8cb97f 100644
--- a/tests/threads/diff.c
+++ b/tests/threads/diff.c
@@ -17,7 +17,7 @@
static git_repository *_repo;
static git_tree *_a, *_b;
-static git_atomic _counts[4];
+static git_atomic32 _counts[4];
static int _check_counts;
#ifdef GIT_WIN32
static int _retries;
@@ -66,10 +66,10 @@ static void free_trees(void)
git_tree_free(_b); _b = NULL;
if (_check_counts) {
- cl_assert_equal_i(288, git_atomic_get(&_counts[0]));
- cl_assert_equal_i(112, git_atomic_get(&_counts[1]));
- cl_assert_equal_i( 80, git_atomic_get(&_counts[2]));
- cl_assert_equal_i( 96, git_atomic_get(&_counts[3]));
+ cl_assert_equal_i(288, git_atomic32_get(&_counts[0]));
+ cl_assert_equal_i(112, git_atomic32_get(&_counts[1]));
+ cl_assert_equal_i( 80, git_atomic32_get(&_counts[2]));
+ cl_assert_equal_i( 96, git_atomic32_get(&_counts[3]));
}
}
@@ -107,14 +107,14 @@ static void *run_index_diffs(void *arg)
/* keep some diff stats to make sure results are as expected */
i = git_diff_num_deltas(diff);
- git_atomic_add(&_counts[0], (int32_t)i);
+ git_atomic32_add(&_counts[0], (int32_t)i);
exp[0] = (int)i;
while (i > 0) {
switch (git_diff_get_delta(diff, --i)->status) {
- case GIT_DELTA_MODIFIED: exp[1]++; git_atomic_inc(&_counts[1]); break;
- case GIT_DELTA_ADDED: exp[2]++; git_atomic_inc(&_counts[2]); break;
- case GIT_DELTA_DELETED: exp[3]++; git_atomic_inc(&_counts[3]); break;
+ case GIT_DELTA_MODIFIED: exp[1]++; git_atomic32_inc(&_counts[1]); break;
+ case GIT_DELTA_ADDED: exp[2]++; git_atomic32_inc(&_counts[2]); break;
+ case GIT_DELTA_DELETED: exp[3]++; git_atomic32_inc(&_counts[3]); break;
default: break;
}
}
diff --git a/tests/threads/thread_helpers.h b/tests/threads/thread_helpers.h
index 3c13cfb6b..0f23a4ce0 100644
--- a/tests/threads/thread_helpers.h
+++ b/tests/threads/thread_helpers.h
@@ -1,4 +1,4 @@
-#include "thread-utils.h"
+#include "thread.h"
void run_in_parallel(
int repeats,
diff --git a/tests/threads/tlsdata.c b/tests/threads/tlsdata.c
new file mode 100644
index 000000000..7c69b4444
--- /dev/null
+++ b/tests/threads/tlsdata.c
@@ -0,0 +1,65 @@
+#include "clar_libgit2.h"
+
+#include "thread_helpers.h"
+
+void test_threads_tlsdata__can_set_and_get(void)
+{
+ git_tlsdata_key key_one, key_two, key_three;
+
+ cl_git_pass(git_tlsdata_init(&key_one, NULL));
+ cl_git_pass(git_tlsdata_init(&key_two, NULL));
+ cl_git_pass(git_tlsdata_init(&key_three, NULL));
+
+ cl_git_pass(git_tlsdata_set(key_one, (void *)(size_t)42424242));
+ cl_git_pass(git_tlsdata_set(key_two, (void *)(size_t)0xdeadbeef));
+ cl_git_pass(git_tlsdata_set(key_three, (void *)(size_t)98761234));
+
+ cl_assert_equal_sz((size_t)42424242, git_tlsdata_get(key_one));
+ cl_assert_equal_sz((size_t)0xdeadbeef, git_tlsdata_get(key_two));
+ cl_assert_equal_sz((size_t)98761234, git_tlsdata_get(key_three));
+
+ cl_git_pass(git_tlsdata_dispose(key_one));
+ cl_git_pass(git_tlsdata_dispose(key_two));
+ cl_git_pass(git_tlsdata_dispose(key_three));
+}
+
+#ifdef GIT_THREADS
+
+static void *set_and_get(void *param)
+{
+ git_tlsdata_key *tlsdata_key = (git_tlsdata_key *)param;
+ int val;
+
+ if (git_tlsdata_set(*tlsdata_key, &val) != 0 ||
+ git_tlsdata_get(*tlsdata_key) != &val)
+ return (void *)0;
+
+ return (void *)1;
+}
+
+#endif
+
+#define THREAD_COUNT 10
+
+void test_threads_tlsdata__threads(void)
+{
+#ifdef GIT_THREADS
+ git_thread thread[THREAD_COUNT];
+ git_tlsdata_key tlsdata;
+ int i;
+
+ cl_git_pass(git_tlsdata_init(&tlsdata, NULL));
+
+ for (i = 0; i < THREAD_COUNT; i++)
+ cl_git_pass(git_thread_create(&thread[i], set_and_get, &tlsdata));
+
+ for (i = 0; i < THREAD_COUNT; i++) {
+ void *result;
+
+ cl_git_pass(git_thread_join(&thread[i], &result));
+ cl_assert_equal_sz(1, (size_t)result);
+ }
+
+ cl_git_pass(git_tlsdata_dispose(tlsdata));
+#endif
+}
diff --git a/tests/trace/windows/stacktrace.c b/tests/trace/windows/stacktrace.c
index 756ac68a3..0a77ef99d 100644
--- a/tests/trace/windows/stacktrace.c
+++ b/tests/trace/windows/stacktrace.c
@@ -1,13 +1,12 @@
#include "clar_libgit2.h"
-#include "win32/w32_stack.h"
-#include "win32/w32_crtdbg_stacktrace.h"
+#include "win32/w32_leakcheck.h"
-#if defined(GIT_MSVC_CRTDBG)
+#if defined(GIT_WIN32_LEAKCHECK)
static void a(void)
{
char buf[10000];
- cl_assert(git_win32__stack(buf, sizeof(buf), 0, NULL, NULL) == 0);
+ cl_assert(git_win32_leakcheck_stack(buf, sizeof(buf), 0, NULL, NULL) == 0);
#if 0
fprintf(stderr, "Stacktrace from [%s:%d]:\n%s\n", __FILE__, __LINE__, buf);
@@ -27,7 +26,7 @@ static void c(void)
void test_trace_windows_stacktrace__basic(void)
{
-#if defined(GIT_MSVC_CRTDBG)
+#if defined(GIT_WIN32_LEAKCHECK)
c();
#endif
}
@@ -35,7 +34,7 @@ void test_trace_windows_stacktrace__basic(void)
void test_trace_windows_stacktrace__leaks(void)
{
-#if defined(GIT_MSVC_CRTDBG)
+#if defined(GIT_WIN32_LEAKCHECK)
void * p1;
void * p2;
void * p3;
@@ -47,84 +46,85 @@ void test_trace_windows_stacktrace__leaks(void)
/* remember outstanding leaks due to set setup
* and set mark/checkpoint.
*/
- before = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_TOTAL |
- GIT_WIN32__CRTDBG_STACKTRACE__SET_MARK,
+ before = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_TOTAL |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_SET_MARK,
NULL);
p1 = git__malloc(5);
- leaks = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK,
+ leaks = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK,
"p1");
- cl_assert((leaks == 1));
+ cl_assert_equal_i(1, leaks);
p2 = git__malloc(5);
- leaks = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK,
+ leaks = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK,
"p1,p2");
- cl_assert((leaks == 2));
+ cl_assert_equal_i(2, leaks);
p3 = git__malloc(5);
- leaks = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK,
+ leaks = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK,
"p1,p2,p3");
- cl_assert((leaks == 3));
+ cl_assert_equal_i(3, leaks);
git__free(p2);
- leaks = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK,
+ leaks = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK,
"p1,p3");
- cl_assert((leaks == 2));
+ cl_assert_equal_i(2, leaks);
/* move the mark. only new leaks should appear afterwards */
- error = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__SET_MARK,
+ error = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_SET_MARK,
NULL);
- cl_assert((error == 0));
+ /* cannot use cl_git_pass() since that may allocate memory. */
+ cl_assert_equal_i(0, error);
- leaks = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK,
+ leaks = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK,
"not_p1,not_p3");
- cl_assert((leaks == 0));
+ cl_assert_equal_i(0, leaks);
p4 = git__malloc(5);
- leaks = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK,
+ leaks = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK,
"p4,not_p1,not_p3");
- cl_assert((leaks == 1));
+ cl_assert_equal_i(1, leaks);
git__free(p1);
git__free(p3);
- leaks = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK,
+ leaks = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK,
"p4");
- cl_assert((leaks == 1));
+ cl_assert_equal_i(1, leaks);
git__free(p4);
- leaks = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK,
+ leaks = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_SINCE_MARK,
"end");
- cl_assert((leaks == 0));
+ cl_assert_equal_i(0, leaks);
/* confirm current absolute leaks count matches beginning value. */
- after = git_win32__crtdbg_stacktrace__dump(
- GIT_WIN32__CRTDBG_STACKTRACE__QUIET |
- GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_TOTAL,
+ after = git_win32_leakcheck_stacktrace_dump(
+ GIT_WIN32_LEAKCHECK_STACKTRACE_QUIET |
+ GIT_WIN32_LEAKCHECK_STACKTRACE_LEAKS_TOTAL,
"total");
- cl_assert((before == after));
+ cl_assert_equal_i(before, after);
#endif
}
-#if defined(GIT_MSVC_CRTDBG)
+#if defined(GIT_WIN32_LEAKCHECK)
static void aux_cb_alloc__1(unsigned int *aux_id)
{
static unsigned int aux_counter = 0;
@@ -141,12 +141,12 @@ static void aux_cb_lookup__1(unsigned int aux_id, char *aux_msg, size_t aux_msg_
void test_trace_windows_stacktrace__aux1(void)
{
-#if defined(GIT_MSVC_CRTDBG)
- git_win32__stack__set_aux_cb(aux_cb_alloc__1, aux_cb_lookup__1);
+#if defined(GIT_WIN32_LEAKCHECK)
+ git_win32_leakcheck_stack_set_aux_cb(aux_cb_alloc__1, aux_cb_lookup__1);
c();
c();
c();
c();
- git_win32__stack__set_aux_cb(NULL, NULL);
+ git_win32_leakcheck_stack_set_aux_cb(NULL, NULL);
#endif
}
diff --git a/tests/win32/longpath.c b/tests/win32/longpath.c
index 80ae08d8b..f8b8c4b0a 100644
--- a/tests/win32/longpath.c
+++ b/tests/win32/longpath.c
@@ -4,9 +4,12 @@
#include "clone.h"
#include "buffer.h"
#include "futils.h"
+#include "repository.h"
static git_buf path = GIT_BUF_INIT;
+#define LONG_FILENAME "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt"
+
void test_win32_longpath__initialize(void)
{
#ifdef GIT_WIN32
@@ -29,34 +32,100 @@ void test_win32_longpath__initialize(void)
void test_win32_longpath__cleanup(void)
{
git_buf_dispose(&path);
+ cl_git_sandbox_cleanup();
}
+void test_win32_longpath__errmsg_on_checkout(void)
+{
#ifdef GIT_WIN32
-void assert_name_too_long(void)
+ git_repository *repo;
+
+ cl_git_fail(git_clone(&repo, cl_fixture("testrepo.git"), path.ptr, NULL));
+ cl_assert(git__prefixcmp(git_error_last()->message, "path too long") == 0);
+#endif
+}
+
+void test_win32_longpath__workdir_path_validated(void)
{
- const git_error *err;
- size_t expected_len, actual_len;
- char *expected_msg;
+#ifdef GIT_WIN32
+ git_repository *repo = cl_git_sandbox_init("testrepo");
+ git_buf out = GIT_BUF_INIT;
+
+ cl_git_pass(git_repository_workdir_path(&out, repo, "a.txt"));
+
+ /* even if the repo path is a drive letter, this is too long */
+ cl_git_fail(git_repository_workdir_path(&out, repo, LONG_FILENAME));
+ cl_assert(git__prefixcmp(git_error_last()->message, "path too long") == 0);
- err = git_error_last();
- actual_len = strlen(err->message);
+ cl_repo_set_bool(repo, "core.longpaths", true);
+ cl_git_pass(git_repository_workdir_path(&out, repo, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt"));
+ cl_git_pass(git_repository_workdir_path(&out, repo, LONG_FILENAME));
+ git_buf_dispose(&out);
+#endif
+}
+
+#ifdef GIT_WIN32
+static void assert_longpath_status_and_add(git_repository *repo, const char *wddata, const char *repodata) {
+ git_index *index;
+ git_blob *blob;
+ git_buf out = GIT_BUF_INIT;
+ const git_index_entry *entry;
+ unsigned int status_flags;
- expected_msg = git_win32_get_error_message(ERROR_FILENAME_EXCED_RANGE);
- expected_len = strlen(expected_msg);
+ cl_git_pass(git_repository_workdir_path(&out, repo, LONG_FILENAME));
- /* check the suffix */
- cl_assert_equal_s(expected_msg, err->message + (actual_len - expected_len));
+ cl_git_rewritefile(out.ptr, wddata);
- git__free(expected_msg);
+ cl_git_pass(git_status_file(&status_flags, repo, LONG_FILENAME));
+ cl_assert_equal_i(GIT_STATUS_WT_NEW, status_flags);
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_git_pass(git_index_add_bypath(index, LONG_FILENAME));
+
+ cl_git_pass(git_status_file(&status_flags, repo, LONG_FILENAME));
+ cl_assert_equal_i(GIT_STATUS_INDEX_NEW, status_flags);
+
+ cl_assert((entry = git_index_get_bypath(index, LONG_FILENAME, 0)) != NULL);
+ cl_git_pass(git_blob_lookup(&blob, repo, &entry->id));
+ cl_assert_equal_s(repodata, git_blob_rawcontent(blob));
+
+ git_blob_free(blob);
+ git_index_free(index);
+ git_buf_dispose(&out);
}
#endif
-void test_win32_longpath__errmsg_on_checkout(void)
+void test_win32_longpath__status_and_add(void)
{
#ifdef GIT_WIN32
- git_repository *repo;
+ git_repository *repo = cl_git_sandbox_init("testrepo");
- cl_git_fail(git_clone(&repo, cl_fixture("testrepo.git"), path.ptr, NULL));
- assert_name_too_long();
+ cl_repo_set_bool(repo, "core.longpaths", true);
+
+ /*
+ * Doing no content filtering, we expect the data we add
+ * to be the data in the repository.
+ */
+ assert_longpath_status_and_add(repo,
+ "This is a long path.\r\n",
+ "This is a long path.\r\n");
+#endif
+}
+
+void test_win32_longpath__status_and_add_with_filter(void)
+{
+#ifdef GIT_WIN32
+ git_repository *repo = cl_git_sandbox_init("testrepo");
+
+ cl_repo_set_bool(repo, "core.longpaths", true);
+ cl_repo_set_bool(repo, "core.autocrlf", true);
+
+ /*
+ * With `core.autocrlf`, we expect the data we add to have
+ * newline conversion performed.
+ */
+ assert_longpath_status_and_add(repo,
+ "This is a long path.\r\n",
+ "This is a long path.\n");
#endif
}
diff --git a/tests/worktree/merge.c b/tests/worktree/merge.c
index 4b743829c..2a1206032 100644
--- a/tests/worktree/merge.c
+++ b/tests/worktree/merge.c
@@ -70,9 +70,9 @@ void test_worktree_merge__merge_setup(void)
ours, (const git_annotated_commit **)&theirs, 1));
for (i = 0; i < ARRAY_SIZE(merge_files); i++) {
- git_buf_clear(&path);
- cl_git_pass(git_buf_printf(&path, "%s/%s",
- fixture.worktree->gitdir, merge_files[i]));
+ cl_git_pass(git_buf_joinpath(&path,
+ fixture.worktree->gitdir,
+ merge_files[i]));
cl_assert(git_path_exists(path.ptr));
}
diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c
index 501255274..27dc667ea 100644
--- a/tests/worktree/refs.c
+++ b/tests/worktree/refs.c
@@ -163,7 +163,10 @@ void test_worktree_refs__renaming_reference_updates_worktree_heads(void)
cl_git_pass(git_branch_lookup(&branch, fixture.repo,
"testrepo-worktree", GIT_BRANCH_LOCAL));
cl_git_pass(git_reference_rename(&renamed, branch, "refs/heads/renamed", 0, NULL));
- cl_git_pass(git_repository_head(&head, fixture.worktree));
+
+ cl_git_pass(git_reference_lookup(&head, fixture.worktree, GIT_HEAD_FILE));
+ cl_assert_equal_i(git_reference_type(head), GIT_REFERENCE_SYMBOLIC);
+ cl_assert_equal_s(git_reference_symbolic_target(head), "refs/heads/renamed");
git_reference_free(head);
git_reference_free(branch);
diff --git a/tests/worktree/repository.c b/tests/worktree/repository.c
index ca56413b7..c4eeadd35 100644
--- a/tests/worktree/repository.c
+++ b/tests/worktree/repository.c
@@ -50,9 +50,12 @@ void test_worktree_repository__head_detached(void)
cl_assert(git_repository_head_detached(fixture.worktree));
cl_assert(git_repository_head_detached_for_worktree(fixture.repo, "testrepo-worktree"));
- cl_git_fail(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree"));
+ cl_git_pass(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree"));
+
+ cl_assert_equal_oid(&ref->target.oid, &head->target.oid);
git_reference_free(ref);
+ git_reference_free(head);
}
void test_worktree_repository__head_detached_fails_for_invalid_worktree(void)
diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c
index 716d0aa0a..9b87bfae6 100644
--- a/tests/worktree/worktree.c
+++ b/tests/worktree/worktree.c
@@ -44,8 +44,9 @@ void test_worktree_worktree__list_with_invalid_worktree_dirs(void)
git_strarray wts;
size_t i, j, len;
- cl_git_pass(git_buf_printf(&path, "%s/worktrees/invalid",
- fixture.repo->commondir));
+ cl_git_pass(git_buf_joinpath(&path,
+ fixture.repo->commondir,
+ "worktrees/invalid"));
cl_git_pass(p_mkdir(path.ptr, 0755));
len = path.size;
@@ -145,9 +146,9 @@ void test_worktree_worktree__open_invalid_commondir(void)
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/commondir"));
- cl_git_pass(git_buf_printf(&path,
- "%s/worktrees/testrepo-worktree/commondir",
- fixture.repo->commondir));
+ cl_git_pass(git_buf_joinpath(&path,
+ fixture.repo->commondir,
+ "worktrees/testrepo-worktree/commondir"));
cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644));
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
@@ -165,9 +166,9 @@ void test_worktree_worktree__open_invalid_gitdir(void)
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/gitdir"));
- cl_git_pass(git_buf_printf(&path,
- "%s/worktrees/testrepo-worktree/gitdir",
- fixture.repo->commondir));
+ cl_git_pass(git_buf_joinpath(&path,
+ fixture.repo->commondir,
+ "worktrees/testrepo-worktree/gitdir"));
cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644));
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
@@ -581,45 +582,44 @@ void test_worktree_worktree__prune_worktree(void)
git_worktree_free(wt);
}
-static int read_head_ref(git_repository *repo, const char *path, void *payload)
+static int foreach_worktree_cb(git_repository *worktree, void *payload)
{
- git_vector *refs = (git_vector *) payload;
- git_reference *head;
+ int *counter = (int *)payload;
- GIT_UNUSED(repo);
-
- cl_git_pass(git_reference__read_head(&head, repo, path));
+ switch (*counter) {
+ case 0:
+ cl_assert_equal_s(git_repository_path(fixture.repo),
+ git_repository_path(worktree));
+ cl_assert(!git_repository_is_worktree(worktree));
+ break;
+ case 1:
+ cl_assert_equal_s(git_repository_path(fixture.worktree),
+ git_repository_path(worktree));
+ cl_assert(git_repository_is_worktree(worktree));
+ break;
+ default:
+ cl_fail("more worktrees found than expected");
+ }
- git_vector_insert(refs, head);
+ (*counter)++;
return 0;
}
-void test_worktree_worktree__foreach_head_gives_same_results_in_wt_and_repo(void)
+void test_worktree_worktree__foreach_worktree_lists_all_worktrees(void)
{
- git_vector repo_refs = GIT_VECTOR_INIT, worktree_refs = GIT_VECTOR_INIT;
- git_reference *heads[2];
- size_t i;
-
- cl_git_pass(git_reference_lookup(&heads[0], fixture.repo, GIT_HEAD_FILE));
- cl_git_pass(git_reference_lookup(&heads[1], fixture.worktree, GIT_HEAD_FILE));
-
- cl_git_pass(git_repository_foreach_head(fixture.repo, read_head_ref, 0, &repo_refs));
- cl_git_pass(git_repository_foreach_head(fixture.worktree, read_head_ref, 0, &worktree_refs));
-
- cl_assert_equal_i(repo_refs.length, ARRAY_SIZE(heads));
- cl_assert_equal_i(worktree_refs.length, ARRAY_SIZE(heads));
+ int counter = 0;
+ cl_git_pass(git_repository_foreach_worktree(fixture.repo, foreach_worktree_cb, &counter));
+}
- for (i = 0; i < ARRAY_SIZE(heads); i++) {
- cl_assert_equal_s(heads[i]->name, ((git_reference *) repo_refs.contents[i])->name);
- cl_assert_equal_s(heads[i]->name, ((git_reference *) repo_refs.contents[i])->name);
- cl_assert_equal_s(heads[i]->name, ((git_reference *) worktree_refs.contents[i])->name);
+void test_worktree_worktree__validate_invalid_worktreedir(void)
+{
+ git_worktree *wt;
- git_reference_free(heads[i]);
- git_reference_free(repo_refs.contents[i]);
- git_reference_free(worktree_refs.contents[i]);
- }
+ cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
+ p_rename("testrepo-worktree", "testrepo-worktree-tmp");
+ cl_git_fail(git_worktree_validate(wt));
+ p_rename("testrepo-worktree-tmp", "testrepo-worktree");
- git_vector_free(&repo_refs);
- git_vector_free(&worktree_refs);
+ git_worktree_free(wt);
}