diff --git a/Cargo.lock b/Cargo.lock index e17bb71ffb..6018748338 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2418,6 +2418,7 @@ dependencies = [ "fs_extra", "gix-discover", "gix-fs", + "gix-hash", "gix-lock", "gix-tempfile", "gix-worktree", diff --git a/gix-commitgraph/Cargo.toml b/gix-commitgraph/Cargo.toml index 1bc5fd784a..7257d14ff3 100644 --- a/gix-commitgraph/Cargo.toml +++ b/gix-commitgraph/Cargo.toml @@ -33,6 +33,7 @@ document-features = { version = "0.2.0", optional = true } [dev-dependencies] gix-testtools = { path = "../tests/tools" } gix-date = { path = "../gix-date" } +gix-hash = { path = "../gix-hash", features = ["sha256"] } [package.metadata.docs.rs] all-features = true diff --git a/gix-commitgraph/src/access.rs b/gix-commitgraph/src/access.rs index e09ff63504..85cd5daf5c 100644 --- a/gix-commitgraph/src/access.rs +++ b/gix-commitgraph/src/access.rs @@ -11,6 +11,20 @@ impl Graph { r.file.commit_at(r.pos) } + /// The kind of hash used in this `Graph`. + /// + /// Note that it is always conforming to the hash used in the owning repository. + /// + /// # Panics + /// + /// If the graph does not contain any `File`. + pub fn object_hash(&self) -> gix_hash::Kind { + self.files + .first() + .map(super::File::object_hash) + .expect("graph to have at least one file") + } + /// Returns the commit matching the given `id`. pub fn commit_by_id(&self, id: impl AsRef) -> Option> { let r = self.lookup_by_id(id.as_ref())?; diff --git a/gix-commitgraph/tests/fixtures/generated-archives/generation_number_overflow_sha256.tar b/gix-commitgraph/tests/fixtures/generated-archives/generation_number_overflow_sha256.tar new file mode 100644 index 0000000000..96db68e7a8 Binary files /dev/null and b/gix-commitgraph/tests/fixtures/generated-archives/generation_number_overflow_sha256.tar differ diff --git a/gix-commitgraph/tests/fixtures/generated-archives/octopus_merges_sha256.tar b/gix-commitgraph/tests/fixtures/generated-archives/octopus_merges_sha256.tar new file mode 100644 index 0000000000..757aa8ef78 Binary files /dev/null and b/gix-commitgraph/tests/fixtures/generated-archives/octopus_merges_sha256.tar differ diff --git a/gix-commitgraph/tests/fixtures/generated-archives/single_commit_huge_dates_sha256.tar b/gix-commitgraph/tests/fixtures/generated-archives/single_commit_huge_dates_sha256.tar new file mode 100644 index 0000000000..b68642249e Binary files /dev/null and b/gix-commitgraph/tests/fixtures/generated-archives/single_commit_huge_dates_sha256.tar differ diff --git a/gix-commitgraph/tests/fixtures/generated-archives/single_commit_sha256.tar b/gix-commitgraph/tests/fixtures/generated-archives/single_commit_sha256.tar new file mode 100644 index 0000000000..9016ac1728 Binary files /dev/null and b/gix-commitgraph/tests/fixtures/generated-archives/single_commit_sha256.tar differ diff --git a/gix-commitgraph/tests/fixtures/generated-archives/single_parent_sha256.tar b/gix-commitgraph/tests/fixtures/generated-archives/single_parent_sha256.tar new file mode 100644 index 0000000000..f0e15f61bb Binary files /dev/null and b/gix-commitgraph/tests/fixtures/generated-archives/single_parent_sha256.tar differ diff --git a/gix-commitgraph/tests/fixtures/generated-archives/two_parents_sha256.tar b/gix-commitgraph/tests/fixtures/generated-archives/two_parents_sha256.tar new file mode 100644 index 0000000000..06de56f910 Binary files /dev/null and b/gix-commitgraph/tests/fixtures/generated-archives/two_parents_sha256.tar differ diff --git a/gix-diff/src/tree/visit.rs b/gix-diff/src/tree/visit.rs index b410fe89ee..6bc05b7528 100644 --- a/gix-diff/src/tree/visit.rs +++ b/gix-diff/src/tree/visit.rs @@ -151,9 +151,12 @@ mod tests { #[test] fn size_of_change() { let actual = std::mem::size_of::(); + let sha1 = 48; + let sha256_extra = 24; + let ceiling = sha1 + sha256_extra; assert!( - actual <= 48, - "{actual} <= 48: this type shouldn't grow without us knowing" + actual <= ceiling, + "{actual} <= {ceiling}: this type shouldn't grow without us knowing" ); } } diff --git a/gix-index/src/extension/tree/mod.rs b/gix-index/src/extension/tree/mod.rs index 5e68ff7197..6846c4a001 100644 --- a/gix-index/src/extension/tree/mod.rs +++ b/gix-index/src/extension/tree/mod.rs @@ -18,7 +18,9 @@ mod tests { #[test] fn size_of_tree() { let actual = std::mem::size_of::(); - let expected = 88; + let sha1 = 88; + let sha256_extra = 16; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "the size of this structure should not change unexpectedly: {actual} <~ {expected}" diff --git a/gix-index/tests/Cargo.toml b/gix-index/tests/Cargo.toml index faaa043829..5ace21e1ba 100644 --- a/gix-index/tests/Cargo.toml +++ b/gix-index/tests/Cargo.toml @@ -24,6 +24,6 @@ gix-features = { path = "../../gix-features", features = ["progress"] } gix-testtools = { path = "../../tests/tools" } gix-odb = { path = "../../gix-odb" } gix-object = { path = "../../gix-object" } -gix-hash = { path = "../../gix-hash" } +gix-hash = { path = "../../gix-hash", features = ["sha256"] } filetime = "0.2.27" bstr = { version = "1.12.0", default-features = false } diff --git a/gix-index/tests/index/mod.rs b/gix-index/tests/index/mod.rs index 1878edcaa1..ccb5c4d61b 100644 --- a/gix-index/tests/index/mod.rs +++ b/gix-index/tests/index/mod.rs @@ -27,7 +27,9 @@ pub fn loose_file_path(name: &str) -> PathBuf { #[test] fn size_of_entry() { let actual = std::mem::size_of::(); - let expected = 80; + let sha1 = 80; + let sha256_extra = 16; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "the size of this structure should not change unexpectedly: {actual} <~ {expected}" diff --git a/gix-negotiate/tests/negotiate.rs b/gix-negotiate/tests/negotiate.rs index 9410308e39..ac4244093a 100644 --- a/gix-negotiate/tests/negotiate.rs +++ b/gix-negotiate/tests/negotiate.rs @@ -39,7 +39,9 @@ mod baseline; #[test] fn size_of_entry() { let actual = std::mem::size_of::>(); - let expected = 56; + let sha1 = 56; + let sha256_extra = 16; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "we may keep a lot of these, so let's not let them grow unnoticed: {actual} <~ {expected}" diff --git a/gix-object/tests/object/main.rs b/gix-object/tests/object/main.rs index bf7c8eeea5..7d5d3c005c 100644 --- a/gix-object/tests/object/main.rs +++ b/gix-object/tests/object/main.rs @@ -80,9 +80,12 @@ fn fixture_name(kind: &str, path: &str) -> Vec { #[test] fn size_in_memory() { let actual = std::mem::size_of::(); + let sha1 = 272; + let sha256_extra = 16; + let expected = sha1 + sha256_extra; assert!( - actual <= 272, - "{actual} <= 272: Prevent unexpected growth of what should be lightweight objects" + actual <= expected, + "{actual} <= {expected}: Prevent unexpected growth of what should be lightweight objects" ); } diff --git a/gix-pack/Cargo.toml b/gix-pack/Cargo.toml index 0dc5488b59..999f5bbdd4 100644 --- a/gix-pack/Cargo.toml +++ b/gix-pack/Cargo.toml @@ -65,6 +65,7 @@ gix-tempfile = { version = "^21.0.0", default-features = false, path = "../gix-t [dev-dependencies] gix-testtools = { path = "../tests/tools" } +gix-hash = { version = "^0.22.0", path = "../gix-hash", features = ["sha256"] } [package.metadata.docs.rs] all-features = true diff --git a/gix-pack/src/cache/delta/tree.rs b/gix-pack/src/cache/delta/tree.rs index f93608727f..b122ada5f6 100644 --- a/gix-pack/src/cache/delta/tree.rs +++ b/gix-pack/src/cache/delta/tree.rs @@ -255,7 +255,9 @@ mod tests { } let actual = std::mem::size_of::<[Item; 7_500_000]>(); - let expected = 840_000_000; + let sha1 = 840_000_000; + let sha256_extra = 120_000_000; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "we don't want these to grow unnoticed: {actual} <~ {expected}" diff --git a/gix-pack/tests/Cargo.toml b/gix-pack/tests/Cargo.toml index 82725f7ae7..1e401a21d6 100644 --- a/gix-pack/tests/Cargo.toml +++ b/gix-pack/tests/Cargo.toml @@ -6,7 +6,7 @@ version = "0.0.0" repository = "https://github.com/GitoxideLabs/gitoxide" authors = ["Sebastian Thiel "] license = "MIT OR Apache-2.0" -description = "Please use `gix-` instead ('git' -> 'gix')" +description = "Tests for the gix-pack crate" edition = "2021" rust-version = "1.82" @@ -27,5 +27,5 @@ bstr = { version = "1.12.0", default-features = false, features = ["std"] } maplit = "1.0.2" gix-object = { path = "../../gix-object" } gix-traverse = { path = "../../gix-traverse" } -gix-hash = { path = "../../gix-hash" } +gix-hash = { path = "../../gix-hash", features = ["sha256"] } memmap2 = "0.9.7" diff --git a/gix-pack/tests/pack/data/output/mod.rs b/gix-pack/tests/pack/data/output/mod.rs index 59e80d2b30..961ee1ae4b 100644 --- a/gix-pack/tests/pack/data/output/mod.rs +++ b/gix-pack/tests/pack/data/output/mod.rs @@ -6,7 +6,9 @@ use gix_testtools::size_ok; #[test] fn size_of_entry() { let actual = std::mem::size_of::(); - let expected = 80; + let sha1 = 80; + let sha256_extra = 32; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "The size of the structure shouldn't change unexpectedly: {actual} <~ {expected}" @@ -16,7 +18,9 @@ fn size_of_entry() { #[test] fn size_of_count() { let actual = std::mem::size_of::(); - let expected = 56; + let sha1 = 56; + let sha256_extra = 16; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "The size of the structure shouldn't change unexpectedly: {actual} <~ {expected}" diff --git a/gix-pack/tests/pack/iter.rs b/gix-pack/tests/pack/iter.rs index 4b7b0cb32f..b4c829a158 100644 --- a/gix-pack/tests/pack/iter.rs +++ b/gix-pack/tests/pack/iter.rs @@ -4,7 +4,9 @@ use gix_testtools::size_ok; #[test] fn size_of_entry() { let actual = std::mem::size_of::(); - let expected = 104; + let sha1 = 104; + let sha256_extra = 32; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "let's keep the size in check as we have many of them: {actual} <~ {expected}" diff --git a/gix-ref/src/raw.rs b/gix-ref/src/raw.rs index d476bd17cf..d5d6978048 100644 --- a/gix-ref/src/raw.rs +++ b/gix-ref/src/raw.rs @@ -100,7 +100,9 @@ mod tests { #[test] fn size_of_reference() { let actual = std::mem::size_of::(); - let expected = 80; + let sha1 = 80; + let sha256_extra = 24; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "let's not let it change size undetected: {actual} <~ {expected}" diff --git a/gix-revwalk/tests/revwalk.rs b/gix-revwalk/tests/revwalk.rs index 371eee9a78..3f532b43d7 100644 --- a/gix-revwalk/tests/revwalk.rs +++ b/gix-revwalk/tests/revwalk.rs @@ -5,7 +5,9 @@ mod graph { #[test] fn size_of_commit() { let actual = std::mem::size_of::>(); - let expected = 48; + let sha1 = 48; + let sha256_extra = 16; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "We might see quite a lot of these, so they shouldn't grow unexpectedly: {actual} <~ {expected}" diff --git a/gix-worktree-state/tests/Cargo.toml b/gix-worktree-state/tests/Cargo.toml index b9790e0014..10fa440073 100644 --- a/gix-worktree-state/tests/Cargo.toml +++ b/gix-worktree-state/tests/Cargo.toml @@ -24,7 +24,7 @@ gix-object = { path = "../../gix-object" } gix-discover = { path = "../../gix-discover" } gix-filter = { path = "../../gix-filter" } gix-index = { path = "../../gix-index" } -gix-hash = { path = "../../gix-hash" } +gix-hash = { path = "../../gix-hash", features = ["sha256"] } gix-fs = { path = "../../gix-fs" } gix-features = { path = "../../gix-features" } gix-testtools = { path = "../../tests/tools" } diff --git a/gix-worktree/tests/Cargo.toml b/gix-worktree/tests/Cargo.toml index fb8bd2a292..827ba3e6fe 100644 --- a/gix-worktree/tests/Cargo.toml +++ b/gix-worktree/tests/Cargo.toml @@ -22,7 +22,7 @@ gix-features-parallel = ["gix-features/parallel"] gix-worktree = { path = "..", features = ["attributes"] } gix-index = { path = "../../gix-index" } gix-fs = { path = "../../gix-fs" } -gix-hash = { path = "../../gix-hash" } +gix-hash = { path = "../../gix-hash", features = ["sha256"] } gix-object = { path = "../../gix-object" } gix-glob = { path = "../../gix-glob" } gix-path = { path = "../../gix-path" } diff --git a/gix/Cargo.toml b/gix/Cargo.toml index 918fcfce1c..8152a79ba6 100644 --- a/gix/Cargo.toml +++ b/gix/Cargo.toml @@ -411,6 +411,7 @@ document-features = { version = "0.2.0", optional = true } gix = { path = ".", default-features = false, features = [ "need-more-recent-msrv", "tree-error" ] } +gix-hash = { version = "^0.22.0", path = "../gix-hash", features = ["sha256"] } pretty_assertions = "1.4.0" gix-testtools = { path = "../tests/tools" } is_ci = "1.1.1" diff --git a/gix/src/id.rs b/gix/src/id.rs index 317f9340b5..fa6c7e13ad 100644 --- a/gix/src/id.rs +++ b/gix/src/id.rs @@ -198,7 +198,9 @@ mod tests { #[test] fn size_of_oid() { let actual = std::mem::size_of::>(); - let ceiling = 32; + let sha1 = 32; + let sha256_extra = 16; + let ceiling = sha1 + sha256_extra; assert!( actual <= ceiling, "size of oid shouldn't change without notice: {actual} <= {ceiling}" diff --git a/gix/tests/gix/object/mod.rs b/gix/tests/gix/object/mod.rs index 8dd1aedaae..2bc05ba122 100644 --- a/gix/tests/gix/object/mod.rs +++ b/gix/tests/gix/object/mod.rs @@ -7,7 +7,9 @@ use gix_testtools::size_ok; #[test] fn object_ref_size_in_memory() { let actual = std::mem::size_of::>(); - let expected = 56; + let sha1 = 56; + let sha256_extra = 16; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "the size of this structure should not change unexpectedly: {actual} <~ {expected}" @@ -17,7 +19,9 @@ fn object_ref_size_in_memory() { #[test] fn oid_size_in_memory() { let actual = std::mem::size_of::>(); - let expected = 32; + let sha1 = 32; + let sha256_extra = 16; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "the size of this structure should not change unexpectedly: {actual} <~ {expected}" diff --git a/gix/tests/gix/revision/spec/from_bytes/mod.rs b/gix/tests/gix/revision/spec/from_bytes/mod.rs index 2755ff00f2..109b263369 100644 --- a/gix/tests/gix/revision/spec/from_bytes/mod.rs +++ b/gix/tests/gix/revision/spec/from_bytes/mod.rs @@ -147,7 +147,7 @@ fn bad_objects_are_valid_until_they_are_actually_read_from_the_odb() { | └─ An error occurred while obtaining an object from the loose object store | - └─ decompression of loose object at 'tests/fixtures/generated-do-not-edit/make_rev_spec_parse_repos/2990428670-unix/blob.corrupt/objects/ca/fea31147e840161a1860c50af999917ae1536b' failed + └─ decompression of loose object at 'tests/fixtures/generated-do-not-edit/make_rev_spec_parse_repos/sha1/2990428670-unix/blob.corrupt/objects/ca/fea31147e840161a1860c50af999917ae1536b' failed | └─ Could not decode zip stream, status was 'Invalid input data' | diff --git a/gix/tests/gix/status.rs b/gix/tests/gix/status.rs index 8b832f5c2c..eb7f69355e 100644 --- a/gix/tests/gix/status.rs +++ b/gix/tests/gix/status.rs @@ -29,7 +29,9 @@ mod into_iter { #[test] fn item_size() { let actual = std::mem::size_of::(); - let expected = 264; + let sha1 = 264; + let sha256_extra = 56; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "The size is the same as the one for the index-worktree-item: {actual} <~ {expected}" @@ -303,7 +305,9 @@ mod index_worktree { #[test] fn item_size() { let actual = std::mem::size_of::(); - let expected = 264; + let sha1 = 264; + let sha256_extra = 56; + let expected = sha1 + sha256_extra; assert!( size_ok(actual, expected), "The size is pretty huge and goes down ideally: {actual} <~ {expected}" diff --git a/justfile b/justfile index 62fdbc85da..d633dc6a45 100755 --- a/justfile +++ b/justfile @@ -155,13 +155,15 @@ unit-tests: cargo nextest run -p gix-archive --no-default-features --features tar_gz --no-fail-fast cargo nextest run -p gix-archive --no-default-features --features zip --no-fail-fast cargo nextest run -p gix-status-tests --features gix-features-parallel --no-fail-fast - cargo nextest run -p gix-worktree-state-tests --features gix-features-parallel --no-fail-fast - cargo nextest run -p gix-worktree-tests --features gix-features-parallel --no-fail-fast + env GIX_TEST_FIXTURE_HASH=sha1 cargo nextest run -p gix-worktree-state-tests --features gix-features-parallel --no-fail-fast + env GIX_TEST_FIXTURE_HASH=sha1 cargo nextest run -p gix-worktree-tests --features gix-features-parallel --no-fail-fast cargo nextest run -p gix-error --no-fail-fast --test auto-chain-error --features auto-chain-error cargo nextest run -p gix-error --no-fail-fast cargo nextest run -p gix-hash --no-fail-fast cargo nextest run -p gix-hash --features sha256 --no-fail-fast cargo nextest run -p gix-hash --no-default-features --features sha256 --no-fail-fast # TODO: make this actually work by removing 'sha1' from default features. + env GIX_TEST_FIXTURE_HASH=sha1 cargo nextest run -p gix-commitgraph --no-fail-fast + env GIX_TEST_FIXTURE_HASH=sha256 cargo nextest run -p gix-commitgraph --no-fail-fast cargo nextest run -p gix-object --no-fail-fast cargo nextest run -p gix-object --features verbose-object-parsing-errors --no-fail-fast cargo nextest run -p gix-tempfile --features signals --no-fail-fast @@ -169,10 +171,11 @@ unit-tests: cargo nextest run -p gix-ref-tests --all-features --no-fail-fast cargo nextest run -p gix-odb --all-features --no-fail-fast cargo nextest run -p gix-odb-tests --features gix-features-parallel --no-fail-fast - cargo nextest run -p gix-pack --all-features --no-fail-fast + env GIX_TEST_FIXTURE_HASH=sha1 cargo nextest run -p gix-pack --all-features --no-fail-fast + env GIX_TEST_FIXTURE_HASH=sha256 cargo nextest run -p gix-pack --all-features --no-fail-fast cargo nextest run -p gix-pack-tests --features all-features --no-fail-fast cargo nextest run -p gix-pack-tests --features gix-features-parallel --no-fail-fast - cargo nextest run -p gix-index-tests --features gix-features-parallel --no-fail-fast + env GIX_TEST_FIXTURE_HASH=sha1 cargo nextest run -p gix-index-tests --features gix-features-parallel --no-fail-fast cargo nextest run -p gix-packetline --features blocking-io,maybe-async/is_sync --test blocking-packetline --no-fail-fast cargo nextest run -p gix-packetline --features async-io --test async-packetline --no-fail-fast cargo nextest run -p gix-transport --features http-client-curl,maybe-async/is_sync --no-fail-fast diff --git a/tests/tools/Cargo.toml b/tests/tools/Cargo.toml index d65e8d9203..1a2625e171 100644 --- a/tests/tools/Cargo.toml +++ b/tests/tools/Cargo.toml @@ -25,6 +25,7 @@ default = [] xz = ["dep:xz2"] [dependencies] +gix-hash = { version = "^0.22.0", path = "../../gix-hash" } gix-lock = { version = "^21.0.0", path = "../../gix-lock" } gix-discover = { version = "^0.46.0", path = "../../gix-discover" } gix-worktree = { version = "^0.47.0", path = "../../gix-worktree" } diff --git a/tests/tools/src/lib.rs b/tests/tools/src/lib.rs index 7f8001c24f..96aba164fb 100644 --- a/tests/tools/src/lib.rs +++ b/tests/tools/src/lib.rs @@ -287,7 +287,7 @@ enum DirectoryRoot { StandaloneTest, } -/// Don't add a suffix to the archive name as `args` are platform dependent, none-deterministic, +/// Don't add a suffix to the archive name as `args` are platform dependent, non-deterministic, /// or otherwise don't influence the content of the archive. /// Note that this also means that `args` won't be used to control the hash of the archive itself. #[derive(Copy, Clone)] @@ -508,7 +508,7 @@ pub fn copy_recursively_into_existing_dir(src_dir: impl AsRef, dst_dir: im Ok(()) } -/// Like `scripted_fixture_read_only()`], but passes `args` to `script_name`. +/// Like [`scripted_fixture_read_only()`], but passes `args` to `script_name`. pub fn scripted_fixture_read_only_with_args( script_name: impl AsRef, args: impl IntoIterator>, @@ -870,19 +870,43 @@ pub fn scripted_fixture_writable_with_args_standalone_single_archive_with_post(name: &str, version: u32, make_fixture: F) -> Result<(PathBuf, T)> +pub fn rust_fixture_read_only( + name: &str, + version: u32, + make_fixture: F, + hash_kind: gix_hash::Kind, +) -> Result<(PathBuf, T)> where F: FnOnce(FixtureState<'_>) -> PostResult, { - rust_fixture_read_only_inner(name, version, make_fixture, None, DirectoryRoot::IntegrationTest) + rust_fixture_read_only_inner( + name, + version, + make_fixture, + None, + hash_kind, + DirectoryRoot::IntegrationTest, + ) } /// Like [`rust_fixture_read_only()`], but does not prefix the fixture directory with `tests`. -pub fn rust_fixture_read_only_standalone(name: &str, version: u32, make_fixture: F) -> Result<(PathBuf, T)> +pub fn rust_fixture_read_only_standalone( + name: &str, + version: u32, + make_fixture: F, + hash_kind: gix_hash::Kind, +) -> Result<(PathBuf, T)> where F: FnOnce(FixtureState<'_>) -> PostResult, { - rust_fixture_read_only_inner(name, version, make_fixture, None, DirectoryRoot::StandaloneTest) + rust_fixture_read_only_inner( + name, + version, + make_fixture, + None, + hash_kind, + DirectoryRoot::StandaloneTest, + ) } /// Execute a Rust closure in a directory, returning a writable temporary directory. @@ -918,11 +942,19 @@ pub fn rust_fixture_writable( version: u32, mode: Creation, make_fixture: F, + hash_kind: gix_hash::Kind, ) -> Result<(tempfile::TempDir, T)> where F: FnMut(FixtureState<'_>) -> PostResult, { - rust_fixture_writable_inner(name, version, make_fixture, mode, DirectoryRoot::IntegrationTest) + rust_fixture_writable_inner( + name, + version, + make_fixture, + mode, + hash_kind, + DirectoryRoot::IntegrationTest, + ) } /// Like [`rust_fixture_writable()`], but does not prefix the fixture directory with `tests`. @@ -931,11 +963,19 @@ pub fn rust_fixture_writable_standalone( version: u32, mode: Creation, make_fixture: F, + hash_kind: gix_hash::Kind, ) -> Result<(tempfile::TempDir, T)> where F: FnMut(FixtureState<'_>) -> PostResult, { - rust_fixture_writable_inner(name, version, make_fixture, mode, DirectoryRoot::StandaloneTest) + rust_fixture_writable_inner( + name, + version, + make_fixture, + mode, + hash_kind, + DirectoryRoot::StandaloneTest, + ) } fn rust_fixture_writable_inner( @@ -943,6 +983,7 @@ fn rust_fixture_writable_inner( version: u32, mut make_fixture: F, mode: Creation, + hash_kind: gix_hash::Kind, root: DirectoryRoot, ) -> Result<(tempfile::TempDir, T)> where @@ -951,13 +992,15 @@ where let dst = tempfile::TempDir::new()?; let res = match mode { Creation::CopyFromReadOnly => { - let (ro_dir, _res_ignored) = rust_fixture_read_only_inner(name, version, &mut make_fixture, None, root)?; + let (ro_dir, _res_ignored) = + rust_fixture_read_only_inner(name, version, &mut make_fixture, None, hash_kind, root)?; copy_recursively_into_existing_dir(ro_dir, dst.path())?; let res = make_fixture(FixtureState::Fresh(dst.path()))?; res } Creation::Execute => { - let (_, res) = rust_fixture_read_only_inner(name, version, make_fixture, Some(dst.path()), root)?; + let (_, res) = + rust_fixture_read_only_inner(name, version, make_fixture, Some(dst.path()), hash_kind, root)?; res } }; @@ -969,6 +1012,7 @@ fn rust_fixture_read_only_inner( version: u32, make_fixture: F, destination_dir: Option<&Path>, + hash_kind: gix_hash::Kind, root: DirectoryRoot, ) -> Result<(PathBuf, T)> where @@ -988,7 +1032,8 @@ where Path::new(ARCHIVE_DIR_NAME).join(format!("{archive_name}.{}", tar_extension())), root, ); - let (force_run, script_result_directory) = force_and_dir(destination_dir, root, &archive_name, &script_identity); + let (force_run, script_result_directory) = + force_and_dir(destination_dir, root, &archive_name, hash_kind, &script_identity); let _marker = marker_if_needed(destination_dir, archive_name)?; run_fixture_generator_with_marker_handling( @@ -1024,16 +1069,16 @@ fn force_and_dir( destination_dir: Option<&Path>, root: DirectoryRoot, archive_name: impl AsRef, + hash_kind: gix_hash::Kind, script_identity: &dyn std::fmt::Display, ) -> (bool, PathBuf) { destination_dir.map_or_else( || { let dir = fixture_path_inner( - Path::new("generated-do-not-edit").join(archive_name).join(format!( - "{}-{}", - script_identity, - family_name() - )), + Path::new("generated-do-not-edit") + .join(archive_name) + .join(hash_kind.to_string()) + .join(format!("{}-{}", script_identity, family_name())), root, ); (false, dir) @@ -1127,6 +1172,19 @@ where gix_tempfile::signal::handler::Mode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour, ); + let gix_test_hash = env::var_os("GIX_TEST_FIXTURE_HASH").and_then(|os_string| os_string.into_string().ok()); + let hash_kind = match gix_test_hash { + Some(gix_test_hash) => gix_hash::Kind::from_str(&gix_test_hash).unwrap_or_else(|_| { + panic!( + "GIX_TEST_FIXTURE_HASH was set to {gix_test_hash} which is an invalid value. Valid values are {}. Exiting.", + gix_hash::Kind::all().iter().map(std::string::ToString::to_string).collect::>().join(", ") + ) + }), + None => gix_hash::Kind::default(), + }; + + eprintln!("Using hash '{hash_kind}' when determining which fixture to use or recreate"); + let script_location = script_name.as_ref(); let script_path = fixture_path_inner(script_location, root); @@ -1135,7 +1193,12 @@ where let post_version = post_process.as_ref().map(|(v, _)| *v); let script_identity = { let mut map = SCRIPT_IDENTITY.lock(); - let key = args.iter().fold(script_path.clone(), |p, a| p.join(a)); + let init = if hash_kind == gix_hash::Kind::Sha1 { + script_path.clone() + } else { + script_path.clone().join(hash_kind.to_string()) + }; + let key = args.iter().fold(init, |p, a| p.join(a)); // Include post_version in the key if present let key = if let Some(v) = post_version { key.join(format!("post-v{v}")) @@ -1178,15 +1241,21 @@ where } ArgsInHash::No => "".into(), }; + let potential_hash_suffix = if hash_kind == gix_hash::Kind::Sha1 { + "".into() + } else { + format!("_{hash_kind}") + }; Path::new(ARCHIVE_DIR_NAME).join(format!( - "{}{suffix}.{}", + "{}{suffix}{potential_hash_suffix}.{}", script_basename.to_str().expect("valid UTF-8"), tar_extension() )) }, root, ); - let (force_run, script_result_directory) = force_and_dir(destination_dir, root, script_basename, &script_identity); + let (force_run, script_result_directory) = + force_and_dir(destination_dir, root, script_basename, hash_kind, &script_identity); let _marker = marker_if_needed(destination_dir, script_basename)?; let script_identity_for_archive = match args_in_hash { @@ -1205,14 +1274,14 @@ where |fixture_state| { if let FixtureState::Uninitialized(dir) = fixture_state { let mut cmd = std::process::Command::new(&script_absolute_path); - let output = match configure_command(&mut cmd, &args, dir).output() { + let output = match configure_command(&mut cmd, hash_kind, &args, dir).output() { Ok(out) => out, Err(err) if err.kind() == std::io::ErrorKind::PermissionDenied || err.raw_os_error() == Some(193) /* windows */ => { cmd = std::process::Command::new(bash_program()); - configure_command(cmd.arg(&script_absolute_path), &args, dir).output()? + configure_command(cmd.arg(&script_absolute_path), hash_kind, &args, dir).output()? } Err(err) => return Err(err.into()), }; @@ -1240,6 +1309,7 @@ const NULL_DEVICE: &str = "/dev/null"; fn configure_command<'a, I: IntoIterator, S: AsRef>( cmd: &'a mut std::process::Command, + hash_kind: gix_hash::Kind, args: I, script_result_directory: &Path, ) -> &'a mut std::process::Command { @@ -1279,6 +1349,7 @@ fn configure_command<'a, I: IntoIterator, S: AsRef>( .env("GIT_CONFIG_VALUE_2", "main") .env("GIT_CONFIG_KEY_3", "protocol.file.allow") .env("GIT_CONFIG_VALUE_3", "always") + .env("GIT_DEFAULT_HASH", hash_kind.to_string()) } /// Get the path attempted as a `bash` interpreter, for fixture scripts having no `#!` we can use. diff --git a/tests/tools/src/tests.rs b/tests/tools/src/tests.rs index 049a379e12..e879cb2cc7 100644 --- a/tests/tools/src/tests.rs +++ b/tests/tools/src/tests.rs @@ -44,7 +44,12 @@ fn configure_command_clears_external_config() { let mut cmd = std::process::Command::new(GIT_PROGRAM); cmd.env("GIT_CONFIG_SYSTEM", SCOPE_ENV_VALUE); cmd.env("GIT_CONFIG_GLOBAL", SCOPE_ENV_VALUE); - configure_command(&mut cmd, ["config", "-l", "--show-origin"], temp.path()); + configure_command( + &mut cmd, + gix_hash::Kind::default(), + ["config", "-l", "--show-origin"], + temp.path(), + ); let output = cmd.output().expect("can run git"); let lines: Vec<_> = output diff --git a/tests/tools/tests/tools/rust_fixture.rs b/tests/tools/tests/tools/rust_fixture.rs index d46cd132d3..1ccbddb3bc 100644 --- a/tests/tools/tests/tools/rust_fixture.rs +++ b/tests/tools/tests/tools/rust_fixture.rs @@ -3,18 +3,23 @@ use gix_testtools::{Creation, FixtureState, Result}; #[test] fn rust_fixture_read_only_creates_and_caches_fixture() -> Result { // First call should create the fixture - let (dir, (a, b, c)) = gix_testtools::rust_fixture_read_only("test_fixture_read_only", 1, |fixture| { - let dir = fixture.path(); - let a = dir.join("test_file.txt"); - let b = dir.join("subdir"); - let c = dir.join("subdir/nested.txt"); - if fixture.is_uninitialized() { - std::fs::write(&a, "test content")?; - std::fs::create_dir(&b)?; - std::fs::write(&c, "nested content")?; - } - Ok((a, b, c)) - })?; + let (dir, (a, b, c)) = gix_testtools::rust_fixture_read_only( + "test_fixture_read_only", + 1, + |fixture| { + let dir = fixture.path(); + let a = dir.join("test_file.txt"); + let b = dir.join("subdir"); + let c = dir.join("subdir/nested.txt"); + if fixture.is_uninitialized() { + std::fs::write(&a, "test content")?; + std::fs::create_dir(&b)?; + std::fs::write(&c, "nested content")?; + } + Ok((a, b, c)) + }, + gix_hash::Kind::default(), + )?; // Verify the fixture was created correctly assert!(dir.is_dir()); @@ -26,13 +31,18 @@ fn rust_fixture_read_only_creates_and_caches_fixture() -> Result { // Second call with same version should return cached result // The closure is still called but knows that it's fresh. - let (dir2, _) = gix_testtools::rust_fixture_read_only("test_fixture_read_only", 1, |fixture| { - assert!( - matches!(fixture, gix_testtools::FixtureState::Fresh(_)), - "Expected cached fixture on second call" - ); - Ok(()) - })?; + let (dir2, _) = gix_testtools::rust_fixture_read_only( + "test_fixture_read_only", + 1, + |fixture| { + assert!( + matches!(fixture, gix_testtools::FixtureState::Fresh(_)), + "Expected cached fixture on second call" + ); + Ok(()) + }, + gix_hash::Kind::default(), + )?; // Both should point to the same directory assert_eq!(dir, dir2); @@ -43,20 +53,30 @@ fn rust_fixture_read_only_creates_and_caches_fixture() -> Result { #[test] fn rust_fixture_read_only_version_change_invalidates_cache() -> Result { // Create fixture with version 1 - let (dir1, _) = gix_testtools::rust_fixture_read_only("test_fixture_version", 1, |fixture| { - if let FixtureState::Uninitialized(dir) = fixture { - std::fs::write(dir.join("version.txt"), "v1")?; - } - Ok(()) - })?; + let (dir1, _) = gix_testtools::rust_fixture_read_only( + "test_fixture_version", + 1, + |fixture| { + if let FixtureState::Uninitialized(dir) = fixture { + std::fs::write(dir.join("version.txt"), "v1")?; + } + Ok(()) + }, + gix_hash::Kind::default(), + )?; // Version 2 should create a new fixture in a different directory - let (dir2, _) = gix_testtools::rust_fixture_read_only("test_fixture_version", 2, |fixture| { - if let FixtureState::Uninitialized(dir) = fixture { - std::fs::write(dir.join("version.txt"), "v2")?; - } - Ok(()) - })?; + let (dir2, _) = gix_testtools::rust_fixture_read_only( + "test_fixture_version", + 2, + |fixture| { + if let FixtureState::Uninitialized(dir) = fixture { + std::fs::write(dir.join("version.txt"), "v2")?; + } + Ok(()) + }, + gix_hash::Kind::default(), + )?; assert_ne!( dir1, dir2, @@ -73,12 +93,18 @@ fn rust_fixture_read_only_version_change_invalidates_cache() -> Result { #[test] fn rust_fixture_writable() -> Result { for creation in [Creation::CopyFromReadOnly, Creation::Execute] { - let (tmp, _) = gix_testtools::rust_fixture_writable("test_fixture_writable_copy", 1, creation, |fixture| { - if let FixtureState::Uninitialized(dir) = fixture { - std::fs::write(dir.join("original.txt"), "original content")?; - } - Ok(()) - })?; + let (tmp, _) = gix_testtools::rust_fixture_writable( + "test_fixture_writable_copy", + 1, + creation, + |fixture| { + if let FixtureState::Uninitialized(dir) = fixture { + std::fs::write(dir.join("original.txt"), "original content")?; + } + Ok(()) + }, + gix_hash::Kind::default(), + )?; // Verify the fixture was created let original_path = tmp.path().join("original.txt"); @@ -97,9 +123,12 @@ fn rust_fixture_writable() -> Result { #[test] fn rust_fixture_closure_error_propagates() { // Test that errors from the closure are properly propagated - let res = gix_testtools::rust_fixture_read_only("test_fixture_error", 1, |_fixture| { - Err::<(), _>("intentional error".into()) - }); + let res = gix_testtools::rust_fixture_read_only( + "test_fixture_error", + 1, + |_fixture| Err::<(), _>("intentional error".into()), + gix_hash::Kind::default(), + ); let err_msg = res.unwrap_err().to_string(); assert!( @@ -110,12 +139,17 @@ fn rust_fixture_closure_error_propagates() { #[test] fn rust_fixture_standalone_uses_fixtures_directory() -> Result { - let (dir, _) = gix_testtools::rust_fixture_read_only_standalone("test_fixture_standalone", 1, |fixture| { - if let FixtureState::Uninitialized(dir) = fixture { - std::fs::write(dir.join("standalone.txt"), "standalone")?; - } - Ok(()) - })?; + let (dir, _) = gix_testtools::rust_fixture_read_only_standalone( + "test_fixture_standalone", + 1, + |fixture| { + if let FixtureState::Uninitialized(dir) = fixture { + std::fs::write(dir.join("standalone.txt"), "standalone")?; + } + Ok(()) + }, + gix_hash::Kind::default(), + )?; // Standalone fixtures are stored in fixtures/generated-do-not-edit, not tests/fixtures/... let dir_str = dir.to_string_lossy();