From c14b5419443b5ee2dc628a07561e8dd264055c73 Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Thu, 1 Oct 2026 14:13:57 +0900 Subject: [PATCH] wip: gix-pack: tests Signed-off-by: Seongmin Lee --- Cargo.lock | 604 ++++++++++++++---- Cargo.toml | 2 +- knot2/third_party/gix-pack/Cargo.toml | 15 + ...bf8e71d8c18879e499335762dd95119d93d9f1.idx | Bin 0 -> 2248 bytes ...f8e71d8c18879e499335762dd95119d93d9f1.pack | Bin 0 -> 3732 bytes ...438c19fb16422b6bbcce24387b3264416d485b.idx | Bin 0 -> 2672 bytes ...38c19fb16422b6bbcce24387b3264416d485b.pack | Bin 0 -> 49113 bytes .../third_party/gix-pack/tests/ref_deltas.rs | 141 ++++ 8 files changed, 620 insertions(+), 142 deletions(-) create mode 100644 knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-a2bf8e71d8c18879e499335762dd95119d93d9f1.idx create mode 100644 knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-a2bf8e71d8c18879e499335762dd95119d93d9f1.pack create mode 100644 knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-c0438c19fb16422b6bbcce24387b3264416d485b.idx create mode 100644 knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-c0438c19fb16422b6bbcce24387b3264416d485b.pack create mode 100644 knot2/third_party/gix-pack/tests/ref_deltas.rs diff --git a/Cargo.lock b/Cargo.lock index 2b62ac983..b463dc6a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2149,6 +2149,15 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -2369,7 +2378,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2985,7 +2994,7 @@ dependencies = [ "gix", "gix-hash", "gix-negotiate", - "gix-object", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-pack", "gix-protocol", "gix-transport", @@ -3062,53 +3071,53 @@ version = "0.84.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae54ae0ebd1a5a3c3f8d95dd3b5ca6e63f4fed9bfd585e13801a97d7bde8f9ce" dependencies = [ - "gix-actor", + "gix-actor 0.41.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-archive", - "gix-attributes", + "gix-attributes 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-blame", "gix-command", "gix-commitgraph", "gix-config", "gix-credentials", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-diff", "gix-dir", - "gix-discover", + "gix-discover 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-error", "gix-features", "gix-filter", - "gix-fs", - "gix-glob", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-glob 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", - "gix-hashtable", - "gix-ignore", - "gix-index", - "gix-lock", + "gix-hashtable 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-ignore 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-index 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-lock 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-mailmap", "gix-merge", "gix-negotiate", - "gix-object", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-odb", "gix-pack", "gix-path", "gix-pathspec", "gix-prompt", "gix-protocol", - "gix-ref", + "gix-ref 0.64.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-refspec", "gix-revision", - "gix-revwalk", - "gix-sec", + "gix-revwalk 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-sec 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-shallow", "gix-status", "gix-submodule", - "gix-tempfile", + "gix-tempfile 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-trace", - "gix-traverse", + "gix-traverse 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-url", "gix-utils", "gix-validate", - "gix-worktree", + "gix-worktree 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-worktree-state", "gix-worktree-stream", "nonempty 0.12.0", @@ -3126,7 +3135,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bc998b8f746dda8565450d08a63b792ced9165d8c27a1ed3f02799ec6a7820f" dependencies = [ "bstr", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-error", + "serde", +] + +[[package]] +name = "gix-actor" +version = "0.41.1" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "gix-date 0.15.4 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-error", ] @@ -3138,9 +3158,9 @@ checksum = "16909cacc78936ab96f6c3be08379d0a2e88bfa3a7527972d2ed75c7517ef31e" dependencies = [ "bstr", "flate2", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-error", - "gix-object", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", "gix-worktree-stream", "rawzip", @@ -3154,9 +3174,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d43f12e246d3bf7ec624c8fc15ac4a4b62b7c4c6f586cb82be6c90bf84c9d02" dependencies = [ "bstr", - "gix-glob", + "gix-glob 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", - "gix-quote", + "gix-quote 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-trace", + "kstring", + "smallvec", + "thiserror 2.0.18", + "unicode-bom", +] + +[[package]] +name = "gix-attributes" +version = "0.33.1" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "gix-glob 0.26.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-path", + "gix-quote 0.7.2 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-trace", "kstring", "smallvec", @@ -3173,6 +3209,14 @@ dependencies = [ "gix-error", ] +[[package]] +name = "gix-bitmap" +version = "0.3.2" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "gix-error", +] + [[package]] name = "gix-blame" version = "0.14.0" @@ -3180,15 +3224,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d39a0c14af94c2edaa5eefe06d5ef2cdea55316ae9a9321314288e3f55fa4c0" dependencies = [ "gix-commitgraph", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-diff", "gix-error", "gix-hash", - "gix-object", - "gix-revwalk", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-revwalk 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-trace", - "gix-traverse", - "gix-worktree", + "gix-traverse 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-worktree 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec", "thiserror 2.0.18", ] @@ -3209,7 +3253,7 @@ checksum = "00706d4fef135ef4b01680d5218c6ee40cda8baf697b864296cbc887d19118f6" dependencies = [ "bstr", "gix-path", - "gix-quote", + "gix-quote 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-trace", "shell-words", ] @@ -3237,10 +3281,10 @@ dependencies = [ "bstr", "gix-config-value", "gix-features", - "gix-glob", + "gix-glob 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", - "gix-ref", - "gix-sec", + "gix-ref 0.64.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-sec 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec", "thiserror 2.0.18", "unicode-bom", @@ -3268,10 +3312,10 @@ dependencies = [ "bstr", "gix-command", "gix-config-value", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", "gix-prompt", - "gix-sec", + "gix-sec 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-trace", "gix-url", "thiserror 2.0.18", @@ -3282,6 +3326,18 @@ name = "gix-date" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3ecab64a98bbac9f8e02990a9ea5e3c974a7d49b95f2bd70ad94ad22fa6b48c" +dependencies = [ + "bstr", + "gix-error", + "itoa", + "jiff", + "serde", +] + +[[package]] +name = "gix-date" +version = "0.15.4" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" dependencies = [ "bstr", "gix-error", @@ -3296,20 +3352,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b6d9528f32d94cef2edf39a1ac01fe5a0fc44ddbb18d9e44099936047c3302b" dependencies = [ "bstr", - "gix-attributes", + "getrandom 0.4.3", + "gix-attributes 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-command", "gix-filter", - "gix-fs", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", "gix-imara-diff", - "gix-index", - "gix-object", + "gix-index 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", "gix-pathspec", - "gix-tempfile", + "gix-tempfile 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-trace", - "gix-traverse", - "gix-worktree", + "gix-traverse 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-worktree 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 2.0.18", ] @@ -3320,16 +3377,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bb2a53a6fd917ec499ed0bfb5b6887de7a15bd79197dcea7c987938749a9f1" dependencies = [ "bstr", - "gix-discover", - "gix-fs", - "gix-ignore", - "gix-index", - "gix-object", + "gix-discover 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-ignore 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-index 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", "gix-pathspec", "gix-trace", "gix-utils", - "gix-worktree", + "gix-worktree 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 2.0.18", ] @@ -3341,10 +3398,24 @@ checksum = "77bacdd12b7879d2178a80c58c2f319995e4654e1a7a23e3181e5c8a12b824f7" dependencies = [ "bstr", "dunce", - "gix-fs", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", - "gix-ref", - "gix-sec", + "gix-ref 0.64.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-sec 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 2.0.18", +] + +[[package]] +name = "gix-discover" +version = "0.52.0" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "dunce", + "gix-fs 0.21.2 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-path", + "gix-ref 0.64.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-sec 0.14.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "thiserror 2.0.18", ] @@ -3385,13 +3456,13 @@ checksum = "ecf74b7d16f6694ce4a3049074c41be0c7987105743674f1671807bd6dce09fa" dependencies = [ "bstr", "encoding_rs", - "gix-attributes", + "gix-attributes 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-command", "gix-hash", - "gix-object", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-packetline", "gix-path", - "gix-quote", + "gix-quote 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-trace", "gix-utils", "smallvec", @@ -3412,6 +3483,19 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "gix-fs" +version = "0.21.2" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "fastrand", + "gix-features", + "gix-path", + "gix-utils", + "thiserror 2.0.18", +] + [[package]] name = "gix-glob" version = "0.26.1" @@ -3424,6 +3508,17 @@ dependencies = [ "gix-path", ] +[[package]] +name = "gix-glob" +version = "0.26.1" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bitflags 2.13.0", + "bstr", + "gix-features", + "gix-path", +] + [[package]] name = "gix-hash" version = "0.25.1" @@ -3431,6 +3526,7 @@ source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686 dependencies = [ "faster-hex", "gix-features", + "serde", "sha1-checked", "sha2 0.11.0", "thiserror 2.0.18", @@ -3447,6 +3543,16 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "gix-hashtable" +version = "0.15.1" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "gix-hash", + "hashbrown 0.17.1", + "parking_lot", +] + [[package]] name = "gix-ignore" version = "0.21.1" @@ -3454,7 +3560,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d491bab9bf2c9f341dc754f425c31d5d3f63aca615312167b82e1deeaca97d8d" dependencies = [ "bstr", - "gix-glob", + "gix-glob 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-path", + "gix-trace", + "unicode-bom", +] + +[[package]] +name = "gix-ignore" +version = "0.21.1" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "gix-glob 0.26.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-path", "gix-trace", "unicode-bom", @@ -3467,7 +3585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19753d40da53d0ec41604750eeb969097a90fb2d7f7992730d904541c04e2c19" dependencies = [ "bstr", - "hashbrown 0.15.5", + "hashbrown 0.17.1", ] [[package]] @@ -3480,13 +3598,40 @@ dependencies = [ "bstr", "filetime", "fnv", - "gix-bitmap", + "gix-bitmap 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-features", - "gix-fs", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", - "gix-lock", - "gix-object", - "gix-traverse", + "gix-lock 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-traverse 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-utils", + "gix-validate", + "hashbrown 0.17.1", + "itoa", + "libc", + "memmap2", + "rustix", + "smallvec", + "thiserror 2.0.18", +] + +[[package]] +name = "gix-index" +version = "0.52.0" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bitflags 2.13.0", + "bstr", + "filetime", + "fnv", + "gix-bitmap 0.3.2 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-features", + "gix-fs 0.21.2 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-hash", + "gix-lock 23.0.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-object 0.61.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-traverse 0.58.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-utils", "gix-validate", "hashbrown 0.17.1", @@ -3504,7 +3649,17 @@ version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65c9dedd9e90b0d47624d2ed241d394e09294118364e87b9b7e5f1fe755f3c2c" dependencies = [ - "gix-tempfile", + "gix-tempfile 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-utils", + "thiserror 2.0.18", +] + +[[package]] +name = "gix-lock" +version = "23.0.1" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "gix-tempfile 23.0.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-utils", "thiserror 2.0.18", ] @@ -3516,8 +3671,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "195fd20808055824531be2fd0d34136d900e5fbca3ffb0a3c07e8beeefb9c828" dependencies = [ "bstr", - "gix-actor", - "gix-date", + "gix-actor 0.41.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-error", ] @@ -3531,18 +3686,18 @@ dependencies = [ "gix-command", "gix-diff", "gix-filter", - "gix-fs", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", "gix-imara-diff", - "gix-index", - "gix-object", + "gix-index 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", - "gix-quote", + "gix-quote 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-revision", - "gix-revwalk", - "gix-tempfile", + "gix-revwalk 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-tempfile 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-trace", - "gix-worktree", + "gix-worktree 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)", "nonempty 0.12.0", "thiserror 2.0.18", ] @@ -3555,10 +3710,10 @@ checksum = "890c936a215bae25818c076cb881cb2e54d2c66ba947ba58b8dd47cff921bf55" dependencies = [ "bitflags 2.13.0", "gix-commitgraph", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", - "gix-object", - "gix-revwalk", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-revwalk 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3568,11 +3723,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5cd857e29429c7213bdef3f5aef83f8cc124774fe8ae0d27b1607d218d6d525" dependencies = [ "bstr", - "gix-actor", - "gix-date", + "gix-actor 0.41.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-features", + "gix-hash", + "gix-hashtable 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-utils", + "gix-validate", + "itoa", + "serde", + "smallvec", + "thiserror 2.0.18", +] + +[[package]] +name = "gix-object" +version = "0.61.0" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "gix-actor 0.41.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-date 0.15.4 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-features", "gix-hash", - "gix-hashtable", + "gix-hashtable 0.15.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-utils", "gix-validate", "itoa", @@ -3588,13 +3762,13 @@ checksum = "7d004c32858b1556f2d7874405edb3c97dc78fc09beaa87d57bb077ee2858a7d" dependencies = [ "arc-swap", "gix-features", - "gix-fs", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", - "gix-hashtable", - "gix-object", + "gix-hashtable 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-pack", "gix-path", - "gix-quote", + "gix-quote 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "memmap2", "parking_lot", "tempfile", @@ -3605,20 +3779,27 @@ dependencies = [ name = "gix-pack" version = "0.71.0" dependencies = [ + "bstr", "clru", + "document-features", "gix-chunk", "gix-diff", "gix-error", "gix-features", "gix-hash", - "gix-hashtable", - "gix-object", + "gix-hashtable 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-odb", "gix-path", - "gix-tempfile", - "gix-traverse", + "gix-tempfile 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-testtools", + "gix-traverse 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit", "memmap2", "parking_lot", + "serde", "smallvec", + "tempfile", "thiserror 2.0.18", "uluru", ] @@ -3657,9 +3838,9 @@ checksum = "3050783b41ee11511e1e8fb35623df81806194f4030395f14f48ea37c2798c9f" dependencies = [ "bitflags 2.13.0", "bstr", - "gix-attributes", + "gix-attributes 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-config-value", - "gix-glob", + "gix-glob 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", "thiserror 2.0.18", ] @@ -3685,15 +3866,15 @@ checksum = "51dea3acb390707ab868f1f9584f18449eb95d869deffae96768e47d303595ee" dependencies = [ "bstr", "gix-credentials", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-features", "gix-hash", - "gix-lock", + "gix-lock 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-negotiate", - "gix-object", - "gix-ref", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-ref 0.64.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-refspec", - "gix-revwalk", + "gix-revwalk 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-shallow", "gix-trace", "gix-transport", @@ -3714,16 +3895,26 @@ dependencies = [ "gix-utils", ] +[[package]] +name = "gix-quote" +version = "0.7.2" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "gix-error", + "gix-utils", +] + [[package]] name = "gix-rebase" version = "0.0.1" dependencies = [ "gix", - "gix-actor", + "gix-actor 0.41.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-diff", "gix-hash", "gix-merge", - "gix-object", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile", "thiserror 2.0.18", ] @@ -3736,9 +3927,9 @@ dependencies = [ "gix", "gix-features", "gix-hash", - "gix-object", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-packetline", - "gix-ref", + "gix-ref 0.64.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-transport", "thiserror 2.0.18", ] @@ -3749,14 +3940,33 @@ version = "0.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c04f64c37eb7e6feb73c7060f8dc6f381cc5de5d53249bfd450bc48a86b2e8b" dependencies = [ - "gix-actor", + "gix-actor 0.41.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-features", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-hash", + "gix-lock 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-path", + "gix-tempfile 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-utils", + "gix-validate", + "memmap2", + "thiserror 2.0.18", +] + +[[package]] +name = "gix-ref" +version = "0.64.0" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "gix-actor 0.41.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-features", - "gix-fs", + "gix-fs 0.21.2 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-hash", - "gix-lock", - "gix-object", + "gix-lock 23.0.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-object 0.61.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-path", - "gix-tempfile", + "gix-tempfile 23.0.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-utils", "gix-validate", "memmap2", @@ -3771,7 +3981,7 @@ checksum = "b216ae06ec74b5f24ad0142026a997fb0a935b7410eaf9c1616fc3f0e6c5a6d3" dependencies = [ "bstr", "gix-error", - "gix-glob", + "gix-glob 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", "gix-revision", "gix-validate", @@ -3788,12 +3998,12 @@ dependencies = [ "bitflags 2.13.0", "bstr", "gix-commitgraph", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-error", "gix-hash", - "gix-hashtable", - "gix-object", - "gix-revwalk", + "gix-hashtable 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-revwalk 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-trace", "nonempty 0.12.0", ] @@ -3805,11 +4015,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85f5756abffe0917827aac683b13684ed99875bc398fa1f9b8f479b0681ef9e6" dependencies = [ "gix-commitgraph", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "gix-error", "gix-hash", - "gix-hashtable", - "gix-object", + "gix-hashtable 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", + "thiserror 2.0.18", +] + +[[package]] +name = "gix-revwalk" +version = "0.32.0" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "gix-commitgraph", + "gix-date 0.15.4 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-error", + "gix-hash", + "gix-hashtable 0.15.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-object 0.61.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "smallvec", "thiserror 2.0.18", ] @@ -3826,6 +4051,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "gix-sec" +version = "0.14.1" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bitflags 2.13.0", + "gix-path", + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "gix-shallow" version = "0.12.1" @@ -3834,7 +4070,7 @@ checksum = "a292fc2fe548c5dfa575479d16b445b0ddf1dd2f56f1fec6aed386f82553cd97" dependencies = [ "bstr", "gix-hash", - "gix-lock", + "gix-lock 23.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "nonempty 0.12.0", "thiserror 2.0.18", ] @@ -3851,13 +4087,13 @@ dependencies = [ "gix-dir", "gix-features", "gix-filter", - "gix-fs", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", - "gix-index", - "gix-object", + "gix-index 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", "gix-pathspec", - "gix-worktree", + "gix-worktree 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)", "portable-atomic", "thiserror 2.0.18", ] @@ -3884,7 +4120,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27850097e1ff9515f46a0dad0f5f9c9d020e972727772dabab9450690c4adb22" dependencies = [ "dashmap", - "gix-fs", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "parking_lot", + "signal-hook", + "signal-hook-registry", + "tempfile", +] + +[[package]] +name = "gix-tempfile" +version = "23.0.1" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "gix-fs 0.21.2 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "libc", "parking_lot", "signal-hook", @@ -3892,6 +4141,28 @@ dependencies = [ "tempfile", ] +[[package]] +name = "gix-testtools" +version = "0.19.0" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "crc", + "fastrand", + "fs_extra", + "gix-discover 0.52.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-fs 0.21.2 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-hash", + "gix-lock 23.0.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-tempfile 23.0.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-worktree 0.53.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "io-close", + "is_ci", + "parking_lot", + "tar", + "tempfile", +] + [[package]] name = "gix-trace" version = "0.1.20" @@ -3912,8 +4183,8 @@ dependencies = [ "gix-credentials", "gix-features", "gix-packetline", - "gix-quote", - "gix-sec", + "gix-quote 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-sec 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-url", "pin-project-lite", "reqwest 0.13.5", @@ -3928,11 +4199,27 @@ checksum = "e8de590ecc86a3b2870665f2288324fa9f7f8672c7fc2d4e020fdd81cd1f7aed" dependencies = [ "bitflags 2.13.0", "gix-commitgraph", - "gix-date", + "gix-date 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-hash", + "gix-hashtable 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-revwalk 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", + "thiserror 2.0.18", +] + +[[package]] +name = "gix-traverse" +version = "0.58.0" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bitflags 2.13.0", + "gix-commitgraph", + "gix-date 0.15.4 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-hash", - "gix-hashtable", - "gix-object", - "gix-revwalk", + "gix-hashtable 0.15.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-object 0.61.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-revwalk 0.32.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "smallvec", "thiserror 2.0.18", ] @@ -3974,13 +4261,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cef414ed275e8407cd5d53d301e83be19700b0dd3f859d2434417b58f454a2d1" dependencies = [ "bstr", - "gix-attributes", - "gix-fs", - "gix-glob", + "gix-attributes 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-glob 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-hash", + "gix-ignore 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-index 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-path", + "gix-validate", +] + +[[package]] +name = "gix-worktree" +version = "0.53.0" +source = "git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c#3d6f61e6a32444db44686937fd7f143ab1a9a00c" +dependencies = [ + "bstr", + "gix-attributes 0.33.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-fs 0.21.2 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-glob 0.26.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-hash", - "gix-ignore", - "gix-index", - "gix-object", + "gix-ignore 0.21.1 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-index 0.52.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", + "gix-object 0.61.0 (git+https://knot1.tangled.sh/boltless.me/gix?rev=3d6f61e6a32444db44686937fd7f143ab1a9a00c)", "gix-path", "gix-validate", ] @@ -3994,11 +4298,11 @@ dependencies = [ "bstr", "gix-features", "gix-filter", - "gix-fs", - "gix-index", - "gix-object", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-index 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", - "gix-worktree", + "gix-worktree 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)", "io-close", "thiserror 2.0.18", ] @@ -4009,15 +4313,15 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25e9ed30100c63f7590bc581c225e53f731a53e06aa79a245739c07f7dcc557" dependencies = [ - "gix-attributes", + "gix-attributes 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)", "gix-error", "gix-features", "gix-filter", - "gix-fs", + "gix-fs 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", - "gix-object", + "gix-object 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "gix-path", - "gix-traverse", + "gix-traverse 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot", ] @@ -4769,6 +5073,12 @@ dependencies = [ "unsigned-varint 0.7.2", ] +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -5399,7 +5709,7 @@ dependencies = [ "flate2", "gix", "gix-archive", - "gix-bitmap", + "gix-bitmap 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gix-hash", "gix-odb", "gix-pack", @@ -6052,6 +6362,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + [[package]] name = "lock_api" version = "0.4.14" @@ -6129,6 +6445,12 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "markup5ever" version = "0.12.1" @@ -8174,7 +8496,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -8268,7 +8590,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -9463,10 +9785,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -10532,7 +10854,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 01ddef22a..dca3a9847 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "3" -members = ["bobbin/crates/*", "crates/*", "shuttle", "knot2/crates/*", "gitmirror/crates/*"] +members = ["bobbin/crates/*", "crates/*", "shuttle", "knot2/crates/*", "knot2/third_party/gix-pack", "gitmirror/crates/*"] default-members = ["bobbin/crates/*", "crates/*", "knot2/crates/*", "gitmirror/crates/*"] exclude = ["sites"] diff --git a/knot2/third_party/gix-pack/Cargo.toml b/knot2/third_party/gix-pack/Cargo.toml index dd0ebff6b..4feb1b497 100644 --- a/knot2/third_party/gix-pack/Cargo.toml +++ b/knot2/third_party/gix-pack/Cargo.toml @@ -77,6 +77,11 @@ name = "gix_pack" path = "src/lib.rs" doctest = false +[[test]] +name = "ref_deltas" +path = "tests/ref_deltas.rs" +required-features = ["sha1", "streaming-input"] + [dependencies.clru] version = "0.6.1" optional = true @@ -153,6 +158,16 @@ default-features = false [dev-dependencies.maplit] version = "1.0.2" +[dev-dependencies.gix-odb] +version = "0.81.0" + +[dev-dependencies.gix-testtools] +git = "https://knot1.tangled.sh/boltless.me/gix" +rev = "3d6f61e6a32444db44686937fd7f143ab1a9a00c" + +[dev-dependencies.tempfile] +version = "3" + [target.'cfg(not(target_arch = "wasm32"))'.dependencies.gix-tempfile] version = "^23.0.0" optional = true diff --git a/knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-a2bf8e71d8c18879e499335762dd95119d93d9f1.idx b/knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-a2bf8e71d8c18879e499335762dd95119d93d9f1.idx new file mode 100644 index 0000000000000000000000000000000000000000..a7d6c7177ef3ca68b3b93adafa738b190db9e7ac GIT binary patch literal 2248 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 literal 0 HcmV?d00001 diff --git a/knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-c0438c19fb16422b6bbcce24387b3264416d485b.idx b/knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-c0438c19fb16422b6bbcce24387b3264416d485b.idx new file mode 100644 index 0000000000000000000000000000000000000000..87c635f48cbdd3ef50ed7f14bf339382f9af6e5a GIT binary patch literal 2672 zcmZNS1&j;~3^2^Zz`#HVGczzSAY&E=1_n|vD+2=qIhdV+fdLtFGB7Z3K`}Q20|O5U zn2&*h0fhM(7#KiUfPsO56fDTVzyQNS3=9m&SeSu<0fa>v7#KiUjDdjx8TV8DkZ z85kH~Sc-vx0UMTPU|>MUG7Jn1Ff7Z!zyQK>3=9mUV0i`x1`t+YU|>*0!b%Jb49W}) z3@T_?m4Sf)8LKfcFsP$p4F(1V5Y}X1U?7CG85kHqScidufe_YZU|`Tg!}<&i4EV4C z0|NsL8!|93fUpq*0|N{jGcYiKun7YL0|=WjFfbrva|Q+m5Vl}oV8Dhg85kJQu@wUY zgEbnqVPIguhwT^`7;s^G1_lNYc3@y&K*mlC3=A;r%)r2a1vjNJXJ5;Ixh+y|>b%^q zf(g&eR!e2*F)++vV_U1n8kV?n=abS4KbG&!mHF-Td=djgT`#|*rQ8{YSBF(zmE9`~ zsgUtM$LYtw(78c)t!Udk)7)F1-+f(lgN5<%tX1D{Ffh3OlwY!T_G^w$79EY=GbK#g zSGSsX|7BpXNz>7K`9u~dvlL4tRKBo^&~tWW zU}zLHW&W$KzWvRq^TJC0_WY;CGtGNXpnXYMOU~uAyzSzn# z<4EQy&d&Xnskase+1*GJWnh>zCsEGF*XhPZF|WIvKh@So>pbYV9ml}HusU%s^Sq}# z+kA_XO#~v(>80AU}()tCSfScJ+0M%oF7Bdv_#2I$9@I z>8V=2N6>QyhIobUn}<~spU;)_RsSV$X2zndMW@qk7#QXx_PuT26}7!@OLCaeAqnS5 zmh=lZQWzMP-0lB($JCOc`EW{)-_uHd(`4JJ37HHGmFg3s-87e!cNWA5m&9Mqd2mwd z-V$jBhV3h+JWW@N`nhbD!QGhf7RzleegO==3=I1h&N%aMgT+dYeMe=^>etE0r}S*m zT*$zXpfr>3fwJkMN11j;yH;qc&QWf$*IK~9Fmcn|Z^7Tbu79r3&K7Z<)B5gyyR?1l z85np<=ksXk$giGdsPCN7Fg16dRG+SCroEc$)k@rq8!np_|3P>2?wWL+iiI z(&h=h^^%Ooy%a*#3l6hAGfwAWU=a4+lCbGkzGG$0Vo5f)*Y;0O{gv9=!oaXUVTV=3 zwUoT95`o+CjSL)ao5hL>7BDa*UOeE}y{i3F@)osw;-UG;rc#eW)=gz#XiYsFR8^W9 zQm`{>%Pvlamj~Boi7t+3V3?eF^xd+LeY(H)vP%~~3#c(Uw0-O2`3wyGD^DChCCGKz z_r1{KNH5WZ&4*d_wlgv?OsGDkvwM~Anf=C*qH#`>3_r(*9{v7+fg!Z*%(O%7Ci@** zrt=3kI;NSQ&vShx%)qe0;mnim)z@70^p1AkIB`%TeXI?y^5VTzdL!KPJze8 zc~9+Mvu&u1X<%T;U;b*#<6FCC2x;2-F~r#I)A+fv+~pht1DCfnoXgUvHEq-h8HXJooJ8_re$2 zbK>msHR^V~pV=|}CiAmr+sbUM@{ZhzZi$Z4R(N0h|D~XKtI_>7W$lz^o~>p8T+RTO literal 0 HcmV?d00001 diff --git a/knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-c0438c19fb16422b6bbcce24387b3264416d485b.pack b/knot2/third_party/gix-pack/tests/fixtures/objects/pack/pack-c0438c19fb16422b6bbcce24387b3264416d485b.pack new file mode 100644 index 0000000000000000000000000000000000000000..a69b28ac68bd547d49ad7502b1b3fdd42d74ec71 GIT binary patch literal 49113 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 literal 0 HcmV?d00001 diff --git a/knot2/third_party/gix-pack/tests/ref_deltas.rs b/knot2/third_party/gix-pack/tests/ref_deltas.rs new file mode 100644 index 000000000..cf49db538 --- /dev/null +++ b/knot2/third_party/gix-pack/tests/ref_deltas.rs @@ -0,0 +1,141 @@ +use std::io::Write as _; +use std::path::Path; +use std::process::{Command, Stdio}; +use std::sync::atomic::AtomicBool; + +use gix_pack::data::entry::Header; +use gix_pack::data::input::{BytesToEntriesIter, EntriesToBytesIter, EntryDataMode, Mode}; + +const KIND: gix_hash::Kind = gix_hash::Kind::Sha1; + +fn git(dir: &Path, args: &[&str], stdin: &[u8]) -> Vec { + let mut child = Command::new("git") + .args(args) + .current_dir(dir) + .env("GIT_AUTHOR_NAME", "t") + .env("GIT_AUTHOR_EMAIL", "t@t") + .env("GIT_COMMITTER_NAME", "t") + .env("GIT_COMMITTER_EMAIL", "t@t") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("run git"); + child.stdin.take().unwrap().write_all(stdin).unwrap(); + let out = child.wait_with_output().unwrap(); + assert!(out.status.success(), "git {args:?} failed"); + out.stdout +} + +fn history() -> tempfile::TempDir { + let dir = tempfile::tempdir().unwrap(); + let p = dir.path(); + git(p, &["init", "-q", "-b", "main"], b""); + let mut lines: Vec = (0..400).map(|i| format!("line {i}")).collect(); + for round in 0..6 { + lines[round * 50] = format!("changed in round {round}"); + std::fs::write(p.join("file"), lines.join("\n")).unwrap(); + std::fs::write(p.join("other"), lines[..200 + round].join("\n")).unwrap(); + git(p, &["add", "-A"], b""); + git(p, &["commit", "-q", "-m", &format!("round {round}")], b""); + } + dir +} + +fn entries(pack: &[u8]) -> Vec { + BytesToEntriesIter::new_from_header(pack, Mode::Verify, EntryDataMode::Keep, KIND) + .unwrap() + .collect::>() + .unwrap() +} + +fn count_ref_deltas(pack: &[u8]) -> usize { + entries(pack) + .iter() + .filter(|e| matches!(e.header, Header::RefDelta { .. })) + .count() +} + +fn reversed(pack: &[u8]) -> Vec { + let mut entries = entries(pack); + assert!( + entries + .iter() + .all(|e| !matches!(e.header, Header::OfsDelta { .. })) + ); + entries.reverse(); + let mut out = std::io::Cursor::new(Vec::new()); + for entry in EntriesToBytesIter::new( + entries.into_iter().map(Ok), + &mut out, + gix_pack::data::Version::V2, + KIND, + ) { + entry.unwrap(); + } + out.into_inner() +} + +fn index( + pack: &[u8], + lookup: Option, +) -> Result<(tempfile::TempDir, u32), gix_pack::bundle::write::Error> { + let dir = tempfile::tempdir().unwrap(); + let outcome = gix_pack::Bundle::write_to_directory( + &mut &pack[..], + Some(dir.path()), + &mut gix_features::progress::Discard, + &AtomicBool::new(false), + lookup, + gix_pack::bundle::write::Options { + thread_limit: None, + iteration_mode: Mode::Verify, + index_version: gix_pack::index::Version::default(), + object_hash: KIND, + }, + )?; + let index_path = outcome.index_path.expect("non-empty pack"); + git( + dir.path(), + &["verify-pack", index_path.to_str().unwrap()], + b"", + ); + Ok((dir, outcome.index.num_objects)) +} + +#[test] +fn ref_deltas_resolve_against_bases_anywhere_in_the_pack() { + let repo = history(); + let pack = git( + repo.path(), + &["pack-objects", "--revs", "--stdout", "--no-reuse-delta"], + b"main\n", + ); + assert!(count_ref_deltas(&pack) > 0); + let all = entries(&pack).len() as u32; + + assert_eq!(index(&pack, None).unwrap().1, all); + assert_eq!(index(&reversed(&pack), None).unwrap().1, all); +} + +#[test] +fn thin_packs_are_completed_with_bases_from_the_lookup() { + let repo = history(); + let pack = git( + repo.path(), + &["pack-objects", "--revs", "--stdout", "--thin"], + b"main\n^main~2\n", + ); + assert!(count_ref_deltas(&pack) > 0); + let sent = entries(&pack).len() as u32; + + assert!(matches!( + index(&pack, None), + Err(gix_pack::bundle::write::Error::IndexWrite( + gix_pack::index::write::Error::UnresolvedRefDeltas(_) + )) + )); + + let odb = gix_odb::at(repo.path().join(".git/objects")).unwrap(); + let (_dir, num_objects) = index(&pack, Some(odb)).unwrap(); + assert!(num_objects > sent); +} -- knotmirror 0.0.1