diff --git a/scripts/truth.py b/scripts/truth.py index 5611d882..7ef05940 100644 --- a/scripts/truth.py +++ b/scripts/truth.py @@ -18,6 +18,9 @@ from hashing import parse_md5_list from validation import filter_files_by_mode, read_from_system_dir + +_CONFLICTS_SHOWN: set[tuple[str, ...]] = set() + def _serialize_source_ref(sr: object) -> str: """Convert a source_ref value to a clean string for serialization.""" if isinstance(sr, str): @@ -260,11 +263,16 @@ def _merge_hashes( existing[h] = [*o_list, *added] continue if not {str(v).lower() for v in t_list} & {str(v).lower() for v in o_list}: - print( - f"WARNING: hash conflict for {file_entry['name']} " - f"({h}: {ours} vs {theirs}, core {emu_name})", - file=sys.stderr, - ) + # Once per process: a run over every platform met the same pair + # once per platform and opened its output on six copies. + key = (file_entry["name"], h, str(ours), str(theirs), emu_name) + if key not in _CONFLICTS_SHOWN: + _CONFLICTS_SHOWN.add(key) + print( + f"WARNING: hash conflict for {file_entry['name']} " + f"({h}: {ours} vs {theirs}, core {emu_name})", + file=sys.stderr, + ) def _merge_priority(existing: dict, theirs: int | None) -> None: diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py index 341eddee..a6394a7b 100644 --- a/tests/test_audit_regressions.py +++ b/tests/test_audit_regressions.py @@ -5553,5 +5553,24 @@ class AStepThatCannotFailTheRunIsNotShownFailed(unittest.TestCase): (ROOT / "scripts" / "pipeline.py").read_text(encoding="utf-8")) +class AHashConflictIsReportedOnce(unittest.TestCase): + """check_freshness opened on six copies of one truth.py warning, one per + platform whose model met the same two GameIndex.yaml declarations.""" + + def test_the_same_pair_prints_once(self): + import contextlib + import io + + import truth + + truth._CONFLICTS_SHOWN.clear() + err = io.StringIO() + with contextlib.redirect_stderr(err): + for _platform in range(6): + existing = {"name": "x.yaml", "sha1": "a" * 40} + truth._merge_hashes(existing, {"name": "x.yaml", "sha1": "b" * 40}, "core") + self.assertEqual(err.getvalue().count("WARNING"), 1) + + if __name__ == "__main__": unittest.main()