mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-16 08:23:28 -05:00
fix: count files the emulator pack drops
This commit is contained in:
1 parent
d049270515
commit
98c21f19f7
3 files changed
+97
-8
No files matched your search
@@ -1224,6 +1224,14 @@ def _pack_data_tree(
|
||||
return added
|
||||
|
||||
|
||||
def _same_bytes(path: str, other: str | None) -> bool:
|
||||
if not other:
|
||||
return False
|
||||
if os.path.realpath(path) == os.path.realpath(other):
|
||||
return True
|
||||
return compute_hashes(path)["sha1"] == compute_hashes(other)["sha1"]
|
||||
|
||||
|
||||
def generate_emulator_pack(
|
||||
profile_names: list[str],
|
||||
emulators_dir: str,
|
||||
@@ -1279,6 +1287,9 @@ def generate_emulator_pack(
|
||||
set()
|
||||
) # parent dirs of added files (path conflict detection)
|
||||
seen_hashes: set[str] = set() # SHA1 dedup for same file, different path
|
||||
# Loose file packed at each folded destination, to tell a profile asking
|
||||
# for the same file there from one asking for other bytes.
|
||||
packed_at: dict[str, str] = {}
|
||||
data_dir_notices: list[str] = []
|
||||
data_registry = load_data_dir_registry(
|
||||
platforms_dir or os.path.join(os.path.dirname(__file__), "..", "platforms")
|
||||
@@ -1390,15 +1401,18 @@ def generate_emulator_pack(
|
||||
slots.setdefault(dest, []).append(fe)
|
||||
|
||||
for dest, alternatives in slots.items():
|
||||
if dest.lower() in seen_lower:
|
||||
continue
|
||||
if _has_path_conflict(dest, seen_destinations, seen_parents):
|
||||
continue
|
||||
# Name order, first file wins, case folded: verify replays
|
||||
# the rule and reports a later profile's file as missing.
|
||||
block = placement_block(
|
||||
dest, seen_destinations, seen_lower, seen_parents, True
|
||||
)
|
||||
|
||||
provided = next(
|
||||
(fe for fe in alternatives if fe.get("storage") == "user_provided"),
|
||||
None,
|
||||
)
|
||||
if provided is not None and block:
|
||||
continue
|
||||
if provided is not None:
|
||||
# Instructions, not a file: written beside the slot the
|
||||
# user fills, and counted apart from what the pack holds.
|
||||
@@ -1421,6 +1435,7 @@ def generate_emulator_pack(
|
||||
chosen: tuple[dict, str, str | None] | None = None
|
||||
fallback: tuple[dict, str, str | None] | None = None
|
||||
refusal: str | None = None
|
||||
refused_path: str | None = None
|
||||
for fe in alternatives:
|
||||
local_path, status = resolve_file(
|
||||
{**fe, "source_profile": emu_name},
|
||||
@@ -1446,6 +1461,7 @@ def generate_emulator_pack(
|
||||
if disagreement:
|
||||
reason = disagreement.split(" says ", 1)[-1]
|
||||
refusal = refusal or f"{fe['name']} -{reason}"
|
||||
refused_path = refused_path or local_path
|
||||
continue
|
||||
if better != local_path:
|
||||
chosen = (fe, better, None)
|
||||
@@ -1459,6 +1475,20 @@ def generate_emulator_pack(
|
||||
break
|
||||
chosen = chosen or fallback
|
||||
|
||||
if block:
|
||||
held = (
|
||||
chosen[1] if chosen is not None and chosen[2] != "external"
|
||||
else None if chosen is not None else refused_path
|
||||
)
|
||||
if chosen is not None or held is not None:
|
||||
if block == "taken" and held and _same_bytes(
|
||||
held, packed_at.get(dest.lower())
|
||||
):
|
||||
# The file already at this path, asked for twice.
|
||||
continue
|
||||
missing_files.append(alternatives[0]["name"])
|
||||
continue
|
||||
|
||||
if chosen is None:
|
||||
if refusal:
|
||||
rejected_files.append(refusal)
|
||||
@@ -1508,6 +1538,7 @@ def generate_emulator_pack(
|
||||
seen_destinations.add(dest)
|
||||
_register_path(dest, seen_destinations, seen_parents)
|
||||
seen_lower.add(dest.lower())
|
||||
packed_at[dest.lower()] = local_path
|
||||
total_files += 1
|
||||
|
||||
# Remove empty ZIP (no files packed and no missing = nothing to ship)
|
||||
|
||||
+57
-2
@@ -1463,7 +1463,12 @@ def verify_emulator(
|
||||
A region priority list narrows the report the same way a pack built with the
|
||||
same list would be narrowed, through the emulator pack's own drop set.
|
||||
"""
|
||||
from packpaths import _archive_destination, _resolve_destination
|
||||
from packpaths import (
|
||||
_archive_destination,
|
||||
_register_path,
|
||||
_resolve_destination,
|
||||
placement_block,
|
||||
)
|
||||
|
||||
load_emulator_profiles(emulators_dir)
|
||||
zip_contents = build_zip_contents_index(db)
|
||||
@@ -1491,7 +1496,16 @@ def verify_emulator(
|
||||
|
||||
region_drops = emulator_region_drops(selected, standalone, regions)
|
||||
|
||||
for emu_name, profile in selected:
|
||||
# The emulator pack walks profiles in name order and keeps the first
|
||||
# file at a path, folding case: a later profile's different file there
|
||||
# (zesarux pentagon.rom after speccy's PENTAGON.ROM) is not in the pack.
|
||||
sha1_by_path = {
|
||||
entry.get("path"): sha1 for sha1, entry in db.get("files", {}).items()
|
||||
}
|
||||
placed: dict[str, tuple[str | None, str, str]] = {}
|
||||
placed_files: set[str] = set()
|
||||
placed_parents: set[str] = set()
|
||||
for emu_name, profile in sorted(selected):
|
||||
files = expand_directory_entries(
|
||||
filter_files_by_mode(profile.get("files", []), standalone),
|
||||
db,
|
||||
@@ -1701,7 +1715,48 @@ def verify_emulator(
|
||||
held = [a for a in alternatives if a[0]["status"] == Status.OK]
|
||||
if held and len(alternatives) > 1:
|
||||
alternatives = held[:1]
|
||||
# What the emulator pack places here: an accepted file, else a
|
||||
# file whose hash the profile contradicts. A refused copy is held
|
||||
# but never packed.
|
||||
fallback_reason = "declared hash contradicted by the local file"
|
||||
packed = next(
|
||||
(a[0].get("path") for a in alternatives
|
||||
if a[0]["status"] == Status.OK and a[0].get("path")),
|
||||
None,
|
||||
) or next(
|
||||
(a[0].get("path") for a in alternatives
|
||||
if a[0]["status"] == Status.UNTESTED
|
||||
and a[0].get("reason") == fallback_reason and a[0].get("path")),
|
||||
None,
|
||||
)
|
||||
held = packed or next(
|
||||
(a[0].get("path") for a in alternatives
|
||||
if a[0]["status"] != Status.MISSING and a[0].get("path")),
|
||||
None,
|
||||
)
|
||||
block = placement_block(
|
||||
dest, placed_files, set(placed), placed_parents, True
|
||||
)
|
||||
block_reason = ""
|
||||
if block and held is not None:
|
||||
other_sha1, owner, other_dest = placed.get(dest.lower(), (None, "", ""))
|
||||
if block == "path_conflict":
|
||||
block_reason = "a packed file occupies its directory"
|
||||
elif block == "case_twin":
|
||||
block_reason = (
|
||||
f"packed only as {other_dest}, from {owner}"
|
||||
if sha1_by_path.get(held) == other_sha1
|
||||
else f"the pack holds {owner}'s {other_dest} at this path"
|
||||
)
|
||||
elif sha1_by_path.get(held) != other_sha1:
|
||||
block_reason = f"the pack holds {owner}'s {other_dest} at this path"
|
||||
elif not block and packed is not None:
|
||||
placed[dest.lower()] = (sha1_by_path.get(packed), emu_name, dest)
|
||||
_register_path(dest, placed_files, placed_parents)
|
||||
for result, required, hle in alternatives:
|
||||
if block_reason and result["status"] != Status.MISSING:
|
||||
result["status"] = Status.MISSING
|
||||
result["reason"] = block_reason
|
||||
result["destination"] = dest
|
||||
details.append(result)
|
||||
|
||||
|
||||
Reference in new issue
Block a user