diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py index b91627d1..802cadd7 100644 --- a/scripts/profile_sync.py +++ b/scripts/profile_sync.py @@ -488,9 +488,17 @@ def _find_all(haystack: list[str], needle: list[str]) -> list[int]: def _map_index( opcodes: list[tuple[str, int, int, int, int]], index: int ) -> int | None: + """Line of HEAD that a pinned line became. + + A replace block of equal size edits each line in place (a column added to + every row of a table), so its lines map one to one like an equal block. + Collapsed onto the first line, eight refs citing eight rows all landed on + the first row. + """ for tag, i1, i2, j1, j2 in opcodes: if i1 <= index < i2: - return j1 + (index - i1) if tag == "equal" else j1 + in_place = tag == "equal" or (tag == "replace" and i2 - i1 == j2 - j1) + return j1 + (index - i1) if in_place else j1 return None diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py index dd69ddb3..576796db 100644 --- a/tests/test_profile_sync.py +++ b/tests/test_profile_sync.py @@ -378,6 +378,15 @@ class TestAnchorBlock(unittest.TestCase): self.assertEqual(result.status, "CHANGED") self.assertEqual(result.start, 3) + def test_rows_edited_in_place_keep_their_own_line(self): + rows = [f'{{"ipl{i}", 0x{i:02x}}}' for i in range(8)] + pin = ["a", "b", *rows, "z"] + head = ["a", "b", *[row + ", false" for row in rows], "z"] + for line in (3, 5, 10): + result = anchor_block(pin, head, line, line) + self.assertEqual(result.status, "CHANGED") + self.assertEqual(result.start, line) + def test_gone_when_content_vanished(self): result = anchor_block(["a", "unique marker", "b"], ["x"] * 200, 2, 2) self.assertEqual(result.status, "GONE")