Files
sunnypilot/docs_sp/tools/content_cache.py
T
Jason Wen 922ad64d13 sync
2026-03-12 21:46:34 -04:00

59 lines
2.0 KiB
Python

"""SHA-256 content cache for skipping unchanged docs on re-sync.
Stores one .sha256 file per doc in .discourse_sync_cache/. On re-run,
compares the current file hash against the cached hash to determine
whether the doc needs syncing.
"""
from __future__ import annotations
import hashlib
from pathlib import Path
DEFAULT_CACHE_DIR = Path(__file__).resolve().parent.parent.parent / ".discourse_sync_cache"
class ContentCache:
"""File-based SHA-256 content cache."""
def __init__(self, cache_dir: str | Path = DEFAULT_CACHE_DIR) -> None:
self._cache_dir = Path(cache_dir)
@property
def cache_dir(self) -> Path:
return self._cache_dir
@staticmethod
def compute_hash(content: str) -> str:
"""Compute SHA-256 hex digest of content."""
return hashlib.sha256(content.encode("utf-8")).hexdigest()
def _cache_path(self, doc_path: str) -> Path:
"""Map a doc path (e.g. 'features/cruise/icbm.md') to its cache file."""
slug = doc_path.replace("/", "_").replace(".md", "")
return self._cache_dir / f"{slug}.sha256"
def is_changed(self, doc_path: str, content: str) -> bool:
"""Return True if content differs from the cached hash (or no cache exists)."""
content_hash = self.compute_hash(content)
cached = self._cache_path(doc_path)
if not cached.exists():
return True
return cached.read_text().strip() != content_hash
def save(self, doc_path: str, content: str) -> None:
"""Save the SHA-256 hash of content to the cache file."""
content_hash = self.compute_hash(content)
self._cache_dir.mkdir(parents=True, exist_ok=True)
self._cache_path(doc_path).write_text(content_hash + "\n")
def clear(self) -> int:
"""Remove all cached hashes. Returns the number of files removed."""
if not self._cache_dir.exists():
return 0
count = 0
for f in self._cache_dir.glob("*.sha256"):
f.unlink()
count += 1
return count