diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py index a78f8cbd3..9da95411a 100644 --- a/scripts/generate_pack.py +++ b/scripts/generate_pack.py @@ -3477,6 +3477,22 @@ def _main(held: contextlib.ExitStack) -> None: parser.error("Specify --platform or --all") return + # A mistyped target is refused before the output lock and the data + # directory refresh: checked after them, `--target swich` waited on a + # pipeline's caches before saying the target does not exist. + target_cores_cache: dict[str, set[str] | None] = {} + if args.target: + try: + target_cores_cache, platforms = build_target_cores_cache( + platforms, + args.target, + args.platforms_dir, + is_all=args.all, + ) + except (FileNotFoundError, ValueError) as e: + print(f"ERROR: {e}", file=sys.stderr) + sys.exit(1) + data_registry = load_data_dir_registry(args.platforms_dir) # The output directory is claimed before the data directory refresh: a # refresh waits for every run that holds a cache, so a second build @@ -3498,19 +3514,6 @@ def _main(held: contextlib.ExitStack) -> None: emu_profiles = load_emulator_profiles(args.emulators_dir) - target_cores_cache: dict[str, set[str] | None] = {} - if args.target: - try: - target_cores_cache, platforms = build_target_cores_cache( - platforms, - args.target, - args.platforms_dir, - is_all=args.all, - ) - except (FileNotFoundError, ValueError) as e: - print(f"ERROR: {e}", file=sys.stderr) - sys.exit(1) - groups = group_identical_platforms( platforms, args.platforms_dir, target_cores_cache if args.target else None ) diff --git a/tests/test_target_verify.py b/tests/test_target_verify.py index 9f9c50385..231bd8f65 100644 --- a/tests/test_target_verify.py +++ b/tests/test_target_verify.py @@ -58,5 +58,32 @@ class ANameClaimsOnlyANarrowingThatHappened(unittest.TestCase): ) +class AMistypedTargetIsRefusedFirst(unittest.TestCase): + """`--platform retroarch --target swich` took the dist lock and waited on + the data directory refresh, 22 s here and hours behind a pipeline, before + saying the target does not exist.""" + + def test_no_lock_and_no_refresh_before_the_refusal(self): + from unittest import mock + + import generate_pack + + def touched(*_a, **_kw): + raise AssertionError("lock or refresh taken before the target check") + + argv = ["generate_pack.py", "--platform", "retroarch", "--target", "swich", + "--output-dir", str(REPO_ROOT / "tmp" / "never-written")] + err = io.StringIO() + with mock.patch.object(sys, "argv", argv), \ + mock.patch.object(generate_pack, "_pack_output_lock", touched), \ + mock.patch.object(generate_pack, "hold_data_dirs", touched), \ + contextlib.redirect_stdout(io.StringIO()), \ + contextlib.redirect_stderr(err), \ + self.assertRaises(SystemExit) as ctx: + generate_pack.main() + self.assertEqual(ctx.exception.code, 1) + self.assertIn("Unknown target 'swich'", err.getvalue()) + + if __name__ == "__main__": unittest.main()