diff --git a/swift/codegen/lib/render.py b/swift/codegen/lib/render.py index 9564f5eb4ab..cc26880fbac 100644 --- a/swift/codegen/lib/render.py +++ b/swift/codegen/lib/render.py @@ -103,12 +103,18 @@ class RenderManager(Renderer): return self def __exit__(self, exc_type, exc_val, exc_tb): - for f in self._existing - self._skipped - self.written: - self._hashes.pop(self._get_path(f), None) - f.unlink(missing_ok=True) - log.info(f"removed {f.name}") - for f in self.written: - self._hashes[self._get_path(f)].post = self._hash_file(f) + if exc_val is None: + for f in self._existing - self._skipped - self.written: + self._hashes.pop(self._get_path(f), None) + f.unlink(missing_ok=True) + log.info(f"removed {f.name}") + for f in self.written: + self._hashes[self._get_path(f)].post = self._hash_file(f) + else: + # if an error was encountered, drop already written files from the registry + # so that they get the chance to be regenerated again during the next run + for f in self.written: + self._hashes.pop(self._get_path(f), None) self._dump_registry() def _do_write(self, mnemonic: str, contents: str, output: pathlib.Path): diff --git a/swift/codegen/test/test_render.py b/swift/codegen/test/test_render.py index 64cc745046f..8c48902eea7 100644 --- a/swift/codegen/test/test_render.py +++ b/swift/codegen/test/test_render.py @@ -192,6 +192,45 @@ def test_managed_render_with_modified_stub_file_not_marked_as_generated(pystache assert_file(registry, "") +class MyError(Exception): + pass + + +def test_managed_render_exception_drops_written_from_registry(pystache_renderer, sut): + data = mock.Mock(spec=("template",)) + text = "some text" + pystache_renderer.render_name.side_effect = (text,) + output = paths.swift_dir / "some/output.txt" + registry = paths.swift_dir / "a/registry.list" + write(output, text) + write(registry, "a a a\n" + f"some/output.txt whatever {hash(text)}\n" + "b b b") + + with pytest.raises(MyError): + with sut.manage(generated=(), stubs=(), registry=registry) as renderer: + renderer.render(data, output) + raise MyError + + assert_file(registry, "a a a\nb b b\n") + + +def test_managed_render_exception_does_not_erase(pystache_renderer, sut): + output = paths.swift_dir / "some/output.txt" + stub = paths.swift_dir / "some/stub.txt" + registry = paths.swift_dir / "a/registry.list" + write(output) + write(stub, "// generated bla bla") + write(registry) + + with pytest.raises(MyError): + with sut.manage(generated=(output,), stubs=(stub,), registry=registry) as renderer: + raise MyError + + assert output.is_file() + assert stub.is_file() + + def test_render_with_extensions(pystache_renderer, sut): data = mock.Mock(spec=("template", "extensions")) data.template = "test_template"