From 1c84a7cfa0d37fbbc475bcebdb5dc6944164cb3c Mon Sep 17 00:00:00 2001 From: hbrain Date: Sun, 14 Jun 2026 00:13:18 +0200 Subject: [PATCH] Fix worker chmod handling for web-owned files --- mvlog_worker.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/mvlog_worker.py b/mvlog_worker.py index 40b14d9..4ff9bdd 100755 --- a/mvlog_worker.py +++ b/mvlog_worker.py @@ -51,6 +51,17 @@ def remote_q(path: str) -> str: return quote(path) +def safe_chmod(path: Path, mode: int) -> None: + try: + path.chmod(mode) + except PermissionError: + # The worker may have group write access to www-data-owned files but + # still cannot chmod files it does not own. Do not fail rendering for that. + pass + except FileNotFoundError: + pass + + def list_jobs(host: str | None, remote_root: str) -> list[str]: if host is None: root = Path(remote_root) / "in-dir" @@ -185,7 +196,7 @@ def write_state(host: str | None, job_dir: str, state: dict) -> None: if host is None: path = Path(job_dir) / STATE_NAME path.write_text(json.dumps(state, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") - path.chmod(0o664) + safe_chmod(path, 0o664) return path = f"{job_dir}/{STATE_NAME}" tmp_path = f"{path}.tmp.$$" @@ -240,7 +251,9 @@ def publish_output(host: str | None, remote_root: str, local_mp4: Path, old_outp final = out_dir / out_name tmp = out_dir / f".{out_name}.tmp" shutil.copy2(local_mp4, tmp) + safe_chmod(tmp, 0o664) tmp.replace(final) + safe_chmod(final, 0o664) (Path(remote_root) / "cache" / "videos.json").unlink(missing_ok=True) if old_output and old_output != out_name: (out_dir / old_output).unlink(missing_ok=True) @@ -279,6 +292,7 @@ def upload_audio_files(host: str | None, job_dir: str, local_input: Path) -> lis if host is None: Path(parent).mkdir(parents=True, exist_ok=True) shutil.copy2(str(path), remote_path) + safe_chmod(Path(remote_path), 0o664) else: # Ensure parent directory exists on the remote host ssh(host, f"mkdir -p {remote_q(parent)}") @@ -365,6 +379,7 @@ def process_job(host: str | None, remote_root: str, job: str, work_dir: Path, ex else: processing_state["fingerprint"] = fingerprint_before processing_state["output"] = old_output + processing_state.pop("message", None) write_state(host, job_dir, processing_state) local_job = work_dir / job @@ -421,6 +436,7 @@ def process_job(host: str | None, remote_root: str, job: str, work_dir: Path, ex }) if article_id: new_state["article_id"] = article_id + new_state.pop("message", None) write_state(host, job_dir, new_state) print(f"published preview: {job} -> {preview_output}") @@ -447,6 +463,7 @@ def process_job(host: str | None, remote_root: str, job: str, work_dir: Path, ex }) if article_id: new_state["article_id"] = article_id + new_state.pop("message", None) write_state(host, job_dir, new_state) print(f"published: {job} -> {output}")