diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py index 8e2f54e29..7fde29014 100644 --- a/scripts/profile_sync.py +++ b/scripts/profile_sync.py @@ -4627,8 +4627,14 @@ def _apply_writes( # The guard above read the prose under the pins the profile held. # A bump that moves upstream_commit can leave prose the report # judged in the fork under the new upstream pin (dolphin-mmjr2, - # hatari, xenios): read it again on what was written. - left = realign_prose(path, args.cache_dir, args.offline, dry_run=True) + # hatari, xenios): read it again on what was written. It reads + # the profile's own history, so it runs on the real path, and a + # read that fails (offline, rate limit) puts the profile back. + try: + left = realign_prose(path, args.cache_dir, args.offline, dry_run=True) + except BaseException: + path.write_bytes(original) + raise if moved and left: path.write_bytes(original) print( diff --git a/tests/test_profile_sync.py b/tests/test_profile_sync.py index d28137fb1..92b51c817 100644 --- a/tests/test_profile_sync.py +++ b/tests/test_profile_sync.py @@ -2670,6 +2670,19 @@ class TestWriteDryRun(unittest.TestCase): counts={"SHIFTED": 1}, ) + def test_a_prose_read_that_fails_leaves_the_profile_as_it_was(self): + """The bumped profile was promoted before the prose under its new pin + was read. Offline, an uncached cited file raised NotCachedError past + the restore and the profile kept a pin the guard would refuse.""" + from unittest import mock # noqa: PLC0415 + + before = self.path.read_bytes() + cold = profile_sync.upstream.NotCachedError("x.c not cached") + with mock.patch.object(profile_sync, "realign_prose", side_effect=[[], cold]), \ + self.assertRaises(profile_sync.upstream.NotCachedError): + self._run(self._args(rebase_refs=True, dry_run=False), self._shifted()) + self.assertEqual(self.path.read_bytes(), before) + def test_rebase_states_the_move_and_leaves_the_file(self): before = self.path.read_text() output = self._run(self._args(rebase_refs=True), self._shifted())