diff --git a/emulators/dosbox-pure-unleashed.yml b/emulators/dosbox-pure-unleashed.yml index 56a85c24..cd37dd29 100644 --- a/emulators/dosbox-pure-unleashed.yml +++ b/emulators/dosbox-pure-unleashed.yml @@ -103,7 +103,7 @@ files: size: 65536 sha1: "5a5cb5a77d7d55ee69657c2f870416daed52dea7" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5112, source src/gui/mt32emu.h:5129" + source_ref: "upstream src/gui/mt32emu.h:5112, upstream src/gui/mt32emu.h:5129" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.05" @@ -112,7 +112,7 @@ files: size: 65536 sha1: "e17a3a6d265bf1fa150312061134293d2b58288c" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5113, source src/gui/mt32emu.h:5130" + source_ref: "upstream src/gui/mt32emu.h:5113, upstream src/gui/mt32emu.h:5130" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.06" @@ -121,7 +121,7 @@ files: size: 65536 sha1: "a553481f4e2794c10cfe597fef154eef0d8257de" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5114, source src/gui/mt32emu.h:5131" + source_ref: "upstream src/gui/mt32emu.h:5114, upstream src/gui/mt32emu.h:5131" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.07" @@ -130,7 +130,7 @@ files: size: 65536 sha1: "b083518fffb7f66b03c23b7eb4f868e62dc5a987" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5115, source src/gui/mt32emu.h:5132" + source_ref: "upstream src/gui/mt32emu.h:5115, upstream src/gui/mt32emu.h:5132" - name: "MT32_CONTROL.ROM" description: "MT-32 Control BlueRidge" @@ -139,7 +139,7 @@ files: size: 65536 sha1: "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5116, source src/gui/mt32emu.h:5133" + source_ref: "upstream src/gui/mt32emu.h:5116, upstream src/gui/mt32emu.h:5133" # -- MT-32 v2.x control ROMs (128 KB, pair with MT32_PCM.ROM) -- @@ -150,7 +150,7 @@ files: size: 131072 sha1: "5837064c9df4741a55f7c4d8787ac158dff2d3ce" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5118, source src/gui/mt32emu.h:5135" + source_ref: "upstream src/gui/mt32emu.h:5118, upstream src/gui/mt32emu.h:5135" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.04" @@ -159,7 +159,7 @@ files: size: 131072 sha1: "2c16432b6c73dd2a3947cba950a0f4c19d6180eb" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5119, source src/gui/mt32emu.h:5136" + source_ref: "upstream src/gui/mt32emu.h:5119, upstream src/gui/mt32emu.h:5136" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.06" @@ -168,7 +168,7 @@ files: size: 131072 sha1: "2869cf4c235d671668cfcb62415e2ce8323ad4ed" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5120, source src/gui/mt32emu.h:5137" + source_ref: "upstream src/gui/mt32emu.h:5120, upstream src/gui/mt32emu.h:5137" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.07" @@ -177,7 +177,7 @@ files: size: 131072 sha1: "47b52adefedaec475c925e54340e37673c11707c" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5121, source src/gui/mt32emu.h:5138" + source_ref: "upstream src/gui/mt32emu.h:5121, upstream src/gui/mt32emu.h:5138" # -- CM-32L / LAPC-I control ROMs (64 KB, pair with CM32L_PCM.ROM) -- @@ -188,7 +188,7 @@ files: size: 65536 sha1: "73683d585cd6948cc19547942ca0e14a0319456d" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5122, source src/gui/mt32emu.h:5139" + source_ref: "upstream src/gui/mt32emu.h:5122, upstream src/gui/mt32emu.h:5139" - name: "CM32L_CONTROL.ROM" description: "CM-32L/LAPC-I Control v1.02" @@ -197,7 +197,7 @@ files: size: 65536 sha1: "a439fbb390da38cada95a7cbb1d6ca199cd66ef8" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5123, source src/gui/mt32emu.h:5140" + source_ref: "upstream src/gui/mt32emu.h:5123, upstream src/gui/mt32emu.h:5140" # -- CM-32LN / CM-500 / LAPC-N control ROM (64 KB, pairs with CM32L_PCM.ROM) -- @@ -208,7 +208,7 @@ files: size: 65536 sha1: "dc1c5b1b90a4646d00f7daf3679733c7badc7077" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5124, source src/gui/mt32emu.h:5141" + source_ref: "upstream src/gui/mt32emu.h:5124, upstream src/gui/mt32emu.h:5141" # -- PCM ROMs -- @@ -219,7 +219,7 @@ files: size: 524288 sha1: "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5126, source src/gui/mt32emu.h:5143" + source_ref: "upstream src/gui/mt32emu.h:5126, upstream src/gui/mt32emu.h:5143" note: "accepted by every MT-32 control ROM, v1.x and v2.x (pcmCount 128)" - name: "CM32L_PCM.ROM" @@ -230,7 +230,7 @@ files: sha1: "289cc298ad532b702461bfc738009d9ebe8025ea" validation: [sha1, size] aliases: ["CM32LN_PCM.ROM"] - source_ref: "upstream src/gui/mt32emu.h:5127, source src/gui/mt32emu.h:5144" + source_ref: "upstream src/gui/mt32emu.h:5127, upstream src/gui/mt32emu.h:5144" note: > accepted by the CM-32L and CM-32LN control ROMs (pcmCount 256). The alias covers the name derived from CM32LN_CONTROL.ROM. diff --git a/emulators/dosbox_pure.yml b/emulators/dosbox_pure.yml index eeaa8c51..b6d84a53 100644 --- a/emulators/dosbox_pure.yml +++ b/emulators/dosbox_pure.yml @@ -61,7 +61,7 @@ files: size: 65536 sha1: "5a5cb5a77d7d55ee69657c2f870416daed52dea7" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5112, source src/gui/mt32emu.h:5129" + source_ref: "source src/gui/mt32emu.h:5112, source src/gui/mt32emu.h:5129" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.05" @@ -70,7 +70,7 @@ files: size: 65536 sha1: "e17a3a6d265bf1fa150312061134293d2b58288c" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5113, source src/gui/mt32emu.h:5130" + source_ref: "source src/gui/mt32emu.h:5113, source src/gui/mt32emu.h:5130" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.06" @@ -79,7 +79,7 @@ files: size: 65536 sha1: "a553481f4e2794c10cfe597fef154eef0d8257de" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5114, source src/gui/mt32emu.h:5131" + source_ref: "source src/gui/mt32emu.h:5114, source src/gui/mt32emu.h:5131" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v1.07" @@ -88,7 +88,7 @@ files: size: 65536 sha1: "b083518fffb7f66b03c23b7eb4f868e62dc5a987" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5115, source src/gui/mt32emu.h:5132" + source_ref: "source src/gui/mt32emu.h:5115, source src/gui/mt32emu.h:5132" - name: "MT32_CONTROL.ROM" description: "MT-32 Control BlueRidge" @@ -97,7 +97,7 @@ files: size: 65536 sha1: "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5116, source src/gui/mt32emu.h:5133" + source_ref: "source src/gui/mt32emu.h:5116, source src/gui/mt32emu.h:5133" # -- MT-32 v2.x Control ROMs (128 KB) -- @@ -108,7 +108,7 @@ files: size: 131072 sha1: "5837064c9df4741a55f7c4d8787ac158dff2d3ce" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5118, source src/gui/mt32emu.h:5135" + source_ref: "source src/gui/mt32emu.h:5118, source src/gui/mt32emu.h:5135" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.04" @@ -117,7 +117,7 @@ files: size: 131072 sha1: "2c16432b6c73dd2a3947cba950a0f4c19d6180eb" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5119, source src/gui/mt32emu.h:5136" + source_ref: "source src/gui/mt32emu.h:5119, source src/gui/mt32emu.h:5136" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.06" @@ -126,7 +126,7 @@ files: size: 131072 sha1: "2869cf4c235d671668cfcb62415e2ce8323ad4ed" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5120, source src/gui/mt32emu.h:5137" + source_ref: "source src/gui/mt32emu.h:5120, source src/gui/mt32emu.h:5137" - name: "MT32_CONTROL.ROM" description: "MT-32 Control v2.07" @@ -135,7 +135,7 @@ files: size: 131072 sha1: "47b52adefedaec475c925e54340e37673c11707c" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5121, source src/gui/mt32emu.h:5138" + source_ref: "source src/gui/mt32emu.h:5121, source src/gui/mt32emu.h:5138" # -- CM-32L / LAPC-I Control ROMs (64 KB) -- @@ -146,7 +146,7 @@ files: size: 65536 sha1: "73683d585cd6948cc19547942ca0e14a0319456d" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5122, source src/gui/mt32emu.h:5139" + source_ref: "source src/gui/mt32emu.h:5122, source src/gui/mt32emu.h:5139" - name: "CM32L_CONTROL.ROM" description: "CM-32L/LAPC-I Control v1.02" @@ -155,7 +155,7 @@ files: size: 65536 sha1: "a439fbb390da38cada95a7cbb1d6ca199cd66ef8" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5123, source src/gui/mt32emu.h:5140" + source_ref: "source src/gui/mt32emu.h:5123, source src/gui/mt32emu.h:5140" # -- CM-32LN / CM-500 / LAPC-N Control ROM (64 KB) -- @@ -166,7 +166,7 @@ files: size: 65536 sha1: "dc1c5b1b90a4646d00f7daf3679733c7badc7077" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5124, source src/gui/mt32emu.h:5141" + source_ref: "source src/gui/mt32emu.h:5124, source src/gui/mt32emu.h:5141" # -- PCM ROMs -- @@ -177,7 +177,7 @@ files: size: 524288 sha1: "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252" validation: [sha1, size] - source_ref: "upstream src/gui/mt32emu.h:5126, source src/gui/mt32emu.h:5143" + source_ref: "source src/gui/mt32emu.h:5126, source src/gui/mt32emu.h:5143" note: > accepted by every MT-32 control ROM, v1.x and v2.x. Each control ROM fixes the PCM size it accepts through its pcmCount: 128 requires this @@ -191,7 +191,7 @@ files: sha1: "289cc298ad532b702461bfc738009d9ebe8025ea" validation: [sha1, size] aliases: ["CM32LN_PCM.ROM"] - source_ref: "upstream src/gui/mt32emu.h:5127, source src/gui/mt32emu.h:5144" + source_ref: "source src/gui/mt32emu.h:5127, source src/gui/mt32emu.h:5144" note: > accepted by the CM-32L and CM-32LN control ROMs, which carry pcmCount 256 and require this 1048576 byte image. The alias covers the name diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py index b91627d1..e56e0e9b 100644 --- a/scripts/profile_sync.py +++ b/scripts/profile_sync.py @@ -902,6 +902,33 @@ def resolve_by_shift(part: PartResult, shifts: dict[str, int]) -> PartResult: ) +def refuse_collapsing_moves(parts: list[PartResult]) -> list[PartResult]: + """Hold back a recale that would land on another part of the same ref. + + Two parts of one source_ref cite two places on purpose. dosbox_pure cited + the SHA-1 line of mt32emu.h and the ROMInfo line that ties it to a file + name, under two repository words: the second was self-checked alone, + found the hash once, and read MOVED onto the first line. Recaling it + would drop the ROMInfo citation without a word, so the part goes to + review instead. + """ + cited = { + (p.part.path, p.part.start, p.part.last) + for p in parts if p.part.start is not None + } + held = [] + for part in parts: + target = (part.new_path or part.part.path, part.start, part.end or part.start) + own = (part.part.path, part.part.start, part.part.last) + if part.status in REBASE_STATUSES and target != own and target in cited: + part = replace( + part, status="AMBIGUOUS", candidates=[part.start], + reason="lands on a line another part of this ref already cites", + ) + held.append(part) + return held + + @dataclass class EntryReport: name: str @@ -1246,14 +1273,19 @@ def reconcile_self_check( against HEAD rather than self-checked is never rewritten. """ eligible = eligible if eligible is not None else [True] * len(parts) - anchored_files = { - part.part.path - for part, ok in zip(parts, eligible) - if ok and part.status == "ANCHORED" - } + # The settled part lies in the tree its anchor was found in: without the + # repository, attribution wrote dosbox-pure-unleashed's ROMInfo line + # under `source`, a repository that carries no mt32emu.h. + anchored_files: dict[str, str | None] = {} + for part, ok in zip(parts, eligible): + if ok and part.status == "ANCHORED": + anchored_files.setdefault(part.part.path, part.repo) kept = ("ANCHORED", "GONE", "EXTERNAL", "BINARY") return [ - PartResult(part.part, "ANCHORED", None, None, None, []) + PartResult( + part.part, "ANCHORED", None, None, None, [], + repo=anchored_files[part.part.path], + ) if ok and part.status not in kept and part.part.path in anchored_files else part for part, ok in zip(parts, eligible) @@ -1918,7 +1950,7 @@ def build_report( shifts = dominant_shifts([p for _, _, _, parts in staged for p in parts]) for entry_name, ref, citation, parts in staged: - parts = [resolve_by_shift(p, shifts) for p in parts] + parts = refuse_collapsing_moves([resolve_by_shift(p, shifts) for p in parts]) status = worst_status([p.status for p in parts]) report.entries.append(EntryReport( entry_name, ref, status, parts, citation.kind, citation.field diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py index dd69ddb3..ab98ce32 100644 --- a/tests/test_profile_sync.py +++ b/tests/test_profile_sync.py @@ -4158,6 +4158,15 @@ class TestReconcilePerFile(unittest.TestCase): result = profile_sync.reconcile_self_check([anchored, same, other]) self.assertEqual([p.status for p in result], ["ANCHORED", "ANCHORED", "AMBIGUOUS"]) + def test_a_settled_part_keeps_the_repository_of_its_anchor(self): + anchored = PartResult(RefPart("mt32emu.h", 5112, 5112, "5112"), "ANCHORED", + None, None, None, [], repo="schelling/dosbox-pure") + same = PartResult(RefPart("mt32emu.h", 5129, 5129, "5129"), "MOVED", + None, 5112, 5112, [5112]) + result = profile_sync.reconcile_self_check([anchored, same]) + self.assertEqual(result[1].status, "ANCHORED") + self.assertEqual(result[1].repo, "schelling/dosbox-pure") + def test_a_compared_part_is_never_rewritten(self): anchored = PartResult(RefPart("a.c", 5, 5, "5"), "ANCHORED", None, None, None, []) shifted = PartResult(RefPart("a.c", 9, 9, "9"), "SHIFTED", None, 12, 12, []) @@ -4165,6 +4174,24 @@ class TestReconcilePerFile(unittest.TestCase): self.assertEqual(result[1].status, "SHIFTED") +class TestCollapsingMoves(unittest.TestCase): + """A recale never folds two parts of one ref onto the same line.""" + + def test_a_move_onto_a_sibling_part_goes_to_review(self): + sha = PartResult(RefPart("mt32emu.h", 5112, 5112, "upstream mt32emu.h:5112", "upstream"), + "ANCHORED", None, None, None, []) + info = PartResult(RefPart("mt32emu.h", 5129, 5129, "source mt32emu.h:5129", "source"), + "MOVED", None, 5112, 5112, [5112]) + result = profile_sync.refuse_collapsing_moves([sha, info]) + self.assertEqual([p.status for p in result], ["ANCHORED", "AMBIGUOUS"]) + + def test_a_move_to_a_free_line_is_kept(self): + first = PartResult(RefPart("a.c", 5, 5, "a.c:5"), "ANCHORED", None, None, None, []) + moved = PartResult(RefPart("a.c", 9, 9, "a.c:9"), "MOVED", None, 12, 12, [12]) + result = profile_sync.refuse_collapsing_moves([first, moved]) + self.assertEqual(result[1].status, "MOVED") + + class TestRealignFlagMatrix(unittest.TestCase): """--realign-prose applies a flag or refuses it, never swallows it."""