From a252e2d158ef6858d276f8c5d30738e92e00c6e6 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Tue, 6 Oct 2026 12:59:23 +0200 Subject: [PATCH] fix: a cited range past the file end is gone --- scripts/profile_sync.py | 23 ++++++++++++++--------- tests/test_profile_sync.py | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py index c4a3247b..c50f79b7 100644 --- a/scripts/profile_sync.py +++ b/scripts/profile_sync.py @@ -675,8 +675,8 @@ def anchor_block( pin = _normalize(pin_lines) head = _normalize(head_lines) lo, hi = start - 1, end - if lo < 0 or lo >= len(pin): - return AnchorResult("GONE", None, None, []) + if lo < 0 or hi > len(pin): + return AnchorResult("GONE", None, None, [], "cited range ends past the end of the file") if not any(pin[lo:hi]): return AnchorResult("CHANGED", None, None, [], "cited range is blank") @@ -910,17 +910,22 @@ def anchor_part( reason = "written against HEAD, pin names an older revision" return PartResult(part, "GONE", None, None, None, [], reason, slug, url) - if part.start > len(pin_lines) and _written_against_head(part, head_lines): + end = part.end or part.start + if end > len(pin_lines): # The file is there and the line is not yet: the pinned revision is # shorter than the one the ref was written against. nestopia cited # the palette and database loads at 2041 and 2063, which is where - # HEAD carries them, over a pin four hundred lines shorter. - return PartResult( - part, "GONE", None, None, None, [], - "written against HEAD, pin names an older revision", slug, url, + # HEAD carries them, over a pin four hundred lines shorter. A range + # that only ends past the file is no better: dolphin cited 239-323 in + # a 317-line NANDImporter.cpp, and the block found above the end + # anchored it. + reason = ( + "written against HEAD, pin names an older revision" + if _written_against_head(part, head_lines) + else "cited range ends past the end of the file" ) + return PartResult(part, "GONE", None, None, None, [], reason, slug, url) - end = part.end or part.start anchored = anchor_block(pin_lines, head_lines, part.start, end) note = anchored.reason if anchored.status in REVIEW_STATUSES: @@ -1168,7 +1173,7 @@ def verify_at_pin(part: RefPart, pin_lines, tokens, hash_tokens=()) -> PartResul ) if part.start is None: return PartResult(part, "ANCHORED", None, None, None, []) - if part.start > len(pin_lines): + if (part.end or part.start) > len(pin_lines): return PartResult( part, "GONE", None, None, None, [], "beyond the end of the file" ) diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py index d18c2c59..2dc44dce 100644 --- a/tests/test_profile_sync.py +++ b/tests/test_profile_sync.py @@ -303,6 +303,13 @@ class TestWorstStatus(unittest.TestCase): class TestAnchorBlock(unittest.TestCase): + def test_a_range_ending_past_the_file_is_gone(self): + """dolphin cited NANDImporter.cpp:239-323 in a 317-line file; the + part inside the file anchored, and the ref read as sound.""" + lines = [f"line {n}" for n in range(1, 11)] + self.assertEqual(anchor_block(lines, list(lines), 8, 14).status, "GONE") + self.assertEqual(anchor_block(lines, list(lines), 8, 10).status, "ANCHORED") + def test_anchored_same_position(self): lines = ["a", "target", "b"] result = anchor_block(lines, list(lines), 2, 2) @@ -388,6 +395,13 @@ class TestVerifyAtPin(unittest.TestCase): LINES = ["pad", "pad", 'ROM_LOAD("bios.bin", CRC(deadbeef))', "pad"] + def test_a_range_ending_past_the_file_is_gone(self): + """mame cited casloopy.cpp:2105-2462 in a 2105-line file.""" + part = RefPart("a.c", 3, 9, "a.c:3-9") + self.assertEqual( + profile_sync.verify_at_pin(part, self.LINES, ["deadbeef"]).status, "GONE" + ) + def test_declared_value_present(self): part = RefPart("a.c", 3, 3, "a.c:3") self.assertEqual(