use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use uv_distribution_types::{DistributionId, IndexMetadata, IndexUrl};
use uv_normalize::PackageName;
use uv_pep440::Version;
use crate::pubgrub::Range;
use crate::resolver::{InMemoryIndex, MetadataResponse, Request, VersionsResponse};
use crate::{PythonRequirement, ResolveError};
#[derive(Clone)]
pub(crate) struct MetadataRequests {
index: InMemoryIndex,
sender: Sender<Request>,
}
impl MetadataRequests {
pub(crate) fn new(index: InMemoryIndex, sender: Sender<Request>) -> Self {
Self { index, sender }
}
pub(crate) fn request_package(
&self,
name: &PackageName,
index: Option<&IndexMetadata>,
) -> Result<(), ResolveError> {
let registered = if let Some(index) = index {
self.index
.explicit()
.register((name.clone(), index.url().clone()))
} else {
self.index.implicit().register(name.clone())
};
if registered {
self.sender
.blocking_send(Request::Package(name.clone(), index.cloned()))?;
}
Ok(())
}
pub(crate) fn request_metadata(
&self,
id: DistributionId,
request: impl FnOnce() -> Result<Request, ResolveError>,
) -> Result<(), ResolveError> {
if self.index.distributions().register(id) {
self.sender.blocking_send(request()?)?;
}
Ok(())
}
pub(crate) fn prefetch(
&self,
name: &PackageName,
range: &Range<Version>,
python_requirement: &PythonRequirement,
) -> Result<(), ResolveError> {
self.sender.blocking_send(Request::Prefetch(
name.clone(),
range.clone(),
python_requirement.clone(),
))?;
Ok(())
}
pub(crate) fn wait_for_versions(
&self,
name: &PackageName,
index: Option<&IndexUrl>,
) -> Result<Arc<VersionsResponse>, ResolveError> {
if let Some(index) = index {
self.index
.explicit()
.wait_blocking(&(name.clone(), index.clone()))
.map_err(|_| ResolveError::UnregisteredTask(name.to_string()))
} else {
self.index
.implicit()
.wait_blocking(name)
.map_err(|_| ResolveError::UnregisteredTask(name.to_string()))
}
}
pub(crate) fn wait_for_metadata(
&self,
id: &DistributionId,
description: impl FnOnce() -> String,
) -> Result<Arc<MetadataResponse>, ResolveError> {
self.index
.distributions()
.wait_blocking(id)
.map_err(|_| ResolveError::UnregisteredTask(description()))
}
}