Source code for nix_daemon_protocol.valid_path_info

"""ValidPathInfo — StorePath + UnkeyedValidPathInfo as nested fields."""

from __future__ import annotations

from typing import Any

from .content_address import ContentAddress
from .context import WriteContext
from .io import BytesWriter
from .nar_hash import NARHash
from .path_info import UnkeyedValidPathInfo
from .signature import Signature
from .store_dir import store_prefix
from .store_path import StorePath
from .wire_message import WireModel
from .wire_time import Time


[docs] class ValidPathInfo(WireModel): """Wire mirror of ValidPathInfo. Wire order: ``path`` then all ``info`` fields inline. ``WireModel`` serializes nested ``WireModel`` fields inline, so this produces the correct flat wire format. """ path: StorePath info: UnkeyedValidPathInfo
[docs] async def bytes_wire(self) -> bytes: """Serialize this ValidPathInfo to bytes (in-memory BytesWriter is sync).""" buf = BytesWriter() ctx = WriteContext(writer=buf, version=0) await self.to_writer(ctx) return buf.bytes()
@classmethod def from_narinfo(cls, content: str) -> ValidPathInfo: data: dict[str, Any] = { "references": set(), "sigs": set(), } for line in content.splitlines(): line = line.strip() if not line or ":" not in line or line.startswith("#"): continue key, val = line.split(":", 1) key = key.strip() val = val.strip() if key == "StorePath": data["path"] = StorePath(path=val) elif key == "NarHash": data["nar_hash"] = NARHash(hash=val.removeprefix("sha256:")) elif key == "NarSize": data["nar_size"] = int(val) elif key == "References": for ref in val.split(): if ref: ref_path = ref if ref.startswith(store_prefix()) else f"{store_prefix()}{ref}" data["references"].add(StorePath(path=ref_path)) elif key == "Deriver": if val and val != "unknown-deriver": deriver = val if val.startswith(store_prefix()) else f"{store_prefix()}{val}" data["deriver"] = StorePath(path=deriver) else: data["deriver"] = None elif key == "Sig": data["sigs"].add(Signature(**Signature.from_str(val))) elif key == "CA": data["ca"] = ContentAddress(value=val) info = UnkeyedValidPathInfo( deriver=data.get("deriver"), nar_hash=data.get("nar_hash", NARHash(hash="")), references=data.get("references", set()), registration_time=Time(ts=data.get("registration_time", 0)), nar_size=data.get("nar_size", 0), ultimate=bool(data.get("ultimate", False)), sigs=data.get("sigs", set()), ca=data.get("ca", ContentAddress(value="")), ) return cls(path=data.get("path", StorePath(path="")), info=info) def to_narinfo(self) -> str: nar_hash = str(self.info.nar_hash) if not nar_hash.startswith("sha256:"): nar_hash = f"sha256:{nar_hash}" path_hash = self.path.hash_part() lines = [ f"StorePath: {self.path}", f"URL: nar/{path_hash}.nar", "Compression: none", f"NarHash: {nar_hash}", f"NarSize: {self.info.nar_size}", ] if self.info.references: refs = " ".join(sorted(ref.name for ref in self.info.references)) lines.append(f"References: {refs}") if self.info.deriver: lines.append(f"Deriver: {self.info.deriver.name}") lines.extend(f"Sig: {sig.to_str()}" for sig in sorted(self.info.sigs, key=str)) if self.info.ca: lines.append(f"CA: {self.info.ca}") return "\n".join(lines) + "\n"