diff --git a/Cargo.lock b/Cargo.lock index b19a2e3c5d..8f26469686 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2436,6 +2436,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..06985be863 100644 --- a/gix-commitgraph/Cargo.toml +++ b/gix-commitgraph/Cargo.toml @@ -16,6 +16,8 @@ rust-version = "1.82" doctest = false [features] +## Support for SHA256 hashes and digests. +sha256 = ["gix-hash/sha256"] ## Data structures implement `serde::Serialize` and `serde::Deserialize` serde = ["dep:serde", "gix-hash/serde", "bstr/serde"] @@ -33,6 +35,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/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/justfile b/justfile index 1514bf95cd..8540695a0c 100755 --- a/justfile +++ b/justfile @@ -106,6 +106,7 @@ check: cargo check -p gix-features --features zlib cargo check -p gix-features --features cache-efficiency-debug cargo check -p gix-commitgraph --all-features + cargo check -p gix-commitgraph --features sha256 cargo check -p gix-config-value --all-features cargo check -p gix-config --all-features cargo check -p gix-diff --no-default-features @@ -162,6 +163,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_HASH=sha1 cargo nextest run -p gix-commitgraph --no-fail-fast + env GIX_TEST_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 diff --git a/tests/tools/Cargo.toml b/tests/tools/Cargo.toml index 369e86e4f3..42e9146b95 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 19e88aab81..9b70d61cf8 100644 --- a/tests/tools/src/lib.rs +++ b/tests/tools/src/lib.rs @@ -247,7 +247,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)] @@ -416,7 +416,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>, @@ -470,6 +470,13 @@ fn scripted_fixture_read_only_with_args_inner( gix_tempfile::signal::handler::Mode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour, ); + let gix_test_hash = env::var_os("GIX_TEST_HASH") + .and_then(|os_string| os_string.into_string().ok()) + .unwrap_or_default(); + let hash_kind = gix_hash::Kind::from_str(&gix_test_hash).unwrap_or_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); @@ -477,7 +484,12 @@ fn scripted_fixture_read_only_with_args_inner( let args: Vec = args.into_iter().map(Into::into).collect(); let script_identity = { let mut map = SCRIPT_IDENTITY.lock(); - map.entry(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()) + }; + map.entry(args.iter().fold(init, |p, a| p.join(a))) .or_insert_with(|| { let crc_value = crc::Crc::::new(&crc::CRC_32_CKSUM); let mut crc_digest = crc_value.digest(); @@ -509,8 +521,13 @@ fn scripted_fixture_read_only_with_args_inner( } ArgsInHash::No => "".into(), }; + let potential_hash_suffix = if hash_kind == gix_hash::Kind::Sha1 { + "".into() + } else { + format!("_{hash_kind}") + }; Path::new("generated-archives").join(format!( - "{}{suffix}.tar{}", + "{}{suffix}{potential_hash_suffix}.tar{}", script_basename.to_str().expect("valid UTF-8"), if cfg!(feature = "xz") { ".xz" } else { "" } )) @@ -519,14 +536,12 @@ fn scripted_fixture_read_only_with_args_inner( ); let (force_run, script_result_directory) = destination_dir.map_or_else( || { - let dir = fixture_path_inner( - Path::new("generated-do-not-edit").join(script_basename).join(format!( - "{}-{}", - script_identity, - family_name() - )), - root, - ); + let mut path = Path::new("generated-do-not-edit").join(script_basename); + if hash_kind != gix_hash::Kind::Sha1 { + path = path.join(hash_kind.to_string()); + } + path = path.join(format!("{}-{}", script_identity, family_name())); + let dir = fixture_path_inner(path, root); (false, dir) }, |d| (true, d.to_owned()), @@ -588,13 +603,13 @@ fn scripted_fixture_read_only_with_args_inner( } let script_absolute_path = env::current_dir()?.join(script_path); let mut cmd = std::process::Command::new(&script_absolute_path); - let output = match configure_command(&mut cmd, &args, &script_result_directory).output() { + let output = match configure_command(&mut cmd, hash_kind, &args, &script_result_directory).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, &script_result_directory).output()? + configure_command(cmd.arg(script_absolute_path), hash_kind, &args, &script_result_directory).output()? } Err(err) => return Err(err.into()), }; @@ -625,6 +640,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 { @@ -664,6 +680,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. @@ -1051,7 +1068,12 @@ mod tests { 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::Sha1, + ["config", "-l", "--show-origin"], + temp.path(), + ); let output = cmd.output().expect("can run git"); let lines: Vec<_> = output