mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
fix: arbitrate slots on the strongest profile proof
This commit is contained in:
1 parent
a8415c33c3
commit
16f4c071fe
2 files changed
+46
-4
No files matched your search
+26
-4
@@ -319,6 +319,15 @@ def pack_overrides(
|
||||
return overrides
|
||||
|
||||
|
||||
def _strongest(claims: list[Claim]) -> Claim:
|
||||
"""The profile claim with the strongest proof; the first emulator breaks ties.
|
||||
|
||||
yaps2 pins its GameIndex.yaml by sha1 while armsx2 and lrps2 only match a
|
||||
path: alphabetical order served armsx2's copy to all three.
|
||||
"""
|
||||
return max(claims, key=lambda claim: (_claim_rank(claim), -claims.index(claim)))
|
||||
|
||||
|
||||
def arbitrate(conflict: Conflict, mode: str, addressee: str = "platform") -> Decision:
|
||||
"""Decide a contested destination for the pack being built.
|
||||
|
||||
@@ -333,7 +342,7 @@ def arbitrate(conflict: Conflict, mode: str, addressee: str = "platform") -> Dec
|
||||
addressee decides; the loss is reported rather than absorbed, because the
|
||||
cause is an upstream declaration that needs fixing at its source.
|
||||
"""
|
||||
profile = conflict.profile_claims[0]
|
||||
profile = _strongest(conflict.profile_claims)
|
||||
if addressee == "emulator":
|
||||
return Decision(conflict, profile, ADDRESSEE)
|
||||
if not nativemode.reads_file_contents(mode):
|
||||
@@ -345,11 +354,24 @@ def format_decision(decision: Decision) -> str:
|
||||
"""One line naming the contested slot, the winner and the ground for it."""
|
||||
conflict = decision.conflict
|
||||
if decision.serves_both:
|
||||
return (
|
||||
f"{conflict.destination}: serve {decision.winner.local_path} "
|
||||
f"({', '.join(conflict.emulators) or 'profile'}); the frontend only "
|
||||
winner = decision.winner.local_path
|
||||
served = sorted({
|
||||
c.emulator for c in conflict.profile_claims
|
||||
if c.emulator and c.local_path == winner
|
||||
})
|
||||
others = sorted({
|
||||
c.emulator for c in conflict.profile_claims
|
||||
if c.emulator and c.local_path != winner
|
||||
})
|
||||
line = (
|
||||
f"{conflict.destination}: serve {winner} "
|
||||
f"({', '.join(served) or 'profile'}); the frontend only "
|
||||
"checks the path, so both are satisfied"
|
||||
)
|
||||
if others:
|
||||
# One path holds one file: an emulator pinning another is not served.
|
||||
line += f"; {', '.join(others)} expected another file"
|
||||
return line
|
||||
if decision.reason == ADDRESSEE:
|
||||
return (
|
||||
f"{conflict.destination}: serve {decision.winner.local_path}, "
|
||||
|
||||
@@ -555,5 +555,25 @@ class ManifestFollowsTheArbitration(unittest.TestCase):
|
||||
self.assertEqual(by_dest[dest]["repo_path"], path)
|
||||
|
||||
|
||||
class StrongestProfileClaimWins(unittest.TestCase):
|
||||
"""yaps2 pins GameIndex.yaml by sha1; armsx2 matched a path only."""
|
||||
|
||||
def test_hash_proof_beats_path_proof(self):
|
||||
from slots import Claim, Conflict, arbitrate, format_decision
|
||||
|
||||
def claim(emu, path, status):
|
||||
return Claim("profile", "pcsx2/resources/GameIndex.yaml", "GameIndex.yaml",
|
||||
emulator=emu, local_path=path, status=status)
|
||||
|
||||
conflict = Conflict(
|
||||
"pcsx2/resources/GameIndex.yaml",
|
||||
Claim("platform", "pcsx2/resources/GameIndex.yaml", "GameIndex.yaml",
|
||||
local_path="p", status="path_exact"),
|
||||
[claim("armsx2", "a", "path_exact"), claim("yaps2", "y", "sha1_exact")],
|
||||
)
|
||||
decision = arbitrate(conflict, "existence")
|
||||
self.assertEqual(decision.winner.emulator, "yaps2")
|
||||
self.assertIn("armsx2 expected another file", format_decision(decision))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user