diff --git a/Cargo.lock b/Cargo.lock index e17bb71ffb4..60187483380 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 1bc5fd784a0..7257d14ff3c 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 e09ff635047..85cd5daf5c1 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/commitgraph.rs b/gix-commitgraph/tests/commitgraph.rs index 8b2ae8776dc..1952b2be37e 100644 --- a/gix-commitgraph/tests/commitgraph.rs +++ b/gix-commitgraph/tests/commitgraph.rs @@ -81,6 +81,14 @@ pub fn graph_and_expected_named( let expected = inspect_refs(&repo_dir, refs); let cg = Graph::from_info_dir(&repo_dir.join(".git").join("objects").join("info")).expect("graph present and valid"); + let object_hash = cg.object_hash(); + let any_ref = expected.values().next().expect("at least one ref"); + assert_eq!( + object_hash, + any_ref.id().kind(), + "graph hash kind should match fixture object IDs" + ); + (cg, expected) } 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 00000000000..96db68e7a87 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 00000000000..757aa8ef786 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 00000000000..b68642249e3 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 00000000000..9016ac17286 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 00000000000..f0e15f61bbc 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 00000000000..06de56f9102 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 b410fe89ee6..6bc05b75283 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 5e68ff7197f..6846c4a0016 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 faaa0438296..5ace21e1ba8 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 1878edcaa1f..ccb5c4d61ba 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 9410308e39f..ac4244093a5 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 bf7c8eeea55..7d5d3c005c0 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 0dc5488b592..999f5bbdd4a 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 f93608727f4..b122ada5f6a 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 82725f7ae79..1e401a21d66 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 59e80d2b303..961ee1ae4b1 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 4b7b0cb32f3..b4c829a158e 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 d476bd17cf9..d5d6978048e 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 371eee9a781..3f532b43d7c 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 b9790e00142..10fa4400731 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 fb8bd2a2920..827ba3e6fea 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 918fcfce1ca..8152a79ba6e 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 317f9340b50..fa6c7e13ad5 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 8dd1aedaae5..2bc05ba122f 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 2755ff00f25..109b263369e 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 8b832f5c2c8..eb7f69355ee 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 62fdbc85dab..1b0d568e566 100755 --- a/justfile +++ b/justfile @@ -162,6 +162,8 @@ unit-tests: 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,7 +171,8 @@ 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 diff --git a/tests/tools/Cargo.toml b/tests/tools/Cargo.toml index d65e8d92030..1a2625e171b 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 7f8001c24f2..f236f8ea005 100644 --- a/tests/tools/src/lib.rs +++ b/tests/tools/src/lib.rs @@ -1,5 +1,14 @@ //! Utilities for testing `gitoxide` crates, many of which might be useful for testing programs that use `git` in general. //! +//! ## Environment Variables +//! +//! ### `GIX_TEST_FIXTURE_HASH` +//! +//! Set this variable to control which hash function is used when creating or loading test fixtures. +//! Valid values are the names of hash functions supported by `gix_hash::Kind` (e.g., `sha1`, `sha256`). +//! If not set, the default hash function via `gix_hash::Kind::default()` is used. +//! + //! ## Feature Flags #![cfg_attr( all(doc, feature = "document-features"), @@ -287,7 +296,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 +517,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>, @@ -874,7 +883,7 @@ pub fn rust_fixture_read_only(name: &str, version: u32, make_fixture: F) - where F: FnOnce(FixtureState<'_>) -> PostResult, { - rust_fixture_read_only_inner(name, version, make_fixture, None, DirectoryRoot::IntegrationTest) + rust_fixture_read_only_inner(name, version, None, make_fixture, None, DirectoryRoot::IntegrationTest) } /// Like [`rust_fixture_read_only()`], but does not prefix the fixture directory with `tests`. @@ -882,7 +891,7 @@ pub fn rust_fixture_read_only_standalone(name: &str, version: u32, make_fi where F: FnOnce(FixtureState<'_>) -> PostResult, { - rust_fixture_read_only_inner(name, version, make_fixture, None, DirectoryRoot::StandaloneTest) + rust_fixture_read_only_inner(name, version, None, make_fixture, None, DirectoryRoot::StandaloneTest) } /// Execute a Rust closure in a directory, returning a writable temporary directory. @@ -922,7 +931,7 @@ pub fn rust_fixture_writable( where F: FnMut(FixtureState<'_>) -> PostResult, { - rust_fixture_writable_inner(name, version, make_fixture, mode, DirectoryRoot::IntegrationTest) + rust_fixture_writable_inner(name, version, None, make_fixture, mode, DirectoryRoot::IntegrationTest) } /// Like [`rust_fixture_writable()`], but does not prefix the fixture directory with `tests`. @@ -935,12 +944,13 @@ pub fn rust_fixture_writable_standalone( where F: FnMut(FixtureState<'_>) -> PostResult, { - rust_fixture_writable_inner(name, version, make_fixture, mode, DirectoryRoot::StandaloneTest) + rust_fixture_writable_inner(name, version, None, make_fixture, mode, DirectoryRoot::StandaloneTest) } fn rust_fixture_writable_inner( name: &str, version: u32, + object_hash: Option, mut make_fixture: F, mode: Creation, root: DirectoryRoot, @@ -951,13 +961,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, object_hash, &mut make_fixture, None, 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, object_hash, make_fixture, Some(dst.path()), root)?; res } }; @@ -967,6 +979,7 @@ where fn rust_fixture_read_only_inner( name: &str, version: u32, + object_hash: Option, make_fixture: F, destination_dir: Option<&Path>, root: DirectoryRoot, @@ -988,7 +1001,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, object_hash, &script_identity); let _marker = marker_if_needed(destination_dir, archive_name)?; run_fixture_generator_with_marker_handling( @@ -1024,16 +1038,16 @@ fn force_and_dir( destination_dir: Option<&Path>, root: DirectoryRoot, archive_name: impl AsRef, + hash_kind: Option, 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.unwrap_or_else(hash_kind_from_env).to_string()) + .join(format!("{}-{}", script_identity, family_name())), root, ); (false, dir) @@ -1127,6 +1141,9 @@ where gix_tempfile::signal::handler::Mode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour, ); + let hash_kind = hash_kind_from_env(); + 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 +1152,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 +1200,26 @@ 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, + Some(hash_kind), + &script_identity, + ); let _marker = marker_if_needed(destination_dir, script_basename)?; let script_identity_for_archive = match args_in_hash { @@ -1205,14 +1238,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()), }; @@ -1233,6 +1266,17 @@ where Ok((script_result_directory, res)) } +fn hash_kind_from_env() -> gix_hash::Kind { + env::var_os("GIX_TEST_FIXTURE_HASH").and_then(|value| value.into_string().ok()).map(|object_kind| { + gix_hash::Kind::from_str(&object_kind).unwrap_or_else(|_| { + panic!( + "GIX_TEST_FIXTURE_HASH was set to {object_kind} which is an invalid value. Valid values are {}. Exiting.", + gix_hash::Kind::all().iter().map(std::string::ToString::to_string).collect::>().join(", ") + ) + }) + }).unwrap_or_default() +} + #[cfg(windows)] const NULL_DEVICE: &str = "nul"; // See `gix_path::env::git::NULL_DEVICE` on why this form is used. #[cfg(not(windows))] @@ -1240,6 +1284,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 +1324,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 049a379e127..e879cb2cc77 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