summaryrefslogtreecommitdiffstats
path: root/vendor/gix
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix')
-rw-r--r--vendor/gix/.cargo-checksum.json2
-rw-r--r--vendor/gix/CHANGELOG.md835
-rw-r--r--vendor/gix/Cargo.lock1181
-rw-r--r--vendor/gix/Cargo.toml240
-rw-r--r--vendor/gix/src/assets/baseline-init/description1
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/applypatch-msg.sample15
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/commit-msg.sample24
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/fsmonitor-watchman.sample173
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/post-update.sample8
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/pre-applypatch.sample14
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/pre-commit.sample49
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/pre-merge-commit.sample13
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/pre-push.sample53
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/pre-rebase.sample169
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/pre-receive.sample24
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/prepare-commit-msg.sample42
-rwxr-xr-xvendor/gix/src/assets/baseline-init/hooks/update.sample128
-rw-r--r--vendor/gix/src/assets/baseline-init/info/exclude6
-rw-r--r--vendor/gix/src/assets/init/HEAD (renamed from vendor/gix/src/assets/baseline-init/HEAD)0
-rw-r--r--vendor/gix/src/assets/init/description1
-rwxr-xr-xvendor/gix/src/assets/init/hooks/applypatch-msg.sample25
-rwxr-xr-xvendor/gix/src/assets/init/hooks/commit-msg.sample25
-rw-r--r--vendor/gix/src/assets/init/hooks/docs.url1
-rwxr-xr-xvendor/gix/src/assets/init/hooks/fsmonitor-watchman.sample16
-rwxr-xr-xvendor/gix/src/assets/init/hooks/post-update.sample12
-rwxr-xr-xvendor/gix/src/assets/init/hooks/pre-applypatch.sample27
-rwxr-xr-xvendor/gix/src/assets/init/hooks/pre-commit.sample19
-rwxr-xr-xvendor/gix/src/assets/init/hooks/pre-merge-commit.sample16
-rwxr-xr-xvendor/gix/src/assets/init/hooks/pre-push.sample46
-rwxr-xr-xvendor/gix/src/assets/init/hooks/pre-rebase.sample40
-rwxr-xr-xvendor/gix/src/assets/init/hooks/prepare-commit-msg.sample54
-rw-r--r--vendor/gix/src/assets/init/info/exclude5
-rw-r--r--vendor/gix/src/attribute_stack.rs69
-rw-r--r--vendor/gix/src/attributes.rs9
-rw-r--r--vendor/gix/src/clone/checkout.rs39
-rw-r--r--vendor/gix/src/clone/fetch/mod.rs21
-rw-r--r--vendor/gix/src/clone/fetch/util.rs12
-rw-r--r--vendor/gix/src/clone/mod.rs31
-rw-r--r--vendor/gix/src/commit.rs17
-rw-r--r--vendor/gix/src/config/cache/access.rs200
-rw-r--r--vendor/gix/src/config/cache/incubate.rs4
-rw-r--r--vendor/gix/src/config/cache/init.rs58
-rw-r--r--vendor/gix/src/config/cache/util.rs36
-rw-r--r--vendor/gix/src/config/mod.rs60
-rw-r--r--vendor/gix/src/config/overrides.rs12
-rw-r--r--vendor/gix/src/config/snapshot/access.rs54
-rw-r--r--vendor/gix/src/config/snapshot/credential_helpers.rs4
-rw-r--r--vendor/gix/src/config/snapshot/mod.rs1
-rw-r--r--vendor/gix/src/config/tree/keys.rs2
-rw-r--r--vendor/gix/src/config/tree/mod.rs8
-rw-r--r--vendor/gix/src/config/tree/sections/core.rs249
-rw-r--r--vendor/gix/src/config/tree/sections/diff.rs21
-rw-r--r--vendor/gix/src/config/tree/sections/fetch.rs81
-rw-r--r--vendor/gix/src/config/tree/sections/gitoxide.rs62
-rw-r--r--vendor/gix/src/config/tree/sections/index.rs5
-rw-r--r--vendor/gix/src/config/tree/sections/mod.rs2
-rw-r--r--vendor/gix/src/config/tree/sections/protocol.rs2
-rw-r--r--vendor/gix/src/create.rs38
-rw-r--r--vendor/gix/src/discover.rs6
-rw-r--r--vendor/gix/src/env.rs3
-rw-r--r--vendor/gix/src/ext/mod.rs4
-rw-r--r--vendor/gix/src/ext/tree.rs24
-rw-r--r--vendor/gix/src/filter.rs229
-rw-r--r--vendor/gix/src/head/mod.rs6
-rw-r--r--vendor/gix/src/id.rs23
-rw-r--r--vendor/gix/src/init.rs5
-rw-r--r--vendor/gix/src/interrupt.rs99
-rw-r--r--vendor/gix/src/lib.rs73
-rw-r--r--vendor/gix/src/object/blob.rs1
-rw-r--r--vendor/gix/src/object/commit.rs16
-rw-r--r--vendor/gix/src/object/errors.rs10
-rw-r--r--vendor/gix/src/object/tree/diff/for_each.rs5
-rw-r--r--vendor/gix/src/object/tree/diff/mod.rs4
-rw-r--r--vendor/gix/src/object/tree/diff/rewrites.rs2
-rw-r--r--vendor/gix/src/object/tree/iter.rs19
-rw-r--r--vendor/gix/src/object/tree/mod.rs111
-rw-r--r--vendor/gix/src/open/options.rs6
-rw-r--r--vendor/gix/src/open/repository.rs44
-rw-r--r--vendor/gix/src/pathspec.rs207
-rw-r--r--vendor/gix/src/reference/edits.rs5
-rw-r--r--vendor/gix/src/reference/iter.rs14
-rw-r--r--vendor/gix/src/reference/log.rs5
-rw-r--r--vendor/gix/src/reference/mod.rs17
-rw-r--r--vendor/gix/src/remote/build.rs23
-rw-r--r--vendor/gix/src/remote/connect.rs6
-rw-r--r--vendor/gix/src/remote/connection/fetch/mod.rs60
-rw-r--r--vendor/gix/src/remote/connection/fetch/negotiate.rs141
-rw-r--r--vendor/gix/src/remote/connection/fetch/receive_pack.rs129
-rw-r--r--vendor/gix/src/remote/connection/fetch/update_refs/mod.rs368
-rw-r--r--vendor/gix/src/remote/connection/fetch/update_refs/tests.rs427
-rw-r--r--vendor/gix/src/remote/connection/fetch/update_refs/update.rs45
-rw-r--r--vendor/gix/src/remote/connection/ref_map.rs6
-rw-r--r--vendor/gix/src/remote/errors.rs23
-rw-r--r--vendor/gix/src/remote/fetch.rs19
-rw-r--r--vendor/gix/src/remote/init.rs13
-rw-r--r--vendor/gix/src/remote/save.rs5
-rw-r--r--vendor/gix/src/repository/attributes.rs119
-rw-r--r--vendor/gix/src/repository/config/mod.rs15
-rw-r--r--vendor/gix/src/repository/config/transport.rs5
-rw-r--r--vendor/gix/src/repository/excludes.rs45
-rw-r--r--vendor/gix/src/repository/filter.rs64
-rw-r--r--vendor/gix/src/repository/graph.rs26
-rw-r--r--vendor/gix/src/repository/identity.rs20
-rw-r--r--vendor/gix/src/repository/impls.rs12
-rw-r--r--vendor/gix/src/repository/index.rs133
-rw-r--r--vendor/gix/src/repository/init.rs17
-rw-r--r--vendor/gix/src/repository/location.rs42
-rw-r--r--vendor/gix/src/repository/mailmap.rs (renamed from vendor/gix/src/repository/snapshots.rs)3
-rw-r--r--vendor/gix/src/repository/mod.rs94
-rw-r--r--vendor/gix/src/repository/object.rs105
-rw-r--r--vendor/gix/src/repository/pathspec.rs55
-rw-r--r--vendor/gix/src/repository/reference.rs29
-rw-r--r--vendor/gix/src/repository/remote.rs42
-rw-r--r--vendor/gix/src/repository/revision.rs5
-rw-r--r--vendor/gix/src/repository/submodule.rs96
-rw-r--r--vendor/gix/src/repository/worktree.rs137
-rw-r--r--vendor/gix/src/revision/mod.rs3
-rw-r--r--vendor/gix/src/revision/spec/parse/delegate/mod.rs7
-rw-r--r--vendor/gix/src/revision/spec/parse/delegate/navigate.rs24
-rw-r--r--vendor/gix/src/revision/spec/parse/delegate/revision.rs8
-rw-r--r--vendor/gix/src/revision/spec/parse/mod.rs2
-rw-r--r--vendor/gix/src/revision/spec/parse/types.rs10
-rw-r--r--vendor/gix/src/revision/walk.rs128
-rw-r--r--vendor/gix/src/submodule/errors.rs106
-rw-r--r--vendor/gix/src/submodule/mod.rs287
-rw-r--r--vendor/gix/src/types.rs53
-rw-r--r--vendor/gix/src/worktree/mod.rs111
127 files changed, 6261 insertions, 2106 deletions
diff --git a/vendor/gix/.cargo-checksum.json b/vendor/gix/.cargo-checksum.json
index 2450144e5..4c3735e08 100644
--- a/vendor/gix/.cargo-checksum.json
+++ b/vendor/gix/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"2798efe9ba9ba30789fb2b006f6a88e43cf8dccf84ca51780b720387ff4fd716","Cargo.lock":"463fe594d84c3f623a3e23e40bc754765e9b3ba3df47af1fc8d237e518175fb3","Cargo.toml":"f67af22736fe7da071886f81faf421116d925593d70683e5bdb34cdfa52ba6e3","LICENSE-APACHE":"cb4780590812826851ba250f90bed0ed19506ec98f6865a0e2e20bbf62391ff9","LICENSE-MIT":"49df47913ab2beafe8dc45607877ae64198bf0eee64aaad3e82ed9e4d27424e8","src/assets/baseline-init/HEAD":"28d25bf82af4c0e2b72f50959b2beb859e3e60b9630a5e8c603dad4ddb2b6e80","src/assets/baseline-init/description":"85ab6c163d43a17ea9cf7788308bca1466f1b0a8d1cc92e26e9bf63da4062aee","src/assets/baseline-init/hooks/applypatch-msg.sample":"64b47216779d705b5270e94970aa0bc7b96fd256af0a624e936f6b1b85a014db","src/assets/baseline-init/hooks/commit-msg.sample":"1f74d5e9292979b573ebd59741d46cb93ff391acdd083d340b94370753d92437","src/assets/baseline-init/hooks/fsmonitor-watchman.sample":"f3c0228d8e827f1c5260ac59fdd92c3d425c46e54711ef713c5a54ae0a4db2b4","src/assets/baseline-init/hooks/post-update.sample":"81765af2daef323061dcbc5e61fc16481cb74b3bac9ad8a174b186523586f6c5","src/assets/baseline-init/hooks/pre-applypatch.sample":"e99aee3f6ff6a07f775cab64af1c6507d46d20afa4a5a87fd3402d22b1de2797","src/assets/baseline-init/hooks/pre-commit.sample":"f9af7d95eb1231ecf2eba9770fedfa8d4797a12b02d7240e98d568201251244a","src/assets/baseline-init/hooks/pre-merge-commit.sample":"d3825a70337940ebbd0a5c072984e13245920cdf8898bd225c8d27a6dfc9cb53","src/assets/baseline-init/hooks/pre-push.sample":"4b1119e1e13a212571976f4aee77847cdbd40978546d6273a557e238981a40d1","src/assets/baseline-init/hooks/pre-rebase.sample":"3ac3a30cffe859b71a27d77a7fc1635d35ff5d5aaecc896bba11bd01e1b307ce","src/assets/baseline-init/hooks/pre-receive.sample":"a4c3d2b9c7bb3fd8d1441c31bd4ee71a595d66b44fcf49ddb310252320169989","src/assets/baseline-init/hooks/prepare-commit-msg.sample":"e9ddcaa4189fddd25ed97fc8c789eca7b6ca16390b2392ae3276f0c8e1aa4619","src/assets/baseline-init/hooks/update.sample":"978235ae8b913ab4d0f906a8af621a0bfe7c314d84b715f4f64ee9b1aa3cce2d","src/assets/baseline-init/info/exclude":"6671fe83b7a07c8932ee89164d1f2793b2318058eb8b98dc5c06ee0a5a3b0ec1","src/attributes.rs":"af39ccaf9438b1b832808e7758610876cabda0c137d1e8cb6d1ecb7ef3121ce0","src/clone/access.rs":"285795cc8f32a66cfb7a98ad7458dad29415ef8331eff995ca0b87a63aa39410","src/clone/checkout.rs":"82ebd7de88815b5975e00f4740114f77ed78441c31eb42a74b6213eb5acf0798","src/clone/fetch/mod.rs":"fa55696e8e57abab3f8078da7a3ffe5a78006c120a0f78acc9d88dd32d4d856f","src/clone/fetch/util.rs":"6d97f3013f4e9d40f1a527e6a9cbd5b99873dc895e89d3e987c31e6331db9d29","src/clone/mod.rs":"2bfb9a6d352aefa0f4575ce318f9e65eb5879c0a6ca1e92d19f073087bc4d89f","src/commit.rs":"26b1d03ecefa10113713b1f1d2b4c700c187692db29d28d07d7a64e0abd92961","src/config/cache/access.rs":"72253ec261e949e81ed020fc0cf7fb4323738a492db8aafa1918855fa68b8a5e","src/config/cache/incubate.rs":"babac6fef1f7ecec4bc5549a29db82857621de8e81e209ea0efd342783d3d88d","src/config/cache/init.rs":"e993fb7f764432fd0dc6cd4d763abceb13109897d7c512bbdefa1c46dc925e2a","src/config/cache/mod.rs":"3cce2cf0fafbc4f828870b85fef411a826ad6d1fe3ac5b6cbd2f5e049331aebf","src/config/cache/util.rs":"672dd1dcc9a5b66187f99a469005bd2d9df5e0467793dfe9360d9e7b024f2ebe","src/config/mod.rs":"b723aa6946443b50799598ddf3e5b1b63b9bede315591e6671a56397f21ae34c","src/config/overrides.rs":"f7efe80641d6ef181139881ef9a066133d0ebd31570a029649ec685c0916fd6a","src/config/snapshot/_impls.rs":"edae9b731c69828effbdfe01d32b7caa8c536df81d33de1cb67b88ece01a7218","src/config/snapshot/access.rs":"fc9b5df53f74627cb0d4f0bbcdb933ae9086394678929623dccb23f957fcfe91","src/config/snapshot/credential_helpers.rs":"28a821ed2921d433c9c5ae40baed7762514ed3e187aa8c7a4ea1c8997da9d275","src/config/snapshot/mod.rs":"5377723de24b00ccb58e15df119831d7c0d9f2695f4499621db37546a5fccaff","src/config/tree/keys.rs":"3dfbd42ecb2c278dbcf08d0f2f30d5e5c1430fda08508628e1e83ed5c1812224","src/config/tree/mod.rs":"8a2b308e1001f92d0751d137cfe1c276a1b9758be199a3754ba8c863cdf3f321","src/config/tree/sections/author.rs":"a27cf6ad5150aa5ccbd64d2786183983e1567c094a221b016875864c9e8f6980","src/config/tree/sections/branch.rs":"105211bb0eefbdc718923d5e770261889163a5d61dc8f0c22af33473cfb32100","src/config/tree/sections/checkout.rs":"329ebe10cca7c5414f9e6229d6dce3178cdb5821a1b7e72bbfac3a60b5b42dc2","src/config/tree/sections/clone.rs":"bbc86890044721ac34ae7610b14987035ab8714c856cec2787fae49c286a6d6d","src/config/tree/sections/committer.rs":"2f99b8bc6e2c4ad9bdba3a85bc6b717acb5b09d1ada2723d3ba5954f804368eb","src/config/tree/sections/core.rs":"83ee8ed46b2ba6a6a2d4cbde071013f071167253fb39b6b0beb52c542ae78c4d","src/config/tree/sections/credential.rs":"e1ce72dc24b9d2f06827b9fc6e8c963f888844ab5a4b48f6d867ad8542909b94","src/config/tree/sections/diff.rs":"b2bdfba61b34bc08c81d84b6b9e7ba009f8e0277f71e79393020d26c4112cde6","src/config/tree/sections/extensions.rs":"f73c444f2e2c8fbc8d1b1991c0d63532c792362e42833f3ae06059c07387cf66","src/config/tree/sections/fetch.rs":"3f5e49203f2ace0f9d7febc41d61212779afc008717a1fc46c4e1fc1ce7655ac","src/config/tree/sections/gitoxide.rs":"3bc1cc8f907c74a65f5cda6053d9bf466ef09d244d8af607f843da6d5d65cde7","src/config/tree/sections/http.rs":"58c9a9b8abcee4066eb4e20f9679dbbf888c04c21f4dbfff0d2ad7f0a18d4fcd","src/config/tree/sections/index.rs":"01e6abb77443f65aa413059256c6b412dd4f258f3fcc68da1710bc42990326a8","src/config/tree/sections/init.rs":"e87e33ac5091797bde302f78c8fb7cefce0fb1752610409c1db53c3f7b4179af","src/config/tree/sections/mod.rs":"6706dee32dd931300273835ab01de664bba355cf1fcb750b2454188878915591","src/config/tree/sections/pack.rs":"0a6dcdc7603b0d7a84159a70789b63b6c26d539f98808c520a8e644fc9dbd2f3","src/config/tree/sections/protocol.rs":"6b9eed6bd37c4c1e9eae1449563ca430f65f81226cd675282810bf7873bd0e05","src/config/tree/sections/remote.rs":"eb06d89125dc72b5754b642cf561e6e430cad4fbbd57dcd1049d306291afc41f","src/config/tree/sections/safe.rs":"4e96f49ff56d6ebb8944406fe2ae3c4a1fa80c5383f08935015ddc6036b583c3","src/config/tree/sections/ssh.rs":"7db83236912bcb7aa1770f0eb1a388ee0fac94c1548bd9a19051b34c25622841","src/config/tree/sections/url.rs":"e342edcd20979feaf54663a919a0751aaf32b4e1f2e47cf5d028faec62e6b731","src/config/tree/sections/user.rs":"8f02172a5db830832b4edf28693fdef33cece6ba1990c4d7a338e4c9291375ab","src/config/tree/traits.rs":"524f1752e9131c27db3a9016ee6c3abc61175345c2167426ffd5a41602cb950d","src/create.rs":"0cba6d6381cd75482d28b3be5e008513197eb3d8565f540330f2458dd3ade472","src/diff.rs":"52bc752a2a8decff56b7a41d1ae97b90c0f3422332f999ced67fc884d6b25d18","src/discover.rs":"d1ff7f43fb4c2b5303fc6c045bb65f68bb394a5c20e2bf36d8378c7a053ce785","src/env.rs":"1446448d4bf1ba89eefd13a3b4080874456669e889efc1e8df48b866e659d029","src/ext/mod.rs":"3c96daa11ca8321dedc9b968176e31f6e3626e4cd60f308ad46e2ec7fe586bde","src/ext/object_id.rs":"a70afd79c84731df0023d738332b3688a2adbcbdda802f8ee70297fc8fe0ca38","src/ext/reference.rs":"a51fe4f63e5708afa4fbabd13638b88c34845a64263db77308cd1b974a0f325f","src/ext/rev_spec.rs":"c196f21a3981b7ad84e9385ba3924a554accf9c7a3b4f8e2bba13cb74f108ec8","src/ext/tree.rs":"c4446627523e22c032c0e322e5daa35b3105bf68f6eaa45da84c590edb76420e","src/head/log.rs":"0de9d5f834b633756001bdd246e98266084d521d7f775537e6e6ead5ed93d7e4","src/head/mod.rs":"443c8f5129d2e92d893f53d4d6babc1ae1a79c88c1474738d35f2cc8aac98465","src/head/peel.rs":"4d92eb96c94abfcc653fbd00fcb0800985105d9b7804f5dbe81756da3b8b8bae","src/id.rs":"3e238cc4a58aed58d0cf6486e250cb0f361493d03aa3f6fd08a1c1ad82bd3819","src/init.rs":"84d97d8ca3f61cb87dfc99be1ee56ee53c6bdac75a741bd5c7bf995f7d5cb137","src/interrupt.rs":"f6aaa74d277900528f5628e483bddc9c821199ea06db39630e3f55ef93dc31e9","src/lib.rs":"9cb64f7b920911fca411db726496e573596a34f563a8a8ca55b8e2fb35ef9cc8","src/mailmap.rs":"415301bdcb3d6991675c7ea86a92eea152cf65df7b2d14da4b58b3b605039e4e","src/object/blob.rs":"ae504ea412a4b0df0bb1d4e61655ed1d9f5654e1e586eedcf0d72fa1d20f7866","src/object/commit.rs":"d969468a537f8c509b708e9d2403da33ca1ac1442543589e683d080cefe66237","src/object/errors.rs":"f1b322fbff0e400dfb153e67e7f6de1839ec488b53e552ac968545131a79ac74","src/object/impls.rs":"6b9f76d332da496148adaa9b5b5de5dcf98c3fd92deba245dd2e6c2a3895eb77","src/object/mod.rs":"158263fe6f6a8db6ecebc741dac012a517508d5041e70909228e1c0ae9cee1c7","src/object/peel.rs":"c23ac9baac1216d9320c71926f56548d18f7f3964bdbcccd8ca81f6b756f7ad9","src/object/tag.rs":"b40e2b908de9dd500d297f1bcbd969facfe7beadcf62cc6a7cb975169f2da8be","src/object/tree/diff/change.rs":"95df7e1fb3b58fa2a0086f205c39940fb590ccdac92aee53a6cff5f29181f30c","src/object/tree/diff/for_each.rs":"05f11ffc85e3efdcb0c8c8a039a69d20f3a94715228d133e21816af6aa2f2a61","src/object/tree/diff/mod.rs":"980ec8425e9783a445d06d1a81b7a7f0cd05798a84a9ce2c7d7506e9c5912259","src/object/tree/diff/rewrites.rs":"52873aa41d64bbdcbc1079cf5ab4f853951006a35eb24fa9f03f66d266e380e1","src/object/tree/diff/tracked.rs":"4b8226a3722b08e41b00c800efc81ee611f801cf42606203c26d568f2d6d16fa","src/object/tree/iter.rs":"4e54d72fce5a5bc9299ea36147dd2d95d3d25d34d97dd5d663e7ce0eb87b1f13","src/object/tree/mod.rs":"9d09e9fa8ad9a41b969b8f682447a5ad889a5ff713b53492e05302007ae2b252","src/object/tree/traverse.rs":"ae0342857d42b6afb82167423dfdac9611ce1b7281b6b9b542e230960c564c0f","src/open/mod.rs":"d25c11246536e7d57172b375569bd8545b8060f13bbfbc49cbf0f85636627076","src/open/options.rs":"697287cb2715d4a27353dbf7745ff381edd19f062ddd73e14b54f5e11c36d022","src/open/permissions.rs":"5a55970e738ba7a9af7b51cdeb03955af533b3306baaef278b398cf99f8a312b","src/open/repository.rs":"130a3a676c2353822b53e52034b4f0b48a818317e9761087e97f89d5c8e5effd","src/path.rs":"3cd4c92a626384f8f4db89b2f7594923b922d7b841681c167748a01abc7dc3f7","src/prelude.rs":"8dc6fa25bb01fbc1e012364949982e406b17ab22bde464e154f12286fba293cf","src/progress.rs":"a9ba8ec6cc21eea78121b02d1feaba8f6aab04be441bfe8be9f3dffe4c5e0ba5","src/reference/edits.rs":"324520036d184dbc9db44b723fe52c8038a8b2bdd2c3d76d5c05f16a248b9ee0","src/reference/errors.rs":"f0699048b34163a8e9fb19306827f16dd0d8376660787646ee75e73c70fe7497","src/reference/iter.rs":"645ebf083877a73c05202e8b79489e19fad290e1e6e41b7d817e08307e2822c3","src/reference/log.rs":"95b3e85dde8ca06251c15756ad3b54eeb48804ac6718ec4634f367091bd42b80","src/reference/mod.rs":"e0cad649928296e68df1b89119a35814ac4c6887957f7cdf644113b59fd74645","src/reference/remote.rs":"4467c1bf9d463d1781a3254a3874c7fc763201e33d51e1a92a6f0dcbc6776135","src/remote/access.rs":"76e75baca0155710c2eea0e439df0774ecb0cd6c7e6b950876dd9e6e75be5e9f","src/remote/build.rs":"773a10e61826a4976b872ae2922f723c55174e0ed4c0b941ab8034bc33b314cc","src/remote/connect.rs":"a25e99e3556c0c7f4a6ce2101179190468163bfe743e4896e240303528819c95","src/remote/connection/access.rs":"075f04705680959074cf3db6856bf34180d68d1a3065011ca56b67a861e2b168","src/remote/connection/fetch/config.rs":"93b1392fdc409dba073e96272f13ad7ab996522d59df819edc800431ee36975b","src/remote/connection/fetch/error.rs":"21ccf5ff0cba287247581849c510aa3dd1acdd510cfbb858a579dd85b2c7b050","src/remote/connection/fetch/mod.rs":"708d6985903e70f51c611ecc6489b41de3291933689665e5b3638698d6c8a4e8","src/remote/connection/fetch/negotiate.rs":"8dcb137d8642e7cdd4eb77995f863ae97dae97d28aa985a9ba1b35ceda184714","src/remote/connection/fetch/receive_pack.rs":"5d2f810d04c87c5b5233cb0aadb902dfd68b3a82da4ba10304360561d3642095","src/remote/connection/fetch/update_refs/mod.rs":"a1e93355795ee0b4ca28946fc464dcd29af460b3f37b4376b7e31760050805af","src/remote/connection/fetch/update_refs/tests.rs":"65a45137898327627bd16ebc7352db8c255813ffe4dac683c6894495eaeee0af","src/remote/connection/fetch/update_refs/update.rs":"069156a6fcebd0eab64d1f816eae6612bc5d0523f3dae05e69ece40a23c00a95","src/remote/connection/mod.rs":"863f4a7f2476f5b5d8622959d5069424decea29ba7f66619f679344e6fb5a5d1","src/remote/connection/ref_map.rs":"4179bcab5f65ad6a5e900e7038153cb4e2eaae1d4947f46d8cb71dc910a03cf3","src/remote/errors.rs":"148318b54894fddf1eee58bbb622861122fcd5d6b6a9470083779945f75c3257","src/remote/fetch.rs":"b44f5214b154645a4aaacb1538032e8b2814f08a1e874139fdb6ff364fa1b031","src/remote/init.rs":"519adc4da7ca2739697bd4e48d0100458a146c8cb71069b8a6a721198199d3d9","src/remote/mod.rs":"14a1532470cc76cf3b727657439923f3515dd781ebfc7030d9481056c6bbf162","src/remote/name.rs":"9fa7e81a157375ecb40ddfba5da850fef7513296a68014a50f5148d57f40b8b7","src/remote/save.rs":"3c42980bd6632a1763bbd3b34d488f0c9eeec9ebcefae2e727d20bafd42508a5","src/remote/url/mod.rs":"a3279f5330fc83193e583f2b839ab08006c293b0040db6cc74969d50813fbbaa","src/remote/url/rewrite.rs":"4d43167909020458abc5e3e7310e3efaddb9fc7c783581fbc9422fa8b057d95d","src/remote/url/scheme_permission.rs":"4f6e528260c67af54171477d97707050f048c0c35e77f088f8ddc4ae135e6386","src/repository/attributes.rs":"2d727b5be3b13446415dc7fea5848c409c56b759e8a21eeeaca4649a6b4c8739","src/repository/cache.rs":"72d41c8f90d2e49c10b884582613fa5941ea0e1d15cc7d0a4d0d7be0b0243d4d","src/repository/config/mod.rs":"a38da6ac7e3815ade1d1d1acfb571b459651dd675491a1d21deae99317a9c73e","src/repository/config/transport.rs":"cb163133228cb4d75c140b747fdc132b4512bd5b86b10f70bd8cd8f9a432859f","src/repository/excludes.rs":"408693ed4ac09d47354b3a9bf90c278252435eada4dfb0bb104f57395c2acca1","src/repository/graph.rs":"ab61194c67a2fdac702475bfa46feb3e6c6e69a870c7b871749bcf0d1094ebcb","src/repository/identity.rs":"81d368f2b7d65800bf93d623f130ddb44a8d9e965cdd9757455733d31f92d483","src/repository/impls.rs":"7af7dd5ef7b7c1ff28e957175b4a2fea39574668d2768d20561ded5a48460a39","src/repository/init.rs":"b6c9280a38296669cd79acbee23800c798ea40f7cf6523e3b8338aeb131364e3","src/repository/kind.rs":"a32375689f9de7c74d29079caa2f025db8a4b13a3dc31a587039548343b23ade","src/repository/location.rs":"23acc9c1128528039eb6d67a241b328a0cd843b9050442465dd20ea069bb0eea","src/repository/mod.rs":"2319d6b10311c302dc1c9964b566ce1f8a8a72ebe42209acba3f4a3aa8e920f1","src/repository/object.rs":"ee64408564227c373cfc08fe1bf90e775abc5d5df38affbb91c060c211d66165","src/repository/permissions.rs":"9f7f41fd250d043cea7ee6ff0cdc315838dbb6226bde3dca2a7666f01d648090","src/repository/reference.rs":"c37e556966dd4308bc8b5784484612d9d62a438a443d1d667374ed604b238f5e","src/repository/remote.rs":"8740998547516f89eaa9268b7ba48ee89f73de411194d558502fee18139f9680","src/repository/revision.rs":"66126940c3a94776d94b901c14078d5b749723c3c0ed8500639edfe37aaa97da","src/repository/shallow.rs":"ce0b3358ed0ccca6ac52a985555793013f7c2d5de83291cd9810181ac22e714a","src/repository/snapshots.rs":"3a8f439bdf9e6d71873fe114c12565adf98be0ba478586cc6ccbbf515f281e24","src/repository/state.rs":"040cca4a26463211aef85e4539d084969240f30d985c1bd3ae9bb3cd01009d1d","src/repository/thread_safe.rs":"40e455ea3b5637da6e2acae4f5d13c4b8e8a25b8944a4c2870243e31f7f13632","src/repository/worktree.rs":"cc95d78cd4cb8277a906d01ce207216ee705c7c8d65aa264ad8a0d9a1829307d","src/revision/mod.rs":"a466315d4aea646ddba99c54f9ae118431b56dafbca6d0462ebabca3695d027d","src/revision/spec/mod.rs":"aa1516ed667a49bfa0db55fdea0bfbcc3227411be105496f0867bd7efb5d5dda","src/revision/spec/parse/delegate/mod.rs":"bfe787c5c881b5e4acf4bbcb79d966b8a92e56e8b2d20525bf0c0cd6ba0a0b8d","src/revision/spec/parse/delegate/navigate.rs":"bd3c8550ec76e52225db9ba16390f045ec977b6196f76b99bd67beb5c193c70d","src/revision/spec/parse/delegate/revision.rs":"51ff36007b7376305cfcf8acbacc53ddb72796aceec8b761f4d1f1843554487c","src/revision/spec/parse/error.rs":"48c0c2e7dcffe80aac5563094787e0502c4275619fc35467a2687499bbad0fef","src/revision/spec/parse/mod.rs":"141e591acacfce8cc8d11c5b72d18c8d05baad1b21dead0d8e7242f4963410b7","src/revision/spec/parse/types.rs":"0713678daae38786c8828bf04a9608b75adf3751803e20711ed5d265998a3b8b","src/revision/walk.rs":"f96694a47f85b0e2dbf75871950dc6d8b2f02143e67981c473753d09d36399d4","src/shallow.rs":"4296fb5298ef71eb1d78aae21d11bfb129a4f5a5f3cf43bf6d5256fec40f8dc3","src/state.rs":"1e3c5e1df4016e8b3e60028def84b0f706c4fcffaba11b1152d9240e144f21e8","src/tag.rs":"f60043aaa7afb54652ab6cf64765ebd61607f19a83dd5960abf8077d2cb91d44","src/types.rs":"d80b2a66393b5ebe7155a61ad7ae7c8b7be0a16759001ada12349b642103a8c0","src/worktree/mod.rs":"7f09a39827ed42c66fc688752ed87ae2abc6605991bdf214e60c725766b044ea","src/worktree/proxy.rs":"07ff3cfc6a8f326fb7d62f6762f682498e9e5f131ece935acfd26b5223a338f1"},"package":"bf2a03ec66ee24d1b2bae3ab718f8d14f141613810cb7ff6756f7db667f1cd82"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"1d19c01836b4304d7ff947d7d708c920c82bb3e890c409bc3a595f04e8a53f7c","Cargo.lock":"a6d5cde82a8ae844af84ae8aeea87244b431b9d89625e5fcc7fd75659dd40a0b","Cargo.toml":"411958a94d8058aaffc2ba36b91605162a10d5387475e58cf8f48e49eedb874c","LICENSE-APACHE":"cb4780590812826851ba250f90bed0ed19506ec98f6865a0e2e20bbf62391ff9","LICENSE-MIT":"49df47913ab2beafe8dc45607877ae64198bf0eee64aaad3e82ed9e4d27424e8","src/assets/init/HEAD":"28d25bf82af4c0e2b72f50959b2beb859e3e60b9630a5e8c603dad4ddb2b6e80","src/assets/init/description":"47aad2f8621afc777c66085c31f5ed14656df9bcfa5a2ae445680f175d0d2d0c","src/assets/init/hooks/applypatch-msg.sample":"1ae81b995a5c8c54582e1977084babed1e947a5a5c247ad29563142e432955ab","src/assets/init/hooks/commit-msg.sample":"b1451a4c89ee4406ba56f003a7e3d142e24a7452861fddddc23bfc77163c8650","src/assets/init/hooks/docs.url":"4424200fb80650f5063a3ec0a3864af4aaa3103f1319fe576b64d3bfc74f8a67","src/assets/init/hooks/fsmonitor-watchman.sample":"99ed87d785ada3687b4d86b8d9aa562f3430ce7061834e5381166b6a35a0d495","src/assets/init/hooks/post-update.sample":"e6d88132de729f20c45f66c2df51cc2e223a4b8b1512a2ce1cfdd0033ee53e53","src/assets/init/hooks/pre-applypatch.sample":"4c9754cac1c73109e4113ffd76070ae528a42667a85135e87fb826d572d13a4c","src/assets/init/hooks/pre-commit.sample":"1dd0fb2a11956784eb184e72af2fd87feca9050903400f163b90d4db7f19ce78","src/assets/init/hooks/pre-merge-commit.sample":"fca192309544e8e23638bd0987be7a5d00e271599b55382c1c6a4812070da223","src/assets/init/hooks/pre-push.sample":"0e6762e0b35b2475849d11c71d504cfae10cab2be0b947d7caa1e0d5959f2cec","src/assets/init/hooks/pre-rebase.sample":"d7c629ddbaa5f984d21c97a14889599d2019230220d3459aa103648316500968","src/assets/init/hooks/prepare-commit-msg.sample":"f804b4efd22ef832b49506a815a6a6b1103b8f77b6d6556fc3756232727396d8","src/assets/init/info/exclude":"df4c844761dc873ca9ea2f6fabcc2e2460b2f804ca65f8470e39ffbda7c3446e","src/attribute_stack.rs":"835abb1ed1477b26d6e57eb25b418096ad09b3c2d4781bc5f21bf72741846a42","src/clone/access.rs":"285795cc8f32a66cfb7a98ad7458dad29415ef8331eff995ca0b87a63aa39410","src/clone/checkout.rs":"bfb9f26cb9e471e0af0cdcd417a87bbbf28f4f7cabe3443480be5471f35c0be1","src/clone/fetch/mod.rs":"f00acfadcd4f9a1759ca029593be6692a1a913b5b41308464d163e9eac2f6bbe","src/clone/fetch/util.rs":"27ab217f25aa73690e3a31acf5655bd412c1f47653860bcb6a9a668d0b7ef01d","src/clone/mod.rs":"f4238d146b6cd29bbb12c77f08efc25efd33f50eb4834daecead2176154fab79","src/commit.rs":"3cf4f1f485c025982e9bb398c48d356af321d9fd8775de7c1a911de1052a1ece","src/config/cache/access.rs":"d7942372d42748ee5a04c8cb8dbff8c0fcb710109c9b56f53eb4edfe0ac0914c","src/config/cache/incubate.rs":"75a949861c7c2d11eec84dea92c80059b68a6ebedaf399690305544836e0a7d3","src/config/cache/init.rs":"37fee4c9c661a37d2186940b832c2a067cfcaa2ea9ebc185ce8fb4bbb6ec72f5","src/config/cache/mod.rs":"3cce2cf0fafbc4f828870b85fef411a826ad6d1fe3ac5b6cbd2f5e049331aebf","src/config/cache/util.rs":"6dbd15b84e47d3d32c6535d1b9f6a9ad73171137411d5a8bb764c5d1f60b005e","src/config/mod.rs":"7895c0860c3b84faaf5df05a2cf06065fc2ade4b0e01e1322040713b559d8d67","src/config/overrides.rs":"ca3b08e3ab4d292c904ef3a0746e937c4e90440ae19389b03321c5645177e39e","src/config/snapshot/_impls.rs":"edae9b731c69828effbdfe01d32b7caa8c536df81d33de1cb67b88ece01a7218","src/config/snapshot/access.rs":"c08dfa7bb0c969913efb6e08692203c5bed7ef2502053a89f6181846aec5918a","src/config/snapshot/credential_helpers.rs":"cd269ffb60aab86a752839294b3514b31bd59de5b4ae941f25111dfba25aad33","src/config/snapshot/mod.rs":"21f6eaeb511e470df6f3d8948dfd65b688741b39d534fbaf78e3ee620bc6a5c5","src/config/tree/keys.rs":"16b9625821e1d7bba9dc79181fbf34b0266cea4ffda5108c36fd23325c157253","src/config/tree/mod.rs":"be9654a1c844b8444c2f5d0003937fbc06bae7f934073eb206e0541df3b81425","src/config/tree/sections/author.rs":"a27cf6ad5150aa5ccbd64d2786183983e1567c094a221b016875864c9e8f6980","src/config/tree/sections/branch.rs":"105211bb0eefbdc718923d5e770261889163a5d61dc8f0c22af33473cfb32100","src/config/tree/sections/checkout.rs":"329ebe10cca7c5414f9e6229d6dce3178cdb5821a1b7e72bbfac3a60b5b42dc2","src/config/tree/sections/clone.rs":"bbc86890044721ac34ae7610b14987035ab8714c856cec2787fae49c286a6d6d","src/config/tree/sections/committer.rs":"2f99b8bc6e2c4ad9bdba3a85bc6b717acb5b09d1ada2723d3ba5954f804368eb","src/config/tree/sections/core.rs":"e5f04b31611fab9252ff0f00b8e95e1e06ad36c0e5e8fcc2fa5495537152c9f4","src/config/tree/sections/credential.rs":"e1ce72dc24b9d2f06827b9fc6e8c963f888844ab5a4b48f6d867ad8542909b94","src/config/tree/sections/diff.rs":"9c577772d544d9c9c0d06485955aecab0c64d8e1a0117e71a33f75dd281baa83","src/config/tree/sections/extensions.rs":"f73c444f2e2c8fbc8d1b1991c0d63532c792362e42833f3ae06059c07387cf66","src/config/tree/sections/fetch.rs":"437a6a13df2e1da4a06e9a28d9da020eccab395f13150d398e94bf4cd3e690f8","src/config/tree/sections/gitoxide.rs":"a483361a58e3221bbaf64847cfe70698fc4a73d24ce80875e4970af889fbf5b7","src/config/tree/sections/http.rs":"58c9a9b8abcee4066eb4e20f9679dbbf888c04c21f4dbfff0d2ad7f0a18d4fcd","src/config/tree/sections/index.rs":"30166326b339c9d0b171ebfd1c1f0fb90e38dc8b2edcd66dfead2a87c38eb938","src/config/tree/sections/init.rs":"e87e33ac5091797bde302f78c8fb7cefce0fb1752610409c1db53c3f7b4179af","src/config/tree/sections/mod.rs":"31f480fde038af3532667fb3ff511b6b978de262fa6cef4e19e1e64655060bc8","src/config/tree/sections/pack.rs":"0a6dcdc7603b0d7a84159a70789b63b6c26d539f98808c520a8e644fc9dbd2f3","src/config/tree/sections/protocol.rs":"feae4977f6576adb446d0599f018d41421a7b1b0871a74e8fcfe5e2b7104de74","src/config/tree/sections/remote.rs":"eb06d89125dc72b5754b642cf561e6e430cad4fbbd57dcd1049d306291afc41f","src/config/tree/sections/safe.rs":"4e96f49ff56d6ebb8944406fe2ae3c4a1fa80c5383f08935015ddc6036b583c3","src/config/tree/sections/ssh.rs":"7db83236912bcb7aa1770f0eb1a388ee0fac94c1548bd9a19051b34c25622841","src/config/tree/sections/url.rs":"e342edcd20979feaf54663a919a0751aaf32b4e1f2e47cf5d028faec62e6b731","src/config/tree/sections/user.rs":"8f02172a5db830832b4edf28693fdef33cece6ba1990c4d7a338e4c9291375ab","src/config/tree/traits.rs":"524f1752e9131c27db3a9016ee6c3abc61175345c2167426ffd5a41602cb950d","src/create.rs":"7da6fbdf8c18a32ad4ab9cea8a062fb8aadb08d8478c9d1c3de09c7e6e4448fe","src/diff.rs":"52bc752a2a8decff56b7a41d1ae97b90c0f3422332f999ced67fc884d6b25d18","src/discover.rs":"41631f880b7880f62d77bfb0511f4d85a82a574ca5f53b8cb8fe35edd5b886f6","src/env.rs":"57da96b315b6fe057a326639cd3e85849793449c4c8f3477b79a032b1a029b31","src/ext/mod.rs":"cc6a4c10c2eb53eb261e0186ee51411dada06bbb245c205356fce1de9d4628f5","src/ext/object_id.rs":"a70afd79c84731df0023d738332b3688a2adbcbdda802f8ee70297fc8fe0ca38","src/ext/reference.rs":"a51fe4f63e5708afa4fbabd13638b88c34845a64263db77308cd1b974a0f325f","src/ext/rev_spec.rs":"c196f21a3981b7ad84e9385ba3924a554accf9c7a3b4f8e2bba13cb74f108ec8","src/ext/tree.rs":"60753a38cfd6cbb43b794236de0258a5af40f0a88864dde9e1f7d6cdb8cbb04f","src/filter.rs":"5f106fe06646beb2beb3f181258e7b717f7b3111ed41380c5e22fb3db215bd89","src/head/log.rs":"0de9d5f834b633756001bdd246e98266084d521d7f775537e6e6ead5ed93d7e4","src/head/mod.rs":"5be9b17e6ffb5dd4c9548b8a4d9e25d6ab6600450762293c43ca0bcbd2a6284f","src/head/peel.rs":"4d92eb96c94abfcc653fbd00fcb0800985105d9b7804f5dbe81756da3b8b8bae","src/id.rs":"1f5f97d24d8c00460d085e2815c08b89632ae1e3cde283a4362798cc4b1276ea","src/init.rs":"ac6f329feb2d33cd8a5f0ce21bb77a166e18656a9952d4cba147196242558c9a","src/interrupt.rs":"217d8611ebe2932e7cb52f77a90cec4a6dbe0bd69eb16b951a70fbd8b5e95853","src/lib.rs":"28fabd0194e9cb3168a46f6552752dd02f21736dc42b301653e74ae619d21428","src/mailmap.rs":"415301bdcb3d6991675c7ea86a92eea152cf65df7b2d14da4b58b3b605039e4e","src/object/blob.rs":"5b613976f017190b857e1ace8140ae0b2656da5d94389dfc84525919eeea54f6","src/object/commit.rs":"533da4ff0639db444548bcb3345fb34db505af997dd477f7ad53a8000ef24e75","src/object/errors.rs":"b2b456480e10dc4cdd213650dacb619d96bd9770e19d6042a80621991acd5255","src/object/impls.rs":"6b9f76d332da496148adaa9b5b5de5dcf98c3fd92deba245dd2e6c2a3895eb77","src/object/mod.rs":"158263fe6f6a8db6ecebc741dac012a517508d5041e70909228e1c0ae9cee1c7","src/object/peel.rs":"c23ac9baac1216d9320c71926f56548d18f7f3964bdbcccd8ca81f6b756f7ad9","src/object/tag.rs":"b40e2b908de9dd500d297f1bcbd969facfe7beadcf62cc6a7cb975169f2da8be","src/object/tree/diff/change.rs":"95df7e1fb3b58fa2a0086f205c39940fb590ccdac92aee53a6cff5f29181f30c","src/object/tree/diff/for_each.rs":"da534722f9dbfdf26e66dc564de0c7e694e92cf54f33e29f3364ed056cea8c78","src/object/tree/diff/mod.rs":"672ef727e70da7a6f214e59ea45b16833c68c5b57a95fe7e71c89aac054eaaf4","src/object/tree/diff/rewrites.rs":"d91983f629bf3f0256da17d0067daf8271503345423f725d3a23fb5a40eac4d2","src/object/tree/diff/tracked.rs":"4b8226a3722b08e41b00c800efc81ee611f801cf42606203c26d568f2d6d16fa","src/object/tree/iter.rs":"cf3ae9dfd5018b55228ccc0b4b707b39a3fa2c5d2b130e209da5dcf9080e10ca","src/object/tree/mod.rs":"b0ba34a7227ce7ff82cc7686061251e8e6789d9ef04f5b9d6590cc5242488909","src/object/tree/traverse.rs":"ae0342857d42b6afb82167423dfdac9611ce1b7281b6b9b542e230960c564c0f","src/open/mod.rs":"d25c11246536e7d57172b375569bd8545b8060f13bbfbc49cbf0f85636627076","src/open/options.rs":"1ffda0517724d1328b2fb296a782d89305a482be65ed24a1d9d867bead8eb5a5","src/open/permissions.rs":"5a55970e738ba7a9af7b51cdeb03955af533b3306baaef278b398cf99f8a312b","src/open/repository.rs":"ae4100ee1dd30890d961dc12a57dcf03dee1ffa9a99c54a6704dde5493416764","src/path.rs":"3cd4c92a626384f8f4db89b2f7594923b922d7b841681c167748a01abc7dc3f7","src/pathspec.rs":"bddfa7360ee13ac72a97fa0e1388c9605518da3fc96fd35e76e245f25b73b813","src/prelude.rs":"8dc6fa25bb01fbc1e012364949982e406b17ab22bde464e154f12286fba293cf","src/progress.rs":"a9ba8ec6cc21eea78121b02d1feaba8f6aab04be441bfe8be9f3dffe4c5e0ba5","src/reference/edits.rs":"5d857cd65d7415d4de5aed1ea8acc9c227000a71b2e202293546cd23be1f62b2","src/reference/errors.rs":"f0699048b34163a8e9fb19306827f16dd0d8376660787646ee75e73c70fe7497","src/reference/iter.rs":"1feb3aaed665b39780136f0d703f67f4b34f6239e90cd2a0c632aad40523e025","src/reference/log.rs":"f1eab69b8272b15bd23beeb68e88a8b53f003f74d86783196b2de4a84f0497fd","src/reference/mod.rs":"1920cf8657100d1ea50efdc510333fc073ae756d9778553d06ee0a17ea5f4414","src/reference/remote.rs":"4467c1bf9d463d1781a3254a3874c7fc763201e33d51e1a92a6f0dcbc6776135","src/remote/access.rs":"76e75baca0155710c2eea0e439df0774ecb0cd6c7e6b950876dd9e6e75be5e9f","src/remote/build.rs":"0bfcf98ee6b96c401a410c71b749426e84a78c17eff944ea7d6229ef2dc3e5e8","src/remote/connect.rs":"a147cf33f7ac1413e07d7b5aae0c6a557ee9b29f9172e7ea2413446d670ac71b","src/remote/connection/access.rs":"075f04705680959074cf3db6856bf34180d68d1a3065011ca56b67a861e2b168","src/remote/connection/fetch/config.rs":"93b1392fdc409dba073e96272f13ad7ab996522d59df819edc800431ee36975b","src/remote/connection/fetch/error.rs":"21ccf5ff0cba287247581849c510aa3dd1acdd510cfbb858a579dd85b2c7b050","src/remote/connection/fetch/mod.rs":"c88b8b968debe3192ecc6a5e46a1587f590b1ae45b76df4c13d8a64df956860c","src/remote/connection/fetch/negotiate.rs":"7258ddb2d5adf92f5041709bda16f1d19313ec867717ed270c6a191fdc92b3b9","src/remote/connection/fetch/receive_pack.rs":"d3d4809a7e4ae52868d5975c5de8d16e1218f662ee83e35498291ee582accdc9","src/remote/connection/fetch/update_refs/mod.rs":"f28b33d42f0992b3e91b7eba3672d6fe4d41811f8ea170e9bf11fac688c6e882","src/remote/connection/fetch/update_refs/tests.rs":"69a25df4dc1f84b5a7cb603e2451114cf0a7e356c026317995f3d14bfd07a345","src/remote/connection/fetch/update_refs/update.rs":"729ae1cfef895df37ae5a34c19d9aac9b77e664f107f3adf81a79ae58412e960","src/remote/connection/mod.rs":"863f4a7f2476f5b5d8622959d5069424decea29ba7f66619f679344e6fb5a5d1","src/remote/connection/ref_map.rs":"35913d6c4d8976025ff880ac71bd8e5af0b73fd83e6ca53be1ec275b6dc009e4","src/remote/errors.rs":"6c4986618c55c2a86e4623b02837918dc61849c3d634e7d474a123eb7e01bcbc","src/remote/fetch.rs":"cf78b682074ad700ea6eb4d511401a737a905bd4af0dcfd639b7f850227f5978","src/remote/init.rs":"87576486ae399945b2134dbce70e960ff4c2b3a3046988449f6da0c25f6d646c","src/remote/mod.rs":"14a1532470cc76cf3b727657439923f3515dd781ebfc7030d9481056c6bbf162","src/remote/name.rs":"9fa7e81a157375ecb40ddfba5da850fef7513296a68014a50f5148d57f40b8b7","src/remote/save.rs":"a8b2160cde235c9a2ecddc0181d1cca57a01e046eae8d3b11fa7b29e43ca6866","src/remote/url/mod.rs":"a3279f5330fc83193e583f2b839ab08006c293b0040db6cc74969d50813fbbaa","src/remote/url/rewrite.rs":"4d43167909020458abc5e3e7310e3efaddb9fc7c783581fbc9422fa8b057d95d","src/remote/url/scheme_permission.rs":"4f6e528260c67af54171477d97707050f048c0c35e77f088f8ddc4ae135e6386","src/repository/attributes.rs":"6c28910869eafda6c4c9d6a2b06a2a881f2d5fcf6f5c084ac501850ced2af810","src/repository/cache.rs":"72d41c8f90d2e49c10b884582613fa5941ea0e1d15cc7d0a4d0d7be0b0243d4d","src/repository/config/mod.rs":"b6d7d9b3fb86f0e76cc585efb110aec0bdee4b82c8bdbe6a3bb67d65ffd31de9","src/repository/config/transport.rs":"78683c40947e95d9835809d6b9adc89bbce4e8a06345279c56554b2a76dc4e7c","src/repository/filter.rs":"cc65692a78e3cc28166f595d3bf05c0d3f12757fc8d320512638f6edb724c209","src/repository/graph.rs":"07763932b3215ac25e3981a60ab0750449af992475da7fd47bb0412cdf0fc727","src/repository/identity.rs":"0d7c575578eef869d16d99ce465696f41b1c7e8d2bdba93945219d7453b3d717","src/repository/impls.rs":"b07dd79074b3a175df1ec43042c6cd0ad98b884885e25deae6828a59cc290e2a","src/repository/index.rs":"44e74a6f5be41da88a42a1b5fc5f9b4a70fb42302696a6b4394822fab918ba05","src/repository/init.rs":"f72f56ff1ebb225d043a088c922adb24495d4031d4de2edf6a144156f1f6305e","src/repository/kind.rs":"a32375689f9de7c74d29079caa2f025db8a4b13a3dc31a587039548343b23ade","src/repository/location.rs":"31204869db066e0a1ea58be0b5c41b247f581b16a2ea011942d8d6b5702403b8","src/repository/mailmap.rs":"3ca35665ac2d2c6f100826169822750e1b6647b1f284206f408126e749718030","src/repository/mod.rs":"2154ccecc6167644cd02b88906597d735632a8ed8c5f60dfac5934a7dc7198ea","src/repository/object.rs":"dd2ea672c630aacfda15366349562f3e2dbabcf8bc9201775dc4c0e86633f488","src/repository/pathspec.rs":"6da21d9a2f75ace735cc96aa6dd709bf323f2c5fc05daa40dfc3d393b2485187","src/repository/permissions.rs":"9f7f41fd250d043cea7ee6ff0cdc315838dbb6226bde3dca2a7666f01d648090","src/repository/reference.rs":"9a5f7109bee3bb165bf7da31ef7ae3b3a9018573da1b82407fe158a0ffb13851","src/repository/remote.rs":"4ecc9021f3369d9530a130fe2dbe3c98dc50b593a5194c8584293808fc2bc4a4","src/repository/revision.rs":"c2d50c2bed8b465e5e2f24483d5cc54791fa68c6f558feea5871dfdcc7f6c4ec","src/repository/shallow.rs":"ce0b3358ed0ccca6ac52a985555793013f7c2d5de83291cd9810181ac22e714a","src/repository/state.rs":"040cca4a26463211aef85e4539d084969240f30d985c1bd3ae9bb3cd01009d1d","src/repository/submodule.rs":"a44ebd1132a898bbd8454628888bb8ce41611066ca8d78004242fcc522aac27c","src/repository/thread_safe.rs":"40e455ea3b5637da6e2acae4f5d13c4b8e8a25b8944a4c2870243e31f7f13632","src/repository/worktree.rs":"1a7eaf3eb18d55018fd5a3a04b9faa8db96d05aa9debf553cd15ea1ad4e9e928","src/revision/mod.rs":"d3c83f7ae1ac71a18f79cb73a95997432936b11b94f2ad6a2fe6b3fc23554f96","src/revision/spec/mod.rs":"aa1516ed667a49bfa0db55fdea0bfbcc3227411be105496f0867bd7efb5d5dda","src/revision/spec/parse/delegate/mod.rs":"8ee9c646a16c8f46551c03f1bdf450a71fda79ce691dfcd0e1b56631a3fa3d9a","src/revision/spec/parse/delegate/navigate.rs":"2d720500c83e9b80ff1e33e8ad3faf59502116a9e29ee44385510c9a6c8114c8","src/revision/spec/parse/delegate/revision.rs":"b3ee71f7ec701a202c8e1b9fcc6a9397a8dfb251f195fa218429e630b0280ab4","src/revision/spec/parse/error.rs":"48c0c2e7dcffe80aac5563094787e0502c4275619fc35467a2687499bbad0fef","src/revision/spec/parse/mod.rs":"5f16d2141f7e5959b0a83b4f4035ceaadbaef6b7f563bc05d45257fcec9d340e","src/revision/spec/parse/types.rs":"8876e1b5caf323d4c671f31fc06c07043df10592cecec6dcd62714826ba09bfe","src/revision/walk.rs":"aa84696ba6ea7a293e834121ae2e6b79428b637333d2f7673083adbd1a18c522","src/shallow.rs":"4296fb5298ef71eb1d78aae21d11bfb129a4f5a5f3cf43bf6d5256fec40f8dc3","src/state.rs":"1e3c5e1df4016e8b3e60028def84b0f706c4fcffaba11b1152d9240e144f21e8","src/submodule/errors.rs":"996617b2e707f903de4316e775b8bac03a925959c2c70278aa84f56fa68a9fb0","src/submodule/mod.rs":"00c860ed710f4eab48dfdf54b640750f24721be89fda168cfc1c529492901f9c","src/tag.rs":"f60043aaa7afb54652ab6cf64765ebd61607f19a83dd5960abf8077d2cb91d44","src/types.rs":"daa1706f19f9b257de8d875b73553561da107429e0988f610972354d1d8a85e3","src/worktree/mod.rs":"2053c334a780377e12679a363df6441605f5ca1893237304490cb69b8d7068ca","src/worktree/proxy.rs":"07ff3cfc6a8f326fb7d62f6762f682498e9e5f131ece935acfd26b5223a338f1"},"package":"ad6d32e74454459690d57d18ea4ebec1629936e6b130b51d12cb4a81630ac953"} \ No newline at end of file
diff --git a/vendor/gix/CHANGELOG.md b/vendor/gix/CHANGELOG.md
index f7d7d7fd2..eec514b03 100644
--- a/vendor/gix/CHANGELOG.md
+++ b/vendor/gix/CHANGELOG.md
@@ -5,6 +5,838 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## 0.54.1 (2023-09-25)
+
+### Bug Fixes
+
+ - <csr-id-300a83821358f2a43649515606ebb84741e82780/> local refs created during fetching will now always be valid.
+ Previously it could create symbolic refs that were effectively unborn, i.e.
+ point to a reference which doesn't exist.
+
+ Now these will always point to the peeled object instead.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 1 commit contributed to the release.
+ - 1 commit was understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Local refs created during fetching will now always be valid. ([`300a838`](https://github.com/Byron/gitoxide/commit/300a83821358f2a43649515606ebb84741e82780))
+</details>
+
+## 0.54.0 (2023-09-24)
+
+<csr-id-e022096aa495f55a05f83860243f49552be501f7/>
+<csr-id-79e47a512507c7fd7acbdff624a5249e24505e0d/>
+
+### New Features
+
+ - <csr-id-f9d14d86a6578cf0f9a0c4a2256ad227b9264340/> Add `PathspecDetached` as pathspec that can more easily be used across threads.
+ - <csr-id-f066f9889b57a4ffaebc0ed1442d77999498db42/> `PathSpec` implements `gix_status::PathSpec` to allow it to be used there.
+ The reason we need a trait and can't do with simply a function is that multiple calls
+ are needed to test for inclusion *and* allow the common-prefix optimization.
+ - <csr-id-a8333f1137df51d237f6debf056ac075b0a2cd94/> add `Repository::stat_options()` to learn how an index would compare filesystem stats.
+ - <csr-id-2734e84b74b761bff27fc1eb27f57d9d839c9240/> add `parallel` feature toggle
+ Make certain data structure threadsafe (or `Sync`) to facilitate multithreading.
+ Further, many algorithms will now use multiple threads by default.
+ If unset, most of `gix` can only be used in a single thread
+ as data structures won't be `Send` anymore.
+
+### Bug Fixes
+
+ - <csr-id-e22893c1c95a76d9a5f3b2f2a4e2a30f815ee7e5/> do not trust ctime by default.
+ On MacOS it seems to be off by two seconds right from the source, which
+ seems to be an issue `stat` isn't having.
+ - <csr-id-334281c8771790df7a022daa4a700c96b99acbc0/> ignore empty `core.askpass` settings
+ This is the same as what `git` does, it's explicit per value, which
+ means that other paths might be flagged as empty automatically.
+
+### Other
+
+ - <csr-id-e022096aa495f55a05f83860243f49552be501f7/> add note about the trust-model.
+ It should explain why `gix` is happy to open repositories that won't
+ be handled by `git` unless overrides are set.
+
+### Test
+
+ - <csr-id-79e47a512507c7fd7acbdff624a5249e24505e0d/> add assertion to assure `ThreadSafeRepository` is sync.
+ If it doesn't appear to be sync, be sure to use the `max-performance-safe` feature.
+
+### Bug Fixes (BREAKING)
+
+ - <csr-id-ee9276f2a7789c20d88d40624ad648e44b604a27/> `PrepareCheckout::main_worktree()` now takes `Progress` as geric argument.
+ This makes it more flexible and convenient, but is technically a breaking change.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 31 commits contributed to the release over the course of 15 calendar days.
+ - 15 days passed between releases.
+ - 9 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-features v0.35.0, gix-actor v0.27.0, gix-object v0.37.0, gix-glob v0.13.0, gix-attributes v0.19.0, gix-filter v0.5.0, gix-fs v0.7.0, gix-commitgraph v0.21.0, gix-revwalk v0.8.0, gix-traverse v0.33.0, gix-worktree-stream v0.5.0, gix-archive v0.5.0, gix-tempfile v10.0.0, gix-lock v10.0.0, gix-ref v0.37.0, gix-config v0.30.0, gix-url v0.24.0, gix-credentials v0.20.0, gix-diff v0.36.0, gix-discover v0.25.0, gix-ignore v0.8.0, gix-index v0.25.0, gix-mailmap v0.19.0, gix-negotiate v0.8.0, gix-pack v0.43.0, gix-odb v0.53.0, gix-pathspec v0.3.0, gix-transport v0.37.0, gix-protocol v0.40.0, gix-revision v0.22.0, gix-refspec v0.18.0, gix-status v0.1.0, gix-submodule v0.4.0, gix-worktree v0.26.0, gix-worktree-state v0.3.0, gix v0.54.0, gitoxide-core v0.32.0, gitoxide v0.30.0, safety bump 37 crates ([`7891fb1`](https://github.com/Byron/gitoxide/commit/7891fb17348ec2f4c997665f9a25be36e2713da4))
+ - Prepare changelogs prior to release ([`8a60d5b`](https://github.com/Byron/gitoxide/commit/8a60d5b80877c213c3b646d3061e8a33e0e433ec))
+ - Merge branch 'reset' ([`54a8495`](https://github.com/Byron/gitoxide/commit/54a849545140f7f1c0c7564c418071c0a76a34e7))
+ - Add `PathspecDetached` as pathspec that can more easily be used across threads. ([`f9d14d8`](https://github.com/Byron/gitoxide/commit/f9d14d86a6578cf0f9a0c4a2256ad227b9264340))
+ - Do not trust ctime by default. ([`e22893c`](https://github.com/Byron/gitoxide/commit/e22893c1c95a76d9a5f3b2f2a4e2a30f815ee7e5))
+ - `PathSpec` implements `gix_status::PathSpec` to allow it to be used there. ([`f066f98`](https://github.com/Byron/gitoxide/commit/f066f9889b57a4ffaebc0ed1442d77999498db42))
+ - Add `Repository::stat_options()` to learn how an index would compare filesystem stats. ([`a8333f1`](https://github.com/Byron/gitoxide/commit/a8333f1137df51d237f6debf056ac075b0a2cd94))
+ - Fix compile time warning ([`4ce7f7c`](https://github.com/Byron/gitoxide/commit/4ce7f7c2c8bb66f0c093bf6e4d20f5568ca04f6a))
+ - Merge branch 'parallel-feature' ([`c270f78`](https://github.com/Byron/gitoxide/commit/c270f7883e1ea8156d521b12d161a47b2144425c))
+ - Add `parallel` feature toggle ([`2734e84`](https://github.com/Byron/gitoxide/commit/2734e84b74b761bff27fc1eb27f57d9d839c9240))
+ - Add assertion to assure `ThreadSafeRepository` is sync. ([`79e47a5`](https://github.com/Byron/gitoxide/commit/79e47a512507c7fd7acbdff624a5249e24505e0d))
+ - Merge pull request #1015 from NobodyXu/optimize/prepare-checkout ([`14312b6`](https://github.com/Byron/gitoxide/commit/14312b6c21d6382f7e536db7a1d8b519b97b8300))
+ - Merge branch 'path-config' ([`9c528dc`](https://github.com/Byron/gitoxide/commit/9c528dc8282c8b2f3a023e523dccdd0f7a711e61))
+ - Merge pull request #1012 from NobodyXu/optimization/try-into-de-momo ([`afb1960`](https://github.com/Byron/gitoxide/commit/afb1960e3e13bc9fc7cc5f3a3a244945f00966ad))
+ - Ignore empty `core.askpass` settings ([`334281c`](https://github.com/Byron/gitoxide/commit/334281c8771790df7a022daa4a700c96b99acbc0))
+ - Merge branch 'optimize/progress-use' ([`1f2ffb6`](https://github.com/Byron/gitoxide/commit/1f2ffb6d86ef073caf43a2f7a77fe712a1aa495e))
+ - `PrepareCheckout::main_worktree()` now takes `Progress` as geric argument. ([`ee9276f`](https://github.com/Byron/gitoxide/commit/ee9276f2a7789c20d88d40624ad648e44b604a27))
+ - Add note about the trust-model. ([`e022096`](https://github.com/Byron/gitoxide/commit/e022096aa495f55a05f83860243f49552be501f7))
+ - Optimize `clone::PrepareCheckout::main_worktree`` ([`938f518`](https://github.com/Byron/gitoxide/commit/938f5187f0ff51561971ca463584ec0db93f3455))
+ - Fix `maybe_async` ([`c80e809`](https://github.com/Byron/gitoxide/commit/c80e809c2655d15d7f22170782dacd64fe2e01bd))
+ - Rm unused clippy lint ([`d82f84b`](https://github.com/Byron/gitoxide/commit/d82f84b23a3def8e237e2b2511874c6045032c04))
+ - Fixed error by also using trait object in `remote::fetch::Prepare::receive` ([`44faa01`](https://github.com/Byron/gitoxide/commit/44faa01cf0612df5685922710d4a0adf6715ef77))
+ - Revert changes to binary files ([`3eb8653`](https://github.com/Byron/gitoxide/commit/3eb8653b78f2a0ca654fbebb185f3d6416d779d5))
+ - Rm binary files ([`6a33594`](https://github.com/Byron/gitoxide/commit/6a335940332b8d5069cb0c310d2d8e43fbeee01e))
+ - Use trait object for `progress` in `PrepareFetch::fetch_only` ([`70989b3`](https://github.com/Byron/gitoxide/commit/70989b3965077ae00ec6cf344f31627a804a8225))
+ - Fix clippy warnings ([`d5aa2ba`](https://github.com/Byron/gitoxide/commit/d5aa2ba030f57d65021d84efa99c0abc9d61f575))
+ - Optimize `Repository::write_blob_stream`: Avoid dup codegen ([`ca8a373`](https://github.com/Byron/gitoxide/commit/ca8a373b1a3de44d2bef3e4908d6f5269b6cdd1f))
+ - Apply `gix_macros::momo` to `Repository::write_blob` ([`bae928d`](https://github.com/Byron/gitoxide/commit/bae928d9668bbb4ba0dadb4605d77fc773362e3f))
+ - Optimize `Repository::write_object`: Avoid dup momo ([`32f1c7d`](https://github.com/Byron/gitoxide/commit/32f1c7d2bc2e91cb346c8b379dce41293f88b222))
+ - Rm unnecessary lifetime annotation in `Repository::commit_as_inner` ([`cf70a2e`](https://github.com/Byron/gitoxide/commit/cf70a2e0f08dd323c0713b4e23b21f54668a99a2))
+ - Optimize `gix`: de-momo `impl TryInto` by hand ([`b19c140`](https://github.com/Byron/gitoxide/commit/b19c140ce3a6e5d9ddf65684361223a2f9fa7e73))
+</details>
+
+## 0.53.1 (2023-09-08)
+
+### Bug Fixes
+
+ - <csr-id-902639b9b72ead72b5355e0a1a4da5afd7fed46d/> `interrupt` feature only gates signal-handling, but leaves the `interrupt` module alone.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 2 commits contributed to the release.
+ - 1 commit was understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix v0.53.1 ([`1b1fc25`](https://github.com/Byron/gitoxide/commit/1b1fc257d5748c7c41e899bf2d1447ffd9f22d19))
+ - `interrupt` feature only gates signal-handling, but leaves the `interrupt` module alone. ([`902639b`](https://github.com/Byron/gitoxide/commit/902639b9b72ead72b5355e0a1a4da5afd7fed46d))
+</details>
+
+## 0.53.0 (2023-09-08)
+
+<csr-id-ed327f6163f54756e58c20f86a563a97efb256ca/>
+
+This release adds feature toggles which help to reduce compile time. Please [see the library](https://docs.rs/gix/0.53.0/gix/) documentation for all the details.
+
+### New Features
+
+ - <csr-id-2b8d09f785f471aa12fc6793f0ea40c1f8d9ea4a/> remove `log` dependency in favor of `gix-trace`
+ - <csr-id-36d34bd7e8cd944c009cb7acbe39c1dc445b4adc/> add `interrupt` feature to reduce dependencies
+ - <csr-id-721c37722ca8b12a5f9c060061040c79f9da6aa9/> Allow index access to be toggled with the `index` feature.
+ - <csr-id-92dd18154b526b4c5132d770960a36ccf739dec8/> add `excludes` feature to make exclude-checks possible.
+ - <csr-id-c4ffde013a62a38a6f63c4a160bc3cdb6aafd65a/> add `mailmap` feature
+ - <csr-id-c42064d8ca382513c944f3df5c08e4ff66d5f804/> add `revision` component behind a feature toggle.
+ - <csr-id-147528ff647dc74473ef8dd4ceac6fedebc0b15c/> `gix` without connection support includes less code
+ - <csr-id-fea044e5d09282a5772c8fe9a534d9ebf7f11bbc/> allow disabling the `blob-diff` capability
+ This also removes all diff capabilities.
+ - <csr-id-c5ec244979b7e6baf9a8237e4f12cb87809131ae/> improve feature documentation.
+ This should make optimizing compile time and performance easier, while
+ assuring these options aren't pre-determined by library providers.
+ - <csr-id-c79991cde8216271ab854b7574e7d97efd79d07c/> `Clone` for `ThreadSafeRepository`
+ It is `Sync` and can easily be passed by reference, but sometimes it's nice
+ to be cloning it as well.
+ - <csr-id-d22b7fb1304cce3b2aabac42cc58fe7c5911f276/> provide `Repository::find_fetch_remote()` to obtain a remote just like git would.
+
+### Bug Fixes
+
+ - <csr-id-a957478e0f623803bc6358d08b9ffaa2305e24d4/> put `gix-credentials` and `gix-prompt` behind the 'credentials' feature toggle.
+ They are also available when using https transports.
+ - <csr-id-4971a4837ff5ac6654aa75214bdd2243d4d864a5/> handle submodules whose entry in the index is a file.
+
+### Chore (BREAKING)
+
+ - <csr-id-ed327f6163f54756e58c20f86a563a97efb256ca/> update to the latest `prodash`
+ It makes proper usage of `Progress` types easier and allows them to be used
+ as `dyn` traits as well.
+
+### New Features (BREAKING)
+
+ - <csr-id-58b0e6f860d4d3b5548c18d3eae97141bc6dc377/> Use `stack` abstraction in `Repository::excludes()`.
+ This makes it easier to use.
+ - <csr-id-24dd870919ba444aa8099c63a78ea120d47ec28e/> use `prodash::Count` to indicate that nothing more than counting is performed, in place of `prodash::Progress`
+ - <csr-id-54291fdfc62c7d8a31bc5564713c23eab3865dc5/> Provide a wrapper for `gix_worktree::Stack` for simpler attribute queries.
+
+### Bug Fixes (BREAKING)
+
+ - <csr-id-741b41e6e6c6f283c1632a7de0da44a5e7842817/> remove `regex` feature in favor of `revparse-regex`.
+ `revparse-regex` is only used when parsing revspecs that use a special syntax.
+ This feature is also enabled by default.
+ - <csr-id-072ee32f693a31161cd6a843da6582d13efbb20b/> use `dyn` trait where possible.
+ This reduces compile time due to avoiding duplication.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 57 commits contributed to the release over the course of 17 calendar days.
+ - 17 days passed between releases.
+ - 19 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Thanks Clippy
+
+<csr-read-only-do-not-edit/>
+
+[Clippy](https://github.com/rust-lang/rust-clippy) helped 2 times to make code idiomatic.
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-transport v0.36.0, gix-protocol v0.39.0, gix-revision v0.21.0, gix-refspec v0.17.0, gix-submodule v0.3.0, gix-worktree v0.25.0, gix-worktree-state v0.2.0, gix v0.53.0 ([`1ff3064`](https://github.com/Byron/gitoxide/commit/1ff30641b8724efd6699d8bef5c71d28454e98b9))
+ - Release gix-date v0.8.0, gix-hash v0.13.0, gix-features v0.34.0, gix-actor v0.26.0, gix-object v0.36.0, gix-path v0.10.0, gix-glob v0.12.0, gix-attributes v0.18.0, gix-packetline-blocking v0.16.6, gix-filter v0.4.0, gix-fs v0.6.0, gix-commitgraph v0.20.0, gix-hashtable v0.4.0, gix-revwalk v0.7.0, gix-traverse v0.32.0, gix-worktree-stream v0.4.0, gix-archive v0.4.0, gix-config-value v0.14.0, gix-tempfile v9.0.0, gix-lock v9.0.0, gix-ref v0.36.0, gix-sec v0.10.0, gix-config v0.29.0, gix-prompt v0.7.0, gix-url v0.23.0, gix-credentials v0.19.0, gix-diff v0.35.0, gix-discover v0.24.0, gix-ignore v0.7.0, gix-index v0.24.0, gix-macros v0.1.0, gix-mailmap v0.18.0, gix-negotiate v0.7.0, gix-pack v0.42.0, gix-odb v0.52.0, gix-pathspec v0.2.0, gix-packetline v0.16.6, gix-transport v0.36.0, gix-protocol v0.39.0, gix-revision v0.21.0, gix-refspec v0.17.0, gix-submodule v0.3.0, gix-worktree v0.25.0, gix-worktree-state v0.2.0, gix v0.53.0, safety bump 39 crates ([`8bd0456`](https://github.com/Byron/gitoxide/commit/8bd045676bb2cdc02624ab93e73ff8518064ca38))
+ - Prepare changelogs for release ([`375db06`](https://github.com/Byron/gitoxide/commit/375db06a8442378c3f7a922fae38e2a6694d9d04))
+ - Merge branch 'optimizations' ([`6135a5e`](https://github.com/Byron/gitoxide/commit/6135a5ea8709646f01da62939a59dd3a9750e007))
+ - Adapt to changes in `gix` ([`805b8aa`](https://github.com/Byron/gitoxide/commit/805b8aa74b064b7aa08d87094a994bb8c7aae6ed))
+ - Remove `log` dependency in favor of `gix-trace` ([`2b8d09f`](https://github.com/Byron/gitoxide/commit/2b8d09f785f471aa12fc6793f0ea40c1f8d9ea4a))
+ - Add `interrupt` feature to reduce dependencies ([`36d34bd`](https://github.com/Byron/gitoxide/commit/36d34bd7e8cd944c009cb7acbe39c1dc445b4adc))
+ - Allow index access to be toggled with the `index` feature. ([`721c377`](https://github.com/Byron/gitoxide/commit/721c37722ca8b12a5f9c060061040c79f9da6aa9))
+ - Put `gix-credentials` and `gix-prompt` behind the 'credentials' feature toggle. ([`a957478`](https://github.com/Byron/gitoxide/commit/a957478e0f623803bc6358d08b9ffaa2305e24d4))
+ - Add `excludes` feature to make exclude-checks possible. ([`92dd181`](https://github.com/Byron/gitoxide/commit/92dd18154b526b4c5132d770960a36ccf739dec8))
+ - Use `stack` abstraction in `Repository::excludes()`. ([`58b0e6f`](https://github.com/Byron/gitoxide/commit/58b0e6f860d4d3b5548c18d3eae97141bc6dc377))
+ - Add `mailmap` feature ([`c4ffde0`](https://github.com/Byron/gitoxide/commit/c4ffde013a62a38a6f63c4a160bc3cdb6aafd65a))
+ - Simplify test-suite ([`799a515`](https://github.com/Byron/gitoxide/commit/799a5152c7ca444a8240a022e049c14b0b61d22d))
+ - Remove `regex` feature in favor of `revparse-regex`. ([`741b41e`](https://github.com/Byron/gitoxide/commit/741b41e6e6c6f283c1632a7de0da44a5e7842817))
+ - Add `revision` component behind a feature toggle. ([`c42064d`](https://github.com/Byron/gitoxide/commit/c42064d8ca382513c944f3df5c08e4ff66d5f804))
+ - `gix` without connection support includes less code ([`147528f`](https://github.com/Byron/gitoxide/commit/147528ff647dc74473ef8dd4ceac6fedebc0b15c))
+ - Allow disabling the `blob-diff` capability ([`fea044e`](https://github.com/Byron/gitoxide/commit/fea044e5d09282a5772c8fe9a534d9ebf7f11bbc))
+ - Improve feature documentation. ([`c5ec244`](https://github.com/Byron/gitoxide/commit/c5ec244979b7e6baf9a8237e4f12cb87809131ae))
+ - Merge branch 'feat/gix-momo' ([`a1ed6a1`](https://github.com/Byron/gitoxide/commit/a1ed6a1aacae02a167b7ec44e1a47411a2194ff7))
+ - Handle submodules whose entry in the index is a file. ([`4971a48`](https://github.com/Byron/gitoxide/commit/4971a4837ff5ac6654aa75214bdd2243d4d864a5))
+ - Merge branch `dyn`ification ([`f658fcc`](https://github.com/Byron/gitoxide/commit/f658fcc52dc2200ae34ca53dc10be97fb9012057))
+ - Use `dyn` trait where possible. ([`072ee32`](https://github.com/Byron/gitoxide/commit/072ee32f693a31161cd6a843da6582d13efbb20b))
+ - Use `prodash::Count` to indicate that nothing more than counting is performed, in place of `prodash::Progress` ([`24dd870`](https://github.com/Byron/gitoxide/commit/24dd870919ba444aa8099c63a78ea120d47ec28e))
+ - Update to the latest `prodash` ([`ed327f6`](https://github.com/Byron/gitoxide/commit/ed327f6163f54756e58c20f86a563a97efb256ca))
+ - Merge branch 'improvements' ([`8a7c2af`](https://github.com/Byron/gitoxide/commit/8a7c2af0d302d5acc87ef2d432bd6870017af63e))
+ - Provide a wrapper for `gix_worktree::Stack` for simpler attribute queries. ([`54291fd`](https://github.com/Byron/gitoxide/commit/54291fdfc62c7d8a31bc5564713c23eab3865dc5))
+ - `Clone` for `ThreadSafeRepository` ([`c79991c`](https://github.com/Byron/gitoxide/commit/c79991cde8216271ab854b7574e7d97efd79d07c))
+ - Merge branch 'adjustments-for-cargo' ([`b7560a2`](https://github.com/Byron/gitoxide/commit/b7560a2445b62f888bf5aa2ba4c5a47ae037cb23))
+ - Adapt to changes in `gix-submodule` ([`f8471b1`](https://github.com/Byron/gitoxide/commit/f8471b11e0d65fdb2617b927a8a207659a161439))
+ - Release gix-index v0.23.1 ([`11b9c71`](https://github.com/Byron/gitoxide/commit/11b9c71311df978ebb20cca0d765cf249c8eedcf))
+ - Release gix-date v0.7.4, gix-index v0.23.0, safety bump 5 crates ([`3be2b1c`](https://github.com/Byron/gitoxide/commit/3be2b1ccfe30eeae45711c64b88efc522a2b51b7))
+ - Apply `momo` to fn `gix::Remote::save_as_to` ([`875c287`](https://github.com/Byron/gitoxide/commit/875c28757e4a91cf314ec59dd1a0dde779698e53))
+ - Apply `momo` to fn `gix::revision::Spec::from_bstr` ([`1d90301`](https://github.com/Byron/gitoxide/commit/1d9030112b54699db9bd8d1125116e46c4a6f71e))
+ - Apply `momo` to mod `config::snapshot::access` ([`25912fe`](https://github.com/Byron/gitoxide/commit/25912fe1e5d60765458a2e90c0fa487657b0831c))
+ - Apply `momo` to mod `gix::create::into` ([`cd3c289`](https://github.com/Byron/gitoxide/commit/cd3c2893b095d38d36f0c969549f0aaadfcef2ee))
+ - Rm unnecessary `#[allow(unused_mut)]` put on `momo`ed functions ([`89ae797`](https://github.com/Byron/gitoxide/commit/89ae797c7f1f4d26c48ed54c5d8b31f39599f063))
+ - Remove unnecessary change in `repository/config/transport.rs` ([`86b8e50`](https://github.com/Byron/gitoxide/commit/86b8e50fafa7e5d57989acb9e8b848fd95d271a9))
+ - Remove unnecessary `#[allow(clippy::needless_lifetimes)]` ([`e1b9d51`](https://github.com/Byron/gitoxide/commit/e1b9d51acd137cdea7680584451702e52aab775f))
+ - Dramatically simplify `gix_macros::momo` ([`c72eaa0`](https://github.com/Byron/gitoxide/commit/c72eaa05697a3e34adaa3ee90584dce4b5c00120))
+ - Manually de-`momo` `Repository::try_find_remote_{without_url_rewrite}` ([`e760225`](https://github.com/Byron/gitoxide/commit/e7602257662cd9ddb4cfe41ef26cdf28cc007be7))
+ - Merge branch 'fixes' ([`4bfd1cc`](https://github.com/Byron/gitoxide/commit/4bfd1cc8f7922a8c4de6b9d078d54b93e78f51ff))
+ - Thanks clippy ([`0d6d4ec`](https://github.com/Byron/gitoxide/commit/0d6d4ec8030d2e8f4c7a9d6f421d54776c4b67fb))
+ - Adapt to changes in `gix-index` and pass skip-hash through for performance.. ([`713cd59`](https://github.com/Byron/gitoxide/commit/713cd59f0b1eff6397b80f1e1fceec278532fd59))
+ - Use new `gix` method to obtain the fetch remote (instead of implementing it by hand) ([`e2c0912`](https://github.com/Byron/gitoxide/commit/e2c0912cfede044431c17ae81ddae02746650ae4))
+ - Provide `Repository::find_fetch_remote()` to obtain a remote just like git would. ([`d22b7fb`](https://github.com/Byron/gitoxide/commit/d22b7fb1304cce3b2aabac42cc58fe7c5911f276))
+ - Fix clippy lints in `gix/src/repository/remote.rs` ([`ff210d8`](https://github.com/Byron/gitoxide/commit/ff210d82573cebfdf4edbfb39beaef08979c058f))
+ - Apply `momo` to mod `gix::repository` ([`5a50537`](https://github.com/Byron/gitoxide/commit/5a505377199730354c2a6b6b7b060184558bb9c4))
+ - Apply `momo` to mod `remote::connection::fetch::receive_pack` ([`ea5c2db`](https://github.com/Byron/gitoxide/commit/ea5c2dbabe9d3c1eb1ab5f15a578ec9f9c36a5d8))
+ - Apply `momo` to `gix::reference` ([`3c205ab`](https://github.com/Byron/gitoxide/commit/3c205abbdc0a80090b9f0f5681ce0949497e770f))
+ - Apply `momo` to `gix::pathspec` ([`767ec2d`](https://github.com/Byron/gitoxide/commit/767ec2dcfd1fadaca93390770604494d03f88ab3))
+ - Apply `momo` to mod `gix::open::repository` ([`3ce0144`](https://github.com/Byron/gitoxide/commit/3ce014499a86e4e8bb57ffe7caa540792c1c0a47))
+ - Apply `momo` to `gix::object::tree` ([`d835526`](https://github.com/Byron/gitoxide/commit/d8355267fd64dbcf22a01a11cb29d93e75f0fb4c))
+ - Apply `momo` to mod `gix::init` ([`46a9dfe`](https://github.com/Byron/gitoxide/commit/46a9dfe12dedc1cbf997ea408d1f1d2c5d673ba5))
+ - Apply `momo` to mod `gix::discover` ([`58fbb08`](https://github.com/Byron/gitoxide/commit/58fbb08461064d96dd9816e2fb6911cf76b6badc))
+ - Thanks clippy ([`5044c3b`](https://github.com/Byron/gitoxide/commit/5044c3b87456cf58ebfbbd00f23c9ba671cb290c))
+ - Imrpove git2 mapping by using aliases. ([`6194ebe`](https://github.com/Byron/gitoxide/commit/6194ebe1fb10dedc22f1937b91df858dffc50db3))
+ - Merge branch 'gix-submodule' ([`363ee77`](https://github.com/Byron/gitoxide/commit/363ee77400805f473c9ad66eadad9214e7ab66f4))
+</details>
+
+## 0.52.0 (2023-08-22)
+
+### New Features
+
+ - <csr-id-28249bda58b56af340c7d6af883496c3bb2d6804/> add `Worktree::pathspec()` to easily get worktree-scoped pathspec searches.
+ - <csr-id-59bb3c4109c4e7f1977cea602293be85b7d14a8a/> add `Submodule` type to represent a declared submodule.
+ - <csr-id-a7d0e441b2326520ae467e83e045302792e6bcd0/> `pathspec_search([specs])` to instantiate a search using pathspecs.
+ It can be used to for filtering input paths.
+ This type also makes filtering index entries easy.
+ - <csr-id-77da01456118227a59b654f32c15eeb1e5e19cd9/> make `gix-pathspec` crate available
+ - <csr-id-5c13459721eabb9d0746899a2498a104ddbdae59/> add `Commit::signature()` to yield the PGP sigature of a commit, if present.
+
+### Bug Fixes
+
+ - <csr-id-c51c8daee1ab54130ae3ed83ce67d08f01c4881a/> fix incorrect s/git-config/gix-config/
+ 3a861c8f049f6502d3bcbdac752659aa1aeda46a just blindly replaced any
+ occurence of "git-config" or "git_config" with "gix-config"/"gix_config".
+
+ There is no such thing as a gix-config file.
+ gix-config is a git-config file parser.
+
+### New Features (BREAKING)
+
+ - <csr-id-b1e55d6f9e4c0d78f0cdeb7b85e09c2eb7032ced/> `Repository::prefix()` turns `Option<Result` into `Result<Option`.
+ This makes it easier for the caller as they won't have to call transpose anymore.
+ - <csr-id-46225c2bc399e6db5a56b522c978e0d1fac163df/> improve `interrupt::init_handler()` to be usable from multiple threads
+ Previously it was geared towards applications which would initialize handlers
+ only from the main thread.
+
+ Now the API supports multiple threads.
+
+### Bug Fixes (BREAKING)
+
+ - <csr-id-430e58cd1efef0044fc36b23de019156a21f947c/> `Repository::prefix()` is now side-effect free and won't error if CWD is outside of working tree dir.
+ This makes it more usable, especially in contexts where many repositories are held, possibly with
+ changing current working dirs.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 32 commits contributed to the release over the course of 18 calendar days.
+ - 19 days passed between releases.
+ - 9 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-url v0.22.0, gix-credentials v0.18.0, gix-diff v0.34.0, gix-discover v0.23.0, gix-ignore v0.6.0, gix-bitmap v0.2.7, gix-index v0.22.0, gix-mailmap v0.17.0, gix-negotiate v0.6.0, gix-pack v0.41.0, gix-odb v0.51.0, gix-pathspec v0.1.0, gix-packetline v0.16.5, gix-transport v0.35.0, gix-protocol v0.38.0, gix-revision v0.20.0, gix-refspec v0.16.0, gix-submodule v0.2.0, gix-worktree v0.24.0, gix-worktree-state v0.1.0, gix v0.52.0, gitoxide-core v0.31.0, gitoxide v0.29.0 ([`6c62e74`](https://github.com/Byron/gitoxide/commit/6c62e748240ac0980fc23fdf30f8477dea8b9bc3))
+ - Release gix-date v0.7.3, gix-hash v0.12.0, gix-features v0.33.0, gix-actor v0.25.0, gix-object v0.35.0, gix-path v0.9.0, gix-glob v0.11.0, gix-quote v0.4.7, gix-attributes v0.17.0, gix-command v0.2.9, gix-packetline-blocking v0.16.5, gix-filter v0.3.0, gix-fs v0.5.0, gix-commitgraph v0.19.0, gix-hashtable v0.3.0, gix-revwalk v0.6.0, gix-traverse v0.31.0, gix-worktree-stream v0.3.0, gix-archive v0.3.0, gix-config-value v0.13.0, gix-tempfile v8.0.0, gix-lock v8.0.0, gix-ref v0.35.0, gix-sec v0.9.0, gix-config v0.28.0, gix-prompt v0.6.0, gix-url v0.22.0, gix-credentials v0.18.0, gix-diff v0.34.0, gix-discover v0.23.0, gix-ignore v0.6.0, gix-bitmap v0.2.7, gix-index v0.22.0, gix-mailmap v0.17.0, gix-negotiate v0.6.0, gix-pack v0.41.0, gix-odb v0.51.0, gix-pathspec v0.1.0, gix-packetline v0.16.5, gix-transport v0.35.0, gix-protocol v0.38.0, gix-revision v0.20.0, gix-refspec v0.16.0, gix-submodule v0.2.0, gix-worktree v0.24.0, gix-worktree-state v0.1.0, gix v0.52.0, gitoxide-core v0.31.0, gitoxide v0.29.0, safety bump 41 crates ([`30b2761`](https://github.com/Byron/gitoxide/commit/30b27615047692d3ced1b2d9c2ac15a80f79fbee))
+ - Update changelogs prior to release ([`f23ea88`](https://github.com/Byron/gitoxide/commit/f23ea8828f2d9ba7559973daca388c9591bcc5fc))
+ - Merge branch 'gix-submodule' ([`8f3f358`](https://github.com/Byron/gitoxide/commit/8f3f358800f1fe77d7ba7ebd396a90b692d3c0c1))
+ - Make sure that submodule hashes aren't attached as the parent repo is the wrong one here. ([`c96f26b`](https://github.com/Byron/gitoxide/commit/c96f26b5c13581812753638a24d261c3f75dddcf))
+ - Properly isolate environment variable based tests into their own binary ([`c35ddab`](https://github.com/Byron/gitoxide/commit/c35ddab41ff6f18ad9cd11df44cfffee91563433))
+ - Just fmt ([`0d258f4`](https://github.com/Byron/gitoxide/commit/0d258f40afcd848509e2b0c7c264e9f346ed1726))
+ - Merge branch 'submodule-in-gix' ([`36f7b78`](https://github.com/Byron/gitoxide/commit/36f7b783c67b8a087076a130f5ee9b90b23bc3cc))
+ - Adapt to changes in `gix` ([`9fe3052`](https://github.com/Byron/gitoxide/commit/9fe305291cf8ba908eaf38235f54abfa1d0ddeed))
+ - Add `Worktree::pathspec()` to easily get worktree-scoped pathspec searches. ([`28249bd`](https://github.com/Byron/gitoxide/commit/28249bda58b56af340c7d6af883496c3bb2d6804))
+ - Add `Submodule` type to represent a declared submodule. ([`59bb3c4`](https://github.com/Byron/gitoxide/commit/59bb3c4109c4e7f1977cea602293be85b7d14a8a))
+ - Merge branch 'worktree-organization' ([`8d0d8e0`](https://github.com/Byron/gitoxide/commit/8d0d8e005d7f11924a6717954d892aae5cec45e7))
+ - Adapt to changes in `gix-worktree` ([`e5717e1`](https://github.com/Byron/gitoxide/commit/e5717e1d12c49285d31a90b03b7f8e9cbc6c1108))
+ - Merge pull request #988 from not-my-profile/fix-gix-config-sub ([`7735047`](https://github.com/Byron/gitoxide/commit/7735047198bd7cc5059ca338f5c2147dd273f711))
+ - Fix incorrect s/git-config/gix-config/ ([`c51c8da`](https://github.com/Byron/gitoxide/commit/c51c8daee1ab54130ae3ed83ce67d08f01c4881a))
+ - Merge branch 'submodule-active' ([`a3afaa4`](https://github.com/Byron/gitoxide/commit/a3afaa42741616a0f1abeef9b54557e7c2b800cb))
+ - Adapt to changes in `gix-url` ([`f8fc662`](https://github.com/Byron/gitoxide/commit/f8fc6625d8c22f43e7ab5f1cdf1e8eb9a6ea34de))
+ - `pathspec_search([specs])` to instantiate a search using pathspecs. ([`a7d0e44`](https://github.com/Byron/gitoxide/commit/a7d0e441b2326520ae467e83e045302792e6bcd0))
+ - `Repository::prefix()` is now side-effect free and won't error if CWD is outside of working tree dir. ([`430e58c`](https://github.com/Byron/gitoxide/commit/430e58cd1efef0044fc36b23de019156a21f947c))
+ - Merge branch 'pathspec-matching' ([`9f4dfe0`](https://github.com/Byron/gitoxide/commit/9f4dfe0f0b948280692916b596923959ea2fd9da))
+ - `Repository::prefix()` turns `Option<Result` into `Result<Option`. ([`b1e55d6`](https://github.com/Byron/gitoxide/commit/b1e55d6f9e4c0d78f0cdeb7b85e09c2eb7032ced))
+ - Make `gix-pathspec` crate available ([`77da014`](https://github.com/Byron/gitoxide/commit/77da01456118227a59b654f32c15eeb1e5e19cd9))
+ - Merge branch 'handlers-mt' ([`f584d76`](https://github.com/Byron/gitoxide/commit/f584d7698d93836daef2000fd369034de46037f0))
+ - Improve `interrupt::init_handler()` to be usable from multiple threads ([`46225c2`](https://github.com/Byron/gitoxide/commit/46225c2bc399e6db5a56b522c978e0d1fac163df))
+ - Merge branch 'extract-signatures' ([`b37affe`](https://github.com/Byron/gitoxide/commit/b37affefecfb30a94431cd21dae6659004ca6244))
+ - Add `Commit::signature()` to yield the PGP sigature of a commit, if present. ([`5c13459`](https://github.com/Byron/gitoxide/commit/5c13459721eabb9d0746899a2498a104ddbdae59))
+ - Release gix-glob v0.10.2, gix-date v0.7.2, gix-validate v0.8.0, gix-object v0.34.0, gix-ref v0.34.0, gix-config v0.27.0, gix-commitgraph v0.18.2, gix-revwalk v0.5.0, gix-revision v0.19.0, gix-refspec v0.15.0, gix-submodule v0.1.0, safety bump 18 crates ([`4604f83`](https://github.com/Byron/gitoxide/commit/4604f83ef238dc07c85aaeae097399b67f3cfd0c))
+ - Merge branch 'submodules' ([`b629f8a`](https://github.com/Byron/gitoxide/commit/b629f8a774931d58c0a9b124fa75f85807c6c5d1))
+ - More idiomatic use of `config.section_by_name()` ([`0a584ee`](https://github.com/Byron/gitoxide/commit/0a584eeb5c756ec4b0d54c4fd9ea3cc1497f4ba9))
+ - Adjust to changes in `gix-validate` ([`a8bc0de`](https://github.com/Byron/gitoxide/commit/a8bc0de6d071be82364434b6e27afecc02f3be51))
+ - Merge branch 'dev-on-linux' ([`6b4a303`](https://github.com/Byron/gitoxide/commit/6b4a30330fe49fc97daa73f55bf56580cc0597aa))
+ - Fix various tests to run properly on linux ([`ef8ccd9`](https://github.com/Byron/gitoxide/commit/ef8ccd9d16143d37155d063747c69cade80f162d))
+</details>
+
+## 0.51.0 (2023-08-02)
+
+This is mostly a bug-fix release with many improvements for fetching, along with more forgiving commit parsing.
+
+### New Features
+
+ - <csr-id-d9e551b44aa3e84109660328de7637d465d59578/> Add `Reference::follow()` as a way to peel symbolic refs step by step.
+
+### Bug Fixes (BREAKING)
+
+ - <csr-id-74ce8639e88db5107691e9279df2bbfd38d26de3/> handle symbolic ref updates far more gracefully and with more logical consistency.
+ Previously, refspecs couldn't be used to update sybolic references locally, particularly because the logic
+ to do so correctly isn't trivial and `git` itself also seems to cover only the most common cases.
+
+ However, the logic now changed so that remote updates will only be rejected if
+
+ * fast-forward rules are violated
+* the local ref is currently checked out
+* existing refs would not become 'unborn', i.e. point to a reference that doesn't exist and won't be created due to ref-specs
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 7 commits contributed to the release over the course of 2 calendar days.
+ - 9 days passed between releases.
+ - 2 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-actor v0.24.2, gix-object v0.33.2, gix-ref v0.33.3, gix-config v0.26.2, gix-prompt v0.5.5, gix-odb v0.50.2, gix-transport v0.34.2, gix-protocol v0.37.0, gix-worktree v0.23.1, gix v0.51.0, safety bump 3 crates ([`231ac1c`](https://github.com/Byron/gitoxide/commit/231ac1c6ad5ca9a84dbeb0dee14bfbf2fef1ae1e))
+ - Prepare additional changelogs ([`db63815`](https://github.com/Byron/gitoxide/commit/db6381522395a0de047118e81df5cd3cbeb862b9))
+ - Prepare changelogs ([`e4d2890`](https://github.com/Byron/gitoxide/commit/e4d2890a85bf60e9cdb4016dddfab3c4dccbe75e))
+ - Merge branch 'fixes-and-improvements' ([`f8b1f55`](https://github.com/Byron/gitoxide/commit/f8b1f553371f25b1bea6bce7cbb2ff1f01194856))
+ - Handle symbolic ref updates far more gracefully and with more logical consistency. ([`74ce863`](https://github.com/Byron/gitoxide/commit/74ce8639e88db5107691e9279df2bbfd38d26de3))
+ - Adapt to changes in `gix-protocol` ([`df81076`](https://github.com/Byron/gitoxide/commit/df810766dfeaaad7474339358a3d844b2c3368cd))
+ - Add `Reference::follow()` as a way to peel symbolic refs step by step. ([`d9e551b`](https://github.com/Byron/gitoxide/commit/d9e551b44aa3e84109660328de7637d465d59578))
+</details>
+
+## 0.50.1 (2023-07-24)
+
+### Bug Fixes
+
+ - <csr-id-145f8658a32c46db1f54d3098cf9371fe6eeec5e/> `Tree::lookup_entry(_by_path)()` now actually works
+ Previously it was lacking a test and that showed.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 3 commits contributed to the release.
+ - 1 day passed between releases.
+ - 1 commit was understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-archive v0.2.1, gix-ref v0.33.2, gix-pack v0.40.2, gix v0.50.1 ([`13883e5`](https://github.com/Byron/gitoxide/commit/13883e5528385f892ee402e911298121e0c297c0))
+ - Prepare changelogs ([`735c206`](https://github.com/Byron/gitoxide/commit/735c2062625aaeffbdbca3c1395dbcf075661e3a))
+ - `Tree::lookup_entry(_by_path)()` now actually works ([`145f865`](https://github.com/Byron/gitoxide/commit/145f8658a32c46db1f54d3098cf9371fe6eeec5e))
+</details>
+
+## 0.50.0 (2023-07-22)
+
+### New Features
+
+ - <csr-id-caa8fb9502906fa47546c26bbeb3c546664ad944/> `TreeEntryRefExt` and `TreeEntryExt` to be able to easily attach a repo to it.
+ Also, add `detach()` to types that were missing it.
+ - <csr-id-62cacd4b7a9fc0c0e4c5049f6d0aa7011c8ef923/> `Tree::find_entry()` to easily find an entry in a tree's entries.
+ - <csr-id-c4a1fb1ba461c28ac3ea2482adf5f75721d14706/> add `Repository::archive()` as extra
+ It implements a high-level interface to achieve `git archive` like functionality.
+ - <csr-id-4ee285741e6e1cde3a967980fbf48bab20ddbf68/> optionally make `gix-workspace-stream` available via `Repository::worktree_stream()`
+ That way it's easy to obtain a representation of the worktree
+ in a fully streaming fashion, which is also the basis for
+ `archive`-like functionality.
+
+### New Features (BREAKING)
+
+ - <csr-id-d5e4ee0e6e26ff3feeed1f5aee5bdd0cdc03d1f8/> unify API between `object::tree::Entry` and `object::tree::EntryRef<'_>`
+
+### Bug Fixes (BREAKING)
+
+ - <csr-id-8cad009eafe8e1054a715dc99bb9a884325d5ea5/> `Tree::lookup_entry(_by_path))()` are not mutating anymore; add `Tree::peel_to_entry()` and `peel_to_entry_by_path()`
+ The previous implementation was a crutch that could now be circumvented.
+
+ The new methods allow to reuse a buffer in case the object isn't used or needed further,
+ possibly saving allocations.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 18 commits contributed to the release over the course of 1 calendar day.
+ - 3 days passed between releases.
+ - 6 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-config v0.26.1, gix v0.50.0 ([`d34a4ea`](https://github.com/Byron/gitoxide/commit/d34a4ea27cd83b916c84cf15e1c05da35576db5e))
+ - Release gix-diff v0.33.1, gix-discover v0.22.1, gix-ignore v0.5.1, gix-bitmap v0.2.6, gix-index v0.21.1, gix-mailmap v0.16.1, gix-negotiate v0.5.1, gix-pack v0.40.1, gix-odb v0.50.1, gix-packetline v0.16.4, gix-transport v0.34.1, gix-protocol v0.36.1, gix-revision v0.18.1, gix-refspec v0.14.1, gix-worktree v0.23.0, gix v0.50.0 ([`0062971`](https://github.com/Byron/gitoxide/commit/00629710dffeb10fda340665530353703cf5d129))
+ - Release gix-tempfile v7.0.2, gix-utils v0.1.5, gix-lock v7.0.2, gix-ref v0.33.1, gix-sec v0.8.4, gix-prompt v0.5.4, gix-url v0.21.1, gix-credentials v0.17.1, gix-diff v0.33.1, gix-discover v0.22.1, gix-ignore v0.5.1, gix-bitmap v0.2.6, gix-index v0.21.1, gix-mailmap v0.16.1, gix-negotiate v0.5.1, gix-pack v0.40.1, gix-odb v0.50.1, gix-packetline v0.16.4, gix-transport v0.34.1, gix-protocol v0.36.1, gix-revision v0.18.1, gix-refspec v0.14.1, gix-worktree v0.23.0, gix v0.50.0 ([`107a64e`](https://github.com/Byron/gitoxide/commit/107a64e734580ad9e2c4142db96394529d8072df))
+ - Release gix-features v0.32.1, gix-actor v0.24.1, gix-validate v0.7.7, gix-object v0.33.1, gix-path v0.8.4, gix-glob v0.10.1, gix-quote v0.4.6, gix-attributes v0.16.0, gix-command v0.2.8, gix-packetline-blocking v0.16.4, gix-filter v0.2.0, gix-fs v0.4.1, gix-chunk v0.4.4, gix-commitgraph v0.18.1, gix-hashtable v0.2.4, gix-revwalk v0.4.1, gix-traverse v0.30.1, gix-worktree-stream v0.2.0, gix-archive v0.2.0, gix-config-value v0.12.5, gix-tempfile v7.0.1, gix-utils v0.1.5, gix-lock v7.0.2, gix-ref v0.33.1, gix-sec v0.8.4, gix-prompt v0.5.4, gix-url v0.21.1, gix-credentials v0.17.1, gix-diff v0.33.1, gix-discover v0.22.1, gix-ignore v0.5.1, gix-bitmap v0.2.6, gix-index v0.21.1, gix-mailmap v0.16.1, gix-negotiate v0.5.1, gix-pack v0.40.1, gix-odb v0.50.1, gix-packetline v0.16.4, gix-transport v0.34.1, gix-protocol v0.36.1, gix-revision v0.18.1, gix-refspec v0.14.1, gix-worktree v0.23.0, gix v0.50.0, safety bump 5 crates ([`16295b5`](https://github.com/Byron/gitoxide/commit/16295b58e2581d2e8b8b762816f52baabe871c75))
+ - Prepare more changelogs ([`c4cc5f2`](https://github.com/Byron/gitoxide/commit/c4cc5f261d29f712a101033a18293a97a9d4ae85))
+ - Release gix-date v0.7.1, gix-hash v0.11.4, gix-trace v0.1.3, gix-features v0.32.0, gix-actor v0.24.0, gix-validate v0.7.7, gix-object v0.33.0, gix-path v0.8.4, gix-glob v0.10.0, gix-quote v0.4.6, gix-attributes v0.15.0, gix-command v0.2.7, gix-packetline-blocking v0.16.3, gix-filter v0.1.0, gix-fs v0.4.0, gix-chunk v0.4.4, gix-commitgraph v0.18.0, gix-hashtable v0.2.4, gix-revwalk v0.4.0, gix-traverse v0.30.0, gix-worktree-stream v0.2.0, gix-archive v0.2.0, gix-config-value v0.12.4, gix-tempfile v7.0.1, gix-utils v0.1.5, gix-lock v7.0.2, gix-ref v0.33.0, gix-sec v0.8.4, gix-prompt v0.5.3, gix-url v0.21.0, gix-credentials v0.17.0, gix-diff v0.33.0, gix-discover v0.22.0, gix-ignore v0.5.0, gix-bitmap v0.2.6, gix-index v0.21.0, gix-mailmap v0.16.0, gix-negotiate v0.5.0, gix-pack v0.40.0, gix-odb v0.50.0, gix-packetline v0.16.4, gix-transport v0.34.0, gix-protocol v0.36.0, gix-revision v0.18.0, gix-refspec v0.14.0, gix-worktree v0.22.0, gix v0.49.1 ([`5cb3589`](https://github.com/Byron/gitoxide/commit/5cb3589b74fc5376e02cbfe151e71344e1c417fe))
+ - Update changelogs prior to release ([`2fc66b5`](https://github.com/Byron/gitoxide/commit/2fc66b55097ed494b72d1af939ba5561f71fde97))
+ - Merge branch 'improvements-for-crates-index' ([`3f914e8`](https://github.com/Byron/gitoxide/commit/3f914e8840afc59441c3c463bdc89c53136d583e))
+ - `TreeEntryRefExt` and `TreeEntryExt` to be able to easily attach a repo to it. ([`caa8fb9`](https://github.com/Byron/gitoxide/commit/caa8fb9502906fa47546c26bbeb3c546664ad944))
+ - `Tree::find_entry()` to easily find an entry in a tree's entries. ([`62cacd4`](https://github.com/Byron/gitoxide/commit/62cacd4b7a9fc0c0e4c5049f6d0aa7011c8ef923))
+ - `Tree::lookup_entry(_by_path))()` are not mutating anymore; add `Tree::peel_to_entry()` and `peel_to_entry_by_path()` ([`8cad009`](https://github.com/Byron/gitoxide/commit/8cad009eafe8e1054a715dc99bb9a884325d5ea5))
+ - Unify API between `object::tree::Entry` and `object::tree::EntryRef<'_>` ([`d5e4ee0`](https://github.com/Byron/gitoxide/commit/d5e4ee0e6e26ff3feeed1f5aee5bdd0cdc03d1f8))
+ - J fmt ([`57cab40`](https://github.com/Byron/gitoxide/commit/57cab40f5cb437cc5b0a2c1fc5ae0f91f98bbbcc))
+ - Merge branch 'gix-archive' ([`1dda48b`](https://github.com/Byron/gitoxide/commit/1dda48ba2fccb93ebac00fe3460e923af43c86ce))
+ - Change archive implementation to require the seek bound. ([`61aed0e`](https://github.com/Byron/gitoxide/commit/61aed0e955974f65f4fea042cbae68ea8a2cc2f5))
+ - Add `Repository::archive()` as extra ([`c4a1fb1`](https://github.com/Byron/gitoxide/commit/c4a1fb1ba461c28ac3ea2482adf5f75721d14706))
+ - Optionally make `gix-workspace-stream` available via `Repository::worktree_stream()` ([`4ee2857`](https://github.com/Byron/gitoxide/commit/4ee285741e6e1cde3a967980fbf48bab20ddbf68))
+ - Update license field following SPDX 2.1 license expression standard ([`9064ea3`](https://github.com/Byron/gitoxide/commit/9064ea31fae4dc59a56bdd3a06c0ddc990ee689e))
+</details>
+
+## 0.49.1 (2023-07-19)
+
+A maintenance release without user-facing changes.
+
+### Bug Fixes (BREAKING)
+
+ - <csr-id-8cad009eafe8e1054a715dc99bb9a884325d5ea5/> `Tree::lookup_entry(_by_path))()` are not mutating anymore; add `Tree::peel_to_entry()` and `peel_to_entry_by_path()`
+ The previous implementation was a crutch that could now be circumvented.
+
+ The new methods allow to reuse a buffer in case the object isn't used or needed further,
+ possibly saving allocations.
+
+### New Features (BREAKING)
+
+ - <csr-id-d5e4ee0e6e26ff3feeed1f5aee5bdd0cdc03d1f8/> unify API between `object::tree::Entry` and `object::tree::EntryRef<'_>`
+
+### New Features
+
+ - <csr-id-caa8fb9502906fa47546c26bbeb3c546664ad944/> `TreeEntryRefExt` and `TreeEntryExt` to be able to easily attach a repo to it.
+ Also, add `detach()` to types that were missing it.
+ - <csr-id-62cacd4b7a9fc0c0e4c5049f6d0aa7011c8ef923/> `Tree::find_entry()` to easily find an entry in a tree's entries.
+ - <csr-id-c4a1fb1ba461c28ac3ea2482adf5f75721d14706/> add `Repository::archive()` as extra
+ It implements a high-level interface to achieve `git archive` like functionality.
+ - <csr-id-4ee285741e6e1cde3a967980fbf48bab20ddbf68/> optionally make `gix-workspace-stream` available via `Repository::worktree_stream()`
+ That way it's easy to obtain a representation of the worktree
+ in a fully streaming fashion, which is also the basis for
+ `archive`-like functionality.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 4 commits contributed to the release.
+ - 0 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-prompt v0.5.3, gix v0.49.1, cargo-smart-release v0.20.0 ([`f069852`](https://github.com/Byron/gitoxide/commit/f0698522940c9ba4d45db5a44dce9f21ca29cb4e))
+ - Prepare changelogs prior to release ([`849f508`](https://github.com/Byron/gitoxide/commit/849f5081313c4a44bdaef6848758d0d9a5d1598b))
+ - Merge branch 'smart-release-stability' ([`8629f56`](https://github.com/Byron/gitoxide/commit/8629f569cd5917b6c0c3fd928fde021e7976ee85))
+ - Update git2 API mapping and be clear what stability means as well. ([`64cd396`](https://github.com/Byron/gitoxide/commit/64cd396ab05959e1f843f7ccd53ac5d4585584ad))
+</details>
+
+## 0.49.0 (2023-07-19)
+
+<csr-id-c548780e6ea49453ecdb45b11bf4c5781b105e6b/>
+
+### New Features
+
+ - <csr-id-980c2ba591dce7fc787c418aed85078c19e2d6d4/> Make `EntryMode` available from `gix::object::tree`.
+ Previously one had to go through `gix::objs::tree` which wasn't symmetric
+ with `gix::object::Kind`.
+ - <csr-id-d4a8f8cf6d8b059978719ea314fc8a4bfe26c60d/> Add `Id::header()` and `Id::try_header()` as syblings to `::object()` and `::try_object()`.
+ With the new header related functions one can obtain information about an object more quickly.
+ - <csr-id-b73435b3bf334d5be2931c2ea6a597a9dd51b783/> `Repository::header()` and `::try_header()` to learn about objects, quickly
+ Accessing just the headers of an object is much faster than accessing the entire
+ object. Previously, this method was only available on the `objects` field, now it's
+ available through `Repository` directly.
+ - <csr-id-c05eb2204620a5ff5e04b766009c873a14ae0f9e/> top-level examples that represent fully-fledged command-line applications.
+ Please note that these are just examples, which aren't necessarily
+ production ready in terms of quality or performance.
+ - <csr-id-8cc106aa430d39ac9967dcfb3d293725fc76cb79/> checkouts when cloning now respect attributes and use filters.
+ - <csr-id-8993b777cd0331e7260d7d7d1f820afc79a34b19/> add `Repository::filter_pipeline()` to obtain a primitive to handle data conversions.
+ It's fully configured as git would, and can be used to convert data from git or to git.
+
+### Bug Fixes
+
+ - <csr-id-47ca8465e04bdd13fe2ebfc6f012f8191e3f7896/> properly re-initialize object caches after their configuration changes.
+
+### Refactor (BREAKING)
+
+ - <csr-id-c548780e6ea49453ecdb45b11bf4c5781b105e6b/> move error structs into `repository` module where appropriate.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 28 commits contributed to the release over the course of 11 calendar days.
+ - 19 days passed between releases.
+ - 8 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 1 unique issue was worked on: [#925](https://github.com/Byron/gitoxide/issues/925)
+
+### Thanks Clippy
+
+<csr-read-only-do-not-edit/>
+
+[Clippy](https://github.com/rust-lang/rust-clippy) helped 1 time to make code idiomatic.
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **[#925](https://github.com/Byron/gitoxide/issues/925)**
+ - Remove all copies of repo-initialization files and rework them to be our own. ([`5ac2269`](https://github.com/Byron/gitoxide/commit/5ac22699936dbc5c09c5eefd28b75d48271b286b))
+ * **Uncategorized**
+ - Release gix-filter v0.1.0, gix-ignore v0.5.0, gix-revwalk v0.4.0, gix-traverse v0.30.0, gix-index v0.21.0, gix-mailmap v0.16.0, gix-negotiate v0.5.0, gix-pack v0.40.0, gix-odb v0.50.0, gix-transport v0.34.0, gix-protocol v0.36.0, gix-revision v0.18.0, gix-refspec v0.14.0, gix-worktree v0.22.0, gix v0.49.0 ([`4aca8c2`](https://github.com/Byron/gitoxide/commit/4aca8c2ae2ec588fb65ec4faa0c07c19d219569f))
+ - Release gix-features v0.32.0, gix-actor v0.24.0, gix-glob v0.10.0, gix-attributes v0.15.0, gix-commitgraph v0.18.0, gix-config-value v0.12.4, gix-fs v0.4.0, gix-object v0.33.0, gix-ref v0.33.0, gix-config v0.26.0, gix-command v0.2.7, gix-url v0.21.0, gix-credentials v0.17.0, gix-diff v0.33.0, gix-discover v0.22.0, gix-filter v0.1.0, gix-ignore v0.5.0, gix-revwalk v0.4.0, gix-traverse v0.30.0, gix-index v0.21.0, gix-mailmap v0.16.0, gix-negotiate v0.5.0, gix-pack v0.40.0, gix-odb v0.50.0, gix-transport v0.34.0, gix-protocol v0.36.0, gix-revision v0.18.0, gix-refspec v0.14.0, gix-worktree v0.22.0, gix v0.49.0 ([`68ae3ff`](https://github.com/Byron/gitoxide/commit/68ae3ff9d642ec56f088a6a682a073dc16f4e8ca))
+ - Adjust package versions (by cargo-smart-release) ([`c70e54f`](https://github.com/Byron/gitoxide/commit/c70e54f163c312c87753a506eeaad462e8579bfb))
+ - Prepare changelogs prior to release ([`e4dded0`](https://github.com/Byron/gitoxide/commit/e4dded05138562f9737a7dcfb60570c55769486d))
+ - Just fmt ([`a063c62`](https://github.com/Byron/gitoxide/commit/a063c62e3a30006d837b267e2ce74e70e48b4fb6))
+ - Merge branch 'adjustments-for-crates-index' ([`b82868d`](https://github.com/Byron/gitoxide/commit/b82868d5688d8d4849c47ed3d209a96ee59e69b3))
+ - Make `EntryMode` available from `gix::object::tree`. ([`980c2ba`](https://github.com/Byron/gitoxide/commit/980c2ba591dce7fc787c418aed85078c19e2d6d4))
+ - Add `Id::header()` and `Id::try_header()` as syblings to `::object()` and `::try_object()`. ([`d4a8f8c`](https://github.com/Byron/gitoxide/commit/d4a8f8cf6d8b059978719ea314fc8a4bfe26c60d))
+ - `Repository::header()` and `::try_header()` to learn about objects, quickly ([`b73435b`](https://github.com/Byron/gitoxide/commit/b73435b3bf334d5be2931c2ea6a597a9dd51b783))
+ - Properly re-initialize object caches after their configuration changes. ([`47ca846`](https://github.com/Byron/gitoxide/commit/47ca8465e04bdd13fe2ebfc6f012f8191e3f7896))
+ - Top-level examples that represent fully-fledged command-line applications. ([`c05eb22`](https://github.com/Byron/gitoxide/commit/c05eb2204620a5ff5e04b766009c873a14ae0f9e))
+ - Cargo fmt ([`6121b8f`](https://github.com/Byron/gitoxide/commit/6121b8f6a7da7f263c6e066155f053a1d7c81477))
+ - `git log` example include empty parents and paths ([`bd59bbe`](https://github.com/Byron/gitoxide/commit/bd59bbebddf804a4dd0872127dcc31b5c3b29c2f))
+ - `git log` example now accepts multiple paths. ([`0df9f70`](https://github.com/Byron/gitoxide/commit/0df9f707987c8001c4ca81faf69033c679a75fd5))
+ - `git log` example filter for min/max parents ([`01e9c29`](https://github.com/Byron/gitoxide/commit/01e9c29bf7106b30d8e3e8c71b37eff77bcc38b5))
+ - `git log` example iterator now properly lazy ([`8a6f1e8`](https://github.com/Byron/gitoxide/commit/8a6f1e89fa4d736a2c902be55413887e14885957))
+ - `git log` example now shows merge parents ([`5cbb6a7`](https://github.com/Byron/gitoxide/commit/5cbb6a72c34d926a2782569d8370e54d4c63ab34))
+ - A `git log` example ([`03b3423`](https://github.com/Byron/gitoxide/commit/03b342306c5effac5e8aa92a349385e59785c0b7))
+ - A `git ls-tree` example ([`6f4b431`](https://github.com/Byron/gitoxide/commit/6f4b43101f7b46e38c2f61c2f859347085d8214f))
+ - Thanks clippy ([`3ef32af`](https://github.com/Byron/gitoxide/commit/3ef32af9bf477cbc60d24da8bb3f15d20976e9e0))
+ - Merge branch 'unique-templates' ([`cbb0db8`](https://github.com/Byron/gitoxide/commit/cbb0db80ccc5c29c92f7abd8af2a03c67d86fc2b))
+ - Adapt journey tests to changes in init templates ([`6297d22`](https://github.com/Byron/gitoxide/commit/6297d2201abb97ec999986a7a19b9ddb02114e24))
+ - Merge branch 'integrate-filtering' ([`b19a56d`](https://github.com/Byron/gitoxide/commit/b19a56dcfa9bea86332a84aa4e8fad445e7d1724))
+ - Checkouts when cloning now respect attributes and use filters. ([`8cc106a`](https://github.com/Byron/gitoxide/commit/8cc106aa430d39ac9967dcfb3d293725fc76cb79))
+ - Add `Repository::filter_pipeline()` to obtain a primitive to handle data conversions. ([`8993b77`](https://github.com/Byron/gitoxide/commit/8993b777cd0331e7260d7d7d1f820afc79a34b19))
+ - Move error structs into `repository` module where appropriate. ([`c548780`](https://github.com/Byron/gitoxide/commit/c548780e6ea49453ecdb45b11bf4c5781b105e6b))
+ - Add keys required to deal with worktree conversions and filters. ([`3fbd7b0`](https://github.com/Byron/gitoxide/commit/3fbd7b0c864cf2f1a38ae24e85d47b0b26b271a7))
+</details>
+
+## 0.48.0 (2023-06-29)
+
+<csr-id-fb63f3f07f0f9545be5942bcb66b06040fbc7fe9/>
+<csr-id-3c8e3c1e88d36657d4e6eeaf0819be7fd9341ae1/>
+
+The main feature of this release is support dates prior to the UNIX epoch. Note that this is a feature that isn't supported by `git`, but only by `libgit2`.
+
+### Bug Fixes
+
+ - <csr-id-9cfc4aa318bc44c9e4310db7d3764b015472e1af/> use type for time consistently.
+ This will allow it to be changed more easily later.
+
+### Other
+
+ - <csr-id-fb63f3f07f0f9545be5942bcb66b06040fbc7fe9/> Add incomplete mapping of typical `git2` functions and their counterpart in `gix`.
+ That way the ground-work is laid for making the usage of `gix` easier for those who used
+ `git2` before.
+ - <csr-id-3c8e3c1e88d36657d4e6eeaf0819be7fd9341ae1/> make clear what can happen if rewrite-tracking isn't disabled if it is not desired.
+ Triggered by this `onefetch` PR: https://github.com/o2sh/onefetch/pull/1093
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 15 commits contributed to the release over the course of 6 calendar days.
+ - 6 days passed between releases.
+ - 3 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-transport v0.33.1, gix v0.48.0 ([`f27ca12`](https://github.com/Byron/gitoxide/commit/f27ca128c5f109ad02e4e1a12dc14e93b07bbfcf))
+ - Release gix-lock v7.0.1, gix v0.48.0 ([`5ce81ef`](https://github.com/Byron/gitoxide/commit/5ce81ef16210f0b0b72dfd5710a064ccda96ac1c))
+ - Release gix-glob v0.9.1, gix-attributes v0.14.1, gix-config-value v0.12.3, gix-ref v0.32.1, gix-sec v0.8.3, gix-config v0.25.1, gix-url v0.20.1, gix-credentials v0.16.1, gix-discover v0.21.1, gix-ignore v0.4.1, gix-pack v0.39.1, gix-odb v0.49.1, gix-worktree v0.21.1, gix v0.48.0 ([`69c6a36`](https://github.com/Byron/gitoxide/commit/69c6a36ba14cbef129deebda9fd8870005fefa17))
+ - Release gix-features v0.31.1, gix-path v0.8.3, gix v0.48.0 ([`9ca3464`](https://github.com/Byron/gitoxide/commit/9ca346462806671fbc49643a87cea25ab0da3be8))
+ - Release gix-date v0.7.0, gix-trace v0.1.2, gix-actor v0.23.0, gix-commitgraph v0.17.1, gix-utils v0.1.4, gix-object v0.32.0, gix-ref v0.32.0, gix-config v0.25.0, gix-diff v0.32.0, gix-discover v0.21.0, gix-hashtable v0.2.3, gix-revwalk v0.3.0, gix-traverse v0.29.0, gix-index v0.20.0, gix-mailmap v0.15.0, gix-negotiate v0.4.0, gix-pack v0.39.0, gix-odb v0.49.0, gix-protocol v0.35.0, gix-revision v0.17.0, gix-refspec v0.13.0, gix-worktree v0.21.0, gix v0.48.0, safety bump 20 crates ([`27e8c18`](https://github.com/Byron/gitoxide/commit/27e8c18db5a9a21843381c116a8ed6d9f681b3f8))
+ - Prepare changelogs prior to release ([`00f96fb`](https://github.com/Byron/gitoxide/commit/00f96fb3110a8f81a1bd0d74c757c15b8773c6f6))
+ - Merge branch 'i64-times' ([`b407461`](https://github.com/Byron/gitoxide/commit/b407461d8991db67a5bdb2ab13f518f78a85ed40))
+ - Add incomplete mapping of typical `git2` functions and their counterpart in `gix`. ([`fb63f3f`](https://github.com/Byron/gitoxide/commit/fb63f3f07f0f9545be5942bcb66b06040fbc7fe9))
+ - Adapt to changes in `gix-date` ([`fba45c6`](https://github.com/Byron/gitoxide/commit/fba45c68d57d5f73070a6949556a04187d42e427))
+ - Use type for time consistently. ([`9cfc4aa`](https://github.com/Byron/gitoxide/commit/9cfc4aa318bc44c9e4310db7d3764b015472e1af))
+ - Add a test to see what happens if negative dates are used in commits ([`57a5cd1`](https://github.com/Byron/gitoxide/commit/57a5cd1ca2f8153568c366cd1709be7d4ebec972))
+ - Make clear what can happen if rewrite-tracking isn't disabled if it is not desired. ([`3c8e3c1`](https://github.com/Byron/gitoxide/commit/3c8e3c1e88d36657d4e6eeaf0819be7fd9341ae1))
+ - More tracing information when updating refs ([`6906e0d`](https://github.com/Byron/gitoxide/commit/6906e0d717bb04efb0744eb20afb4c53ebe360c9))
+ - Add more details for negotation phases ([`8341d08`](https://github.com/Byron/gitoxide/commit/8341d0882697b02275ec2bb0f05229ba3b60df3b))
+ - Add a span for each negotiation round ([`ec73479`](https://github.com/Byron/gitoxide/commit/ec7347971163e838e0fdedb0bc6bc88d32d30d8e))
+</details>
+
+## 0.47.0 (2023-06-22)
+
+<csr-id-bcad5c22049d56a25ef69d6c7a3344e78f9a1d4d/>
+
+### Chore
+
+ - <csr-id-bcad5c22049d56a25ef69d6c7a3344e78f9a1d4d/> Add `clippy::redundant-closure-for-method-calls` lint
+
+### New Features
+
+ - <csr-id-3cffa268460eb2d41bd6a30d45778b88db4ec602/> provide basic `tracing` spans for common operations.
+ This is just the beginning and more crates will integrate with it over time.
+ - <csr-id-47c7b0dff9ca82e7c0c60b1dcf1d120f7bec7955/> expose `hashtable` in root for access to optimized-for-object-ids sets and maps.
+
+### Bug Fixes
+
+ - <csr-id-67c06d99dc8387ce566c2fe436c28cdaa041bf07/> make sure empty packs in shallow clones are working as well.
+ - <csr-id-db69e31d8bb73aba886a9a323bfa154a23deacf8/> no-want detection for negotiation phase is now consistent.
+ It being inconsistent was a reason for 'failing to parse server response' which
+ was empty as we didn't provide any wants to the server, but didn't detect that case
+ in the initial negotiation-preparation phase.
+
+ Turns out we didn't detect it as our special handling of implicit tags was not done
+ in the negotiation-preparation phase.
+
+ The fix consists of unifying the filtering phase to all places that needed, so
+ the preparation phase outcome is now consistent with what would have come later.
+
+### New Features (BREAKING)
+
+ - <csr-id-682def03ce6ec93d7bcd2f79eedea52021b77f03/> provide `fetch::outcome::Negotiate` for details on what happened during negotiation.
+ We also remove the `negotiation_rounds` field in favor of a far more detailed `fetch::outcome::Negotiate` struct.
+ - <csr-id-574e0f4786719bd56da2fa218772f879fda282bf/> respect the `core.commitGraph` option.
+ Previously, we would always use the commitgraph when available, but now we only do so
+ if the `core.commitGraph` option is set.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 22 commits contributed to the release over the course of 11 calendar days.
+ - 12 days passed between releases.
+ - 7 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-date v0.6.0, gix-hash v0.11.3, gix-trace v0.1.1, gix-features v0.31.0, gix-actor v0.22.0, gix-path v0.8.2, gix-glob v0.9.0, gix-quote v0.4.5, gix-attributes v0.14.0, gix-chunk v0.4.3, gix-commitgraph v0.17.0, gix-config-value v0.12.2, gix-fs v0.3.0, gix-tempfile v7.0.0, gix-utils v0.1.3, gix-lock v7.0.0, gix-validate v0.7.6, gix-object v0.31.0, gix-ref v0.31.0, gix-sec v0.8.2, gix-config v0.24.0, gix-command v0.2.6, gix-prompt v0.5.2, gix-url v0.20.0, gix-credentials v0.16.0, gix-diff v0.31.0, gix-discover v0.20.0, gix-hashtable v0.2.2, gix-ignore v0.4.0, gix-bitmap v0.2.5, gix-revwalk v0.2.0, gix-traverse v0.28.0, gix-index v0.19.0, gix-mailmap v0.14.0, gix-negotiate v0.3.0, gix-pack v0.38.0, gix-odb v0.48.0, gix-packetline v0.16.3, gix-transport v0.33.0, gix-protocol v0.34.0, gix-revision v0.16.0, gix-refspec v0.12.0, gix-worktree v0.20.0, gix v0.47.0, gitoxide-core v0.29.0, gitoxide v0.27.0, safety bump 30 crates ([`ea9f942`](https://github.com/Byron/gitoxide/commit/ea9f9424e777f10da0e33bb9ffbbefd01c4c5a74))
+ - Prepare changelogs prior to release ([`18b0a37`](https://github.com/Byron/gitoxide/commit/18b0a371941aa2d4d62512437d5daa351ba99ffd))
+ - Add a span for another potentially expensive portion of the negotiation ([`f2e7ec4`](https://github.com/Byron/gitoxide/commit/f2e7ec4d80299933327ebdc932a758d5d9c7f218))
+ - `just fmt` ([`871dd0b`](https://github.com/Byron/gitoxide/commit/871dd0b977caf17159092a4739ba5408403cdb2c))
+ - Merge branch 'corpus' ([`aa16c8c`](https://github.com/Byron/gitoxide/commit/aa16c8ce91452a3e3063cf1cf0240b6014c4743f))
+ - Change MSRV to 1.65 ([`4f635fc`](https://github.com/Byron/gitoxide/commit/4f635fc4429350bae2582d25de86429969d28f30))
+ - Provide basic `tracing` spans for common operations. ([`3cffa26`](https://github.com/Byron/gitoxide/commit/3cffa268460eb2d41bd6a30d45778b88db4ec602))
+ - Merge branch 'gix-revision-graph' ([`036e60a`](https://github.com/Byron/gitoxide/commit/036e60a3ad39ba9b018c0b56454f12fad455c7bb))
+ - Expose `hashtable` in root for access to optimized-for-object-ids sets and maps. ([`47c7b0d`](https://github.com/Byron/gitoxide/commit/47c7b0dff9ca82e7c0c60b1dcf1d120f7bec7955))
+ - Provide `fetch::outcome::Negotiate` for details on what happened during negotiation. ([`682def0`](https://github.com/Byron/gitoxide/commit/682def03ce6ec93d7bcd2f79eedea52021b77f03))
+ - Merge branch 'fix-no-want-detection' ([`71efcbb`](https://github.com/Byron/gitoxide/commit/71efcbba112376b4acaf37d662cdb38d369462be))
+ - Make sure empty packs in shallow clones are working as well. ([`67c06d9`](https://github.com/Byron/gitoxide/commit/67c06d99dc8387ce566c2fe436c28cdaa041bf07))
+ - No-want detection for negotiation phase is now consistent. ([`db69e31`](https://github.com/Byron/gitoxide/commit/db69e31d8bb73aba886a9a323bfa154a23deacf8))
+ - Merge branch 'help-874-redundant-closures' ([`fe59956`](https://github.com/Byron/gitoxide/commit/fe59956ad667303a923d7cfd9ffd72283df41d78))
+ - Add `clippy::redundant-closure-for-method-calls` lint ([`bcad5c2`](https://github.com/Byron/gitoxide/commit/bcad5c22049d56a25ef69d6c7a3344e78f9a1d4d))
+ - Merge branch 'future-dates' ([`8d2e6a9`](https://github.com/Byron/gitoxide/commit/8d2e6a91ac92a033e9e3daad5cffa90263075536))
+ - Respect the `core.commitGraph` option. ([`574e0f4`](https://github.com/Byron/gitoxide/commit/574e0f4786719bd56da2fa218772f879fda282bf))
+ - Adapt to changes in `gix-revision`/`gix-revwalk` ([`1fdaf71`](https://github.com/Byron/gitoxide/commit/1fdaf71d32eb60ad056376d27837ff37d4d314cd))
+ - Adapt to changes in `gix-protocol` ([`b785e81`](https://github.com/Byron/gitoxide/commit/b785e811232d645ad72bfb87459efbd80cb0a399))
+ - Adapt to changes in `gix-traverse` ([`b447f47`](https://github.com/Byron/gitoxide/commit/b447f478b8a5a28c659cef178b2a06b666f89ec3))
+ - Adapt to changes in `gix-actor` ([`4a80e86`](https://github.com/Byron/gitoxide/commit/4a80e868f9530896616e649838e9be64b6d10036))
+ - Adapt to changes in `gix-date` ([`d575336`](https://github.com/Byron/gitoxide/commit/d575336c26e6026e463cd06d88266bb2bdd3e162))
+</details>
+
+## 0.46.0 (2023-06-10)
+
+<csr-id-f0ddc3b9c5a34b7930b965dfb1438f95279a8bde/>
+
+### New Features (BREAKING)
+
+ - <csr-id-7e9f202746d4376332f9779c6e4bd67933d618c7/> `revision::Walk` yields `revision::Info` structs instead of `Id`s.
+ This enables re-use of information that was already obtained, like the parents of
+ a commit and possibly its commit-time.
+
+### Changed (BREAKING)
+
+ - <csr-id-068603a4b7a52eaa397d61212e7aec5a0195ac29/> rename `Repository::commit_graph()` to `::revision_graph()`.
+ THat's a better fix given its locaion in `gix-revision`, while differentiating
+ it further from the lower-level `commit-graph`.
+
+ Also rename `Repository::commit_cache()` to `::commit_graph()` now that the name is free.
+
+### Other
+
+ - <csr-id-f0ddc3b9c5a34b7930b965dfb1438f95279a8bde/> `gix::revision::walk::Platform` now informas about the commitgraph.
+ In short, one should use the `Graph` to obtain the tools necessary for potentially
+ accelerated, custom commit walks.
+
+### New Features
+
+ - <csr-id-cc72e497868636b0e7c943f675bda82860c2b53e/> make it possible to use `config::tree::Key` to more conveniently set values via `config::SnapshotMut::set()`
+ - <csr-id-b2b88dc11d1b745e787596e9b94122238ccaf34c/> use the `commitgraph` if possible and allow its usage to be controlled via `revision::walk::Platform::use_commit_graph(toggle)`.
+ The commitgraph is a data structure to greatly accelerate commit walks. It is now supported and
+ used by default, but can be deactivated if desired.
+
+ Further, add `Repository::commit_cache()` for direct access to just the commit-graph datastructure,
+ without the extras provided by `gix_revision::Graph`.
+ - <csr-id-5d320121533d60fc594792da7838a4f9c661dea0/> add `Repository::index_or_load_from_head()`.
+ That way it's possible to either open the existing worktree index, or create one
+ in-memory by turning our HEAD tree into an index on the fly.
+ - <csr-id-2a698fab7323fd5befd14926bcb9cebf09afc312/> make it possible to use `config::tree::Key` to more conveniently set values via `config::SnapshotMut::set()`
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 15 commits contributed to the release over the course of 2 calendar days.
+ - 3 days passed between releases.
+ - 6 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-attributes v0.13.1, gix-diff v0.30.1, gix-revwalk v0.1.0, gix-traverse v0.27.0, gix-index v0.18.0, gix-revision v0.15.2, gix-negotiate v0.2.1, gix-pack v0.37.0, gix-odb v0.47.0, gix-protocol v0.33.2, gix-worktree v0.19.0, gix v0.46.0, safety bump 7 crates ([`2560a2c`](https://github.com/Byron/gitoxide/commit/2560a2cc3e1d8c60cd812e15696fa4761d036e19))
+ - Prepare changelogs prior to release ([`298f3d7`](https://github.com/Byron/gitoxide/commit/298f3d7359c5b183314d8c584e45dcdd559d88b3))
+ - Improve tests related to the handling of shallow repos ([`d50bfa9`](https://github.com/Byron/gitoxide/commit/d50bfa97f528141e0183558f21a364d969911ef4))
+ - Merge branch 'walk-with-commitgraph' ([`fdee9a2`](https://github.com/Byron/gitoxide/commit/fdee9a22873a13ae644d3dc92f8fe93f8f0266c0))
+ - Adapt to changes in `gix` ([`20f73c8`](https://github.com/Byron/gitoxide/commit/20f73c8224ead1b423a1b6331c9cab65f769d46a))
+ - `revision::Walk` yields `revision::Info` structs instead of `Id`s. ([`7e9f202`](https://github.com/Byron/gitoxide/commit/7e9f202746d4376332f9779c6e4bd67933d618c7))
+ - Rename `Repository::commit_graph()` to `::revision_graph()`. ([`068603a`](https://github.com/Byron/gitoxide/commit/068603a4b7a52eaa397d61212e7aec5a0195ac29))
+ - Use the `commitgraph` if possible and allow its usage to be controlled via `revision::walk::Platform::use_commit_graph(toggle)`. ([`b2b88dc`](https://github.com/Byron/gitoxide/commit/b2b88dc11d1b745e787596e9b94122238ccaf34c))
+ - Adapt to changes in `gix-traverse` ([`1f682fd`](https://github.com/Byron/gitoxide/commit/1f682fd991b9b76a8d37e6852567ff239c0ac0db))
+ - Adapt to changes in `gix-revwalk` ([`f7d95d1`](https://github.com/Byron/gitoxide/commit/f7d95d189af1422a7ba48db1857452e32e1d9db9))
+ - Add `Repository::index_or_load_from_head()`. ([`5d32012`](https://github.com/Byron/gitoxide/commit/5d320121533d60fc594792da7838a4f9c661dea0))
+ - `gix::revision::walk::Platform` now informas about the commitgraph. ([`f0ddc3b`](https://github.com/Byron/gitoxide/commit/f0ddc3b9c5a34b7930b965dfb1438f95279a8bde))
+ - Update changelog with information for the `gix` CLI. ([`4e081f2`](https://github.com/Byron/gitoxide/commit/4e081f2141dcb9919597c53dfd5706cc9439d541))
+ - Make it possible to use `config::tree::Key` to more conveniently set values via `config::SnapshotMut::set()` ([`2a698fa`](https://github.com/Byron/gitoxide/commit/2a698fab7323fd5befd14926bcb9cebf09afc312))
+ - Release gix-protocol v0.33.1 ([`9c99ed3`](https://github.com/Byron/gitoxide/commit/9c99ed30162081a7f26d72e0ed26966ff62d2b1c))
+</details>
+
## 0.45.1 (2023-06-06)
### Bug Fixes
@@ -17,7 +849,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<csr-read-only-do-not-edit/>
- - 2 commits contributed to the release.
+ - 3 commits contributed to the release.
- 1 commit was understood as [conventional](https://www.conventionalcommits.org).
- 0 issues like '(#ID)' were seen in commit messages
@@ -28,6 +860,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<details><summary>view details</summary>
* **Uncategorized**
+ - Release gix-revision v0.15.1, gix v0.45.1 ([`11766a0`](https://github.com/Byron/gitoxide/commit/11766a0a82754fee9918ccdb8eaf92af6d2561ba))
- Merge branch 'adjustments-for-cargo' ([`04f011c`](https://github.com/Byron/gitoxide/commit/04f011c3c3e49e87a3b868d4bf6e77a361b96da8))
- `gix::env::fetch::collate::Error` now considers negotiation errors a sign of corrupt git repos. ([`9010f58`](https://github.com/Byron/gitoxide/commit/9010f586ac46fcea5b8abba8f30a5639ed6b9225))
</details>
diff --git a/vendor/gix/Cargo.lock b/vendor/gix/Cargo.lock
index ff624f434..9f8f5a075 100644
--- a/vendor/gix/Cargo.lock
+++ b/vendor/gix/Cargo.lock
@@ -3,6 +3,15 @@
version = 3
[[package]]
+name = "addr2line"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -21,10 +30,19 @@ dependencies = [
]
[[package]]
+name = "aho-corasick"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "anyhow"
-version = "1.0.70"
+version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
+checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
[[package]]
name = "arc-swap"
@@ -34,9 +52,9 @@ checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
name = "arrayvec"
-version = "0.7.2"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
+checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "async-attributes"
@@ -50,9 +68,9 @@ dependencies = [
[[package]]
name = "async-channel"
-version = "1.8.0"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833"
+checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
dependencies = [
"concurrent-queue",
"event-listener",
@@ -68,7 +86,7 @@ dependencies = [
"async-lock",
"async-task",
"concurrent-queue",
- "fastrand",
+ "fastrand 1.9.0",
"futures-lite",
"slab",
]
@@ -102,9 +120,9 @@ dependencies = [
"log",
"parking",
"polling",
- "rustix",
+ "rustix 0.37.23",
"slab",
- "socket2",
+ "socket2 0.4.9",
"waker-fn",
]
@@ -152,13 +170,13 @@ checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
[[package]]
name = "async-trait"
-version = "0.1.68"
+version = "0.1.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.15",
+ "syn 2.0.29",
]
[[package]]
@@ -174,10 +192,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
+name = "backtrace"
+version = "0.3.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
name = "base64"
-version = "0.21.0"
+version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "bitflags"
@@ -187,9 +220,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.1.0"
+version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c70beb79cbb5ce9c4f8e20849978f34225931f665bb49efa6982875a4d5facb3"
+checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
dependencies = [
"serde",
]
@@ -213,19 +246,18 @@ dependencies = [
"async-lock",
"async-task",
"atomic-waker",
- "fastrand",
+ "fastrand 1.9.0",
"futures-lite",
"log",
]
[[package]]
name = "bstr"
-version = "1.4.0"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09"
+checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05"
dependencies = [
"memchr",
- "once_cell",
"regex-automata",
"serde",
]
@@ -241,9 +273,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.12.0"
+version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
+checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "bytes"
@@ -258,6 +290,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38fcc2979eff34a4b84e1cf9a1e3da42a7d44b3b690a40cdcb23e3d556cfb2e5"
[[package]]
+name = "byteyarn"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7534301c0ea17abb4db06d75efc7b4b0fa360fce8e175a4330d721c71c942ff"
+
+[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -311,9 +349,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "cpufeatures"
-version = "0.2.7"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
+checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
dependencies = [
"libc",
]
@@ -364,9 +402,9 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.14"
+version = "0.9.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
dependencies = [
"autocfg",
"cfg-if",
@@ -387,9 +425,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
-version = "0.8.15"
+version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
dependencies = [
"cfg-if",
]
@@ -405,16 +443,6 @@ dependencies = [
]
[[package]]
-name = "ctor"
-version = "0.1.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
-dependencies = [
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
name = "curl"
version = "0.4.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -425,15 +453,15 @@ dependencies = [
"openssl-probe",
"openssl-sys",
"schannel",
- "socket2",
+ "socket2 0.4.9",
"winapi",
]
[[package]]
name = "curl-sys"
-version = "0.4.61+curl-8.0.1"
+version = "0.4.63+curl-8.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14d05c10f541ae6f3bc5b3d923c20001f47db7d5f0b2bc6ad16490133842db79"
+checksum = "aeb0fef7046022a1e2ad67a004978f0e3cacb9e3123dc62ce768f92197b771dc"
dependencies = [
"cc",
"libc",
@@ -446,12 +474,12 @@ dependencies = [
[[package]]
name = "dashmap"
-version = "5.4.0"
+version = "5.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"
+checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d"
dependencies = [
"cfg-if",
- "hashbrown 0.12.3",
+ "hashbrown 0.14.0",
"lock_api",
"once_cell",
"parking_lot_core",
@@ -459,15 +487,15 @@ dependencies = [
[[package]]
name = "data-encoding"
-version = "2.3.3"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
+checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "digest"
-version = "0.10.6"
+version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
@@ -523,7 +551,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
@@ -543,6 +571,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
+name = "faster-hex"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9042d281a5eec0f2387f8c3ea6c4514e2cf2732c90a85aaf383b761ee3b290d"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "fastrand"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -552,6 +589,12 @@ dependencies = [
]
[[package]]
+name = "fastrand"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
+
+[[package]]
name = "filetime"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -560,14 +603,14 @@ dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.2.16",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
name = "flate2"
-version = "1.0.25"
+version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
dependencies = [
"crc32fast",
"libz-ng-sys",
@@ -597,9 +640,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
@@ -631,7 +674,7 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
dependencies = [
- "fastrand",
+ "fastrand 1.9.0",
"futures-core",
"futures-io",
"memchr",
@@ -641,6 +684,17 @@ dependencies = [
]
[[package]]
+name = "futures-macro"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
+]
+
+[[package]]
name = "futures-sink"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -660,6 +714,7 @@ checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [
"futures-core",
"futures-io",
+ "futures-macro",
"futures-task",
"memchr",
"pin-project-lite",
@@ -679,9 +734,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.9"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
@@ -689,13 +744,20 @@ dependencies = [
]
[[package]]
+name = "gimli"
+version = "0.27.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
+
+[[package]]
name = "gix"
-version = "0.45.1"
+version = "0.54.1"
dependencies = [
"anyhow",
"async-std",
"document-features",
"gix-actor",
+ "gix-archive",
"gix-attributes",
"gix-commitgraph",
"gix-config",
@@ -704,6 +766,7 @@ dependencies = [
"gix-diff",
"gix-discover",
"gix-features",
+ "gix-filter",
"gix-fs",
"gix-glob",
"gix-hash",
@@ -711,28 +774,36 @@ dependencies = [
"gix-ignore",
"gix-index",
"gix-lock",
+ "gix-macros",
"gix-mailmap",
"gix-negotiate",
"gix-object",
"gix-odb",
"gix-pack",
"gix-path",
+ "gix-pathspec",
"gix-prompt",
"gix-protocol",
"gix-ref",
"gix-refspec",
"gix-revision",
+ "gix-revwalk",
"gix-sec",
+ "gix-status",
+ "gix-submodule",
"gix-tempfile",
+ "gix-trace",
"gix-transport",
"gix-traverse",
"gix-url",
"gix-utils",
"gix-validate",
"gix-worktree",
+ "gix-worktree-state",
+ "gix-worktree-stream",
"is_ci",
- "log",
"once_cell",
+ "parking_lot",
"prodash",
"regex",
"reqwest",
@@ -747,31 +818,44 @@ dependencies = [
[[package]]
name = "gix-actor"
-version = "0.21.0"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fe73f9f6be1afbf1bd5be919a9636fa560e2f14d42262a934423ed6760cd838"
+checksum = "08c60e982c5290897122d4e2622447f014a2dadd5a18cb73d50bb91b31645e27"
dependencies = [
"bstr",
"btoi",
"gix-date",
"itoa",
- "nom",
"serde",
"thiserror",
+ "winnow",
+]
+
+[[package]]
+name = "gix-archive"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab71635f7fb38ad4cc7da7e98af79e3010e35b05de5cb6eb79b2da68ab93eac7"
+dependencies = [
+ "bstr",
+ "gix-date",
+ "gix-object",
+ "gix-worktree-stream",
+ "thiserror",
]
[[package]]
name = "gix-attributes"
-version = "0.13.0"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "644d4e1182dd21af10f455265eb15cb10ca3ae9c63475d7247e538e62ebacc56"
+checksum = "2451665e70709ba4753b623ef97511ee98c4a73816b2c5b5df25678d607ed820"
dependencies = [
"bstr",
+ "byteyarn",
"gix-glob",
"gix-path",
"gix-quote",
- "kstring",
- "log",
+ "gix-trace",
"serde",
"smallvec",
"thiserror",
@@ -780,36 +864,36 @@ dependencies = [
[[package]]
name = "gix-bitmap"
-version = "0.2.4"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc02feb20ad313d52a450852f2005c2205d24f851e74d82b7807cbe12c371667"
+checksum = "0ccab4bc576844ddb51b78d81b4a42d73e6229660fa614dfc3d3999c874d1959"
dependencies = [
"thiserror",
]
[[package]]
name = "gix-chunk"
-version = "0.4.2"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7acf3bc6c4b91e8fb260086daf5e105ea3a6d913f5fd3318137f7e309d6e540"
+checksum = "5b42ea64420f7994000130328f3c7a2038f639120518870436d31b8bde704493"
dependencies = [
"thiserror",
]
[[package]]
name = "gix-command"
-version = "0.2.5"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6141b70cfb21255223e42f3379855037cbbe8673b58dd8318d2f09b516fad1"
+checksum = "0f28f654184b5f725c5737c7e4f466cbd8f0102ac352d5257eeab19647ee4256"
dependencies = [
"bstr",
]
[[package]]
name = "gix-commitgraph"
-version = "0.16.0"
+version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8490ae1b3d55c47e6a71d247c082304a2f79f8d0332c1a2f5693d42a2021a09"
+checksum = "e75a975ee22cf0a002bfe9b5d5cb3d2a88e263a8a178cd7509133cff10f4df8a"
dependencies = [
"bstr",
"gix-chunk",
@@ -822,9 +906,9 @@ dependencies = [
[[package]]
name = "gix-config"
-version = "0.23.0"
+version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51f310120ae1ba8f0ca52fb22876ce9bad5b15c8ffb3eb7302e4b64a3b9f681c"
+checksum = "c171514b40487d3f677ae37efc0f45ac980e3169f23c27eb30a70b47fdf88ab5"
dependencies = [
"bstr",
"gix-config-value",
@@ -833,22 +917,21 @@ dependencies = [
"gix-path",
"gix-ref",
"gix-sec",
- "log",
"memchr",
- "nom",
"once_cell",
"smallvec",
"thiserror",
"unicode-bom",
+ "winnow",
]
[[package]]
name = "gix-config-value"
-version = "0.12.1"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f216df1c33e6e1555923eff0096858a879e8aaadd35b5d788641e4e8064c892"
+checksum = "ea7505b97f4d8e7933e29735a568ba2f86d8de466669d9f0e8321384f9972f47"
dependencies = [
- "bitflags 2.1.0",
+ "bitflags 2.3.3",
"bstr",
"gix-path",
"libc",
@@ -857,9 +940,9 @@ dependencies = [
[[package]]
name = "gix-credentials"
-version = "0.15.0"
+version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6f89fea8acd28f5ef8fa5042146f1637afd4d834bc8f13439d8fd1e5aca0d65"
+checksum = "46900b884cc5af6a6c141ee741607c0c651a4e1d33614b8d888a1ba81cc0bc8a"
dependencies = [
"bstr",
"gix-command",
@@ -874,9 +957,9 @@ dependencies = [
[[package]]
name = "gix-date"
-version = "0.5.1"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc164145670e9130a60a21670d9b6f0f4f8de04e5dd256c51fa5a0340c625902"
+checksum = "fc7df669639582dc7c02737642f76890b03b5544e141caba68a7d6b4eb551e0d"
dependencies = [
"bstr",
"itoa",
@@ -887,9 +970,9 @@ dependencies = [
[[package]]
name = "gix-diff"
-version = "0.30.0"
+version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bed89e910e19b48d31132b2b5392cef60786dd081cca5d0e31de32064f7300eb"
+checksum = "788ddb152c388206e81f36bcbb574e7ed7827c27d8fa62227b34edc333d8928c"
dependencies = [
"gix-hash",
"gix-object",
@@ -899,9 +982,9 @@ dependencies = [
[[package]]
name = "gix-discover"
-version = "0.19.0"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aba9c6c0d1f2b2efe65581de73de4305004612d49c83773e783202a7ef204f46"
+checksum = "69507643d75a0ea9a402fcf73ced517d2b95cc95385904ac09d03e0b952fde33"
dependencies = [
"bstr",
"dunce",
@@ -914,9 +997,9 @@ dependencies = [
[[package]]
name = "gix-features"
-version = "0.30.0"
+version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a8c493409bf6060d408eec9bbdd1b12ea351266b50012e2a522f75dfc7b8314"
+checksum = "9b9ff423ae4983f762659040d13dd7a5defbd54b6a04ac3cc7347741cec828cd"
dependencies = [
"bytes",
"bytesize",
@@ -924,6 +1007,7 @@ dependencies = [
"crossbeam-channel",
"flate2",
"gix-hash",
+ "gix-trace",
"jwalk",
"libc",
"once_cell",
@@ -936,21 +1020,41 @@ dependencies = [
]
[[package]]
+name = "gix-filter"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1be40d28cd41445bb6cd52c4d847d915900e5466f7433eaee6a9e0a3d1d88b08"
+dependencies = [
+ "bstr",
+ "encoding_rs",
+ "gix-attributes",
+ "gix-command",
+ "gix-hash",
+ "gix-object",
+ "gix-packetline-blocking",
+ "gix-path",
+ "gix-quote",
+ "gix-trace",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
name = "gix-fs"
-version = "0.2.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30da8997008adb87f94e15beb7ee229f8a48e97af585a584bfee4a5a1880aab5"
+checksum = "09815faba62fe9b32d918b75a554686c98e43f7d48c43a80df58eb718e5c6635"
dependencies = [
"gix-features",
]
[[package]]
name = "gix-glob"
-version = "0.8.0"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd0ade1e80ab1f079703d1824e1daf73009096386aa7fd2f0477f6e4ac0a558e"
+checksum = "a9d76e85f11251dcf751d2c5e918a14f562db5be6f727fd24775245653e9b19d"
dependencies = [
- "bitflags 2.1.0",
+ "bitflags 2.3.3",
"bstr",
"gix-features",
"gix-path",
@@ -959,31 +1063,31 @@ dependencies = [
[[package]]
name = "gix-hash"
-version = "0.11.2"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee181c85d3955f54c4426e6bfaeeada4428692e1a39b8788c2ac7785fc301dd8"
+checksum = "2ccf425543779cddaa4a7c62aba3fa9d90ea135b160be0a72dd93c063121ad4a"
dependencies = [
- "hex",
+ "faster-hex",
"serde",
"thiserror",
]
[[package]]
name = "gix-hashtable"
-version = "0.2.1"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd259bd0d96e6153e357a8cdaca76c48e103fd34208b6c0ce77b1ad995834bd2"
+checksum = "409268480841ad008e81c17ca5a293393fbf9f2b6c2f85b8ab9de1f0c5176a16"
dependencies = [
"gix-hash",
- "hashbrown 0.13.2",
+ "hashbrown 0.14.0",
"parking_lot",
]
[[package]]
name = "gix-ignore"
-version = "0.3.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc6f7f101a0ccce808dbf7008ba131dede94e20257e7bde7a44cbb2f8c775625"
+checksum = "b048f443a1f6b02da4205c34d2e287e3fd45d75e8e2f06cfb216630ea9bff5e3"
dependencies = [
"bstr",
"gix-glob",
@@ -994,16 +1098,17 @@ dependencies = [
[[package]]
name = "gix-index"
-version = "0.17.0"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "616ba958fabfb11263fa042c35690d48a6c7be4e9277e2c7e24ff263b3fe7b82"
+checksum = "f54d63a9d13c13088f41f5a3accbec284e492ac8f4f707fcc307c139622e17b7"
dependencies = [
- "bitflags 2.1.0",
+ "bitflags 2.3.3",
"bstr",
"btoi",
"filetime",
"gix-bitmap",
"gix-features",
+ "gix-fs",
"gix-hash",
"gix-lock",
"gix-object",
@@ -1017,9 +1122,9 @@ dependencies = [
[[package]]
name = "gix-lock"
-version = "6.0.0"
+version = "10.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ec5d5e6f07316d3553aa7425e3ecd935ec29882556021fe1696297a448af8d2"
+checksum = "47fc96fa8b6b6d33555021907c81eb3b27635daecf6e630630bdad44f8feaa95"
dependencies = [
"gix-tempfile",
"gix-utils",
@@ -1027,59 +1132,73 @@ dependencies = [
]
[[package]]
+name = "gix-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d8acb5ee668d55f0f2d19a320a3f9ef67a6999ad483e11135abcc2464ed18b6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
+]
+
+[[package]]
name = "gix-mailmap"
-version = "0.13.0"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4653701922c920e009f1bc4309feaff14882ade017770788f9a150928da3fa6a"
+checksum = "40f00fa96e29e066ef208f5d13e0f5f95fa70c3ae4bd4f0234272ed4d708a7db"
dependencies = [
"bstr",
"gix-actor",
+ "gix-date",
"serde",
"thiserror",
]
[[package]]
name = "gix-negotiate"
-version = "0.2.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82297847a7ad2d920707da5fc9ca8bb5eadf2891948dbe65625db1ffaa9803f9"
+checksum = "6f1697bf9911c6d1b8d709b9e6ef718cb5ea5821a1b7991520125a8134448004"
dependencies = [
- "bitflags 2.1.0",
+ "bitflags 2.3.3",
"gix-commitgraph",
+ "gix-date",
"gix-hash",
"gix-object",
- "gix-revision",
+ "gix-revwalk",
"smallvec",
"thiserror",
]
[[package]]
name = "gix-object"
-version = "0.30.0"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8926c8f51c44dec3e709cb5dbc93deb9e8d4064c43c9efc54c158dcdfe8446c7"
+checksum = "1e7e19616c67967374137bae83e950e9b518a9ea8a605069bd6716ada357fd6f"
dependencies = [
"bstr",
"btoi",
"gix-actor",
+ "gix-date",
"gix-features",
"gix-hash",
"gix-validate",
- "hex",
"itoa",
- "nom",
"serde",
"smallvec",
"thiserror",
+ "winnow",
]
[[package]]
name = "gix-odb"
-version = "0.46.0"
+version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b234d806278eeac2f907c8b5a105c4ba537230c1a9d9236d822bf0db291f8f3"
+checksum = "8d6a392c6ba3a2f133cdc63120e9bc7aec81eef763db372c817de31febfe64bf"
dependencies = [
"arc-swap",
+ "gix-date",
"gix-features",
"gix-hash",
"gix-object",
@@ -1094,20 +1213,18 @@ dependencies = [
[[package]]
name = "gix-pack"
-version = "0.36.0"
+version = "0.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d2a14cb3156037eedb17d6cb7209b7180522b8949b21fd0fe3184c0a1d0af88"
+checksum = "7536203a45b31e1bc5694bbf90ba8da1b736c77040dd6a520db369f371eb1ab3"
dependencies = [
"clru",
"gix-chunk",
- "gix-diff",
"gix-features",
"gix-hash",
"gix-hashtable",
"gix-object",
"gix-path",
"gix-tempfile",
- "gix-traverse",
"memmap2",
"parking_lot",
"serde",
@@ -1118,48 +1235,75 @@ dependencies = [
[[package]]
name = "gix-packetline"
-version = "0.16.2"
+version = "0.16.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74414f89a6b72fa1a530ce8e646faf1a05499c3f4a5c15441d17ae8c978578eb"
+checksum = "d6df0b75361353e7c0a6d72d49617a37379a7a22cba4569ae33a7720a4c8755a"
dependencies = [
"bstr",
+ "faster-hex",
"futures-io",
"futures-lite",
- "hex",
"pin-project-lite",
"thiserror",
]
[[package]]
+name = "gix-packetline-blocking"
+version = "0.16.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d8395f7501c84d6a1fe902035fdfd8cd86d89e2dd6be0200ec1a72fd3c92d39"
+dependencies = [
+ "bstr",
+ "faster-hex",
+ "thiserror",
+]
+
+[[package]]
name = "gix-path"
-version = "0.8.1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1226f2e50adeb4d76c754c1856c06f13a24cad1624801653fbf09b869e5b808"
+checksum = "6a1d370115171e3ae03c5c6d4f7d096f2981a40ddccb98dfd704c773530ba73b"
dependencies = [
"bstr",
+ "gix-trace",
"home",
"once_cell",
"thiserror",
]
[[package]]
+name = "gix-pathspec"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3e26c9b47c51be73f98d38c84494bd5fb99334c5d6fda14ef5d036d50a9e5fd"
+dependencies = [
+ "bitflags 2.3.3",
+ "bstr",
+ "gix-attributes",
+ "gix-config-value",
+ "gix-glob",
+ "gix-path",
+ "thiserror",
+]
+
+[[package]]
name = "gix-prompt"
-version = "0.5.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e15fe57fa48572b7d3bf465d6a2a0351cd3c55cba74fd5f0b9c23689f9c1a31e"
+checksum = "5c9a913769516f5e9d937afac206fb76428e3d7238e538845842887fda584678"
dependencies = [
"gix-command",
"gix-config-value",
"parking_lot",
- "rustix",
+ "rustix 0.38.4",
"thiserror",
]
[[package]]
name = "gix-protocol"
-version = "0.33.0"
+version = "0.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "182667706e9a7e87315a32833a1c84048bbd2f540758dabdd5a5b5742a7820f3"
+checksum = "cc7b700dc20cc9be8a5130a1fd7e10c34117ffa7068431c8c24d963f0a2e0c9b"
dependencies = [
"async-trait",
"bstr",
@@ -1167,20 +1311,21 @@ dependencies = [
"futures-io",
"futures-lite",
"gix-credentials",
+ "gix-date",
"gix-features",
"gix-hash",
"gix-transport",
"maybe-async",
- "nom",
"serde",
"thiserror",
+ "winnow",
]
[[package]]
name = "gix-quote"
-version = "0.4.4"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29d59489bff95b06dcdabe763b7266d3dc0a628cac1ac1caf65a7ca0a43eeae0"
+checksum = "475c86a97dd0127ba4465fbb239abac9ea10e68301470c9791a6dd5351cdc905"
dependencies = [
"bstr",
"btoi",
@@ -1189,11 +1334,12 @@ dependencies = [
[[package]]
name = "gix-ref"
-version = "0.30.0"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebdd999256f4ce8a5eefa89999879c159c263f3493a951d62aa5ce42c0397e1c"
+checksum = "22e6b749660b613641769edc1954132eb8071a13c32224891686091bef078de4"
dependencies = [
"gix-actor",
+ "gix-date",
"gix-features",
"gix-fs",
"gix-hash",
@@ -1203,16 +1349,16 @@ dependencies = [
"gix-tempfile",
"gix-validate",
"memmap2",
- "nom",
"serde",
"thiserror",
+ "winnow",
]
[[package]]
name = "gix-refspec"
-version = "0.11.0"
+version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72bfd622abc86dd8ad1ec51b9eb77b4f1a766b94e3a1b87cf4a022c5b5570cf4"
+checksum = "0895cb7b1e70f3c3bd4550c329e9f5caf2975f97fcd4238e05754e72208ef61e"
dependencies = [
"bstr",
"gix-hash",
@@ -1224,28 +1370,43 @@ dependencies = [
[[package]]
name = "gix-revision"
-version = "0.15.1"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9abc4f68f85f42029ade0bece087aef7071016335772f0c7cb7d425aaaed3b33"
+checksum = "c8c4b15cf2ab7a35f5bcb3ef146187c8d36df0177e171ca061913cbaaa890e89"
dependencies = [
"bstr",
- "gix-commitgraph",
"gix-date",
"gix-hash",
"gix-hashtable",
"gix-object",
+ "gix-revwalk",
+ "gix-trace",
"serde",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-revwalk"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9870c6b1032f2084567710c3b2106ac603377f8d25766b8a6b7c33e6e3ca279"
+dependencies = [
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
"smallvec",
"thiserror",
]
[[package]]
name = "gix-sec"
-version = "0.8.1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2b7b38b766eb95dcc5350a9c450030b69892c0902fa35f4a6d0809273bd9dae"
+checksum = "92b9542ac025a8c02ed5d17b3fc031a111a384e859d0be3532ec4d58c40a0f28"
dependencies = [
- "bitflags 2.1.0",
+ "bitflags 2.3.3",
"gix-path",
"libc",
"serde",
@@ -1253,10 +1414,43 @@ dependencies = [
]
[[package]]
+name = "gix-status"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "082801c42ba707f2407b5cce3d99b89cfa84f3794962946dc94cfdc00ae522fa"
+dependencies = [
+ "bstr",
+ "filetime",
+ "gix-features",
+ "gix-fs",
+ "gix-hash",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "gix-pathspec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-submodule"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0150e82e9282d3f2ab2dd57a22f9f6c3447b9d9856e5321ac92d38e3e0e2b7"
+dependencies = [
+ "bstr",
+ "gix-config",
+ "gix-path",
+ "gix-pathspec",
+ "gix-refspec",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
name = "gix-tempfile"
-version = "6.0.0"
+version = "10.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3785cb010e9dc5c446dfbf02bc1119fc17d3a48a27c029efcb3a3c32953eb10"
+checksum = "5ae0978f3e11dc57290ee75ac2477c815bca1ce2fa7ed5dc5f16db067410ac4d"
dependencies = [
"dashmap",
"gix-fs",
@@ -1269,10 +1463,16 @@ dependencies = [
]
[[package]]
+name = "gix-trace"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96b6d623a1152c3facb79067d6e2ecdae48130030cf27d6eb21109f13bd7b836"
+
+[[package]]
name = "gix-transport"
-version = "0.32.0"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64a39ffed9a9078ed700605e064b15d7c6ae50aa65e7faa36ca6919e8081df15"
+checksum = "b9ec726e6a245e68ace59a34126a1d679de60360676612985e70b0d3b102fb4e"
dependencies = [
"async-std",
"async-trait",
@@ -1296,21 +1496,25 @@ dependencies = [
[[package]]
name = "gix-traverse"
-version = "0.26.0"
+version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0842e984cb4bf26339dc559f3a1b8bf8cdb83547799b2b096822a59f87f33d9"
+checksum = "22ef04ab3643acba289b5cedd25d6f53c0430770b1d689d1d654511e6fb81ba0"
dependencies = [
+ "gix-commitgraph",
+ "gix-date",
"gix-hash",
"gix-hashtable",
"gix-object",
+ "gix-revwalk",
+ "smallvec",
"thiserror",
]
[[package]]
name = "gix-url"
-version = "0.19.0"
+version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1663df25ac42047a2547618d2a6979a26f478073f6306997429235d2cd4c863"
+checksum = "6125ecf46e8c68bf7202da6cad239831daebf0247ffbab30210d72f3856e420f"
dependencies = [
"bstr",
"gix-features",
@@ -1323,18 +1527,18 @@ dependencies = [
[[package]]
name = "gix-utils"
-version = "0.1.2"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbcfcb150c7ef553d76988467d223254045bdcad0dc6724890f32fbe96415da5"
+checksum = "b85d89dc728613e26e0ed952a19583744e7f5240fcd4aa30d6c824ffd8b52f0f"
dependencies = [
- "fastrand",
+ "fastrand 2.0.0",
]
[[package]]
name = "gix-validate"
-version = "0.7.5"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57ea5845b506c7728b9d89f4227cc369a5fc5a1d5b26c3add0f0d323413a3a60"
+checksum = "e05cab2b03a45b866156e052aa38619f4ece4adcb2f79978bfc249bc3b21b8c5"
dependencies = [
"bstr",
"thiserror",
@@ -1342,12 +1546,11 @@ dependencies = [
[[package]]
name = "gix-worktree"
-version = "0.18.0"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d388ad962e8854402734a7387af8790f6bdbc8d05349052dab16ca4a0def50f6"
+checksum = "9f5e32972801bd82d56609e6fc84efc358fa1f11f25c5e83b7807ee2280f14fe"
dependencies = [
"bstr",
- "filetime",
"gix-attributes",
"gix-features",
"gix-fs",
@@ -1357,8 +1560,44 @@ dependencies = [
"gix-index",
"gix-object",
"gix-path",
- "io-close",
"serde",
+]
+
+[[package]]
+name = "gix-worktree-state"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3aeb06960f2c5ac9e4cdb6b38eb3c2b99d5e525e68285fef21ed17dfbd597ad"
+dependencies = [
+ "bstr",
+ "gix-features",
+ "gix-filter",
+ "gix-fs",
+ "gix-glob",
+ "gix-hash",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "gix-worktree",
+ "io-close",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-worktree-stream"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c89fe93a12e45cc3ad6ba429a7dd7506b03d7d406374a65ad9998b5cb2627569"
+dependencies = [
+ "gix-attributes",
+ "gix-features",
+ "gix-filter",
+ "gix-fs",
+ "gix-hash",
+ "gix-object",
+ "gix-path",
+ "gix-traverse",
+ "parking_lot",
"thiserror",
]
@@ -1376,9 +1615,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.3.18"
+version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
+checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049"
dependencies = [
"bytes",
"fnv",
@@ -1401,9 +1640,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
-version = "0.13.2"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
+checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "heck"
@@ -1413,32 +1652,17 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
-
-[[package]]
-name = "hex"
-version = "0.4.3"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
[[package]]
name = "home"
-version = "0.5.4"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"
+checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
dependencies = [
- "winapi",
+ "windows-sys",
]
[[package]]
@@ -1494,9 +1718,9 @@ checksum = "86cce260d758a9aa3d7c4b99d55c815a540f8a37514ba6046ab6be402a157cb0"
[[package]]
name = "hyper"
-version = "0.14.26"
+version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
+checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [
"bytes",
"futures-channel",
@@ -1509,7 +1733,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
- "socket2",
+ "socket2 0.4.9",
"tokio",
"tower-service",
"tracing",
@@ -1518,10 +1742,11 @@ dependencies = [
[[package]]
name = "hyper-rustls"
-version = "0.23.2"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
+checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
dependencies = [
+ "futures-util",
"http",
"hyper",
"rustls",
@@ -1555,9 +1780,9 @@ dependencies = [
[[package]]
name = "idna"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@@ -1604,32 +1829,32 @@ dependencies = [
[[package]]
name = "io-lifetimes"
-version = "1.0.10"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
- "hermit-abi 0.3.1",
+ "hermit-abi",
"libc",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
name = "ipconfig"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be"
+checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
dependencies = [
- "socket2",
+ "socket2 0.5.3",
"widestring",
- "winapi",
+ "windows-sys",
"winreg",
]
[[package]]
name = "ipnet"
-version = "2.7.2"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
+checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
[[package]]
name = "is_ci"
@@ -1639,15 +1864,15 @@ checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
[[package]]
name = "itoa"
-version = "1.0.6"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "js-sys"
-version = "0.3.61"
+version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [
"wasm-bindgen",
]
@@ -1663,16 +1888,6 @@ dependencies = [
]
[[package]]
-name = "kstring"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747"
-dependencies = [
- "serde",
- "static_assertions",
-]
-
-[[package]]
name = "kv-log-macro"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1689,15 +1904,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.142"
+version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "libz-ng-sys"
-version = "1.1.8"
+version = "1.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4399ae96a9966bf581e726de86969f803a81b7ce795fcd5480e640589457e0f2"
+checksum = "3dd9f43e75536a46ee0f92b758f6b63846e594e86638c61a9251338a65baea63"
dependencies = [
"cmake",
"libc",
@@ -1705,9 +1920,9 @@ dependencies = [
[[package]]
name = "libz-sys"
-version = "1.1.8"
+version = "1.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf"
+checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b"
dependencies = [
"cc",
"libc",
@@ -1723,9 +1938,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
-version = "0.3.3"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b085a4f2cde5781fc4b1717f2e86c62f5cda49de7ba99a7c2eae02b61c9064c"
+checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
[[package]]
name = "litrs"
@@ -1735,9 +1956,9 @@ checksum = "f9275e0933cf8bb20f008924c0cb07a0692fe54d8064996520bf998de9eb79aa"
[[package]]
name = "lock_api"
-version = "0.4.9"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
@@ -1745,11 +1966,10 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.17"
+version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
dependencies = [
- "cfg-if",
"value-bag",
]
@@ -1787,24 +2007,24 @@ dependencies = [
[[package]]
name = "memchr"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "76fc44e2588d5b436dbc3c6cf62aef290f90dab6235744a93dfe1cc18f451e2c"
[[package]]
name = "memmap2"
-version = "0.5.10"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
+checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6"
dependencies = [
"libc",
]
[[package]]
name = "memoffset"
-version = "0.8.0"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
dependencies = [
"autocfg",
]
@@ -1816,30 +2036,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
-name = "minimal-lexical"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-
-[[package]]
name = "miniz_oxide"
-version = "0.6.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
-version = "0.8.6"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
- "log",
"wasi",
- "windows-sys 0.45.0",
+ "windows-sys",
]
[[package]]
@@ -1861,16 +2074,6 @@ dependencies = [
]
[[package]]
-name = "nom"
-version = "7.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
-dependencies = [
- "memchr",
- "minimal-lexical",
-]
-
-[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1881,11 +2084,11 @@ dependencies = [
[[package]]
name = "num_cpus"
-version = "1.15.0"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
- "hermit-abi 0.2.6",
+ "hermit-abi",
"libc",
]
@@ -1899,16 +2102,25 @@ dependencies = [
]
[[package]]
+name = "object"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "once_cell"
-version = "1.17.1"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "openssl"
-version = "0.10.51"
+version = "0.10.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97ea2d98598bf9ada7ea6ee8a30fb74f9156b63bbe495d64ec2b87c269d2dda3"
+checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
dependencies = [
"bitflags 1.3.2",
"cfg-if",
@@ -1927,7 +2139,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.15",
+ "syn 2.0.29",
]
[[package]]
@@ -1938,9 +2150,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
-version = "0.9.86"
+version = "0.9.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "992bac49bdbab4423199c654a5515bd2a6c6a23bf03f2dd3bdb7e5ae6259bc69"
+checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
dependencies = [
"cc",
"libc",
@@ -1966,28 +2178,28 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.7"
+version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.2.16",
+ "redox_syscall 0.3.5",
"smallvec",
- "windows-sys 0.45.0",
+ "windows-targets",
]
[[package]]
name = "percent-encoding"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pin-project-lite"
-version = "0.2.9"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
[[package]]
name = "pin-utils"
@@ -1997,9 +2209,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.26"
+version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
+checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "polling"
@@ -2014,7 +2226,7 @@ dependencies = [
"libc",
"log",
"pin-project-lite",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
@@ -2025,18 +2237,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
-version = "1.0.56"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "prodash"
-version = "25.0.0"
+version = "26.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3236ce1618b6da4c7b618e0143c4d5b5dc190f75f81c49f248221382f7e9e9ae"
+checksum = "794b5bf8e2d19b53dcdcec3e4bba628e20f5b6062503ba89281fa7037dd7bbcf"
dependencies = [
"bytesize",
"human_format",
@@ -2051,9 +2263,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
-version = "1.0.26"
+version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
dependencies = [
"proc-macro2",
]
@@ -2130,30 +2342,38 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.8.0"
+version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac6cf59af1067a3fb53fbe5c88c053764e930f932be1d71d3ffe032cbe147f59"
+checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
-version = "0.1.10"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
[[package]]
name = "regex-syntax"
-version = "0.7.0"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6868896879ba532248f33598de5181522d8b3d9d724dfd230911e1a7d4822f5"
+checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
[[package]]
name = "reqwest"
-version = "0.11.16"
+version = "0.11.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254"
+checksum = "20b9b67e2ca7dd9e9f9285b759de30ff538aab981abaaf7bc9bd90b84a0126c3"
dependencies = [
"base64",
"bytes",
@@ -2218,45 +2438,74 @@ dependencies = [
]
[[package]]
+name = "rustc-demangle"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+
+[[package]]
name = "rustix"
-version = "0.37.13"
+version = "0.37.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f79bef90eb6d984c72722595b5b1348ab39275a5e5123faca6863bf07d75a4e0"
+checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
- "linux-raw-sys",
- "windows-sys 0.48.0",
+ "linux-raw-sys 0.3.8",
+ "windows-sys",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
+dependencies = [
+ "bitflags 2.3.3",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.4.3",
+ "windows-sys",
]
[[package]]
name = "rustls"
-version = "0.20.8"
+version = "0.21.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
+checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb"
dependencies = [
"log",
"ring",
+ "rustls-webpki",
"sct",
- "webpki",
]
[[package]]
name = "rustls-pemfile"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
+checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2"
dependencies = [
"base64",
]
[[package]]
+name = "rustls-webpki"
+version = "0.101.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
name = "ryu"
-version = "1.0.13"
+version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "same-file"
@@ -2269,18 +2518,18 @@ dependencies = [
[[package]]
name = "schannel"
-version = "0.1.21"
+version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
+checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
dependencies = [
- "windows-sys 0.42.0",
+ "windows-sys",
]
[[package]]
name = "scopeguard"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sct"
@@ -2294,9 +2543,9 @@ dependencies = [
[[package]]
name = "security-framework"
-version = "2.8.2"
+version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
+checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
@@ -2307,9 +2556,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.8.0"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
+checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
dependencies = [
"core-foundation-sys",
"libc",
@@ -2317,29 +2566,29 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.160"
+version = "1.0.185"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
+checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.160"
+version = "1.0.185"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
+checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.15",
+ "syn 2.0.29",
]
[[package]]
name = "serde_json"
-version = "1.0.96"
+version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
+checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b"
dependencies = [
"itoa",
"ryu",
@@ -2378,7 +2627,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.15",
+ "syn 2.0.29",
]
[[package]]
@@ -2410,9 +2659,9 @@ checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
[[package]]
name = "signal-hook"
-version = "0.3.15"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
+checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
@@ -2438,9 +2687,9 @@ dependencies = [
[[package]]
name = "smallvec"
-version = "1.10.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
dependencies = [
"serde",
]
@@ -2456,16 +2705,20 @@ dependencies = [
]
[[package]]
-name = "spin"
-version = "0.5.2"
+name = "socket2"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
[[package]]
-name = "static_assertions"
-version = "1.1.0"
+name = "spin"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "syn"
@@ -2480,9 +2733,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.15"
+version = "2.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
dependencies = [
"proc-macro2",
"quote",
@@ -2491,42 +2744,43 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.5.0"
+version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
dependencies = [
+ "autocfg",
"cfg-if",
- "fastrand",
+ "fastrand 1.9.0",
"redox_syscall 0.3.5",
- "rustix",
- "windows-sys 0.45.0",
+ "rustix 0.37.23",
+ "windows-sys",
]
[[package]]
name = "thiserror"
-version = "1.0.40"
+version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.40"
+version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.15",
+ "syn 2.0.29",
]
[[package]]
name = "time"
-version = "0.3.20"
+version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
+checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446"
dependencies = [
"itoa",
"libc",
@@ -2538,15 +2792,15 @@ dependencies = [
[[package]]
name = "time-core"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]]
name = "time-macros"
-version = "0.2.8"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
+checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4"
dependencies = [
"time-core",
]
@@ -2568,18 +2822,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.27.0"
+version = "1.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
+checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
dependencies = [
"autocfg",
+ "backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
- "socket2",
- "windows-sys 0.45.0",
+ "socket2 0.4.9",
+ "windows-sys",
]
[[package]]
@@ -2594,20 +2849,19 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.23.4"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
+checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls",
"tokio",
- "webpki",
]
[[package]]
name = "tokio-util"
-version = "0.7.7"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
+checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
dependencies = [
"bytes",
"futures-core",
@@ -2637,20 +2891,20 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.23"
+version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
+checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.29",
]
[[package]]
name = "tracing-core"
-version = "0.1.30"
+version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
dependencies = [
"once_cell",
]
@@ -2735,9 +2989,9 @@ checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552"
[[package]]
name = "unicode-ident"
-version = "1.0.8"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "unicode-normalization"
@@ -2756,24 +3010,20 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "url"
-version = "2.3.1"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
dependencies = [
"form_urlencoded",
- "idna 0.3.0",
+ "idna 0.4.0",
"percent-encoding",
]
[[package]]
name = "value-bag"
-version = "1.0.0-alpha.9"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55"
-dependencies = [
- "ctor",
- "version_check",
-]
+checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3"
[[package]]
name = "vcpkg"
@@ -2805,11 +3055,10 @@ dependencies = [
[[package]]
name = "want"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
- "log",
"try-lock",
]
@@ -2821,9 +3070,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.84"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -2831,24 +3080,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.84"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.29",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.34"
+version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
+checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
dependencies = [
"cfg-if",
"js-sys",
@@ -2858,9 +3107,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.84"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2868,57 +3117,44 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.84"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.29",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.84"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]]
name = "web-sys"
-version = "0.3.61"
+version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
+checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
-name = "webpki"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
-dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
name = "webpki-roots"
-version = "0.22.6"
+version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
-dependencies = [
- "webpki",
-]
+checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
[[package]]
name = "widestring"
-version = "0.5.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983"
+checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
[[package]]
name = "winapi"
@@ -2957,31 +3193,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
- "windows-targets 0.48.0",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.45.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
-dependencies = [
- "windows-targets 0.42.2",
+ "windows-targets",
]
[[package]]
@@ -2990,128 +3202,81 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "windows-targets 0.48.0",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets",
]
[[package]]
name = "windows-targets"
-version = "0.48.0"
+version = "0.48.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
dependencies = [
- "windows_aarch64_gnullvm 0.48.0",
- "windows_aarch64_msvc 0.48.0",
- "windows_i686_gnu 0.48.0",
- "windows_i686_msvc 0.48.0",
- "windows_x86_64_gnu 0.48.0",
- "windows_x86_64_gnullvm 0.48.0",
- "windows_x86_64_msvc 0.48.0",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
-
-[[package]]
-name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
-
-[[package]]
-name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
-
-[[package]]
-name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
-
-[[package]]
-name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.42.2"
+version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.0"
+name = "winnow"
+version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+checksum = "d09770118a7eb1ccaf4a594a221334119a44a814fcb0d31c5b85e83e97227a97"
+dependencies = [
+ "memchr",
+]
[[package]]
name = "winreg"
-version = "0.10.1"
+version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
+checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
- "winapi",
+ "cfg-if",
+ "windows-sys",
]
diff --git a/vendor/gix/Cargo.toml b/vendor/gix/Cargo.toml
index 101a6b8cb..a6ec392f3 100644
--- a/vendor/gix/Cargo.toml
+++ b/vendor/gix/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.64"
+rust-version = "1.65"
name = "gix"
-version = "0.45.1"
+version = "0.54.1"
authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]
include = [
"src/**/*",
@@ -21,7 +21,7 @@ include = [
"CHANGELOG.md",
]
description = "Interact with git repositories just like git would"
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/Byron/gitoxide"
[package.metadata.docs.rs]
@@ -29,6 +29,7 @@ features = [
"document-features",
"max-performance",
"blocking-network-client",
+ "blocking-http-transport-curl",
"serde",
]
rustdoc-args = [
@@ -45,16 +46,6 @@ name = "clone"
path = "examples/clone.rs"
required-features = ["blocking-network-client"]
-[[test]]
-name = "gix"
-path = "tests/gix.rs"
-required-features = []
-
-[[test]]
-name = "gix-with-regex"
-path = "tests/gix-with-regex.rs"
-required-features = ["regex"]
-
[dependencies.async-std]
version = "1.12.0"
optional = true
@@ -64,127 +55,176 @@ version = "0.2.0"
optional = true
[dependencies.gix-actor]
-version = "^0.21.0"
+version = "^0.27.0"
+
+[dependencies.gix-archive]
+version = "^0.5.0"
+optional = true
+default-features = false
[dependencies.gix-attributes]
-version = "^0.13.0"
+version = "^0.19.0"
+optional = true
[dependencies.gix-commitgraph]
-version = "^0.16.0"
+version = "^0.21.0"
[dependencies.gix-config]
-version = "^0.23.0"
+version = "^0.30.0"
[dependencies.gix-credentials]
-version = "^0.15.0"
+version = "^0.20.0"
+optional = true
[dependencies.gix-date]
-version = "^0.5.1"
+version = "^0.8.0"
[dependencies.gix-diff]
-version = "^0.30.0"
+version = "^0.36.0"
+default-features = false
[dependencies.gix-discover]
-version = "^0.19.0"
+version = "^0.25.0"
[dependencies.gix-features]
-version = "^0.30.0"
+version = "^0.35.0"
features = [
"progress",
"once_cell",
]
+[dependencies.gix-filter]
+version = "^0.5.0"
+optional = true
+
[dependencies.gix-fs]
-version = "^0.2.0"
+version = "^0.7.0"
[dependencies.gix-glob]
-version = "^0.8.0"
+version = "^0.13.0"
[dependencies.gix-hash]
-version = "^0.11.2"
+version = "^0.13.0"
[dependencies.gix-hashtable]
-version = "^0.2.1"
+version = "^0.4.0"
[dependencies.gix-ignore]
-version = "^0.3.0"
+version = "^0.8.0"
+optional = true
[dependencies.gix-index]
-version = "^0.17.0"
+version = "^0.25.0"
+optional = true
[dependencies.gix-lock]
-version = "^6.0.0"
+version = "^10.0.0"
+
+[dependencies.gix-macros]
+version = "^0.1.0"
[dependencies.gix-mailmap]
-version = "^0.13.0"
+version = "^0.19.0"
+optional = true
[dependencies.gix-negotiate]
-version = "^0.2.0"
+version = "^0.8.0"
+optional = true
[dependencies.gix-object]
-version = "^0.30.0"
+version = "^0.37.0"
[dependencies.gix-odb]
-version = "^0.46.0"
+version = "^0.53.0"
[dependencies.gix-pack]
-version = "^0.36.0"
+version = "^0.43.0"
features = ["object-cache-dynamic"]
+default-features = false
[dependencies.gix-path]
-version = "^0.8.1"
+version = "^0.10.0"
+
+[dependencies.gix-pathspec]
+version = "^0.3.0"
+optional = true
[dependencies.gix-prompt]
-version = "^0.5.1"
+version = "^0.7.0"
+optional = true
[dependencies.gix-protocol]
-version = "^0.33.0"
+version = "^0.40.0"
optional = true
[dependencies.gix-ref]
-version = "^0.30.0"
+version = "^0.37.0"
[dependencies.gix-refspec]
-version = "^0.11.0"
+version = "^0.18.0"
[dependencies.gix-revision]
-version = "^0.15.1"
+version = "^0.22.0"
+default-features = false
+
+[dependencies.gix-revwalk]
+version = "^0.8.0"
[dependencies.gix-sec]
-version = "^0.8.1"
+version = "^0.10.0"
+
+[dependencies.gix-status]
+version = "^0.1.0"
+optional = true
+
+[dependencies.gix-submodule]
+version = "^0.4.0"
+optional = true
[dependencies.gix-tempfile]
-version = "^6.0.0"
-features = ["signals"]
+version = "^10.0.0"
default-features = false
+[dependencies.gix-trace]
+version = "^0.1.3"
+
[dependencies.gix-transport]
-version = "^0.32.0"
+version = "^0.37.0"
optional = true
[dependencies.gix-traverse]
-version = "^0.26.0"
+version = "^0.33.0"
[dependencies.gix-url]
-version = "^0.19.0"
+version = "^0.24.0"
[dependencies.gix-utils]
-version = "^0.1.2"
+version = "^0.1.5"
[dependencies.gix-validate]
-version = "^0.7.5"
+version = "^0.8.0"
[dependencies.gix-worktree]
-version = "^0.18.0"
+version = "^0.26.0"
+optional = true
+default-features = false
-[dependencies.log]
-version = "0.4.14"
+[dependencies.gix-worktree-state]
+version = "^0.3.0"
+optional = true
+
+[dependencies.gix-worktree-stream]
+version = "^0.5.0"
+optional = true
[dependencies.once_cell]
version = "1.14.0"
+[dependencies.parking_lot]
+version = "0.12.1"
+
[dependencies.prodash]
-version = "25.0"
+version = "26.2.2"
features = ["progress-tree"]
optional = true
default-features = false
@@ -209,6 +249,7 @@ default-features = false
[dependencies.signal-hook]
version = "0.3.9"
+optional = true
default-features = false
[dependencies.smallvec]
@@ -235,12 +276,31 @@ default-features = false
version = "2.3.2"
[features]
-async-network-client = ["gix-protocol/async-client"]
+async-network-client = [
+ "gix-protocol/async-client",
+ "gix-pack/streaming-input",
+ "attributes",
+ "credentials",
+]
async-network-client-async-std = [
"async-std",
"async-network-client",
"gix-transport/async-std",
]
+attributes = [
+ "excludes",
+ "dep:gix-filter",
+ "dep:gix-pathspec",
+ "dep:gix-attributes",
+ "dep:gix-submodule",
+ "gix-worktree?/attributes",
+]
+basic = [
+ "blob-diff",
+ "revision",
+ "index",
+]
+blob-diff = ["gix-diff/blob"]
blocking-http-transport-curl = [
"blocking-network-client",
"gix-transport/http-client-curl",
@@ -258,32 +318,76 @@ blocking-http-transport-reqwest-rust-tls = [
"reqwest-for-configuration-only/rustls-tls",
"reqwest-for-configuration-only/trust-dns",
]
-blocking-network-client = ["gix-protocol/blocking-client"]
+blocking-network-client = [
+ "gix-protocol/blocking-client",
+ "gix-pack/streaming-input",
+ "attributes",
+ "credentials",
+]
cache-efficiency-debug = ["gix-features/cache-efficiency-debug"]
comfort = [
"gix-features/progress-unit-bytes",
"gix-features/progress-unit-human-numbers",
]
+credentials = [
+ "dep:gix-credentials",
+ "dep:gix-prompt",
+ "dep:gix-negotiate",
+]
default = [
"max-performance-safe",
"comfort",
+ "basic",
+ "extras",
+]
+excludes = [
+ "dep:gix-ignore",
+ "dep:gix-worktree",
+ "index",
+]
+extras = [
+ "worktree-stream",
+ "worktree-archive",
+ "revparse-regex",
+ "mailmap",
+ "excludes",
+ "attributes",
+ "worktree-mutation",
+ "credentials",
+ "interrupt",
+ "status",
]
fast-sha1 = ["gix-features/fast-sha1"]
hp-tempfile-registry = ["gix-tempfile/hp-hashmap"]
+index = ["dep:gix-index"]
+interrupt = [
+ "dep:signal-hook",
+ "gix-tempfile/signals",
+]
+mailmap = ["dep:gix-mailmap"]
max-performance = [
"max-performance-safe",
"gix-features/zlib-ng",
"fast-sha1",
]
max-performance-safe = [
- "gix-features/parallel",
+ "parallel",
"pack-cache-lru-static",
"pack-cache-lru-dynamic",
"gix-features/fs-walkdir-parallel",
]
pack-cache-lru-dynamic = ["gix-pack/pack-cache-lru-dynamic"]
pack-cache-lru-static = ["gix-pack/pack-cache-lru-static"]
+parallel = ["gix-features/parallel"]
progress-tree = ["prodash/progress-tree"]
+revision = [
+ "gix-revision/describe",
+ "index",
+]
+revparse-regex = [
+ "regex",
+ "revision",
+]
serde = [
"dep:serde",
"gix-pack/serde",
@@ -292,15 +396,29 @@ serde = [
"gix-transport?/serde",
"gix-ref/serde",
"gix-odb/serde",
- "gix-index/serde",
- "gix-mailmap/serde",
+ "gix-index?/serde",
+ "gix-mailmap?/serde",
"gix-url/serde",
- "gix-attributes/serde",
- "gix-ignore/serde",
+ "gix-attributes?/serde",
+ "gix-ignore?/serde",
"gix-revision/serde",
- "gix-worktree/serde",
+ "gix-worktree?/serde",
"gix-commitgraph/serde",
- "gix-credentials/serde",
+ "gix-credentials?/serde",
+]
+status = ["gix-status"]
+worktree-archive = [
+ "gix-archive",
+ "worktree-stream",
+ "attributes",
+]
+worktree-mutation = [
+ "attributes",
+ "dep:gix-worktree-state",
+]
+worktree-stream = [
+ "gix-worktree-stream",
+ "attributes",
]
[target."cfg(target_vendor = \"apple\")".dependencies.unicode-normalization]
diff --git a/vendor/gix/src/assets/baseline-init/description b/vendor/gix/src/assets/baseline-init/description
deleted file mode 100644
index 498b267a8..000000000
--- a/vendor/gix/src/assets/baseline-init/description
+++ /dev/null
@@ -1 +0,0 @@
-Unnamed repository; edit this file 'description' to name the repository.
diff --git a/vendor/gix/src/assets/baseline-init/hooks/applypatch-msg.sample b/vendor/gix/src/assets/baseline-init/hooks/applypatch-msg.sample
deleted file mode 100755
index 20fbb51a2..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/applypatch-msg.sample
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to check the commit log message taken by
-# applypatch from an e-mail message.
-#
-# The hook should exit with non-zero status after issuing an
-# appropriate message if it wants to stop the commit. The hook is
-# allowed to edit the commit message file.
-#
-# To enable this hook, rename this file to "applypatch-msg".
-
-. git-sh-setup
-commitmsg="$(git rev-parse --gix-path hooks/commit-msg)"
-test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
-:
diff --git a/vendor/gix/src/assets/baseline-init/hooks/commit-msg.sample b/vendor/gix/src/assets/baseline-init/hooks/commit-msg.sample
deleted file mode 100755
index b58d1184a..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/commit-msg.sample
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to check the commit log message.
-# Called by "git commit" with one argument, the name of the file
-# that has the commit message. The hook should exit with non-zero
-# status after issuing an appropriate message if it wants to stop the
-# commit. The hook is allowed to edit the commit message file.
-#
-# To enable this hook, rename this file to "commit-msg".
-
-# Uncomment the below to add a Signed-off-by line to the message.
-# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
-# hook is more suited to it.
-#
-# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
-# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
-
-# This example catches duplicate Signed-off-by lines.
-
-test "" = "$(grep '^Signed-off-by: ' "$1" |
- sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
- echo >&2 Duplicate Signed-off-by lines.
- exit 1
-}
diff --git a/vendor/gix/src/assets/baseline-init/hooks/fsmonitor-watchman.sample b/vendor/gix/src/assets/baseline-init/hooks/fsmonitor-watchman.sample
deleted file mode 100755
index 14ed0aa42..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/fsmonitor-watchman.sample
+++ /dev/null
@@ -1,173 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-use IPC::Open2;
-
-# An example hook script to integrate Watchman
-# (https://facebook.github.io/watchman/) with git to speed up detecting
-# new and modified files.
-#
-# The hook is passed a version (currently 2) and last update token
-# formatted as a string and outputs to stdout a new update token and
-# all files that have been modified since the update token. Paths must
-# be relative to the root of the working tree and separated by a single NUL.
-#
-# To enable this hook, rename this file to "query-watchman" and set
-# 'git config core.fsmonitor .git/hooks/query-watchman'
-#
-my ($version, $last_update_token) = @ARGV;
-
-# Uncomment for debugging
-# print STDERR "$0 $version $last_update_token\n";
-
-# Check the hook interface version
-if ($version ne 2) {
- die "Unsupported query-fsmonitor hook version '$version'.\n" .
- "Falling back to scanning...\n";
-}
-
-my $git_work_tree = get_working_dir();
-
-my $retry = 1;
-
-my $json_pkg;
-eval {
- require JSON::XS;
- $json_pkg = "JSON::XS";
- 1;
-} or do {
- require JSON::PP;
- $json_pkg = "JSON::PP";
-};
-
-launch_watchman();
-
-sub launch_watchman {
- my $o = watchman_query();
- if (is_work_tree_watched($o)) {
- output_result($o->{clock}, @{$o->{files}});
- }
-}
-
-sub output_result {
- my ($clockid, @files) = @_;
-
- # Uncomment for debugging watchman output
- # open (my $fh, ">", ".git/watchman-output.out");
- # binmode $fh, ":utf8";
- # print $fh "$clockid\n@files\n";
- # close $fh;
-
- binmode STDOUT, ":utf8";
- print $clockid;
- print "\0";
- local $, = "\0";
- print @files;
-}
-
-sub watchman_clock {
- my $response = qx/watchman clock "$git_work_tree"/;
- die "Failed to get clock id on '$git_work_tree'.\n" .
- "Falling back to scanning...\n" if $? != 0;
-
- return $json_pkg->new->utf8->decode($response);
-}
-
-sub watchman_query {
- my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
- or die "open2() failed: $!\n" .
- "Falling back to scanning...\n";
-
- # In the query expression below we're asking for names of files that
- # changed since $last_update_token but not from the .git folder.
- #
- # To accomplish this, we're using the "since" generator to use the
- # recency index to select candidate nodes and "fields" to limit the
- # output to file names only. Then we're using the "expression" term to
- # further constrain the results.
- if (substr($last_update_token, 0, 1) eq "c") {
- $last_update_token = "\"$last_update_token\"";
- }
- my $query = <<" END";
- ["query", "$git_work_tree", {
- "since": $last_update_token,
- "fields": ["name"],
- "expression": ["not", ["dirname", ".git"]]
- }]
- END
-
- # Uncomment for debugging the watchman query
- # open (my $fh, ">", ".git/watchman-query.json");
- # print $fh $query;
- # close $fh;
-
- print CHLD_IN $query;
- close CHLD_IN;
- my $response = do {local $/; <CHLD_OUT>};
-
- # Uncomment for debugging the watch response
- # open ($fh, ">", ".git/watchman-response.json");
- # print $fh $response;
- # close $fh;
-
- die "Watchman: command returned no output.\n" .
- "Falling back to scanning...\n" if $response eq "";
- die "Watchman: command returned invalid output: $response\n" .
- "Falling back to scanning...\n" unless $response =~ /^\{/;
-
- return $json_pkg->new->utf8->decode($response);
-}
-
-sub is_work_tree_watched {
- my ($output) = @_;
- my $error = $output->{error};
- if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
- $retry--;
- my $response = qx/watchman watch "$git_work_tree"/;
- die "Failed to make watchman watch '$git_work_tree'.\n" .
- "Falling back to scanning...\n" if $? != 0;
- $output = $json_pkg->new->utf8->decode($response);
- $error = $output->{error};
- die "Watchman: $error.\n" .
- "Falling back to scanning...\n" if $error;
-
- # Uncomment for debugging watchman output
- # open (my $fh, ">", ".git/watchman-output.out");
- # close $fh;
-
- # Watchman will always return all files on the first query so
- # return the fast "everything is dirty" flag to git and do the
- # Watchman query just to get it over with now so we won't pay
- # the cost in git to look up each individual file.
- my $o = watchman_clock();
- $error = $output->{error};
-
- die "Watchman: $error.\n" .
- "Falling back to scanning...\n" if $error;
-
- output_result($o->{clock}, ("/"));
- $last_update_token = $o->{clock};
-
- eval { launch_watchman() };
- return 0;
- }
-
- die "Watchman: $error.\n" .
- "Falling back to scanning...\n" if $error;
-
- return 1;
-}
-
-sub get_working_dir {
- my $working_dir;
- if ($^O =~ 'msys' || $^O =~ 'cygwin') {
- $working_dir = Win32::GetCwd();
- $working_dir =~ tr/\\/\//;
- } else {
- require Cwd;
- $working_dir = Cwd::cwd();
- }
-
- return $working_dir;
-}
diff --git a/vendor/gix/src/assets/baseline-init/hooks/post-update.sample b/vendor/gix/src/assets/baseline-init/hooks/post-update.sample
deleted file mode 100755
index ec17ec193..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/post-update.sample
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to prepare a packed repository for use over
-# dumb transports.
-#
-# To enable this hook, rename this file to "post-update".
-
-exec git update-server-info
diff --git a/vendor/gix/src/assets/baseline-init/hooks/pre-applypatch.sample b/vendor/gix/src/assets/baseline-init/hooks/pre-applypatch.sample
deleted file mode 100755
index d61828510..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/pre-applypatch.sample
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to verify what is about to be committed
-# by applypatch from an e-mail message.
-#
-# The hook should exit with non-zero status after issuing an
-# appropriate message if it wants to stop the commit.
-#
-# To enable this hook, rename this file to "pre-applypatch".
-
-. git-sh-setup
-precommit="$(git rev-parse --gix-path hooks/pre-commit)"
-test -x "$precommit" && exec "$precommit" ${1+"$@"}
-:
diff --git a/vendor/gix/src/assets/baseline-init/hooks/pre-commit.sample b/vendor/gix/src/assets/baseline-init/hooks/pre-commit.sample
deleted file mode 100755
index e144712c8..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/pre-commit.sample
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to verify what is about to be committed.
-# Called by "git commit" with no arguments. The hook should
-# exit with non-zero status after issuing an appropriate message if
-# it wants to stop the commit.
-#
-# To enable this hook, rename this file to "pre-commit".
-
-if git rev-parse --verify HEAD >/dev/null 2>&1
-then
- against=HEAD
-else
- # Initial commit: diff against an empty tree object
- against=$(git hash-object -t tree /dev/null)
-fi
-
-# If you want to allow non-ASCII filenames set this variable to true.
-allownonascii=$(git config --type=bool hooks.allownonascii)
-
-# Redirect output to stderr.
-exec 1>&2
-
-# Cross platform projects tend to avoid non-ASCII filenames; prevent
-# them from being added to the repository. We exploit the fact that the
-# printable range starts at the space character and ends with tilde.
-if [ "$allownonascii" != "true" ] &&
- # Note that the use of brackets around a tr range is ok here, (it's
- # even required, for portability to Solaris 10's /usr/bin/tr), since
- # the square bracket bytes happen to fall in the designated range.
- test $(git diff --cached --name-only --diff-filter=A -z $against |
- LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
-then
- cat <<\EOF
-Error: Attempt to add a non-ASCII file name.
-
-This can cause problems if you want to work with people on other platforms.
-
-To be portable it is advisable to rename the file.
-
-If you know what you are doing you can disable this check using:
-
- git config hooks.allownonascii true
-EOF
- exit 1
-fi
-
-# If there are whitespace errors, print the offending file names and fail.
-exec git diff-index --check --cached $against --
diff --git a/vendor/gix/src/assets/baseline-init/hooks/pre-merge-commit.sample b/vendor/gix/src/assets/baseline-init/hooks/pre-merge-commit.sample
deleted file mode 100755
index 399eab192..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/pre-merge-commit.sample
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to verify what is about to be committed.
-# Called by "git merge" with no arguments. The hook should
-# exit with non-zero status after issuing an appropriate message to
-# stderr if it wants to stop the merge commit.
-#
-# To enable this hook, rename this file to "pre-merge-commit".
-
-. git-sh-setup
-test -x "$GIT_DIR/hooks/pre-commit" &&
- exec "$GIT_DIR/hooks/pre-commit"
-:
diff --git a/vendor/gix/src/assets/baseline-init/hooks/pre-push.sample b/vendor/gix/src/assets/baseline-init/hooks/pre-push.sample
deleted file mode 100755
index 6187dbf43..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/pre-push.sample
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/sh
-
-# An example hook script to verify what is about to be pushed. Called by "git
-# push" after it has checked the remote status, but before anything has been
-# pushed. If this script exits with a non-zero status nothing will be pushed.
-#
-# This hook is called with the following parameters:
-#
-# $1 -- Name of the remote to which the push is being done
-# $2 -- URL to which the push is being done
-#
-# If pushing without using a named remote those arguments will be equal.
-#
-# Information about the commits which are being pushed is supplied as lines to
-# the standard input in the form:
-#
-# <local ref> <local sha1> <remote ref> <remote sha1>
-#
-# This sample shows how to prevent push of commits where the log message starts
-# with "WIP" (work in progress).
-
-remote="$1"
-url="$2"
-
-z40=0000000000000000000000000000000000000000
-
-while read local_ref local_sha remote_ref remote_sha
-do
- if [ "$local_sha" = $z40 ]
- then
- # Handle delete
- :
- else
- if [ "$remote_sha" = $z40 ]
- then
- # New branch, examine all commits
- range="$local_sha"
- else
- # Update to existing branch, examine new commits
- range="$remote_sha..$local_sha"
- fi
-
- # Check for WIP commit
- commit=`git rev-list -n 1 --grep '^WIP' "$range"`
- if [ -n "$commit" ]
- then
- echo >&2 "Found WIP commit in $local_ref, not pushing"
- exit 1
- fi
- fi
-done
-
-exit 0
diff --git a/vendor/gix/src/assets/baseline-init/hooks/pre-rebase.sample b/vendor/gix/src/assets/baseline-init/hooks/pre-rebase.sample
deleted file mode 100755
index d6ac43f64..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/pre-rebase.sample
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2006, 2008 Junio C Hamano
-#
-# The "pre-rebase" hook is run just before "git rebase" starts doing
-# its job, and can prevent the command from running by exiting with
-# non-zero status.
-#
-# The hook is called with the following parameters:
-#
-# $1 -- the upstream the series was forked from.
-# $2 -- the branch being rebased (or empty when rebasing the current branch).
-#
-# This sample shows how to prevent topic branches that are already
-# merged to 'next' branch from getting rebased, because allowing it
-# would result in rebasing already published history.
-
-publish=next
-basebranch="$1"
-if test "$#" = 2
-then
- topic="refs/heads/$2"
-else
- topic=`git symbolic-ref HEAD` ||
- exit 0 ;# we do not interrupt rebasing detached HEAD
-fi
-
-case "$topic" in
-refs/heads/??/*)
- ;;
-*)
- exit 0 ;# we do not interrupt others.
- ;;
-esac
-
-# Now we are dealing with a topic branch being rebased
-# on top of main. Is it OK to rebase it?
-
-# Does the topic really exist?
-git show-ref -q "$topic" || {
- echo >&2 "No such branch $topic"
- exit 1
-}
-
-# Is topic fully merged to main?
-not_in_main=`git rev-list --pretty=oneline ^main "$topic"`
-if test -z "$not_in_main"
-then
- echo >&2 "$topic is fully merged to main; better remove it."
- exit 1 ;# we could allow it, but there is no point.
-fi
-
-# Is topic ever merged to next? If so you should not be rebasing it.
-only_next_1=`git rev-list ^main "^$topic" ${publish} | sort`
-only_next_2=`git rev-list ^main ${publish} | sort`
-if test "$only_next_1" = "$only_next_2"
-then
- not_in_topic=`git rev-list "^$topic" main`
- if test -z "$not_in_topic"
- then
- echo >&2 "$topic is already up to date with main"
- exit 1 ;# we could allow it, but there is no point.
- else
- exit 0
- fi
-else
- not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
- /usr/bin/perl -e '
- my $topic = $ARGV[0];
- my $msg = "* $topic has commits already merged to public branch:\n";
- my (%not_in_next) = map {
- /^([0-9a-f]+) /;
- ($1 => 1);
- } split(/\n/, $ARGV[1]);
- for my $elem (map {
- /^([0-9a-f]+) (.*)$/;
- [$1 => $2];
- } split(/\n/, $ARGV[2])) {
- if (!exists $not_in_next{$elem->[0]}) {
- if ($msg) {
- print STDERR $msg;
- undef $msg;
- }
- print STDERR " $elem->[1]\n";
- }
- }
- ' "$topic" "$not_in_next" "$not_in_main"
- exit 1
-fi
-
-<<\DOC_END
-
-This sample hook safeguards topic branches that have been
-published from being rewound.
-
-The workflow assumed here is:
-
- * Once a topic branch forks from "main", "main" is never
- merged into it again (either directly or indirectly).
-
- * Once a topic branch is fully cooked and merged into "main",
- it is deleted. If you need to build on top of it to correct
- earlier mistakes, a new topic branch is created by forking at
- the tip of the "main". This is not strictly necessary, but
- it makes it easier to keep your history simple.
-
- * Whenever you need to test or publish your changes to topic
- branches, merge them into "next" branch.
-
-The script, being an example, hardcodes the publish branch name
-to be "next", but it is trivial to make it configurable via
-$GIT_DIR/config mechanism.
-
-With this workflow, you would want to know:
-
-(1) ... if a topic branch has ever been merged to "next". Young
- topic branches can have stupid mistakes you would rather
- clean up before publishing, and things that have not been
- merged into other branches can be easily rebased without
- affecting other people. But once it is published, you would
- not want to rewind it.
-
-(2) ... if a topic branch has been fully merged to "main".
- Then you can delete it. More importantly, you should not
- build on top of it -- other people may already want to
- change things related to the topic as patches against your
- "main", so if you need further changes, it is better to
- fork the topic (perhaps with the same name) afresh from the
- tip of "main".
-
-Let's look at this example:
-
- o---o---o---o---o---o---o---o---o---o "next"
- / / / /
- / a---a---b A / /
- / / / /
- / / c---c---c---c B /
- / / / \ /
- / / / b---b C \ /
- / / / / \ /
- ---o---o---o---o---o---o---o---o---o---o---o "main"
-
-
-A, B and C are topic branches.
-
- * A has one fix since it was merged up to "next".
-
- * B has finished. It has been fully merged up to "main" and "next",
- and is ready to be deleted.
-
- * C has not merged to "next" at all.
-
-We would want to allow C to be rebased, refuse A, and encourage
-B to be deleted.
-
-To compute (1):
-
- git rev-list ^main ^topic next
- git rev-list ^main next
-
- if these match, topic has not merged in next at all.
-
-To compute (2):
-
- git rev-list main..topic
-
- if this is empty, it is fully merged to "main".
-
-DOC_END
diff --git a/vendor/gix/src/assets/baseline-init/hooks/pre-receive.sample b/vendor/gix/src/assets/baseline-init/hooks/pre-receive.sample
deleted file mode 100755
index a1fd29ec1..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/pre-receive.sample
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to make use of push options.
-# The example simply echoes all push options that start with 'echoback='
-# and rejects all pushes when the "reject" push option is used.
-#
-# To enable this hook, rename this file to "pre-receive".
-
-if test -n "$GIT_PUSH_OPTION_COUNT"
-then
- i=0
- while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
- do
- eval "value=\$GIT_PUSH_OPTION_$i"
- case "$value" in
- echoback=*)
- echo "echo from the pre-receive-hook: ${value#*=}" >&2
- ;;
- reject)
- exit 1
- esac
- i=$((i + 1))
- done
-fi
diff --git a/vendor/gix/src/assets/baseline-init/hooks/prepare-commit-msg.sample b/vendor/gix/src/assets/baseline-init/hooks/prepare-commit-msg.sample
deleted file mode 100755
index 10fa14c5a..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/prepare-commit-msg.sample
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to prepare the commit log message.
-# Called by "git commit" with the name of the file that has the
-# commit message, followed by the description of the commit
-# message's source. The hook's purpose is to edit the commit
-# message file. If the hook fails with a non-zero status,
-# the commit is aborted.
-#
-# To enable this hook, rename this file to "prepare-commit-msg".
-
-# This hook includes three examples. The first one removes the
-# "# Please enter the commit message..." help message.
-#
-# The second includes the output of "git diff --name-status -r"
-# into the message, just before the "git status" output. It is
-# commented because it doesn't cope with --amend or with squashed
-# commits.
-#
-# The third example adds a Signed-off-by line to the message, that can
-# still be edited. This is rarely a good idea.
-
-COMMIT_MSG_FILE=$1
-COMMIT_SOURCE=$2
-SHA1=$3
-
-/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
-
-# case "$COMMIT_SOURCE,$SHA1" in
-# ,|template,)
-# /usr/bin/perl -i.bak -pe '
-# print "\n" . `git diff --cached --name-status -r`
-# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
-# *) ;;
-# esac
-
-# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
-# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
-# if test -z "$COMMIT_SOURCE"
-# then
-# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
-# fi
diff --git a/vendor/gix/src/assets/baseline-init/hooks/update.sample b/vendor/gix/src/assets/baseline-init/hooks/update.sample
deleted file mode 100755
index 5014c4b31..000000000
--- a/vendor/gix/src/assets/baseline-init/hooks/update.sample
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to block unannotated tags from entering.
-# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
-#
-# To enable this hook, rename this file to "update".
-#
-# Config
-# ------
-# hooks.allowunannotated
-# This boolean sets whether unannotated tags will be allowed into the
-# repository. By default they won't be.
-# hooks.allowdeletetag
-# This boolean sets whether deleting tags will be allowed in the
-# repository. By default they won't be.
-# hooks.allowmodifytag
-# This boolean sets whether a tag may be modified after creation. By default
-# it won't be.
-# hooks.allowdeletebranch
-# This boolean sets whether deleting branches will be allowed in the
-# repository. By default they won't be.
-# hooks.denycreatebranch
-# This boolean sets whether remotely creating branches will be denied
-# in the repository. By default this is allowed.
-#
-
-# --- Command line
-refname="$1"
-oldrev="$2"
-newrev="$3"
-
-# --- Safety check
-if [ -z "$GIT_DIR" ]; then
- echo "Don't run this script from the command line." >&2
- echo " (if you want, you could supply GIT_DIR then run" >&2
- echo " $0 <ref> <oldrev> <newrev>)" >&2
- exit 1
-fi
-
-if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
- echo "usage: $0 <ref> <oldrev> <newrev>" >&2
- exit 1
-fi
-
-# --- Config
-allowunannotated=$(git config --type=bool hooks.allowunannotated)
-allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
-denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
-allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
-allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
-
-# check for no description
-projectdesc=$(sed -e '1q' "$GIT_DIR/description")
-case "$projectdesc" in
-"Unnamed repository"* | "")
- echo "*** Project description file hasn't been set" >&2
- exit 1
- ;;
-esac
-
-# --- Check types
-# if $newrev is 0000...0000, it's a commit to delete a ref.
-zero="0000000000000000000000000000000000000000"
-if [ "$newrev" = "$zero" ]; then
- newrev_type=delete
-else
- newrev_type=$(git cat-file -t $newrev)
-fi
-
-case "$refname","$newrev_type" in
- refs/tags/*,commit)
- # un-annotated tag
- short_refname=${refname##refs/tags/}
- if [ "$allowunannotated" != "true" ]; then
- echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
- echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
- exit 1
- fi
- ;;
- refs/tags/*,delete)
- # delete tag
- if [ "$allowdeletetag" != "true" ]; then
- echo "*** Deleting a tag is not allowed in this repository" >&2
- exit 1
- fi
- ;;
- refs/tags/*,tag)
- # annotated tag
- if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
- then
- echo "*** Tag '$refname' already exists." >&2
- echo "*** Modifying a tag is not allowed in this repository." >&2
- exit 1
- fi
- ;;
- refs/heads/*,commit)
- # branch
- if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
- echo "*** Creating a branch is not allowed in this repository" >&2
- exit 1
- fi
- ;;
- refs/heads/*,delete)
- # delete branch
- if [ "$allowdeletebranch" != "true" ]; then
- echo "*** Deleting a branch is not allowed in this repository" >&2
- exit 1
- fi
- ;;
- refs/remotes/*,commit)
- # tracking branch
- ;;
- refs/remotes/*,delete)
- # delete tracking branch
- if [ "$allowdeletebranch" != "true" ]; then
- echo "*** Deleting a tracking branch is not allowed in this repository" >&2
- exit 1
- fi
- ;;
- *)
- # Anything else (is there anything else?)
- echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
- exit 1
- ;;
-esac
-
-# --- Finished
-exit 0
diff --git a/vendor/gix/src/assets/baseline-init/info/exclude b/vendor/gix/src/assets/baseline-init/info/exclude
deleted file mode 100644
index a5196d1be..000000000
--- a/vendor/gix/src/assets/baseline-init/info/exclude
+++ /dev/null
@@ -1,6 +0,0 @@
-# git ls-files --others --exclude-from=.git/info/exclude
-# Lines that start with '#' are comments.
-# For a project mostly in C, the following would be a good set of
-# exclude patterns (uncomment them if you want to use them):
-# *.[oa]
-# *~
diff --git a/vendor/gix/src/assets/baseline-init/HEAD b/vendor/gix/src/assets/init/HEAD
index b870d8262..b870d8262 100644
--- a/vendor/gix/src/assets/baseline-init/HEAD
+++ b/vendor/gix/src/assets/init/HEAD
diff --git a/vendor/gix/src/assets/init/description b/vendor/gix/src/assets/init/description
new file mode 100644
index 000000000..7ffa6830d
--- /dev/null
+++ b/vendor/gix/src/assets/init/description
@@ -0,0 +1 @@
+Unnamed repository; everything before the `;` is the name of the repository.
diff --git a/vendor/gix/src/assets/init/hooks/applypatch-msg.sample b/vendor/gix/src/assets/init/hooks/applypatch-msg.sample
new file mode 100755
index 000000000..945f2f6b3
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/applypatch-msg.sample
@@ -0,0 +1,25 @@
+#!/bin/sh
+# A sample hook to check commit messages created by `git am`
+###########################################################
+#
+# When you receive a patch via email, the `git am` command is commonly used to apply
+# that patch. During the `git am` process, the `applypatch-msg` hook is executed before
+# creating the commit. Its purpose is to validate and modify the commit log message
+# before the patch is applied as a commit in your Git repository.
+#
+# This script serves as an example to validate that the commit message introduced by
+# the patch from an email would pass the `commit-msg` hook, which would be executed
+# if you had created the commit yourself.
+#
+# This hook is the first and followed up by `pre-applypatch` and `post-applypatch`.
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+# Retrieve the path of the commit-msg hook script.
+commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
+
+# If the commit-msg hook script is executable, execute it and pass any command-line arguments to it.
+test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
+
+# Be sure to exit without error if `exec` isn't called.
+:
diff --git a/vendor/gix/src/assets/init/hooks/commit-msg.sample b/vendor/gix/src/assets/init/hooks/commit-msg.sample
new file mode 100755
index 000000000..a7f612f6b
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/commit-msg.sample
@@ -0,0 +1,25 @@
+#!/bin/sh
+# A sample hook to check commit messages created by `git commit`
+################################################################
+#
+# This example script checks commit messages for duplicate `Signed-off-by`
+# lines and rejects the commit if these are present.
+#
+# It is called by "git commit" with a single argument: the name of the file
+# that contains the final commit message, which would be used in the commit.
+# A a non-zero exit status after issuing an appropriate message stops the operation.
+# The hook is allowed to edit the commit message file by rewriting the file
+# containing it.
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+# Check for duplicate Signed-off-by lines in the commit message.
+# The following command uses grep to find lines starting with "Signed-off-by: "
+# in the commit message file specified by the first argument `$1`.
+# It then sorts the lines, counts the number of occurrences of each line,
+# and removes any lines that occur only once.
+# If there are any remaining lines, it means there are duplicate Signed-off-by lines.
+test "$(grep '^Signed-off-by: ' "$1" | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" = "" || {
+ echo "Remove duplicate Signed-off-by lines and repeat the commit." 1>&2
+ exit 1
+}
diff --git a/vendor/gix/src/assets/init/hooks/docs.url b/vendor/gix/src/assets/init/hooks/docs.url
new file mode 100644
index 000000000..bbec3978f
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/docs.url
@@ -0,0 +1 @@
+https://git-scm.com/docs/githooks
diff --git a/vendor/gix/src/assets/init/hooks/fsmonitor-watchman.sample b/vendor/gix/src/assets/init/hooks/fsmonitor-watchman.sample
new file mode 100755
index 000000000..cd8985bc8
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/fsmonitor-watchman.sample
@@ -0,0 +1,16 @@
+#!/usr/bin/sh
+# How to use hook-based fs-monitor integrations
+###############################################
+
+# This script is meant as a placeholder for integrating filesystem monitors with git
+# using hooks in order to speed up commands like `git-status`.
+#
+# To setup the fs-monitor for use with watchman, run
+# `git config core.fsmonitor .git/hooks/fsmonitor-watchman` and paste the content of
+# the example script over at https://github.com/git/git/blob/aa9166bcc0ba654fc21f198a30647ec087f733ed/templates/hooks--fsmonitor-watchman.sample
+# into `.git/hooks/fsmonitor-watchman`.
+#
+# Note that by now and as of this writing on MacOS and Windows and starting from git 2.35.1
+# one can use the built-in fs-monitor implementation using `git config core.fsmonitor true`
+
+exit 42
diff --git a/vendor/gix/src/assets/init/hooks/post-update.sample b/vendor/gix/src/assets/init/hooks/post-update.sample
new file mode 100755
index 000000000..506a06511
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/post-update.sample
@@ -0,0 +1,12 @@
+#!/bin/sh
+# A sample hook that runs after receiving a pack on a remote
+############################################################
+# This hook is called after a pack was received on the remote, i.e. after a successful `git push` operation.
+# It's useful on the server side only.
+#
+# There many more receive hooks which are documented in the official documentation: https://git-scm.com/docs/githooks.
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+# Update static files to support the 'dumb' git HTTP protocol.
+exec git update-server-info
diff --git a/vendor/gix/src/assets/init/hooks/pre-applypatch.sample b/vendor/gix/src/assets/init/hooks/pre-applypatch.sample
new file mode 100755
index 000000000..de06c7f7f
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/pre-applypatch.sample
@@ -0,0 +1,27 @@
+#!/bin/sh
+# A sample hook to check commit messages created by `git am`
+###########################################################
+
+# This hook script is triggered by `git am` without any context just before creating a commit,
+# which is useful to inspect the current tree or run scripts for further verification.
+#
+# If it exits with a non-zero exit code, the commit will not be created. Everything printed
+# to the output or error channels will be visible to the user.
+#
+# Note that there is a sibling hook called `post-applypatch` (also without further context)
+# which is run after the commit was created. It is useful to use the commit hash for further
+# processing, like sending information to the involved parties.
+# Finally, the `applypatch-msg` hook is called at the very beginning of the `git am` operation
+# to provide access to the commit-message.
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+# Retrieve the path to the pre-commit hook script using the "git rev-parse" command.
+precommit="$(git rev-parse --git-path hooks/pre-commit)"
+
+# Check if the pre-commit hook script exists and is executable.
+# If it does, execute it passing the arguments from this script (if any) using the "exec" command.
+test -x "$precommit" && exec "$precommit" ${1+"$@"}
+
+# Be sure to exit without error if `exec` isn't called.
+:
diff --git a/vendor/gix/src/assets/init/hooks/pre-commit.sample b/vendor/gix/src/assets/init/hooks/pre-commit.sample
new file mode 100755
index 000000000..9d256d4c6
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/pre-commit.sample
@@ -0,0 +1,19 @@
+#!/bin/sh
+# A sample hook to prevent commits with merge-markers
+#####################################################
+# This example hook rejects changes that are about to be committed with merge markers,
+# as that would be a clear indication of a failed merge. It is triggered by `git commit`
+# and returning with non-zero exit status prevents the commit from being created.
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+# Check for merge markers in modified files
+for file in $(git diff --cached --name-only); do
+ if grep -q -E '^(<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|)$' "$file"; then
+ echo "Error: File '$file' contains merge markers. Please remove them before committing."
+ exit 1
+ fi
+done
+
+# Exit with success if there are no errors
+exit 0
diff --git a/vendor/gix/src/assets/init/hooks/pre-merge-commit.sample b/vendor/gix/src/assets/init/hooks/pre-merge-commit.sample
new file mode 100755
index 000000000..0896f5b6f
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/pre-merge-commit.sample
@@ -0,0 +1,16 @@
+#!/bin/sh
+# A sample hook to check commits created by `git merge`
+#######################################################
+#
+# This hook is invoked by `git merge` without further context right before creating a commit.
+# It should be used to validate the current state that is supposed to be committed, or exit
+# with a non-zero status to prevent the commit.
+# All output will be visible to the user.
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+# Check if the pre-commit hook exists and is executable. If it is, it executes the pre-commit hook script.
+test -x "$GIT_DIR/hooks/pre-commit" && exec "$GIT_DIR/hooks/pre-commit"
+
+# Be sure to exit without error if `exec` isn't called.
+:
diff --git a/vendor/gix/src/assets/init/hooks/pre-push.sample b/vendor/gix/src/assets/init/hooks/pre-push.sample
new file mode 100755
index 000000000..8846fe8a1
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/pre-push.sample
@@ -0,0 +1,46 @@
+#!/bin/sh
+# Check for "DELME" in commit messages of about-to-be-pushed commits
+####################################################################
+# This hook script is triggered by `git push` right after a connection to the remote
+# was established and its initial response was received, and right before generating
+# and pushing a pack-file.
+# The operation will be aborted when exiting with a non-zero status.
+#
+# The following arguments are provided:
+#
+# $1 - The symbolic name of the remote to push to, like "origin" or the URL like "https://github.com/Byron/gitoxide" if there is no such name.
+# $2 - The URL of the remote to push to, like "https://github.com/Byron/gitoxide".
+#
+# The hook should then read from standard input in a line-by-line fashion and split the following space-separated fields:
+#
+# * local ref - the left side of a ref-spec, i.e. "local" of the "local:refs/heads/remote" ref-spec
+# * local hash - the hash of the commit pointed to by `local ref`
+# * remote ref - the right side of a ref-spec, i.e. "refs/heads/remote" of the "local:refs/heads/remote" ref-spec
+# * remote hash - the hash of the commit pointed to by `remote ref`
+#
+# In this example, we abort the push if any of the about-to-be-pushed commits have "DELME" in their commit message.
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+remote="$1"
+url="$2"
+
+# Check each commit being pushed
+while read _local_ref local_hash _remote_ref _remote_hash; do
+ # Skip if the local hash is all zeroes (deletion)
+ zero_sha=$(printf "%0${#local_hash}d" 0)
+ if [ "$local_hash" = "$zero_sha" ]; then
+ continue
+ fi
+ # Get the commit message
+ commit_msg=$(git log --format=%s -n 1 "$local_hash")
+
+ # Check if the commit message contains "DELME"
+ if echo "$commit_msg" | grep -iq "DELME"; then
+ echo "Error: Found commit with 'DELME' in message. Push aborted to $remote ($url) aborted." 1>&2
+ exit 1
+ fi
+done
+
+# If no commit with "DELME" found, allow the push
+exit 0
diff --git a/vendor/gix/src/assets/init/hooks/pre-rebase.sample b/vendor/gix/src/assets/init/hooks/pre-rebase.sample
new file mode 100755
index 000000000..485012068
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/pre-rebase.sample
@@ -0,0 +1,40 @@
+#!/bin/sh
+# A sample hook to validate the branches involved in a rebase operation
+#######################################################################
+#
+# This hook is invoked right before `git rebase` starts its work and
+# prevents anything else to happen by returning a non-zero exit code.
+#
+# The following arguments are provided:
+#
+# $1 - the branch that contains the commit from which $2 was forked.
+# $2 - the branch being rebased or no second argument at all if the rebase applies to `HEAD`.
+#
+# This example hook aborts the rebase operation if the branch being rebased is not up to date
+# with the latest changes from the upstream branch, or if there are any uncommitted changes.
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+upstream_branch=$1
+if [ "$#" -eq 2 ]; then
+ branch_being_rebased=$2
+else
+ branch_being_rebased=$(git symbolic-ref --quiet --short HEAD) || exit 0 # ignore rebases on detached heads
+fi
+
+# Check if the branch being rebased is behind the upstream branch
+if git log --oneline ${upstream_branch}..${branch_being_rebased} > /dev/null; then
+ echo "Warning: The branch being rebased (${branch_being_rebased}) is behind the upstream branch (${upstream_branch})." 1>&2
+ echo "Please update your branch before rebasing." 1>&2
+ exit 1
+fi
+
+# Check if there are any uncommitted changes
+if ! git diff-index --quiet HEAD --; then
+ echo "Warning: There are uncommitted changes in your branch ${branch_being_rebased}." 1>&2
+ echo "Please commit or stash your changes before rebasing." 1>&2
+ exit 2
+fi
+
+# All good, let the rebase proceed.
+exit 0
diff --git a/vendor/gix/src/assets/init/hooks/prepare-commit-msg.sample b/vendor/gix/src/assets/init/hooks/prepare-commit-msg.sample
new file mode 100755
index 000000000..a38ff5a59
--- /dev/null
+++ b/vendor/gix/src/assets/init/hooks/prepare-commit-msg.sample
@@ -0,0 +1,54 @@
+#!/bin/sh
+# A hook called by `git commit` to adjust the commit message right before the user sees it
+##########################################################################################
+#
+# This script is called by `git commit` after commit message was initialized and right before
+# an editor is launched.
+#
+# It receives one to three arguments:
+#
+# $1 - the path to the file containing the commit message. It can be edited to change the message.
+# $2 - the kind of source of the message contained in $1. Possible values are
+# "message" - a message was provided via `-m` or `-F`
+# "commit" - `-c`, `-C` or `--amend` was given
+# "squash" - the `.git/SQUASH_MSG` file exists
+# "merge" - this is a merge or the `.git/MERGE` file exists
+# "template" - `-t` was provided or `commit.template` was set
+# $3 - If $2 is "commit" then this is the hash of the commit.
+# It can also take other values, best understood by studying the source code at
+# https://github.com/git/git/blob/aa9166bcc0ba654fc21f198a30647ec087f733ed/builtin/commit.c#L745
+#
+# The following example
+#
+# To enable this hook remove the `.sample` suffix from this file entirely.
+
+COMMIT_MSG_FILE=$1
+
+# Check if the commit message file is empty or already contains a message
+if [ -s "$COMMIT_MSG_FILE" ]; then
+ # If the commit message is already provided, exit without making any changes.
+ # This can happen if the user provided a message via `-m` or a template.
+ exit 0
+fi
+
+# Retrieve the branch name from the current HEAD commit
+BRANCH_NAME=$(git symbolic-ref --short HEAD)
+
+# Generate a default commit message based on the branch name
+DEFAULT_MSG=""
+
+case "$BRANCH_NAME" in
+ "feature/*")
+ DEFAULT_MSG="feat: "
+ ;;
+ "bugfix/*")
+ DEFAULT_MSG="fix: "
+ ;;
+ *)
+ DEFAULT_MSG="chore: "
+ ;;
+esac
+
+# Set the commit message that will be presented to the user.
+echo "$DEFAULT_MSG" > "$COMMIT_MSG_FILE"
+
diff --git a/vendor/gix/src/assets/init/info/exclude b/vendor/gix/src/assets/init/info/exclude
new file mode 100644
index 000000000..1beb19eee
--- /dev/null
+++ b/vendor/gix/src/assets/init/info/exclude
@@ -0,0 +1,5 @@
+# Thise file contains repository-wide exclude patterns that git will ignore.
+# They are local and will not be shared when pushing or pulling.
+# When using Rust the following would be typical exclude patterns.
+# Remove the '# ' prefix to let them take effect.
+# /target/
diff --git a/vendor/gix/src/attribute_stack.rs b/vendor/gix/src/attribute_stack.rs
new file mode 100644
index 000000000..1aaca0f2b
--- /dev/null
+++ b/vendor/gix/src/attribute_stack.rs
@@ -0,0 +1,69 @@
+use crate::bstr::BStr;
+use crate::types::AttributeStack;
+use crate::Repository;
+use gix_odb::FindExt;
+use std::ops::{Deref, DerefMut};
+
+/// Lifecycle
+impl<'repo> AttributeStack<'repo> {
+ /// Create a new instance from a `repo` and the underlying pre-configured `stack`.
+ ///
+ /// Note that this type is typically created by [`Repository::attributes()`] or [`Repository::attributes_only()`].
+ pub fn new(stack: gix_worktree::Stack, repo: &'repo Repository) -> Self {
+ AttributeStack { repo, inner: stack }
+ }
+
+ /// Detach the repository and return the underlying plumbing datatype.
+ pub fn detach(self) -> gix_worktree::Stack {
+ self.inner
+ }
+}
+
+impl Deref for AttributeStack<'_> {
+ type Target = gix_worktree::Stack;
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
+
+impl DerefMut for AttributeStack<'_> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.inner
+ }
+}
+
+/// Platform retrieval
+impl<'repo> AttributeStack<'repo> {
+ /// Append the `relative` path to the root directory of the cache and efficiently create leading directories, while assuring that no
+ /// symlinks are in that path.
+ /// Unless `is_dir` is known with `Some(…)`, then `relative` points to a directory itself in which case the entire resulting
+ /// path is created as directory. If it's not known it is assumed to be a file.
+ ///
+ /// Provide access to cached information for that `relative` path via the returned platform.
+ pub fn at_path(
+ &mut self,
+ relative: impl AsRef<std::path::Path>,
+ is_dir: Option<bool>,
+ ) -> std::io::Result<gix_worktree::stack::Platform<'_>> {
+ self.inner
+ .at_path(relative, is_dir, |id, buf| self.repo.objects.find_blob(id, buf))
+ }
+
+ /// Obtain a platform for lookups from a repo-`relative` path, typically obtained from an index entry. `is_dir` should reflect
+ /// whether it's a directory or not, or left at `None` if unknown.
+ ///
+ /// If `relative` ends with `/` and `is_dir` is `None`, it is automatically assumed to be a directory.
+ ///
+ /// ### Panics
+ ///
+ /// - on illformed UTF8 in `relative`
+ pub fn at_entry<'r>(
+ &mut self,
+ relative: impl Into<&'r BStr>,
+ is_dir: Option<bool>,
+ ) -> std::io::Result<gix_worktree::stack::Platform<'_>> {
+ self.inner
+ .at_entry(relative, is_dir, |id, buf| self.repo.objects.find_blob(id, buf))
+ }
+}
diff --git a/vendor/gix/src/attributes.rs b/vendor/gix/src/attributes.rs
deleted file mode 100644
index bb8636460..000000000
--- a/vendor/gix/src/attributes.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-/// The error returned by [`Repository::attributes()`][crate::Repository::attributes()].
-#[derive(Debug, thiserror::Error)]
-#[allow(missing_docs)]
-pub enum Error {
- #[error(transparent)]
- ConfigureAttributes(#[from] crate::config::attribute_stack::Error),
- #[error(transparent)]
- ConfigureExcludes(#[from] crate::config::exclude_stack::Error),
-}
diff --git a/vendor/gix/src/clone/checkout.rs b/vendor/gix/src/clone/checkout.rs
index 823005551..ece480a56 100644
--- a/vendor/gix/src/clone/checkout.rs
+++ b/vendor/gix/src/clone/checkout.rs
@@ -26,9 +26,7 @@ pub mod main_worktree {
#[error(transparent)]
CheckoutOptions(#[from] crate::config::checkout_options::Error),
#[error(transparent)]
- IndexCheckout(
- #[from] gix_worktree::checkout::Error<gix_odb::find::existing_object::Error<gix_odb::store::find::Error>>,
- ),
+ IndexCheckout(#[from] gix_worktree_state::checkout::Error<gix_odb::find::existing_object::Error>),
#[error("Failed to reopen object database as Arc (only if thread-safety wasn't compiled in)")]
OpenArcOdb(#[from] std::io::Error),
#[error("The HEAD reference could not be located")]
@@ -64,11 +62,24 @@ pub mod main_worktree {
///
/// Note that this is a no-op if the remote was empty, leaving this repository empty as well. This can be validated by checking
/// if the `head()` of the returned repository is not unborn.
- pub fn main_worktree(
+ pub fn main_worktree<P>(
&mut self,
- mut progress: impl crate::Progress,
+ mut progress: P,
should_interrupt: &AtomicBool,
- ) -> Result<(Repository, gix_worktree::checkout::Outcome), Error> {
+ ) -> Result<(Repository, gix_worktree_state::checkout::Outcome), Error>
+ where
+ P: gix_features::progress::NestedProgress,
+ P::SubProgress: gix_features::progress::NestedProgress + 'static,
+ {
+ self.main_worktree_inner(&mut progress, should_interrupt)
+ }
+
+ fn main_worktree_inner(
+ &mut self,
+ progress: &mut dyn gix_features::progress::DynNestedProgress,
+ should_interrupt: &AtomicBool,
+ ) -> Result<(Repository, gix_worktree_state::checkout::Outcome), Error> {
+ let _span = gix_trace::coarse!("gix::clone::PrepareCheckout::main_worktree()");
let repo = self
.repo
.as_ref()
@@ -81,7 +92,7 @@ pub mod main_worktree {
None => {
return Ok((
self.repo.take().expect("still present"),
- gix_worktree::checkout::Outcome::default(),
+ gix_worktree_state::checkout::Outcome::default(),
))
}
};
@@ -92,25 +103,27 @@ pub mod main_worktree {
})?;
let mut index = gix_index::File::from_state(index, repo.index_path());
- let mut opts = repo.config.checkout_options(repo.git_dir())?;
+ let mut opts = repo
+ .config
+ .checkout_options(repo, gix_worktree::stack::state::attributes::Source::IdMapping)?;
opts.destination_is_initially_empty = true;
- let mut files = progress.add_child_with_id("checkout", ProgressId::CheckoutFiles.into());
- let mut bytes = progress.add_child_with_id("writing", ProgressId::BytesWritten.into());
+ let mut files = progress.add_child_with_id("checkout".to_string(), ProgressId::CheckoutFiles.into());
+ let mut bytes = progress.add_child_with_id("writing".to_string(), ProgressId::BytesWritten.into());
files.init(Some(index.entries().len()), crate::progress::count("files"));
bytes.init(None, crate::progress::bytes());
let start = std::time::Instant::now();
- let outcome = gix_worktree::checkout(
+ let outcome = gix_worktree_state::checkout(
&mut index,
workdir,
{
let objects = repo.objects.clone().into_arc()?;
move |oid, buf| objects.find_blob(oid, buf)
},
- &mut files,
- &mut bytes,
+ &files,
+ &bytes,
should_interrupt,
opts,
)?;
diff --git a/vendor/gix/src/clone/fetch/mod.rs b/vendor/gix/src/clone/fetch/mod.rs
index e20cc96cb..c03b8f839 100644
--- a/vendor/gix/src/clone/fetch/mod.rs
+++ b/vendor/gix/src/clone/fetch/mod.rs
@@ -26,7 +26,7 @@ pub enum Error {
SaveConfigIo(#[from] std::io::Error),
#[error("The remote HEAD points to a reference named {head_ref_name:?} which is invalid.")]
InvalidHeadRef {
- source: gix_validate::refname::Error,
+ source: gix_validate::reference::name::Error,
head_ref_name: crate::bstr::BString,
},
#[error("Failed to update HEAD with values from remote")]
@@ -55,9 +55,18 @@ impl PrepareFetch {
should_interrupt: &std::sync::atomic::AtomicBool,
) -> Result<(crate::Repository, crate::remote::fetch::Outcome), Error>
where
- P: crate::Progress,
+ P: crate::NestedProgress,
P::SubProgress: 'static,
{
+ self.fetch_only_inner(&mut progress, should_interrupt).await
+ }
+
+ #[gix_protocol::maybe_async::maybe_async]
+ async fn fetch_only_inner(
+ &mut self,
+ progress: &mut dyn crate::DynNestedProgress,
+ should_interrupt: &std::sync::atomic::AtomicBool,
+ ) -> Result<(crate::Repository, crate::remote::fetch::Outcome), Error> {
use crate::{bstr::ByteVec, remote, remote::fetch::RefLogMessage};
let repo = self
@@ -111,7 +120,7 @@ impl PrepareFetch {
f(&mut connection).map_err(|err| Error::RemoteConnection(err))?;
}
connection
- .prepare_fetch(&mut progress, {
+ .prepare_fetch(&mut *progress, {
let mut opts = self.fetch_options.clone();
if !opts.extra_refspecs.contains(&head_refspec) {
opts.extra_refspecs.push(head_refspec)
@@ -134,7 +143,7 @@ impl PrepareFetch {
message: reflog_message.clone(),
})
.with_shallow(self.shallow.clone())
- .receive(progress, should_interrupt)
+ .receive_inner(progress, should_interrupt)
.await?;
util::append_config_to_repo_config(repo, config);
@@ -149,14 +158,14 @@ impl PrepareFetch {
}
/// Similar to [`fetch_only()`][Self::fetch_only()`], but passes ownership to a utility type to configure a checkout operation.
- #[cfg(feature = "blocking-network-client")]
+ #[cfg(all(feature = "worktree-mutation", feature = "blocking-network-client"))]
pub fn fetch_then_checkout<P>(
&mut self,
progress: P,
should_interrupt: &std::sync::atomic::AtomicBool,
) -> Result<(crate::clone::PrepareCheckout, crate::remote::fetch::Outcome), Error>
where
- P: crate::Progress,
+ P: crate::NestedProgress,
P::SubProgress: 'static,
{
let (repo, fetch_outcome) = self.fetch_only(progress, should_interrupt)?;
diff --git a/vendor/gix/src/clone/fetch/util.rs b/vendor/gix/src/clone/fetch/util.rs
index cb79669ac..ab90435d0 100644
--- a/vendor/gix/src/clone/fetch/util.rs
+++ b/vendor/gix/src/clone/fetch/util.rs
@@ -51,7 +51,7 @@ fn write_to_local_config(config: &gix_config::File<'static>, mode: WriteMode) ->
.append(matches!(mode, WriteMode::Append))
.open(config.meta().path.as_deref().expect("local config with path set"))?;
local_config.write_all(config.detect_newline_style())?;
- config.write_to_filter(&mut local_config, |s| s.meta().source == gix_config::Source::Local)
+ config.write_to_filter(&mut local_config, &mut |s| s.meta().source == gix_config::Source::Local)
}
pub fn append_config_to_repo_config(repo: &mut Repository, config: gix_config::File<'static>) {
@@ -76,6 +76,7 @@ pub fn update_head(
gix_protocol::handshake::Ref::Symbolic {
full_ref_name,
target,
+ tag: _,
object,
} if full_ref_name == "HEAD" => (Some(object.as_ref()), Some(target)),
gix_protocol::handshake::Ref::Direct { full_ref_name, object } if full_ref_name == "HEAD" => {
@@ -106,12 +107,7 @@ pub fn update_head(
repo.refs
.transaction()
.packed_refs(gix_ref::file::transaction::PackedRefs::DeletionsAndNonSymbolicUpdates(
- Box::new(|oid, buf| {
- repo.objects
- .try_find(oid, buf)
- .map(|obj| obj.map(|obj| obj.kind))
- .map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync + 'static>)
- }),
+ Box::new(|oid, buf| repo.objects.try_find(&oid, buf).map(|obj| obj.map(|obj| obj.kind))),
))
.prepare(
{
@@ -202,7 +198,7 @@ fn setup_branch_config(
let remote = repo
.find_remote(remote_name)
.expect("remote was just created and must be visible in config");
- let group = gix_refspec::MatchGroup::from_fetch_specs(remote.fetch_specs.iter().map(|s| s.to_ref()));
+ let group = gix_refspec::MatchGroup::from_fetch_specs(remote.fetch_specs.iter().map(gix_refspec::RefSpec::to_ref));
let null = gix_hash::ObjectId::null(repo.object_hash());
let res = group.match_remotes(
Some(gix_refspec::match_group::Item {
diff --git a/vendor/gix/src/clone/mod.rs b/vendor/gix/src/clone/mod.rs
index 9ec226135..8afc3b99b 100644
--- a/vendor/gix/src/clone/mod.rs
+++ b/vendor/gix/src/clone/mod.rs
@@ -68,20 +68,37 @@ impl PrepareFetch {
url: Url,
path: impl AsRef<std::path::Path>,
kind: crate::create::Kind,
- mut create_opts: crate::create::Options,
+ create_opts: crate::create::Options,
open_opts: crate::open::Options,
) -> Result<Self, Error>
where
Url: TryInto<gix_url::Url, Error = E>,
gix_url::parse::Error: From<E>,
{
- let mut url = url.try_into().map_err(gix_url::parse::Error::from)?;
- url.canonicalize().map_err(|err| Error::CanonicalizeUrl {
- url: url.clone(),
- source: err,
- })?;
+ Self::new_inner(
+ url.try_into().map_err(gix_url::parse::Error::from)?,
+ path.as_ref(),
+ kind,
+ create_opts,
+ open_opts,
+ )
+ }
+
+ #[allow(clippy::result_large_err)]
+ fn new_inner(
+ mut url: gix_url::Url,
+ path: &std::path::Path,
+ kind: crate::create::Kind,
+ mut create_opts: crate::create::Options,
+ open_opts: crate::open::Options,
+ ) -> Result<Self, Error> {
create_opts.destination_must_be_empty = true;
let mut repo = crate::ThreadSafeRepository::init_opts(path, kind, create_opts, open_opts)?.to_thread_local();
+ url.canonicalize(repo.options.current_dir_or_empty())
+ .map_err(|err| Error::CanonicalizeUrl {
+ url: url.clone(),
+ source: err,
+ })?;
if repo.committer().is_none() {
let mut config = gix_config::File::new(gix_config::file::Metadata::api());
config
@@ -121,6 +138,7 @@ impl PrepareFetch {
/// A utility to collect configuration on how to perform a checkout into a working tree, and when dropped without checking out successfully
/// the fetched repository will be dropped.
#[must_use]
+#[cfg(feature = "worktree-mutation")]
pub struct PrepareCheckout {
/// A freshly initialized repository which is owned by us, or `None` if it was handed to the user
pub(self) repo: Option<crate::Repository>,
@@ -164,4 +182,5 @@ mod access_feat {
pub mod fetch;
///
+#[cfg(feature = "worktree-mutation")]
pub mod checkout;
diff --git a/vendor/gix/src/commit.rs b/vendor/gix/src/commit.rs
index 68e1eeba7..2cc8226f5 100644
--- a/vendor/gix/src/commit.rs
+++ b/vendor/gix/src/commit.rs
@@ -22,6 +22,7 @@ pub enum Error {
}
///
+#[cfg(feature = "revision")]
pub mod describe {
use std::borrow::Cow;
@@ -91,7 +92,7 @@ pub mod describe {
let (prio, tag_time) = match target_id {
Some(target_id) if peeled_id != *target_id => {
let tag = repo.find_object(target_id).ok()?.try_into_tag().ok()?;
- (1, tag.tagger().ok()??.time.seconds_since_unix_epoch)
+ (1, tag.tagger().ok()??.time.seconds)
}
_ => (0, 0),
};
@@ -124,11 +125,7 @@ pub mod describe {
// TODO: we assume direct refs for tags, which is the common case, but it doesn't have to be
// so rather follow symrefs till the first object and then peel tags after the first object was found.
let tag = r.try_id()?.object().ok()?.try_into_tag().ok()?;
- let tag_time = tag
- .tagger()
- .ok()
- .and_then(|s| s.map(|s| s.time.seconds_since_unix_epoch))
- .unwrap_or(0);
+ let tag_time = tag.tagger().ok().and_then(|s| s.map(|s| s.time.seconds)).unwrap_or(0);
let commit_id = tag.target_id().ok()?.object().ok()?.try_into_commit().ok()?.id;
Some((commit_id, tag_time, Cow::<BStr>::from(r.name().shorten().to_owned())))
})
@@ -187,7 +184,7 @@ pub mod describe {
///
/// Note that there will always be `Some(format)`
pub fn try_format(&self) -> Result<Option<gix_revision::describe::Format<'static>>, Error> {
- self.try_resolve()?.map(|r| r.format()).transpose()
+ self.try_resolve()?.map(Resolution::format).transpose()
}
/// Try to find a name for the configured commit id using all prior configuration, returning `Some(Outcome)`
@@ -201,14 +198,14 @@ pub mod describe {
/// to save ~40% of time.
pub fn try_resolve(&self) -> Result<Option<Resolution<'repo>>, Error> {
// TODO: dirty suffix with respective dirty-detection
- let mut graph = gix_revision::Graph::new(
+ let mut graph = gix_revwalk::Graph::new(
|id, buf| {
self.repo
.objects
.try_find(id, buf)
- .map(|r| r.and_then(|d| d.try_into_commit_iter()))
+ .map(|r| r.and_then(gix_object::Data::try_into_commit_iter))
},
- gix_commitgraph::Graph::from_info_dir(self.repo.objects.store_ref().path().join("info")).ok(),
+ gix_commitgraph::Graph::from_info_dir(self.repo.objects.store_ref().path().join("info").as_ref()).ok(),
);
let outcome = gix_revision::describe(
&self.id,
diff --git a/vendor/gix/src/config/cache/access.rs b/vendor/gix/src/config/cache/access.rs
index cea56f973..352bc9712 100644
--- a/vendor/gix/src/config/cache/access.rs
+++ b/vendor/gix/src/config/cache/access.rs
@@ -1,16 +1,15 @@
#![allow(clippy::result_large_err)]
use std::{borrow::Cow, path::PathBuf, time::Duration};
-use gix_attributes::Source;
use gix_lock::acquire::Fail;
use crate::{
bstr::BStr,
config,
config::{
- cache::util::{ApplyLeniency, ApplyLeniencyDefault},
- checkout_options,
- tree::{gitoxide, Checkout, Core, Key},
+ boolean,
+ cache::util::{ApplyLeniency, ApplyLeniencyDefaultValue},
+ tree::{Core, Key},
Cache,
},
remote,
@@ -19,7 +18,9 @@ use crate::{
/// Access
impl Cache {
+ #[cfg(feature = "blob-diff")]
pub(crate) fn diff_algorithm(&self) -> Result<gix_diff::blob::Algorithm, config::diff::algorithm::Error> {
+ use crate::config::cache::util::ApplyLeniencyDefault;
use crate::config::diff::algorithm::Error;
self.diff_algorithm
.get_or_try_init(|| {
@@ -69,6 +70,18 @@ impl Cache {
.get_or_try_init(|| remote::url::SchemePermission::from_config(&self.resolved, self.filter_config_section))
}
+ pub(crate) fn may_use_commit_graph(&self) -> Result<bool, config::boolean::Error> {
+ const DEFAULT: bool = true;
+ self.resolved
+ .boolean_by_key("core.commitGraph")
+ .map_or(Ok(DEFAULT), |res| {
+ Core::COMMIT_GRAPH
+ .enrich_error(res)
+ .with_lenient_default_value(self.lenient_config, DEFAULT)
+ })
+ }
+
+ #[cfg(feature = "blob-diff")]
pub(crate) fn diff_renames(
&self,
) -> Result<Option<crate::object::tree::diff::Rewrites>, crate::object::tree::diff::rewrites::Error> {
@@ -100,9 +113,10 @@ impl Cache {
}
/// The path to the user-level excludes file to ignore certain files in the worktree.
+ #[cfg(feature = "excludes")]
pub(crate) fn excludes_file(&self) -> Option<Result<PathBuf, gix_config::path::interpolate::Error>> {
self.trusted_file_path("core", None, Core::EXCLUDES_FILE.name)?
- .map(|p| p.into_owned())
+ .map(std::borrow::Cow::into_owned)
.into()
}
@@ -123,7 +137,7 @@ impl Cache {
let install_dir = crate::path::install_dir().ok();
let home = self.home_dir();
- let ctx = crate::config::cache::interpolate_context(install_dir.as_deref(), home.as_deref());
+ let ctx = config::cache::interpolate_context(install_dir.as_deref(), home.as_deref());
Some(path.interpolate(ctx))
}
@@ -131,80 +145,108 @@ impl Cache {
res.transpose().with_leniency(self.lenient_config)
}
+ pub(crate) fn fs_capabilities(&self) -> Result<gix_fs::Capabilities, boolean::Error> {
+ Ok(gix_fs::Capabilities {
+ precompose_unicode: boolean(self, "core.precomposeUnicode", &Core::PRECOMPOSE_UNICODE, false)?,
+ ignore_case: boolean(self, "core.ignoreCase", &Core::IGNORE_CASE, false)?,
+ executable_bit: boolean(self, "core.fileMode", &Core::FILE_MODE, true)?,
+ symlink: boolean(self, "core.symlinks", &Core::SYMLINKS, true)?,
+ })
+ }
+
+ #[cfg(feature = "index")]
+ pub(crate) fn stat_options(&self) -> Result<gix_index::entry::stat::Options, config::stat_options::Error> {
+ use crate::config::tree::gitoxide;
+ Ok(gix_index::entry::stat::Options {
+ trust_ctime: boolean(
+ self,
+ "core.trustCTime",
+ &Core::TRUST_C_TIME,
+ // For now, on MacOS it's known to not be trust-worthy at least with the Rust STDlib, being 2s off
+ !cfg!(target_os = "macos"),
+ )?,
+ use_nsec: boolean(self, "gitoxide.core.useNsec", &gitoxide::Core::USE_NSEC, false)?,
+ use_stdev: boolean(self, "gitoxide.core.useStdev", &gitoxide::Core::USE_STDEV, false)?,
+ check_stat: self
+ .apply_leniency(
+ self.resolved
+ .string("core", None, "checkStat")
+ .map(|v| Core::CHECK_STAT.try_into_checkstat(v)),
+ )?
+ .unwrap_or(true),
+ })
+ }
+
/// Collect everything needed to checkout files into a worktree.
/// Note that some of the options being returned will be defaulted so safe settings, the caller might have to override them
/// depending on the use-case.
+ #[cfg(feature = "worktree-mutation")]
pub(crate) fn checkout_options(
&self,
- git_dir: &std::path::Path,
- ) -> Result<gix_worktree::checkout::Options, checkout_options::Error> {
- fn boolean(
- me: &Cache,
- full_key: &str,
- key: &'static config::tree::keys::Boolean,
- default: bool,
- ) -> Result<bool, checkout_options::Error> {
- debug_assert_eq!(
- full_key,
- key.logical_name(),
- "BUG: key name and hardcoded name must match"
- );
- Ok(me
- .apply_leniency(me.resolved.boolean_by_key(full_key).map(|v| key.enrich_error(v)))?
- .unwrap_or(default))
- }
-
+ repo: &crate::Repository,
+ attributes_source: gix_worktree::stack::state::attributes::Source,
+ ) -> Result<gix_worktree_state::checkout::Options, config::checkout_options::Error> {
+ use crate::config::tree::gitoxide;
+ let git_dir = repo.git_dir();
let thread_limit = self.apply_leniency(
self.resolved
.integer_filter_by_key("checkout.workers", &mut self.filter_config_section.clone())
- .map(|value| Checkout::WORKERS.try_from_workers(value)),
+ .map(|value| crate::config::tree::Checkout::WORKERS.try_from_workers(value)),
)?;
- let capabilities = gix_fs::Capabilities {
- precompose_unicode: boolean(self, "core.precomposeUnicode", &Core::PRECOMPOSE_UNICODE, false)?,
- ignore_case: boolean(self, "core.ignoreCase", &Core::IGNORE_CASE, false)?,
- executable_bit: boolean(self, "core.fileMode", &Core::FILE_MODE, true)?,
- symlink: boolean(self, "core.symlinks", &Core::SYMLINKS, true)?,
+ let capabilities = self.fs_capabilities()?;
+ let filters = {
+ let collection = Default::default();
+ let mut filters = gix_filter::Pipeline::new(&collection, crate::filter::Pipeline::options(repo)?);
+ if let Ok(mut head) = repo.head() {
+ let ctx = filters.driver_context_mut();
+ ctx.ref_name = head.referent_name().map(|name| name.as_bstr().to_owned());
+ ctx.treeish = head.peel_to_commit_in_place().ok().map(|commit| commit.id);
+ }
+ filters
+ };
+ let filter_process_delay = if boolean(
+ self,
+ "gitoxide.core.filterProcessDelay",
+ &gitoxide::Core::FILTER_PROCESS_DELAY,
+ true,
+ )? {
+ gix_filter::driver::apply::Delay::Allow
+ } else {
+ gix_filter::driver::apply::Delay::Forbid
};
- Ok(gix_worktree::checkout::Options {
+ Ok(gix_worktree_state::checkout::Options {
+ filter_process_delay,
+ filters,
attributes: self
- .assemble_attribute_globals(
- git_dir,
- gix_worktree::cache::state::attributes::Source::IdMappingThenWorktree,
- self.attributes,
- )?
+ .assemble_attribute_globals(git_dir, attributes_source, self.attributes)?
.0,
fs: capabilities,
thread_limit,
destination_is_initially_empty: false,
overwrite_existing: false,
keep_going: false,
- stat_options: gix_index::entry::stat::Options {
- trust_ctime: boolean(self, "core.trustCTime", &Core::TRUST_C_TIME, true)?,
- use_nsec: boolean(self, "gitoxide.core.useNsec", &gitoxide::Core::USE_NSEC, false)?,
- use_stdev: boolean(self, "gitoxide.core.useStdev", &gitoxide::Core::USE_STDEV, false)?,
- check_stat: self
- .apply_leniency(
- self.resolved
- .string("core", None, "checkStat")
- .map(|v| Core::CHECK_STAT.try_into_checkstat(v)),
- )?
- .unwrap_or(true),
- },
+ stat_options: self.stat_options().map_err(|err| match err {
+ config::stat_options::Error::ConfigCheckStat(err) => {
+ config::checkout_options::Error::ConfigCheckStat(err)
+ }
+ config::stat_options::Error::ConfigBoolean(err) => config::checkout_options::Error::ConfigBoolean(err),
+ })?,
})
}
+ #[cfg(feature = "excludes")]
pub(crate) fn assemble_exclude_globals(
&self,
git_dir: &std::path::Path,
overrides: Option<gix_ignore::Search>,
- source: gix_worktree::cache::state::ignore::Source,
+ source: gix_worktree::stack::state::ignore::Source,
buf: &mut Vec<u8>,
- ) -> Result<gix_worktree::cache::state::Ignore, config::exclude_stack::Error> {
+ ) -> Result<gix_worktree::stack::state::Ignore, config::exclude_stack::Error> {
let excludes_file = match self.excludes_file().transpose()? {
Some(user_path) => Some(user_path),
None => self.xdg_config_path("ignore")?,
};
- Ok(gix_worktree::cache::state::Ignore::new(
+ Ok(gix_worktree::stack::state::Ignore::new(
overrides.unwrap_or_default(),
gix_ignore::Search::from_git_dir(git_dir, excludes_file, buf)?,
None,
@@ -212,12 +254,14 @@ impl Cache {
))
}
// TODO: at least one test, maybe related to core.attributesFile configuration.
+ #[cfg(feature = "attributes")]
pub(crate) fn assemble_attribute_globals(
&self,
git_dir: &std::path::Path,
- source: gix_worktree::cache::state::attributes::Source,
+ source: gix_worktree::stack::state::attributes::Source,
attributes: crate::open::permissions::Attributes,
- ) -> Result<(gix_worktree::cache::state::Attributes, Vec<u8>), config::attribute_stack::Error> {
+ ) -> Result<(gix_worktree::stack::state::Attributes, Vec<u8>), config::attribute_stack::Error> {
+ use gix_attributes::Source;
let configured_or_user_attributes = match self
.trusted_file_path("core", None, Core::ATTRIBUTES_FILE.name)
.transpose()?
@@ -243,15 +287,45 @@ impl Cache {
let info_attributes_path = git_dir.join("info").join("attributes");
let mut buf = Vec::new();
let mut collection = gix_attributes::search::MetadataCollection::default();
- let res = gix_worktree::cache::state::Attributes::new(
+ let state = gix_worktree::stack::state::Attributes::new(
gix_attributes::Search::new_globals(attribute_files, &mut buf, &mut collection)?,
Some(info_attributes_path),
source,
collection,
);
- Ok((res, buf))
+ Ok((state, buf))
}
+ #[cfg(feature = "attributes")]
+ pub(crate) fn pathspec_defaults(
+ &self,
+ ) -> Result<gix_pathspec::Defaults, gix_pathspec::defaults::from_environment::Error> {
+ use crate::config::tree::gitoxide;
+ let res = gix_pathspec::Defaults::from_environment(&mut |name| {
+ let key = [
+ &gitoxide::Pathspec::ICASE,
+ &gitoxide::Pathspec::GLOB,
+ &gitoxide::Pathspec::NOGLOB,
+ &gitoxide::Pathspec::LITERAL,
+ ]
+ .iter()
+ .find_map(|key| (key.environment_override().expect("set") == name).then_some(key))
+ .expect("we must know all possible input variable names");
+
+ let val = self
+ .resolved
+ .string("gitoxide", Some("pathspec".into()), key.name())
+ .map(gix_path::from_bstr)?;
+ Some(val.into_owned().into())
+ });
+ if res.is_err() && self.lenient_config {
+ Ok(gix_pathspec::Defaults::default())
+ } else {
+ res
+ }
+ }
+
+ #[cfg(any(feature = "attributes", feature = "excludes"))]
pub(crate) fn xdg_config_path(
&self,
resource_file_name: &str,
@@ -284,3 +358,19 @@ impl Cache {
gix_path::env::home_dir().and_then(|path| self.environment.home.check_opt(path))
}
}
+
+fn boolean(
+ me: &Cache,
+ full_key: &str,
+ key: &'static config::tree::keys::Boolean,
+ default: bool,
+) -> Result<bool, boolean::Error> {
+ debug_assert_eq!(
+ full_key,
+ key.logical_name(),
+ "BUG: key name and hardcoded name must match"
+ );
+ Ok(me
+ .apply_leniency(me.resolved.boolean_by_key(full_key).map(|v| key.enrich_error(v)))?
+ .unwrap_or(default))
+}
diff --git a/vendor/gix/src/config/cache/incubate.rs b/vendor/gix/src/config/cache/incubate.rs
index 44c537b50..cf7c5dcdf 100644
--- a/vendor/gix/src/config/cache/incubate.rs
+++ b/vendor/gix/src/config/cache/incubate.rs
@@ -102,7 +102,7 @@ fn load_config(
path: config_path,
};
if lenient {
- log::warn!("ignoring: {err:#?}");
+ gix_trace::warn!("ignoring: {err:#?}");
return Ok(gix_config::File::new(metadata));
} else {
return Err(err);
@@ -117,7 +117,7 @@ fn load_config(
path: config_path,
};
if lenient {
- log::warn!("ignoring: {err:#?}");
+ gix_trace::warn!("ignoring: {err:#?}");
buf.clear();
} else {
return Err(err);
diff --git a/vendor/gix/src/config/cache/init.rs b/vendor/gix/src/config/cache/init.rs
index 6fcbcc4ec..3c482b154 100644
--- a/vendor/gix/src/config/cache/init.rs
+++ b/vendor/gix/src/config/cache/init.rs
@@ -13,6 +13,7 @@ use crate::{
Cache,
},
open,
+ repository::init::setup_objects,
};
/// Initialization
@@ -71,7 +72,7 @@ impl Cache {
let config = {
let git_prefix = &git_prefix;
- let metas = [
+ let mut metas = [
gix_config::source::Kind::GitInstallation,
gix_config::source::Kind::System,
gix_config::source::Kind::Global,
@@ -99,7 +100,7 @@ impl Cache {
let err_on_nonexisting_paths = false;
let mut globals = gix_config::File::from_paths_metadata_buf(
- metas,
+ &mut metas,
&mut buf,
err_on_nonexisting_paths,
gix_config::file::init::Options {
@@ -150,6 +151,7 @@ impl Cache {
true,
lenient_config,
)?;
+ #[cfg(feature = "revision")]
let object_kind_hint = util::disambiguate_hint(&config, lenient_config)?;
let (static_pack_cache_limit_bytes, pack_cache_bytes, object_cache_bytes) =
util::parse_object_caches(&config, lenient_config, filter_config_section)?;
@@ -158,6 +160,7 @@ impl Cache {
resolved: config.into(),
use_multi_pack_index,
object_hash,
+ #[cfg(feature = "revision")]
object_kind_hint,
static_pack_cache_limit_bytes,
pack_cache_bytes,
@@ -173,9 +176,11 @@ impl Cache {
user_agent: Default::default(),
personas: Default::default(),
url_rewrite: Default::default(),
+ #[cfg(feature = "blob-diff")]
diff_renames: Default::default(),
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
url_scheme: Default::default(),
+ #[cfg(feature = "blob-diff")]
diff_algorithm: Default::default(),
})
}
@@ -210,19 +215,26 @@ impl Cache {
false,
self.lenient_config,
)?;
- let object_kind_hint = util::disambiguate_hint(config, self.lenient_config)?;
+
+ #[cfg(feature = "revision")]
+ {
+ let object_kind_hint = util::disambiguate_hint(config, self.lenient_config)?;
+ self.object_kind_hint = object_kind_hint;
+ }
let reflog = util::query_refupdates(config, self.lenient_config)?;
self.hex_len = hex_len;
self.ignore_case = ignore_case;
- self.object_kind_hint = object_kind_hint;
self.reflog = reflog;
self.user_agent = Default::default();
self.personas = Default::default();
self.url_rewrite = Default::default();
- self.diff_renames = Default::default();
- self.diff_algorithm = Default::default();
+ #[cfg(feature = "blob-diff")]
+ {
+ self.diff_renames = Default::default();
+ self.diff_algorithm = Default::default();
+ }
(
self.static_pack_cache_limit_bytes,
self.pack_cache_bytes,
@@ -268,8 +280,19 @@ impl crate::Repository {
&mut self,
config: crate::Config,
) -> Result<(), Error> {
+ let (a, b, c) = (
+ self.config.static_pack_cache_limit_bytes,
+ self.config.pack_cache_bytes,
+ self.config.object_cache_bytes,
+ );
self.config.reread_values_and_clear_caches_replacing_config(config)?;
self.apply_changed_values();
+ if a != self.config.static_pack_cache_limit_bytes
+ || b != self.config.pack_cache_bytes
+ || c != self.config.object_cache_bytes
+ {
+ setup_objects(&mut self.objects, &self.config);
+ }
Ok(())
}
@@ -446,6 +469,29 @@ fn apply_environment_overrides(
}],
),
(
+ "gitoxide",
+ Some(Cow::Borrowed("pathspec".into())),
+ git_prefix,
+ &[
+ {
+ let key = &gitoxide::Pathspec::LITERAL;
+ (env(key), key.name)
+ },
+ {
+ let key = &gitoxide::Pathspec::GLOB;
+ (env(key), key.name)
+ },
+ {
+ let key = &gitoxide::Pathspec::NOGLOB;
+ (env(key), key.name)
+ },
+ {
+ let key = &gitoxide::Pathspec::ICASE;
+ (env(key), key.name)
+ },
+ ],
+ ),
+ (
"ssh",
None,
git_prefix,
diff --git a/vendor/gix/src/config/cache/util.rs b/vendor/gix/src/config/cache/util.rs
index 7c478fcf9..4032b2cb1 100644
--- a/vendor/gix/src/config/cache/util.rs
+++ b/vendor/gix/src/config/cache/util.rs
@@ -3,7 +3,6 @@ use super::Error;
use crate::{
config,
config::tree::{gitoxide, Core},
- revision::spec::parse::ObjectKindHint,
};
pub(crate) fn interpolate_context<'a>(
@@ -51,7 +50,7 @@ pub(crate) fn query_refupdates(
) -> Result<Option<gix_ref::store::WriteReflog>, Error> {
let key = "core.logAllRefUpdates";
Core::LOG_ALL_REF_UPDATES
- .try_into_ref_updates(config.boolean_by_key(key), || config.string_by_key(key))
+ .try_into_ref_updates(config.boolean_by_key(key))
.with_leniency(lenient_config)
.map_err(Into::into)
}
@@ -74,7 +73,7 @@ pub(crate) fn parse_object_caches(
mut filter_config_section: fn(&gix_config::file::Metadata) -> bool,
) -> Result<(Option<usize>, Option<usize>, usize), Error> {
let static_pack_cache_limit = config
- .integer_filter_by_key("core.deltaBaseCacheLimit", &mut filter_config_section)
+ .integer_filter_by_key("gitoxide.core.deltaBaseCacheLimit", &mut filter_config_section)
.map(|res| gitoxide::Core::DEFAULT_PACK_CACHE_MEMORY_LIMIT.try_into_usize(res))
.transpose()
.with_leniency(lenient)?;
@@ -103,10 +102,11 @@ pub(crate) fn parse_core_abbrev(
.flatten())
}
+#[cfg(feature = "revision")]
pub(crate) fn disambiguate_hint(
config: &gix_config::File<'static>,
lenient_config: bool,
-) -> Result<Option<ObjectKindHint>, config::key::GenericErrorWithValue> {
+) -> Result<Option<crate::revision::spec::parse::ObjectKindHint>, config::key::GenericErrorWithValue> {
match config.string_by_key("core.disambiguate") {
None => Ok(None),
Some(value) => Core::DISAMBIGUATE
@@ -120,10 +120,18 @@ pub trait ApplyLeniency {
fn with_leniency(self, is_lenient: bool) -> Self;
}
+pub trait IgnoreEmptyPath {
+ fn ignore_empty(self) -> Self;
+}
+
pub trait ApplyLeniencyDefault {
fn with_lenient_default(self, is_lenient: bool) -> Self;
}
+pub trait ApplyLeniencyDefaultValue<T> {
+ fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self;
+}
+
impl<T, E> ApplyLeniency for Result<Option<T>, E> {
fn with_leniency(self, is_lenient: bool) -> Self {
match self {
@@ -134,6 +142,16 @@ impl<T, E> ApplyLeniency for Result<Option<T>, E> {
}
}
+impl IgnoreEmptyPath for Result<Option<std::borrow::Cow<'_, std::path::Path>>, gix_config::path::interpolate::Error> {
+ fn ignore_empty(self) -> Self {
+ match self {
+ Ok(maybe_path) => Ok(maybe_path),
+ Err(gix_config::path::interpolate::Error::Missing { .. }) => Ok(None),
+ Err(err) => Err(err),
+ }
+ }
+}
+
impl<T, E> ApplyLeniencyDefault for Result<T, E>
where
T: Default,
@@ -146,3 +164,13 @@ where
}
}
}
+
+impl<T, E> ApplyLeniencyDefaultValue<T> for Result<T, E> {
+ fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self {
+ match self {
+ Ok(v) => Ok(v),
+ Err(_) if is_lenient => Ok(default),
+ Err(err) => Err(err),
+ }
+ }
+}
diff --git a/vendor/gix/src/config/mod.rs b/vendor/gix/src/config/mod.rs
index 3353806f8..102c7a482 100644
--- a/vendor/gix/src/config/mod.rs
+++ b/vendor/gix/src/config/mod.rs
@@ -1,10 +1,11 @@
pub use gix_config::*;
use gix_features::threading::OnceCell;
-use crate::{bstr::BString, repository::identity, revision::spec, Repository};
+use crate::{bstr::BString, repository::identity, Repository};
pub(crate) mod cache;
mod snapshot;
+#[cfg(feature = "credentials")]
pub use snapshot::credential_helpers;
///
@@ -46,6 +47,23 @@ pub(crate) mod section {
}
}
+///
+pub mod set_value {
+ /// The error produced when calling [`SnapshotMut::set(_subsection)?_value()`][crate::config::SnapshotMut::set_value()]
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ SetRaw(#[from] gix_config::file::set_raw_value::Error),
+ #[error(transparent)]
+ Validate(#[from] crate::config::tree::key::validate::Error),
+ #[error("The key needs a subsection parameter to be valid.")]
+ SubSectionRequired,
+ #[error("The key must not be used with a subsection")]
+ SubSectionForbidden,
+ }
+}
+
/// The error returned when failing to initialize the repository configuration.
///
/// This configuration is on the critical path when opening a repository.
@@ -102,6 +120,20 @@ pub mod diff {
}
///
+pub mod stat_options {
+ /// The error produced when collecting stat information, and returned by [Repository::stat_options()](crate::Repository::stat_options()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ ConfigCheckStat(#[from] super::key::GenericErrorWithValue),
+ #[error(transparent)]
+ ConfigBoolean(#[from] super::boolean::Error),
+ }
+}
+
+///
+#[cfg(feature = "attributes")]
pub mod checkout_options {
/// The error produced when collecting all information needed for checking out files into a worktree.
#[derive(Debug, thiserror::Error)]
@@ -115,6 +147,8 @@ pub mod checkout_options {
CheckoutWorkers(#[from] super::checkout::workers::Error),
#[error(transparent)]
Attributes(#[from] super::attribute_stack::Error),
+ #[error(transparent)]
+ FilterPipelineOptions(#[from] crate::filter::pipeline::options::Error),
}
}
@@ -275,6 +309,23 @@ pub mod key {
}
///
+pub mod encoding {
+ use crate::bstr::BString;
+
+ /// The error produced when failing to parse the `core.checkRoundTripEncoding` key.
+ #[derive(Debug, thiserror::Error)]
+ #[error("The encoding named '{encoding}' seen in key '{key}={value}' is unsupported")]
+ pub struct Error {
+ /// The configuration key that contained the value.
+ pub key: BString,
+ /// The value that was assigned to `key`.
+ pub value: BString,
+ /// The encoding that failed.
+ pub encoding: BString,
+ }
+}
+
+///
pub mod checkout {
///
pub mod workers {
@@ -424,6 +475,7 @@ pub mod transport {
key: Cow<'static, BStr>,
},
#[error("Could not configure the credential helpers for the authenticated proxy url")]
+ #[cfg(feature = "credentials")]
ConfigureProxyAuthenticate(#[from] crate::config::snapshot::credential_helpers::Error),
#[error(transparent)]
InvalidSslVersion(#[from] crate::config::ssl_version::Error),
@@ -459,11 +511,13 @@ pub(crate) struct Cache {
/// A lazily loaded rewrite list for remote urls
pub(crate) url_rewrite: OnceCell<crate::remote::url::Rewrite>,
/// The lazy-loaded rename information for diffs.
+ #[cfg(feature = "blob-diff")]
pub(crate) diff_renames: OnceCell<Option<crate::object::tree::diff::Rewrites>>,
/// A lazily loaded mapping to know which url schemes to allow
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
pub(crate) url_scheme: OnceCell<crate::remote::url::SchemePermission>,
/// The algorithm to use when diffing blobs
+ #[cfg(feature = "blob-diff")]
pub(crate) diff_algorithm: OnceCell<gix_diff::blob::Algorithm>,
/// The amount of bytes to use for a memory backed delta pack cache. If `Some(0)`, no cache is used, if `None`
/// a standard cache is used which costs near to nothing and always pays for itself.
@@ -475,12 +529,14 @@ pub(crate) struct Cache {
/// The config section filter from the options used to initialize this instance. Keep these in sync!
filter_config_section: fn(&gix_config::file::Metadata) -> bool,
/// The object kind to pick if a prefix is ambiguous.
- pub object_kind_hint: Option<spec::parse::ObjectKindHint>,
+ #[cfg(feature = "revision")]
+ pub object_kind_hint: Option<crate::revision::spec::parse::ObjectKindHint>,
/// If true, we are on a case-insensitive file system.
pub ignore_case: bool,
/// If true, we should default what's possible if something is misconfigured, on case by case basis, to be more resilient.
/// Also available in options! Keep in sync!
pub lenient_config: bool,
+ #[cfg_attr(not(feature = "worktree-mutation"), allow(dead_code))]
attributes: crate::open::permissions::Attributes,
environment: crate::open::permissions::Environment,
// TODO: make core.precomposeUnicode available as well.
diff --git a/vendor/gix/src/config/overrides.rs b/vendor/gix/src/config/overrides.rs
index 4bdf4a13f..6b3fc728c 100644
--- a/vendor/gix/src/config/overrides.rs
+++ b/vendor/gix/src/config/overrides.rs
@@ -26,11 +26,15 @@ pub(crate) fn append(
let mut file = gix_config::File::new(gix_config::file::Metadata::from(source));
for key_value in values {
let key_value = key_value.as_ref();
- let mut tokens = key_value.splitn(2, |b| *b == b'=').map(|v| v.trim());
+ let mut tokens = key_value.splitn(2, |b| *b == b'=').map(ByteSlice::trim);
let key = tokens.next().expect("always one value").as_bstr();
let value = tokens.next();
- let key = gix_config::parse::key(key.to_str().map_err(|_| Error::InvalidKey { input: key.into() })?)
- .ok_or_else(|| Error::InvalidKey { input: key.into() })?;
+ let key = gix_config::parse::key(
+ key.to_str()
+ .map_err(|_| Error::InvalidKey { input: key.into() })?
+ .into(),
+ )
+ .ok_or_else(|| Error::InvalidKey { input: key.into() })?;
let mut section = file.section_mut_or_create_new(key.section_name, key.subsection_name)?;
let key =
gix_config::parse::section::Key::try_from(key.value_name.to_owned()).map_err(|err| Error::SectionKey {
@@ -38,7 +42,7 @@ pub(crate) fn append(
key: key.value_name.into(),
})?;
let comment = make_comment(key_value);
- let value = value.map(|v| v.as_bstr());
+ let value = value.map(ByteSlice::as_bstr);
match comment {
Some(comment) => section.push_with_comment(key, value, &**comment),
None => section.push(key, value),
diff --git a/vendor/gix/src/config/snapshot/access.rs b/vendor/gix/src/config/snapshot/access.rs
index 1710348a9..7dc593880 100644
--- a/vendor/gix/src/config/snapshot/access.rs
+++ b/vendor/gix/src/config/snapshot/access.rs
@@ -2,9 +2,11 @@
use std::borrow::Cow;
use gix_features::threading::OwnShared;
+use gix_macros::momo;
+use crate::bstr::ByteSlice;
use crate::{
- bstr::BStr,
+ bstr::{BStr, BString},
config::{CommitAutoRollback, Snapshot, SnapshotMut},
};
@@ -25,6 +27,7 @@ impl<'repo> Snapshot<'repo> {
}
/// Like [`boolean()`][Self::boolean()], but it will report an error if the value couldn't be interpreted as boolean.
+ #[momo]
pub fn try_boolean<'a>(&self, key: impl Into<&'a BStr>) -> Option<Result<bool, gix_config::value::Error>> {
self.repo.config.resolved.boolean_by_key(key)
}
@@ -40,6 +43,7 @@ impl<'repo> Snapshot<'repo> {
}
/// Like [`integer()`][Self::integer()], but it will report an error if the value couldn't be interpreted as boolean.
+ #[momo]
pub fn try_integer<'a>(&self, key: impl Into<&'a BStr>) -> Option<Result<i64, gix_config::value::Error>> {
self.repo.config.resolved.integer_by_key(key)
}
@@ -47,6 +51,7 @@ impl<'repo> Snapshot<'repo> {
/// Return the string at `key`, or `None` if there is no such value.
///
/// Note that this method takes the most recent value at `key` even if it is from a file with reduced trust.
+ #[momo]
pub fn string<'a>(&self, key: impl Into<&'a BStr>) -> Option<Cow<'_, BStr>> {
self.repo.config.resolved.string_by_key(key)
}
@@ -54,11 +59,12 @@ impl<'repo> Snapshot<'repo> {
/// Return the trusted and fully interpolated path at `key`, or `None` if there is no such value
/// or if no value was found in a trusted file.
/// An error occurs if the path could not be interpolated to its final value.
+ #[momo]
pub fn trusted_path<'a>(
&self,
key: impl Into<&'a BStr>,
) -> Option<Result<Cow<'_, std::path::Path>, gix_config::path::interpolate::Error>> {
- let key = gix_config::parse::key(key)?;
+ let key = gix_config::parse::key(key.into())?;
self.repo
.config
.trusted_file_path(key.section_name, key.subsection_name, key.value_name)
@@ -99,6 +105,50 @@ impl<'repo> SnapshotMut<'repo> {
self.commit_inner(repo)
}
+ /// Set the value at `key` to `new_value`, possibly creating the section if it doesn't exist yet, or overriding the most recent existing
+ /// value, which will be returned.
+ #[momo]
+ pub fn set_value<'b>(
+ &mut self,
+ key: &'static dyn crate::config::tree::Key,
+ new_value: impl Into<&'b BStr>,
+ ) -> Result<Option<BString>, crate::config::set_value::Error> {
+ if let Some(crate::config::tree::SubSectionRequirement::Parameter(_)) = key.subsection_requirement() {
+ return Err(crate::config::set_value::Error::SubSectionRequired);
+ }
+ let value = new_value.into();
+ key.validate(value)?;
+ let current = self
+ .config
+ .set_raw_value(key.section().name(), None, key.name(), value)?;
+ Ok(current.map(std::borrow::Cow::into_owned))
+ }
+
+ /// Set the value at `key` to `new_value` in the given `subsection`, possibly creating the section and sub-section if it doesn't exist yet,
+ /// or overriding the most recent existing value, which will be returned.
+ #[momo]
+ pub fn set_subsection_value<'a, 'b>(
+ &mut self,
+ key: &'static dyn crate::config::tree::Key,
+ subsection: impl Into<&'a BStr>,
+ new_value: impl Into<&'b BStr>,
+ ) -> Result<Option<BString>, crate::config::set_value::Error> {
+ if let Some(crate::config::tree::SubSectionRequirement::Never) = key.subsection_requirement() {
+ return Err(crate::config::set_value::Error::SubSectionForbidden);
+ }
+ let value = new_value.into();
+ key.validate(value)?;
+
+ let name = key
+ .full_name(Some(subsection.into()))
+ .expect("we know it needs a subsection");
+ let key = gix_config::parse::key((**name).as_bstr()).expect("statically known keys can always be parsed");
+ let current =
+ self.config
+ .set_raw_value(key.section_name, key.subsection_name, key.value_name.to_owned(), value)?;
+ Ok(current.map(std::borrow::Cow::into_owned))
+ }
+
pub(crate) fn commit_inner(
&mut self,
repo: &'repo mut crate::Repository,
diff --git a/vendor/gix/src/config/snapshot/credential_helpers.rs b/vendor/gix/src/config/snapshot/credential_helpers.rs
index c4eef35d6..189e74471 100644
--- a/vendor/gix/src/config/snapshot/credential_helpers.rs
+++ b/vendor/gix/src/config/snapshot/credential_helpers.rs
@@ -2,6 +2,7 @@ use std::{borrow::Cow, convert::TryFrom};
pub use error::Error;
+use crate::config::cache::util::IgnoreEmptyPath;
use crate::{
bstr::{ByteSlice, ByteVec},
config::{
@@ -140,7 +141,8 @@ impl Snapshot<'_> {
let prompt_options = gix_prompt::Options {
askpass: self
.trusted_path(Core::ASKPASS.logical_name().as_str())
- .transpose()?
+ .transpose()
+ .ignore_empty()?
.map(|c| Cow::Owned(c.into_owned())),
..Default::default()
}
diff --git a/vendor/gix/src/config/snapshot/mod.rs b/vendor/gix/src/config/snapshot/mod.rs
index 80ec6f948..de143ea1f 100644
--- a/vendor/gix/src/config/snapshot/mod.rs
+++ b/vendor/gix/src/config/snapshot/mod.rs
@@ -2,4 +2,5 @@ mod _impls;
mod access;
///
+#[cfg(feature = "credentials")]
pub mod credential_helpers;
diff --git a/vendor/gix/src/config/tree/keys.rs b/vendor/gix/src/config/tree/keys.rs
index b03fa49c6..5a5257af5 100644
--- a/vendor/gix/src/config/tree/keys.rs
+++ b/vendor/gix/src/config/tree/keys.rs
@@ -464,7 +464,7 @@ mod remote_name {
}
}
-/// Provide a way to validate a value, or decode a value from `gix-config`.
+/// Provide a way to validate a value, or decode a value from `git-config`.
pub trait Validate {
/// Validate `value` or return an error.
fn validate(&self, value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>>;
diff --git a/vendor/gix/src/config/tree/mod.rs b/vendor/gix/src/config/tree/mod.rs
index 3f69ccb97..d8415154f 100644
--- a/vendor/gix/src/config/tree/mod.rs
+++ b/vendor/gix/src/config/tree/mod.rs
@@ -31,6 +31,7 @@ pub(crate) mod root {
/// The `credential` section.
pub const CREDENTIAL: sections::Credential = sections::Credential;
/// The `diff` section.
+ #[cfg(feature = "blob-diff")]
pub const DIFF: sections::Diff = sections::Diff;
/// The `extensions` section.
pub const EXTENSIONS: sections::Extensions = sections::Extensions;
@@ -69,6 +70,7 @@ pub(crate) mod root {
&Self::COMMITTER,
&Self::CORE,
&Self::CREDENTIAL,
+ #[cfg(feature = "blob-diff")]
&Self::DIFF,
&Self::EXTENSIONS,
&Self::FETCH,
@@ -90,10 +92,12 @@ pub(crate) mod root {
mod sections;
pub use sections::{
- branch, checkout, core, credential, diff, extensions, fetch, gitoxide, http, index, protocol, remote, ssh, Author,
- Branch, Checkout, Clone, Committer, Core, Credential, Diff, Extensions, Fetch, Gitoxide, Http, Index, Init, Pack,
+ branch, checkout, core, credential, extensions, fetch, gitoxide, http, index, protocol, remote, ssh, Author,
+ Branch, Checkout, Clone, Committer, Core, Credential, Extensions, Fetch, Gitoxide, Http, Index, Init, Pack,
Protocol, Remote, Safe, Ssh, Url, User,
};
+#[cfg(feature = "blob-diff")]
+pub use sections::{diff, Diff};
/// Generic value implementations for static instantiation.
pub mod keys;
diff --git a/vendor/gix/src/config/tree/sections/core.rs b/vendor/gix/src/config/tree/sections/core.rs
index 93d2fcd01..ab3e2bab9 100644
--- a/vendor/gix/src/config/tree/sections/core.rs
+++ b/vendor/gix/src/config/tree/sections/core.rs
@@ -45,7 +45,8 @@ impl Core {
/// The `core.symlinks` key.
pub const SYMLINKS: keys::Boolean = keys::Boolean::new_boolean("symlinks", &config::Tree::CORE);
/// The `core.trustCTime` key.
- pub const TRUST_C_TIME: keys::Boolean = keys::Boolean::new_boolean("trustCTime", &config::Tree::CORE);
+ pub const TRUST_C_TIME: keys::Boolean = keys::Boolean::new_boolean("trustCTime", &config::Tree::CORE)
+ .with_deviation("Currently the default is false, instead of true, as it seems to be 2s off in tests");
/// The `core.worktree` key.
pub const WORKTREE: keys::Any = keys::Any::new("worktree", &config::Tree::CORE)
.with_environment_override("GIT_WORK_TREE")
@@ -66,6 +67,24 @@ impl Core {
/// The `core.useReplaceRefs` key.
pub const USE_REPLACE_REFS: keys::Boolean = keys::Boolean::new_boolean("useReplaceRefs", &config::Tree::CORE)
.with_environment_override("GIT_NO_REPLACE_OBJECTS");
+ /// The `core.commitGraph` key.
+ pub const COMMIT_GRAPH: keys::Boolean = keys::Boolean::new_boolean("commitGraph", &config::Tree::CORE);
+ /// The `core.safecrlf` key.
+ #[cfg(feature = "attributes")]
+ pub const SAFE_CRLF: SafeCrlf = SafeCrlf::new_with_validate("safecrlf", &config::Tree::CORE, validate::SafeCrlf);
+ /// The `core.autocrlf` key.
+ #[cfg(feature = "attributes")]
+ pub const AUTO_CRLF: AutoCrlf = AutoCrlf::new_with_validate("autocrlf", &config::Tree::CORE, validate::AutoCrlf);
+ /// The `core.eol` key.
+ #[cfg(feature = "attributes")]
+ pub const EOL: Eol = Eol::new_with_validate("eol", &config::Tree::CORE, validate::Eol);
+ /// The `core.checkRoundTripEncoding` key.
+ #[cfg(feature = "attributes")]
+ pub const CHECK_ROUND_TRIP_ENCODING: CheckRoundTripEncoding = CheckRoundTripEncoding::new_with_validate(
+ "checkRoundTripEncoding",
+ &config::Tree::CORE,
+ validate::CheckRoundTripEncoding,
+ );
}
impl Section for Core {
@@ -96,6 +115,15 @@ impl Section for Core {
&Self::ATTRIBUTES_FILE,
&Self::SSH_COMMAND,
&Self::USE_REPLACE_REFS,
+ &Self::COMMIT_GRAPH,
+ #[cfg(feature = "attributes")]
+ &Self::SAFE_CRLF,
+ #[cfg(feature = "attributes")]
+ &Self::AUTO_CRLF,
+ #[cfg(feature = "attributes")]
+ &Self::EOL,
+ #[cfg(feature = "attributes")]
+ &Self::CHECK_ROUND_TRIP_ENCODING,
]
}
}
@@ -112,6 +140,154 @@ pub type LogAllRefUpdates = keys::Any<validate::LogAllRefUpdates>;
/// The `core.disambiguate` key.
pub type Disambiguate = keys::Any<validate::Disambiguate>;
+#[cfg(feature = "attributes")]
+mod filter {
+ use super::validate;
+ use crate::config::tree::keys;
+
+ /// The `core.safecrlf` key.
+ pub type SafeCrlf = keys::Any<validate::SafeCrlf>;
+
+ /// The `core.autocrlf` key.
+ pub type AutoCrlf = keys::Any<validate::AutoCrlf>;
+
+ /// The `core.eol` key.
+ pub type Eol = keys::Any<validate::Eol>;
+
+ /// The `core.checkRoundTripEncoding` key.
+ pub type CheckRoundTripEncoding = keys::Any<validate::CheckRoundTripEncoding>;
+
+ mod check_round_trip_encoding {
+ use std::borrow::Cow;
+
+ use crate::{
+ bstr::{BStr, ByteSlice},
+ config,
+ config::tree::{core::CheckRoundTripEncoding, Key},
+ };
+
+ impl CheckRoundTripEncoding {
+ /// Convert `value` into a list of encodings, which are either space or coma separated. Fail if an encoding is unknown.
+ /// If `None`, the default is returned.
+ pub fn try_into_encodings(
+ &'static self,
+ value: Option<Cow<'_, BStr>>,
+ ) -> Result<Vec<&'static gix_filter::encoding::Encoding>, config::encoding::Error> {
+ Ok(match value {
+ None => vec![gix_filter::encoding::SHIFT_JIS],
+ Some(value) => {
+ let mut out = Vec::new();
+ for encoding in value
+ .as_ref()
+ .split(|b| *b == b',' || *b == b' ')
+ .filter(|e| !e.trim().is_empty())
+ {
+ out.push(
+ gix_filter::encoding::Encoding::for_label(encoding.trim()).ok_or_else(|| {
+ config::encoding::Error {
+ key: self.logical_name().into(),
+ value: value.as_ref().to_owned(),
+ encoding: encoding.into(),
+ }
+ })?,
+ );
+ }
+ out
+ }
+ })
+ }
+ }
+ }
+
+ mod eol {
+ use std::borrow::Cow;
+
+ use crate::{
+ bstr::{BStr, ByteSlice},
+ config,
+ config::tree::core::Eol,
+ };
+
+ impl Eol {
+ /// Convert `value` into the default end-of-line mode.
+ ///
+ /// ### Deviation
+ ///
+ /// git will allow any value and silently leaves it unset, we will fail if the value is not known.
+ pub fn try_into_eol(
+ &'static self,
+ value: Cow<'_, BStr>,
+ ) -> Result<gix_filter::eol::Mode, config::key::GenericErrorWithValue> {
+ Ok(match value.to_str_lossy().as_ref() {
+ "lf" => gix_filter::eol::Mode::Lf,
+ "crlf" => gix_filter::eol::Mode::CrLf,
+ "native" => gix_filter::eol::Mode::default(),
+ _ => return Err(config::key::GenericErrorWithValue::from_value(self, value.into_owned())),
+ })
+ }
+ }
+ }
+
+ mod safecrlf {
+ use std::borrow::Cow;
+
+ use gix_filter::pipeline::CrlfRoundTripCheck;
+
+ use crate::{bstr::BStr, config, config::tree::core::SafeCrlf};
+
+ impl SafeCrlf {
+ /// Convert `value` into the safe-crlf enumeration, if possible.
+ pub fn try_into_safecrlf(
+ &'static self,
+ value: Cow<'_, BStr>,
+ ) -> Result<CrlfRoundTripCheck, config::key::GenericErrorWithValue> {
+ if value.as_ref() == "warn" {
+ return Ok(CrlfRoundTripCheck::Warn);
+ }
+ let value = gix_config::Boolean::try_from(value.as_ref()).map_err(|err| {
+ config::key::GenericErrorWithValue::from_value(self, value.into_owned()).with_source(err)
+ })?;
+ Ok(if value.into() {
+ CrlfRoundTripCheck::Fail
+ } else {
+ CrlfRoundTripCheck::Skip
+ })
+ }
+ }
+ }
+
+ mod autocrlf {
+ use std::borrow::Cow;
+
+ use gix_filter::eol;
+
+ use crate::{bstr::BStr, config, config::tree::core::AutoCrlf};
+
+ impl AutoCrlf {
+ /// Convert `value` into the safe-crlf enumeration, if possible.
+ pub fn try_into_autocrlf(
+ &'static self,
+ value: Cow<'_, BStr>,
+ ) -> Result<eol::AutoCrlf, config::key::GenericErrorWithValue> {
+ if value.as_ref() == "input" {
+ return Ok(eol::AutoCrlf::Input);
+ }
+ let value = gix_config::Boolean::try_from(value.as_ref()).map_err(|err| {
+ config::key::GenericErrorWithValue::from_value(self, value.into_owned()).with_source(err)
+ })?;
+ Ok(if value.into() {
+ eol::AutoCrlf::Enabled
+ } else {
+ eol::AutoCrlf::Disabled
+ })
+ }
+ }
+ }
+}
+#[cfg(feature = "attributes")]
+pub use filter::*;
+
+#[cfg(feature = "revision")]
mod disambiguate {
use std::borrow::Cow;
@@ -143,30 +319,27 @@ mod disambiguate {
}
mod log_all_ref_updates {
- use std::borrow::Cow;
-
- use crate::{bstr::BStr, config, config::tree::core::LogAllRefUpdates};
+ use crate::{config, config::tree::core::LogAllRefUpdates};
impl LogAllRefUpdates {
- /// Returns the mode for ref-updates as parsed from `value`. If `value` is not a boolean, `string_on_failure` will be called
- /// to obtain the key `core.logAllRefUpdates` as string instead. For correctness, this two step process is necessary as
- /// the interpretation of booleans in special in `gix-config`, i.e. we can't just treat it as string.
- pub fn try_into_ref_updates<'a>(
+ /// Returns the mode for ref-updates as parsed from `value`. If `value` is not a boolean, we try
+ /// to interpret the string value instead. For correctness, this two step process is necessary as
+ /// the interpretation of booleans in special in `git-config`, i.e. we can't just treat it as string.
+ pub fn try_into_ref_updates(
&'static self,
value: Option<Result<bool, gix_config::value::Error>>,
- string_on_failure: impl FnOnce() -> Option<Cow<'a, BStr>>,
) -> Result<Option<gix_ref::store::WriteReflog>, config::key::GenericErrorWithValue> {
- match value.transpose().ok().flatten() {
- Some(bool) => Ok(Some(if bool {
+ match value {
+ Some(Ok(bool)) => Ok(Some(if bool {
gix_ref::store::WriteReflog::Normal
} else {
gix_ref::store::WriteReflog::Disable
})),
- None => match string_on_failure() {
- Some(val) if val.eq_ignore_ascii_case(b"always") => Ok(Some(gix_ref::store::WriteReflog::Always)),
- Some(val) => Err(config::key::GenericErrorWithValue::from_value(self, val.into_owned())),
- None => Ok(None),
+ Some(Err(err)) => match err.input {
+ val if val.eq_ignore_ascii_case(b"always") => Ok(Some(gix_ref::store::WriteReflog::Always)),
+ val => Err(config::key::GenericErrorWithValue::from_value(self, val)),
},
+ None => Ok(None),
}
}
}
@@ -270,7 +443,9 @@ mod validate {
pub struct Disambiguate;
impl keys::Validate for Disambiguate {
+ #[cfg_attr(not(feature = "revision"), allow(unused_variables))]
fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "revision")]
super::Core::DISAMBIGUATE.try_into_object_kind_hint(value.into())?;
Ok(())
}
@@ -280,9 +455,7 @@ mod validate {
impl keys::Validate for LogAllRefUpdates {
fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
super::Core::LOG_ALL_REF_UPDATES
- .try_into_ref_updates(Some(gix_config::Boolean::try_from(value).map(|b| b.0)), || {
- Some(value.into())
- })?;
+ .try_into_ref_updates(Some(gix_config::Boolean::try_from(value).map(|b| b.0)))?;
Ok(())
}
}
@@ -303,4 +476,44 @@ mod validate {
Ok(())
}
}
+
+ pub struct SafeCrlf;
+ impl keys::Validate for SafeCrlf {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "attributes")]
+ super::Core::SAFE_CRLF.try_into_safecrlf(value.into())?;
+ Ok(())
+ }
+ }
+
+ pub struct AutoCrlf;
+ impl keys::Validate for AutoCrlf {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "attributes")]
+ super::Core::AUTO_CRLF.try_into_autocrlf(value.into())?;
+ Ok(())
+ }
+ }
+
+ pub struct Eol;
+ impl keys::Validate for Eol {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "attributes")]
+ super::Core::EOL.try_into_eol(value.into())?;
+ Ok(())
+ }
+ }
+
+ pub struct CheckRoundTripEncoding;
+ impl keys::Validate for CheckRoundTripEncoding {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "attributes")]
+ super::Core::CHECK_ROUND_TRIP_ENCODING.try_into_encodings(Some(value.into()))?;
+ Ok(())
+ }
+ }
}
diff --git a/vendor/gix/src/config/tree/sections/diff.rs b/vendor/gix/src/config/tree/sections/diff.rs
index 103bb7001..7c467b8f5 100644
--- a/vendor/gix/src/config/tree/sections/diff.rs
+++ b/vendor/gix/src/config/tree/sections/diff.rs
@@ -68,10 +68,8 @@ mod algorithm {
}
mod renames {
- use std::borrow::Cow;
-
use crate::{
- bstr::{BStr, ByteSlice},
+ bstr::ByteSlice,
config::{
key::GenericError,
tree::{keys, sections::diff::Renames, Section},
@@ -84,21 +82,20 @@ mod renames {
pub const fn new_renames(name: &'static str, section: &'static dyn Section) -> Self {
keys::Any::new_with_validate(name, section, super::validate::Renames)
}
- /// Try to convert the configuration into a valid rename tracking variant. Use `value` and if it's an error, call `value_string`
- /// to try and interpret the key as string.
- pub fn try_into_renames<'a>(
+ /// Try to convert the configuration into a valid rename tracking variant. Use `value` and if it's an error, interpret
+ /// the boolean as string
+ pub fn try_into_renames(
&'static self,
value: Result<bool, gix_config::value::Error>,
- value_string: impl FnOnce() -> Option<Cow<'a, BStr>>,
) -> Result<Tracking, GenericError> {
Ok(match value {
Ok(true) => Tracking::Renames,
Ok(false) => Tracking::Disabled,
Err(err) => {
- let value = value_string().ok_or_else(|| GenericError::from(self))?;
- match value.as_ref().as_bytes() {
+ let value = &err.input;
+ match value.as_bytes() {
b"copy" | b"copies" => Tracking::RenamesAndCopies,
- _ => return Err(GenericError::from_value(self, value.into_owned()).with_source(err)),
+ _ => return Err(GenericError::from_value(self, value.clone()).with_source(err)),
}
}
})
@@ -107,8 +104,6 @@ mod renames {
}
mod validate {
- use std::borrow::Cow;
-
use crate::{
bstr::BStr,
config::tree::{keys, Diff},
@@ -126,7 +121,7 @@ mod validate {
impl keys::Validate for Renames {
fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
let boolean = gix_config::Boolean::try_from(value).map(|b| b.0);
- Diff::RENAMES.try_into_renames(boolean, || Some(Cow::Borrowed(value)))?;
+ Diff::RENAMES.try_into_renames(boolean)?;
Ok(())
}
}
diff --git a/vendor/gix/src/config/tree/sections/fetch.rs b/vendor/gix/src/config/tree/sections/fetch.rs
index 117cabfd2..32db7be5f 100644
--- a/vendor/gix/src/config/tree/sections/fetch.rs
+++ b/vendor/gix/src/config/tree/sections/fetch.rs
@@ -10,6 +10,10 @@ impl Fetch {
&config::Tree::FETCH,
validate::NegotiationAlgorithm,
);
+ /// The `fetch.recurseSubmodules` key.
+ #[cfg(feature = "attributes")]
+ pub const RECURSE_SUBMODULES: RecurseSubmodules =
+ RecurseSubmodules::new_with_validate("recurseSubmodules", &config::Tree::FETCH, validate::RecurseSubmodules);
}
impl Section for Fetch {
@@ -18,50 +22,81 @@ impl Section for Fetch {
}
fn keys(&self) -> &[&dyn Key] {
- &[&Self::NEGOTIATION_ALGORITHM]
+ &[
+ &Self::NEGOTIATION_ALGORITHM,
+ #[cfg(feature = "attributes")]
+ &Self::RECURSE_SUBMODULES,
+ ]
}
}
/// The `fetch.negotiationAlgorithm` key.
pub type NegotiationAlgorithm = keys::Any<validate::NegotiationAlgorithm>;
-mod algorithm {
- use std::borrow::Cow;
-
- use gix_object::bstr::ByteSlice;
+/// The `fetch.recurseSubmodules` key.
+#[cfg(feature = "attributes")]
+pub type RecurseSubmodules = keys::Any<validate::RecurseSubmodules>;
- use crate::{
- bstr::BStr,
- config::{key::GenericErrorWithValue, tree::sections::fetch::NegotiationAlgorithm},
- remote::fetch::negotiate,
- };
-
- impl NegotiationAlgorithm {
+mod algorithm {
+ #[cfg(feature = "credentials")]
+ impl crate::config::tree::sections::fetch::NegotiationAlgorithm {
/// Derive the negotiation algorithm identified by `name`, case-sensitively.
pub fn try_into_negotiation_algorithm(
&'static self,
- name: Cow<'_, BStr>,
- ) -> Result<negotiate::Algorithm, GenericErrorWithValue> {
+ name: std::borrow::Cow<'_, crate::bstr::BStr>,
+ ) -> Result<crate::remote::fetch::negotiate::Algorithm, crate::config::key::GenericErrorWithValue> {
+ use crate::bstr::ByteSlice;
+ use crate::remote::fetch::negotiate::Algorithm;
+
Ok(match name.as_ref().as_bytes() {
- b"noop" => negotiate::Algorithm::Noop,
- b"consecutive" | b"default" => negotiate::Algorithm::Consecutive,
- b"skipping" => negotiate::Algorithm::Skipping,
- _ => return Err(GenericErrorWithValue::from_value(self, name.into_owned())),
+ b"noop" => Algorithm::Noop,
+ b"consecutive" | b"default" => Algorithm::Consecutive,
+ b"skipping" => Algorithm::Skipping,
+ _ => {
+ return Err(crate::config::key::GenericErrorWithValue::from_value(
+ self,
+ name.into_owned(),
+ ))
+ }
})
}
}
+
+ #[cfg(feature = "attributes")]
+ impl crate::config::tree::sections::fetch::RecurseSubmodules {
+ /// Obtain the way submodules should be updated.
+ pub fn try_into_recurse_submodules(
+ &'static self,
+ value: Result<bool, gix_config::value::Error>,
+ ) -> Result<gix_submodule::config::FetchRecurse, crate::config::key::GenericErrorWithValue> {
+ gix_submodule::config::FetchRecurse::new(value)
+ .map_err(|err| crate::config::key::GenericErrorWithValue::from_value(self, err))
+ }
+ }
}
mod validate {
- use crate::{
- bstr::BStr,
- config::tree::{keys, Fetch},
- };
+ use crate::{bstr::BStr, config::tree::keys};
pub struct NegotiationAlgorithm;
impl keys::Validate for NegotiationAlgorithm {
+ #[cfg_attr(not(feature = "credentials"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "credentials")]
+ crate::config::tree::Fetch::NEGOTIATION_ALGORITHM.try_into_negotiation_algorithm(value.into())?;
+ Ok(())
+ }
+ }
+
+ pub struct RecurseSubmodules;
+ impl keys::Validate for RecurseSubmodules {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
- Fetch::NEGOTIATION_ALGORITHM.try_into_negotiation_algorithm(value.into())?;
+ #[cfg(feature = "attributes")]
+ {
+ let boolean = gix_config::Boolean::try_from(value).map(|b| b.0);
+ crate::config::tree::Fetch::RECURSE_SUBMODULES.try_into_recurse_submodules(boolean)?;
+ }
Ok(())
}
}
diff --git a/vendor/gix/src/config/tree/sections/gitoxide.rs b/vendor/gix/src/config/tree/sections/gitoxide.rs
index f07d494fb..966d5af7c 100644
--- a/vendor/gix/src/config/tree/sections/gitoxide.rs
+++ b/vendor/gix/src/config/tree/sections/gitoxide.rs
@@ -24,6 +24,8 @@ impl Gitoxide {
pub const SSH: Ssh = Ssh;
/// The `gitoxide.user` section.
pub const USER: User = User;
+ /// The `gitoxide.pathspec` section.
+ pub const PATHSPEC: Pathspec = Pathspec;
/// The `gitoxide.userAgent` Key.
pub const USER_AGENT: keys::Any = keys::Any::new("userAgent", &config::Tree::GITOXIDE).with_note(
@@ -52,6 +54,7 @@ impl Section for Gitoxide {
&Self::OBJECTS,
&Self::SSH,
&Self::USER,
+ &Self::PATHSPEC,
]
}
}
@@ -86,6 +89,12 @@ mod subsections {
.with_deviation(
"relative file paths will always be made relative to the git-common-dir, whereas `git` keeps them as is.",
);
+
+ /// The `gitoxide.core.filterProcessDelay` key (default `true`).
+ ///
+ /// It controls whether or not long running filter driver processes can use the 'delay' capability.
+ pub const FILTER_PROCESS_DELAY: keys::Boolean =
+ keys::Boolean::new_boolean("filterProcessDelay", &Gitoxide::CORE);
}
impl Section for Core {
@@ -99,6 +108,7 @@ mod subsections {
&Self::USE_NSEC,
&Self::USE_STDEV,
&Self::SHALLOW_FILE,
+ &Self::FILTER_PROCESS_DELAY,
]
}
@@ -306,6 +316,56 @@ mod subsections {
}
}
+ /// The `pathspec` sub-section.
+ #[derive(Copy, Clone, Default)]
+ pub struct Pathspec;
+
+ impl Pathspec {
+ /// The `gitoxide.pathspec.glob` key.
+ pub const GLOB: keys::Boolean = keys::Boolean::new_boolean("glob", &Gitoxide::PATHSPEC)
+ .with_environment_override("GIT_GLOB_PATHSPECS")
+ .with_note("pathspec wildcards don't match the slash character, then needing '**' to get past them");
+ /// The `gitoxide.pathspec.noglob` key.
+ pub const NOGLOB: keys::Boolean = keys::Boolean::new_boolean("noglob", &Gitoxide::PATHSPEC)
+ .with_environment_override("GIT_NOGLOB_PATHSPECS")
+ .with_note("Enable literal matching for glob patterns, effectively disabling globbing");
+ /// The `gitoxide.pathspec.literal` key.
+ pub const LITERAL: keys::Boolean = keys::Boolean::new_boolean("literal", &Gitoxide::PATHSPEC)
+ .with_environment_override("GIT_LITERAL_PATHSPECS")
+ .with_note("Make the entire spec used verbatim, the only way to get ':()name' verbatim for instance");
+ /// The `gitoxide.pathspec.icase` key.
+ pub const ICASE: keys::Boolean = keys::Boolean::new_boolean("icase", &Gitoxide::PATHSPEC)
+ .with_environment_override("GIT_ICASE_PATHSPECS")
+ .with_note("Compare string in a case-insensitive manner");
+ /// The `gitoxide.pathspec.inheritIgnoreCase` key, defaulting to `true` if unspecified.
+ /// If set, pathspecs will automatically be match case-insensitively if the underlying filesystem is configured that way.
+ pub const INHERIT_IGNORE_CASE: keys::Boolean =
+ keys::Boolean::new_boolean("inheritIgnoreCase", &Gitoxide::PATHSPEC)
+ .with_note("Inherit `core.ignoreCase` for defaults in pathspecs");
+ /// The default value for `gitoxide.pathspec.inheritIgnoreCase`.
+ pub const INHERIT_IGNORE_CASE_DEFAULT: bool = true;
+ }
+
+ impl Section for Pathspec {
+ fn name(&self) -> &str {
+ "pathspec"
+ }
+
+ fn keys(&self) -> &[&dyn Key] {
+ &[
+ &Self::GLOB,
+ &Self::NOGLOB,
+ &Self::LITERAL,
+ &Self::ICASE,
+ &Self::INHERIT_IGNORE_CASE,
+ ]
+ }
+
+ fn parent(&self) -> Option<&dyn Section> {
+ Some(&Tree::GITOXIDE)
+ }
+ }
+
/// The `objects` sub-section.
#[derive(Copy, Clone, Default)]
pub struct Objects;
@@ -391,7 +451,7 @@ mod subsections {
}
}
}
-pub use subsections::{Allow, Author, Commit, Committer, Core, Http, Https, Objects, Ssh, User};
+pub use subsections::{Allow, Author, Commit, Committer, Core, Http, Https, Objects, Pathspec, Ssh, User};
pub mod validate {
use std::error::Error;
diff --git a/vendor/gix/src/config/tree/sections/index.rs b/vendor/gix/src/config/tree/sections/index.rs
index 08f7ec1bd..026f35b6d 100644
--- a/vendor/gix/src/config/tree/sections/index.rs
+++ b/vendor/gix/src/config/tree/sections/index.rs
@@ -7,6 +7,9 @@ impl Index {
/// The `index.threads` key.
pub const THREADS: IndexThreads =
IndexThreads::new_with_validate("threads", &config::Tree::INDEX, validate::IndexThreads);
+ /// The `index.skipHash` key.
+ pub const SKIP_HASH: keys::Boolean = keys::Boolean::new_boolean("skipHash", &config::Tree::INDEX)
+ .with_deviation("also used to skip the hash when reading, even if a hash exists in the index file");
}
/// The `index.threads` key.
@@ -47,7 +50,7 @@ impl Section for Index {
}
fn keys(&self) -> &[&dyn Key] {
- &[&Self::THREADS]
+ &[&Self::THREADS, &Self::SKIP_HASH]
}
}
diff --git a/vendor/gix/src/config/tree/sections/mod.rs b/vendor/gix/src/config/tree/sections/mod.rs
index ebf24a8b7..34929c5d1 100644
--- a/vendor/gix/src/config/tree/sections/mod.rs
+++ b/vendor/gix/src/config/tree/sections/mod.rs
@@ -37,7 +37,9 @@ pub mod credential;
/// The `diff` top-level section.
#[derive(Copy, Clone, Default)]
+#[cfg(feature = "blob-diff")]
pub struct Diff;
+#[cfg(feature = "blob-diff")]
pub mod diff;
/// The `extension` top-level section.
diff --git a/vendor/gix/src/config/tree/sections/protocol.rs b/vendor/gix/src/config/tree/sections/protocol.rs
index a0510f2b8..7ef2cc8cb 100644
--- a/vendor/gix/src/config/tree/sections/protocol.rs
+++ b/vendor/gix/src/config/tree/sections/protocol.rs
@@ -127,7 +127,7 @@ mod validate {
.to_decimal()
.ok_or_else(|| format!("integer {value} cannot be represented as integer"))?;
match value {
- 0 | 1 | 2 => Ok(()),
+ 0..=2 => Ok(()),
_ => Err(format!("protocol version {value} is unknown").into()),
}
}
diff --git a/vendor/gix/src/create.rs b/vendor/gix/src/create.rs
index 878ec1164..1ef63b9aa 100644
--- a/vendor/gix/src/create.rs
+++ b/vendor/gix/src/create.rs
@@ -7,6 +7,7 @@ use std::{
use gix_config::parse::section;
use gix_discover::DOT_GIT_DIR;
+use gix_macros::momo;
/// The error used in [`into()`].
#[derive(Debug, thiserror::Error)]
@@ -35,21 +36,20 @@ pub enum Kind {
Bare,
}
-const TPL_INFO_EXCLUDE: &[u8] = include_bytes!("assets/baseline-init/info/exclude");
-const TPL_HOOKS_APPLYPATCH_MSG: &[u8] = include_bytes!("assets/baseline-init/hooks/applypatch-msg.sample");
-const TPL_HOOKS_COMMIT_MSG: &[u8] = include_bytes!("assets/baseline-init/hooks/commit-msg.sample");
-const TPL_HOOKS_FSMONITOR_WATCHMAN: &[u8] = include_bytes!("assets/baseline-init/hooks/fsmonitor-watchman.sample");
-const TPL_HOOKS_POST_UPDATE: &[u8] = include_bytes!("assets/baseline-init/hooks/post-update.sample");
-const TPL_HOOKS_PRE_APPLYPATCH: &[u8] = include_bytes!("assets/baseline-init/hooks/pre-applypatch.sample");
-const TPL_HOOKS_PRE_COMMIT: &[u8] = include_bytes!("assets/baseline-init/hooks/pre-commit.sample");
-const TPL_HOOKS_PRE_MERGE_COMMIT: &[u8] = include_bytes!("assets/baseline-init/hooks/pre-merge-commit.sample");
-const TPL_HOOKS_PRE_PUSH: &[u8] = include_bytes!("assets/baseline-init/hooks/pre-push.sample");
-const TPL_HOOKS_PRE_REBASE: &[u8] = include_bytes!("assets/baseline-init/hooks/pre-rebase.sample");
-const TPL_HOOKS_PRE_RECEIVE: &[u8] = include_bytes!("assets/baseline-init/hooks/pre-receive.sample");
-const TPL_HOOKS_PREPARE_COMMIT_MSG: &[u8] = include_bytes!("assets/baseline-init/hooks/prepare-commit-msg.sample");
-const TPL_HOOKS_UPDATE: &[u8] = include_bytes!("assets/baseline-init/hooks/update.sample");
-const TPL_DESCRIPTION: &[u8] = include_bytes!("assets/baseline-init/description");
-const TPL_HEAD: &[u8] = include_bytes!("assets/baseline-init/HEAD");
+const TPL_INFO_EXCLUDE: &[u8] = include_bytes!("assets/init/info/exclude");
+const TPL_HOOKS_APPLYPATCH_MSG: &[u8] = include_bytes!("assets/init/hooks/applypatch-msg.sample");
+const TPL_HOOKS_COMMIT_MSG: &[u8] = include_bytes!("assets/init/hooks/commit-msg.sample");
+const TPL_HOOKS_FSMONITOR_WATCHMAN: &[u8] = include_bytes!("assets/init/hooks/fsmonitor-watchman.sample");
+const TPL_HOOKS_POST_UPDATE: &[u8] = include_bytes!("assets/init/hooks/post-update.sample");
+const TPL_HOOKS_PRE_APPLYPATCH: &[u8] = include_bytes!("assets/init/hooks/pre-applypatch.sample");
+const TPL_HOOKS_PRE_COMMIT: &[u8] = include_bytes!("assets/init/hooks/pre-commit.sample");
+const TPL_HOOKS_PRE_MERGE_COMMIT: &[u8] = include_bytes!("assets/init/hooks/pre-merge-commit.sample");
+const TPL_HOOKS_PRE_PUSH: &[u8] = include_bytes!("assets/init/hooks/pre-push.sample");
+const TPL_HOOKS_PRE_REBASE: &[u8] = include_bytes!("assets/init/hooks/pre-rebase.sample");
+const TPL_HOOKS_PREPARE_COMMIT_MSG: &[u8] = include_bytes!("assets/init/hooks/prepare-commit-msg.sample");
+const TPL_HOOKS_DOCS_URL: &[u8] = include_bytes!("assets/init/hooks/docs.url");
+const TPL_DESCRIPTION: &[u8] = include_bytes!("assets/init/description");
+const TPL_HEAD: &[u8] = include_bytes!("assets/init/HEAD");
struct PathCursor<'a>(&'a mut PathBuf);
@@ -115,7 +115,7 @@ pub struct Options {
///
/// By default repos with worktree can be initialized into a non-empty repository as long as there is no `.git` directory.
pub destination_must_be_empty: bool,
- /// If set, use these filesystem capabilities to populate the respective gix-config fields.
+ /// If set, use these filesystem capabilities to populate the respective git-config fields.
/// If `None`, the directory will be probed.
pub fs_capabilities: Option<gix_fs::Capabilities>,
}
@@ -125,6 +125,7 @@ pub struct Options {
/// Note that this is a simple template-based initialization routine which should be accompanied with additional corrections
/// to respect git configuration, which is accomplished by [its callers][crate::ThreadSafeRepository::init_opts()]
/// that return a [Repository][crate::Repository].
+#[momo]
pub fn into(
directory: impl Into<PathBuf>,
kind: Kind,
@@ -172,9 +173,8 @@ pub fn into(
{
let mut cursor = NewDir(&mut dot_git).at("hooks")?;
for (tpl, filename) in &[
- (TPL_HOOKS_UPDATE, "update.sample"),
+ (TPL_HOOKS_DOCS_URL, "docs.url"),
(TPL_HOOKS_PREPARE_COMMIT_MSG, "prepare-commit-msg.sample"),
- (TPL_HOOKS_PRE_RECEIVE, "pre-receive.sample"),
(TPL_HOOKS_PRE_REBASE, "pre-rebase.sample"),
(TPL_HOOKS_PRE_PUSH, "pre-push.sample"),
(TPL_HOOKS_PRE_COMMIT, "pre-commit.sample"),
@@ -234,7 +234,7 @@ pub fn into(
} else {
gix_discover::repository::Kind::WorkTree { linked_git_dir: None }
},
- std::env::current_dir()?,
+ &std::env::current_dir()?,
)
.expect("by now the `dot_git` dir is valid as we have accessed it"))
}
diff --git a/vendor/gix/src/discover.rs b/vendor/gix/src/discover.rs
index fa0edfd5f..964108810 100644
--- a/vendor/gix/src/discover.rs
+++ b/vendor/gix/src/discover.rs
@@ -2,6 +2,7 @@
use std::path::Path;
pub use gix_discover::*;
+use gix_macros::momo;
use crate::{bstr::BString, ThreadSafeRepository};
@@ -31,12 +32,14 @@ impl ThreadSafeRepository {
/// if the directory that is discovered can indeed be trusted (or else they'd have to implement the discovery themselves
/// and be sure that no attacker ever gets access to a directory structure. The cost of this is a permission check, which
/// seems acceptable).
+ #[momo]
pub fn discover_opts(
directory: impl AsRef<Path>,
options: upwards::Options<'_>,
trust_map: gix_sec::trust::Mapping<crate::open::Options>,
) -> Result<Self, Error> {
- let (path, trust) = upwards_opts(directory, options)?;
+ let _span = gix_trace::coarse!("ThreadSafeRepository::discover()");
+ let (path, trust) = upwards_opts(directory.as_ref(), options)?;
let (git_dir, worktree_dir) = path.into_repository_and_work_tree_directories();
let mut options = trust_map.into_value_by_level(trust);
options.git_dir_trust = trust.into();
@@ -60,6 +63,7 @@ impl ThreadSafeRepository {
///
/// Finally, use the `trust_map` to determine which of our own repository options to use
/// based on the trust level of the effective repository directory.
+ #[momo]
pub fn discover_with_environment_overrides_opts(
directory: impl AsRef<Path>,
mut options: upwards::Options<'_>,
diff --git a/vendor/gix/src/env.rs b/vendor/gix/src/env.rs
index ce5461bcc..b4973b8d5 100644
--- a/vendor/gix/src/env.rs
+++ b/vendor/gix/src/env.rs
@@ -20,7 +20,7 @@ pub fn args_os() -> impl Iterator<Item = OsString> {
/// Equivalent to `std::env::args_os()`, but with precomposed unicode on MacOS and other apple platforms.
///
-/// Note that this ignores `core.precomposeUnicode` as gix-config isn't available yet. It's default enabled in modern git though.
+/// Note that this ignores `core.precomposeUnicode` as git-config isn't available yet. It's default enabled in modern git though.
#[cfg(target_vendor = "apple")]
pub fn args_os() -> impl Iterator<Item = OsString> {
use unicode_normalization::UnicodeNormalization;
@@ -65,6 +65,7 @@ pub mod collate {
#[error(transparent)]
FindExistingRemote(#[from] crate::remote::find::existing::Error),
#[error(transparent)]
+ #[cfg(feature = "credentials")]
CredentialHelperConfig(#[from] crate::config::credential_helpers::Error),
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
#[error(transparent)]
diff --git a/vendor/gix/src/ext/mod.rs b/vendor/gix/src/ext/mod.rs
index beb9007fa..ad69fec07 100644
--- a/vendor/gix/src/ext/mod.rs
+++ b/vendor/gix/src/ext/mod.rs
@@ -1,9 +1,11 @@
pub use object_id::ObjectIdExt;
pub use reference::ReferenceExt;
+#[cfg(feature = "revision")]
pub use rev_spec::RevSpecExt;
-pub use tree::TreeIterExt;
+pub use tree::{TreeEntryExt, TreeEntryRefExt, TreeIterExt};
mod object_id;
mod reference;
+#[cfg(feature = "revision")]
mod rev_spec;
mod tree;
diff --git a/vendor/gix/src/ext/tree.rs b/vendor/gix/src/ext/tree.rs
index 09220fc40..56b832b84 100644
--- a/vendor/gix/src/ext/tree.rs
+++ b/vendor/gix/src/ext/tree.rs
@@ -42,3 +42,27 @@ impl<'d> TreeIterExt for TreeRefIter<'d> {
breadthfirst(self.clone(), state, find, delegate)
}
}
+
+/// Extensions for [EntryRef][gix_object::tree::EntryRef].
+pub trait TreeEntryRefExt<'a>: 'a {
+ /// Attach [`Repository`][crate::Repository] to the given tree entry. It can be detached later with `detach()`.
+ fn attach<'repo>(self, repo: &'repo crate::Repository) -> crate::object::tree::EntryRef<'repo, 'a>;
+}
+
+impl<'a> TreeEntryRefExt<'a> for gix_object::tree::EntryRef<'a> {
+ fn attach<'repo>(self, repo: &'repo crate::Repository) -> crate::object::tree::EntryRef<'repo, 'a> {
+ crate::object::tree::EntryRef { inner: self, repo }
+ }
+}
+
+/// Extensions for [Entry][gix_object::tree::Entry].
+pub trait TreeEntryExt {
+ /// Attach [`Repository`][crate::Repository] to the given tree entry. It can be detached later with `detach()`.
+ fn attach(self, repo: &crate::Repository) -> crate::object::tree::Entry<'_>;
+}
+
+impl TreeEntryExt for gix_object::tree::Entry {
+ fn attach(self, repo: &crate::Repository) -> crate::object::tree::Entry<'_> {
+ crate::object::tree::Entry { inner: self, repo }
+ }
+}
diff --git a/vendor/gix/src/filter.rs b/vendor/gix/src/filter.rs
new file mode 100644
index 000000000..935c91108
--- /dev/null
+++ b/vendor/gix/src/filter.rs
@@ -0,0 +1,229 @@
+//! lower-level access to filters which are applied to create working tree checkouts or to 'clean' working tree contents for storage in git.
+use std::borrow::Cow;
+
+pub use gix_filter as plumbing;
+use gix_odb::{Find, FindExt};
+
+use crate::{
+ bstr::BStr,
+ config::{
+ cache::util::{ApplyLeniency, ApplyLeniencyDefaultValue},
+ tree::Core,
+ },
+ Repository,
+};
+
+///
+pub mod pipeline {
+ ///
+ pub mod options {
+ use crate::{bstr::BString, config};
+
+ /// The error returned by [Pipeline::options()][crate::filter::Pipeline::options()].
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ CheckRoundTripEncodings(#[from] config::encoding::Error),
+ #[error(transparent)]
+ SafeCrlf(#[from] config::key::GenericErrorWithValue),
+ #[error("Could not interpret 'filter.{name}.required' configuration")]
+ Driver {
+ name: BString,
+ source: gix_config::value::Error,
+ },
+ }
+ }
+
+ ///
+ pub mod convert_to_git {
+ /// The error returned by [Pipeline::convert_to_git()][crate::filter::Pipeline::convert_to_git()].
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error("Failed to prime attributes to the path at which the data resides")]
+ WorktreeCacheAtPath(#[from] std::io::Error),
+ #[error(transparent)]
+ Convert(#[from] gix_filter::pipeline::convert::to_git::Error),
+ }
+ }
+
+ ///
+ pub mod convert_to_worktree {
+ /// The error returned by [Pipeline::convert_to_worktree()][crate::filter::Pipeline::convert_to_worktree()].
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error("Failed to prime attributes to the path at which the data resides")]
+ WorktreeCacheAtPath(#[from] std::io::Error),
+ #[error(transparent)]
+ Convert(#[from] gix_filter::pipeline::convert::to_worktree::Error),
+ }
+ }
+}
+
+/// A git pipeline for transforming data *to-git* and *to-worktree*, based
+/// [on git configuration and attributes](https://git-scm.com/docs/gitattributes).
+#[derive(Clone)]
+pub struct Pipeline<'repo> {
+ inner: gix_filter::Pipeline,
+ cache: gix_worktree::Stack,
+ repo: &'repo Repository,
+}
+
+/// Lifecycle
+impl<'repo> Pipeline<'repo> {
+ /// Extract options from `repo` that are needed to properly drive a standard git filter pipeline.
+ pub fn options(repo: &'repo Repository) -> Result<gix_filter::pipeline::Options, pipeline::options::Error> {
+ let config = &repo.config.resolved;
+ let encodings =
+ Core::CHECK_ROUND_TRIP_ENCODING.try_into_encodings(config.string_by_key("core.checkRoundtripEncoding"))?;
+ let safe_crlf = config
+ .string_by_key("core.safecrlf")
+ .map(|value| Core::SAFE_CRLF.try_into_safecrlf(value))
+ .transpose()
+ .map(Option::unwrap_or_default)
+ .with_lenient_default_value(
+ repo.config.lenient_config,
+ // in lenient mode, we prefer the safe option, instead of just (trying) to output warnings.
+ gix_filter::pipeline::CrlfRoundTripCheck::Fail,
+ )?;
+ let auto_crlf = config
+ .string_by_key("core.autocrlf")
+ .map(|value| Core::AUTO_CRLF.try_into_autocrlf(value))
+ .transpose()
+ .with_leniency(repo.config.lenient_config)?
+ .unwrap_or_default();
+ let eol = config
+ .string_by_key("core.eol")
+ .map(|value| Core::EOL.try_into_eol(value))
+ .transpose()?;
+ let drivers = extract_drivers(repo)?;
+ Ok(gix_filter::pipeline::Options {
+ drivers,
+ eol_config: gix_filter::eol::Configuration { auto_crlf, eol },
+ encodings_with_roundtrip_check: encodings,
+ crlf_roundtrip_check: safe_crlf,
+ object_hash: repo.object_hash(),
+ })
+ }
+
+ /// Create a new instance by extracting all necessary information and configuration from a `repo` along with `cache` for accessing
+ /// attributes. The `index` is used for some filters which may access it under very specific circumstances.
+ pub fn new(repo: &'repo Repository, cache: gix_worktree::Stack) -> Result<Self, pipeline::options::Error> {
+ let pipeline = gix_filter::Pipeline::new(cache.attributes_collection(), Self::options(repo)?);
+ Ok(Pipeline {
+ inner: pipeline,
+ cache,
+ repo,
+ })
+ }
+
+ /// Detach the repository and obtain the individual functional parts.
+ pub fn into_parts(self) -> (gix_filter::Pipeline, gix_worktree::Stack) {
+ (self.inner, self.cache)
+ }
+}
+
+/// Conversions
+impl<'repo> Pipeline<'repo> {
+ /// Convert a `src` stream (to be found at `rela_path`, a repo-relative path) to a representation suitable for storage in `git`
+ /// by using all attributes at `rela_path` and configuration of the repository to know exactly which filters apply.
+ /// `index` is used in particularly rare cases where the CRLF filter in auto-mode tries to determine whether or not to apply itself,
+ /// and it should match the state used when [instantiating this instance][Self::new()].
+ /// Note that the return-type implements [`std::io::Read`].
+ pub fn convert_to_git<R>(
+ &mut self,
+ src: R,
+ rela_path: &std::path::Path,
+ index: &gix_index::State,
+ ) -> Result<gix_filter::pipeline::convert::ToGitOutcome<'_, R>, pipeline::convert_to_git::Error>
+ where
+ R: std::io::Read,
+ {
+ let entry = self
+ .cache
+ .at_path(rela_path, Some(false), |id, buf| self.repo.objects.find_blob(id, buf))?;
+ Ok(self.inner.convert_to_git(
+ src,
+ rela_path,
+ &mut |_, attrs| {
+ entry.matching_attributes(attrs);
+ },
+ &mut |rela_path, buf| -> Result<_, gix_odb::find::Error> {
+ let entry = match index.entry_by_path(rela_path) {
+ None => return Ok(None),
+ Some(entry) => entry,
+ };
+ let obj = self.repo.objects.try_find(&entry.id, buf)?;
+ Ok(obj.filter(|obj| obj.kind == gix_object::Kind::Blob).map(|_| ()))
+ },
+ )?)
+ }
+
+ /// Convert a `src` buffer located at `rela_path` (in the index) from what's in `git` to the worktree representation.
+ /// This method will obtain all attributes and configuration necessary to know exactly which filters to apply.
+ /// Note that the return-type implements [`std::io::Read`].
+ ///
+ /// Use `can_delay` to tell driver processes that they may delay the return of data. Doing this will require the caller to specifically
+ /// handle delayed files by keeping state and using [`Self::into_parts()`] to get access to the driver state to follow the delayed-files
+ /// protocol. For simplicity, most will want to disallow delayed processing.
+ pub fn convert_to_worktree<'input>(
+ &mut self,
+ src: &'input [u8],
+ rela_path: &BStr,
+ can_delay: gix_filter::driver::apply::Delay,
+ ) -> Result<gix_filter::pipeline::convert::ToWorktreeOutcome<'input, '_>, pipeline::convert_to_worktree::Error>
+ {
+ let entry = self
+ .cache
+ .at_entry(rela_path, Some(false), |id, buf| self.repo.objects.find_blob(id, buf))?;
+ Ok(self.inner.convert_to_worktree(
+ src,
+ rela_path,
+ &mut |_, attrs| {
+ entry.matching_attributes(attrs);
+ },
+ can_delay,
+ )?)
+ }
+
+ /// Retrieve the static context that is made available to the process filters.
+ ///
+ /// The context set here is relevant for the [`convert_to_git()`][Self::convert_to_git()] and
+ /// [`convert_to_worktree()`][Self::convert_to_worktree()] methods.
+ pub fn driver_context_mut(&mut self) -> &mut gix_filter::pipeline::Context {
+ self.inner.driver_context_mut()
+ }
+}
+
+/// Obtain a list of all configured driver, but ignore those in sections that we don't trust enough.
+fn extract_drivers(repo: &Repository) -> Result<Vec<gix_filter::Driver>, pipeline::options::Error> {
+ repo.config
+ .resolved
+ .sections_by_name("filter")
+ .into_iter()
+ .flatten()
+ .filter(|s| repo.filter_config_section()(s.meta()))
+ .filter_map(|s| {
+ s.header().subsection_name().map(|name| {
+ Ok(gix_filter::Driver {
+ name: name.to_owned(),
+ clean: s.value("clean").map(Cow::into_owned),
+ smudge: s.value("smudge").map(Cow::into_owned),
+ process: s.value("process").map(Cow::into_owned),
+ required: s
+ .value("required")
+ .map(|value| gix_config::Boolean::try_from(value.as_ref()))
+ .transpose()
+ .map_err(|err| pipeline::options::Error::Driver {
+ name: name.to_owned(),
+ source: err,
+ })?
+ .unwrap_or_default()
+ .into(),
+ })
+ })
+ })
+ .collect::<Result<Vec<_>, pipeline::options::Error>>()
+}
diff --git a/vendor/gix/src/head/mod.rs b/vendor/gix/src/head/mod.rs
index 094e78a86..399b872ba 100644
--- a/vendor/gix/src/head/mod.rs
+++ b/vendor/gix/src/head/mod.rs
@@ -101,8 +101,10 @@ mod remote {
/// This is equivalent to calling [`Reference::remote(…)`][crate::Reference::remote()] and
/// [`Repository::remote_default_name()`][crate::Repository::remote_default_name()] in order.
///
- /// Combine it with [`find_default_remote()`][crate::Repository::find_default_remote()] as fallback to handle detached heads,
- /// i.e. obtain a remote even in case of detached heads.
+ /// Combine it with [`Repository::find_default_remote()`][crate::Repository::find_default_remote()] as fallback to
+ /// handle detached heads, i.e. obtain a remote even in case of detached heads,
+ /// or call [`Repository::find_fetch_remote(…)`](crate::Repository::find_fetch_remote()) for the highest-level way of finding
+ /// the right remote, just like `git fetch` does.
pub fn into_remote(
self,
direction: remote::Direction,
diff --git a/vendor/gix/src/id.rs b/vendor/gix/src/id.rs
index 0d5c86752..7214ec320 100644
--- a/vendor/gix/src/id.rs
+++ b/vendor/gix/src/id.rs
@@ -3,9 +3,9 @@ use std::ops::Deref;
use gix_hash::{oid, ObjectId};
-use crate::{object::find, revision, Id, Object};
+use crate::{object::find, Id, Object};
-/// An [object id][ObjectId] infused with `Easy`.
+/// An [object id][ObjectId] infused with a [`Repository`][crate::Repository].
impl<'repo> Id<'repo> {
/// Find the [`Object`] associated with this object id, and consider it an error if it doesn't exist.
///
@@ -16,6 +16,13 @@ impl<'repo> Id<'repo> {
self.repo.find_object(self.inner)
}
+ /// Find the [`header`][gix_odb::find::Header] associated with this object id, or an error if it doesn't exist.
+ ///
+ /// Use this method if there is no interest in the contents of the object, which generally is much faster to obtain.
+ pub fn header(&self) -> Result<gix_odb::find::Header, find::existing::Error> {
+ self.repo.find_header(self.inner)
+ }
+
/// Try to find the [`Object`] associated with this object id, and return `None` if it's not available locally.
///
/// # Note
@@ -25,6 +32,13 @@ impl<'repo> Id<'repo> {
self.repo.try_find_object(self.inner)
}
+ /// Find the [`header`][gix_odb::find::Header] associated with this object id, or return `None` if it doesn't exist.
+ ///
+ /// Use this method if there is no interest in the contents of the object, which generally is much faster to obtain.
+ pub fn try_header(&self) -> Result<Option<gix_odb::find::Header>, find::Error> {
+ self.repo.try_find_header(self.inner)
+ }
+
/// Turn this object id into a shortened id with a length in hex as configured by `core.abbrev`.
pub fn shorten(&self) -> Result<gix_hash::Prefix, shorten::Error> {
let hex_len = self.repo.config.hex_len.map_or_else(
@@ -89,9 +103,8 @@ impl<'repo> Id<'repo> {
impl<'repo> Id<'repo> {
/// Obtain a platform for traversing ancestors of this commit.
- ///
- pub fn ancestors(&self) -> revision::walk::Platform<'repo> {
- revision::walk::Platform::new(Some(self.inner), self.repo)
+ pub fn ancestors(&self) -> crate::revision::walk::Platform<'repo> {
+ crate::revision::walk::Platform::new(Some(self.inner), self.repo)
}
}
diff --git a/vendor/gix/src/init.rs b/vendor/gix/src/init.rs
index d04de0806..21c2debd8 100644
--- a/vendor/gix/src/init.rs
+++ b/vendor/gix/src/init.rs
@@ -1,6 +1,7 @@
#![allow(clippy::result_large_err)]
use std::{borrow::Cow, convert::TryInto, path::Path};
+use gix_macros::momo;
use gix_ref::{
store::WriteReflog,
transaction::{PreviousValue, RefEdit},
@@ -29,7 +30,7 @@ pub enum Error {
#[error("Invalid default branch name: {name:?}")]
InvalidBranchName {
name: BString,
- source: gix_validate::refname::Error,
+ source: gix_validate::reference::name::Error,
},
#[error("Could not edit HEAD reference with new default name")]
EditHeadForDefaultBranch(#[from] crate::reference::edit::Error),
@@ -40,6 +41,7 @@ impl ThreadSafeRepository {
///
/// Fails without action if there is already a `.git` repository inside of `directory`, but
/// won't mind if the `directory` otherwise is non-empty.
+ #[momo]
pub fn init(
directory: impl AsRef<Path>,
kind: crate::create::Kind,
@@ -56,6 +58,7 @@ impl ThreadSafeRepository {
///
/// Instead of naming the default branch `master`, we name it `main` unless configured explicitly using the `init.defaultBranch`
/// configuration key.
+ #[momo]
pub fn init_opts(
directory: impl AsRef<Path>,
kind: crate::create::Kind,
diff --git a/vendor/gix/src/interrupt.rs b/vendor/gix/src/interrupt.rs
index c94cbdbfa..b3244a7c0 100644
--- a/vendor/gix/src/interrupt.rs
+++ b/vendor/gix/src/interrupt.rs
@@ -5,49 +5,66 @@
//! Such checks for interrupts are provided in custom implementations of various traits to transparently add interrupt
//! support to methods who wouldn't otherwise by injecting it. see [`Read`].
+#[cfg(feature = "interrupt")]
mod init {
use std::{
io,
- sync::atomic::{AtomicBool, AtomicUsize, Ordering},
+ sync::atomic::{AtomicUsize, Ordering},
};
- static IS_INITIALIZED: AtomicBool = AtomicBool::new(false);
+ static DEREGISTER_COUNT: AtomicUsize = AtomicUsize::new(0);
+ static REGISTERED_HOOKS: once_cell::sync::Lazy<parking_lot::Mutex<Vec<(i32, signal_hook::SigId)>>> =
+ once_cell::sync::Lazy::new(Default::default);
+ static DEFAULT_BEHAVIOUR_HOOKS: once_cell::sync::Lazy<parking_lot::Mutex<Vec<signal_hook::SigId>>> =
+ once_cell::sync::Lazy::new(Default::default);
+ /// A type to help deregistering hooks registered with [`init_handler`](super::init_handler());
#[derive(Default)]
- pub struct Deregister(Vec<(i32, signal_hook::SigId)>);
+ pub struct Deregister {
+ do_reset: bool,
+ }
pub struct AutoDeregister(Deregister);
impl Deregister {
- /// Remove all previously registered handlers, and assure the default behaviour is reinstated.
+ /// Remove all previously registered handlers, and assure the default behaviour is reinstated, if this is the last available instance.
///
/// Note that only the instantiation of the default behaviour can fail.
pub fn deregister(self) -> std::io::Result<()> {
- if self.0.is_empty() {
+ let mut hooks = REGISTERED_HOOKS.lock();
+ let count = DEREGISTER_COUNT.fetch_sub(1, Ordering::SeqCst);
+ if count > 1 || hooks.is_empty() {
return Ok(());
}
- static REINSTATE_DEFAULT_BEHAVIOUR: AtomicBool = AtomicBool::new(true);
- for (_, hook_id) in &self.0 {
+ if self.do_reset {
+ super::reset();
+ }
+ for (_, hook_id) in hooks.iter() {
signal_hook::low_level::unregister(*hook_id);
}
- IS_INITIALIZED.store(false, Ordering::SeqCst);
- if REINSTATE_DEFAULT_BEHAVIOUR
- .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| Some(false))
- .expect("always returns value")
- {
- for (sig, _) in self.0 {
- // # SAFETY
- // * we only call a handler that is specifically designed to run in this environment.
- #[allow(unsafe_code)]
- unsafe {
- signal_hook::low_level::register(sig, move || {
- signal_hook::low_level::emulate_default_handler(sig).ok();
- })?;
- }
+
+ let hooks = hooks.drain(..);
+ let mut default_hooks = DEFAULT_BEHAVIOUR_HOOKS.lock();
+ // Even if dropped, `drain(..)` clears the vec which is a must.
+ for (sig, _) in hooks {
+ // # SAFETY
+ // * we only register a handler that is specifically designed to run in this environment.
+ #[allow(unsafe_code)]
+ unsafe {
+ default_hooks.push(signal_hook::low_level::register(sig, move || {
+ signal_hook::low_level::emulate_default_handler(sig).ok();
+ })?);
}
}
Ok(())
}
+ /// If called with `toggle` being `true`, when actually deregistering, we will also reset the trigger by
+ /// calling [`reset()`](super::reset()).
+ pub fn with_reset(mut self, toggle: bool) -> Self {
+ self.do_reset = toggle;
+ self
+ }
+
/// Return a type that deregisters all installed signal handlers on drop.
pub fn auto_deregister(self) -> AutoDeregister {
AutoDeregister(self)
@@ -60,20 +77,33 @@ mod init {
}
}
- /// Initialize a signal handler to listen to SIGINT and SIGTERM and trigger our [`trigger()`][super::trigger()] that way.
- /// Also trigger `interrupt()` which promises to never use a Mutex, allocate or deallocate.
+ /// Initialize a signal handler to listen to SIGINT and SIGTERM and trigger our [`trigger()`](super::trigger()) that way.
+ /// Also trigger `interrupt()` which promises to never use a Mutex, allocate or deallocate, or do anything else that's blocking.
+ /// Use `grace_count` to determine how often the termination signal can be received before it's terminal, e.g. 1 would only terminate
+ /// the application the second time the signal is received.
+ /// Note that only the `grace_count` and `interrupt` of the first call are effective, all others will be ignored.
+ ///
+ /// Use the returned `Deregister` type to explicitly deregister hooks, or to do so automatically.
///
/// # Note
///
/// It will abort the process on second press and won't inform the user about this behaviour either as we are unable to do so without
/// deadlocking even when trying to write to stderr directly.
- pub fn init_handler(interrupt: impl Fn() + Send + Sync + Clone + 'static) -> io::Result<Deregister> {
- if IS_INITIALIZED
- .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| Some(true))
- .expect("always returns value")
- {
- return Err(io::Error::new(io::ErrorKind::Other, "Already initialized"));
+ pub fn init_handler(
+ grace_count: usize,
+ interrupt: impl Fn() + Send + Sync + Clone + 'static,
+ ) -> io::Result<Deregister> {
+ let prev_count = DEREGISTER_COUNT.fetch_add(1, Ordering::SeqCst);
+ if prev_count != 0 {
+ // Try to obtain the lock before we return just to wait for the signals to actually be registered.
+ let _guard = REGISTERED_HOOKS.lock();
+ return Ok(Deregister::default());
+ }
+ let mut guard = REGISTERED_HOOKS.lock();
+ if !guard.is_empty() {
+ return Ok(Deregister::default());
}
+
let mut hooks = Vec::with_capacity(signal_hook::consts::TERM_SIGNALS.len());
for sig in signal_hook::consts::TERM_SIGNALS {
// # SAFETY
@@ -88,7 +118,7 @@ mod init {
INTERRUPT_COUNT.store(0, Ordering::SeqCst);
}
let msg_idx = INTERRUPT_COUNT.fetch_add(1, Ordering::SeqCst);
- if msg_idx == 1 {
+ if msg_idx == grace_count {
gix_tempfile::registry::cleanup_tempfiles_signal_safe();
signal_hook::low_level::emulate_default_handler(*sig).ok();
}
@@ -98,11 +128,15 @@ mod init {
hooks.push((*sig, hook_id));
}
}
+ for hook_id in DEFAULT_BEHAVIOUR_HOOKS.lock().drain(..) {
+ signal_hook::low_level::unregister(hook_id);
+ }
// This means that they won't setup a handler allowing us to call them right before we actually abort.
gix_tempfile::signal::setup(gix_tempfile::signal::handler::Mode::None);
- Ok(Deregister(hooks))
+ *guard = hooks;
+ Ok(Deregister::default())
}
}
use std::{
@@ -110,7 +144,8 @@ use std::{
sync::atomic::{AtomicBool, Ordering},
};
-pub use init::init_handler;
+#[cfg(feature = "interrupt")]
+pub use init::{init_handler, Deregister};
/// A wrapper for an inner iterator which will check for interruptions on each iteration.
pub struct Iter<I, EFN> {
diff --git a/vendor/gix/src/lib.rs b/vendor/gix/src/lib.rs
index 5de702dbf..672d5c91c 100644
--- a/vendor/gix/src/lib.rs
+++ b/vendor/gix/src/lib.rs
@@ -4,7 +4,18 @@
//! individually. Sometimes it may hide complexity under the assumption that the performance difference doesn't matter
//! for all but the fewest tools out there, which would be using the underlying crates directly or file an issue.
//!
-//! # The prelude and extensions
+//! ### The Trust Model
+//!
+//! It is very simple - based on the ownership of the repository compared to the user of the current process [Trust](sec::Trust)
+//! is assigned. This can be [overridden](open::Options::with()) as well. Further, git configuration files track their trust level
+//! per section based on and sensitive values like paths to executables or certain values will be skipped if they are from a source
+//! that isn't [fully](sec::Trust::Full) trusted.
+//!
+//! That way, data can safely be obtained without risking to execute untrusted executables.
+//!
+//! Note that it's possible to let `gix` act like `git` or `git2` by setting the [open::Options::bail_if_untrusted()] option.
+//!
+//! ### The prelude and extensions
//!
//! With `use git_repository::prelude::*` you should be ready to go as it pulls in various extension traits to make functionality
//! available on objects that may use it.
@@ -14,13 +25,13 @@
//! Most extensions to existing objects provide an `obj_with_extension.attach(&repo).an_easier_version_of_a_method()` for simpler
//! call signatures.
//!
-//! ## `ThreadSafe` Mode
+//! ### `ThreadSafe` Mode
//!
//! By default, the [`Repository`] isn't `Sync` and thus can't be used in certain contexts which require the `Sync` trait.
//!
//! To help with this, convert it with [`.into_sync()`][Repository::into_sync()] into a [`ThreadSafeRepository`].
//!
-//! ## Object-Access Performance
+//! ### Object-Access Performance
//!
//! Accessing objects quickly is the bread-and-butter of working with git, right after accessing references. Hence it's vital
//! to understand which cache levels exist and how to leverage them.
@@ -42,9 +53,9 @@
//! When reading the documentation of the canonical gix-worktree program one gets the impression work tree and working tree are used
//! interchangeably. We use the term _work tree_ only and try to do so consistently as its shorter and assumed to be the same.
//!
-//! # Cargo-features
+//! ### Plumbing Crates
//!
-//! To make using _sub-crates_ easier these are re-exported into the root of this crate. Here we list how to access nested plumbing
+//! To make using _sub-crates_ and their types easier, these are re-exported into the root of this crate. Here we list how to access nested plumbing
//! crates which are otherwise harder to discover:
//!
//! **`git_repository::`**
@@ -54,44 +65,69 @@
//! * [`transport`][protocol::transport]
//! * [`packetline`][protocol::transport::packetline]
//!
+//! ### `libgit2` API to `gix`
+//!
+//! This doc-aliases are used to help finding methods under a possibly changed name. Just search in the docs.
+//! Entering `git2` into the search field will also surface all methods with such annotations.
+//!
+//! What follows is a list of methods you might be missing, along with workarounds if available.
+//! * [`git2::Repository::open_bare()`](https://docs.rs/git2/*/git2/struct.Repository.html#method.open_bare) ➡ ❌ - use [`open()`] and discard if it is not bare.
+//! * [`git2::build::CheckoutBuilder::disable_filters()](https://docs.rs/git2/*/git2/build/struct.CheckoutBuilder.html#method.disable_filters) ➡ ❌ *(filters are always applied during checkouts)*
+//! * [`git2::Repository::submodule_status()`](https://docs.rs/git2/*/git2/struct.Repository.html#method.submodule_status) ➡ [`Submodule::state()`] - status provides more information and conveniences though, and an actual worktree status isn't performed.
//!
-//! ## Feature Flags
+//! ### Feature Flags
#![cfg_attr(
feature = "document-features",
cfg_attr(doc, doc = ::document_features::document_features!())
)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![deny(missing_docs, rust_2018_idioms, unsafe_code)]
+#![allow(clippy::result_large_err)]
// Re-exports to make this a potential one-stop shop crate avoiding people from having to reference various crates themselves.
// This also means that their major version changes affect our major version, but that's alright as we directly expose their
// APIs/instances anyway.
pub use gix_actor as actor;
+#[cfg(feature = "attributes")]
pub use gix_attributes as attrs;
pub use gix_commitgraph as commitgraph;
+#[cfg(feature = "credentials")]
pub use gix_credentials as credentials;
pub use gix_date as date;
pub use gix_features as features;
use gix_features::threading::OwnShared;
-pub use gix_features::{parallel, progress::Progress, threading};
+pub use gix_features::{
+ parallel,
+ progress::{Count, DynNestedProgress, NestedProgress, Progress},
+ threading,
+};
pub use gix_fs as fs;
pub use gix_glob as glob;
pub use gix_hash as hash;
+pub use gix_hashtable as hashtable;
+#[cfg(feature = "excludes")]
pub use gix_ignore as ignore;
#[doc(inline)]
+#[cfg(feature = "index")]
pub use gix_index as index;
pub use gix_lock as lock;
+#[cfg(feature = "credentials")]
pub use gix_negotiate as negotiate;
pub use gix_object as objs;
pub use gix_object::bstr;
pub use gix_odb as odb;
+#[cfg(feature = "credentials")]
pub use gix_prompt as prompt;
-#[cfg(all(feature = "gix-protocol"))]
+#[cfg(feature = "gix-protocol")]
pub use gix_protocol as protocol;
pub use gix_ref as refs;
pub use gix_refspec as refspec;
+pub use gix_revwalk as revwalk;
pub use gix_sec as sec;
+#[cfg(feature = "status")]
+pub use gix_status as status;
pub use gix_tempfile as tempfile;
+pub use gix_trace as trace;
pub use gix_traverse as traverse;
pub use gix_url as url;
#[doc(inline)]
@@ -101,13 +137,13 @@ pub use hash::{oid, ObjectId};
pub mod interrupt;
-///
-pub mod attributes;
-
mod ext;
///
pub mod prelude;
+#[cfg(feature = "excludes")]
+mod attribute_stack;
+
///
pub mod path;
@@ -118,11 +154,14 @@ pub type OdbHandle = gix_odb::Handle;
/// A way to access git configuration
pub(crate) type Config = OwnShared<gix_config::File<'static>>;
-///
mod types;
+#[cfg(any(feature = "excludes", feature = "attributes"))]
+pub use types::AttributeStack;
pub use types::{
Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree, Worktree,
};
+#[cfg(feature = "attributes")]
+pub use types::{Pathspec, PathspecDetached, Submodule};
///
pub mod clone;
@@ -130,8 +169,12 @@ pub mod commit;
pub mod head;
pub mod id;
pub mod object;
+#[cfg(feature = "attributes")]
+pub mod pathspec;
pub mod reference;
pub mod repository;
+#[cfg(feature = "attributes")]
+pub mod submodule;
pub mod tag;
///
@@ -217,12 +260,14 @@ fn open_opts_with_git_binary_config() -> open::Options {
/// See [`ThreadSafeRepository::open()`], but returns a [`Repository`] instead.
#[allow(clippy::result_large_err)]
+#[doc(alias = "git2")]
pub fn open(directory: impl Into<std::path::PathBuf>) -> Result<Repository, open::Error> {
ThreadSafeRepository::open(directory).map(Into::into)
}
/// See [`ThreadSafeRepository::open_opts()`], but returns a [`Repository`] instead.
#[allow(clippy::result_large_err)]
+#[doc(alias = "open_ext", alias = "git2")]
pub fn open_opts(directory: impl Into<std::path::PathBuf>, options: open::Options) -> Result<Repository, open::Error> {
ThreadSafeRepository::open_opts(directory, options).map(Into::into)
}
@@ -237,6 +282,7 @@ pub mod open;
pub mod config;
///
+#[cfg(feature = "mailmap")]
pub mod mailmap;
///
@@ -244,6 +290,9 @@ pub mod worktree;
pub mod revision;
+#[cfg(feature = "attributes")]
+pub mod filter;
+
///
pub mod remote;
diff --git a/vendor/gix/src/object/blob.rs b/vendor/gix/src/object/blob.rs
index f35605422..00b3519ed 100644
--- a/vendor/gix/src/object/blob.rs
+++ b/vendor/gix/src/object/blob.rs
@@ -1,4 +1,5 @@
///
+#[cfg(feature = "blob-diff")]
pub mod diff {
use std::ops::Range;
diff --git a/vendor/gix/src/object/commit.rs b/vendor/gix/src/object/commit.rs
index 5a9dfd4f3..1fb9eff67 100644
--- a/vendor/gix/src/object/commit.rs
+++ b/vendor/gix/src/object/commit.rs
@@ -1,4 +1,4 @@
-use crate::{bstr, bstr::BStr, revision, Commit, ObjectDetached, Tree};
+use crate::{bstr, bstr::BStr, Commit, ObjectDetached, Tree};
mod error {
use crate::object;
@@ -65,7 +65,7 @@ impl<'repo> Commit<'repo> {
/// Decode the commit and obtain the time at which the commit was created.
///
/// For the time at which it was authored, refer to `.decode()?.author.time`.
- pub fn time(&self) -> Result<gix_actor::Time, Error> {
+ pub fn time(&self) -> Result<gix_date::Time, Error> {
Ok(self.committer()?.time)
}
@@ -131,12 +131,13 @@ impl<'repo> Commit<'repo> {
}
/// Obtain a platform for traversing ancestors of this commit.
- pub fn ancestors(&self) -> revision::walk::Platform<'repo> {
+ pub fn ancestors(&self) -> crate::revision::walk::Platform<'repo> {
self.id().ancestors()
}
/// Create a platform to further configure a `git describe` operation to find a name for this commit by looking
/// at the closest annotated tags (by default) in its past.
+ #[cfg(feature = "revision")]
pub fn describe(&self) -> crate::commit::describe::Platform<'repo> {
crate::commit::describe::Platform {
id: self.id,
@@ -147,6 +148,15 @@ impl<'repo> Commit<'repo> {
max_candidates: 10,
}
}
+
+ /// Extracts the PGP signature and the data that was used to create the signature, or `None` if it wasn't signed.
+ // TODO: make it possible to verify the signature, probably by wrapping `SignedData`. It's quite some work to do it properly.
+ pub fn signature(
+ &self,
+ ) -> Result<Option<(std::borrow::Cow<'_, BStr>, gix_object::commit::SignedData<'_>)>, gix_object::decode::Error>
+ {
+ gix_object::CommitRefIter::signature(&self.data)
+ }
}
impl<'r> std::fmt::Debug for Commit<'r> {
diff --git a/vendor/gix/src/object/errors.rs b/vendor/gix/src/object/errors.rs
index eb7733473..92789b6cb 100644
--- a/vendor/gix/src/object/errors.rs
+++ b/vendor/gix/src/object/errors.rs
@@ -18,17 +18,21 @@ pub mod conversion {
///
pub mod find {
/// Indicate that an error occurred when trying to find an object.
- pub type Error = gix_odb::store::find::Error;
+ #[derive(Debug, thiserror::Error)]
+ #[error(transparent)]
+ pub struct Error(#[from] pub gix_odb::find::Error);
///
pub mod existing {
/// An object could not be found in the database, or an error occurred when trying to obtain it.
- pub type Error = gix_odb::find::existing::Error<gix_odb::store::find::Error>;
+ pub type Error = gix_odb::find::existing::Error;
}
}
///
pub mod write {
/// An error to indicate writing to the loose object store failed.
- pub type Error = gix_odb::store::write::Error;
+ #[derive(Debug, thiserror::Error)]
+ #[error(transparent)]
+ pub struct Error(#[from] pub gix_odb::find::Error);
}
diff --git a/vendor/gix/src/object/tree/diff/for_each.rs b/vendor/gix/src/object/tree/diff/for_each.rs
index a72033182..3932f9027 100644
--- a/vendor/gix/src/object/tree/diff/for_each.rs
+++ b/vendor/gix/src/object/tree/diff/for_each.rs
@@ -75,8 +75,9 @@ impl<'a, 'old> Platform<'a, 'old> {
}
Err(gix_diff::tree::changes::Error::Cancelled) => delegate
.err
- .map(|err| Err(Error::ForEach(Box::new(err))))
- .unwrap_or(Err(Error::Diff(gix_diff::tree::changes::Error::Cancelled))),
+ .map_or(Err(Error::Diff(gix_diff::tree::changes::Error::Cancelled)), |err| {
+ Err(Error::ForEach(Box::new(err)))
+ }),
Err(err) => Err(err.into()),
}
}
diff --git a/vendor/gix/src/object/tree/diff/mod.rs b/vendor/gix/src/object/tree/diff/mod.rs
index 447eeaa84..5f7a041e4 100644
--- a/vendor/gix/src/object/tree/diff/mod.rs
+++ b/vendor/gix/src/object/tree/diff/mod.rs
@@ -34,6 +34,10 @@ impl<'repo> Tree<'repo> {
///
/// It's highly recommended to set an object cache to avoid extracting the same object multiple times.
/// By default, similar to `git diff`, rename tracking will be enabled if it is not configured.
+ ///
+ /// Note that if a clone with `--filter=blob=none` was created, rename tracking may fail as it might
+ /// try to access blobs to compute a similarity metric. Thus, it's more compatible to turn rewrite tracking off
+ /// using [`Platform::track_rewrites()`].
#[allow(clippy::result_large_err)]
pub fn changes<'a>(&'a self) -> Result<Platform<'a, 'repo>, rewrites::Error> {
Ok(Platform {
diff --git a/vendor/gix/src/object/tree/diff/rewrites.rs b/vendor/gix/src/object/tree/diff/rewrites.rs
index 1502048ec..e434726d9 100644
--- a/vendor/gix/src/object/tree/diff/rewrites.rs
+++ b/vendor/gix/src/object/tree/diff/rewrites.rs
@@ -80,7 +80,7 @@ impl Rewrites {
let key = "diff.renames";
let copies = match config
.boolean_by_key(key)
- .map(|value| Diff::RENAMES.try_into_renames(value, || config.string_by_key(key)))
+ .map(|value| Diff::RENAMES.try_into_renames(value))
.transpose()
.with_leniency(lenient)?
{
diff --git a/vendor/gix/src/object/tree/iter.rs b/vendor/gix/src/object/tree/iter.rs
index c841e2574..848d9eeab 100644
--- a/vendor/gix/src/object/tree/iter.rs
+++ b/vendor/gix/src/object/tree/iter.rs
@@ -25,10 +25,25 @@ impl<'repo, 'a> EntryRef<'repo, 'a> {
crate::Id::from_id(self.inner.oid, self.repo)
}
- /// Return the entries id, without repository connection.
- pub fn oid(&self) -> gix_hash::ObjectId {
+ /// Return the plain object id of this entry, without access to the repository.
+ pub fn oid(&self) -> &gix_hash::oid {
+ self.inner.oid
+ }
+
+ /// Return the object this entry points to.
+ pub fn object(&self) -> Result<crate::Object<'repo>, crate::object::find::existing::Error> {
+ self.id().object()
+ }
+
+ /// Return the plain object id of this entry, without access to the repository.
+ pub fn object_id(&self) -> gix_hash::ObjectId {
self.inner.oid.to_owned()
}
+
+ /// Detach the repository from this instance.
+ pub fn detach(&self) -> gix_object::tree::EntryRef<'a> {
+ self.inner
+ }
}
impl<'repo, 'a> std::fmt::Display for EntryRef<'repo, 'a> {
diff --git a/vendor/gix/src/object/tree/mod.rs b/vendor/gix/src/object/tree/mod.rs
index bbd392289..5bf59a25c 100644
--- a/vendor/gix/src/object/tree/mod.rs
+++ b/vendor/gix/src/object/tree/mod.rs
@@ -1,5 +1,8 @@
use gix_hash::ObjectId;
+use gix_macros::momo;
+pub use gix_object::tree::EntryMode;
use gix_object::{bstr::BStr, TreeRefIter};
+use gix_odb::FindExt;
use crate::{object::find, Id, Tree};
@@ -27,9 +30,20 @@ impl<'repo> Tree<'repo> {
gix_object::TreeRef::from_bytes(&self.data)
}
- // TODO: tests.
+ /// Find the entry named `name` by iteration, or return `None` if it wasn't found.
+ pub fn find_entry(&self, name: impl PartialEq<BStr>) -> Option<EntryRef<'repo, '_>> {
+ TreeRefIter::from_bytes(&self.data)
+ .filter_map(Result::ok)
+ .find(|entry| name.eq(entry.filename))
+ .map(|entry| EntryRef {
+ inner: entry,
+ repo: self.repo,
+ })
+ }
+
/// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component
/// is looked up and its tree entry is returned.
+ /// Use `buf` as temporary location for sub-trees to avoid allocating a temporary buffer for each lookup.
///
/// # Performance Notes
///
@@ -37,12 +51,51 @@ impl<'repo> Tree<'repo> {
/// to re-use a vector and use a binary search instead, which might be able to improve performance over all.
/// However, a benchmark should be created first to have some data and see which trade-off to choose here.
///
- /// # Why is this consuming?
+ pub fn lookup_entry<I, P>(&self, path: I, buf: &mut Vec<u8>) -> Result<Option<Entry<'repo>>, find::existing::Error>
+ where
+ I: IntoIterator<Item = P>,
+ P: PartialEq<BStr>,
+ {
+ let mut path = path.into_iter().peekable();
+ buf.clear();
+ buf.extend_from_slice(&self.data);
+ while let Some(component) = path.next() {
+ match TreeRefIter::from_bytes(buf)
+ .filter_map(Result::ok)
+ .find(|entry| component.eq(entry.filename))
+ {
+ Some(entry) => {
+ if path.peek().is_none() {
+ return Ok(Some(Entry {
+ inner: entry.into(),
+ repo: self.repo,
+ }));
+ } else {
+ let next_id = entry.oid.to_owned();
+ let obj = self.repo.objects.find(&next_id, buf)?;
+ if !obj.kind.is_tree() {
+ return Ok(None);
+ }
+ }
+ }
+ None => return Ok(None),
+ }
+ }
+ Ok(None)
+ }
+
+ /// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component
+ /// is looked up and its tree entry is returned, while changing this instance to point to the last seen tree.
+ /// Note that if the lookup fails, it may be impossible to continue making lookups through this tree.
+ /// It's useful to have this function to be able to reuse the internal buffer of the tree.
+ ///
+ /// # Performance Notes
+ ///
+ /// Searching tree entries is currently done in sequence, which allows to the search to be allocation free. It would be possible
+ /// to re-use a vector and use a binary search instead, which might be able to improve performance over all.
+ /// However, a benchmark should be created first to have some data and see which trade-off to choose here.
///
- /// The borrow checker shows pathological behaviour in loops that mutate a buffer, but also want to return from it.
- /// Workarounds include keeping an index and doing a separate access to the memory, which seems hard to do here without
- /// re-parsing the entries.
- pub fn lookup_entry<I, P>(mut self, path: I) -> Result<Option<Entry<'repo>>, find::existing::Error>
+ pub fn peel_to_entry<I, P>(&mut self, path: I) -> Result<Option<Entry<'repo>>, find::existing::Error>
where
I: IntoIterator<Item = P>,
P: PartialEq<BStr>,
@@ -61,12 +114,11 @@ impl<'repo> Tree<'repo> {
}));
} else {
let next_id = entry.oid.to_owned();
- let repo = self.repo;
- drop(self);
- self = match repo.find_object(next_id)?.try_into_tree() {
- Ok(tree) => tree,
- Err(_) => return Ok(None),
- };
+ let obj = self.repo.objects.find(&next_id, &mut self.data)?;
+ self.id = next_id;
+ if !obj.kind.is_tree() {
+ return Ok(None);
+ }
}
}
None => return Ok(None),
@@ -75,18 +127,42 @@ impl<'repo> Tree<'repo> {
Ok(None)
}
- /// Like [`lookup_entry()`][Self::lookup_entry()], but takes a `Path` directly via `relative_path`, a path relative to this tree.
+ /// Like [`Self::lookup_entry()`], but takes a `Path` directly via `relative_path`, a path relative to this tree.
///
/// # Note
///
/// If any path component contains illformed UTF-8 and thus can't be converted to bytes on platforms which can't do so natively,
/// the returned component will be empty which makes the lookup fail.
+ #[momo]
pub fn lookup_entry_by_path(
- self,
+ &self,
+ relative_path: impl AsRef<std::path::Path>,
+ buf: &mut Vec<u8>,
+ ) -> Result<Option<Entry<'repo>>, find::existing::Error> {
+ use crate::bstr::ByteSlice;
+ self.lookup_entry(
+ relative_path.as_ref().components().map(|c: std::path::Component<'_>| {
+ gix_path::os_str_into_bstr(c.as_os_str())
+ .unwrap_or_else(|_| "".into())
+ .as_bytes()
+ }),
+ buf,
+ )
+ }
+
+ /// Like [`Self::peel_to_entry()`], but takes a `Path` directly via `relative_path`, a path relative to this tree.
+ ///
+ /// # Note
+ ///
+ /// If any path component contains illformed UTF-8 and thus can't be converted to bytes on platforms which can't do so natively,
+ /// the returned component will be empty which makes the lookup fail.
+ #[momo]
+ pub fn peel_to_entry_by_path(
+ &mut self,
relative_path: impl AsRef<std::path::Path>,
) -> Result<Option<Entry<'repo>>, find::existing::Error> {
use crate::bstr::ByteSlice;
- self.lookup_entry(relative_path.as_ref().components().map(|c: std::path::Component<'_>| {
+ self.peel_to_entry(relative_path.as_ref().components().map(|c: std::path::Component<'_>| {
gix_path::os_str_into_bstr(c.as_os_str())
.unwrap_or_else(|_| "".into())
.as_bytes()
@@ -95,6 +171,7 @@ impl<'repo> Tree<'repo> {
}
///
+#[cfg(feature = "blob-diff")]
pub mod diff;
///
@@ -113,8 +190,8 @@ impl<'r> std::fmt::Debug for Tree<'r> {
/// An entry in a [`Tree`], similar to an entry in a directory.
#[derive(PartialEq, Debug, Clone)]
pub struct Entry<'repo> {
- inner: gix_object::tree::Entry,
- repo: &'repo crate::Repository,
+ pub(crate) inner: gix_object::tree::Entry,
+ pub(crate) repo: &'repo crate::Repository,
}
mod entry {
diff --git a/vendor/gix/src/open/options.rs b/vendor/gix/src/open/options.rs
index b098d55c1..930fb414c 100644
--- a/vendor/gix/src/open/options.rs
+++ b/vendor/gix/src/open/options.rs
@@ -149,6 +149,12 @@ impl Options {
}
}
+impl Options {
+ pub(crate) fn current_dir_or_empty(&self) -> &std::path::Path {
+ self.current_dir.as_deref().unwrap_or(std::path::Path::new(""))
+ }
+}
+
impl gix_sec::trust::DefaultForLevel for Options {
fn default_for_level(level: gix_sec::Trust) -> Self {
match level {
diff --git a/vendor/gix/src/open/repository.rs b/vendor/gix/src/open/repository.rs
index e89fdc430..fde647a4e 100644
--- a/vendor/gix/src/open/repository.rs
+++ b/vendor/gix/src/open/repository.rs
@@ -2,6 +2,7 @@
use std::{borrow::Cow, path::PathBuf};
use gix_features::threading::OwnShared;
+use gix_macros::momo;
use super::{Error, Options};
use crate::{
@@ -50,7 +51,17 @@ impl ThreadSafeRepository {
/// `options` for fine-grained control.
///
/// Note that you should use [`crate::discover()`] if security should be adjusted by ownership.
+ ///
+ /// ### Differences to `git2::Repository::open_ext()`
+ ///
+ /// Whereas `open_ext()` is the jack-of-all-trades that can do anything depending on its options, `gix` will always differentiate
+ /// between discovering git repositories by searching, and opening a well-known repository by work tree or `.git` repository.
+ ///
+ /// Note that opening a repository for implementing custom hooks is also handle specifically in
+ /// [`open_with_environment_overrides()`][Self::open_with_environment_overrides()].
+ #[momo]
pub fn open_opts(path: impl Into<PathBuf>, mut options: Options) -> Result<Self, Error> {
+ let _span = gix_trace::coarse!("ThreadSafeRepository::open()");
let (path, kind) = {
let path = path.into();
let looks_like_git_dir =
@@ -96,13 +107,16 @@ impl ThreadSafeRepository {
/// Note that this will read various `GIT_*` environment variables to check for overrides, and is probably most useful when implementing
/// custom hooks.
// TODO: tests, with hooks, GIT_QUARANTINE for ref-log and transaction control (needs gix-sec support to remove write access in gix-ref)
- // TODO: The following vars should end up as overrides of the respective configuration values (see gix-config).
+ // TODO: The following vars should end up as overrides of the respective configuration values (see git-config).
// GIT_PROXY_SSL_CERT, GIT_PROXY_SSL_KEY, GIT_PROXY_SSL_CERT_PASSWORD_PROTECTED.
// GIT_PROXY_SSL_CAINFO, GIT_SSL_CIPHER_LIST, GIT_HTTP_MAX_REQUESTS, GIT_CURL_FTP_NO_EPSV,
+ #[doc(alias = "open_from_env", alias = "git2")]
+ #[momo]
pub fn open_with_environment_overrides(
fallback_directory: impl Into<PathBuf>,
trust_map: gix_sec::trust::Mapping<Options>,
) -> Result<Self, Error> {
+ let _span = gix_trace::coarse!("ThreadSafeRepository::open_with_environment_overrides()");
let overrides = EnvironmentOverrides::from_env()?;
let (path, path_kind): (PathBuf, _) = match overrides.git_dir {
Some(git_dir) => gix_discover::is_git(&git_dir)
@@ -139,6 +153,7 @@ impl ThreadSafeRepository {
mut worktree_dir: Option<PathBuf>,
options: Options,
) -> Result<Self, Error> {
+ let _span = gix_trace::detail!("open_from_paths()");
let Options {
git_dir_trust,
object_store_slots,
@@ -164,7 +179,7 @@ impl ThreadSafeRepository {
// This would be something read in later as have to first check for extensions. Also this means
// that each worktree, even if accessible through this instance, has to come in its own Repository instance
// as it may have its own configuration. That's fine actually.
- let common_dir = gix_discover::path::from_plain_file(git_dir.join("commondir"))
+ let common_dir = gix_discover::path::from_plain_file(git_dir.join("commondir").as_ref())
.transpose()?
.map(|cd| git_dir.join(cd));
let common_dir_ref = common_dir.as_deref().unwrap_or(&git_dir);
@@ -180,8 +195,10 @@ impl ThreadSafeRepository {
let reflog = repo_config.reflog.unwrap_or(gix_ref::store::WriteReflog::Disable);
let object_hash = repo_config.object_hash;
match &common_dir {
- Some(common_dir) => crate::RefStore::for_linked_worktree(&git_dir, common_dir, reflog, object_hash),
- None => crate::RefStore::at(&git_dir, reflog, object_hash),
+ Some(common_dir) => {
+ crate::RefStore::for_linked_worktree(git_dir.to_owned(), common_dir.into(), reflog, object_hash)
+ }
+ None => crate::RefStore::at(git_dir.to_owned(), reflog, object_hash),
}
};
let head = refs.find("HEAD").ok();
@@ -205,7 +222,13 @@ impl ThreadSafeRepository {
)?;
if bail_if_untrusted && git_dir_trust != gix_sec::Trust::Full {
- check_safe_directories(&git_dir, git_install_dir.as_deref(), home.as_deref(), &config)?;
+ check_safe_directories(
+ &git_dir,
+ git_install_dir.as_deref(),
+ current_dir,
+ home.as_deref(),
+ &config,
+ )?;
}
// core.worktree might be used to overwrite the worktree directory
@@ -218,7 +241,7 @@ impl ThreadSafeRepository {
.interpolate(interpolate_context(git_install_dir.as_deref(), home.as_deref()))
.map_err(config::Error::PathInterpolation)?;
worktree_dir = {
- gix_path::normalize(git_dir.join(wt_path), current_dir)
+ gix_path::normalize(git_dir.join(wt_path).into(), current_dir)
.and_then(|wt| wt.as_ref().is_dir().then(|| wt.into_owned()))
}
}
@@ -238,6 +261,7 @@ impl ThreadSafeRepository {
refs.write_reflog = config::cache::util::reflog_or_default(config.reflog, worktree_dir.is_some());
let replacements = replacement_objects_refs_prefix(&config.resolved, lenient_config, filter_config_section)?
.and_then(|prefix| {
+ let _span = gix_trace::detail!("find replacement objects");
let platform = refs.iter().ok()?;
let iter = platform.prefixed(&prefix).ok()?;
let prefix = prefix.to_str()?;
@@ -257,7 +281,7 @@ impl ThreadSafeRepository {
Ok(ThreadSafeRepository {
objects: OwnShared::new(gix_odb::Store::at_opts(
common_dir_ref.join("objects"),
- replacements,
+ &mut replacements.into_iter(),
gix_odb::store::init::Options {
slots: object_store_slots,
object_hash: config.object_hash,
@@ -271,8 +295,11 @@ impl ThreadSafeRepository {
config,
// used when spawning new repositories off this one when following worktrees
linked_worktree_options: options,
+ #[cfg(feature = "index")]
index: gix_fs::SharedFileSnapshotMut::new().into(),
shallow_commits: gix_fs::SharedFileSnapshotMut::new().into(),
+ #[cfg(feature = "attributes")]
+ modules: gix_fs::SharedFileSnapshotMut::new().into(),
})
}
}
@@ -309,11 +336,12 @@ fn replacement_objects_refs_prefix(
fn check_safe_directories(
git_dir: &std::path::Path,
git_install_dir: Option<&std::path::Path>,
+ current_dir: &std::path::Path,
home: Option<&std::path::Path>,
config: &config::Cache,
) -> Result<(), Error> {
let mut is_safe = false;
- let git_dir = match gix_path::realpath(git_dir) {
+ let git_dir = match gix_path::realpath_opts(git_dir, current_dir, gix_path::realpath::MAX_SYMLINKS) {
Ok(p) => p,
Err(_) => git_dir.to_owned(),
};
diff --git a/vendor/gix/src/pathspec.rs b/vendor/gix/src/pathspec.rs
new file mode 100644
index 000000000..235a91d76
--- /dev/null
+++ b/vendor/gix/src/pathspec.rs
@@ -0,0 +1,207 @@
+//! Pathspec plumbing and abstractions
+use gix_macros::momo;
+use gix_odb::FindExt;
+pub use gix_pathspec::*;
+
+use crate::{bstr::BStr, AttributeStack, Pathspec, PathspecDetached, Repository};
+
+///
+pub mod init {
+ /// The error returned by [`Pathspec::new()`](super::Pathspec::new()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ MakeAttributes(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
+ #[error(transparent)]
+ Defaults(#[from] crate::repository::pathspec_defaults_ignore_case::Error),
+ #[error(transparent)]
+ ParseSpec(#[from] gix_pathspec::parse::Error),
+ #[error(
+ "Could not obtain the repository prefix as the relative path of the CWD as seen from the working tree"
+ )]
+ NormalizeSpec(#[from] gix_pathspec::normalize::Error),
+ #[error(transparent)]
+ RepoPrefix(#[from] gix_path::realpath::Error),
+ }
+}
+
+/// Lifecycle
+impl<'repo> Pathspec<'repo> {
+ /// Create a new instance by parsing `patterns` into [`Pathspecs`](Pattern) to make them usable for searches.
+ /// `make_attribute` may be called if one of the patterns has a `(attr:a)` element which requires attribute matching. It should
+ /// be used to control where attributes are coming from.
+ /// If `inherit_ignore_case` is `true`, the pathspecs may have their ignore-case default overridden to be case-insensitive by default.
+ /// This only works towards turning ignore-case for pathspecs on, but won't ever turn that setting off if.
+ ///
+ /// ### Deviation
+ ///
+ /// Pathspecs can declare to be case-insensitive as part of their elements, which is a setting that is now respected for attribute
+ /// queries as well.
+ pub fn new(
+ repo: &'repo Repository,
+ patterns: impl IntoIterator<Item = impl AsRef<BStr>>,
+ inherit_ignore_case: bool,
+ make_attributes: impl FnOnce() -> Result<gix_worktree::Stack, Box<dyn std::error::Error + Send + Sync + 'static>>,
+ ) -> Result<Self, init::Error> {
+ let defaults = repo.pathspec_defaults_inherit_ignore_case(inherit_ignore_case)?;
+ let patterns = patterns
+ .into_iter()
+ .map(move |p| parse(p.as_ref(), defaults))
+ .collect::<Result<Vec<_>, _>>()?;
+ let needs_cache = patterns.iter().any(|p| !p.attributes.is_empty());
+ let search = Search::from_specs(
+ patterns,
+ repo.prefix()?,
+ &gix_path::realpath_opts(
+ repo.work_dir().unwrap_or_else(|| repo.git_dir()),
+ repo.options.current_dir_or_empty(),
+ gix_path::realpath::MAX_SYMLINKS,
+ )?,
+ )?;
+ let cache = needs_cache.then(make_attributes).transpose()?;
+ Ok(Self {
+ repo,
+ search,
+ stack: cache,
+ })
+ }
+ /// Turn ourselves into the functional parts for direct usage.
+ /// Note that the [`cache`](AttributeStack) is only set if one of the [`search` patterns](Search)
+ /// is specifying attributes to match for.
+ pub fn into_parts(self) -> (Search, Option<AttributeStack<'repo>>) {
+ (
+ self.search,
+ self.stack.map(|stack| AttributeStack::new(stack, self.repo)),
+ )
+ }
+
+ /// Turn ourselves into an implementation that works without a repository instance and that is rather minimal.
+ pub fn detach(self) -> std::io::Result<PathspecDetached> {
+ Ok(PathspecDetached {
+ search: self.search,
+ stack: self.stack,
+ odb: self.repo.objects.clone().into_arc()?,
+ })
+ }
+}
+
+/// Access
+impl<'repo> Pathspec<'repo> {
+ /// Return the attributes cache which is used when matching attributes in pathspecs, or `None` if none of the pathspecs require that.
+ pub fn attributes(&self) -> Option<&gix_worktree::Stack> {
+ self.stack.as_ref()
+ }
+
+ /// Return the search itself which can be used for matching paths or accessing the actual patterns that will be used.
+ pub fn search(&self) -> &gix_pathspec::Search {
+ &self.search
+ }
+
+ /// Return the first [`Match`](search::Match) of `relative_path`, or `None`.
+ /// Note that the match might [be excluded](search::Match::is_excluded()).
+ /// `is_dir` is true if `relative_path` is a directory.
+ #[doc(
+ alias = "match_diff",
+ alias = "match_tree",
+ alias = "match_index",
+ alias = "match_workdir",
+ alias = "matches_path",
+ alias = "git2"
+ )]
+ #[momo]
+ pub fn pattern_matching_relative_path<'a>(
+ &mut self,
+ relative_path: impl Into<&'a BStr>,
+ is_dir: Option<bool>,
+ ) -> Option<gix_pathspec::search::Match<'_>> {
+ self.search.pattern_matching_relative_path(
+ relative_path.into(),
+ is_dir,
+ &mut |relative_path, case, is_dir, out| {
+ let stack = self.stack.as_mut().expect("initialized in advance");
+ stack
+ .set_case(case)
+ .at_entry(relative_path, Some(is_dir), |id, buf| {
+ self.repo.objects.find_blob(id, buf)
+ })
+ .map_or(false, |platform| platform.matching_attributes(out))
+ },
+ )
+ }
+
+ /// The simplified version of [`pattern_matching_relative_path()`](Self::pattern_matching_relative_path()) which returns
+ /// `true` if `relative_path` is included in the set of positive pathspecs, while not being excluded.
+ #[momo]
+ pub fn is_included<'a>(&mut self, relative_path: impl Into<&'a BStr>, is_dir: Option<bool>) -> bool {
+ self.pattern_matching_relative_path(relative_path, is_dir)
+ .map_or(false, |m| !m.is_excluded())
+ }
+
+ /// Return an iterator over all entries along with their path if the path matches the pathspec, or `None` if the pathspec is
+ /// known to match no entry.
+ // TODO: tests
+ pub fn index_entries_with_paths<'s: 'repo, 'a: 'repo>(
+ &'s mut self,
+ index: &'a gix_index::State,
+ ) -> Option<impl Iterator<Item = (&'a BStr, &'a gix_index::Entry)> + 'repo + 's> {
+ index.prefixed_entries(self.search.common_prefix()).map(|entries| {
+ entries.iter().filter_map(move |entry| {
+ let path = entry.path(index);
+ self.is_included(path, Some(false)).then_some((path, entry))
+ })
+ })
+ }
+}
+
+/// Access
+impl PathspecDetached {
+ /// Return the first [`Match`](search::Match) of `relative_path`, or `None`.
+ /// Note that the match might [be excluded](search::Match::is_excluded()).
+ /// `is_dir` is true if `relative_path` is a directory.
+ #[doc(
+ alias = "match_diff",
+ alias = "match_tree",
+ alias = "match_index",
+ alias = "match_workdir",
+ alias = "matches_path",
+ alias = "git2"
+ )]
+ #[momo]
+ pub fn pattern_matching_relative_path<'a>(
+ &mut self,
+ relative_path: impl Into<&'a BStr>,
+ is_dir: Option<bool>,
+ ) -> Option<gix_pathspec::search::Match<'_>> {
+ self.search.pattern_matching_relative_path(
+ relative_path.into(),
+ is_dir,
+ &mut |relative_path, case, is_dir, out| {
+ let stack = self.stack.as_mut().expect("initialized in advance");
+ stack
+ .set_case(case)
+ .at_entry(relative_path, Some(is_dir), |id, buf| self.odb.find_blob(id, buf))
+ .map_or(false, |platform| platform.matching_attributes(out))
+ },
+ )
+ }
+
+ /// The simplified version of [`pattern_matching_relative_path()`](Self::pattern_matching_relative_path()) which returns
+ /// `true` if `relative_path` is included in the set of positive pathspecs, while not being excluded.
+ #[momo]
+ pub fn is_included<'a>(&mut self, relative_path: impl Into<&'a BStr>, is_dir: Option<bool>) -> bool {
+ self.pattern_matching_relative_path(relative_path, is_dir)
+ .map_or(false, |m| !m.is_excluded())
+ }
+}
+
+#[cfg(feature = "status")]
+impl gix_status::Pathspec for PathspecDetached {
+ fn common_prefix(&self) -> &BStr {
+ self.search.common_prefix()
+ }
+
+ fn is_included(&mut self, relative_path: &BStr, is_dir: Option<bool>) -> bool {
+ self.is_included(relative_path, is_dir)
+ }
+}
diff --git a/vendor/gix/src/reference/edits.rs b/vendor/gix/src/reference/edits.rs
index c6510c2e0..208340770 100644
--- a/vendor/gix/src/reference/edits.rs
+++ b/vendor/gix/src/reference/edits.rs
@@ -1,8 +1,8 @@
///
pub mod set_target_id {
- use gix_ref::{transaction::PreviousValue, Target};
-
use crate::{bstr::BString, Reference};
+ use gix_macros::momo;
+ use gix_ref::{transaction::PreviousValue, Target};
mod error {
use gix_ref::FullName;
@@ -28,6 +28,7 @@ pub mod set_target_id {
/// If multiple reference should be changed, use [`Repository::edit_references()`][crate::Repository::edit_references()]
/// or the lower level reference database instead.
#[allow(clippy::result_large_err)]
+ #[momo]
pub fn set_target_id(
&mut self,
id: impl Into<gix_hash::ObjectId>,
diff --git a/vendor/gix/src/reference/iter.rs b/vendor/gix/src/reference/iter.rs
index a2b022f64..a79a74743 100644
--- a/vendor/gix/src/reference/iter.rs
+++ b/vendor/gix/src/reference/iter.rs
@@ -1,6 +1,7 @@
//!
use std::path::Path;
+use gix_macros::momo;
use gix_odb::pack::Find;
use gix_ref::file::ReferenceExt;
@@ -42,8 +43,9 @@ impl<'r> Platform<'r> {
/// These are of the form `refs/heads` or `refs/remotes/origin`, and must not contain relative paths components like `.` or `..`.
// TODO: Create a custom `Path` type that enforces the requirements of git naturally, this type is surprising possibly on windows
// and when not using a trailing '/' to signal directories.
+ #[momo]
pub fn prefixed(&self, prefix: impl AsRef<Path>) -> Result<Iter<'_>, init::Error> {
- Ok(Iter::new(self.repo, self.platform.prefixed(prefix)?))
+ Ok(Iter::new(self.repo, self.platform.prefixed(prefix.as_ref())?))
}
// TODO: tests
@@ -51,7 +53,7 @@ impl<'r> Platform<'r> {
///
/// They are all prefixed with `refs/tags`.
pub fn tags(&self) -> Result<Iter<'_>, init::Error> {
- Ok(Iter::new(self.repo, self.platform.prefixed("refs/tags/")?))
+ Ok(Iter::new(self.repo, self.platform.prefixed("refs/tags/".as_ref())?))
}
// TODO: tests
@@ -59,7 +61,7 @@ impl<'r> Platform<'r> {
///
/// They are all prefixed with `refs/heads`.
pub fn local_branches(&self) -> Result<Iter<'_>, init::Error> {
- Ok(Iter::new(self.repo, self.platform.prefixed("refs/heads/")?))
+ Ok(Iter::new(self.repo, self.platform.prefixed("refs/heads/".as_ref())?))
}
// TODO: tests
@@ -67,7 +69,7 @@ impl<'r> Platform<'r> {
///
/// They are all prefixed with `refs/remotes`.
pub fn remote_branches(&self) -> Result<Iter<'_>, init::Error> {
- Ok(Iter::new(self.repo, self.platform.prefixed("refs/remotes/")?))
+ Ok(Iter::new(self.repo, self.platform.prefixed("refs/remotes/".as_ref())?))
}
}
@@ -95,10 +97,10 @@ impl<'r> Iterator for Iter<'r> {
.and_then(|mut r| {
if self.peel {
let handle = &self.repo;
- r.peel_to_id_in_place(&handle.refs, |oid, buf| {
+ r.peel_to_id_in_place(&handle.refs, &mut |oid, buf| {
handle
.objects
- .try_find(oid, buf)
+ .try_find(oid.as_ref(), buf)
.map(|po| po.map(|(o, _l)| (o.kind, o.data)))
})
.map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync + 'static>)
diff --git a/vendor/gix/src/reference/log.rs b/vendor/gix/src/reference/log.rs
index b516e6499..2fea1782c 100644
--- a/vendor/gix/src/reference/log.rs
+++ b/vendor/gix/src/reference/log.rs
@@ -12,6 +12,11 @@ impl<'repo> Reference<'repo> {
pub fn log_iter(&self) -> gix_ref::file::log::iter::Platform<'_, '_> {
self.inner.log_iter(&self.repo.refs)
}
+
+ /// Return true if a reflog is present for this reference.
+ pub fn log_exists(&self) -> bool {
+ self.inner.log_exists(&self.repo.refs)
+ }
}
/// Generate a message typical for git commit logs based on the given `operation`, commit `message` and `num_parents` of the commit.
diff --git a/vendor/gix/src/reference/mod.rs b/vendor/gix/src/reference/mod.rs
index e2ee0d3b2..e80057fb4 100644
--- a/vendor/gix/src/reference/mod.rs
+++ b/vendor/gix/src/reference/mod.rs
@@ -62,6 +62,7 @@ impl<'repo> Reference<'repo> {
}
}
+/// Peeling
impl<'repo> Reference<'repo> {
/// Follow all symbolic targets this reference might point to and peel the underlying object
/// to the end of the chain, and return it.
@@ -69,9 +70,9 @@ impl<'repo> Reference<'repo> {
/// This is useful to learn where this reference is ultimately pointing to.
pub fn peel_to_id_in_place(&mut self) -> Result<Id<'repo>, peel::Error> {
let repo = &self.repo;
- let oid = self.inner.peel_to_id_in_place(&repo.refs, |oid, buf| {
+ let oid = self.inner.peel_to_id_in_place(&repo.refs, &mut |oid, buf| {
repo.objects
- .try_find(oid, buf)
+ .try_find(&oid, buf)
.map(|po| po.map(|(o, _l)| (o.kind, o.data)))
})?;
Ok(Id::from_id(oid, repo))
@@ -81,6 +82,18 @@ impl<'repo> Reference<'repo> {
pub fn into_fully_peeled_id(mut self) -> Result<Id<'repo>, peel::Error> {
self.peel_to_id_in_place()
}
+
+ /// Follow this symbolic reference one level and return the ref it refers to.
+ ///
+ /// Returns `None` if this is not a symbolic reference, hence the leaf of the chain.
+ pub fn follow(&self) -> Option<Result<Reference<'repo>, gix_ref::file::find::existing::Error>> {
+ self.inner.follow(&self.repo.refs).map(|res| {
+ res.map(|r| Reference {
+ inner: r,
+ repo: self.repo,
+ })
+ })
+ }
}
mod edits;
diff --git a/vendor/gix/src/remote/build.rs b/vendor/gix/src/remote/build.rs
index 10c216537..452da66a0 100644
--- a/vendor/gix/src/remote/build.rs
+++ b/vendor/gix/src/remote/build.rs
@@ -10,7 +10,10 @@ impl Remote<'_> {
Url: TryInto<gix_url::Url, Error = E>,
gix_url::parse::Error: From<E>,
{
- self.push_url_inner(url, true)
+ self.push_url_inner(
+ url.try_into().map_err(|err| remote::init::Error::Url(err.into()))?,
+ true,
+ )
}
/// Set the `url` to be used when pushing data to a remote, without applying rewrite rules in case these could be faulty,
@@ -20,7 +23,10 @@ impl Remote<'_> {
Url: TryInto<gix_url::Url, Error = E>,
gix_url::parse::Error: From<E>,
{
- self.push_url_inner(url, false)
+ self.push_url_inner(
+ url.try_into().map_err(|err| remote::init::Error::Url(err.into()))?,
+ false,
+ )
}
/// Configure how tags should be handled when fetching from the remote.
@@ -29,14 +35,11 @@ impl Remote<'_> {
self
}
- fn push_url_inner<Url, E>(mut self, push_url: Url, should_rewrite_urls: bool) -> Result<Self, remote::init::Error>
- where
- Url: TryInto<gix_url::Url, Error = E>,
- gix_url::parse::Error: From<E>,
- {
- let push_url = push_url
- .try_into()
- .map_err(|err| remote::init::Error::Url(err.into()))?;
+ fn push_url_inner(
+ mut self,
+ push_url: gix_url::Url,
+ should_rewrite_urls: bool,
+ ) -> Result<Self, remote::init::Error> {
self.push_url = push_url.into();
let (_, push_url_alias) = should_rewrite_urls
diff --git a/vendor/gix/src/remote/connect.rs b/vendor/gix/src/remote/connect.rs
index 63475b7c5..6acc9f67f 100644
--- a/vendor/gix/src/remote/connect.rs
+++ b/vendor/gix/src/remote/connect.rs
@@ -1,5 +1,7 @@
#![allow(clippy::result_large_err)]
+
use gix_protocol::transport::client::Transport;
+use std::borrow::Cow;
use crate::{remote::Connection, Remote};
@@ -104,7 +106,7 @@ impl<'repo> Remote<'repo> {
) -> Result<(gix_url::Url, gix_protocol::transport::Protocol), Error> {
fn sanitize(mut url: gix_url::Url) -> Result<gix_url::Url, Error> {
if url.scheme == gix_url::Scheme::File {
- let mut dir = gix_path::to_native_path_on_windows(url.path.as_ref());
+ let mut dir = gix_path::to_native_path_on_windows(Cow::Borrowed(url.path.as_ref()));
let kind = gix_discover::is_git(dir.as_ref())
.or_else(|_| {
dir.to_mut().push(gix_discover::DOT_GIT_DIR);
@@ -117,7 +119,7 @@ impl<'repo> Remote<'repo> {
let (git_dir, _work_dir) = gix_discover::repository::Path::from_dot_git_dir(
dir.clone().into_owned(),
kind,
- std::env::current_dir()?,
+ &std::env::current_dir()?,
)
.ok_or_else(|| Error::InvalidRemoteRepositoryPath {
directory: dir.into_owned(),
diff --git a/vendor/gix/src/remote/connection/fetch/mod.rs b/vendor/gix/src/remote/connection/fetch/mod.rs
index b4fe00935..8327d5abc 100644
--- a/vendor/gix/src/remote/connection/fetch/mod.rs
+++ b/vendor/gix/src/remote/connection/fetch/mod.rs
@@ -46,27 +46,25 @@ pub enum Status {
///
/// As we could determine that nothing changed without remote interaction, there was no negotiation at all.
NoPackReceived {
+ /// If `true`, we didn't receive a pack due to dry-run mode being enabled.
+ dry_run: bool,
+ /// Information about the pack negotiation phase if negotiation happened at all.
+ ///
+ /// It's possible that negotiation didn't have to happen as no reference of interest changed on the server.
+ negotiate: Option<outcome::Negotiate>,
/// However, depending on the refspecs, references might have been updated nonetheless to point to objects as
/// reported by the remote.
update_refs: refs::update::Outcome,
},
/// There was at least one tip with a new object which we received.
Change {
- /// The number of rounds it took to minimize the pack to contain only the objects we don't have.
- negotiation_rounds: usize,
+ /// Information about the pack negotiation phase.
+ negotiate: outcome::Negotiate,
/// Information collected while writing the pack and its index.
write_pack_bundle: gix_pack::bundle::write::Outcome,
/// Information collected while updating references.
update_refs: refs::update::Outcome,
},
- /// A dry run was performed which leaves the local repository without any change
- /// nor will a pack have been received.
- DryRun {
- /// The number of rounds it took to minimize the *would-be-sent*-pack to contain only the objects we don't have.
- negotiation_rounds: usize,
- /// Information about what updates to refs would have been done.
- update_refs: refs::update::Outcome,
- },
}
/// The outcome of receiving a pack via [`Prepare::receive()`].
@@ -78,6 +76,46 @@ pub struct Outcome {
pub status: Status,
}
+/// Additional types related to the outcome of a fetch operation.
+pub mod outcome {
+ /// Information about the negotiation phase of a fetch.
+ ///
+ /// Note that negotiation can happen even if no pack is ultimately produced.
+ #[derive(Default, Debug, Clone)]
+ pub struct Negotiate {
+ /// The negotiation graph indicating what kind of information 'the algorithm' collected in the end.
+ pub graph: gix_negotiate::IdMap,
+ /// Additional information for each round of negotiation.
+ pub rounds: Vec<negotiate::Round>,
+ }
+
+ ///
+ pub mod negotiate {
+ /// Key information about each round in the pack-negotiation.
+ #[derive(Debug, Clone)]
+ pub struct Round {
+ /// The amount of `HAVE` lines sent this round.
+ ///
+ /// Each `HAVE` is an object that we tell the server about which would acknowledge each one it has as well.
+ pub haves_sent: usize,
+ /// A total counter, over all previous rounds, indicating how many `HAVE`s we sent without seeing a single acknowledgement,
+ /// i.e. the indication of a common object.
+ ///
+ /// This number maybe zero or be lower compared to the previous round if we have received at least one acknowledgement.
+ pub in_vain: usize,
+ /// The amount of haves we should send in this round.
+ ///
+ /// If the value is lower than `haves_sent` (the `HAVE` lines actually sent), the negotiation algorithm has run out of options
+ /// which typically indicates the end of the negotiation phase.
+ pub haves_to_send: usize,
+ /// If `true`, the server reported, as response to our previous `HAVE`s, that at least one of them is in common by acknowledging it.
+ ///
+ /// This may also lead to the server responding with a pack.
+ pub previous_response_had_at_least_one_in_common: bool,
+ }
+ }
+}
+
/// The progress ids used in during various steps of the fetch operation.
///
/// Note that tagged progress isn't very widely available yet, but support can be improved as needed.
@@ -129,7 +167,7 @@ where
/// Note that at this point, the `transport` should already be configured using the [`transport_mut()`][Self::transport_mut()]
/// method, as it will be consumed here.
///
- /// From there additional properties of the fetch can be adjusted to override the defaults that are configured via gix-config.
+ /// From there additional properties of the fetch can be adjusted to override the defaults that are configured via git-config.
///
/// # Async Experimental
///
diff --git a/vendor/gix/src/remote/connection/fetch/negotiate.rs b/vendor/gix/src/remote/connection/fetch/negotiate.rs
index e94461bab..92a141f6f 100644
--- a/vendor/gix/src/remote/connection/fetch/negotiate.rs
+++ b/vendor/gix/src/remote/connection/fetch/negotiate.rs
@@ -1,12 +1,13 @@
use std::borrow::Cow;
+use gix_date::SecondsSinceUnixEpoch;
use gix_negotiate::Flags;
use gix_odb::HeaderExt;
use gix_pack::Find;
use crate::remote::{fetch, fetch::Shallow};
-type Queue = gix_revision::PriorityQueue<gix_revision::graph::CommitterTimestamp, gix_hash::ObjectId>;
+type Queue = gix_revwalk::PriorityQueue<SecondsSinceUnixEpoch, gix_hash::ObjectId>;
/// The error returned during negotiation.
#[derive(Debug, thiserror::Error)]
@@ -15,7 +16,7 @@ pub enum Error {
#[error("We were unable to figure out what objects the server should send after {rounds} round(s)")]
NegotiationFailed { rounds: usize },
#[error(transparent)]
- LookupCommitInGraph(#[from] gix_revision::graph::lookup::commit::Error),
+ LookupCommitInGraph(#[from] gix_revwalk::graph::lookup::commit::Error),
#[error(transparent)]
InitRefsIterator(#[from] crate::reference::iter::init::Error),
#[error(transparent)]
@@ -67,7 +68,9 @@ pub(crate) fn mark_complete_and_common_ref(
graph: &mut gix_negotiate::Graph<'_>,
ref_map: &fetch::RefMap,
shallow: &fetch::Shallow,
+ mapping_is_ignored: impl Fn(&fetch::Mapping) -> bool,
) -> Result<Action, Error> {
+ let _span = gix_trace::detail!("mark_complete_and_common_ref", mappings = ref_map.mappings.len());
if let fetch::Shallow::Deepen(0) = shallow {
// Avoid deepening (relative) with zero as it seems to upset the server. Git also doesn't actually
// perform the negotiation for some reason (couldn't find it in code).
@@ -85,9 +88,10 @@ pub(crate) fn mark_complete_and_common_ref(
// Compute the cut-off date by checking which of the refs advertised (and matched in refspecs) by the remote we have,
// and keep the oldest one.
- let mut cutoff_date = None::<gix_revision::graph::CommitterTimestamp>;
+ let mut cutoff_date = None::<SecondsSinceUnixEpoch>;
let mut num_mappings_with_change = 0;
let mut remote_ref_target_known: Vec<bool> = std::iter::repeat(false).take(ref_map.mappings.len()).collect();
+ let mut remote_ref_included: Vec<bool> = std::iter::repeat(false).take(ref_map.mappings.len()).collect();
for (mapping_idx, mapping) in ref_map.mappings.iter().enumerate() {
let want_id = mapping.remote.as_id();
@@ -97,9 +101,13 @@ pub(crate) fn mark_complete_and_common_ref(
r.target().try_id().map(ToOwned::to_owned)
});
- // Like git, we don't let known unchanged mappings participate in the tree traversal
- if want_id.zip(have_id).map_or(true, |(want, have)| want != have) {
- num_mappings_with_change += 1;
+ // Even for ignored mappings we want to know if the `want` is already present locally, so skip nothing else.
+ if !mapping_is_ignored(mapping) {
+ remote_ref_included[mapping_idx] = true;
+ // Like git, we don't let known unchanged mappings participate in the tree traversal
+ if want_id.zip(have_id).map_or(true, |(want, have)| want != have) {
+ num_mappings_with_change += 1;
+ }
}
if let Some(commit) = want_id
@@ -113,11 +121,15 @@ pub(crate) fn mark_complete_and_common_ref(
}
}
- // If any kind of shallowing operation is desired, the server may still create a pack for us.
if matches!(shallow, Shallow::NoChange) {
if num_mappings_with_change == 0 {
return Ok(Action::NoChange);
- } else if remote_ref_target_known.iter().all(|known| *known) {
+ } else if remote_ref_target_known
+ .iter()
+ .zip(remote_ref_included)
+ .filter_map(|(known, included)| included.then_some(known))
+ .all(|known| *known)
+ {
return Ok(Action::SkipToRefUpdate);
}
}
@@ -137,51 +149,75 @@ pub(crate) fn mark_complete_and_common_ref(
Cow::Borrowed(&queue)
};
- // mark all complete advertised refs as common refs.
- for mapping in ref_map
- .mappings
- .iter()
- .zip(remote_ref_target_known.iter().copied())
- // We need this filter as the graph wouldn't contain annotated tags.
- .filter_map(|(mapping, known)| (!known).then_some(mapping))
- {
- let want_id = mapping.remote.as_id();
- if let Some(common_id) = want_id
- .and_then(|id| graph.get(id).map(|c| (c, id)))
- .filter(|(c, _)| c.data.flags.contains(Flags::COMPLETE))
- .map(|(_, id)| id)
+ gix_trace::detail!("mark known_common").into_scope(|| -> Result<_, Error> {
+ // mark all complete advertised refs as common refs.
+ for mapping in ref_map
+ .mappings
+ .iter()
+ .zip(remote_ref_target_known.iter().copied())
+ // We need this filter as the graph wouldn't contain annotated tags.
+ .filter_map(|(mapping, known)| (!known).then_some(mapping))
{
- negotiator.known_common(common_id.into(), graph)?;
+ let want_id = mapping.remote.as_id();
+ if let Some(common_id) = want_id
+ .and_then(|id| graph.get(id).map(|c| (c, id)))
+ .filter(|(c, _)| c.data.flags.contains(Flags::COMPLETE))
+ .map(|(_, id)| id)
+ {
+ negotiator.known_common(common_id.into(), graph)?;
+ }
}
- }
+ Ok(())
+ })?;
// As negotiators currently may rely on getting `known_common` calls first and tips after, we adhere to that which is the only
// reason we cached the set of tips.
- for tip in tips.iter_unordered() {
- negotiator.add_tip(*tip, graph)?;
- }
+ gix_trace::detail!("mark tips", num_tips = tips.len()).into_scope(|| -> Result<_, Error> {
+ for tip in tips.iter_unordered() {
+ negotiator.add_tip(*tip, graph)?;
+ }
+ Ok(())
+ })?;
Ok(Action::MustNegotiate {
remote_ref_target_known,
})
}
-/// Add all `wants` to `arguments`, which is the unpeeled direct target that the advertised remote ref points to.
-pub(crate) fn add_wants(
- repo: &crate::Repository,
- arguments: &mut gix_protocol::fetch::Arguments,
- ref_map: &fetch::RefMap,
- mapping_known: &[bool],
- shallow: &fetch::Shallow,
+/// Create a predicate that checks if a refspec mapping should be ignored.
+///
+/// We want to ignore mappings during negotiation if they would be handled implicitly by the server, which is the case
+/// when tags would be sent implicitly due to `Tags::Included`.
+pub(crate) fn make_refmapping_ignore_predicate(
fetch_tags: fetch::Tags,
-) {
+ ref_map: &fetch::RefMap,
+) -> impl Fn(&fetch::Mapping) -> bool + '_ {
// With included tags, we have to keep mappings of tags to handle them later when updating refs, but we don't want to
// explicitly `want` them as the server will determine by itself which tags are pointing to a commit it wants to send.
// If we would not exclude implicit tag mappings like this, we would get too much of the graph.
let tag_refspec_to_ignore = matches!(fetch_tags, crate::remote::fetch::Tags::Included)
.then(|| fetch_tags.to_refspec())
.flatten();
+ move |mapping| {
+ tag_refspec_to_ignore.map_or(false, |tag_spec| {
+ mapping
+ .spec_index
+ .implicit_index()
+ .and_then(|idx| ref_map.extra_refspecs.get(idx))
+ .map_or(false, |spec| spec.to_ref() == tag_spec)
+ })
+ }
+}
+/// Add all `wants` to `arguments`, which is the unpeeled direct target that the advertised remote ref points to.
+pub(crate) fn add_wants(
+ repo: &crate::Repository,
+ arguments: &mut gix_protocol::fetch::Arguments,
+ ref_map: &fetch::RefMap,
+ mapping_known: &[bool],
+ shallow: &fetch::Shallow,
+ mapping_is_ignored: impl Fn(&fetch::Mapping) -> bool,
+) {
// When using shallow, we can't exclude `wants` as the remote won't send anything then. Thus we have to resend everything
// we have as want instead to get exactly the same graph, but possibly deepened.
let is_shallow = !matches!(shallow, fetch::Shallow::NoChange);
@@ -189,17 +225,9 @@ pub(crate) fn add_wants(
.mappings
.iter()
.zip(mapping_known)
- .filter_map(|(m, known)| (is_shallow || !*known).then_some(m));
+ .filter_map(|(m, known)| (is_shallow || !*known).then_some(m))
+ .filter(|m| !mapping_is_ignored(m));
for want in wants {
- // Here we ignore implicit tag mappings if needed.
- if tag_refspec_to_ignore.map_or(false, |tag_spec| {
- want.spec_index
- .implicit_index()
- .and_then(|idx| ref_map.extra_refspecs.get(idx))
- .map_or(false, |spec| spec.to_ref() == tag_spec)
- }) {
- continue;
- }
let id_on_remote = want.remote.as_id();
if !arguments.can_use_ref_in_want() || matches!(want.remote, fetch::Source::ObjectId(_)) {
if let Some(id) = id_on_remote {
@@ -228,13 +256,14 @@ pub(crate) fn add_wants(
fn mark_recent_complete_commits(
queue: &mut Queue,
graph: &mut gix_negotiate::Graph<'_>,
- cutoff: gix_revision::graph::CommitterTimestamp,
+ cutoff: SecondsSinceUnixEpoch,
) -> Result<(), Error> {
+ let _span = gix_trace::detail!("mark_recent_complete", queue_len = queue.len());
while let Some(id) = queue
.peek()
.and_then(|(commit_time, id)| (commit_time >= &cutoff).then_some(*id))
{
- queue.pop();
+ queue.pop_value();
let commit = graph.get(&id).expect("definitely set when adding tips or parents");
for parent_id in commit.parents.clone() {
let mut was_complete = false;
@@ -258,6 +287,7 @@ fn mark_all_refs_in_repo(
queue: &mut Queue,
mark: Flags,
) -> Result<(), Error> {
+ let _span = gix_trace::detail!("mark_all_refs");
for local_ref in repo.references()?.all()?.peeled() {
let local_ref = local_ref?;
let id = local_ref.id().detach();
@@ -280,17 +310,14 @@ fn mark_alternate_complete(
graph: &mut gix_negotiate::Graph<'_>,
queue: &mut Queue,
) -> Result<(), Error> {
- for alternate_repo in repo
- .objects
- .store_ref()
- .alternate_db_paths()?
- .into_iter()
- .filter_map(|path| {
- path.ancestors()
- .nth(1)
- .and_then(|git_dir| crate::open_opts(git_dir, repo.options.clone()).ok())
- })
- {
+ let alternates = repo.objects.store_ref().alternate_db_paths()?;
+ let _span = gix_trace::detail!("mark_alternate_refs", num_odb = alternates.len());
+
+ for alternate_repo in alternates.into_iter().filter_map(|path| {
+ path.ancestors()
+ .nth(1)
+ .and_then(|git_dir| crate::open_opts(git_dir, repo.options.clone()).ok())
+ }) {
mark_all_refs_in_repo(&alternate_repo, graph, queue, Flags::ALTERNATE | Flags::COMPLETE)?;
}
Ok(())
diff --git a/vendor/gix/src/remote/connection/fetch/receive_pack.rs b/vendor/gix/src/remote/connection/fetch/receive_pack.rs
index 7837a9d3a..18e5ac159 100644
--- a/vendor/gix/src/remote/connection/fetch/receive_pack.rs
+++ b/vendor/gix/src/remote/connection/fetch/receive_pack.rs
@@ -19,17 +19,18 @@ use crate::{
connection::fetch::config,
fetch,
fetch::{
- negotiate, negotiate::Algorithm, refs, Error, Outcome, Prepare, ProgressId, RefLogMessage, Shallow, Status,
+ negotiate, negotiate::Algorithm, outcome, refs, Error, Outcome, Prepare, ProgressId, RefLogMessage,
+ Shallow, Status,
},
},
- Progress, Repository,
+ Repository,
};
impl<'remote, 'repo, T> Prepare<'remote, 'repo, T>
where
T: Transport,
{
- /// Receive the pack and perform the operation as configured by git via `gix-config` or overridden by various builder methods.
+ /// Receive the pack and perform the operation as configured by git via `git-config` or overridden by various builder methods.
/// Return `Ok(None)` if there was nothing to do because all remote refs are at the same state as they are locally, or `Ok(Some(outcome))`
/// to inform about all the changes that were made.
///
@@ -72,18 +73,28 @@ where
/// - `gitoxide.userAgent` is read to obtain the application user agent for git servers and for HTTP servers as well.
///
#[gix_protocol::maybe_async::maybe_async]
- pub async fn receive<P>(mut self, mut progress: P, should_interrupt: &AtomicBool) -> Result<Outcome, Error>
+ pub async fn receive<P>(self, mut progress: P, should_interrupt: &AtomicBool) -> Result<Outcome, Error>
where
- P: Progress,
+ P: gix_features::progress::NestedProgress,
P::SubProgress: 'static,
{
+ self.receive_inner(&mut progress, should_interrupt).await
+ }
+
+ #[gix_protocol::maybe_async::maybe_async]
+ #[allow(clippy::drop_non_drop)]
+ pub(crate) async fn receive_inner(
+ mut self,
+ progress: &mut dyn crate::DynNestedProgress,
+ should_interrupt: &AtomicBool,
+ ) -> Result<Outcome, Error> {
+ let _span = gix_trace::coarse!("fetch::Prepare::receive()");
let mut con = self.con.take().expect("receive() can only be called once");
let handshake = &self.ref_map.handshake;
let protocol_version = handshake.server_protocol_version;
let fetch = gix_protocol::Command::Fetch;
- let progress = &mut progress;
let repo = con.remote.repo;
let fetch_features = {
let mut f = fetch.default_features(protocol_version, &handshake.capabilities);
@@ -114,6 +125,7 @@ where
});
}
+ let negotiate_span = gix_trace::detail!("negotiate");
let mut negotiator = repo
.config
.resolved
@@ -131,20 +143,20 @@ where
r.objects.unset_object_cache();
r
};
- let mut graph = graph_repo.commit_graph();
+ let mut graph = graph_repo.revision_graph();
let action = negotiate::mark_complete_and_common_ref(
&graph_repo,
negotiator.deref_mut(),
&mut graph,
&self.ref_map,
&self.shallow,
+ negotiate::make_refmapping_ignore_predicate(con.remote.fetch_tags, &self.ref_map),
)?;
let mut previous_response = None::<gix_protocol::fetch::Response>;
- let mut round = 1;
- let mut write_pack_bundle = match &action {
+ let (mut write_pack_bundle, negotiate) = match &action {
negotiate::Action::NoChange | negotiate::Action::SkipToRefUpdate => {
gix_protocol::indicate_end_of_interaction(&mut con.transport).await.ok();
- None
+ (None, None)
}
negotiate::Action::MustNegotiate {
remote_ref_target_known,
@@ -155,17 +167,19 @@ where
&self.ref_map,
remote_ref_target_known,
&self.shallow,
- con.remote.fetch_tags,
+ negotiate::make_refmapping_ignore_predicate(con.remote.fetch_tags, &self.ref_map),
);
+ let mut rounds = Vec::new();
let is_stateless =
arguments.is_stateless(!con.transport.connection_persists_across_multiple_requests());
let mut haves_to_send = gix_negotiate::window_size(is_stateless, None);
let mut seen_ack = false;
let mut in_vain = 0;
let mut common = is_stateless.then(Vec::new);
- let reader = 'negotiation: loop {
+ let mut reader = 'negotiation: loop {
+ let _round = gix_trace::detail!("negotiate round", round = rounds.len() + 1);
progress.step();
- progress.set_name(format!("negotiate (round {round})"));
+ progress.set_name(format!("negotiate (round {})", rounds.len() + 1));
let is_done = match negotiate::one_round(
negotiator.deref_mut(),
@@ -181,8 +195,14 @@ where
}
seen_ack |= ack_seen;
in_vain += haves_sent;
+ rounds.push(outcome::negotiate::Round {
+ haves_sent,
+ in_vain,
+ haves_to_send,
+ previous_response_had_at_least_one_in_common: ack_seen,
+ });
let is_done = haves_sent != haves_to_send || (seen_ack && in_vain >= 256);
- haves_to_send = gix_negotiate::window_size(is_stateless, haves_to_send);
+ haves_to_send = gix_negotiate::window_size(is_stateless, Some(haves_to_send));
is_done
}
Err(err) => {
@@ -200,17 +220,17 @@ where
previous_response = Some(response);
if has_pack {
progress.step();
- progress.set_name("receiving pack");
+ progress.set_name("receiving pack".into());
if !sideband_all {
setup_remote_progress(progress, &mut reader, should_interrupt);
}
break 'negotiation reader;
- } else {
- round += 1;
}
};
- drop(graph);
+ let graph = graph.detach();
drop(graph_repo);
+ drop(negotiate_span);
+
let previous_response = previous_response.expect("knowledge of a pack means a response was received");
if !previous_response.shallow_updates().is_empty() && shallow_lock.is_none() {
let reject_shallow_remote = repo
@@ -234,28 +254,34 @@ where
};
let write_pack_bundle = if matches!(self.dry_run, fetch::DryRun::No) {
- Some(gix_pack::Bundle::write_to_directory(
- #[cfg(feature = "async-network-client")]
- {
- gix_protocol::futures_lite::io::BlockOn::new(reader)
- },
- #[cfg(not(feature = "async-network-client"))]
- {
- reader
- },
- Some(repo.objects.store_ref().path().join("pack")),
+ #[cfg(not(feature = "async-network-client"))]
+ let mut rd = reader;
+ #[cfg(feature = "async-network-client")]
+ let mut rd = gix_protocol::futures_lite::io::BlockOn::new(reader);
+ let res = gix_pack::Bundle::write_to_directory(
+ &mut rd,
+ Some(&repo.objects.store_ref().path().join("pack")),
progress,
should_interrupt,
Some(Box::new({
let repo = repo.clone();
- move |oid, buf| repo.objects.find(oid, buf).ok()
+ move |oid, buf| repo.objects.find(&oid, buf).ok()
})),
options,
- )?)
+ )?;
+ #[cfg(feature = "async-network-client")]
+ {
+ reader = rd.into_inner();
+ }
+ #[cfg(not(feature = "async-network-client"))]
+ {
+ reader = rd;
+ }
+ Some(res)
} else {
- drop(reader);
None
};
+ drop(reader);
if matches!(protocol_version, gix_protocol::transport::Protocol::V2) {
gix_protocol::indicate_end_of_interaction(&mut con.transport).await.ok();
@@ -266,7 +292,7 @@ where
crate::shallow::write(shallow_lock, shallow_commits, previous_response.shallow_updates())?;
}
}
- write_pack_bundle
+ (write_pack_bundle, Some(outcome::Negotiate { graph, rounds }))
}
};
@@ -293,21 +319,17 @@ where
let out = Outcome {
ref_map: std::mem::take(&mut self.ref_map),
- status: if matches!(self.dry_run, fetch::DryRun::Yes) {
- assert!(write_pack_bundle.is_none(), "in dry run we never read a bundle");
- Status::DryRun {
+ status: match write_pack_bundle {
+ Some(write_pack_bundle) => Status::Change {
+ write_pack_bundle,
update_refs,
- negotiation_rounds: round,
- }
- } else {
- match write_pack_bundle {
- Some(write_pack_bundle) => Status::Change {
- write_pack_bundle,
- update_refs,
- negotiation_rounds: round,
- },
- None => Status::NoPackReceived { update_refs },
- }
+ negotiate: negotiate.expect("if we have a pack, we always negotiated it"),
+ },
+ None => Status::NoPackReceived {
+ dry_run: matches!(self.dry_run, fetch::DryRun::Yes),
+ negotiate,
+ update_refs,
+ },
},
};
Ok(out)
@@ -348,14 +370,14 @@ fn add_shallow_args(
args.deepen_relative();
}
Shallow::Since { cutoff } => {
- args.deepen_since(cutoff.seconds_since_unix_epoch as usize);
+ args.deepen_since(cutoff.seconds);
}
Shallow::Exclude {
remote_refs,
since_cutoff,
} => {
if let Some(cutoff) = since_cutoff {
- args.deepen_since(cutoff.seconds_since_unix_epoch as usize);
+ args.deepen_since(cutoff.seconds);
}
for ref_ in remote_refs {
args.deepen_not(ref_.as_ref().as_bstr());
@@ -365,17 +387,14 @@ fn add_shallow_args(
Ok((shallow_commits, shallow_lock))
}
-fn setup_remote_progress<P>(
- progress: &mut P,
+fn setup_remote_progress(
+ progress: &mut dyn crate::DynNestedProgress,
reader: &mut Box<dyn gix_protocol::transport::client::ExtendedBufRead + Unpin + '_>,
should_interrupt: &AtomicBool,
-) where
- P: Progress,
- P::SubProgress: 'static,
-{
+) {
use gix_protocol::transport::client::ExtendedBufRead;
reader.set_progress_handler(Some(Box::new({
- let mut remote_progress = progress.add_child_with_id("remote", ProgressId::RemoteProgress.into());
+ let mut remote_progress = progress.add_child_with_id("remote".to_string(), ProgressId::RemoteProgress.into());
// SAFETY: Ugh, so, with current Rust I can't declare lifetimes in the involved traits the way they need to
// be and I also can't use scoped threads to pump from local scopes to an Arc version that could be
// used here due to the this being called from sync AND async code (and the async version doesn't work
diff --git a/vendor/gix/src/remote/connection/fetch/update_refs/mod.rs b/vendor/gix/src/remote/connection/fetch/update_refs/mod.rs
index 953490672..3d6fb18bd 100644
--- a/vendor/gix/src/remote/connection/fetch/update_refs/mod.rs
+++ b/vendor/gix/src/remote/connection/fetch/update_refs/mod.rs
@@ -11,7 +11,10 @@ use crate::{
ext::ObjectIdExt,
remote::{
fetch,
- fetch::{refs::update::Mode, RefLogMessage, Source},
+ fetch::{
+ refs::update::{Mode, TypeChange},
+ RefLogMessage, Source,
+ },
},
Repository,
};
@@ -23,14 +26,20 @@ pub mod update;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Update {
/// The way the update was performed.
- pub mode: update::Mode,
+ pub mode: Mode,
+ /// If not `None`, the update also affects the type of the reference. This also implies that `edit_index` is not None.
+ pub type_change: Option<TypeChange>,
/// The index to the edit that was created from the corresponding mapping, or `None` if there was no local ref.
pub edit_index: Option<usize>,
}
-impl From<update::Mode> for Update {
+impl From<Mode> for Update {
fn from(mode: Mode) -> Self {
- Update { mode, edit_index: None }
+ Update {
+ mode,
+ type_change: None,
+ edit_index: None,
+ }
}
}
@@ -42,6 +51,14 @@ impl From<update::Mode> for Update {
/// `action` is the prefix used for reflog entries, and is typically "fetch".
///
/// It can be used to produce typical information that one is used to from `git fetch`.
+///
+/// We will reject updates only if…
+///
+/// * …fast-forward rules are violated
+/// * …the local ref is currently checked out
+/// * …existing refs would not become 'unborn', i.e. point to a reference that doesn't exist and won't be created due to ref-specs
+///
+/// With these safeguards in place, one can handle each naturally and implement mirrors or bare repos easily.
#[allow(clippy::too_many_arguments)]
pub(crate) fn update(
repo: &Repository,
@@ -53,8 +70,10 @@ pub(crate) fn update(
dry_run: fetch::DryRun,
write_packed_refs: fetch::WritePackedRefs,
) -> Result<update::Outcome, update::Error> {
+ let _span = gix_trace::detail!("update_refs()", mappings = mappings.len());
let mut edits = Vec::new();
let mut updates = Vec::new();
+ let mut edit_indices_to_validate = Vec::new();
let implicit_tag_refspec = fetch_tags
.to_refspec()
@@ -75,46 +94,56 @@ pub(crate) fn update(
})
},
) {
- let remote_id = match remote.as_id() {
- Some(id) => id,
- None => continue,
- };
- if dry_run == fetch::DryRun::No && !repo.objects.contains(remote_id) {
- let update = if is_implicit_tag {
- update::Mode::ImplicitTagNotSentByRemote.into()
- } else {
- update::Mode::RejectedSourceObjectNotFound { id: remote_id.into() }.into()
- };
- updates.push(update);
- continue;
+ // `None` only if unborn.
+ let remote_id = remote.as_id();
+ if matches!(dry_run, fetch::DryRun::No) && !remote_id.map_or(true, |id| repo.objects.contains(id)) {
+ if let Some(remote_id) = remote_id.filter(|id| !repo.objects.contains(id)) {
+ let update = if is_implicit_tag {
+ Mode::ImplicitTagNotSentByRemote.into()
+ } else {
+ Mode::RejectedSourceObjectNotFound { id: remote_id.into() }.into()
+ };
+ updates.push(update);
+ continue;
+ }
}
- let checked_out_branches = worktree_branches(repo)?;
- let (mode, edit_index) = match local {
+ let mut checked_out_branches = worktree_branches(repo)?;
+ let (mode, edit_index, type_change) = match local {
Some(name) => {
let (mode, reflog_message, name, previous_value) = match repo.try_find_reference(name)? {
Some(existing) => {
- if let Some(wt_dir) = checked_out_branches.get(existing.name()) {
- let mode = update::Mode::RejectedCurrentlyCheckedOut {
- worktree_dir: wt_dir.to_owned(),
+ if let Some(wt_dirs) = checked_out_branches.get_mut(existing.name()) {
+ wt_dirs.sort();
+ wt_dirs.dedup();
+ let mode = Mode::RejectedCurrentlyCheckedOut {
+ worktree_dirs: wt_dirs.to_owned(),
};
updates.push(mode.into());
continue;
}
- match existing.target() {
- TargetRef::Symbolic(_) => {
- updates.push(update::Mode::RejectedSymbolic.into());
- continue;
- }
- TargetRef::Peeled(local_id) => {
- let previous_value =
- PreviousValue::MustExistAndMatch(Target::Peeled(local_id.to_owned()));
+
+ match existing
+ .try_id()
+ .map_or_else(|| existing.clone().peel_to_id_in_place(), Ok)
+ .map(crate::Id::detach)
+ {
+ Ok(local_id) => {
+ let remote_id = match remote_id {
+ Some(id) => id,
+ None => {
+ // we don't allow to go back to unborn state if there is a local reference already present.
+ // Note that we will be changing it to a symbolic reference just fine.
+ updates.push(Mode::RejectedToReplaceWithUnborn.into());
+ continue;
+ }
+ };
let (mode, reflog_message) = if local_id == remote_id {
- (update::Mode::NoChangeNeeded, "no update will be performed")
+ (Mode::NoChangeNeeded, "no update will be performed")
} else if let Some(gix_ref::Category::Tag) = existing.name().category() {
if spec.allow_non_fast_forward() {
- (update::Mode::Forced, "updating tag")
+ (Mode::Forced, "updating tag")
} else {
- updates.push(update::Mode::RejectedTagUpdate.into());
+ updates.push(Mode::RejectedTagUpdate.into());
continue;
}
} else {
@@ -126,21 +155,21 @@ pub(crate) fn update(
.try_into_commit()
.map_err(|_| ())
.and_then(|c| {
- c.committer().map(|a| a.time.seconds_since_unix_epoch).map_err(|_| ())
+ c.committer().map(|a| a.time.seconds).map_err(|_| ())
}).and_then(|local_commit_time|
- remote_id
- .to_owned()
- .ancestors(|id, buf| repo.objects.find_commit_iter(id, buf))
- .sorting(
- gix_traverse::commit::Sorting::ByCommitTimeNewestFirstCutoffOlderThan {
- time_in_seconds_since_epoch: local_commit_time
- },
- )
- .map_err(|_| ())
- );
+ remote_id
+ .to_owned()
+ .ancestors(|id, buf| repo.objects.find_commit_iter(id, buf))
+ .sorting(
+ gix_traverse::commit::Sorting::ByCommitTimeNewestFirstCutoffOlderThan {
+ seconds: local_commit_time
+ },
+ )
+ .map_err(|_| ())
+ );
match ancestors {
Ok(mut ancestors) => {
- ancestors.any(|cid| cid.map_or(false, |cid| cid == local_id))
+ ancestors.any(|cid| cid.map_or(false, |c| c.id == local_id))
}
Err(_) => {
force = true;
@@ -152,20 +181,41 @@ pub(crate) fn update(
};
if is_fast_forward {
(
- update::Mode::FastForward,
+ Mode::FastForward,
matches!(dry_run, fetch::DryRun::Yes)
.then(|| "fast-forward (guessed in dry-run)")
.unwrap_or("fast-forward"),
)
} else if force {
- (update::Mode::Forced, "forced-update")
+ (Mode::Forced, "forced-update")
} else {
- updates.push(update::Mode::RejectedNonFastForward.into());
+ updates.push(Mode::RejectedNonFastForward.into());
continue;
}
};
- (mode, reflog_message, existing.name().to_owned(), previous_value)
+ (
+ mode,
+ reflog_message,
+ existing.name().to_owned(),
+ PreviousValue::MustExistAndMatch(existing.target().into_owned()),
+ )
}
+ Err(crate::reference::peel::Error::ToId(gix_ref::peel::to_id::Error::Follow(_))) => {
+ // An unborn reference, always allow it to be changed to whatever the remote wants.
+ (
+ if existing.target().try_name().map(gix_ref::FullNameRef::as_bstr)
+ == remote.as_target()
+ {
+ Mode::NoChangeNeeded
+ } else {
+ Mode::Forced
+ },
+ "change unborn ref",
+ existing.name().to_owned(),
+ PreviousValue::MustExistAndMatch(existing.target().into_owned()),
+ )
+ }
+ Err(err) => return Err(err.into()),
}
}
None => {
@@ -176,13 +226,37 @@ pub(crate) fn update(
_ => "storing ref",
};
(
- update::Mode::New,
+ Mode::New,
reflog_msg,
name,
- PreviousValue::ExistingMustMatch(Target::Peeled(remote_id.to_owned())),
+ PreviousValue::ExistingMustMatch(new_value_by_remote(repo, remote, mappings)?),
)
}
};
+
+ let new = new_value_by_remote(repo, remote, mappings)?;
+ let type_change = match (&previous_value, &new) {
+ (
+ PreviousValue::ExistingMustMatch(Target::Peeled(_))
+ | PreviousValue::MustExistAndMatch(Target::Peeled(_)),
+ Target::Symbolic(_),
+ ) => Some(TypeChange::DirectToSymbolic),
+ (
+ PreviousValue::ExistingMustMatch(Target::Symbolic(_))
+ | PreviousValue::MustExistAndMatch(Target::Symbolic(_)),
+ Target::Peeled(_),
+ ) => Some(TypeChange::SymbolicToDirect),
+ _ => None,
+ };
+ // We are here because this edit should work and fast-forward rules are respected.
+ // But for setting a symref-target, we have to be sure that the target already exists
+ // or will exists. To be sure all rules are respected, we delay the check to when the
+ // edit-list has been built.
+ let edit_index = edits.len();
+ if matches!(new, Target::Symbolic(_)) {
+ let anticipated_update_index = updates.len();
+ edit_indices_to_validate.push((anticipated_update_index, edit_index));
+ }
let edit = RefEdit {
change: Change::Update {
log: LogChange {
@@ -191,42 +265,57 @@ pub(crate) fn update(
message: message.compose(reflog_message),
},
expected: previous_value,
- new: if let Source::Ref(gix_protocol::handshake::Ref::Symbolic { target, .. }) = &remote {
- match mappings.iter().find_map(|m| {
- m.remote.as_name().and_then(|name| {
- (name == target)
- .then(|| m.local.as_ref().and_then(|local| local.try_into().ok()))
- .flatten()
- })
- }) {
- Some(local_branch) => {
- // This is always safe because…
- // - the reference may exist already
- // - if it doesn't exist it will be created - we are here because it's in the list of mappings after all
- // - if it exists and is updated, and the update is rejected due to non-fastforward for instance, the
- // target reference still exists and we can point to it.
- Target::Symbolic(local_branch)
- }
- None => Target::Peeled(remote_id.into()),
- }
- } else {
- Target::Peeled(remote_id.into())
- },
+ new,
},
name,
+ // We must not deref symrefs or we will overwrite their destination, which might be checked out
+ // and we don't check for that case.
deref: false,
};
- let edit_index = edits.len();
edits.push(edit);
- (mode, Some(edit_index))
+ (mode, Some(edit_index), type_change)
}
- None => (update::Mode::NoChangeNeeded, None),
+ None => (Mode::NoChangeNeeded, None, None),
};
- updates.push(Update { mode, edit_index })
+ updates.push(Update {
+ mode,
+ type_change,
+ edit_index,
+ })
+ }
+
+ for (update_index, edit_index) in edit_indices_to_validate {
+ let edit = &edits[edit_index];
+ if update_needs_adjustment_as_edits_symbolic_target_is_missing(edit, repo, &edits) {
+ let edit = &mut edits[edit_index];
+ let update = &mut updates[update_index];
+
+ update.mode = Mode::RejectedToReplaceWithUnborn;
+ update.type_change = None;
+
+ match edit.change {
+ Change::Update {
+ ref expected,
+ ref mut new,
+ ref mut log,
+ ..
+ } => match expected {
+ PreviousValue::MustExistAndMatch(existing) => {
+ *new = existing.clone();
+ log.message = "no-op".into();
+ }
+ _ => unreachable!("at this point it can only be one variant"),
+ },
+ Change::Delete { .. } => {
+ unreachable!("we don't do that here")
+ }
+ };
+ }
}
let edits = match dry_run {
fetch::DryRun::No => {
+ let _span = gix_trace::detail!("apply", edits = edits.len());
let (file_lock_fail, packed_refs_lock_fail) = repo
.config
.lock_timeout()
@@ -238,9 +327,8 @@ pub(crate) fn update(
fetch::WritePackedRefs::Only => {
gix_ref::file::transaction::PackedRefs::DeletionsAndNonSymbolicUpdatesRemoveLooseSourceReference(Box::new(|oid, buf| {
repo.objects
- .try_find(oid, buf)
+ .try_find(&oid, buf)
.map(|obj| obj.map(|obj| obj.kind))
- .map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync + 'static>)
}))},
fetch::WritePackedRefs::Never => gix_ref::file::transaction::PackedRefs::DeletionsOnly
}
@@ -256,16 +344,128 @@ pub(crate) fn update(
Ok(update::Outcome { edits, updates })
}
-fn worktree_branches(repo: &Repository) -> Result<BTreeMap<gix_ref::FullName, PathBuf>, update::Error> {
- let mut map = BTreeMap::new();
- if let Some((wt_dir, head_ref)) = repo.work_dir().zip(repo.head_ref().ok().flatten()) {
- map.insert(head_ref.inner.name, wt_dir.to_owned());
+/// Figure out if target of `edit` points to a reference that doesn't exist in `repo` and won't exist as it's not in any of `edits`.
+/// If so, return true.
+fn update_needs_adjustment_as_edits_symbolic_target_is_missing(
+ edit: &RefEdit,
+ repo: &Repository,
+ edits: &[RefEdit],
+) -> bool {
+ match edit.change.new_value().expect("here we need a symlink") {
+ TargetRef::Peeled(_) => unreachable!("BUG: we already know it's symbolic"),
+ TargetRef::Symbolic(new_target_ref) => {
+ match &edit.change {
+ Change::Update { expected, .. } => match expected {
+ PreviousValue::MustExistAndMatch(current_target) => {
+ if let Target::Symbolic(current_target_name) = current_target {
+ if current_target_name.as_ref() == new_target_ref {
+ return false; // no-op are always fine
+ }
+ let current_is_unborn = repo.refs.try_find(current_target_name).ok().flatten().is_none();
+ if current_is_unborn {
+ return false;
+ }
+ }
+ }
+ PreviousValue::ExistingMustMatch(_) => return false, // this means the ref doesn't exist locally, so we can create unborn refs anyway
+ _ => {
+ unreachable!("BUG: we don't do that here")
+ }
+ },
+ Change::Delete { .. } => {
+ unreachable!("we don't ever delete here")
+ }
+ };
+ let target_ref_exists_locally = repo.refs.try_find(new_target_ref).ok().flatten().is_some();
+ if target_ref_exists_locally {
+ return false;
+ }
+
+ let target_ref_will_be_created = edits.iter().any(|edit| edit.name.as_ref() == new_target_ref);
+ !target_ref_will_be_created
+ }
}
+}
+
+fn new_value_by_remote(
+ repo: &Repository,
+ remote: &Source,
+ mappings: &[fetch::Mapping],
+) -> Result<Target, update::Error> {
+ let remote_id = remote.as_id();
+ Ok(
+ if let Source::Ref(
+ gix_protocol::handshake::Ref::Symbolic { target, .. } | gix_protocol::handshake::Ref::Unborn { target, .. },
+ ) = &remote
+ {
+ match mappings.iter().find_map(|m| {
+ m.remote.as_name().and_then(|name| {
+ (name == target)
+ .then(|| m.local.as_ref().and_then(|local| local.try_into().ok()))
+ .flatten()
+ })
+ }) {
+ // Map the target on the remote to the local branch name, which should be covered by refspecs.
+ Some(local_branch) => {
+ // This is always safe because…
+ // - the reference may exist already
+ // - if it doesn't exist it will be created - we are here because it's in the list of mappings after all
+ // - if it exists and is updated, and the update is rejected due to non-fastforward for instance, the
+ // target reference still exists and we can point to it.
+ Target::Symbolic(local_branch)
+ }
+ None => {
+ // If we can't map it, it's usually a an unborn branch causing this, or a the target isn't covered
+ // by any refspec so we don't officially pull it in.
+ match remote_id {
+ Some(desired_id) => {
+ if repo.try_find_reference(target)?.is_some() {
+ // We are allowed to change a direct reference to a symbolic one, which may point to other objects
+ // than the remote. The idea is that we are fine as long as the resulting refs are valid.
+ Target::Symbolic(target.try_into()?)
+ } else {
+ // born branches that we don't have in our refspecs we create peeled. That way they can be used.
+ Target::Peeled(desired_id.to_owned())
+ }
+ }
+ // Unborn branches we create as such, with the location they point to on the remote which helps mirroring.
+ None => Target::Symbolic(target.try_into()?),
+ }
+ }
+ }
+ } else {
+ Target::Peeled(remote_id.expect("unborn case handled earlier").to_owned())
+ },
+ )
+}
+
+fn insert_head(
+ head: Option<crate::Head<'_>>,
+ out: &mut BTreeMap<gix_ref::FullName, Vec<PathBuf>>,
+) -> Result<(), update::Error> {
+ if let Some((head, wd)) = head.and_then(|head| head.repo.work_dir().map(|wd| (head, wd))) {
+ out.entry("HEAD".try_into().expect("valid"))
+ .or_default()
+ .push(wd.to_owned());
+ let mut ref_chain = Vec::new();
+ let mut cursor = head.try_into_referent();
+ while let Some(ref_) = cursor {
+ ref_chain.push(ref_.name().to_owned());
+ cursor = ref_.follow().transpose()?;
+ }
+ for name in ref_chain {
+ out.entry(name).or_default().push(wd.to_owned());
+ }
+ }
+ Ok(())
+}
+
+fn worktree_branches(repo: &Repository) -> Result<BTreeMap<gix_ref::FullName, Vec<PathBuf>>, update::Error> {
+ let mut map = BTreeMap::new();
+ insert_head(repo.head().ok(), &mut map)?;
for proxy in repo.worktrees()? {
let repo = proxy.into_repo_with_possibly_inaccessible_worktree()?;
- if let Some((wt_dir, head_ref)) = repo.work_dir().zip(repo.head_ref().ok().flatten()) {
- map.insert(head_ref.inner.name, wt_dir.to_owned());
- }
+ insert_head(repo.head().ok(), &mut map)?;
}
Ok(map)
}
diff --git a/vendor/gix/src/remote/connection/fetch/update_refs/tests.rs b/vendor/gix/src/remote/connection/fetch/update_refs/tests.rs
index 47ab5d1a5..0b29f14f4 100644
--- a/vendor/gix/src/remote/connection/fetch/update_refs/tests.rs
+++ b/vendor/gix/src/remote/connection/fetch/update_refs/tests.rs
@@ -31,6 +31,10 @@ mod update {
gix_testtools::scripted_fixture_read_only_with_args("make_fetch_repos.sh", [base_repo_path()]).unwrap();
gix::open_opts(dir.join(name), restricted()).unwrap()
}
+ fn named_repo(name: &str) -> gix::Repository {
+ let dir = gix_testtools::scripted_fixture_read_only("make_remote_repos.sh").unwrap();
+ gix::open_opts(dir.join(name), restricted()).unwrap()
+ }
fn repo_rw(name: &str) -> (gix::Repository, gix_testtools::tempfile::TempDir) {
let dir = gix_testtools::scripted_fixture_writable_with_args(
"make_fetch_repos.sh",
@@ -41,13 +45,19 @@ mod update {
let repo = gix::open_opts(dir.path().join(name), restricted()).unwrap();
(repo, dir)
}
- use gix_ref::{transaction::Change, TargetRef};
+ use gix_ref::{
+ transaction::{Change, LogChange, PreviousValue, RefEdit, RefLog},
+ Target, TargetRef,
+ };
use crate::{
bstr::BString,
remote::{
fetch,
- fetch::{refs::tests::restricted, Mapping, RefLogMessage, Source, SpecIndex},
+ fetch::{
+ refs::{tests::restricted, update::TypeChange},
+ Mapping, RefLogMessage, Source, SpecIndex,
+ },
},
};
@@ -112,7 +122,7 @@ mod update {
(
"+refs/remotes/origin/g:refs/heads/main",
fetch::refs::update::Mode::RejectedCurrentlyCheckedOut {
- worktree_dir: repo.work_dir().expect("present").to_owned(),
+ worktree_dirs: vec![repo.work_dir().expect("present").to_owned()],
},
None,
"checked out branches cannot be written, as it requires a merge of sorts which isn't done here",
@@ -148,6 +158,7 @@ mod update {
assert_eq!(
out.updates,
vec![fetch::refs::Update {
+ type_change: None,
mode: expected_mode.clone(),
edit_index: reflog_message.map(|_| 0),
}],
@@ -180,7 +191,7 @@ mod update {
#[test]
fn checked_out_branches_in_worktrees_are_rejected_with_additional_information() -> Result {
- let root = gix_path::realpath(gix_testtools::scripted_fixture_read_only_with_args(
+ let root = gix_path::realpath(&gix_testtools::scripted_fixture_read_only_with_args(
"make_fetch_repos.sh",
[base_repo_path()],
)?)?;
@@ -211,8 +222,9 @@ mod update {
out.updates,
vec![fetch::refs::Update {
mode: fetch::refs::update::Mode::RejectedCurrentlyCheckedOut {
- worktree_dir: root.join(path_from_root),
+ worktree_dirs: vec![root.join(path_from_root)],
},
+ type_change: None,
edit_index: None,
}],
"{spec}: checked-out checks are done before checking if a change would actually be required (here it isn't)"
@@ -223,10 +235,350 @@ mod update {
}
#[test]
- fn local_symbolic_refs_are_never_written() {
+ fn unborn_remote_branches_can_be_created_locally_if_they_are_new() -> Result {
+ let repo = named_repo("unborn");
+ let (mappings, specs) = mapping_from_spec("HEAD:refs/remotes/origin/HEAD", &repo);
+ assert_eq!(mappings.len(), 1);
+ let out = fetch::refs::update(
+ &repo,
+ prefixed("action"),
+ &mappings,
+ &specs,
+ &[],
+ fetch::Tags::None,
+ fetch::DryRun::Yes,
+ fetch::WritePackedRefs::Never,
+ )?;
+ assert_eq!(
+ out.updates,
+ vec![fetch::refs::Update {
+ mode: fetch::refs::update::Mode::New,
+ type_change: None,
+ edit_index: Some(0)
+ }]
+ );
+ assert_eq!(out.edits.len(), 1, "we are OK with creating unborn refs");
+ Ok(())
+ }
+
+ #[test]
+ fn unborn_remote_branches_can_update_local_unborn_branches() -> Result {
+ let repo = named_repo("unborn");
+ let (mappings, specs) = mapping_from_spec("HEAD:refs/heads/existing-unborn-symbolic", &repo);
+ assert_eq!(mappings.len(), 1);
+ let out = fetch::refs::update(
+ &repo,
+ prefixed("action"),
+ &mappings,
+ &specs,
+ &[],
+ fetch::Tags::None,
+ fetch::DryRun::Yes,
+ fetch::WritePackedRefs::Never,
+ )?;
+ assert_eq!(
+ out.updates,
+ vec![fetch::refs::Update {
+ mode: fetch::refs::update::Mode::NoChangeNeeded,
+ type_change: None,
+ edit_index: Some(0)
+ }]
+ );
+ assert_eq!(out.edits.len(), 1, "we are OK with updating unborn refs");
+ assert_eq!(
+ out.edits[0],
+ RefEdit {
+ change: Change::Update {
+ log: LogChange {
+ mode: RefLog::AndReference,
+ force_create_reflog: false,
+ message: "action: change unborn ref".into(),
+ },
+ expected: PreviousValue::MustExistAndMatch(Target::Symbolic(
+ "refs/heads/main".try_into().expect("valid"),
+ )),
+ new: Target::Symbolic("refs/heads/main".try_into().expect("valid")),
+ },
+ name: "refs/heads/existing-unborn-symbolic".try_into().expect("valid"),
+ deref: false,
+ }
+ );
+
+ let (mappings, specs) = mapping_from_spec("HEAD:refs/heads/existing-unborn-symbolic-other", &repo);
+ assert_eq!(mappings.len(), 1);
+ let out = fetch::refs::update(
+ &repo,
+ prefixed("action"),
+ &mappings,
+ &specs,
+ &[],
+ fetch::Tags::None,
+ fetch::DryRun::Yes,
+ fetch::WritePackedRefs::Never,
+ )?;
+ assert_eq!(
+ out.updates,
+ vec![fetch::refs::Update {
+ mode: fetch::refs::update::Mode::Forced,
+ type_change: None,
+ edit_index: Some(0)
+ }]
+ );
+ assert_eq!(
+ out.edits.len(),
+ 1,
+ "we are OK with creating unborn refs even without actually forcing it"
+ );
+ assert_eq!(
+ out.edits[0],
+ RefEdit {
+ change: Change::Update {
+ log: LogChange {
+ mode: RefLog::AndReference,
+ force_create_reflog: false,
+ message: "action: change unborn ref".into(),
+ },
+ expected: PreviousValue::MustExistAndMatch(Target::Symbolic(
+ "refs/heads/other".try_into().expect("valid"),
+ )),
+ new: Target::Symbolic("refs/heads/main".try_into().expect("valid")),
+ },
+ name: "refs/heads/existing-unborn-symbolic-other".try_into().expect("valid"),
+ deref: false,
+ }
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn remote_symbolic_refs_with_locally_unavailable_target_result_in_valid_peeled_branches() -> Result {
+ let remote_repo = named_repo("one-commit-with-symref");
+ let local_repo = named_repo("unborn");
+ let (mappings, specs) = mapping_from_spec("refs/heads/symbolic:refs/heads/new", &remote_repo);
+ assert_eq!(mappings.len(), 1);
+
+ let out = fetch::refs::update(
+ &local_repo,
+ prefixed("action"),
+ &mappings,
+ &specs,
+ &[],
+ fetch::Tags::None,
+ fetch::DryRun::Yes,
+ fetch::WritePackedRefs::Never,
+ )?;
+ assert_eq!(
+ out.updates,
+ vec![fetch::refs::Update {
+ mode: fetch::refs::update::Mode::New,
+ type_change: None,
+ edit_index: Some(0)
+ }]
+ );
+ assert_eq!(out.edits.len(), 1);
+ let target = Target::Peeled(hex_to_id("66f16e4e8baf5c77bb6d0484495bebea80e916ce"));
+ assert_eq!(
+ out.edits[0],
+ RefEdit {
+ change: Change::Update {
+ log: LogChange {
+ mode: RefLog::AndReference,
+ force_create_reflog: false,
+ message: "action: storing head".into(),
+ },
+ expected: PreviousValue::ExistingMustMatch(target.clone()),
+ new: target,
+ },
+ name: "refs/heads/new".try_into().expect("valid"),
+ deref: false,
+ },
+ "we create local-refs whose targets aren't present yet, even though the remote knows them.\
+ This leaves the caller with assuring all refs are mentioned in mappings."
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn remote_symbolic_refs_with_locally_unavailable_target_dont_overwrite_valid_local_branches() -> Result {
+ let remote_repo = named_repo("one-commit-with-symref");
+ let local_repo = named_repo("one-commit-with-symref-missing-branch");
+ let (mappings, specs) = mapping_from_spec("refs/heads/unborn:refs/heads/valid-locally", &remote_repo);
+ assert_eq!(mappings.len(), 1);
+
+ let out = fetch::refs::update(
+ &local_repo,
+ prefixed("action"),
+ &mappings,
+ &specs,
+ &[],
+ fetch::Tags::None,
+ fetch::DryRun::Yes,
+ fetch::WritePackedRefs::Never,
+ )?;
+ assert_eq!(
+ out.updates,
+ vec![fetch::refs::Update {
+ mode: fetch::refs::update::Mode::RejectedToReplaceWithUnborn,
+ type_change: None,
+ edit_index: None
+ }]
+ );
+ assert_eq!(out.edits.len(), 0);
+ Ok(())
+ }
+
+ #[test]
+ fn unborn_remote_refs_dont_overwrite_valid_local_refs() -> Result {
+ let remote_repo = named_repo("unborn");
+ let local_repo = named_repo("one-commit-with-symref");
+ let (mappings, specs) =
+ mapping_from_spec("refs/heads/existing-unborn-symbolic:refs/heads/branch", &remote_repo);
+ assert_eq!(mappings.len(), 1);
+
+ let out = fetch::refs::update(
+ &local_repo,
+ prefixed("action"),
+ &mappings,
+ &specs,
+ &[],
+ fetch::Tags::None,
+ fetch::DryRun::Yes,
+ fetch::WritePackedRefs::Never,
+ )?;
+ assert_eq!(
+ out.updates,
+ vec![fetch::refs::Update {
+ mode: fetch::refs::update::Mode::RejectedToReplaceWithUnborn,
+ type_change: None,
+ edit_index: None
+ }],
+ "we don't overwrite locally present refs with unborn ones for safety"
+ );
+ assert_eq!(out.edits.len(), 0);
+ Ok(())
+ }
+
+ #[test]
+ fn local_symbolic_refs_can_be_overwritten() {
let repo = repo("two-origins");
- for source in ["refs/heads/main", "refs/heads/symbolic", "HEAD"] {
- let (mappings, specs) = mapping_from_spec(&format!("{source}:refs/heads/symbolic"), &repo);
+ for (source, destination, expected_update, expected_edit) in [
+ (
+ // attempt to overwrite HEAD isn't possible as the matching engine will normalize the path. That way, `HEAD`
+ // can never be set. This is by design (of git) and we follow it.
+ "refs/heads/symbolic",
+ "HEAD",
+ fetch::refs::Update {
+ mode: fetch::refs::update::Mode::New,
+ type_change: None,
+ edit_index: Some(0),
+ },
+ Some(RefEdit {
+ change: Change::Update {
+ log: LogChange {
+ mode: RefLog::AndReference,
+ force_create_reflog: false,
+ message: "action: storing head".into(),
+ },
+ expected: PreviousValue::ExistingMustMatch(Target::Symbolic(
+ "refs/heads/main".try_into().expect("valid"),
+ )),
+ new: Target::Symbolic("refs/heads/main".try_into().expect("valid")),
+ },
+ name: "refs/heads/HEAD".try_into().expect("valid"),
+ deref: false,
+ }),
+ ),
+ (
+ // attempt to overwrite checked out branch fails
+ "refs/remotes/origin/b", // strange, but the remote-refs are simulated and based on local refs
+ "refs/heads/main",
+ fetch::refs::Update {
+ mode: fetch::refs::update::Mode::RejectedCurrentlyCheckedOut {
+ worktree_dirs: vec![repo.work_dir().expect("present").to_owned()],
+ },
+ type_change: None,
+ edit_index: None,
+ },
+ None,
+ ),
+ (
+ // symbolic becomes direct
+ "refs/heads/main",
+ "refs/heads/symbolic",
+ fetch::refs::Update {
+ mode: fetch::refs::update::Mode::NoChangeNeeded,
+ type_change: Some(TypeChange::SymbolicToDirect),
+ edit_index: Some(0),
+ },
+ Some(RefEdit {
+ change: Change::Update {
+ log: LogChange {
+ mode: RefLog::AndReference,
+ force_create_reflog: false,
+ message: "action: no update will be performed".into(),
+ },
+ expected: PreviousValue::MustExistAndMatch(Target::Symbolic(
+ "refs/heads/main".try_into().expect("valid"),
+ )),
+ new: Target::Peeled(hex_to_id("f99771fe6a1b535783af3163eba95a927aae21d5")),
+ },
+ name: "refs/heads/symbolic".try_into().expect("valid"),
+ deref: false,
+ }),
+ ),
+ (
+ // direct becomes symbolic
+ "refs/heads/symbolic",
+ "refs/remotes/origin/a",
+ fetch::refs::Update {
+ mode: fetch::refs::update::Mode::NoChangeNeeded,
+ type_change: Some(TypeChange::DirectToSymbolic),
+ edit_index: Some(0),
+ },
+ Some(RefEdit {
+ change: Change::Update {
+ log: LogChange {
+ mode: RefLog::AndReference,
+ force_create_reflog: false,
+ message: "action: no update will be performed".into(),
+ },
+ expected: PreviousValue::MustExistAndMatch(Target::Peeled(hex_to_id(
+ "f99771fe6a1b535783af3163eba95a927aae21d5",
+ ))),
+ new: Target::Symbolic("refs/heads/main".try_into().expect("valid")),
+ },
+ name: "refs/remotes/origin/a".try_into().expect("valid"),
+ deref: false,
+ }),
+ ),
+ (
+ // symbolic to symbolic (same)
+ "refs/heads/symbolic",
+ "refs/heads/symbolic",
+ fetch::refs::Update {
+ mode: fetch::refs::update::Mode::NoChangeNeeded,
+ type_change: None,
+ edit_index: Some(0),
+ },
+ Some(RefEdit {
+ change: Change::Update {
+ log: LogChange {
+ mode: RefLog::AndReference,
+ force_create_reflog: false,
+ message: "action: no update will be performed".into(),
+ },
+ expected: PreviousValue::MustExistAndMatch(Target::Symbolic(
+ "refs/heads/main".try_into().expect("valid"),
+ )),
+ new: Target::Symbolic("refs/heads/main".try_into().expect("valid")),
+ },
+ name: "refs/heads/symbolic".try_into().expect("valid"),
+ deref: false,
+ }),
+ ),
+ ] {
+ let (mappings, specs) = mapping_from_spec(&format!("{source}:{destination}"), &repo);
+ assert_eq!(mappings.len(), 1);
let out = fetch::refs::update(
&repo,
prefixed("action"),
@@ -239,15 +591,11 @@ mod update {
)
.unwrap();
- assert_eq!(out.edits.len(), 0);
- assert_eq!(
- out.updates,
- vec![fetch::refs::Update {
- mode: fetch::refs::update::Mode::RejectedSymbolic,
- edit_index: None
- }],
- "we don't overwrite these as the checked-out check needs to consider much more than it currently does, we are playing it safe"
- );
+ assert_eq!(out.edits.len(), usize::from(expected_edit.is_some()));
+ assert_eq!(out.updates, vec![expected_update]);
+ if let Some(expected) = expected_edit {
+ assert_eq!(out.edits, vec![expected]);
+ }
}
}
@@ -275,17 +623,19 @@ mod update {
)
.unwrap();
- assert_eq!(out.edits.len(), 1);
+ assert_eq!(out.edits.len(), 2, "symbolic refs are handled just like any other ref");
assert_eq!(
out.updates,
vec![
fetch::refs::Update {
mode: fetch::refs::update::Mode::New,
+ type_change: None,
edit_index: Some(0)
},
fetch::refs::Update {
- mode: fetch::refs::update::Mode::RejectedSymbolic,
- edit_index: None
+ mode: fetch::refs::update::Mode::NoChangeNeeded,
+ type_change: Some(TypeChange::SymbolicToDirect),
+ edit_index: Some(1)
}
],
);
@@ -303,7 +653,7 @@ mod update {
}
#[test]
- fn local_direct_refs_are_never_written_with_symbolic_ones_but_see_only_the_destination() {
+ fn local_direct_refs_are_written_with_symbolic_ones() {
let repo = repo("two-origins");
let (mappings, specs) = mapping_from_spec("refs/heads/symbolic:refs/heads/not-currently-checked-out", &repo);
let out = fetch::refs::update(
@@ -323,6 +673,7 @@ mod update {
out.updates,
vec![fetch::refs::Update {
mode: fetch::refs::update::Mode::NoChangeNeeded,
+ type_change: Some(fetch::refs::update::TypeChange::DirectToSymbolic),
edit_index: Some(0)
}],
);
@@ -349,6 +700,7 @@ mod update {
out.updates,
vec![fetch::refs::Update {
mode: fetch::refs::update::Mode::New,
+ type_change: None,
edit_index: Some(0),
}],
);
@@ -399,10 +751,12 @@ mod update {
vec![
fetch::refs::Update {
mode: fetch::refs::update::Mode::New,
+ type_change: None,
edit_index: Some(0),
},
fetch::refs::Update {
mode: fetch::refs::update::Mode::NoChangeNeeded,
+ type_change: None,
edit_index: Some(1),
}
],
@@ -446,6 +800,7 @@ mod update {
out.updates,
vec![fetch::refs::Update {
mode: fetch::refs::update::Mode::FastForward,
+ type_change: None,
edit_index: Some(0),
}],
"The caller has to be aware and note that dry-runs can't know about fast-forwards as they don't have remote objects"
@@ -480,6 +835,7 @@ mod update {
out.updates,
vec![fetch::refs::Update {
mode: fetch::refs::update::Mode::RejectedNonFastForward,
+ type_change: None,
edit_index: None,
}]
);
@@ -502,6 +858,7 @@ mod update {
out.updates,
vec![fetch::refs::Update {
mode: fetch::refs::update::Mode::FastForward,
+ type_change: None,
edit_index: Some(0),
}]
);
@@ -535,6 +892,7 @@ mod update {
out.updates,
vec![fetch::refs::Update {
mode: fetch::refs::update::Mode::FastForward,
+ type_change: None,
edit_index: Some(0),
}]
);
@@ -548,12 +906,15 @@ mod update {
}
}
- fn mapping_from_spec(spec: &str, repo: &gix::Repository) -> (Vec<fetch::Mapping>, Vec<gix::refspec::RefSpec>) {
+ fn mapping_from_spec(
+ spec: &str,
+ remote_repo: &gix::Repository,
+ ) -> (Vec<fetch::Mapping>, Vec<gix::refspec::RefSpec>) {
let spec = gix_refspec::parse(spec.into(), gix_refspec::parse::Operation::Fetch).unwrap();
let group = gix_refspec::MatchGroup::from_fetch_specs(Some(spec));
- let references = repo.references().unwrap();
+ let references = remote_repo.references().unwrap();
let mut references: Vec<_> = references.all().unwrap().map(|r| into_remote_ref(r.unwrap())).collect();
- references.push(into_remote_ref(repo.find_reference("HEAD").unwrap()));
+ references.push(into_remote_ref(remote_repo.find_reference("HEAD").unwrap()));
let mappings = group
.match_remotes(references.iter().map(remote_ref_to_item))
.mappings
@@ -566,7 +927,7 @@ mod update {
},
|idx| fetch::Source::Ref(references[idx].clone()),
),
- local: m.rhs.map(|r| r.into_owned()),
+ local: m.rhs.map(std::borrow::Cow::into_owned),
spec_index: SpecIndex::ExplicitInRemote(m.spec_index),
})
.collect();
@@ -582,11 +943,14 @@ mod update {
},
TargetRef::Symbolic(name) => {
let target = name.as_bstr().into();
- let id = r.peel_to_id_in_place().unwrap();
- gix_protocol::handshake::Ref::Symbolic {
- full_ref_name,
- target,
- object: id.detach(),
+ match r.peel_to_id_in_place() {
+ Ok(id) => gix_protocol::handshake::Ref::Symbolic {
+ full_ref_name,
+ target,
+ tag: None,
+ object: id.detach(),
+ },
+ Err(_) => gix_protocol::handshake::Ref::Unborn { full_ref_name, target },
}
}
}
@@ -594,9 +958,10 @@ mod update {
fn remote_ref_to_item(r: &gix_protocol::handshake::Ref) -> gix_refspec::match_group::Item<'_> {
let (full_ref_name, target, object) = r.unpack();
+ static NULL: gix_hash::ObjectId = gix_hash::Kind::Sha1.null();
gix_refspec::match_group::Item {
full_ref_name,
- target: target.expect("no unborn HEAD"),
+ target: target.unwrap_or(NULL.as_ref()),
object,
}
}
diff --git a/vendor/gix/src/remote/connection/fetch/update_refs/update.rs b/vendor/gix/src/remote/connection/fetch/update_refs/update.rs
index 6eda1ffc0..41ed3753d 100644
--- a/vendor/gix/src/remote/connection/fetch/update_refs/update.rs
+++ b/vendor/gix/src/remote/connection/fetch/update_refs/update.rs
@@ -10,7 +10,7 @@ mod error {
#[error(transparent)]
FindReference(#[from] crate::reference::find::Error),
#[error("A remote reference had a name that wasn't considered valid. Corrupt remote repo or insufficient checks on remote?")]
- InvalidRefName(#[from] gix_validate::refname::Error),
+ InvalidRefName(#[from] gix_validate::reference::name::Error),
#[error("Failed to update references to their new position to match their remote locations")]
EditReferences(#[from] crate::reference::edit::Error),
#[error("Failed to read or iterate worktree dir")]
@@ -19,6 +19,10 @@ mod error {
OpenWorktreeRepo(#[from] crate::open::Error),
#[error("Could not find local commit for fast-forward ancestor check")]
FindCommit(#[from] crate::object::find::existing::Error),
+ #[error("Could not peel symbolic local reference to its ID")]
+ PeelToId(#[from] crate::reference::peel::Error),
+ #[error("Failed to follow a symbolic reference to assure worktree isn't affected")]
+ FollowSymref(#[from] gix_ref::file::find::existing::Error),
}
}
@@ -35,11 +39,14 @@ pub struct Outcome {
pub updates: Vec<super::Update>,
}
-/// Describe the way a ref was updated
+/// Describe the way a ref was updated, with particular focus on how the (peeled) target commit was affected.
+///
+/// Note that for all the variants that signal a change or `NoChangeNeeded` it's additionally possible to change the target type
+/// from symbolic to direct, or the other way around.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Mode {
/// No change was attempted as the remote ref didn't change compared to the current ref, or because no remote ref was specified
- /// in the ref-spec.
+ /// in the ref-spec. Note that the expected value is still asserted to uncover potential race conditions with other processes.
NoChangeNeeded,
/// The old ref's commit was an ancestor of the new one, allowing for a fast-forward without a merge.
FastForward,
@@ -62,14 +69,19 @@ pub enum Mode {
RejectedTagUpdate,
/// The reference update would not have been a fast-forward, and force is not specified in the ref-spec.
RejectedNonFastForward,
- /// The update of a local symbolic reference was rejected.
- RejectedSymbolic,
+ /// The remote has an unborn symbolic reference where we have one that is set. This means the remote
+ /// has reset itself to a newly initialized state or a state that is highly unusual.
+ /// It may also mean that the remote knows the target name, but it's not available locally and not included in the ref-mappings
+ /// to be created, so we would effectively change a valid local ref into one that seems unborn, which is rejected.
+ /// Note that this mode may have an associated ref-edit that is a no-op, or current-state assertion, for logistical reasons only
+ /// and having no edit would be preferred.
+ RejectedToReplaceWithUnborn,
/// The update was rejected because the branch is checked out in the given worktree_dir.
///
/// Note that the check applies to any known worktree, whether it's present on disk or not.
RejectedCurrentlyCheckedOut {
- /// The path to the worktree directory where the branch is checked out.
- worktree_dir: PathBuf,
+ /// The path(s) to the worktree directory where the branch is checked out.
+ worktree_dirs: Vec<PathBuf>,
},
}
@@ -84,12 +96,16 @@ impl std::fmt::Display for Mode {
Mode::RejectedSourceObjectNotFound { id } => return write!(f, "rejected ({id} not found)"),
Mode::RejectedTagUpdate => "rejected (would overwrite existing tag)",
Mode::RejectedNonFastForward => "rejected (non-fast-forward)",
- Mode::RejectedSymbolic => "rejected (refusing to write symbolic refs)",
- Mode::RejectedCurrentlyCheckedOut { worktree_dir } => {
+ Mode::RejectedToReplaceWithUnborn => "rejected (refusing to overwrite existing with unborn ref)",
+ Mode::RejectedCurrentlyCheckedOut { worktree_dirs } => {
return write!(
f,
"rejected (cannot write into checked-out branch at \"{}\")",
- worktree_dir.display()
+ worktree_dirs
+ .iter()
+ .filter_map(|d| d.to_str())
+ .collect::<Vec<_>>()
+ .join(", ")
)
}
}
@@ -97,6 +113,15 @@ impl std::fmt::Display for Mode {
}
}
+/// Indicates that a ref changes its type.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
+pub enum TypeChange {
+ /// A local direct reference is changed into a symbolic one.
+ DirectToSymbolic,
+ /// A local symbolic reference is changed into a direct one.
+ SymbolicToDirect,
+}
+
impl Outcome {
/// Produce an iterator over all information used to produce the this outcome, ref-update by ref-update, using the `mappings`
/// used when producing the ref update.
diff --git a/vendor/gix/src/remote/connection/ref_map.rs b/vendor/gix/src/remote/connection/ref_map.rs
index 95ddb6214..f1b40d56e 100644
--- a/vendor/gix/src/remote/connection/ref_map.rs
+++ b/vendor/gix/src/remote/connection/ref_map.rs
@@ -133,7 +133,7 @@ where
)
.await?;
let num_explicit_specs = self.remote.fetch_specs.len();
- let group = gix_refspec::MatchGroup::from_fetch_specs(specs.iter().map(|s| s.to_ref()));
+ let group = gix_refspec::MatchGroup::from_fetch_specs(specs.iter().map(gix_refspec::RefSpec::to_ref));
let (res, fixes) = group
.match_remotes(remote.refs.iter().map(|r| {
let (full_ref_name, target, object) = r.unpack();
@@ -157,7 +157,7 @@ where
},
|idx| fetch::Source::Ref(remote.refs[idx].clone()),
),
- local: m.rhs.map(|c| c.into_owned()),
+ local: m.rhs.map(std::borrow::Cow::into_owned),
spec_index: if m.spec_index < num_explicit_specs {
SpecIndex::ExplicitInRemote(m.spec_index)
} else {
@@ -204,7 +204,7 @@ where
self.transport_options = self
.remote
.repo
- .transport_options(url.as_ref(), self.remote.name().map(|n| n.as_bstr()))
+ .transport_options(url.as_ref(), self.remote.name().map(crate::remote::Name::as_bstr))
.map_err(|err| Error::GatherTransportConfig {
source: err,
url: url.into_owned(),
diff --git a/vendor/gix/src/remote/errors.rs b/vendor/gix/src/remote/errors.rs
index 20060cedf..34ed8246b 100644
--- a/vendor/gix/src/remote/errors.rs
+++ b/vendor/gix/src/remote/errors.rs
@@ -2,7 +2,7 @@
pub mod find {
use crate::{bstr::BString, config, remote};
- /// The error returned by [`Repository::find_remote(…)`][crate::Repository::find_remote()].
+ /// The error returned by [`Repository::find_remote(…)`](crate::Repository::find_remote()).
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
@@ -30,7 +30,7 @@ pub mod find {
pub mod existing {
use crate::bstr::BString;
- /// The error returned by [`Repository::find_remote(…)`][crate::Repository::find_remote()].
+ /// The error returned by [`Repository::find_remote(…)`](crate::Repository::find_remote()).
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
@@ -42,4 +42,23 @@ pub mod find {
NotFound { name: BString },
}
}
+
+ ///
+ pub mod for_fetch {
+ /// The error returned by [`Repository::find_fetch_remote(…)`](crate::Repository::find_fetch_remote()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ FindExisting(#[from] super::existing::Error),
+ #[error(transparent)]
+ FindExistingReferences(#[from] crate::reference::find::existing::Error),
+ #[error("Could not initialize a URL remote")]
+ Init(#[from] crate::remote::init::Error),
+ #[error("remote name could not be parsed as URL")]
+ UrlParse(#[from] gix_url::parse::Error),
+ #[error("No configured remote could be found, or too many were available")]
+ ExactlyOneRemoteNotAvailable,
+ }
+ }
}
diff --git a/vendor/gix/src/remote/fetch.rs b/vendor/gix/src/remote/fetch.rs
index 0947ace3f..4700201de 100644
--- a/vendor/gix/src/remote/fetch.rs
+++ b/vendor/gix/src/remote/fetch.rs
@@ -1,17 +1,20 @@
///
pub mod negotiate {
+ #[cfg(feature = "credentials")]
pub use gix_negotiate::Algorithm;
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
pub use super::super::connection::fetch::negotiate::Error;
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
pub(crate) use super::super::connection::fetch::negotiate::{
- add_wants, mark_complete_and_common_ref, one_round, Action,
+ add_wants, make_refmapping_ignore_predicate, mark_complete_and_common_ref, one_round, Action,
};
}
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
-pub use super::connection::fetch::{prepare, refs, Error, Outcome, Prepare, ProgressId, RefLogMessage, Status};
+pub use super::connection::fetch::{
+ outcome, prepare, refs, Error, Outcome, Prepare, ProgressId, RefLogMessage, Status,
+};
/// If `Yes`, don't really make changes but do as much as possible to get an idea of what would be done.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -152,6 +155,18 @@ impl Source {
}
}
+ /// Return the target that this symbolic ref is pointing to, or `None` if it is no symbolic ref.
+ pub fn as_target(&self) -> Option<&crate::bstr::BStr> {
+ match self {
+ Source::ObjectId(_) => None,
+ Source::Ref(r) => match r {
+ gix_protocol::handshake::Ref::Peeled { .. } | gix_protocol::handshake::Ref::Direct { .. } => None,
+ gix_protocol::handshake::Ref::Symbolic { target, .. }
+ | gix_protocol::handshake::Ref::Unborn { target, .. } => Some(target.as_ref()),
+ },
+ }
+ }
+
/// Returns the peeled id of this instance, that is the object that can't be de-referenced anymore.
pub fn peeled_id(&self) -> Option<&gix_hash::oid> {
match self {
diff --git a/vendor/gix/src/remote/init.rs b/vendor/gix/src/remote/init.rs
index bba116946..13b747eda 100644
--- a/vendor/gix/src/remote/init.rs
+++ b/vendor/gix/src/remote/init.rs
@@ -67,7 +67,18 @@ impl<'repo> Remote<'repo> {
Url: TryInto<gix_url::Url, Error = E>,
gix_url::parse::Error: From<E>,
{
- let url = url.try_into().map_err(|err| Error::Url(err.into()))?;
+ Self::from_fetch_url_inner(
+ url.try_into().map_err(|err| Error::Url(err.into()))?,
+ should_rewrite_urls,
+ repo,
+ )
+ }
+
+ fn from_fetch_url_inner(
+ url: gix_url::Url,
+ should_rewrite_urls: bool,
+ repo: &'repo Repository,
+ ) -> Result<Self, Error> {
let (url_alias, _) = should_rewrite_urls
.then(|| rewrite_urls(&repo.config, Some(&url), None))
.unwrap_or(Ok((None, None)))?;
diff --git a/vendor/gix/src/remote/save.rs b/vendor/gix/src/remote/save.rs
index ad6a75b14..2a91dfa9c 100644
--- a/vendor/gix/src/remote/save.rs
+++ b/vendor/gix/src/remote/save.rs
@@ -1,5 +1,7 @@
use std::convert::TryInto;
+use gix_macros::momo;
+
use crate::{
bstr::{BStr, BString},
config, remote, Remote,
@@ -25,7 +27,7 @@ pub enum AsError {
Name(#[from] crate::remote::name::Error),
}
-/// Serialize into gix-config.
+/// Serialize into git-config.
impl Remote<'_> {
/// Save ourselves to the given `config` if we are a named remote or fail otherwise.
///
@@ -111,6 +113,7 @@ impl Remote<'_> {
/// If this name is different from the current one, the git configuration will still contain the previous name,
/// and the caller should account for that.
#[allow(clippy::result_large_err)]
+ #[momo]
pub fn save_as_to(
&mut self,
name: impl Into<BString>,
diff --git a/vendor/gix/src/repository/attributes.rs b/vendor/gix/src/repository/attributes.rs
index 252529761..7f747f7fd 100644
--- a/vendor/gix/src/repository/attributes.rs
+++ b/vendor/gix/src/repository/attributes.rs
@@ -1,5 +1,15 @@
//! exclude information
-use crate::Repository;
+use crate::{config, AttributeStack, Repository};
+
+/// The error returned by [`Repository::attributes()`].
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
+pub enum Error {
+ #[error(transparent)]
+ ConfigureAttributes(#[from] config::attribute_stack::Error),
+ #[error(transparent)]
+ ConfigureExcludes(#[from] config::exclude_stack::Error),
+}
impl Repository {
/// Configure a file-system cache for accessing git attributes *and* excludes on a per-path basis.
@@ -14,15 +24,14 @@ impl Repository {
///
/// * `$XDG_CONFIG_HOME/…/ignore|attributes` if `core.excludesFile|attributesFile` is *not* set, otherwise use the configured file.
/// * `$GIT_DIR/info/exclude|attributes` if present.
- // TODO: test, provide higher-level custom Cache wrapper that is much easier to use and doesn't panic when accessing entries
- // by non-relative path.
+ #[cfg(feature = "attributes")]
pub fn attributes(
&self,
index: &gix_index::State,
- attributes_source: gix_worktree::cache::state::attributes::Source,
- ignore_source: gix_worktree::cache::state::ignore::Source,
+ attributes_source: gix_worktree::stack::state::attributes::Source,
+ ignore_source: gix_worktree::stack::state::ignore::Source,
exclude_overrides: Option<gix_ignore::Search>,
- ) -> Result<gix_worktree::Cache, crate::attributes::Error> {
+ ) -> Result<AttributeStack<'_>, Error> {
let case = if self.config.ignore_case {
gix_glob::pattern::Case::Fold
} else {
@@ -36,15 +45,95 @@ impl Repository {
let ignore =
self.config
.assemble_exclude_globals(self.git_dir(), exclude_overrides, ignore_source, &mut buf)?;
- let state = gix_worktree::cache::State::AttributesAndIgnoreStack { attributes, ignore };
- let attribute_list = state.id_mappings_from_index(index, index.path_backing(), ignore_source, case);
- Ok(gix_worktree::Cache::new(
- // this is alright as we don't cause mutation of that directory, it's virtual.
- self.work_dir().unwrap_or(self.git_dir()),
- state,
- case,
- buf,
- attribute_list,
+ let state = gix_worktree::stack::State::AttributesAndIgnoreStack { attributes, ignore };
+ let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);
+ Ok(AttributeStack::new(
+ gix_worktree::Stack::new(
+ // this is alright as we don't cause mutation of that directory, it's virtual.
+ self.work_dir().unwrap_or(self.git_dir()),
+ state,
+ case,
+ buf,
+ attribute_list,
+ ),
+ self,
+ ))
+ }
+
+ /// Like [attributes()][Self::attributes()], but without access to exclude/ignore information.
+ #[cfg(feature = "attributes")]
+ pub fn attributes_only(
+ &self,
+ index: &gix_index::State,
+ attributes_source: gix_worktree::stack::state::attributes::Source,
+ ) -> Result<AttributeStack<'_>, config::attribute_stack::Error> {
+ let case = if self.config.ignore_case {
+ gix_glob::pattern::Case::Fold
+ } else {
+ gix_glob::pattern::Case::Sensitive
+ };
+ let (attributes, buf) = self.config.assemble_attribute_globals(
+ self.git_dir(),
+ attributes_source,
+ self.options.permissions.attributes,
+ )?;
+ let state = gix_worktree::stack::State::AttributesStack(attributes);
+ let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);
+ Ok(AttributeStack::new(
+ gix_worktree::Stack::new(
+ // this is alright as we don't cause mutation of that directory, it's virtual.
+ self.work_dir().unwrap_or(self.git_dir()),
+ state,
+ case,
+ buf,
+ attribute_list,
+ ),
+ self,
+ ))
+ }
+
+ /// Configure a file-system cache checking if files below the repository are excluded, reading `.gitignore` files from
+ /// the specified `source`.
+ ///
+ /// Note that no worktree is required for this to work, even though access to in-tree `.gitignore` files would require
+ /// a non-empty `index` that represents a tree with `.gitignore` files.
+ ///
+ /// This takes into consideration all the usual repository configuration, namely:
+ ///
+ /// * `$XDG_CONFIG_HOME/…/ignore` if `core.excludesFile` is *not* set, otherwise use the configured file.
+ /// * `$GIT_DIR/info/exclude` if present.
+ ///
+ /// When only excludes are desired, this is the most efficient way to obtain them. Otherwise use
+ /// [`Repository::attributes()`] for accessing both attributes and excludes.
+ // TODO: test
+ #[cfg(feature = "excludes")]
+ pub fn excludes(
+ &self,
+ index: &gix_index::State,
+ overrides: Option<gix_ignore::Search>,
+ source: gix_worktree::stack::state::ignore::Source,
+ ) -> Result<AttributeStack<'_>, config::exclude_stack::Error> {
+ let case = if self.config.ignore_case {
+ gix_glob::pattern::Case::Fold
+ } else {
+ gix_glob::pattern::Case::Sensitive
+ };
+ let mut buf = Vec::with_capacity(512);
+ let ignore = self
+ .config
+ .assemble_exclude_globals(self.git_dir(), overrides, source, &mut buf)?;
+ let state = gix_worktree::stack::State::IgnoreStack(ignore);
+ let attribute_list = state.id_mappings_from_index(index, index.path_backing(), case);
+ Ok(AttributeStack::new(
+ gix_worktree::Stack::new(
+ // this is alright as we don't cause mutation of that directory, it's virtual.
+ self.work_dir().unwrap_or(self.git_dir()),
+ state,
+ case,
+ buf,
+ attribute_list,
+ ),
+ self,
))
}
}
diff --git a/vendor/gix/src/repository/config/mod.rs b/vendor/gix/src/repository/config/mod.rs
index e5c8b64f3..618ccf0f6 100644
--- a/vendor/gix/src/repository/config/mod.rs
+++ b/vendor/gix/src/repository/config/mod.rs
@@ -22,6 +22,21 @@ impl crate::Repository {
}
}
+ /// Return filesystem options as retrieved from the repository configuration.
+ ///
+ /// Note that these values have not been [probed](gix_fs::Capabilities::probe()).
+ pub fn filesystem_options(&self) -> Result<gix_fs::Capabilities, config::boolean::Error> {
+ self.config.fs_capabilities()
+ }
+
+ /// Return filesystem options on how to perform stat-checks, typically in relation to the index.
+ ///
+ /// Note that these values have not been [probed](gix_fs::Capabilities::probe()).
+ #[cfg(feature = "index")]
+ pub fn stat_options(&self) -> Result<gix_index::entry::stat::Options, config::stat_options::Error> {
+ self.config.stat_options()
+ }
+
/// The options used to open the repository.
pub fn open_options(&self) -> &crate::open::Options {
&self.options
diff --git a/vendor/gix/src/repository/config/transport.rs b/vendor/gix/src/repository/config/transport.rs
index dcfbc0bf6..99b5a7f47 100644
--- a/vendor/gix/src/repository/config/transport.rs
+++ b/vendor/gix/src/repository/config/transport.rs
@@ -1,6 +1,8 @@
#![allow(clippy::result_large_err)]
use std::any::Any;
+use gix_macros::momo;
+
use crate::bstr::BStr;
impl crate::Repository {
@@ -21,6 +23,7 @@ impl crate::Repository {
)),
allow(unused_variables)
)]
+ #[momo]
pub fn transport_options<'a>(
&self,
url: impl Into<&'a BStr>,
@@ -359,7 +362,7 @@ impl crate::Repository {
self.install_dir().ok().as_deref(),
self.config.home_dir().as_deref(),
))
- .map(|cow| cow.into_owned())
+ .map(std::borrow::Cow::into_owned)
})
.transpose()
.with_leniency(lenient)
diff --git a/vendor/gix/src/repository/excludes.rs b/vendor/gix/src/repository/excludes.rs
deleted file mode 100644
index 6281549e0..000000000
--- a/vendor/gix/src/repository/excludes.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-//! exclude information
-use crate::{config, Repository};
-impl Repository {
- /// Configure a file-system cache checking if files below the repository are excluded, reading `.gitignore` files from
- /// the specified `source`.
- ///
- /// Note that no worktree is required for this to work, even though access to in-tree `.gitignore` files would require
- /// a non-empty `index` that represents a tree with `.gitignore` files.
- ///
- /// This takes into consideration all the usual repository configuration, namely:
- ///
- /// * `$XDG_CONFIG_HOME/…/ignore` if `core.excludesFile` is *not* set, otherwise use the configured file.
- /// * `$GIT_DIR/info/exclude` if present.
- ///
- /// When only excludes are desired, this is the most efficient way to obtain them. Otherwise use
- /// [`Repository::attributes()`] for accessing both attributes and excludes.
- // TODO: test, provide higher-level custom Cache wrapper that is much easier to use and doesn't panic when accessing entries
- // by non-relative path.
- pub fn excludes(
- &self,
- index: &gix_index::State,
- overrides: Option<gix_ignore::Search>,
- source: gix_worktree::cache::state::ignore::Source,
- ) -> Result<gix_worktree::Cache, config::exclude_stack::Error> {
- let case = if self.config.ignore_case {
- gix_glob::pattern::Case::Fold
- } else {
- gix_glob::pattern::Case::Sensitive
- };
- let mut buf = Vec::with_capacity(512);
- let ignore = self
- .config
- .assemble_exclude_globals(self.git_dir(), overrides, source, &mut buf)?;
- let state = gix_worktree::cache::State::IgnoreStack(ignore);
- let attribute_list = state.id_mappings_from_index(index, index.path_backing(), source, case);
- Ok(gix_worktree::Cache::new(
- // this is alright as we don't cause mutation of that directory, it's virtual.
- self.work_dir().unwrap_or(self.git_dir()),
- state,
- case,
- buf,
- attribute_list,
- ))
- }
-}
diff --git a/vendor/gix/src/repository/filter.rs b/vendor/gix/src/repository/filter.rs
new file mode 100644
index 000000000..3aacb1a3d
--- /dev/null
+++ b/vendor/gix/src/repository/filter.rs
@@ -0,0 +1,64 @@
+use crate::{filter, repository::IndexPersistedOrInMemory, Id, Repository};
+
+///
+pub mod pipeline {
+ /// The error returned by [Repository::filter_pipeline()][super::Repository::filter_pipeline()].
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error("Could not obtain head commit of bare repository")]
+ HeadCommit(#[from] crate::reference::head_commit::Error),
+ #[error(transparent)]
+ DecodeCommit(#[from] gix_object::decode::Error),
+ #[error("Could not create index from tree at HEAD^{{tree}}")]
+ TreeTraverse(#[from] gix_traverse::tree::breadthfirst::Error),
+ #[error(transparent)]
+ BareAttributes(#[from] crate::config::attribute_stack::Error),
+ #[error(transparent)]
+ WorktreeIndex(#[from] crate::worktree::open_index::Error),
+ #[error(transparent)]
+ Init(#[from] crate::filter::pipeline::options::Error),
+ }
+}
+
+impl Repository {
+ /// Configure a pipeline for converting byte buffers to the worktree representation, and byte streams to the git-internal
+ /// representation. Also return the index that was used when initializing the pipeline as it may be useful when calling
+ /// [convert_to_git()][filter::Pipeline::convert_to_git()].
+ /// Bare repositories will either use `HEAD^{tree}` for accessing all relevant worktree files or the given `tree_if_bare`.
+ ///
+ /// Note that this is considered a primitive as it operates on data directly and will not have permanent effects.
+ /// We also return the index that was used to configure the attributes cache (for accessing `.gitattributes`), which can be reused
+ /// after it was possibly created from a tree, an expensive operation.
+ ///
+ /// ### Performance
+ ///
+ /// Note that when in a repository with worktree, files in the worktree will be read with priority, which causes at least a stat
+ /// each time the directory is changed. This can be expensive if access isn't in sorted order, which would cause more then necessary
+ /// stats: one per directory.
+ pub fn filter_pipeline(
+ &self,
+ tree_if_bare: Option<gix_hash::ObjectId>,
+ ) -> Result<(filter::Pipeline<'_>, IndexPersistedOrInMemory), pipeline::Error> {
+ let (cache, index) = if self.is_bare() {
+ let index = self.index_from_tree(&tree_if_bare.map_or_else(
+ || {
+ self.head_commit()
+ .map_err(pipeline::Error::from)
+ .and_then(|c| c.tree_id().map(Id::detach).map_err(Into::into))
+ },
+ Ok,
+ )?)?;
+ let cache = self.attributes_only(&index, gix_worktree::stack::state::attributes::Source::IdMapping)?;
+ (cache, IndexPersistedOrInMemory::InMemory(index))
+ } else {
+ let index = self.index()?;
+ let cache = self.attributes_only(
+ &index,
+ gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
+ )?;
+ (cache, IndexPersistedOrInMemory::Persisted(index))
+ };
+ Ok((filter::Pipeline::new(self, cache.detach())?, index))
+ }
+}
diff --git a/vendor/gix/src/repository/graph.rs b/vendor/gix/src/repository/graph.rs
index a1f6c7f89..f4f2b18cc 100644
--- a/vendor/gix/src/repository/graph.rs
+++ b/vendor/gix/src/repository/graph.rs
@@ -7,18 +7,34 @@ impl crate::Repository {
/// Note that the commitgraph will be used if it is present and readable, but it won't be an error if it is corrupted. In that case,
/// it will just not be used.
///
+ /// Note that a commitgraph is only allowed to be used if `core.commitGraph` is true (the default), and that configuration errors are
+ /// ignored as well.
+ ///
/// ### Performance
///
- /// Note that the [Graph][gix_revision::Graph] can be sensitive to various object database settings that may affect the performance
+ /// Note that the [Graph][gix_revwalk::Graph] can be sensitive to various object database settings that may affect the performance
/// of the commit walk.
- pub fn commit_graph<T>(&self) -> gix_revision::Graph<'_, T> {
- gix_revision::Graph::new(
+ pub fn revision_graph<T>(&self) -> gix_revwalk::Graph<'_, T> {
+ gix_revwalk::Graph::new(
|id, buf| {
self.objects
.try_find(id, buf)
- .map(|r| r.and_then(|d| d.try_into_commit_iter()))
+ .map(|r| r.and_then(gix_object::Data::try_into_commit_iter))
},
- gix_commitgraph::at(self.objects.store_ref().path().join("info")).ok(),
+ self.config
+ .may_use_commit_graph()
+ .unwrap_or(true)
+ .then(|| gix_commitgraph::at(self.objects.store_ref().path().join("info")).ok())
+ .flatten(),
)
}
+
+ /// Return a cache for commits and their graph structure, as managed by `git commit-graph`, for accelerating commit walks on
+ /// a low level.
+ ///
+ /// Note that [`revision_graph()`][crate::Repository::revision_graph()] should be preferred for general purpose walks that don't
+ /// rely on the actual commit cache to be present, while leveraging it if possible.
+ pub fn commit_graph(&self) -> Result<gix_commitgraph::Graph, gix_commitgraph::init::Error> {
+ gix_commitgraph::at(self.objects.store_ref().path().join("info"))
+ }
}
diff --git a/vendor/gix/src/repository/identity.rs b/vendor/gix/src/repository/identity.rs
index 61a4b4a98..a4e39089e 100644
--- a/vendor/gix/src/repository/identity.rs
+++ b/vendor/gix/src/repository/identity.rs
@@ -31,13 +31,13 @@ impl crate::Repository {
let p = self.config.personas();
Ok(gix_actor::SignatureRef {
- name: p.committer.name.as_ref().or(p.user.name.as_ref()).map(|v| v.as_ref())?,
+ name: p.committer.name.as_ref().or(p.user.name.as_ref()).map(AsRef::as_ref)?,
email: p
.committer
.email
.as_ref()
.or(p.user.email.as_ref())
- .map(|v| v.as_ref())?,
+ .map(AsRef::as_ref)?,
time: match extract_time_or_default(p.committer.time.as_ref(), &gitoxide::Commit::COMMITTER_DATE) {
Ok(t) => t,
Err(err) => return Some(Err(err)),
@@ -61,8 +61,8 @@ impl crate::Repository {
let p = self.config.personas();
Ok(gix_actor::SignatureRef {
- name: p.author.name.as_ref().or(p.user.name.as_ref()).map(|v| v.as_ref())?,
- email: p.author.email.as_ref().or(p.user.email.as_ref()).map(|v| v.as_ref())?,
+ name: p.author.name.as_ref().or(p.user.name.as_ref()).map(AsRef::as_ref)?,
+ email: p.author.email.as_ref().or(p.user.email.as_ref()).map(AsRef::as_ref)?,
time: match extract_time_or_default(p.author.time.as_ref(), &gitoxide::Commit::AUTHOR_DATE) {
Ok(t) => t,
Err(err) => return Some(Err(err)),
@@ -73,9 +73,9 @@ impl crate::Repository {
}
fn extract_time_or_default(
- time: Option<&Result<gix_actor::Time, gix_date::parse::Error>>,
+ time: Option<&Result<gix_date::Time, gix_date::parse::Error>>,
config_key: &'static keys::Time,
-) -> Result<gix_actor::Time, config::time::Error> {
+) -> Result<gix_date::Time, config::time::Error> {
match time {
Some(Ok(t)) => Ok(*t),
None => Ok(gix_date::Time::now_local_or_utc()),
@@ -88,7 +88,7 @@ pub(crate) struct Entity {
pub name: Option<BString>,
pub email: Option<BString>,
/// A time parsed from an environment variable, handling potential errors is delayed.
- pub time: Option<Result<gix_actor::Time, gix_date::parse::Error>>,
+ pub time: Option<Result<gix_date::Time, gix_date::parse::Error>>,
}
#[derive(Debug, Clone)]
@@ -117,11 +117,11 @@ impl Personas {
config
.string(name_key.section.name(), None, name_key.name)
.or_else(|| fallback.as_ref().and_then(|(s, name_key, _)| s.value(name_key.name)))
- .map(|v| v.into_owned()),
+ .map(std::borrow::Cow::into_owned),
config
.string(email_key.section.name(), None, email_key.name)
.or_else(|| fallback.as_ref().and_then(|(s, _, email_key)| s.value(email_key.name)))
- .map(|v| v.into_owned()),
+ .map(std::borrow::Cow::into_owned),
)
}
let now = SystemTime::now();
@@ -152,7 +152,7 @@ impl Personas {
user_email = user_email.or_else(|| {
config
.string_by_key(gitoxide::User::EMAIL_FALLBACK.logical_name().as_str())
- .map(|v| v.into_owned())
+ .map(std::borrow::Cow::into_owned)
});
Personas {
user: Entity {
diff --git a/vendor/gix/src/repository/impls.rs b/vendor/gix/src/repository/impls.rs
index 5da55290c..36fd788dc 100644
--- a/vendor/gix/src/repository/impls.rs
+++ b/vendor/gix/src/repository/impls.rs
@@ -7,8 +7,11 @@ impl Clone for crate::Repository {
self.common_dir.clone(),
self.config.clone(),
self.options.clone(),
+ #[cfg(feature = "index")]
self.index.clone(),
self.shallow_commits.clone(),
+ #[cfg(feature = "attributes")]
+ self.modules.clone(),
)
}
}
@@ -40,8 +43,11 @@ impl From<&crate::ThreadSafeRepository> for crate::Repository {
repo.common_dir.clone(),
repo.config.clone(),
repo.linked_worktree_options.clone(),
+ #[cfg(feature = "index")]
repo.index.clone(),
repo.shallow_commits.clone(),
+ #[cfg(feature = "attributes")]
+ repo.modules.clone(),
)
}
}
@@ -55,8 +61,11 @@ impl From<crate::ThreadSafeRepository> for crate::Repository {
repo.common_dir,
repo.config,
repo.linked_worktree_options,
+ #[cfg(feature = "index")]
repo.index,
repo.shallow_commits,
+ #[cfg(feature = "attributes")]
+ repo.modules.clone(),
)
}
}
@@ -70,7 +79,10 @@ impl From<crate::Repository> for crate::ThreadSafeRepository {
common_dir: r.common_dir,
config: r.config,
linked_worktree_options: r.options,
+ #[cfg(feature = "index")]
index: r.index,
+ #[cfg(feature = "attributes")]
+ modules: r.modules,
shallow_commits: r.shallow_commits,
}
}
diff --git a/vendor/gix/src/repository/index.rs b/vendor/gix/src/repository/index.rs
new file mode 100644
index 000000000..a21b138a5
--- /dev/null
+++ b/vendor/gix/src/repository/index.rs
@@ -0,0 +1,133 @@
+use gix_odb::FindExt;
+
+use crate::{config::cache::util::ApplyLeniencyDefault, repository::IndexPersistedOrInMemory, worktree};
+
+/// Index access
+impl crate::Repository {
+ /// Open a new copy of the index file and decode it entirely.
+ ///
+ /// It will use the `index.threads` configuration key to learn how many threads to use.
+ /// Note that it may fail if there is no index.
+ pub fn open_index(&self) -> Result<gix_index::File, worktree::open_index::Error> {
+ let thread_limit = self
+ .config
+ .resolved
+ .string("index", None, "threads")
+ .map(|value| crate::config::tree::Index::THREADS.try_into_index_threads(value))
+ .transpose()
+ .with_lenient_default(self.config.lenient_config)?;
+ let skip_hash = self
+ .config
+ .resolved
+ .boolean("index", None, "skipHash")
+ .map(|res| crate::config::tree::Index::SKIP_HASH.enrich_error(res))
+ .transpose()
+ .with_lenient_default(self.config.lenient_config)?
+ .unwrap_or_default();
+
+ let index = gix_index::File::at(
+ self.index_path(),
+ self.object_hash(),
+ skip_hash,
+ gix_index::decode::Options {
+ thread_limit,
+ min_extension_block_in_bytes_for_threading: 0,
+ expected_checksum: None,
+ },
+ )?;
+
+ Ok(index)
+ }
+
+ /// Return a shared worktree index which is updated automatically if the in-memory snapshot has become stale as the underlying file
+ /// on disk has changed.
+ ///
+ /// The index file is shared across all clones of this repository.
+ pub fn index(&self) -> Result<worktree::Index, worktree::open_index::Error> {
+ self.try_index().and_then(|opt| match opt {
+ Some(index) => Ok(index),
+ None => Err(worktree::open_index::Error::IndexFile(
+ gix_index::file::init::Error::Io(std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ format!("Could not find index file at {:?} for opening.", self.index_path()),
+ )),
+ )),
+ })
+ }
+
+ /// Return a shared worktree index which is updated automatically if the in-memory snapshot has become stale as the underlying file
+ /// on disk has changed, or `None` if no such file exists.
+ ///
+ /// The index file is shared across all clones of this repository.
+ pub fn try_index(&self) -> Result<Option<worktree::Index>, worktree::open_index::Error> {
+ self.index.recent_snapshot(
+ || self.index_path().metadata().and_then(|m| m.modified()).ok(),
+ || {
+ self.open_index().map(Some).or_else(|err| match err {
+ worktree::open_index::Error::IndexFile(gix_index::file::init::Error::Io(err))
+ if err.kind() == std::io::ErrorKind::NotFound =>
+ {
+ Ok(None)
+ }
+ err => Err(err),
+ })
+ },
+ )
+ }
+
+ /// Open the persisted worktree index or generate it from the current `HEAD^{tree}` to live in-memory only.
+ ///
+ /// Use this method to get an index in any repository, even bare ones that don't have one naturally.
+ ///
+ /// ### Note
+ ///
+ /// The locally stored index is not guaranteed to represent `HEAD^{tree}` if this repository is bare - bare repos
+ /// don't naturally have an index and if an index is present it must have been generated by hand.
+ pub fn index_or_load_from_head(
+ &self,
+ ) -> Result<IndexPersistedOrInMemory, crate::repository::index_or_load_from_head::Error> {
+ Ok(match self.try_index()? {
+ Some(index) => IndexPersistedOrInMemory::Persisted(index),
+ None => {
+ let tree = self.head_commit()?.tree_id()?;
+ IndexPersistedOrInMemory::InMemory(self.index_from_tree(&tree)?)
+ }
+ })
+ }
+
+ /// Create new index-file, which would live at the correct location, in memory from the given `tree`.
+ ///
+ /// Note that this is an expensive operation as it requires recursively traversing the entire tree to unpack it into the index.
+ pub fn index_from_tree(
+ &self,
+ tree: &gix_hash::oid,
+ ) -> Result<gix_index::File, gix_traverse::tree::breadthfirst::Error> {
+ Ok(gix_index::File::from_state(
+ gix_index::State::from_tree(tree, |oid, buf| self.objects.find_tree_iter(oid, buf).ok())?,
+ self.git_dir().join("index"),
+ ))
+ }
+}
+
+impl std::ops::Deref for IndexPersistedOrInMemory {
+ type Target = gix_index::File;
+
+ fn deref(&self) -> &Self::Target {
+ match self {
+ IndexPersistedOrInMemory::Persisted(i) => i,
+ IndexPersistedOrInMemory::InMemory(i) => i,
+ }
+ }
+}
+
+impl IndexPersistedOrInMemory {
+ /// Consume this instance and turn it into an owned index file.
+ ///
+ /// Note that this will cause the persisted index to be cloned, which would happen whenever the repository has a worktree.
+ pub fn into_owned(self) -> gix_index::File {
+ match self {
+ IndexPersistedOrInMemory::Persisted(i) => gix_index::File::clone(&i),
+ IndexPersistedOrInMemory::InMemory(i) => i,
+ }
+ }
+}
diff --git a/vendor/gix/src/repository/init.rs b/vendor/gix/src/repository/init.rs
index 255ff90d6..65b3d59ab 100644
--- a/vendor/gix/src/repository/init.rs
+++ b/vendor/gix/src/repository/init.rs
@@ -4,15 +4,16 @@ impl crate::Repository {
#[allow(clippy::too_many_arguments)]
pub(crate) fn from_refs_and_objects(
refs: crate::RefStore,
- objects: crate::OdbHandle,
+ mut objects: crate::OdbHandle,
work_tree: Option<std::path::PathBuf>,
common_dir: Option<std::path::PathBuf>,
config: crate::config::Cache,
linked_worktree_options: crate::open::Options,
- index: crate::worktree::IndexStorage,
+ #[cfg(feature = "index")] index: crate::worktree::IndexStorage,
shallow_commits: crate::shallow::CommitsStorage,
+ #[cfg(feature = "attributes")] modules: crate::submodule::ModulesFileStorage,
) -> Self {
- let objects = setup_objects(objects, &config);
+ setup_objects(&mut objects, &config);
crate::Repository {
bufs: RefCell::new(Vec::with_capacity(4)),
work_tree,
@@ -21,8 +22,11 @@ impl crate::Repository {
refs,
config,
options: linked_worktree_options,
+ #[cfg(feature = "index")]
index,
shallow_commits,
+ #[cfg(feature = "attributes")]
+ modules,
}
}
@@ -33,7 +37,7 @@ impl crate::Repository {
}
#[cfg_attr(not(feature = "max-performance-safe"), allow(unused_variables, unused_mut))]
-fn setup_objects(mut objects: crate::OdbHandle, config: &crate::config::Cache) -> crate::OdbHandle {
+pub(crate) fn setup_objects(objects: &mut crate::OdbHandle, config: &crate::config::Cache) {
#[cfg(feature = "max-performance-safe")]
{
match config.pack_cache_bytes {
@@ -54,10 +58,5 @@ fn setup_objects(mut objects: crate::OdbHandle, config: &crate::config::Cache) -
let bytes = config.object_cache_bytes;
objects.set_object_cache(move || Box::new(gix_pack::cache::object::MemoryCappedHashmap::new(bytes)));
}
- objects
- }
- #[cfg(not(feature = "max-performance-safe"))]
- {
- objects
}
}
diff --git a/vendor/gix/src/repository/location.rs b/vendor/gix/src/repository/location.rs
index 3e2ff907c..5811e7bf9 100644
--- a/vendor/gix/src/repository/location.rs
+++ b/vendor/gix/src/repository/location.rs
@@ -1,4 +1,4 @@
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use gix_path::realpath::MAX_SYMLINKS;
@@ -25,6 +25,12 @@ impl crate::Repository {
self.git_dir().join("index")
}
+ /// The path to the `.gitmodules` file in the worktree, if a worktree is available.
+ #[cfg(feature = "attributes")]
+ pub fn modules_path(&self) -> Option<PathBuf> {
+ self.work_dir().map(|wtd| wtd.join(crate::submodule::MODULES_FILE))
+ }
+
/// The path to the `.git` directory itself, or equivalent if this is a bare repository.
pub fn path(&self) -> &std::path::Path {
self.git_dir()
@@ -42,30 +48,18 @@ impl crate::Repository {
}
/// Returns the relative path which is the components between the working tree and the current working dir (CWD).
- /// Note that there may be `None` if there is no work tree, even though the `PathBuf` will be empty
- /// if the CWD is at the root of the work tree.
+ /// Note that it may be `None` if there is no work tree, or if CWD isn't inside of the working tree directory.
+ ///
+ /// Note that the CWD is obtained once upon instantiation of the repository.
// TODO: tests, details - there is a lot about environment variables to change things around.
- pub fn prefix(&self) -> Option<std::io::Result<PathBuf>> {
- self.work_tree.as_ref().map(|root| {
- std::env::current_dir().and_then(|cwd| {
- gix_path::realpath_opts(root, &cwd, MAX_SYMLINKS)
- .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))
- .and_then(|root| {
- cwd.strip_prefix(&root)
- .map_err(|_| {
- std::io::Error::new(
- std::io::ErrorKind::Other,
- format!(
- "CWD '{}' isn't within the work tree '{}'",
- cwd.display(),
- root.display()
- ),
- )
- })
- .map(ToOwned::to_owned)
- })
- })
- })
+ pub fn prefix(&self) -> Result<Option<&Path>, gix_path::realpath::Error> {
+ let (root, current_dir) = match self.work_dir().zip(self.options.current_dir.as_deref()) {
+ Some((work_dir, cwd)) => (work_dir, cwd),
+ None => return Ok(None),
+ };
+
+ let root = gix_path::realpath_opts(root, current_dir, MAX_SYMLINKS)?;
+ Ok(current_dir.strip_prefix(&root).ok())
}
/// Return the kind of repository, either bare or one with a work tree.
diff --git a/vendor/gix/src/repository/snapshots.rs b/vendor/gix/src/repository/mailmap.rs
index 96de5080d..b4a2f4a0e 100644
--- a/vendor/gix/src/repository/snapshots.rs
+++ b/vendor/gix/src/repository/mailmap.rs
@@ -37,12 +37,11 @@ impl crate::Repository {
});
match self.work_dir() {
None => {
- // TODO: replace with ref-spec `HEAD:.mailmap` for less verbose way of getting the blob id
blob_id = blob_id.or_else(|| {
self.head().ok().and_then(|mut head| {
let commit = head.peel_to_commit_in_place().ok()?;
let tree = commit.tree().ok()?;
- tree.lookup_entry(Some(".mailmap")).ok()?.map(|e| e.object_id())
+ tree.find_entry(".mailmap").map(|e| e.object_id())
})
});
}
diff --git a/vendor/gix/src/repository/mod.rs b/vendor/gix/src/repository/mod.rs
index f8a51e8d0..e3742894b 100644
--- a/vendor/gix/src/repository/mod.rs
+++ b/vendor/gix/src/repository/mod.rs
@@ -4,6 +4,8 @@
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Kind {
/// A submodule worktree, whose `git` repository lives in `.git/modules/**/<name>` of the parent repository.
+ ///
+ /// Note that 'old-form' submodule will register as `Worktree {is_linked: false}`.
Submodule,
/// A bare repository does not have a work tree, that is files on disk beyond the `git` repository itself.
Bare,
@@ -33,22 +35,106 @@ impl crate::Repository {
}
}
-mod attributes;
+#[cfg(any(feature = "attributes", feature = "excludes"))]
+pub mod attributes;
mod cache;
mod config;
-mod excludes;
+///
+#[cfg(feature = "attributes")]
+pub mod filter;
mod graph;
pub(crate) mod identity;
mod impls;
-mod init;
+#[cfg(feature = "index")]
+mod index;
+pub(crate) mod init;
mod kind;
mod location;
+#[cfg(feature = "mailmap")]
+mod mailmap;
mod object;
+#[cfg(feature = "attributes")]
+mod pathspec;
mod reference;
mod remote;
+#[cfg(feature = "revision")]
mod revision;
mod shallow;
-mod snapshots;
mod state;
+#[cfg(feature = "attributes")]
+mod submodule;
mod thread_safe;
mod worktree;
+
+/// A type to represent an index which either was loaded from disk as it was persisted there, or created on the fly in memory.
+#[cfg(feature = "index")]
+pub enum IndexPersistedOrInMemory {
+ /// The index as loaded from disk, and shared across clones of the owning `Repository`.
+ Persisted(crate::worktree::Index),
+ /// A temporary index as created from the `HEAD^{tree}`, with the file path set to the place where it would be stored naturally.
+ ///
+ /// Note that unless saved explicitly, it will not persist.
+ InMemory(gix_index::File),
+}
+
+///
+#[cfg(feature = "attributes")]
+pub mod pathspec_defaults_ignore_case {
+ /// The error returned by [Repository::pathspec_defaults_ignore_case()](crate::Repository::pathspec_defaults_inherit_ignore_case()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error("Filesystem configuration could not be obtained to learn about case sensitivity")]
+ FilesystemConfig(#[from] crate::config::boolean::Error),
+ #[error(transparent)]
+ Defaults(#[from] gix_pathspec::defaults::from_environment::Error),
+ }
+}
+
+///
+#[cfg(feature = "index")]
+pub mod index_or_load_from_head {
+ /// The error returned by [`Repository::index_or_load_from_head()`][crate::Repository::index_or_load_from_head()].
+ #[derive(thiserror::Error, Debug)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ HeadCommit(#[from] crate::reference::head_commit::Error),
+ #[error(transparent)]
+ TreeId(#[from] gix_object::decode::Error),
+ #[error(transparent)]
+ TraverseTree(#[from] gix_traverse::tree::breadthfirst::Error),
+ #[error(transparent)]
+ OpenIndex(#[from] crate::worktree::open_index::Error),
+ }
+}
+
+///
+#[cfg(feature = "worktree-stream")]
+pub mod worktree_stream {
+ /// The error returned by [`Repository::worktree_stream()`][crate::Repository::worktree_stream()].
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ FindTree(#[from] crate::object::find::existing::Error),
+ #[error(transparent)]
+ OpenTree(#[from] gix_traverse::tree::breadthfirst::Error),
+ #[error(transparent)]
+ AttributesCache(#[from] crate::config::attribute_stack::Error),
+ #[error(transparent)]
+ FilterPipeline(#[from] crate::filter::pipeline::options::Error),
+ #[error("Needed {id} to be a tree to turn into a workspace stream, got {actual}")]
+ NotATree {
+ id: gix_hash::ObjectId,
+ actual: gix_object::Kind,
+ },
+ }
+}
+
+///
+#[cfg(feature = "worktree-archive")]
+pub mod worktree_archive {
+ /// The error returned by [`Repository::worktree_archive()`][crate::Repository::worktree_archive()].
+ pub type Error = gix_archive::Error;
+}
diff --git a/vendor/gix/src/repository/object.rs b/vendor/gix/src/repository/object.rs
index 787dcda4e..c156971d0 100644
--- a/vendor/gix/src/repository/object.rs
+++ b/vendor/gix/src/repository/object.rs
@@ -2,11 +2,13 @@
use std::{convert::TryInto, ops::DerefMut};
use gix_hash::ObjectId;
-use gix_odb::{Find, FindExt, Write};
+use gix_macros::momo;
+use gix_odb::{Find, FindExt, Header, HeaderExt, Write};
use gix_ref::{
transaction::{LogChange, PreviousValue, RefLog},
FullName,
};
+use smallvec::SmallVec;
use crate::{commit, ext::ObjectIdExt, object, tag, Id, Object, Reference, Tree};
@@ -21,6 +23,7 @@ impl crate::Repository {
///
/// In order to get the kind of the object, is must be fully decoded from storage if it is packed with deltas.
/// Loose object could be partially decoded, even though that's not implemented.
+ #[momo]
pub fn find_object(&self, id: impl Into<ObjectId>) -> Result<Object<'_>, object::find::existing::Error> {
let id = id.into();
if id == gix_hash::ObjectId::empty_tree(self.object_hash()) {
@@ -32,11 +35,46 @@ impl crate::Repository {
});
}
let mut buf = self.free_buf();
- let kind = self.objects.find(id, &mut buf)?.kind;
+ let kind = self.objects.find(&id, &mut buf)?.kind;
Ok(Object::from_data(id, kind, buf, self))
}
+ /// Obtain information about an object without fully decoding it, or fail if the object doesn't exist.
+ ///
+ /// Note that despite being cheaper than [`Self::find_object()`], there is still some effort traversing delta-chains.
+ #[doc(alias = "read_header", alias = "git2")]
+ #[momo]
+ pub fn find_header(&self, id: impl Into<ObjectId>) -> Result<gix_odb::find::Header, object::find::existing::Error> {
+ let id = id.into();
+ if id == gix_hash::ObjectId::empty_tree(self.object_hash()) {
+ return Ok(gix_odb::find::Header::Loose {
+ kind: gix_object::Kind::Tree,
+ size: 0,
+ });
+ }
+ self.objects.header(id)
+ }
+
+ /// Obtain information about an object without fully decoding it, or `None` if the object doesn't exist.
+ ///
+ /// Note that despite being cheaper than [`Self::try_find_object()`], there is still some effort traversing delta-chains.
+ #[momo]
+ pub fn try_find_header(
+ &self,
+ id: impl Into<ObjectId>,
+ ) -> Result<Option<gix_odb::find::Header>, object::find::Error> {
+ let id = id.into();
+ if id == gix_hash::ObjectId::empty_tree(self.object_hash()) {
+ return Ok(Some(gix_odb::find::Header::Loose {
+ kind: gix_object::Kind::Tree,
+ size: 0,
+ }));
+ }
+ self.objects.try_header(&id).map_err(Into::into)
+ }
+
/// Try to find the object with `id` or return `None` if it wasn't found.
+ #[momo]
pub fn try_find_object(&self, id: impl Into<ObjectId>) -> Result<Option<Object<'_>>, object::find::Error> {
let id = id.into();
if id == gix_hash::ObjectId::empty_tree(self.object_hash()) {
@@ -49,7 +87,7 @@ impl crate::Repository {
}
let mut buf = self.free_buf();
- match self.objects.try_find(id, &mut buf)? {
+ match self.objects.try_find(&id, &mut buf)? {
Some(obj) => {
let kind = obj.kind;
Ok(Some(Object::from_data(id, kind, buf, self)))
@@ -76,15 +114,19 @@ impl crate::Repository {
/// we avoid writing duplicate objects using slow disks that will eventually have to be garbage collected.
pub fn write_object(&self, object: impl gix_object::WriteTo) -> Result<Id<'_>, object::write::Error> {
let mut buf = self.shared_empty_buf();
- object.write_to(buf.deref_mut())?;
+ object.write_to(buf.deref_mut()).expect("write to memory works");
- let oid = gix_object::compute_hash(self.object_hash(), object.kind(), &buf);
- if self.objects.contains(oid) {
+ self.write_object_inner(&buf, object.kind())
+ }
+
+ fn write_object_inner(&self, buf: &[u8], kind: gix_object::Kind) -> Result<Id<'_>, object::write::Error> {
+ let oid = gix_object::compute_hash(self.object_hash(), kind, buf);
+ if self.objects.contains(&oid) {
return Ok(oid.attach(self));
}
self.objects
- .write_buf(object.kind(), &buf)
+ .write_buf(kind, buf)
.map(|oid| oid.attach(self))
.map_err(Into::into)
}
@@ -93,14 +135,16 @@ impl crate::Repository {
///
/// We avoid writing duplicate objects to slow disks that will eventually have to be garbage collected by
/// pre-hashing the data, and checking if the object is already present.
+ #[momo]
pub fn write_blob(&self, bytes: impl AsRef<[u8]>) -> Result<Id<'_>, object::write::Error> {
let bytes = bytes.as_ref();
let oid = gix_object::compute_hash(self.object_hash(), gix_object::Kind::Blob, bytes);
- if self.objects.contains(oid) {
+ if self.objects.contains(&oid) {
return Ok(oid.attach(self));
}
self.objects
.write_buf(gix_object::Kind::Blob, bytes)
+ .map_err(Into::into)
.map(|oid| oid.attach(self))
}
@@ -115,14 +159,20 @@ impl crate::Repository {
mut bytes: impl std::io::Read + std::io::Seek,
) -> Result<Id<'_>, object::write::Error> {
let mut buf = self.shared_empty_buf();
- std::io::copy(&mut bytes, buf.deref_mut())?;
- let oid = gix_object::compute_hash(self.object_hash(), gix_object::Kind::Blob, &buf);
- if self.objects.contains(oid) {
+ std::io::copy(&mut bytes, buf.deref_mut()).expect("write to memory works");
+
+ self.write_blob_stream_inner(&buf)
+ }
+
+ fn write_blob_stream_inner(&self, buf: &[u8]) -> Result<Id<'_>, object::write::Error> {
+ let oid = gix_object::compute_hash(self.object_hash(), gix_object::Kind::Blob, buf);
+ if self.objects.contains(&oid) {
return Ok(oid.attach(self));
}
self.objects
- .write_buf(gix_object::Kind::Blob, &buf)
+ .write_buf(gix_object::Kind::Blob, buf)
+ .map_err(Into::into)
.map(|oid| oid.attach(self))
}
@@ -131,6 +181,7 @@ impl crate::Repository {
///
/// It will be created with `constraint` which is most commonly to [only create it][PreviousValue::MustNotExist]
/// or to [force overwriting a possibly existing tag](PreviousValue::Any).
+ #[momo]
pub fn tag(
&self,
name: impl AsRef<str>,
@@ -168,6 +219,25 @@ impl crate::Repository {
Name: TryInto<FullName, Error = E>,
commit::Error: From<E>,
{
+ self.commit_as_inner(
+ committer.into(),
+ author.into(),
+ reference.try_into()?,
+ message.as_ref(),
+ tree.into(),
+ parents.into_iter().map(Into::into).collect(),
+ )
+ }
+
+ fn commit_as_inner(
+ &self,
+ committer: gix_actor::SignatureRef<'_>,
+ author: gix_actor::SignatureRef<'_>,
+ reference: FullName,
+ message: &str,
+ tree: ObjectId,
+ parents: SmallVec<[gix_hash::ObjectId; 1]>,
+ ) -> Result<Id<'_>, commit::Error> {
use gix_ref::{
transaction::{Change, RefEdit},
Target,
@@ -175,14 +245,13 @@ impl crate::Repository {
// TODO: possibly use CommitRef to save a few allocations (but will have to allocate for object ids anyway.
// This can be made vastly more efficient though if we wanted to, so we lie in the API
- let reference = reference.try_into()?;
let commit = gix_object::Commit {
- message: message.as_ref().into(),
- tree: tree.into(),
- author: author.into().to_owned(),
- committer: committer.into().to_owned(),
+ message: message.into(),
+ tree,
+ author: author.into(),
+ committer: committer.into(),
encoding: None,
- parents: parents.into_iter().map(|id| id.into()).collect(),
+ parents,
extra_headers: Default::default(),
};
diff --git a/vendor/gix/src/repository/pathspec.rs b/vendor/gix/src/repository/pathspec.rs
new file mode 100644
index 000000000..8e7e9bbe9
--- /dev/null
+++ b/vendor/gix/src/repository/pathspec.rs
@@ -0,0 +1,55 @@
+use gix_pathspec::MagicSignature;
+
+use crate::{bstr::BStr, config::cache::util::ApplyLeniencyDefault, AttributeStack, Pathspec, Repository};
+
+impl Repository {
+ /// Create a new pathspec abstraction that allows to conduct searches using `patterns`.
+ /// `inherit_ignore_case` should be `true` if `patterns` will match against files on disk, or `false` otherwise, for more natural matching
+ /// (but also note that `git` does not do that).
+ /// `index` may be needed to load attributes which is required only if `patterns` refer to attributes via `:(attr:…)` syntax.
+ /// In the same vein, `attributes_source` affects where `.gitattributes` files are read from if pathspecs need to match against attributes.
+ ///
+ /// It will be initialized exactly how it would, and attribute matching will be conducted by reading the worktree first if available.
+ /// If that is not desirable, consider calling [`Pathspec::new()`] directly.
+ #[doc(alias = "Pathspec", alias = "git2")]
+ pub fn pathspec(
+ &self,
+ patterns: impl IntoIterator<Item = impl AsRef<BStr>>,
+ inherit_ignore_case: bool,
+ index: &gix_index::State,
+ attributes_source: gix_worktree::stack::state::attributes::Source,
+ ) -> Result<Pathspec<'_>, crate::pathspec::init::Error> {
+ Pathspec::new(self, patterns, inherit_ignore_case, || {
+ self.attributes_only(index, attributes_source)
+ .map(AttributeStack::detach)
+ .map_err(Into::into)
+ })
+ }
+
+ /// Return default settings that are required when [parsing pathspecs](gix_pathspec::parse()) by hand.
+ ///
+ /// These are stemming from environment variables which have been converted to [config settings](crate::config::tree::gitoxide::Pathspec),
+ /// which now serve as authority for configuration.
+ pub fn pathspec_defaults(&self) -> Result<gix_pathspec::Defaults, gix_pathspec::defaults::from_environment::Error> {
+ self.config.pathspec_defaults()
+ }
+
+ /// Similar to [Self::pathspec_defaults()], but will automatically configure the returned defaults to match case-insensitively if the underlying
+ /// filesystem is also configured to be case-insensitive according to `core.ignoreCase`, and `inherit_ignore_case` is `true`.
+ pub fn pathspec_defaults_inherit_ignore_case(
+ &self,
+ inherit_ignore_case: bool,
+ ) -> Result<gix_pathspec::Defaults, crate::repository::pathspec_defaults_ignore_case::Error> {
+ let mut defaults = self.config.pathspec_defaults()?;
+ if inherit_ignore_case
+ && self
+ .config
+ .fs_capabilities()
+ .with_lenient_default(self.config.lenient_config)?
+ .ignore_case
+ {
+ defaults.signature |= MagicSignature::ICASE;
+ }
+ Ok(defaults)
+ }
+}
diff --git a/vendor/gix/src/repository/reference.rs b/vendor/gix/src/repository/reference.rs
index e5a8aadcb..5a14c60b5 100644
--- a/vendor/gix/src/repository/reference.rs
+++ b/vendor/gix/src/repository/reference.rs
@@ -1,6 +1,7 @@
use std::convert::TryInto;
use gix_hash::ObjectId;
+use gix_macros::momo;
use gix_ref::{
transaction::{Change, LogChange, PreviousValue, RefEdit, RefLog},
FullName, PartialNameRef, Target,
@@ -14,6 +15,7 @@ impl crate::Repository {
///
/// It will be created with `constraint` which is most commonly to [only create it][PreviousValue::MustNotExist]
/// or to [force overwriting a possibly existing tag](PreviousValue::Any).
+ #[momo]
pub fn tag_reference(
&self,
name: impl AsRef<str>,
@@ -60,10 +62,10 @@ impl crate::Repository {
pub fn set_namespace<'a, Name, E>(
&mut self,
namespace: Name,
- ) -> Result<Option<gix_ref::Namespace>, gix_validate::refname::Error>
+ ) -> Result<Option<gix_ref::Namespace>, gix_validate::reference::name::Error>
where
Name: TryInto<&'a PartialNameRef, Error = E>,
- gix_validate::refname::Error: From<E>,
+ gix_validate::reference::name::Error: From<E>,
{
let namespace = gix_ref::namespace::expand(namespace)?;
Ok(self.refs.namespace.replace(namespace))
@@ -85,14 +87,27 @@ impl crate::Repository {
Name: TryInto<FullName, Error = E>,
gix_validate::reference::name::Error: From<E>,
{
- let name = name.try_into().map_err(gix_validate::reference::name::Error::from)?;
- let id = target.into();
+ self.reference_inner(
+ name.try_into().map_err(gix_validate::reference::name::Error::from)?,
+ target.into(),
+ constraint,
+ log_message.into(),
+ )
+ }
+
+ fn reference_inner(
+ &self,
+ name: FullName,
+ id: ObjectId,
+ constraint: PreviousValue,
+ log_message: BString,
+ ) -> Result<Reference<'_>, reference::edit::Error> {
let mut edits = self.edit_reference(RefEdit {
change: Change::Update {
log: LogChange {
mode: RefLog::AndReference,
force_create_reflog: false,
- message: log_message.into(),
+ message: log_message,
},
expected: constraint,
new: Target::Peeled(id),
@@ -124,7 +139,7 @@ impl crate::Repository {
/// Edit one or more references as described by their `edits`.
/// Note that one can set the committer name for use in the ref-log by temporarily
- /// [overriding the gix-config][crate::Repository::config_snapshot_mut()].
+ /// [overriding the git-config][crate::Repository::config_snapshot_mut()].
///
/// Returns all reference edits, which might be more than where provided due the splitting of symbolic references, and
/// whose previous (_old_) values are the ones seen on in storage after the reference was locked.
@@ -180,7 +195,7 @@ impl crate::Repository {
/// The difference to [`head_ref()`][Self::head_ref()] is that the latter requires the reference to exist,
/// whereas here we merely return a the name of the possibly unborn reference.
pub fn head_name(&self) -> Result<Option<FullName>, reference::find::existing::Error> {
- Ok(self.head()?.referent_name().map(|n| n.to_owned()))
+ Ok(self.head()?.referent_name().map(std::borrow::ToOwned::to_owned))
}
/// Return the reference that `HEAD` points to, or `None` if the head is detached or unborn.
diff --git a/vendor/gix/src/repository/remote.rs b/vendor/gix/src/repository/remote.rs
index 74ebbaea0..be0845178 100644
--- a/vendor/gix/src/repository/remote.rs
+++ b/vendor/gix/src/repository/remote.rs
@@ -28,7 +28,8 @@ impl crate::Repository {
Remote::from_fetch_url(url, false, self)
}
- /// Find the remote with the given `name_or_url` or report an error, similar to [`try_find_remote(…)`][Self::try_find_remote()].
+ /// Find the configured remote with the given `name_or_url` or report an error,
+ /// similar to [`try_find_remote(…)`][Self::try_find_remote()].
///
/// Note that we will obtain remotes only if we deem them [trustworthy][crate::open::Options::filter_config_section()].
pub fn find_remote<'a>(&self, name_or_url: impl Into<&'a BStr>) -> Result<Remote<'_>, find::existing::Error> {
@@ -42,7 +43,7 @@ impl crate::Repository {
/// Find the default remote as configured, or `None` if no such configuration could be found.
///
- /// See [`remote_default_name()`][Self::remote_default_name()] for more information on the `direction` parameter.
+ /// See [`remote_default_name()`](Self::remote_default_name()) for more information on the `direction` parameter.
pub fn find_default_remote(
&self,
direction: remote::Direction,
@@ -51,8 +52,8 @@ impl crate::Repository {
.map(|name| self.find_remote(name.as_ref()))
}
- /// Find the remote with the given `name_or_url` or return `None` if it doesn't exist, for the purpose of fetching or pushing
- /// data to a remote.
+ /// Find the configured remote with the given `name_or_url` or return `None` if it doesn't exist,
+ /// for the purpose of fetching or pushing data.
///
/// There are various error kinds related to partial information or incorrectly formatted URLs or ref-specs.
/// Also note that the created `Remote` may have neither fetch nor push ref-specs set at all.
@@ -62,7 +63,36 @@ impl crate::Repository {
///
/// We will only include information if we deem it [trustworthy][crate::open::Options::filter_config_section()].
pub fn try_find_remote<'a>(&self, name_or_url: impl Into<&'a BStr>) -> Option<Result<Remote<'_>, find::Error>> {
- self.try_find_remote_inner(name_or_url, true)
+ self.try_find_remote_inner(name_or_url.into(), true)
+ }
+
+ /// This method emulate what `git fetch <remote>` does in order to obtain a remote to fetch from.
+ ///
+ /// As such, with `name_or_url` being `Some`, it will:
+ ///
+ /// * use `name_or_url` verbatim if it is a URL, creating a new remote in memory as needed.
+ /// * find the named remote if `name_or_url` is a remote name
+ ///
+ /// If `name_or_url` is `None`:
+ ///
+ /// * use the current `HEAD` branch to find a configured remote
+ /// * fall back to either a generally configured remote or the only configured remote.
+ ///
+ /// Fail if no remote could be found despite all of the above.
+ pub fn find_fetch_remote(&self, name_or_url: Option<&BStr>) -> Result<Remote<'_>, find::for_fetch::Error> {
+ Ok(match name_or_url {
+ Some(name) => match self.try_find_remote(name).and_then(Result::ok) {
+ Some(remote) => remote,
+ None => self.remote_at(gix_url::parse(name)?)?,
+ },
+ None => self
+ .head()?
+ .into_remote(remote::Direction::Fetch)
+ .transpose()?
+ .map(Ok)
+ .or_else(|| self.find_default_remote(remote::Direction::Fetch))
+ .ok_or_else(|| find::for_fetch::Error::ExactlyOneRemoteNotAvailable)??,
+ })
}
/// Similar to [`try_find_remote()`][Self::try_find_remote()], but removes a failure mode if rewritten URLs turn out to be invalid
@@ -72,7 +102,7 @@ impl crate::Repository {
&self,
name_or_url: impl Into<&'a BStr>,
) -> Option<Result<Remote<'_>, find::Error>> {
- self.try_find_remote_inner(name_or_url, false)
+ self.try_find_remote_inner(name_or_url.into(), false)
}
fn try_find_remote_inner<'a>(
diff --git a/vendor/gix/src/repository/revision.rs b/vendor/gix/src/repository/revision.rs
index 3018c2be8..bb9b56d57 100644
--- a/vendor/gix/src/repository/revision.rs
+++ b/vendor/gix/src/repository/revision.rs
@@ -1,4 +1,5 @@
use crate::{bstr::BStr, revision, Id};
+use gix_macros::momo;
/// Methods for resolving revisions by spec or working with the commit graph.
impl crate::Repository {
@@ -8,6 +9,8 @@ impl crate::Repository {
///
/// - `@` actually stands for `HEAD`, whereas `git` resolves it to the object pointed to by `HEAD` without making the
/// `HEAD` ref available for lookups.
+ #[doc(alias = "revparse", alias = "git2")]
+ #[momo]
pub fn rev_parse<'a>(&self, spec: impl Into<&'a BStr>) -> Result<revision::Spec<'_>, revision::spec::parse::Error> {
revision::Spec::from_bstr(
spec,
@@ -20,6 +23,7 @@ impl crate::Repository {
}
/// Parse a revision specification and return single object id as represented by this instance.
+ #[doc(alias = "revparse_single", alias = "git2")]
pub fn rev_parse_single<'repo, 'a>(
&'repo self,
spec: impl Into<&'a BStr>,
@@ -33,6 +37,7 @@ impl crate::Repository {
/// Create the baseline for a revision walk by initializing it with the `tips` to start iterating on.
///
/// It can be configured further before starting the actual walk.
+ #[doc(alias = "revwalk", alias = "git2")]
pub fn rev_walk(
&self,
tips: impl IntoIterator<Item = impl Into<gix_hash::ObjectId>>,
diff --git a/vendor/gix/src/repository/submodule.rs b/vendor/gix/src/repository/submodule.rs
new file mode 100644
index 000000000..a605bfbd3
--- /dev/null
+++ b/vendor/gix/src/repository/submodule.rs
@@ -0,0 +1,96 @@
+use std::rc::Rc;
+
+use crate::{submodule, Repository};
+
+impl Repository {
+ /// Open the `.gitmodules` file as present in the worktree, or return `None` if no such file is available.
+ /// Note that git configuration is also contributing to the result based on the current snapshot.
+ ///
+ /// Note that his method will not look in other places, like the index or the `HEAD` tree.
+ // TODO(submodule): make it use an updated snapshot instead once we have `config()`.
+ pub fn open_modules_file(&self) -> Result<Option<gix_submodule::File>, submodule::open_modules_file::Error> {
+ let path = match self.modules_path() {
+ Some(path) => path,
+ None => return Ok(None),
+ };
+ let buf = match std::fs::read(&path) {
+ Ok(buf) => buf,
+ Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
+ Err(err) => return Err(err.into()),
+ };
+
+ Ok(Some(gix_submodule::File::from_bytes(
+ &buf,
+ path,
+ &self.config.resolved,
+ )?))
+ }
+
+ /// Return a shared [`.gitmodules` file](crate::submodule::File) which is updated automatically if the in-memory snapshot
+ /// has become stale as the underlying file on disk has changed. The snapshot based on the file on disk is shared across all
+ /// clones of this repository.
+ ///
+ /// If a file on disk isn't present, we will try to load it from the index, and finally from the current tree.
+ /// In the latter two cases, the result will not be cached in this repository instance as we can't detect freshness anymore,
+ /// so time this method is called a new [modules file](submodule::ModulesSnapshot) will be created.
+ ///
+ /// Note that git configuration is also contributing to the result based on the current snapshot.
+ ///
+ // TODO(submodule): make it use an updated snapshot instead once we have `config()`.
+ pub fn modules(&self) -> Result<Option<submodule::ModulesSnapshot>, submodule::modules::Error> {
+ match self.modules.recent_snapshot(
+ || {
+ self.modules_path()
+ .and_then(|path| path.metadata().and_then(|m| m.modified()).ok())
+ },
+ || self.open_modules_file(),
+ )? {
+ Some(m) => Ok(Some(m)),
+ None => {
+ let id = match self.try_index()?.and_then(|index| {
+ index
+ .entry_by_path(submodule::MODULES_FILE.into())
+ .map(|entry| entry.id)
+ }) {
+ Some(id) => id,
+ None => match self
+ .head_commit()?
+ .tree()?
+ .find_entry(submodule::MODULES_FILE)
+ .map(|entry| entry.inner.oid)
+ {
+ Some(id) => id.to_owned(),
+ None => return Ok(None),
+ },
+ };
+ Ok(Some(gix_features::threading::OwnShared::new(
+ gix_submodule::File::from_bytes(&self.find_object(id)?.data, None, &self.config.resolved)
+ .map_err(submodule::open_modules_file::Error::from)?
+ .into(),
+ )))
+ }
+ }
+ }
+
+ /// Return the list of available submodules, or `None` if there is no submodule configuration.
+ #[doc(alias = "git2")]
+ pub fn submodules(&self) -> Result<Option<impl Iterator<Item = crate::Submodule<'_>>>, submodule::modules::Error> {
+ let modules = match self.modules()? {
+ None => return Ok(None),
+ Some(m) => m,
+ };
+ let shared_state = Rc::new(submodule::SharedState::new(self, modules));
+ Ok(Some(
+ shared_state
+ .modules
+ .names()
+ .map(ToOwned::to_owned)
+ .collect::<Vec<_>>()
+ .into_iter()
+ .map(move |name| crate::Submodule {
+ state: shared_state.clone(),
+ name,
+ }),
+ ))
+ }
+}
diff --git a/vendor/gix/src/repository/worktree.rs b/vendor/gix/src/repository/worktree.rs
index f522a3f18..cc6f0bf73 100644
--- a/vendor/gix/src/repository/worktree.rs
+++ b/vendor/gix/src/repository/worktree.rs
@@ -1,4 +1,4 @@
-use crate::{config::cache::util::ApplyLeniencyDefault, worktree, Worktree};
+use crate::{worktree, Worktree};
/// Interact with individual worktrees and their information.
impl crate::Repository {
@@ -37,7 +37,8 @@ impl crate::Repository {
/// Return the currently set worktree if there is one, acting as platform providing a validated worktree base path.
///
/// Note that there would be `None` if this repository is `bare` and the parent [`Repository`][crate::Repository] was instantiated without
- /// registered worktree in the current working dir.
+ /// registered worktree in the current working dir, even if no `.git` file or directory exists.
+ /// It's merely based on configuration, see [Worktree::dot_git_exists()] for a way to perform more validation.
pub fn worktree(&self) -> Option<Worktree<'_>> {
self.work_dir().map(|path| Worktree { parent: self, path })
}
@@ -50,57 +51,95 @@ impl crate::Repository {
self.config.is_bare && self.work_dir().is_none()
}
- /// Open a new copy of the index file and decode it entirely.
+ /// If `id` points to a tree, produce a stream that yields one worktree entry after the other. The index of the tree at `id`
+ /// is returned as well as it is an intermediate byproduct that might be useful to callers.
///
- /// It will use the `index.threads` configuration key to learn how many threads to use.
- /// Note that it may fail if there is no index.
- pub fn open_index(&self) -> Result<gix_index::File, worktree::open_index::Error> {
- let thread_limit = self
- .config
- .resolved
- .string("index", None, "threads")
- .map(|value| crate::config::tree::Index::THREADS.try_into_index_threads(value))
- .transpose()
- .with_lenient_default(self.config.lenient_config)?;
- gix_index::File::at(
- self.index_path(),
- self.object_hash(),
- gix_index::decode::Options {
- thread_limit,
- min_extension_block_in_bytes_for_threading: 0,
- expected_checksum: None,
+ /// The entries will look exactly like they would if one would check them out, with filters applied.
+ /// The `export-ignore` attribute is used to skip blobs or directories to which it applies.
+ #[cfg(feature = "worktree-stream")]
+ #[gix_macros::momo]
+ pub fn worktree_stream(
+ &self,
+ id: impl Into<gix_hash::ObjectId>,
+ ) -> Result<(gix_worktree_stream::Stream, gix_index::File), crate::repository::worktree_stream::Error> {
+ use gix_odb::{FindExt, HeaderExt};
+ let id = id.into();
+ let header = self.objects.header(id)?;
+ if !header.kind().is_tree() {
+ return Err(crate::repository::worktree_stream::Error::NotATree {
+ id,
+ actual: header.kind(),
+ });
+ }
+
+ // TODO(perf): potential performance improvements could be to use the index at `HEAD` if possible (`index_from_head_tree…()`)
+ // TODO(perf): when loading a non-HEAD tree, we effectively traverse the tree twice. This is usually fast though, and sharing
+ // an object cache between the copies of the ODB handles isn't trivial and needs a lock.
+ let index = self.index_from_tree(&id)?;
+ let mut cache = self
+ .attributes_only(&index, gix_worktree::stack::state::attributes::Source::IdMapping)?
+ .detach();
+ let pipeline =
+ gix_filter::Pipeline::new(cache.attributes_collection(), crate::filter::Pipeline::options(self)?);
+ let objects = self.objects.clone().into_arc().expect("TBD error handling");
+ let stream = gix_worktree_stream::from_tree(
+ id,
+ {
+ let objects = objects.clone();
+ move |id, buf| objects.find(id, buf)
+ },
+ pipeline,
+ move |path, mode, attrs| -> std::io::Result<()> {
+ let entry = cache.at_entry(path, Some(mode.is_tree()), |id, buf| objects.find_blob(id, buf))?;
+ entry.matching_attributes(attrs);
+ Ok(())
},
- )
- .map_err(Into::into)
+ );
+ Ok((stream, index))
}
- /// Return a shared worktree index which is updated automatically if the in-memory snapshot has become stale as the underlying file
- /// on disk has changed.
+ /// Produce an archive from the `stream` and write it to `out` according to `options`.
+ /// Use `blob` to provide progress for each entry written to `out`, and note that it should already be initialized to the amount
+ /// of expected entries, with `should_interrupt` being queried between each entry to abort if needed, and on each write to `out`.
+ ///
+ /// ### Performance
+ ///
+ /// Be sure that `out` is able to handle a lot of write calls. Otherwise wrap it in a [`BufWriter`][std::io::BufWriter].
///
- /// The index file is shared across all clones of this repository.
- pub fn index(&self) -> Result<worktree::Index, worktree::open_index::Error> {
- self.index
- .recent_snapshot(
- || self.index_path().metadata().and_then(|m| m.modified()).ok(),
- || {
- self.open_index().map(Some).or_else(|err| match err {
- worktree::open_index::Error::IndexFile(gix_index::file::init::Error::Io(err))
- if err.kind() == std::io::ErrorKind::NotFound =>
- {
- Ok(None)
- }
- err => Err(err),
- })
- },
- )
- .and_then(|opt| match opt {
- Some(index) => Ok(index),
- None => Err(worktree::open_index::Error::IndexFile(
- gix_index::file::init::Error::Io(std::io::Error::new(
- std::io::ErrorKind::NotFound,
- format!("Could not find index file at {:?} for opening.", self.index_path()),
- )),
- )),
- })
+ /// ### Additional progress and fine-grained interrupt handling
+ ///
+ /// For additional progress reporting, wrap `out` into a writer that counts throughput on each write.
+ /// This can also be used to react to interrupts on each write, instead of only for each entry.
+ #[cfg(feature = "worktree-archive")]
+ pub fn worktree_archive(
+ &self,
+ mut stream: gix_worktree_stream::Stream,
+ out: impl std::io::Write + std::io::Seek,
+ blobs: impl gix_features::progress::Count,
+ should_interrupt: &std::sync::atomic::AtomicBool,
+ options: gix_archive::Options,
+ ) -> Result<(), crate::repository::worktree_archive::Error> {
+ let mut out = gix_features::interrupt::Write {
+ inner: out,
+ should_interrupt,
+ };
+ if options.format == gix_archive::Format::InternalTransientNonPersistable {
+ std::io::copy(&mut stream.into_read(), &mut out)?;
+ return Ok(());
+ }
+ gix_archive::write_stream_seek(
+ &mut stream,
+ |stream| {
+ if should_interrupt.load(std::sync::atomic::Ordering::Relaxed) {
+ return Err(std::io::Error::new(std::io::ErrorKind::Other, "Cancelled by user").into());
+ }
+ let res = stream.next_entry();
+ blobs.inc();
+ res
+ },
+ out,
+ options,
+ )?;
+ Ok(())
}
}
diff --git a/vendor/gix/src/revision/mod.rs b/vendor/gix/src/revision/mod.rs
index 4b11a8766..3de528ecd 100644
--- a/vendor/gix/src/revision/mod.rs
+++ b/vendor/gix/src/revision/mod.rs
@@ -2,6 +2,7 @@
//!
//! This module provides utilities to walk graphs of revisions and specify revisions and ranges of revisions.
+#[cfg(feature = "revision")]
pub use gix_revision as plumbing;
///
@@ -9,6 +10,7 @@ pub mod walk;
pub use walk::iter::Walk;
///
+#[cfg(feature = "revision")]
pub mod spec;
/// The specification of a revision as parsed from a revision specification like `HEAD@{1}` or `v1.2.3...main`.
@@ -17,6 +19,7 @@ pub mod spec;
/// See the [official git documentation](https://git-scm.com/docs/git-rev-parse#_specifying_revisions) for reference on how
/// to specify revisions and revision ranges.
#[derive(Clone, Debug)]
+#[cfg(feature = "revision")]
pub struct Spec<'repo> {
pub(crate) inner: gix_revision::Spec,
/// The first name of a reference as seen while parsing a `RevSpec`, for completeness.
diff --git a/vendor/gix/src/revision/spec/parse/delegate/mod.rs b/vendor/gix/src/revision/spec/parse/delegate/mod.rs
index 78e4ab9ee..eaf7f5fd6 100644
--- a/vendor/gix/src/revision/spec/parse/delegate/mod.rs
+++ b/vendor/gix/src/revision/spec/parse/delegate/mod.rs
@@ -1,10 +1,7 @@
use std::collections::HashSet;
use gix_hash::ObjectId;
-use gix_revision::spec::{
- parse,
- parse::delegate::{self},
-};
+use gix_revision::spec::{parse, parse::delegate};
use smallvec::SmallVec;
use super::{Delegate, Error, ObjectKindHint};
@@ -209,7 +206,7 @@ impl<'repo> Delegate<'repo> {
.attach(repo)
.peel_to_id_in_place()
.ok()
- .map(|id| id.detach())
+ .map(crate::Id::detach)
}) {
obj_opt.get_or_insert_with(HashSet::default).insert(id);
};
diff --git a/vendor/gix/src/revision/spec/parse/delegate/navigate.rs b/vendor/gix/src/revision/spec/parse/delegate/navigate.rs
index f6e085368..51feb1d76 100644
--- a/vendor/gix/src/revision/spec/parse/delegate/navigate.rs
+++ b/vendor/gix/src/revision/spec/parse/delegate/navigate.rs
@@ -15,6 +15,7 @@ use crate::{
delegate::{handle_errors_and_replacements, peel, Replacements},
Delegate, Error,
},
+ Object,
};
impl<'repo> delegate::Navigate for Delegate<'repo> {
@@ -62,10 +63,9 @@ impl<'repo> delegate::Navigate for Delegate<'repo> {
.all()
.expect("cannot fail without sorting")
.skip(num)
- .filter_map(Result::ok)
- .next()
+ .find_map(Result::ok)
{
- Some(id) => replacements.push((*obj, id.detach())),
+ Some(commit) => replacements.push((*obj, commit.id)),
None => errors.push((
*obj,
Error::AncestorOutOfRange {
@@ -123,9 +123,9 @@ impl<'repo> delegate::Navigate for Delegate<'repo> {
if path.is_empty() {
return Ok(tree_id);
}
- let tree = repo.find_object(tree_id)?.into_tree();
+ let mut tree = repo.find_object(tree_id)?.into_tree();
let entry =
- tree.lookup_entry_by_path(gix_path::from_bstr(path))?
+ tree.peel_to_entry_by_path(gix_path::from_bstr(path))?
.ok_or_else(|| Error::PathNotFound {
path: path.into(),
object: obj.attach(repo).shorten_or_id(),
@@ -142,7 +142,7 @@ impl<'repo> delegate::Navigate for Delegate<'repo> {
}
PeelTo::RecursiveTagObject => {
for oid in objs.iter() {
- match oid.attach(repo).object().and_then(|obj| obj.peel_tags_to_end()) {
+ match oid.attach(repo).object().and_then(Object::peel_tags_to_end) {
Ok(obj) => replacements.push((*oid, obj.id)),
Err(err) => errors.push((*oid, err.into())),
}
@@ -157,9 +157,9 @@ impl<'repo> delegate::Navigate for Delegate<'repo> {
self.unset_disambiguate_call();
self.follow_refs_to_objects_if_needed()?;
- #[cfg(not(feature = "regex"))]
+ #[cfg(not(feature = "revparse-regex"))]
let matches = |message: &BStr| -> bool { message.contains_str(regex) ^ negated };
- #[cfg(feature = "regex")]
+ #[cfg(feature = "revparse-regex")]
let matches = match regex::bytes::Regex::new(regex.to_str_lossy().as_ref()) {
Ok(compiled) => {
let needs_regex = regex::escape(compiled.as_str()) != regex;
@@ -193,8 +193,8 @@ impl<'repo> delegate::Navigate for Delegate<'repo> {
let mut matched = false;
let mut count = 0;
let commits = iter.map(|res| {
- res.map_err(Error::from).and_then(|commit_id| {
- commit_id.object().map_err(Error::from).map(|obj| obj.into_commit())
+ res.map_err(Error::from).and_then(|commit| {
+ commit.id().object().map_err(Error::from).map(Object::into_commit)
})
});
for commit in commits {
@@ -250,8 +250,8 @@ impl<'repo> delegate::Navigate for Delegate<'repo> {
let mut matched = false;
let mut count = 0;
let commits = iter.map(|res| {
- res.map_err(Error::from).and_then(|commit_id| {
- commit_id.object().map_err(Error::from).map(|obj| obj.into_commit())
+ res.map_err(Error::from).and_then(|commit| {
+ commit.id().object().map_err(Error::from).map(Object::into_commit)
})
});
for commit in commits {
diff --git a/vendor/gix/src/revision/spec/parse/delegate/revision.rs b/vendor/gix/src/revision/spec/parse/delegate/revision.rs
index 7ea691a28..2b84dda23 100644
--- a/vendor/gix/src/revision/spec/parse/delegate/revision.rs
+++ b/vendor/gix/src/revision/spec/parse/delegate/revision.rs
@@ -114,7 +114,7 @@ impl<'repo> delegate::Revision for Delegate<'repo> {
ReflogLookup::Entry(no) => {
let r = match &mut self.refs[self.idx] {
Some(r) => r.clone().attach(self.repo),
- val @ None => match self.repo.head().map(|head| head.try_into_referent()) {
+ val @ None => match self.repo.head().map(crate::Head::try_into_referent) {
Ok(Some(r)) => {
*val = Some(r.clone().detach());
r
@@ -139,7 +139,7 @@ impl<'repo> delegate::Revision for Delegate<'repo> {
Some(())
}
None => {
- let available = platform.rev().ok().flatten().map_or(0, |it| it.count());
+ let available = platform.rev().ok().flatten().map_or(0, Iterator::count);
self.err.push(Error::RefLogEntryOutOfRange {
reference: r.detach(),
desired: no,
@@ -190,7 +190,7 @@ impl<'repo> delegate::Revision for Delegate<'repo> {
Ok(Some((ref_name, id))) => {
let id = match self.repo.find_reference(ref_name.as_bstr()) {
Ok(mut r) => {
- let id = r.peel_to_id_in_place().map(|id| id.detach()).unwrap_or(id);
+ let id = r.peel_to_id_in_place().map(crate::Id::detach).unwrap_or(id);
self.refs[self.idx] = Some(r.detach());
id
}
@@ -203,7 +203,7 @@ impl<'repo> delegate::Revision for Delegate<'repo> {
self.err.push(Error::PriorCheckoutOutOfRange {
desired: branch_no,
available: prior_checkouts_iter(&mut head.log_iter())
- .map(|it| it.count())
+ .map(Iterator::count)
.unwrap_or(0),
});
None
diff --git a/vendor/gix/src/revision/spec/parse/mod.rs b/vendor/gix/src/revision/spec/parse/mod.rs
index f69ecc4af..950dfa004 100644
--- a/vendor/gix/src/revision/spec/parse/mod.rs
+++ b/vendor/gix/src/revision/spec/parse/mod.rs
@@ -1,6 +1,7 @@
use std::collections::HashSet;
use gix_hash::ObjectId;
+use gix_macros::momo;
use gix_revision::spec::parse;
use crate::{bstr::BStr, revision::Spec, Repository};
@@ -30,6 +31,7 @@ impl<'repo> Spec<'repo> {
/// Parse `spec` and use information from `repo` to resolve it, using `opts` to learn how to deal with ambiguity.
///
/// Note that it's easier and to use [`repo.rev_parse()`][Repository::rev_parse()] instead.
+ #[momo]
pub fn from_bstr<'a>(spec: impl Into<&'a BStr>, repo: &'repo Repository, opts: Options) -> Result<Self, Error> {
let mut delegate = Delegate::new(repo, opts);
match gix_revision::spec::parse(spec.into(), &mut delegate) {
diff --git a/vendor/gix/src/revision/spec/parse/types.rs b/vendor/gix/src/revision/spec/parse/types.rs
index d852c297e..5dc626eee 100644
--- a/vendor/gix/src/revision/spec/parse/types.rs
+++ b/vendor/gix/src/revision/spec/parse/types.rs
@@ -100,15 +100,15 @@ pub enum Error {
RevWalkIterInit(#[from] crate::reference::iter::init::Error),
#[error(transparent)]
RevWalkAllReferences(#[from] gix_ref::packed::buffer::open::Error),
- #[cfg(feature = "regex")]
+ #[cfg(feature = "revparse-regex")]
#[error(transparent)]
InvalidRegex(#[from] regex::Error),
#[cfg_attr(
- feature = "regex",
+ feature = "revparse-regex",
error("None of {commits_searched} commits from {oid} matched regex {regex:?}")
)]
#[cfg_attr(
- not(feature = "regex"),
+ not(feature = "revparse-regex"),
error("None of {commits_searched} commits from {oid} matched text {regex:?}")
)]
NoRegexMatch {
@@ -117,11 +117,11 @@ pub enum Error {
commits_searched: usize,
},
#[cfg_attr(
- feature = "regex",
+ feature = "revparse-regex",
error("None of {commits_searched} commits reached from all references matched regex {regex:?}")
)]
#[cfg_attr(
- not(feature = "regex"),
+ not(feature = "revparse-regex"),
error("None of {commits_searched} commits reached from all references matched text {regex:?}")
)]
NoRegexMatchAllRefs { regex: BString, commits_searched: usize },
diff --git a/vendor/gix/src/revision/walk.rs b/vendor/gix/src/revision/walk.rs
index 9c545d0d4..5e76ad898 100644
--- a/vendor/gix/src/revision/walk.rs
+++ b/vendor/gix/src/revision/walk.rs
@@ -1,7 +1,7 @@
use gix_hash::ObjectId;
use gix_odb::FindExt;
-use crate::{revision, Repository};
+use crate::{ext::ObjectIdExt, revision, Repository};
/// The error returned by [`Platform::all()`].
#[derive(Debug, thiserror::Error)]
@@ -11,15 +11,90 @@ pub enum Error {
AncestorIter(#[from] gix_traverse::commit::ancestors::Error),
#[error(transparent)]
ShallowCommits(#[from] crate::shallow::open::Error),
+ #[error(transparent)]
+ ConfigBoolean(#[from] crate::config::boolean::Error),
+}
+
+/// Information about a commit that we obtained naturally as part of the iteration.
+#[derive(Debug, Clone)]
+pub struct Info<'repo> {
+ /// The detached id of the commit.
+ pub id: gix_hash::ObjectId,
+ /// All parent ids we have encountered. Note that these will be at most one if [`Parents::First`][gix_traverse::commit::Parents::First] is enabled.
+ pub parent_ids: gix_traverse::commit::ParentIds,
+ /// The time at which the commit was created. It's only `Some(_)` if sorting is not [`Sorting::BreadthFirst`][gix_traverse::commit::Sorting::BreadthFirst],
+ /// as the walk needs to require the commit-date.
+ pub commit_time: Option<gix_date::SecondsSinceUnixEpoch>,
+
+ repo: &'repo Repository,
+}
+
+/// Access
+impl<'repo> Info<'repo> {
+ /// Provide an attached version of our [`id`][Info::id] field.
+ pub fn id(&self) -> crate::Id<'repo> {
+ self.id.attach(self.repo)
+ }
+
+ /// Read the whole object from the object database.
+ ///
+ /// Note that this is an expensive operation which shouldn't be performed unless one needs more than parent ids
+ /// and commit time.
+ pub fn object(&self) -> Result<crate::Commit<'repo>, crate::object::find::existing::Error> {
+ Ok(self.id().object()?.into_commit())
+ }
+
+ /// Provide an iterator yielding attached versions of our [`parent_ids`][Info::parent_ids] field.
+ pub fn parent_ids(&self) -> impl Iterator<Item = crate::Id<'repo>> + '_ {
+ self.parent_ids.iter().map(|id| id.attach(self.repo))
+ }
+
+ /// Returns the commit-time of this commit.
+ ///
+ /// ### Panics
+ ///
+ /// If the iteration wasn't ordered by date.
+ pub fn commit_time(&self) -> gix_date::SecondsSinceUnixEpoch {
+ self.commit_time.expect("traversal involving date caused it to be set")
+ }
+}
+
+/// Initialization and detachment
+impl<'repo> Info<'repo> {
+ /// Create a new instance that represents `info`, but is attached to `repo` as well.
+ pub fn new(info: gix_traverse::commit::Info, repo: &'repo Repository) -> Self {
+ Info {
+ id: info.id,
+ parent_ids: info.parent_ids,
+ commit_time: info.commit_time,
+ repo,
+ }
+ }
+ /// Consume this instance and remove the reference to the underlying repository.
+ ///
+ /// This is useful for sending instances across threads, for example.
+ pub fn detach(self) -> gix_traverse::commit::Info {
+ gix_traverse::commit::Info {
+ id: self.id,
+ parent_ids: self.parent_ids,
+ commit_time: self.commit_time,
+ }
+ }
}
/// A platform to traverse the revision graph by adding starting points as well as points which shouldn't be crossed,
/// returned by [`Repository::rev_walk()`].
+///
+/// **Note that we automatically leverage the commitgraph data structure**, but if you know that additional information like
+/// author or commit messages will be required of *all* commits traversed here, it should be better to avoid trying to load it
+/// by [turning commit-graph support off][Platform::use_commit_graph()]. This certainly is a micro-optimization though.
pub struct Platform<'repo> {
pub(crate) repo: &'repo Repository,
pub(crate) tips: Vec<ObjectId>,
pub(crate) sorting: gix_traverse::commit::Sorting,
pub(crate) parents: gix_traverse::commit::Parents,
+ pub(crate) use_commit_graph: Option<bool>,
+ pub(crate) commit_graph: Option<gix_commitgraph::Graph>,
}
impl<'repo> Platform<'repo> {
@@ -29,13 +104,15 @@ impl<'repo> Platform<'repo> {
tips: tips.into_iter().map(Into::into).collect(),
sorting: Default::default(),
parents: Default::default(),
+ use_commit_graph: None,
+ commit_graph: None,
}
}
}
/// Create-time builder methods
impl<'repo> Platform<'repo> {
- /// Set the sort mode for commits to the given value. The default is to order by topology.
+ /// Set the sort mode for commits to the given value. The default is to order topologically breadth-first.
pub fn sorting(mut self, sorting: gix_traverse::commit::Sorting) -> Self {
self.sorting = sorting;
self
@@ -46,6 +123,26 @@ impl<'repo> Platform<'repo> {
self.parents = gix_traverse::commit::Parents::First;
self
}
+
+ /// Allow using the commitgraph, if present, if `toggle` is `true`, or disallow it with `false`. Set it to `None` to leave
+ /// control over this to the configuration of `core.commitGraph` (the default).
+ ///
+ /// Errors when loading the graph lead to falling back to the object database, it's treated as optional cache.
+ pub fn use_commit_graph(mut self, toggle: impl Into<Option<bool>>) -> Self {
+ self.use_commit_graph = toggle.into();
+ self
+ }
+
+ /// Set or unset the commit-graph to use for the iteration. This is useful if the caller wants to check if a commit-graph exists
+ /// and refer different implementations depending on the outcome.
+ ///
+ /// It interacts with [`use_commit_graph`][Platform::use_commit_graph()] as one would expect, but it's worth noting that if `None`,
+ /// with [`use_commit_graph`][Platform::use_commit_graph()] being `true`, a graph will still be used for iteration.
+ /// To turn the commit-graph off, call [`use_commit_graph(false)`][Platform::use_commit_graph()] instead.
+ pub fn with_commit_graph(mut self, graph: Option<gix_commitgraph::Graph>) -> Self {
+ self.commit_graph = graph;
+ self
+ }
}
/// Produce the iterator
@@ -63,6 +160,8 @@ impl<'repo> Platform<'repo> {
tips,
sorting,
parents,
+ use_commit_graph,
+ commit_graph,
} = self;
Ok(revision::Walk {
repo,
@@ -72,6 +171,8 @@ impl<'repo> Platform<'repo> {
gix_traverse::commit::ancestors::State::default(),
move |oid, buf| repo.objects.find_commit_iter(oid, buf),
{
+ // Note that specific shallow handling for commit-graphs isn't needed as these contain
+ // all information there is, and exclude shallow parents to be structurally consistent.
let shallow_commits = repo.shallow_commits()?;
let mut grafted_parents_to_skip = Vec::new();
let mut buf = Vec::new();
@@ -87,7 +188,7 @@ impl<'repo> Platform<'repo> {
return false;
};
if commits.binary_search(&id).is_ok() {
- if let Ok(commit) = repo.objects.find_commit_iter(id, &mut buf) {
+ if let Ok(commit) = repo.objects.find_commit_iter(&id, &mut buf) {
grafted_parents_to_skip.extend(commit.parent_ids());
grafted_parents_to_skip.sort();
}
@@ -100,7 +201,13 @@ impl<'repo> Platform<'repo> {
},
)
.sorting(sorting)?
- .parents(parents),
+ .parents(parents)
+ .commit_graph(
+ commit_graph.or(use_commit_graph
+ .map_or_else(|| self.repo.config.may_use_commit_graph(), Ok)?
+ .then(|| self.repo.commit_graph().ok())
+ .flatten()),
+ ),
),
})
}
@@ -116,20 +223,21 @@ impl<'repo> Platform<'repo> {
}
pub(crate) mod iter {
- use crate::{ext::ObjectIdExt, Id};
-
/// The iterator returned by [`crate::revision::walk::Platform::all()`].
pub struct Walk<'repo> {
pub(crate) repo: &'repo crate::Repository,
- pub(crate) inner:
- Box<dyn Iterator<Item = Result<gix_hash::ObjectId, gix_traverse::commit::ancestors::Error>> + 'repo>,
+ pub(crate) inner: Box<
+ dyn Iterator<Item = Result<gix_traverse::commit::Info, gix_traverse::commit::ancestors::Error>> + 'repo,
+ >,
}
impl<'repo> Iterator for Walk<'repo> {
- type Item = Result<Id<'repo>, gix_traverse::commit::ancestors::Error>;
+ type Item = Result<super::Info<'repo>, gix_traverse::commit::ancestors::Error>;
fn next(&mut self) -> Option<Self::Item> {
- self.inner.next().map(|res| res.map(|id| id.attach(self.repo)))
+ self.inner
+ .next()
+ .map(|res| res.map(|info| super::Info::new(info, self.repo)))
}
}
}
diff --git a/vendor/gix/src/submodule/errors.rs b/vendor/gix/src/submodule/errors.rs
new file mode 100644
index 000000000..4e41337de
--- /dev/null
+++ b/vendor/gix/src/submodule/errors.rs
@@ -0,0 +1,106 @@
+///
+pub mod open_modules_file {
+ /// The error returned by [Repository::open_modules_file()](crate::Repository::open_modules_file()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ Configuration(#[from] gix_config::parse::Error),
+ #[error("Could not read '.gitmodules' file")]
+ Io(#[from] std::io::Error),
+ }
+}
+
+///
+pub mod modules {
+ /// The error returned by [Repository::modules()](crate::Repository::modules()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ OpenModulesFile(#[from] crate::submodule::open_modules_file::Error),
+ #[error(transparent)]
+ OpenIndex(#[from] crate::worktree::open_index::Error),
+ #[error("Could not find the .gitmodules file by id in the object database")]
+ FindExistingBlob(#[from] crate::object::find::existing::Error),
+ #[error("Did not find commit in current HEAD to access its tree")]
+ FindHeadCommit(#[from] crate::reference::head_commit::Error),
+ #[error(transparent)]
+ TreeFromCommit(#[from] crate::object::commit::Error),
+ }
+}
+
+///
+pub mod is_active {
+ /// The error returned by [Submodule::is_active()](crate::Submodule::is_active()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ InitIsActivePlatform(#[from] gix_submodule::is_active_platform::Error),
+ #[error(transparent)]
+ QueryIsActive(#[from] gix_config::value::Error),
+ #[error(transparent)]
+ InitAttributes(#[from] crate::config::attribute_stack::Error),
+ #[error(transparent)]
+ InitPathspecDefaults(#[from] gix_pathspec::defaults::from_environment::Error),
+ #[error(transparent)]
+ ObtainIndex(#[from] crate::repository::index_or_load_from_head::Error),
+ }
+}
+
+///
+pub mod fetch_recurse {
+ /// The error returned by [Submodule::fetch_recurse()](crate::Submodule::fetch_recurse()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ ModuleBoolean(#[from] gix_submodule::config::Error),
+ #[error(transparent)]
+ ConfigurationFallback(#[from] crate::config::key::GenericErrorWithValue),
+ }
+}
+
+///
+pub mod open {
+ /// The error returned by [Submodule::open()](crate::Submodule::open()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ OpenRepository(#[from] crate::open::Error),
+ #[error(transparent)]
+ PathConfiguration(#[from] gix_submodule::config::path::Error),
+ }
+}
+
+///
+pub mod index_id {
+ /// The error returned by [Submodule::index_id()](crate::Submodule::index_id()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ PathConfiguration(#[from] gix_submodule::config::path::Error),
+ #[error(transparent)]
+ Index(#[from] crate::repository::index_or_load_from_head::Error),
+ }
+}
+
+///
+pub mod head_id {
+ /// The error returned by [Submodule::head_id()](crate::Submodule::head_id()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ HeadCommit(#[from] crate::reference::head_commit::Error),
+ #[error("Could not get tree of head commit")]
+ CommitTree(#[from] crate::object::commit::Error),
+ #[error("Could not peel tree to submodule path")]
+ PeelTree(#[from] crate::object::find::existing::Error),
+ #[error(transparent)]
+ PathConfiguration(#[from] gix_submodule::config::path::Error),
+ }
+}
diff --git a/vendor/gix/src/submodule/mod.rs b/vendor/gix/src/submodule/mod.rs
new file mode 100644
index 000000000..52c5938fc
--- /dev/null
+++ b/vendor/gix/src/submodule/mod.rs
@@ -0,0 +1,287 @@
+#![allow(clippy::result_large_err)]
+//! Submodule plumbing and abstractions
+//!
+use std::{
+ borrow::Cow,
+ cell::{Ref, RefCell, RefMut},
+ path::PathBuf,
+};
+
+use gix_odb::FindExt;
+pub use gix_submodule::*;
+
+use crate::{bstr::BStr, repository::IndexPersistedOrInMemory, Repository, Submodule};
+
+pub(crate) type ModulesFileStorage = gix_features::threading::OwnShared<gix_fs::SharedFileSnapshotMut<File>>;
+/// A lazily loaded and auto-updated worktree index.
+pub type ModulesSnapshot = gix_fs::SharedFileSnapshot<File>;
+
+/// The name of the file containing (sub) module information.
+pub(crate) const MODULES_FILE: &str = ".gitmodules";
+
+mod errors;
+pub use errors::*;
+
+/// A platform maintaining state needed to interact with submodules, created by [`Repository::submodules()].
+pub(crate) struct SharedState<'repo> {
+ pub(crate) repo: &'repo Repository,
+ pub(crate) modules: ModulesSnapshot,
+ is_active: RefCell<Option<IsActiveState>>,
+ index: RefCell<Option<IndexPersistedOrInMemory>>,
+}
+
+impl<'repo> SharedState<'repo> {
+ pub(crate) fn new(repo: &'repo Repository, modules: ModulesSnapshot) -> Self {
+ SharedState {
+ repo,
+ modules,
+ is_active: RefCell::new(None),
+ index: RefCell::new(None),
+ }
+ }
+
+ fn index(&self) -> Result<Ref<'_, IndexPersistedOrInMemory>, crate::repository::index_or_load_from_head::Error> {
+ {
+ let mut state = self.index.borrow_mut();
+ if state.is_none() {
+ *state = self.repo.index_or_load_from_head()?.into();
+ }
+ }
+ Ok(Ref::map(self.index.borrow(), |opt| {
+ opt.as_ref().expect("just initialized")
+ }))
+ }
+
+ fn active_state_mut(
+ &self,
+ ) -> Result<(RefMut<'_, IsActivePlatform>, RefMut<'_, gix_worktree::Stack>), is_active::Error> {
+ let mut state = self.is_active.borrow_mut();
+ if state.is_none() {
+ let platform = self
+ .modules
+ .is_active_platform(&self.repo.config.resolved, self.repo.config.pathspec_defaults()?)?;
+ let index = self.index()?;
+ let attributes = self
+ .repo
+ .attributes_only(
+ &index,
+ gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping
+ .adjust_for_bare(self.repo.is_bare()),
+ )?
+ .detach();
+ *state = Some(IsActiveState { platform, attributes });
+ }
+ Ok(RefMut::map_split(state, |opt| {
+ let state = opt.as_mut().expect("populated above");
+ (&mut state.platform, &mut state.attributes)
+ }))
+ }
+}
+
+struct IsActiveState {
+ platform: IsActivePlatform,
+ attributes: gix_worktree::Stack,
+}
+
+///Access
+impl<'repo> Submodule<'repo> {
+ /// Return the submodule's name.
+ pub fn name(&self) -> &BStr {
+ self.name.as_ref()
+ }
+ /// Return the path at which the submodule can be found, relative to the repository.
+ ///
+ /// For details, see [gix_submodule::File::path()].
+ pub fn path(&self) -> Result<Cow<'_, BStr>, config::path::Error> {
+ self.state.modules.path(self.name())
+ }
+
+ /// Return the url from which to clone or update the submodule.
+ pub fn url(&self) -> Result<gix_url::Url, config::url::Error> {
+ self.state.modules.url(self.name())
+ }
+
+ /// Return the `update` field from this submodule's configuration, if present, or `None`.
+ pub fn update(&self) -> Result<Option<config::Update>, config::update::Error> {
+ self.state.modules.update(self.name())
+ }
+
+ /// Return the `branch` field from this submodule's configuration, if present, or `None`.
+ pub fn branch(&self) -> Result<Option<config::Branch>, config::branch::Error> {
+ self.state.modules.branch(self.name())
+ }
+
+ /// Return the `fetchRecurseSubmodules` field from this submodule's configuration, or retrieve the value from `fetch.recurseSubmodules` if unset.
+ pub fn fetch_recurse(&self) -> Result<Option<config::FetchRecurse>, fetch_recurse::Error> {
+ Ok(match self.state.modules.fetch_recurse(self.name())? {
+ Some(val) => Some(val),
+ None => self
+ .state
+ .repo
+ .config
+ .resolved
+ .boolean_by_key("fetch.recurseSubmodules")
+ .map(|res| crate::config::tree::Fetch::RECURSE_SUBMODULES.try_into_recurse_submodules(res))
+ .transpose()?,
+ })
+ }
+
+ /// Return the `ignore` field from this submodule's configuration, if present, or `None`.
+ pub fn ignore(&self) -> Result<Option<config::Ignore>, config::Error> {
+ self.state.modules.ignore(self.name())
+ }
+
+ /// Return the `shallow` field from this submodule's configuration, if present, or `None`.
+ ///
+ /// If `true`, the submodule will be checked out with `depth = 1`. If unset, `false` is assumed.
+ pub fn shallow(&self) -> Result<Option<bool>, gix_config::value::Error> {
+ self.state.modules.shallow(self.name())
+ }
+
+ /// Returns true if this submodule is considered active and can thus participate in an operation.
+ ///
+ /// Please see the [plumbing crate documentation](gix_submodule::IsActivePlatform::is_active()) for details.
+ pub fn is_active(&self) -> Result<bool, is_active::Error> {
+ let (mut platform, mut attributes) = self.state.active_state_mut()?;
+ let is_active = platform.is_active(&self.state.repo.config.resolved, self.name.as_ref(), {
+ &mut |relative_path, case, is_dir, out| {
+ attributes
+ .set_case(case)
+ .at_entry(relative_path, Some(is_dir), |id, buf| {
+ self.state.repo.objects.find_blob(id, buf)
+ })
+ .map_or(false, |platform| platform.matching_attributes(out))
+ }
+ })?;
+ Ok(is_active)
+ }
+
+ /// Return the object id of the submodule as stored in the index of the superproject,
+ /// or `None` if it was deleted from the index.
+ ///
+ /// If `None`, but `Some()` when calling [`Self::head_id()`], then the submodule was just deleted but the change
+ /// wasn't yet committed. Note that `None` is also returned if the entry at the submodule path isn't a submodule.
+ /// If `Some()`, but `None` when calling [`Self::head_id()`], then the submodule was just added without having committed the change.
+ pub fn index_id(&self) -> Result<Option<gix_hash::ObjectId>, index_id::Error> {
+ let path = self.path()?;
+ Ok(self
+ .state
+ .index()?
+ .entry_by_path(&path)
+ .and_then(|entry| (entry.mode == gix_index::entry::Mode::COMMIT).then_some(entry.id)))
+ }
+
+ /// Return the object id of the submodule as stored in `HEAD^{tree}` of the superproject, or `None` if it wasn't yet committed.
+ ///
+ /// If `Some()`, but `None` when calling [`Self::index_id()`], then the submodule was just deleted but the change
+ /// wasn't yet committed. Note that `None` is also returned if the entry at the submodule path isn't a submodule.
+ /// If `None`, but `Some()` when calling [`Self::index_id()`], then the submodule was just added without having committed the change.
+ pub fn head_id(&self) -> Result<Option<gix_hash::ObjectId>, head_id::Error> {
+ let path = self.path()?;
+ Ok(self
+ .state
+ .repo
+ .head_commit()?
+ .tree()?
+ .peel_to_entry_by_path(gix_path::from_bstr(path.as_ref()))?
+ .and_then(|entry| (entry.mode() == gix_object::tree::EntryMode::Commit).then_some(entry.inner.oid)))
+ }
+
+ /// Return the path at which the repository of the submodule should be located.
+ ///
+ /// The directory might not exist yet.
+ pub fn git_dir(&self) -> PathBuf {
+ self.state
+ .repo
+ .common_dir()
+ .join("modules")
+ .join(gix_path::from_bstr(self.name()))
+ }
+
+ /// Return the path to the location at which the workdir would be checked out.
+ ///
+ /// Note that it may be a path relative to the repository if, for some reason, the parent directory
+ /// doesn't have a working dir set.
+ pub fn work_dir(&self) -> Result<PathBuf, config::path::Error> {
+ let worktree_git = gix_path::from_bstr(self.path()?);
+ Ok(match self.state.repo.work_dir() {
+ None => worktree_git.into_owned(),
+ Some(prefix) => prefix.join(worktree_git),
+ })
+ }
+
+ /// Return the path at which the repository of the submodule should be located, or the path inside of
+ /// the superproject's worktree where it actually *is* located if the submodule in the 'old-form', thus is a directory
+ /// inside of the superproject's work-tree.
+ ///
+ /// Note that 'old-form' paths returned aren't verified, i.e. the `.git` repository might be corrupt or otherwise
+ /// invalid - it's left to the caller to try to open it.
+ ///
+ /// Also note that the returned path may not actually exist.
+ pub fn git_dir_try_old_form(&self) -> Result<PathBuf, config::path::Error> {
+ let worktree_git = self.work_dir()?.join(gix_discover::DOT_GIT_DIR);
+ Ok(if worktree_git.is_dir() {
+ worktree_git
+ } else {
+ self.git_dir()
+ })
+ }
+
+ /// Query various parts of the submodule and assemble it into state information.
+ #[doc(alias = "status", alias = "git2")]
+ pub fn state(&self) -> Result<State, config::path::Error> {
+ let maybe_old_path = self.git_dir_try_old_form()?;
+ let git_dir = self.git_dir();
+ let worktree_git = self.work_dir()?.join(gix_discover::DOT_GIT_DIR);
+ let superproject_configuration = self
+ .state
+ .repo
+ .config
+ .resolved
+ .sections_by_name("submodule")
+ .into_iter()
+ .flatten()
+ .any(|section| section.header().subsection_name() == Some(self.name.as_ref()));
+ Ok(State {
+ repository_exists: maybe_old_path.is_dir(),
+ is_old_form: maybe_old_path != git_dir,
+ worktree_checkout: worktree_git.exists(),
+ superproject_configuration,
+ })
+ }
+
+ /// Open the submodule as repository, or `None` if the submodule wasn't initialized yet.
+ ///
+ /// More states can be derived here:
+ ///
+ /// * *initialized* - a repository exists, i.e. `Some(repo)` and the working tree is present.
+ /// * *uninitialized* - a repository does not exist, i.e. `None`
+ /// * *deinitialized* - a repository does exist, i.e. `Some(repo)`, but its working tree is empty.
+ ///
+ /// Also see the [state()](Self::state()) method for learning about the submodule.
+ /// The repository can also be used to learn about the submodule `HEAD`, i.e. where its working tree is at,
+ /// which may differ compared to the superproject's index or `HEAD` commit.
+ pub fn open(&self) -> Result<Option<Repository>, open::Error> {
+ match crate::open_opts(self.git_dir_try_old_form()?, self.state.repo.options.clone()) {
+ Ok(repo) => Ok(Some(repo)),
+ Err(crate::open::Error::NotARepository { .. }) => Ok(None),
+ Err(err) => Err(err.into()),
+ }
+ }
+}
+
+/// A summary of the state of all parts forming a submodule, which allows to answer various questions about it.
+///
+/// Note that expensive questions about its presence in the `HEAD` or the `index` are left to the caller.
+#[derive(Default, Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
+pub struct State {
+ /// if the submodule repository has been cloned.
+ pub repository_exists: bool,
+ /// if the submodule repository is located directly in the worktree of the superproject.
+ pub is_old_form: bool,
+ /// if the worktree is checked out.
+ pub worktree_checkout: bool,
+ /// If submodule configuration was found in the superproject's `.git/config` file.
+ /// Note that the presence of a single section is enough, independently of the actual values.
+ pub superproject_configuration: bool,
+}
diff --git a/vendor/gix/src/types.rs b/vendor/gix/src/types.rs
index cdb5f731d..0739cdd25 100644
--- a/vendor/gix/src/types.rs
+++ b/vendor/gix/src/types.rs
@@ -5,6 +5,7 @@ use gix_hash::ObjectId;
use crate::{head, remote};
/// A worktree checkout containing the files of the repository in consumable form.
+#[derive(Debug, Clone)]
pub struct Worktree<'repo> {
pub(crate) parent: &'repo Repository,
/// The root path of the checkout.
@@ -137,7 +138,10 @@ pub struct Repository {
///
/// Particularly useful when following linked worktrees and instantiating new equally configured worktree repositories.
pub(crate) options: crate::open::Options,
+ #[cfg(feature = "index")]
pub(crate) index: crate::worktree::IndexStorage,
+ #[cfg(feature = "attributes")]
+ pub(crate) modules: crate::submodule::ModulesFileStorage,
pub(crate) shallow_commits: crate::shallow::CommitsStorage,
}
@@ -148,6 +152,9 @@ pub struct Repository {
///
/// Note that this type purposefully isn't very useful until it is converted into a thread-local repository with `to_thread_local()`,
/// it's merely meant to be able to exist in a `Sync` context.
+///
+/// Note that it can also cheaply be cloned, and it will retain references to all contained resources.
+#[derive(Clone)]
pub struct ThreadSafeRepository {
/// A store for references to point at objects
pub refs: crate::RefStore,
@@ -161,7 +168,10 @@ pub struct ThreadSafeRepository {
/// options obtained when instantiating this repository for use when following linked worktrees.
pub(crate) linked_worktree_options: crate::open::Options,
/// The index of this instances worktree.
+ #[cfg(feature = "index")]
pub(crate) index: crate::worktree::IndexStorage,
+ #[cfg(feature = "attributes")]
+ pub(crate) modules: crate::submodule::ModulesFileStorage,
pub(crate) shallow_commits: crate::shallow::CommitsStorage,
}
@@ -191,3 +201,46 @@ pub struct Remote<'repo> {
// pub(crate) prune_tags: bool,
pub(crate) repo: &'repo Repository,
}
+
+/// A utility to make matching against pathspecs simple.
+///
+/// Note that to perform pathspec matching, attribute access might need to be provided. For that, we use our own
+/// and argue that the implementation is only going to incur costs for it when a pathspec matches *and* has attributes.
+/// Should this potential duplication of effort to maintain attribute state be unacceptable, the user may fall back
+/// to the underlying plumbing.
+#[derive(Clone)]
+#[cfg(feature = "attributes")]
+pub struct Pathspec<'repo> {
+ pub(crate) repo: &'repo Repository,
+ /// The cache to power attribute access. It's only initialized if we have a pattern with attributes.
+ pub(crate) stack: Option<gix_worktree::Stack>,
+ /// The prepared search to use for checking matches.
+ pub(crate) search: gix_pathspec::Search,
+}
+
+/// Like [`Pathspec`], but without a Repository reference and with minimal API.
+#[derive(Clone)]
+#[cfg(feature = "attributes")]
+pub struct PathspecDetached {
+ /// The cache to power attribute access. It's only initialized if we have a pattern with attributes.
+ pub stack: Option<gix_worktree::Stack>,
+ /// The prepared search to use for checking matches.
+ pub search: gix_pathspec::Search,
+ /// A thread-safe version of an ODB.
+ pub odb: gix_odb::HandleArc,
+}
+
+/// A stand-in for the submodule of a particular name.
+#[derive(Clone)]
+#[cfg(feature = "attributes")]
+pub struct Submodule<'repo> {
+ pub(crate) state: std::rc::Rc<crate::submodule::SharedState<'repo>>,
+ pub(crate) name: crate::bstr::BString,
+}
+
+/// A utility to access `.gitattributes` and `.gitignore` information efficiently.
+#[cfg(any(feature = "attributes", feature = "excludes"))]
+pub struct AttributeStack<'repo> {
+ pub(crate) repo: &'repo Repository,
+ pub(crate) inner: gix_worktree::Stack,
+}
diff --git a/vendor/gix/src/worktree/mod.rs b/vendor/gix/src/worktree/mod.rs
index 8db123554..b0a1cc6f4 100644
--- a/vendor/gix/src/worktree/mod.rs
+++ b/vendor/gix/src/worktree/mod.rs
@@ -1,14 +1,23 @@
use std::path::PathBuf;
+#[cfg(feature = "worktree-archive")]
+pub use gix_archive as archive;
+#[cfg(feature = "excludes")]
pub use gix_worktree::*;
+#[cfg(feature = "worktree-mutation")]
+pub use gix_worktree_state as state;
+#[cfg(feature = "worktree-stream")]
+pub use gix_worktree_stream as stream;
use crate::{
bstr::{BStr, BString},
Repository,
};
+#[cfg(feature = "index")]
pub(crate) type IndexStorage = gix_features::threading::OwnShared<gix_fs::SharedFileSnapshotMut<gix_index::File>>;
/// A lazily loaded and auto-updated worktree index.
+#[cfg(feature = "index")]
pub type Index = gix_fs::SharedFileSnapshot<gix_index::File>;
/// A stand-in to a worktree as result of a worktree iteration.
@@ -54,6 +63,13 @@ impl<'repo> crate::Worktree<'repo> {
pub fn id(&self) -> Option<&BStr> {
id(self.parent.git_dir(), self.parent.common_dir.is_some())
}
+
+ /// Returns true if the `.git` file or directory exists within the worktree.
+ ///
+ /// This is an indicator for the worktree to be checked out particularly if the parent repository is a submodule.
+ pub fn dot_git_exists(&self) -> bool {
+ self.path.join(gix_discover::DOT_GIT_DIR).exists()
+ }
}
pub(crate) fn id(git_dir: &std::path::Path, has_common_dir: bool) -> Option<&BStr> {
@@ -70,6 +86,7 @@ pub(crate) fn id(git_dir: &std::path::Path, has_common_dir: bool) -> Option<&BSt
pub mod proxy;
///
+#[cfg(feature = "index")]
pub mod open_index {
/// The error returned by [`Worktree::open_index()`][crate::Worktree::open_index()].
#[derive(Debug, thiserror::Error)]
@@ -78,7 +95,11 @@ pub mod open_index {
#[error(transparent)]
ConfigIndexThreads(#[from] crate::config::key::GenericErrorWithValue),
#[error(transparent)]
+ ConfigSkipHash(#[from] crate::config::boolean::Error),
+ #[error(transparent)]
IndexFile(#[from] gix_index::file::init::Error),
+ #[error(transparent)]
+ IndexCorrupt(#[from] gix_index::file::verify::Error),
}
impl<'repo> crate::Worktree<'repo> {
@@ -95,7 +116,10 @@ pub mod open_index {
}
///
+#[cfg(feature = "excludes")]
pub mod excludes {
+ use crate::AttributeStack;
+
/// The error returned by [`Worktree::excludes()`][crate::Worktree::excludes()].
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
@@ -116,44 +140,115 @@ pub mod excludes {
///
/// When only excludes are desired, this is the most efficient way to obtain them. Otherwise use
/// [`Worktree::attributes()`][crate::Worktree::attributes()] for accessing both attributes and excludes.
- pub fn excludes(&self, overrides: Option<gix_ignore::Search>) -> Result<gix_worktree::Cache, Error> {
+ pub fn excludes(&self, overrides: Option<gix_ignore::Search>) -> Result<AttributeStack<'_>, Error> {
let index = self.index()?;
Ok(self.parent.excludes(
&index,
overrides,
- gix_worktree::cache::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,
+ gix_worktree::stack::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,
)?)
}
}
}
///
+#[cfg(feature = "attributes")]
pub mod attributes {
- /// The error returned by [`Worktree::attributes()`][crate::Worktree::attributes()].
+ use crate::{AttributeStack, Worktree};
+
+ /// The error returned by [`Worktree::attributes()`].
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
OpenIndex(#[from] crate::worktree::open_index::Error),
#[error(transparent)]
- CreateCache(#[from] crate::attributes::Error),
+ CreateCache(#[from] crate::repository::attributes::Error),
}
- impl<'repo> crate::Worktree<'repo> {
+ impl<'repo> Worktree<'repo> {
/// Configure a file-system cache checking if files below the repository are excluded or for querying their attributes.
///
/// This takes into consideration all the usual repository configuration, namely:
///
/// * `$XDG_CONFIG_HOME/…/ignore|attributes` if `core.excludesFile|attributesFile` is *not* set, otherwise use the configured file.
/// * `$GIT_DIR/info/exclude|attributes` if present.
- pub fn attributes(&self, overrides: Option<gix_ignore::Search>) -> Result<gix_worktree::Cache, Error> {
+ pub fn attributes(&self, overrides: Option<gix_ignore::Search>) -> Result<AttributeStack<'repo>, Error> {
let index = self.index()?;
Ok(self.parent.attributes(
&index,
- gix_worktree::cache::state::attributes::Source::WorktreeThenIdMapping,
- gix_worktree::cache::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,
+ gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
+ gix_worktree::stack::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,
overrides,
)?)
}
+
+ /// Like [attributes()][Self::attributes()], but without access to exclude/ignore information.
+ pub fn attributes_only(&self) -> Result<AttributeStack<'repo>, Error> {
+ let index = self.index()?;
+ self.parent
+ .attributes_only(
+ &index,
+ gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
+ )
+ .map_err(|err| Error::CreateCache(err.into()))
+ }
+ }
+}
+
+///
+#[cfg(feature = "attributes")]
+pub mod pathspec {
+ use crate::{
+ bstr::BStr,
+ config::{cache::util::ApplyLeniencyDefaultValue, tree::gitoxide},
+ Worktree,
+ };
+
+ /// The error returned by [`Worktree::pathspec()`].
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ Init(#[from] crate::pathspec::init::Error),
+ #[error(transparent)]
+ OpenIndex(#[from] crate::worktree::open_index::Error),
+ }
+
+ impl<'repo> Worktree<'repo> {
+ /// Configure pathspecs `patterns` to be matched against, with pathspec attributes read from the worktree and then from the index
+ /// if needed.
+ ///
+ /// ### Deviation
+ ///
+ /// Pathspec attributes match case-insensitively by default if the underlying filesystem is configured that way.
+ pub fn pathspec(
+ &self,
+ patterns: impl IntoIterator<Item = impl AsRef<BStr>>,
+ ) -> Result<crate::Pathspec<'repo>, Error> {
+ let index = self.index()?;
+ let inherit_ignore_case = self
+ .parent
+ .config
+ .resolved
+ .boolean_by_key("gitoxide.pathspec.inheritIgnoreCase")
+ .map(|res| {
+ gitoxide::Pathspec::INHERIT_IGNORE_CASE
+ .enrich_error(res)
+ .with_lenient_default_value(
+ self.parent.config.lenient_config,
+ gitoxide::Pathspec::INHERIT_IGNORE_CASE_DEFAULT,
+ )
+ })
+ .transpose()
+ .map_err(|err| Error::Init(crate::pathspec::init::Error::Defaults(err.into())))?
+ .unwrap_or(gitoxide::Pathspec::INHERIT_IGNORE_CASE_DEFAULT);
+ Ok(self.parent.pathspec(
+ patterns,
+ inherit_ignore_case,
+ &index,
+ gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
+ )?)
+ }
}
}