From 203e75c1f42d45d83bf9b83e28dcc4a88d61b506 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sat, 10 Oct 2026 07:49:14 +0200 Subject: [PATCH] fix: let the live, owning repository judge a ref --- scripts/profile_sync.py | 26 ++++++++++++++--- tests/test_profile_sync.py | 57 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py index 652505be..0fcb79f3 100644 --- a/scripts/profile_sync.py +++ b/scripts/profile_sync.py @@ -1666,10 +1666,17 @@ def build_report( token on the cited line, so no single attribution can be right for all of them; taking the best outcome across repositories settles it. """ + owner, _actual = resolve_path(part.path, part.start, tuple(tokens)) + carrying = [ + view for view in views + if fetch_from(view.repo, view.pin, part.path) is not None + ] + live = { + id(view) for view in carrying + if fetch_from(view.repo, view.head, part.path) is not None + } best = None - for view in views: - if fetch_from(view.repo, view.pin, part.path) is None: - continue + for view in carrying: result = anchor_part( part, lambda which, path, start=None, toks=(), _v=view: fetch( @@ -1681,8 +1688,19 @@ def build_report( ), tokens, ) + if ( + live and id(view) not in live + and result.status in ("AMBIGUOUS", "GONE") + ): + # dosbox-pure's upstream was emptied: its rename search + # offered the .info, .sln and .vcxproj as candidates and hid + # the real change in the port that still carries the file. + continue rank = STATUS_ORDER.index(result.status) - if best is None or rank < best[0]: + # On a tie the repository the citation is attributed to speaks: + # mame's "written against HEAD, pin names an older revision" was + # replaced by whatever the first repository said. + if best is None or rank < best[0] or (rank == best[0] and view is owner): best = (rank, result) return best[1] if best else anchor_part( part, fetch, rename_getter, describe, tokens diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py index 2dc44dce..251a740f 100644 --- a/tests/test_profile_sync.py +++ b/tests/test_profile_sync.py @@ -1453,6 +1453,63 @@ class TestBuildReport(unittest.TestCase): report = build_report("mame", profile, self.dir) self.assertEqual(report.entries[0].status, "ANCHORED") + def test_an_emptied_upstream_does_not_hide_the_ports_change(self): + # dosbox-pure moved to Codeberg and emptied its GitHub repository. + # The rename search run for that repository picked up the port's + # .info, .sln and .vcxproj sharing the file's root, and that + # AMBIGUOUS outranked the port's own CHANGED. + pin_lines = ["a", "scan the system folder", "for ROM.BIN", "c"] + self.files[("portpin", "core.cpp")] = list(pin_lines) + self.files[("porthead", "core.cpp")] = ["a", "scan every folder", "for nothing", "c"] + self.files[("uppin", "core.cpp")] = list(pin_lines) + for name in ("core.info", "core.sln", "core.vcxproj"): + self.files[("porthead", name)] = ["x"] + heads = {"o/port": "porthead", "o/up": "uphead"} + profile_sync.upstream.resolve_head = ( + lambda repo, cache, offline=False, branch=None: heads[repo.slug] + ) + profile_sync.upstream.list_tree = ( + lambda repo, sha, cache_dir, offline=False: ( + sorted(path for revision, path in self.files if revision == sha), False + ) + ) + profile = { + "emulator": "Pure", + "source": "https://github.com/o/port", + "upstream": "https://github.com/o/up", + "source_commit": "portpin", + "upstream_commit": "uppin", + "notes": "The scan accepts it (core.cpp:2-3).", + "files": [], + } + report = build_report("pure", profile, self.dir) + self.assertEqual([e.status for e in report.entries], ["CHANGED"]) + + def test_a_tie_reports_the_owning_repository(self): + # Both repositories call the ref GONE. mamedev, which the citation is + # attributed to, says why: the ref was written against HEAD. The port + # only says the range runs past its file. + self.files[("portpin", "src/stv.cpp")] = ["x"] + self.files[("porthead", "src/stv.cpp")] = ["x"] + self.files[("uppin", "src/stv.cpp")] = ["x"] + self.files[("uphead", "src/stv.cpp")] = ["x", "y", "GAME( 1996, stvbios,"] + heads = {"o/port": "porthead", "o/up": "uphead"} + profile_sync.upstream.resolve_head = ( + lambda repo, cache, offline=False, branch=None: heads[repo.slug] + ) + profile = { + "emulator": "MAME", + "source": "https://github.com/o/port", + "upstream": "https://github.com/o/up", + "source_commit": "portpin", + "upstream_commit": "uppin", + "files": [{"name": "stvbios.zip", "source_ref": "src/stv.cpp:3"}], + } + report = build_report("mame", profile, self.dir) + entry = report.entries[0] + self.assertEqual(entry.status, "GONE") + self.assertIn("written against HEAD", entry.parts[0].reason) + def test_pin_on_the_declared_version_tag_is_flagged(self): self.files[("pinsha", "a.c")] = ["x", "hit"] self.files[("headsha", "a.c")] = ["x", "hit"]