diff --git a/install.ps1 b/install.ps1 index d31fa3a10..48f2ca54b 100644 --- a/install.ps1 +++ b/install.ps1 @@ -16,7 +16,7 @@ # and Invoke-WebRequest throws on a cut transfer before the hash is read: # the site's build rewrites this line there (scripts/sitebootstrap.py). $mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that." - $defaultInstallSha256 = "6e625f7a8c9c3ba095c8240dc3e8482dddd514e438302a576a2f80807e79a547" + $defaultInstallSha256 = "627e9c3bb72daacae022a93f5ca2ba010cd8fb025ef92d69f020734575ee9bad" $maximumInstallerBytes = 2MB $installerExit = 0 $installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null } diff --git a/install.py b/install.py index 0bd9c4d18..21dcb64d4 100644 --- a/install.py +++ b/install.py @@ -1246,11 +1246,14 @@ def _retroarch_cfg_dir( A value left empty or at `default` is the directory RetroArch falls back on, `default` under app_dir. None when the config is unreadable or does - not set the key. + not set the key. A config this user cannot read is said once, like a + closed folder: a retroarch.cfg a `sudo retroarch` left to root hid the + setup without a word. """ try: lines = cfg_path.read_text(encoding="utf-8", errors="replace").splitlines() - except OSError: + except OSError as exc: + _note_refused(cfg_path, exc) return None for line in lines: line = line.strip() diff --git a/install.sh b/install.sh index d98b63192..7e3eb0e3f 100755 --- a/install.sh +++ b/install.sh @@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins # curl or wget stop on a cut transfer before the hash is read: the site's # build rewrites this line there (scripts/sitebootstrap.py). MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that." -DEFAULT_INSTALL_SHA256="6e625f7a8c9c3ba095c8240dc3e8482dddd514e438302a576a2f80807e79a547" +DEFAULT_INSTALL_SHA256="627e9c3bb72daacae022a93f5ca2ba010cd8fb025ef92d69f020734575ee9bad" MAX_INSTALLER_BYTES=2097152 cleanup() { diff --git a/install/launchers/index.json b/install/launchers/index.json index bbf635adc..45856d1f4 100644 --- a/install/launchers/index.json +++ b/install/launchers/index.json @@ -27,8 +27,8 @@ { "dest": "roms/ports/retrobios/install.py", "repo_path": "install.py", - "size": 1079846, - "sha256": "6e625f7a8c9c3ba095c8240dc3e8482dddd514e438302a576a2f80807e79a547", + "size": 1080043, + "sha256": "627e9c3bb72daacae022a93f5ca2ba010cd8fb025ef92d69f020734575ee9bad", "executable": false }, { @@ -71,8 +71,8 @@ "muos": { "archive": { "dest": "ARCHIVE/RetroBIOS.muxapp", - "size": 1133023, - "sha256": "ff64d48ae2d5bd2dcf341917c55da88f8ca7174a2ccbc4e7786b69444da11ff8" + "size": 1133220, + "sha256": "818f6453e8c441729b395a765f47735d5c3710a03db288ab5609b4485710d2cd" }, "members": [ { @@ -92,8 +92,8 @@ { "name": "RetroBIOS/install.py", "repo_path": "install.py", - "size": 1079846, - "sha256": "6e625f7a8c9c3ba095c8240dc3e8482dddd514e438302a576a2f80807e79a547", + "size": 1080043, + "sha256": "627e9c3bb72daacae022a93f5ca2ba010cd8fb025ef92d69f020734575ee9bad", "executable": false }, { @@ -166,8 +166,8 @@ { "dest": ".config/modules/retrobios/install.py", "repo_path": "install.py", - "size": 1079846, - "sha256": "6e625f7a8c9c3ba095c8240dc3e8482dddd514e438302a576a2f80807e79a547", + "size": 1080043, + "sha256": "627e9c3bb72daacae022a93f5ca2ba010cd8fb025ef92d69f020734575ee9bad", "executable": false }, { diff --git a/tests/test_install_experience.py b/tests/test_install_experience.py index 4a7306aa0..ba86703cb 100644 --- a/tests/test_install_experience.py +++ b/tests/test_install_experience.py @@ -823,6 +823,38 @@ class APartlyClosedHome(unittest.TestCase): self.assertEqual([entry["bios_dir"] for entry in detect["platforms"]], [str(system)]) +class AnUnreadableRetroArchConfigIsSaid(unittest.TestCase): + """A retroarch.cfg a `sudo retroarch` left at 0600 for root was read as + no config at all: RetroArch was not found and nothing said why.""" + + @unittest.skipIf(os.name == "nt" or os.geteuid() == 0, + "a file without read permission is POSIX") + def test_the_closed_config_is_named(self): + with FakeRepository() as repo: + home = repo.root / "home" + cfg = home / ".config" / "retroarch" / "retroarch.cfg" + cfg.parent.mkdir(parents=True) + cfg.write_text('system_directory = "/media/card/bios"\n') + env = {**repo.env(), "HOME": str(home), "RETROBIOS_OS": "linux"} + os.chmod(cfg, 0o000) + try: + proc = subprocess.run( + [sys.executable, str(REPO_ROOT / "install.py"), "--check", + "--no-input", "--events"], + env=env, capture_output=True, text=True, timeout=60, + stdin=subprocess.DEVNULL) + finally: + os.chmod(cfg, 0o644) + self.assertNotIn("Traceback", proc.stderr) + refusal = (f"Could not look for setups: this user cannot open {cfg} " + "(Permission denied)") + self.assertEqual(" ".join(proc.stderr.split()).count(refusal), 1, proc.stderr) + events = [json.loads(line) for line in proc.stdout.splitlines()] + unsearched = [event for event in events if event["event"] == "unsearched"] + self.assertEqual([(event["folder"], event["reason"]) for event in unsearched], + [(str(cfg), "Permission denied")]) + + class OutputToAFileAsksNothing(unittest.TestCase): """`install.py > log.txt` at a terminal: the menu went into the file and the run waited on an answer to a prompt nobody could see."""