mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Save the build state before the source generation starts, so a generation cut short after it wrote layout.json runs again on the next try instead of being taken as done.
After Keep Build Cache removed the generated sources and the kit was updated, the lift ran because layout.json was gone while its key still matched. An interruption after layout.json was back left the saved state calling the lift complete, and the next run compiled unfinished sources. The pull request's two commits (one a merge of main) are applied here as their net change. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
@@ -1554,13 +1554,14 @@ class MakeGameTest(Tmp):
|
||||
(kits[1] / 'runtime' / 'h.h').write_text('#define V 2\n') # the new version changed the header
|
||||
self.assertEqual(go(kits[1])[:2], (1, 0))
|
||||
|
||||
def main_with(self, romfs, lift, compile_):
|
||||
"""make_game.main() in this process for a first build, with the given step functions in place of the real
|
||||
def main_with(self, romfs, lift, compile_, rebuild=False):
|
||||
"""make_game.main() in this process, with the given step functions in place of the real
|
||||
lift and compile (they need real modules and clang). Returns the SystemExit code, or 0."""
|
||||
sys.path.insert(0, str(self.layout.pydeps)) # the fake zbic
|
||||
saved = (self.mg.step_romfs, self.mg.step_lift, self.mg.step_compile, sys.argv)
|
||||
self.mg.step_romfs, self.mg.step_lift, self.mg.step_compile = romfs, lift, compile_
|
||||
sys.argv = ['make_game.py', '--nup', str(self.nup), '--out', str(self.out), '--msys', str(self.msys),
|
||||
source = ['--rebuild'] if rebuild else ['--nup', str(self.nup)]
|
||||
sys.argv = ['make_game.py', *source, '--out', str(self.out), '--msys', str(self.msys),
|
||||
'--until', 'compile'] # the shaders step needs the shader translator
|
||||
try:
|
||||
with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
|
||||
@@ -1572,6 +1573,37 @@ class MakeGameTest(Tmp):
|
||||
self.mg.step_romfs, self.mg.step_lift, self.mg.step_compile, sys.argv = saved
|
||||
sys.path.remove(str(self.layout.pydeps))
|
||||
|
||||
def test_retry_interrupted_lift_after_cache_cleanup(self):
|
||||
layout = self.out / 'build-cache' / 'lift' / 'layout.json'
|
||||
ran = []
|
||||
|
||||
def lift(out, cache):
|
||||
ran.append('lift')
|
||||
layout.parent.mkdir(exist_ok=True)
|
||||
layout.write_text('[]')
|
||||
|
||||
def compile_(out, cache, msys, jobs, romfs_job, update):
|
||||
ran.append('compile')
|
||||
self.assertTrue(layout.is_file())
|
||||
|
||||
def interrupted(out, cache):
|
||||
lift(out, cache)
|
||||
raise SystemExit(1) # layout exists again, but the lift did not finish
|
||||
|
||||
with mock.patch.object(self.mg, 'WIN', True): # use the fixture's MSYS toolchain check
|
||||
self.assertEqual(self.main_with(self.mg.step_romfs, lift, compile_), 0)
|
||||
self.nup.unlink()
|
||||
ran.clear()
|
||||
shutil.rmtree(layout.parent)
|
||||
self.assertEqual(self.main_with(self.mg.step_romfs, lift, compile_, rebuild=True), 0)
|
||||
self.assertEqual(ran, []) # cleaning the cache alone does not require a compile
|
||||
|
||||
with mock.patch.object(self.mg, 'kit_version', return_value='updated kit'):
|
||||
self.assertEqual(self.main_with(self.mg.step_romfs, interrupted, compile_, rebuild=True), 1)
|
||||
self.assertEqual(self.main_with(self.mg.step_romfs, lift, compile_, rebuild=True), 0)
|
||||
self.assertEqual(self.main_with(self.mg.step_romfs, lift, compile_, rebuild=True), 0)
|
||||
self.assertEqual(ran, ['lift', 'lift', 'compile'])
|
||||
|
||||
def test_romfs_beside_lift_and_compile(self):
|
||||
"""A first build packs the RomFS image while the lift and the compile run; the compile gets the running step
|
||||
and waits for it only for the RomFS index."""
|
||||
|
||||
@@ -2487,6 +2487,10 @@ def build_main():
|
||||
for later in STEPS[STEPS.index(name):]:
|
||||
if later == name or not ({name, later} & set(OWN_KEY_STEPS) or (name, later) in UNAFFECTED):
|
||||
state['steps'].pop(later, None)
|
||||
if name == 'lift':
|
||||
# The generator writes layout.json before the sources. A retry must finish an interrupted lift
|
||||
# even if the layout is back and the previous lift key still matches its inputs.
|
||||
save()
|
||||
say(f'{name}:')
|
||||
emit('step', step=name, state='start')
|
||||
if name in ('shaders', 'prompts', 'scan') and romfs_job: # they read the RomFS image
|
||||
|
||||
Reference in New Issue
Block a user