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"