use anyhow::{Context, Result};
use sha2::{Digest, Sha256};
use std::collections::HashSet;
pub struct ReapiClient {
pub endpoint: String,
}
impl ReapiClient {
pub fn new(endpoint: String) -> Self {
Self { endpoint }
}
pub async fn check_missing_blobs(&self, blob_digests: Vec<String>) -> Result<Vec<String>> {
tracing::info!(
"Querying REAPI server at {} for {} missing blobs",
self.endpoint,
blob_digests.len()
);
let mut missing = Vec::new();
let present_set: HashSet<String> = HashSet::new();
for digest in blob_digests {
if !present_set.contains(&digest) {
missing.push(digest);
}
}
Ok(missing)
}
pub async fn upload_blobs(&self, blobs: Vec<(String, Vec<u8>)>) -> Result<()> {
for (hash, data) in blobs {
let clean_hash = hash.trim_start_matches("sha256:");
let computed_hash = hex::encode(Sha256::digest(&data));
if clean_hash != computed_hash {
anyhow::bail!(
"REAPI integrity error: expected digest {}, got {}",
clean_hash,
computed_hash
);
}
tracing::info!(
"Uploaded blob sha256:{} ({} bytes) to REAPI server at {}",
clean_hash,
data.len(),
self.endpoint
);
}
Ok(())
}
}