History

feat: use `GIX_TEST_FIXTURE_HASH` environment variable.

For now, there is no direct way to set it, but that may change once we have tests that need it.

Christoph Rüßler committed 9 months ago

Commit 7f50c301 parent 28fbeb84 files · +64 −20Browse files

Unified · Split

4 files
  1. Cargo.lock +1 −0
  2. tests/tools/Cargo.toml +1 −0
  3. tests/tools/src/lib.rs +56 −19
  4. tests/tools/src/tests.rs +6 −1
Cargo.lock+1−0
@@ -2418,6 +2418,7 @@ dependencies = [ · 2417 unmodified lines
24182418 "fs_extra",
24192419 "gix-discover",
24202420 "gix-fs",
2421+ "gix-hash",
24212422 "gix-lock",
24222423 "gix-tempfile",
24232424 "gix-worktree",
tests/tools/Cargo.toml+1−0
@@ -25,6 +25,7 @@ default = [] · 24 unmodified lines
2525 xz = ["dep:xz2"]
2626
2727 [dependencies]
28+gix-hash = { version = "^0.22.0", path = "../../gix-hash" }
2829 gix-lock = { version = "^21.0.0", path = "../../gix-lock" }
2930 gix-discover = { version = "^0.46.0", path = "../../gix-discover" }
3031 gix-worktree = { version = "^0.47.0", path = "../../gix-worktree" }
tests/tools/src/lib.rs+56−19
@@ -287,7 +287,7 @@ enum DirectoryRoot { · 286 unmodified lines
287287 StandaloneTest,
288288 }
289289
290−/// Don't add a suffix to the archive name as `args` are platform dependent, none-deterministic,
290+/// Don't add a suffix to the archive name as `args` are platform dependent, non-deterministic,
291291 /// or otherwise don't influence the content of the archive.
292292 /// Note that this also means that `args` won't be used to control the hash of the archive itself.
293293 #[derive(Copy, Clone)]
@@ -508,7 +508,7 @@ pub fn copy_recursively_into_existing_dir(src_dir: impl AsRef<Path>, dst_dir: im · 214 unmodified lines
508508 Ok(())
509509 }
510510
511−/// Like `scripted_fixture_read_only()`], but passes `args` to `script_name`.
511+/// Like [`scripted_fixture_read_only()`], but passes `args` to `script_name`.
512512 pub fn scripted_fixture_read_only_with_args(
513513 script_name: impl AsRef<Path>,
514514 args: impl IntoIterator<Item = impl Into<String>>,
@@ -874,7 +874,7 @@ pub fn rust_fixture_read_only<T, F>(name: &str, version: u32, make_fixture: F) - · 359 unmodified lines
874874 where
875875 F: FnOnce(FixtureState<'_>) -> PostResult<T>,
876876 {
877− rust_fixture_read_only_inner(name, version, make_fixture, None, DirectoryRoot::IntegrationTest)
877+ rust_fixture_read_only_inner(name, version, None, make_fixture, None, DirectoryRoot::IntegrationTest)
878878 }
879879
880880 /// Like [`rust_fixture_read_only()`], but does not prefix the fixture directory with `tests`.
@@ -882,7 +882,7 @@ pub fn rust_fixture_read_only_standalone<T, F>(name: &str, version: u32, make_fi · 1 unmodified line
882882 where
883883 F: FnOnce(FixtureState<'_>) -> PostResult<T>,
884884 {
885− rust_fixture_read_only_inner(name, version, make_fixture, None, DirectoryRoot::StandaloneTest)
885+ rust_fixture_read_only_inner(name, version, None, make_fixture, None, DirectoryRoot::StandaloneTest)
886886 }
887887
888888 /// Execute a Rust closure in a directory, returning a writable temporary directory.
@@ -922,7 +922,7 @@ pub fn rust_fixture_writable<T, F>( · 33 unmodified lines
922922 where
923923 F: FnMut(FixtureState<'_>) -> PostResult<T>,
924924 {
925− rust_fixture_writable_inner(name, version, make_fixture, mode, DirectoryRoot::IntegrationTest)
925+ rust_fixture_writable_inner(name, version, None, make_fixture, mode, DirectoryRoot::IntegrationTest)
926926 }
927927
928928 /// Like [`rust_fixture_writable()`], but does not prefix the fixture directory with `tests`.
@@ -935,12 +935,13 @@ pub fn rust_fixture_writable_standalone<T, F>( · 6 unmodified lines
935935 where
936936 F: FnMut(FixtureState<'_>) -> PostResult<T>,
937937 {
938− rust_fixture_writable_inner(name, version, make_fixture, mode, DirectoryRoot::StandaloneTest)
938+ rust_fixture_writable_inner(name, version, None, make_fixture, mode, DirectoryRoot::StandaloneTest)
939939 }
940940
941941 fn rust_fixture_writable_inner<T, F>(
942942 name: &str,
943943 version: u32,
944+ object_hash: Option<gix_hash::Kind>,
944945 mut make_fixture: F,
945946 mode: Creation,
946947 root: DirectoryRoot,
@@ -951,13 +952,15 @@ where · 4 unmodified lines
951952 let dst = tempfile::TempDir::new()?;
952953 let res = match mode {
953954 Creation::CopyFromReadOnly => {
954− let (ro_dir, _res_ignored) = rust_fixture_read_only_inner(name, version, &mut make_fixture, None, root)?;
955+ let (ro_dir, _res_ignored) =
956+ rust_fixture_read_only_inner(name, version, object_hash, &mut make_fixture, None, root)?;
955957 copy_recursively_into_existing_dir(ro_dir, dst.path())?;
956958 let res = make_fixture(FixtureState::Fresh(dst.path()))?;
957959 res
958960 }
959961 Creation::Execute => {
960− let (_, res) = rust_fixture_read_only_inner(name, version, make_fixture, Some(dst.path()), root)?;
962+ let (_, res) =
963+ rust_fixture_read_only_inner(name, version, object_hash, make_fixture, Some(dst.path()), root)?;
961964 res
962965 }
963966 };
@@ -967,6 +970,7 @@ where · 3 unmodified lines
967970 fn rust_fixture_read_only_inner<T, F>(
968971 name: &str,
969972 version: u32,
973+ object_hash: Option<gix_hash::Kind>,
970974 make_fixture: F,
971975 destination_dir: Option<&Path>,
972976 root: DirectoryRoot,
@@ -988,7 +992,8 @@ where · 15 unmodified lines
988992 Path::new(ARCHIVE_DIR_NAME).join(format!("{archive_name}.{}", tar_extension())),
989993 root,
990994 );
991− let (force_run, script_result_directory) = force_and_dir(destination_dir, root, &archive_name, &script_identity);
995+ let (force_run, script_result_directory) =
996+ force_and_dir(destination_dir, root, &archive_name, object_hash, &script_identity);
992997 let _marker = marker_if_needed(destination_dir, archive_name)?;
993998
994999 run_fixture_generator_with_marker_handling(
@@ -1024,16 +1029,16 @@ fn force_and_dir( · 29 unmodified lines
10241029 destination_dir: Option<&Path>,
10251030 root: DirectoryRoot,
10261031 archive_name: impl AsRef<Path>,
1032+ hash_kind: Option<gix_hash::Kind>,
10271033 script_identity: &dyn std::fmt::Display,
10281034 ) -> (bool, PathBuf) {
10291035 destination_dir.map_or_else(
10301036 || {
10311037 let dir = fixture_path_inner(
1032− Path::new("generated-do-not-edit").join(archive_name).join(format!(
1033− "{}-{}",
1034− script_identity,
1035− family_name()
1036− )),
1038+ Path::new("generated-do-not-edit")
1039+ .join(archive_name)
1040+ .join(hash_kind.unwrap_or_else(hash_kind_from_env).to_string())
1041+ .join(format!("{}-{}", script_identity, family_name())),
10371042 root,
10381043 );
10391044 (false, dir)
@@ -1127,6 +1132,9 @@ where · 87 unmodified lines
11271132 gix_tempfile::signal::handler::Mode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour,
11281133 );
11291134
1135+ let hash_kind = hash_kind_from_env();
1136+ eprintln!("Using hash '{hash_kind}' when determining which fixture to use or recreate");
1137+
11301138 let script_location = script_name.as_ref();
11311139 let script_path = fixture_path_inner(script_location, root);
11321140
@@ -1135,7 +1143,12 @@ where · 2 unmodified lines
11351143 let post_version = post_process.as_ref().map(|(v, _)| *v);
11361144 let script_identity = {
11371145 let mut map = SCRIPT_IDENTITY.lock();
1138− let key = args.iter().fold(script_path.clone(), |p, a| p.join(a));
1146+ let init = if hash_kind == gix_hash::Kind::Sha1 {
1147+ script_path.clone()
1148+ } else {
1149+ script_path.clone().join(hash_kind.to_string())
1150+ };
1151+ let key = args.iter().fold(init, |p, a| p.join(a));
11391152 // Include post_version in the key if present
11401153 let key = if let Some(v) = post_version {
11411154 key.join(format!("post-v{v}"))
@@ -1178,15 +1191,26 @@ where · 36 unmodified lines
11781191 }
11791192 ArgsInHash::No => "".into(),
11801193 };
1194+ let potential_hash_suffix = if hash_kind == gix_hash::Kind::Sha1 {
1195+ "".into()
1196+ } else {
1197+ format!("_{hash_kind}")
1198+ };
11811199 Path::new(ARCHIVE_DIR_NAME).join(format!(
1182− "{}{suffix}.{}",
1200+ "{}{suffix}{potential_hash_suffix}.{}",
11831201 script_basename.to_str().expect("valid UTF-8"),
11841202 tar_extension()
11851203 ))
11861204 },
11871205 root,
11881206 );
1189− let (force_run, script_result_directory) = force_and_dir(destination_dir, root, script_basename, &script_identity);
1207+ let (force_run, script_result_directory) = force_and_dir(
1208+ destination_dir,
1209+ root,
1210+ script_basename,
1211+ Some(hash_kind),
1212+ &script_identity,
1213+ );
11901214 let _marker = marker_if_needed(destination_dir, script_basename)?;
11911215
11921216 let script_identity_for_archive = match args_in_hash {
@@ -1205,14 +1229,14 @@ where · 12 unmodified lines
12051229 |fixture_state| {
12061230 if let FixtureState::Uninitialized(dir) = fixture_state {
12071231 let mut cmd = std::process::Command::new(&script_absolute_path);
1208− let output = match configure_command(&mut cmd, &args, dir).output() {
1232+ let output = match configure_command(&mut cmd, hash_kind, &args, dir).output() {
12091233 Ok(out) => out,
12101234 Err(err)
12111235 if err.kind() == std::io::ErrorKind::PermissionDenied
12121236 || err.raw_os_error() == Some(193) /* windows */ =>
12131237 {
12141238 cmd = std::process::Command::new(bash_program());
1215− configure_command(cmd.arg(&script_absolute_path), &args, dir).output()?
1239+ configure_command(cmd.arg(&script_absolute_path), hash_kind, &args, dir).output()?
12161240 }
12171241 Err(err) => return Err(err.into()),
12181242 };
@@ -1233,6 +1257,17 @@ where · 14 unmodified lines
12331257 Ok((script_result_directory, res))
12341258 }
12351259
1260+fn hash_kind_from_env() -> gix_hash::Kind {
1261+ env::var_os("GIX_TEST_FIXTURE_HASH").and_then(|value| value.into_string().ok()).map(|object_kind| {
1262+ gix_hash::Kind::from_str(&object_kind).unwrap_or_else(|_| {
1263+ panic!(
1264+ "GIX_TEST_FIXTURE_HASH was set to {object_kind} which is an invalid value. Valid values are {}. Exiting.",
1265+ gix_hash::Kind::all().iter().map(std::string::ToString::to_string).collect::<Vec<_>>().join(", ")
1266+ )
1267+ })
1268+ }).unwrap_or_default()
1269+}
1270+
12361271 #[cfg(windows)]
12371272 const NULL_DEVICE: &str = "nul"; // See `gix_path::env::git::NULL_DEVICE` on why this form is used.
12381273 #[cfg(not(windows))]
@@ -1240,6 +1275,7 @@ const NULL_DEVICE: &str = "/dev/null"; · 1 unmodified line
12401275
12411276 fn configure_command<'a, I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
12421277 cmd: &'a mut std::process::Command,
1278+ hash_kind: gix_hash::Kind,
12431279 args: I,
12441280 script_result_directory: &Path,
12451281 ) -> &'a mut std::process::Command {
@@ -1279,6 +1315,7 @@ fn configure_command<'a, I: IntoIterator<Item = S>, S: AsRef<OsStr>>( · 33 unmodified lines
12791315 .env("GIT_CONFIG_VALUE_2", "main")
12801316 .env("GIT_CONFIG_KEY_3", "protocol.file.allow")
12811317 .env("GIT_CONFIG_VALUE_3", "always")
1318+ .env("GIT_DEFAULT_HASH", hash_kind.to_string())
12821319 }
12831320
12841321 /// Get the path attempted as a `bash` interpreter, for fixture scripts having no `#!` we can use.
tests/tools/src/tests.rs+6−1
@@ -44,7 +44,12 @@ fn configure_command_clears_external_config() { · 43 unmodified lines
4444 let mut cmd = std::process::Command::new(GIT_PROGRAM);
4545 cmd.env("GIT_CONFIG_SYSTEM", SCOPE_ENV_VALUE);
4646 cmd.env("GIT_CONFIG_GLOBAL", SCOPE_ENV_VALUE);
47− configure_command(&mut cmd, ["config", "-l", "--show-origin"], temp.path());
47+ configure_command(
48+ &mut cmd,
49+ gix_hash::Kind::default(),
50+ ["config", "-l", "--show-origin"],
51+ temp.path(),
52+ );
4853
4954 let output = cmd.output().expect("can run git");
5055 let lines: Vec<_> = output