mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-29 15:17:20 -05:00
fix: stop on a digest an unmoved file contradicts
This commit is contained in:
1 parent
d4f02de3fd
commit
2a50bc21f7
2 files changed
+26
-6
No files matched your search
+12
-6
@@ -80,8 +80,11 @@ def _settled_hashes(
|
|||||||
A forced run rehashes everything, and this host has given a wrong SHA-1
|
A forced run rehashes everything, and this host has given a wrong SHA-1
|
||||||
under load (DSi_Nand_USA.bin read as 834b140f, not ef08ae02). An entry
|
under load (DSi_Nand_USA.bin read as 834b140f, not ef08ae02). An entry
|
||||||
whose mtime and size did not move but whose digest did is hashed a
|
whose mtime and size did not move but whose digest did is hashed a
|
||||||
second time, and the two computations that agree win. The previous run's
|
second time. A second reading that gives the cached value back settles it.
|
||||||
value is the independent check the forced run used to throw away.
|
Two readings that agree against it do not: the host has returned the same
|
||||||
|
wrong digest twice in a row (62b100f2 for the same file), and a value
|
||||||
|
taken then is cached and read back by every later run. A file rewritten
|
||||||
|
in place moves its mtime, so the run stops instead of choosing.
|
||||||
"""
|
"""
|
||||||
hashes = compute_hashes(filepath)
|
hashes = compute_hashes(filepath)
|
||||||
if not cached or cached.get("mtime") != mtime or cached.get("size") != size:
|
if not cached or cached.get("mtime") != mtime or cached.get("size") != size:
|
||||||
@@ -89,15 +92,18 @@ def _settled_hashes(
|
|||||||
if cached.get("sha1") in (None, hashes["sha1"]):
|
if cached.get("sha1") in (None, hashes["sha1"]):
|
||||||
return hashes
|
return hashes
|
||||||
again = compute_hashes(filepath, cache=False)
|
again = compute_hashes(filepath, cache=False)
|
||||||
if again["sha1"] == hashes["sha1"]:
|
|
||||||
# Two fresh readings agree: the bytes changed under an unchanged mtime.
|
|
||||||
return hashes
|
|
||||||
print(
|
print(
|
||||||
f" WARNING: {filepath}: sha1 read as {hashes['sha1'][:8]} then "
|
f" WARNING: {filepath}: sha1 read as {hashes['sha1'][:8]} then "
|
||||||
f"{again['sha1'][:8]}, cached {cached['sha1'][:8]}",
|
f"{again['sha1'][:8]}, cached {cached['sha1'][:8]}",
|
||||||
file=sys.stderr,
|
file=sys.stderr,
|
||||||
)
|
)
|
||||||
return again if again["sha1"] == cached["sha1"] else hashes
|
if again["sha1"] == cached["sha1"]:
|
||||||
|
return again
|
||||||
|
raise RuntimeError(
|
||||||
|
f"{filepath}: read as {again['sha1'][:8]}, cached as {cached['sha1'][:8]}, "
|
||||||
|
"with the same mtime and size. Rerun when the host is idle, or "
|
||||||
|
f"`touch {filepath}` if its bytes really changed."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def scan_bios_dir(bios_dir: Path, cache: dict, force: bool) -> tuple[dict, dict, dict]:
|
def scan_bios_dir(bios_dir: Path, cache: dict, force: bool) -> tuple[dict, dict, dict]:
|
||||||
|
|||||||
@@ -5928,6 +5928,20 @@ class AForcedRehashIsCheckedAgainstTheLastOne(unittest.TestCase):
|
|||||||
self.assertEqual(settled["sha1"], "a" * 40)
|
self.assertEqual(settled["sha1"], "a" * 40)
|
||||||
self.assertIn("WARNING", err.getvalue())
|
self.assertIn("WARNING", err.getvalue())
|
||||||
|
|
||||||
|
def test_two_agreeing_readings_against_an_unmoved_file_stop_the_run(self):
|
||||||
|
"""The host has returned the same wrong SHA-1 twice in a row
|
||||||
|
(DSi_Nand_USA.bin as 62b100f2, 2026-10-22). Taking two agreeing
|
||||||
|
readings as a rewrite put the wrong value in the cache, where every
|
||||||
|
later run read it back. An unmoved file is never rewritten silently."""
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from scripts import generate_db
|
||||||
|
|
||||||
|
cached = {"sha1": "a" * 40, "mtime": 1.0, "size": 4}
|
||||||
|
with mock.patch.object(generate_db, "compute_hashes", lambda *a, **k: {"sha1": "b" * 40}), \
|
||||||
|
self.assertRaisesRegex(RuntimeError, "touch"):
|
||||||
|
generate_db._settled_hashes(Path("x.bin"), cached, 1.0, 4)
|
||||||
|
|
||||||
def test_a_changed_file_takes_its_new_digest(self):
|
def test_a_changed_file_takes_its_new_digest(self):
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user