fix: name the file a variant download is saved as

A .variants/ copy downloads as advision.zip.1c086064, its storage name:
raw.githubusercontent.com sends no Content-Disposition and the download
attribute is ignored across origins. A card whose download name differs
from the file name now says what to save it as, at a glance.
This commit is contained in:
Abdessamad Derraz committed 2026-11-06 08:20:03 +01:00
1 parent 4f930b5573
commit d1535d0787
2 files changed
+31 -1

No files matched your search

+14 -1
View File
@@ -5805,6 +5805,13 @@ def _wanted_list(source: str, label: str, data: dict, by_dat: dict[str, list],
_RELEASE_ASSET_NAMES: dict[str, str] | None = None
def _download_name(path: str) -> str:
"""The name a browser saves a collection file under: the last segment
of its download URL. Neither host sends a Content-Disposition, and the
download attribute is ignored on another origin."""
return urllib.parse.unquote(_fetch_url(path).rsplit("/", 1)[-1])
def _fetch_url(path: str) -> str:
"""Where a collection file downloads from: its raw URL, or the
large-files release asset when .gitignore keeps it out of git."""
@@ -6179,6 +6186,12 @@ def _system_file_card(
# Each fact: its label, its values, whether the search reads it. What a
# setup does with the file comes first, the fingerprints last.
facts: list[tuple[str, list[str], bool]] = []
saved = _download_name(f["path"]) if f.get("path") else name
if saved != name:
# A .variants/ copy is stored as advision.zip.1c086064, and the
# browser names the download after the URL: copied as it came, the
# file a platform pins was not found under its name.
facts.append(("Save as", [f"{_code(name)}, the download is named {_code(saved)}"], False))
if plats:
# Each link lands on the platform's system section, and says where
# that platform puts the file. Out of the search: the card's title
@@ -6237,7 +6250,7 @@ def _system_file_card(
# What a system card shows at a glance: who lists the file and who reads it.
# Its fingerprints and the rest open on demand, so a page of 250 cards reads
# as a list of files, not a wall of hashes.
_CARD_KEY_FACTS = ("On the setup's list", "Packed for its emulators by", "Emulators")
_CARD_KEY_FACTS = ("Save as", "On the setup's list", "Packed for its emulators by", "Emulators")
_CARD_HASHES = ("SHA1", "MD5", "CRC32", "SHA256")
# The words a card's fold names its other facts by.
_CARD_MORE_WORDS = {"Romset": "romset", "Collection path": "collection path",
+17
View File
@@ -5207,6 +5207,23 @@ class CollectionCardsCarryFullHashes(unittest.TestCase):
self.assertIn(f'<dd class="rb-hash">{value}</dd>', text)
class AVariantCardSaysWhatToSaveItAs(unittest.TestCase):
"""The Download button of a .variants/ card saved advision.zip.1c086064,
the storage name, and nothing said RetroBat looks for advision.zip."""
def test_the_name_to_save_it_under(self):
from scripts.generate_site import FileConsumers, _system_file_card
entry = {"name": "advision.zip", "size": 10, "sha1": "a" * 40,
"path": "bios/Entex/Adventure Vision/.variants/advision.zip.1c086064"}
text = "\n".join(_system_file_card(entry, FileConsumers({}, {})))
self.assertIn("Save as", text)
self.assertIn("advision.zip.1c086064", text)
plain = "\n".join(_system_file_card(
{**entry, "path": "bios/Entex/Adventure Vision/advision.zip"}, FileConsumers({}, {})))
self.assertNotIn("Save as", plain)
class NullReadsAsNone(unittest.TestCase):
"""`upstream: ~` printed `| Upstream | None |` and `bios_filename: null`