mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
fix: skip data trees a read-only folder refuses
A BIOS folder this user cannot write no longer tries each data tree's archive and blames its URL with a raw errno. The tree is counted failed for the same cause as the BIOS files, so the summary keeps its one line and its advice.
This commit is contained in:
1 parent
f8702a19f7
commit
2ecbea56b5
5 files changed
+59
-13
No files matched your search
+1
-1
@@ -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 = "78ef177611168c1c7699cafa8982f901aaaf5342b6c55d6e158ba18fb4cc0ae2"
|
||||
$defaultInstallSha256 = "c8cf4b65474279c30c2e1781028d3e05f195e26dd759a98a37db3477b6dd3014"
|
||||
$maximumInstallerBytes = 2MB
|
||||
$installerExit = 0
|
||||
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
|
||||
|
||||
+22
-3
@@ -7198,7 +7198,12 @@ def install_data_directory(entry: dict, bios_path: Path,
|
||||
# Kept apart, so the advice is the offline one, not the network's.
|
||||
counts["error"] = OfflineReason(str(exc))
|
||||
except (urllib.error.URLError, OSError, ValueError, tarfile.TarError) as exc:
|
||||
counts["error"] = str(getattr(exc, "reason", None) or exc)
|
||||
# The tree's folder refused, not the source: said as the BIOS files
|
||||
# say it, never as an archive that could not be read.
|
||||
counts["error"] = (NOT_WRITABLE if isinstance(exc, OSError)
|
||||
and not isinstance(exc, urllib.error.URLError)
|
||||
and _write_refused(exc) and not _folder_writable(root)
|
||||
else str(getattr(exc, "reason", None) or exc))
|
||||
except _MEMBER_ERRORS as exc:
|
||||
# A damaged, encrypted or unsupported member, in words.
|
||||
counts["error"] = unreadable_words(exc)
|
||||
@@ -15838,8 +15843,19 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
|
||||
# PPSSPP's assets. Fetched from their source archive, each file
|
||||
# checked against the hash the list records.
|
||||
if data_dirs and not total_interrupted:
|
||||
print("\nData directories:")
|
||||
# A tree whose folder this user cannot write is not fetched: the
|
||||
# BIOS files above already said the cause and its remedy, and
|
||||
# each archive was named as unreadable.
|
||||
writable = []
|
||||
for entry, state in data_states:
|
||||
if state[1] and not _folder_writable(state[0]):
|
||||
failures.append((entry["ref"], NOT_WRITABLE))
|
||||
total_errors += 1
|
||||
else:
|
||||
writable.append((entry, state))
|
||||
if writable:
|
||||
print("\nData directories:")
|
||||
for entry, state in writable:
|
||||
counts = install_data_directory(entry, bios_path, state)
|
||||
total_downloaded += counts["installed"]
|
||||
data_landed += counts["installed"]
|
||||
@@ -15866,7 +15882,10 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
|
||||
f", {counts['changed'] + counts['absent']} no longer in "
|
||||
"the source (the pack has them)")
|
||||
print(line)
|
||||
if counts["error"]:
|
||||
if counts["error"] == NOT_WRITABLE:
|
||||
failures.append((entry["ref"], NOT_WRITABLE))
|
||||
total_errors += 1
|
||||
elif counts["error"]:
|
||||
print(f" {entry['ref']}: could not read "
|
||||
f"{LOCAL.pack.name if LOCAL.pack is not None else entry['url']}: "
|
||||
f"{counts['error']}", file=sys.stderr)
|
||||
|
||||
+1
-1
@@ -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="78ef177611168c1c7699cafa8982f901aaaf5342b6c55d6e158ba18fb4cc0ae2"
|
||||
DEFAULT_INSTALL_SHA256="c8cf4b65474279c30c2e1781028d3e05f195e26dd759a98a37db3477b6dd3014"
|
||||
MAX_INSTALLER_BYTES=2097152
|
||||
|
||||
cleanup() {
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
{
|
||||
"dest": "roms/ports/retrobios/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 1100388,
|
||||
"sha256": "78ef177611168c1c7699cafa8982f901aaaf5342b6c55d6e158ba18fb4cc0ae2",
|
||||
"size": 1101457,
|
||||
"sha256": "c8cf4b65474279c30c2e1781028d3e05f195e26dd759a98a37db3477b6dd3014",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
@@ -71,8 +71,8 @@
|
||||
"muos": {
|
||||
"archive": {
|
||||
"dest": "ARCHIVE/RetroBIOS.muxapp",
|
||||
"size": 1154015,
|
||||
"sha256": "03bcbdf8385808576afb0899860e5f11af37a9aee709b72481064e7a0ee79afa"
|
||||
"size": 1155084,
|
||||
"sha256": "41b72bf029de9d855312e472cc9a10046f71692a55e02c4a959efdf4201505ad"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
@@ -92,8 +92,8 @@
|
||||
{
|
||||
"name": "RetroBIOS/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 1100388,
|
||||
"sha256": "78ef177611168c1c7699cafa8982f901aaaf5342b6c55d6e158ba18fb4cc0ae2",
|
||||
"size": 1101457,
|
||||
"sha256": "c8cf4b65474279c30c2e1781028d3e05f195e26dd759a98a37db3477b6dd3014",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
@@ -166,8 +166,8 @@
|
||||
{
|
||||
"dest": ".config/modules/retrobios/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 1100388,
|
||||
"sha256": "78ef177611168c1c7699cafa8982f901aaaf5342b6c55d6e158ba18fb4cc0ae2",
|
||||
"size": 1101457,
|
||||
"sha256": "c8cf4b65474279c30c2e1781028d3e05f195e26dd759a98a37db3477b6dd3014",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -951,6 +951,33 @@ class OfflineLeavesFilesMissing(Scratch):
|
||||
self.assertNotIn("could not read", proc.stderr)
|
||||
self.assertNotIn("no longer in the source", proc.stdout)
|
||||
|
||||
@unittest.skipIf(os.name == "nt" or os.geteuid() == 0,
|
||||
"a read-only folder is refused by POSIX permissions")
|
||||
def test_a_tree_in_a_folder_not_writable_is_not_fetched(self):
|
||||
"""A read-only card blamed each data archive's URL with a raw
|
||||
errno, and that second cause split the one-line summary."""
|
||||
listed = manifest()
|
||||
listed["data_directories"] = [{
|
||||
"ref": "bluemsx", "dest": "Machines", "type": "zip",
|
||||
"url": "https://example.invalid/blueMSX.zip", "systems": ["nintendo-gba"],
|
||||
"files": {"a.txt": {"sha1": _sha1(b"a"), "size": 1}},
|
||||
}, {
|
||||
"ref": "fbneo-cheats", "dest": "fbneo/cheats", "type": "zip",
|
||||
"url": "https://example.invalid/cheats.zip", "systems": ["nintendo-gba"],
|
||||
"files": {"b.txt": {"sha1": _sha1(b"b"), "size": 1}},
|
||||
}]
|
||||
self.list.write_text(json.dumps(listed))
|
||||
self.complete()
|
||||
self.dest.chmod(0o555)
|
||||
self.addCleanup(self.dest.chmod, 0o755)
|
||||
proc = self.run_installer("--manifest", str(self.list), "--no-input")
|
||||
out = proc.stdout + proc.stderr
|
||||
self.assertEqual(proc.returncode, 2, out)
|
||||
self.assertNotIn("could not read", out)
|
||||
self.assertNotIn("Errno", out)
|
||||
self.assertNotIn("Data directories:", out)
|
||||
self.assertIn("failed: 2 files (folder not writable), first bluemsx", out)
|
||||
|
||||
|
||||
class OneOfflineVocabulary(Scratch):
|
||||
"""--offline said one
|
||||
|
||||
Reference in new issue
Block a user