fester/backend/cache_local.py

81 lines
1.8 KiB
Python

import os
import json
import hashlib
from pathlib import Path
# Resolve cache directory with graceful fallbacks for unprivileged environments
def _resolve_cache_dir() -> Path:
env = os.environ.get("FESTER_CACHE_DIR")
if env:
p = Path(env)
p.mkdir(parents=True, exist_ok=True)
return p
for c in [
Path("/var/lib/fester/cache"),
Path.home() / ".fester" / "cache",
Path("/tmp/fester_cache"),
]:
try:
c.mkdir(parents=True, exist_ok=True)
return c
except (OSError, PermissionError):
continue
# Last-resort in-memory (caller must handle None)
return None
CACHE_DIR = _resolve_cache_dir()
def hash_dict(d):
raw = json.dumps(d, sort_keys=True).encode()
return hashlib.sha256(raw).hexdigest()
def make_build_key(snapshot_hash, target, env):
return hashlib.sha256(
f"{snapshot_hash}:{target}:{hash_dict(env)}".encode()
).hexdigest()
def cache_hit(key):
if CACHE_DIR is None:
return False
return (CACHE_DIR / key / "done").exists()
def cache_store(key, log):
if CACHE_DIR is None:
return False
base = CACHE_DIR / key
base.mkdir(parents=True, exist_ok=True)
(base / "done").write_text("1")
(base / "log.txt").write_text(log)
return True
def cache_log(key):
if CACHE_DIR is None:
return None
p = CACHE_DIR / key / "log.txt"
return p.read_text() if p.exists() else None
# ----------------------------
# ccache health probe
# ----------------------------
def ccache_stats():
try:
import subprocess
out = subprocess.check_output(
["ccache", "-s"],
stderr=subprocess.STDOUT
).decode()
return out
except:
return "ccache not available"