use crate::config::WasmerEnv;
use super::PackageSource;
use anyhow::anyhow;
use sha2::{Digest, Sha256};
use std::{
path::{Path, PathBuf},
time::UNIX_EPOCH,
};
use wasmer_config::package::PackageSource as PackageSpecifier;
pub(crate) mod net;
const DEFAULT_WASMER_PKG_CAPABILITY_CACHE_DIR: &str = "pkg_capabilities";
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub(crate) struct PkgCapabilityCache {
pub enable_networking: bool,
}
pub(crate) fn get_capability_cache_path(
env: &WasmerEnv,
input: &PackageSource,
) -> anyhow::Result<PathBuf> {
let registry_name = env
.registry_public_url()?
.host_str()
.unwrap_or("unknown_registry")
.replace('.', "_");
let package_cache_path = match &input {
PackageSource::File(f) => {
let full_path = f.canonicalize()?.to_path_buf();
let metadata = full_path
.parent()
.ok_or(anyhow!("No parent!"))?
.metadata()?
.modified()?;
let mut hash = Sha256::new();
hash.update(
full_path
.into_os_string()
.into_string()
.map_err(|e| anyhow!("{e:?}"))?
.as_bytes(),
);
hash.update(
metadata
.duration_since(UNIX_EPOCH)?
.as_millis()
.to_be_bytes(),
);
format!("path_{}.json", hex::encode(hash.finalize()))
}
PackageSource::Dir(f) => {
let full_path = f.canonicalize()?.to_path_buf();
let metadata = full_path.metadata()?.modified()?;
let mut hash = Sha256::new();
hash.update(
full_path
.into_os_string()
.into_string()
.map_err(|e| anyhow!("{e:?}"))?
.as_bytes(),
);
hash.update(
metadata
.duration_since(UNIX_EPOCH)?
.as_millis()
.to_be_bytes(),
);
format!("path_{}.json", hex::encode(hash.finalize()))
}
PackageSource::Package(p) => match p {
PackageSpecifier::Ident(id) => match id {
wasmer_config::package::PackageIdent::Named(n) => format!(
"ident_{}_{}",
n.namespace.clone().unwrap_or("unknown_namespace".into()),
n.name
),
wasmer_config::package::PackageIdent::Hash(h) => {
format!("hash_{h}")
}
},
PackageSpecifier::Path(f) => {
let full_path = PathBuf::from(f).canonicalize()?.to_path_buf();
let mut hasher = Sha256::new();
hasher.update(
full_path
.clone()
.into_os_string()
.into_string()
.map_err(|e| anyhow!("{e:?}"))?
.as_bytes(),
);
if full_path.is_dir() {
hasher.update(
full_path
.metadata()?
.modified()?
.duration_since(UNIX_EPOCH)?
.as_millis()
.to_be_bytes(),
);
} else if full_path.is_file() {
hasher.update(
full_path
.parent()
.ok_or(anyhow!("No parent!"))?
.metadata()?
.modified()?
.duration_since(UNIX_EPOCH)?
.as_millis()
.to_be_bytes(),
);
}
format!("path_{}.json", hex::encode(hasher.finalize()))
}
PackageSpecifier::Url(u) => {
let mut hasher = Sha256::new();
hasher.update(u.to_string().as_bytes());
format!("path_{}.json", hex::encode(hasher.finalize()))
}
},
};
Ok(env
.cache_dir()
.join(DEFAULT_WASMER_PKG_CAPABILITY_CACHE_DIR)
.join(registry_name)
.join(package_cache_path))
}
pub(crate) fn get_cached_capability(path: &Path) -> anyhow::Result<PkgCapabilityCache> {
let raw = std::fs::read_to_string(path)?;
tracing::debug!("cache hit for package capability at {}", path.display());
serde_json::from_str::<PkgCapabilityCache>(&raw)
.map_err(|e| anyhow!("while deserializing package capability cache: {e:?}"))
}