feat(cache): add rebuild and provenance safeguards
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
This commit is contained in:
parent
bf3f416b82
commit
5dc2f3cdf6
11 changed files with 2809 additions and 4 deletions
|
|
@ -3,6 +3,8 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
|
@ -32,9 +34,11 @@ class RepoIndex:
|
|||
repo_root: str
|
||||
head_sha: str | None
|
||||
observed_at: str
|
||||
source_fingerprint: str | None = None
|
||||
source_files: list[str] = field(default_factory=list)
|
||||
work_records: list[WorkRecordEntry] = field(default_factory=list)
|
||||
events: list[dict[str, Any]] = field(default_factory=list)
|
||||
schema: str = "repo_manager.index.v0"
|
||||
schema: str = "repo_manager.index.v1"
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
return {
|
||||
|
|
@ -43,6 +47,8 @@ class RepoIndex:
|
|||
"repo_root": self.repo_root,
|
||||
"head_sha": self.head_sha,
|
||||
"observed_at": self.observed_at,
|
||||
"source_fingerprint": self.source_fingerprint,
|
||||
"source_files": self.source_files,
|
||||
"work_records": [asdict(r) for r in self.work_records],
|
||||
"events": self.events,
|
||||
}
|
||||
|
|
@ -58,6 +64,8 @@ class RepoIndex:
|
|||
repo_root=data["repo_root"],
|
||||
head_sha=data.get("head_sha"),
|
||||
observed_at=data.get("observed_at") or _now(),
|
||||
source_fingerprint=data.get("source_fingerprint"),
|
||||
source_files=list(data.get("source_files") or []),
|
||||
work_records=records,
|
||||
events=list(data.get("events") or []),
|
||||
schema=data.get("schema") or "repo_manager.index.v0",
|
||||
|
|
@ -71,7 +79,24 @@ def default_index_path(repo_root: Path) -> Path:
|
|||
def save_index(index: RepoIndex, path: Path | None = None) -> Path:
|
||||
path = path or default_index_path(Path(index.repo_root))
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(index.to_dict(), indent=2) + "\n", encoding="utf-8")
|
||||
temporary: Path | None = None
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
mode="w",
|
||||
encoding="utf-8",
|
||||
dir=path.parent,
|
||||
prefix=f".{path.name}.",
|
||||
delete=False,
|
||||
) as handle:
|
||||
temporary = Path(handle.name)
|
||||
handle.write(json.dumps(index.to_dict(), indent=2) + "\n")
|
||||
handle.flush()
|
||||
os.fsync(handle.fileno())
|
||||
os.replace(temporary, path)
|
||||
temporary = None
|
||||
finally:
|
||||
if temporary is not None:
|
||||
temporary.unlink(missing_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue