pesde/src/download.rs

134 lines
4.4 KiB
Rust
Raw Normal View History

2024-07-28 18:19:54 +02:00
use crate::{
lockfile::{DependencyGraph, DownloadedDependencyGraphNode, DownloadedGraph},
source::{
traits::{PackageRef, PackageSource},
PackageSources,
},
Project, PACKAGES_CONTAINER_NAME,
};
2024-07-17 19:38:01 +02:00
use std::{
collections::HashSet,
2024-07-17 19:38:01 +02:00
fs::create_dir_all,
sync::{mpsc::Receiver, Arc, Mutex},
2024-07-17 19:38:01 +02:00
};
type MultithreadedGraph = Arc<Mutex<DownloadedGraph>>;
type MultithreadDownloadJob = (
Receiver<Result<(), errors::DownloadGraphError>>,
MultithreadedGraph,
);
2024-07-17 19:38:01 +02:00
impl Project {
2024-08-03 22:18:38 +02:00
/// Downloads a graph of dependencies
2024-07-17 19:38:01 +02:00
pub fn download_graph(
&self,
graph: &DependencyGraph,
refreshed_sources: &mut HashSet<PackageSources>,
reqwest: &reqwest::blocking::Client,
threads: usize,
) -> Result<MultithreadDownloadJob, errors::DownloadGraphError> {
2024-07-17 19:38:01 +02:00
let manifest = self.deser_manifest()?;
let downloaded_graph: MultithreadedGraph = Arc::new(Mutex::new(Default::default()));
2024-07-17 19:38:01 +02:00
let threadpool = threadpool::ThreadPool::new(threads);
let (tx, rx) = std::sync::mpsc::channel();
2024-07-17 19:38:01 +02:00
for (name, versions) in graph {
2024-07-22 23:16:04 +02:00
for (version_id, node) in versions {
2024-07-23 16:37:47 +02:00
let source = node.pkg_ref.source();
2024-07-17 19:38:01 +02:00
if refreshed_sources.insert(source.clone()) {
source.refresh(self).map_err(Box::new)?;
}
let container_folder = node.container_folder(
&self
.path()
.join(node.base_folder(manifest.target.kind(), true))
.join(PACKAGES_CONTAINER_NAME),
name,
2024-07-22 23:16:04 +02:00
version_id.version(),
2024-07-17 19:38:01 +02:00
);
create_dir_all(&container_folder)?;
let tx = tx.clone();
2024-07-17 19:38:01 +02:00
let name = name.clone();
let version_id = version_id.clone();
let node = node.clone();
let project = Arc::new(self.clone());
let reqwest = reqwest.clone();
let downloaded_graph = downloaded_graph.clone();
threadpool.execute(move || {
let project = project.clone();
2024-07-24 00:53:34 +02:00
log::debug!("downloading {name}@{version_id}");
2024-07-28 18:19:54 +02:00
let (fs, target) = match source.download(&node.pkg_ref, &project, &reqwest) {
Ok(target) => target,
Err(e) => {
tx.send(Err(e.into())).unwrap();
return;
}
};
2024-07-24 00:53:34 +02:00
log::debug!("downloaded {name}@{version_id}");
2024-07-28 18:19:54 +02:00
match fs.write_to(container_folder, project.cas_dir(), true) {
Ok(_) => {}
Err(e) => {
tx.send(Err(errors::DownloadGraphError::WriteFailed(e)))
.unwrap();
return;
}
};
let mut downloaded_graph = downloaded_graph.lock().unwrap();
downloaded_graph
.entry(name)
.or_default()
.insert(version_id, DownloadedDependencyGraphNode { node, target });
tx.send(Ok(())).unwrap();
});
2024-07-17 19:38:01 +02:00
}
}
Ok((rx, downloaded_graph))
2024-07-17 19:38:01 +02:00
}
}
2024-08-03 22:18:38 +02:00
/// Errors that can occur when downloading a graph
2024-07-17 19:38:01 +02:00
pub mod errors {
use thiserror::Error;
2024-08-03 22:18:38 +02:00
/// Errors that can occur when downloading a graph
2024-07-17 19:38:01 +02:00
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum DownloadGraphError {
2024-08-03 22:18:38 +02:00
/// Error occurred deserializing the project manifest
2024-07-17 19:38:01 +02:00
#[error("error deserializing project manifest")]
ManifestDeserializationFailed(#[from] crate::errors::ManifestReadError),
2024-08-03 22:18:38 +02:00
/// Error occurred refreshing a package source
2024-07-17 19:38:01 +02:00
#[error("failed to refresh package source")]
RefreshFailed(#[from] Box<crate::source::errors::RefreshError>),
2024-08-03 22:18:38 +02:00
/// Error interacting with the filesystem
2024-07-17 19:38:01 +02:00
#[error("error interacting with filesystem")]
Io(#[from] std::io::Error),
2024-08-03 22:18:38 +02:00
/// Error downloading a package
2024-07-17 19:38:01 +02:00
#[error("failed to download package")]
DownloadFailed(#[from] crate::source::errors::DownloadError),
2024-07-28 18:19:54 +02:00
2024-08-03 22:18:38 +02:00
/// Error writing package contents
2024-07-28 18:19:54 +02:00
#[error("failed to write package contents")]
WriteFailed(std::io::Error),
2024-07-17 19:38:01 +02:00
}
}