From 89168e9a1af69d0762eec815f4a8afdfb9e40b8e Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 15 May 2022 18:26:05 +0200 Subject: [PATCH] correct download --- Cargo.lock | 12 ++++++------ src/download.rs | 35 +++++++++++++++++++++++++++++------ src/helper.rs | 19 +++++++++++++++++++ src/main.rs | 26 +++++++++++--------------- 4 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 src/helper.rs diff --git a/Cargo.lock b/Cargo.lock index 04efb0d..8c2b71a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -742,9 +742,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435" [[package]] name = "owo-colors" @@ -947,9 +947,9 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustls" -version = "0.20.4" +version = "0.20.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +checksum = "a024a432ae760ab3bff924ad91ce1cfa52cb57ed16e1ef32d0d249cfee1a6c13" dependencies = [ "log", "ring", @@ -1265,9 +1265,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" dependencies = [ "bytes", "futures-core", diff --git a/src/download.rs b/src/download.rs index 2877913..221f84a 100644 --- a/src/download.rs +++ b/src/download.rs @@ -8,10 +8,11 @@ use indexmap::IndexMap; use node_semver::Version; use reqwest::Client; use serde::Deserialize; -use tar::Archive; +use tokio::task::spawn_blocking; use tracing::{debug, info}; use crate::{ + create_dir_if_not_exists, manifest::{Bugs, Human, Person, Repository}, PackageJson, WrapErr, }; @@ -103,6 +104,10 @@ impl NpmClient { #[tracing::instrument(skip(self))] pub async fn download_package(&self, name: &str, url: &str) -> Result<()> { + let module = Path::new("node_modules").join(name); + + create_dir_if_not_exists(&module).await?; + let response = self .reqwest .get(url) @@ -111,11 +116,29 @@ impl NpmClient { .wrap_err("getting response")?; let tarball = response.bytes().await.wrap_err("fetching body")?; - let tar = flate2::read::GzDecoder::new(tarball.reader()); - let mut archive = tar::Archive::new(tar); - archive - .unpack(Path::new("node_modules").join(name)) - .wrap_err("unpack tarball")?; + spawn_blocking(move || -> Result<()> { + let tar = flate2::read::GzDecoder::new(tarball.reader()); + let mut archive = tar::Archive::new(tar); + + for entry in archive.entries()? { + let mut entry = entry?; + let path = entry.path()?; + let path = path + .strip_prefix("package") + .wrap_err("file name must start with package/")?; + + let path = module.join(path); + + info!(?path, "Unpacking file"); + + entry + .unpack(&path) + .wrap_err(format!("unpacking file {}", path.display()))?; + } + + Ok(()) + }) + .await??; info!("successfully downloaded package"); diff --git a/src/helper.rs b/src/helper.rs new file mode 100644 index 0000000..3ede0b5 --- /dev/null +++ b/src/helper.rs @@ -0,0 +1,19 @@ +use std::{io, path::Path}; + +use color_eyre::{eyre::bail, Result}; +use tokio::fs; + +use crate::WrapErr; + +pub async fn create_dir_if_not_exists(path: impl AsRef) -> Result<()> { + match fs::metadata(&path).await { + Ok(_) => {} + Err(e) if e.kind() == io::ErrorKind::NotFound => { + fs::create_dir(&path) + .await + .wrap_err("creating node_modules directory")?; + } + Err(e) => bail!(e), + } + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index a35ac5f..31c2456 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,15 @@ -use std::{fs, io}; - -use color_eyre::{ - eyre::{bail, WrapErr}, - Result, -}; +use color_eyre::{eyre::WrapErr, Result}; +use tokio::fs; use tracing::metadata::LevelFilter; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry}; -use crate::{download::NpmClient, manifest::PackageJson, resolve::ResolveContext}; +use crate::{ + download::NpmClient, helper::create_dir_if_not_exists, manifest::PackageJson, + resolve::ResolveContext, +}; mod download; +mod helper; mod manifest; mod resolve; @@ -19,19 +19,15 @@ async fn main() -> Result<()> { setup_tracing()?; let manifest = "package.json"; - let manifest = fs::read_to_string(manifest).wrap_err("Opening package.json file")?; + let manifest = fs::read_to_string(manifest) + .await + .wrap_err("Opening package.json file")?; let manifest: PackageJson = serde_json::from_str(&manifest)?; let resolve_context = ResolveContext::new(); - match fs::metadata("node_modules") { - Ok(_) => {} - Err(e) if e.kind() == io::ErrorKind::NotFound => { - fs::create_dir("node_modules").wrap_err("creating node_modules directory")?; - } - Err(e) => bail!(e), - } + create_dir_if_not_exists("node_modules").await?; for (name, requested_version) in &manifest.dependencies.unwrap() { resolve_context