mirror of
https://github.com/Noratrieb/node-package-manager.git
synced 2026-01-14 15:45:03 +01:00
download package (badly)
This commit is contained in:
parent
b4bc82f7e4
commit
f9c5a18720
6 changed files with 327 additions and 97 deletions
79
src/resolve.rs
Normal file
79
src/resolve.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use color_eyre::{eyre::bail, Result};
|
||||
use node_semver::Range;
|
||||
use tracing::{debug, info};
|
||||
|
||||
use crate::{download::PackageMeta, NpmClient, WrapErr};
|
||||
|
||||
pub struct ResolveContext {
|
||||
meta_cache: Arc<RwLock<HashMap<String, Arc<PackageMeta>>>>,
|
||||
client: NpmClient,
|
||||
}
|
||||
|
||||
impl ResolveContext {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
meta_cache: Arc::new(Default::default()),
|
||||
client: NpmClient::default(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_meta(&self, name: &str) -> Result<Arc<PackageMeta>> {
|
||||
{
|
||||
let cache_read = self.meta_cache.read().unwrap();
|
||||
if let Some(meta) = cache_read.get(name) {
|
||||
return Ok(Arc::clone(meta));
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Fetching package info..");
|
||||
|
||||
// two futures might race here - who cares
|
||||
let meta = self
|
||||
.client
|
||||
.fetch_package_meta(name)
|
||||
.await
|
||||
.wrap_err("fetching package metadata")?;
|
||||
|
||||
let meta = Arc::new(meta);
|
||||
|
||||
let mut cache_write = self.meta_cache.write().unwrap();
|
||||
cache_write.insert(name.to_owned(), Arc::clone(&meta));
|
||||
|
||||
Ok(meta)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, requested_version), fields(requested_version = %requested_version))]
|
||||
pub async fn download_package_and_deps(
|
||||
&self,
|
||||
name: &str,
|
||||
requested_version: &Range,
|
||||
) -> Result<()> {
|
||||
let meta = self.get_meta(name).await?;
|
||||
|
||||
info!(versions = ?meta.versions.keys().map(ToString::to_string).collect::<Vec<_>>());
|
||||
|
||||
let chosen = meta
|
||||
.versions
|
||||
.keys()
|
||||
.filter(|version| version.satisfies(requested_version))
|
||||
.max();
|
||||
|
||||
match chosen {
|
||||
Some(version) => {
|
||||
info!(%version, "Found version");
|
||||
self.client
|
||||
.download_package(name, &meta.versions[version].dist.tarball)
|
||||
.await
|
||||
.wrap_err("downloading package")?;
|
||||
}
|
||||
None => bail!("could not find matching version for '{requested_version}'"),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue