Skip to content

Commit fbc6001

Browse files
committed
fix: temp file cleanup on download failure, rollback without backup
- Consolidate download+install into single try/finally so temp files are always cleaned up even if download fails - On registry update failure when no backup existed (dir was missing), remove the newly placed workflow directory to restore pre-update state
1 parent 8a4dbaf commit fbc6001

1 file changed

Lines changed: 12 additions & 7 deletions

File tree

src/specify_cli/__init__.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5018,19 +5018,20 @@ def _validate_and_install_local(yaml_path: Path, source_label: str) -> None:
50185018
console.print("Only install workflows from sources you trust.\n")
50195019

50205020
import tempfile
5021+
tmp_path = None
50215022
try:
50225023
with tempfile.NamedTemporaryFile(suffix=".yml", delete=False) as tmp:
50235024
tmp_path = Path(tmp.name)
50245025
_download_validated(from_url, tmp_path)
5026+
_validate_and_install_local(tmp_path, from_url)
50255027
except typer.Exit:
50265028
raise
50275029
except Exception as exc:
50285030
console.print(f"[red]Error:[/red] Failed to download workflow: {exc}")
50295031
raise typer.Exit(1)
5030-
try:
5031-
_validate_and_install_local(tmp_path, from_url)
50325032
finally:
5033-
tmp_path.unlink(missing_ok=True)
5033+
if tmp_path:
5034+
tmp_path.unlink(missing_ok=True)
50345035
return
50355036

50365037
# Try as URL (http/https)
@@ -5042,19 +5043,20 @@ def _validate_and_install_local(yaml_path: Path, source_label: str) -> None:
50425043
raise typer.Exit(1)
50435044

50445045
import tempfile
5046+
tmp_path = None
50455047
try:
50465048
with tempfile.NamedTemporaryFile(suffix=".yml", delete=False) as tmp:
50475049
tmp_path = Path(tmp.name)
50485050
_download_validated(source, tmp_path)
5051+
_validate_and_install_local(tmp_path, source)
50495052
except typer.Exit:
50505053
raise
50515054
except Exception as exc:
50525055
console.print(f"[red]Error:[/red] Failed to download workflow: {exc}")
50535056
raise typer.Exit(1)
5054-
try:
5055-
_validate_and_install_local(tmp_path, source)
50565057
finally:
5057-
tmp_path.unlink(missing_ok=True)
5058+
if tmp_path:
5059+
tmp_path.unlink(missing_ok=True)
50585060
return
50595061

50605062
# Try as a local file/directory
@@ -5497,11 +5499,14 @@ def workflow_update(
54975499
registry_snapshot = None
54985500
# Reload in-memory state from restored file
54995501
registry.data = registry._load()
5500-
# Restore workflow from backup
5502+
# Restore workflow from backup, or remove new dir if no backup existed
55015503
if backup_dir and backup_dir.exists():
55025504
if wf_dir.exists():
55035505
shutil.rmtree(wf_dir)
55045506
backup_dir.rename(wf_dir)
5507+
elif wf_dir.exists() and not backup_dir:
5508+
# No prior directory existed; remove the newly placed one
5509+
shutil.rmtree(wf_dir, ignore_errors=True)
55055510
raise
55065511
finally:
55075512
if registry_snapshot and registry_snapshot.exists():

0 commit comments

Comments
 (0)