From 4bc9074dfe34fdf7e72ef6ec9c4f4ccb0a03705b Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Thu, 5 Nov 2026 19:29:22 +0100 Subject: [PATCH] feat: say why an upstream revision is held The emulator page showed the reason for pin_frozen and never the one for upstream_frozen, which 11 profiles record: mupen64plus read as left behind HEAD. --- scripts/generate_site.py | 12 ++++++++---- tests/test_site_emulator_page.py | 11 +++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/scripts/generate_site.py b/scripts/generate_site.py index f2a47ed66..3c7a3d6f4 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -7984,10 +7984,14 @@ def _build_rows(profile: dict) -> list[str]: found = _found_by_text(profile.get("found_by")) if found: rows.append(f"| Files found by | {found} |") - frozen = profile.get("pin_frozen") - if frozen: - held = _escape_tags(' '.join(str(frozen).split())).replace('|', r'\|') - rows.append(f"| Revision held | {held} |") + # Each pin says why it is held: a bare upstream revision read as a + # profile left behind HEAD (mupen64plus, aps3e). + for field, label in (("pin_frozen", "Revision held"), + ("upstream_frozen", "Upstream revision held")): + frozen = profile.get(field) + if frozen: + held = _escape_tags(' '.join(str(frozen).split())).replace('|', r'\|') + rows.append(f"| {label} | {held} |") announced = profile.get("version_source") if isinstance(announced, dict) and announced.get("url"): url = str(announced["url"]) diff --git a/tests/test_site_emulator_page.py b/tests/test_site_emulator_page.py index ba592d3e3..382ec4d9f 100644 --- a/tests/test_site_emulator_page.py +++ b/tests/test_site_emulator_page.py @@ -68,6 +68,17 @@ class WhoShipsTheBuildAndWhy(unittest.TestCase): "(https://example.org/news) (version 13.0 announced there, " "found only as rebuilt copies) |", page) + def test_the_upstream_pin_says_why_it_is_held(self): + """mupen64plus showed its core revision and not that AmberELEC + builds that one: read as a profile behind HEAD.""" + page = _page("mupen64plus", { + "type": "libretro", + "upstream_frozen": "AmberELEC builds the core at this revision.", + "files": [], + }) + self.assertIn("| Upstream revision held | AmberELEC builds the core at this " + "revision. |", page) + class ACardKeepsItsAddress(unittest.TestCase): """emulators/raze/#file-duke3d-grp stopped pointing at its card once a