mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
fix: quote rom and core names in yaml
YAML 1.1 reads an unquoted 01 as the integer 1 and 81 as 81, so the manager set stopped naming the file its driver opens and the API published "cores": [2048] as a number where consumers match strings. Ground truth from MAME 0.289 at the revision the profile cites: src/mame/vtech/crvision.cpp:957 loads "01" and "23". The root cause was the scraper: _hash_merge wrote these names through an f-string, so quoting the profiles alone would be undone on the next refresh. _yaml_scalar now quotes every name, archive and description it writes.
This commit is contained in:
1 parent
5d417c8229
commit
597a8ff919
7 files changed
+66
-11
No files matched your search
+1
-1
@@ -7,7 +7,7 @@ profiled_date: "2026-03-22"
|
|||||||
source_commit: "e70c3f82d2b861c64943aaff7fcc29a63013997d"
|
source_commit: "e70c3f82d2b861c64943aaff7fcc29a63013997d"
|
||||||
core_version: "1.0"
|
core_version: "1.0"
|
||||||
display_name: "2048"
|
display_name: "2048"
|
||||||
cores: [2048]
|
cores: ["2048"]
|
||||||
systems: []
|
systems: []
|
||||||
files: []
|
files: []
|
||||||
notes: >
|
notes: >
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ profiled_date: "2026-03-22"
|
|||||||
source_commit: "fa7094910d040baa5fd8b11dbf6a1a618330ecd9"
|
source_commit: "fa7094910d040baa5fd8b11dbf6a1a618330ecd9"
|
||||||
core_version: "1.0a"
|
core_version: "1.0a"
|
||||||
display_name: "Sinclair - ZX 81 (EightyOne)"
|
display_name: "Sinclair - ZX 81 (EightyOne)"
|
||||||
cores: [81]
|
cores: ["81"]
|
||||||
systems:
|
systems:
|
||||||
- sinclair-zx81
|
- sinclair-zx81
|
||||||
- sinclair-zx80
|
- sinclair-zx80
|
||||||
|
|||||||
+2
-2
@@ -3543,11 +3543,11 @@ files:
|
|||||||
source_ref: "src/mame/vtech/crvision.cpp:955-959"
|
source_ref: "src/mame/vtech/crvision.cpp:955-959"
|
||||||
note: "Salora Manager (Finnish variant)"
|
note: "Salora Manager (Finnish variant)"
|
||||||
contents:
|
contents:
|
||||||
- name: 01
|
- name: "01"
|
||||||
description: ROM bank 0-1
|
description: ROM bank 0-1
|
||||||
size: 8192
|
size: 8192
|
||||||
crc32: "702f4cf5"
|
crc32: "702f4cf5"
|
||||||
- name: 23
|
- name: "23"
|
||||||
description: ROM bank 2-3
|
description: ROM bank 2-3
|
||||||
size: 8192
|
size: 8192
|
||||||
crc32: "46489d88"
|
crc32: "46489d88"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"windows": [
|
"windows": [
|
||||||
81,
|
"81",
|
||||||
"a5200",
|
"a5200",
|
||||||
"abuse",
|
"abuse",
|
||||||
"arduous",
|
"arduous",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ scraped_at: "2026-03-26T00:00:00Z"
|
|||||||
targets:
|
targets:
|
||||||
windows:
|
windows:
|
||||||
architecture: x86_64
|
architecture: x86_64
|
||||||
cores: [81, a5200, abuse, arduous, atari800, azahar, bennugd, bk, bluemsx, bsnes,
|
cores: ['81', a5200, abuse, arduous, atari800, azahar, bennugd, bk, bluemsx, bsnes,
|
||||||
bstone, cannonball, cap32, catacombgl, cdogs, cemu, cgenius, citron, clk, corsixth,
|
bstone, cannonball, cap32, catacombgl, cdogs, cemu, cgenius, citron, clk, corsixth,
|
||||||
demul, devilutionx, dhewm3, dice, dolphin, dosbox_pure, dxx-rebirth, easyrpg,
|
demul, devilutionx, dhewm3, dice, dolphin, dosbox_pure, dxx-rebirth, easyrpg,
|
||||||
ecwolf, eduke32, eka2l1, emuscv, etlegacy, fake08, fallout1-ce, fallout2-ce,
|
ecwolf, eduke32, eka2l1, emuscv, etlegacy, fake08, fallout1-ce, fallout2-ce,
|
||||||
|
|||||||
@@ -507,7 +507,7 @@ def _append_new_entries(text: str, files: list[dict], original: str) -> str:
|
|||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
for fe in new_entries:
|
for fe in new_entries:
|
||||||
lines.append(f"\n - name: {fe['name']}")
|
lines.append(f"\n - name: {_yaml_scalar(fe['name'])}")
|
||||||
lines.append(f" required: {str(fe['required']).lower()}")
|
lines.append(f" required: {str(fe['required']).lower()}")
|
||||||
lines.append(" category: bios_zip")
|
lines.append(" category: bios_zip")
|
||||||
if fe.get("source_ref"):
|
if fe.get("source_ref"):
|
||||||
@@ -521,13 +521,22 @@ def _append_new_entries(text: str, files: list[dict], original: str) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def _yaml_scalar(value) -> str:
|
||||||
|
"""Quote a scalar so YAML reads back exactly what the source said.
|
||||||
|
|
||||||
|
A MAME ROM named ``01`` written bare re-parses as the integer 1, and the
|
||||||
|
set stops naming the file the driver loads. Quoting is not cosmetic here.
|
||||||
|
"""
|
||||||
|
return json.dumps(str(value), ensure_ascii=False)
|
||||||
|
|
||||||
|
|
||||||
def _format_contents(contents: list[dict]) -> str:
|
def _format_contents(contents: list[dict]) -> str:
|
||||||
"""Format a contents list as YAML text."""
|
"""Format a contents list as YAML text."""
|
||||||
lines = [" contents:"]
|
lines = [" contents:"]
|
||||||
for rom in contents:
|
for rom in contents:
|
||||||
lines.append(f" - name: {rom['name']}")
|
lines.append(f" - name: {_yaml_scalar(rom['name'])}")
|
||||||
if rom.get("description"):
|
if rom.get("description"):
|
||||||
lines.append(f" description: {rom['description']}")
|
lines.append(f" description: {_yaml_scalar(rom['description'])}")
|
||||||
if rom.get("size"):
|
if rom.get("size"):
|
||||||
lines.append(f" size: {rom['size']}")
|
lines.append(f" size: {rom['size']}")
|
||||||
if rom.get("crc32"):
|
if rom.get("crc32"):
|
||||||
@@ -569,8 +578,8 @@ def _backup_and_write_fbneo(path: str, data: dict, hashes: dict) -> None:
|
|||||||
if new_roms:
|
if new_roms:
|
||||||
lines = []
|
lines = []
|
||||||
for fe in new_roms:
|
for fe in new_roms:
|
||||||
lines.append(f' - name: "{fe["name"]}"')
|
lines.append(f" - name: {_yaml_scalar(fe['name'])}")
|
||||||
lines.append(f" archive: {fe['archive']}")
|
lines.append(f" archive: {_yaml_scalar(fe['archive'])}")
|
||||||
lines.append(f" required: {str(fe.get('required', True)).lower()}")
|
lines.append(f" required: {str(fe.get('required', True)).lower()}")
|
||||||
if fe.get("size"):
|
if fe.get("size"):
|
||||||
lines.append(f" size: {fe['size']}")
|
lines.append(f" size: {fe['size']}")
|
||||||
|
|||||||
@@ -196,6 +196,52 @@ class TestMameMerge(unittest.TestCase):
|
|||||||
self.assertTrue(pgm["required"])
|
self.assertTrue(pgm["required"])
|
||||||
self.assertEqual(pgm["category"], "bios_zip")
|
self.assertEqual(pgm["category"], "bios_zip")
|
||||||
|
|
||||||
|
def test_numeric_looking_rom_name_survives_the_write(self) -> None:
|
||||||
|
"""MAME ships ROMs named 01 and 23. Bare YAML turns them into numbers.
|
||||||
|
|
||||||
|
The manager set loads "01"; written unquoted it re-parses as the
|
||||||
|
integer 1 and the profile stops naming the file the driver opens.
|
||||||
|
"""
|
||||||
|
from scripts.scraper._hash_merge import (
|
||||||
|
_append_new_entries,
|
||||||
|
_format_contents,
|
||||||
|
)
|
||||||
|
|
||||||
|
contents = [
|
||||||
|
{"name": "01", "description": "ROM bank 0-1", "size": 8192,
|
||||||
|
"crc32": "702f4cf5"},
|
||||||
|
{"name": "23", "description": "ROM bank 2-3", "size": 8192,
|
||||||
|
"crc32": "46489d88"},
|
||||||
|
]
|
||||||
|
document = yaml.safe_load(
|
||||||
|
"files:\n - name: manager.zip\n" + _format_contents(contents)
|
||||||
|
)
|
||||||
|
names = [rom["name"] for rom in document["files"][0]["contents"]]
|
||||||
|
self.assertEqual(names, ["01", "23"])
|
||||||
|
for name in names:
|
||||||
|
self.assertIsInstance(name, str)
|
||||||
|
|
||||||
|
original = "emulator: MAME\nfiles:\n - name: neogeo.zip\n"
|
||||||
|
appended = _append_new_entries(
|
||||||
|
original,
|
||||||
|
[{
|
||||||
|
"name": "manager.zip",
|
||||||
|
"required": False,
|
||||||
|
"category": "bios_zip",
|
||||||
|
"source_ref": "src/mame/vtech/crvision.cpp:955-959",
|
||||||
|
"contents": contents,
|
||||||
|
}],
|
||||||
|
original,
|
||||||
|
)
|
||||||
|
entry = next(
|
||||||
|
f
|
||||||
|
for f in yaml.safe_load(appended)["files"]
|
||||||
|
if f["name"] == "manager.zip"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
[rom["name"] for rom in entry["contents"]], ["01", "23"]
|
||||||
|
)
|
||||||
|
|
||||||
def test_merge_preserves_non_bios_files(self) -> None:
|
def test_merge_preserves_non_bios_files(self) -> None:
|
||||||
profile = _make_mame_profile()
|
profile = _make_mame_profile()
|
||||||
profile["files"].append({"name": "hiscore.dat", "required": False})
|
profile["files"].append({"name": "hiscore.dat", "required": False})
|
||||||
|
|||||||
Reference in new issue
Block a user