pub async fn write_package_cache_archive<R: OperatorResolver + ?Sized>(
resolver: &R,
request: &PackageCacheArchiveWriteRequest,
archive: &[u8],
) -> Result<PackageCacheArchiveWriteReceipt, PackageCacheArchiveWriteError>Expand description
Writes caller-supplied exact archive bytes to one package-cache object.
This low-level operation does not expand the archive, validate a Package Tree, or insert it into a Package Catalog. Direct use with unvalidated bytes can poison a cache because a present malformed cache candidate is terminal. Callers should write registry bytes only after successful expansion, validation, and insertion.
Dropping the returned future yields no receipt, and already-issued storage
work may have occurred. The caller retains archive; full replay with the
same exact bytes is the recovery contract.
use std::error::Error;
use typst_pack::{
PackageReadFailures, PackageCatalog, PackageDisposition,
PackageExpansionLimits,
};
use typst_pack::opendal::OperatorBindings;
use typst_pack::opendal::pack_assembly::{
PackageRead, RegistryArchiveResidue, insert_read_package,
};
use typst_pack::opendal::write::{
PackageCacheArchiveWriteRequest, write_package_cache_archive,
};
async fn insert_then_write_registry_archive(
bindings: &OperatorBindings,
catalog: &mut PackageCatalog,
failures: &mut PackageReadFailures,
read: PackageRead,
) -> Result<Option<RegistryArchiveResidue>, Box<dyn Error>> {
let Some(residue) = insert_read_package(
catalog,
failures,
read,
PackageDisposition::Embedded,
PackageExpansionLimits::reference_v1(),
)? else {
return Ok(None);
};
let request = PackageCacheArchiveWriteRequest::new(
residue.destination().clone(),
)?;
if let Err(cache_failure) =
write_package_cache_archive(bindings, &request, residue.bytes()).await
{
// Insertion remains successful. The residue retains the exact bytes
// and destination so the caller can report and replay independently.
drop(cache_failure);
}
Ok(Some(residue))
}