fix: install emuelec configs from the boot copy

duckstation.sh quotes its glob, so its copy names a file called * and
installs nothing. userconfig-setup copies /usr/config into
/storage/.config at every boot, an existing file kept (false | cp -i),
and /emuelec links there: that copy installs settings.ini and
advmame.rc. A quoted glob is no install, and a redirection ends the
copy's operands. Rescraped at v4.8: only these installs change.
This commit is contained in:
Abdessamad Derraz committed 2026-11-11 11:57:12 +01:00
1 parent b29500846b
commit 8770b9c067
4 files changed
+144 -32

No files matched your search

+44 -23
View File
@@ -4295,8 +4295,8 @@ launchers:
\ PathPAL unset"
fails_when_missing: false
installs:
path: /emuelec/configs/duckstation/settings.ini
source_ref: "packages/sx05re/emulators/duckstation/scripts/duckstation.sh:15"
path: /storage/.config/emuelec/configs/duckstation/settings.ini
source_ref: "packages/sx05re/emulators/duckstation/package.mk:56, packages/sysutils/systemd/scripts/userconfig-setup:12"
kept_if_present: true
overrides: []
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:207-209, packages/sx05re/emulators/duckstation/config/settings.ini:6-9,\
@@ -4372,7 +4372,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4391,7 +4392,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4409,7 +4411,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4428,7 +4431,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4446,7 +4450,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4465,7 +4470,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4483,7 +4489,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4502,7 +4509,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4520,7 +4528,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4539,7 +4548,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4557,7 +4567,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4576,7 +4587,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4594,7 +4606,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4613,7 +4626,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4631,7 +4645,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4650,7 +4665,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4667,7 +4683,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4684,7 +4701,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4703,7 +4721,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4721,7 +4740,8 @@ launchers:
depends_on_option: system != arcade
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
@@ -4740,7 +4760,8 @@ launchers:
fails_when_missing: false
installs:
path: /emuelec/configs/advmame/advmame.rc
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
source_ref: "packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sysutils/systemd/scripts/userconfig-setup:12,\
\ packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
kept_if_present: false
overrides:
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
+37 -4
View File
@@ -40,6 +40,10 @@ EMULATORS = f"{SX05RE}/emulators"
LIBRETRO = f"{SX05RE}/libretro"
RETROARCH_MK = f"{SX05RE}/libretro_base/retroarch/package.mk"
BIOS_ROOT = "/storage/roms/bios"
EMUELEC_MK = f"{SX05RE}/emuelec/package.mk"
# The copy of every package's /usr/config into /storage/.config at each boot,
# an existing file kept (cp -i answered by false).
USERCONFIG = "packages/sysutils/systemd/scripts/userconfig-setup"
# The roms root that holds it (packages/sx05re/libretro_base/retroarch/package.mk:112,117).
ROMS_ROOT = "/storage/roms"
@@ -106,6 +110,19 @@ class Runs:
return (RUN_EMU, set(self.of(name).lines))
def _storage_path(tree: RepoTree, target: str) -> str:
"""target with the /emuelec link resolved to the folder it points at.
The emuelec package links /emuelec to /storage/.config/emuelec, where
the first-boot copy of /usr/config lands.
"""
mk = _read(tree, EMUELEC_MK)
_line, link = mk.find(r"ln -sf (/storage/\S+) \$\{INSTALL\}(/emuelec)$", "/emuelec link")
if target == link.group(2) or target.startswith(link.group(2) + "/"):
return link.group(1) + target[len(link.group(2)):]
return target
def _evidence(
record: Launcher,
script: Script,
@@ -113,15 +130,28 @@ def _evidence(
keys: list[str],
source_name: str = "",
rewrites: Iterable[int] = (),
tree: RepoTree | None = None,
installed: Iterable[tuple[str, Iterable[int]]] = (),
) -> Launcher:
"""A config record with the start script lines that put its file in place.
"""A config record with the lines that put its file in place: the
first-boot copy of /usr/config when ``tree`` is given, then the start
script's own. ``installed`` are the package.mk lines putting the file
in /usr/config.
``rewrites`` are lines the extractor read as rewriting the record's
values without naming their keys (advmame.sh's sed of /roms/mame).
"""
placement = config_placement(script, target, keys, source_name=source_name)
placements = []
if tree is not None:
setup = _read(tree, USERCONFIG)
placements.append(config_placement(
setup, _storage_path(tree, target), required=False, sources=("/usr/config/",)
))
placement = config_placement(script, target, keys, source_name=source_name,
required=not placements or not placements[0].install)
placement.overrides |= set(rewrites)
fields = evidence_fields([placement])
placements.append(placement)
fields = evidence_fields(placements, installed)
record.installs = fields["installs"]
record.kept_if_present = fields["kept_if_present"]
record.overrides = fields["overrides"]
@@ -356,6 +386,8 @@ def duckstation(tree: RepoTree, runs: Runs) -> list[Launcher]:
script,
script.expand("${CONFIG_DIR}/settings.ini", run_line, set()),
[f"[{s}] {k}" for s, k in (folder_key, *file_keys)],
tree=tree,
installed=[(mk.path, {mk_line})],
)]
@@ -569,7 +601,8 @@ def advancemame(tree: RepoTree, runs: Runs) -> list[Launcher]:
target = script.expand("${CONFIG_DIR}/advmame.rc", run_line, set())
def proved(record: Launcher, key: str) -> Launcher:
return _evidence(record, script, target, [key], rewrites={sed_line})
return _evidence(record, script, target, [key], rewrites={sed_line}, tree=tree,
installed=[(mk.path, {mk_line for _, _, mk_line in configs})])
records = []
for key, folder in value:
+19 -2
View File
@@ -483,6 +483,15 @@ def _guarded(script: Script, number: int, target: str) -> bool:
return False
def _quoted_glob(command: str) -> bool:
"""Whether the source of a copy holds a "*" only inside quotes."""
found = [w for w in words(command)[1:] if not w.raw.startswith("-")]
if len(found) < 2:
return False
raw = found[0].raw
return "*" in raw and "*" not in re.sub(r'"[^"]*"|\'[^\']*\'', "", raw)
def config_placement(
script: Script,
target: str,
@@ -511,12 +520,16 @@ def config_placement(
args = []
for word in words(line[copy.start(1):])[1:]:
# The command ends at a separator or a redirection.
if word.raw in {";", "&&", "||", "|"} or re.match(r"\d*>", word.raw):
if word.raw in {";", "&&", "||", "|"} or re.match(r"\d*>|&>", word.raw):
break
args.append(word.text)
operands = [a for a in args if not a.startswith("-")]
if not operands:
continue
# A quoted "*" is a file named *, which no package installs:
# the copy does nothing (EmuELEC's duckstation.sh).
if _quoted_glob(line[copy.start(1):]):
continue
destination = script.expand(operands[-1], number, set()).rstrip("/")
source = script.expand(operands[0], number, set()).rstrip("/")
hits = target == destination or target.startswith(destination + "/") or (
@@ -536,7 +549,11 @@ def config_placement(
continue
if sources and not source.startswith(sources):
continue
skip = "-n" in args or "--ignore-existing" in args
# cp -i fed by false answers no to every overwrite.
prompted = any(
a.startswith("-") and not a.startswith("--") and "i" in a[1:] for a in args
) and re.search(r"\bfalse\s*\|\s*$", line[:copy.start(1)])
skip = "-n" in args or "--ignore-existing" in args or bool(prompted)
else:
skip = False
install.add(number)
+44 -3
View File
@@ -229,11 +229,25 @@ DUCKSTATION_SH = text(
CONFIG_DIR="/emuelec/configs/duckstation"
duckstation-nogui -fullscreen -settings "${CONFIG_DIR}/settings.ini" -- "${1}"
if [ ! -d "${CONFIG_DIR}" ]; then
cp -rf /usr/config/emuelec/configs/duckstation/* "${CONFIG_DIR}"
cp -rf "/usr/config/emuelec/configs/duckstation/*" "${CONFIG_DIR}"
fi
"""
)
# packages/sysutils/systemd/scripts/userconfig-setup:11-12 at v4.8.
USERCONFIG = text(
"""
# Copy config files, but don't overwrite - this should replace our sample files
false | cp -iRp /usr/config/* /storage/.config/ &>/dev/null
"""
)
EMUELEC_MK = text(
"""
ln -sf /storage/.config/emuelec ${INSTALL}/emuelec
"""
)
def yabasanshiro_sh(program: str) -> str:
return text(
@@ -400,6 +414,8 @@ FILES = {
f"{EMU}/duckstation/config/settings.ini": DUCKSTATION_INI,
f"{EMU}/duckstation/package.mk": DUCKSTATION_MK,
f"{EMU}/duckstation/scripts/duckstation.sh": DUCKSTATION_SH,
el.USERCONFIG: USERCONFIG,
el.EMUELEC_MK: EMUELEC_MK,
el.YABASANSHIRO_SCRIPTS[0]: yabasanshiro_sh("yabasanshiro"),
el.YABASANSHIRO_SCRIPTS[1]: yabasanshiro_sh("yabasanshiro1_5"),
f"{EMU}/jzintv/scripts/jzintv.sh": JZINTV_SH,
@@ -540,12 +556,37 @@ class StandaloneRecords(unittest.TestCase):
(record,) = records(el.duckstation)
self.assertEqual((record["kind"], record["search_dir"]), ("scans_dir", "/storage/roms/bios"))
def test_duckstation_config_is_kept_when_present(self):
def test_duckstation_config_comes_from_the_boot_copy(self):
"""duckstation.sh quotes its glob: its copy names a file called *, so
the settings.ini in place is the one userconfig-setup copies from
/usr/config, an existing file kept (false | cp -i)."""
(record,) = records(el.duckstation)
self.assertEqual(record["installs"]["path"], "/emuelec/configs/duckstation/settings.ini")
self.assertEqual(
record["installs"],
{"path": "/storage/.config/emuelec/configs/duckstation/settings.ini",
"source_ref": f"{EMU}/duckstation/package.mk:1, {el.USERCONFIG}:2"},
)
self.assertIs(record["kept_if_present"], True)
self.assertEqual(record["overrides"], [])
def test_an_unquoted_glob_in_the_start_script_installs_too(self):
unquoted = DUCKSTATION_SH.replace(
'"/usr/config/emuelec/configs/duckstation/*"', "/usr/config/emuelec/configs/duckstation/*"
)
(record,) = records(el.duckstation, **{f"{EMU}/duckstation/scripts/duckstation.sh": unquoted})
self.assertEqual(record["installs"]["path"], "/emuelec/configs/duckstation/settings.ini")
self.assertIs(record["kept_if_present"], True)
def test_without_a_boot_copy_the_quoted_glob_installs_nothing(self):
with self.assertRaises(LauncherPatternMissing):
records(el.duckstation, **{el.USERCONFIG: "#!/bin/sh\n"})
def test_an_overwriting_boot_copy_does_not_keep_the_file(self):
(record,) = records(el.duckstation, **{
el.USERCONFIG: "cp -Rp /usr/config/* /storage/.config/ &>/dev/null\n",
})
self.assertIs(record["kept_if_present"], False)
def test_duckstation_with_a_fixed_bios_path_raises(self):
changed = DUCKSTATION_INI.replace("PathPAL =", "PathPAL = /storage/roms/bios/scph5502.bin")
with self.assertRaises(LauncherPatternMissing):