chore: merge main into the audit 17 answers

# Conflicts:
#	install.ps1
#	install.sh
#	install/launchers/index.json
This commit is contained in:
Abdessamad Derraz committed 2026-10-27 12:48:04 +01:00
commit a67dc339bc
10 files changed
+153 -69

No files matched your search

+22 -20
View File
@@ -835,28 +835,30 @@ class BiosIntegrity(Scratch):
return str(self.tmp / "database.json")
class SubjectsFollowTheRepositoryHook(unittest.TestCase):
"""The vocabulary rules live in the commit-msg hook alone: a copy in the
runner put the very words the history refuses into a tracked file."""
class SubjectsFollowTheRepositoryRules(unittest.TestCase):
"""The commit rules live in scripts/commit_rules.py, which the local hook
calls: a copy in the hook alone let CI check only the shape."""
def test_a_refusal_comes_from_the_hook(self):
def test_the_runner_reads_the_tracked_rules(self):
import commit_rules # noqa: PLC0415
for subject in ("chore: fix the broken manifests", "update things", "chore: " + "a" * 60):
with self.subTest(subject=subject):
self.assertEqual(ar.check_subject(subject), commit_rules.problems(subject))
self.assertTrue(ar.check_subject(subject))
self.assertEqual(ar.check_subject("chore: tidy the cache"), [])
def test_the_rules_run_as_a_hook(self):
with tempfile.TemporaryDirectory() as tmp:
hook = Path(tmp) / "commit-msg"
hook.write_text('#!/bin/sh\ngrep -q forbiddenword "$1" && echo refused && exit 1\nexit 0\n')
hook.chmod(0o755)
real = subprocess.run
def fake(argv, *args, **kwargs):
if argv[:3] == ["git", "rev-parse", "--git-path"]:
return subprocess.CompletedProcess(argv, 0, stdout=str(hook) + "\n", stderr="")
return real(argv, *args, **kwargs)
with unittest.mock.patch.object(ar.subprocess, "run", side_effect=fake):
self.assertEqual(ar.check_subject("chore: tidy the cache"), [])
self.assertEqual(ar.check_subject("chore: add forbiddenword"), ["refused"])
def test_the_shape_is_checked_without_a_hook(self):
problems = ar.check_subject("not a subject that follows the type rule at all, too long")
self.assertTrue(any("50 at most" in p for p in problems))
self.assertTrue(any("type: description" in p for p in problems))
message = Path(tmp) / "MSG"
script = REPO_ROOT / "scripts" / "commit_rules.py"
for text, code in (("fix: keep the cache\n", 0), ("fix: a broken cache\n", 1),
("fix: keep it\n\nCo-Authored-By: x\n", 1)):
message.write_text(text)
done = subprocess.run([sys.executable, str(script), str(message)],
capture_output=True, text=True, check=False)
with self.subTest(text=text):
self.assertEqual(done.returncode, code, done.stderr)
if __name__ == "__main__":
+30 -5
View File
@@ -9,6 +9,7 @@ import importlib.util
import io
import json
import os
import stat
import shlex
import re
import shutil
@@ -5740,11 +5741,35 @@ class AFileYouHadIsKept(unittest.TestCase):
@unittest.skipUnless(hasattr(os, "getuid"), "user ids are POSIX")
def test_a_holder_another_user_owns_is_refused(self):
(self.home / install.BACKUP_DIR).mkdir()
with self.assertRaises(OSError):
with unittest.mock.patch.object(install.os, "getuid", return_value=os.getuid() + 1):
install._check_holder(self.home / install.BACKUP_DIR)
install._check_holder(self.home / install.BACKUP_DIR)
holder = self.home / install.BACKUP_DIR
holder.mkdir()
real = os.lstat
def planted(path, *args, **kwargs):
info = real(path, *args, **kwargs)
if Path(path) != holder:
return info
fields = list(info)
fields[stat.ST_UID] = info.st_uid + 2
return os.stat_result(fields)
with self.assertRaises(OSError), \
unittest.mock.patch.object(install.os, "lstat", side_effect=planted):
install._check_holder(holder)
install._check_holder(holder)
@unittest.skipUnless(hasattr(os, "getuid"), "user ids are POSIX")
def test_a_storage_with_one_owner_for_every_file_takes_the_holder(self):
# Android's shared storage, seen from Termux on Android 17: a folder
# the run has just made is shown as another user's, like every other
# file there. Refusing it left 25 files unreplaced on a real phone.
holder = self.home / install.BACKUP_DIR
holder.mkdir()
with unittest.mock.patch.object(install.os, "getuid", return_value=os.getuid() + 1):
install._check_holder(holder)
(self.bios / "x.bin").write_bytes(self.OLD)
self.assertTrue(self._download("x.bin")[1])
self.assertEqual((self._run_folder() / "system" / "x.bin").read_bytes(), self.OLD)
def test_restore_refuses_a_folder_the_installer_did_not_write(self):
planted = self.home / install.BACKUP_DIR / "20260101-000000"
+15
View File
@@ -337,6 +337,21 @@ class ProgressOutput(unittest.TestCase):
self.assertIn("failed: x.bin (HTTP 404)", out)
self.assertIn("2.0 KB downloaded in 0:02", out)
def test_files_not_set_aside_get_a_remedy_not_a_retry(self):
# A real Android run: 25 files whose backup folder was refused, told
# to run again, which refuses them the same way.
reason = f"{install.NOT_KEPT} (/sdcard/RetroArch/retrobios-backup belongs to another user)"
buf = io.StringIO()
with contextlib.redirect_stdout(buf), self.assertRaises(SystemExit) as end:
install._report_outcome(
[Path("/b")], 3, 0, 2, 0, False,
failures=[("a.zip", reason), ("b.zip", reason)],
)
out = buf.getvalue()
self.assertEqual(end.exception.code, 1)
self.assertIn("The files in place were left as they were", out)
self.assertNotIn("retry only those", out)
class CommandLine(unittest.TestCase):
def test_a_dry_run_writes_nothing(self):
+2 -1
View File
@@ -168,7 +168,8 @@ class NoMarketingVocabulary(unittest.TestCase):
def test_no_tracked_text_uses_them(self):
offenders = []
for path in _tracked():
if path.name == "test_prose_style.py":
# This file and the commit rules have to name the words they refuse.
if path.name in {"test_prose_style.py", "commit_rules.py"}:
continue
text = path.read_text(encoding="utf-8", errors="replace")
for number, line in enumerate(text.splitlines(), 1):