Files
wehub-resource-sync 91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:19 +08:00

64 lines
2.1 KiB
Python

"""Local image cache at ~/.cua/cua-sandbox/images/."""
from __future__ import annotations
import json
import shutil
from pathlib import Path
from typing import Optional
CACHE_ROOT = Path.home() / ".cua" / "cua-sandbox" / "images"
class ImageCache:
"""Manages locally cached VM/container images."""
def __init__(self, root: Optional[Path] = None):
self.root = root or CACHE_ROOT
self.root.mkdir(parents=True, exist_ok=True)
def image_dir(self, registry: str, org: str, name: str, tag: str) -> Path:
return self.root / registry / org / name / tag
def is_cached(self, registry: str, org: str, name: str, tag: str) -> bool:
return (self.image_dir(registry, org, name, tag) / "manifest.json").exists()
def save_manifest(self, registry: str, org: str, name: str, tag: str, manifest: dict) -> Path:
d = self.image_dir(registry, org, name, tag)
d.mkdir(parents=True, exist_ok=True)
p = d / "manifest.json"
p.write_text(json.dumps(manifest, indent=2))
return d
def get_manifest(self, registry: str, org: str, name: str, tag: str) -> Optional[dict]:
p = self.image_dir(registry, org, name, tag) / "manifest.json"
if p.exists():
return json.loads(p.read_text())
return None
def list_images(self) -> list[dict]:
images = []
for p in self.root.rglob("manifest.json"):
try:
parts = p.relative_to(self.root).parts
if len(parts) >= 4:
images.append(
{
"registry": parts[0],
"org": parts[1],
"name": parts[2],
"tag": parts[3],
"path": str(p.parent),
}
)
except Exception:
pass
return images
def remove(self, registry: str, org: str, name: str, tag: str) -> bool:
d = self.image_dir(registry, org, name, tag)
if d.exists():
shutil.rmtree(d)
return True
return False