use std::{path::Path, sync::Arc};
use tracing::debug;
use crate::{client::HttpClient, schema::packages::PackageUri, utils::packaging::DirectoryPackage};
#[derive(Debug, Clone)]
pub struct PackagesClient {
http: Arc<HttpClient>,
}
impl PackagesClient {
pub(crate) fn new(http: Arc<HttpClient>) -> Self {
Self { http }
}
pub async fn exists(&self, uri: &PackageUri) -> crate::Result<bool> {
let path = format!("/api/packages/{}/{}", uri.protocol, uri.name);
let request = self.http.request(reqwest::Method::GET, &path)?;
match request.send().await {
Ok(response) => match response.status() {
reqwest::StatusCode::OK => Ok(true),
reqwest::StatusCode::NOT_FOUND => Ok(false),
_ => Err(crate::Error::Generic(format!(
"Unexpected status code checking package existence: {}",
response.status()
))),
},
Err(e) => Err(e.into()),
}
}
pub async fn upload(&self, package: &DirectoryPackage) -> crate::Result<()> {
debug!(
"Uploading package {} ({} bytes)",
package.uri(),
package.data().len()
);
let path = format!("/api/packages/{}/{}", package.uri().protocol, package.uri().name);
let request = self.http.request(reqwest::Method::PUT, &path)?;
let response = request
.body(package.data().to_vec())
.send()
.await?
.error_for_status()?;
debug!("Package uploaded successfully: {}", response.status());
Ok(())
}
pub async fn upload_directory(&self, directory: &Path) -> crate::Result<PackageUri> {
let directory = directory.to_owned();
let package = blocking::unblock(move || DirectoryPackage::new(&directory)).await?;
if self.exists(package.uri()).await? {
debug!("Package {} already exists, skipping upload", package.uri());
} else {
self.upload(&package).await?;
}
Ok(package.uri().clone())
}
}