fix: a citation in an unmoved repo needs no move

This commit is contained in:
Abdessamad Derraz committed 2026-10-10 07:51:09 +02:00
1 parent a213898c6d
commit 884c43c109
2 files changed
+53 -4

No files matched your search

+26 -4
View File
@@ -2654,9 +2654,15 @@ def _resolve_at(
def _realign_part( def _realign_part(
part: RefPart, pairs, cache_dir: str, offline: bool part: RefPart, pairs, cache_dir: str, offline: bool, pinned=()
) -> tuple[str, object] | None: ) -> tuple[str, object] | None:
"""One range, anchored from its writing revision to the current pin.""" """One range, anchored from its writing revision to the current pin.
`pinned` lists every declared (repository, current pin). A path no moved
repository carries but an unmoved one does lives where nothing moved:
it needs no move, and calling it absent made two readings of the same
history disagree on every run (nethersx2's AetherSX2 citations).
"""
if is_external_citation(part.path): if is_external_citation(part.path):
return None return None
unclear = None unclear = None
@@ -2683,6 +2689,13 @@ def _realign_part(
return "skip", f"{part.path}:{part.start} {anchored.status.lower()}" return "skip", f"{part.path}:{part.start} {anchored.status.lower()}"
if unclear: if unclear:
return "skip", f"{part.path}: {unclear}" return "skip", f"{part.path}: {unclear}"
moved = {repo for repo, _written, _current in pairs}
if any(
upstream.fetch_file(repo, pin, part.path, cache_dir, offline) is not None
for repo, pin in pinned
if repo not in moved
):
return None
return "skip", f"{part.path} absent at the writing revision" return "skip", f"{part.path} absent at the writing revision"
@@ -2722,6 +2735,7 @@ def _realign_citation(
ambiguous: list[str], ambiguous: list[str],
cache_dir: str, cache_dir: str,
offline: bool, offline: bool,
pinned=(),
) -> tuple[dict[int, tuple[int, int, str | None]], list[str]]: ) -> tuple[dict[int, tuple[int, int, str | None]], list[str]]:
"""The moves one prose run needs, and what blocks them. """The moves one prose run needs, and what blocks them.
@@ -2737,7 +2751,7 @@ def _realign_citation(
outcomes = { outcomes = {
repr(result): result repr(result): result
for result in ( for result in (
_realign_part(part, pairs, cache_dir, offline) if pairs else None _realign_part(part, pairs, cache_dir, offline, pinned) if pairs else None
for pairs in readings for pairs in readings
) )
} }
@@ -2784,6 +2798,12 @@ def realign_prose(
repos = [(field, repo) for field, repo in repos if repo is not None] repos = [(field, repo) for field, repo in repos if repo is not None]
if not repos: if not repos:
return [] return []
pinned = [
(repo, document[f"{field}_commit"])
for field, repo in repos
if isinstance(document.get(f"{field}_commit"), str)
and document[f"{field}_commit"]
]
history = _git_history(path) history = _git_history(path)
if not history: if not history:
return [] return []
@@ -2819,7 +2839,9 @@ def realign_prose(
readings, ambiguous = _writing_pairs(document, repos, revisions, intro_sha) readings, ambiguous = _writing_pairs(document, repos, revisions, intro_sha)
if not any(readings): if not any(readings):
continue continue
moves, blocked = _realign_citation(citation, readings, ambiguous, cache_dir, offline) moves, blocked = _realign_citation(
citation, readings, ambiguous, cache_dir, offline, pinned
)
if blocked: if blocked:
# Half a run must not move: the untouched ranges would read as # Half a run must not move: the untouched ranges would read as
# already realigned when they were never even located. # already realigned when they were never even located.
+27
View File
@@ -3372,6 +3372,33 @@ class TestRealignProse(unittest.TestCase):
) )
self.assertEqual(self.path.read_text(), before) self.assertEqual(self.path.read_text(), before)
def test_a_citation_in_an_unmoved_upstream_needs_no_reading(self):
"""nethersx2 cites AetherSX2 files that only its upstream carries,
at an upstream pin that never moved. The port's pin did move under
the text, and the reading through the port called each file absent
while the other said nothing: thirteen disagreements on every run."""
sample = (
'emulator: Test\n'
'source: "https://github.com/o/port"\n'
'upstream: "https://github.com/o/up"\n'
'source_commit: "oldpin"\n'
'upstream_commit: "uppin"\n'
'notes: |\n'
' The BIOS check lives upstream (up.c:5).\n'
)
self._git("init", "-q")
self._git("config", "user.email", "t@t")
self._git("config", "user.name", "t")
self._commit(sample, "profile")
self._commit(sample.replace('"oldpin"', '"pin"'), "advance the port")
self.files[("uppin", "up.c")] = ["a", "b", "c", "d", "check bios"]
before = self.path.read_text()
messages = profile_sync.realign_prose(self.path, self.tmp.name, dry_run=True)
self.assertFalse(
any("readings disagree" in m for m in messages), messages
)
self.assertEqual(self.path.read_text(), before)
def test_dry_run_writes_nothing(self): def test_dry_run_writes_nothing(self):
self._repo_with_advanced_pin() self._repo_with_advanced_pin()
self.files[("oldpin", "a.c")] = ["x"] * 9 + ["subject"] self.files[("oldpin", "a.c")] = ["x"] * 9 + ["subject"]