From 0038a6e714075f63d4aea97e0168b9044cbaccd5 Mon Sep 17 00:00:00 2001 From: John Menke Date: Sun, 1 Nov 2026 14:22:23 -0500 Subject: [PATCH] Refuse to leave a truncated concat file when cleanup fails. A failed delete used to be ignored, and the timeout error still said the file was removed. Co-authored-by: Cursor --- src/docgen/concat.py | 13 ++++++++----- tests/test_concat.py | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/docgen/concat.py b/src/docgen/concat.py index a858408..8cacff7 100644 --- a/src/docgen/concat.py +++ b/src/docgen/concat.py @@ -117,8 +117,11 @@ def _build_one(self, out_name: str, seg_ids: list[str]) -> None: def _unlink_incomplete(path: Path) -> None: """Remove a truncated concat output so later stages cannot treat it as finished.""" - if path.exists(): - try: - path.unlink() - except OSError: - pass + if not path.exists(): + return + try: + path.unlink() + except OSError as exc: + raise ConcatError( + f"[concat] incomplete {path.name} could not be removed" + ) from exc diff --git a/tests/test_concat.py b/tests/test_concat.py index b97f61e..e3e232a 100644 --- a/tests/test_concat.py +++ b/tests/test_concat.py @@ -157,6 +157,23 @@ def fake_run(cmd, **_kwargs): assert not list((tmp_path / "recordings").glob(".concat-*.txt")) +def test_concat_timeout_refuses_when_incomplete_output_remains( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + cfg = _cfg(tmp_path, {"full": ["01", "02"]}) + _seed_recordings(tmp_path) + out = tmp_path / "recordings" / "full.mp4" + out.mkdir() + + def fake_run(cmd, **_kwargs): + raise subprocess.TimeoutExpired(cmd=cmd, timeout=300) + + monkeypatch.setattr(subprocess, "run", fake_run) + with pytest.raises(ConcatError, match="could not be removed"): + ConcatBuilder(cfg).build(name="full") + assert out.is_dir() + + def test_concat_ffmpeg_failure_removes_incomplete_output( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: